diff --git a/.github/actions/nodejs/action.yaml b/.github/actions/nodejs/action.yaml index 4141c5fe6d9..537c402977a 100644 --- a/.github/actions/nodejs/action.yaml +++ b/.github/actions/nodejs/action.yaml @@ -5,7 +5,7 @@ inputs: node-version: description: "Node.js version to use" required: false - default: "20" + default: "24" runs: using: composite steps: diff --git a/.github/workflows/prebuild-devcontainers.yml b/.github/workflows/prebuild-devcontainers.yml index 38a1ecd4031..dcf2dd5a49f 100644 --- a/.github/workflows/prebuild-devcontainers.yml +++ b/.github/workflows/prebuild-devcontainers.yml @@ -27,7 +27,7 @@ jobs: - name: Setup Node.JS uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "24" - name: Install skopeo run: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 90f02ec0cc1..609be39af84 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -158,7 +158,7 @@ jobs: - name: Setup Node.JS uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "24" - name: Enable corepack run: corepack enable diff --git a/.pnp.cjs b/.pnp.cjs index 10f1bc69086..1b9f481e83a 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -145,13 +145,19 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@dashevo/platform", "workspace:."],\ ["@iarna/toml", "npm:2.2.5"],\ + ["@typescript-eslint/parser", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:8.54.0"],\ ["add-stream", "npm:1.0.0"],\ ["conventional-changelog", "npm:3.1.24"],\ ["conventional-changelog-dash", "https://github.com/dashevo/conventional-changelog-dash.git#commit=3d4d77e2cea876a27b92641c28b15aedf13eb788"],\ ["dompurify", "npm:3.2.6"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-config-airbnb-extended", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:3.0.1"],\ + ["eslint-plugin-jsdoc", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:50.8.0"],\ + ["globals", "npm:15.15.0"],\ ["node-gyp", "npm:10.0.1"],\ ["semver", "npm:7.5.3"],\ ["tempfile", "npm:3.0.0"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["ultra-runner", "npm:3.10.5"]\ ],\ "linkType": "SOFT"\ @@ -258,6 +264,16 @@ const RAW_RUNTIME_STATE = ["picocolors", "npm:1.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-code-frame-npm-7.28.6-7d31d84e6c-93e7ed9e03.zip/node_modules/@babel/code-frame/",\ + "packageDependencies": [\ + ["@babel/code-frame", "npm:7.28.6"],\ + ["@babel/helper-validator-identifier", "npm:7.28.5"],\ + ["js-tokens", "npm:4.0.0"],\ + ["picocolors", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/compat-data", [\ @@ -274,6 +290,13 @@ const RAW_RUNTIME_STATE = ["@babel/compat-data", "npm:7.26.8"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-compat-data-npm-7.28.6-4e0cdcaa44-dc17dfb557.zip/node_modules/@babel/compat-data/",\ + "packageDependencies": [\ + ["@babel/compat-data", "npm:7.28.6"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/core", [\ @@ -298,49 +321,31 @@ const RAW_RUNTIME_STATE = ["semver", "npm:7.5.3"]\ ],\ "linkType": "HARD"\ - }]\ - ]],\ - ["@babel/eslint-parser", [\ - ["npm:7.26.10", {\ - "packageLocation": "./.yarn/cache/@babel-eslint-parser-npm-7.26.10-52ac28fff9-27eb60d16b.zip/node_modules/@babel/eslint-parser/",\ - "packageDependencies": [\ - ["@babel/eslint-parser", "npm:7.26.10"]\ - ],\ - "linkType": "SOFT"\ }],\ - ["virtual:6c6296bde00603e266f7d80babe1e01aa0c19f626934f58fe08f890a291bb1a38fcee25bf30c24857d5cfba290f01209decc48384318fd6815c5a514cb48be25#npm:7.26.10", {\ - "packageLocation": "./.yarn/__virtual__/@babel-eslint-parser-virtual-44fbd8254f/0/cache/@babel-eslint-parser-npm-7.26.10-52ac28fff9-27eb60d16b.zip/node_modules/@babel/eslint-parser/",\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-core-npm-7.28.6-0abdbf2b3d-1a150a69c5.zip/node_modules/@babel/core/",\ "packageDependencies": [\ - ["@babel/core", "npm:7.26.10"],\ - ["@babel/eslint-parser", "virtual:6c6296bde00603e266f7d80babe1e01aa0c19f626934f58fe08f890a291bb1a38fcee25bf30c24857d5cfba290f01209decc48384318fd6815c5a514cb48be25#npm:7.26.10"],\ - ["@nicolo-ribaudo/eslint-scope-5-internals", "npm:5.1.1-v1"],\ - ["@types/babel__core", null],\ - ["@types/eslint", null],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-visitor-keys", "npm:2.1.0"],\ + ["@babel/code-frame", "npm:7.28.6"],\ + ["@babel/core", "npm:7.28.6"],\ + ["@babel/generator", "npm:7.28.6"],\ + ["@babel/helper-compilation-targets", "npm:7.28.6"],\ + ["@babel/helper-module-transforms", "virtual:0abdbf2b3dddd7b9d77c473b73bf51ed3451655589b6a81eda5023cecdc1ae74fa5329c3f9b029b710d752d9b6e0955385f3a9ec07632ebfba66ccf9c9c13c53#npm:7.28.6"],\ + ["@babel/helpers", "npm:7.28.6"],\ + ["@babel/parser", "npm:7.28.6"],\ + ["@babel/template", "npm:7.28.6"],\ + ["@babel/traverse", "npm:7.28.6"],\ + ["@babel/types", "npm:7.28.6"],\ + ["@jridgewell/remapping", "npm:2.3.5"],\ + ["convert-source-map", "npm:2.0.0"],\ + ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ + ["gensync", "npm:1.0.0-beta.2"],\ + ["json5", "npm:2.2.3"],\ ["semver", "npm:7.5.3"]\ ],\ - "packagePeers": [\ - "@babel/core",\ - "@types/babel__core",\ - "@types/eslint",\ - "eslint"\ - ],\ "linkType": "HARD"\ }]\ ]],\ ["@babel/generator", [\ - ["npm:7.23.3", {\ - "packageLocation": "./.yarn/cache/@babel-generator-npm-7.23.3-a2ca9dda65-0f815d275c.zip/node_modules/@babel/generator/",\ - "packageDependencies": [\ - ["@babel/generator", "npm:7.23.3"],\ - ["@babel/types", "npm:7.23.3"],\ - ["@jridgewell/gen-mapping", "npm:0.3.3"],\ - ["@jridgewell/trace-mapping", "npm:0.3.18"],\ - ["jsesc", "npm:2.5.2"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:7.26.10", {\ "packageLocation": "./.yarn/cache/@babel-generator-npm-7.26.10-ee5de9766f-acf5e6544e.zip/node_modules/@babel/generator/",\ "packageDependencies": [\ @@ -352,6 +357,18 @@ const RAW_RUNTIME_STATE = ["jsesc", "npm:3.1.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-generator-npm-7.28.6-18c2d22a25-ef2af927e8.zip/node_modules/@babel/generator/",\ + "packageDependencies": [\ + ["@babel/generator", "npm:7.28.6"],\ + ["@babel/parser", "npm:7.28.6"],\ + ["@babel/types", "npm:7.28.6"],\ + ["@jridgewell/gen-mapping", "npm:0.3.13"],\ + ["@jridgewell/trace-mapping", "npm:0.3.31"],\ + ["jsesc", "npm:3.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-annotate-as-pure", [\ @@ -396,6 +413,18 @@ const RAW_RUNTIME_STATE = ["semver", "npm:7.5.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-helper-compilation-targets-npm-7.28.6-8880f389c9-f512a5aeee.zip/node_modules/@babel/helper-compilation-targets/",\ + "packageDependencies": [\ + ["@babel/compat-data", "npm:7.28.6"],\ + ["@babel/helper-compilation-targets", "npm:7.28.6"],\ + ["@babel/helper-validator-option", "npm:7.27.1"],\ + ["browserslist", "npm:4.24.4"],\ + ["lru-cache", "npm:5.1.1"],\ + ["semver", "npm:7.5.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-create-class-features-plugin", [\ @@ -502,32 +531,11 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@babel/helper-environment-visitor", [\ - ["npm:7.22.20", {\ - "packageLocation": "./.yarn/cache/@babel-helper-environment-visitor-npm-7.22.20-260909e014-d80ee98ff6.zip/node_modules/@babel/helper-environment-visitor/",\ - "packageDependencies": [\ - ["@babel/helper-environment-visitor", "npm:7.22.20"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["@babel/helper-function-name", [\ - ["npm:7.23.0", {\ - "packageLocation": "./.yarn/cache/@babel-helper-function-name-npm-7.23.0-ce38271242-7b2ae024cd.zip/node_modules/@babel/helper-function-name/",\ - "packageDependencies": [\ - ["@babel/helper-function-name", "npm:7.23.0"],\ - ["@babel/template", "npm:7.22.15"],\ - ["@babel/types", "npm:7.23.3"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["@babel/helper-hoist-variables", [\ - ["npm:7.22.5", {\ - "packageLocation": "./.yarn/cache/@babel-helper-hoist-variables-npm-7.22.5-6db3192347-394ca191b4.zip/node_modules/@babel/helper-hoist-variables/",\ + ["@babel/helper-globals", [\ + ["npm:7.28.0", {\ + "packageLocation": "./.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-91445f7edf.zip/node_modules/@babel/helper-globals/",\ "packageDependencies": [\ - ["@babel/helper-hoist-variables", "npm:7.22.5"],\ - ["@babel/types", "npm:7.23.3"]\ + ["@babel/helper-globals", "npm:7.28.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -552,6 +560,15 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.26.10"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-helper-module-imports-npm-7.28.6-5b95b9145c-64b1380d74.zip/node_modules/@babel/helper-module-imports/",\ + "packageDependencies": [\ + ["@babel/helper-module-imports", "npm:7.28.6"],\ + ["@babel/traverse", "npm:7.28.6"],\ + ["@babel/types", "npm:7.28.6"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-module-transforms", [\ @@ -562,6 +579,29 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-helper-module-transforms-npm-7.28.6-5923cf5a95-2e421c7db7.zip/node_modules/@babel/helper-module-transforms/",\ + "packageDependencies": [\ + ["@babel/helper-module-transforms", "npm:7.28.6"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:0abdbf2b3dddd7b9d77c473b73bf51ed3451655589b6a81eda5023cecdc1ae74fa5329c3f9b029b710d752d9b6e0955385f3a9ec07632ebfba66ccf9c9c13c53#npm:7.28.6", {\ + "packageLocation": "./.yarn/__virtual__/@babel-helper-module-transforms-virtual-adcea07681/0/cache/@babel-helper-module-transforms-npm-7.28.6-5923cf5a95-2e421c7db7.zip/node_modules/@babel/helper-module-transforms/",\ + "packageDependencies": [\ + ["@babel/core", "npm:7.28.6"],\ + ["@babel/helper-module-imports", "npm:7.28.6"],\ + ["@babel/helper-module-transforms", "virtual:0abdbf2b3dddd7b9d77c473b73bf51ed3451655589b6a81eda5023cecdc1ae74fa5329c3f9b029b710d752d9b6e0955385f3a9ec07632ebfba66ccf9c9c13c53#npm:7.28.6"],\ + ["@babel/helper-validator-identifier", "npm:7.28.5"],\ + ["@babel/traverse", "npm:7.28.6"],\ + ["@types/babel__core", null]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@types/babel__core"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:0b29e369b5cabceb66f4f9f7eb2bfea5004820a7141f28569a8c55dbecef082f3ef9191fa4288e8f13bbcfed9896b6f90431a16a9ce18c31d8a25782f02d5f09#npm:7.26.0", {\ "packageLocation": "./.yarn/__virtual__/@babel-helper-module-transforms-virtual-60af4713da/0/cache/@babel-helper-module-transforms-npm-7.26.0-7557a3558f-9841d2a62f.zip/node_modules/@babel/helper-module-transforms/",\ "packageDependencies": [\ @@ -666,16 +706,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@babel/helper-split-export-declaration", [\ - ["npm:7.22.6", {\ - "packageLocation": "./.yarn/cache/@babel-helper-split-export-declaration-npm-7.22.6-e723505aef-e141cace58.zip/node_modules/@babel/helper-split-export-declaration/",\ - "packageDependencies": [\ - ["@babel/helper-split-export-declaration", "npm:7.22.6"],\ - ["@babel/types", "npm:7.23.3"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@babel/helper-string-parser", [\ ["npm:7.22.5", {\ "packageLocation": "./.yarn/cache/@babel-helper-string-parser-npm-7.22.5-448ff0e489-7f275a7f1a.zip/node_modules/@babel/helper-string-parser/",\ @@ -690,6 +720,13 @@ const RAW_RUNTIME_STATE = ["@babel/helper-string-parser", "npm:7.25.9"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-0ae29cc200.zip/node_modules/@babel/helper-string-parser/",\ + "packageDependencies": [\ + ["@babel/helper-string-parser", "npm:7.27.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-validator-identifier", [\ @@ -706,6 +743,13 @@ const RAW_RUNTIME_STATE = ["@babel/helper-validator-identifier", "npm:7.25.9"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-8e5d9b0133.zip/node_modules/@babel/helper-validator-identifier/",\ + "packageDependencies": [\ + ["@babel/helper-validator-identifier", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-validator-option", [\ @@ -722,6 +766,13 @@ const RAW_RUNTIME_STATE = ["@babel/helper-validator-option", "npm:7.25.9"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-db73e6a308.zip/node_modules/@babel/helper-validator-option/",\ + "packageDependencies": [\ + ["@babel/helper-validator-option", "npm:7.27.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-wrap-function", [\ @@ -745,6 +796,15 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.26.10"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-helpers-npm-7.28.6-682df48628-213485cdff.zip/node_modules/@babel/helpers/",\ + "packageDependencies": [\ + ["@babel/helpers", "npm:7.28.6"],\ + ["@babel/template", "npm:7.28.6"],\ + ["@babel/types", "npm:7.28.6"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/highlight", [\ @@ -760,14 +820,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@babel/parser", [\ - ["npm:7.23.3", {\ - "packageLocation": "./.yarn/cache/@babel-parser-npm-7.23.3-8d3a021e39-284c22ec1d.zip/node_modules/@babel/parser/",\ - "packageDependencies": [\ - ["@babel/parser", "npm:7.23.3"],\ - ["@babel/types", "npm:7.23.3"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:7.26.10", {\ "packageLocation": "./.yarn/cache/@babel-parser-npm-7.26.10-51865d5633-3f87781f46.zip/node_modules/@babel/parser/",\ "packageDependencies": [\ @@ -775,6 +827,14 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.26.10"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-parser-npm-7.28.6-b41fd3a428-483a6fb5f9.zip/node_modules/@babel/parser/",\ + "packageDependencies": [\ + ["@babel/parser", "npm:7.28.6"],\ + ["@babel/types", "npm:7.28.6"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/plugin-bugfix-firefox-class-in-computed-class-key", [\ @@ -2311,16 +2371,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@babel/template", [\ - ["npm:7.22.15", {\ - "packageLocation": "./.yarn/cache/@babel-template-npm-7.22.15-0b464facb4-21e768e4ee.zip/node_modules/@babel/template/",\ - "packageDependencies": [\ - ["@babel/code-frame", "npm:7.22.13"],\ - ["@babel/parser", "npm:7.23.3"],\ - ["@babel/template", "npm:7.22.15"],\ - ["@babel/types", "npm:7.23.3"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:7.26.9", {\ "packageLocation": "./.yarn/cache/@babel-template-npm-7.26.9-6339558068-240288ceba.zip/node_modules/@babel/template/",\ "packageDependencies": [\ @@ -2330,26 +2380,19 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.26.10"]\ ],\ "linkType": "HARD"\ - }]\ - ]],\ - ["@babel/traverse", [\ - ["npm:7.23.3", {\ - "packageLocation": "./.yarn/cache/@babel-traverse-npm-7.23.3-a268f4c943-522ef8eefe.zip/node_modules/@babel/traverse/",\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-template-npm-7.28.6-bff3bc3923-0ad6e32bf1.zip/node_modules/@babel/template/",\ "packageDependencies": [\ - ["@babel/code-frame", "npm:7.22.13"],\ - ["@babel/generator", "npm:7.23.3"],\ - ["@babel/helper-environment-visitor", "npm:7.22.20"],\ - ["@babel/helper-function-name", "npm:7.23.0"],\ - ["@babel/helper-hoist-variables", "npm:7.22.5"],\ - ["@babel/helper-split-export-declaration", "npm:7.22.6"],\ - ["@babel/parser", "npm:7.23.3"],\ - ["@babel/traverse", "npm:7.23.3"],\ - ["@babel/types", "npm:7.23.3"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["globals", "npm:11.12.0"]\ + ["@babel/code-frame", "npm:7.28.6"],\ + ["@babel/parser", "npm:7.28.6"],\ + ["@babel/template", "npm:7.28.6"],\ + ["@babel/types", "npm:7.28.6"]\ ],\ "linkType": "HARD"\ - }],\ + }]\ + ]],\ + ["@babel/traverse", [\ ["npm:7.26.10", {\ "packageLocation": "./.yarn/cache/@babel-traverse-npm-7.26.10-bdeb9ff2c2-e9c77390ce.zip/node_modules/@babel/traverse/",\ "packageDependencies": [\ @@ -2363,6 +2406,20 @@ const RAW_RUNTIME_STATE = ["globals", "npm:11.12.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-traverse-npm-7.28.6-e426afeacf-dd71efe941.zip/node_modules/@babel/traverse/",\ + "packageDependencies": [\ + ["@babel/code-frame", "npm:7.28.6"],\ + ["@babel/generator", "npm:7.28.6"],\ + ["@babel/helper-globals", "npm:7.28.0"],\ + ["@babel/parser", "npm:7.28.6"],\ + ["@babel/template", "npm:7.28.6"],\ + ["@babel/traverse", "npm:7.28.6"],\ + ["@babel/types", "npm:7.28.6"],\ + ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/types", [\ @@ -2384,6 +2441,15 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.26.10"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.6", {\ + "packageLocation": "./.yarn/cache/@babel-types-npm-7.28.6-623ccfc882-f9c6e52b45.zip/node_modules/@babel/types/",\ + "packageDependencies": [\ + ["@babel/helper-string-parser", "npm:7.27.1"],\ + ["@babel/helper-validator-identifier", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.6"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@balena/dockerignore", [\ @@ -2435,13 +2501,10 @@ const RAW_RUNTIME_STATE = ["@dashevo/dpns-contract", "workspace:packages/dpns-contract"],\ ["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\ ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ - ["babel-eslint", "virtual:27dae49067a60fa65fec6e1c3adad1497d0dda3f71eda711624109131ff3b7d1061a20f55e89b5a0a219da1f7a0a1a0a76bc414d36870315bd60acf5bdcb7f55#npm:10.1.0"],\ ["console-table-printer", "npm:2.11.0"],\ ["dash", "workspace:packages/js-dash-sdk"],\ ["dotenv-safe", "npm:8.2.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["lodash", "npm:4.17.23"],\ ["mathjs", "npm:10.4.3"],\ ["mocha", "npm:11.1.0"]\ @@ -2464,7 +2527,6 @@ const RAW_RUNTIME_STATE = "packageLocation": "./packages/dapi/",\ "packageDependencies": [\ ["@babel/core", "npm:7.26.10"],\ - ["@babel/eslint-parser", "virtual:6c6296bde00603e266f7d80babe1e01aa0c19f626934f58fe08f890a291bb1a38fcee25bf30c24857d5cfba290f01209decc48384318fd6815c5a514cb48be25#npm:7.26.10"],\ ["@dashevo/bls", "npm:1.2.9"],\ ["@dashevo/dapi", "workspace:packages/dapi"],\ ["@dashevo/dapi-client", "workspace:packages/js-dapi-client"],\ @@ -2485,9 +2547,7 @@ const RAW_RUNTIME_STATE = ["dotenv", "npm:8.6.0"],\ ["dotenv-expand", "npm:5.1.0"],\ ["dotenv-safe", "npm:8.2.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["google-protobuf", "npm:3.19.1"],\ ["jayson", "npm:4.1.0"],\ ["lodash", "npm:4.17.23"],\ @@ -2529,10 +2589,7 @@ const RAW_RUNTIME_STATE = ["core-js", "npm:3.33.2"],\ ["crypto-browserify", "npm:3.12.1"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ - ["eslint-plugin-jsdoc", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:46.9.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["google-protobuf", "npm:3.19.1"],\ ["karma", "npm:6.4.3"],\ @@ -2577,9 +2634,7 @@ const RAW_RUNTIME_STATE = ["chai", "npm:4.3.10"],\ ["chai-as-promised", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:7.1.1"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["google-protobuf", "npm:3.19.1"],\ ["long", "npm:5.2.0"],\ ["mocha", "npm:11.1.0"],\ @@ -2608,9 +2663,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/dash-util", "npm:2.0.3"],\ ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["chai", "npm:4.3.10"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["levelup", "npm:4.4.0"],\ ["memdown", "npm:5.1.0"],\ ["mocha", "npm:11.1.0"],\ @@ -2681,9 +2734,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -2723,9 +2774,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -2739,21 +2788,20 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@dashevo/evo-sdk", "workspace:packages/js-evo-sdk"],\ ["@dashevo/wasm-sdk", "workspace:packages/wasm-sdk"],\ - ["@typescript-eslint/eslint-plugin", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["@typescript-eslint/parser", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ + ["@types/chai", "npm:4.3.20"],\ + ["@types/mocha", "npm:10.0.10"],\ + ["@types/node", "npm:20.19.30"],\ + ["@types/sinon", "npm:9.0.11"],\ + ["@types/sinon-chai", "npm:3.2.5"],\ ["assert", "npm:2.0.0"],\ ["buffer", "npm:6.0.3"],\ ["chai", "npm:4.3.10"],\ - ["chai-as-promised", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:7.1.1"],\ - ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:15.0.0"],\ - ["eslint-config-airbnb-typescript", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:17.0.0"],\ - ["eslint-plugin-import", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.29.0"],\ - ["eslint-plugin-jsdoc", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:46.9.0"],\ + ["chai-as-promised", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:7.1.1"],\ + ["dirty-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.0.1"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["karma", "npm:6.4.3"],\ - ["karma-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:0.1.0"],\ + ["karma-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ ["karma-mocha", "npm:2.0.1"],\ @@ -2763,11 +2811,12 @@ const RAW_RUNTIME_STATE = ["path-browserify", "npm:1.0.1"],\ ["process", "npm:0.11.10"],\ ["sinon", "npm:17.0.1"],\ - ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"],\ + ["sinon-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:3.7.0"],\ ["string_decoder", "npm:1.3.0"],\ ["terser-webpack-plugin", "virtual:da12f6bb23b671689b7f4f5cfff69cabf980ba04aff1ffd96860c787f7d5d08d32b0db765d9f16463de0d1af2c01fa6987b861cf5df2362e38e0ef415f29b51c#npm:5.3.11"],\ ["ts-loader", "virtual:da12f6bb23b671689b7f4f5cfff69cabf980ba04aff1ffd96860c787f7d5d08d32b0db765d9f16463de0d1af2c01fa6987b861cf5df2362e38e0ef415f29b51c#npm:9.5.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"],\ + ["ts-node", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:10.9.2"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["url", "npm:0.11.3"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:da12f6bb23b671689b7f4f5cfff69cabf980ba04aff1ffd96860c787f7d5d08d32b0db765d9f16463de0d1af2c01fa6987b861cf5df2362e38e0ef415f29b51c#npm:5.94.0"],\ @@ -2784,9 +2833,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -2806,9 +2853,7 @@ const RAW_RUNTIME_STATE = ["chai", "npm:4.3.10"],\ ["chai-as-promised", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:7.1.1"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["lodash", "npm:4.17.23"],\ ["long", "npm:5.2.0"],\ ["mocha", "npm:11.1.0"],\ @@ -2829,9 +2874,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -2847,9 +2890,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -2863,13 +2904,19 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@dashevo/platform", "workspace:."],\ ["@iarna/toml", "npm:2.2.5"],\ + ["@typescript-eslint/parser", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:8.54.0"],\ ["add-stream", "npm:1.0.0"],\ ["conventional-changelog", "npm:3.1.24"],\ ["conventional-changelog-dash", "https://github.com/dashevo/conventional-changelog-dash.git#commit=3d4d77e2cea876a27b92641c28b15aedf13eb788"],\ ["dompurify", "npm:3.2.6"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-config-airbnb-extended", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:3.0.1"],\ + ["eslint-plugin-jsdoc", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:50.8.0"],\ + ["globals", "npm:15.15.0"],\ ["node-gyp", "npm:10.0.1"],\ ["semver", "npm:7.5.3"],\ ["tempfile", "npm:3.0.0"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["ultra-runner", "npm:3.10.5"]\ ],\ "linkType": "SOFT"\ @@ -2900,9 +2947,7 @@ const RAW_RUNTIME_STATE = ["dash", "workspace:packages/js-dash-sdk"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ ["dotenv-safe", "npm:8.2.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["glob", "npm:10.4.1"],\ ["https-browserify", "npm:1.0.0"],\ @@ -2977,9 +3022,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -3008,9 +3051,7 @@ const RAW_RUNTIME_STATE = ["crypto-js", "npm:4.2.0"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ ["dotenv-safe", "npm:8.2.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["https-browserify", "npm:1.0.0"],\ ["karma", "npm:6.4.3"],\ @@ -3054,9 +3095,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -3077,7 +3116,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/dpns-contract", "workspace:packages/dpns-contract"],\ ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["@types/bs58", "npm:4.0.4"],\ - ["@types/node", "npm:14.17.34"],\ + ["@types/node", "npm:20.19.30"],\ ["@yarnpkg/pnpify", "npm:4.0.0-rc.42"],\ ["ajv", "npm:8.12.0"],\ ["assert", "npm:2.0.0"],\ @@ -3089,9 +3128,7 @@ const RAW_RUNTIME_STATE = ["chai-string", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:1.5.0"],\ ["crypto-browserify", "npm:3.12.1"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["fast-json-patch", "npm:3.1.1"],\ ["https-browserify", "npm:1.0.0"],\ @@ -3115,7 +3152,7 @@ const RAW_RUNTIME_STATE = ["string_decoder", "npm:1.3.0"],\ ["ts-loader", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:9.5.0"],\ ["tsd", "npm:0.28.1"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["url", "npm:0.11.3"],\ ["util", "npm:0.12.4"],\ ["varint", "npm:6.0.0"],\ @@ -3130,19 +3167,19 @@ const RAW_RUNTIME_STATE = "packageLocation": "./packages/wasm-dpp2/",\ "packageDependencies": [\ ["@dashevo/wasm-dpp2", "workspace:packages/wasm-dpp2"],\ + ["@types/chai", "npm:4.3.20"],\ + ["@types/mocha", "npm:10.0.10"],\ + ["@types/node", "npm:20.19.30"],\ ["assert", "npm:2.0.0"],\ ["bs58", "npm:4.0.1"],\ ["buffer", "npm:6.0.3"],\ ["chai", "npm:4.3.10"],\ - ["chai-as-promised", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:7.1.1"],\ - ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ - ["eslint-plugin-jsdoc", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:46.9.0"],\ + ["chai-as-promised", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:7.1.1"],\ + ["dirty-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.0.1"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["karma", "npm:6.4.3"],\ - ["karma-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:0.1.0"],\ + ["karma-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ ["karma-mocha", "npm:2.0.1"],\ @@ -3152,6 +3189,9 @@ const RAW_RUNTIME_STATE = ["path-browserify", "npm:1.0.1"],\ ["process", "npm:0.11.10"],\ ["string_decoder", "npm:1.3.0"],\ + ["ts-loader", "virtual:897449be52adaf897095babe74bfcc926f5d083ac9aac6fbc5e260f1f71b7e3ada3f268ac9457d3009b9c6fca51fe685ec21fbed21ec5087df84ab489b719456#npm:9.5.0"],\ + ["ts-node", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:10.9.2"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["url", "npm:0.11.3"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:897449be52adaf897095babe74bfcc926f5d083ac9aac6fbc5e260f1f71b7e3ada3f268ac9457d3009b9c6fca51fe685ec21fbed21ec5087df84ab489b719456#npm:5.94.0"],\ @@ -3165,18 +3205,18 @@ const RAW_RUNTIME_STATE = "packageLocation": "./packages/wasm-sdk/",\ "packageDependencies": [\ ["@dashevo/wasm-sdk", "workspace:packages/wasm-sdk"],\ + ["@types/chai", "npm:4.3.20"],\ + ["@types/mocha", "npm:10.0.10"],\ + ["@types/node", "npm:20.19.30"],\ ["assert", "npm:2.0.0"],\ ["buffer", "npm:6.0.3"],\ ["chai", "npm:4.3.10"],\ - ["chai-as-promised", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:7.1.1"],\ - ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ - ["eslint-plugin-jsdoc", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:46.9.0"],\ + ["chai-as-promised", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:7.1.1"],\ + ["dirty-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.0.1"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["karma", "npm:6.4.3"],\ - ["karma-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:0.1.0"],\ + ["karma-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ ["karma-mocha", "npm:2.0.1"],\ @@ -3186,6 +3226,9 @@ const RAW_RUNTIME_STATE = ["path-browserify", "npm:1.0.1"],\ ["process", "npm:0.11.10"],\ ["string_decoder", "npm:1.3.0"],\ + ["ts-loader", "virtual:98d1afeac78a19485e4cb7428abff692e58b6fc468d8040035b560ed49383fc95857be6b5014af27e53063e6f08b654690c2b945f3443c22dd60c6b083684b3c#npm:9.5.0"],\ + ["ts-node", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:10.9.2"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["url", "npm:0.11.3"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:98d1afeac78a19485e4cb7428abff692e58b6fc468d8040035b560ed49383fc95857be6b5014af27e53063e6f08b654690c2b945f3443c22dd60c6b083684b3c#npm:5.94.0"],\ @@ -3202,9 +3245,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/withdrawals-contract", "workspace:packages/withdrawals-contract"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["mocha", "npm:11.1.0"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ @@ -3230,14 +3271,47 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@emnapi/core", [\ + ["npm:1.8.1", {\ + "packageLocation": "./.yarn/cache/@emnapi-core-npm-1.8.1-9be0a25589-904ea60c91.zip/node_modules/@emnapi/core/",\ + "packageDependencies": [\ + ["@emnapi/core", "npm:1.8.1"],\ + ["@emnapi/wasi-threads", "npm:1.1.0"],\ + ["tslib", "npm:2.6.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@emnapi/runtime", [\ + ["npm:1.8.1", {\ + "packageLocation": "./.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-26725e202d.zip/node_modules/@emnapi/runtime/",\ + "packageDependencies": [\ + ["@emnapi/runtime", "npm:1.8.1"],\ + ["tslib", "npm:2.6.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@emnapi/wasi-threads", [\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/@emnapi-wasi-threads-npm-1.1.0-4dc2c60138-0d557e7526.zip/node_modules/@emnapi/wasi-threads/",\ + "packageDependencies": [\ + ["@emnapi/wasi-threads", "npm:1.1.0"],\ + ["tslib", "npm:2.6.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@es-joy/jsdoccomment", [\ - ["npm:0.41.0", {\ - "packageLocation": "./.yarn/cache/@es-joy-jsdoccomment-npm-0.41.0-20acf8fb8c-ea581983f3.zip/node_modules/@es-joy/jsdoccomment/",\ + ["npm:0.50.2", {\ + "packageLocation": "./.yarn/cache/@es-joy-jsdoccomment-npm-0.50.2-971362ab5d-a309f01bd1.zip/node_modules/@es-joy/jsdoccomment/",\ "packageDependencies": [\ - ["@es-joy/jsdoccomment", "npm:0.41.0"],\ + ["@es-joy/jsdoccomment", "npm:0.50.2"],\ + ["@types/estree", "npm:1.0.8"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ ["comment-parser", "npm:1.4.1"],\ - ["esquery", "npm:1.5.0"],\ - ["jsdoc-type-pratt-parser", "npm:4.0.0"]\ + ["esquery", "npm:1.7.0"],\ + ["jsdoc-type-pratt-parser", "npm:4.1.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -3250,12 +3324,19 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:2fc5c501d26c4c2fbc6a1d931e87d32adb7d9118fbcd7303a7b7faae809112bde136383859a265761a47c2852a001b7b803bf80e734ffa8ddc2ca30c129d1d76#npm:4.4.0", {\ - "packageLocation": "./.yarn/__virtual__/@eslint-community-eslint-utils-virtual-4b69618f4d/0/cache/@eslint-community-eslint-utils-npm-4.4.0-d1791bd5a3-8d70bcdcd8.zip/node_modules/@eslint-community/eslint-utils/",\ + ["npm:4.9.1", {\ + "packageLocation": "./.yarn/cache/@eslint-community-eslint-utils-npm-4.9.1-30ad3d49de-863b546786.zip/node_modules/@eslint-community/eslint-utils/",\ + "packageDependencies": [\ + ["@eslint-community/eslint-utils", "npm:4.9.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:79c28034d94a28ec559d9137247270112d4bba82f5cf5320ba8f69e7c1dc984374b4c8c82e16031069e9919a8ce0b231c49891795c762408cc665fe7a8cd02ee#npm:4.9.1", {\ + "packageLocation": "./.yarn/__virtual__/@eslint-community-eslint-utils-virtual-6ea10338c1/0/cache/@eslint-community-eslint-utils-npm-4.9.1-30ad3d49de-863b546786.zip/node_modules/@eslint-community/eslint-utils/",\ "packageDependencies": [\ - ["@eslint-community/eslint-utils", "virtual:2fc5c501d26c4c2fbc6a1d931e87d32adb7d9118fbcd7303a7b7faae809112bde136383859a265761a47c2852a001b7b803bf80e734ffa8ddc2ca30c129d1d76#npm:4.4.0"],\ + ["@eslint-community/eslint-utils", "virtual:79c28034d94a28ec559d9137247270112d4bba82f5cf5320ba8f69e7c1dc984374b4c8c82e16031069e9919a8ce0b231c49891795c762408cc665fe7a8cd02ee#npm:4.9.1"],\ ["@types/eslint", null],\ - ["eslint", "npm:8.53.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["eslint-visitor-keys", "npm:3.4.3"]\ ],\ "packagePeers": [\ @@ -3280,23 +3361,55 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@eslint-community/regexpp", [\ - ["npm:4.10.0", {\ - "packageLocation": "./.yarn/cache/@eslint-community-regexpp-npm-4.10.0-6bfb984c81-8c36169c81.zip/node_modules/@eslint-community/regexpp/",\ + ["npm:4.12.2", {\ + "packageLocation": "./.yarn/cache/@eslint-community-regexpp-npm-4.12.2-3d54624470-049b280fdd.zip/node_modules/@eslint-community/regexpp/",\ "packageDependencies": [\ - ["@eslint-community/regexpp", "npm:4.10.0"]\ + ["@eslint-community/regexpp", "npm:4.12.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@eslint/config-array", [\ + ["npm:0.21.1", {\ + "packageLocation": "./.yarn/cache/@eslint-config-array-npm-0.21.1-c33ed9ec91-6eaa043597.zip/node_modules/@eslint/config-array/",\ + "packageDependencies": [\ + ["@eslint/config-array", "npm:0.21.1"],\ + ["@eslint/object-schema", "npm:2.1.7"],\ + ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ + ["minimatch", "npm:3.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@eslint/config-helpers", [\ + ["npm:0.4.2", {\ + "packageLocation": "./.yarn/cache/@eslint-config-helpers-npm-0.4.2-a55655f805-3f2b4712d8.zip/node_modules/@eslint/config-helpers/",\ + "packageDependencies": [\ + ["@eslint/config-helpers", "npm:0.4.2"],\ + ["@eslint/core", "npm:0.17.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@eslint/core", [\ + ["npm:0.17.0", {\ + "packageLocation": "./.yarn/cache/@eslint-core-npm-0.17.0-8579df04c4-f9a428cc65.zip/node_modules/@eslint/core/",\ + "packageDependencies": [\ + ["@eslint/core", "npm:0.17.0"],\ + ["@types/json-schema", "npm:7.0.15"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@eslint/eslintrc", [\ - ["npm:2.1.3", {\ - "packageLocation": "./.yarn/cache/@eslint-eslintrc-npm-2.1.3-088d1bae55-77b70a8923.zip/node_modules/@eslint/eslintrc/",\ + ["npm:3.3.3", {\ + "packageLocation": "./.yarn/cache/@eslint-eslintrc-npm-3.3.3-8ccf6281a3-b586a364ff.zip/node_modules/@eslint/eslintrc/",\ "packageDependencies": [\ - ["@eslint/eslintrc", "npm:2.1.3"],\ + ["@eslint/eslintrc", "npm:3.3.3"],\ ["ajv", "npm:6.12.6"],\ ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["espree", "npm:9.6.1"],\ - ["globals", "npm:13.23.0"],\ + ["espree", "npm:10.4.0"],\ + ["globals", "npm:14.0.0"],\ ["ignore", "npm:5.2.0"],\ ["import-fresh", "npm:3.3.0"],\ ["js-yaml", "npm:4.1.1"],\ @@ -3307,10 +3420,30 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@eslint/js", [\ - ["npm:8.53.0", {\ - "packageLocation": "./.yarn/cache/@eslint-js-npm-8.53.0-1ffdbc6083-a372d55aa2.zip/node_modules/@eslint/js/",\ + ["npm:9.39.2", {\ + "packageLocation": "./.yarn/cache/@eslint-js-npm-9.39.2-c8e5f9bf73-6b7f676746.zip/node_modules/@eslint/js/",\ + "packageDependencies": [\ + ["@eslint/js", "npm:9.39.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@eslint/object-schema", [\ + ["npm:2.1.7", {\ + "packageLocation": "./.yarn/cache/@eslint-object-schema-npm-2.1.7-cb962a5b9b-946ef5d623.zip/node_modules/@eslint/object-schema/",\ + "packageDependencies": [\ + ["@eslint/object-schema", "npm:2.1.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@eslint/plugin-kit", [\ + ["npm:0.4.1", {\ + "packageLocation": "./.yarn/cache/@eslint-plugin-kit-npm-0.4.1-3df70dd079-c5947d0ffe.zip/node_modules/@eslint/plugin-kit/",\ "packageDependencies": [\ - ["@eslint/js", "npm:8.53.0"]\ + ["@eslint/core", "npm:0.17.0"],\ + ["@eslint/plugin-kit", "npm:0.4.1"],\ + ["levn", "npm:0.4.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -3368,14 +3501,22 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@humanwhocodes/config-array", [\ - ["npm:0.11.13", {\ - "packageLocation": "./.yarn/cache/@humanwhocodes-config-array-npm-0.11.13-12314014f2-9f655e1df7.zip/node_modules/@humanwhocodes/config-array/",\ + ["@humanfs/core", [\ + ["npm:0.19.1", {\ + "packageLocation": "./.yarn/cache/@humanfs-core-npm-0.19.1-e2e7aaeb6e-270d936be4.zip/node_modules/@humanfs/core/",\ "packageDependencies": [\ - ["@humanwhocodes/config-array", "npm:0.11.13"],\ - ["@humanwhocodes/object-schema", "npm:2.0.1"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["minimatch", "npm:3.1.2"]\ + ["@humanfs/core", "npm:0.19.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@humanfs/node", [\ + ["npm:0.16.7", {\ + "packageLocation": "./.yarn/cache/@humanfs-node-npm-0.16.7-fa16bdb590-b3633d3dce.zip/node_modules/@humanfs/node/",\ + "packageDependencies": [\ + ["@humanfs/core", "npm:0.19.1"],\ + ["@humanfs/node", "npm:0.16.7"],\ + ["@humanwhocodes/retry", "npm:0.4.3"]\ ],\ "linkType": "HARD"\ }]\ @@ -3389,11 +3530,11 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@humanwhocodes/object-schema", [\ - ["npm:2.0.1", {\ - "packageLocation": "./.yarn/cache/@humanwhocodes-object-schema-npm-2.0.1-c23364bbfc-dbddfd0465.zip/node_modules/@humanwhocodes/object-schema/",\ + ["@humanwhocodes/retry", [\ + ["npm:0.4.3", {\ + "packageLocation": "./.yarn/cache/@humanwhocodes-retry-npm-0.4.3-a8d7ca1663-0b32cfd362.zip/node_modules/@humanwhocodes/retry/",\ "packageDependencies": [\ - ["@humanwhocodes/object-schema", "npm:2.0.1"]\ + ["@humanwhocodes/retry", "npm:0.4.3"]\ ],\ "linkType": "HARD"\ }]\ @@ -3439,6 +3580,25 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@isaacs/balanced-match", [\ + ["npm:4.0.1", {\ + "packageLocation": "./.yarn/cache/@isaacs-balanced-match-npm-4.0.1-8965afafe6-102fbc6d2c.zip/node_modules/@isaacs/balanced-match/",\ + "packageDependencies": [\ + ["@isaacs/balanced-match", "npm:4.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@isaacs/brace-expansion", [\ + ["npm:5.0.0", {\ + "packageLocation": "./.yarn/cache/@isaacs-brace-expansion-npm-5.0.0-754d3cb3f5-cf3b7f206a.zip/node_modules/@isaacs/brace-expansion/",\ + "packageDependencies": [\ + ["@isaacs/balanced-match", "npm:4.0.1"],\ + ["@isaacs/brace-expansion", "npm:5.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@isaacs/cliui", [\ ["npm:8.0.2", {\ "packageLocation": "./.yarn/cache/@isaacs-cliui-npm-8.0.2-f4364666d5-e9ed5fd27c.zip/node_modules/@isaacs/cliui/",\ @@ -3516,6 +3676,15 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@jridgewell/gen-mapping", [\ + ["npm:0.3.13", {\ + "packageLocation": "./.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-902f8261dc.zip/node_modules/@jridgewell/gen-mapping/",\ + "packageDependencies": [\ + ["@jridgewell/gen-mapping", "npm:0.3.13"],\ + ["@jridgewell/sourcemap-codec", "npm:1.5.5"],\ + ["@jridgewell/trace-mapping", "npm:0.3.25"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:0.3.3", {\ "packageLocation": "./.yarn/cache/@jridgewell-gen-mapping-npm-0.3.3-1815eba94c-072ace159c.zip/node_modules/@jridgewell/gen-mapping/",\ "packageDependencies": [\ @@ -3537,6 +3706,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@jridgewell/remapping", [\ + ["npm:2.3.5", {\ + "packageLocation": "./.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-c2bb01856e.zip/node_modules/@jridgewell/remapping/",\ + "packageDependencies": [\ + ["@jridgewell/gen-mapping", "npm:0.3.5"],\ + ["@jridgewell/remapping", "npm:2.3.5"],\ + ["@jridgewell/trace-mapping", "npm:0.3.25"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@jridgewell/resolve-uri", [\ ["npm:3.1.0", {\ "packageLocation": "./.yarn/cache/@jridgewell-resolve-uri-npm-3.1.0-6ff2351e61-320ceb37af.zip/node_modules/@jridgewell/resolve-uri/",\ @@ -3594,6 +3774,13 @@ const RAW_RUNTIME_STATE = ["@jridgewell/sourcemap-codec", "npm:1.5.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.5.5", {\ + "packageLocation": "./.yarn/cache/@jridgewell-sourcemap-codec-npm-1.5.5-5189d9fc79-5d9d207b46.zip/node_modules/@jridgewell/sourcemap-codec/",\ + "packageDependencies": [\ + ["@jridgewell/sourcemap-codec", "npm:1.5.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@jridgewell/trace-mapping", [\ @@ -3615,6 +3802,15 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ + ["npm:0.3.31", {\ + "packageLocation": "./.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-da0283270e.zip/node_modules/@jridgewell/trace-mapping/",\ + "packageDependencies": [\ + ["@jridgewell/resolve-uri", "npm:3.1.2"],\ + ["@jridgewell/sourcemap-codec", "npm:1.5.0"],\ + ["@jridgewell/trace-mapping", "npm:0.3.31"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:0.3.9", {\ "packageLocation": "./.yarn/cache/@jridgewell-trace-mapping-npm-0.3.9-91625cd7fb-83deafb8e7.zip/node_modules/@jridgewell/trace-mapping/",\ "packageDependencies": [\ @@ -3652,21 +3848,33 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@nicolo-ribaudo/chokidar-2", [\ - ["npm:2.1.8-no-fsevents.3", {\ - "packageLocation": "./.yarn/cache/@nicolo-ribaudo-chokidar-2-npm-2.1.8-no-fsevents.3-79ca8bfcef-c6e83af3b5.zip/node_modules/@nicolo-ribaudo/chokidar-2/",\ + ["@napi-rs/wasm-runtime", [\ + ["npm:0.2.12", {\ + "packageLocation": "./.yarn/cache/@napi-rs-wasm-runtime-npm-0.2.12-8f0d65e253-5fd5181824.zip/node_modules/@napi-rs/wasm-runtime/",\ "packageDependencies": [\ - ["@nicolo-ribaudo/chokidar-2", "npm:2.1.8-no-fsevents.3"]\ + ["@emnapi/core", "npm:1.8.1"],\ + ["@emnapi/runtime", "npm:1.8.1"],\ + ["@napi-rs/wasm-runtime", "npm:0.2.12"],\ + ["@tybys/wasm-util", "npm:0.10.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/eslint-plugin-next", [\ + ["npm:16.1.5", {\ + "packageLocation": "./.yarn/cache/@next-eslint-plugin-next-npm-16.1.5-a20eef2072-8846e6a014.zip/node_modules/@next/eslint-plugin-next/",\ + "packageDependencies": [\ + ["@next/eslint-plugin-next", "npm:16.1.5"],\ + ["fast-glob", "npm:3.3.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@nicolo-ribaudo/eslint-scope-5-internals", [\ - ["npm:5.1.1-v1", {\ - "packageLocation": "./.yarn/cache/@nicolo-ribaudo-eslint-scope-5-internals-npm-5.1.1-v1-87df86be4b-f2e3b2d6a6.zip/node_modules/@nicolo-ribaudo/eslint-scope-5-internals/",\ + ["@nicolo-ribaudo/chokidar-2", [\ + ["npm:2.1.8-no-fsevents.3", {\ + "packageLocation": "./.yarn/cache/@nicolo-ribaudo-chokidar-2-npm-2.1.8-no-fsevents.3-79ca8bfcef-c6e83af3b5.zip/node_modules/@nicolo-ribaudo/chokidar-2/",\ "packageDependencies": [\ - ["@nicolo-ribaudo/eslint-scope-5-internals", "npm:5.1.1-v1"],\ - ["eslint-scope", "npm:5.1.1"]\ + ["@nicolo-ribaudo/chokidar-2", "npm:2.1.8-no-fsevents.3"]\ ],\ "linkType": "HARD"\ }]\ @@ -4378,6 +4586,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@rtsao/scc", [\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/@rtsao-scc-npm-1.1.0-f4ba9ceb2c-17d04adf40.zip/node_modules/@rtsao/scc/",\ + "packageDependencies": [\ + ["@rtsao/scc", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@sigstore/bundle", [\ ["npm:1.1.0", {\ "packageLocation": "./.yarn/cache/@sigstore-bundle-npm-1.1.0-b2cf24a13e-79e6cc4cc1.zip/node_modules/@sigstore/bundle/",\ @@ -4536,6 +4753,34 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@stylistic/eslint-plugin", [\ + ["npm:5.7.1", {\ + "packageLocation": "./.yarn/cache/@stylistic-eslint-plugin-npm-5.7.1-d417cddca9-df50c60e11.zip/node_modules/@stylistic/eslint-plugin/",\ + "packageDependencies": [\ + ["@stylistic/eslint-plugin", "npm:5.7.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:5.7.1", {\ + "packageLocation": "./.yarn/__virtual__/@stylistic-eslint-plugin-virtual-79c28034d9/0/cache/@stylistic-eslint-plugin-npm-5.7.1-d417cddca9-df50c60e11.zip/node_modules/@stylistic/eslint-plugin/",\ + "packageDependencies": [\ + ["@eslint-community/eslint-utils", "virtual:79c28034d94a28ec559d9137247270112d4bba82f5cf5320ba8f69e7c1dc984374b4c8c82e16031069e9919a8ce0b231c49891795c762408cc665fe7a8cd02ee#npm:4.9.1"],\ + ["@stylistic/eslint-plugin", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:5.7.1"],\ + ["@types/eslint", null],\ + ["@typescript-eslint/types", "npm:8.53.1"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-visitor-keys", "npm:4.2.1"],\ + ["espree", "npm:10.4.0"],\ + ["estraverse", "npm:5.3.0"],\ + ["picomatch", "npm:4.0.3"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@szmarczak/http-timer", [\ ["npm:4.0.6", {\ "packageLocation": "./.yarn/cache/@szmarczak-http-timer-npm-4.0.6-6ace00d82d-c29df3bcec.zip/node_modules/@szmarczak/http-timer/",\ @@ -4628,6 +4873,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@tybys/wasm-util", [\ + ["npm:0.10.1", {\ + "packageLocation": "./.yarn/cache/@tybys-wasm-util-npm-0.10.1-607c8a7e5c-7fe0d23939.zip/node_modules/@tybys/wasm-util/",\ + "packageDependencies": [\ + ["@tybys/wasm-util", "npm:0.10.1"],\ + ["tslib", "npm:2.6.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/bs58", [\ ["npm:4.0.4", {\ "packageLocation": "./.yarn/cache/@types-bs58-npm-4.0.4-61d579b54c-9cac5a0034.zip/node_modules/@types/bs58/",\ @@ -4659,6 +4914,13 @@ const RAW_RUNTIME_STATE = ["@types/chai", "npm:4.2.22"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.3.20", {\ + "packageLocation": "./.yarn/cache/@types-chai-npm-4.3.20-468371f41f-94fd87036f.zip/node_modules/@types/chai/",\ + "packageDependencies": [\ + ["@types/chai", "npm:4.3.20"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@types/chai-as-promised", [\ @@ -4754,6 +5016,13 @@ const RAW_RUNTIME_STATE = ["@types/estree", "npm:1.0.5"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.8", {\ + "packageLocation": "./.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-25a4c16a67.zip/node_modules/@types/estree/",\ + "packageDependencies": [\ + ["@types/estree", "npm:1.0.8"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@types/expect", [\ @@ -4821,10 +5090,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@types/mocha", [\ - ["npm:8.2.3", {\ - "packageLocation": "./.yarn/cache/@types-mocha-npm-8.2.3-7aff51fdb4-c768b67d8f.zip/node_modules/@types/mocha/",\ + ["npm:10.0.10", {\ + "packageLocation": "./.yarn/cache/@types-mocha-npm-10.0.10-1e025e7c6e-4e3b61ed51.zip/node_modules/@types/mocha/",\ "packageDependencies": [\ - ["@types/mocha", "npm:8.2.3"]\ + ["@types/mocha", "npm:10.0.10"]\ ],\ "linkType": "HARD"\ }]\ @@ -4851,13 +5120,6 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:14.17.34", {\ - "packageLocation": "./.yarn/cache/@types-node-npm-14.17.34-1d7f20f643-a7e23fc63c.zip/node_modules/@types/node/",\ - "packageDependencies": [\ - ["@types/node", "npm:14.17.34"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:15.14.9", {\ "packageLocation": "./.yarn/cache/@types-node-npm-15.14.9-739a59edff-5c9cc5346c.zip/node_modules/@types/node/",\ "packageDependencies": [\ @@ -4871,6 +5133,14 @@ const RAW_RUNTIME_STATE = ["@types/node", "npm:18.16.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:20.19.30", {\ + "packageLocation": "./.yarn/cache/@types-node-npm-20.19.30-e3d3d7af6e-4a25e5cbcd.zip/node_modules/@types/node/",\ + "packageDependencies": [\ + ["@types/node", "npm:20.19.30"],\ + ["undici-types", "npm:6.21.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@types/normalize-package-data", [\ @@ -4979,33 +5249,31 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@typescript-eslint/eslint-plugin", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.55.0-16386bf9af-05f921647a.zip/node_modules/@typescript-eslint/eslint-plugin/",\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.54.0-e6f6e349b5-8f1c74ac77.zip/node_modules/@typescript-eslint/eslint-plugin/",\ "packageDependencies": [\ - ["@typescript-eslint/eslint-plugin", "npm:5.55.0"]\ + ["@typescript-eslint/eslint-plugin", "npm:8.54.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-eslint-plugin-virtual-0e22d802b6/0/cache/@typescript-eslint-eslint-plugin-npm-5.55.0-16386bf9af-05f921647a.zip/node_modules/@typescript-eslint/eslint-plugin/",\ + ["virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-eslint-plugin-virtual-7a0e8d9430/0/cache/@typescript-eslint-eslint-plugin-npm-8.54.0-e6f6e349b5-8f1c74ac77.zip/node_modules/@typescript-eslint/eslint-plugin/",\ "packageDependencies": [\ - ["@eslint-community/regexpp", "npm:4.10.0"],\ + ["@eslint-community/regexpp", "npm:4.12.2"],\ ["@types/eslint", null],\ ["@types/typescript", null],\ ["@types/typescript-eslint__parser", null],\ - ["@typescript-eslint/eslint-plugin", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["@typescript-eslint/parser", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["@typescript-eslint/scope-manager", "npm:5.55.0"],\ - ["@typescript-eslint/type-utils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:5.55.0"],\ - ["@typescript-eslint/utils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:5.55.0"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["eslint", "npm:8.53.0"],\ - ["grapheme-splitter", "npm:1.0.4"],\ - ["ignore", "npm:5.2.0"],\ - ["natural-compare-lite", "npm:1.4.0"],\ - ["semver", "npm:7.5.3"],\ - ["tsutils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:3.21.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"]\ + ["@typescript-eslint/eslint-plugin", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/parser", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/scope-manager", "npm:8.54.0"],\ + ["@typescript-eslint/type-utils", "virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:8.54.0"],\ + ["@typescript-eslint/utils", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/visitor-keys", "npm:8.54.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["ignore", "npm:7.0.5"],\ + ["natural-compare", "npm:1.4.0"],\ + ["ts-api-utils", "virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:2.4.0"],\ + ["typescript", null]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -5019,25 +5287,48 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@typescript-eslint/parser", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-parser-npm-5.55.0-ee38253ad6-a7c48c1d39.zip/node_modules/@typescript-eslint/parser/",\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-parser-npm-8.54.0-9b917cc1cb-d2e09462c9.zip/node_modules/@typescript-eslint/parser/",\ "packageDependencies": [\ - ["@typescript-eslint/parser", "npm:5.55.0"]\ + ["@typescript-eslint/parser", "npm:8.54.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-parser-virtual-2089cd6370/0/cache/@typescript-eslint-parser-npm-5.55.0-ee38253ad6-a7c48c1d39.zip/node_modules/@typescript-eslint/parser/",\ + ["virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-parser-virtual-0ee70eb356/0/cache/@typescript-eslint-parser-npm-8.54.0-9b917cc1cb-d2e09462c9.zip/node_modules/@typescript-eslint/parser/",\ "packageDependencies": [\ ["@types/eslint", null],\ ["@types/typescript", null],\ - ["@typescript-eslint/parser", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["@typescript-eslint/scope-manager", "npm:5.55.0"],\ - ["@typescript-eslint/types", "npm:5.55.0"],\ - ["@typescript-eslint/typescript-estree", "virtual:0c2ac79ebf72f4493d7516f3ee57421c8337be2bdf9498590055ee112e7fdf62dd0b817c13f6c8a030baf64dbe843920deec4c3c8ea8bd6888b7baf950492c3a#npm:5.55.0"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["eslint", "npm:8.53.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"]\ + ["@typescript-eslint/parser", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/scope-manager", "npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/visitor-keys", "npm:8.54.0"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["typescript", null]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "@types/typescript",\ + "eslint",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-parser-virtual-4cab2f911c/0/cache/@typescript-eslint-parser-npm-8.54.0-9b917cc1cb-d2e09462c9.zip/node_modules/@typescript-eslint/parser/",\ + "packageDependencies": [\ + ["@types/eslint", null],\ + ["@types/typescript", null],\ + ["@typescript-eslint/parser", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:8.54.0"],\ + ["@typescript-eslint/scope-manager", "npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:8.54.0"],\ + ["@typescript-eslint/visitor-keys", "npm:8.54.0"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -5048,16 +5339,48 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@typescript-eslint/scope-manager", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-scope-manager-npm-5.55.0-d7744f8a94-a089b0f45b.zip/node_modules/@typescript-eslint/scope-manager/",\ + ["@typescript-eslint/project-service", [\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-project-service-npm-8.54.0-df3e89508b-93f0483f6b.zip/node_modules/@typescript-eslint/project-service/",\ + "packageDependencies": [\ + ["@typescript-eslint/project-service", "npm:8.54.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:e23667a5b32248a12ae73c52027669f5b894be4fbb985cc67d024501c3bc7ea8a70b9e6820163ae197299cdf37bdeddcddb662f9f81d5cf5133ed55fc3b42995#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-project-service-virtual-afcbbc0ac0/0/cache/@typescript-eslint-project-service-npm-8.54.0-df3e89508b-93f0483f6b.zip/node_modules/@typescript-eslint/project-service/",\ "packageDependencies": [\ - ["@typescript-eslint/scope-manager", "npm:5.55.0"],\ - ["@typescript-eslint/types", "npm:5.55.0"],\ - ["@typescript-eslint/visitor-keys", "npm:5.55.0"]\ + ["@types/typescript", null],\ + ["@typescript-eslint/project-service", "virtual:e23667a5b32248a12ae73c52027669f5b894be4fbb985cc67d024501c3bc7ea8a70b9e6820163ae197299cdf37bdeddcddb662f9f81d5cf5133ed55fc3b42995#npm:8.54.0"],\ + ["@typescript-eslint/tsconfig-utils", "virtual:e23667a5b32248a12ae73c52027669f5b894be4fbb985cc67d024501c3bc7ea8a70b9e6820163ae197299cdf37bdeddcddb662f9f81d5cf5133ed55fc3b42995#npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["typescript", null]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ ],\ "linkType": "HARD"\ }],\ + ["virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-project-service-virtual-74cc671d64/0/cache/@typescript-eslint-project-service-npm-8.54.0-df3e89508b-93f0483f6b.zip/node_modules/@typescript-eslint/project-service/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["@typescript-eslint/project-service", "virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:8.54.0"],\ + ["@typescript-eslint/tsconfig-utils", "virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@typescript-eslint/scope-manager", [\ ["npm:6.10.0", {\ "packageLocation": "./.yarn/cache/@typescript-eslint-scope-manager-npm-6.10.0-a8ebca443c-518cd60f9e.zip/node_modules/@typescript-eslint/scope-manager/",\ "packageDependencies": [\ @@ -5066,28 +5389,73 @@ const RAW_RUNTIME_STATE = ["@typescript-eslint/visitor-keys", "npm:6.10.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-scope-manager-npm-8.54.0-4f2ea67471-3474f3197e.zip/node_modules/@typescript-eslint/scope-manager/",\ + "packageDependencies": [\ + ["@typescript-eslint/scope-manager", "npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/visitor-keys", "npm:8.54.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@typescript-eslint/tsconfig-utils", [\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-tsconfig-utils-npm-8.54.0-73efc09e2a-e9d6b29538.zip/node_modules/@typescript-eslint/tsconfig-utils/",\ + "packageDependencies": [\ + ["@typescript-eslint/tsconfig-utils", "npm:8.54.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:e23667a5b32248a12ae73c52027669f5b894be4fbb985cc67d024501c3bc7ea8a70b9e6820163ae197299cdf37bdeddcddb662f9f81d5cf5133ed55fc3b42995#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-tsconfig-utils-virtual-dbe4d89c70/0/cache/@typescript-eslint-tsconfig-utils-npm-8.54.0-73efc09e2a-e9d6b29538.zip/node_modules/@typescript-eslint/tsconfig-utils/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["@typescript-eslint/tsconfig-utils", "virtual:e23667a5b32248a12ae73c52027669f5b894be4fbb985cc67d024501c3bc7ea8a70b9e6820163ae197299cdf37bdeddcddb662f9f81d5cf5133ed55fc3b42995#npm:8.54.0"],\ + ["typescript", null]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-tsconfig-utils-virtual-5839688328/0/cache/@typescript-eslint-tsconfig-utils-npm-8.54.0-73efc09e2a-e9d6b29538.zip/node_modules/@typescript-eslint/tsconfig-utils/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["@typescript-eslint/tsconfig-utils", "virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:8.54.0"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/type-utils", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-type-utils-npm-5.55.0-333e5c4b16-267a2144fa.zip/node_modules/@typescript-eslint/type-utils/",\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-type-utils-npm-8.54.0-a5168062ab-60e92fb322.zip/node_modules/@typescript-eslint/type-utils/",\ "packageDependencies": [\ - ["@typescript-eslint/type-utils", "npm:5.55.0"]\ + ["@typescript-eslint/type-utils", "npm:8.54.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:5.55.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-type-utils-virtual-0c2ac79ebf/0/cache/@typescript-eslint-type-utils-npm-5.55.0-333e5c4b16-267a2144fa.zip/node_modules/@typescript-eslint/type-utils/",\ + ["virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-type-utils-virtual-41d0626054/0/cache/@typescript-eslint-type-utils-npm-8.54.0-a5168062ab-60e92fb322.zip/node_modules/@typescript-eslint/type-utils/",\ "packageDependencies": [\ ["@types/eslint", null],\ ["@types/typescript", null],\ - ["@typescript-eslint/type-utils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:5.55.0"],\ - ["@typescript-eslint/typescript-estree", "virtual:0c2ac79ebf72f4493d7516f3ee57421c8337be2bdf9498590055ee112e7fdf62dd0b817c13f6c8a030baf64dbe843920deec4c3c8ea8bd6888b7baf950492c3a#npm:5.55.0"],\ - ["@typescript-eslint/utils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:5.55.0"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["eslint", "npm:8.53.0"],\ - ["tsutils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:3.21.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"]\ + ["@typescript-eslint/type-utils", "virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/utils", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["ts-api-utils", "virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:2.4.0"],\ + ["typescript", null]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -5099,49 +5467,58 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@typescript-eslint/types", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-5.55.0-694e3d296a-5ff3b2880e.zip/node_modules/@typescript-eslint/types/",\ + ["npm:6.10.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-6.10.0-ad3bff287b-bc8faf3d00.zip/node_modules/@typescript-eslint/types/",\ "packageDependencies": [\ - ["@typescript-eslint/types", "npm:5.55.0"]\ + ["@typescript-eslint/types", "npm:6.10.0"]\ ],\ "linkType": "HARD"\ }],\ - ["npm:6.10.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-6.10.0-ad3bff287b-bc8faf3d00.zip/node_modules/@typescript-eslint/types/",\ + ["npm:8.53.1", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-8.53.1-b5f0956f64-9a01aa3433.zip/node_modules/@typescript-eslint/types/",\ "packageDependencies": [\ - ["@typescript-eslint/types", "npm:6.10.0"]\ + ["@typescript-eslint/types", "npm:8.53.1"]\ + ],\ + "linkType": "HARD"\ + }],\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-8.54.0-75d29a589d-c25cc0bdf9.zip/node_modules/@typescript-eslint/types/",\ + "packageDependencies": [\ + ["@typescript-eslint/types", "npm:8.54.0"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/typescript-estree", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-typescript-estree-npm-5.55.0-aefc08af17-e6c51080c0.zip/node_modules/@typescript-eslint/typescript-estree/",\ + ["npm:6.10.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-typescript-estree-npm-6.10.0-7880dab921-41fc6dd0cf.zip/node_modules/@typescript-eslint/typescript-estree/",\ "packageDependencies": [\ - ["@typescript-eslint/typescript-estree", "npm:5.55.0"]\ + ["@typescript-eslint/typescript-estree", "npm:6.10.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["npm:6.10.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-typescript-estree-npm-6.10.0-7880dab921-41fc6dd0cf.zip/node_modules/@typescript-eslint/typescript-estree/",\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-typescript-estree-npm-8.54.0-643fee1e58-3a545037c6.zip/node_modules/@typescript-eslint/typescript-estree/",\ "packageDependencies": [\ - ["@typescript-eslint/typescript-estree", "npm:6.10.0"]\ + ["@typescript-eslint/typescript-estree", "npm:8.54.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:0c2ac79ebf72f4493d7516f3ee57421c8337be2bdf9498590055ee112e7fdf62dd0b817c13f6c8a030baf64dbe843920deec4c3c8ea8bd6888b7baf950492c3a#npm:5.55.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-891ed1ca66/0/cache/@typescript-eslint-typescript-estree-npm-5.55.0-aefc08af17-e6c51080c0.zip/node_modules/@typescript-eslint/typescript-estree/",\ + ["virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-f9171b24fe/0/cache/@typescript-eslint-typescript-estree-npm-8.54.0-643fee1e58-3a545037c6.zip/node_modules/@typescript-eslint/typescript-estree/",\ "packageDependencies": [\ ["@types/typescript", null],\ - ["@typescript-eslint/types", "npm:5.55.0"],\ - ["@typescript-eslint/typescript-estree", "virtual:0c2ac79ebf72f4493d7516f3ee57421c8337be2bdf9498590055ee112e7fdf62dd0b817c13f6c8a030baf64dbe843920deec4c3c8ea8bd6888b7baf950492c3a#npm:5.55.0"],\ - ["@typescript-eslint/visitor-keys", "npm:5.55.0"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["globby", "npm:11.1.0"],\ - ["is-glob", "npm:4.0.3"],\ + ["@typescript-eslint/project-service", "virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:8.54.0"],\ + ["@typescript-eslint/tsconfig-utils", "virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:8.54.0"],\ + ["@typescript-eslint/visitor-keys", "npm:8.54.0"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["minimatch", "npm:9.0.5"],\ ["semver", "npm:7.5.3"],\ - ["tsutils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:3.21.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"]\ + ["tinyglobby", "npm:0.2.15"],\ + ["ts-api-utils", "virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:2.4.0"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"]\ ],\ "packagePeers": [\ "@types/typescript",\ @@ -5149,18 +5526,18 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:67e332304c8830574d5d9be2a388885a47a9962cf1d2441a6ada47207b10c98d9a1a1914d73816338b986563032864745d812b3a7df145ee8f3bb51baa4027e5#npm:5.55.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-ad07d3460a/0/cache/@typescript-eslint-typescript-estree-npm-5.55.0-aefc08af17-e6c51080c0.zip/node_modules/@typescript-eslint/typescript-estree/",\ + ["virtual:b13453c6e327a35c05e8ce1283d4970e5e4619ba21a2fa8909367ea67136c23860ec34186acaf505374401498c777e7891702b73bbd3697c54d0993c3fd435cd#npm:6.10.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-4884f2aa86/0/cache/@typescript-eslint-typescript-estree-npm-6.10.0-7880dab921-41fc6dd0cf.zip/node_modules/@typescript-eslint/typescript-estree/",\ "packageDependencies": [\ ["@types/typescript", null],\ - ["@typescript-eslint/types", "npm:5.55.0"],\ - ["@typescript-eslint/typescript-estree", "virtual:67e332304c8830574d5d9be2a388885a47a9962cf1d2441a6ada47207b10c98d9a1a1914d73816338b986563032864745d812b3a7df145ee8f3bb51baa4027e5#npm:5.55.0"],\ - ["@typescript-eslint/visitor-keys", "npm:5.55.0"],\ + ["@typescript-eslint/types", "npm:6.10.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:b13453c6e327a35c05e8ce1283d4970e5e4619ba21a2fa8909367ea67136c23860ec34186acaf505374401498c777e7891702b73bbd3697c54d0993c3fd435cd#npm:6.10.0"],\ + ["@typescript-eslint/visitor-keys", "npm:6.10.0"],\ ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ ["globby", "npm:11.1.0"],\ ["is-glob", "npm:4.0.3"],\ ["semver", "npm:7.5.3"],\ - ["tsutils", "virtual:ad07d3460ae416a99f304e6734121d5396603792c47f7c9a1b9c5c798d407da37779ac7289222241db922614d91f9d569b0f43bc10c027fcc720138b2f32e9fc#npm:3.21.0"],\ + ["ts-api-utils", "virtual:4884f2aa861da86c426c7089ed81a0a62b1c0338d3dd3b13ae03e14336a6aca2dd95612a024a0b64fa991e4dcc30ee6382e5fe33a6942b2990875fd837c701c8#npm:1.0.3"],\ ["typescript", null]\ ],\ "packagePeers": [\ @@ -5169,18 +5546,20 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:b13453c6e327a35c05e8ce1283d4970e5e4619ba21a2fa8909367ea67136c23860ec34186acaf505374401498c777e7891702b73bbd3697c54d0993c3fd435cd#npm:6.10.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-4884f2aa86/0/cache/@typescript-eslint-typescript-estree-npm-6.10.0-7880dab921-41fc6dd0cf.zip/node_modules/@typescript-eslint/typescript-estree/",\ + ["virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-typescript-estree-virtual-e23667a5b3/0/cache/@typescript-eslint-typescript-estree-npm-8.54.0-643fee1e58-3a545037c6.zip/node_modules/@typescript-eslint/typescript-estree/",\ "packageDependencies": [\ ["@types/typescript", null],\ - ["@typescript-eslint/types", "npm:6.10.0"],\ - ["@typescript-eslint/typescript-estree", "virtual:b13453c6e327a35c05e8ce1283d4970e5e4619ba21a2fa8909367ea67136c23860ec34186acaf505374401498c777e7891702b73bbd3697c54d0993c3fd435cd#npm:6.10.0"],\ - ["@typescript-eslint/visitor-keys", "npm:6.10.0"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["globby", "npm:11.1.0"],\ - ["is-glob", "npm:4.0.3"],\ + ["@typescript-eslint/project-service", "virtual:e23667a5b32248a12ae73c52027669f5b894be4fbb985cc67d024501c3bc7ea8a70b9e6820163ae197299cdf37bdeddcddb662f9f81d5cf5133ed55fc3b42995#npm:8.54.0"],\ + ["@typescript-eslint/tsconfig-utils", "virtual:e23667a5b32248a12ae73c52027669f5b894be4fbb985cc67d024501c3bc7ea8a70b9e6820163ae197299cdf37bdeddcddb662f9f81d5cf5133ed55fc3b42995#npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/visitor-keys", "npm:8.54.0"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["minimatch", "npm:9.0.5"],\ ["semver", "npm:7.5.3"],\ - ["ts-api-utils", "virtual:4884f2aa861da86c426c7089ed81a0a62b1c0338d3dd3b13ae03e14336a6aca2dd95612a024a0b64fa991e4dcc30ee6382e5fe33a6942b2990875fd837c701c8#npm:1.0.3"],\ + ["tinyglobby", "npm:0.2.15"],\ + ["ts-api-utils", "virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:2.4.0"],\ ["typescript", null]\ ],\ "packagePeers": [\ @@ -5191,17 +5570,17 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@typescript-eslint/utils", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-utils-npm-5.55.0-6a927fceb5-121c5fc48c.zip/node_modules/@typescript-eslint/utils/",\ + ["npm:6.10.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-utils-npm-6.10.0-38043b4e14-acf55bc231.zip/node_modules/@typescript-eslint/utils/",\ "packageDependencies": [\ - ["@typescript-eslint/utils", "npm:5.55.0"]\ + ["@typescript-eslint/utils", "npm:6.10.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["npm:6.10.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-utils-npm-6.10.0-38043b4e14-acf55bc231.zip/node_modules/@typescript-eslint/utils/",\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-utils-npm-8.54.0-c71ca4c1ce-9f88a2a7ab.zip/node_modules/@typescript-eslint/utils/",\ "packageDependencies": [\ - ["@typescript-eslint/utils", "npm:6.10.0"]\ + ["@typescript-eslint/utils", "npm:8.54.0"]\ ],\ "linkType": "SOFT"\ }],\ @@ -5225,38 +5604,29 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:5.55.0", {\ - "packageLocation": "./.yarn/__virtual__/@typescript-eslint-utils-virtual-67e332304c/0/cache/@typescript-eslint-utils-npm-5.55.0-6a927fceb5-121c5fc48c.zip/node_modules/@typescript-eslint/utils/",\ + ["virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/@typescript-eslint-utils-virtual-a33d3607ab/0/cache/@typescript-eslint-utils-npm-8.54.0-c71ca4c1ce-9f88a2a7ab.zip/node_modules/@typescript-eslint/utils/",\ "packageDependencies": [\ - ["@eslint-community/eslint-utils", "virtual:2fc5c501d26c4c2fbc6a1d931e87d32adb7d9118fbcd7303a7b7faae809112bde136383859a265761a47c2852a001b7b803bf80e734ffa8ddc2ca30c129d1d76#npm:4.4.0"],\ + ["@eslint-community/eslint-utils", "virtual:79c28034d94a28ec559d9137247270112d4bba82f5cf5320ba8f69e7c1dc984374b4c8c82e16031069e9919a8ce0b231c49891795c762408cc665fe7a8cd02ee#npm:4.9.1"],\ ["@types/eslint", null],\ - ["@types/json-schema", "npm:7.0.15"],\ - ["@types/semver", "npm:7.5.5"],\ - ["@typescript-eslint/scope-manager", "npm:5.55.0"],\ - ["@typescript-eslint/types", "npm:5.55.0"],\ - ["@typescript-eslint/typescript-estree", "virtual:67e332304c8830574d5d9be2a388885a47a9962cf1d2441a6ada47207b10c98d9a1a1914d73816338b986563032864745d812b3a7df145ee8f3bb51baa4027e5#npm:5.55.0"],\ - ["@typescript-eslint/utils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:5.55.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-scope", "npm:5.1.1"],\ - ["semver", "npm:7.5.3"]\ + ["@types/typescript", null],\ + ["@typescript-eslint/scope-manager", "npm:8.54.0"],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/utils", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["typescript", null]\ ],\ "packagePeers": [\ "@types/eslint",\ - "eslint"\ + "@types/typescript",\ + "eslint",\ + "typescript"\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@typescript-eslint/visitor-keys", [\ - ["npm:5.55.0", {\ - "packageLocation": "./.yarn/cache/@typescript-eslint-visitor-keys-npm-5.55.0-7f3c07beeb-5b6a0e4813.zip/node_modules/@typescript-eslint/visitor-keys/",\ - "packageDependencies": [\ - ["@typescript-eslint/types", "npm:5.55.0"],\ - ["@typescript-eslint/visitor-keys", "npm:5.55.0"],\ - ["eslint-visitor-keys", "npm:3.4.3"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:6.10.0", {\ "packageLocation": "./.yarn/cache/@typescript-eslint-visitor-keys-npm-6.10.0-6783c90d56-17a6962e10.zip/node_modules/@typescript-eslint/visitor-keys/",\ "packageDependencies": [\ @@ -5265,100 +5635,272 @@ const RAW_RUNTIME_STATE = ["eslint-visitor-keys", "npm:3.4.3"]\ ],\ "linkType": "HARD"\ - }]\ - ]],\ - ["@ungap/structured-clone", [\ - ["npm:1.2.0", {\ - "packageLocation": "./.yarn/cache/@ungap-structured-clone-npm-1.2.0-648f0b82e0-c6fe89a505.zip/node_modules/@ungap/structured-clone/",\ + }],\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/@typescript-eslint-visitor-keys-npm-8.54.0-b1e3d0cbc5-cca5380ee3.zip/node_modules/@typescript-eslint/visitor-keys/",\ "packageDependencies": [\ - ["@ungap/structured-clone", "npm:1.2.0"]\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/visitor-keys", "npm:8.54.0"],\ + ["eslint-visitor-keys", "npm:4.2.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/ast", [\ - ["npm:1.12.1", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-ast-npm-1.12.1-3ff9ea1c0e-a775b05594.zip/node_modules/@webassemblyjs/ast/",\ + ["@unrs/resolver-binding-android-arm-eabi", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-android-arm-eabi-npm-1.11.1-06ce6674af/node_modules/@unrs/resolver-binding-android-arm-eabi/",\ "packageDependencies": [\ - ["@webassemblyjs/ast", "npm:1.12.1"],\ - ["@webassemblyjs/helper-numbers", "npm:1.11.6"],\ - ["@webassemblyjs/helper-wasm-bytecode", "npm:1.11.6"]\ + ["@unrs/resolver-binding-android-arm-eabi", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/floating-point-hex-parser", [\ - ["npm:1.11.6", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-floating-point-hex-parser-npm-1.11.6-3a9928fc76-29b0875884.zip/node_modules/@webassemblyjs/floating-point-hex-parser/",\ + ["@unrs/resolver-binding-android-arm64", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-android-arm64-npm-1.11.1-1f130db68b/node_modules/@unrs/resolver-binding-android-arm64/",\ "packageDependencies": [\ - ["@webassemblyjs/floating-point-hex-parser", "npm:1.11.6"]\ + ["@unrs/resolver-binding-android-arm64", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/helper-api-error", [\ - ["npm:1.11.6", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-helper-api-error-npm-1.11.6-75f6275ff4-e8563df851.zip/node_modules/@webassemblyjs/helper-api-error/",\ + ["@unrs/resolver-binding-darwin-arm64", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-darwin-arm64-npm-1.11.1-c78d4bd2cb/node_modules/@unrs/resolver-binding-darwin-arm64/",\ "packageDependencies": [\ - ["@webassemblyjs/helper-api-error", "npm:1.11.6"]\ + ["@unrs/resolver-binding-darwin-arm64", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/helper-buffer", [\ - ["npm:1.12.1", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-helper-buffer-npm-1.12.1-d025434a45-1d8705daa4.zip/node_modules/@webassemblyjs/helper-buffer/",\ + ["@unrs/resolver-binding-darwin-x64", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-darwin-x64-npm-1.11.1-8b085bc124/node_modules/@unrs/resolver-binding-darwin-x64/",\ "packageDependencies": [\ - ["@webassemblyjs/helper-buffer", "npm:1.12.1"]\ + ["@unrs/resolver-binding-darwin-x64", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/helper-numbers", [\ - ["npm:1.11.6", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-helper-numbers-npm-1.11.6-819ddab1da-9ffd258ad8.zip/node_modules/@webassemblyjs/helper-numbers/",\ + ["@unrs/resolver-binding-freebsd-x64", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-freebsd-x64-npm-1.11.1-1fa015e147/node_modules/@unrs/resolver-binding-freebsd-x64/",\ "packageDependencies": [\ - ["@webassemblyjs/floating-point-hex-parser", "npm:1.11.6"],\ - ["@webassemblyjs/helper-api-error", "npm:1.11.6"],\ - ["@webassemblyjs/helper-numbers", "npm:1.11.6"],\ - ["@xtuc/long", "npm:4.2.2"]\ + ["@unrs/resolver-binding-freebsd-x64", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/helper-wasm-bytecode", [\ - ["npm:1.11.6", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-helper-wasm-bytecode-npm-1.11.6-3bc23747de-4ebf03e9c1.zip/node_modules/@webassemblyjs/helper-wasm-bytecode/",\ + ["@unrs/resolver-binding-linux-arm-gnueabihf", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-arm-gnueabihf-npm-1.11.1-5392340ab8/node_modules/@unrs/resolver-binding-linux-arm-gnueabihf/",\ "packageDependencies": [\ - ["@webassemblyjs/helper-wasm-bytecode", "npm:1.11.6"]\ + ["@unrs/resolver-binding-linux-arm-gnueabihf", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/helper-wasm-section", [\ - ["npm:1.12.1", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-helper-wasm-section-npm-1.12.1-cd0e2f1eab-e91e6b2811.zip/node_modules/@webassemblyjs/helper-wasm-section/",\ + ["@unrs/resolver-binding-linux-arm-musleabihf", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-arm-musleabihf-npm-1.11.1-a767cbd98d/node_modules/@unrs/resolver-binding-linux-arm-musleabihf/",\ "packageDependencies": [\ - ["@webassemblyjs/ast", "npm:1.12.1"],\ - ["@webassemblyjs/helper-buffer", "npm:1.12.1"],\ - ["@webassemblyjs/helper-wasm-bytecode", "npm:1.11.6"],\ - ["@webassemblyjs/helper-wasm-section", "npm:1.12.1"],\ - ["@webassemblyjs/wasm-gen", "npm:1.12.1"]\ + ["@unrs/resolver-binding-linux-arm-musleabihf", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/ieee754", [\ - ["npm:1.11.6", {\ - "packageLocation": "./.yarn/cache/@webassemblyjs-ieee754-npm-1.11.6-95c92f446a-13574b8e41.zip/node_modules/@webassemblyjs/ieee754/",\ + ["@unrs/resolver-binding-linux-arm64-gnu", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-arm64-gnu-npm-1.11.1-9df43e91b5/node_modules/@unrs/resolver-binding-linux-arm64-gnu/",\ "packageDependencies": [\ - ["@webassemblyjs/ieee754", "npm:1.11.6"],\ - ["@xtuc/ieee754", "npm:1.2.0"]\ + ["@unrs/resolver-binding-linux-arm64-gnu", "npm:1.11.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["@webassemblyjs/leb128", [\ + ["@unrs/resolver-binding-linux-arm64-musl", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-arm64-musl-npm-1.11.1-56bc63ba54/node_modules/@unrs/resolver-binding-linux-arm64-musl/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-linux-arm64-musl", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-linux-ppc64-gnu", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-ppc64-gnu-npm-1.11.1-0b8bf102a2/node_modules/@unrs/resolver-binding-linux-ppc64-gnu/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-linux-ppc64-gnu", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-linux-riscv64-gnu", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-riscv64-gnu-npm-1.11.1-320ad6c64e/node_modules/@unrs/resolver-binding-linux-riscv64-gnu/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-linux-riscv64-gnu", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-linux-riscv64-musl", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-riscv64-musl-npm-1.11.1-26046daaf7/node_modules/@unrs/resolver-binding-linux-riscv64-musl/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-linux-riscv64-musl", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-linux-s390x-gnu", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-s390x-gnu-npm-1.11.1-9f00ee4143/node_modules/@unrs/resolver-binding-linux-s390x-gnu/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-linux-s390x-gnu", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-linux-x64-gnu", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-x64-gnu-npm-1.11.1-93a00570de/node_modules/@unrs/resolver-binding-linux-x64-gnu/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-linux-x64-gnu", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-linux-x64-musl", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-linux-x64-musl-npm-1.11.1-e50d25f974/node_modules/@unrs/resolver-binding-linux-x64-musl/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-linux-x64-musl", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-wasm32-wasi", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-wasm32-wasi-npm-1.11.1-bad5761d71/node_modules/@unrs/resolver-binding-wasm32-wasi/",\ + "packageDependencies": [\ + ["@napi-rs/wasm-runtime", "npm:0.2.12"],\ + ["@unrs/resolver-binding-wasm32-wasi", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-win32-arm64-msvc", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-win32-arm64-msvc-npm-1.11.1-88c7759a88/node_modules/@unrs/resolver-binding-win32-arm64-msvc/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-win32-arm64-msvc", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-win32-ia32-msvc", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-win32-ia32-msvc-npm-1.11.1-5679839eac/node_modules/@unrs/resolver-binding-win32-ia32-msvc/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-win32-ia32-msvc", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@unrs/resolver-binding-win32-x64-msvc", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/@unrs-resolver-binding-win32-x64-msvc-npm-1.11.1-4121c06678/node_modules/@unrs/resolver-binding-win32-x64-msvc/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-win32-x64-msvc", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/ast", [\ + ["npm:1.12.1", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-ast-npm-1.12.1-3ff9ea1c0e-a775b05594.zip/node_modules/@webassemblyjs/ast/",\ + "packageDependencies": [\ + ["@webassemblyjs/ast", "npm:1.12.1"],\ + ["@webassemblyjs/helper-numbers", "npm:1.11.6"],\ + ["@webassemblyjs/helper-wasm-bytecode", "npm:1.11.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/floating-point-hex-parser", [\ + ["npm:1.11.6", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-floating-point-hex-parser-npm-1.11.6-3a9928fc76-29b0875884.zip/node_modules/@webassemblyjs/floating-point-hex-parser/",\ + "packageDependencies": [\ + ["@webassemblyjs/floating-point-hex-parser", "npm:1.11.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/helper-api-error", [\ + ["npm:1.11.6", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-helper-api-error-npm-1.11.6-75f6275ff4-e8563df851.zip/node_modules/@webassemblyjs/helper-api-error/",\ + "packageDependencies": [\ + ["@webassemblyjs/helper-api-error", "npm:1.11.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/helper-buffer", [\ + ["npm:1.12.1", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-helper-buffer-npm-1.12.1-d025434a45-1d8705daa4.zip/node_modules/@webassemblyjs/helper-buffer/",\ + "packageDependencies": [\ + ["@webassemblyjs/helper-buffer", "npm:1.12.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/helper-numbers", [\ + ["npm:1.11.6", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-helper-numbers-npm-1.11.6-819ddab1da-9ffd258ad8.zip/node_modules/@webassemblyjs/helper-numbers/",\ + "packageDependencies": [\ + ["@webassemblyjs/floating-point-hex-parser", "npm:1.11.6"],\ + ["@webassemblyjs/helper-api-error", "npm:1.11.6"],\ + ["@webassemblyjs/helper-numbers", "npm:1.11.6"],\ + ["@xtuc/long", "npm:4.2.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/helper-wasm-bytecode", [\ + ["npm:1.11.6", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-helper-wasm-bytecode-npm-1.11.6-3bc23747de-4ebf03e9c1.zip/node_modules/@webassemblyjs/helper-wasm-bytecode/",\ + "packageDependencies": [\ + ["@webassemblyjs/helper-wasm-bytecode", "npm:1.11.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/helper-wasm-section", [\ + ["npm:1.12.1", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-helper-wasm-section-npm-1.12.1-cd0e2f1eab-e91e6b2811.zip/node_modules/@webassemblyjs/helper-wasm-section/",\ + "packageDependencies": [\ + ["@webassemblyjs/ast", "npm:1.12.1"],\ + ["@webassemblyjs/helper-buffer", "npm:1.12.1"],\ + ["@webassemblyjs/helper-wasm-bytecode", "npm:1.11.6"],\ + ["@webassemblyjs/helper-wasm-section", "npm:1.12.1"],\ + ["@webassemblyjs/wasm-gen", "npm:1.12.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/ieee754", [\ + ["npm:1.11.6", {\ + "packageLocation": "./.yarn/cache/@webassemblyjs-ieee754-npm-1.11.6-95c92f446a-13574b8e41.zip/node_modules/@webassemblyjs/ieee754/",\ + "packageDependencies": [\ + ["@webassemblyjs/ieee754", "npm:1.11.6"],\ + ["@xtuc/ieee754", "npm:1.2.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@webassemblyjs/leb128", [\ ["npm:1.11.6", {\ "packageLocation": "./.yarn/cache/@webassemblyjs-leb128-npm-1.11.6-697d62da2e-ec3b72db0e.zip/node_modules/@webassemblyjs/leb128/",\ "packageDependencies": [\ @@ -5853,7 +6395,7 @@ const RAW_RUNTIME_STATE = ["p-limit", "npm:2.3.0"],\ ["semver", "npm:7.5.3"],\ ["strip-ansi", "npm:6.0.1"],\ - ["tar", "npm:7.5.6"],\ + ["tar", "npm:7.5.7"],\ ["tinylogic", "npm:2.0.0"],\ ["treeify", "npm:1.1.0"],\ ["tslib", "npm:2.6.2"],\ @@ -6037,6 +6579,13 @@ const RAW_RUNTIME_STATE = ["acorn", "npm:8.12.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:8.15.0", {\ + "packageLocation": "./.yarn/cache/acorn-npm-8.15.0-0764cf600e-77f2de5051.zip/node_modules/acorn/",\ + "packageDependencies": [\ + ["acorn", "npm:8.15.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["acorn-import-attributes", [\ @@ -6069,6 +6618,19 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["virtual:9633b00e55c5aebf81b0127f50addd44705c175a47a287258963782da8f9f4e66c2da6640a60ed2826e19f024f73cd554a58729ee1644f93800bbd0d7b7ddd79#npm:5.3.2", {\ + "packageLocation": "./.yarn/__virtual__/acorn-jsx-virtual-642bf0c873/0/cache/acorn-jsx-npm-5.3.2-d7594599ea-d4371eaef7.zip/node_modules/acorn-jsx/",\ + "packageDependencies": [\ + ["@types/acorn", null],\ + ["acorn", "npm:8.15.0"],\ + ["acorn-jsx", "virtual:9633b00e55c5aebf81b0127f50addd44705c175a47a287258963782da8f9f4e66c2da6640a60ed2826e19f024f73cd554a58729ee1644f93800bbd0d7b7ddd79#npm:5.3.2"]\ + ],\ + "packagePeers": [\ + "@types/acorn",\ + "acorn"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:a50722a5a9326b6a5f12350c494c4db3aa0f4caeac45e3e9e5fe071da20014ecfe738fe2ebe2c9c98abae81a4ea86b42f56d776b3bd5ec37f9ad3670c242b242#npm:5.3.2", {\ "packageLocation": "./.yarn/__virtual__/acorn-jsx-virtual-834321b202/0/cache/acorn-jsx-npm-5.3.2-d7594599ea-d4371eaef7.zip/node_modules/acorn-jsx/",\ "packageDependencies": [\ @@ -6418,6 +6980,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["aria-query", [\ + ["npm:5.3.2", {\ + "packageLocation": "./.yarn/cache/aria-query-npm-5.3.2-78632ac5c5-b2fe9bc98b.zip/node_modules/aria-query/",\ + "packageDependencies": [\ + ["aria-query", "npm:5.3.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["array-buffer-byte-length", [\ ["npm:1.0.0", {\ "packageLocation": "./.yarn/cache/array-buffer-byte-length-npm-1.0.0-331671f28a-044e101ce1.zip/node_modules/array-buffer-byte-length/",\ @@ -6427,6 +6998,15 @@ const RAW_RUNTIME_STATE = ["is-array-buffer", "npm:3.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/array-buffer-byte-length-npm-1.0.2-c2be1e97e0-0ae3786195.zip/node_modules/array-buffer-byte-length/",\ + "packageDependencies": [\ + ["array-buffer-byte-length", "npm:1.0.2"],\ + ["call-bound", "npm:1.0.4"],\ + ["is-array-buffer", "npm:3.0.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["array-differ", [\ @@ -6448,15 +7028,18 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["array-includes", [\ - ["npm:3.1.7", {\ - "packageLocation": "./.yarn/cache/array-includes-npm-3.1.7-d32a5ee179-856a8be5d1.zip/node_modules/array-includes/",\ + ["npm:3.1.9", {\ + "packageLocation": "./.yarn/cache/array-includes-npm-3.1.9-b081638946-8bfe9a58df.zip/node_modules/array-includes/",\ "packageDependencies": [\ - ["array-includes", "npm:3.1.7"],\ - ["call-bind", "npm:1.0.5"],\ + ["array-includes", "npm:3.1.9"],\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ ["define-properties", "npm:1.2.1"],\ - ["es-abstract", "npm:1.22.3"],\ - ["get-intrinsic", "npm:1.2.2"],\ - ["is-string", "npm:1.0.7"]\ + ["es-abstract", "npm:1.24.1"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["get-intrinsic", "npm:1.3.0"],\ + ["is-string", "npm:1.1.1"],\ + ["math-intrinsics", "npm:1.1.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -6470,29 +7053,46 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["array.prototype.findlast", [\ + ["npm:1.2.5", {\ + "packageLocation": "./.yarn/cache/array.prototype.findlast-npm-1.2.5-316cb71d39-7dffcc665a.zip/node_modules/array.prototype.findlast/",\ + "packageDependencies": [\ + ["array.prototype.findlast", "npm:1.2.5"],\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["es-shim-unscopables", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["array.prototype.findlastindex", [\ - ["npm:1.2.3", {\ - "packageLocation": "./.yarn/cache/array.prototype.findlastindex-npm-1.2.3-2a36f4417b-063cbab8ee.zip/node_modules/array.prototype.findlastindex/",\ + ["npm:1.2.6", {\ + "packageLocation": "./.yarn/cache/array.prototype.findlastindex-npm-1.2.6-65fef3f969-5ddb6420e8.zip/node_modules/array.prototype.findlastindex/",\ "packageDependencies": [\ - ["array.prototype.findlastindex", "npm:1.2.3"],\ - ["call-bind", "npm:1.0.5"],\ + ["array.prototype.findlastindex", "npm:1.2.6"],\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ ["define-properties", "npm:1.2.1"],\ - ["es-abstract", "npm:1.22.3"],\ - ["es-shim-unscopables", "npm:1.0.2"],\ - ["get-intrinsic", "npm:1.2.2"]\ + ["es-abstract", "npm:1.24.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["es-shim-unscopables", "npm:1.1.0"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["array.prototype.flat", [\ - ["npm:1.3.2", {\ - "packageLocation": "./.yarn/cache/array.prototype.flat-npm-1.3.2-350729f7f4-d9d2f6f275.zip/node_modules/array.prototype.flat/",\ + ["npm:1.3.3", {\ + "packageLocation": "./.yarn/cache/array.prototype.flat-npm-1.3.3-51377719d9-f9b992fa07.zip/node_modules/array.prototype.flat/",\ "packageDependencies": [\ - ["array.prototype.flat", "npm:1.3.2"],\ - ["call-bind", "npm:1.0.5"],\ + ["array.prototype.flat", "npm:1.3.3"],\ + ["call-bind", "npm:1.0.8"],\ ["define-properties", "npm:1.2.1"],\ - ["es-abstract", "npm:1.22.3"],\ - ["es-shim-unscopables", "npm:1.0.2"]\ + ["es-abstract", "npm:1.24.1"],\ + ["es-shim-unscopables", "npm:1.1.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -6508,6 +7108,31 @@ const RAW_RUNTIME_STATE = ["es-shim-unscopables", "npm:1.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.3.3", {\ + "packageLocation": "./.yarn/cache/array.prototype.flatmap-npm-1.3.3-db3afdbfda-473534573a.zip/node_modules/array.prototype.flatmap/",\ + "packageDependencies": [\ + ["array.prototype.flatmap", "npm:1.3.3"],\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-shim-unscopables", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["array.prototype.tosorted", [\ + ["npm:1.1.4", {\ + "packageLocation": "./.yarn/cache/array.prototype.tosorted-npm-1.1.4-c1fc919434-874694e5d5.zip/node_modules/array.prototype.tosorted/",\ + "packageDependencies": [\ + ["array.prototype.tosorted", "npm:1.1.4"],\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-shim-unscopables", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["arraybuffer.prototype.slice", [\ @@ -6524,6 +7149,20 @@ const RAW_RUNTIME_STATE = ["is-shared-array-buffer", "npm:1.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.4", {\ + "packageLocation": "./.yarn/cache/arraybuffer.prototype.slice-npm-1.0.4-01f62a9713-4821ebdfe7.zip/node_modules/arraybuffer.prototype.slice/",\ + "packageDependencies": [\ + ["array-buffer-byte-length", "npm:1.0.2"],\ + ["arraybuffer.prototype.slice", "npm:1.0.4"],\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["is-array-buffer", "npm:3.0.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["arrify", [\ @@ -6609,6 +7248,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["ast-types-flow", [\ + ["npm:0.0.8", {\ + "packageLocation": "./.yarn/cache/ast-types-flow-npm-0.0.8-d5c457c18e-85a1c24af4.zip/node_modules/ast-types-flow/",\ + "packageDependencies": [\ + ["ast-types-flow", "npm:0.0.8"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["astral-regex", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/astral-regex-npm-2.0.0-f30d866aab-876231688c.zip/node_modules/astral-regex/",\ @@ -6718,6 +7366,24 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["axe-core", [\ + ["npm:4.11.1", {\ + "packageLocation": "./.yarn/cache/axe-core-npm-4.11.1-87a6aa2514-bbc8e89592.zip/node_modules/axe-core/",\ + "packageDependencies": [\ + ["axe-core", "npm:4.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["axobject-query", [\ + ["npm:4.1.0", {\ + "packageLocation": "./.yarn/cache/axobject-query-npm-4.1.0-9703554323-e275dea9b6.zip/node_modules/axobject-query/",\ + "packageDependencies": [\ + ["axobject-query", "npm:4.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["b4a", [\ ["npm:1.6.7", {\ "packageLocation": "./.yarn/cache/b4a-npm-1.6.7-a52d28b4e2-1ac056e3bc.zip/node_modules/b4a/",\ @@ -6727,39 +7393,11 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["babel-eslint", [\ - ["npm:10.1.0", {\ - "packageLocation": "./.yarn/cache/babel-eslint-npm-10.1.0-6a6d2b1533-dc5dd948f8.zip/node_modules/babel-eslint/",\ + ["babel-loader", [\ + ["npm:9.1.3", {\ + "packageLocation": "./.yarn/cache/babel-loader-npm-9.1.3-cbf4da21df-7086e67827.zip/node_modules/babel-loader/",\ "packageDependencies": [\ - ["babel-eslint", "npm:10.1.0"]\ - ],\ - "linkType": "SOFT"\ - }],\ - ["virtual:27dae49067a60fa65fec6e1c3adad1497d0dda3f71eda711624109131ff3b7d1061a20f55e89b5a0a219da1f7a0a1a0a76bc414d36870315bd60acf5bdcb7f55#npm:10.1.0", {\ - "packageLocation": "./.yarn/__virtual__/babel-eslint-virtual-ff1372ed3f/0/cache/babel-eslint-npm-10.1.0-6a6d2b1533-dc5dd948f8.zip/node_modules/babel-eslint/",\ - "packageDependencies": [\ - ["@babel/code-frame", "npm:7.22.13"],\ - ["@babel/parser", "npm:7.23.3"],\ - ["@babel/traverse", "npm:7.23.3"],\ - ["@babel/types", "npm:7.23.3"],\ - ["@types/eslint", null],\ - ["babel-eslint", "virtual:27dae49067a60fa65fec6e1c3adad1497d0dda3f71eda711624109131ff3b7d1061a20f55e89b5a0a219da1f7a0a1a0a76bc414d36870315bd60acf5bdcb7f55#npm:10.1.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-visitor-keys", "npm:1.3.0"],\ - ["resolve", "patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d"]\ - ],\ - "packagePeers": [\ - "@types/eslint",\ - "eslint"\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["babel-loader", [\ - ["npm:9.1.3", {\ - "packageLocation": "./.yarn/cache/babel-loader-npm-9.1.3-cbf4da21df-7086e67827.zip/node_modules/babel-loader/",\ - "packageDependencies": [\ - ["babel-loader", "npm:9.1.3"]\ + ["babel-loader", "npm:9.1.3"]\ ],\ "linkType": "SOFT"\ }],\ @@ -7378,15 +8016,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["builtin-modules", [\ - ["npm:3.3.0", {\ - "packageLocation": "./.yarn/cache/builtin-modules-npm-3.3.0-db4f3d32de-62e063ab40.zip/node_modules/builtin-modules/",\ - "packageDependencies": [\ - ["builtin-modules", "npm:3.3.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["builtin-status-codes", [\ ["npm:3.0.0", {\ "packageLocation": "./.yarn/cache/builtin-status-codes-npm-3.0.0-e376b0580b-1119429cf4.zip/node_modules/builtin-status-codes/",\ @@ -7437,7 +8066,7 @@ const RAW_RUNTIME_STATE = ["minipass-pipeline", "npm:1.2.4"],\ ["p-map", "npm:4.0.0"],\ ["ssri", "npm:10.0.5"],\ - ["tar", "npm:7.5.6"],\ + ["tar", "npm:7.5.7"],\ ["unique-filename", "npm:3.0.0"]\ ],\ "linkType": "HARD"\ @@ -7687,7 +8316,7 @@ const RAW_RUNTIME_STATE = ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:7.1.1", {\ "packageLocation": "./.yarn/__virtual__/chai-as-promised-virtual-bf848fb7b9/0/cache/chai-as-promised-npm-7.1.1-cdc17e4612-5d9ecab37b.zip/node_modules/chai-as-promised/",\ "packageDependencies": [\ - ["@types/chai", "npm:4.2.22"],\ + ["@types/chai", "npm:4.3.20"],\ ["chai", "npm:4.3.10"],\ ["chai-as-promised", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:7.1.1"],\ ["check-error", "npm:1.0.3"]\ @@ -8315,6 +8944,13 @@ const RAW_RUNTIME_STATE = ["comment-parser", "npm:1.4.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.4.5", {\ + "packageLocation": "./.yarn/cache/comment-parser-npm-1.4.5-f67638c027-4b5cacc7ab.zip/node_modules/comment-parser/",\ + "packageDependencies": [\ + ["comment-parser", "npm:1.4.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["common-ancestor-path", [\ @@ -8365,10 +9001,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["confusing-browser-globals", [\ - ["npm:1.0.10", {\ - "packageLocation": "./.yarn/cache/confusing-browser-globals-npm-1.0.10-ecb768852b-7ccdc44c2c.zip/node_modules/confusing-browser-globals/",\ + ["npm:1.0.11", {\ + "packageLocation": "./.yarn/cache/confusing-browser-globals-npm-1.0.11-b3ff8e9483-3afc635abd.zip/node_modules/confusing-browser-globals/",\ "packageDependencies": [\ - ["confusing-browser-globals", "npm:1.0.10"]\ + ["confusing-browser-globals", "npm:1.0.11"]\ ],\ "linkType": "HARD"\ }]\ @@ -8840,6 +9476,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["damerau-levenshtein", [\ + ["npm:1.0.8", {\ + "packageLocation": "./.yarn/cache/damerau-levenshtein-npm-1.0.8-bda7311c69-f4eba1c901.zip/node_modules/damerau-levenshtein/",\ + "packageDependencies": [\ + ["damerau-levenshtein", "npm:1.0.8"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["dargs", [\ ["npm:7.0.0", {\ "packageLocation": "./.yarn/cache/dargs-npm-7.0.0-62701e0c7a-b8f1e3cba5.zip/node_modules/dargs/",\ @@ -8864,14 +9509,12 @@ const RAW_RUNTIME_STATE = ["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\ ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["@dashevo/withdrawals-contract", "workspace:packages/withdrawals-contract"],\ - ["@types/chai", "npm:4.2.22"],\ + ["@types/chai", "npm:4.3.20"],\ ["@types/dirty-chai", "npm:2.0.2"],\ - ["@types/mocha", "npm:8.2.3"],\ - ["@types/node", "npm:14.17.34"],\ + ["@types/mocha", "npm:10.0.10"],\ + ["@types/node", "npm:20.19.30"],\ ["@types/sinon", "npm:9.0.11"],\ ["@types/sinon-chai", "npm:3.2.5"],\ - ["@typescript-eslint/eslint-plugin", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["@typescript-eslint/parser", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ ["@yarnpkg/pnpify", "npm:4.0.0-rc.42"],\ ["assert", "npm:2.0.0"],\ ["browserify-zlib", "npm:0.2.0"],\ @@ -8884,10 +9527,7 @@ const RAW_RUNTIME_STATE = ["dash", "workspace:packages/js-dash-sdk"],\ ["dirty-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.0.1"],\ ["dotenv-safe", "npm:8.2.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:15.0.0"],\ - ["eslint-config-airbnb-typescript", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:17.0.0"],\ - ["eslint-plugin-import", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["events", "npm:3.3.0"],\ ["https-browserify", "npm:1.0.0"],\ ["karma", "npm:6.4.3"],\ @@ -8916,7 +9556,7 @@ const RAW_RUNTIME_STATE = ["ts-mock-imports", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:1.3.8"],\ ["ts-node", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:10.9.2"],\ ["tsd", "npm:0.28.1"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["url", "npm:0.11.3"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.94.0"],\ @@ -8931,7 +9571,6 @@ const RAW_RUNTIME_STATE = "packageLocation": "./packages/dashmate/",\ "packageDependencies": [\ ["@babel/core", "npm:7.26.10"],\ - ["@babel/eslint-parser", "virtual:6c6296bde00603e266f7d80babe1e01aa0c19f626934f58fe08f890a291bb1a38fcee25bf30c24857d5cfba290f01209decc48384318fd6815c5a514cb48be25#npm:7.26.10"],\ ["@dashevo/bls", "npm:1.2.9"],\ ["@dashevo/dapi-client", "workspace:packages/js-dapi-client"],\ ["@dashevo/dashcore-lib", "npm:0.22.0"],\ @@ -8957,9 +9596,7 @@ const RAW_RUNTIME_STATE = ["dot", "npm:1.1.3"],\ ["dotenv", "npm:8.6.0"],\ ["enquirer", "https://github.com/dashpay/enquirer.git#commit=86aaef0b1c82dfaa3436775e6b37de310eeb94f5"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["glob", "npm:10.4.1"],\ ["globby", "npm:11.1.0"],\ ["hasbin", "npm:1.2.3"],\ @@ -8984,12 +9621,48 @@ const RAW_RUNTIME_STATE = ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"],\ ["systeminformation", "npm:5.27.14"],\ ["table", "npm:6.8.1"],\ - ["tar", "npm:7.5.6"],\ + ["tar", "npm:7.5.7"],\ ["wrap-ansi", "npm:7.0.0"]\ ],\ "linkType": "SOFT"\ }]\ ]],\ + ["data-view-buffer", [\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/data-view-buffer-npm-1.0.2-93c9247e37-c10b155a4e.zip/node_modules/data-view-buffer/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["data-view-buffer", "npm:1.0.2"],\ + ["es-errors", "npm:1.3.0"],\ + ["is-data-view", "npm:1.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["data-view-byte-length", [\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/data-view-byte-length-npm-1.0.2-96d312fb9c-2a47055fcf.zip/node_modules/data-view-byte-length/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["data-view-byte-length", "npm:1.0.2"],\ + ["es-errors", "npm:1.3.0"],\ + ["is-data-view", "npm:1.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["data-view-byte-offset", [\ + ["npm:1.0.1", {\ + "packageLocation": "./.yarn/cache/data-view-byte-offset-npm-1.0.1-315a12a556-fa3bdfa096.zip/node_modules/data-view-byte-offset/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["data-view-byte-offset", "npm:1.0.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["is-data-view", "npm:1.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["date-format", [\ ["npm:4.0.13", {\ "packageLocation": "./.yarn/cache/date-format-npm-4.0.13-64e384acc1-a53b77c10e.zip/node_modules/date-format/",\ @@ -9051,6 +9724,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:4.4.3", {\ + "packageLocation": "./.yarn/cache/debug-npm-4.4.3-0105c6123a-9ada3434ea.zip/node_modules/debug/",\ + "packageDependencies": [\ + ["debug", "npm:4.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:02719845fd5201c955bdd7a997ac097487e4abbecfc5636e22f31b749d9380689c8965647293b3e329ccc5fe1790fddb1d7f8791f5385e4538cbcf7c463cfc82#npm:4.3.4", {\ "packageLocation": "./.yarn/__virtual__/debug-virtual-8dcd8821e8/0/cache/debug-npm-4.3.4-4513954577-0073c3bcbd.zip/node_modules/debug/",\ "packageDependencies": [\ @@ -9107,6 +9787,20 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ + ["virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3", {\ + "packageLocation": "./.yarn/__virtual__/debug-virtual-d3365303ea/0/cache/debug-npm-4.4.3-0105c6123a-9ada3434ea.zip/node_modules/debug/",\ + "packageDependencies": [\ + ["@types/supports-color", null],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["ms", "npm:2.1.3"],\ + ["supports-color", null]\ + ],\ + "packagePeers": [\ + "@types/supports-color",\ + "supports-color"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:7a0505537f63825f62aaaf982168c2b7c1e816756656d44af98202b8d07990e163024e7dadf5587aa11d691887401ca8792ff06467da4d479c747705c9e87544#npm:4.3.5", {\ "packageLocation": "./.yarn/__virtual__/debug-virtual-e443f3d004/0/cache/debug-npm-4.3.5-b5001f59b7-cb6eab424c.zip/node_modules/debug/",\ "packageDependencies": [\ @@ -9450,7 +10144,7 @@ const RAW_RUNTIME_STATE = ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.0.1", {\ "packageLocation": "./.yarn/__virtual__/dirty-chai-virtual-776ab6e5e1/0/cache/dirty-chai-npm-2.0.1-acaf82c8df-b4f3d1ea01.zip/node_modules/dirty-chai/",\ "packageDependencies": [\ - ["@types/chai", "npm:4.2.22"],\ + ["@types/chai", "npm:4.3.20"],\ ["chai", "npm:4.3.10"],\ ["dirty-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.0.1"]\ ],\ @@ -9954,6 +10648,67 @@ const RAW_RUNTIME_STATE = ["which-typed-array", "npm:1.1.13"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.24.1", {\ + "packageLocation": "./.yarn/cache/es-abstract-npm-1.24.1-4503972a58-c84cb69eba.zip/node_modules/es-abstract/",\ + "packageDependencies": [\ + ["array-buffer-byte-length", "npm:1.0.2"],\ + ["arraybuffer.prototype.slice", "npm:1.0.4"],\ + ["available-typed-arrays", "npm:1.0.7"],\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["data-view-buffer", "npm:1.0.2"],\ + ["data-view-byte-length", "npm:1.0.2"],\ + ["data-view-byte-offset", "npm:1.0.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-define-property", "npm:1.0.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["es-set-tostringtag", "npm:2.1.0"],\ + ["es-to-primitive", "npm:1.3.0"],\ + ["function.prototype.name", "npm:1.1.8"],\ + ["get-intrinsic", "npm:1.3.0"],\ + ["get-proto", "npm:1.0.1"],\ + ["get-symbol-description", "npm:1.1.0"],\ + ["globalthis", "npm:1.0.4"],\ + ["gopd", "npm:1.2.0"],\ + ["has-property-descriptors", "npm:1.0.2"],\ + ["has-proto", "npm:1.2.0"],\ + ["has-symbols", "npm:1.1.0"],\ + ["hasown", "npm:2.0.2"],\ + ["internal-slot", "npm:1.1.0"],\ + ["is-array-buffer", "npm:3.0.5"],\ + ["is-callable", "npm:1.2.7"],\ + ["is-data-view", "npm:1.0.2"],\ + ["is-negative-zero", "npm:2.0.3"],\ + ["is-regex", "npm:1.2.1"],\ + ["is-set", "npm:2.0.3"],\ + ["is-shared-array-buffer", "npm:1.0.4"],\ + ["is-string", "npm:1.1.1"],\ + ["is-typed-array", "npm:1.1.15"],\ + ["is-weakref", "npm:1.1.1"],\ + ["math-intrinsics", "npm:1.1.0"],\ + ["object-inspect", "npm:1.13.4"],\ + ["object-keys", "npm:1.1.1"],\ + ["object.assign", "npm:4.1.7"],\ + ["own-keys", "npm:1.0.1"],\ + ["regexp.prototype.flags", "npm:1.5.4"],\ + ["safe-array-concat", "npm:1.1.3"],\ + ["safe-push-apply", "npm:1.0.0"],\ + ["safe-regex-test", "npm:1.1.0"],\ + ["set-proto", "npm:1.0.0"],\ + ["stop-iteration-iterator", "npm:1.1.0"],\ + ["string.prototype.trim", "npm:1.2.10"],\ + ["string.prototype.trimend", "npm:1.0.9"],\ + ["string.prototype.trimstart", "npm:1.0.8"],\ + ["typed-array-buffer", "npm:1.0.3"],\ + ["typed-array-byte-length", "npm:1.0.3"],\ + ["typed-array-byte-offset", "npm:1.0.4"],\ + ["typed-array-length", "npm:1.0.7"],\ + ["unbox-primitive", "npm:1.1.0"],\ + ["which-typed-array", "npm:1.1.20"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["es-define-property", [\ @@ -9974,6 +10729,31 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["es-iterator-helpers", [\ + ["npm:1.2.2", {\ + "packageLocation": "./.yarn/cache/es-iterator-helpers-npm-1.2.2-470224dac7-17b5b2834c.zip/node_modules/es-iterator-helpers/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-iterator-helpers", "npm:1.2.2"],\ + ["es-set-tostringtag", "npm:2.1.0"],\ + ["function-bind", "npm:1.1.2"],\ + ["get-intrinsic", "npm:1.3.0"],\ + ["globalthis", "npm:1.0.4"],\ + ["gopd", "npm:1.2.0"],\ + ["has-property-descriptors", "npm:1.0.2"],\ + ["has-proto", "npm:1.2.0"],\ + ["has-symbols", "npm:1.1.0"],\ + ["internal-slot", "npm:1.1.0"],\ + ["iterator.prototype", "npm:1.1.5"],\ + ["safe-array-concat", "npm:1.1.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["es-module-lexer", [\ ["npm:1.5.4", {\ "packageLocation": "./.yarn/cache/es-module-lexer-npm-1.5.4-b52b96b8fc-f29c7c97a5.zip/node_modules/es-module-lexer/",\ @@ -10003,6 +10783,17 @@ const RAW_RUNTIME_STATE = ["has-tostringtag", "npm:1.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.1.0", {\ + "packageLocation": "./.yarn/cache/es-set-tostringtag-npm-2.1.0-4e55705d3f-86814bf8af.zip/node_modules/es-set-tostringtag/",\ + "packageDependencies": [\ + ["es-errors", "npm:1.3.0"],\ + ["es-set-tostringtag", "npm:2.1.0"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["hasown", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["es-shim-unscopables", [\ @@ -10013,6 +10804,14 @@ const RAW_RUNTIME_STATE = ["hasown", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/es-shim-unscopables-npm-1.1.0-13f1970345-c351f586c3.zip/node_modules/es-shim-unscopables/",\ + "packageDependencies": [\ + ["es-shim-unscopables", "npm:1.1.0"],\ + ["hasown", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["es-to-primitive", [\ @@ -10025,6 +10824,16 @@ const RAW_RUNTIME_STATE = ["is-symbol", "npm:1.0.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.3.0", {\ + "packageLocation": "./.yarn/cache/es-to-primitive-npm-1.3.0-470b6d51b6-17faf35c22.zip/node_modules/es-to-primitive/",\ + "packageDependencies": [\ + ["es-to-primitive", "npm:1.3.0"],\ + ["is-callable", "npm:1.2.7"],\ + ["is-date-object", "npm:1.1.0"],\ + ["is-symbol", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["es6-error", [\ @@ -10143,133 +10952,113 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["eslint", [\ - ["npm:8.53.0", {\ - "packageLocation": "./.yarn/cache/eslint-npm-8.53.0-2fc5c501d2-e305a71ce2.zip/node_modules/eslint/",\ - "packageDependencies": [\ - ["@eslint-community/eslint-utils", "virtual:2fc5c501d26c4c2fbc6a1d931e87d32adb7d9118fbcd7303a7b7faae809112bde136383859a265761a47c2852a001b7b803bf80e734ffa8ddc2ca30c129d1d76#npm:4.4.0"],\ - ["@eslint-community/regexpp", "npm:4.10.0"],\ - ["@eslint/eslintrc", "npm:2.1.3"],\ - ["@eslint/js", "npm:8.53.0"],\ - ["@humanwhocodes/config-array", "npm:0.11.13"],\ + ["npm:9.39.2", {\ + "packageLocation": "./.yarn/cache/eslint-npm-9.39.2-af6e824e47-53ff0e9c82.zip/node_modules/eslint/",\ + "packageDependencies": [\ + ["eslint", "npm:9.39.2"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2", {\ + "packageLocation": "./.yarn/__virtual__/eslint-virtual-85ad2db2a7/0/cache/eslint-npm-9.39.2-af6e824e47-53ff0e9c82.zip/node_modules/eslint/",\ + "packageDependencies": [\ + ["@eslint-community/eslint-utils", "virtual:79c28034d94a28ec559d9137247270112d4bba82f5cf5320ba8f69e7c1dc984374b4c8c82e16031069e9919a8ce0b231c49891795c762408cc665fe7a8cd02ee#npm:4.9.1"],\ + ["@eslint-community/regexpp", "npm:4.12.2"],\ + ["@eslint/config-array", "npm:0.21.1"],\ + ["@eslint/config-helpers", "npm:0.4.2"],\ + ["@eslint/core", "npm:0.17.0"],\ + ["@eslint/eslintrc", "npm:3.3.3"],\ + ["@eslint/js", "npm:9.39.2"],\ + ["@eslint/plugin-kit", "npm:0.4.1"],\ + ["@humanfs/node", "npm:0.16.7"],\ ["@humanwhocodes/module-importer", "npm:1.0.1"],\ - ["@nodelib/fs.walk", "npm:1.2.8"],\ - ["@ungap/structured-clone", "npm:1.2.0"],\ + ["@humanwhocodes/retry", "npm:0.4.3"],\ + ["@types/estree", "npm:1.0.8"],\ + ["@types/jiti", null],\ ["ajv", "npm:6.12.6"],\ ["chalk", "npm:4.1.2"],\ ["cross-spawn", "npm:7.0.5"],\ ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ - ["doctrine", "npm:3.0.0"],\ ["escape-string-regexp", "npm:4.0.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-scope", "npm:7.2.2"],\ - ["eslint-visitor-keys", "npm:3.4.3"],\ - ["espree", "npm:9.6.1"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-scope", "npm:8.4.0"],\ + ["eslint-visitor-keys", "npm:4.2.1"],\ + ["espree", "npm:10.4.0"],\ ["esquery", "npm:1.5.0"],\ ["esutils", "npm:2.0.3"],\ ["fast-deep-equal", "npm:3.1.3"],\ - ["file-entry-cache", "npm:6.0.1"],\ + ["file-entry-cache", "npm:8.0.0"],\ ["find-up", "npm:5.0.0"],\ ["glob-parent", "npm:6.0.2"],\ - ["globals", "npm:13.23.0"],\ - ["graphemer", "npm:1.4.0"],\ ["ignore", "npm:5.2.0"],\ ["imurmurhash", "npm:0.1.4"],\ ["is-glob", "npm:4.0.3"],\ - ["is-path-inside", "npm:3.0.3"],\ - ["js-yaml", "npm:4.1.1"],\ + ["jiti", null],\ ["json-stable-stringify-without-jsonify", "npm:1.0.1"],\ - ["levn", "npm:0.4.1"],\ ["lodash.merge", "npm:4.6.2"],\ ["minimatch", "npm:3.1.2"],\ ["natural-compare", "npm:1.4.0"],\ - ["optionator", "npm:0.9.3"],\ - ["strip-ansi", "npm:6.0.1"],\ - ["text-table", "npm:0.2.0"]\ + ["optionator", "npm:0.9.3"]\ + ],\ + "packagePeers": [\ + "@types/jiti",\ + "jiti"\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["eslint-config-airbnb-base", [\ - ["npm:15.0.0", {\ - "packageLocation": "./.yarn/cache/eslint-config-airbnb-base-npm-15.0.0-802837dd26-daa68a1dcb.zip/node_modules/eslint-config-airbnb-base/",\ + ["eslint-compat-utils", [\ + ["npm:0.5.1", {\ + "packageLocation": "./.yarn/cache/eslint-compat-utils-npm-0.5.1-f1f8ade49a-ac65ac1c61.zip/node_modules/eslint-compat-utils/",\ "packageDependencies": [\ - ["eslint-config-airbnb-base", "npm:15.0.0"]\ + ["eslint-compat-utils", "npm:0.5.1"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:15.0.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-config-airbnb-base-virtual-d3b85b0c35/0/cache/eslint-config-airbnb-base-npm-15.0.0-802837dd26-daa68a1dcb.zip/node_modules/eslint-config-airbnb-base/",\ - "packageDependencies": [\ - ["@types/eslint", null],\ - ["@types/eslint-plugin-import", null],\ - ["confusing-browser-globals", "npm:1.0.10"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.29.0"],\ - ["object.assign", "npm:4.1.4"],\ - ["object.entries", "npm:1.1.6"],\ - ["semver", "npm:7.5.3"]\ - ],\ - "packagePeers": [\ - "@types/eslint-plugin-import",\ - "@types/eslint",\ - "eslint-plugin-import",\ - "eslint"\ - ],\ - "linkType": "HARD"\ - }],\ - ["virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-config-airbnb-base-virtual-47ddf9a4c4/0/cache/eslint-config-airbnb-base-npm-15.0.0-802837dd26-daa68a1dcb.zip/node_modules/eslint-config-airbnb-base/",\ + ["virtual:0eeddb8890c74d0fbd09500b310c37048127ccff9af8af65afe3804eb66d8f620eec65d986067db284ba7d6028268ba8218c2ef97a2c6be174d4d752476f480b#npm:0.5.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-compat-utils-virtual-7df2c8a537/0/cache/eslint-compat-utils-npm-0.5.1-f1f8ade49a-ac65ac1c61.zip/node_modules/eslint-compat-utils/",\ "packageDependencies": [\ ["@types/eslint", null],\ - ["@types/eslint-plugin-import", null],\ - ["confusing-browser-globals", "npm:1.0.10"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ - ["object.assign", "npm:4.1.4"],\ - ["object.entries", "npm:1.1.6"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-compat-utils", "virtual:0eeddb8890c74d0fbd09500b310c37048127ccff9af8af65afe3804eb66d8f620eec65d986067db284ba7d6028268ba8218c2ef97a2c6be174d4d752476f480b#npm:0.5.1"],\ ["semver", "npm:7.5.3"]\ ],\ "packagePeers": [\ - "@types/eslint-plugin-import",\ "@types/eslint",\ - "eslint-plugin-import",\ "eslint"\ ],\ "linkType": "HARD"\ }]\ ]],\ - ["eslint-config-airbnb-typescript", [\ - ["npm:17.0.0", {\ - "packageLocation": "./.yarn/cache/eslint-config-airbnb-typescript-npm-17.0.0-e1f8a377d2-43158416b1.zip/node_modules/eslint-config-airbnb-typescript/",\ + ["eslint-config-airbnb-extended", [\ + ["npm:3.0.1", {\ + "packageLocation": "./.yarn/cache/eslint-config-airbnb-extended-npm-3.0.1-e232343c3c-24e89d991e.zip/node_modules/eslint-config-airbnb-extended/",\ "packageDependencies": [\ - ["eslint-config-airbnb-typescript", "npm:17.0.0"]\ + ["eslint-config-airbnb-extended", "npm:3.0.1"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:17.0.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-config-airbnb-typescript-virtual-6af0d12a15/0/cache/eslint-config-airbnb-typescript-npm-17.0.0-e1f8a377d2-43158416b1.zip/node_modules/eslint-config-airbnb-typescript/",\ + ["virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:3.0.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-config-airbnb-extended-virtual-ebe53227cf/0/cache/eslint-config-airbnb-extended-npm-3.0.1-e232343c3c-24e89d991e.zip/node_modules/eslint-config-airbnb-extended/",\ "packageDependencies": [\ + ["@next/eslint-plugin-next", "npm:16.1.5"],\ + ["@stylistic/eslint-plugin", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:5.7.1"],\ ["@types/eslint", null],\ - ["@types/eslint-plugin-import", null],\ - ["@types/typescript-eslint__eslint-plugin", null],\ - ["@types/typescript-eslint__parser", null],\ - ["@typescript-eslint/eslint-plugin", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["@typescript-eslint/parser", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:15.0.0"],\ - ["eslint-config-airbnb-typescript", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:17.0.0"],\ - ["eslint-plugin-import", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.29.0"]\ + ["confusing-browser-globals", "npm:1.0.11"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-config-airbnb-extended", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:3.0.1"],\ + ["eslint-import-resolver-typescript", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:4.4.4"],\ + ["eslint-plugin-import", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:2.32.0"],\ + ["eslint-plugin-import-x", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:4.16.1"],\ + ["eslint-plugin-jsx-a11y", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:6.10.2"],\ + ["eslint-plugin-n", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:17.23.2"],\ + ["eslint-plugin-react", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:7.37.5"],\ + ["eslint-plugin-react-hooks", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:7.0.1"],\ + ["globals", "npm:17.1.0"],\ + ["typescript-eslint", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:8.54.0"]\ ],\ "packagePeers": [\ - "@types/eslint-plugin-import",\ "@types/eslint",\ - "@types/typescript-eslint__eslint-plugin",\ - "@types/typescript-eslint__parser",\ - "@typescript-eslint/eslint-plugin",\ - "@typescript-eslint/parser",\ - "eslint-plugin-import",\ "eslint"\ ],\ "linkType": "HARD"\ @@ -10292,6 +11081,30 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["eslint-import-context", [\ + ["npm:0.1.9", {\ + "packageLocation": "./.yarn/cache/eslint-import-context-npm-0.1.9-5e2eb7c9a9-f0778126bb.zip/node_modules/eslint-import-context/",\ + "packageDependencies": [\ + ["eslint-import-context", "npm:0.1.9"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:879b458582c99b98b5838718f60a6b7207e313bfd5f5d6d8c0b0fbd039438f386554521da2c4624a6e72e08ef192e9356c988a77bfa51cc316e71a0f4875d081#npm:0.1.9", {\ + "packageLocation": "./.yarn/__virtual__/eslint-import-context-virtual-e3b8aa0cb5/0/cache/eslint-import-context-npm-0.1.9-5e2eb7c9a9-f0778126bb.zip/node_modules/eslint-import-context/",\ + "packageDependencies": [\ + ["@types/unrs-resolver", null],\ + ["eslint-import-context", "virtual:879b458582c99b98b5838718f60a6b7207e313bfd5f5d6d8c0b0fbd039438f386554521da2c4624a6e72e08ef192e9356c988a77bfa51cc316e71a0f4875d081#npm:0.1.9"],\ + ["get-tsconfig", "npm:4.13.0"],\ + ["stable-hash-x", "npm:0.2.0"],\ + ["unrs-resolver", "npm:1.11.1"]\ + ],\ + "packagePeers": [\ + "@types/unrs-resolver",\ + "unrs-resolver"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["eslint-import-resolver-node", [\ ["npm:0.3.9", {\ "packageLocation": "./.yarn/cache/eslint-import-resolver-node-npm-0.3.9-2a426afc4b-d52e08e1d9.zip/node_modules/eslint-import-resolver-node/",\ @@ -10304,16 +11117,53 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["eslint-import-resolver-typescript", [\ + ["npm:4.4.4", {\ + "packageLocation": "./.yarn/cache/eslint-import-resolver-typescript-npm-4.4.4-e7b670a36b-4f871f6d1a.zip/node_modules/eslint-import-resolver-typescript/",\ + "packageDependencies": [\ + ["eslint-import-resolver-typescript", "npm:4.4.4"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:4.4.4", {\ + "packageLocation": "./.yarn/__virtual__/eslint-import-resolver-typescript-virtual-879b458582/0/cache/eslint-import-resolver-typescript-npm-4.4.4-e7b670a36b-4f871f6d1a.zip/node_modules/eslint-import-resolver-typescript/",\ + "packageDependencies": [\ + ["@types/eslint", null],\ + ["@types/eslint-plugin-import", null],\ + ["@types/eslint-plugin-import-x", null],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-import-context", "virtual:879b458582c99b98b5838718f60a6b7207e313bfd5f5d6d8c0b0fbd039438f386554521da2c4624a6e72e08ef192e9356c988a77bfa51cc316e71a0f4875d081#npm:0.1.9"],\ + ["eslint-import-resolver-typescript", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:4.4.4"],\ + ["eslint-plugin-import", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:2.32.0"],\ + ["eslint-plugin-import-x", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:4.16.1"],\ + ["get-tsconfig", "npm:4.13.0"],\ + ["is-bun-module", "npm:2.0.0"],\ + ["stable-hash-x", "npm:0.2.0"],\ + ["tinyglobby", "npm:0.2.15"],\ + ["unrs-resolver", "npm:1.11.1"]\ + ],\ + "packagePeers": [\ + "@types/eslint-plugin-import-x",\ + "@types/eslint-plugin-import",\ + "@types/eslint",\ + "eslint-plugin-import-x",\ + "eslint-plugin-import",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["eslint-module-utils", [\ - ["npm:2.8.0", {\ - "packageLocation": "./.yarn/cache/eslint-module-utils-npm-2.8.0-05e42bcab0-a9a7ed93eb.zip/node_modules/eslint-module-utils/",\ + ["npm:2.12.1", {\ + "packageLocation": "./.yarn/cache/eslint-module-utils-npm-2.12.1-11995f0970-bd25d6610e.zip/node_modules/eslint-module-utils/",\ "packageDependencies": [\ - ["eslint-module-utils", "npm:2.8.0"]\ + ["eslint-module-utils", "npm:2.12.1"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:8c23f029ec8fcaddd7c1772c46d1b354be8557accc5ee94d468bb5c9856c6d506fb5b23f4590689a485949974d3dbc05f8c89dc171ea5e6af3810cde4eedb9ed#npm:2.8.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-module-utils-virtual-2b6ac89a9e/0/cache/eslint-module-utils-npm-2.8.0-05e42bcab0-a9a7ed93eb.zip/node_modules/eslint-module-utils/",\ + ["virtual:198f270b94f05709dc9fe91d3eef0655acb3b669a1a2a1214e3304e3a760c6dd8b09612fc7fa3745cddb0c0b667ed1e58e258e2dccc3f7684e49f976a0285a8c#npm:2.12.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-module-utils-virtual-666aaca361/0/cache/eslint-module-utils-npm-2.12.1-11995f0970-bd25d6610e.zip/node_modules/eslint-module-utils/",\ "packageDependencies": [\ ["@types/eslint", null],\ ["@types/eslint-import-resolver-node", null],\ @@ -10322,11 +11172,11 @@ const RAW_RUNTIME_STATE = ["@types/typescript-eslint__parser", null],\ ["@typescript-eslint/parser", null],\ ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ - ["eslint", "npm:8.53.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["eslint-import-resolver-node", "npm:0.3.9"],\ ["eslint-import-resolver-typescript", null],\ ["eslint-import-resolver-webpack", null],\ - ["eslint-module-utils", "virtual:8c23f029ec8fcaddd7c1772c46d1b354be8557accc5ee94d468bb5c9856c6d506fb5b23f4590689a485949974d3dbc05f8c89dc171ea5e6af3810cde4eedb9ed#npm:2.8.0"]\ + ["eslint-module-utils", "virtual:198f270b94f05709dc9fe91d3eef0655acb3b669a1a2a1214e3304e3a760c6dd8b09612fc7fa3745cddb0c0b667ed1e58e258e2dccc3f7684e49f976a0285a8c#npm:2.12.1"]\ ],\ "packagePeers": [\ "@types/eslint-import-resolver-node",\ @@ -10341,70 +11191,67 @@ const RAW_RUNTIME_STATE = "eslint"\ ],\ "linkType": "HARD"\ + }]\ + ]],\ + ["eslint-plugin-es-x", [\ + ["npm:7.8.0", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-es-x-npm-7.8.0-8237bd972e-1df8d52c4f.zip/node_modules/eslint-plugin-es-x/",\ + "packageDependencies": [\ + ["eslint-plugin-es-x", "npm:7.8.0"]\ + ],\ + "linkType": "SOFT"\ }],\ - ["virtual:96d640851883502a7bd515b59a6344edcdb68909de6ad63d27c942e2ef48b71a193045890c1a5fd7be54566bd89b997453ac77f12dd5f7a83f610e16386b924c#npm:2.8.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-module-utils-virtual-52df2ee179/0/cache/eslint-module-utils-npm-2.8.0-05e42bcab0-a9a7ed93eb.zip/node_modules/eslint-module-utils/",\ + ["virtual:61e2ff1032c3492f5829d4326762d5c67af3b3ef5c7b4087320873e596f5a35b31ebda3dcb132749c6ab237f350cd625874adab839d2512369f2cec5dee0c7d3#npm:7.8.0", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-es-x-virtual-0eeddb8890/0/cache/eslint-plugin-es-x-npm-7.8.0-8237bd972e-1df8d52c4f.zip/node_modules/eslint-plugin-es-x/",\ "packageDependencies": [\ + ["@eslint-community/eslint-utils", "virtual:79c28034d94a28ec559d9137247270112d4bba82f5cf5320ba8f69e7c1dc984374b4c8c82e16031069e9919a8ce0b231c49891795c762408cc665fe7a8cd02ee#npm:4.9.1"],\ + ["@eslint-community/regexpp", "npm:4.12.2"],\ ["@types/eslint", null],\ - ["@types/eslint-import-resolver-node", null],\ - ["@types/eslint-import-resolver-typescript", null],\ - ["@types/eslint-import-resolver-webpack", null],\ - ["@types/typescript-eslint__parser", null],\ - ["@typescript-eslint/parser", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-import-resolver-node", "npm:0.3.9"],\ - ["eslint-import-resolver-typescript", null],\ - ["eslint-import-resolver-webpack", null],\ - ["eslint-module-utils", "virtual:96d640851883502a7bd515b59a6344edcdb68909de6ad63d27c942e2ef48b71a193045890c1a5fd7be54566bd89b997453ac77f12dd5f7a83f610e16386b924c#npm:2.8.0"]\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-compat-utils", "virtual:0eeddb8890c74d0fbd09500b310c37048127ccff9af8af65afe3804eb66d8f620eec65d986067db284ba7d6028268ba8218c2ef97a2c6be174d4d752476f480b#npm:0.5.1"],\ + ["eslint-plugin-es-x", "virtual:61e2ff1032c3492f5829d4326762d5c67af3b3ef5c7b4087320873e596f5a35b31ebda3dcb132749c6ab237f350cd625874adab839d2512369f2cec5dee0c7d3#npm:7.8.0"]\ ],\ "packagePeers": [\ - "@types/eslint-import-resolver-node",\ - "@types/eslint-import-resolver-typescript",\ - "@types/eslint-import-resolver-webpack",\ "@types/eslint",\ - "@types/typescript-eslint__parser",\ - "@typescript-eslint/parser",\ - "eslint-import-resolver-node",\ - "eslint-import-resolver-typescript",\ - "eslint-import-resolver-webpack",\ "eslint"\ ],\ "linkType": "HARD"\ }]\ ]],\ ["eslint-plugin-import", [\ - ["npm:2.29.0", {\ - "packageLocation": "./.yarn/cache/eslint-plugin-import-npm-2.29.0-9cd6da0b0a-d6e8d016f3.zip/node_modules/eslint-plugin-import/",\ + ["npm:2.32.0", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-import-npm-2.32.0-a1643bce9b-1bacf4967e.zip/node_modules/eslint-plugin-import/",\ "packageDependencies": [\ - ["eslint-plugin-import", "npm:2.29.0"]\ + ["eslint-plugin-import", "npm:2.32.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.29.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-plugin-import-virtual-96d6408518/0/cache/eslint-plugin-import-npm-2.29.0-9cd6da0b0a-d6e8d016f3.zip/node_modules/eslint-plugin-import/",\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:2.32.0", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-import-virtual-198f270b94/0/cache/eslint-plugin-import-npm-2.32.0-a1643bce9b-1bacf4967e.zip/node_modules/eslint-plugin-import/",\ "packageDependencies": [\ + ["@rtsao/scc", "npm:1.1.0"],\ ["@types/eslint", null],\ ["@types/typescript-eslint__parser", null],\ - ["@typescript-eslint/parser", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.55.0"],\ - ["array-includes", "npm:3.1.7"],\ - ["array.prototype.findlastindex", "npm:1.2.3"],\ - ["array.prototype.flat", "npm:1.3.2"],\ - ["array.prototype.flatmap", "npm:1.3.2"],\ + ["@typescript-eslint/parser", null],\ + ["array-includes", "npm:3.1.9"],\ + ["array.prototype.findlastindex", "npm:1.2.6"],\ + ["array.prototype.flat", "npm:1.3.3"],\ + ["array.prototype.flatmap", "npm:1.3.3"],\ ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ ["doctrine", "npm:2.1.0"],\ - ["eslint", "npm:8.53.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ ["eslint-import-resolver-node", "npm:0.3.9"],\ - ["eslint-module-utils", "virtual:96d640851883502a7bd515b59a6344edcdb68909de6ad63d27c942e2ef48b71a193045890c1a5fd7be54566bd89b997453ac77f12dd5f7a83f610e16386b924c#npm:2.8.0"],\ - ["eslint-plugin-import", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.29.0"],\ - ["hasown", "npm:2.0.0"],\ - ["is-core-module", "npm:2.13.1"],\ + ["eslint-module-utils", "virtual:198f270b94f05709dc9fe91d3eef0655acb3b669a1a2a1214e3304e3a760c6dd8b09612fc7fa3745cddb0c0b667ed1e58e258e2dccc3f7684e49f976a0285a8c#npm:2.12.1"],\ + ["eslint-plugin-import", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:2.32.0"],\ + ["hasown", "npm:2.0.2"],\ + ["is-core-module", "npm:2.16.1"],\ ["is-glob", "npm:4.0.3"],\ ["minimatch", "npm:3.1.2"],\ - ["object.fromentries", "npm:2.0.7"],\ - ["object.groupby", "npm:1.0.1"],\ - ["object.values", "npm:1.1.7"],\ + ["object.fromentries", "npm:2.0.8"],\ + ["object.groupby", "npm:1.0.3"],\ + ["object.values", "npm:1.2.1"],\ ["semver", "npm:7.5.3"],\ + ["string.prototype.trimend", "npm:1.0.9"],\ ["tsconfig-paths", "npm:4.2.0"]\ ],\ "packagePeers": [\ @@ -10414,65 +11261,139 @@ const RAW_RUNTIME_STATE = "eslint"\ ],\ "linkType": "HARD"\ + }]\ + ]],\ + ["eslint-plugin-import-x", [\ + ["npm:4.16.1", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-import-x-npm-4.16.1-b1dd938e9f-d1390d4949.zip/node_modules/eslint-plugin-import-x/",\ + "packageDependencies": [\ + ["eslint-plugin-import-x", "npm:4.16.1"]\ + ],\ + "linkType": "SOFT"\ }],\ - ["virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-plugin-import-virtual-8c23f029ec/0/cache/eslint-plugin-import-npm-2.29.0-9cd6da0b0a-d6e8d016f3.zip/node_modules/eslint-plugin-import/",\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:4.16.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-import-x-virtual-d6cffa3718/0/cache/eslint-plugin-import-x-npm-4.16.1-b1dd938e9f-d1390d4949.zip/node_modules/eslint-plugin-import-x/",\ "packageDependencies": [\ ["@types/eslint", null],\ - ["@types/typescript-eslint__parser", null],\ - ["@typescript-eslint/parser", null],\ - ["array-includes", "npm:3.1.7"],\ - ["array.prototype.findlastindex", "npm:1.2.3"],\ - ["array.prototype.flat", "npm:1.3.2"],\ - ["array.prototype.flatmap", "npm:1.3.2"],\ - ["debug", "virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7"],\ - ["doctrine", "npm:2.1.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-import-resolver-node", "npm:0.3.9"],\ - ["eslint-module-utils", "virtual:8c23f029ec8fcaddd7c1772c46d1b354be8557accc5ee94d468bb5c9856c6d506fb5b23f4590689a485949974d3dbc05f8c89dc171ea5e6af3810cde4eedb9ed#npm:2.8.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ - ["hasown", "npm:2.0.0"],\ - ["is-core-module", "npm:2.13.1"],\ + ["@types/eslint-import-resolver-node", null],\ + ["@types/typescript-eslint__utils", null],\ + ["@typescript-eslint/types", "npm:8.54.0"],\ + ["@typescript-eslint/utils", null],\ + ["comment-parser", "npm:1.4.5"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-import-context", "virtual:879b458582c99b98b5838718f60a6b7207e313bfd5f5d6d8c0b0fbd039438f386554521da2c4624a6e72e08ef192e9356c988a77bfa51cc316e71a0f4875d081#npm:0.1.9"],\ + ["eslint-import-resolver-node", null],\ + ["eslint-plugin-import-x", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:4.16.1"],\ ["is-glob", "npm:4.0.3"],\ - ["minimatch", "npm:3.1.2"],\ - ["object.fromentries", "npm:2.0.7"],\ - ["object.groupby", "npm:1.0.1"],\ - ["object.values", "npm:1.1.7"],\ + ["minimatch", "npm:10.1.1"],\ ["semver", "npm:7.5.3"],\ - ["tsconfig-paths", "npm:4.2.0"]\ + ["stable-hash-x", "npm:0.2.0"],\ + ["unrs-resolver", "npm:1.11.1"]\ ],\ "packagePeers": [\ + "@types/eslint-import-resolver-node",\ "@types/eslint",\ - "@types/typescript-eslint__parser",\ - "@typescript-eslint/parser",\ + "@types/typescript-eslint__utils",\ + "@typescript-eslint/utils",\ + "eslint-import-resolver-node",\ "eslint"\ ],\ "linkType": "HARD"\ }]\ ]],\ ["eslint-plugin-jsdoc", [\ - ["npm:46.9.0", {\ - "packageLocation": "./.yarn/cache/eslint-plugin-jsdoc-npm-46.9.0-43e0861b76-0dd2068804.zip/node_modules/eslint-plugin-jsdoc/",\ + ["npm:50.8.0", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-jsdoc-npm-50.8.0-4cbbdea7df-8857bb6583.zip/node_modules/eslint-plugin-jsdoc/",\ "packageDependencies": [\ - ["eslint-plugin-jsdoc", "npm:46.9.0"]\ + ["eslint-plugin-jsdoc", "npm:50.8.0"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:46.9.0", {\ - "packageLocation": "./.yarn/__virtual__/eslint-plugin-jsdoc-virtual-d57cf84450/0/cache/eslint-plugin-jsdoc-npm-46.9.0-43e0861b76-0dd2068804.zip/node_modules/eslint-plugin-jsdoc/",\ + ["virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:50.8.0", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-jsdoc-virtual-d58c3bbb04/0/cache/eslint-plugin-jsdoc-npm-50.8.0-4cbbdea7df-8857bb6583.zip/node_modules/eslint-plugin-jsdoc/",\ "packageDependencies": [\ - ["@es-joy/jsdoccomment", "npm:0.41.0"],\ + ["@es-joy/jsdoccomment", "npm:0.50.2"],\ ["@types/eslint", null],\ ["are-docs-informative", "npm:0.0.2"],\ ["comment-parser", "npm:1.4.1"],\ - ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ + ["debug", "virtual:4cab2f911c7bb125b2b902d5b07dde62c1fa4786a7a9de44b05e92a7acca0abc44e62efc4308b97c387822cda7afa56e0fb3a143c5b0459115eebe45195a20d4#npm:4.4.3"],\ ["escape-string-regexp", "npm:4.0.0"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-plugin-jsdoc", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:46.9.0"],\ - ["esquery", "npm:1.5.0"],\ - ["is-builtin-module", "npm:3.2.1"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-plugin-jsdoc", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:50.8.0"],\ + ["espree", "npm:10.4.0"],\ + ["esquery", "npm:1.7.0"],\ + ["parse-imports-exports", "npm:0.2.4"],\ ["semver", "npm:7.5.3"],\ - ["spdx-expression-parse", "npm:3.0.1"]\ + ["spdx-expression-parse", "npm:4.0.0"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["eslint-plugin-jsx-a11y", [\ + ["npm:6.10.2", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-jsx-a11y-npm-6.10.2-23afcd8d2e-3885507985.zip/node_modules/eslint-plugin-jsx-a11y/",\ + "packageDependencies": [\ + ["eslint-plugin-jsx-a11y", "npm:6.10.2"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:6.10.2", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-jsx-a11y-virtual-e89c46b938/0/cache/eslint-plugin-jsx-a11y-npm-6.10.2-23afcd8d2e-3885507985.zip/node_modules/eslint-plugin-jsx-a11y/",\ + "packageDependencies": [\ + ["@types/eslint", null],\ + ["aria-query", "npm:5.3.2"],\ + ["array-includes", "npm:3.1.9"],\ + ["array.prototype.flatmap", "npm:1.3.2"],\ + ["ast-types-flow", "npm:0.0.8"],\ + ["axe-core", "npm:4.11.1"],\ + ["axobject-query", "npm:4.1.0"],\ + ["damerau-levenshtein", "npm:1.0.8"],\ + ["emoji-regex", "npm:9.2.2"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-plugin-jsx-a11y", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:6.10.2"],\ + ["hasown", "npm:2.0.2"],\ + ["jsx-ast-utils", "npm:3.3.5"],\ + ["language-tags", "npm:1.0.9"],\ + ["minimatch", "npm:3.1.2"],\ + ["object.fromentries", "npm:2.0.8"],\ + ["safe-regex-test", "npm:1.1.0"],\ + ["string.prototype.includes", "npm:2.0.1"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["eslint-plugin-n", [\ + ["npm:17.23.2", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-n-npm-17.23.2-2a838a76f9-67a15908b2.zip/node_modules/eslint-plugin-n/",\ + "packageDependencies": [\ + ["eslint-plugin-n", "npm:17.23.2"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:17.23.2", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-n-virtual-61e2ff1032/0/cache/eslint-plugin-n-npm-17.23.2-2a838a76f9-67a15908b2.zip/node_modules/eslint-plugin-n/",\ + "packageDependencies": [\ + ["@eslint-community/eslint-utils", "virtual:79c28034d94a28ec559d9137247270112d4bba82f5cf5320ba8f69e7c1dc984374b4c8c82e16031069e9919a8ce0b231c49891795c762408cc665fe7a8cd02ee#npm:4.9.1"],\ + ["@types/eslint", null],\ + ["enhanced-resolve", "npm:5.17.1"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-plugin-es-x", "virtual:61e2ff1032c3492f5829d4326762d5c67af3b3ef5c7b4087320873e596f5a35b31ebda3dcb132749c6ab237f350cd625874adab839d2512369f2cec5dee0c7d3#npm:7.8.0"],\ + ["eslint-plugin-n", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:17.23.2"],\ + ["get-tsconfig", "npm:4.13.0"],\ + ["globals", "npm:15.15.0"],\ + ["globrex", "npm:0.1.2"],\ + ["ignore", "npm:5.3.2"],\ + ["semver", "npm:7.5.3"],\ + ["ts-declaration-location", "virtual:61e2ff1032c3492f5829d4326762d5c67af3b3ef5c7b4087320873e596f5a35b31ebda3dcb132749c6ab237f350cd625874adab839d2512369f2cec5dee0c7d3#npm:1.0.7"]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -10522,6 +11443,73 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["eslint-plugin-react", [\ + ["npm:7.37.5", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-react-npm-7.37.5-d03f6b6543-ee1bd4e0ec.zip/node_modules/eslint-plugin-react/",\ + "packageDependencies": [\ + ["eslint-plugin-react", "npm:7.37.5"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:7.37.5", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-react-virtual-e8e298e45d/0/cache/eslint-plugin-react-npm-7.37.5-d03f6b6543-ee1bd4e0ec.zip/node_modules/eslint-plugin-react/",\ + "packageDependencies": [\ + ["@types/eslint", null],\ + ["array-includes", "npm:3.1.9"],\ + ["array.prototype.findlast", "npm:1.2.5"],\ + ["array.prototype.flatmap", "npm:1.3.3"],\ + ["array.prototype.tosorted", "npm:1.1.4"],\ + ["doctrine", "npm:2.1.0"],\ + ["es-iterator-helpers", "npm:1.2.2"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-plugin-react", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:7.37.5"],\ + ["estraverse", "npm:5.3.0"],\ + ["hasown", "npm:2.0.2"],\ + ["jsx-ast-utils", "npm:3.3.5"],\ + ["minimatch", "npm:3.1.2"],\ + ["object.entries", "npm:1.1.9"],\ + ["object.fromentries", "npm:2.0.8"],\ + ["object.values", "npm:1.2.1"],\ + ["prop-types", "npm:15.8.1"],\ + ["resolve", "patch:resolve@npm%3A2.0.0-next.5#optional!builtin::version=2.0.0-next.5&hash=c3c19d"],\ + ["semver", "npm:7.5.3"],\ + ["string.prototype.matchall", "npm:4.0.12"],\ + ["string.prototype.repeat", "npm:1.0.0"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["eslint-plugin-react-hooks", [\ + ["npm:7.0.1", {\ + "packageLocation": "./.yarn/cache/eslint-plugin-react-hooks-npm-7.0.1-218b8cae26-12e96c68d5.zip/node_modules/eslint-plugin-react-hooks/",\ + "packageDependencies": [\ + ["eslint-plugin-react-hooks", "npm:7.0.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:7.0.1", {\ + "packageLocation": "./.yarn/__virtual__/eslint-plugin-react-hooks-virtual-097f27741d/0/cache/eslint-plugin-react-hooks-npm-7.0.1-218b8cae26-12e96c68d5.zip/node_modules/eslint-plugin-react-hooks/",\ + "packageDependencies": [\ + ["@babel/core", "npm:7.28.6"],\ + ["@babel/parser", "npm:7.28.6"],\ + ["@types/eslint", null],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["eslint-plugin-react-hooks", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:7.0.1"],\ + ["hermes-parser", "npm:0.25.1"],\ + ["zod", "npm:4.3.6"],\ + ["zod-validation-error", "virtual:097f27741dd7a82ac250aa766dbcf2b0f412a6af223498f6266f2e95d7fc4506b64ede3a0f0ba5416e3c5e32f4f84aaf10f3427e75957ee48e6797b149f5498a#npm:4.0.2"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "eslint"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["eslint-rule-docs", [\ ["npm:1.1.235", {\ "packageLocation": "./.yarn/cache/eslint-rule-docs-npm-1.1.235-64d33df34f-38af5ab724.zip/node_modules/eslint-rule-docs/",\ @@ -10541,10 +11529,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:7.2.2", {\ - "packageLocation": "./.yarn/cache/eslint-scope-npm-7.2.2-53cb0df8e8-5c660fb905.zip/node_modules/eslint-scope/",\ + ["npm:8.4.0", {\ + "packageLocation": "./.yarn/cache/eslint-scope-npm-8.4.0-8ed12feb40-e8e611701f.zip/node_modules/eslint-scope/",\ "packageDependencies": [\ - ["eslint-scope", "npm:7.2.2"],\ + ["eslint-scope", "npm:8.4.0"],\ ["esrecurse", "npm:4.3.0"],\ ["estraverse", "npm:5.3.0"]\ ],\ @@ -10552,29 +11540,32 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["eslint-visitor-keys", [\ - ["npm:1.3.0", {\ - "packageLocation": "./.yarn/cache/eslint-visitor-keys-npm-1.3.0-c07780a0fb-595ab230e0.zip/node_modules/eslint-visitor-keys/",\ - "packageDependencies": [\ - ["eslint-visitor-keys", "npm:1.3.0"]\ - ],\ - "linkType": "HARD"\ - }],\ - ["npm:2.1.0", {\ - "packageLocation": "./.yarn/cache/eslint-visitor-keys-npm-2.1.0-c31806b6b9-db4547eef5.zip/node_modules/eslint-visitor-keys/",\ + ["npm:3.4.3", {\ + "packageLocation": "./.yarn/cache/eslint-visitor-keys-npm-3.4.3-a356ac7e46-3f357c554a.zip/node_modules/eslint-visitor-keys/",\ "packageDependencies": [\ - ["eslint-visitor-keys", "npm:2.1.0"]\ + ["eslint-visitor-keys", "npm:3.4.3"]\ ],\ "linkType": "HARD"\ }],\ - ["npm:3.4.3", {\ - "packageLocation": "./.yarn/cache/eslint-visitor-keys-npm-3.4.3-a356ac7e46-3f357c554a.zip/node_modules/eslint-visitor-keys/",\ + ["npm:4.2.1", {\ + "packageLocation": "./.yarn/cache/eslint-visitor-keys-npm-4.2.1-435d5be22a-3ee00fc6a7.zip/node_modules/eslint-visitor-keys/",\ "packageDependencies": [\ - ["eslint-visitor-keys", "npm:3.4.3"]\ + ["eslint-visitor-keys", "npm:4.2.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["espree", [\ + ["npm:10.4.0", {\ + "packageLocation": "./.yarn/cache/espree-npm-10.4.0-9633b00e55-9b355b32db.zip/node_modules/espree/",\ + "packageDependencies": [\ + ["acorn", "npm:8.15.0"],\ + ["acorn-jsx", "virtual:9633b00e55c5aebf81b0127f50addd44705c175a47a287258963782da8f9f4e66c2da6640a60ed2826e19f024f73cd554a58729ee1644f93800bbd0d7b7ddd79#npm:5.3.2"],\ + ["eslint-visitor-keys", "npm:4.2.1"],\ + ["espree", "npm:10.4.0"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:9.6.1", {\ "packageLocation": "./.yarn/cache/espree-npm-9.6.1-a50722a5a9-255ab260f0.zip/node_modules/espree/",\ "packageDependencies": [\ @@ -10603,6 +11594,14 @@ const RAW_RUNTIME_STATE = ["estraverse", "npm:5.3.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.7.0", {\ + "packageLocation": "./.yarn/cache/esquery-npm-1.7.0-c1e8da438a-4afaf30893.zip/node_modules/esquery/",\ + "packageDependencies": [\ + ["esquery", "npm:1.7.0"],\ + ["estraverse", "npm:5.3.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["esrecurse", [\ @@ -10782,6 +11781,18 @@ const RAW_RUNTIME_STATE = ["micromatch", "npm:4.0.8"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:3.3.1", {\ + "packageLocation": "./.yarn/cache/fast-glob-npm-3.3.1-8045ff8f4d-51bcd15472.zip/node_modules/fast-glob/",\ + "packageDependencies": [\ + ["@nodelib/fs.stat", "npm:2.0.5"],\ + ["@nodelib/fs.walk", "npm:1.2.8"],\ + ["fast-glob", "npm:3.3.1"],\ + ["glob-parent", "npm:5.1.2"],\ + ["merge2", "npm:1.4.1"],\ + ["micromatch", "npm:4.0.8"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["fast-json-patch", [\ @@ -10856,6 +11867,28 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["fdir", [\ + ["npm:6.5.0", {\ + "packageLocation": "./.yarn/cache/fdir-npm-6.5.0-8814a0dec7-14ca1c9f0a.zip/node_modules/fdir/",\ + "packageDependencies": [\ + ["fdir", "npm:6.5.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:0e783aadbd2b4b8e6f6056033c0b290501892d23bc7c5dad5477e00e48ad8bd3e4434c3962a52dd75a58e06dbb7218094a494bac954ef2f7f6fdb65d9717e5f4#npm:6.5.0", {\ + "packageLocation": "./.yarn/__virtual__/fdir-virtual-abd4ab2082/0/cache/fdir-npm-6.5.0-8814a0dec7-14ca1c9f0a.zip/node_modules/fdir/",\ + "packageDependencies": [\ + ["@types/picomatch", null],\ + ["fdir", "virtual:0e783aadbd2b4b8e6f6056033c0b290501892d23bc7c5dad5477e00e48ad8bd3e4434c3962a52dd75a58e06dbb7218094a494bac954ef2f7f6fdb65d9717e5f4#npm:6.5.0"],\ + ["picomatch", "npm:4.0.3"]\ + ],\ + "packagePeers": [\ + "@types/picomatch",\ + "picomatch"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["fecha", [\ ["npm:4.2.1", {\ "packageLocation": "./.yarn/cache/fecha-npm-4.2.1-40d84f7733-6cf959d41a.zip/node_modules/fecha/",\ @@ -10876,11 +11909,11 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["file-entry-cache", [\ - ["npm:6.0.1", {\ - "packageLocation": "./.yarn/cache/file-entry-cache-npm-6.0.1-31965cf0af-099bb9d4ab.zip/node_modules/file-entry-cache/",\ + ["npm:8.0.0", {\ + "packageLocation": "./.yarn/cache/file-entry-cache-npm-8.0.0-5b09d19a83-afe55c4de4.zip/node_modules/file-entry-cache/",\ "packageDependencies": [\ - ["file-entry-cache", "npm:6.0.1"],\ - ["flat-cache", "npm:3.0.4"]\ + ["file-entry-cache", "npm:8.0.0"],\ + ["flat-cache", "npm:4.0.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -11028,12 +12061,12 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["flat-cache", [\ - ["npm:3.0.4", {\ - "packageLocation": "./.yarn/cache/flat-cache-npm-3.0.4-ee77e5911e-9fe5d0cb97.zip/node_modules/flat-cache/",\ + ["npm:4.0.1", {\ + "packageLocation": "./.yarn/cache/flat-cache-npm-4.0.1-12bf2455f7-58ce851d90.zip/node_modules/flat-cache/",\ "packageDependencies": [\ - ["flat-cache", "npm:3.0.4"],\ - ["flatted", "npm:3.2.7"],\ - ["rimraf", "npm:3.0.2"]\ + ["flat-cache", "npm:4.0.1"],\ + ["flatted", "npm:3.3.3"],\ + ["keyv", "npm:4.5.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -11045,6 +12078,13 @@ const RAW_RUNTIME_STATE = ["flatted", "npm:3.2.7"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:3.3.3", {\ + "packageLocation": "./.yarn/cache/flatted-npm-3.3.3-ca455563b2-8c96c02fbe.zip/node_modules/flatted/",\ + "packageDependencies": [\ + ["flatted", "npm:3.3.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["fn.name", [\ @@ -11230,6 +12270,19 @@ const RAW_RUNTIME_STATE = ["functions-have-names", "npm:1.2.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.8", {\ + "packageLocation": "./.yarn/cache/function.prototype.name-npm-1.1.8-2cf198aac8-25b9e5bea9.zip/node_modules/function.prototype.name/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["define-properties", "npm:1.2.1"],\ + ["function.prototype.name", "npm:1.1.8"],\ + ["functions-have-names", "npm:1.2.3"],\ + ["hasown", "npm:2.0.2"],\ + ["is-callable", "npm:1.2.7"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["functional-red-black-tree", [\ @@ -11422,6 +12475,26 @@ const RAW_RUNTIME_STATE = ["get-symbol-description", "npm:1.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/get-symbol-description-npm-1.1.0-7a9e0b1c24-a353e3a959.zip/node_modules/get-symbol-description/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["es-errors", "npm:1.3.0"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["get-symbol-description", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["get-tsconfig", [\ + ["npm:4.13.0", {\ + "packageLocation": "./.yarn/cache/get-tsconfig-npm-4.13.0-009b232bdd-3603c6da30.zip/node_modules/get-tsconfig/",\ + "packageDependencies": [\ + ["get-tsconfig", "npm:4.13.0"],\ + ["resolve-pkg-maps", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["git-raw-commits", [\ @@ -11589,11 +12662,24 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:13.23.0", {\ - "packageLocation": "./.yarn/cache/globals-npm-13.23.0-7f02426fd5-bf6a8616f4.zip/node_modules/globals/",\ + ["npm:14.0.0", {\ + "packageLocation": "./.yarn/cache/globals-npm-14.0.0-5fc3d8d5da-03939c8af9.zip/node_modules/globals/",\ + "packageDependencies": [\ + ["globals", "npm:14.0.0"]\ + ],\ + "linkType": "HARD"\ + }],\ + ["npm:15.15.0", {\ + "packageLocation": "./.yarn/cache/globals-npm-15.15.0-5ddcb6c553-7f561c87b2.zip/node_modules/globals/",\ + "packageDependencies": [\ + ["globals", "npm:15.15.0"]\ + ],\ + "linkType": "HARD"\ + }],\ + ["npm:17.1.0", {\ + "packageLocation": "./.yarn/cache/globals-npm-17.1.0-baf660f37b-6e77442a3b.zip/node_modules/globals/",\ "packageDependencies": [\ - ["globals", "npm:13.23.0"],\ - ["type-fest", "npm:0.20.2"]\ + ["globals", "npm:17.1.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -11606,6 +12692,15 @@ const RAW_RUNTIME_STATE = ["globalthis", "npm:1.0.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.4", {\ + "packageLocation": "./.yarn/cache/globalthis-npm-1.0.4-de22ac6193-1f1fd078fb.zip/node_modules/globalthis/",\ + "packageDependencies": [\ + ["define-properties", "npm:1.2.1"],\ + ["globalthis", "npm:1.0.4"],\ + ["gopd", "npm:1.0.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["globby", [\ @@ -11721,15 +12816,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["graphemer", [\ - ["npm:1.4.0", {\ - "packageLocation": "./.yarn/cache/graphemer-npm-1.4.0-0627732d35-6dd60dba97.zip/node_modules/graphemer/",\ - "packageDependencies": [\ - ["graphemer", "npm:1.4.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["grouped-queue", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/grouped-queue-npm-2.0.0-81fdc84ef7-be5c6cfac0.zip/node_modules/grouped-queue/",\ @@ -11822,6 +12908,14 @@ const RAW_RUNTIME_STATE = ["has-proto", "npm:1.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.2.0", {\ + "packageLocation": "./.yarn/cache/has-proto-npm-1.2.0-0108d177d3-7eaed07728.zip/node_modules/has-proto/",\ + "packageDependencies": [\ + ["dunder-proto", "npm:1.0.1"],\ + ["has-proto", "npm:1.2.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["has-symbols", [\ @@ -11977,6 +13071,25 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["hermes-estree", [\ + ["npm:0.25.1", {\ + "packageLocation": "./.yarn/cache/hermes-estree-npm-0.25.1-d7752f3952-7b1eca98b2.zip/node_modules/hermes-estree/",\ + "packageDependencies": [\ + ["hermes-estree", "npm:0.25.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["hermes-parser", [\ + ["npm:0.25.1", {\ + "packageLocation": "./.yarn/cache/hermes-parser-npm-0.25.1-832deac23b-805efc0569.zip/node_modules/hermes-parser/",\ + "packageDependencies": [\ + ["hermes-estree", "npm:0.25.1"],\ + ["hermes-parser", "npm:0.25.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["hmac-drbg", [\ ["npm:1.0.1", {\ "packageLocation": "./.yarn/cache/hmac-drbg-npm-1.0.1-3499ad31cd-0298a1445b.zip/node_modules/hmac-drbg/",\ @@ -12212,6 +13325,20 @@ const RAW_RUNTIME_STATE = ["ignore", "npm:5.2.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:5.3.2", {\ + "packageLocation": "./.yarn/cache/ignore-npm-5.3.2-346d3ba017-cceb6a4570.zip/node_modules/ignore/",\ + "packageDependencies": [\ + ["ignore", "npm:5.3.2"]\ + ],\ + "linkType": "HARD"\ + }],\ + ["npm:7.0.5", {\ + "packageLocation": "./.yarn/cache/ignore-npm-7.0.5-dea34ee430-f134b96a4d.zip/node_modules/ignore/",\ + "packageDependencies": [\ + ["ignore", "npm:7.0.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["ignore-by-default", [\ @@ -12389,6 +13516,16 @@ const RAW_RUNTIME_STATE = ["side-channel", "npm:1.0.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/internal-slot-npm-1.1.0-269ac0e8be-1d5219273a.zip/node_modules/internal-slot/",\ + "packageDependencies": [\ + ["es-errors", "npm:1.3.0"],\ + ["hasown", "npm:2.0.2"],\ + ["internal-slot", "npm:1.1.0"],\ + ["side-channel", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["interpret", [\ @@ -12457,6 +13594,16 @@ const RAW_RUNTIME_STATE = ["is-typed-array", "npm:1.1.12"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:3.0.5", {\ + "packageLocation": "./.yarn/cache/is-array-buffer-npm-3.0.5-8f0828e156-ef1095c55b.zip/node_modules/is-array-buffer/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["is-array-buffer", "npm:3.0.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-arrayish", [\ @@ -12475,6 +13622,20 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["is-async-function", [\ + ["npm:2.1.1", {\ + "packageLocation": "./.yarn/cache/is-async-function-npm-2.1.1-547309fbf2-7c2ac7efdf.zip/node_modules/is-async-function/",\ + "packageDependencies": [\ + ["async-function", "npm:1.0.0"],\ + ["call-bound", "npm:1.0.4"],\ + ["get-proto", "npm:1.0.1"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["is-async-function", "npm:2.1.1"],\ + ["safe-regex-test", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["is-bigint", [\ ["npm:1.0.4", {\ "packageLocation": "./.yarn/cache/is-bigint-npm-1.0.4-31c2eecbc9-cc981cf056.zip/node_modules/is-bigint/",\ @@ -12483,6 +13644,14 @@ const RAW_RUNTIME_STATE = ["is-bigint", "npm:1.0.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/is-bigint-npm-1.1.0-963b4e89e1-10cf327310.zip/node_modules/is-bigint/",\ + "packageDependencies": [\ + ["has-bigints", "npm:1.0.2"],\ + ["is-bigint", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-binary-path", [\ @@ -12504,14 +13673,23 @@ const RAW_RUNTIME_STATE = ["is-boolean-object", "npm:1.1.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.2.2", {\ + "packageLocation": "./.yarn/cache/is-boolean-object-npm-1.2.2-ceb8c82b17-051fa95fdb.zip/node_modules/is-boolean-object/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["is-boolean-object", "npm:1.2.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ - ["is-builtin-module", [\ - ["npm:3.2.1", {\ - "packageLocation": "./.yarn/cache/is-builtin-module-npm-3.2.1-2f92a5d353-e8f0ffc19a.zip/node_modules/is-builtin-module/",\ + ["is-bun-module", [\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/is-bun-module-npm-2.0.0-820a4713ec-cded5a1a58.zip/node_modules/is-bun-module/",\ "packageDependencies": [\ - ["builtin-modules", "npm:3.3.0"],\ - ["is-builtin-module", "npm:3.2.1"]\ + ["is-bun-module", "npm:2.0.0"],\ + ["semver", "npm:7.5.3"]\ ],\ "linkType": "HARD"\ }]\ @@ -12533,6 +13711,26 @@ const RAW_RUNTIME_STATE = ["is-core-module", "npm:2.13.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.16.1", {\ + "packageLocation": "./.yarn/cache/is-core-module-npm-2.16.1-a54837229e-452b2c2fb7.zip/node_modules/is-core-module/",\ + "packageDependencies": [\ + ["hasown", "npm:2.0.2"],\ + ["is-core-module", "npm:2.16.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["is-data-view", [\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/is-data-view-npm-1.0.2-8a9e34c5e6-357e9a48fa.zip/node_modules/is-data-view/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["is-data-view", "npm:1.0.2"],\ + ["is-typed-array", "npm:1.1.15"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-date-object", [\ @@ -12543,6 +13741,15 @@ const RAW_RUNTIME_STATE = ["is-date-object", "npm:1.0.5"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/is-date-object-npm-1.1.0-c444eba828-3a811b2c31.zip/node_modules/is-date-object/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["is-date-object", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-docker", [\ @@ -12563,6 +13770,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["is-finalizationregistry", [\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/is-finalizationregistry-npm-1.1.1-f9cad6c9aa-0bfb145e9a.zip/node_modules/is-finalizationregistry/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["is-finalizationregistry", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["is-fullwidth-code-point", [\ ["npm:3.0.0", {\ "packageLocation": "./.yarn/cache/is-fullwidth-code-point-npm-3.0.0-1ecf4ebee5-44a30c2945.zip/node_modules/is-fullwidth-code-point/",\ @@ -12580,6 +13797,18 @@ const RAW_RUNTIME_STATE = ["is-generator-function", "npm:1.0.10"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.2", {\ + "packageLocation": "./.yarn/cache/is-generator-function-npm-1.1.2-d0a84b1a72-cc50fa0103.zip/node_modules/is-generator-function/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["generator-function", "npm:2.0.1"],\ + ["get-proto", "npm:1.0.1"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["is-generator-function", "npm:1.1.2"],\ + ["safe-regex-test", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-glob", [\ @@ -12620,6 +13849,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["is-map", [\ + ["npm:2.0.3", {\ + "packageLocation": "./.yarn/cache/is-map-npm-2.0.3-9e061e76e3-8de7b41715.zip/node_modules/is-map/",\ + "packageDependencies": [\ + ["is-map", "npm:2.0.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["is-nan", [\ ["npm:1.3.2", {\ "packageLocation": "./.yarn/cache/is-nan-npm-1.3.2-a087d31a28-1f784d3472.zip/node_modules/is-nan/",\ @@ -12638,6 +13876,13 @@ const RAW_RUNTIME_STATE = ["is-negative-zero", "npm:2.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.0.3", {\ + "packageLocation": "./.yarn/cache/is-negative-zero-npm-2.0.3-d06b09e322-8fe5cffd8d.zip/node_modules/is-negative-zero/",\ + "packageDependencies": [\ + ["is-negative-zero", "npm:2.0.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-number", [\ @@ -12657,6 +13902,15 @@ const RAW_RUNTIME_STATE = ["is-number-object", "npm:1.0.6"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/is-number-object-npm-1.1.1-010c417fc6-a5922fb877.zip/node_modules/is-number-object/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["is-number-object", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-obj", [\ @@ -12668,15 +13922,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["is-path-inside", [\ - ["npm:3.0.3", {\ - "packageLocation": "./.yarn/cache/is-path-inside-npm-3.0.3-2ea0ef44fd-abd50f0618.zip/node_modules/is-path-inside/",\ - "packageDependencies": [\ - ["is-path-inside", "npm:3.0.3"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["is-plain-obj", [\ ["npm:1.1.0", {\ "packageLocation": "./.yarn/cache/is-plain-obj-npm-1.1.0-1046f64c0b-0ee0480779.zip/node_modules/is-plain-obj/",\ @@ -12719,6 +13964,17 @@ const RAW_RUNTIME_STATE = ["is-regex", "npm:1.1.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.2.1", {\ + "packageLocation": "./.yarn/cache/is-regex-npm-1.2.1-70a484f2c8-c42b7efc58.zip/node_modules/is-regex/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["gopd", "npm:1.2.0"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["hasown", "npm:2.0.2"],\ + ["is-regex", "npm:1.2.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-retry-allowed", [\ @@ -12740,6 +13996,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["is-set", [\ + ["npm:2.0.3", {\ + "packageLocation": "./.yarn/cache/is-set-npm-2.0.3-1b72c9a855-5685df33f0.zip/node_modules/is-set/",\ + "packageDependencies": [\ + ["is-set", "npm:2.0.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["is-shared-array-buffer", [\ ["npm:1.0.2", {\ "packageLocation": "./.yarn/cache/is-shared-array-buffer-npm-1.0.2-32e4181fcd-23d82259d6.zip/node_modules/is-shared-array-buffer/",\ @@ -12748,6 +14013,14 @@ const RAW_RUNTIME_STATE = ["is-shared-array-buffer", "npm:1.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.4", {\ + "packageLocation": "./.yarn/cache/is-shared-array-buffer-npm-1.0.4-70c977585b-0380d7c60c.zip/node_modules/is-shared-array-buffer/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["is-shared-array-buffer", "npm:1.0.4"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-stream", [\ @@ -12767,6 +14040,15 @@ const RAW_RUNTIME_STATE = ["is-string", "npm:1.0.7"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/is-string-npm-1.1.1-d2c4f9f448-5277cb9e22.zip/node_modules/is-string/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["is-string", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-symbol", [\ @@ -12777,6 +14059,16 @@ const RAW_RUNTIME_STATE = ["is-symbol", "npm:1.0.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/is-symbol-npm-1.1.1-f17b666ca9-db495c0d8c.zip/node_modules/is-symbol/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["has-symbols", "npm:1.1.0"],\ + ["is-symbol", "npm:1.1.1"],\ + ["safe-regex-test", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-text-path", [\ @@ -12834,6 +14126,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["is-weakmap", [\ + ["npm:2.0.2", {\ + "packageLocation": "./.yarn/cache/is-weakmap-npm-2.0.2-ced3cab2dc-a7b7e23206.zip/node_modules/is-weakmap/",\ + "packageDependencies": [\ + ["is-weakmap", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["is-weakref", [\ ["npm:1.0.2", {\ "packageLocation": "./.yarn/cache/is-weakref-npm-1.0.2-ff80e8c314-0023fd0e4b.zip/node_modules/is-weakref/",\ @@ -12842,6 +14143,25 @@ const RAW_RUNTIME_STATE = ["is-weakref", "npm:1.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/is-weakref-npm-1.1.1-e6458807f4-543506fd82.zip/node_modules/is-weakref/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["is-weakref", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["is-weakset", [\ + ["npm:2.0.4", {\ + "packageLocation": "./.yarn/cache/is-weakset-npm-2.0.4-155b83e84b-1d5e1d0179.zip/node_modules/is-weakset/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["is-weakset", "npm:2.0.4"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["is-windows", [\ @@ -13031,6 +14351,21 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["iterator.prototype", [\ + ["npm:1.1.5", {\ + "packageLocation": "./.yarn/cache/iterator.prototype-npm-1.1.5-923c4c9977-352bcf333f.zip/node_modules/iterator.prototype/",\ + "packageDependencies": [\ + ["define-data-property", "npm:1.1.4"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["get-proto", "npm:1.0.1"],\ + ["has-symbols", "npm:1.1.0"],\ + ["iterator.prototype", "npm:1.1.5"],\ + ["set-function-name", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["jackspeak", [\ ["npm:3.1.2", {\ "packageLocation": "./.yarn/cache/jackspeak-npm-3.1.2-dbb3ed8474-7e6b94103e.zip/node_modules/jackspeak/",\ @@ -13190,10 +14525,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["jsdoc-type-pratt-parser", [\ - ["npm:4.0.0", {\ - "packageLocation": "./.yarn/cache/jsdoc-type-pratt-parser-npm-4.0.0-7b035921c4-a225ab874e.zip/node_modules/jsdoc-type-pratt-parser/",\ + ["npm:4.1.0", {\ + "packageLocation": "./.yarn/cache/jsdoc-type-pratt-parser-npm-4.1.0-6f90ea9fa7-30d88f95f6.zip/node_modules/jsdoc-type-pratt-parser/",\ "packageDependencies": [\ - ["jsdoc-type-pratt-parser", "npm:4.0.0"]\ + ["jsdoc-type-pratt-parser", "npm:4.1.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -13206,13 +14541,6 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:2.5.2", {\ - "packageLocation": "./.yarn/cache/jsesc-npm-2.5.2-c5acb78804-d2096abdcd.zip/node_modules/jsesc/",\ - "packageDependencies": [\ - ["jsesc", "npm:2.5.2"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:3.0.2", {\ "packageLocation": "./.yarn/cache/jsesc-npm-3.0.2-3b3b74ec0d-8e5a7de6b7.zip/node_modules/jsesc/",\ "packageDependencies": [\ @@ -13366,6 +14694,19 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["jsx-ast-utils", [\ + ["npm:3.3.5", {\ + "packageLocation": "./.yarn/cache/jsx-ast-utils-npm-3.3.5-114c80f97a-b61d446136.zip/node_modules/jsx-ast-utils/",\ + "packageDependencies": [\ + ["array-includes", "npm:3.1.9"],\ + ["array.prototype.flat", "npm:1.3.3"],\ + ["jsx-ast-utils", "npm:3.3.5"],\ + ["object.assign", "npm:4.1.4"],\ + ["object.values", "npm:1.2.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["just-diff", [\ ["npm:5.0.1", {\ "packageLocation": "./.yarn/cache/just-diff-npm-5.0.1-6477d7b637-160c31bb68.zip/node_modules/just-diff/",\ @@ -13437,7 +14778,7 @@ const RAW_RUNTIME_STATE = ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:0.1.0", {\ "packageLocation": "./.yarn/__virtual__/karma-chai-virtual-e2e0d5ff8a/0/cache/karma-chai-npm-0.1.0-d1d807f507-7fae0b4ace.zip/node_modules/karma-chai/",\ "packageDependencies": [\ - ["@types/chai", "npm:4.2.22"],\ + ["@types/chai", "npm:4.3.20"],\ ["@types/karma", null],\ ["chai", "npm:4.3.10"],\ ["karma", "npm:6.4.3"],\ @@ -13701,6 +15042,25 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["language-subtag-registry", [\ + ["npm:0.3.23", {\ + "packageLocation": "./.yarn/cache/language-subtag-registry-npm-0.3.23-06b360f90f-fe13ed74ab.zip/node_modules/language-subtag-registry/",\ + "packageDependencies": [\ + ["language-subtag-registry", "npm:0.3.23"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["language-tags", [\ + ["npm:1.0.9", {\ + "packageLocation": "./.yarn/cache/language-tags-npm-1.0.9-3ea51f204b-d3a7c14b69.zip/node_modules/language-tags/",\ + "packageDependencies": [\ + ["language-subtag-registry", "npm:0.3.23"],\ + ["language-tags", "npm:1.0.9"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["level-concat-iterator", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/level-concat-iterator-npm-2.0.1-5179af5bd2-96b7d77d21.zip/node_modules/level-concat-iterator/",\ @@ -14108,6 +15468,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["loose-envify", [\ + ["npm:1.4.0", {\ + "packageLocation": "./.yarn/cache/loose-envify-npm-1.4.0-6307b72ccf-6517e24e0c.zip/node_modules/loose-envify/",\ + "packageDependencies": [\ + ["js-tokens", "npm:4.0.0"],\ + ["loose-envify", "npm:1.4.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["loupe", [\ ["npm:2.3.7", {\ "packageLocation": "./.yarn/cache/loupe-npm-2.3.7-f294c2ef33-635c8f0914.zip/node_modules/loupe/",\ @@ -14637,6 +16007,14 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["minimatch", [\ + ["npm:10.1.1", {\ + "packageLocation": "./.yarn/cache/minimatch-npm-10.1.1-453db4ee1a-110f38921e.zip/node_modules/minimatch/",\ + "packageDependencies": [\ + ["@isaacs/brace-expansion", "npm:5.0.0"],\ + ["minimatch", "npm:10.1.1"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:3.1.2", {\ "packageLocation": "./.yarn/cache/minimatch-npm-3.1.2-9405269906-e0b25b04cd.zip/node_modules/minimatch/",\ "packageDependencies": [\ @@ -15021,6 +16399,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["napi-postinstall", [\ + ["npm:0.3.4", {\ + "packageLocation": "./.yarn/cache/napi-postinstall-npm-0.3.4-a58e1fcbc3-5541381508.zip/node_modules/napi-postinstall/",\ + "packageDependencies": [\ + ["napi-postinstall", "npm:0.3.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["natural-compare", [\ ["npm:1.4.0", {\ "packageLocation": "./.yarn/cache/natural-compare-npm-1.4.0-97b75b362d-23ad088b08.zip/node_modules/natural-compare/",\ @@ -15171,7 +16558,7 @@ const RAW_RUNTIME_STATE = ["nopt", "npm:7.2.0"],\ ["proc-log", "npm:3.0.0"],\ ["semver", "npm:7.5.3"],\ - ["tar", "npm:7.5.6"],\ + ["tar", "npm:7.5.7"],\ ["which", "npm:4.0.0"]\ ],\ "linkType": "HARD"\ @@ -15621,53 +17008,68 @@ const RAW_RUNTIME_STATE = ["object.assign", "npm:4.1.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.1.7", {\ + "packageLocation": "./.yarn/cache/object.assign-npm-4.1.7-a3464be41b-3fe28cdd77.zip/node_modules/object.assign/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["has-symbols", "npm:1.1.0"],\ + ["object-keys", "npm:1.1.1"],\ + ["object.assign", "npm:4.1.7"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["object.entries", [\ - ["npm:1.1.6", {\ - "packageLocation": "./.yarn/cache/object.entries-npm-1.1.6-5f9ba14b46-08a09ff839.zip/node_modules/object.entries/",\ + ["npm:1.1.9", {\ + "packageLocation": "./.yarn/cache/object.entries-npm-1.1.9-32f1b371e0-24163ab1e1.zip/node_modules/object.entries/",\ "packageDependencies": [\ - ["call-bind", "npm:1.0.5"],\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ ["define-properties", "npm:1.2.1"],\ - ["es-abstract", "npm:1.22.3"],\ - ["object.entries", "npm:1.1.6"]\ + ["es-object-atoms", "npm:1.1.1"],\ + ["object.entries", "npm:1.1.9"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["object.fromentries", [\ - ["npm:2.0.7", {\ - "packageLocation": "./.yarn/cache/object.fromentries-npm-2.0.7-2e38392540-1bfbe42a51.zip/node_modules/object.fromentries/",\ + ["npm:2.0.8", {\ + "packageLocation": "./.yarn/cache/object.fromentries-npm-2.0.8-8f6e2db04a-5b2e80f7af.zip/node_modules/object.fromentries/",\ "packageDependencies": [\ - ["call-bind", "npm:1.0.5"],\ + ["call-bind", "npm:1.0.8"],\ ["define-properties", "npm:1.2.1"],\ - ["es-abstract", "npm:1.22.3"],\ - ["object.fromentries", "npm:2.0.7"]\ + ["es-abstract", "npm:1.24.1"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["object.fromentries", "npm:2.0.8"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["object.groupby", [\ - ["npm:1.0.1", {\ - "packageLocation": "./.yarn/cache/object.groupby-npm-1.0.1-fc268391fe-b7123d9140.zip/node_modules/object.groupby/",\ + ["npm:1.0.3", {\ + "packageLocation": "./.yarn/cache/object.groupby-npm-1.0.3-d5feb41454-44cb86dd2c.zip/node_modules/object.groupby/",\ "packageDependencies": [\ - ["call-bind", "npm:1.0.5"],\ + ["call-bind", "npm:1.0.8"],\ ["define-properties", "npm:1.2.1"],\ - ["es-abstract", "npm:1.22.3"],\ - ["get-intrinsic", "npm:1.2.2"],\ - ["object.groupby", "npm:1.0.1"]\ + ["es-abstract", "npm:1.24.1"],\ + ["object.groupby", "npm:1.0.3"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["object.values", [\ - ["npm:1.1.7", {\ - "packageLocation": "./.yarn/cache/object.values-npm-1.1.7-deae619f88-20ab42c0bb.zip/node_modules/object.values/",\ + ["npm:1.2.1", {\ + "packageLocation": "./.yarn/cache/object.values-npm-1.2.1-cd21c82f2d-f5ec9eccde.zip/node_modules/object.values/",\ "packageDependencies": [\ - ["call-bind", "npm:1.0.5"],\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ ["define-properties", "npm:1.2.1"],\ - ["es-abstract", "npm:1.22.3"],\ - ["object.values", "npm:1.1.7"]\ + ["es-object-atoms", "npm:1.1.1"],\ + ["object.values", "npm:1.2.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -15848,6 +17250,18 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["own-keys", [\ + ["npm:1.0.1", {\ + "packageLocation": "./.yarn/cache/own-keys-npm-1.0.1-1253f9b344-ab4bb3b863.zip/node_modules/own-keys/",\ + "packageDependencies": [\ + ["get-intrinsic", "npm:1.3.1"],\ + ["object-keys", "npm:1.1.1"],\ + ["own-keys", "npm:1.0.1"],\ + ["safe-push-apply", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["p-cancelable", [\ ["npm:2.1.1", {\ "packageLocation": "./.yarn/cache/p-cancelable-npm-2.1.1-9388305f02-7f1b64db17.zip/node_modules/p-cancelable/",\ @@ -16052,7 +17466,7 @@ const RAW_RUNTIME_STATE = ["read-package-json-fast", "npm:2.0.3"],\ ["rimraf", "npm:3.0.2"],\ ["ssri", "npm:8.0.1"],\ - ["tar", "npm:7.5.6"]\ + ["tar", "npm:7.5.7"]\ ],\ "linkType": "HARD"\ }],\ @@ -16077,7 +17491,7 @@ const RAW_RUNTIME_STATE = ["read-package-json-fast", "npm:3.0.2"],\ ["sigstore", "npm:1.9.0"],\ ["ssri", "npm:10.0.5"],\ - ["tar", "npm:7.5.6"]\ + ["tar", "npm:7.5.7"]\ ],\ "linkType": "HARD"\ }]\ @@ -16147,6 +17561,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["parse-imports-exports", [\ + ["npm:0.2.4", {\ + "packageLocation": "./.yarn/cache/parse-imports-exports-npm-0.2.4-4af940c595-144d459771.zip/node_modules/parse-imports-exports/",\ + "packageDependencies": [\ + ["parse-imports-exports", "npm:0.2.4"],\ + ["parse-statements", "npm:1.0.11"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["parse-json", [\ ["npm:4.0.0", {\ "packageLocation": "./.yarn/cache/parse-json-npm-4.0.0-a6f7771010-0fe227d410.zip/node_modules/parse-json/",\ @@ -16178,6 +17602,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["parse-statements", [\ + ["npm:1.0.11", {\ + "packageLocation": "./.yarn/cache/parse-statements-npm-1.0.11-f733998c18-287c2739f4.zip/node_modules/parse-statements/",\ + "packageDependencies": [\ + ["parse-statements", "npm:1.0.11"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["parseurl", [\ ["npm:1.3.3", {\ "packageLocation": "./.yarn/cache/parseurl-npm-1.3.3-1542397e00-407cee8e0a.zip/node_modules/parseurl/",\ @@ -16387,6 +17820,13 @@ const RAW_RUNTIME_STATE = ["picomatch", "npm:2.3.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.0.3", {\ + "packageLocation": "./.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-57b99055f4.zip/node_modules/picomatch/",\ + "packageDependencies": [\ + ["picomatch", "npm:4.0.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["pid-cwd", [\ @@ -16693,6 +18133,18 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["prop-types", [\ + ["npm:15.8.1", {\ + "packageLocation": "./.yarn/cache/prop-types-npm-15.8.1-17c71ee7ee-7d959caec0.zip/node_modules/prop-types/",\ + "packageDependencies": [\ + ["loose-envify", "npm:1.4.0"],\ + ["object-assign", "npm:4.1.1"],\ + ["prop-types", "npm:15.8.1"],\ + ["react-is", "npm:16.13.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["proper-lockfile", [\ ["npm:3.2.0", {\ "packageLocation": "./.yarn/cache/proper-lockfile-npm-3.2.0-4c500143f0-5025248895.zip/node_modules/proper-lockfile/",\ @@ -16931,6 +18383,13 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["react-is", [\ + ["npm:16.13.1", {\ + "packageLocation": "./.yarn/cache/react-is-npm-16.13.1-a9b9382b4f-5aa564a1cd.zip/node_modules/react-is/",\ + "packageDependencies": [\ + ["react-is", "npm:16.13.1"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:18.2.0", {\ "packageLocation": "./.yarn/cache/react-is-npm-18.2.0-0cc5edb910-200cd65bf2.zip/node_modules/react-is/",\ "packageDependencies": [\ @@ -17145,6 +18604,23 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["reflect.getprototypeof", [\ + ["npm:1.0.10", {\ + "packageLocation": "./.yarn/cache/reflect.getprototypeof-npm-1.0.10-8c3ce862a2-80a4e2be71.zip/node_modules/reflect.getprototypeof/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["get-proto", "npm:1.0.1"],\ + ["reflect.getprototypeof", "npm:1.0.10"],\ + ["which-builtin-type", "npm:1.2.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["regenerate", [\ ["npm:1.4.2", {\ "packageLocation": "./.yarn/cache/regenerate-npm-1.4.2-b296c5b63a-dc6c95ae4b.zip/node_modules/regenerate/",\ @@ -17201,6 +18677,19 @@ const RAW_RUNTIME_STATE = ["set-function-name", "npm:2.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.5.4", {\ + "packageLocation": "./.yarn/cache/regexp.prototype.flags-npm-1.5.4-39008ab64c-8ab897ca44.zip/node_modules/regexp.prototype.flags/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["get-proto", "npm:1.0.1"],\ + ["gopd", "npm:1.2.0"],\ + ["regexp.prototype.flags", "npm:1.5.4"],\ + ["set-function-name", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["regexpu-core", [\ @@ -17350,6 +18839,16 @@ const RAW_RUNTIME_STATE = ["supports-preserve-symlinks-flag", "npm:1.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["patch:resolve@npm%3A2.0.0-next.5#optional!builtin::version=2.0.0-next.5&hash=c3c19d", {\ + "packageLocation": "./.yarn/cache/resolve-patch-95f8f5d302-05fa778de9.zip/node_modules/resolve/",\ + "packageDependencies": [\ + ["is-core-module", "npm:2.13.1"],\ + ["path-parse", "npm:1.0.7"],\ + ["resolve", "patch:resolve@npm%3A2.0.0-next.5#optional!builtin::version=2.0.0-next.5&hash=c3c19d"],\ + ["supports-preserve-symlinks-flag", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["resolve-alpn", [\ @@ -17387,6 +18886,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["resolve-pkg-maps", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-0763150adf.zip/node_modules/resolve-pkg-maps/",\ + "packageDependencies": [\ + ["resolve-pkg-maps", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["responselike", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/responselike-npm-2.0.1-7f64b6e122-b122535466.zip/node_modules/responselike/",\ @@ -17536,6 +19044,18 @@ const RAW_RUNTIME_STATE = ["safe-array-concat", "npm:1.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.3", {\ + "packageLocation": "./.yarn/cache/safe-array-concat-npm-1.1.3-dab0384e54-fac4f40f20.zip/node_modules/safe-array-concat/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["has-symbols", "npm:1.1.0"],\ + ["isarray", "npm:2.0.5"],\ + ["safe-array-concat", "npm:1.1.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["safe-buffer", [\ @@ -17554,6 +19074,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["safe-push-apply", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/safe-push-apply-npm-1.0.0-51a0a42944-2bd4e53b66.zip/node_modules/safe-push-apply/",\ + "packageDependencies": [\ + ["es-errors", "npm:1.3.0"],\ + ["isarray", "npm:2.0.5"],\ + ["safe-push-apply", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["safe-regex-test", [\ ["npm:1.0.0", {\ "packageLocation": "./.yarn/cache/safe-regex-test-npm-1.0.0-e94a09b84e-c7248dfa07.zip/node_modules/safe-regex-test/",\ @@ -17564,6 +19095,16 @@ const RAW_RUNTIME_STATE = ["safe-regex-test", "npm:1.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/safe-regex-test-npm-1.1.0-453eb81b83-ebdb61f305.zip/node_modules/safe-regex-test/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["es-errors", "npm:1.3.0"],\ + ["is-regex", "npm:1.2.1"],\ + ["safe-regex-test", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["safe-stable-stringify", [\ @@ -17765,6 +19306,29 @@ const RAW_RUNTIME_STATE = ["set-function-name", "npm:2.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.0.2", {\ + "packageLocation": "./.yarn/cache/set-function-name-npm-2.0.2-3d9a2d8899-c7614154a5.zip/node_modules/set-function-name/",\ + "packageDependencies": [\ + ["define-data-property", "npm:1.1.4"],\ + ["es-errors", "npm:1.3.0"],\ + ["functions-have-names", "npm:1.2.3"],\ + ["has-property-descriptors", "npm:1.0.2"],\ + ["set-function-name", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["set-proto", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/set-proto-npm-1.0.0-68d7485485-b87f8187bc.zip/node_modules/set-proto/",\ + "packageDependencies": [\ + ["dunder-proto", "npm:1.0.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["set-proto", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["setimmediate", [\ @@ -18069,7 +19633,7 @@ const RAW_RUNTIME_STATE = ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:3.7.0", {\ "packageLocation": "./.yarn/__virtual__/sinon-chai-virtual-02851cc178/0/cache/sinon-chai-npm-3.7.0-8e6588805e-028853eb8a.zip/node_modules/sinon-chai/",\ "packageDependencies": [\ - ["@types/chai", "npm:4.2.22"],\ + ["@types/chai", "npm:4.3.20"],\ ["@types/sinon", "npm:9.0.11"],\ ["chai", "npm:4.3.10"],\ ["sinon", "npm:17.0.1"],\ @@ -18370,6 +19934,15 @@ const RAW_RUNTIME_STATE = ["spdx-license-ids", "npm:3.0.11"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.0.0", {\ + "packageLocation": "./.yarn/cache/spdx-expression-parse-npm-4.0.0-1c2f5caf51-936be681fb.zip/node_modules/spdx-expression-parse/",\ + "packageDependencies": [\ + ["spdx-exceptions", "npm:2.3.0"],\ + ["spdx-expression-parse", "npm:4.0.0"],\ + ["spdx-license-ids", "npm:3.0.11"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["spdx-license-ids", [\ @@ -18475,6 +20048,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["stable-hash-x", [\ + ["npm:0.2.0", {\ + "packageLocation": "./.yarn/cache/stable-hash-x-npm-0.2.0-1eebae4f09-136f05d0e4.zip/node_modules/stable-hash-x/",\ + "packageDependencies": [\ + ["stable-hash-x", "npm:0.2.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["stack-trace", [\ ["npm:0.0.10", {\ "packageLocation": "./.yarn/cache/stack-trace-npm-0.0.10-9460b173e1-7bd633f0e9.zip/node_modules/stack-trace/",\ @@ -18500,6 +20082,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["stop-iteration-iterator", [\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/stop-iteration-iterator-npm-1.1.0-057344287e-ff36c4db17.zip/node_modules/stop-iteration-iterator/",\ + "packageDependencies": [\ + ["es-errors", "npm:1.3.0"],\ + ["internal-slot", "npm:1.1.0"],\ + ["stop-iteration-iterator", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["stream-browserify", [\ ["npm:3.0.0", {\ "packageLocation": "./.yarn/cache/stream-browserify-npm-3.0.0-4c0bd97245-05a3cd0a0c.zip/node_modules/stream-browserify/",\ @@ -18568,9 +20161,68 @@ const RAW_RUNTIME_STATE = ["strip-ansi", "npm:7.1.0"]\ ],\ "linkType": "HARD"\ - }]\ - ]],\ - ["string.prototype.trim", [\ + }]\ + ]],\ + ["string.prototype.includes", [\ + ["npm:2.0.1", {\ + "packageLocation": "./.yarn/cache/string.prototype.includes-npm-2.0.1-12fb63787c-939a5447e4.zip/node_modules/string.prototype.includes/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["string.prototype.includes", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["string.prototype.matchall", [\ + ["npm:4.0.12", {\ + "packageLocation": "./.yarn/cache/string.prototype.matchall-npm-4.0.12-0bc859367d-e4ab34b9e7.zip/node_modules/string.prototype.matchall/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-errors", "npm:1.3.0"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["get-intrinsic", "npm:1.3.1"],\ + ["gopd", "npm:1.2.0"],\ + ["has-symbols", "npm:1.1.0"],\ + ["internal-slot", "npm:1.1.0"],\ + ["regexp.prototype.flags", "npm:1.5.4"],\ + ["set-function-name", "npm:2.0.2"],\ + ["side-channel", "npm:1.1.0"],\ + ["string.prototype.matchall", "npm:4.0.12"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["string.prototype.repeat", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/string.prototype.repeat-npm-1.0.0-3f87f5fd9e-4b1bd91b75.zip/node_modules/string.prototype.repeat/",\ + "packageDependencies": [\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["string.prototype.repeat", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["string.prototype.trim", [\ + ["npm:1.2.10", {\ + "packageLocation": "./.yarn/cache/string.prototype.trim-npm-1.2.10-40a44bc719-47bb63cd24.zip/node_modules/string.prototype.trim/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["define-data-property", "npm:1.1.4"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-abstract", "npm:1.24.1"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["has-property-descriptors", "npm:1.0.2"],\ + ["string.prototype.trim", "npm:1.2.10"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:1.2.8", {\ "packageLocation": "./.yarn/cache/string.prototype.trim-npm-1.2.8-7ed4517ce8-9301f6cb2b.zip/node_modules/string.prototype.trim/",\ "packageDependencies": [\ @@ -18592,6 +20244,17 @@ const RAW_RUNTIME_STATE = ["string.prototype.trimend", "npm:1.0.7"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.9", {\ + "packageLocation": "./.yarn/cache/string.prototype.trimend-npm-1.0.9-e8729528fb-140c73899b.zip/node_modules/string.prototype.trimend/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["string.prototype.trimend", "npm:1.0.9"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["string.prototype.trimstart", [\ @@ -18604,6 +20267,16 @@ const RAW_RUNTIME_STATE = ["string.prototype.trimstart", "npm:1.0.7"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.8", {\ + "packageLocation": "./.yarn/cache/string.prototype.trimstart-npm-1.0.8-8c6b16ba6e-160167dfbd.zip/node_modules/string.prototype.trimstart/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["define-properties", "npm:1.2.1"],\ + ["es-object-atoms", "npm:1.1.1"],\ + ["string.prototype.trimstart", "npm:1.0.8"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["string_decoder", [\ @@ -18859,14 +20532,14 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["tar", [\ - ["npm:7.5.6", {\ - "packageLocation": "./.yarn/cache/tar-npm-7.5.6-955ec951c2-cf4a84d79b.zip/node_modules/tar/",\ + ["npm:7.5.7", {\ + "packageLocation": "./.yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip/node_modules/tar/",\ "packageDependencies": [\ ["@isaacs/fs-minipass", "npm:4.0.1"],\ ["chownr", "npm:3.0.0"],\ ["minipass", "npm:7.1.2"],\ ["minizlib", "npm:3.1.0"],\ - ["tar", "npm:7.5.6"],\ + ["tar", "npm:7.5.7"],\ ["yallist", "npm:5.0.0"]\ ],\ "linkType": "HARD"\ @@ -19362,6 +21035,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["tinyglobby", [\ + ["npm:0.2.15", {\ + "packageLocation": "./.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-d72bd826a8.zip/node_modules/tinyglobby/",\ + "packageDependencies": [\ + ["fdir", "virtual:0e783aadbd2b4b8e6f6056033c0b290501892d23bc7c5dad5477e00e48ad8bd3e4434c3962a52dd75a58e06dbb7218094a494bac954ef2f7f6fdb65d9717e5f4#npm:6.5.0"],\ + ["picomatch", "npm:4.0.3"],\ + ["tinyglobby", "npm:0.2.15"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["tinylogic", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/tinylogic-npm-2.0.0-700fcc2fe0-6467b1ed9b.zip/node_modules/tinylogic/",\ @@ -19492,6 +21176,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:2.4.0", {\ + "packageLocation": "./.yarn/cache/ts-api-utils-npm-2.4.0-1179124e9a-d6b2b3b6ca.zip/node_modules/ts-api-utils/",\ + "packageDependencies": [\ + ["ts-api-utils", "npm:2.4.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:4884f2aa861da86c426c7089ed81a0a62b1c0338d3dd3b13ae03e14336a6aca2dd95612a024a0b64fa991e4dcc30ee6382e5fe33a6942b2990875fd837c701c8#npm:1.0.3", {\ "packageLocation": "./.yarn/__virtual__/ts-api-utils-virtual-f40b0f0c58/0/cache/ts-api-utils-npm-1.0.3-992f360d9b-1350a5110e.zip/node_modules/ts-api-utils/",\ "packageDependencies": [\ @@ -19504,6 +21195,55 @@ const RAW_RUNTIME_STATE = "typescript"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:2.4.0", {\ + "packageLocation": "./.yarn/__virtual__/ts-api-utils-virtual-f9d2e22849/0/cache/ts-api-utils-npm-2.4.0-1179124e9a-d6b2b3b6ca.zip/node_modules/ts-api-utils/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["ts-api-utils", "virtual:7a0e8d94303bde515e3bfcd8da7461b2acf1acc9c32b34f44e6f90b0c3583695623a60350a3b7a54deb3ee4d1fb16e9cee0aae66568026b0d1a281c8bf9f7ffd#npm:2.4.0"],\ + ["typescript", null]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:2.4.0", {\ + "packageLocation": "./.yarn/__virtual__/ts-api-utils-virtual-109258176c/0/cache/ts-api-utils-npm-2.4.0-1179124e9a-d6b2b3b6ca.zip/node_modules/ts-api-utils/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["ts-api-utils", "virtual:f9171b24fe2e543e9aa53531c88c2e7fe06ed5e78346a8295ff0ec461ebf1c1ec95332be858693513d91bb41a8b9667fe6be68b657310f6b0b82f965aacdde1c#npm:2.4.0"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["ts-declaration-location", [\ + ["npm:1.0.7", {\ + "packageLocation": "./.yarn/cache/ts-declaration-location-npm-1.0.7-804f747b5c-a7932fc75d.zip/node_modules/ts-declaration-location/",\ + "packageDependencies": [\ + ["ts-declaration-location", "npm:1.0.7"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:61e2ff1032c3492f5829d4326762d5c67af3b3ef5c7b4087320873e596f5a35b31ebda3dcb132749c6ab237f350cd625874adab839d2512369f2cec5dee0c7d3#npm:1.0.7", {\ + "packageLocation": "./.yarn/__virtual__/ts-declaration-location-virtual-0b1d7ef41b/0/cache/ts-declaration-location-npm-1.0.7-804f747b5c-a7932fc75d.zip/node_modules/ts-declaration-location/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["picomatch", "npm:4.0.3"],\ + ["ts-declaration-location", "virtual:61e2ff1032c3492f5829d4326762d5c67af3b3ef5c7b4087320873e596f5a35b31ebda3dcb132749c6ab237f350cd625874adab839d2512369f2cec5dee0c7d3#npm:1.0.7"],\ + ["typescript", null]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "typescript"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["ts-loader", [\ @@ -19514,6 +21254,50 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["virtual:897449be52adaf897095babe74bfcc926f5d083ac9aac6fbc5e260f1f71b7e3ada3f268ac9457d3009b9c6fca51fe685ec21fbed21ec5087df84ab489b719456#npm:9.5.0", {\ + "packageLocation": "./.yarn/__virtual__/ts-loader-virtual-a3720f3357/0/cache/ts-loader-npm-9.5.0-9514617263-8ffc6411ec.zip/node_modules/ts-loader/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["@types/webpack", null],\ + ["chalk", "npm:4.1.2"],\ + ["enhanced-resolve", "npm:5.15.0"],\ + ["micromatch", "npm:4.0.8"],\ + ["semver", "npm:7.5.3"],\ + ["source-map", "npm:0.7.4"],\ + ["ts-loader", "virtual:897449be52adaf897095babe74bfcc926f5d083ac9aac6fbc5e260f1f71b7e3ada3f268ac9457d3009b9c6fca51fe685ec21fbed21ec5087df84ab489b719456#npm:9.5.0"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ + ["webpack", "virtual:897449be52adaf897095babe74bfcc926f5d083ac9aac6fbc5e260f1f71b7e3ada3f268ac9457d3009b9c6fca51fe685ec21fbed21ec5087df84ab489b719456#npm:5.94.0"]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "@types/webpack",\ + "typescript",\ + "webpack"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:98d1afeac78a19485e4cb7428abff692e58b6fc468d8040035b560ed49383fc95857be6b5014af27e53063e6f08b654690c2b945f3443c22dd60c6b083684b3c#npm:9.5.0", {\ + "packageLocation": "./.yarn/__virtual__/ts-loader-virtual-af653dcb94/0/cache/ts-loader-npm-9.5.0-9514617263-8ffc6411ec.zip/node_modules/ts-loader/",\ + "packageDependencies": [\ + ["@types/typescript", null],\ + ["@types/webpack", null],\ + ["chalk", "npm:4.1.2"],\ + ["enhanced-resolve", "npm:5.15.0"],\ + ["micromatch", "npm:4.0.8"],\ + ["semver", "npm:7.5.3"],\ + ["source-map", "npm:0.7.4"],\ + ["ts-loader", "virtual:98d1afeac78a19485e4cb7428abff692e58b6fc468d8040035b560ed49383fc95857be6b5014af27e53063e6f08b654690c2b945f3443c22dd60c6b083684b3c#npm:9.5.0"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ + ["webpack", "virtual:98d1afeac78a19485e4cb7428abff692e58b6fc468d8040035b560ed49383fc95857be6b5014af27e53063e6f08b654690c2b945f3443c22dd60c6b083684b3c#npm:5.94.0"]\ + ],\ + "packagePeers": [\ + "@types/typescript",\ + "@types/webpack",\ + "typescript",\ + "webpack"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:9.5.0", {\ "packageLocation": "./.yarn/__virtual__/ts-loader-virtual-43597e08e9/0/cache/ts-loader-npm-9.5.0-9514617263-8ffc6411ec.zip/node_modules/ts-loader/",\ "packageDependencies": [\ @@ -19525,7 +21309,7 @@ const RAW_RUNTIME_STATE = ["semver", "npm:7.5.3"],\ ["source-map", "npm:0.7.4"],\ ["ts-loader", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:9.5.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["webpack", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.94.0"]\ ],\ "packagePeers": [\ @@ -19547,7 +21331,7 @@ const RAW_RUNTIME_STATE = ["semver", "npm:7.5.3"],\ ["source-map", "npm:0.7.4"],\ ["ts-loader", "virtual:da12f6bb23b671689b7f4f5cfff69cabf980ba04aff1ffd96860c787f7d5d08d32b0db765d9f16463de0d1af2c01fa6987b861cf5df2362e38e0ef415f29b51c#npm:9.5.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["webpack", "virtual:da12f6bb23b671689b7f4f5cfff69cabf980ba04aff1ffd96860c787f7d5d08d32b0db765d9f16463de0d1af2c01fa6987b861cf5df2362e38e0ef415f29b51c#npm:5.94.0"]\ ],\ "packagePeers": [\ @@ -19569,7 +21353,7 @@ const RAW_RUNTIME_STATE = ["semver", "npm:7.5.3"],\ ["source-map", "npm:0.7.4"],\ ["ts-loader", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:9.5.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["webpack", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:5.94.0"]\ ],\ "packagePeers": [\ @@ -19596,7 +21380,7 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["sinon", "npm:17.0.1"],\ ["ts-mock-imports", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:1.3.8"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"]\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"]\ ],\ "packagePeers": [\ "@types/sinon",\ @@ -19632,7 +21416,7 @@ const RAW_RUNTIME_STATE = ["@tsconfig/node12", "npm:1.0.9"],\ ["@tsconfig/node14", "npm:1.0.1"],\ ["@tsconfig/node16", "npm:1.0.2"],\ - ["@types/node", "npm:14.17.34"],\ + ["@types/node", "npm:20.19.30"],\ ["@types/swc__core", null],\ ["@types/swc__wasm", null],\ ["@types/typescript", null],\ @@ -19643,7 +21427,7 @@ const RAW_RUNTIME_STATE = ["diff", "npm:4.0.4"],\ ["make-error", "npm:1.3.6"],\ ["ts-node", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:10.9.2"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"],\ ["v8-compile-cache-lib", "npm:3.0.1"],\ ["yn", "npm:3.1.1"]\ ],\ @@ -19767,43 +21551,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["tsutils", [\ - ["npm:3.21.0", {\ - "packageLocation": "./.yarn/cache/tsutils-npm-3.21.0-347e6636c5-ea036bec1d.zip/node_modules/tsutils/",\ - "packageDependencies": [\ - ["tsutils", "npm:3.21.0"]\ - ],\ - "linkType": "SOFT"\ - }],\ - ["virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:3.21.0", {\ - "packageLocation": "./.yarn/__virtual__/tsutils-virtual-32b99c9531/0/cache/tsutils-npm-3.21.0-347e6636c5-ea036bec1d.zip/node_modules/tsutils/",\ - "packageDependencies": [\ - ["@types/typescript", null],\ - ["tslib", "npm:1.14.1"],\ - ["tsutils", "virtual:0e22d802b65219681b64a9f99af596d56d444fb6f03cdf776b56a06fb9ddeefe4b0a611780f0b0eea0b47a1f1fba5a366d19cd6561bbc1e55271f08c190cd76f#npm:3.21.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"]\ - ],\ - "packagePeers": [\ - "@types/typescript",\ - "typescript"\ - ],\ - "linkType": "HARD"\ - }],\ - ["virtual:ad07d3460ae416a99f304e6734121d5396603792c47f7c9a1b9c5c798d407da37779ac7289222241db922614d91f9d569b0f43bc10c027fcc720138b2f32e9fc#npm:3.21.0", {\ - "packageLocation": "./.yarn/__virtual__/tsutils-virtual-5e94504d8c/0/cache/tsutils-npm-3.21.0-347e6636c5-ea036bec1d.zip/node_modules/tsutils/",\ - "packageDependencies": [\ - ["@types/typescript", null],\ - ["tslib", "npm:1.14.1"],\ - ["tsutils", "virtual:ad07d3460ae416a99f304e6734121d5396603792c47f7c9a1b9c5c798d407da37779ac7289222241db922614d91f9d569b0f43bc10c027fcc720138b2f32e9fc#npm:3.21.0"],\ - ["typescript", null]\ - ],\ - "packagePeers": [\ - "@types/typescript",\ - "typescript"\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["tuf-js", [\ ["npm:1.1.7", {\ "packageLocation": "./.yarn/cache/tuf-js-npm-1.1.7-045f70823d-8ce0061b76.zip/node_modules/tuf-js/",\ @@ -19888,13 +21635,6 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:0.20.2", {\ - "packageLocation": "./.yarn/cache/type-fest-npm-0.20.2-b36432617f-8907e16284.zip/node_modules/type-fest/",\ - "packageDependencies": [\ - ["type-fest", "npm:0.20.2"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:0.21.3", {\ "packageLocation": "./.yarn/cache/type-fest-npm-0.21.3-5ff2a9c6fd-f4254070d9.zip/node_modules/type-fest/",\ "packageDependencies": [\ @@ -19961,6 +21701,18 @@ const RAW_RUNTIME_STATE = ["typed-array-byte-length", "npm:1.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.3", {\ + "packageLocation": "./.yarn/cache/typed-array-byte-length-npm-1.0.3-0769937080-269dad101d.zip/node_modules/typed-array-byte-length/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["for-each", "npm:0.3.3"],\ + ["gopd", "npm:1.2.0"],\ + ["has-proto", "npm:1.2.0"],\ + ["is-typed-array", "npm:1.1.15"],\ + ["typed-array-byte-length", "npm:1.0.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["typed-array-byte-offset", [\ @@ -19975,6 +21727,20 @@ const RAW_RUNTIME_STATE = ["typed-array-byte-offset", "npm:1.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.4", {\ + "packageLocation": "./.yarn/cache/typed-array-byte-offset-npm-1.0.4-12f60e4553-c2869aa584.zip/node_modules/typed-array-byte-offset/",\ + "packageDependencies": [\ + ["available-typed-arrays", "npm:1.0.7"],\ + ["call-bind", "npm:1.0.8"],\ + ["for-each", "npm:0.3.3"],\ + ["gopd", "npm:1.2.0"],\ + ["has-proto", "npm:1.2.0"],\ + ["is-typed-array", "npm:1.1.15"],\ + ["reflect.getprototypeof", "npm:1.0.10"],\ + ["typed-array-byte-offset", "npm:1.0.4"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["typed-array-length", [\ @@ -19987,6 +21753,19 @@ const RAW_RUNTIME_STATE = ["typed-array-length", "npm:1.0.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.7", {\ + "packageLocation": "./.yarn/cache/typed-array-length-npm-1.0.7-ac6ef772a7-d6b2f0e811.zip/node_modules/typed-array-length/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.8"],\ + ["for-each", "npm:0.3.3"],\ + ["gopd", "npm:1.0.1"],\ + ["is-typed-array", "npm:1.1.15"],\ + ["possible-typed-array-names", "npm:1.1.0"],\ + ["reflect.getprototypeof", "npm:1.0.10"],\ + ["typed-array-length", "npm:1.0.7"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["typed-function", [\ @@ -20015,6 +21794,43 @@ const RAW_RUNTIME_STATE = ["typescript", "patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3"]\ ],\ "linkType": "HARD"\ + }],\ + ["patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5", {\ + "packageLocation": "./.yarn/cache/typescript-patch-6fda4d02cf-696e1b017b.zip/node_modules/typescript/",\ + "packageDependencies": [\ + ["typescript", "patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["typescript-eslint", [\ + ["npm:8.54.0", {\ + "packageLocation": "./.yarn/cache/typescript-eslint-npm-8.54.0-4dca5fd4d6-21b1a27fd4.zip/node_modules/typescript-eslint/",\ + "packageDependencies": [\ + ["typescript-eslint", "npm:8.54.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:8.54.0", {\ + "packageLocation": "./.yarn/__virtual__/typescript-eslint-virtual-d4bd20e333/0/cache/typescript-eslint-npm-8.54.0-4dca5fd4d6-21b1a27fd4.zip/node_modules/typescript-eslint/",\ + "packageDependencies": [\ + ["@types/eslint", null],\ + ["@types/typescript", null],\ + ["@typescript-eslint/eslint-plugin", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/parser", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/typescript-estree", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["@typescript-eslint/utils", "virtual:d4bd20e333c5ce27dda9b238d0192b1fce0aeb7e3919230f972c80698c333e68f9a41eb49db2320d305ca1c1c2a360d892c2f46705ca1a0e94b494d96615ae56#npm:8.54.0"],\ + ["eslint", "virtual:de32c10d523830f1843784ae863166d6ef2e074b6da9615f2b3296a1f90385ed3f59e274e3957326ba7cf3442d82470d9e1ec01e6720989a570c075c95d90dbc#npm:9.39.2"],\ + ["typescript", null],\ + ["typescript-eslint", "virtual:ebe53227cf44f91e7e28ad3f7ba32ed24bbe34f70980677cfe8a35e8b9abb48f92736e4f60dfb08a49652a1788b380dd9495c14498e60fcbe16a5736d9732b8d#npm:8.54.0"]\ + ],\ + "packagePeers": [\ + "@types/eslint",\ + "@types/typescript",\ + "eslint",\ + "typescript"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["ua-parser-js", [\ @@ -20073,6 +21889,17 @@ const RAW_RUNTIME_STATE = ["which-boxed-primitive", "npm:1.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/unbox-primitive-npm-1.1.0-269638c590-fadb347020.zip/node_modules/unbox-primitive/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["has-bigints", "npm:1.0.2"],\ + ["has-symbols", "npm:1.1.0"],\ + ["unbox-primitive", "npm:1.1.0"],\ + ["which-boxed-primitive", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["undefsafe", [\ @@ -20084,6 +21911,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["undici-types", [\ + ["npm:6.21.0", {\ + "packageLocation": "./.yarn/cache/undici-types-npm-6.21.0-eb2b0ed56a-ec8f41aa43.zip/node_modules/undici-types/",\ + "packageDependencies": [\ + ["undici-types", "npm:6.21.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["unicode-canonical-property-names-ecmascript", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/unicode-canonical-property-names-ecmascript-npm-2.0.0-d2d8554a14-39be078afd.zip/node_modules/unicode-canonical-property-names-ecmascript/",\ @@ -20178,6 +22014,35 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["unrs-resolver", [\ + ["npm:1.11.1", {\ + "packageLocation": "./.yarn/unplugged/unrs-resolver-npm-1.11.1-9828edd1f1/node_modules/unrs-resolver/",\ + "packageDependencies": [\ + ["@unrs/resolver-binding-android-arm-eabi", "npm:1.11.1"],\ + ["@unrs/resolver-binding-android-arm64", "npm:1.11.1"],\ + ["@unrs/resolver-binding-darwin-arm64", "npm:1.11.1"],\ + ["@unrs/resolver-binding-darwin-x64", "npm:1.11.1"],\ + ["@unrs/resolver-binding-freebsd-x64", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-arm-gnueabihf", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-arm-musleabihf", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-arm64-gnu", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-arm64-musl", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-ppc64-gnu", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-riscv64-gnu", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-riscv64-musl", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-s390x-gnu", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-x64-gnu", "npm:1.11.1"],\ + ["@unrs/resolver-binding-linux-x64-musl", "npm:1.11.1"],\ + ["@unrs/resolver-binding-wasm32-wasi", "npm:1.11.1"],\ + ["@unrs/resolver-binding-win32-arm64-msvc", "npm:1.11.1"],\ + ["@unrs/resolver-binding-win32-ia32-msvc", "npm:1.11.1"],\ + ["@unrs/resolver-binding-win32-x64-msvc", "npm:1.11.1"],\ + ["napi-postinstall", "npm:0.3.4"],\ + ["unrs-resolver", "npm:1.11.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["untildify", [\ ["npm:4.0.0", {\ "packageLocation": "./.yarn/cache/untildify-npm-4.0.0-4a8b569825-39ced9c418.zip/node_modules/untildify/",\ @@ -21217,6 +23082,53 @@ const RAW_RUNTIME_STATE = ["which-boxed-primitive", "npm:1.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/which-boxed-primitive-npm-1.1.1-80ca20c912-a877c0667b.zip/node_modules/which-boxed-primitive/",\ + "packageDependencies": [\ + ["is-bigint", "npm:1.1.0"],\ + ["is-boolean-object", "npm:1.2.2"],\ + ["is-number-object", "npm:1.1.1"],\ + ["is-string", "npm:1.1.1"],\ + ["is-symbol", "npm:1.1.1"],\ + ["which-boxed-primitive", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["which-builtin-type", [\ + ["npm:1.2.1", {\ + "packageLocation": "./.yarn/cache/which-builtin-type-npm-1.2.1-bbbdf9137f-22c81c5cb7.zip/node_modules/which-builtin-type/",\ + "packageDependencies": [\ + ["call-bound", "npm:1.0.4"],\ + ["function.prototype.name", "npm:1.1.6"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["is-async-function", "npm:2.1.1"],\ + ["is-date-object", "npm:1.1.0"],\ + ["is-finalizationregistry", "npm:1.1.1"],\ + ["is-generator-function", "npm:1.1.2"],\ + ["is-regex", "npm:1.2.1"],\ + ["is-weakref", "npm:1.0.2"],\ + ["isarray", "npm:2.0.5"],\ + ["which-boxed-primitive", "npm:1.1.1"],\ + ["which-builtin-type", "npm:1.2.1"],\ + ["which-collection", "npm:1.0.2"],\ + ["which-typed-array", "npm:1.1.19"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["which-collection", [\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/which-collection-npm-1.0.2-0d6277e921-674bf659b9.zip/node_modules/which-collection/",\ + "packageDependencies": [\ + ["is-map", "npm:2.0.3"],\ + ["is-set", "npm:2.0.3"],\ + ["is-weakmap", "npm:2.0.2"],\ + ["is-weakset", "npm:2.0.4"],\ + ["which-collection", "npm:1.0.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["which-module", [\ @@ -21265,6 +23177,20 @@ const RAW_RUNTIME_STATE = ["which-typed-array", "npm:1.1.19"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.20", {\ + "packageLocation": "./.yarn/cache/which-typed-array-npm-1.1.20-8cc727cdc7-e56da3fc99.zip/node_modules/which-typed-array/",\ + "packageDependencies": [\ + ["available-typed-arrays", "npm:1.0.7"],\ + ["call-bind", "npm:1.0.8"],\ + ["call-bound", "npm:1.0.4"],\ + ["for-each", "npm:0.3.5"],\ + ["get-proto", "npm:1.0.1"],\ + ["gopd", "npm:1.2.0"],\ + ["has-tostringtag", "npm:1.0.2"],\ + ["which-typed-array", "npm:1.1.20"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["wide-align", [\ @@ -21753,6 +23679,37 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }]\ + ]],\ + ["zod", [\ + ["npm:4.3.6", {\ + "packageLocation": "./.yarn/cache/zod-npm-4.3.6-a096e305e6-25fc0f62e0.zip/node_modules/zod/",\ + "packageDependencies": [\ + ["zod", "npm:4.3.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["zod-validation-error", [\ + ["npm:4.0.2", {\ + "packageLocation": "./.yarn/cache/zod-validation-error-npm-4.0.2-1b963160c8-5e35ca8ebb.zip/node_modules/zod-validation-error/",\ + "packageDependencies": [\ + ["zod-validation-error", "npm:4.0.2"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:097f27741dd7a82ac250aa766dbcf2b0f412a6af223498f6266f2e95d7fc4506b64ede3a0f0ba5416e3c5e32f4f84aaf10f3427e75957ee48e6797b149f5498a#npm:4.0.2", {\ + "packageLocation": "./.yarn/__virtual__/zod-validation-error-virtual-f7c05e2010/0/cache/zod-validation-error-npm-4.0.2-1b963160c8-5e35ca8ebb.zip/node_modules/zod-validation-error/",\ + "packageDependencies": [\ + ["@types/zod", null],\ + ["zod", "npm:4.3.6"],\ + ["zod-validation-error", "virtual:097f27741dd7a82ac250aa766dbcf2b0f412a6af223498f6266f2e95d7fc4506b64ede3a0f0ba5416e3c5e32f4f84aaf10f3427e75957ee48e6797b149f5498a#npm:4.0.2"]\ + ],\ + "packagePeers": [\ + "@types/zod",\ + "zod"\ + ],\ + "linkType": "HARD"\ + }]\ ]]\ ]\ }'; diff --git a/.yarn/cache/@babel-code-frame-npm-7.28.6-7d31d84e6c-93e7ed9e03.zip b/.yarn/cache/@babel-code-frame-npm-7.28.6-7d31d84e6c-93e7ed9e03.zip new file mode 100644 index 00000000000..cb434cbcbea Binary files /dev/null and b/.yarn/cache/@babel-code-frame-npm-7.28.6-7d31d84e6c-93e7ed9e03.zip differ diff --git a/.yarn/cache/@babel-compat-data-npm-7.28.6-4e0cdcaa44-dc17dfb557.zip b/.yarn/cache/@babel-compat-data-npm-7.28.6-4e0cdcaa44-dc17dfb557.zip new file mode 100644 index 00000000000..2185cb11afe Binary files /dev/null and b/.yarn/cache/@babel-compat-data-npm-7.28.6-4e0cdcaa44-dc17dfb557.zip differ diff --git a/.yarn/cache/@babel-core-npm-7.28.6-0abdbf2b3d-1a150a69c5.zip b/.yarn/cache/@babel-core-npm-7.28.6-0abdbf2b3d-1a150a69c5.zip new file mode 100644 index 00000000000..ff02e0c65cc Binary files /dev/null and b/.yarn/cache/@babel-core-npm-7.28.6-0abdbf2b3d-1a150a69c5.zip differ diff --git a/.yarn/cache/@babel-eslint-parser-npm-7.26.10-52ac28fff9-27eb60d16b.zip b/.yarn/cache/@babel-eslint-parser-npm-7.26.10-52ac28fff9-27eb60d16b.zip deleted file mode 100644 index 65ae2111742..00000000000 Binary files a/.yarn/cache/@babel-eslint-parser-npm-7.26.10-52ac28fff9-27eb60d16b.zip and /dev/null differ diff --git a/.yarn/cache/@babel-generator-npm-7.23.3-a2ca9dda65-0f815d275c.zip b/.yarn/cache/@babel-generator-npm-7.23.3-a2ca9dda65-0f815d275c.zip deleted file mode 100644 index 3738cca6bc8..00000000000 Binary files a/.yarn/cache/@babel-generator-npm-7.23.3-a2ca9dda65-0f815d275c.zip and /dev/null differ diff --git a/.yarn/cache/@babel-generator-npm-7.28.6-18c2d22a25-ef2af927e8.zip b/.yarn/cache/@babel-generator-npm-7.28.6-18c2d22a25-ef2af927e8.zip new file mode 100644 index 00000000000..429b9683970 Binary files /dev/null and b/.yarn/cache/@babel-generator-npm-7.28.6-18c2d22a25-ef2af927e8.zip differ diff --git a/.yarn/cache/@babel-helper-compilation-targets-npm-7.28.6-8880f389c9-f512a5aeee.zip b/.yarn/cache/@babel-helper-compilation-targets-npm-7.28.6-8880f389c9-f512a5aeee.zip new file mode 100644 index 00000000000..ff63e1b6875 Binary files /dev/null and b/.yarn/cache/@babel-helper-compilation-targets-npm-7.28.6-8880f389c9-f512a5aeee.zip differ diff --git a/.yarn/cache/@babel-helper-environment-visitor-npm-7.22.20-260909e014-d80ee98ff6.zip b/.yarn/cache/@babel-helper-environment-visitor-npm-7.22.20-260909e014-d80ee98ff6.zip deleted file mode 100644 index 3d5f74720b2..00000000000 Binary files a/.yarn/cache/@babel-helper-environment-visitor-npm-7.22.20-260909e014-d80ee98ff6.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-function-name-npm-7.23.0-ce38271242-7b2ae024cd.zip b/.yarn/cache/@babel-helper-function-name-npm-7.23.0-ce38271242-7b2ae024cd.zip deleted file mode 100644 index b6a4704442e..00000000000 Binary files a/.yarn/cache/@babel-helper-function-name-npm-7.23.0-ce38271242-7b2ae024cd.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-91445f7edf.zip b/.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-91445f7edf.zip new file mode 100644 index 00000000000..17e2b2cd156 Binary files /dev/null and b/.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-91445f7edf.zip differ diff --git a/.yarn/cache/@babel-helper-hoist-variables-npm-7.22.5-6db3192347-394ca191b4.zip b/.yarn/cache/@babel-helper-hoist-variables-npm-7.22.5-6db3192347-394ca191b4.zip deleted file mode 100644 index cf472663962..00000000000 Binary files a/.yarn/cache/@babel-helper-hoist-variables-npm-7.22.5-6db3192347-394ca191b4.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-module-imports-npm-7.28.6-5b95b9145c-64b1380d74.zip b/.yarn/cache/@babel-helper-module-imports-npm-7.28.6-5b95b9145c-64b1380d74.zip new file mode 100644 index 00000000000..6b77ecc2c79 Binary files /dev/null and b/.yarn/cache/@babel-helper-module-imports-npm-7.28.6-5b95b9145c-64b1380d74.zip differ diff --git a/.yarn/cache/@babel-helper-module-transforms-npm-7.28.6-5923cf5a95-2e421c7db7.zip b/.yarn/cache/@babel-helper-module-transforms-npm-7.28.6-5923cf5a95-2e421c7db7.zip new file mode 100644 index 00000000000..48651a8a4ba Binary files /dev/null and b/.yarn/cache/@babel-helper-module-transforms-npm-7.28.6-5923cf5a95-2e421c7db7.zip differ diff --git a/.yarn/cache/@babel-helper-split-export-declaration-npm-7.22.6-e723505aef-e141cace58.zip b/.yarn/cache/@babel-helper-split-export-declaration-npm-7.22.6-e723505aef-e141cace58.zip deleted file mode 100644 index c2ebd88f020..00000000000 Binary files a/.yarn/cache/@babel-helper-split-export-declaration-npm-7.22.6-e723505aef-e141cace58.zip and /dev/null differ diff --git a/.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-0ae29cc200.zip b/.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-0ae29cc200.zip new file mode 100644 index 00000000000..db113bb54d6 Binary files /dev/null and b/.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-0ae29cc200.zip differ diff --git a/.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-8e5d9b0133.zip b/.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-8e5d9b0133.zip new file mode 100644 index 00000000000..c67a0ac568c Binary files /dev/null and b/.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-8e5d9b0133.zip differ diff --git a/.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-db73e6a308.zip b/.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-db73e6a308.zip new file mode 100644 index 00000000000..27c1a7fa344 Binary files /dev/null and b/.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-db73e6a308.zip differ diff --git a/.yarn/cache/@babel-helpers-npm-7.28.6-682df48628-213485cdff.zip b/.yarn/cache/@babel-helpers-npm-7.28.6-682df48628-213485cdff.zip new file mode 100644 index 00000000000..c894d4a2860 Binary files /dev/null and b/.yarn/cache/@babel-helpers-npm-7.28.6-682df48628-213485cdff.zip differ diff --git a/.yarn/cache/@babel-parser-npm-7.23.3-8d3a021e39-284c22ec1d.zip b/.yarn/cache/@babel-parser-npm-7.23.3-8d3a021e39-284c22ec1d.zip deleted file mode 100644 index 9d6e9be167b..00000000000 Binary files a/.yarn/cache/@babel-parser-npm-7.23.3-8d3a021e39-284c22ec1d.zip and /dev/null differ diff --git a/.yarn/cache/@babel-parser-npm-7.28.6-b41fd3a428-483a6fb5f9.zip b/.yarn/cache/@babel-parser-npm-7.28.6-b41fd3a428-483a6fb5f9.zip new file mode 100644 index 00000000000..f2d7aa1e281 Binary files /dev/null and b/.yarn/cache/@babel-parser-npm-7.28.6-b41fd3a428-483a6fb5f9.zip differ diff --git a/.yarn/cache/@babel-template-npm-7.22.15-0b464facb4-21e768e4ee.zip b/.yarn/cache/@babel-template-npm-7.22.15-0b464facb4-21e768e4ee.zip deleted file mode 100644 index 68979e397b5..00000000000 Binary files a/.yarn/cache/@babel-template-npm-7.22.15-0b464facb4-21e768e4ee.zip and /dev/null differ diff --git a/.yarn/cache/@babel-template-npm-7.28.6-bff3bc3923-0ad6e32bf1.zip b/.yarn/cache/@babel-template-npm-7.28.6-bff3bc3923-0ad6e32bf1.zip new file mode 100644 index 00000000000..970194132ea Binary files /dev/null and b/.yarn/cache/@babel-template-npm-7.28.6-bff3bc3923-0ad6e32bf1.zip differ diff --git a/.yarn/cache/@babel-traverse-npm-7.23.3-a268f4c943-522ef8eefe.zip b/.yarn/cache/@babel-traverse-npm-7.23.3-a268f4c943-522ef8eefe.zip deleted file mode 100644 index 6deb3eb1793..00000000000 Binary files a/.yarn/cache/@babel-traverse-npm-7.23.3-a268f4c943-522ef8eefe.zip and /dev/null differ diff --git a/.yarn/cache/@babel-traverse-npm-7.28.6-e426afeacf-dd71efe941.zip b/.yarn/cache/@babel-traverse-npm-7.28.6-e426afeacf-dd71efe941.zip new file mode 100644 index 00000000000..38fc42decd1 Binary files /dev/null and b/.yarn/cache/@babel-traverse-npm-7.28.6-e426afeacf-dd71efe941.zip differ diff --git a/.yarn/cache/@babel-types-npm-7.28.6-623ccfc882-f9c6e52b45.zip b/.yarn/cache/@babel-types-npm-7.28.6-623ccfc882-f9c6e52b45.zip new file mode 100644 index 00000000000..acbaa915f18 Binary files /dev/null and b/.yarn/cache/@babel-types-npm-7.28.6-623ccfc882-f9c6e52b45.zip differ diff --git a/.yarn/cache/@emnapi-core-npm-1.8.1-9be0a25589-904ea60c91.zip b/.yarn/cache/@emnapi-core-npm-1.8.1-9be0a25589-904ea60c91.zip new file mode 100644 index 00000000000..b97b75b57e7 Binary files /dev/null and b/.yarn/cache/@emnapi-core-npm-1.8.1-9be0a25589-904ea60c91.zip differ diff --git a/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-26725e202d.zip b/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-26725e202d.zip new file mode 100644 index 00000000000..669c0bafe14 Binary files /dev/null and b/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-26725e202d.zip differ diff --git a/.yarn/cache/@emnapi-wasi-threads-npm-1.1.0-4dc2c60138-0d557e7526.zip b/.yarn/cache/@emnapi-wasi-threads-npm-1.1.0-4dc2c60138-0d557e7526.zip new file mode 100644 index 00000000000..0dbd6d7dab9 Binary files /dev/null and b/.yarn/cache/@emnapi-wasi-threads-npm-1.1.0-4dc2c60138-0d557e7526.zip differ diff --git a/.yarn/cache/@es-joy-jsdoccomment-npm-0.41.0-20acf8fb8c-ea581983f3.zip b/.yarn/cache/@es-joy-jsdoccomment-npm-0.41.0-20acf8fb8c-ea581983f3.zip deleted file mode 100644 index e4cb94088c0..00000000000 Binary files a/.yarn/cache/@es-joy-jsdoccomment-npm-0.41.0-20acf8fb8c-ea581983f3.zip and /dev/null differ diff --git a/.yarn/cache/@es-joy-jsdoccomment-npm-0.50.2-971362ab5d-a309f01bd1.zip b/.yarn/cache/@es-joy-jsdoccomment-npm-0.50.2-971362ab5d-a309f01bd1.zip new file mode 100644 index 00000000000..36ab2583ab0 Binary files /dev/null and b/.yarn/cache/@es-joy-jsdoccomment-npm-0.50.2-971362ab5d-a309f01bd1.zip differ diff --git a/.yarn/cache/@eslint-community-eslint-utils-npm-4.9.1-30ad3d49de-863b546786.zip b/.yarn/cache/@eslint-community-eslint-utils-npm-4.9.1-30ad3d49de-863b546786.zip new file mode 100644 index 00000000000..2367d46b6dd Binary files /dev/null and b/.yarn/cache/@eslint-community-eslint-utils-npm-4.9.1-30ad3d49de-863b546786.zip differ diff --git a/.yarn/cache/@eslint-community-regexpp-npm-4.10.0-6bfb984c81-8c36169c81.zip b/.yarn/cache/@eslint-community-regexpp-npm-4.10.0-6bfb984c81-8c36169c81.zip deleted file mode 100644 index 14fb460b5df..00000000000 Binary files a/.yarn/cache/@eslint-community-regexpp-npm-4.10.0-6bfb984c81-8c36169c81.zip and /dev/null differ diff --git a/.yarn/cache/@eslint-community-regexpp-npm-4.12.2-3d54624470-049b280fdd.zip b/.yarn/cache/@eslint-community-regexpp-npm-4.12.2-3d54624470-049b280fdd.zip new file mode 100644 index 00000000000..06474fdbb17 Binary files /dev/null and b/.yarn/cache/@eslint-community-regexpp-npm-4.12.2-3d54624470-049b280fdd.zip differ diff --git a/.yarn/cache/@eslint-config-array-npm-0.21.1-c33ed9ec91-6eaa043597.zip b/.yarn/cache/@eslint-config-array-npm-0.21.1-c33ed9ec91-6eaa043597.zip new file mode 100644 index 00000000000..ff5d07c348b Binary files /dev/null and b/.yarn/cache/@eslint-config-array-npm-0.21.1-c33ed9ec91-6eaa043597.zip differ diff --git a/.yarn/cache/@eslint-config-helpers-npm-0.4.2-a55655f805-3f2b4712d8.zip b/.yarn/cache/@eslint-config-helpers-npm-0.4.2-a55655f805-3f2b4712d8.zip new file mode 100644 index 00000000000..6beec5b229d Binary files /dev/null and b/.yarn/cache/@eslint-config-helpers-npm-0.4.2-a55655f805-3f2b4712d8.zip differ diff --git a/.yarn/cache/@eslint-core-npm-0.17.0-8579df04c4-f9a428cc65.zip b/.yarn/cache/@eslint-core-npm-0.17.0-8579df04c4-f9a428cc65.zip new file mode 100644 index 00000000000..ecbbc958699 Binary files /dev/null and b/.yarn/cache/@eslint-core-npm-0.17.0-8579df04c4-f9a428cc65.zip differ diff --git a/.yarn/cache/@eslint-eslintrc-npm-2.1.3-088d1bae55-77b70a8923.zip b/.yarn/cache/@eslint-eslintrc-npm-2.1.3-088d1bae55-77b70a8923.zip deleted file mode 100644 index e6ecb249947..00000000000 Binary files a/.yarn/cache/@eslint-eslintrc-npm-2.1.3-088d1bae55-77b70a8923.zip and /dev/null differ diff --git a/.yarn/cache/@eslint-eslintrc-npm-3.3.3-8ccf6281a3-b586a364ff.zip b/.yarn/cache/@eslint-eslintrc-npm-3.3.3-8ccf6281a3-b586a364ff.zip new file mode 100644 index 00000000000..ff7cd454739 Binary files /dev/null and b/.yarn/cache/@eslint-eslintrc-npm-3.3.3-8ccf6281a3-b586a364ff.zip differ diff --git a/.yarn/cache/@eslint-js-npm-8.53.0-1ffdbc6083-a372d55aa2.zip b/.yarn/cache/@eslint-js-npm-8.53.0-1ffdbc6083-a372d55aa2.zip deleted file mode 100644 index 47ee7e703e6..00000000000 Binary files a/.yarn/cache/@eslint-js-npm-8.53.0-1ffdbc6083-a372d55aa2.zip and /dev/null differ diff --git a/.yarn/cache/@eslint-js-npm-9.39.2-c8e5f9bf73-6b7f676746.zip b/.yarn/cache/@eslint-js-npm-9.39.2-c8e5f9bf73-6b7f676746.zip new file mode 100644 index 00000000000..8919e7e5081 Binary files /dev/null and b/.yarn/cache/@eslint-js-npm-9.39.2-c8e5f9bf73-6b7f676746.zip differ diff --git a/.yarn/cache/@eslint-object-schema-npm-2.1.7-cb962a5b9b-946ef5d623.zip b/.yarn/cache/@eslint-object-schema-npm-2.1.7-cb962a5b9b-946ef5d623.zip new file mode 100644 index 00000000000..f4debd97cb0 Binary files /dev/null and b/.yarn/cache/@eslint-object-schema-npm-2.1.7-cb962a5b9b-946ef5d623.zip differ diff --git a/.yarn/cache/@eslint-plugin-kit-npm-0.4.1-3df70dd079-c5947d0ffe.zip b/.yarn/cache/@eslint-plugin-kit-npm-0.4.1-3df70dd079-c5947d0ffe.zip new file mode 100644 index 00000000000..76767638b08 Binary files /dev/null and b/.yarn/cache/@eslint-plugin-kit-npm-0.4.1-3df70dd079-c5947d0ffe.zip differ diff --git a/.yarn/cache/@humanfs-core-npm-0.19.1-e2e7aaeb6e-270d936be4.zip b/.yarn/cache/@humanfs-core-npm-0.19.1-e2e7aaeb6e-270d936be4.zip new file mode 100644 index 00000000000..0d6b5389950 Binary files /dev/null and b/.yarn/cache/@humanfs-core-npm-0.19.1-e2e7aaeb6e-270d936be4.zip differ diff --git a/.yarn/cache/@humanfs-node-npm-0.16.7-fa16bdb590-b3633d3dce.zip b/.yarn/cache/@humanfs-node-npm-0.16.7-fa16bdb590-b3633d3dce.zip new file mode 100644 index 00000000000..168ec6c7cca Binary files /dev/null and b/.yarn/cache/@humanfs-node-npm-0.16.7-fa16bdb590-b3633d3dce.zip differ diff --git a/.yarn/cache/@humanwhocodes-config-array-npm-0.11.13-12314014f2-9f655e1df7.zip b/.yarn/cache/@humanwhocodes-config-array-npm-0.11.13-12314014f2-9f655e1df7.zip deleted file mode 100644 index b9d9d908651..00000000000 Binary files a/.yarn/cache/@humanwhocodes-config-array-npm-0.11.13-12314014f2-9f655e1df7.zip and /dev/null differ diff --git a/.yarn/cache/@humanwhocodes-object-schema-npm-2.0.1-c23364bbfc-dbddfd0465.zip b/.yarn/cache/@humanwhocodes-object-schema-npm-2.0.1-c23364bbfc-dbddfd0465.zip deleted file mode 100644 index 8f9b36f179d..00000000000 Binary files a/.yarn/cache/@humanwhocodes-object-schema-npm-2.0.1-c23364bbfc-dbddfd0465.zip and /dev/null differ diff --git a/.yarn/cache/@humanwhocodes-retry-npm-0.4.3-a8d7ca1663-0b32cfd362.zip b/.yarn/cache/@humanwhocodes-retry-npm-0.4.3-a8d7ca1663-0b32cfd362.zip new file mode 100644 index 00000000000..821368ba44e Binary files /dev/null and b/.yarn/cache/@humanwhocodes-retry-npm-0.4.3-a8d7ca1663-0b32cfd362.zip differ diff --git a/.yarn/cache/@isaacs-balanced-match-npm-4.0.1-8965afafe6-102fbc6d2c.zip b/.yarn/cache/@isaacs-balanced-match-npm-4.0.1-8965afafe6-102fbc6d2c.zip new file mode 100644 index 00000000000..c4f239c1ab5 Binary files /dev/null and b/.yarn/cache/@isaacs-balanced-match-npm-4.0.1-8965afafe6-102fbc6d2c.zip differ diff --git a/.yarn/cache/@isaacs-brace-expansion-npm-5.0.0-754d3cb3f5-cf3b7f206a.zip b/.yarn/cache/@isaacs-brace-expansion-npm-5.0.0-754d3cb3f5-cf3b7f206a.zip new file mode 100644 index 00000000000..6fd9e4bbe9d Binary files /dev/null and b/.yarn/cache/@isaacs-brace-expansion-npm-5.0.0-754d3cb3f5-cf3b7f206a.zip differ diff --git a/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-902f8261dc.zip b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-902f8261dc.zip new file mode 100644 index 00000000000..e130971fd99 Binary files /dev/null and b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-902f8261dc.zip differ diff --git a/.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-c2bb01856e.zip b/.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-c2bb01856e.zip new file mode 100644 index 00000000000..3376d7035ad Binary files /dev/null and b/.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-c2bb01856e.zip differ diff --git a/.yarn/cache/@jridgewell-sourcemap-codec-npm-1.5.5-5189d9fc79-5d9d207b46.zip b/.yarn/cache/@jridgewell-sourcemap-codec-npm-1.5.5-5189d9fc79-5d9d207b46.zip new file mode 100644 index 00000000000..4282d81ad8d Binary files /dev/null and b/.yarn/cache/@jridgewell-sourcemap-codec-npm-1.5.5-5189d9fc79-5d9d207b46.zip differ diff --git a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-da0283270e.zip b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-da0283270e.zip new file mode 100644 index 00000000000..d61ababcdd3 Binary files /dev/null and b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-da0283270e.zip differ diff --git a/.yarn/cache/@napi-rs-wasm-runtime-npm-0.2.12-8f0d65e253-5fd5181824.zip b/.yarn/cache/@napi-rs-wasm-runtime-npm-0.2.12-8f0d65e253-5fd5181824.zip new file mode 100644 index 00000000000..ddc8e2e6d84 Binary files /dev/null and b/.yarn/cache/@napi-rs-wasm-runtime-npm-0.2.12-8f0d65e253-5fd5181824.zip differ diff --git a/.yarn/cache/@next-eslint-plugin-next-npm-16.1.5-a20eef2072-8846e6a014.zip b/.yarn/cache/@next-eslint-plugin-next-npm-16.1.5-a20eef2072-8846e6a014.zip new file mode 100644 index 00000000000..748a06b3edd Binary files /dev/null and b/.yarn/cache/@next-eslint-plugin-next-npm-16.1.5-a20eef2072-8846e6a014.zip differ diff --git a/.yarn/cache/@nicolo-ribaudo-eslint-scope-5-internals-npm-5.1.1-v1-87df86be4b-f2e3b2d6a6.zip b/.yarn/cache/@nicolo-ribaudo-eslint-scope-5-internals-npm-5.1.1-v1-87df86be4b-f2e3b2d6a6.zip deleted file mode 100644 index 93ca0c341d5..00000000000 Binary files a/.yarn/cache/@nicolo-ribaudo-eslint-scope-5-internals-npm-5.1.1-v1-87df86be4b-f2e3b2d6a6.zip and /dev/null differ diff --git a/.yarn/cache/@rtsao-scc-npm-1.1.0-f4ba9ceb2c-17d04adf40.zip b/.yarn/cache/@rtsao-scc-npm-1.1.0-f4ba9ceb2c-17d04adf40.zip new file mode 100644 index 00000000000..2740c0f4244 Binary files /dev/null and b/.yarn/cache/@rtsao-scc-npm-1.1.0-f4ba9ceb2c-17d04adf40.zip differ diff --git a/.yarn/cache/@stylistic-eslint-plugin-npm-5.7.1-d417cddca9-df50c60e11.zip b/.yarn/cache/@stylistic-eslint-plugin-npm-5.7.1-d417cddca9-df50c60e11.zip new file mode 100644 index 00000000000..7544c96ca03 Binary files /dev/null and b/.yarn/cache/@stylistic-eslint-plugin-npm-5.7.1-d417cddca9-df50c60e11.zip differ diff --git a/.yarn/cache/@tybys-wasm-util-npm-0.10.1-607c8a7e5c-7fe0d23939.zip b/.yarn/cache/@tybys-wasm-util-npm-0.10.1-607c8a7e5c-7fe0d23939.zip new file mode 100644 index 00000000000..b2c724f5933 Binary files /dev/null and b/.yarn/cache/@tybys-wasm-util-npm-0.10.1-607c8a7e5c-7fe0d23939.zip differ diff --git a/.yarn/cache/@types-chai-npm-4.3.20-468371f41f-94fd87036f.zip b/.yarn/cache/@types-chai-npm-4.3.20-468371f41f-94fd87036f.zip new file mode 100644 index 00000000000..b3e2ab23a08 Binary files /dev/null and b/.yarn/cache/@types-chai-npm-4.3.20-468371f41f-94fd87036f.zip differ diff --git a/.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-25a4c16a67.zip b/.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-25a4c16a67.zip new file mode 100644 index 00000000000..7039d832f08 Binary files /dev/null and b/.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-25a4c16a67.zip differ diff --git a/.yarn/cache/@types-mocha-npm-10.0.10-1e025e7c6e-4e3b61ed51.zip b/.yarn/cache/@types-mocha-npm-10.0.10-1e025e7c6e-4e3b61ed51.zip new file mode 100644 index 00000000000..f725f2d31b9 Binary files /dev/null and b/.yarn/cache/@types-mocha-npm-10.0.10-1e025e7c6e-4e3b61ed51.zip differ diff --git a/.yarn/cache/@types-mocha-npm-8.2.3-7aff51fdb4-c768b67d8f.zip b/.yarn/cache/@types-mocha-npm-8.2.3-7aff51fdb4-c768b67d8f.zip deleted file mode 100644 index 5dfeb79abb1..00000000000 Binary files a/.yarn/cache/@types-mocha-npm-8.2.3-7aff51fdb4-c768b67d8f.zip and /dev/null differ diff --git a/.yarn/cache/@types-node-npm-14.17.34-1d7f20f643-a7e23fc63c.zip b/.yarn/cache/@types-node-npm-14.17.34-1d7f20f643-a7e23fc63c.zip deleted file mode 100644 index bc723f31bc9..00000000000 Binary files a/.yarn/cache/@types-node-npm-14.17.34-1d7f20f643-a7e23fc63c.zip and /dev/null differ diff --git a/.yarn/cache/@types-node-npm-20.19.30-e3d3d7af6e-4a25e5cbcd.zip b/.yarn/cache/@types-node-npm-20.19.30-e3d3d7af6e-4a25e5cbcd.zip new file mode 100644 index 00000000000..a2ad60a210a Binary files /dev/null and b/.yarn/cache/@types-node-npm-20.19.30-e3d3d7af6e-4a25e5cbcd.zip differ diff --git a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.55.0-16386bf9af-05f921647a.zip b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.55.0-16386bf9af-05f921647a.zip deleted file mode 100644 index 0843a31a8b7..00000000000 Binary files a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-5.55.0-16386bf9af-05f921647a.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.54.0-e6f6e349b5-8f1c74ac77.zip b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.54.0-e6f6e349b5-8f1c74ac77.zip new file mode 100644 index 00000000000..06762085a02 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.54.0-e6f6e349b5-8f1c74ac77.zip differ diff --git a/.yarn/cache/@typescript-eslint-parser-npm-5.55.0-ee38253ad6-a7c48c1d39.zip b/.yarn/cache/@typescript-eslint-parser-npm-5.55.0-ee38253ad6-a7c48c1d39.zip deleted file mode 100644 index 51ec0c06a44..00000000000 Binary files a/.yarn/cache/@typescript-eslint-parser-npm-5.55.0-ee38253ad6-a7c48c1d39.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-parser-npm-8.54.0-9b917cc1cb-d2e09462c9.zip b/.yarn/cache/@typescript-eslint-parser-npm-8.54.0-9b917cc1cb-d2e09462c9.zip new file mode 100644 index 00000000000..7660c0c3978 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-parser-npm-8.54.0-9b917cc1cb-d2e09462c9.zip differ diff --git a/.yarn/cache/@typescript-eslint-project-service-npm-8.54.0-df3e89508b-93f0483f6b.zip b/.yarn/cache/@typescript-eslint-project-service-npm-8.54.0-df3e89508b-93f0483f6b.zip new file mode 100644 index 00000000000..a8c7fbbe013 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-project-service-npm-8.54.0-df3e89508b-93f0483f6b.zip differ diff --git a/.yarn/cache/@typescript-eslint-scope-manager-npm-5.55.0-d7744f8a94-a089b0f45b.zip b/.yarn/cache/@typescript-eslint-scope-manager-npm-5.55.0-d7744f8a94-a089b0f45b.zip deleted file mode 100644 index 9b428d8446e..00000000000 Binary files a/.yarn/cache/@typescript-eslint-scope-manager-npm-5.55.0-d7744f8a94-a089b0f45b.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-scope-manager-npm-8.54.0-4f2ea67471-3474f3197e.zip b/.yarn/cache/@typescript-eslint-scope-manager-npm-8.54.0-4f2ea67471-3474f3197e.zip new file mode 100644 index 00000000000..66bd590f2c9 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-scope-manager-npm-8.54.0-4f2ea67471-3474f3197e.zip differ diff --git a/.yarn/cache/@typescript-eslint-tsconfig-utils-npm-8.54.0-73efc09e2a-e9d6b29538.zip b/.yarn/cache/@typescript-eslint-tsconfig-utils-npm-8.54.0-73efc09e2a-e9d6b29538.zip new file mode 100644 index 00000000000..d1a5281af6d Binary files /dev/null and b/.yarn/cache/@typescript-eslint-tsconfig-utils-npm-8.54.0-73efc09e2a-e9d6b29538.zip differ diff --git a/.yarn/cache/@typescript-eslint-type-utils-npm-5.55.0-333e5c4b16-267a2144fa.zip b/.yarn/cache/@typescript-eslint-type-utils-npm-5.55.0-333e5c4b16-267a2144fa.zip deleted file mode 100644 index e55614a4930..00000000000 Binary files a/.yarn/cache/@typescript-eslint-type-utils-npm-5.55.0-333e5c4b16-267a2144fa.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-type-utils-npm-8.54.0-a5168062ab-60e92fb322.zip b/.yarn/cache/@typescript-eslint-type-utils-npm-8.54.0-a5168062ab-60e92fb322.zip new file mode 100644 index 00000000000..a9c53516af2 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-type-utils-npm-8.54.0-a5168062ab-60e92fb322.zip differ diff --git a/.yarn/cache/@typescript-eslint-types-npm-5.55.0-694e3d296a-5ff3b2880e.zip b/.yarn/cache/@typescript-eslint-types-npm-5.55.0-694e3d296a-5ff3b2880e.zip deleted file mode 100644 index 177c8858608..00000000000 Binary files a/.yarn/cache/@typescript-eslint-types-npm-5.55.0-694e3d296a-5ff3b2880e.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-types-npm-8.53.1-b5f0956f64-9a01aa3433.zip b/.yarn/cache/@typescript-eslint-types-npm-8.53.1-b5f0956f64-9a01aa3433.zip new file mode 100644 index 00000000000..1bef5eb68d2 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-types-npm-8.53.1-b5f0956f64-9a01aa3433.zip differ diff --git a/.yarn/cache/@typescript-eslint-types-npm-8.54.0-75d29a589d-c25cc0bdf9.zip b/.yarn/cache/@typescript-eslint-types-npm-8.54.0-75d29a589d-c25cc0bdf9.zip new file mode 100644 index 00000000000..75ce1f83822 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-types-npm-8.54.0-75d29a589d-c25cc0bdf9.zip differ diff --git a/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.55.0-aefc08af17-e6c51080c0.zip b/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.55.0-aefc08af17-e6c51080c0.zip deleted file mode 100644 index b97510da18e..00000000000 Binary files a/.yarn/cache/@typescript-eslint-typescript-estree-npm-5.55.0-aefc08af17-e6c51080c0.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.54.0-643fee1e58-3a545037c6.zip b/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.54.0-643fee1e58-3a545037c6.zip new file mode 100644 index 00000000000..438553c0fd9 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.54.0-643fee1e58-3a545037c6.zip differ diff --git a/.yarn/cache/@typescript-eslint-utils-npm-5.55.0-6a927fceb5-121c5fc48c.zip b/.yarn/cache/@typescript-eslint-utils-npm-5.55.0-6a927fceb5-121c5fc48c.zip deleted file mode 100644 index 9c1edcc9cbf..00000000000 Binary files a/.yarn/cache/@typescript-eslint-utils-npm-5.55.0-6a927fceb5-121c5fc48c.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-utils-npm-8.54.0-c71ca4c1ce-9f88a2a7ab.zip b/.yarn/cache/@typescript-eslint-utils-npm-8.54.0-c71ca4c1ce-9f88a2a7ab.zip new file mode 100644 index 00000000000..6a6e7f78f15 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-utils-npm-8.54.0-c71ca4c1ce-9f88a2a7ab.zip differ diff --git a/.yarn/cache/@typescript-eslint-visitor-keys-npm-5.55.0-7f3c07beeb-5b6a0e4813.zip b/.yarn/cache/@typescript-eslint-visitor-keys-npm-5.55.0-7f3c07beeb-5b6a0e4813.zip deleted file mode 100644 index bf9a12eb7ac..00000000000 Binary files a/.yarn/cache/@typescript-eslint-visitor-keys-npm-5.55.0-7f3c07beeb-5b6a0e4813.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.54.0-b1e3d0cbc5-cca5380ee3.zip b/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.54.0-b1e3d0cbc5-cca5380ee3.zip new file mode 100644 index 00000000000..22f0c93c94f Binary files /dev/null and b/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.54.0-b1e3d0cbc5-cca5380ee3.zip differ diff --git a/.yarn/cache/@ungap-structured-clone-npm-1.2.0-648f0b82e0-c6fe89a505.zip b/.yarn/cache/@ungap-structured-clone-npm-1.2.0-648f0b82e0-c6fe89a505.zip deleted file mode 100644 index dce273dd015..00000000000 Binary files a/.yarn/cache/@ungap-structured-clone-npm-1.2.0-648f0b82e0-c6fe89a505.zip and /dev/null differ diff --git a/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.1-c78d4bd2cb-10.zip b/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.1-c78d4bd2cb-10.zip new file mode 100644 index 00000000000..c25b83d2ad6 Binary files /dev/null and b/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.1-c78d4bd2cb-10.zip differ diff --git a/.yarn/cache/acorn-npm-8.15.0-0764cf600e-77f2de5051.zip b/.yarn/cache/acorn-npm-8.15.0-0764cf600e-77f2de5051.zip new file mode 100644 index 00000000000..2eb7997f384 Binary files /dev/null and b/.yarn/cache/acorn-npm-8.15.0-0764cf600e-77f2de5051.zip differ diff --git a/.yarn/cache/aria-query-npm-5.3.2-78632ac5c5-b2fe9bc98b.zip b/.yarn/cache/aria-query-npm-5.3.2-78632ac5c5-b2fe9bc98b.zip new file mode 100644 index 00000000000..4cf38651330 Binary files /dev/null and b/.yarn/cache/aria-query-npm-5.3.2-78632ac5c5-b2fe9bc98b.zip differ diff --git a/.yarn/cache/array-buffer-byte-length-npm-1.0.2-c2be1e97e0-0ae3786195.zip b/.yarn/cache/array-buffer-byte-length-npm-1.0.2-c2be1e97e0-0ae3786195.zip new file mode 100644 index 00000000000..59b7d2ea5e6 Binary files /dev/null and b/.yarn/cache/array-buffer-byte-length-npm-1.0.2-c2be1e97e0-0ae3786195.zip differ diff --git a/.yarn/cache/array-includes-npm-3.1.7-d32a5ee179-856a8be5d1.zip b/.yarn/cache/array-includes-npm-3.1.7-d32a5ee179-856a8be5d1.zip deleted file mode 100644 index c1b8f8a07f9..00000000000 Binary files a/.yarn/cache/array-includes-npm-3.1.7-d32a5ee179-856a8be5d1.zip and /dev/null differ diff --git a/.yarn/cache/array-includes-npm-3.1.9-b081638946-8bfe9a58df.zip b/.yarn/cache/array-includes-npm-3.1.9-b081638946-8bfe9a58df.zip new file mode 100644 index 00000000000..a26b58d2a7a Binary files /dev/null and b/.yarn/cache/array-includes-npm-3.1.9-b081638946-8bfe9a58df.zip differ diff --git a/.yarn/cache/array.prototype.findlast-npm-1.2.5-316cb71d39-7dffcc665a.zip b/.yarn/cache/array.prototype.findlast-npm-1.2.5-316cb71d39-7dffcc665a.zip new file mode 100644 index 00000000000..9a7f9692a43 Binary files /dev/null and b/.yarn/cache/array.prototype.findlast-npm-1.2.5-316cb71d39-7dffcc665a.zip differ diff --git a/.yarn/cache/array.prototype.findlastindex-npm-1.2.3-2a36f4417b-063cbab8ee.zip b/.yarn/cache/array.prototype.findlastindex-npm-1.2.3-2a36f4417b-063cbab8ee.zip deleted file mode 100644 index 9e3b8d7325d..00000000000 Binary files a/.yarn/cache/array.prototype.findlastindex-npm-1.2.3-2a36f4417b-063cbab8ee.zip and /dev/null differ diff --git a/.yarn/cache/array.prototype.findlastindex-npm-1.2.6-65fef3f969-5ddb6420e8.zip b/.yarn/cache/array.prototype.findlastindex-npm-1.2.6-65fef3f969-5ddb6420e8.zip new file mode 100644 index 00000000000..174afd9debe Binary files /dev/null and b/.yarn/cache/array.prototype.findlastindex-npm-1.2.6-65fef3f969-5ddb6420e8.zip differ diff --git a/.yarn/cache/array.prototype.flat-npm-1.3.2-350729f7f4-d9d2f6f275.zip b/.yarn/cache/array.prototype.flat-npm-1.3.3-51377719d9-f9b992fa07.zip similarity index 59% rename from .yarn/cache/array.prototype.flat-npm-1.3.2-350729f7f4-d9d2f6f275.zip rename to .yarn/cache/array.prototype.flat-npm-1.3.3-51377719d9-f9b992fa07.zip index 08000966f71..2694ee58c4a 100644 Binary files a/.yarn/cache/array.prototype.flat-npm-1.3.2-350729f7f4-d9d2f6f275.zip and b/.yarn/cache/array.prototype.flat-npm-1.3.3-51377719d9-f9b992fa07.zip differ diff --git a/.yarn/cache/array.prototype.flatmap-npm-1.3.3-db3afdbfda-473534573a.zip b/.yarn/cache/array.prototype.flatmap-npm-1.3.3-db3afdbfda-473534573a.zip new file mode 100644 index 00000000000..bd38e2bcb7b Binary files /dev/null and b/.yarn/cache/array.prototype.flatmap-npm-1.3.3-db3afdbfda-473534573a.zip differ diff --git a/.yarn/cache/array.prototype.tosorted-npm-1.1.4-c1fc919434-874694e5d5.zip b/.yarn/cache/array.prototype.tosorted-npm-1.1.4-c1fc919434-874694e5d5.zip new file mode 100644 index 00000000000..2965bf97448 Binary files /dev/null and b/.yarn/cache/array.prototype.tosorted-npm-1.1.4-c1fc919434-874694e5d5.zip differ diff --git a/.yarn/cache/arraybuffer.prototype.slice-npm-1.0.4-01f62a9713-4821ebdfe7.zip b/.yarn/cache/arraybuffer.prototype.slice-npm-1.0.4-01f62a9713-4821ebdfe7.zip new file mode 100644 index 00000000000..0c5d1e98610 Binary files /dev/null and b/.yarn/cache/arraybuffer.prototype.slice-npm-1.0.4-01f62a9713-4821ebdfe7.zip differ diff --git a/.yarn/cache/ast-types-flow-npm-0.0.8-d5c457c18e-85a1c24af4.zip b/.yarn/cache/ast-types-flow-npm-0.0.8-d5c457c18e-85a1c24af4.zip new file mode 100644 index 00000000000..706300b1b6d Binary files /dev/null and b/.yarn/cache/ast-types-flow-npm-0.0.8-d5c457c18e-85a1c24af4.zip differ diff --git a/.yarn/cache/axe-core-npm-4.11.1-87a6aa2514-bbc8e89592.zip b/.yarn/cache/axe-core-npm-4.11.1-87a6aa2514-bbc8e89592.zip new file mode 100644 index 00000000000..3435e3c3aa8 Binary files /dev/null and b/.yarn/cache/axe-core-npm-4.11.1-87a6aa2514-bbc8e89592.zip differ diff --git a/.yarn/cache/axobject-query-npm-4.1.0-9703554323-e275dea9b6.zip b/.yarn/cache/axobject-query-npm-4.1.0-9703554323-e275dea9b6.zip new file mode 100644 index 00000000000..333049a40f8 Binary files /dev/null and b/.yarn/cache/axobject-query-npm-4.1.0-9703554323-e275dea9b6.zip differ diff --git a/.yarn/cache/babel-eslint-npm-10.1.0-6a6d2b1533-dc5dd948f8.zip b/.yarn/cache/babel-eslint-npm-10.1.0-6a6d2b1533-dc5dd948f8.zip deleted file mode 100644 index 01961c7d222..00000000000 Binary files a/.yarn/cache/babel-eslint-npm-10.1.0-6a6d2b1533-dc5dd948f8.zip and /dev/null differ diff --git a/.yarn/cache/builtin-modules-npm-3.3.0-db4f3d32de-62e063ab40.zip b/.yarn/cache/builtin-modules-npm-3.3.0-db4f3d32de-62e063ab40.zip deleted file mode 100644 index 103f85deda7..00000000000 Binary files a/.yarn/cache/builtin-modules-npm-3.3.0-db4f3d32de-62e063ab40.zip and /dev/null differ diff --git a/.yarn/cache/comment-parser-npm-1.4.5-f67638c027-4b5cacc7ab.zip b/.yarn/cache/comment-parser-npm-1.4.5-f67638c027-4b5cacc7ab.zip new file mode 100644 index 00000000000..8a6710217d1 Binary files /dev/null and b/.yarn/cache/comment-parser-npm-1.4.5-f67638c027-4b5cacc7ab.zip differ diff --git a/.yarn/cache/confusing-browser-globals-npm-1.0.10-ecb768852b-7ccdc44c2c.zip b/.yarn/cache/confusing-browser-globals-npm-1.0.11-b3ff8e9483-3afc635abd.zip similarity index 50% rename from .yarn/cache/confusing-browser-globals-npm-1.0.10-ecb768852b-7ccdc44c2c.zip rename to .yarn/cache/confusing-browser-globals-npm-1.0.11-b3ff8e9483-3afc635abd.zip index c453b25b9bf..19db1b915ae 100644 Binary files a/.yarn/cache/confusing-browser-globals-npm-1.0.10-ecb768852b-7ccdc44c2c.zip and b/.yarn/cache/confusing-browser-globals-npm-1.0.11-b3ff8e9483-3afc635abd.zip differ diff --git a/.yarn/cache/damerau-levenshtein-npm-1.0.8-bda7311c69-f4eba1c901.zip b/.yarn/cache/damerau-levenshtein-npm-1.0.8-bda7311c69-f4eba1c901.zip new file mode 100644 index 00000000000..904cfa668a6 Binary files /dev/null and b/.yarn/cache/damerau-levenshtein-npm-1.0.8-bda7311c69-f4eba1c901.zip differ diff --git a/.yarn/cache/data-view-buffer-npm-1.0.2-93c9247e37-c10b155a4e.zip b/.yarn/cache/data-view-buffer-npm-1.0.2-93c9247e37-c10b155a4e.zip new file mode 100644 index 00000000000..7f92c2bc567 Binary files /dev/null and b/.yarn/cache/data-view-buffer-npm-1.0.2-93c9247e37-c10b155a4e.zip differ diff --git a/.yarn/cache/data-view-byte-length-npm-1.0.2-96d312fb9c-2a47055fcf.zip b/.yarn/cache/data-view-byte-length-npm-1.0.2-96d312fb9c-2a47055fcf.zip new file mode 100644 index 00000000000..3ec67eedc2d Binary files /dev/null and b/.yarn/cache/data-view-byte-length-npm-1.0.2-96d312fb9c-2a47055fcf.zip differ diff --git a/.yarn/cache/data-view-byte-offset-npm-1.0.1-315a12a556-fa3bdfa096.zip b/.yarn/cache/data-view-byte-offset-npm-1.0.1-315a12a556-fa3bdfa096.zip new file mode 100644 index 00000000000..cac83395310 Binary files /dev/null and b/.yarn/cache/data-view-byte-offset-npm-1.0.1-315a12a556-fa3bdfa096.zip differ diff --git a/.yarn/cache/debug-npm-4.4.3-0105c6123a-9ada3434ea.zip b/.yarn/cache/debug-npm-4.4.3-0105c6123a-9ada3434ea.zip new file mode 100644 index 00000000000..b8f325d4729 Binary files /dev/null and b/.yarn/cache/debug-npm-4.4.3-0105c6123a-9ada3434ea.zip differ diff --git a/.yarn/cache/es-abstract-npm-1.24.1-4503972a58-c84cb69eba.zip b/.yarn/cache/es-abstract-npm-1.24.1-4503972a58-c84cb69eba.zip new file mode 100644 index 00000000000..2f51c3a1424 Binary files /dev/null and b/.yarn/cache/es-abstract-npm-1.24.1-4503972a58-c84cb69eba.zip differ diff --git a/.yarn/cache/es-iterator-helpers-npm-1.2.2-470224dac7-17b5b2834c.zip b/.yarn/cache/es-iterator-helpers-npm-1.2.2-470224dac7-17b5b2834c.zip new file mode 100644 index 00000000000..eeed1938ffa Binary files /dev/null and b/.yarn/cache/es-iterator-helpers-npm-1.2.2-470224dac7-17b5b2834c.zip differ diff --git a/.yarn/cache/es-set-tostringtag-npm-2.1.0-4e55705d3f-86814bf8af.zip b/.yarn/cache/es-set-tostringtag-npm-2.1.0-4e55705d3f-86814bf8af.zip new file mode 100644 index 00000000000..a22f6f363c1 Binary files /dev/null and b/.yarn/cache/es-set-tostringtag-npm-2.1.0-4e55705d3f-86814bf8af.zip differ diff --git a/.yarn/cache/es-shim-unscopables-npm-1.1.0-13f1970345-c351f586c3.zip b/.yarn/cache/es-shim-unscopables-npm-1.1.0-13f1970345-c351f586c3.zip new file mode 100644 index 00000000000..80f0ff56bbd Binary files /dev/null and b/.yarn/cache/es-shim-unscopables-npm-1.1.0-13f1970345-c351f586c3.zip differ diff --git a/.yarn/cache/es-to-primitive-npm-1.3.0-470b6d51b6-17faf35c22.zip b/.yarn/cache/es-to-primitive-npm-1.3.0-470b6d51b6-17faf35c22.zip new file mode 100644 index 00000000000..4ca11ee28de Binary files /dev/null and b/.yarn/cache/es-to-primitive-npm-1.3.0-470b6d51b6-17faf35c22.zip differ diff --git a/.yarn/cache/eslint-compat-utils-npm-0.5.1-f1f8ade49a-ac65ac1c61.zip b/.yarn/cache/eslint-compat-utils-npm-0.5.1-f1f8ade49a-ac65ac1c61.zip new file mode 100644 index 00000000000..5fb652c747b Binary files /dev/null and b/.yarn/cache/eslint-compat-utils-npm-0.5.1-f1f8ade49a-ac65ac1c61.zip differ diff --git a/.yarn/cache/eslint-config-airbnb-base-npm-15.0.0-802837dd26-daa68a1dcb.zip b/.yarn/cache/eslint-config-airbnb-base-npm-15.0.0-802837dd26-daa68a1dcb.zip deleted file mode 100644 index 18cd421b379..00000000000 Binary files a/.yarn/cache/eslint-config-airbnb-base-npm-15.0.0-802837dd26-daa68a1dcb.zip and /dev/null differ diff --git a/.yarn/cache/eslint-config-airbnb-extended-npm-3.0.1-e232343c3c-24e89d991e.zip b/.yarn/cache/eslint-config-airbnb-extended-npm-3.0.1-e232343c3c-24e89d991e.zip new file mode 100644 index 00000000000..7c8803ee3e8 Binary files /dev/null and b/.yarn/cache/eslint-config-airbnb-extended-npm-3.0.1-e232343c3c-24e89d991e.zip differ diff --git a/.yarn/cache/eslint-config-airbnb-typescript-npm-17.0.0-e1f8a377d2-43158416b1.zip b/.yarn/cache/eslint-config-airbnb-typescript-npm-17.0.0-e1f8a377d2-43158416b1.zip deleted file mode 100644 index fc941e13996..00000000000 Binary files a/.yarn/cache/eslint-config-airbnb-typescript-npm-17.0.0-e1f8a377d2-43158416b1.zip and /dev/null differ diff --git a/.yarn/cache/eslint-import-context-npm-0.1.9-5e2eb7c9a9-f0778126bb.zip b/.yarn/cache/eslint-import-context-npm-0.1.9-5e2eb7c9a9-f0778126bb.zip new file mode 100644 index 00000000000..52d08afa4f2 Binary files /dev/null and b/.yarn/cache/eslint-import-context-npm-0.1.9-5e2eb7c9a9-f0778126bb.zip differ diff --git a/.yarn/cache/eslint-import-resolver-typescript-npm-4.4.4-e7b670a36b-4f871f6d1a.zip b/.yarn/cache/eslint-import-resolver-typescript-npm-4.4.4-e7b670a36b-4f871f6d1a.zip new file mode 100644 index 00000000000..4b11b7cb0aa Binary files /dev/null and b/.yarn/cache/eslint-import-resolver-typescript-npm-4.4.4-e7b670a36b-4f871f6d1a.zip differ diff --git a/.yarn/cache/eslint-module-utils-npm-2.12.1-11995f0970-bd25d6610e.zip b/.yarn/cache/eslint-module-utils-npm-2.12.1-11995f0970-bd25d6610e.zip new file mode 100644 index 00000000000..cda6873a9a1 Binary files /dev/null and b/.yarn/cache/eslint-module-utils-npm-2.12.1-11995f0970-bd25d6610e.zip differ diff --git a/.yarn/cache/eslint-module-utils-npm-2.8.0-05e42bcab0-a9a7ed93eb.zip b/.yarn/cache/eslint-module-utils-npm-2.8.0-05e42bcab0-a9a7ed93eb.zip deleted file mode 100644 index 7a1bda555af..00000000000 Binary files a/.yarn/cache/eslint-module-utils-npm-2.8.0-05e42bcab0-a9a7ed93eb.zip and /dev/null differ diff --git a/.yarn/cache/eslint-npm-8.53.0-2fc5c501d2-e305a71ce2.zip b/.yarn/cache/eslint-npm-8.53.0-2fc5c501d2-e305a71ce2.zip deleted file mode 100644 index ed4f4dd20f1..00000000000 Binary files a/.yarn/cache/eslint-npm-8.53.0-2fc5c501d2-e305a71ce2.zip and /dev/null differ diff --git a/.yarn/cache/eslint-npm-9.39.2-af6e824e47-53ff0e9c82.zip b/.yarn/cache/eslint-npm-9.39.2-af6e824e47-53ff0e9c82.zip new file mode 100644 index 00000000000..0dbc38d1cec Binary files /dev/null and b/.yarn/cache/eslint-npm-9.39.2-af6e824e47-53ff0e9c82.zip differ diff --git a/.yarn/cache/eslint-plugin-es-x-npm-7.8.0-8237bd972e-1df8d52c4f.zip b/.yarn/cache/eslint-plugin-es-x-npm-7.8.0-8237bd972e-1df8d52c4f.zip new file mode 100644 index 00000000000..248740b3723 Binary files /dev/null and b/.yarn/cache/eslint-plugin-es-x-npm-7.8.0-8237bd972e-1df8d52c4f.zip differ diff --git a/.yarn/cache/eslint-plugin-import-npm-2.29.0-9cd6da0b0a-d6e8d016f3.zip b/.yarn/cache/eslint-plugin-import-npm-2.29.0-9cd6da0b0a-d6e8d016f3.zip deleted file mode 100644 index 62dcfb94eea..00000000000 Binary files a/.yarn/cache/eslint-plugin-import-npm-2.29.0-9cd6da0b0a-d6e8d016f3.zip and /dev/null differ diff --git a/.yarn/cache/eslint-plugin-import-npm-2.32.0-a1643bce9b-1bacf4967e.zip b/.yarn/cache/eslint-plugin-import-npm-2.32.0-a1643bce9b-1bacf4967e.zip new file mode 100644 index 00000000000..0b85b6deb54 Binary files /dev/null and b/.yarn/cache/eslint-plugin-import-npm-2.32.0-a1643bce9b-1bacf4967e.zip differ diff --git a/.yarn/cache/eslint-plugin-import-x-npm-4.16.1-b1dd938e9f-d1390d4949.zip b/.yarn/cache/eslint-plugin-import-x-npm-4.16.1-b1dd938e9f-d1390d4949.zip new file mode 100644 index 00000000000..b32136b65b0 Binary files /dev/null and b/.yarn/cache/eslint-plugin-import-x-npm-4.16.1-b1dd938e9f-d1390d4949.zip differ diff --git a/.yarn/cache/eslint-plugin-jsdoc-npm-46.9.0-43e0861b76-0dd2068804.zip b/.yarn/cache/eslint-plugin-jsdoc-npm-46.9.0-43e0861b76-0dd2068804.zip deleted file mode 100644 index e3a00fef323..00000000000 Binary files a/.yarn/cache/eslint-plugin-jsdoc-npm-46.9.0-43e0861b76-0dd2068804.zip and /dev/null differ diff --git a/.yarn/cache/eslint-plugin-jsdoc-npm-50.8.0-4cbbdea7df-8857bb6583.zip b/.yarn/cache/eslint-plugin-jsdoc-npm-50.8.0-4cbbdea7df-8857bb6583.zip new file mode 100644 index 00000000000..178982cfffd Binary files /dev/null and b/.yarn/cache/eslint-plugin-jsdoc-npm-50.8.0-4cbbdea7df-8857bb6583.zip differ diff --git a/.yarn/cache/eslint-plugin-jsx-a11y-npm-6.10.2-23afcd8d2e-3885507985.zip b/.yarn/cache/eslint-plugin-jsx-a11y-npm-6.10.2-23afcd8d2e-3885507985.zip new file mode 100644 index 00000000000..520fe1290cf Binary files /dev/null and b/.yarn/cache/eslint-plugin-jsx-a11y-npm-6.10.2-23afcd8d2e-3885507985.zip differ diff --git a/.yarn/cache/eslint-plugin-n-npm-17.23.2-2a838a76f9-67a15908b2.zip b/.yarn/cache/eslint-plugin-n-npm-17.23.2-2a838a76f9-67a15908b2.zip new file mode 100644 index 00000000000..2c697dbc240 Binary files /dev/null and b/.yarn/cache/eslint-plugin-n-npm-17.23.2-2a838a76f9-67a15908b2.zip differ diff --git a/.yarn/cache/eslint-plugin-react-hooks-npm-7.0.1-218b8cae26-12e96c68d5.zip b/.yarn/cache/eslint-plugin-react-hooks-npm-7.0.1-218b8cae26-12e96c68d5.zip new file mode 100644 index 00000000000..e83bde57017 Binary files /dev/null and b/.yarn/cache/eslint-plugin-react-hooks-npm-7.0.1-218b8cae26-12e96c68d5.zip differ diff --git a/.yarn/cache/eslint-plugin-react-npm-7.37.5-d03f6b6543-ee1bd4e0ec.zip b/.yarn/cache/eslint-plugin-react-npm-7.37.5-d03f6b6543-ee1bd4e0ec.zip new file mode 100644 index 00000000000..f50b860714d Binary files /dev/null and b/.yarn/cache/eslint-plugin-react-npm-7.37.5-d03f6b6543-ee1bd4e0ec.zip differ diff --git a/.yarn/cache/eslint-scope-npm-7.2.2-53cb0df8e8-5c660fb905.zip b/.yarn/cache/eslint-scope-npm-7.2.2-53cb0df8e8-5c660fb905.zip deleted file mode 100644 index 628d419ed06..00000000000 Binary files a/.yarn/cache/eslint-scope-npm-7.2.2-53cb0df8e8-5c660fb905.zip and /dev/null differ diff --git a/.yarn/cache/eslint-scope-npm-8.4.0-8ed12feb40-e8e611701f.zip b/.yarn/cache/eslint-scope-npm-8.4.0-8ed12feb40-e8e611701f.zip new file mode 100644 index 00000000000..b34748e930d Binary files /dev/null and b/.yarn/cache/eslint-scope-npm-8.4.0-8ed12feb40-e8e611701f.zip differ diff --git a/.yarn/cache/eslint-visitor-keys-npm-1.3.0-c07780a0fb-595ab230e0.zip b/.yarn/cache/eslint-visitor-keys-npm-1.3.0-c07780a0fb-595ab230e0.zip deleted file mode 100644 index 49b7726148d..00000000000 Binary files a/.yarn/cache/eslint-visitor-keys-npm-1.3.0-c07780a0fb-595ab230e0.zip and /dev/null differ diff --git a/.yarn/cache/eslint-visitor-keys-npm-2.1.0-c31806b6b9-db4547eef5.zip b/.yarn/cache/eslint-visitor-keys-npm-2.1.0-c31806b6b9-db4547eef5.zip deleted file mode 100644 index 86352d4c2b8..00000000000 Binary files a/.yarn/cache/eslint-visitor-keys-npm-2.1.0-c31806b6b9-db4547eef5.zip and /dev/null differ diff --git a/.yarn/cache/eslint-visitor-keys-npm-4.2.1-435d5be22a-3ee00fc6a7.zip b/.yarn/cache/eslint-visitor-keys-npm-4.2.1-435d5be22a-3ee00fc6a7.zip new file mode 100644 index 00000000000..bea4ce38dd9 Binary files /dev/null and b/.yarn/cache/eslint-visitor-keys-npm-4.2.1-435d5be22a-3ee00fc6a7.zip differ diff --git a/.yarn/cache/espree-npm-10.4.0-9633b00e55-9b355b32db.zip b/.yarn/cache/espree-npm-10.4.0-9633b00e55-9b355b32db.zip new file mode 100644 index 00000000000..7f75a146288 Binary files /dev/null and b/.yarn/cache/espree-npm-10.4.0-9633b00e55-9b355b32db.zip differ diff --git a/.yarn/cache/esquery-npm-1.7.0-c1e8da438a-4afaf30893.zip b/.yarn/cache/esquery-npm-1.7.0-c1e8da438a-4afaf30893.zip new file mode 100644 index 00000000000..077b6932411 Binary files /dev/null and b/.yarn/cache/esquery-npm-1.7.0-c1e8da438a-4afaf30893.zip differ diff --git a/.yarn/cache/fast-glob-npm-3.3.1-8045ff8f4d-51bcd15472.zip b/.yarn/cache/fast-glob-npm-3.3.1-8045ff8f4d-51bcd15472.zip new file mode 100644 index 00000000000..c4c8d7729fc Binary files /dev/null and b/.yarn/cache/fast-glob-npm-3.3.1-8045ff8f4d-51bcd15472.zip differ diff --git a/.yarn/cache/fdir-npm-6.5.0-8814a0dec7-14ca1c9f0a.zip b/.yarn/cache/fdir-npm-6.5.0-8814a0dec7-14ca1c9f0a.zip new file mode 100644 index 00000000000..09feebec3a2 Binary files /dev/null and b/.yarn/cache/fdir-npm-6.5.0-8814a0dec7-14ca1c9f0a.zip differ diff --git a/.yarn/cache/file-entry-cache-npm-6.0.1-31965cf0af-099bb9d4ab.zip b/.yarn/cache/file-entry-cache-npm-6.0.1-31965cf0af-099bb9d4ab.zip deleted file mode 100644 index 5169985ebed..00000000000 Binary files a/.yarn/cache/file-entry-cache-npm-6.0.1-31965cf0af-099bb9d4ab.zip and /dev/null differ diff --git a/.yarn/cache/file-entry-cache-npm-8.0.0-5b09d19a83-afe55c4de4.zip b/.yarn/cache/file-entry-cache-npm-8.0.0-5b09d19a83-afe55c4de4.zip new file mode 100644 index 00000000000..58498b44eaf Binary files /dev/null and b/.yarn/cache/file-entry-cache-npm-8.0.0-5b09d19a83-afe55c4de4.zip differ diff --git a/.yarn/cache/flat-cache-npm-3.0.4-ee77e5911e-9fe5d0cb97.zip b/.yarn/cache/flat-cache-npm-3.0.4-ee77e5911e-9fe5d0cb97.zip deleted file mode 100644 index 8fad0082303..00000000000 Binary files a/.yarn/cache/flat-cache-npm-3.0.4-ee77e5911e-9fe5d0cb97.zip and /dev/null differ diff --git a/.yarn/cache/flat-cache-npm-4.0.1-12bf2455f7-58ce851d90.zip b/.yarn/cache/flat-cache-npm-4.0.1-12bf2455f7-58ce851d90.zip new file mode 100644 index 00000000000..dddd10dc200 Binary files /dev/null and b/.yarn/cache/flat-cache-npm-4.0.1-12bf2455f7-58ce851d90.zip differ diff --git a/.yarn/cache/flatted-npm-3.3.3-ca455563b2-8c96c02fbe.zip b/.yarn/cache/flatted-npm-3.3.3-ca455563b2-8c96c02fbe.zip new file mode 100644 index 00000000000..1c4a006ad9c Binary files /dev/null and b/.yarn/cache/flatted-npm-3.3.3-ca455563b2-8c96c02fbe.zip differ diff --git a/.yarn/cache/fsevents-patch-19706e7e35-10.zip b/.yarn/cache/fsevents-patch-19706e7e35-10.zip new file mode 100644 index 00000000000..aff1ab12ce5 Binary files /dev/null and b/.yarn/cache/fsevents-patch-19706e7e35-10.zip differ diff --git a/.yarn/cache/function.prototype.name-npm-1.1.8-2cf198aac8-25b9e5bea9.zip b/.yarn/cache/function.prototype.name-npm-1.1.8-2cf198aac8-25b9e5bea9.zip new file mode 100644 index 00000000000..ce1e805d5b6 Binary files /dev/null and b/.yarn/cache/function.prototype.name-npm-1.1.8-2cf198aac8-25b9e5bea9.zip differ diff --git a/.yarn/cache/get-symbol-description-npm-1.1.0-7a9e0b1c24-a353e3a959.zip b/.yarn/cache/get-symbol-description-npm-1.1.0-7a9e0b1c24-a353e3a959.zip new file mode 100644 index 00000000000..b4f5ef5be34 Binary files /dev/null and b/.yarn/cache/get-symbol-description-npm-1.1.0-7a9e0b1c24-a353e3a959.zip differ diff --git a/.yarn/cache/get-tsconfig-npm-4.13.0-009b232bdd-3603c6da30.zip b/.yarn/cache/get-tsconfig-npm-4.13.0-009b232bdd-3603c6da30.zip new file mode 100644 index 00000000000..521c2617f06 Binary files /dev/null and b/.yarn/cache/get-tsconfig-npm-4.13.0-009b232bdd-3603c6da30.zip differ diff --git a/.yarn/cache/globals-npm-13.23.0-7f02426fd5-bf6a8616f4.zip b/.yarn/cache/globals-npm-13.23.0-7f02426fd5-bf6a8616f4.zip deleted file mode 100644 index abd4e2c4ac7..00000000000 Binary files a/.yarn/cache/globals-npm-13.23.0-7f02426fd5-bf6a8616f4.zip and /dev/null differ diff --git a/.yarn/cache/globals-npm-14.0.0-5fc3d8d5da-03939c8af9.zip b/.yarn/cache/globals-npm-14.0.0-5fc3d8d5da-03939c8af9.zip new file mode 100644 index 00000000000..d912b49acee Binary files /dev/null and b/.yarn/cache/globals-npm-14.0.0-5fc3d8d5da-03939c8af9.zip differ diff --git a/.yarn/cache/globals-npm-15.15.0-5ddcb6c553-7f561c87b2.zip b/.yarn/cache/globals-npm-15.15.0-5ddcb6c553-7f561c87b2.zip new file mode 100644 index 00000000000..4b368e55a37 Binary files /dev/null and b/.yarn/cache/globals-npm-15.15.0-5ddcb6c553-7f561c87b2.zip differ diff --git a/.yarn/cache/globals-npm-17.1.0-baf660f37b-6e77442a3b.zip b/.yarn/cache/globals-npm-17.1.0-baf660f37b-6e77442a3b.zip new file mode 100644 index 00000000000..66cca1fdcb6 Binary files /dev/null and b/.yarn/cache/globals-npm-17.1.0-baf660f37b-6e77442a3b.zip differ diff --git a/.yarn/cache/globalthis-npm-1.0.4-de22ac6193-1f1fd078fb.zip b/.yarn/cache/globalthis-npm-1.0.4-de22ac6193-1f1fd078fb.zip new file mode 100644 index 00000000000..a1b0ba8fb91 Binary files /dev/null and b/.yarn/cache/globalthis-npm-1.0.4-de22ac6193-1f1fd078fb.zip differ diff --git a/.yarn/cache/graphemer-npm-1.4.0-0627732d35-6dd60dba97.zip b/.yarn/cache/graphemer-npm-1.4.0-0627732d35-6dd60dba97.zip deleted file mode 100644 index cbccd943980..00000000000 Binary files a/.yarn/cache/graphemer-npm-1.4.0-0627732d35-6dd60dba97.zip and /dev/null differ diff --git a/.yarn/cache/has-proto-npm-1.2.0-0108d177d3-7eaed07728.zip b/.yarn/cache/has-proto-npm-1.2.0-0108d177d3-7eaed07728.zip new file mode 100644 index 00000000000..c3160423ae7 Binary files /dev/null and b/.yarn/cache/has-proto-npm-1.2.0-0108d177d3-7eaed07728.zip differ diff --git a/.yarn/cache/hermes-estree-npm-0.25.1-d7752f3952-7b1eca98b2.zip b/.yarn/cache/hermes-estree-npm-0.25.1-d7752f3952-7b1eca98b2.zip new file mode 100644 index 00000000000..8d849204d9b Binary files /dev/null and b/.yarn/cache/hermes-estree-npm-0.25.1-d7752f3952-7b1eca98b2.zip differ diff --git a/.yarn/cache/hermes-parser-npm-0.25.1-832deac23b-805efc0569.zip b/.yarn/cache/hermes-parser-npm-0.25.1-832deac23b-805efc0569.zip new file mode 100644 index 00000000000..5aa23e6ff31 Binary files /dev/null and b/.yarn/cache/hermes-parser-npm-0.25.1-832deac23b-805efc0569.zip differ diff --git a/.yarn/cache/ignore-npm-5.3.2-346d3ba017-cceb6a4570.zip b/.yarn/cache/ignore-npm-5.3.2-346d3ba017-cceb6a4570.zip new file mode 100644 index 00000000000..e7580729a88 Binary files /dev/null and b/.yarn/cache/ignore-npm-5.3.2-346d3ba017-cceb6a4570.zip differ diff --git a/.yarn/cache/ignore-npm-7.0.5-dea34ee430-f134b96a4d.zip b/.yarn/cache/ignore-npm-7.0.5-dea34ee430-f134b96a4d.zip new file mode 100644 index 00000000000..bf990f3a24d Binary files /dev/null and b/.yarn/cache/ignore-npm-7.0.5-dea34ee430-f134b96a4d.zip differ diff --git a/.yarn/cache/internal-slot-npm-1.1.0-269ac0e8be-1d5219273a.zip b/.yarn/cache/internal-slot-npm-1.1.0-269ac0e8be-1d5219273a.zip new file mode 100644 index 00000000000..34a4c5a50af Binary files /dev/null and b/.yarn/cache/internal-slot-npm-1.1.0-269ac0e8be-1d5219273a.zip differ diff --git a/.yarn/cache/is-array-buffer-npm-3.0.5-8f0828e156-ef1095c55b.zip b/.yarn/cache/is-array-buffer-npm-3.0.5-8f0828e156-ef1095c55b.zip new file mode 100644 index 00000000000..47db98fda31 Binary files /dev/null and b/.yarn/cache/is-array-buffer-npm-3.0.5-8f0828e156-ef1095c55b.zip differ diff --git a/.yarn/cache/is-async-function-npm-2.1.1-547309fbf2-7c2ac7efdf.zip b/.yarn/cache/is-async-function-npm-2.1.1-547309fbf2-7c2ac7efdf.zip new file mode 100644 index 00000000000..64b4cdf96aa Binary files /dev/null and b/.yarn/cache/is-async-function-npm-2.1.1-547309fbf2-7c2ac7efdf.zip differ diff --git a/.yarn/cache/is-bigint-npm-1.1.0-963b4e89e1-10cf327310.zip b/.yarn/cache/is-bigint-npm-1.1.0-963b4e89e1-10cf327310.zip new file mode 100644 index 00000000000..b9018b35edd Binary files /dev/null and b/.yarn/cache/is-bigint-npm-1.1.0-963b4e89e1-10cf327310.zip differ diff --git a/.yarn/cache/is-boolean-object-npm-1.2.2-ceb8c82b17-051fa95fdb.zip b/.yarn/cache/is-boolean-object-npm-1.2.2-ceb8c82b17-051fa95fdb.zip new file mode 100644 index 00000000000..bceaaa3e223 Binary files /dev/null and b/.yarn/cache/is-boolean-object-npm-1.2.2-ceb8c82b17-051fa95fdb.zip differ diff --git a/.yarn/cache/is-builtin-module-npm-3.2.1-2f92a5d353-e8f0ffc19a.zip b/.yarn/cache/is-builtin-module-npm-3.2.1-2f92a5d353-e8f0ffc19a.zip deleted file mode 100644 index be908976b53..00000000000 Binary files a/.yarn/cache/is-builtin-module-npm-3.2.1-2f92a5d353-e8f0ffc19a.zip and /dev/null differ diff --git a/.yarn/cache/is-bun-module-npm-2.0.0-820a4713ec-cded5a1a58.zip b/.yarn/cache/is-bun-module-npm-2.0.0-820a4713ec-cded5a1a58.zip new file mode 100644 index 00000000000..c89f381309d Binary files /dev/null and b/.yarn/cache/is-bun-module-npm-2.0.0-820a4713ec-cded5a1a58.zip differ diff --git a/.yarn/cache/is-core-module-npm-2.16.1-a54837229e-452b2c2fb7.zip b/.yarn/cache/is-core-module-npm-2.16.1-a54837229e-452b2c2fb7.zip new file mode 100644 index 00000000000..2b29ae8d20b Binary files /dev/null and b/.yarn/cache/is-core-module-npm-2.16.1-a54837229e-452b2c2fb7.zip differ diff --git a/.yarn/cache/is-data-view-npm-1.0.2-8a9e34c5e6-357e9a48fa.zip b/.yarn/cache/is-data-view-npm-1.0.2-8a9e34c5e6-357e9a48fa.zip new file mode 100644 index 00000000000..4c5972d1eaf Binary files /dev/null and b/.yarn/cache/is-data-view-npm-1.0.2-8a9e34c5e6-357e9a48fa.zip differ diff --git a/.yarn/cache/is-date-object-npm-1.1.0-c444eba828-3a811b2c31.zip b/.yarn/cache/is-date-object-npm-1.1.0-c444eba828-3a811b2c31.zip new file mode 100644 index 00000000000..1f1e2bfc166 Binary files /dev/null and b/.yarn/cache/is-date-object-npm-1.1.0-c444eba828-3a811b2c31.zip differ diff --git a/.yarn/cache/is-finalizationregistry-npm-1.1.1-f9cad6c9aa-0bfb145e9a.zip b/.yarn/cache/is-finalizationregistry-npm-1.1.1-f9cad6c9aa-0bfb145e9a.zip new file mode 100644 index 00000000000..7b7ce8eb2de Binary files /dev/null and b/.yarn/cache/is-finalizationregistry-npm-1.1.1-f9cad6c9aa-0bfb145e9a.zip differ diff --git a/.yarn/cache/is-generator-function-npm-1.1.2-d0a84b1a72-cc50fa0103.zip b/.yarn/cache/is-generator-function-npm-1.1.2-d0a84b1a72-cc50fa0103.zip new file mode 100644 index 00000000000..ab0c2cecf48 Binary files /dev/null and b/.yarn/cache/is-generator-function-npm-1.1.2-d0a84b1a72-cc50fa0103.zip differ diff --git a/.yarn/cache/is-map-npm-2.0.3-9e061e76e3-8de7b41715.zip b/.yarn/cache/is-map-npm-2.0.3-9e061e76e3-8de7b41715.zip new file mode 100644 index 00000000000..ba460dc2f08 Binary files /dev/null and b/.yarn/cache/is-map-npm-2.0.3-9e061e76e3-8de7b41715.zip differ diff --git a/.yarn/cache/is-negative-zero-npm-2.0.3-d06b09e322-8fe5cffd8d.zip b/.yarn/cache/is-negative-zero-npm-2.0.3-d06b09e322-8fe5cffd8d.zip new file mode 100644 index 00000000000..4d055b36edd Binary files /dev/null and b/.yarn/cache/is-negative-zero-npm-2.0.3-d06b09e322-8fe5cffd8d.zip differ diff --git a/.yarn/cache/is-number-object-npm-1.1.1-010c417fc6-a5922fb877.zip b/.yarn/cache/is-number-object-npm-1.1.1-010c417fc6-a5922fb877.zip new file mode 100644 index 00000000000..ae8279bfbc9 Binary files /dev/null and b/.yarn/cache/is-number-object-npm-1.1.1-010c417fc6-a5922fb877.zip differ diff --git a/.yarn/cache/is-path-inside-npm-3.0.3-2ea0ef44fd-abd50f0618.zip b/.yarn/cache/is-path-inside-npm-3.0.3-2ea0ef44fd-abd50f0618.zip deleted file mode 100644 index 27f29d70bee..00000000000 Binary files a/.yarn/cache/is-path-inside-npm-3.0.3-2ea0ef44fd-abd50f0618.zip and /dev/null differ diff --git a/.yarn/cache/is-regex-npm-1.2.1-70a484f2c8-c42b7efc58.zip b/.yarn/cache/is-regex-npm-1.2.1-70a484f2c8-c42b7efc58.zip new file mode 100644 index 00000000000..595feded985 Binary files /dev/null and b/.yarn/cache/is-regex-npm-1.2.1-70a484f2c8-c42b7efc58.zip differ diff --git a/.yarn/cache/is-set-npm-2.0.3-1b72c9a855-5685df33f0.zip b/.yarn/cache/is-set-npm-2.0.3-1b72c9a855-5685df33f0.zip new file mode 100644 index 00000000000..3b1e3d0efbe Binary files /dev/null and b/.yarn/cache/is-set-npm-2.0.3-1b72c9a855-5685df33f0.zip differ diff --git a/.yarn/cache/is-shared-array-buffer-npm-1.0.4-70c977585b-0380d7c60c.zip b/.yarn/cache/is-shared-array-buffer-npm-1.0.4-70c977585b-0380d7c60c.zip new file mode 100644 index 00000000000..3204946d003 Binary files /dev/null and b/.yarn/cache/is-shared-array-buffer-npm-1.0.4-70c977585b-0380d7c60c.zip differ diff --git a/.yarn/cache/is-string-npm-1.1.1-d2c4f9f448-5277cb9e22.zip b/.yarn/cache/is-string-npm-1.1.1-d2c4f9f448-5277cb9e22.zip new file mode 100644 index 00000000000..74b44764f4c Binary files /dev/null and b/.yarn/cache/is-string-npm-1.1.1-d2c4f9f448-5277cb9e22.zip differ diff --git a/.yarn/cache/is-symbol-npm-1.1.1-f17b666ca9-db495c0d8c.zip b/.yarn/cache/is-symbol-npm-1.1.1-f17b666ca9-db495c0d8c.zip new file mode 100644 index 00000000000..408261fcb0d Binary files /dev/null and b/.yarn/cache/is-symbol-npm-1.1.1-f17b666ca9-db495c0d8c.zip differ diff --git a/.yarn/cache/is-weakmap-npm-2.0.2-ced3cab2dc-a7b7e23206.zip b/.yarn/cache/is-weakmap-npm-2.0.2-ced3cab2dc-a7b7e23206.zip new file mode 100644 index 00000000000..56e3990f2f1 Binary files /dev/null and b/.yarn/cache/is-weakmap-npm-2.0.2-ced3cab2dc-a7b7e23206.zip differ diff --git a/.yarn/cache/is-weakref-npm-1.1.1-e6458807f4-543506fd82.zip b/.yarn/cache/is-weakref-npm-1.1.1-e6458807f4-543506fd82.zip new file mode 100644 index 00000000000..241a2727893 Binary files /dev/null and b/.yarn/cache/is-weakref-npm-1.1.1-e6458807f4-543506fd82.zip differ diff --git a/.yarn/cache/is-weakset-npm-2.0.4-155b83e84b-1d5e1d0179.zip b/.yarn/cache/is-weakset-npm-2.0.4-155b83e84b-1d5e1d0179.zip new file mode 100644 index 00000000000..359b59c1de1 Binary files /dev/null and b/.yarn/cache/is-weakset-npm-2.0.4-155b83e84b-1d5e1d0179.zip differ diff --git a/.yarn/cache/iterator.prototype-npm-1.1.5-923c4c9977-352bcf333f.zip b/.yarn/cache/iterator.prototype-npm-1.1.5-923c4c9977-352bcf333f.zip new file mode 100644 index 00000000000..e162f2ea05d Binary files /dev/null and b/.yarn/cache/iterator.prototype-npm-1.1.5-923c4c9977-352bcf333f.zip differ diff --git a/.yarn/cache/jsdoc-type-pratt-parser-npm-4.0.0-7b035921c4-a225ab874e.zip b/.yarn/cache/jsdoc-type-pratt-parser-npm-4.1.0-6f90ea9fa7-30d88f95f6.zip similarity index 55% rename from .yarn/cache/jsdoc-type-pratt-parser-npm-4.0.0-7b035921c4-a225ab874e.zip rename to .yarn/cache/jsdoc-type-pratt-parser-npm-4.1.0-6f90ea9fa7-30d88f95f6.zip index d6e0588c79e..316f26326ac 100644 Binary files a/.yarn/cache/jsdoc-type-pratt-parser-npm-4.0.0-7b035921c4-a225ab874e.zip and b/.yarn/cache/jsdoc-type-pratt-parser-npm-4.1.0-6f90ea9fa7-30d88f95f6.zip differ diff --git a/.yarn/cache/jsesc-npm-2.5.2-c5acb78804-d2096abdcd.zip b/.yarn/cache/jsesc-npm-2.5.2-c5acb78804-d2096abdcd.zip deleted file mode 100644 index aa7eb96488b..00000000000 Binary files a/.yarn/cache/jsesc-npm-2.5.2-c5acb78804-d2096abdcd.zip and /dev/null differ diff --git a/.yarn/cache/jsx-ast-utils-npm-3.3.5-114c80f97a-b61d446136.zip b/.yarn/cache/jsx-ast-utils-npm-3.3.5-114c80f97a-b61d446136.zip new file mode 100644 index 00000000000..1d4d11d18cb Binary files /dev/null and b/.yarn/cache/jsx-ast-utils-npm-3.3.5-114c80f97a-b61d446136.zip differ diff --git a/.yarn/cache/language-subtag-registry-npm-0.3.23-06b360f90f-fe13ed74ab.zip b/.yarn/cache/language-subtag-registry-npm-0.3.23-06b360f90f-fe13ed74ab.zip new file mode 100644 index 00000000000..71cdc2f1e88 Binary files /dev/null and b/.yarn/cache/language-subtag-registry-npm-0.3.23-06b360f90f-fe13ed74ab.zip differ diff --git a/.yarn/cache/language-tags-npm-1.0.9-3ea51f204b-d3a7c14b69.zip b/.yarn/cache/language-tags-npm-1.0.9-3ea51f204b-d3a7c14b69.zip new file mode 100644 index 00000000000..8878cf0c0b1 Binary files /dev/null and b/.yarn/cache/language-tags-npm-1.0.9-3ea51f204b-d3a7c14b69.zip differ diff --git a/.yarn/cache/loose-envify-npm-1.4.0-6307b72ccf-6517e24e0c.zip b/.yarn/cache/loose-envify-npm-1.4.0-6307b72ccf-6517e24e0c.zip new file mode 100644 index 00000000000..ba25b876ce3 Binary files /dev/null and b/.yarn/cache/loose-envify-npm-1.4.0-6307b72ccf-6517e24e0c.zip differ diff --git a/.yarn/cache/minimatch-npm-10.1.1-453db4ee1a-110f38921e.zip b/.yarn/cache/minimatch-npm-10.1.1-453db4ee1a-110f38921e.zip new file mode 100644 index 00000000000..0f7dea95fc0 Binary files /dev/null and b/.yarn/cache/minimatch-npm-10.1.1-453db4ee1a-110f38921e.zip differ diff --git a/.yarn/cache/napi-postinstall-npm-0.3.4-a58e1fcbc3-5541381508.zip b/.yarn/cache/napi-postinstall-npm-0.3.4-a58e1fcbc3-5541381508.zip new file mode 100644 index 00000000000..0d00d6a7178 Binary files /dev/null and b/.yarn/cache/napi-postinstall-npm-0.3.4-a58e1fcbc3-5541381508.zip differ diff --git a/.yarn/cache/object.assign-npm-4.1.7-a3464be41b-3fe28cdd77.zip b/.yarn/cache/object.assign-npm-4.1.7-a3464be41b-3fe28cdd77.zip new file mode 100644 index 00000000000..a229aa30b25 Binary files /dev/null and b/.yarn/cache/object.assign-npm-4.1.7-a3464be41b-3fe28cdd77.zip differ diff --git a/.yarn/cache/object.entries-npm-1.1.6-5f9ba14b46-08a09ff839.zip b/.yarn/cache/object.entries-npm-1.1.6-5f9ba14b46-08a09ff839.zip deleted file mode 100644 index ef7ca5e0173..00000000000 Binary files a/.yarn/cache/object.entries-npm-1.1.6-5f9ba14b46-08a09ff839.zip and /dev/null differ diff --git a/.yarn/cache/object.entries-npm-1.1.9-32f1b371e0-24163ab1e1.zip b/.yarn/cache/object.entries-npm-1.1.9-32f1b371e0-24163ab1e1.zip new file mode 100644 index 00000000000..42c0abeb3f4 Binary files /dev/null and b/.yarn/cache/object.entries-npm-1.1.9-32f1b371e0-24163ab1e1.zip differ diff --git a/.yarn/cache/object.fromentries-npm-2.0.7-2e38392540-1bfbe42a51.zip b/.yarn/cache/object.fromentries-npm-2.0.8-8f6e2db04a-5b2e80f7af.zip similarity index 54% rename from .yarn/cache/object.fromentries-npm-2.0.7-2e38392540-1bfbe42a51.zip rename to .yarn/cache/object.fromentries-npm-2.0.8-8f6e2db04a-5b2e80f7af.zip index 54aedc088c3..3d8e3e7ddb4 100644 Binary files a/.yarn/cache/object.fromentries-npm-2.0.7-2e38392540-1bfbe42a51.zip and b/.yarn/cache/object.fromentries-npm-2.0.8-8f6e2db04a-5b2e80f7af.zip differ diff --git a/.yarn/cache/object.groupby-npm-1.0.1-fc268391fe-b7123d9140.zip b/.yarn/cache/object.groupby-npm-1.0.1-fc268391fe-b7123d9140.zip deleted file mode 100644 index 87592b6fdc1..00000000000 Binary files a/.yarn/cache/object.groupby-npm-1.0.1-fc268391fe-b7123d9140.zip and /dev/null differ diff --git a/.yarn/cache/object.groupby-npm-1.0.3-d5feb41454-44cb86dd2c.zip b/.yarn/cache/object.groupby-npm-1.0.3-d5feb41454-44cb86dd2c.zip new file mode 100644 index 00000000000..7e6e04bf5c5 Binary files /dev/null and b/.yarn/cache/object.groupby-npm-1.0.3-d5feb41454-44cb86dd2c.zip differ diff --git a/.yarn/cache/object.values-npm-1.1.7-deae619f88-20ab42c0bb.zip b/.yarn/cache/object.values-npm-1.1.7-deae619f88-20ab42c0bb.zip deleted file mode 100644 index e8bfded9832..00000000000 Binary files a/.yarn/cache/object.values-npm-1.1.7-deae619f88-20ab42c0bb.zip and /dev/null differ diff --git a/.yarn/cache/object.values-npm-1.2.1-cd21c82f2d-f5ec9eccde.zip b/.yarn/cache/object.values-npm-1.2.1-cd21c82f2d-f5ec9eccde.zip new file mode 100644 index 00000000000..d6b14127fa2 Binary files /dev/null and b/.yarn/cache/object.values-npm-1.2.1-cd21c82f2d-f5ec9eccde.zip differ diff --git a/.yarn/cache/own-keys-npm-1.0.1-1253f9b344-ab4bb3b863.zip b/.yarn/cache/own-keys-npm-1.0.1-1253f9b344-ab4bb3b863.zip new file mode 100644 index 00000000000..6e137232fd5 Binary files /dev/null and b/.yarn/cache/own-keys-npm-1.0.1-1253f9b344-ab4bb3b863.zip differ diff --git a/.yarn/cache/parse-imports-exports-npm-0.2.4-4af940c595-144d459771.zip b/.yarn/cache/parse-imports-exports-npm-0.2.4-4af940c595-144d459771.zip new file mode 100644 index 00000000000..21e6c0610d0 Binary files /dev/null and b/.yarn/cache/parse-imports-exports-npm-0.2.4-4af940c595-144d459771.zip differ diff --git a/.yarn/cache/parse-statements-npm-1.0.11-f733998c18-287c2739f4.zip b/.yarn/cache/parse-statements-npm-1.0.11-f733998c18-287c2739f4.zip new file mode 100644 index 00000000000..2a01690d261 Binary files /dev/null and b/.yarn/cache/parse-statements-npm-1.0.11-f733998c18-287c2739f4.zip differ diff --git a/.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-57b99055f4.zip b/.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-57b99055f4.zip new file mode 100644 index 00000000000..beb9c3bb3e8 Binary files /dev/null and b/.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-57b99055f4.zip differ diff --git a/.yarn/cache/prop-types-npm-15.8.1-17c71ee7ee-7d959caec0.zip b/.yarn/cache/prop-types-npm-15.8.1-17c71ee7ee-7d959caec0.zip new file mode 100644 index 00000000000..32adf29b387 Binary files /dev/null and b/.yarn/cache/prop-types-npm-15.8.1-17c71ee7ee-7d959caec0.zip differ diff --git a/.yarn/cache/react-is-npm-16.13.1-a9b9382b4f-5aa564a1cd.zip b/.yarn/cache/react-is-npm-16.13.1-a9b9382b4f-5aa564a1cd.zip new file mode 100644 index 00000000000..39d1323f7b4 Binary files /dev/null and b/.yarn/cache/react-is-npm-16.13.1-a9b9382b4f-5aa564a1cd.zip differ diff --git a/.yarn/cache/reflect.getprototypeof-npm-1.0.10-8c3ce862a2-80a4e2be71.zip b/.yarn/cache/reflect.getprototypeof-npm-1.0.10-8c3ce862a2-80a4e2be71.zip new file mode 100644 index 00000000000..1f6e7858583 Binary files /dev/null and b/.yarn/cache/reflect.getprototypeof-npm-1.0.10-8c3ce862a2-80a4e2be71.zip differ diff --git a/.yarn/cache/regexp.prototype.flags-npm-1.5.4-39008ab64c-8ab897ca44.zip b/.yarn/cache/regexp.prototype.flags-npm-1.5.4-39008ab64c-8ab897ca44.zip new file mode 100644 index 00000000000..4d6f258f89d Binary files /dev/null and b/.yarn/cache/regexp.prototype.flags-npm-1.5.4-39008ab64c-8ab897ca44.zip differ diff --git a/.yarn/cache/resolve-npm-2.0.0-next.5-0e83bf26ee-2d6fd28699.zip b/.yarn/cache/resolve-npm-2.0.0-next.5-0e83bf26ee-2d6fd28699.zip new file mode 100644 index 00000000000..97bc54c8dec Binary files /dev/null and b/.yarn/cache/resolve-npm-2.0.0-next.5-0e83bf26ee-2d6fd28699.zip differ diff --git a/.yarn/cache/resolve-patch-95f8f5d302-05fa778de9.zip b/.yarn/cache/resolve-patch-95f8f5d302-05fa778de9.zip new file mode 100644 index 00000000000..bedfa85b088 Binary files /dev/null and b/.yarn/cache/resolve-patch-95f8f5d302-05fa778de9.zip differ diff --git a/.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-0763150adf.zip b/.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-0763150adf.zip new file mode 100644 index 00000000000..8e3561c417d Binary files /dev/null and b/.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-0763150adf.zip differ diff --git a/.yarn/cache/safe-array-concat-npm-1.1.3-dab0384e54-fac4f40f20.zip b/.yarn/cache/safe-array-concat-npm-1.1.3-dab0384e54-fac4f40f20.zip new file mode 100644 index 00000000000..ea290b6f0ac Binary files /dev/null and b/.yarn/cache/safe-array-concat-npm-1.1.3-dab0384e54-fac4f40f20.zip differ diff --git a/.yarn/cache/safe-push-apply-npm-1.0.0-51a0a42944-2bd4e53b66.zip b/.yarn/cache/safe-push-apply-npm-1.0.0-51a0a42944-2bd4e53b66.zip new file mode 100644 index 00000000000..d1722560d74 Binary files /dev/null and b/.yarn/cache/safe-push-apply-npm-1.0.0-51a0a42944-2bd4e53b66.zip differ diff --git a/.yarn/cache/safe-regex-test-npm-1.1.0-453eb81b83-ebdb61f305.zip b/.yarn/cache/safe-regex-test-npm-1.1.0-453eb81b83-ebdb61f305.zip new file mode 100644 index 00000000000..c288a5684b0 Binary files /dev/null and b/.yarn/cache/safe-regex-test-npm-1.1.0-453eb81b83-ebdb61f305.zip differ diff --git a/.yarn/cache/set-function-name-npm-2.0.2-3d9a2d8899-c7614154a5.zip b/.yarn/cache/set-function-name-npm-2.0.2-3d9a2d8899-c7614154a5.zip new file mode 100644 index 00000000000..7a64e14695f Binary files /dev/null and b/.yarn/cache/set-function-name-npm-2.0.2-3d9a2d8899-c7614154a5.zip differ diff --git a/.yarn/cache/set-proto-npm-1.0.0-68d7485485-b87f8187bc.zip b/.yarn/cache/set-proto-npm-1.0.0-68d7485485-b87f8187bc.zip new file mode 100644 index 00000000000..5417a365681 Binary files /dev/null and b/.yarn/cache/set-proto-npm-1.0.0-68d7485485-b87f8187bc.zip differ diff --git a/.yarn/cache/spdx-expression-parse-npm-4.0.0-1c2f5caf51-936be681fb.zip b/.yarn/cache/spdx-expression-parse-npm-4.0.0-1c2f5caf51-936be681fb.zip new file mode 100644 index 00000000000..764abcd3520 Binary files /dev/null and b/.yarn/cache/spdx-expression-parse-npm-4.0.0-1c2f5caf51-936be681fb.zip differ diff --git a/.yarn/cache/stable-hash-x-npm-0.2.0-1eebae4f09-136f05d0e4.zip b/.yarn/cache/stable-hash-x-npm-0.2.0-1eebae4f09-136f05d0e4.zip new file mode 100644 index 00000000000..665ee80085d Binary files /dev/null and b/.yarn/cache/stable-hash-x-npm-0.2.0-1eebae4f09-136f05d0e4.zip differ diff --git a/.yarn/cache/stop-iteration-iterator-npm-1.1.0-057344287e-ff36c4db17.zip b/.yarn/cache/stop-iteration-iterator-npm-1.1.0-057344287e-ff36c4db17.zip new file mode 100644 index 00000000000..450f7adf412 Binary files /dev/null and b/.yarn/cache/stop-iteration-iterator-npm-1.1.0-057344287e-ff36c4db17.zip differ diff --git a/.yarn/cache/string.prototype.includes-npm-2.0.1-12fb63787c-939a5447e4.zip b/.yarn/cache/string.prototype.includes-npm-2.0.1-12fb63787c-939a5447e4.zip new file mode 100644 index 00000000000..98c859e8185 Binary files /dev/null and b/.yarn/cache/string.prototype.includes-npm-2.0.1-12fb63787c-939a5447e4.zip differ diff --git a/.yarn/cache/string.prototype.matchall-npm-4.0.12-0bc859367d-e4ab34b9e7.zip b/.yarn/cache/string.prototype.matchall-npm-4.0.12-0bc859367d-e4ab34b9e7.zip new file mode 100644 index 00000000000..c5e2520234b Binary files /dev/null and b/.yarn/cache/string.prototype.matchall-npm-4.0.12-0bc859367d-e4ab34b9e7.zip differ diff --git a/.yarn/cache/string.prototype.repeat-npm-1.0.0-3f87f5fd9e-4b1bd91b75.zip b/.yarn/cache/string.prototype.repeat-npm-1.0.0-3f87f5fd9e-4b1bd91b75.zip new file mode 100644 index 00000000000..004c48324c9 Binary files /dev/null and b/.yarn/cache/string.prototype.repeat-npm-1.0.0-3f87f5fd9e-4b1bd91b75.zip differ diff --git a/.yarn/cache/string.prototype.trim-npm-1.2.10-40a44bc719-47bb63cd24.zip b/.yarn/cache/string.prototype.trim-npm-1.2.10-40a44bc719-47bb63cd24.zip new file mode 100644 index 00000000000..897598e85d5 Binary files /dev/null and b/.yarn/cache/string.prototype.trim-npm-1.2.10-40a44bc719-47bb63cd24.zip differ diff --git a/.yarn/cache/string.prototype.trimend-npm-1.0.9-e8729528fb-140c73899b.zip b/.yarn/cache/string.prototype.trimend-npm-1.0.9-e8729528fb-140c73899b.zip new file mode 100644 index 00000000000..0bd8f076243 Binary files /dev/null and b/.yarn/cache/string.prototype.trimend-npm-1.0.9-e8729528fb-140c73899b.zip differ diff --git a/.yarn/cache/string.prototype.trimstart-npm-1.0.8-8c6b16ba6e-160167dfbd.zip b/.yarn/cache/string.prototype.trimstart-npm-1.0.8-8c6b16ba6e-160167dfbd.zip new file mode 100644 index 00000000000..8f20c76a68b Binary files /dev/null and b/.yarn/cache/string.prototype.trimstart-npm-1.0.8-8c6b16ba6e-160167dfbd.zip differ diff --git a/.yarn/cache/tar-npm-7.5.6-955ec951c2-cf4a84d79b.zip b/.yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip similarity index 83% rename from .yarn/cache/tar-npm-7.5.6-955ec951c2-cf4a84d79b.zip rename to .yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip index 0da88d1aa8c..4e183c1f29e 100644 Binary files a/.yarn/cache/tar-npm-7.5.6-955ec951c2-cf4a84d79b.zip and b/.yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip differ diff --git a/.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-d72bd826a8.zip b/.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-d72bd826a8.zip new file mode 100644 index 00000000000..4455c77cc39 Binary files /dev/null and b/.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-d72bd826a8.zip differ diff --git a/.yarn/cache/ts-api-utils-npm-2.4.0-1179124e9a-d6b2b3b6ca.zip b/.yarn/cache/ts-api-utils-npm-2.4.0-1179124e9a-d6b2b3b6ca.zip new file mode 100644 index 00000000000..7ddfe9f181c Binary files /dev/null and b/.yarn/cache/ts-api-utils-npm-2.4.0-1179124e9a-d6b2b3b6ca.zip differ diff --git a/.yarn/cache/ts-declaration-location-npm-1.0.7-804f747b5c-a7932fc75d.zip b/.yarn/cache/ts-declaration-location-npm-1.0.7-804f747b5c-a7932fc75d.zip new file mode 100644 index 00000000000..72540888ad5 Binary files /dev/null and b/.yarn/cache/ts-declaration-location-npm-1.0.7-804f747b5c-a7932fc75d.zip differ diff --git a/.yarn/cache/tsutils-npm-3.21.0-347e6636c5-ea036bec1d.zip b/.yarn/cache/tsutils-npm-3.21.0-347e6636c5-ea036bec1d.zip deleted file mode 100644 index 75c33788c29..00000000000 Binary files a/.yarn/cache/tsutils-npm-3.21.0-347e6636c5-ea036bec1d.zip and /dev/null differ diff --git a/.yarn/cache/type-fest-npm-0.20.2-b36432617f-8907e16284.zip b/.yarn/cache/type-fest-npm-0.20.2-b36432617f-8907e16284.zip deleted file mode 100644 index 8246f460f50..00000000000 Binary files a/.yarn/cache/type-fest-npm-0.20.2-b36432617f-8907e16284.zip and /dev/null differ diff --git a/.yarn/cache/typed-array-byte-length-npm-1.0.3-0769937080-269dad101d.zip b/.yarn/cache/typed-array-byte-length-npm-1.0.3-0769937080-269dad101d.zip new file mode 100644 index 00000000000..fa0892abc9b Binary files /dev/null and b/.yarn/cache/typed-array-byte-length-npm-1.0.3-0769937080-269dad101d.zip differ diff --git a/.yarn/cache/typed-array-byte-offset-npm-1.0.4-12f60e4553-c2869aa584.zip b/.yarn/cache/typed-array-byte-offset-npm-1.0.4-12f60e4553-c2869aa584.zip new file mode 100644 index 00000000000..99deb2208e5 Binary files /dev/null and b/.yarn/cache/typed-array-byte-offset-npm-1.0.4-12f60e4553-c2869aa584.zip differ diff --git a/.yarn/cache/typed-array-length-npm-1.0.7-ac6ef772a7-d6b2f0e811.zip b/.yarn/cache/typed-array-length-npm-1.0.7-ac6ef772a7-d6b2f0e811.zip new file mode 100644 index 00000000000..7c248a9b8ff Binary files /dev/null and b/.yarn/cache/typed-array-length-npm-1.0.7-ac6ef772a7-d6b2f0e811.zip differ diff --git a/.yarn/cache/typescript-eslint-npm-8.54.0-4dca5fd4d6-21b1a27fd4.zip b/.yarn/cache/typescript-eslint-npm-8.54.0-4dca5fd4d6-21b1a27fd4.zip new file mode 100644 index 00000000000..773ac95944c Binary files /dev/null and b/.yarn/cache/typescript-eslint-npm-8.54.0-4dca5fd4d6-21b1a27fd4.zip differ diff --git a/.yarn/cache/typescript-npm-5.9.3-48715be868-c089d9d3da.zip b/.yarn/cache/typescript-npm-5.9.3-48715be868-c089d9d3da.zip new file mode 100644 index 00000000000..0eabff58df5 Binary files /dev/null and b/.yarn/cache/typescript-npm-5.9.3-48715be868-c089d9d3da.zip differ diff --git a/.yarn/cache/typescript-patch-6fda4d02cf-696e1b017b.zip b/.yarn/cache/typescript-patch-6fda4d02cf-696e1b017b.zip new file mode 100644 index 00000000000..6cd39270319 Binary files /dev/null and b/.yarn/cache/typescript-patch-6fda4d02cf-696e1b017b.zip differ diff --git a/.yarn/cache/unbox-primitive-npm-1.1.0-269638c590-fadb347020.zip b/.yarn/cache/unbox-primitive-npm-1.1.0-269638c590-fadb347020.zip new file mode 100644 index 00000000000..bbb5e94fde2 Binary files /dev/null and b/.yarn/cache/unbox-primitive-npm-1.1.0-269638c590-fadb347020.zip differ diff --git a/.yarn/cache/undici-types-npm-6.21.0-eb2b0ed56a-ec8f41aa43.zip b/.yarn/cache/undici-types-npm-6.21.0-eb2b0ed56a-ec8f41aa43.zip new file mode 100644 index 00000000000..1ab7a8859e8 Binary files /dev/null and b/.yarn/cache/undici-types-npm-6.21.0-eb2b0ed56a-ec8f41aa43.zip differ diff --git a/.yarn/cache/unrs-resolver-npm-1.11.1-9828edd1f1-4de653508c.zip b/.yarn/cache/unrs-resolver-npm-1.11.1-9828edd1f1-4de653508c.zip new file mode 100644 index 00000000000..9fd3614ef5c Binary files /dev/null and b/.yarn/cache/unrs-resolver-npm-1.11.1-9828edd1f1-4de653508c.zip differ diff --git a/.yarn/cache/which-boxed-primitive-npm-1.1.1-80ca20c912-a877c0667b.zip b/.yarn/cache/which-boxed-primitive-npm-1.1.1-80ca20c912-a877c0667b.zip new file mode 100644 index 00000000000..866e843ec5e Binary files /dev/null and b/.yarn/cache/which-boxed-primitive-npm-1.1.1-80ca20c912-a877c0667b.zip differ diff --git a/.yarn/cache/which-builtin-type-npm-1.2.1-bbbdf9137f-22c81c5cb7.zip b/.yarn/cache/which-builtin-type-npm-1.2.1-bbbdf9137f-22c81c5cb7.zip new file mode 100644 index 00000000000..2a4871f8acc Binary files /dev/null and b/.yarn/cache/which-builtin-type-npm-1.2.1-bbbdf9137f-22c81c5cb7.zip differ diff --git a/.yarn/cache/which-collection-npm-1.0.2-0d6277e921-674bf659b9.zip b/.yarn/cache/which-collection-npm-1.0.2-0d6277e921-674bf659b9.zip new file mode 100644 index 00000000000..19ae6c6cc0f Binary files /dev/null and b/.yarn/cache/which-collection-npm-1.0.2-0d6277e921-674bf659b9.zip differ diff --git a/.yarn/cache/which-typed-array-npm-1.1.20-8cc727cdc7-e56da3fc99.zip b/.yarn/cache/which-typed-array-npm-1.1.20-8cc727cdc7-e56da3fc99.zip new file mode 100644 index 00000000000..5734461ebe8 Binary files /dev/null and b/.yarn/cache/which-typed-array-npm-1.1.20-8cc727cdc7-e56da3fc99.zip differ diff --git a/.yarn/cache/zod-npm-4.3.6-a096e305e6-25fc0f62e0.zip b/.yarn/cache/zod-npm-4.3.6-a096e305e6-25fc0f62e0.zip new file mode 100644 index 00000000000..2c93f1e5fd8 Binary files /dev/null and b/.yarn/cache/zod-npm-4.3.6-a096e305e6-25fc0f62e0.zip differ diff --git a/.yarn/cache/zod-validation-error-npm-4.0.2-1b963160c8-5e35ca8ebb.zip b/.yarn/cache/zod-validation-error-npm-4.0.2-1b963160c8-5e35ca8ebb.zip new file mode 100644 index 00000000000..c39a3b27f51 Binary files /dev/null and b/.yarn/cache/zod-validation-error-npm-4.0.2-1b963160c8-5e35ca8ebb.zip differ diff --git a/eslint/base.mjs b/eslint/base.mjs new file mode 100644 index 00000000000..68b36a336e4 --- /dev/null +++ b/eslint/base.mjs @@ -0,0 +1,86 @@ +import { configs, plugins } from 'eslint-config-airbnb-extended'; +import globals from 'globals'; + +/** + * Base ESLint configuration for all packages. + * Contains common rules and overrides used across the monorepo. + */ +export const baseConfig = [ + // Register the plugins required by airbnb-extended + // Each plugin export is a config object with nested plugins + plugins.stylistic, + plugins.importX, + plugins.node, + ...configs.base.recommended, + { + languageOptions: { + ecmaVersion: 2022, + sourceType: 'module', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + globals: { + ...globals.node, + BigInt: 'readonly', + }, + }, + rules: { + // Common overrides from existing configs + 'no-plusplus': 'off', + 'eol-last': ['error', 'always'], + 'class-methods-use-this': 'off', + curly: ['warn', 'all'], + 'no-await-in-loop': 'off', + 'no-continue': 'off', + // Custom restricted syntax - remove ForOfStatement restriction from airbnb + 'no-restricted-syntax': [ + 'error', + { + selector: 'LabeledStatement', + message: 'Labels are a form of GOTO; using them makes code confusing.', + }, + { + selector: 'WithStatement', + message: '`with` is disallowed in strict mode.', + }, + ], + // Disable import-x rules that don't work well in monorepo + 'import-x/no-relative-packages': 'off', + 'import-x/extensions': 'off', + 'import-x/no-named-as-default': 'off', + // Increase line length limit + '@stylistic/max-len': ['warn', { code: 120, ignoreStrings: true, ignoreTemplateLiterals: true, ignoreUrls: true, ignoreRegExpLiterals: true, ignoreComments: true }], + // Disable @stylistic rules that weren't enforced before + '@stylistic/indent': 'off', + '@stylistic/brace-style': 'off', + '@stylistic/max-statements-per-line': 'off', + '@stylistic/operator-linebreak': 'off', + '@stylistic/member-delimiter-style': 'off', + '@stylistic/type-annotation-spacing': 'off', + '@stylistic/arrow-parens': 'off', + '@stylistic/arrow-spacing': 'off', + '@stylistic/semi': 'off', + '@stylistic/comma-spacing': 'off', + '@stylistic/comma-dangle': 'off', + '@stylistic/quote-props': 'off', + '@stylistic/quotes': 'off', + '@stylistic/lines-between-class-members': 'off', + '@stylistic/object-curly-newline': 'off', + '@stylistic/no-mixed-operators': 'off', + // Disable other rules that weren't enforced before + 'prefer-arrow-callback': 'off', + 'prefer-object-has-own': 'off', + 'no-new': 'off', + 'no-restricted-exports': 'off', + // Disable import-x rules that cause too many warnings + 'import-x/newline-after-import': 'off', + 'import-x/no-useless-path-segments': 'off', + 'import-x/no-rename-default': 'off', + 'import-x/namespace': 'off', + 'import-x/prefer-default-export': 'off', + }, + }, +]; + +export default baseConfig; diff --git a/eslint/mocha-tests.mjs b/eslint/mocha-tests.mjs new file mode 100644 index 00000000000..9d5bf3f3696 --- /dev/null +++ b/eslint/mocha-tests.mjs @@ -0,0 +1,32 @@ +import globals from 'globals'; + +/** + * Mocha test files ESLint configuration. + * Provides test-specific globals and rule relaxations. + */ +export const mochaTestConfig = { + files: [ + '**/test/**/*.js', + '**/test/**/*.ts', + '**/tests/**/*.js', + '**/tests/**/*.ts', + '**/*.spec.js', + '**/*.spec.ts', + '**/test-d/**/*.ts', + ], + languageOptions: { + globals: { + ...globals.mocha, + expect: 'readonly', + }, + }, + rules: { + // Allow dev dependencies in tests + 'import-x/no-extraneous-dependencies': 'off', + // dirty-chai uses property assertions + 'no-unused-expressions': 'off', + '@typescript-eslint/no-unused-expressions': 'off', + }, +}; + +export default mochaTestConfig; diff --git a/eslint/typescript.mjs b/eslint/typescript.mjs new file mode 100644 index 00000000000..6d1629e668f --- /dev/null +++ b/eslint/typescript.mjs @@ -0,0 +1,50 @@ +import { configs, plugins } from 'eslint-config-airbnb-extended'; + +/** + * TypeScript ESLint configuration. + * Extends base config with TypeScript-specific rules and relaxations. + */ +export const typescriptConfig = [ + // Register the TypeScript plugin + plugins.typescriptEslint, + ...configs.base.typescript, + { + files: ['**/*.ts', '**/*.tsx'], + rules: { + // Disable base rules that conflict with TypeScript versions + 'no-return-await': 'off', + '@typescript-eslint/return-await': 'warn', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': 'warn', + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': 'error', + + // Relax strict TypeScript rules for backward compatibility + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-unsafe-function-type': 'off', + '@typescript-eslint/no-this-alias': 'off', + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-use-before-define': 'off', + 'no-use-before-define': 'off', + + // Disable new @typescript-eslint rules not previously enforced + '@typescript-eslint/consistent-indexed-object-style': 'off', + '@typescript-eslint/consistent-type-definitions': 'off', + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/array-type': 'off', + '@typescript-eslint/prefer-function-type': 'off', + + // Import resolution handled by TypeScript + 'import-x/extensions': 'off', + 'import-x/no-unresolved': 'off', + + // Disable @stylistic rules for TypeScript files (not previously enforced) + '@stylistic/member-delimiter-style': 'off', + '@stylistic/type-annotation-spacing': 'off', + }, + }, +]; + +export default typescriptConfig; diff --git a/eslint/wasm.mjs b/eslint/wasm.mjs new file mode 100644 index 00000000000..00aa34252f0 --- /dev/null +++ b/eslint/wasm.mjs @@ -0,0 +1,25 @@ +/** + * WASM-specific ESLint configuration. + * Relaxes rules that conflict with WASM bindings and FFI patterns. + */ +export const wasmConfig = { + rules: { + // WASM bindings use __type, _wbg_ptr naming conventions + 'no-underscore-dangle': 'off', + // Legitimate use in hex conversion and buffer operations + 'no-bitwise': 'off', + // for-of loops are acceptable in modern TypeScript + 'no-restricted-syntax': 'off', + // Extended line length for WASM binding code + 'max-len': [ + 'error', + { + code: 140, + ignoreStrings: true, + ignoreTemplateLiterals: true, + }, + ], + }, +}; + +export default wasmConfig; diff --git a/package.json b/package.json index 5b595416e03..35b0dee8482 100644 --- a/package.json +++ b/package.json @@ -42,11 +42,17 @@ }, "devDependencies": { "@iarna/toml": "^2.2.5", + "@typescript-eslint/parser": "^8.0.0", "add-stream": "^1.0.0", "conventional-changelog": "^3.1.24", "conventional-changelog-dash": "github:dashevo/conventional-changelog-dash", + "eslint": "^9.18.0", + "eslint-config-airbnb-extended": "^3.0.1", + "eslint-plugin-jsdoc": "^50.6.3", + "globals": "^15.14.0", "semver": "^7.5.3", "tempfile": "^3.0.0", + "typescript": "^5.7.3", "ultra-runner": "^3.10.5" }, "workspaces": [ @@ -75,6 +81,7 @@ "packages/js-evo-sdk" ], "resolutions": { + "tar": "7.5.7", "pbkdf2": "^3.1.3", "elliptic": "6.6.1", "bn.js": "4.12.0", @@ -108,7 +115,6 @@ "cross-spawn": "^7.0.5", "nanoid": "^3.3.8", "tar-fs": "^3.0.9", - "tar": "^7.5.4", "brace-expansion": "^2.0.2", "cipher-base": "^1.0.5", "sha.js": "^2.4.12", diff --git a/packages/bench-suite/.eslintrc b/packages/bench-suite/.eslintrc deleted file mode 100644 index 53708855109..00000000000 --- a/packages/bench-suite/.eslintrc +++ /dev/null @@ -1,36 +0,0 @@ -{ - "extends": "airbnb-base", - "env": { - "es2021": true, - "node": true - }, - "parser": "babel-eslint", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "no-continue": "off", - "class-methods-use-this": "off", - "no-await-in-loop": "off", - "no-restricted-syntax": [ - "error", - { - "selector": "LabeledStatement", - "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand." - }, - { - "selector": "WithStatement", - "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." - } - ], - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/bench-suite/benchmarks/basicValidation.js b/packages/bench-suite/benchmarks/basicValidation.js index 40c0944241c..6561fae6c7f 100644 --- a/packages/bench-suite/benchmarks/basicValidation.js +++ b/packages/bench-suite/benchmarks/basicValidation.js @@ -2,7 +2,7 @@ const { PrivateKey } = require('@dashevo/dashcore-lib'); const dpnsDocumentTypes = require('@dashevo/dpns-contract/schema/v1/dpns-contract-documents.json'); -// const { DashPlatformProtocol, Identity, Identifier, default: loadWasmDpp } = require('@dashevo/wasm-dpp'); +const { Identity, Identifier } = require('@dashevo/wasm-dpp'); const generateRandomIdentifier = require('@dashevo/wasm-dpp/lib/test/utils/generateRandomIdentifierAsync'); const crypto = require('crypto'); diff --git a/packages/bench-suite/benchmarks/index.js b/packages/bench-suite/benchmarks/index.js index 0bd564ce90a..d01166184f4 100644 --- a/packages/bench-suite/benchmarks/index.js +++ b/packages/bench-suite/benchmarks/index.js @@ -1,5 +1,3 @@ -/* eslint-disable global-require */ - module.exports = [ require('./documents/100string'), require('./documents/indices'), diff --git a/packages/bench-suite/eslint.config.mjs b/packages/bench-suite/eslint.config.mjs new file mode 100644 index 00000000000..207121987dc --- /dev/null +++ b/packages/bench-suite/eslint.config.mjs @@ -0,0 +1,8 @@ +import baseConfig from '../../eslint/base.mjs'; + +export default [ + ...baseConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/bench-suite/lib/Runner.js b/packages/bench-suite/lib/Runner.js index 0ec30f765e0..89fcee76f27 100644 --- a/packages/bench-suite/lib/Runner.js +++ b/packages/bench-suite/lib/Runner.js @@ -49,7 +49,7 @@ class Runner { * @param {string} filePath */ loadBenchmarks(filePath) { - // eslint-disable-next-line global-require,import/no-dynamic-require + // eslint-disable-next-line import-x/no-dynamic-require const benchmarks = require(filePath); for (const benchmarkConfig of benchmarks) { diff --git a/packages/bench-suite/lib/metrics/drive/DriveMetricsCollector.js b/packages/bench-suite/lib/metrics/drive/DriveMetricsCollector.js index 08af3ea2f7f..0c0f57c4bea 100644 --- a/packages/bench-suite/lib/metrics/drive/DriveMetricsCollector.js +++ b/packages/bench-suite/lib/metrics/drive/DriveMetricsCollector.js @@ -48,7 +48,7 @@ class DriveMetricsCollector extends events.EventEmitter { let logData; try { logData = JSON.parse(line); - } catch (e) { + } catch { return; } diff --git a/packages/bench-suite/package.json b/packages/bench-suite/package.json index 13c70a9f87b..ca54af424a0 100644 --- a/packages/bench-suite/package.json +++ b/packages/bench-suite/package.json @@ -5,7 +5,7 @@ "description": "Dash Platform benchmark tool", "scripts": { "bench": "node ./bin/bench.js", - "lint": "" + "lint": "eslint ." }, "dependencies": { "@dashevo/dashcore-lib": "~0.22.0", @@ -20,10 +20,7 @@ "mocha": "^11.1.0" }, "devDependencies": { - "babel-eslint": "^10.1.0", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0" + "eslint": "^9.18.0" }, "repository": { "type": "git", diff --git a/packages/dapi-grpc/.eslintignore b/packages/dapi-grpc/.eslintignore deleted file mode 100644 index 77ae260f313..00000000000 --- a/packages/dapi-grpc/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -clients/*/v*/web/ -clients/*/v*/nodejs/*_protoc.js -clients/*/v*/nodejs/*_pbjs.js diff --git a/packages/dapi-grpc/.eslintrc b/packages/dapi-grpc/.eslintrc deleted file mode 100644 index 4d651184c49..00000000000 --- a/packages/dapi-grpc/.eslintrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "airbnb-base", - "env": { - "es2020": true - }, - "rules": { - "import/no-extraneous-dependencies": ["error", { "packageDir": "." }], - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - } -} diff --git a/packages/dapi-grpc/eslint.config.mjs b/packages/dapi-grpc/eslint.config.mjs new file mode 100644 index 00000000000..62682622791 --- /dev/null +++ b/packages/dapi-grpc/eslint.config.mjs @@ -0,0 +1,11 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + // Generated protobuf code - ignore clients and src generated directories + ignores: ['dist/**', 'node_modules/**', 'clients/**', 'src/**'], + }, +]; diff --git a/packages/dapi-grpc/lib/test/.eslintrc b/packages/dapi-grpc/lib/test/.eslintrc deleted file mode 100644 index 5092d807856..00000000000 --- a/packages/dapi-grpc/lib/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "globals": { - "expect": true - } -} diff --git a/packages/dapi-grpc/package.json b/packages/dapi-grpc/package.json index f01b1935bac..cf73b25ef8d 100644 --- a/packages/dapi-grpc/package.json +++ b/packages/dapi-grpc/package.json @@ -56,9 +56,7 @@ "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "mocha-sinon": "^2.1.2", "sinon": "^17.0.1", diff --git a/packages/dapi-grpc/test/.eslintrc b/packages/dapi-grpc/test/.eslintrc deleted file mode 100644 index 5092d807856..00000000000 --- a/packages/dapi-grpc/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "globals": { - "expect": true - } -} diff --git a/packages/dapi/.eslintignore b/packages/dapi/.eslintignore deleted file mode 100644 index 4ebc8aea50e..00000000000 --- a/packages/dapi/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -coverage diff --git a/packages/dapi/.eslintrc b/packages/dapi/.eslintrc deleted file mode 100644 index 7eb94b2144b..00000000000 --- a/packages/dapi/.eslintrc +++ /dev/null @@ -1,37 +0,0 @@ -{ - "extends": "airbnb-base", - "parserOptions": { - // Required for certain syntax usages - "ecmaVersion": 2022, - "requireConfigFile": false - }, - "parser": "@babel/eslint-parser", - "env": { - "node": true - }, - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "no-continue": "off", - "class-methods-use-this": "off", - "no-await-in-loop": "off", - "no-restricted-syntax": [ - "error", - { - "selector": "LabeledStatement", - "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand." - }, - { - "selector": "WithStatement", - "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." - } - ], - "curly": [ - "error", - "all" - ] - } -} diff --git a/packages/dapi/eslint.config.mjs b/packages/dapi/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/dapi/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/dapi/lib/test/.eslintrc b/packages/dapi/lib/test/.eslintrc deleted file mode 100644 index 4c2b11fe817..00000000000 --- a/packages/dapi/lib/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - } -} diff --git a/packages/dapi/package.json b/packages/dapi/package.json index 73e94bd9c2a..cff4a9bd75e 100644 --- a/packages/dapi/package.json +++ b/packages/dapi/package.json @@ -57,15 +57,12 @@ }, "devDependencies": { "@babel/core": "^7.26.10", - "@babel/eslint-parser": "^7.26.10", "@dashevo/dapi-client": "workspace:*", "@dashevo/dp-services-ctl": "github:dashevo/js-dp-services-ctl#v0.19-dev", "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "mocha-sinon": "^2.1.2", "nyc": "^15.1.0", diff --git a/packages/dapi/test/.eslintrc b/packages/dapi/test/.eslintrc deleted file mode 100644 index 9066747d6ca..00000000000 --- a/packages/dapi/test/.eslintrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "env": { - "es2020": true, - "node": true, - "mocha": true - }, - "globals": { - "expect": true - } -} diff --git a/packages/dash-spv/.eslintignore b/packages/dash-spv/.eslintignore deleted file mode 100644 index 5772aab4a64..00000000000 --- a/packages/dash-spv/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -dist/ -.nyc_output/ diff --git a/packages/dash-spv/.eslintrc.json b/packages/dash-spv/.eslintrc.json deleted file mode 100644 index 41aa1d3c147..00000000000 --- a/packages/dash-spv/.eslintrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "airbnb-base", - "env": { - "mocha": true, - "node": true - } - } diff --git a/packages/dash-spv/eslint.config.mjs b/packages/dash-spv/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/dash-spv/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/dash-spv/lib/test/.eslintrc b/packages/dash-spv/lib/test/.eslintrc deleted file mode 100644 index 4c2b11fe817..00000000000 --- a/packages/dash-spv/lib/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - } -} diff --git a/packages/dash-spv/package.json b/packages/dash-spv/package.json index bfd91054213..dd6ff5e18fa 100644 --- a/packages/dash-spv/package.json +++ b/packages/dash-spv/package.json @@ -21,9 +21,7 @@ }, "devDependencies": { "chai": "^4.3.10", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "should": "^13.2.3", "sinon": "^17.0.1" diff --git a/packages/dashmate/.eslintrc b/packages/dashmate/.eslintrc deleted file mode 100644 index 117a1399511..00000000000 --- a/packages/dashmate/.eslintrc +++ /dev/null @@ -1,43 +0,0 @@ -{ - "extends": "airbnb-base", - "parserOptions": { - // Required for certain syntax usages - "ecmaVersion": 2022, - "requireConfigFile": false - }, - "parser": "@babel/eslint-parser", - "env": { - "node": true - }, - "rules": { - "import/extensions": [ - "error", - { - "js": "ignorePackages" - } - ], - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "no-continue": "off", - "class-methods-use-this": "off", - "no-await-in-loop": "off", - "no-restricted-syntax": [ - "error", - { - "selector": "LabeledStatement", - "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand." - }, - { - "selector": "WithStatement", - "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." - } - ], - "curly": [ - "error", - "all" - ] - } -} diff --git a/packages/dashmate/eslint.config.mjs b/packages/dashmate/eslint.config.mjs new file mode 100644 index 00000000000..4ac2c26e3b4 --- /dev/null +++ b/packages/dashmate/eslint.config.mjs @@ -0,0 +1,17 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + { + files: ['**/*.js'], + rules: { + // Require .js extension for imports (ESM) + 'import-x/extensions': ['error', 'ignorePackages', { js: 'always' }], + }, + }, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/dashmate/package.json b/packages/dashmate/package.json index bd77ad51abb..14e3da1bf86 100644 --- a/packages/dashmate/package.json +++ b/packages/dashmate/package.json @@ -93,18 +93,15 @@ "semver": "^7.5.3", "systeminformation": "^5.27.14", "table": "^6.8.1", - "tar": "7.5.4", + "tar": "7.5.7", "wrap-ansi": "^7.0.0" }, "devDependencies": { "@babel/core": "^7.26.10", - "@babel/eslint-parser": "^7.26.10", "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "globby": "^11", "mocha": "^11.1.0", "mocha-sinon": "^2.1.2", diff --git a/packages/dashmate/src/commands/setup.js b/packages/dashmate/src/commands/setup.js index f9e1465a226..f3ca8217c83 100644 --- a/packages/dashmate/src/commands/setup.js +++ b/packages/dashmate/src/commands/setup.js @@ -141,7 +141,7 @@ export default class SetupCommand extends BaseCommand { ); if (!isVerbose) { // TODO: We need to print it only with default renderer - // eslint-disable-next-line import/extensions + // eslint-disable-next-line import-x/extensions const { begoo } = await import('begoo/index.js'); // don't remove index! const welcomeText = begoo( diff --git a/packages/dashmate/src/status/enums/dockerStatus.js b/packages/dashmate/src/status/enums/dockerStatus.js index 6020d2c2eeb..54cbcb3b655 100644 --- a/packages/dashmate/src/status/enums/dockerStatus.js +++ b/packages/dashmate/src/status/enums/dockerStatus.js @@ -1,4 +1,4 @@ -/* eslint-disable import/prefer-default-export */ +/* eslint-disable import-x/prefer-default-export */ export const DockerStatusEnum = { // all possible Docker statuses created: 'created', diff --git a/packages/dashmate/src/status/enums/masternodeState.js b/packages/dashmate/src/status/enums/masternodeState.js index 6adb52e7997..924558834bc 100644 --- a/packages/dashmate/src/status/enums/masternodeState.js +++ b/packages/dashmate/src/status/enums/masternodeState.js @@ -1,4 +1,4 @@ -/* eslint-disable import/prefer-default-export */ +/* eslint-disable import-x/prefer-default-export */ // according doc https://dashcore.readme.io/docs/core-api-ref-remote-procedure-calls-dash#masternode-status export const MasternodeStateEnum = { WAITING_FOR_PROTX: 'WAITING_FOR_PROTX', diff --git a/packages/dashmate/src/status/enums/masternodeSyncAsset.js b/packages/dashmate/src/status/enums/masternodeSyncAsset.js index eaf0d6a340a..e2c8b4c67cd 100644 --- a/packages/dashmate/src/status/enums/masternodeSyncAsset.js +++ b/packages/dashmate/src/status/enums/masternodeSyncAsset.js @@ -1,4 +1,4 @@ -/* eslint-disable import/prefer-default-export */ +/* eslint-disable import-x/prefer-default-export */ // according doc https://dashcore.readme.io/docs/core-api-ref-remote-procedure-calls-dash#mnsync export const MasternodeSyncAssetEnum = { MASTERNODE_SYNC_INITIAL: 'MASTERNODE_SYNC_INITIAL', diff --git a/packages/dashmate/src/status/enums/portState.js b/packages/dashmate/src/status/enums/portState.js index cad12a247e9..c67af6795e6 100644 --- a/packages/dashmate/src/status/enums/portState.js +++ b/packages/dashmate/src/status/enums/portState.js @@ -1,4 +1,4 @@ -/* eslint-disable import/prefer-default-export */ +/* eslint-disable import-x/prefer-default-export */ export const PortStateEnum = { OPEN: 'OPEN', CLOSED: 'CLOSED', diff --git a/packages/dashmate/src/status/enums/serviceStatus.js b/packages/dashmate/src/status/enums/serviceStatus.js index 09cb1f1c390..ab979ad3499 100644 --- a/packages/dashmate/src/status/enums/serviceStatus.js +++ b/packages/dashmate/src/status/enums/serviceStatus.js @@ -1,4 +1,4 @@ -/* eslint-disable import/prefer-default-export */ +/* eslint-disable import-x/prefer-default-export */ export const ServiceStatusEnum = { stopped: 'stopped', up: 'up', diff --git a/packages/dashmate/src/test/.eslintrc b/packages/dashmate/src/test/.eslintrc deleted file mode 100644 index cb08c367aa5..00000000000 --- a/packages/dashmate/src/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "globals": { - "expect": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - } -} diff --git a/packages/dashmate/test/.eslintrc b/packages/dashmate/test/.eslintrc deleted file mode 100644 index 5092d807856..00000000000 --- a/packages/dashmate/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "globals": { - "expect": true - } -} diff --git a/packages/dashmate/test/bootstrap.js b/packages/dashmate/test/bootstrap.js index b766e719c99..1488dce8609 100644 --- a/packages/dashmate/test/bootstrap.js +++ b/packages/dashmate/test/bootstrap.js @@ -10,7 +10,7 @@ use(dirtyChai); process.env.NODE_ENV = 'test'; -// eslint-disable-next-line import/prefer-default-export +// eslint-disable-next-line import-x/prefer-default-export export const mochaHooks = { beforeEach() { if (!this.sinon) { diff --git a/packages/dashpay-contract/.eslintrc b/packages/dashpay-contract/.eslintrc deleted file mode 100644 index 00e5bd1251f..00000000000 --- a/packages/dashpay-contract/.eslintrc +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "env": { - "node": true, - "mocha": true - }, - "globals": { - "expect": true, - "BigInt": true - } -} diff --git a/packages/dashpay-contract/eslint.config.mjs b/packages/dashpay-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/dashpay-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/dashpay-contract/lib/test/.eslintrc b/packages/dashpay-contract/lib/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/dashpay-contract/lib/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/dashpay-contract/package.json b/packages/dashpay-contract/package.json index 630f5ebab03..a68f2f5c167 100644 --- a/packages/dashpay-contract/package.json +++ b/packages/dashpay-contract/package.json @@ -28,9 +28,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/dashpay-contract/test/.eslintrc b/packages/dashpay-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/dashpay-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/dpns-contract/.eslintrc b/packages/dpns-contract/.eslintrc deleted file mode 100644 index cb6c7636b60..00000000000 --- a/packages/dpns-contract/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/dpns-contract/eslint.config.mjs b/packages/dpns-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/dpns-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/dpns-contract/package.json b/packages/dpns-contract/package.json index ef7e04ebf62..f750ff48056 100644 --- a/packages/dpns-contract/package.json +++ b/packages/dpns-contract/package.json @@ -34,9 +34,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/dpns-contract/test/.eslintrc b/packages/dpns-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/dpns-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/feature-flags-contract/.eslintrc b/packages/feature-flags-contract/.eslintrc deleted file mode 100644 index cb6c7636b60..00000000000 --- a/packages/feature-flags-contract/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/feature-flags-contract/eslint.config.mjs b/packages/feature-flags-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/feature-flags-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/feature-flags-contract/package.json b/packages/feature-flags-contract/package.json index a23e2072a28..97272535ae8 100644 --- a/packages/feature-flags-contract/package.json +++ b/packages/feature-flags-contract/package.json @@ -35,9 +35,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/feature-flags-contract/test/.eslintrc b/packages/feature-flags-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/feature-flags-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/js-dapi-client/.eslintignore b/packages/js-dapi-client/.eslintignore deleted file mode 100644 index 5772aab4a64..00000000000 --- a/packages/js-dapi-client/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -dist/ -.nyc_output/ diff --git a/packages/js-dapi-client/.eslintrc.yml b/packages/js-dapi-client/.eslintrc.yml deleted file mode 100644 index 5296a3af919..00000000000 --- a/packages/js-dapi-client/.eslintrc.yml +++ /dev/null @@ -1,15 +0,0 @@ -extends: - - airbnb-base - - plugin:jsdoc/recommended -env: - es2020: true -rules: - eol-last: - - error - - always - class-methods-use-this: off - curly: - - error - - all -plugins: - - jsdoc diff --git a/packages/js-dapi-client/eslint.config.mjs b/packages/js-dapi-client/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/js-dapi-client/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/js-dapi-client/lib/test/.eslintrc b/packages/js-dapi-client/lib/test/.eslintrc deleted file mode 100644 index 4c2b11fe817..00000000000 --- a/packages/js-dapi-client/lib/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - } -} diff --git a/packages/js-dapi-client/package.json b/packages/js-dapi-client/package.json index 764a5ef4359..2e47c42595c 100644 --- a/packages/js-dapi-client/package.json +++ b/packages/js-dapi-client/package.json @@ -52,10 +52,7 @@ "core-js": "^3.33.1", "crypto-browserify": "^3.12.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-jsdoc": "^46.9.0", + "eslint": "^9.18.0", "events": "^3.3.0", "karma": "^6.4.3", "karma-chai": "^0.1.0", diff --git a/packages/js-dapi-client/test/.eslintrc b/packages/js-dapi-client/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/js-dapi-client/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/js-dash-sdk/.eslintrc.js b/packages/js-dash-sdk/.eslintrc.js deleted file mode 100644 index a974c430f1b..00000000000 --- a/packages/js-dash-sdk/.eslintrc.js +++ /dev/null @@ -1,95 +0,0 @@ -// A set of rules to easen misuse in the existing codebase -// We should fix these warnigns when possible -const warnRules = { - 'import/prefer-default-export': 'warn', - 'no-param-reassign': 'warn', - 'import/no-cycle': 'warn', - 'import/no-named-default': 'warn', - 'import/no-named-as-default': 'warn', -}; - -// A set of common rules applicable to both JS and TS files -const commonRules = { - 'no-await-in-loop': 'off', -}; - -module.exports = { - extends: [ - 'airbnb-base', - ], - root: true, - env: { - node: true, - mocha: true, - }, - rules: { - ...warnRules, - ...commonRules, - }, - overrides: [ - // TypeScript general rules - { - files: [ - '**/*.ts', - ], - extends: [ - 'airbnb-base', - 'airbnb-typescript/base', - ], - parserOptions: { - project: ['./tsconfig.json'], - }, - rules: { - '@typescript-eslint/return-await': 'warn', - ...warnRules, - ...commonRules, - }, - }, - // TypeScript tests - { - files: [ - 'src/**/*.spec.ts', - 'src/test/**/*.ts', - 'tests/**/*.ts', - ], - rules: { - // Ignore dirty-chai errors - '@typescript-eslint/no-unused-expressions': 0, - // Ignore require('dev-dependency') errors for tests and mocks - 'import/no-extraneous-dependencies': 0, - }, - parserOptions: { - project: ['./tsconfig.mocha.json'], - }, - }, - // Typings tests - { - files: [ - 'test-d/**/*.ts', - ], - parserOptions: { - project: ['./tsconfig.tsd.json'], - }, - }, - // JS tests - { - files: [ - 'src/test/**/*.js', - 'tests/**/*.js', - '*.config.js', - ], - rules: { - // Ignore dirty-chai errors - 'no-unused-expressions': 0, - // Ignore require('dev-dependency') errors for tests and mocks - 'import/no-extraneous-dependencies': 0, - }, - }, - ], - ignorePatterns: [ - // TODO: why do we have d.ts files in typescript project at all? - '*.d.ts', - 'build', - 'dist', - ], -}; diff --git a/packages/js-dash-sdk/eslint.config.mjs b/packages/js-dash-sdk/eslint.config.mjs new file mode 100644 index 00000000000..736481d07a8 --- /dev/null +++ b/packages/js-dash-sdk/eslint.config.mjs @@ -0,0 +1,41 @@ +import baseConfig from '../../eslint/base.mjs'; +import typescriptConfig from '../../eslint/typescript.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +// Rules that need to be fixed - temporarily set to warn +const warnRules = { + 'import-x/prefer-default-export': 'warn', + 'no-param-reassign': 'warn', + 'import-x/no-cycle': 'warn', + 'import-x/no-named-default': 'warn', + 'import-x/no-named-as-default': 'warn', +}; + +export default [ + ...baseConfig, + ...typescriptConfig, + { + files: ['**/*.ts'], + rules: { + ...warnRules, + }, + }, + { + files: ['src/**/*.spec.ts', 'src/test/**/*.ts', 'tests/**/*.ts'], + rules: { + '@typescript-eslint/no-unused-expressions': 'off', + 'import-x/no-extraneous-dependencies': 'off', + }, + }, + { + files: ['src/test/**/*.js', 'tests/**/*.js', '*.config.js', 'karma/**/*.js'], + rules: { + 'no-unused-expressions': 'off', + 'import-x/no-extraneous-dependencies': 'off', + }, + }, + mochaTestConfig, + { + ignores: ['**/*.d.ts', 'test-d/**', 'build/**', 'dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/js-dash-sdk/karma/options.js b/packages/js-dash-sdk/karma/options.js index 2f207b96f19..0a068894e94 100644 --- a/packages/js-dash-sdk/karma/options.js +++ b/packages/js-dash-sdk/karma/options.js @@ -1,4 +1,4 @@ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable import-x/no-extraneous-dependencies */ const webpack = require('webpack'); const dotenvSafe = require('dotenv-safe'); diff --git a/packages/js-dash-sdk/package.json b/packages/js-dash-sdk/package.json index 127e3eaeb8a..2c178bc0ced 100644 --- a/packages/js-dash-sdk/package.json +++ b/packages/js-dash-sdk/package.json @@ -54,14 +54,12 @@ "winston": "^3.2.1" }, "devDependencies": { - "@types/chai": "^4.2.12", + "@types/chai": "^4.3.11", "@types/dirty-chai": "^2.0.2", - "@types/mocha": "^8.0.3", - "@types/node": "^14.6.0", + "@types/mocha": "^10.0.6", + "@types/node": "^20.10.0", "@types/sinon": "^9.0.4", "@types/sinon-chai": "^3.2.4", - "@typescript-eslint/eslint-plugin": "^5.55.0", - "@typescript-eslint/parser": "^5.55.0", "@yarnpkg/pnpify": "^4.0.0-rc.42", "assert": "^2.0.0", "browserify-zlib": "^0.2.0", @@ -72,10 +70,7 @@ "crypto-browserify": "^3.12.1", "dirty-chai": "^2.0.1", "dotenv-safe": "^8.2.0", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-airbnb-typescript": "^17.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "events": "^3.3.0", "https-browserify": "^1.0.0", "karma": "^6.4.3", @@ -101,9 +96,9 @@ "tls": "^0.0.1", "ts-loader": "^9.5.0", "ts-mock-imports": "^1.3.0", - "ts-node": "^10.4.0", + "ts-node": "^10.9.2", "tsd": "^0.28.1", - "typescript": "^3.9.5", + "typescript": "^5.7.3", "url": "^0.11.3", "util": "^0.12.4", "webpack": "^5.94.0", diff --git a/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts b/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts index bc6fa96bd42..ce4d8578ba2 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts @@ -117,7 +117,7 @@ describe('Dash - Client', function suite() { }); expect.fail('should throw an error'); - } catch (e) { + } catch (e: any) { expect(e.message).to.equal('Wallet and Client networks are different'); } }); diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/broadcastStateTransition.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/broadcastStateTransition.ts index 2dce38a116e..9fb3d04e1f3 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Platform/broadcastStateTransition.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/broadcastStateTransition.ts @@ -58,7 +58,7 @@ export default async function broadcastStateTransition( await client.getDAPIClient().platform.broadcastStateTransition(serializedStateTransition); } catch (error) { if (error instanceof ResponseError) { - let cause = error; + let cause: any = error; // Pass DPP consensus error directly to avoid // additional wrappers diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/internal/waitForCoreChainLockedHeight.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/internal/waitForCoreChainLockedHeight.ts index a3ea11f9b14..21c60199540 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/internal/waitForCoreChainLockedHeight.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/internal/waitForCoreChainLockedHeight.ts @@ -15,7 +15,7 @@ export async function waitForCoreChainLockedHeight( let coreChainLockedHeight = 0; - const promise = new Promise((resolve, reject) => { + const promise = new Promise((resolve, reject) => { async function obtainCoreChainLockedHeight() { try { const response = await platform.client.getDAPIClient().platform.getEpochsInfo(0, 1); diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/names/register.spec.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/names/register.spec.ts index a0648c820d2..17404c0fb07 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/names/register.spec.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/names/register.spec.ts @@ -121,7 +121,7 @@ describe('Platform', () => { await register.call(platformMock, 'user.dash', { identity: await generateRandomIdentifier(), }, identityMock); - } catch (e) { + } catch (e: any) { expect(e.message).to.equal('DPNS is required to register a new name.'); } }); diff --git a/packages/js-evo-sdk/.mocharc.yml b/packages/js-evo-sdk/.mocharc.yml index 3acc6b84406..2b17be7661c 100644 --- a/packages/js-evo-sdk/.mocharc.yml +++ b/packages/js-evo-sdk/.mocharc.yml @@ -1,3 +1,5 @@ +node-option: + - import=ts-node/esm require: - tests/bootstrap.cjs recursive: true diff --git a/packages/js-evo-sdk/eslint.config.mjs b/packages/js-evo-sdk/eslint.config.mjs new file mode 100644 index 00000000000..956ba97d631 --- /dev/null +++ b/packages/js-evo-sdk/eslint.config.mjs @@ -0,0 +1,12 @@ +import baseConfig from '../../eslint/base.mjs'; +import typescriptConfig from '../../eslint/typescript.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + ...typescriptConfig, + mochaTestConfig, + { + ignores: ['dist/**', '**/*.d.ts', 'node_modules/**'], + }, +]; diff --git a/packages/js-evo-sdk/package.json b/packages/js-evo-sdk/package.json index c6528c38993..060964427ec 100644 --- a/packages/js-evo-sdk/package.json +++ b/packages/js-evo-sdk/package.json @@ -26,23 +26,22 @@ }, "scripts": { "build": "rm -rf dist && tsc -p tsconfig.json && webpack --config webpack.config.cjs", - "lint": "eslint \"src/**/*.ts\" \"tests/**/*.*js\"", + "lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"", "test": "yarn run test:unit", - "test:unit": "mocha tests/unit/**/*.spec.mjs && karma start ./tests/karma/karma.conf.cjs --single-run" + "test:unit": "mocha --import ts-node/esm --require tests/bootstrap.cjs tests/unit/**/*.spec.ts && karma start ./tests/karma/karma.conf.cjs --single-run" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.55.0", - "@typescript-eslint/parser": "^5.55.0", + "@types/chai": "^4.3.11", + "@types/mocha": "^10.0.6", + "@types/node": "^20.10.0", + "@types/sinon": "^9.0.4", + "@types/sinon-chai": "^3.2.4", "assert": "^2.0.0", "buffer": "^6.0.3", "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-airbnb-typescript": "^17.0.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-jsdoc": "^46.9.0", + "eslint": "^9.18.0", "events": "^3.3.0", "karma": "^6.4.3", "karma-chai": "^0.1.0", @@ -59,7 +58,8 @@ "string_decoder": "^1.3.0", "terser-webpack-plugin": "^5.3.11", "ts-loader": "^9.5.0", - "typescript": "^3.9.5", + "ts-node": "^10.9.2", + "typescript": "^5.7.3", "url": "^0.11.3", "util": "^0.12.4", "webpack": "^5.94.0", diff --git a/packages/js-evo-sdk/src/.eslintrc.cjs b/packages/js-evo-sdk/src/.eslintrc.cjs deleted file mode 100644 index d226e396249..00000000000 --- a/packages/js-evo-sdk/src/.eslintrc.cjs +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: ['../tsconfig.json'], - tsconfigRootDir: __dirname, - }, - env: { - es2020: true, - browser: true, - node: true, - }, - extends: [ - 'airbnb-base', - 'airbnb-typescript/base', - ], - plugins: [ - '@typescript-eslint', - ], - rules: { - 'import/extensions': 'off', - 'import/prefer-default-export': 'off', - 'object-curly-newline': 'off', - 'class-methods-use-this': 'off', - 'max-len': 'off', - 'no-restricted-exports': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/lines-between-class-members': 'off', - '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', ignoreRestSiblings: true }], - }, - ignorePatterns: [ - '*.d.ts', - ], -}; diff --git a/packages/js-evo-sdk/src/identities/facade.ts b/packages/js-evo-sdk/src/identities/facade.ts index 19c5cc39fed..ca99eca5316 100644 --- a/packages/js-evo-sdk/src/identities/facade.ts +++ b/packages/js-evo-sdk/src/identities/facade.ts @@ -33,32 +33,32 @@ export class IdentitiesFacade { return w.getIdentityKeysWithProofInfo(query); } - async nonce(identityId: wasm.IdentifierLike): Promise { + async nonce(identityId: wasm.IdentifierLike): Promise { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityNonce(identityId); } - async nonceWithProof(identityId: wasm.IdentifierLike): Promise> { + async nonceWithProof(identityId: wasm.IdentifierLike): Promise> { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityNonceWithProofInfo(identityId); } - async contractNonce(identityId: wasm.IdentifierLike, contractId: wasm.IdentifierLike): Promise { + async contractNonce(identityId: wasm.IdentifierLike, contractId: wasm.IdentifierLike): Promise { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityContractNonce(identityId, contractId); } - async contractNonceWithProof(identityId: wasm.IdentifierLike, contractId: wasm.IdentifierLike): Promise> { + async contractNonceWithProof(identityId: wasm.IdentifierLike, contractId: wasm.IdentifierLike): Promise> { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityContractNonceWithProofInfo(identityId, contractId); } - async balance(identityId: wasm.IdentifierLike): Promise { + async balance(identityId: wasm.IdentifierLike): Promise { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityBalance(identityId); } - async balanceWithProof(identityId: wasm.IdentifierLike): Promise> { + async balanceWithProof(identityId: wasm.IdentifierLike): Promise> { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityBalanceWithProofInfo(identityId); } @@ -73,22 +73,22 @@ export class IdentitiesFacade { return w.getIdentitiesBalancesWithProofInfo(identityIds); } - async balanceAndRevision(identityId: wasm.IdentifierLike): Promise { + async balanceAndRevision(identityId: wasm.IdentifierLike): Promise { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityBalanceAndRevision(identityId); } - async balanceAndRevisionWithProof(identityId: wasm.IdentifierLike): Promise> { + async balanceAndRevisionWithProof(identityId: wasm.IdentifierLike): Promise> { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityBalanceAndRevisionWithProofInfo(identityId); } - async byPublicKeyHash(publicKeyHash: string | Uint8Array): Promise { + async byPublicKeyHash(publicKeyHash: string | Uint8Array): Promise { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityByPublicKeyHash(publicKeyHash); } - async byPublicKeyHashWithProof(publicKeyHash: string | Uint8Array): Promise> { + async byPublicKeyHashWithProof(publicKeyHash: string | Uint8Array): Promise> { const w = await this.sdk.getWasmSdkConnected(); return w.getIdentityByPublicKeyHashWithProofInfo(publicKeyHash); } diff --git a/packages/js-evo-sdk/tests/.eslintrc.yml b/packages/js-evo-sdk/tests/.eslintrc.yml deleted file mode 100644 index 06d2a93e05a..00000000000 --- a/packages/js-evo-sdk/tests/.eslintrc.yml +++ /dev/null @@ -1,28 +0,0 @@ -extends: - - airbnb-base - - plugin:jsdoc/recommended -env: - es2022: true - node: true - mocha: true -parserOptions: - ecmaVersion: 2022 - sourceType: module -rules: - eol-last: - - error - - always - import/extensions: off - class-methods-use-this: off - import/no-extraneous-dependencies: off - curly: - - error - - all - no-restricted-syntax: - - error - - selector: "LabeledStatement" - message: Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand. - - selector: "WithStatement" - message: "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." -globals: - expect: true diff --git a/packages/js-evo-sdk/tests/karma/karma.conf.cjs b/packages/js-evo-sdk/tests/karma/karma.conf.cjs index 98bceeb9526..b8ca6eeed24 100644 --- a/packages/js-evo-sdk/tests/karma/karma.conf.cjs +++ b/packages/js-evo-sdk/tests/karma/karma.conf.cjs @@ -6,11 +6,11 @@ module.exports = (config) => { files: [ // Load bootstrap first to initialize chai and globals '../bootstrap.cjs', - '../unit/**/*.spec.mjs', + '../unit/**/*.spec.ts', ], preprocessors: { '../bootstrap.cjs': ['webpack'], - '../unit/**/*.spec.mjs': ['webpack'], + '../unit/**/*.spec.ts': ['webpack'], }, }); }; diff --git a/packages/js-evo-sdk/tests/karma/karma.functional.conf.cjs b/packages/js-evo-sdk/tests/karma/karma.functional.conf.cjs index 39ac2e46ab8..60a68e924ed 100644 --- a/packages/js-evo-sdk/tests/karma/karma.functional.conf.cjs +++ b/packages/js-evo-sdk/tests/karma/karma.functional.conf.cjs @@ -6,11 +6,11 @@ module.exports = (config) => { files: [ // Load bootstrap first to initialize chai and globals '../bootstrap.cjs', - '../functional/**/*.spec.mjs', + '../functional/**/*.spec.ts', ], preprocessors: { '../bootstrap.cjs': ['webpack'], - '../functional/**/*.spec.mjs': ['webpack'], + '../functional/**/*.spec.ts': ['webpack'], }, }); }; diff --git a/packages/js-evo-sdk/tests/karma/options.cjs b/packages/js-evo-sdk/tests/karma/options.cjs index ed64161c77c..74ab6125c6a 100644 --- a/packages/js-evo-sdk/tests/karma/options.cjs +++ b/packages/js-evo-sdk/tests/karma/options.cjs @@ -1,4 +1,4 @@ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable import-x/no-extraneous-dependencies */ const webpack = require('webpack'); const karmaMocha = require('karma-mocha'); const karmaMochaReporter = require('karma-mocha-reporter'); diff --git a/packages/js-evo-sdk/tests/tsconfig.json b/packages/js-evo-sdk/tests/tsconfig.json new file mode 100644 index 00000000000..22956d16664 --- /dev/null +++ b/packages/js-evo-sdk/tests/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "target": "ES2020", + "module": "esnext", + "moduleResolution": "node", + "declaration": false, + "strict": false, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true, + "rootDir": ".", + "baseUrl": ".", + "paths": { + "@dashevo/wasm-sdk/compressed": ["../../wasm-sdk/dist/sdk.d.ts"], + "@dashevo/wasm-sdk": ["../../wasm-sdk/dist/sdk.d.ts"], + "@dashevo/wasm-sdk/*": ["../../wasm-sdk/dist/*"] + } + }, + "include": ["./**/*.ts"], + "exclude": ["node_modules", "karma"] +} diff --git a/packages/js-evo-sdk/tests/unit/facades/addresses.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/addresses.spec.mjs deleted file mode 100644 index eabe639de2f..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/addresses.spec.mjs +++ /dev/null @@ -1,264 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('AddressesFacade', () => { - let wasmSdk; - let client; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - this.sinon.stub(wasmSdk, 'getAddressInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getAddressInfoWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getAddressesInfos').resolves('ok'); - this.sinon.stub(wasmSdk, 'getAddressesInfosWithProofInfo').resolves('ok'); - // Create a mock PlatformAddress for test results - const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), - ); - this.sinon.stub(wasmSdk, 'addressFundsTransfer').resolves({ - type: 'VerifiedAddressInfos', - addressInfos: [{ address: mockAddress, nonce: 1, balance: '90000' }], - }); - }); - - it('get() forwards address to getAddressInfo', async () => { - const address = 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4'; - await client.addresses.get(address); - expect(wasmSdk.getAddressInfo).to.be.calledOnceWithExactly(address); - }); - - it('getWithProof() forwards address to getAddressInfoWithProofInfo', async () => { - const address = 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4'; - await client.addresses.getWithProof(address); - expect(wasmSdk.getAddressInfoWithProofInfo).to.be.calledOnceWithExactly(address); - }); - - it('getMany() forwards array of addresses to getAddressesInfos', async () => { - const addresses = [ - 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4', - 'tevo1abc123def456ghi789jkl012mno345pqr678st', - ]; - await client.addresses.getMany(addresses); - expect(wasmSdk.getAddressesInfos).to.be.calledOnceWithExactly(addresses); - }); - - it('getManyWithProof() forwards array of addresses to getAddressesInfosWithProofInfo', async () => { - const addresses = [ - 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4', - ]; - await client.addresses.getManyWithProof(addresses); - expect(wasmSdk.getAddressesInfosWithProofInfo).to.be.calledOnceWithExactly(addresses); - }); - - it('get() accepts Uint8Array address', async () => { - const addressBytes = new Uint8Array(21); - await client.addresses.get(addressBytes); - expect(wasmSdk.getAddressInfo).to.be.calledOnceWithExactly(addressBytes); - }); - - it('getMany() accepts mixed address formats', async () => { - const bech32Address = 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4'; - const bytesAddress = new Uint8Array(21); - const mixedAddresses = [bech32Address, bytesAddress]; - await client.addresses.getMany(mixedAddresses); - expect(wasmSdk.getAddressesInfos).to.be.calledOnceWithExactly(mixedAddresses); - }); - - it('transfer() forwards options to addressFundsTransfer with PlatformAddressSigner', async () => { - // Create proper PlatformAddress objects - const recipientAddr = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), - ); - - // Create a PrivateKey object from bytes (32 bytes for testnet) - const privateKeyBytes = new Uint8Array(32).fill(1); // Test key bytes - const privateKey = wasmSDKPackage.PrivateKey.fromBytes(privateKeyBytes, 'testnet'); - - // Create signer and derive the sender address from the private key - const signer = new wasmSDKPackage.PlatformAddressSigner(); - const derivedSenderAddr = signer.addKey(privateKey); - - // Create typed input and output objects (address, nonce, amount) - const input = new wasmSDKPackage.PlatformAddressInput(derivedSenderAddr, 0, 100000n); - const output = new wasmSDKPackage.PlatformAddressOutput(recipientAddr, 90000n); - - const options = { - inputs: [input], - outputs: [output], - signer, - }; - const result = await client.addresses.transfer(options); - expect(wasmSdk.addressFundsTransfer).to.be.calledOnce(); - expect(result.type).to.equal('VerifiedAddressInfos'); - expect(result.addressInfos).to.have.lengthOf(1); - expect(result.addressInfos[0].address.addressType).to.equal('P2PKH'); - }); - - it('transfer() handles success result type', async () => { - wasmSdk.addressFundsTransfer.resolves({ - type: 'Success', - message: 'Address funds transfer completed successfully', - }); - - // Create proper PlatformAddress objects - const recipientAddr = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), - ); - - // Create a PrivateKey object from bytes - const privateKeyBytes = new Uint8Array(32).fill(1); // Test key bytes - const privateKey = wasmSDKPackage.PrivateKey.fromBytes(privateKeyBytes, 'testnet'); - - // Create signer and derive the sender address from the private key - const signer = new wasmSDKPackage.PlatformAddressSigner(); - const derivedSenderAddr = signer.addKey(privateKey); - - // Create typed input and output objects (address, nonce, amount) - const input = new wasmSDKPackage.PlatformAddressInput(derivedSenderAddr, 0, 100000n); - const output = new wasmSDKPackage.PlatformAddressOutput(recipientAddr, 90000n); - - const options = { - inputs: [input], - outputs: [output], - signer, - }; - const result = await client.addresses.transfer(options); - expect(result.type).to.equal('Success'); - expect(result.message).to.include('successfully'); - }); - - it('topUpIdentity() forwards options to identityTopUpFromAddresses', async function topUpTest() { - // Create mock address and result - const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), - ); - - this.sinon.stub(wasmSdk, 'identityTopUpFromAddresses').resolves({ - addressInfos: new Map([[mockAddress, { address: mockAddress, nonce: 1n, balance: 50000n }]]), - newBalance: 150000n, - }); - - // Create a mock identity ID (32 bytes) - const identityId = wasmSDKPackage.Identifier.fromBytes(new Uint8Array(32).fill(42)); - - // Mock options - the actual implementation will process these - const options = { - identityId, - inputs: [], - signer: {}, - }; - - const result = await client.addresses.topUpIdentity(options); - expect(wasmSdk.identityTopUpFromAddresses).to.be.calledOnce(); - expect(result.newBalance).to.equal(150000n); - }); - - it('withdraw() forwards options to addressFundsWithdraw', async function withdrawTest() { - // Create mock address and result map - const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), - ); - - const resultMap = new Map(); - resultMap.set(mockAddress, { address: mockAddress, nonce: 1n, balance: 0n }); - - this.sinon.stub(wasmSdk, 'addressFundsWithdraw').resolves(resultMap); - - // Create Core output script (P2PKH) - const coreScript = wasmSDKPackage.CoreScript.newP2PKH(new Uint8Array(20).fill(5)); - - // Mock options - the actual implementation will process these - const options = { - inputs: [], - coreFeePerByte: 1, - pooling: wasmSDKPackage.PoolingWasm.Standard, - outputScript: coreScript, - signer: {}, - }; - - const result = await client.addresses.withdraw(options); - expect(wasmSdk.addressFundsWithdraw).to.be.calledOnce(); - expect(result).to.be.instanceOf(Map); - }); - - it('transferFromIdentity() forwards options to identityTransferToAddresses', async function transferFromIdentityTest() { - // Create mock address - const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), - ); - - this.sinon.stub(wasmSdk, 'identityTransferToAddresses').resolves({ - addressInfos: new Map([[mockAddress, { address: mockAddress, nonce: 0n, balance: 100000n }]]), - newBalance: 400000n, - }); - - // Create a mock identity ID - const identityId = wasmSDKPackage.Identifier.fromBytes(new Uint8Array(32).fill(42)); - - // Mock options - the actual implementation will process these - const options = { - identityId, - outputs: [], - signer: {}, - }; - - const result = await client.addresses.transferFromIdentity(options); - expect(wasmSdk.identityTransferToAddresses).to.be.calledOnce(); - expect(result.newBalance).to.equal(400000n); - }); - - it('fundFromAssetLock() forwards options to addressFundingFromAssetLock', async function fundFromAssetLockTest() { - // Create mock address and result map - const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), - ); - - const resultMap = new Map(); - resultMap.set(mockAddress, { address: mockAddress, nonce: 0n, balance: 100000n }); - - this.sinon.stub(wasmSdk, 'addressFundingFromAssetLock').resolves(resultMap); - - // Mock options - the actual implementation will process these - const options = { - assetLockProof: {}, - assetLockPrivateKey: {}, - outputs: [], - signer: {}, - }; - - const result = await client.addresses.fundFromAssetLock(options); - expect(wasmSdk.addressFundingFromAssetLock).to.be.calledOnce(); - expect(result).to.be.instanceOf(Map); - }); - - it('createIdentity() forwards options to identityCreateFromAddresses', async function createIdentityTest() { - // Create mock address - const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( - new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), - ); - - // Create mock identity ID - const mockIdentityId = wasmSDKPackage.Identifier.fromBytes(new Uint8Array(32).fill(99)); - - this.sinon.stub(wasmSdk, 'identityCreateFromAddresses').resolves({ - identity: { id: () => mockIdentityId }, - addressInfos: new Map([[mockAddress, { address: mockAddress, nonce: 1n, balance: 0n }]]), - }); - - // Mock options - the actual implementation will process these - const options = { - identity: {}, - inputs: [], - identitySigner: {}, - addressSigner: {}, - }; - - const result = await client.addresses.createIdentity(options); - expect(wasmSdk.identityCreateFromAddresses).to.be.calledOnce(); - expect(result.identity).to.exist(); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/addresses.spec.ts b/packages/js-evo-sdk/tests/unit/facades/addresses.spec.ts new file mode 100644 index 00000000000..8dedc931098 --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/addresses.spec.ts @@ -0,0 +1,289 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('AddressesFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + + // Stub references for type-safe assertions + let getAddressInfoStub: SinonStub; + let getAddressInfoWithProofInfoStub: SinonStub; + let getAddressesInfosStub: SinonStub; + let getAddressesInfosWithProofInfoStub: SinonStub; + let addressFundsTransferStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + getAddressInfoStub = this.sinon.stub(wasmSdk, 'getAddressInfo').resolves('ok'); + getAddressInfoWithProofInfoStub = this.sinon.stub(wasmSdk, 'getAddressInfoWithProofInfo').resolves('ok'); + getAddressesInfosStub = this.sinon.stub(wasmSdk, 'getAddressesInfos').resolves('ok'); + getAddressesInfosWithProofInfoStub = this.sinon.stub(wasmSdk, 'getAddressesInfosWithProofInfo').resolves('ok'); + // Create a mock PlatformAddress for test results + const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), + ); + addressFundsTransferStub = this.sinon.stub(wasmSdk, 'addressFundsTransfer').resolves({ + type: 'VerifiedAddressInfos', + addressInfos: [{ address: mockAddress, nonce: 1, balance: '90000' }], + }); + }); + + describe('get()', () => { + it('should forward string address to getAddressInfo', async () => { + const address = 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4'; + await client.addresses.get(address); + expect(getAddressInfoStub).to.be.calledOnceWithExactly(address); + }); + + it('should accept Uint8Array address', async () => { + const addressBytes = new Uint8Array(21); + await client.addresses.get(addressBytes); + expect(getAddressInfoStub).to.be.calledOnceWithExactly(addressBytes); + }); + }); + + describe('getWithProof()', () => { + it('should forward address to getAddressInfoWithProofInfo', async () => { + const address = 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4'; + await client.addresses.getWithProof(address); + expect(getAddressInfoWithProofInfoStub).to.be.calledOnceWithExactly(address); + }); + }); + + describe('getMany()', () => { + it('should forward array of addresses to getAddressesInfos', async () => { + const addresses = [ + 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4', + 'tevo1abc123def456ghi789jkl012mno345pqr678st', + ]; + await client.addresses.getMany(addresses); + expect(getAddressesInfosStub).to.be.calledOnceWithExactly(addresses); + }); + + it('should accept mixed address formats', async () => { + const bech32Address = 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4'; + const bytesAddress = new Uint8Array(21); + const mixedAddresses = [bech32Address, bytesAddress]; + await client.addresses.getMany(mixedAddresses); + expect(getAddressesInfosStub).to.be.calledOnceWithExactly(mixedAddresses); + }); + }); + + describe('getManyWithProof()', () => { + it('should forward array of addresses to getAddressesInfosWithProofInfo', async () => { + const addresses = [ + 'tevo1qr4nl2m5z7v7g7d2c4z6k8x9w3y2f5p6h0s1t4', + ]; + await client.addresses.getManyWithProof(addresses); + expect(getAddressesInfosWithProofInfoStub).to.be.calledOnceWithExactly(addresses); + }); + }); + + describe('transfer()', () => { + it('should forward options to addressFundsTransfer with PlatformAddressSigner', async () => { + // Create proper PlatformAddress objects + const recipientAddr = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), + ); + + // Create a PrivateKey object from bytes (32 bytes for testnet) + const privateKeyBytes = new Uint8Array(32).fill(1); // Test key bytes + const privateKey = wasmSDKPackage.PrivateKey.fromBytes(privateKeyBytes, 'testnet'); + + // Create signer and derive the sender address from the private key + const signer = new wasmSDKPackage.PlatformAddressSigner(); + const derivedSenderAddr = signer.addKey(privateKey); + + // Create typed input and output objects (address, nonce, amount) + const input = new wasmSDKPackage.PlatformAddressInput(derivedSenderAddr, 0, 100000n); + const output = new wasmSDKPackage.PlatformAddressOutput(recipientAddr, 90000n); + + const options = { + inputs: [input], + outputs: [output], + signer, + }; + const result = await client.addresses.transfer(options); + expect(addressFundsTransferStub).to.be.calledOnce(); + expect(result.type).to.equal('VerifiedAddressInfos'); + expect(result.addressInfos).to.have.lengthOf(1); + expect(result.addressInfos[0].address.addressType).to.equal('P2PKH'); + }); + + it('should handle success result type', async () => { + addressFundsTransferStub.resolves({ + type: 'Success', + message: 'Address funds transfer completed successfully', + }); + + // Create proper PlatformAddress objects + const recipientAddr = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), + ); + + // Create a PrivateKey object from bytes + const privateKeyBytes = new Uint8Array(32).fill(1); // Test key bytes + const privateKey = wasmSDKPackage.PrivateKey.fromBytes(privateKeyBytes, 'testnet'); + + // Create signer and derive the sender address from the private key + const signer = new wasmSDKPackage.PlatformAddressSigner(); + const derivedSenderAddr = signer.addKey(privateKey); + + // Create typed input and output objects (address, nonce, amount) + const input = new wasmSDKPackage.PlatformAddressInput(derivedSenderAddr, 0, 100000n); + const output = new wasmSDKPackage.PlatformAddressOutput(recipientAddr, 90000n); + + const options = { + inputs: [input], + outputs: [output], + signer, + }; + const result = await client.addresses.transfer(options); + expect(result.type).to.equal('Success'); + expect(result.message).to.include('successfully'); + }); + }); + + describe('topUpIdentity()', () => { + it('should forward options to identityTopUpFromAddresses', async function topUpTest() { + // Create mock address and result + const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), + ); + + const identityTopUpFromAddressesStub: SinonStub = this.sinon.stub(wasmSdk, 'identityTopUpFromAddresses').resolves({ + addressInfos: new Map([[mockAddress, { address: mockAddress, nonce: 1n, balance: 50000n }]]), + newBalance: 150000n, + }); + + // Create a mock identity ID (32 bytes) + const identityId = wasmSDKPackage.Identifier.fromBytes(new Uint8Array(32).fill(42)); + + // Mock options - the actual implementation will process these + const options = { + identityId, + inputs: [], + signer: {}, + }; + + const result = await client.addresses.topUpIdentity(options); + expect(identityTopUpFromAddressesStub).to.be.calledOnce(); + expect(result.newBalance).to.equal(150000n); + }); + }); + + describe('withdraw()', () => { + it('should forward options to addressFundsWithdraw', async function withdrawTest() { + // Create mock address and result map + const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), + ); + + const resultMap = new Map(); + resultMap.set(mockAddress, { address: mockAddress, nonce: 1n, balance: 0n }); + + const addressFundsWithdrawStub: SinonStub = this.sinon.stub(wasmSdk, 'addressFundsWithdraw').resolves(resultMap); + + // Mock options - the actual implementation will process these + const options = { + inputs: [], + coreFeePerByte: 1, + pooling: wasmSDKPackage.PoolingWasm.Standard, + outputScript: new Uint8Array(25).fill(5), // Mock P2PKH script bytes + signer: {}, + }; + + const result = await client.addresses.withdraw(options); + expect(addressFundsWithdrawStub).to.be.calledOnce(); + expect(result).to.be.instanceOf(Map); + }); + }); + + describe('transferFromIdentity()', () => { + it('should forward options to identityTransferToAddresses', async function transferFromIdentityTest() { + // Create mock address + const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), + ); + + const identityTransferToAddressesStub: SinonStub = this.sinon.stub(wasmSdk, 'identityTransferToAddresses').resolves({ + addressInfos: new Map([[mockAddress, { address: mockAddress, nonce: 0n, balance: 100000n }]]), + newBalance: 400000n, + }); + + // Create a mock identity ID + const identityId = wasmSDKPackage.Identifier.fromBytes(new Uint8Array(32).fill(42)); + + // Mock options - the actual implementation will process these + const options = { + identityId, + outputs: [], + signer: {}, + }; + + const result = await client.addresses.transferFromIdentity(options); + expect(identityTransferToAddressesStub).to.be.calledOnce(); + expect(result.newBalance).to.equal(400000n); + }); + }); + + describe('fundFromAssetLock()', () => { + it('should forward options to addressFundingFromAssetLock', async function fundFromAssetLockTest() { + // Create mock address and result map + const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), + ); + + const resultMap = new Map(); + resultMap.set(mockAddress, { address: mockAddress, nonce: 0n, balance: 100000n }); + + const addressFundingFromAssetLockStub: SinonStub = this.sinon.stub(wasmSdk, 'addressFundingFromAssetLock').resolves(resultMap); + + // Mock options - the actual implementation will process these + const options = { + assetLockProof: {}, + assetLockPrivateKey: {}, + outputs: [], + signer: {}, + }; + + const result = await client.addresses.fundFromAssetLock(options); + expect(addressFundingFromAssetLockStub).to.be.calledOnce(); + expect(result).to.be.instanceOf(Map); + }); + }); + + describe('createIdentity()', () => { + it('should forward options to identityCreateFromAddresses', async function createIdentityTest() { + // Create mock address + const mockAddress = wasmSDKPackage.PlatformAddress.fromBytes( + new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]), + ); + + // Create mock identity ID + const mockIdentityId = wasmSDKPackage.Identifier.fromBytes(new Uint8Array(32).fill(99)); + + const identityCreateFromAddressesStub: SinonStub = this.sinon.stub(wasmSdk, 'identityCreateFromAddresses').resolves({ + identity: { id: () => mockIdentityId }, + addressInfos: new Map([[mockAddress, { address: mockAddress, nonce: 1n, balance: 0n }]]), + }); + + // Mock options - the actual implementation will process these + const options = { + identity: {}, + inputs: [], + identitySigner: {}, + addressSigner: {}, + }; + + const result = await client.addresses.createIdentity(options); + expect(identityCreateFromAddressesStub).to.be.calledOnce(); + expect(result.identity).to.exist(); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/contracts.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/contracts.spec.mjs deleted file mode 100644 index 4c8a895383e..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/contracts.spec.mjs +++ /dev/null @@ -1,134 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('ContractsFacade', () => { - let wasmSdk; - let client; - let dataContract; - let identityKey; - let signer; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - // Create mock objects - dataContract = Object.create(wasmSDKPackage.DataContract.prototype); - identityKey = Object.create(wasmSDKPackage.IdentityPublicKey.prototype); - signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); - - // Stub query methods - this.sinon.stub(wasmSdk, 'getDataContract').resolves(dataContract); - this.sinon.stub(wasmSdk, 'getDataContractWithProofInfo').resolves({ - data: dataContract, - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getDataContractHistory').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getDataContractHistoryWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getDataContracts').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getDataContractsWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - - // Stub transition methods - this.sinon.stub(wasmSdk, 'contractPublish').resolves(dataContract); - this.sinon.stub(wasmSdk, 'contractUpdate').resolves(); - }); - - describe('Query Methods', () => { - it('fetch() returns a DataContract for valid ID', async () => { - const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; - - const result = await client.contracts.fetch(contractId); - - expect(wasmSdk.getDataContract).to.be.calledOnceWithExactly(contractId); - expect(result).to.be.instanceOf(wasmSDKPackage.DataContract); - }); - - it('fetchWithProof() returns DataContract with proof metadata', async () => { - const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; - - await client.contracts.fetchWithProof(contractId); - - expect(wasmSdk.getDataContractWithProofInfo).to.be.calledOnceWithExactly(contractId); - }); - - it('getHistory() fetches contract version history', async () => { - const query = { - dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', - limit: 10, - startAtMs: 1700000000000, - }; - - await client.contracts.getHistory(query); - - expect(wasmSdk.getDataContractHistory).to.be.calledOnceWithExactly(query); - }); - - it('getHistoryWithProof() fetches contract version history with proof', async () => { - const query = { - dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', - }; - - await client.contracts.getHistoryWithProof(query); - - expect(wasmSdk.getDataContractHistoryWithProofInfo).to.be.calledOnceWithExactly(query); - }); - - it('getMany() fetches multiple contracts by IDs', async () => { - const contractIds = [ - 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', - '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', - ]; - - await client.contracts.getMany(contractIds); - - expect(wasmSdk.getDataContracts).to.be.calledOnceWithExactly(contractIds); - }); - - it('getManyWithProof() fetches multiple contracts with proof', async () => { - const contractIds = ['GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec']; - - await client.contracts.getManyWithProof(contractIds); - - expect(wasmSdk.getDataContractsWithProofInfo).to.be.calledOnceWithExactly(contractIds); - }); - }); - - describe('Transition Methods', () => { - it('publish() publishes a new data contract', async () => { - const options = { - dataContract, - identityKey, - signer, - settings: { retries: 3 }, - }; - - const result = await client.contracts.publish(options); - - expect(wasmSdk.contractPublish).to.be.calledOnceWithExactly(options); - expect(result).to.be.instanceOf(wasmSDKPackage.DataContract); - }); - - it('update() updates an existing data contract', async () => { - const options = { - dataContract, - identityKey, - signer, - }; - - await client.contracts.update(options); - - expect(wasmSdk.contractUpdate).to.be.calledOnceWithExactly(options); - }); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/contracts.spec.ts b/packages/js-evo-sdk/tests/unit/facades/contracts.spec.ts new file mode 100644 index 00000000000..fab1c8f379b --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/contracts.spec.ts @@ -0,0 +1,157 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('ContractsFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + let dataContract: wasmSDKPackage.DataContract; + let identityKey: wasmSDKPackage.IdentityPublicKey; + let signer: wasmSDKPackage.IdentitySigner; + + // Stub references for type-safe assertions + let getDataContractStub: SinonStub; + let getDataContractWithProofInfoStub: SinonStub; + let getDataContractHistoryStub: SinonStub; + let getDataContractHistoryWithProofInfoStub: SinonStub; + let getDataContractsStub: SinonStub; + let getDataContractsWithProofInfoStub: SinonStub; + let contractPublishStub: SinonStub; + let contractUpdateStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + // Create mock objects + dataContract = Object.create(wasmSDKPackage.DataContract.prototype); + identityKey = Object.create(wasmSDKPackage.IdentityPublicKey.prototype); + signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); + + // Stub query methods + getDataContractStub = this.sinon.stub(wasmSdk, 'getDataContract').resolves(dataContract); + getDataContractWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDataContractWithProofInfo').resolves({ + data: dataContract, + proof: {}, + metadata: {}, + }); + getDataContractHistoryStub = this.sinon.stub(wasmSdk, 'getDataContractHistory').resolves(new Map()); + getDataContractHistoryWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDataContractHistoryWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getDataContractsStub = this.sinon.stub(wasmSdk, 'getDataContracts').resolves(new Map()); + getDataContractsWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDataContractsWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + + // Stub transition methods + contractPublishStub = this.sinon.stub(wasmSdk, 'contractPublish').resolves(dataContract); + contractUpdateStub = this.sinon.stub(wasmSdk, 'contractUpdate').resolves(); + }); + + describe('fetch()', () => { + it('should return a DataContract for valid ID', async () => { + const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; + + const result = await client.contracts.fetch(contractId); + + expect(getDataContractStub).to.be.calledOnceWithExactly(contractId); + expect(result).to.be.instanceOf(wasmSDKPackage.DataContract); + }); + }); + + describe('fetchWithProof()', () => { + it('should return DataContract with proof metadata', async () => { + const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; + + await client.contracts.fetchWithProof(contractId); + + expect(getDataContractWithProofInfoStub).to.be.calledOnceWithExactly(contractId); + }); + }); + + describe('getHistory()', () => { + it('should fetch contract version history', async () => { + const query = { + dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + limit: 10, + startAtMs: 1700000000000, + }; + + await client.contracts.getHistory(query); + + expect(getDataContractHistoryStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('getHistoryWithProof()', () => { + it('should fetch contract version history with proof', async () => { + const query = { + dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + }; + + await client.contracts.getHistoryWithProof(query); + + expect(getDataContractHistoryWithProofInfoStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('getMany()', () => { + it('should fetch multiple contracts by IDs', async () => { + const contractIds = [ + 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', + ]; + + await client.contracts.getMany(contractIds); + + expect(getDataContractsStub).to.be.calledOnceWithExactly(contractIds); + }); + }); + + describe('getManyWithProof()', () => { + it('should fetch multiple contracts with proof', async () => { + const contractIds = ['GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec']; + + await client.contracts.getManyWithProof(contractIds); + + expect(getDataContractsWithProofInfoStub).to.be.calledOnceWithExactly(contractIds); + }); + }); + + describe('publish()', () => { + it('should publish a new data contract', async () => { + const options = { + dataContract, + identityKey, + signer, + settings: { retries: 3 }, + }; + + const result = await client.contracts.publish(options); + + expect(contractPublishStub).to.be.calledOnceWithExactly(options); + expect(result).to.be.instanceOf(wasmSDKPackage.DataContract); + }); + }); + + describe('update()', () => { + it('should update an existing data contract', async () => { + const options = { + dataContract, + identityKey, + signer, + }; + + await client.contracts.update(options); + + expect(contractUpdateStub).to.be.calledOnceWithExactly(options); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/documents.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/documents.spec.ts similarity index 51% rename from packages/js-evo-sdk/tests/unit/facades/documents.spec.mjs rename to packages/js-evo-sdk/tests/unit/facades/documents.spec.ts index e5b887e0bf5..57f6728d83e 100644 --- a/packages/js-evo-sdk/tests/unit/facades/documents.spec.mjs +++ b/packages/js-evo-sdk/tests/unit/facades/documents.spec.ts @@ -1,17 +1,30 @@ +import type { SinonStub } from 'sinon'; import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; import { EvoSDK } from '../../../dist/sdk.js'; describe('DocumentsFacade', () => { - let wasmSdk; - let client; - let document; - let identityKey; - let signer; + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + let document: wasmSDKPackage.Document; + let identityKey: wasmSDKPackage.IdentityPublicKey; + let signer: wasmSDKPackage.IdentitySigner; + + // Stub references for type-safe assertions + let getDocumentsStub: SinonStub; + let getDocumentsWithProofInfoStub: SinonStub; + let getDocumentStub: SinonStub; + let getDocumentWithProofInfoStub: SinonStub; + let documentCreateStub: SinonStub; + let documentReplaceStub: SinonStub; + let documentDeleteStub: SinonStub; + let documentTransferStub: SinonStub; + let documentPurchaseStub: SinonStub; + let documentSetPriceStub: SinonStub; beforeEach(async function setup() { await init(); const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); + wasmSdk = await builder.build(); client = EvoSDK.fromWasm(wasmSdk); // Create mock objects @@ -20,30 +33,30 @@ describe('DocumentsFacade', () => { signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); // Stub query methods - this.sinon.stub(wasmSdk, 'getDocuments').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getDocumentsWithProofInfo').resolves({ + getDocumentsStub = this.sinon.stub(wasmSdk, 'getDocuments').resolves(new Map()); + getDocumentsWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDocumentsWithProofInfo').resolves({ data: new Map(), proof: {}, metadata: {}, }); - this.sinon.stub(wasmSdk, 'getDocument').resolves(document); - this.sinon.stub(wasmSdk, 'getDocumentWithProofInfo').resolves({ + getDocumentStub = this.sinon.stub(wasmSdk, 'getDocument').resolves(document); + getDocumentWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDocumentWithProofInfo').resolves({ data: document, proof: {}, metadata: {}, }); // Stub transition methods - this.sinon.stub(wasmSdk, 'documentCreate').resolves(); - this.sinon.stub(wasmSdk, 'documentReplace').resolves(); - this.sinon.stub(wasmSdk, 'documentDelete').resolves(); - this.sinon.stub(wasmSdk, 'documentTransfer').resolves(); - this.sinon.stub(wasmSdk, 'documentPurchase').resolves(); - this.sinon.stub(wasmSdk, 'documentSetPrice').resolves(); + documentCreateStub = this.sinon.stub(wasmSdk, 'documentCreate').resolves(); + documentReplaceStub = this.sinon.stub(wasmSdk, 'documentReplace').resolves(); + documentDeleteStub = this.sinon.stub(wasmSdk, 'documentDelete').resolves(); + documentTransferStub = this.sinon.stub(wasmSdk, 'documentTransfer').resolves(); + documentPurchaseStub = this.sinon.stub(wasmSdk, 'documentPurchase').resolves(); + documentSetPriceStub = this.sinon.stub(wasmSdk, 'documentSetPrice').resolves(); }); - describe('Query Methods', () => { - it('query() fetches documents matching criteria', async () => { + describe('query()', () => { + it('should fetch documents matching criteria', async () => { const query = { dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', documentTypeName: 'note', @@ -54,10 +67,12 @@ describe('DocumentsFacade', () => { await client.documents.query(query); - expect(wasmSdk.getDocuments).to.be.calledOnceWithExactly(query); + expect(getDocumentsStub).to.be.calledOnceWithExactly(query); }); + }); - it('queryWithProof() fetches documents with proof metadata', async () => { + describe('queryWithProof()', () => { + it('should fetch documents with proof metadata', async () => { const query = { dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', documentTypeName: 'note', @@ -65,34 +80,38 @@ describe('DocumentsFacade', () => { await client.documents.queryWithProof(query); - expect(wasmSdk.getDocumentsWithProofInfo).to.be.calledOnceWithExactly(query); + expect(getDocumentsWithProofInfoStub).to.be.calledOnceWithExactly(query); }); + }); - it('get() fetches a single document by ID', async () => { + describe('get()', () => { + it('should fetch a single document by ID', async () => { const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; const documentTypeName = 'note'; const documentId = '4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah'; await client.documents.get(contractId, documentTypeName, documentId); - expect(wasmSdk.getDocument) + expect(getDocumentStub) .to.be.calledOnceWithExactly(contractId, documentTypeName, documentId); }); + }); - it('getWithProof() fetches a single document with proof', async () => { + describe('getWithProof()', () => { + it('should fetch a single document with proof', async () => { const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; const documentTypeName = 'note'; const documentId = '4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah'; await client.documents.getWithProof(contractId, documentTypeName, documentId); - expect(wasmSdk.getDocumentWithProofInfo) + expect(getDocumentWithProofInfoStub) .to.be.calledOnceWithExactly(contractId, documentTypeName, documentId); }); }); - describe('Transition Methods', () => { - it('create() creates a new document', async () => { + describe('create()', () => { + it('should create a new document', async () => { const options = { document, identityKey, @@ -101,10 +120,12 @@ describe('DocumentsFacade', () => { await client.documents.create(options); - expect(wasmSdk.documentCreate).to.be.calledOnceWithExactly(options); + expect(documentCreateStub).to.be.calledOnceWithExactly(options); }); + }); - it('replace() replaces an existing document', async () => { + describe('replace()', () => { + it('should replace an existing document', async () => { const options = { document, identityKey, @@ -114,10 +135,12 @@ describe('DocumentsFacade', () => { await client.documents.replace(options); - expect(wasmSdk.documentReplace).to.be.calledOnceWithExactly(options); + expect(documentReplaceStub).to.be.calledOnceWithExactly(options); }); + }); - it('delete() deletes a document', async () => { + describe('delete()', () => { + it('should delete a document', async () => { const options = { document, identityKey, @@ -126,10 +149,10 @@ describe('DocumentsFacade', () => { await client.documents.delete(options); - expect(wasmSdk.documentDelete).to.be.calledOnceWithExactly(options); + expect(documentDeleteStub).to.be.calledOnceWithExactly(options); }); - it('delete() accepts document identifiers instead of Document instance', async () => { + it('should accept document identifiers instead of Document instance', async () => { const options = { document: { id: '4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah', @@ -143,10 +166,12 @@ describe('DocumentsFacade', () => { await client.documents.delete(options); - expect(wasmSdk.documentDelete).to.be.calledOnceWithExactly(options); + expect(documentDeleteStub).to.be.calledOnceWithExactly(options); }); + }); - it('transfer() transfers document ownership to another identity', async () => { + describe('transfer()', () => { + it('should transfer document ownership to another identity', async () => { const recipientId = '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack'; const options = { document, @@ -157,10 +182,12 @@ describe('DocumentsFacade', () => { await client.documents.transfer(options); - expect(wasmSdk.documentTransfer).to.be.calledOnceWithExactly(options); + expect(documentTransferStub).to.be.calledOnceWithExactly(options); }); + }); - it('purchase() purchases a document from another identity', async () => { + describe('purchase()', () => { + it('should purchase a document from another identity', async () => { const buyerId = '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack'; const options = { document, @@ -172,10 +199,12 @@ describe('DocumentsFacade', () => { await client.documents.purchase(options); - expect(wasmSdk.documentPurchase).to.be.calledOnceWithExactly(options); + expect(documentPurchaseStub).to.be.calledOnceWithExactly(options); }); + }); - it('setPrice() sets a price on a document for sale', async () => { + describe('setPrice()', () => { + it('should set a price on a document for sale', async () => { const options = { document, price: BigInt(5000000), // 5M credits @@ -185,7 +214,7 @@ describe('DocumentsFacade', () => { await client.documents.setPrice(options); - expect(wasmSdk.documentSetPrice).to.be.calledOnceWithExactly(options); + expect(documentSetPriceStub).to.be.calledOnceWithExactly(options); }); }); }); diff --git a/packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs deleted file mode 100644 index 5c6db60af16..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs +++ /dev/null @@ -1,65 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('DPNSFacade', () => { - let wasmSdk; - let client; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - this.sinon.stub(wasmSdk, 'dpnsIsNameAvailable').resolves(true); - this.sinon.stub(wasmSdk, 'dpnsResolveName').resolves({}); - this.sinon.stub(wasmSdk, 'dpnsRegisterName').resolves({}); - this.sinon.stub(wasmSdk, 'getDpnsUsernames').resolves([]); - this.sinon.stub(wasmSdk, 'getDpnsUsername').resolves({}); - this.sinon.stub(wasmSdk, 'getDpnsUsernamesWithProofInfo').resolves({}); - this.sinon.stub(wasmSdk, 'getDpnsUsernameWithProofInfo').resolves({}); - this.sinon.stub(wasmSdk, 'getDpnsUsernameByName').resolves({}); - this.sinon.stub(wasmSdk, 'getDpnsUsernameByNameWithProofInfo').resolves({}); - }); - - it('convertToHomographSafe/isValidUsername/isContestedUsername await wasm statics', async () => { - const out1 = await client.dpns.convertToHomographSafe('abc'); - const out2 = await client.dpns.isValidUsername('abc'); - const out3 = await client.dpns.isContestedUsername('abc'); - expect(out1).to.be.ok(); - expect(out2).to.be.a('boolean'); - expect(out3).to.be.a('boolean'); - }); - - it('name resolution and registration forward correctly', async () => { - await client.dpns.isNameAvailable('label'); - await client.dpns.resolveName('name'); - - // New API uses identity, identityKey, signer instead of identityId/publicKeyId/privateKeyWif - const mockIdentity = {}; - const mockIdentityKey = {}; - const mockSigner = {}; - await client.dpns.registerName({ - label: 'l', - identity: mockIdentity, - identityKey: mockIdentityKey, - signer: mockSigner, - }); - await client.dpns.usernames({ identityId: 'i', limit: 2 }); - await client.dpns.username('i'); - await client.dpns.usernamesWithProof({ identityId: 'i', limit: 3 }); - await client.dpns.usernameWithProof('i'); - await client.dpns.getUsernameByName('u.dash'); - await client.dpns.getUsernameByNameWithProof('u.dash'); - - expect(wasmSdk.dpnsIsNameAvailable).to.be.calledOnceWithExactly('label'); - expect(wasmSdk.dpnsResolveName).to.be.calledOnceWithExactly('name'); - expect(wasmSdk.dpnsRegisterName).to.be.calledOnce(); - expect(wasmSdk.getDpnsUsernames).to.be.calledOnceWithExactly({ identityId: 'i', limit: 2 }); - expect(wasmSdk.getDpnsUsername).to.be.calledOnceWithExactly('i'); - expect(wasmSdk.getDpnsUsernamesWithProofInfo).to.be.calledOnceWithExactly({ identityId: 'i', limit: 3 }); - expect(wasmSdk.getDpnsUsernameWithProofInfo).to.be.calledOnceWithExactly('i'); - expect(wasmSdk.getDpnsUsernameByName).to.be.calledOnceWithExactly('u.dash'); - expect(wasmSdk.getDpnsUsernameByNameWithProofInfo).to.be.calledOnceWithExactly('u.dash'); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/dpns.spec.ts b/packages/js-evo-sdk/tests/unit/facades/dpns.spec.ts new file mode 100644 index 00000000000..92e833cd4f1 --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/dpns.spec.ts @@ -0,0 +1,128 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('DPNSFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + + // Stub references for type-safe assertions + let dpnsIsNameAvailableStub: SinonStub; + let dpnsResolveNameStub: SinonStub; + let dpnsRegisterNameStub: SinonStub; + let getDpnsUsernamesStub: SinonStub; + let getDpnsUsernameStub: SinonStub; + let getDpnsUsernamesWithProofInfoStub: SinonStub; + let getDpnsUsernameWithProofInfoStub: SinonStub; + let getDpnsUsernameByNameStub: SinonStub; + let getDpnsUsernameByNameWithProofInfoStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + dpnsIsNameAvailableStub = this.sinon.stub(wasmSdk, 'dpnsIsNameAvailable').resolves(true); + dpnsResolveNameStub = this.sinon.stub(wasmSdk, 'dpnsResolveName').resolves({}); + dpnsRegisterNameStub = this.sinon.stub(wasmSdk, 'dpnsRegisterName').resolves({}); + getDpnsUsernamesStub = this.sinon.stub(wasmSdk, 'getDpnsUsernames').resolves([]); + getDpnsUsernameStub = this.sinon.stub(wasmSdk, 'getDpnsUsername').resolves({}); + getDpnsUsernamesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDpnsUsernamesWithProofInfo').resolves({}); + getDpnsUsernameWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDpnsUsernameWithProofInfo').resolves({}); + getDpnsUsernameByNameStub = this.sinon.stub(wasmSdk, 'getDpnsUsernameByName').resolves({}); + getDpnsUsernameByNameWithProofInfoStub = this.sinon.stub(wasmSdk, 'getDpnsUsernameByNameWithProofInfo').resolves({}); + }); + + describe('convertToHomographSafe()', () => { + it('should await wasm statics and return a result', async () => { + const out = await client.dpns.convertToHomographSafe('abc'); + expect(out).to.be.ok(); + }); + }); + + describe('isValidUsername()', () => { + it('should return a boolean', async () => { + const out = await client.dpns.isValidUsername('abc'); + expect(out).to.be.a('boolean'); + }); + }); + + describe('isContestedUsername()', () => { + it('should return a boolean', async () => { + const out = await client.dpns.isContestedUsername('abc'); + expect(out).to.be.a('boolean'); + }); + }); + + describe('isNameAvailable()', () => { + it('should forward label to wasm', async () => { + await client.dpns.isNameAvailable('label'); + expect(dpnsIsNameAvailableStub).to.be.calledOnceWithExactly('label'); + }); + }); + + describe('resolveName()', () => { + it('should forward name to wasm', async () => { + await client.dpns.resolveName('name'); + expect(dpnsResolveNameStub).to.be.calledOnceWithExactly('name'); + }); + }); + + describe('registerName()', () => { + it('should forward registration options to wasm', async () => { + const mockIdentity = {}; + const mockIdentityKey = {}; + const mockSigner = {}; + await client.dpns.registerName({ + label: 'l', + identity: mockIdentity, + identityKey: mockIdentityKey, + signer: mockSigner, + }); + expect(dpnsRegisterNameStub).to.be.calledOnce(); + }); + }); + + describe('usernames()', () => { + it('should forward query to wasm', async () => { + await client.dpns.usernames({ identityId: 'i', limit: 2 }); + expect(getDpnsUsernamesStub).to.be.calledOnceWithExactly({ identityId: 'i', limit: 2 }); + }); + }); + + describe('username()', () => { + it('should forward identity ID to wasm', async () => { + await client.dpns.username('i'); + expect(getDpnsUsernameStub).to.be.calledOnceWithExactly('i'); + }); + }); + + describe('usernamesWithProof()', () => { + it('should forward query to wasm', async () => { + await client.dpns.usernamesWithProof({ identityId: 'i', limit: 3 }); + expect(getDpnsUsernamesWithProofInfoStub).to.be.calledOnceWithExactly({ identityId: 'i', limit: 3 }); + }); + }); + + describe('usernameWithProof()', () => { + it('should forward identity ID to wasm', async () => { + await client.dpns.usernameWithProof('i'); + expect(getDpnsUsernameWithProofInfoStub).to.be.calledOnceWithExactly('i'); + }); + }); + + describe('getUsernameByName()', () => { + it('should forward name to wasm', async () => { + await client.dpns.getUsernameByName('u.dash'); + expect(getDpnsUsernameByNameStub).to.be.calledOnceWithExactly('u.dash'); + }); + }); + + describe('getUsernameByNameWithProof()', () => { + it('should forward name to wasm', async () => { + await client.dpns.getUsernameByNameWithProof('u.dash'); + expect(getDpnsUsernameByNameWithProofInfoStub).to.be.calledOnceWithExactly('u.dash'); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/epoch.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/epoch.spec.mjs deleted file mode 100644 index 06b0a4be9e6..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/epoch.spec.mjs +++ /dev/null @@ -1,64 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('EpochFacade', () => { - let wasmSdk; - let client; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - this.sinon.stub(wasmSdk, 'getEpochsInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getEpochsInfoWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getFinalizedEpochInfos').resolves('ok'); - this.sinon.stub(wasmSdk, 'getFinalizedEpochInfosWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getCurrentEpoch').resolves('ok'); - this.sinon.stub(wasmSdk, 'getCurrentEpochWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByIds').resolves('ok'); - this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByIdsWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByRange').resolves('ok'); - this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByRangeWithProofInfo').resolves('ok'); - }); - - it('epochsInfo and finalizedInfos forward queries untouched', async () => { - const epochsQuery = { startEpoch: 1, count: 2, ascending: true }; - await client.epoch.epochsInfo(epochsQuery); - await client.epoch.epochsInfoWithProof(); - const finalizedQuery = { startEpoch: 3 }; - await client.epoch.finalizedInfos(finalizedQuery); - const finalizedProofQuery = { startEpoch: 4, count: 5 }; - await client.epoch.finalizedInfosWithProof(finalizedProofQuery); - expect(wasmSdk.getEpochsInfo).to.be.calledOnceWithExactly(epochsQuery); - expect(wasmSdk.getEpochsInfoWithProofInfo).to.be.calledOnce(); - expect(wasmSdk.getEpochsInfoWithProofInfo.firstCall.args[0]).to.deep.equal({}); - expect(wasmSdk.getFinalizedEpochInfos).to.be.calledOnceWithExactly(finalizedQuery); - expect(wasmSdk.getFinalizedEpochInfosWithProofInfo) - .to.be.calledOnceWithExactly(finalizedProofQuery); - }); - - it('current and currentWithProof forward', async () => { - await client.epoch.current(); - await client.epoch.currentWithProof(); - expect(wasmSdk.getCurrentEpoch).to.be.calledOnce(); - expect(wasmSdk.getCurrentEpochWithProofInfo).to.be.calledOnce(); - }); - - it('evonodesProposedBlocks* forward with args', async () => { - await client.epoch.evonodesProposedBlocksByIds(10, ['a', 'b']); - await client.epoch.evonodesProposedBlocksByIdsWithProof(11, ['x']); - const rangeQuery = { - epoch: 12, limit: 2, startAfter: 's', orderAscending: false, - }; - await client.epoch.evonodesProposedBlocksByRange(rangeQuery); - const rangeProofQuery = { epoch: 13 }; - await client.epoch.evonodesProposedBlocksByRangeWithProof(rangeProofQuery); - expect(wasmSdk.getEvonodesProposedEpochBlocksByIds).to.be.calledOnceWithExactly(10, ['a', 'b']); - expect(wasmSdk.getEvonodesProposedEpochBlocksByIdsWithProofInfo).to.be.calledOnceWithExactly(11, ['x']); - expect(wasmSdk.getEvonodesProposedEpochBlocksByRange).to.be.calledOnceWithExactly(rangeQuery); - expect(wasmSdk.getEvonodesProposedEpochBlocksByRangeWithProofInfo) - .to.be.calledOnceWithExactly(rangeProofQuery); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/epoch.spec.ts b/packages/js-evo-sdk/tests/unit/facades/epoch.spec.ts new file mode 100644 index 00000000000..0c6c2026071 --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/epoch.spec.ts @@ -0,0 +1,118 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('EpochFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + + // Stub references for type-safe assertions + let getEpochsInfoStub: SinonStub; + let getEpochsInfoWithProofInfoStub: SinonStub; + let getFinalizedEpochInfosStub: SinonStub; + let getFinalizedEpochInfosWithProofInfoStub: SinonStub; + let getCurrentEpochStub: SinonStub; + let getCurrentEpochWithProofInfoStub: SinonStub; + let getEvonodesProposedEpochBlocksByIdsStub: SinonStub; + let getEvonodesProposedEpochBlocksByIdsWithProofInfoStub: SinonStub; + let getEvonodesProposedEpochBlocksByRangeStub: SinonStub; + let getEvonodesProposedEpochBlocksByRangeWithProofInfoStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + getEpochsInfoStub = this.sinon.stub(wasmSdk, 'getEpochsInfo').resolves('ok'); + getEpochsInfoWithProofInfoStub = this.sinon.stub(wasmSdk, 'getEpochsInfoWithProofInfo').resolves('ok'); + getFinalizedEpochInfosStub = this.sinon.stub(wasmSdk, 'getFinalizedEpochInfos').resolves('ok'); + getFinalizedEpochInfosWithProofInfoStub = this.sinon.stub(wasmSdk, 'getFinalizedEpochInfosWithProofInfo').resolves('ok'); + getCurrentEpochStub = this.sinon.stub(wasmSdk, 'getCurrentEpoch').resolves('ok'); + getCurrentEpochWithProofInfoStub = this.sinon.stub(wasmSdk, 'getCurrentEpochWithProofInfo').resolves('ok'); + getEvonodesProposedEpochBlocksByIdsStub = this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByIds').resolves('ok'); + getEvonodesProposedEpochBlocksByIdsWithProofInfoStub = this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByIdsWithProofInfo').resolves('ok'); + getEvonodesProposedEpochBlocksByRangeStub = this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByRange').resolves('ok'); + getEvonodesProposedEpochBlocksByRangeWithProofInfoStub = this.sinon.stub(wasmSdk, 'getEvonodesProposedEpochBlocksByRangeWithProofInfo').resolves('ok'); + }); + + describe('epochsInfo()', () => { + it('should forward query to wasm untouched', async () => { + const epochsQuery = { startEpoch: 1, count: 2, ascending: true }; + await client.epoch.epochsInfo(epochsQuery); + expect(getEpochsInfoStub).to.be.calledOnceWithExactly(epochsQuery); + }); + }); + + describe('epochsInfoWithProof()', () => { + it('should forward empty object when no query provided', async () => { + await client.epoch.epochsInfoWithProof(); + expect(getEpochsInfoWithProofInfoStub).to.be.calledOnce(); + expect(getEpochsInfoWithProofInfoStub.firstCall.args[0]).to.deep.equal({}); + }); + }); + + describe('finalizedInfos()', () => { + it('should forward query to wasm', async () => { + const finalizedQuery = { startEpoch: 3 }; + await client.epoch.finalizedInfos(finalizedQuery); + expect(getFinalizedEpochInfosStub).to.be.calledOnceWithExactly(finalizedQuery); + }); + }); + + describe('finalizedInfosWithProof()', () => { + it('should forward query to wasm', async () => { + const finalizedProofQuery = { startEpoch: 4, count: 5 }; + await client.epoch.finalizedInfosWithProof(finalizedProofQuery); + expect(getFinalizedEpochInfosWithProofInfoStub) + .to.be.calledOnceWithExactly(finalizedProofQuery); + }); + }); + + describe('current()', () => { + it('should forward call to wasm', async () => { + await client.epoch.current(); + expect(getCurrentEpochStub).to.be.calledOnce(); + }); + }); + + describe('currentWithProof()', () => { + it('should forward call to wasm', async () => { + await client.epoch.currentWithProof(); + expect(getCurrentEpochWithProofInfoStub).to.be.calledOnce(); + }); + }); + + describe('evonodesProposedBlocksByIds()', () => { + it('should forward epoch and IDs to wasm', async () => { + await client.epoch.evonodesProposedBlocksByIds(10, ['a', 'b']); + expect(getEvonodesProposedEpochBlocksByIdsStub).to.be.calledOnceWithExactly(10, ['a', 'b']); + }); + }); + + describe('evonodesProposedBlocksByIdsWithProof()', () => { + it('should forward epoch and IDs to wasm', async () => { + await client.epoch.evonodesProposedBlocksByIdsWithProof(11, ['x']); + expect(getEvonodesProposedEpochBlocksByIdsWithProofInfoStub).to.be.calledOnceWithExactly(11, ['x']); + }); + }); + + describe('evonodesProposedBlocksByRange()', () => { + it('should forward range query to wasm', async () => { + const rangeQuery = { + epoch: 12, limit: 2, startAfter: 's', orderAscending: false, + }; + await client.epoch.evonodesProposedBlocksByRange(rangeQuery); + expect(getEvonodesProposedEpochBlocksByRangeStub).to.be.calledOnceWithExactly(rangeQuery); + }); + }); + + describe('evonodesProposedBlocksByRangeWithProof()', () => { + it('should forward range query to wasm', async () => { + const rangeProofQuery = { epoch: 13 }; + await client.epoch.evonodesProposedBlocksByRangeWithProof(rangeProofQuery); + expect(getEvonodesProposedEpochBlocksByRangeWithProofInfoStub) + .to.be.calledOnceWithExactly(rangeProofQuery); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/group.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/group.spec.mjs deleted file mode 100644 index 3092f17a284..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/group.spec.mjs +++ /dev/null @@ -1,157 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('GroupFacade', () => { - let wasmSdk; - let client; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - this.sinon.stub(wasmSdk, 'getGroupInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupInfoWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupInfos').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupInfosWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupMembers').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupMembersWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getIdentityGroups').resolves('ok'); - this.sinon.stub(wasmSdk, 'getIdentityGroupsWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupActions').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupActionsWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupActionSigners').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupActionSignersWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupsDataContracts').resolves('ok'); - this.sinon.stub(wasmSdk, 'getGroupsDataContractsWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getContestedResources').resolves('ok'); - this.sinon.stub(wasmSdk, 'getContestedResourcesWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getContestedResourceVotersForIdentity').resolves('ok'); - this.sinon.stub(wasmSdk, 'getContestedResourceVotersForIdentityWithProofInfo').resolves('ok'); - }); - - it('info queries forward to wasm', async () => { - await client.group.info('contract', 1); - await client.group.infoWithProof('contract', 2); - expect(wasmSdk.getGroupInfo).to.be.calledOnceWithExactly('contract', 1); - expect(wasmSdk.getGroupInfoWithProofInfo).to.be.calledOnceWithExactly('contract', 2); - }); - - it('infos() forwards optional args with null defaults', async () => { - const query = { dataContractId: 'contract', startAt: { position: 10, included: true }, limit: 5 }; - await client.group.infos(query); - const proofQuery = { dataContractId: 'contract' }; - await client.group.infosWithProof(proofQuery); - expect(wasmSdk.getGroupInfos).to.be.calledOnceWithExactly(query); - expect(wasmSdk.getGroupInfosWithProofInfo).to.be.calledOnceWithExactly(proofQuery); - }); - - it('members() forwards list and optional filters', async () => { - const query = { - dataContractId: 'contract', - groupContractPosition: 1, - memberIds: ['a'], - startAtMemberId: 's', - limit: 2, - }; - await client.group.members(query); - const proofQuery = { dataContractId: 'contract', groupContractPosition: 1 }; - await client.group.membersWithProof(proofQuery); - expect(wasmSdk.getGroupMembers).to.be.calledOnceWithExactly(query); - expect(wasmSdk.getGroupMembersWithProofInfo).to.be.calledOnceWithExactly(proofQuery); - }); - - it('identityGroups() forwards optional contract filters', async () => { - const query = { - identityId: 'identity', - memberDataContracts: ['m'], - ownerDataContracts: ['o'], - moderatorDataContracts: ['d'], - }; - await client.group.identityGroups(query); - const proofQuery = { identityId: 'identity' }; - await client.group.identityGroupsWithProof(proofQuery); - expect(wasmSdk.getIdentityGroups).to.be.calledOnceWithExactly(query); - expect(wasmSdk.getIdentityGroupsWithProofInfo).to.be.calledOnceWithExactly(proofQuery); - }); - - it('group actions helpers forward to wasm', async () => { - const query = { - dataContractId: 'contract', - groupContractPosition: 1, - status: 'ACTIVE', - startAt: { actionId: 'cursor', included: true }, - limit: 3, - }; - await client.group.actions(query); - const proofQuery = { - dataContractId: 'contract', - groupContractPosition: 1, - status: 'CLOSED', - }; - await client.group.actionsWithProof(proofQuery); - const signersQuery = { - dataContractId: 'contract', - groupContractPosition: 1, - status: 'ACTIVE', - actionId: 'action', - }; - await client.group.actionSigners(signersQuery); - await client.group.actionSignersWithProof(signersQuery); - expect(wasmSdk.getGroupActions).to.be.calledOnceWithExactly(query); - expect(wasmSdk.getGroupActionsWithProofInfo).to.be.calledOnceWithExactly(proofQuery); - expect(wasmSdk.getGroupActionSigners).to.be.calledOnceWithExactly(signersQuery); - expect(wasmSdk.getGroupActionSignersWithProofInfo).to.be.calledOnceWithExactly(signersQuery); - }); - - it('groupsDataContracts() forwards', async () => { - await client.group.groupsDataContracts(['a', 'b']); - await client.group.groupsDataContractsWithProof(['a']); - expect(wasmSdk.getGroupsDataContracts).to.be.calledOnceWithExactly(['a', 'b']); - expect(wasmSdk.getGroupsDataContractsWithProofInfo).to.be.calledOnceWithExactly(['a']); - }); - - it('forwards contestedResources and voters queries', async () => { - const contestedQuery = { - dataContractId: 'c', - documentTypeName: 'dt', - indexName: 'i', - startAtValue: new Uint8Array([1]), - limit: 2, - orderAscending: false, - }; - await client.group.contestedResources(contestedQuery); - const contestedProofQuery = { - dataContractId: 'c', - documentTypeName: 'dt', - indexName: 'i', - }; - await client.group.contestedResourcesWithProof(contestedProofQuery); - const votersQuery = { - dataContractId: 'c', - documentTypeName: 'dt', - indexName: 'i', - indexValues: ['v1'], - contestantId: 'id', - startAtVoterId: 's', - limit: 3, - orderAscending: true, - }; - await client.group.contestedResourceVotersForIdentity(votersQuery); - const votersProofQuery = { - dataContractId: 'c', - documentTypeName: 'dt', - indexName: 'i', - indexValues: ['v2'], - contestantId: 'id', - }; - await client.group.contestedResourceVotersForIdentityWithProof(votersProofQuery); - expect(wasmSdk.getContestedResources).to.be.calledOnceWithExactly(contestedQuery); - expect(wasmSdk.getContestedResourcesWithProofInfo).to.be - .calledOnceWithExactly(contestedProofQuery); - expect(wasmSdk.getContestedResourceVotersForIdentity).to.be.calledOnceWithExactly(votersQuery); - expect(wasmSdk.getContestedResourceVotersForIdentityWithProofInfo) - .to.be.calledOnceWithExactly(votersProofQuery); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/group.spec.ts b/packages/js-evo-sdk/tests/unit/facades/group.spec.ts new file mode 100644 index 00000000000..9e60e4a539d --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/group.spec.ts @@ -0,0 +1,253 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('GroupFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + + // Stub references for type-safe assertions + let getGroupInfoStub: SinonStub; + let getGroupInfoWithProofInfoStub: SinonStub; + let getGroupInfosStub: SinonStub; + let getGroupInfosWithProofInfoStub: SinonStub; + let getGroupMembersStub: SinonStub; + let getGroupMembersWithProofInfoStub: SinonStub; + let getIdentityGroupsStub: SinonStub; + let getIdentityGroupsWithProofInfoStub: SinonStub; + let getGroupActionsStub: SinonStub; + let getGroupActionsWithProofInfoStub: SinonStub; + let getGroupActionSignersStub: SinonStub; + let getGroupActionSignersWithProofInfoStub: SinonStub; + let getGroupsDataContractsStub: SinonStub; + let getGroupsDataContractsWithProofInfoStub: SinonStub; + let getContestedResourcesStub: SinonStub; + let getContestedResourcesWithProofInfoStub: SinonStub; + let getContestedResourceVotersForIdentityStub: SinonStub; + let getContestedResourceVotersForIdentityWithProofInfoStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + getGroupInfoStub = this.sinon.stub(wasmSdk, 'getGroupInfo').resolves('ok'); + getGroupInfoWithProofInfoStub = this.sinon.stub(wasmSdk, 'getGroupInfoWithProofInfo').resolves('ok'); + getGroupInfosStub = this.sinon.stub(wasmSdk, 'getGroupInfos').resolves('ok'); + getGroupInfosWithProofInfoStub = this.sinon.stub(wasmSdk, 'getGroupInfosWithProofInfo').resolves('ok'); + getGroupMembersStub = this.sinon.stub(wasmSdk, 'getGroupMembers').resolves('ok'); + getGroupMembersWithProofInfoStub = this.sinon.stub(wasmSdk, 'getGroupMembersWithProofInfo').resolves('ok'); + getIdentityGroupsStub = this.sinon.stub(wasmSdk, 'getIdentityGroups').resolves('ok'); + getIdentityGroupsWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityGroupsWithProofInfo').resolves('ok'); + getGroupActionsStub = this.sinon.stub(wasmSdk, 'getGroupActions').resolves('ok'); + getGroupActionsWithProofInfoStub = this.sinon.stub(wasmSdk, 'getGroupActionsWithProofInfo').resolves('ok'); + getGroupActionSignersStub = this.sinon.stub(wasmSdk, 'getGroupActionSigners').resolves('ok'); + getGroupActionSignersWithProofInfoStub = this.sinon.stub(wasmSdk, 'getGroupActionSignersWithProofInfo').resolves('ok'); + getGroupsDataContractsStub = this.sinon.stub(wasmSdk, 'getGroupsDataContracts').resolves('ok'); + getGroupsDataContractsWithProofInfoStub = this.sinon.stub(wasmSdk, 'getGroupsDataContractsWithProofInfo').resolves('ok'); + getContestedResourcesStub = this.sinon.stub(wasmSdk, 'getContestedResources').resolves('ok'); + getContestedResourcesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getContestedResourcesWithProofInfo').resolves('ok'); + getContestedResourceVotersForIdentityStub = this.sinon.stub(wasmSdk, 'getContestedResourceVotersForIdentity').resolves('ok'); + getContestedResourceVotersForIdentityWithProofInfoStub = this.sinon.stub(wasmSdk, 'getContestedResourceVotersForIdentityWithProofInfo').resolves('ok'); + }); + + describe('info()', () => { + it('should forward contract ID and position to wasm', async () => { + await client.group.info('contract', 1); + expect(getGroupInfoStub).to.be.calledOnceWithExactly('contract', 1); + }); + }); + + describe('infoWithProof()', () => { + it('should forward contract ID and position to wasm', async () => { + await client.group.infoWithProof('contract', 2); + expect(getGroupInfoWithProofInfoStub).to.be.calledOnceWithExactly('contract', 2); + }); + }); + + describe('infos()', () => { + it('should forward query with optional args to wasm', async () => { + const query = { dataContractId: 'contract', startAt: { position: 10, included: true }, limit: 5 }; + await client.group.infos(query); + expect(getGroupInfosStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('infosWithProof()', () => { + it('should forward query to wasm', async () => { + const proofQuery = { dataContractId: 'contract' }; + await client.group.infosWithProof(proofQuery); + expect(getGroupInfosWithProofInfoStub).to.be.calledOnceWithExactly(proofQuery); + }); + }); + + describe('members()', () => { + it('should forward query with optional filters to wasm', async () => { + const query = { + dataContractId: 'contract', + groupContractPosition: 1, + memberIds: ['a'], + startAtMemberId: 's', + limit: 2, + }; + await client.group.members(query); + expect(getGroupMembersStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('membersWithProof()', () => { + it('should forward query to wasm', async () => { + const proofQuery = { dataContractId: 'contract', groupContractPosition: 1 }; + await client.group.membersWithProof(proofQuery); + expect(getGroupMembersWithProofInfoStub).to.be.calledOnceWithExactly(proofQuery); + }); + }); + + describe('identityGroups()', () => { + it('should forward query with optional contract filters to wasm', async () => { + const query = { + identityId: 'identity', + memberDataContracts: ['m'], + ownerDataContracts: ['o'], + moderatorDataContracts: ['d'], + }; + await client.group.identityGroups(query); + expect(getIdentityGroupsStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('identityGroupsWithProof()', () => { + it('should forward query to wasm', async () => { + const proofQuery = { identityId: 'identity' }; + await client.group.identityGroupsWithProof(proofQuery); + expect(getIdentityGroupsWithProofInfoStub).to.be.calledOnceWithExactly(proofQuery); + }); + }); + + describe('actions()', () => { + it('should forward query to wasm', async () => { + const query = { + dataContractId: 'contract', + groupContractPosition: 1, + status: 'ACTIVE', + startAt: { actionId: 'cursor', included: true }, + limit: 3, + }; + await client.group.actions(query); + expect(getGroupActionsStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('actionsWithProof()', () => { + it('should forward query to wasm', async () => { + const proofQuery = { + dataContractId: 'contract', + groupContractPosition: 1, + status: 'CLOSED', + }; + await client.group.actionsWithProof(proofQuery); + expect(getGroupActionsWithProofInfoStub).to.be.calledOnceWithExactly(proofQuery); + }); + }); + + describe('actionSigners()', () => { + it('should forward query to wasm', async () => { + const signersQuery = { + dataContractId: 'contract', + groupContractPosition: 1, + status: 'ACTIVE', + actionId: 'action', + }; + await client.group.actionSigners(signersQuery); + expect(getGroupActionSignersStub).to.be.calledOnceWithExactly(signersQuery); + }); + }); + + describe('actionSignersWithProof()', () => { + it('should forward query to wasm', async () => { + const signersQuery = { + dataContractId: 'contract', + groupContractPosition: 1, + status: 'ACTIVE', + actionId: 'action', + }; + await client.group.actionSignersWithProof(signersQuery); + expect(getGroupActionSignersWithProofInfoStub).to.be.calledOnceWithExactly(signersQuery); + }); + }); + + describe('groupsDataContracts()', () => { + it('should forward contract IDs to wasm', async () => { + await client.group.groupsDataContracts(['a', 'b']); + expect(getGroupsDataContractsStub).to.be.calledOnceWithExactly(['a', 'b']); + }); + }); + + describe('groupsDataContractsWithProof()', () => { + it('should forward contract IDs to wasm', async () => { + await client.group.groupsDataContractsWithProof(['a']); + expect(getGroupsDataContractsWithProofInfoStub).to.be.calledOnceWithExactly(['a']); + }); + }); + + describe('contestedResources()', () => { + it('should forward query to wasm', async () => { + const contestedQuery = { + dataContractId: 'c', + documentTypeName: 'dt', + indexName: 'i', + startAtValue: new Uint8Array([1]), + limit: 2, + orderAscending: false, + }; + await client.group.contestedResources(contestedQuery); + expect(getContestedResourcesStub).to.be.calledOnceWithExactly(contestedQuery); + }); + }); + + describe('contestedResourcesWithProof()', () => { + it('should forward query to wasm', async () => { + const contestedProofQuery = { + dataContractId: 'c', + documentTypeName: 'dt', + indexName: 'i', + }; + await client.group.contestedResourcesWithProof(contestedProofQuery); + expect(getContestedResourcesWithProofInfoStub).to.be + .calledOnceWithExactly(contestedProofQuery); + }); + }); + + describe('contestedResourceVotersForIdentity()', () => { + it('should forward query to wasm', async () => { + const votersQuery = { + dataContractId: 'c', + documentTypeName: 'dt', + indexName: 'i', + indexValues: ['v1'], + contestantId: 'id', + startAtVoterId: 's', + limit: 3, + orderAscending: true, + }; + await client.group.contestedResourceVotersForIdentity(votersQuery); + expect(getContestedResourceVotersForIdentityStub).to.be.calledOnceWithExactly(votersQuery); + }); + }); + + describe('contestedResourceVotersForIdentityWithProof()', () => { + it('should forward query to wasm', async () => { + const votersProofQuery = { + dataContractId: 'c', + documentTypeName: 'dt', + indexName: 'i', + indexValues: ['v2'], + contestantId: 'id', + }; + await client.group.contestedResourceVotersForIdentityWithProof(votersProofQuery); + expect(getContestedResourceVotersForIdentityWithProofInfoStub) + .to.be.calledOnceWithExactly(votersProofQuery); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/identities.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/identities.spec.mjs deleted file mode 100644 index ffd2e528d2e..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/identities.spec.mjs +++ /dev/null @@ -1,337 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('IdentitiesFacade', () => { - let wasmSdk; - let client; - let identity; - let signer; - let assetLockProof; - let assetLockPrivateKey; - let publicKeyInCreation; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - // Create mock objects - identity = Object.create(wasmSDKPackage.Identity.prototype); - signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); - assetLockProof = Object.create(wasmSDKPackage.AssetLockProof.prototype); - assetLockPrivateKey = Object.create(wasmSDKPackage.PrivateKey.prototype); - publicKeyInCreation = Object.create(wasmSDKPackage.IdentityPublicKeyInCreation.prototype); - - // Stub query methods - this.sinon.stub(wasmSdk, 'getIdentity').resolves(identity); - this.sinon.stub(wasmSdk, 'getIdentityWithProofInfo').resolves({ - data: identity, - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityUnproved').resolves(identity); - this.sinon.stub(wasmSdk, 'getIdentityKeys').resolves([]); - this.sinon.stub(wasmSdk, 'getIdentityKeysWithProofInfo').resolves({ - data: [], - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityNonce').resolves(BigInt(1)); - this.sinon.stub(wasmSdk, 'getIdentityNonceWithProofInfo').resolves({ - data: BigInt(1), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityContractNonce').resolves(BigInt(0)); - this.sinon.stub(wasmSdk, 'getIdentityContractNonceWithProofInfo').resolves({ - data: BigInt(0), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityBalance').resolves(BigInt(100000000)); - this.sinon.stub(wasmSdk, 'getIdentityBalanceWithProofInfo').resolves({ - data: BigInt(100000000), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentitiesBalances').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getIdentitiesBalancesWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityBalanceAndRevision').resolves({ - balance: BigInt(100000000), - revision: BigInt(1), - }); - this.sinon.stub(wasmSdk, 'getIdentityBalanceAndRevisionWithProofInfo').resolves({ - data: { balance: BigInt(100000000), revision: BigInt(1) }, - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityByPublicKeyHash').resolves(identity); - this.sinon.stub(wasmSdk, 'getIdentityByPublicKeyHashWithProofInfo').resolves({ - data: identity, - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityByNonUniquePublicKeyHash').resolves([]); - this.sinon.stub(wasmSdk, 'getIdentityByNonUniquePublicKeyHashWithProofInfo').resolves({ - data: [], - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentitiesContractKeys').resolves([]); - this.sinon.stub(wasmSdk, 'getIdentitiesContractKeysWithProofInfo').resolves({ - data: [], - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityTokenBalances').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getIdentityTokenBalancesWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - - // Stub transition methods - this.sinon.stub(wasmSdk, 'identityCreate').resolves(); - this.sinon.stub(wasmSdk, 'identityTopUp').resolves(BigInt(200000000)); - this.sinon.stub(wasmSdk, 'identityCreditTransfer').resolves({ - senderBalance: BigInt(50000000), - recipientBalance: BigInt(50000000), - }); - this.sinon.stub(wasmSdk, 'identityCreditWithdrawal').resolves(BigInt(80000000)); - this.sinon.stub(wasmSdk, 'identityUpdate').resolves(); - }); - - describe('Query Methods', () => { - it('fetch() returns an identity by ID', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - - const result = await client.identities.fetch(identityId); - - expect(wasmSdk.getIdentity).to.be.calledOnceWithExactly(identityId); - expect(result).to.be.instanceOf(wasmSDKPackage.Identity); - }); - - it('fetchWithProof() returns identity with proof metadata', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - - await client.identities.fetchWithProof(identityId); - - expect(wasmSdk.getIdentityWithProofInfo).to.be.calledOnceWithExactly(identityId); - }); - - it('fetchUnproved() returns identity without proof verification', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - - await client.identities.fetchUnproved(identityId); - - expect(wasmSdk.getIdentityUnproved).to.be.calledOnceWithExactly(identityId); - }); - - it('getKeys() fetches identity public keys', async () => { - const query = { - identityId: '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', - request: { - type: 'specific', - specificKeyIds: [0, 1], - }, - limit: 10, - offset: 0, - }; - - await client.identities.getKeys(query); - - expect(wasmSdk.getIdentityKeys).to.be.calledOnceWithExactly(query); - }); - - it('getKeysWithProof() fetches identity keys with proof', async () => { - const query = { - identityId: '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', - request: { type: 'all' }, - }; - - await client.identities.getKeysWithProof(query); - - expect(wasmSdk.getIdentityKeysWithProofInfo).to.be.calledOnceWithExactly(query); - }); - - it('nonce() and nonceWithProof() fetch identity nonce', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - - await client.identities.nonce(identityId); - await client.identities.nonceWithProof(identityId); - - expect(wasmSdk.getIdentityNonce).to.be.calledOnceWithExactly(identityId); - expect(wasmSdk.getIdentityNonceWithProofInfo).to.be.calledOnceWithExactly(identityId); - }); - - it('contractNonce() fetches contract-specific nonce', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; - - await client.identities.contractNonce(identityId, contractId); - await client.identities.contractNonceWithProof(identityId, contractId); - - expect(wasmSdk.getIdentityContractNonce) - .to.be.calledOnceWithExactly(identityId, contractId); - expect(wasmSdk.getIdentityContractNonceWithProofInfo) - .to.be.calledOnceWithExactly(identityId, contractId); - }); - - it('balance() and balances() fetch identity credits', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - const identityIds = [ - '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', - '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack', - ]; - - await client.identities.balance(identityId); - await client.identities.balanceWithProof(identityId); - await client.identities.balances(identityIds); - await client.identities.balancesWithProof(identityIds); - - expect(wasmSdk.getIdentityBalance).to.be.calledOnceWithExactly(identityId); - expect(wasmSdk.getIdentityBalanceWithProofInfo).to.be.calledOnceWithExactly(identityId); - expect(wasmSdk.getIdentitiesBalances).to.be.calledOnceWithExactly(identityIds); - expect(wasmSdk.getIdentitiesBalancesWithProofInfo).to.be.calledOnceWithExactly(identityIds); - }); - - it('balanceAndRevision() fetches balance and revision together', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - - await client.identities.balanceAndRevision(identityId); - await client.identities.balanceAndRevisionWithProof(identityId); - - expect(wasmSdk.getIdentityBalanceAndRevision) - .to.be.calledOnceWithExactly(identityId); - expect(wasmSdk.getIdentityBalanceAndRevisionWithProofInfo) - .to.be.calledOnceWithExactly(identityId); - }); - - it('byPublicKeyHash() looks up identity by public key hash', async () => { - const publicKeyHash = 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'; - - await client.identities.byPublicKeyHash(publicKeyHash); - await client.identities.byPublicKeyHashWithProof(publicKeyHash); - - expect(wasmSdk.getIdentityByPublicKeyHash) - .to.be.calledOnceWithExactly(publicKeyHash); - expect(wasmSdk.getIdentityByPublicKeyHashWithProofInfo) - .to.be.calledOnceWithExactly(publicKeyHash); - }); - - it('byNonUniquePublicKeyHash() supports pagination cursor', async () => { - const publicKeyHash = 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'; - const startAfter = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - - await client.identities.byNonUniquePublicKeyHash(publicKeyHash, startAfter); - await client.identities.byNonUniquePublicKeyHashWithProof(publicKeyHash); - - expect(wasmSdk.getIdentityByNonUniquePublicKeyHash) - .to.be.calledOnceWithExactly(publicKeyHash, startAfter); - expect(wasmSdk.getIdentityByNonUniquePublicKeyHashWithProofInfo) - .to.be.calledOnceWithExactly(publicKeyHash, undefined); - }); - - it('contractKeys() fetches contract-bound keys for identities', async () => { - const query = { - identityIds: ['5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'], - contractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', - purposes: [0, 1], // AUTHENTICATION, ENCRYPTION - }; - - await client.identities.contractKeys(query); - - expect(wasmSdk.getIdentitiesContractKeys).to.be.calledOnceWithExactly(query); - }); - - it('tokenBalances() fetches identity token balances', async () => { - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - const tokenIds = ['BpJvvpPiR2obh7ueZixjtYXsmWQdgJhiZtQJWjD7Ruus']; - - await client.identities.tokenBalances(identityId, tokenIds); - await client.identities.tokenBalancesWithProof(identityId, tokenIds); - - expect(wasmSdk.getIdentityTokenBalances) - .to.be.calledOnceWithExactly(identityId, tokenIds); - expect(wasmSdk.getIdentityTokenBalancesWithProofInfo) - .to.be.calledOnceWithExactly(identityId, tokenIds); - }); - }); - - describe('Transition Methods', () => { - it('create() creates a new identity with asset lock', async () => { - const options = { - identity, - assetLockProof, - assetLockPrivateKey, - signer, - }; - - await client.identities.create(options); - - expect(wasmSdk.identityCreate).to.be.calledOnceWithExactly(options); - }); - - it('topUp() tops up identity balance with asset lock', async () => { - const options = { - identity, - assetLockProof, - assetLockPrivateKey, - }; - - const newBalance = await client.identities.topUp(options); - - expect(wasmSdk.identityTopUp).to.be.calledOnceWithExactly(options); - expect(newBalance).to.equal(BigInt(200000000)); - }); - - it('creditTransfer() transfers credits between identities', async () => { - const recipientId = '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack'; - const options = { - identity, - recipientId, - amount: BigInt(50000000), // 50M credits - signer, - }; - - const result = await client.identities.creditTransfer(options); - - expect(wasmSdk.identityCreditTransfer).to.be.calledOnceWithExactly(options); - expect(result.senderBalance).to.equal(BigInt(50000000)); - expect(result.recipientBalance).to.equal(BigInt(50000000)); - }); - - it('creditWithdrawal() withdraws credits to Dash address', async () => { - const options = { - identity, - amount: BigInt(20000000), // 20M credits - toAddress: 'yNPbcFfabt8MMPjYjWBGjpAJWYhUMoqoUo', - coreFeePerByte: 1, - signer, - }; - - const remainingBalance = await client.identities.creditWithdrawal(options); - - expect(wasmSdk.identityCreditWithdrawal).to.be.calledOnceWithExactly(options); - expect(remainingBalance).to.equal(BigInt(80000000)); - }); - - it('update() adds and disables public keys', async () => { - const options = { - identity, - addPublicKeys: [publicKeyInCreation], - disablePublicKeys: [2, 3], - signer, - }; - - await client.identities.update(options); - - expect(wasmSdk.identityUpdate).to.be.calledOnceWithExactly(options); - }); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/identities.spec.ts b/packages/js-evo-sdk/tests/unit/facades/identities.spec.ts new file mode 100644 index 00000000000..401e76e79f6 --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/identities.spec.ts @@ -0,0 +1,480 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('IdentitiesFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + let identity: wasmSDKPackage.Identity; + let signer: wasmSDKPackage.IdentitySigner; + let assetLockProof: wasmSDKPackage.AssetLockProof; + let assetLockPrivateKey: wasmSDKPackage.PrivateKey; + let publicKeyInCreation: wasmSDKPackage.IdentityPublicKeyInCreation; + + // Stub references for type-safe assertions + let getIdentityStub: SinonStub; + let getIdentityWithProofInfoStub: SinonStub; + let getIdentityUnprovedStub: SinonStub; + let getIdentityKeysStub: SinonStub; + let getIdentityKeysWithProofInfoStub: SinonStub; + let getIdentityNonceStub: SinonStub; + let getIdentityNonceWithProofInfoStub: SinonStub; + let getIdentityContractNonceStub: SinonStub; + let getIdentityContractNonceWithProofInfoStub: SinonStub; + let getIdentityBalanceStub: SinonStub; + let getIdentityBalanceWithProofInfoStub: SinonStub; + let getIdentitiesBalancesStub: SinonStub; + let getIdentitiesBalancesWithProofInfoStub: SinonStub; + let getIdentityBalanceAndRevisionStub: SinonStub; + let getIdentityBalanceAndRevisionWithProofInfoStub: SinonStub; + let getIdentityByPublicKeyHashStub: SinonStub; + let getIdentityByPublicKeyHashWithProofInfoStub: SinonStub; + let getIdentityByNonUniquePublicKeyHashStub: SinonStub; + let getIdentityByNonUniquePublicKeyHashWithProofInfoStub: SinonStub; + let getIdentitiesContractKeysStub: SinonStub; + let getIdentitiesContractKeysWithProofInfoStub: SinonStub; + let getIdentityTokenBalancesStub: SinonStub; + let getIdentityTokenBalancesWithProofInfoStub: SinonStub; + let identityCreateStub: SinonStub; + let identityTopUpStub: SinonStub; + let identityCreditTransferStub: SinonStub; + let identityCreditWithdrawalStub: SinonStub; + let identityUpdateStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + // Create mock objects + identity = Object.create(wasmSDKPackage.Identity.prototype); + signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); + assetLockProof = Object.create(wasmSDKPackage.AssetLockProof.prototype); + assetLockPrivateKey = Object.create(wasmSDKPackage.PrivateKey.prototype); + publicKeyInCreation = Object.create(wasmSDKPackage.IdentityPublicKeyInCreation.prototype); + + // Stub query methods + getIdentityStub = this.sinon.stub(wasmSdk, 'getIdentity').resolves(identity); + getIdentityWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityWithProofInfo').resolves({ + data: identity, + proof: {}, + metadata: {}, + }); + getIdentityUnprovedStub = this.sinon.stub(wasmSdk, 'getIdentityUnproved').resolves(identity); + getIdentityKeysStub = this.sinon.stub(wasmSdk, 'getIdentityKeys').resolves([]); + getIdentityKeysWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityKeysWithProofInfo').resolves({ + data: [], + proof: {}, + metadata: {}, + }); + getIdentityNonceStub = this.sinon.stub(wasmSdk, 'getIdentityNonce').resolves(BigInt(1)); + getIdentityNonceWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityNonceWithProofInfo').resolves({ + data: BigInt(1), + proof: {}, + metadata: {}, + }); + getIdentityContractNonceStub = this.sinon.stub(wasmSdk, 'getIdentityContractNonce').resolves(BigInt(0)); + getIdentityContractNonceWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityContractNonceWithProofInfo').resolves({ + data: BigInt(0), + proof: {}, + metadata: {}, + }); + getIdentityBalanceStub = this.sinon.stub(wasmSdk, 'getIdentityBalance').resolves(BigInt(100000000)); + getIdentityBalanceWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityBalanceWithProofInfo').resolves({ + data: BigInt(100000000), + proof: {}, + metadata: {}, + }); + getIdentitiesBalancesStub = this.sinon.stub(wasmSdk, 'getIdentitiesBalances').resolves(new Map()); + getIdentitiesBalancesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentitiesBalancesWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getIdentityBalanceAndRevisionStub = this.sinon.stub(wasmSdk, 'getIdentityBalanceAndRevision').resolves({ + balance: BigInt(100000000), + revision: BigInt(1), + }); + getIdentityBalanceAndRevisionWithProofInfoStub = this.sinon + .stub(wasmSdk, 'getIdentityBalanceAndRevisionWithProofInfo').resolves({ + data: { balance: BigInt(100000000), revision: BigInt(1) }, + proof: {}, + metadata: {}, + }); + getIdentityByPublicKeyHashStub = this.sinon.stub(wasmSdk, 'getIdentityByPublicKeyHash').resolves(identity); + getIdentityByPublicKeyHashWithProofInfoStub = this.sinon + .stub(wasmSdk, 'getIdentityByPublicKeyHashWithProofInfo').resolves({ + data: identity, + proof: {}, + metadata: {}, + }); + getIdentityByNonUniquePublicKeyHashStub = this.sinon.stub(wasmSdk, 'getIdentityByNonUniquePublicKeyHash').resolves([]); + getIdentityByNonUniquePublicKeyHashWithProofInfoStub = this.sinon + .stub(wasmSdk, 'getIdentityByNonUniquePublicKeyHashWithProofInfo').resolves({ + data: [], + proof: {}, + metadata: {}, + }); + getIdentitiesContractKeysStub = this.sinon.stub(wasmSdk, 'getIdentitiesContractKeys').resolves([]); + getIdentitiesContractKeysWithProofInfoStub = this.sinon + .stub(wasmSdk, 'getIdentitiesContractKeysWithProofInfo').resolves({ + data: [], + proof: {}, + metadata: {}, + }); + getIdentityTokenBalancesStub = this.sinon.stub(wasmSdk, 'getIdentityTokenBalances').resolves(new Map()); + getIdentityTokenBalancesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityTokenBalancesWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + + // Stub transition methods + identityCreateStub = this.sinon.stub(wasmSdk, 'identityCreate').resolves(); + identityTopUpStub = this.sinon.stub(wasmSdk, 'identityTopUp').resolves(BigInt(200000000)); + identityCreditTransferStub = this.sinon.stub(wasmSdk, 'identityCreditTransfer').resolves({ + senderBalance: BigInt(50000000), + recipientBalance: BigInt(50000000), + }); + identityCreditWithdrawalStub = this.sinon.stub(wasmSdk, 'identityCreditWithdrawal').resolves(BigInt(80000000)); + identityUpdateStub = this.sinon.stub(wasmSdk, 'identityUpdate').resolves(); + }); + + describe('fetch()', () => { + it('should return an identity by ID', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + const result = await client.identities.fetch(identityId); + + expect(getIdentityStub).to.be.calledOnceWithExactly(identityId); + expect(result).to.be.instanceOf(wasmSDKPackage.Identity); + }); + }); + + describe('fetchWithProof()', () => { + it('should return identity with proof metadata', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.fetchWithProof(identityId); + + expect(getIdentityWithProofInfoStub).to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('fetchUnproved()', () => { + it('should return identity without proof verification', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.fetchUnproved(identityId); + + expect(getIdentityUnprovedStub).to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('getKeys()', () => { + it('should fetch identity public keys', async () => { + const query = { + identityId: '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', + request: { + type: 'specific', + specificKeyIds: [0, 1], + }, + limit: 10, + offset: 0, + }; + + await client.identities.getKeys(query); + + expect(getIdentityKeysStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('getKeysWithProof()', () => { + it('should fetch identity keys with proof', async () => { + const query = { + identityId: '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', + request: { type: 'all' }, + }; + + await client.identities.getKeysWithProof(query); + + expect(getIdentityKeysWithProofInfoStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('nonce()', () => { + it('should fetch identity nonce', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.nonce(identityId); + + expect(getIdentityNonceStub).to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('nonceWithProof()', () => { + it('should fetch identity nonce with proof', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.nonceWithProof(identityId); + + expect(getIdentityNonceWithProofInfoStub).to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('contractNonce()', () => { + it('should fetch contract-specific nonce', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; + + await client.identities.contractNonce(identityId, contractId); + + expect(getIdentityContractNonceStub) + .to.be.calledOnceWithExactly(identityId, contractId); + }); + }); + + describe('contractNonceWithProof()', () => { + it('should fetch contract-specific nonce with proof', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; + + await client.identities.contractNonceWithProof(identityId, contractId); + + expect(getIdentityContractNonceWithProofInfoStub) + .to.be.calledOnceWithExactly(identityId, contractId); + }); + }); + + describe('balance()', () => { + it('should fetch identity credits balance', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.balance(identityId); + + expect(getIdentityBalanceStub).to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('balanceWithProof()', () => { + it('should fetch identity credits balance with proof', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.balanceWithProof(identityId); + + expect(getIdentityBalanceWithProofInfoStub).to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('balances()', () => { + it('should fetch balances for multiple identities', async () => { + const identityIds = [ + '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', + '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack', + ]; + + await client.identities.balances(identityIds); + + expect(getIdentitiesBalancesStub).to.be.calledOnceWithExactly(identityIds); + }); + }); + + describe('balancesWithProof()', () => { + it('should fetch balances for multiple identities with proof', async () => { + const identityIds = [ + '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS', + '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack', + ]; + + await client.identities.balancesWithProof(identityIds); + + expect(getIdentitiesBalancesWithProofInfoStub).to.be.calledOnceWithExactly(identityIds); + }); + }); + + describe('balanceAndRevision()', () => { + it('should fetch balance and revision together', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.balanceAndRevision(identityId); + + expect(getIdentityBalanceAndRevisionStub) + .to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('balanceAndRevisionWithProof()', () => { + it('should fetch balance and revision with proof', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.balanceAndRevisionWithProof(identityId); + + expect(getIdentityBalanceAndRevisionWithProofInfoStub) + .to.be.calledOnceWithExactly(identityId); + }); + }); + + describe('byPublicKeyHash()', () => { + it('should look up identity by public key hash', async () => { + const publicKeyHash = 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'; + + await client.identities.byPublicKeyHash(publicKeyHash); + + expect(getIdentityByPublicKeyHashStub) + .to.be.calledOnceWithExactly(publicKeyHash); + }); + }); + + describe('byPublicKeyHashWithProof()', () => { + it('should look up identity by public key hash with proof', async () => { + const publicKeyHash = 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'; + + await client.identities.byPublicKeyHashWithProof(publicKeyHash); + + expect(getIdentityByPublicKeyHashWithProofInfoStub) + .to.be.calledOnceWithExactly(publicKeyHash); + }); + }); + + describe('byNonUniquePublicKeyHash()', () => { + it('should support pagination cursor for non-unique public key hash lookup', async () => { + const publicKeyHash = 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'; + const startAfter = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + + await client.identities.byNonUniquePublicKeyHash(publicKeyHash, startAfter); + + expect(getIdentityByNonUniquePublicKeyHashStub) + .to.be.calledOnceWithExactly(publicKeyHash, startAfter); + }); + }); + + describe('byNonUniquePublicKeyHashWithProof()', () => { + it('should look up by non-unique public key hash with proof', async () => { + const publicKeyHash = 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'; + + await client.identities.byNonUniquePublicKeyHashWithProof(publicKeyHash); + + expect(getIdentityByNonUniquePublicKeyHashWithProofInfoStub) + .to.be.calledOnceWithExactly(publicKeyHash, undefined); + }); + }); + + describe('contractKeys()', () => { + it('should fetch contract-bound keys for identities', async () => { + const query = { + identityIds: ['5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'], + contractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + purposes: [0, 1], // AUTHENTICATION, ENCRYPTION + }; + + await client.identities.contractKeys(query); + + expect(getIdentitiesContractKeysStub).to.be.calledOnceWithExactly(query); + }); + }); + + describe('tokenBalances()', () => { + it('should fetch identity token balances', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + const tokenIds = ['BpJvvpPiR2obh7ueZixjtYXsmWQdgJhiZtQJWjD7Ruus']; + + await client.identities.tokenBalances(identityId, tokenIds); + + expect(getIdentityTokenBalancesStub) + .to.be.calledOnceWithExactly(identityId, tokenIds); + }); + }); + + describe('tokenBalancesWithProof()', () => { + it('should fetch identity token balances with proof', async () => { + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + const tokenIds = ['BpJvvpPiR2obh7ueZixjtYXsmWQdgJhiZtQJWjD7Ruus']; + + await client.identities.tokenBalancesWithProof(identityId, tokenIds); + + expect(getIdentityTokenBalancesWithProofInfoStub) + .to.be.calledOnceWithExactly(identityId, tokenIds); + }); + }); + + describe('create()', () => { + it('should create a new identity with asset lock', async () => { + const options = { + identity, + assetLockProof, + assetLockPrivateKey, + signer, + }; + + await client.identities.create(options); + + expect(identityCreateStub).to.be.calledOnceWithExactly(options); + }); + }); + + describe('topUp()', () => { + it('should top up identity balance with asset lock', async () => { + const options = { + identity, + assetLockProof, + assetLockPrivateKey, + }; + + const newBalance = await client.identities.topUp(options); + + expect(identityTopUpStub).to.be.calledOnceWithExactly(options); + expect(newBalance).to.equal(BigInt(200000000)); + }); + }); + + describe('creditTransfer()', () => { + it('should transfer credits between identities', async () => { + const recipientId = '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack'; + const options = { + identity, + recipientId, + amount: BigInt(50000000), // 50M credits + signer, + }; + + const result = await client.identities.creditTransfer(options); + + expect(identityCreditTransferStub).to.be.calledOnceWithExactly(options); + expect(result.senderBalance).to.equal(BigInt(50000000)); + expect(result.recipientBalance).to.equal(BigInt(50000000)); + }); + }); + + describe('creditWithdrawal()', () => { + it('should withdraw credits to Dash address', async () => { + const options = { + identity, + amount: BigInt(20000000), // 20M credits + toAddress: 'yNPbcFfabt8MMPjYjWBGjpAJWYhUMoqoUo', + coreFeePerByte: 1, + signer, + }; + + const remainingBalance = await client.identities.creditWithdrawal(options); + + expect(identityCreditWithdrawalStub).to.be.calledOnceWithExactly(options); + expect(remainingBalance).to.equal(BigInt(80000000)); + }); + }); + + describe('update()', () => { + it('should add and disable public keys', async () => { + const options = { + identity, + addPublicKeys: [publicKeyInCreation], + disablePublicKeys: [2, 3], + signer, + }; + + await client.identities.update(options); + + expect(identityUpdateStub).to.be.calledOnceWithExactly(options); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/protocol.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/protocol.spec.mjs deleted file mode 100644 index bee9c83ed07..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/protocol.spec.mjs +++ /dev/null @@ -1,41 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('ProtocolFacade', () => { - let wasmSdk; - let client; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeState').resolves('ok'); - this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeStateWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeVoteStatus').resolves('ok'); - this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeVoteStatusWithProofInfo').resolves('ok'); - }); - - it('versionUpgradeState and versionUpgradeStateWithProof forward', async () => { - await client.protocol.versionUpgradeState(); - await client.protocol.versionUpgradeStateWithProof(); - expect(wasmSdk.getProtocolVersionUpgradeState).to.be.calledOnce(); - expect(wasmSdk.getProtocolVersionUpgradeStateWithProofInfo).to.be.calledOnce(); - }); - - it('versionUpgradeVoteStatus and withProof forward with positional args', async () => { - await client.protocol.versionUpgradeVoteStatus('h', 5); - await client.protocol.versionUpgradeVoteStatusWithProof('g', 3); - expect(wasmSdk.getProtocolVersionUpgradeVoteStatus).to.be.calledOnceWithExactly('h', 5); - expect(wasmSdk.getProtocolVersionUpgradeVoteStatusWithProofInfo).to.be.calledOnceWithExactly('g', 3); - }); - - it('versionUpgradeVoteStatus accepts Uint8Array and positional args', async () => { - const bytes = new Uint8Array([0xde, 0xad, 0xbe, 0xef]); - await client.protocol.versionUpgradeVoteStatus(bytes, 2); - await client.protocol.versionUpgradeVoteStatusWithProof(bytes, 4); - expect(wasmSdk.getProtocolVersionUpgradeVoteStatus).to.be.calledWith(bytes, 2); - expect(wasmSdk.getProtocolVersionUpgradeVoteStatusWithProofInfo).to.be.calledWith(bytes, 4); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/protocol.spec.ts b/packages/js-evo-sdk/tests/unit/facades/protocol.spec.ts new file mode 100644 index 00000000000..9f54fb348a3 --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/protocol.spec.ts @@ -0,0 +1,66 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('ProtocolFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + + // Stub references for type-safe assertions + let getProtocolVersionUpgradeStateStub: SinonStub; + let getProtocolVersionUpgradeStateWithProofInfoStub: SinonStub; + let getProtocolVersionUpgradeVoteStatusStub: SinonStub; + let getProtocolVersionUpgradeVoteStatusWithProofInfoStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + getProtocolVersionUpgradeStateStub = this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeState').resolves('ok'); + getProtocolVersionUpgradeStateWithProofInfoStub = this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeStateWithProofInfo').resolves('ok'); + getProtocolVersionUpgradeVoteStatusStub = this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeVoteStatus').resolves('ok'); + getProtocolVersionUpgradeVoteStatusWithProofInfoStub = this.sinon.stub(wasmSdk, 'getProtocolVersionUpgradeVoteStatusWithProofInfo').resolves('ok'); + }); + + describe('versionUpgradeState()', () => { + it('should forward to getProtocolVersionUpgradeState', async () => { + await client.protocol.versionUpgradeState(); + expect(getProtocolVersionUpgradeStateStub).to.be.calledOnce(); + }); + }); + + describe('versionUpgradeStateWithProof()', () => { + it('should forward to getProtocolVersionUpgradeStateWithProofInfo', async () => { + await client.protocol.versionUpgradeStateWithProof(); + expect(getProtocolVersionUpgradeStateWithProofInfoStub).to.be.calledOnce(); + }); + }); + + describe('versionUpgradeVoteStatus()', () => { + it('should forward with positional args', async () => { + await client.protocol.versionUpgradeVoteStatus('h', 5); + expect(getProtocolVersionUpgradeVoteStatusStub).to.be.calledOnceWithExactly('h', 5); + }); + + it('should accept Uint8Array and positional args', async () => { + const bytes = new Uint8Array([0xde, 0xad, 0xbe, 0xef]); + await client.protocol.versionUpgradeVoteStatus(bytes, 2); + expect(getProtocolVersionUpgradeVoteStatusStub).to.be.calledWith(bytes, 2); + }); + }); + + describe('versionUpgradeVoteStatusWithProof()', () => { + it('should forward with positional args', async () => { + await client.protocol.versionUpgradeVoteStatusWithProof('g', 3); + expect(getProtocolVersionUpgradeVoteStatusWithProofInfoStub).to.be.calledOnceWithExactly('g', 3); + }); + + it('should accept Uint8Array and positional args', async () => { + const bytes = new Uint8Array([0xde, 0xad, 0xbe, 0xef]); + await client.protocol.versionUpgradeVoteStatusWithProof(bytes, 4); + expect(getProtocolVersionUpgradeVoteStatusWithProofInfoStub).to.be.calledWith(bytes, 4); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/system.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/system.spec.mjs deleted file mode 100644 index 3b5c3e83431..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/system.spec.mjs +++ /dev/null @@ -1,45 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('SystemFacade', () => { - let wasmSdk; - let client; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - this.sinon.stub(wasmSdk, 'getStatus').resolves('ok'); - this.sinon.stub(wasmSdk, 'getCurrentQuorumsInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getTotalCreditsInPlatform').resolves('ok'); - this.sinon.stub(wasmSdk, 'getTotalCreditsInPlatformWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'getPrefundedSpecializedBalance').resolves('ok'); - this.sinon.stub(wasmSdk, 'getPrefundedSpecializedBalanceWithProofInfo').resolves('ok'); - this.sinon.stub(wasmSdk, 'waitForStateTransitionResult').resolves('ok'); - this.sinon.stub(wasmSdk, 'getPathElements').resolves('ok'); - this.sinon.stub(wasmSdk, 'getPathElementsWithProofInfo').resolves('ok'); - }); - - it('forwards all methods to instance methods', async () => { - await client.system.status(); - await client.system.currentQuorumsInfo(); - await client.system.totalCreditsInPlatform(); - await client.system.totalCreditsInPlatformWithProof(); - await client.system.prefundedSpecializedBalance('i'); - await client.system.prefundedSpecializedBalanceWithProof('i'); - await client.system.waitForStateTransitionResult('h'); - await client.system.pathElements(['p'], ['k']); - await client.system.pathElementsWithProof(['p2'], ['k2']); - expect(wasmSdk.getStatus).to.be.calledOnce(); - expect(wasmSdk.getCurrentQuorumsInfo).to.be.calledOnce(); - expect(wasmSdk.getTotalCreditsInPlatform).to.be.calledOnce(); - expect(wasmSdk.getTotalCreditsInPlatformWithProofInfo).to.be.calledOnce(); - expect(wasmSdk.getPrefundedSpecializedBalance).to.be.calledOnce(); - expect(wasmSdk.getPrefundedSpecializedBalanceWithProofInfo).to.be.calledOnce(); - expect(wasmSdk.waitForStateTransitionResult).to.be.calledOnce(); - expect(wasmSdk.getPathElements).to.be.calledOnce(); - expect(wasmSdk.getPathElementsWithProofInfo).to.be.calledOnce(); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/system.spec.ts b/packages/js-evo-sdk/tests/unit/facades/system.spec.ts new file mode 100644 index 00000000000..d7cc688eb40 --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/system.spec.ts @@ -0,0 +1,99 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('SystemFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + + // Stub references for type-safe assertions + let getStatusStub: SinonStub; + let getCurrentQuorumsInfoStub: SinonStub; + let getTotalCreditsInPlatformStub: SinonStub; + let getTotalCreditsInPlatformWithProofInfoStub: SinonStub; + let getPrefundedSpecializedBalanceStub: SinonStub; + let getPrefundedSpecializedBalanceWithProofInfoStub: SinonStub; + let waitForStateTransitionResultStub: SinonStub; + let getPathElementsStub: SinonStub; + let getPathElementsWithProofInfoStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + getStatusStub = this.sinon.stub(wasmSdk, 'getStatus').resolves('ok'); + getCurrentQuorumsInfoStub = this.sinon.stub(wasmSdk, 'getCurrentQuorumsInfo').resolves('ok'); + getTotalCreditsInPlatformStub = this.sinon.stub(wasmSdk, 'getTotalCreditsInPlatform').resolves('ok'); + getTotalCreditsInPlatformWithProofInfoStub = this.sinon.stub(wasmSdk, 'getTotalCreditsInPlatformWithProofInfo').resolves('ok'); + getPrefundedSpecializedBalanceStub = this.sinon.stub(wasmSdk, 'getPrefundedSpecializedBalance').resolves('ok'); + getPrefundedSpecializedBalanceWithProofInfoStub = this.sinon.stub(wasmSdk, 'getPrefundedSpecializedBalanceWithProofInfo').resolves('ok'); + waitForStateTransitionResultStub = this.sinon.stub(wasmSdk, 'waitForStateTransitionResult').resolves('ok'); + getPathElementsStub = this.sinon.stub(wasmSdk, 'getPathElements').resolves('ok'); + getPathElementsWithProofInfoStub = this.sinon.stub(wasmSdk, 'getPathElementsWithProofInfo').resolves('ok'); + }); + + describe('status()', () => { + it('should forward to getStatus', async () => { + await client.system.status(); + expect(getStatusStub).to.be.calledOnce(); + }); + }); + + describe('currentQuorumsInfo()', () => { + it('should forward to getCurrentQuorumsInfo', async () => { + await client.system.currentQuorumsInfo(); + expect(getCurrentQuorumsInfoStub).to.be.calledOnce(); + }); + }); + + describe('totalCreditsInPlatform()', () => { + it('should forward to getTotalCreditsInPlatform', async () => { + await client.system.totalCreditsInPlatform(); + expect(getTotalCreditsInPlatformStub).to.be.calledOnce(); + }); + }); + + describe('totalCreditsInPlatformWithProof()', () => { + it('should forward to getTotalCreditsInPlatformWithProofInfo', async () => { + await client.system.totalCreditsInPlatformWithProof(); + expect(getTotalCreditsInPlatformWithProofInfoStub).to.be.calledOnce(); + }); + }); + + describe('prefundedSpecializedBalance()', () => { + it('should forward to getPrefundedSpecializedBalance', async () => { + await client.system.prefundedSpecializedBalance('i'); + expect(getPrefundedSpecializedBalanceStub).to.be.calledOnce(); + }); + }); + + describe('prefundedSpecializedBalanceWithProof()', () => { + it('should forward to getPrefundedSpecializedBalanceWithProofInfo', async () => { + await client.system.prefundedSpecializedBalanceWithProof('i'); + expect(getPrefundedSpecializedBalanceWithProofInfoStub).to.be.calledOnce(); + }); + }); + + describe('waitForStateTransitionResult()', () => { + it('should forward to waitForStateTransitionResult', async () => { + await client.system.waitForStateTransitionResult('h'); + expect(waitForStateTransitionResultStub).to.be.calledOnce(); + }); + }); + + describe('pathElements()', () => { + it('should forward to getPathElements', async () => { + await client.system.pathElements(['p'], ['k']); + expect(getPathElementsStub).to.be.calledOnce(); + }); + }); + + describe('pathElementsWithProof()', () => { + it('should forward to getPathElementsWithProofInfo', async () => { + await client.system.pathElementsWithProof(['p2'], ['k2']); + expect(getPathElementsWithProofInfoStub).to.be.calledOnce(); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/tokens.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/tokens.spec.mjs deleted file mode 100644 index 6b454d6f901..00000000000 --- a/packages/js-evo-sdk/tests/unit/facades/tokens.spec.mjs +++ /dev/null @@ -1,441 +0,0 @@ -import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; -import { EvoSDK } from '../../../dist/sdk.js'; - -describe('TokensFacade', () => { - let wasmSdk; - let client; - let identityKey; - let signer; - - // Realistic identifiers - const contractId = 'Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv'; - const tokenId = 'BpJvvpPiR2obh7ueZixjtYXsmWQdgJhiZtQJWjD7Ruus'; - const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; - const recipientId = '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack'; - - beforeEach(async function setup() { - await init(); - const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); - client = EvoSDK.fromWasm(wasmSdk); - - // Create mock objects - identityKey = Object.create(wasmSDKPackage.IdentityPublicKey.prototype); - signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); - - // Stub query methods - this.sinon.stub(wasmSdk, 'getTokenPriceByContract').resolves({ - price: BigInt(1000000), - currencyId: tokenId, - }); - this.sinon.stub(wasmSdk, 'getTokenTotalSupply').resolves({ - totalSupply: BigInt(1000000000), - tokenId, - }); - this.sinon.stub(wasmSdk, 'getTokenTotalSupplyWithProofInfo').resolves({ - data: { totalSupply: BigInt(1000000000), tokenId }, - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getTokenStatuses').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getTokenStatusesWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentitiesTokenBalances').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getIdentitiesTokenBalancesWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityTokenBalances').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getIdentityTokenBalancesWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentityTokenInfos').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getIdentitiesTokenInfos').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getIdentityTokenInfosWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getIdentitiesTokenInfosWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getTokenDirectPurchasePrices').resolves(new Map()); - this.sinon.stub(wasmSdk, 'getTokenDirectPurchasePricesWithProofInfo').resolves({ - data: new Map(), - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getTokenContractInfo').resolves({ - contractId, - tokenPosition: 0, - }); - this.sinon.stub(wasmSdk, 'getTokenContractInfoWithProofInfo').resolves({ - data: { contractId, tokenPosition: 0 }, - proof: {}, - metadata: {}, - }); - this.sinon.stub(wasmSdk, 'getTokenPerpetualDistributionLastClaim').resolves(undefined); - this.sinon.stub(wasmSdk, 'getTokenPerpetualDistributionLastClaimWithProofInfo').resolves({ - data: undefined, - proof: {}, - metadata: {}, - }); - - // Stub transition methods - all return result objects - this.sinon.stub(wasmSdk, 'tokenMint').resolves({ - tokenId, - balance: BigInt(100000000), - }); - this.sinon.stub(wasmSdk, 'tokenBurn').resolves({ - tokenId, - balance: BigInt(50000000), - }); - this.sinon.stub(wasmSdk, 'tokenTransfer').resolves({ - tokenId, - senderBalance: BigInt(40000000), - recipientBalance: BigInt(60000000), - }); - this.sinon.stub(wasmSdk, 'tokenFreeze').resolves({ tokenId }); - this.sinon.stub(wasmSdk, 'tokenUnfreeze').resolves({ tokenId }); - this.sinon.stub(wasmSdk, 'tokenDestroyFrozen').resolves({ tokenId }); - this.sinon.stub(wasmSdk, 'tokenEmergencyAction').resolves({ tokenId }); - this.sinon.stub(wasmSdk, 'tokenSetPrice').resolves({ tokenId }); - this.sinon.stub(wasmSdk, 'tokenDirectPurchase').resolves({ - tokenId, - balance: BigInt(10000000), - }); - this.sinon.stub(wasmSdk, 'tokenClaim').resolves({ - tokenId, - claimedAmount: BigInt(5000000), - }); - }); - - describe('Static Methods', () => { - it('calculateId() computes token ID from contract ID and position', async () => { - const result = await client.tokens.calculateId(contractId, 0); - expect(result).to.equal(tokenId); - }); - }); - - describe('Query Methods', () => { - it('priceByContract() fetches token price by contract ID', async () => { - const tokenPosition = 0; - - await client.tokens.priceByContract(contractId, tokenPosition); - - expect(wasmSdk.getTokenPriceByContract) - .to.be.calledOnceWithExactly(contractId, tokenPosition); - }); - - it('totalSupply() fetches total supply of a token', async () => { - await client.tokens.totalSupply(tokenId); - - expect(wasmSdk.getTokenTotalSupply).to.be.calledOnceWithExactly(tokenId); - }); - - it('totalSupplyWithProof() fetches total supply with proof', async () => { - await client.tokens.totalSupplyWithProof(tokenId); - - expect(wasmSdk.getTokenTotalSupplyWithProofInfo).to.be.calledOnceWithExactly(tokenId); - }); - - it('statuses() fetches statuses for multiple tokens', async () => { - const tokenIds = [tokenId, 'AnotherTokenId123456789abcdefghijklmnop']; - - await client.tokens.statuses(tokenIds); - - expect(wasmSdk.getTokenStatuses).to.be.calledOnceWithExactly(tokenIds); - }); - - it('statusesWithProof() fetches token statuses with proof', async () => { - const tokenIds = [tokenId]; - - await client.tokens.statusesWithProof(tokenIds); - - expect(wasmSdk.getTokenStatusesWithProofInfo).to.be.calledOnceWithExactly(tokenIds); - }); - - it('balances() fetches token balances for multiple identities', async () => { - const identityIds = [identityId, recipientId]; - - await client.tokens.balances(identityIds, tokenId); - - expect(wasmSdk.getIdentitiesTokenBalances).to.be.calledOnceWithExactly(identityIds, tokenId); - }); - - it('balancesWithProof() fetches identity balances with proof', async () => { - const identityIds = [identityId]; - - await client.tokens.balancesWithProof(identityIds, tokenId); - - expect(wasmSdk.getIdentitiesTokenBalancesWithProofInfo) - .to.be.calledOnceWithExactly(identityIds, tokenId); - }); - - it('identityBalances() fetches balances for multiple tokens of one identity', async () => { - const tokenIds = [tokenId]; - - await client.tokens.identityBalances(identityId, tokenIds); - - expect(wasmSdk.getIdentityTokenBalances).to.be.calledOnceWithExactly(identityId, tokenIds); - }); - - it('identityBalancesWithProof() fetches identity token balances with proof', async () => { - const tokenIds = [tokenId]; - - await client.tokens.identityBalancesWithProof(identityId, tokenIds); - - expect(wasmSdk.getIdentityTokenBalancesWithProofInfo) - .to.be.calledOnceWithExactly(identityId, tokenIds); - }); - - it('identityTokenInfos() fetches token info for an identity', async () => { - const tokenIds = [tokenId, 'AnotherTokenId123456789abcdefghijklmnop']; - - await client.tokens.identityTokenInfos(identityId, tokenIds); - - expect(wasmSdk.getIdentityTokenInfos).to.be.calledOnceWithExactly(identityId, tokenIds); - }); - - it('identitiesTokenInfos() fetches token info for multiple identities', async () => { - const identityIds = [identityId]; - - await client.tokens.identitiesTokenInfos(identityIds, tokenId); - - expect(wasmSdk.getIdentitiesTokenInfos).to.be.calledOnceWithExactly(identityIds, tokenId); - }); - - it('identityTokenInfosWithProof() fetches token info with proof', async () => { - const tokenIds = [tokenId]; - - await client.tokens.identityTokenInfosWithProof(identityId, tokenIds); - - expect(wasmSdk.getIdentityTokenInfosWithProofInfo) - .to.be.calledOnceWithExactly(identityId, tokenIds); - }); - - it('identitiesTokenInfosWithProof() fetches multiple identities info with proof', async () => { - const identityIds = [identityId]; - - await client.tokens.identitiesTokenInfosWithProof(identityIds, tokenId); - - expect(wasmSdk.getIdentitiesTokenInfosWithProofInfo) - .to.be.calledOnceWithExactly(identityIds, tokenId); - }); - - it('directPurchasePrices() fetches purchase prices for tokens', async () => { - const tokenIds = [tokenId]; - - await client.tokens.directPurchasePrices(tokenIds); - - expect(wasmSdk.getTokenDirectPurchasePrices).to.be.calledOnceWithExactly(tokenIds); - }); - - it('directPurchasePricesWithProof() fetches purchase prices with proof', async () => { - const tokenIds = [tokenId]; - - await client.tokens.directPurchasePricesWithProof(tokenIds); - - expect(wasmSdk.getTokenDirectPurchasePricesWithProofInfo) - .to.be.calledOnceWithExactly(tokenIds); - }); - - it('contractInfo() fetches token contract information', async () => { - await client.tokens.contractInfo(contractId); - - expect(wasmSdk.getTokenContractInfo).to.be.calledOnceWithExactly(contractId); - }); - - it('contractInfoWithProof() fetches contract info with proof', async () => { - await client.tokens.contractInfoWithProof(contractId); - - expect(wasmSdk.getTokenContractInfoWithProofInfo).to.be.calledOnceWithExactly(contractId); - }); - - it('perpetualDistributionLastClaim() fetches last claim time', async () => { - await client.tokens.perpetualDistributionLastClaim(identityId, tokenId); - - expect(wasmSdk.getTokenPerpetualDistributionLastClaim) - .to.be.calledOnceWithExactly(identityId, tokenId); - }); - - it('perpetualDistributionLastClaimWithProof() fetches last claim with proof', async () => { - await client.tokens.perpetualDistributionLastClaimWithProof(identityId, tokenId); - - expect(wasmSdk.getTokenPerpetualDistributionLastClaimWithProofInfo) - .to.be.calledOnceWithExactly(identityId, tokenId); - }); - }); - - describe('Transition Methods', () => { - it('mint() mints new tokens to an identity', async () => { - const options = { - tokenId, - amount: BigInt(50000000), // 50M tokens - recipientId, - identityKey, - signer, - publicNote: 'Initial token distribution', - }; - - const result = await client.tokens.mint(options); - - expect(wasmSdk.tokenMint).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - expect(result.balance).to.equal(BigInt(100000000)); - }); - - it('burn() burns tokens from an identity', async () => { - const options = { - tokenId, - amount: BigInt(10000000), // 10M tokens - identityKey, - signer, - publicNote: 'Token buyback and burn', - }; - - const result = await client.tokens.burn(options); - - expect(wasmSdk.tokenBurn).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - expect(result.balance).to.equal(BigInt(50000000)); - }); - - it('transfer() transfers tokens between identities', async () => { - const options = { - tokenId, - amount: BigInt(25000000), // 25M tokens - recipientId, - identityKey, - signer, - publicNote: 'Payment for services', - }; - - const result = await client.tokens.transfer(options); - - expect(wasmSdk.tokenTransfer).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - expect(result.senderBalance).to.equal(BigInt(40000000)); - expect(result.recipientBalance).to.equal(BigInt(60000000)); - }); - - it('freeze() freezes tokens for an identity', async () => { - const frozenIdentityId = recipientId; - const options = { - tokenId, - frozenIdentityId, - identityKey, - signer, - publicNote: 'Account frozen for compliance review', - }; - - const result = await client.tokens.freeze(options); - - expect(wasmSdk.tokenFreeze).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - }); - - it('unfreeze() unfreezes previously frozen tokens', async () => { - const frozenIdentityId = recipientId; - const options = { - tokenId, - frozenIdentityId, - identityKey, - signer, - publicNote: 'Compliance review completed', - }; - - const result = await client.tokens.unfreeze(options); - - expect(wasmSdk.tokenUnfreeze).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - }); - - it('destroyFrozen() destroys frozen tokens', async () => { - const frozenIdentityId = recipientId; - const options = { - tokenId, - frozenIdentityId, - identityKey, - signer, - publicNote: 'Fraudulent tokens destroyed', - }; - - const result = await client.tokens.destroyFrozen(options); - - expect(wasmSdk.tokenDestroyFrozen).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - }); - - it('emergencyAction() executes emergency token action', async () => { - const options = { - tokenId, - action: 'pause', - identityKey, - signer, - publicNote: 'Emergency pause due to security concern', - }; - - const result = await client.tokens.emergencyAction(options); - - expect(wasmSdk.tokenEmergencyAction).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - }); - - it('setPrice() sets direct purchase price for tokens', async () => { - const options = { - tokenId, - price: { - type: 'fixed', - value: BigInt(1000000), // 1M credits per token - }, - identityKey, - signer, - }; - - const result = await client.tokens.setPrice(options); - - expect(wasmSdk.tokenSetPrice).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - }); - - it('directPurchase() purchases tokens directly', async () => { - const options = { - tokenId, - amount: BigInt(5000000), // 5M tokens - totalAgreedPrice: BigInt(5000000000), // 5B credits - identityKey, - signer, - }; - - const result = await client.tokens.directPurchase(options); - - expect(wasmSdk.tokenDirectPurchase).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - expect(result.balance).to.equal(BigInt(10000000)); - }); - - it('claim() claims token distribution rewards', async () => { - const options = { - tokenId, - identityKey, - signer, - publicNote: 'Claiming weekly distribution', - }; - - const result = await client.tokens.claim(options); - - expect(wasmSdk.tokenClaim).to.be.calledOnceWithExactly(options); - expect(result.tokenId).to.equal(tokenId); - expect(result.claimedAmount).to.equal(BigInt(5000000)); - }); - }); -}); diff --git a/packages/js-evo-sdk/tests/unit/facades/tokens.spec.ts b/packages/js-evo-sdk/tests/unit/facades/tokens.spec.ts new file mode 100644 index 00000000000..bf7cc0e9079 --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/facades/tokens.spec.ts @@ -0,0 +1,527 @@ +import type { SinonStub } from 'sinon'; +import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; +import { EvoSDK } from '../../../dist/sdk.js'; + +describe('TokensFacade', () => { + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + let identityKey: wasmSDKPackage.IdentityPublicKey; + let signer: wasmSDKPackage.IdentitySigner; + + // Realistic identifiers + const contractId = 'Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv'; + const tokenId = 'BpJvvpPiR2obh7ueZixjtYXsmWQdgJhiZtQJWjD7Ruus'; + const identityId = '5mjGWa9mruHnLBht3ntBi8CZ6sNk3hZZsQMgTvgQobjS'; + const recipientId = '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack'; + + // Stub references for type-safe assertions + let getTokenPriceByContractStub: SinonStub; + let getTokenTotalSupplyStub: SinonStub; + let getTokenTotalSupplyWithProofInfoStub: SinonStub; + let getTokenStatusesStub: SinonStub; + let getTokenStatusesWithProofInfoStub: SinonStub; + let getIdentitiesTokenBalancesStub: SinonStub; + let getIdentitiesTokenBalancesWithProofInfoStub: SinonStub; + let getIdentityTokenBalancesStub: SinonStub; + let getIdentityTokenBalancesWithProofInfoStub: SinonStub; + let getIdentityTokenInfosStub: SinonStub; + let getIdentitiesTokenInfosStub: SinonStub; + let getIdentityTokenInfosWithProofInfoStub: SinonStub; + let getIdentitiesTokenInfosWithProofInfoStub: SinonStub; + let getTokenDirectPurchasePricesStub: SinonStub; + let getTokenDirectPurchasePricesWithProofInfoStub: SinonStub; + let getTokenContractInfoStub: SinonStub; + let getTokenContractInfoWithProofInfoStub: SinonStub; + let getTokenPerpetualDistributionLastClaimStub: SinonStub; + let getTokenPerpetualDistributionLastClaimWithProofInfoStub: SinonStub; + let tokenMintStub: SinonStub; + let tokenBurnStub: SinonStub; + let tokenTransferStub: SinonStub; + let tokenFreezeStub: SinonStub; + let tokenUnfreezeStub: SinonStub; + let tokenDestroyFrozenStub: SinonStub; + let tokenEmergencyActionStub: SinonStub; + let tokenSetPriceStub: SinonStub; + let tokenDirectPurchaseStub: SinonStub; + let tokenClaimStub: SinonStub; + + beforeEach(async function setup() { + await init(); + const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); + wasmSdk = await builder.build(); + client = EvoSDK.fromWasm(wasmSdk); + + // Create mock objects + identityKey = Object.create(wasmSDKPackage.IdentityPublicKey.prototype); + signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); + + // Stub query methods + getTokenPriceByContractStub = this.sinon.stub(wasmSdk, 'getTokenPriceByContract').resolves({ + price: BigInt(1000000), + currencyId: tokenId, + }); + getTokenTotalSupplyStub = this.sinon.stub(wasmSdk, 'getTokenTotalSupply').resolves({ + totalSupply: BigInt(1000000000), + tokenId, + }); + getTokenTotalSupplyWithProofInfoStub = this.sinon.stub(wasmSdk, 'getTokenTotalSupplyWithProofInfo').resolves({ + data: { totalSupply: BigInt(1000000000), tokenId }, + proof: {}, + metadata: {}, + }); + getTokenStatusesStub = this.sinon.stub(wasmSdk, 'getTokenStatuses').resolves(new Map()); + getTokenStatusesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getTokenStatusesWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getIdentitiesTokenBalancesStub = this.sinon.stub(wasmSdk, 'getIdentitiesTokenBalances').resolves(new Map()); + getIdentitiesTokenBalancesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentitiesTokenBalancesWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getIdentityTokenBalancesStub = this.sinon.stub(wasmSdk, 'getIdentityTokenBalances').resolves(new Map()); + getIdentityTokenBalancesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityTokenBalancesWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getIdentityTokenInfosStub = this.sinon.stub(wasmSdk, 'getIdentityTokenInfos').resolves(new Map()); + getIdentitiesTokenInfosStub = this.sinon.stub(wasmSdk, 'getIdentitiesTokenInfos').resolves(new Map()); + getIdentityTokenInfosWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentityTokenInfosWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getIdentitiesTokenInfosWithProofInfoStub = this.sinon.stub(wasmSdk, 'getIdentitiesTokenInfosWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getTokenDirectPurchasePricesStub = this.sinon.stub(wasmSdk, 'getTokenDirectPurchasePrices').resolves(new Map()); + getTokenDirectPurchasePricesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getTokenDirectPurchasePricesWithProofInfo').resolves({ + data: new Map(), + proof: {}, + metadata: {}, + }); + getTokenContractInfoStub = this.sinon.stub(wasmSdk, 'getTokenContractInfo').resolves({ + contractId, + tokenPosition: 0, + }); + getTokenContractInfoWithProofInfoStub = this.sinon.stub(wasmSdk, 'getTokenContractInfoWithProofInfo').resolves({ + data: { contractId, tokenPosition: 0 }, + proof: {}, + metadata: {}, + }); + getTokenPerpetualDistributionLastClaimStub = this.sinon.stub(wasmSdk, 'getTokenPerpetualDistributionLastClaim').resolves(undefined); + getTokenPerpetualDistributionLastClaimWithProofInfoStub = this.sinon.stub(wasmSdk, 'getTokenPerpetualDistributionLastClaimWithProofInfo').resolves({ + data: undefined, + proof: {}, + metadata: {}, + }); + + // Stub transition methods - all return result objects + tokenMintStub = this.sinon.stub(wasmSdk, 'tokenMint').resolves({ + tokenId, + balance: BigInt(100000000), + }); + tokenBurnStub = this.sinon.stub(wasmSdk, 'tokenBurn').resolves({ + tokenId, + balance: BigInt(50000000), + }); + tokenTransferStub = this.sinon.stub(wasmSdk, 'tokenTransfer').resolves({ + tokenId, + senderBalance: BigInt(40000000), + recipientBalance: BigInt(60000000), + }); + tokenFreezeStub = this.sinon.stub(wasmSdk, 'tokenFreeze').resolves({ tokenId }); + tokenUnfreezeStub = this.sinon.stub(wasmSdk, 'tokenUnfreeze').resolves({ tokenId }); + tokenDestroyFrozenStub = this.sinon.stub(wasmSdk, 'tokenDestroyFrozen').resolves({ tokenId }); + tokenEmergencyActionStub = this.sinon.stub(wasmSdk, 'tokenEmergencyAction').resolves({ tokenId }); + tokenSetPriceStub = this.sinon.stub(wasmSdk, 'tokenSetPrice').resolves({ tokenId }); + tokenDirectPurchaseStub = this.sinon.stub(wasmSdk, 'tokenDirectPurchase').resolves({ + tokenId, + balance: BigInt(10000000), + }); + tokenClaimStub = this.sinon.stub(wasmSdk, 'tokenClaim').resolves({ + tokenId, + claimedAmount: BigInt(5000000), + }); + }); + + describe('calculateId()', () => { + it('should compute token ID from contract ID and position', async () => { + const result = await client.tokens.calculateId(contractId, 0); + expect(result).to.equal(tokenId); + }); + }); + + describe('priceByContract()', () => { + it('should fetch token price by contract ID', async () => { + const tokenPosition = 0; + + await client.tokens.priceByContract(contractId, tokenPosition); + + expect(getTokenPriceByContractStub) + .to.be.calledOnceWithExactly(contractId, tokenPosition); + }); + }); + + describe('totalSupply()', () => { + it('should fetch total supply of a token', async () => { + await client.tokens.totalSupply(tokenId); + + expect(getTokenTotalSupplyStub).to.be.calledOnceWithExactly(tokenId); + }); + }); + + describe('totalSupplyWithProof()', () => { + it('should fetch total supply with proof', async () => { + await client.tokens.totalSupplyWithProof(tokenId); + + expect(getTokenTotalSupplyWithProofInfoStub).to.be.calledOnceWithExactly(tokenId); + }); + }); + + describe('statuses()', () => { + it('should fetch statuses for multiple tokens', async () => { + const tokenIds = [tokenId, 'AnotherTokenId123456789abcdefghijklmnop']; + + await client.tokens.statuses(tokenIds); + + expect(getTokenStatusesStub).to.be.calledOnceWithExactly(tokenIds); + }); + }); + + describe('statusesWithProof()', () => { + it('should fetch token statuses with proof', async () => { + const tokenIds = [tokenId]; + + await client.tokens.statusesWithProof(tokenIds); + + expect(getTokenStatusesWithProofInfoStub).to.be.calledOnceWithExactly(tokenIds); + }); + }); + + describe('balances()', () => { + it('should fetch token balances for multiple identities', async () => { + const identityIds = [identityId, recipientId]; + + await client.tokens.balances(identityIds, tokenId); + + expect(getIdentitiesTokenBalancesStub).to.be.calledOnceWithExactly(identityIds, tokenId); + }); + }); + + describe('balancesWithProof()', () => { + it('should fetch identity balances with proof', async () => { + const identityIds = [identityId]; + + await client.tokens.balancesWithProof(identityIds, tokenId); + + expect(getIdentitiesTokenBalancesWithProofInfoStub) + .to.be.calledOnceWithExactly(identityIds, tokenId); + }); + }); + + describe('identityBalances()', () => { + it('should fetch balances for multiple tokens of one identity', async () => { + const tokenIds = [tokenId]; + + await client.tokens.identityBalances(identityId, tokenIds); + + expect(getIdentityTokenBalancesStub).to.be.calledOnceWithExactly(identityId, tokenIds); + }); + }); + + describe('identityBalancesWithProof()', () => { + it('should fetch identity token balances with proof', async () => { + const tokenIds = [tokenId]; + + await client.tokens.identityBalancesWithProof(identityId, tokenIds); + + expect(getIdentityTokenBalancesWithProofInfoStub) + .to.be.calledOnceWithExactly(identityId, tokenIds); + }); + }); + + describe('identityTokenInfos()', () => { + it('should fetch token info for an identity', async () => { + const tokenIds = [tokenId, 'AnotherTokenId123456789abcdefghijklmnop']; + + await client.tokens.identityTokenInfos(identityId, tokenIds); + + expect(getIdentityTokenInfosStub).to.be.calledOnceWithExactly(identityId, tokenIds); + }); + }); + + describe('identitiesTokenInfos()', () => { + it('should fetch token info for multiple identities', async () => { + const identityIds = [identityId]; + + await client.tokens.identitiesTokenInfos(identityIds, tokenId); + + expect(getIdentitiesTokenInfosStub).to.be.calledOnceWithExactly(identityIds, tokenId); + }); + }); + + describe('identityTokenInfosWithProof()', () => { + it('should fetch token info with proof', async () => { + const tokenIds = [tokenId]; + + await client.tokens.identityTokenInfosWithProof(identityId, tokenIds); + + expect(getIdentityTokenInfosWithProofInfoStub) + .to.be.calledOnceWithExactly(identityId, tokenIds); + }); + }); + + describe('identitiesTokenInfosWithProof()', () => { + it('should fetch multiple identities info with proof', async () => { + const identityIds = [identityId]; + + await client.tokens.identitiesTokenInfosWithProof(identityIds, tokenId); + + expect(getIdentitiesTokenInfosWithProofInfoStub) + .to.be.calledOnceWithExactly(identityIds, tokenId); + }); + }); + + describe('directPurchasePrices()', () => { + it('should fetch purchase prices for tokens', async () => { + const tokenIds = [tokenId]; + + await client.tokens.directPurchasePrices(tokenIds); + + expect(getTokenDirectPurchasePricesStub).to.be.calledOnceWithExactly(tokenIds); + }); + }); + + describe('directPurchasePricesWithProof()', () => { + it('should fetch purchase prices with proof', async () => { + const tokenIds = [tokenId]; + + await client.tokens.directPurchasePricesWithProof(tokenIds); + + expect(getTokenDirectPurchasePricesWithProofInfoStub) + .to.be.calledOnceWithExactly(tokenIds); + }); + }); + + describe('contractInfo()', () => { + it('should fetch token contract information', async () => { + await client.tokens.contractInfo(contractId); + + expect(getTokenContractInfoStub).to.be.calledOnceWithExactly(contractId); + }); + }); + + describe('contractInfoWithProof()', () => { + it('should fetch contract info with proof', async () => { + await client.tokens.contractInfoWithProof(contractId); + + expect(getTokenContractInfoWithProofInfoStub).to.be.calledOnceWithExactly(contractId); + }); + }); + + describe('perpetualDistributionLastClaim()', () => { + it('should fetch last claim time', async () => { + await client.tokens.perpetualDistributionLastClaim(identityId, tokenId); + + expect(getTokenPerpetualDistributionLastClaimStub) + .to.be.calledOnceWithExactly(identityId, tokenId); + }); + }); + + describe('perpetualDistributionLastClaimWithProof()', () => { + it('should fetch last claim with proof', async () => { + await client.tokens.perpetualDistributionLastClaimWithProof(identityId, tokenId); + + expect(getTokenPerpetualDistributionLastClaimWithProofInfoStub) + .to.be.calledOnceWithExactly(identityId, tokenId); + }); + }); + + describe('mint()', () => { + it('should mint new tokens to an identity', async () => { + const options = { + tokenId, + amount: BigInt(50000000), // 50M tokens + recipientId, + identityKey, + signer, + publicNote: 'Initial token distribution', + }; + + const result = await client.tokens.mint(options); + + expect(tokenMintStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + expect(result.balance).to.equal(BigInt(100000000)); + }); + }); + + describe('burn()', () => { + it('should burn tokens from an identity', async () => { + const options = { + tokenId, + amount: BigInt(10000000), // 10M tokens + identityKey, + signer, + publicNote: 'Token buyback and burn', + }; + + const result = await client.tokens.burn(options); + + expect(tokenBurnStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + expect(result.balance).to.equal(BigInt(50000000)); + }); + }); + + describe('transfer()', () => { + it('should transfer tokens between identities', async () => { + const options = { + tokenId, + amount: BigInt(25000000), // 25M tokens + recipientId, + identityKey, + signer, + publicNote: 'Payment for services', + }; + + const result = await client.tokens.transfer(options); + + expect(tokenTransferStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + expect(result.senderBalance).to.equal(BigInt(40000000)); + expect(result.recipientBalance).to.equal(BigInt(60000000)); + }); + }); + + describe('freeze()', () => { + it('should freeze tokens for an identity', async () => { + const frozenIdentityId = recipientId; + const options = { + tokenId, + frozenIdentityId, + identityKey, + signer, + publicNote: 'Account frozen for compliance review', + }; + + const result = await client.tokens.freeze(options); + + expect(tokenFreezeStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + }); + }); + + describe('unfreeze()', () => { + it('should unfreeze previously frozen tokens', async () => { + const frozenIdentityId = recipientId; + const options = { + tokenId, + frozenIdentityId, + identityKey, + signer, + publicNote: 'Compliance review completed', + }; + + const result = await client.tokens.unfreeze(options); + + expect(tokenUnfreezeStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + }); + }); + + describe('destroyFrozen()', () => { + it('should destroy frozen tokens', async () => { + const frozenIdentityId = recipientId; + const options = { + tokenId, + frozenIdentityId, + identityKey, + signer, + publicNote: 'Fraudulent tokens destroyed', + }; + + const result = await client.tokens.destroyFrozen(options); + + expect(tokenDestroyFrozenStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + }); + }); + + describe('emergencyAction()', () => { + it('should execute emergency token action', async () => { + const options = { + tokenId, + action: 'pause', + identityKey, + signer, + publicNote: 'Emergency pause due to security concern', + }; + + const result = await client.tokens.emergencyAction(options); + + expect(tokenEmergencyActionStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + }); + }); + + describe('setPrice()', () => { + it('should set direct purchase price for tokens', async () => { + const options = { + tokenId, + price: { + type: 'fixed', + value: BigInt(1000000), // 1M credits per token + }, + identityKey, + signer, + }; + + const result = await client.tokens.setPrice(options); + + expect(tokenSetPriceStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + }); + }); + + describe('directPurchase()', () => { + it('should purchase tokens directly', async () => { + const options = { + tokenId, + amount: BigInt(5000000), // 5M tokens + totalAgreedPrice: BigInt(5000000000), // 5B credits + identityKey, + signer, + }; + + const result = await client.tokens.directPurchase(options); + + expect(tokenDirectPurchaseStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + expect(result.balance).to.equal(BigInt(10000000)); + }); + }); + + describe('claim()', () => { + it('should claim token distribution rewards', async () => { + const options = { + tokenId, + identityKey, + signer, + publicNote: 'Claiming weekly distribution', + }; + + const result = await client.tokens.claim(options); + + expect(tokenClaimStub).to.be.calledOnceWithExactly(options); + expect(result.tokenId).to.equal(tokenId); + expect(result.claimedAmount).to.equal(BigInt(5000000)); + }); + }); +}); diff --git a/packages/js-evo-sdk/tests/unit/facades/voting.spec.mjs b/packages/js-evo-sdk/tests/unit/facades/voting.spec.ts similarity index 57% rename from packages/js-evo-sdk/tests/unit/facades/voting.spec.mjs rename to packages/js-evo-sdk/tests/unit/facades/voting.spec.ts index 2cdcae250e5..ed164fa03c7 100644 --- a/packages/js-evo-sdk/tests/unit/facades/voting.spec.mjs +++ b/packages/js-evo-sdk/tests/unit/facades/voting.spec.ts @@ -1,10 +1,11 @@ +import type { SinonStub } from 'sinon'; import init, * as wasmSDKPackage from '@dashevo/wasm-sdk'; import { EvoSDK } from '../../../dist/sdk.js'; describe('VotingFacade', () => { - let wasmSdk; - let client; - let signer; + let wasmSdk: wasmSDKPackage.WasmSdk; + let client: EvoSDK; + let signer: wasmSDKPackage.IdentitySigner; // Realistic identifiers const dataContractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; @@ -12,22 +13,31 @@ describe('VotingFacade', () => { const contenderId = '6o4vL6YpPjamqnnPNpwNSspYJdhPpzYbXvAJ4PYH7Ack'; const masternodeProTxHash = 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2'; + // Stub references for type-safe assertions + let getContestedResourceVoteStateStub: SinonStub; + let getContestedResourceVoteStateWithProofInfoStub: SinonStub; + let getContestedResourceIdentityVotesStub: SinonStub; + let getContestedResourceIdentityVotesWithProofInfoStub: SinonStub; + let getVotePollsByEndDateStub: SinonStub; + let getVotePollsByEndDateWithProofInfoStub: SinonStub; + let masternodeVoteStub: SinonStub; + beforeEach(async function setup() { await init(); const builder = wasmSDKPackage.WasmSdkBuilder.testnetTrusted(); - wasmSdk = builder.build(); + wasmSdk = await builder.build(); client = EvoSDK.fromWasm(wasmSdk); // Create mock objects signer = Object.create(wasmSDKPackage.IdentitySigner.prototype); // Stub query methods - this.sinon.stub(wasmSdk, 'getContestedResourceVoteState').resolves({ + getContestedResourceVoteStateStub = this.sinon.stub(wasmSdk, 'getContestedResourceVoteState').resolves({ contenders: new Map(), abstainVoteCount: 0, lockVoteCount: 0, }); - this.sinon.stub(wasmSdk, 'getContestedResourceVoteStateWithProofInfo').resolves({ + getContestedResourceVoteStateWithProofInfoStub = this.sinon.stub(wasmSdk, 'getContestedResourceVoteStateWithProofInfo').resolves({ data: { contenders: new Map(), abstainVoteCount: 0, @@ -36,27 +46,27 @@ describe('VotingFacade', () => { proof: {}, metadata: {}, }); - this.sinon.stub(wasmSdk, 'getContestedResourceIdentityVotes').resolves([]); - this.sinon.stub(wasmSdk, 'getContestedResourceIdentityVotesWithProofInfo').resolves({ + getContestedResourceIdentityVotesStub = this.sinon.stub(wasmSdk, 'getContestedResourceIdentityVotes').resolves([]); + getContestedResourceIdentityVotesWithProofInfoStub = this.sinon.stub(wasmSdk, 'getContestedResourceIdentityVotesWithProofInfo').resolves({ data: [], proof: {}, metadata: {}, }); - this.sinon.stub(wasmSdk, 'getVotePollsByEndDate').resolves([]); - this.sinon.stub(wasmSdk, 'getVotePollsByEndDateWithProofInfo').resolves({ + getVotePollsByEndDateStub = this.sinon.stub(wasmSdk, 'getVotePollsByEndDate').resolves([]); + getVotePollsByEndDateWithProofInfoStub = this.sinon.stub(wasmSdk, 'getVotePollsByEndDateWithProofInfo').resolves({ data: [], proof: {}, metadata: {}, }); // Stub transition method - this.sinon.stub(wasmSdk, 'masternodeVote').resolves({ + masternodeVoteStub = this.sinon.stub(wasmSdk, 'masternodeVote').resolves({ success: true, }); }); - describe('Query Methods', () => { - it('contestedResourceVoteState() fetches vote state for a contested resource', async () => { + describe('contestedResourceVoteState()', () => { + it('should fetch vote state for a contested resource', async () => { const query = { dataContractId, documentTypeName: 'domain', @@ -67,10 +77,12 @@ describe('VotingFacade', () => { await client.voting.contestedResourceVoteState(query); - expect(wasmSdk.getContestedResourceVoteState).to.be.calledOnceWithExactly(query); + expect(getContestedResourceVoteStateStub).to.be.calledOnceWithExactly(query); }); + }); - it('contestedResourceVoteStateWithProof() fetches vote state with proof and pagination', async () => { + describe('contestedResourceVoteStateWithProof()', () => { + it('should fetch vote state with proof and pagination', async () => { const query = { dataContractId, documentTypeName: 'domain', @@ -85,10 +97,12 @@ describe('VotingFacade', () => { await client.voting.contestedResourceVoteStateWithProof(query); - expect(wasmSdk.getContestedResourceVoteStateWithProofInfo).to.be.calledOnceWithExactly(query); + expect(getContestedResourceVoteStateWithProofInfoStub).to.be.calledOnceWithExactly(query); }); + }); - it('contestedResourceIdentityVotes() fetches votes cast by an identity', async () => { + describe('contestedResourceIdentityVotes()', () => { + it('should fetch votes cast by an identity', async () => { const query = { identityId, limit: 50, @@ -98,10 +112,12 @@ describe('VotingFacade', () => { await client.voting.contestedResourceIdentityVotes(query); - expect(wasmSdk.getContestedResourceIdentityVotes).to.be.calledOnceWithExactly(query); + expect(getContestedResourceIdentityVotesStub).to.be.calledOnceWithExactly(query); }); + }); - it('contestedResourceIdentityVotesWithProof() fetches identity votes with proof', async () => { + describe('contestedResourceIdentityVotesWithProof()', () => { + it('should fetch identity votes with proof', async () => { const query = { identityId, limit: 25, @@ -111,11 +127,13 @@ describe('VotingFacade', () => { await client.voting.contestedResourceIdentityVotesWithProof(query); - expect(wasmSdk.getContestedResourceIdentityVotesWithProofInfo) + expect(getContestedResourceIdentityVotesWithProofInfoStub) .to.be.calledOnceWithExactly(query); }); + }); - it('votePollsByEndDate() fetches active vote polls within a time range', async () => { + describe('votePollsByEndDate()', () => { + it('should fetch active vote polls within a time range', async () => { const query = { startTimeMs: 1704067200000, // 2024-01-01 00:00:00 UTC startTimeIncluded: true, @@ -128,10 +146,12 @@ describe('VotingFacade', () => { await client.voting.votePollsByEndDate(query); - expect(wasmSdk.getVotePollsByEndDate).to.be.calledOnceWithExactly(query); + expect(getVotePollsByEndDateStub).to.be.calledOnceWithExactly(query); }); + }); - it('votePollsByEndDateWithProof() fetches vote polls with proof', async () => { + describe('votePollsByEndDateWithProof()', () => { + it('should fetch vote polls with proof', async () => { const query = { startTimeMs: 1704067200000, endTimeMs: 1706745600000, @@ -142,12 +162,12 @@ describe('VotingFacade', () => { await client.voting.votePollsByEndDateWithProof(query); - expect(wasmSdk.getVotePollsByEndDateWithProofInfo).to.be.calledOnceWithExactly(query); + expect(getVotePollsByEndDateWithProofInfoStub).to.be.calledOnceWithExactly(query); }); }); - describe('Transition Methods', () => { - it('masternodeVote() casts a vote on a contested resource', async () => { + describe('masternodeVote()', () => { + it('should cast a vote on a contested resource', async () => { const options = { masternodeProTxHash, contractId: dataContractId, @@ -160,11 +180,10 @@ describe('VotingFacade', () => { await client.voting.masternodeVote(options); - expect(wasmSdk.masternodeVote).to.be.calledOnceWithExactly(options); + expect(masternodeVoteStub).to.be.calledOnceWithExactly(options); }); - it('masternodeVote() supports different vote choices', async () => { - // Test abstain vote + it('should support abstain vote choice', async () => { const abstainOptions = { masternodeProTxHash, contractId: dataContractId, @@ -177,10 +196,10 @@ describe('VotingFacade', () => { await client.voting.masternodeVote(abstainOptions); - expect(wasmSdk.masternodeVote).to.be.calledWithExactly(abstainOptions); + expect(masternodeVoteStub).to.be.calledWithExactly(abstainOptions); }); - it('masternodeVote() supports lock vote choice', async () => { + it('should support lock vote choice', async () => { const lockOptions = { masternodeProTxHash, contractId: dataContractId, @@ -193,7 +212,7 @@ describe('VotingFacade', () => { await client.voting.masternodeVote(lockOptions); - expect(wasmSdk.masternodeVote).to.be.calledWithExactly(lockOptions); + expect(masternodeVoteStub).to.be.calledWithExactly(lockOptions); }); }); }); diff --git a/packages/js-evo-sdk/tests/unit/helpers/chai.ts b/packages/js-evo-sdk/tests/unit/helpers/chai.ts new file mode 100644 index 00000000000..6c79ec2e44c --- /dev/null +++ b/packages/js-evo-sdk/tests/unit/helpers/chai.ts @@ -0,0 +1,10 @@ +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import dirtyChai from 'dirty-chai'; +import sinonChai from 'sinon-chai'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); +chai.use(dirtyChai); + +export const { expect } = chai; diff --git a/packages/js-evo-sdk/tests/unit/sdk.spec.mjs b/packages/js-evo-sdk/tests/unit/sdk.spec.ts similarity index 77% rename from packages/js-evo-sdk/tests/unit/sdk.spec.mjs rename to packages/js-evo-sdk/tests/unit/sdk.spec.ts index ffa851e7033..546b13343dd 100644 --- a/packages/js-evo-sdk/tests/unit/sdk.spec.mjs +++ b/packages/js-evo-sdk/tests/unit/sdk.spec.ts @@ -7,84 +7,17 @@ const TEST_ADDRESS_3 = 'https://node-3.test:1443'; const TEST_ADDRESSES = [TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3]; describe('EvoSDK', () => { - it('exposes constructor and factories', () => { - expect(EvoSDK).to.be.a('function'); - expect(EvoSDK.testnet).to.be.a('function'); - expect(EvoSDK.mainnet).to.be.a('function'); - expect(EvoSDK.testnetTrusted).to.be.a('function'); - expect(EvoSDK.mainnetTrusted).to.be.a('function'); - expect(EvoSDK.withAddresses).to.be.a('function'); - }); - - it('fromWasm() marks instance as connected', () => { - const wasmStub = { version: () => 1 }; - const sdk = EvoSDK.fromWasm(wasmStub); - expect(sdk.isConnected).to.equal(true); - expect(sdk.wasm).to.equal(wasmStub); - }); - - describe('EvoSDK.withAddresses()', () => { - it('creates SDK instance with specific addresses', () => { - const sdk = EvoSDK.withAddresses([TEST_ADDRESS_1], 'testnet'); - expect(sdk).to.be.instanceof(EvoSDK); - expect(sdk.options.network).to.equal('testnet'); - expect(sdk.isConnected).to.equal(false); - }); - - it('defaults to testnet when network not specified', () => { - const sdk = EvoSDK.withAddresses([TEST_ADDRESS_1]); - expect(sdk).to.be.instanceof(EvoSDK); - expect(sdk.options.network).to.equal('testnet'); - expect(sdk.isConnected).to.equal(false); - }); - - it('accepts mainnet network', () => { - const sdk = EvoSDK.withAddresses([TEST_ADDRESS_2], 'mainnet'); - expect(sdk).to.be.instanceof(EvoSDK); - expect(sdk.options.network).to.equal('mainnet'); - expect(sdk.isConnected).to.equal(false); - }); - - it('accepts multiple addresses', () => { - const sdk = EvoSDK.withAddresses(TEST_ADDRESSES, 'testnet'); - expect(sdk).to.be.instanceof(EvoSDK); - expect(sdk.options.network).to.equal('testnet'); - expect(sdk.options.addresses).to.deep.equal(TEST_ADDRESSES); - }); - - it('accepts additional connection options', () => { - const sdk = EvoSDK.withAddresses( - [TEST_ADDRESS_1], - 'testnet', - { - version: 1, - proofs: true, - logs: 'info', - settings: { - connectTimeoutMs: 10000, - timeoutMs: 30000, - retries: 3, - banFailedAddress: false, - }, - }, - ); - expect(sdk).to.be.instanceof(EvoSDK); - expect(sdk.options.network).to.equal('testnet'); - expect(sdk.options.trusted).to.be.false(); - expect(sdk.options.addresses).to.deep.equal([TEST_ADDRESS_1]); - expect(sdk.options.version).to.equal(1); - expect(sdk.options.proofs).to.be.true(); - expect(sdk.options.logs).to.equal('info'); - expect(sdk.options.settings).to.exist(); - expect(sdk.options.settings.connectTimeoutMs).to.equal(10000); - expect(sdk.options.settings.timeoutMs).to.equal(30000); - expect(sdk.options.settings.retries).to.equal(3); - expect(sdk.options.settings.banFailedAddress).to.be.false(); + describe('constructor()', () => { + it('should expose constructor and factories', () => { + expect(EvoSDK).to.be.a('function'); + expect(EvoSDK.testnet).to.be.a('function'); + expect(EvoSDK.mainnet).to.be.a('function'); + expect(EvoSDK.testnetTrusted).to.be.a('function'); + expect(EvoSDK.mainnetTrusted).to.be.a('function'); + expect(EvoSDK.withAddresses).to.be.a('function'); }); - }); - describe('constructor with addresses option', () => { - it('accepts addresses in options', () => { + it('should accept addresses in options', () => { const sdk = new EvoSDK({ addresses: [TEST_ADDRESS_1], network: 'testnet', @@ -95,7 +28,7 @@ describe('EvoSDK', () => { expect(sdk.isConnected).to.equal(false); }); - it('works with testnet default', () => { + it('should work with testnet default', () => { const sdk = new EvoSDK({ addresses: [TEST_ADDRESS_1], }); @@ -104,7 +37,7 @@ describe('EvoSDK', () => { expect(sdk.options.trusted).to.be.false(); }); - it('works with mainnet', () => { + it('should work with mainnet', () => { const sdk = new EvoSDK({ addresses: [TEST_ADDRESS_2], network: 'mainnet', @@ -114,7 +47,7 @@ describe('EvoSDK', () => { expect(sdk.options.trusted).to.be.false(); }); - it('combines addresses with other options', () => { + it('should combine addresses with other options', () => { const sdk = new EvoSDK({ addresses: [TEST_ADDRESS_1], network: 'testnet', @@ -142,7 +75,7 @@ describe('EvoSDK', () => { expect(sdk.options.settings.banFailedAddress).to.be.true(); }); - it('prioritizes addresses over network presets when both provided', () => { + it('should prioritize addresses over network presets when both provided', () => { // When addresses are provided, they should be used instead of default network addresses const sdk = new EvoSDK({ addresses: [TEST_ADDRESS_3], @@ -154,8 +87,77 @@ describe('EvoSDK', () => { expect(sdk.options.addresses).to.deep.equal([TEST_ADDRESS_3]); expect(sdk.options.trusted).to.be.true(); }); + }); + + describe('fromWasm()', () => { + it('should mark instance as connected when using fromWasm()', () => { + const wasmStub = { version: () => 1 }; + const sdk = EvoSDK.fromWasm(wasmStub); + expect(sdk.isConnected).to.equal(true); + expect(sdk.wasm).to.equal(wasmStub); + }); + }); + + describe('withAddresses()', () => { + it('should create SDK instance with specific addresses', () => { + const sdk = EvoSDK.withAddresses([TEST_ADDRESS_1], 'testnet'); + expect(sdk).to.be.instanceof(EvoSDK); + expect(sdk.options.network).to.equal('testnet'); + expect(sdk.isConnected).to.equal(false); + }); - it('withAddresses() and constructor with addresses produce equivalent SDKs', () => { + it('should default to testnet when network not specified', () => { + const sdk = EvoSDK.withAddresses([TEST_ADDRESS_1]); + expect(sdk).to.be.instanceof(EvoSDK); + expect(sdk.options.network).to.equal('testnet'); + expect(sdk.isConnected).to.equal(false); + }); + + it('should accept mainnet network', () => { + const sdk = EvoSDK.withAddresses([TEST_ADDRESS_2], 'mainnet'); + expect(sdk).to.be.instanceof(EvoSDK); + expect(sdk.options.network).to.equal('mainnet'); + expect(sdk.isConnected).to.equal(false); + }); + + it('should accept multiple addresses', () => { + const sdk = EvoSDK.withAddresses(TEST_ADDRESSES, 'testnet'); + expect(sdk).to.be.instanceof(EvoSDK); + expect(sdk.options.network).to.equal('testnet'); + expect(sdk.options.addresses).to.deep.equal(TEST_ADDRESSES); + }); + + it('should accept additional connection options', () => { + const sdk = EvoSDK.withAddresses( + [TEST_ADDRESS_1], + 'testnet', + { + version: 1, + proofs: true, + logs: 'info', + settings: { + connectTimeoutMs: 10000, + timeoutMs: 30000, + retries: 3, + banFailedAddress: false, + }, + }, + ); + expect(sdk).to.be.instanceof(EvoSDK); + expect(sdk.options.network).to.equal('testnet'); + expect(sdk.options.trusted).to.be.false(); + expect(sdk.options.addresses).to.deep.equal([TEST_ADDRESS_1]); + expect(sdk.options.version).to.equal(1); + expect(sdk.options.proofs).to.be.true(); + expect(sdk.options.logs).to.equal('info'); + expect(sdk.options.settings).to.exist(); + expect(sdk.options.settings.connectTimeoutMs).to.equal(10000); + expect(sdk.options.settings.timeoutMs).to.equal(30000); + expect(sdk.options.settings.retries).to.equal(3); + expect(sdk.options.settings.banFailedAddress).to.be.false(); + }); + + it('should produce equivalent SDKs from withAddresses() and constructor with addresses', () => { const addresses = [TEST_ADDRESS_1]; const options = { version: 1, proofs: true }; @@ -169,8 +171,8 @@ describe('EvoSDK', () => { }); }); - describe('factory methods for standard configurations', () => { - it('testnet() creates testnet instance', () => { + describe('testnet()', () => { + it('should create testnet instance', () => { const sdk = EvoSDK.testnet(); expect(sdk).to.be.instanceof(EvoSDK); expect(sdk.options.network).to.equal('testnet'); @@ -179,37 +181,43 @@ describe('EvoSDK', () => { expect(sdk.isConnected).to.equal(false); }); - it('mainnet() creates mainnet instance', () => { + it('should accept connection options', () => { + const sdk = EvoSDK.testnet({ + version: 1, + proofs: false, + logs: 'warn', + }); + expect(sdk).to.be.instanceof(EvoSDK); + }); + }); + + describe('mainnet()', () => { + it('should create mainnet instance', () => { const sdk = EvoSDK.mainnet(); expect(sdk).to.be.instanceof(EvoSDK); expect(sdk.options.network).to.equal('mainnet'); expect(sdk.options.trusted).to.be.false(); expect(sdk.isConnected).to.equal(false); }); + }); - it('testnetTrusted() creates trusted testnet instance', () => { + describe('testnetTrusted()', () => { + it('should create trusted testnet instance', () => { const sdk = EvoSDK.testnetTrusted(); expect(sdk).to.be.instanceof(EvoSDK); expect(sdk.options.network).to.equal('testnet'); expect(sdk.options.trusted).to.be.true(); expect(sdk.isConnected).to.equal(false); }); + }); - it('mainnetTrusted() creates trusted mainnet instance', () => { + describe('mainnetTrusted()', () => { + it('should create trusted mainnet instance', () => { const sdk = EvoSDK.mainnetTrusted(); expect(sdk).to.be.instanceof(EvoSDK); expect(sdk.options.network).to.equal('mainnet'); expect(sdk.options.trusted).to.be.true(); expect(sdk.isConnected).to.equal(false); }); - - it('factory methods accept connection options', () => { - const sdk = EvoSDK.testnet({ - version: 1, - proofs: false, - logs: 'warn', - }); - expect(sdk).to.be.instanceof(EvoSDK); - }); }); }); diff --git a/packages/js-evo-sdk/tests/unit/wallet.spec.mjs b/packages/js-evo-sdk/tests/unit/wallet.spec.ts similarity index 75% rename from packages/js-evo-sdk/tests/unit/wallet.spec.mjs rename to packages/js-evo-sdk/tests/unit/wallet.spec.ts index b30694bff4f..b779c5c0a05 100644 --- a/packages/js-evo-sdk/tests/unit/wallet.spec.mjs +++ b/packages/js-evo-sdk/tests/unit/wallet.spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { wallet } from '../../dist/sdk.js'; -describe('wallet namespace', () => { +describe('wallet', () => { const exportedFns = [ 'generateMnemonic', 'validateMnemonic', @@ -27,9 +27,11 @@ describe('wallet namespace', () => { 'signMessage', ]; - it('exposes the expected helper functions', () => { - exportedFns.forEach((fn) => { - expect(wallet).to.have.property(fn).that.is.a('function'); + describe('exports', () => { + it('should expose the expected helper functions', () => { + exportedFns.forEach((fn) => { + expect(wallet).to.have.property(fn).that.is.a('function'); + }); }); }); }); diff --git a/packages/js-evo-sdk/tsconfig.tests.json b/packages/js-evo-sdk/tsconfig.tests.json new file mode 100644 index 00000000000..46d42a223ef --- /dev/null +++ b/packages/js-evo-sdk/tsconfig.tests.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "." + }, + "include": [ + "./tests/**/*", + "./src/**/*" + ] +} diff --git a/packages/js-grpc-common/.eslintrc b/packages/js-grpc-common/.eslintrc deleted file mode 100644 index d94c110f931..00000000000 --- a/packages/js-grpc-common/.eslintrc +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "import/no-extraneous-dependencies": ["error", { "packageDir": "." }], - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - } - } - \ No newline at end of file diff --git a/packages/js-grpc-common/eslint.config.mjs b/packages/js-grpc-common/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/js-grpc-common/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/js-grpc-common/lib/test/.eslintrc b/packages/js-grpc-common/lib/test/.eslintrc deleted file mode 100644 index 4c2b11fe817..00000000000 --- a/packages/js-grpc-common/lib/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - } -} diff --git a/packages/js-grpc-common/package.json b/packages/js-grpc-common/package.json index 30a36819e1b..6d112edc0dd 100644 --- a/packages/js-grpc-common/package.json +++ b/packages/js-grpc-common/package.json @@ -16,9 +16,7 @@ "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "mocha-sinon": "^2.1.2", "nyc": "^15.1.0", diff --git a/packages/js-grpc-common/test/.eslintrc b/packages/js-grpc-common/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/js-grpc-common/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/keyword-search-contract/.eslintrc b/packages/keyword-search-contract/.eslintrc deleted file mode 100644 index cb6c7636b60..00000000000 --- a/packages/keyword-search-contract/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/keyword-search-contract/eslint.config.mjs b/packages/keyword-search-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/keyword-search-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/keyword-search-contract/package.json b/packages/keyword-search-contract/package.json index 647483bee2c..cdc3a067bb6 100644 --- a/packages/keyword-search-contract/package.json +++ b/packages/keyword-search-contract/package.json @@ -19,9 +19,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/keyword-search-contract/test/.eslintrc b/packages/keyword-search-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/keyword-search-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/keyword-search-contract/test/unit/searchContract.spec.js b/packages/keyword-search-contract/test/unit/searchContract.spec.js index c13d4d6d681..981b1b605e8 100644 --- a/packages/keyword-search-contract/test/unit/searchContract.spec.js +++ b/packages/keyword-search-contract/test/unit/searchContract.spec.js @@ -37,11 +37,19 @@ describe('Search Contract', () => { identityId = await generateRandomIdentifier(); - dataContract = dpp.dataContract.create(identityId, BigInt(1), keywordSearchContractDocumentsSchema); + dataContract = dpp.dataContract.create( + identityId, + BigInt(1), + keywordSearchContractDocumentsSchema, + ); }); it('should have a valid contract definition', async () => { - expect(() => dpp.dataContract.create(identityId, BigInt(1), keywordSearchContractDocumentsSchema)) + expect(() => dpp.dataContract.create( + identityId, + BigInt(1), + keywordSearchContractDocumentsSchema, + )) .to .not .throw(); diff --git a/packages/masternode-reward-shares-contract/.eslintrc b/packages/masternode-reward-shares-contract/.eslintrc deleted file mode 100644 index cb6c7636b60..00000000000 --- a/packages/masternode-reward-shares-contract/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/masternode-reward-shares-contract/eslint.config.mjs b/packages/masternode-reward-shares-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/masternode-reward-shares-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/masternode-reward-shares-contract/package.json b/packages/masternode-reward-shares-contract/package.json index 811bae73afe..5c0d6d8fcae 100644 --- a/packages/masternode-reward-shares-contract/package.json +++ b/packages/masternode-reward-shares-contract/package.json @@ -34,9 +34,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/masternode-reward-shares-contract/test/.eslintrc b/packages/masternode-reward-shares-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/masternode-reward-shares-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/platform-test-suite/.eslintrc b/packages/platform-test-suite/.eslintrc deleted file mode 100644 index 8e8b7cf892f..00000000000 --- a/packages/platform-test-suite/.eslintrc +++ /dev/null @@ -1,36 +0,0 @@ -{ - "extends": "airbnb-base", - "env": { - "es2020": true, - "node": true, - "mocha": true - }, - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "no-await-in-loop": "off", - "import/no-extraneous-dependencies": "off", - "no-restricted-syntax": [ - "error", - { - "selector": "LabeledStatement", - "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand." - }, - { - "selector": "WithStatement", - "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." - } - ], - "curly": [ - "error", - "all" - ], - "require-await": "error" - }, - "globals": { - "expect": true - } -} diff --git a/packages/platform-test-suite/eslint.config.mjs b/packages/platform-test-suite/eslint.config.mjs new file mode 100644 index 00000000000..347bcb08b7d --- /dev/null +++ b/packages/platform-test-suite/eslint.config.mjs @@ -0,0 +1,18 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + rules: { + // Test suite allows dev dependencies everywhere + 'import/no-extraneous-dependencies': 'off', + // Require await in async functions + 'require-await': 'error', + }, + }, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/platform-test-suite/package.json b/packages/platform-test-suite/package.json index bb09c35a236..397ffce18c0 100644 --- a/packages/platform-test-suite/package.json +++ b/packages/platform-test-suite/package.json @@ -77,8 +77,6 @@ "ws": "^8.17.1" }, "devDependencies": { - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0" + "eslint": "^9.18.0" } } diff --git a/packages/platform-test-suite/test/.eslintrc b/packages/platform-test-suite/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/platform-test-suite/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/token-history-contract/.eslintrc b/packages/token-history-contract/.eslintrc deleted file mode 100644 index cb6c7636b60..00000000000 --- a/packages/token-history-contract/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/token-history-contract/eslint.config.mjs b/packages/token-history-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/token-history-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/token-history-contract/package.json b/packages/token-history-contract/package.json index 0ff8a1fc1c0..9ea493bd468 100644 --- a/packages/token-history-contract/package.json +++ b/packages/token-history-contract/package.json @@ -19,9 +19,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/token-history-contract/test/.eslintrc b/packages/token-history-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/token-history-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/wallet-lib/.eslintrc b/packages/wallet-lib/.eslintrc deleted file mode 100644 index 6ce67870a8b..00000000000 --- a/packages/wallet-lib/.eslintrc +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "airbnb-base", - "env": { - "node": true, - "mocha": true - }, - "ignorePatterns": [ - "**/*.spec.js", - "fixtures", - "dist", - "tests/*", - "!tests/integration", - "!tests/integration/plugins/Workers/BlockHeadersSyncWorker.spec.js", - "!tests/integration/plugins/Workers/TransactionsSyncWorker.spec.js", - "!src/plugins", - "!src/plugins/Workers/BlockHeadersSyncWorker/BlockHeadersSyncWorker.spec.js", - "!src/plugins/Workers/TransactionsSyncWorker/TransactionsSyncWorker.spec.js", - "!src/plugins/Workers/TransactionsSyncWorker/TransactionsReader.spec.js", - "!src/plugins/Workers/TransactionsSyncWorker/utils.spec.js" - ] -} diff --git a/packages/wallet-lib/eslint.config.mjs b/packages/wallet-lib/eslint.config.mjs new file mode 100644 index 00000000000..c0ae7a349f2 --- /dev/null +++ b/packages/wallet-lib/eslint.config.mjs @@ -0,0 +1,30 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + // Global ignores + { + ignores: [ + '**/*.d.ts', + 'dist/**', + 'node_modules/**', + 'fixtures/**', + ], + }, + ...baseConfig, + mochaTestConfig, + { + // Ignore spec files by default, but allow specific ones + ignores: [ + '**/*.spec.js', + 'tests/**', + ], + }, + { + // Re-include specific test files for linting + files: [ + 'tests/integration/**/*.js', + 'src/plugins/**/*.spec.js', + ], + }, +]; diff --git a/packages/wallet-lib/karma/options.js b/packages/wallet-lib/karma/options.js index fac2c19bbad..f772d0a099d 100644 --- a/packages/wallet-lib/karma/options.js +++ b/packages/wallet-lib/karma/options.js @@ -1,4 +1,4 @@ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable import-x/no-extraneous-dependencies */ const webpack = require('webpack'); const dotenvSafe = require('dotenv-safe'); diff --git a/packages/wallet-lib/package.json b/packages/wallet-lib/package.json index b058bce93a6..b5aa5b33db7 100644 --- a/packages/wallet-lib/package.json +++ b/packages/wallet-lib/package.json @@ -67,9 +67,7 @@ "crypto-browserify": "^3.12.1", "dirty-chai": "^2.0.1", "dotenv-safe": "^8.2.0", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "events": "^3.3.0", "https-browserify": "^1.0.0", "karma": "^6.4.3", diff --git a/packages/wallet-lib/src/test/.eslintrc b/packages/wallet-lib/src/test/.eslintrc deleted file mode 100644 index 4c2b11fe817..00000000000 --- a/packages/wallet-lib/src/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - } -} diff --git a/packages/wallet-lib/src/types/Account/.eslintrc b/packages/wallet-lib/src/types/Account/.eslintrc deleted file mode 100644 index a8022ef2b8a..00000000000 --- a/packages/wallet-lib/src/types/Account/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "import/newline-after-import": "off" - } -} diff --git a/packages/wallet-lib/src/types/Wallet/.eslintrc b/packages/wallet-lib/src/types/Wallet/.eslintrc deleted file mode 100644 index a8022ef2b8a..00000000000 --- a/packages/wallet-lib/src/types/Wallet/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "import/newline-after-import": "off" - } -} diff --git a/packages/wallet-lib/src/utils/expectThrowsAsync.js b/packages/wallet-lib/src/utils/expectThrowsAsync.js index 40c8b40068b..71f929f31f4 100644 --- a/packages/wallet-lib/src/utils/expectThrowsAsync.js +++ b/packages/wallet-lib/src/utils/expectThrowsAsync.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line import-x/no-extraneous-dependencies const { expect } = require('chai'); const expectThrowsAsync = async (method, errorMessage) => { diff --git a/packages/wallet-utils-contract/.eslintrc b/packages/wallet-utils-contract/.eslintrc deleted file mode 100644 index cb6c7636b60..00000000000 --- a/packages/wallet-utils-contract/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/wallet-utils-contract/eslint.config.mjs b/packages/wallet-utils-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/wallet-utils-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/wallet-utils-contract/package.json b/packages/wallet-utils-contract/package.json index 531474d3f25..51359afe09f 100644 --- a/packages/wallet-utils-contract/package.json +++ b/packages/wallet-utils-contract/package.json @@ -19,9 +19,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/wallet-utils-contract/test/.eslintrc b/packages/wallet-utils-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/wallet-utils-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/wasm-dpp/.eslintignore b/packages/wasm-dpp/.eslintignore deleted file mode 100644 index e308ff363a4..00000000000 --- a/packages/wasm-dpp/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -dist -wasm \ No newline at end of file diff --git a/packages/wasm-dpp/.eslintrc b/packages/wasm-dpp/.eslintrc deleted file mode 100644 index ec046c0d8a4..00000000000 --- a/packages/wasm-dpp/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "env": { - "es2020": true - }, - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - } -} diff --git a/packages/wasm-dpp/eslint.config.mjs b/packages/wasm-dpp/eslint.config.mjs new file mode 100644 index 00000000000..009c1821104 --- /dev/null +++ b/packages/wasm-dpp/eslint.config.mjs @@ -0,0 +1,30 @@ +import baseConfig from '../../eslint/base.mjs'; +import typescriptConfig from '../../eslint/typescript.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; +import wasmConfig from '../../eslint/wasm.mjs'; + +export default [ + ...baseConfig, + ...typescriptConfig, + { + ...wasmConfig, + }, + mochaTestConfig, + { + files: ['**/*.ts'], + rules: { + // wasm-dpp specific relaxations for TypeScript files + 'max-classes-per-file': 'off', + 'import-x/export': 'off', + '@typescript-eslint/no-useless-constructor': 'off', + 'no-constructor-return': 'off', + '@stylistic/object-curly-spacing': 'off', + '@stylistic/no-extra-semi': 'off', + '@stylistic/no-multiple-empty-lines': 'off', + 'prefer-const': 'off', + }, + }, + { + ignores: ['dist/**', 'pkg/**', 'node_modules/**', 'lib/wasm/**', 'test-d/**'], + }, +]; diff --git a/packages/wasm-dpp/lib/test/.eslintrc b/packages/wasm-dpp/lib/test/.eslintrc deleted file mode 100644 index 4c2b11fe817..00000000000 --- a/packages/wasm-dpp/lib/test/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - } -} diff --git a/packages/wasm-dpp/package.json b/packages/wasm-dpp/package.json index 4a0bfb9a7e1..defc0f4689e 100644 --- a/packages/wasm-dpp/package.json +++ b/packages/wasm-dpp/package.json @@ -46,7 +46,7 @@ "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/dpns-contract": "workspace:*", "@types/bs58": "^4.0.1", - "@types/node": "^14.6.0", + "@types/node": "^20.10.0", "@yarnpkg/pnpify": "^4.0.0-rc.42", "ajv": "^8.6.0", "assert": "^2.0.0", @@ -57,9 +57,7 @@ "chai-string": "^1.5.0", "crypto-browserify": "^3.12.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "events": "^3.3.0", "fast-json-patch": "^3.1.1", "https-browserify": "^1.0.0", @@ -83,7 +81,7 @@ "string_decoder": "^1.3.0", "ts-loader": "^9.5.0", "tsd": "^0.28.1", - "typescript": "^3.9.5", + "typescript": "^5.7.3", "url": "^0.11.3", "util": "^0.12.4", "webpack": "^5.94.0", diff --git a/packages/wasm-dpp/test/.eslintrc b/packages/wasm-dpp/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/wasm-dpp/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/packages/wasm-dpp2/.mocharc.yml b/packages/wasm-dpp2/.mocharc.yml index e82067f393b..89f0713ff01 100644 --- a/packages/wasm-dpp2/.mocharc.yml +++ b/packages/wasm-dpp2/.mocharc.yml @@ -1,4 +1,6 @@ -require: tests/bootstrap.cjs +node-option: + - import=ts-node/esm +extensions: + - ts recursive: true timeout: 8000 - diff --git a/packages/wasm-dpp2/eslint.config.mjs b/packages/wasm-dpp2/eslint.config.mjs new file mode 100644 index 00000000000..ba20f84df03 --- /dev/null +++ b/packages/wasm-dpp2/eslint.config.mjs @@ -0,0 +1,20 @@ +import baseConfig from '../../eslint/base.mjs'; +import typescriptConfig from '../../eslint/typescript.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; +import wasmConfig from '../../eslint/wasm.mjs'; + +export default [ + ...baseConfig, + ...typescriptConfig, + { + files: ['tests/**/*.ts'], + rules: { + ...wasmConfig.rules, + 'import-x/extensions': ['error', 'ignorePackages'], + }, + }, + mochaTestConfig, + { + ignores: ['dist/**', 'pkg/**', 'wasm/**', '**/*.d.ts', 'tests/karma/**', 'node_modules/**'], + }, +]; diff --git a/packages/wasm-dpp2/package.json b/packages/wasm-dpp2/package.json index a6ebe37cc4f..c34992f0022 100644 --- a/packages/wasm-dpp2/package.json +++ b/packages/wasm-dpp2/package.json @@ -31,8 +31,8 @@ "build": "./scripts/build.sh && node ./scripts/bundle.cjs", "build:release": "./scripts/build-optimized.sh && node ./scripts/bundle.cjs", "test": "yarn run test:unit", - "test:unit": "mocha tests/unit/**/*.spec.mjs && karma start ./tests/karma/karma.conf.cjs --single-run", - "lint": "eslint tests/**/*.*js" + "test:unit": "mocha tests/unit/**/*.spec.ts && karma start ./tests/karma/karma.conf.cjs --single-run", + "lint": "eslint tests/**/*.ts" }, "ultra": { "concurrent": [ @@ -40,16 +40,16 @@ ] }, "devDependencies": { + "@types/chai": "^4.3.11", + "@types/mocha": "^10.0.6", + "@types/node": "^20.10.0", "assert": "^2.0.0", "bs58": "^4.0.1", "buffer": "^6.0.3", "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-jsdoc": "^46.9.0", + "eslint": "^9.18.0", "events": "^3.3.0", "karma": "^6.4.3", "karma-chai": "^0.1.0", @@ -62,6 +62,9 @@ "path-browserify": "^1.0.1", "process": "^0.11.10", "string_decoder": "^1.3.0", + "ts-loader": "^9.5.0", + "ts-node": "^10.9.2", + "typescript": "^5.7.3", "url": "^0.11.3", "util": "^0.12.4", "webpack": "^5.94.0", diff --git a/packages/wasm-dpp2/scripts/bundle.cjs b/packages/wasm-dpp2/scripts/bundle.cjs index 42c8313f134..c6442482751 100755 --- a/packages/wasm-dpp2/scripts/bundle.cjs +++ b/packages/wasm-dpp2/scripts/bundle.cjs @@ -44,11 +44,11 @@ const wasmBase64 = wasmBytes.toString('base64'); const wasmGzip = zlib.gzipSync(wasmBytes, { level: zlib.constants.Z_BEST_COMPRESSION }); const wasmGzipBase64 = wasmGzip.toString('base64'); -const wrapper = `// Single-file ESM wrapper around wasm-bindgen output.\n// - Inlines WASM bytes as base64.\n// - Exposes async default init() for both Node and browser.\n\nimport rawInit, { initSync as rawInitSync } from './raw/wasm_dpp2.no_url.js';\n\nexport * from './raw/wasm_dpp2.no_url.js';\nexport { initSync } from './raw/wasm_dpp2.no_url.js';\n\nconst __WASM_BASE64 = '${wasmBase64}';\nfunction __wasmBytes() {\n if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {\n return Buffer.from(__WASM_BASE64, 'base64');\n }\n const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);\n const bin = atobFn(__WASM_BASE64);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nfunction __supportsWorker() {\n return typeof Worker !== 'undefined' && typeof Blob !== 'undefined' && typeof URL !== 'undefined';\n}\n\nasync function __compileInWorker(bytes) {\n if (!__supportsWorker()) {\n return WebAssembly.compile(bytes);\n }\n const src = 'self.onmessage=async(e)=>{try{const m=await WebAssembly.compile(e.data);self.postMessage({ok:1,mod:m});}catch(err){self.postMessage({ok:0,err:String(err)});}}';\n const blob = new Blob([src], { type: 'application/javascript' });\n const url = URL.createObjectURL(blob);\n return new Promise((resolve, reject) => {\n const w = new Worker(url);\n const cleanup = () => {\n URL.revokeObjectURL(url);\n w.terminate();\n };\n w.onmessage = (ev) => {\n const d = ev.data || {};\n if (d.ok && d.mod) {\n cleanup();\n resolve(d.mod);\n } else {\n cleanup();\n reject(new Error(d.err || 'Worker failed to compile WASM.')); - }\n };\n w.onerror = (err) => {\n cleanup();\n reject(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));\n };\n try {\n w.postMessage(bytes.buffer, [bytes.buffer]);\n } catch (_) {\n w.postMessage(new Uint8Array(bytes));\n }\n });\n}\n\nconst isNode = typeof window === 'undefined' && typeof process !== 'undefined' && !!(process.versions && process.versions.node);\n\nexport default async function init(moduleOrPath) {\n if (isNode) {\n if (typeof moduleOrPath === 'undefined') {\n const bytes = __wasmBytes();\n return rawInitSync({ module: bytes });\n }\n return rawInit(moduleOrPath);\n }\n if (typeof moduleOrPath === 'undefined') {\n const bytes = __wasmBytes();\n let mod;\n try {\n mod = await __compileInWorker(bytes);\n } catch (_) {\n mod = await WebAssembly.compile(bytes);\n }\n return rawInit({ module_or_path: mod });\n }\n return rawInit(moduleOrPath);\n}\n`; +const wrapper = `// Single-file ESM wrapper around wasm-bindgen output.\n// - Inlines WASM bytes as base64.\n// - Exposes async default init() for both Node and browser.\n\nimport rawInit, { initSync as rawInitSync } from './raw/wasm_dpp2.no_url.js';\nimport * as _wasmExports from './raw/wasm_dpp2.no_url.js';\n\nexport * from './raw/wasm_dpp2.no_url.js';\nexport { initSync } from './raw/wasm_dpp2.no_url.js';\n\n// Namespace export for convenient access to all WASM bindings\nexport { _wasmExports as wasm };\n\nconst __WASM_BASE64 = '${wasmBase64}';\nfunction __wasmBytes() {\n if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {\n return Buffer.from(__WASM_BASE64, 'base64');\n }\n const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);\n const bin = atobFn(__WASM_BASE64);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nfunction __supportsWorker() {\n return typeof Worker !== 'undefined' && typeof Blob !== 'undefined' && typeof URL !== 'undefined';\n}\n\nasync function __compileInWorker(bytes) {\n if (!__supportsWorker()) {\n return WebAssembly.compile(bytes);\n }\n const src = 'self.onmessage=async(e)=>{try{const m=await WebAssembly.compile(e.data);self.postMessage({ok:1,mod:m});}catch(err){self.postMessage({ok:0,err:String(err)});}}';\n const blob = new Blob([src], { type: 'application/javascript' });\n const url = URL.createObjectURL(blob);\n return new Promise((resolve, reject) => {\n const w = new Worker(url);\n const cleanup = () => {\n URL.revokeObjectURL(url);\n w.terminate();\n };\n w.onmessage = (ev) => {\n const d = ev.data || {};\n if (d.ok && d.mod) {\n cleanup();\n resolve(d.mod);\n } else {\n cleanup();\n reject(new Error(d.err || 'Worker failed to compile WASM.')); + }\n };\n w.onerror = (err) => {\n cleanup();\n reject(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));\n };\n try {\n w.postMessage(bytes.buffer, [bytes.buffer]);\n } catch (_) {\n w.postMessage(new Uint8Array(bytes));\n }\n });\n}\n\nconst isNode = typeof window === 'undefined' && typeof process !== 'undefined' && !!(process.versions && process.versions.node);\n\nexport default async function init(moduleOrPath) {\n if (isNode) {\n if (typeof moduleOrPath === 'undefined') {\n const bytes = __wasmBytes();\n return rawInitSync({ module: bytes });\n }\n return rawInit(moduleOrPath);\n }\n if (typeof moduleOrPath === 'undefined') {\n const bytes = __wasmBytes();\n let mod;\n try {\n mod = await __compileInWorker(bytes);\n } catch (_) {\n mod = await WebAssembly.compile(bytes);\n }\n return rawInit({ module_or_path: mod });\n }\n return rawInit(moduleOrPath);\n}\n\n// Alias for init() with clearer naming\nexport { init as initWasm };\n`; fs.writeFileSync(path.join(distDir, 'dpp.js'), wrapper); -const compressedWrapper = `// Gzip-compressed single-file ESM wrapper around wasm-bindgen output.\n// - Inlines WASM as base64 gzip payload to reduce bundle size.\n\nimport rawInit, { initSync as rawInitSync } from './raw/wasm_dpp2.no_url.js';\n\nexport * from './raw/wasm_dpp2.no_url.js';\nexport { initSync } from './raw/wasm_dpp2.no_url.js';\n\nconst __WASM_COMPRESSED_BASE64 = '${wasmGzipBase64}';\nconst __WASM_COMPRESSION = 'gzip';\nconst isNode = typeof window === 'undefined' && typeof process !== 'undefined' && !!(process.versions && process.versions.node);\n\nfunction __decodeBase64(source) {\n if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {\n return Buffer.from(source, 'base64');\n }\n const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);\n const bin = atobFn(source);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nlet __nodeZlibPromise;\nfunction __loadNodeZlib() {\n if (!__nodeZlibPromise) {\n const importer = new Function('return import(\\"node:zlib\\")');\n __nodeZlibPromise = importer();\n }\n return __nodeZlibPromise;\n}\n\nasync function __decompress(bytes) {\n if (!__WASM_COMPRESSION) {\n return bytes;\n }\n if (isNode) {\n const { gunzipSync } = await __loadNodeZlib();\n const out = gunzipSync(bytes); +const compressedWrapper = `// Gzip-compressed single-file ESM wrapper around wasm-bindgen output.\n// - Inlines WASM as base64 gzip payload to reduce bundle size.\n\nimport rawInit, { initSync as rawInitSync } from './raw/wasm_dpp2.no_url.js';\nimport * as _wasmExports from './raw/wasm_dpp2.no_url.js';\n\nexport * from './raw/wasm_dpp2.no_url.js';\nexport { initSync } from './raw/wasm_dpp2.no_url.js';\n\n// Namespace export for convenient access to all WASM bindings\nexport { _wasmExports as wasm };\n\nconst __WASM_COMPRESSED_BASE64 = '${wasmGzipBase64}';\nconst __WASM_COMPRESSION = 'gzip';\nconst isNode = typeof window === 'undefined' && typeof process !== 'undefined' && !!(process.versions && process.versions.node);\n\nfunction __decodeBase64(source) {\n if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {\n return Buffer.from(source, 'base64');\n }\n const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);\n const bin = atobFn(source);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nlet __nodeZlibPromise;\nfunction __loadNodeZlib() {\n if (!__nodeZlibPromise) {\n const importer = new Function('return import(\\"node:zlib\\")');\n __nodeZlibPromise = importer();\n }\n return __nodeZlibPromise;\n}\n\nasync function __decompress(bytes) {\n if (!__WASM_COMPRESSION) {\n return bytes;\n }\n if (isNode) {\n const { gunzipSync } = await __loadNodeZlib();\n const out = gunzipSync(bytes); return out instanceof Uint8Array ? out : new Uint8Array(out.buffer, out.byteOffset, out.byteLength);\n }\n if (typeof Blob === 'function' && typeof Response === 'function' && typeof DecompressionStream === 'function') {\n const res = new Response(\n new Blob([bytes]).stream().pipeThrough(new DecompressionStream(__WASM_COMPRESSION))\n );\n const buf = await res.arrayBuffer();\n return new Uint8Array(buf);\n }\n throw new Error('Gzip decompression not supported in this environment.');\n}\n\nasync function __wasmBytes(options = {}) {\n const { decompress = true } = options;\n if (!__WASM_COMPRESSION) {\n throw new Error('Compression metadata missing.');\n }\n const compressed = __decodeBase64(__WASM_COMPRESSED_BASE64);\n if (!decompress) {\n return compressed;\n }\n return __decompress(compressed);\n}\n\nfunction __supportsWorker() {\n return typeof Worker !== 'undefined' && typeof Blob !== 'undefined' && typeof URL !== 'undefined';\n}\n\nasync function __compileInWorker(compressedBytes) {\n const bytes = compressedBytes instanceof Uint8Array ? compressedBytes : new Uint8Array(compressedBytes);\n if (!__supportsWorker()) {\n const decompressed = await __decompress(bytes);\n return WebAssembly.compile(decompressed);\n }\n const src = "self.onmessage=async(event)=>{try{const data=event.data||{};let bytes=data.compressed;const compression=data.compression||null;if(!(bytes instanceof Uint8Array)){bytes=bytes?new Uint8Array(bytes):new Uint8Array();}if(compression){if(typeof Blob==='function'&&typeof Response==='function'&&typeof DecompressionStream==='function'){const res=new Response(new Blob([bytes]).stream().pipeThrough(new DecompressionStream(compression)));const buf=await res.arrayBuffer();bytes=new Uint8Array(buf);}else{throw new Error('DecompressionStream not available');}}const mod=await WebAssembly.compile(bytes);self.postMessage({ok:1,mod});}catch(err){self.postMessage({ok:0,err:String(err)})}}"; const blob = new Blob([src], { type: 'application/javascript' }); const url = URL.createObjectURL(blob); @@ -102,6 +102,9 @@ export default async function init(moduleOrPath) { } return rawInit(moduleOrPath); } + +// Alias for init() with clearer naming +export { init as initWasm }; `; fs.writeFileSync(path.join(distDir, 'dpp.compressed.js'), compressedWrapper); @@ -113,12 +116,32 @@ const compressedStat = fs.statSync(dppCompressedPath); const baseGzipSize = zlib.gzipSync(fs.readFileSync(dppJsPath)).length; const compressedGzipSize = zlib.gzipSync(fs.readFileSync(dppCompressedPath)).length; -fs.copyFileSync(dtsPath, path.join(distDir, 'dpp.d.ts')); +// Copy base type declarations and append additional exports +const baseDts = fs.readFileSync(dtsPath, 'utf8'); +const additionalDts = ` +// Namespace export for convenient access to all WASM bindings +import * as _wasm from './dpp.js'; +export { _wasm as wasm }; + +// Alias for init() with clearer naming +export declare function initWasm(module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; +`; +fs.writeFileSync(path.join(distDir, 'dpp.d.ts'), baseDts + additionalDts); + +// Create type declaration for compressed version that re-exports from dpp.d.ts +const compressedDts = `// Re-export all types from dpp.d.ts for the compressed version +export * from './dpp.js'; +export { default } from './dpp.js'; +export { wasm } from './dpp.js'; +export { initWasm } from './dpp.js'; +`; +fs.writeFileSync(path.join(distDir, 'dpp.compressed.d.ts'), compressedDts); console.log(`Wrote dist/dpp.js (${baseStat.size} bytes) single-file wrapper (inline WASM)`); console.log(`Wrote dist/dpp.compressed.js (${compressedStat.size} bytes) gzip inline wrapper`); console.log(`gzip(dpp.js): ${baseGzipSize} bytes | gzip(dpp.compressed.js): ${compressedGzipSize} bytes`); console.log('Wrote dist/dpp.d.ts'); +console.log('Wrote dist/dpp.compressed.d.ts'); console.log('Wrote dist/raw/* (separate JS + WASM)'); try { diff --git a/packages/wasm-dpp2/src/asset_lock_proof/chain.rs b/packages/wasm-dpp2/src/asset_lock_proof/chain.rs index a12b43643f6..a2ccd32e9e4 100644 --- a/packages/wasm-dpp2/src/asset_lock_proof/chain.rs +++ b/packages/wasm-dpp2/src/asset_lock_proof/chain.rs @@ -2,11 +2,40 @@ use crate::asset_lock_proof::outpoint::OutPointWasm; use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use bincode::serde::{decode_from_slice, encode_to_vec}; use dpp::identity::state_transition::asset_lock_proof::chain::ChainAssetLockProof; use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * ChainAssetLockProof serialized as a plain object. + */ +export interface ChainAssetLockProofObject { + coreChainLockedHeight: number; + outPoint: OutPointObject; +} + +/** + * ChainAssetLockProof serialized as JSON. + */ +export interface ChainAssetLockProofJSON { + coreChainLockedHeight: number; + outPoint: OutPointJSON; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ChainAssetLockProofObject")] + pub type ChainAssetLockProofObjectJs; + + #[wasm_bindgen(typescript_type = "ChainAssetLockProofJSON")] + pub type ChainAssetLockProofJSONJs; +} + #[wasm_bindgen(js_name = "ChainAssetLockProof")] #[derive(Clone, Serialize, Deserialize)] pub struct ChainAssetLockProofWasm(ChainAssetLockProof); @@ -25,20 +54,10 @@ impl From for ChainAssetLockProofWasm { #[wasm_bindgen(js_class = ChainAssetLockProof)] impl ChainAssetLockProofWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "ChainAssetLockProof".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "ChainAssetLockProof".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - core_chain_locked_height: u32, - out_point: &OutPointWasm, + pub fn constructor( + #[wasm_bindgen(js_name = "coreChainLockedHeight")] core_chain_locked_height: u32, + #[wasm_bindgen(js_name = "outPoint")] out_point: &OutPointWasm, ) -> WasmDppResult { Ok(ChainAssetLockProofWasm(ChainAssetLockProof { core_chain_locked_height, @@ -47,7 +66,10 @@ impl ChainAssetLockProofWasm { } #[wasm_bindgen(setter = "coreChainLockedHeight")] - pub fn set_core_chain_locked_height(&mut self, core_chain_locked_height: u32) { + pub fn set_core_chain_locked_height( + &mut self, + #[wasm_bindgen(js_name = "coreChainLockedHeight")] core_chain_locked_height: u32, + ) { self.0.core_chain_locked_height = core_chain_locked_height; } @@ -57,12 +79,12 @@ impl ChainAssetLockProofWasm { } #[wasm_bindgen(getter = "coreChainLockedHeight")] - pub fn get_core_chain_locked_height(&self) -> u32 { + pub fn core_chain_locked_height(&self) -> u32 { self.0.core_chain_locked_height } #[wasm_bindgen(getter = "outPoint")] - pub fn get_out_point(&self) -> OutPointWasm { + pub fn out_point(&self) -> OutPointWasm { self.0.out_point.into() } @@ -88,4 +110,10 @@ impl ChainAssetLockProofWasm { } } -impl_wasm_conversions!(ChainAssetLockProofWasm, ChainAssetLockProof); +impl_wasm_conversions!( + ChainAssetLockProofWasm, + ChainAssetLockProof, + ChainAssetLockProofObjectJs, + ChainAssetLockProofJSONJs +); +impl_wasm_type_info!(ChainAssetLockProofWasm, ChainAssetLockProof); diff --git a/packages/wasm-dpp2/src/asset_lock_proof/instant/instant_asset_lock_proof.rs b/packages/wasm-dpp2/src/asset_lock_proof/instant/instant_asset_lock_proof.rs index 11d6eaf7549..2f030bf8cb0 100644 --- a/packages/wasm-dpp2/src/asset_lock_proof/instant/instant_asset_lock_proof.rs +++ b/packages/wasm-dpp2/src/asset_lock_proof/instant/instant_asset_lock_proof.rs @@ -2,11 +2,43 @@ use crate::asset_lock_proof::outpoint::OutPointWasm; use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; +use crate::utils::try_to_u32; use dpp::dashcore::consensus::{deserialize, serialize}; use dpp::dashcore::{InstantLock, Transaction}; use dpp::identity::state_transition::asset_lock_proof::InstantAssetLockProof; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * InstantAssetLockProof serialized as a plain object. + */ +export interface InstantAssetLockProofObject { + instantLock: Uint8Array; + transaction: Uint8Array; + outputIndex: number; +} + +/** + * InstantAssetLockProof serialized as JSON. + */ +export interface InstantAssetLockProofJSON { + instantLock: string; + transaction: string; + outputIndex: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "InstantAssetLockProofObject")] + pub type InstantAssetLockProofObjectJs; + + #[wasm_bindgen(typescript_type = "InstantAssetLockProofJSON")] + pub type InstantAssetLockProofJSONJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "InstantAssetLockProof")] pub struct InstantAssetLockProofWasm(InstantAssetLockProof); @@ -25,21 +57,11 @@ impl From for InstantAssetLockProofWasm { #[wasm_bindgen(js_class = InstantAssetLockProof)] impl InstantAssetLockProofWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "InstantAssetLockProof".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "InstantAssetLockProof".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - instant_lock: Vec, + pub fn constructor( + #[wasm_bindgen(js_name = "instantLock")] instant_lock: Vec, transaction: Vec, - output_index: u32, + #[wasm_bindgen(js_name = "outputIndex")] output_index: u32, ) -> WasmDppResult { let instant_lock: InstantLock = deserialize(instant_lock.as_slice()) .map_err(|err| WasmDppError::serialization(err.to_string()))?; @@ -53,40 +75,47 @@ impl InstantAssetLockProofWasm { })) } - #[wasm_bindgen(js_name = "getOutput")] - pub fn get_output(&self) -> Option> { + #[wasm_bindgen(getter = "output")] + pub fn output(&self) -> Option> { self.0.output().map(serialize) } - #[wasm_bindgen(js_name = "getOutPoint")] - pub fn get_out_point(&self) -> Option { + #[wasm_bindgen(getter = "outPoint")] + pub fn out_point(&self) -> Option { self.0.out_point().map(|output| output.into()) } #[wasm_bindgen(getter = "outputIndex")] - pub fn get_output_index(&self) -> u32 { + pub fn output_index(&self) -> u32 { self.0.output_index() } #[wasm_bindgen(getter = "instantLock")] - pub fn get_instant_lock(&self) -> Vec { + pub fn instant_lock(&self) -> Vec { serialize(&self.0.instant_lock) } #[wasm_bindgen(setter = "outputIndex")] - pub fn set_output_index(&mut self, output_index: u32) { - self.0.output_index = output_index; + pub fn set_output_index( + &mut self, + #[wasm_bindgen(js_name = "outputIndex")] output_index: &js_sys::Number, + ) -> WasmDppResult<()> { + self.0.output_index = try_to_u32(output_index, "outputIndex")?; + Ok(()) } #[wasm_bindgen(setter = "instantLock")] - pub fn set_instant_lock(&mut self, instant_lock: Vec) -> WasmDppResult<()> { + pub fn set_instant_lock( + &mut self, + #[wasm_bindgen(js_name = "instantLock")] instant_lock: Vec, + ) -> WasmDppResult<()> { self.0.instant_lock = deserialize(instant_lock.as_slice()) .map_err(|err| WasmDppError::serialization(err.to_string()))?; Ok(()) } - #[wasm_bindgen(js_name=getTransaction)] - pub fn get_transaction(&self) -> Vec { + #[wasm_bindgen(getter = "transaction")] + pub fn transaction(&self) -> Vec { let transaction = self.0.transaction(); serialize(transaction) } @@ -99,4 +128,10 @@ impl InstantAssetLockProofWasm { } } -impl_wasm_conversions!(InstantAssetLockProofWasm, InstantAssetLockProof); +impl_wasm_conversions!( + InstantAssetLockProofWasm, + InstantAssetLockProof, + InstantAssetLockProofObjectJs, + InstantAssetLockProofJSONJs +); +impl_wasm_type_info!(InstantAssetLockProofWasm, InstantAssetLockProof); diff --git a/packages/wasm-dpp2/src/asset_lock_proof/instant/mod.rs b/packages/wasm-dpp2/src/asset_lock_proof/instant/mod.rs index 8dcd8fcbd4a..0101a1d6fcd 100644 --- a/packages/wasm-dpp2/src/asset_lock_proof/instant/mod.rs +++ b/packages/wasm-dpp2/src/asset_lock_proof/instant/mod.rs @@ -1,3 +1,5 @@ mod instant_asset_lock_proof; -pub use instant_asset_lock_proof::InstantAssetLockProofWasm; +pub use instant_asset_lock_proof::{ + InstantAssetLockProofJSONJs, InstantAssetLockProofObjectJs, InstantAssetLockProofWasm, +}; diff --git a/packages/wasm-dpp2/src/asset_lock_proof/outpoint.rs b/packages/wasm-dpp2/src/asset_lock_proof/outpoint.rs index 0449bc555e2..017f5ead49f 100644 --- a/packages/wasm-dpp2/src/asset_lock_proof/outpoint.rs +++ b/packages/wasm-dpp2/src/asset_lock_proof/outpoint.rs @@ -1,4 +1,5 @@ use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_wasm_type_info; use crate::utils::IntoWasm; use dpp::dashcore::{OutPoint, Txid}; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; @@ -6,6 +7,34 @@ use dpp::platform_value::string_encoding::{decode, encode}; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * OutPoint serialized as a plain object. + */ +export interface OutPointObject { + txid: string; + vout: number; +} + +/** + * OutPoint serialized as JSON. + */ +export interface OutPointJSON { + txid: string; + vout: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "OutPointObject")] + pub type OutPointObjectJs; + + #[wasm_bindgen(typescript_type = "OutPointJSON")] + pub type OutPointJSONJs; +} + #[wasm_bindgen(js_name = "OutPoint")] #[derive(Clone)] pub struct OutPointWasm(OutPoint); @@ -22,29 +51,31 @@ impl From for OutPoint { } } -impl TryFrom for OutPointWasm { +impl TryFrom<&JsValue> for OutPointWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { + + fn try_from(value: &JsValue) -> Result { let value = value.to_wasm::("OutPoint")?; Ok(value.clone()) } } -#[wasm_bindgen(js_class = OutPoint)] -impl OutPointWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "OutPoint".to_string() - } +impl TryFrom for OutPointWasm { + type Error = WasmDppError; - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "OutPoint".to_string() + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) } +} +#[wasm_bindgen(js_class = OutPoint)] +impl OutPointWasm { #[wasm_bindgen(constructor)] - pub fn new(txid_hex: String, vout: u32) -> WasmDppResult { + pub fn constructor( + #[wasm_bindgen(js_name = "txidHex")] txid_hex: String, + vout: u32, + ) -> WasmDppResult { let out_point = Txid::from_hex(&txid_hex) .map_err(|err| WasmDppError::serialization(err.to_string()))?; @@ -54,13 +85,13 @@ impl OutPointWasm { })) } - #[wasm_bindgen(js_name = "getVOUT")] - pub fn get_vout(&self) -> u32 { + #[wasm_bindgen(getter = "vout")] + pub fn vout(&self) -> u32 { self.0.vout } - #[wasm_bindgen(js_name = "getTXID")] - pub fn get_tx_id(&self) -> String { + #[wasm_bindgen(getter = "txid")] + pub fn txid(&self) -> String { self.0.txid.to_hex() } @@ -85,33 +116,37 @@ impl OutPointWasm { } #[wasm_bindgen(js_name = "fromBytes")] - pub fn from_bytes(js_buffer: Vec) -> OutPointWasm { - let mut buffer = [0u8; 36]; - let bytes = js_buffer.as_slice(); - let len = bytes.len(); - buffer[..len].copy_from_slice(bytes); + pub fn from_bytes(buffer: Vec) -> WasmDppResult { + if buffer.len() != 36 { + return Err(WasmDppError::invalid_argument(format!( + "OutPoint must be exactly 36 bytes, got {}", + buffer.len() + ))); + } - OutPointWasm(OutPoint::from(buffer)) + let out_buffer: [u8; 36] = buffer.try_into().expect("length already validated"); + + Ok(OutPointWasm(OutPoint::from(out_buffer))) } #[wasm_bindgen(js_name = "fromHex")] pub fn from_hex(hex: String) -> WasmDppResult { let bytes = decode(hex.as_str(), Hex).map_err(|e| WasmDppError::serialization(e.to_string()))?; - Ok(OutPointWasm::from_bytes(bytes)) + OutPointWasm::from_bytes(bytes) } #[wasm_bindgen(js_name = "fromBase64")] pub fn from_base64(base64: String) -> WasmDppResult { let bytes = decode(base64.as_str(), Base64) .map_err(|e| WasmDppError::serialization(e.to_string()))?; - Ok(OutPointWasm::from_bytes(bytes)) + OutPointWasm::from_bytes(bytes) } } impl OutPointWasm { - pub fn vec_from_js_value(js_outpoints: &js_sys::Array) -> WasmDppResult> { - let outpoints: Vec = js_outpoints + pub fn vec_from_js_value(outpoints: &js_sys::Array) -> WasmDppResult> { + let outpoints: Vec = outpoints .iter() .map(OutPointWasm::try_from) .collect::, WasmDppError>>()?; @@ -119,3 +154,5 @@ impl OutPointWasm { Ok(outpoints) } } + +impl_wasm_type_info!(OutPointWasm, OutPoint); diff --git a/packages/wasm-dpp2/src/asset_lock_proof/proof.rs b/packages/wasm-dpp2/src/asset_lock_proof/proof.rs index 0210289aba2..a078b1f21d8 100644 --- a/packages/wasm-dpp2/src/asset_lock_proof/proof.rs +++ b/packages/wasm-dpp2/src/asset_lock_proof/proof.rs @@ -1,16 +1,72 @@ -use crate::asset_lock_proof::chain::ChainAssetLockProofWasm; -use crate::asset_lock_proof::instant::InstantAssetLockProofWasm; - +use crate::asset_lock_proof::chain::{ + ChainAssetLockProofJSONJs, ChainAssetLockProofObjectJs, ChainAssetLockProofWasm, +}; +use crate::asset_lock_proof::instant::{ + InstantAssetLockProofJSONJs, InstantAssetLockProofObjectJs, InstantAssetLockProofWasm, +}; use crate::asset_lock_proof::outpoint::OutPointWasm; use crate::enums::lock_types::AssetLockProofTypeWasm; use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; -use crate::utils::{IntoWasm, JsValueExt, get_class_type}; +use crate::impl_wasm_type_info; +use crate::utils::{IntoWasm, get_class_type, try_from_options}; use dpp::prelude::AssetLockProof; -use js_sys::{Object, Reflect}; -use wasm_bindgen::JsValue; -use wasm_bindgen::prelude::wasm_bindgen; +use js_sys::Reflect; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * AssetLockProof serialized as a plain object. + * Type 0 = Instant, Type 1 = Chain. + */ +export type AssetLockProofObject = + | ({ type: 0 } & InstantAssetLockProofObject) + | ({ type: 1 } & ChainAssetLockProofObject); + +/** + * AssetLockProof serialized as JSON. + * Type 0 = Instant, Type 1 = Chain. + */ +export type AssetLockProofJSON = + | ({ type: 0 } & InstantAssetLockProofJSON) + | ({ type: 1 } & ChainAssetLockProofJSON); +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "AssetLockProofObject")] + pub type AssetLockProofObjectJs; + + #[wasm_bindgen(typescript_type = "AssetLockProofJSON")] + pub type AssetLockProofJSONJs; +} + +impl From for InstantAssetLockProofObjectJs { + fn from(value: AssetLockProofObjectJs) -> Self { + JsValue::from(value).into() + } +} + +impl From for ChainAssetLockProofObjectJs { + fn from(value: AssetLockProofObjectJs) -> Self { + JsValue::from(value).into() + } +} + +impl From for InstantAssetLockProofJSONJs { + fn from(value: AssetLockProofJSONJs) -> Self { + JsValue::from(value).into() + } +} + +impl From for ChainAssetLockProofJSONJs { + fn from(value: AssetLockProofJSONJs) -> Self { + JsValue::from(value).into() + } +} #[wasm_bindgen(js_name = "AssetLockProof")] #[derive(Clone)] @@ -60,28 +116,24 @@ impl From for InstantAssetLockProofWasm { #[wasm_bindgen(js_class = AssetLockProof)] impl AssetLockProofWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "AssetLockProof".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "AssetLockProof".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(js_asset_lock_proof: &JsValue) -> WasmDppResult { - match get_class_type(js_asset_lock_proof)?.as_str() { + pub fn constructor( + #[wasm_bindgen( + unchecked_param_type = "ChainAssetLockProof | InstantAssetLockProof", + js_name = "assetLockProof" + )] + asset_lock_proof: &JsValue, + ) -> WasmDppResult { + match get_class_type(asset_lock_proof)?.as_str() { "ChainAssetLockProof" => { - let chain_lock = js_asset_lock_proof + let chain_lock = asset_lock_proof .to_wasm::("ChainAssetLockProof")? .clone(); Ok(AssetLockProofWasm::from(chain_lock)) } "InstantAssetLockProof" => { - let instant_lock = js_asset_lock_proof + let instant_lock = asset_lock_proof .to_wasm::("InstantAssetLockProof")? .clone(); @@ -95,41 +147,49 @@ impl AssetLockProofWasm { #[wasm_bindgen(js_name = "createInstantAssetLockProof")] pub fn new_instant_asset_lock_proof( - instant_lock: Vec, + #[wasm_bindgen(js_name = "instantLock")] instant_lock: Vec, transaction: Vec, - output_index: u32, + #[wasm_bindgen(js_name = "outputIndex")] output_index: u32, ) -> WasmDppResult { - Ok(InstantAssetLockProofWasm::new(instant_lock, transaction, output_index)?.into()) + Ok(InstantAssetLockProofWasm::constructor(instant_lock, transaction, output_index)?.into()) } #[wasm_bindgen(js_name = "createChainAssetLockProof")] pub fn new_chain_asset_lock_proof( - core_chain_locked_height: u32, - out_point: &OutPointWasm, + #[wasm_bindgen(js_name = "coreChainLockedHeight")] core_chain_locked_height: u32, + #[wasm_bindgen(js_name = "outPoint")] out_point: &OutPointWasm, ) -> WasmDppResult { - Ok(ChainAssetLockProofWasm::new(core_chain_locked_height, out_point)?.into()) + Ok(ChainAssetLockProofWasm::constructor(core_chain_locked_height, out_point)?.into()) } - #[wasm_bindgen(js_name = "getLockType")] - pub fn get_lock_type(&self) -> String { + #[wasm_bindgen(getter = "lockType")] + pub fn lock_type(&self) -> AssetLockProofTypeWasm { + match self.0 { + AssetLockProof::Chain(_) => AssetLockProofTypeWasm::Chain, + AssetLockProof::Instant(_) => AssetLockProofTypeWasm::Instant, + } + } + + #[wasm_bindgen(getter = "lockTypeName")] + pub fn lock_type_name(&self) -> String { match self.0 { AssetLockProof::Chain(_) => AssetLockProofTypeWasm::Chain.into(), AssetLockProof::Instant(_) => AssetLockProofTypeWasm::Instant.into(), } } - #[wasm_bindgen(js_name = "getInstantLockProof")] - pub fn get_instant_lock(&self) -> InstantAssetLockProofWasm { + #[wasm_bindgen(getter = "instantLockProof")] + pub fn instant_lock_proof(&self) -> InstantAssetLockProofWasm { self.clone().0.into() } - #[wasm_bindgen(js_name = "getChainLockProof")] - pub fn get_chain_lock(&self) -> ChainAssetLockProofWasm { + #[wasm_bindgen(getter = "chainLockProof")] + pub fn chain_lock_proof(&self) -> ChainAssetLockProofWasm { self.clone().0.into() } - #[wasm_bindgen(js_name = "getOutPoint")] - pub fn get_out_point(&self) -> Option { + #[wasm_bindgen(getter = "outPoint")] + pub fn out_point(&self) -> Option { self.0.out_point().map(OutPointWasm::from) } @@ -141,101 +201,82 @@ impl AssetLockProofWasm { } #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self) -> WasmDppResult { - let inner_object = match &self.0 { - AssetLockProof::Chain(chain) => { - ChainAssetLockProofWasm::from(chain.clone()).to_object()? - } - AssetLockProof::Instant(instant) => { - InstantAssetLockProofWasm::from(instant.clone()).to_object()? - } + pub fn to_object(&self) -> WasmDppResult { + let inner_object: JsValue = match &self.0 { + AssetLockProof::Chain(chain) => ChainAssetLockProofWasm::from(chain.clone()) + .to_object()? + .into(), + AssetLockProof::Instant(instant) => InstantAssetLockProofWasm::from(instant.clone()) + .to_object()? + .into(), }; // Add type field: 0 = Instant, 1 = Chain - let object = Object::from(inner_object); let proof_type: u8 = match &self.0 { AssetLockProof::Instant(_) => 0, AssetLockProof::Chain(_) => 1, }; Reflect::set( - &object, + &inner_object, &JsValue::from_str("type"), &JsValue::from(proof_type), ) .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; - Ok(object.into()) + Ok(inner_object.into()) } #[wasm_bindgen(js_name = "fromObject")] - pub fn from_object(js_value: JsValue) -> WasmDppResult { - let object = Object::from(js_value.clone()); - let proof_type = Reflect::get(&object, &JsValue::from_str("type")) - .map_err(|e| WasmDppError::invalid_argument(e.error_message()))?; - - let type_num = proof_type.as_f64().ok_or_else(|| { - WasmDppError::invalid_argument( - "AssetLockProof object must have a 'type' field (0 = Instant, 1 = Chain)" - .to_string(), - ) - })?; - - match type_num as u8 { - 0 => InstantAssetLockProofWasm::from_object(js_value).map(AssetLockProofWasm::from), - 1 => ChainAssetLockProofWasm::from_object(js_value).map(AssetLockProofWasm::from), - _ => Err(WasmDppError::invalid_argument(format!( - "Unknown AssetLockProof type: {}", - type_num - ))), + pub fn from_object(object: AssetLockProofObjectJs) -> WasmDppResult { + let proof_type: AssetLockProofTypeWasm = try_from_options(&object, "type")?; + + match proof_type { + AssetLockProofTypeWasm::Instant => { + InstantAssetLockProofWasm::from_object(object.into()).map(AssetLockProofWasm::from) + } + AssetLockProofTypeWasm::Chain => { + ChainAssetLockProofWasm::from_object(object.into()).map(AssetLockProofWasm::from) + } } } #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self) -> WasmDppResult { - let inner_json = match &self.0 { - AssetLockProof::Chain(chain) => { - ChainAssetLockProofWasm::from(chain.clone()).to_json()? - } - AssetLockProof::Instant(instant) => { - InstantAssetLockProofWasm::from(instant.clone()).to_json()? - } + pub fn to_json(&self) -> WasmDppResult { + let inner_json: JsValue = match &self.0 { + AssetLockProof::Chain(chain) => ChainAssetLockProofWasm::from(chain.clone()) + .to_json()? + .into(), + AssetLockProof::Instant(instant) => InstantAssetLockProofWasm::from(instant.clone()) + .to_json()? + .into(), }; // Add type field: 0 = Instant, 1 = Chain - let object = Object::from(inner_json); let proof_type: u8 = match &self.0 { AssetLockProof::Instant(_) => 0, AssetLockProof::Chain(_) => 1, }; Reflect::set( - &object, + &inner_json, &JsValue::from_str("type"), &JsValue::from(proof_type), ) .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; - Ok(object.into()) + Ok(inner_json.into()) } #[wasm_bindgen(js_name = "fromJSON")] - pub fn from_json(js_value: JsValue) -> WasmDppResult { - let object = Object::from(js_value.clone()); - let proof_type = Reflect::get(&object, &JsValue::from_str("type")) - .map_err(|e| WasmDppError::invalid_argument(e.error_message()))?; - - let type_num = proof_type.as_f64().ok_or_else(|| { - WasmDppError::invalid_argument( - "AssetLockProof JSON must have a 'type' field (0 = Instant, 1 = Chain)".to_string(), - ) - })?; - - match type_num as u8 { - 0 => InstantAssetLockProofWasm::from_json(js_value).map(AssetLockProofWasm::from), - 1 => ChainAssetLockProofWasm::from_json(js_value).map(AssetLockProofWasm::from), - _ => Err(WasmDppError::invalid_argument(format!( - "Unknown AssetLockProof type: {}", - type_num - ))), + pub fn from_json(object: AssetLockProofJSONJs) -> WasmDppResult { + let proof_type: AssetLockProofTypeWasm = try_from_options(&object, "type")?; + + match proof_type { + AssetLockProofTypeWasm::Instant => { + InstantAssetLockProofWasm::from_json(object.into()).map(AssetLockProofWasm::from) + } + AssetLockProofTypeWasm::Chain => { + ChainAssetLockProofWasm::from_json(object.into()).map(AssetLockProofWasm::from) + } } } @@ -247,7 +288,9 @@ impl AssetLockProofWasm { } #[wasm_bindgen(js_name = "fromHex")] - pub fn from_hex(asset_lock_proof: String) -> WasmDppResult { + pub fn from_hex( + #[wasm_bindgen(js_name = "assetLockProof")] asset_lock_proof: String, + ) -> WasmDppResult { let bytes = hex::decode(asset_lock_proof) .map_err(|e| WasmDppError::serialization(e.to_string()))?; let proof: AssetLockProof = bincode::decode_from_slice(&bytes, bincode::config::standard()) @@ -271,4 +314,6 @@ impl AssetLockProofWasm { } } -impl_try_from_options!(AssetLockProofWasm, "AssetLockProof"); +impl_try_from_js_value!(AssetLockProofWasm, "AssetLockProof"); +impl_try_from_options!(AssetLockProofWasm); +impl_wasm_type_info!(AssetLockProofWasm, AssetLockProof); diff --git a/packages/wasm-dpp2/src/block.rs b/packages/wasm-dpp2/src/block.rs index fde4fbd7468..7d6adf5d923 100644 --- a/packages/wasm-dpp2/src/block.rs +++ b/packages/wasm-dpp2/src/block.rs @@ -1,9 +1,65 @@ use crate::error::{WasmDppError, WasmDppResult}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use dpp::block::block_info::BlockInfo; use dpp::block::epoch::Epoch; +use serde::Deserialize; use wasm_bindgen::prelude::*; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct BlockInfoOptions { + time_ms: u64, + height: u64, + core_height: u32, + epoch_index: u16, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Options for creating a BlockInfo instance. + */ +export interface BlockInfoOptions { + timeMs: bigint; + height: bigint; + coreHeight: number; + epochIndex: number; +} + +/** + * BlockInfo serialized as a plain object. + */ +export interface BlockInfoObject { + timeMs: bigint; + height: bigint; + coreHeight: number; + epochIndex: number; +} + +/** + * BlockInfo serialized as JSON. + */ +export interface BlockInfoJSON { + timeMs: string; + height: string; + coreHeight: number; + epochIndex: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "BlockInfoOptions")] + pub type BlockInfoOptionsJs; + + #[wasm_bindgen(typescript_type = "BlockInfoObject")] + pub type BlockInfoObjectJs; + + #[wasm_bindgen(typescript_type = "BlockInfoJSON")] + pub type BlockInfoJSONJs; +} + #[wasm_bindgen(js_name = "BlockInfo")] #[derive(Clone)] pub struct BlockInfoWasm(BlockInfo); @@ -11,19 +67,17 @@ pub struct BlockInfoWasm(BlockInfo); #[wasm_bindgen(js_class = BlockInfo)] impl BlockInfoWasm { #[wasm_bindgen(constructor)] - pub fn new( - time_ms: u64, - height: u64, - core_height: u32, - epoch_index: u16, - ) -> WasmDppResult { - let epoch = - Epoch::new(epoch_index).map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + pub fn constructor(options: BlockInfoOptionsJs) -> WasmDppResult { + let opts: BlockInfoOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + + let epoch = Epoch::new(opts.epoch_index) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(BlockInfoWasm(BlockInfo { - time_ms, - height, - core_height, + time_ms: opts.time_ms, + height: opts.height, + core_height: opts.core_height, epoch, })) } @@ -67,4 +121,6 @@ impl From<&BlockInfoWasm> for BlockInfo { } } -impl_wasm_conversions!(BlockInfoWasm, BlockInfo); +impl_wasm_conversions!(BlockInfoWasm, BlockInfo, BlockInfoObjectJs, BlockInfoJSONJs); + +impl_wasm_type_info!(BlockInfoWasm, BlockInfo); diff --git a/packages/wasm-dpp2/src/consensus_error.rs b/packages/wasm-dpp2/src/consensus_error.rs index 3385bf3dfb2..4b82fbfde86 100644 --- a/packages/wasm-dpp2/src/consensus_error.rs +++ b/packages/wasm-dpp2/src/consensus_error.rs @@ -1,4 +1,5 @@ use crate::error::WasmDppResult; +use crate::impl_wasm_type_info; use dpp::consensus::ConsensusError; use dpp::serialization::PlatformDeserializable; use wasm_bindgen::prelude::wasm_bindgen; @@ -20,3 +21,5 @@ impl ConsensusErrorWasm { self.0.to_string() } } + +impl_wasm_type_info!(ConsensusErrorWasm, ConsensusError); diff --git a/packages/wasm-dpp2/src/core/core_script.rs b/packages/wasm-dpp2/src/core/core_script.rs index bff72dc7aed..64735b05800 100644 --- a/packages/wasm-dpp2/src/core/core_script.rs +++ b/packages/wasm-dpp2/src/core/core_script.rs @@ -1,12 +1,13 @@ -use super::network::NetworkWasm; +use super::network::{NetworkLikeJs, NetworkWasm}; use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use dpp::dashcore::address::Payload; use dpp::dashcore::{Address, opcodes}; use dpp::identity::core_script::CoreScript; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::encode; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; #[wasm_bindgen(js_name = "CoreScript")] @@ -27,37 +28,39 @@ impl From for CoreScriptWasm { #[wasm_bindgen(js_class = CoreScript)] impl CoreScriptWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "CoreScript".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "CoreScript".to_string() - } - #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes(bytes: Vec) -> Self { CoreScriptWasm(CoreScript::from_bytes(bytes)) } - #[wasm_bindgen(js_name = "newP2PKH")] - pub fn new_p2pkh(key_hash: Vec) -> Self { - let mut key_hash_bytes = [0u8; 20]; - let bytes = key_hash.as_slice(); - let len = bytes.len().min(key_hash_bytes.len()); - key_hash_bytes[..len].copy_from_slice(&bytes[..len]); + #[wasm_bindgen(js_name = "fromP2PKH")] + pub fn from_p2pkh( + #[wasm_bindgen(js_name = "keyHash")] key_hash: Vec, + ) -> WasmDppResult { + if key_hash.len() != 20 { + return Err(WasmDppError::invalid_argument(format!( + "P2PKH key hash must be exactly 20 bytes, got {}", + key_hash.len() + ))); + } + + let key_hash_bytes: [u8; 20] = key_hash.try_into().expect("length already validated"); - CoreScriptWasm(CoreScript::new_p2pkh(key_hash_bytes)) + Ok(CoreScriptWasm(CoreScript::new_p2pkh(key_hash_bytes))) } - #[wasm_bindgen(js_name = "newP2SH")] - pub fn new_p2sh(script_hash: Vec) -> Self { - let mut script_hash_bytes = [0u8; 20]; - let bytes = script_hash.as_slice(); - let len = bytes.len().min(script_hash_bytes.len()); - script_hash_bytes[..len].copy_from_slice(&bytes[..len]); + #[wasm_bindgen(js_name = "fromP2SH")] + pub fn from_p2sh( + #[wasm_bindgen(js_name = "scriptHash")] script_hash: Vec, + ) -> WasmDppResult { + if script_hash.len() != 20 { + return Err(WasmDppError::invalid_argument(format!( + "P2SH script hash must be exactly 20 bytes, got {}", + script_hash.len() + ))); + } + + let script_hash_bytes: [u8; 20] = script_hash.try_into().expect("length already validated"); let mut bytes = vec![ opcodes::all::OP_HASH160.to_u8(), @@ -65,15 +68,12 @@ impl CoreScriptWasm { ]; bytes.extend_from_slice(&script_hash_bytes); bytes.push(opcodes::all::OP_EQUAL.to_u8()); - Self::from_bytes(bytes) + Ok(Self::from_bytes(bytes)) } #[wasm_bindgen(js_name = "toAddress")] - pub fn to_address( - &self, - #[wasm_bindgen(unchecked_param_type = "Network | string")] network: &JsValue, - ) -> WasmDppResult { - let network_wasm = NetworkWasm::try_from(network.clone())?; + pub fn to_address(&self, network: NetworkLikeJs) -> WasmDppResult { + let network_wasm: NetworkWasm = network.try_into()?; let payload = Payload::from_script(self.0.as_script()) .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; @@ -109,4 +109,6 @@ impl CoreScriptWasm { } } -impl_try_from_options!(CoreScriptWasm, "CoreScript"); +impl_try_from_js_value!(CoreScriptWasm, "CoreScript"); +impl_try_from_options!(CoreScriptWasm); +impl_wasm_type_info!(CoreScriptWasm, CoreScript); diff --git a/packages/wasm-dpp2/src/core/network.rs b/packages/wasm-dpp2/src/core/network.rs index 34d0d9894e9..66329f482d7 100644 --- a/packages/wasm-dpp2/src/core/network.rs +++ b/packages/wasm-dpp2/src/core/network.rs @@ -1,11 +1,11 @@ -use crate::error::{WasmDppError, WasmDppResult}; +use crate::error::WasmDppError; use dpp::dashcore::Network; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; /// TypeScript type alias for flexible network input #[wasm_bindgen(typescript_custom_section)] -const NETWORK_LIKE_TS: &'static str = r#" +const NETWORK_LIKE_TS: &str = r#" /** * Flexible network type that accepts Network enum, string names, or numeric values. * @@ -15,6 +15,28 @@ const NETWORK_LIKE_TS: &'static str = r#" export type NetworkLike = Network | "mainnet" | "testnet" | "devnet" | "regtest" | 0 | 1 | 2 | 3; "#; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "NetworkLike")] + pub type NetworkLikeJs; +} + +impl TryFrom for NetworkWasm { + type Error = WasmDppError; + fn try_from(value: NetworkLikeJs) -> Result { + let js_value: JsValue = value.into(); + NetworkWasm::try_from(js_value) + } +} + +impl TryFrom for Network { + type Error = WasmDppError; + fn try_from(value: NetworkLikeJs) -> Result { + let wasm: NetworkWasm = value.try_into()?; + Ok(Network::from(wasm)) + } +} + #[wasm_bindgen(js_name = "Network")] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[allow(non_camel_case_types)] @@ -112,45 +134,6 @@ impl From for NetworkWasm { } impl NetworkWasm { - /// Try to extract a Network from an options object field. - /// - /// This helper reads the specified field from an options object and converts it - /// to a NetworkWasm. Accepts Network enum or string names. - pub fn try_from_options(options: &JsValue, field_name: &str) -> WasmDppResult { - let network_js = - js_sys::Reflect::get(options, &JsValue::from_str(field_name)).map_err(|_| { - WasmDppError::invalid_argument(format!("Missing '{}' field", field_name)) - })?; - - if network_js.is_undefined() || network_js.is_null() { - return Err(WasmDppError::invalid_argument(format!( - "'{}' is required", - field_name - ))); - } - - NetworkWasm::try_from(&network_js) - } - - /// Try to extract an optional Network from an options object field. - /// - /// Returns None if the field is undefined or null, otherwise attempts conversion. - pub fn try_from_options_optional( - options: &JsValue, - field_name: &str, - ) -> WasmDppResult> { - let network_js = - js_sys::Reflect::get(options, &JsValue::from_str(field_name)).map_err(|_| { - WasmDppError::invalid_argument(format!("Failed to get '{}'", field_name)) - })?; - - if network_js.is_undefined() || network_js.is_null() { - return Ok(None); - } - - NetworkWasm::try_from(&network_js).map(Some) - } - /// Get the network name as a lowercase string (for compatibility with existing code) pub fn as_str(&self) -> &'static str { match self { diff --git a/packages/wasm-dpp2/src/core/private_key.rs b/packages/wasm-dpp2/src/core/private_key.rs index a09b2af0bd4..f39c8f3c950 100644 --- a/packages/wasm-dpp2/src/core/private_key.rs +++ b/packages/wasm-dpp2/src/core/private_key.rs @@ -1,14 +1,15 @@ use std::convert::TryInto; -use super::network::NetworkWasm; +use super::network::{NetworkLikeJs, NetworkWasm}; use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; +use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use crate::public_key::PublicKeyWasm; -use crate::utils::IntoWasm; use dpp::dashcore::PrivateKey; use dpp::dashcore::hashes::hex::FromHex; use dpp::dashcore::key::Secp256k1; use dpp::dashcore::secp256k1::hashes::hex::{Case, DisplayHex}; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; #[wasm_bindgen(js_name = "PrivateKey")] @@ -36,16 +37,6 @@ impl PrivateKeyWasm { #[wasm_bindgen(js_class = PrivateKey)] impl PrivateKeyWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "PrivateKey".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "PrivateKey".to_string() - } - #[wasm_bindgen(js_name = "fromWIF")] pub fn from_wif(wif: &str) -> WasmDppResult { let pk = PrivateKey::from_wif(wif) @@ -55,11 +46,8 @@ impl PrivateKeyWasm { } #[wasm_bindgen(js_name = "fromBytes")] - pub fn from_bytes( - bytes: Vec, - #[wasm_bindgen(unchecked_param_type = "Network | string")] network: JsValue, - ) -> WasmDppResult { - let network_wasm = NetworkWasm::try_from(network)?; + pub fn from_bytes(bytes: Vec, network: NetworkLikeJs) -> WasmDppResult { + let network_wasm: NetworkWasm = network.try_into()?; let key_bytes: [u8; 32] = bytes.try_into().map_err(|_| { WasmDppError::invalid_argument("Private key bytes must be exactly 32 bytes".to_string()) @@ -73,10 +61,10 @@ impl PrivateKeyWasm { #[wasm_bindgen(js_name = "fromHex")] pub fn from_hex( - hex_key: &str, - #[wasm_bindgen(unchecked_param_type = "Network | string")] network: JsValue, + #[wasm_bindgen(js_name = "hexKey")] hex_key: &str, + network: NetworkLikeJs, ) -> WasmDppResult { - let network_wasm = NetworkWasm::try_from(network)?; + let network_wasm: NetworkWasm = network.try_into()?; let bytes = Vec::from_hex(hex_key) .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; @@ -103,8 +91,8 @@ impl PrivateKeyWasm { #[wasm_bindgen(js_class = PrivateKey)] impl PrivateKeyWasm { - #[wasm_bindgen(js_name = "WIF")] - pub fn get_wif(&self) -> String { + #[wasm_bindgen(js_name = "toWIF")] + pub fn to_wif(&self) -> String { self.0.to_wif() } @@ -126,26 +114,6 @@ impl PrivateKeyWasm { } } -impl PrivateKeyWasm { - /// Try to extract a PrivateKey from an options object field. - /// - /// This helper reads the specified field from an options object and converts it - /// to a PrivateKeyWasm. - pub fn try_from_options(options: &JsValue, field_name: &str) -> WasmDppResult { - let key_js = - js_sys::Reflect::get(options, &JsValue::from_str(field_name)).map_err(|_| { - WasmDppError::invalid_argument(format!("Missing '{}' field", field_name)) - })?; - - if key_js.is_undefined() || key_js.is_null() { - return Err(WasmDppError::invalid_argument(format!( - "'{}' is required", - field_name - ))); - } - - key_js - .to_wasm::("PrivateKey") - .map(|boxed| (*boxed).clone()) - } -} +impl_try_from_js_value!(PrivateKeyWasm, "PrivateKey"); +impl_try_from_options!(PrivateKeyWasm); +impl_wasm_type_info!(PrivateKeyWasm, PrivateKey); diff --git a/packages/wasm-dpp2/src/core/pro_tx_hash.rs b/packages/wasm-dpp2/src/core/pro_tx_hash.rs index beebf323018..b55de99e34a 100644 --- a/packages/wasm-dpp2/src/core/pro_tx_hash.rs +++ b/packages/wasm-dpp2/src/core/pro_tx_hash.rs @@ -1,13 +1,15 @@ use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_wasm_type_info; +use crate::utils::{IntoWasm, try_to_fixed_bytes}; use dpp::dashcore::ProTxHash; use dpp::dashcore::hashes::{Hash, sha256d}; use std::str::FromStr; +use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::{JsCast, JsValue}; /// TypeScript type alias for flexible ProTxHash input #[wasm_bindgen(typescript_custom_section)] -const PRO_TX_HASH_LIKE_TS: &'static str = r#" +const PRO_TX_HASH_LIKE_TS: &str = r#" /** * Flexible ProTxHash type that accepts ProTxHash object, hex string, or Uint8Array. * @@ -15,8 +17,58 @@ const PRO_TX_HASH_LIKE_TS: &'static str = r#" * - Uint8Array: 32 bytes in internal byte order */ export type ProTxHashLike = ProTxHash | string | Uint8Array; +export type ProTxHashLikeArray = Array; "#; +/// Extern type for flexible ProTxHash input +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ProTxHashLike")] + pub type ProTxHashLikeJs; + + #[wasm_bindgen(typescript_type = "ProTxHashLike | null")] + pub type ProTxHashLikeNullableJs; + + #[wasm_bindgen(typescript_type = "ProTxHashLikeArray")] + pub type ProTxHashLikeArrayJs; +} + +impl TryFrom for ProTxHashWasm { + type Error = WasmDppError; + + fn try_from(value: ProTxHashLikeJs) -> Result { + let js_value: JsValue = value.into(); + ProTxHashWasm::try_from(js_value) + } +} + +impl TryFrom for ProTxHash { + type Error = WasmDppError; + + fn try_from(value: ProTxHashLikeJs) -> Result { + let wasm: ProTxHashWasm = value.try_into()?; + Ok(ProTxHash::from(wasm)) + } +} + +impl TryFrom for Option { + type Error = WasmDppError; + + fn try_from(value: ProTxHashLikeNullableJs) -> Result { + let js_value: JsValue = value.into(); + if js_value.is_null() || js_value.is_undefined() { + return Ok(None); + } + // Check for empty string + if let Some(s) = js_value.as_string() + && s.is_empty() + { + return Ok(None); + } + ProTxHashWasm::try_from(js_value).map(|w| Some(ProTxHash::from(w))) + } +} + #[wasm_bindgen(js_name = "ProTxHash")] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ProTxHashWasm(ProTxHash); @@ -53,60 +105,18 @@ impl ProTxHashWasm { .map_err(|e| WasmDppError::invalid_argument(format!("Invalid ProTxHash hex: {}", e)))?; Ok(ProTxHashWasm(hash)) } - - /// Try to extract a ProTxHash from an options object field. - /// - /// This helper reads the specified field from an options object and converts it - /// to a ProTxHashWasm. Accepts hex string, Uint8Array, or ProTxHash object. - pub fn try_from_options(options: &JsValue, field_name: &str) -> WasmDppResult { - let hash_js = - js_sys::Reflect::get(options, &JsValue::from_str(field_name)).map_err(|_| { - WasmDppError::invalid_argument(format!("Missing '{}' field", field_name)) - })?; - - if hash_js.is_undefined() || hash_js.is_null() { - return Err(WasmDppError::invalid_argument(format!( - "'{}' is required", - field_name - ))); - } - - ProTxHashWasm::try_from(&hash_js) - } - - /// Try to extract an optional ProTxHash from an options object field. - /// - /// Returns None if the field is undefined, null, or an empty string/array. - /// Otherwise attempts conversion. - pub fn try_from_options_optional( - options: &JsValue, - field_name: &str, - ) -> WasmDppResult> { - let hash_js = - js_sys::Reflect::get(options, &JsValue::from_str(field_name)).map_err(|_| { - WasmDppError::invalid_argument(format!("Failed to get '{}'", field_name)) - })?; - - if hash_js.is_undefined() || hash_js.is_null() { - return Ok(None); - } - - // Check for empty string - if let Some(s) = hash_js.as_string() - && s.is_empty() - { - return Ok(None); - } - - ProTxHashWasm::try_from(&hash_js).map(Some) - } } impl TryFrom for ProTxHashWasm { type Error = WasmDppError; fn try_from(value: JsValue) -> Result { - // Try as string first (hex format) + // Try as ProTxHash object first + if let Ok(wasm) = value.to_wasm::("ProTxHash") { + return Ok(*wasm); + } + + // Try as string (hex format) if let Some(hex_str) = value.as_string() { let hash = ProTxHash::from_str(&hex_str).map_err(|e| { WasmDppError::invalid_argument(format!("Invalid ProTxHash hex string: {}", e)) @@ -114,24 +124,15 @@ impl TryFrom for ProTxHashWasm { return Ok(ProTxHashWasm(hash)); } - // Try as Uint8Array - if value.is_instance_of::() { - let bytes = js_sys::Uint8Array::new(&value).to_vec(); - if bytes.len() != 32 { - return Err(WasmDppError::invalid_argument(format!( - "ProTxHash must be exactly 32 bytes, got {} bytes", - bytes.len() - ))); - } - let mut arr = [0u8; 32]; - arr.copy_from_slice(&bytes); + // Try as Uint8Array (validates type and 32-byte length) + if let Ok(arr) = try_to_fixed_bytes::<32>(value.clone(), "proTxHash") { let raw = sha256d::Hash::from_byte_array(arr); let hash = ProTxHash::from_raw_hash(raw); return Ok(ProTxHashWasm(hash)); } Err(WasmDppError::invalid_argument( - "ProTxHash must be a hex string or Uint8Array (32 bytes)", + "ProTxHash must be a ProTxHash object, hex string, or Uint8Array (32 bytes)", )) } } @@ -155,3 +156,5 @@ impl From for ProTxHashWasm { ProTxHashWasm(hash) } } + +impl_wasm_type_info!(ProTxHashWasm, ProTxHash); diff --git a/packages/wasm-dpp2/src/data_contract/contract_bounds.rs b/packages/wasm-dpp2/src/data_contract/contract_bounds.rs index 1242c9fafbd..eaf8af6f735 100644 --- a/packages/wasm-dpp2/src/data_contract/contract_bounds.rs +++ b/packages/wasm-dpp2/src/data_contract/contract_bounds.rs @@ -1,11 +1,42 @@ use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use dpp::identity::contract_bounds::ContractBounds; use dpp::prelude::Identifier; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * ContractBounds serialized as a plain object. + */ +export interface ContractBoundsObject { + identifier: Uint8Array; + documentTypeName?: string; + contractBoundsType: "SingleContract" | "SingleContractDocumentType"; +} + +/** + * ContractBounds serialized as JSON. + */ +export interface ContractBoundsJSON { + identifier: string; + documentTypeName?: string; + contractBoundsType: "SingleContract" | "SingleContractDocumentType"; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ContractBoundsObject")] + pub type ContractBoundsObjectJs; + + #[wasm_bindgen(typescript_type = "ContractBoundsJSON")] + pub type ContractBoundsJSONJs; +} + #[wasm_bindgen(js_name = "ContractBounds")] #[derive(Clone)] pub struct ContractBoundsWasm(ContractBounds); @@ -24,23 +55,12 @@ impl From for ContractBounds { #[wasm_bindgen(js_class = ContractBounds)] impl ContractBoundsWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "ContractBounds".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "ContractBounds".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, - document_type_name: Option, + pub fn constructor( + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "documentTypeName")] document_type_name: Option, ) -> WasmDppResult { - let contract_id: Identifier = IdentifierWasm::try_from(js_contract_id)?.into(); + let contract_id: Identifier = contract_id.try_into()?; Ok(ContractBoundsWasm(match document_type_name { Some(document_type_name) => ContractBounds::SingleContractDocumentType { @@ -53,10 +73,9 @@ impl ContractBoundsWasm { #[wasm_bindgen(js_name = "SingleContract")] pub fn single_contract( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> WasmDppResult { - let contract_id: Identifier = IdentifierWasm::try_from(js_contract_id)?.into(); + let contract_id: Identifier = contract_id.try_into()?; Ok(ContractBoundsWasm(ContractBounds::SingleContract { id: contract_id, @@ -65,11 +84,10 @@ impl ContractBoundsWasm { #[wasm_bindgen(js_name = "SingleContractDocumentType")] pub fn single_contract_document_type_name( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, - document_type_name: String, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "documentTypeName")] document_type_name: String, ) -> WasmDppResult { - let contract_id: Identifier = IdentifierWasm::try_from(js_contract_id)?.into(); + let contract_id: Identifier = contract_id.try_into()?; Ok(ContractBoundsWasm( ContractBounds::SingleContractDocumentType { @@ -102,10 +120,9 @@ impl ContractBoundsWasm { #[wasm_bindgen(setter = "identifier")] pub fn set_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let contract_id: Identifier = IdentifierWasm::try_from(js_contract_id)?.into(); + let contract_id: Identifier = contract_id.try_into()?; self.0 = match self.clone().0 { ContractBounds::SingleContract { .. } => { @@ -123,7 +140,10 @@ impl ContractBoundsWasm { } #[wasm_bindgen(setter = "documentTypeName")] - pub fn set_document_type_name(&mut self, document_type_name: String) { + pub fn set_document_type_name( + &mut self, + #[wasm_bindgen(js_name = "documentTypeName")] document_type_name: String, + ) { self.0 = match self.clone().0 { ContractBounds::SingleContract { .. } => self.clone().0, ContractBounds::SingleContractDocumentType { id, .. } => { @@ -136,4 +156,11 @@ impl ContractBoundsWasm { } } -impl_wasm_conversions!(ContractBoundsWasm, ContractBounds); +impl_wasm_conversions!( + ContractBoundsWasm, + ContractBounds, + ContractBoundsObjectJs, + ContractBoundsJSONJs +); +impl_try_from_js_value!(ContractBoundsWasm, "ContractBounds"); +impl_wasm_type_info!(ContractBoundsWasm, ContractBounds); diff --git a/packages/wasm-dpp2/src/data_contract/document/model.rs b/packages/wasm-dpp2/src/data_contract/document/model.rs index 63019a7d384..bc5109ae815 100644 --- a/packages/wasm-dpp2/src/data_contract/document/model.rs +++ b/packages/wasm-dpp2/src/data_contract/document/model.rs @@ -1,10 +1,14 @@ use crate::data_contract::DataContractWasm; -use crate::enums::platform::PlatformVersionWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use crate::serialization; -use crate::utils::ToSerdeJSONExt; +use crate::utils::{ + ToSerdeJSONExt, try_from_options, try_from_options_optional, try_from_options_with, +}; +use crate::version::{PlatformVersionLikeJs, PlatformVersionWasm}; use dpp::document::serialization_traits::{ DocumentJsonMethodsV0, DocumentPlatformConversionMethodsV0, DocumentPlatformValueMethodsV0, }; @@ -13,7 +17,6 @@ use dpp::identifier::Identifier; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::encode; use dpp::platform_value::{Value, ValueMapHelper}; -use dpp::prelude::Revision; use dpp::util::entropy_generator; use dpp::util::entropy_generator::EntropyGenerator; use dpp::version::PlatformVersion; @@ -21,9 +24,77 @@ use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +/// TypeScript interface for Document constructor options +#[wasm_bindgen(typescript_custom_section)] +const DOCUMENT_OPTIONS_TS: &str = r#" +/** + * Options for creating a new Document. + */ +export interface DocumentOptions { + /** Document properties/data */ + properties: Record; + /** Document type name from the data contract */ + documentTypeName: string; + /** Data contract ID this document belongs to */ + dataContractId: IdentifierLike; + /** Owner identity ID */ + ownerId: IdentifierLike; + /** Document revision (default: 1n) */ + revision?: bigint; + /** Document ID (auto-generated if not provided) */ + id?: IdentifierLike; + /** Entropy bytes (32 bytes, auto-generated if not provided) */ + entropy?: Uint8Array; +} + +/** + * Document serialized as a plain object. + * Note: u64 fields are serialized as BigInt when using toObject(). + */ +export interface DocumentObject { + $id: Identifier; + $ownerId: Identifier; + $revision?: bigint; + $createdAt?: bigint; + $updatedAt?: bigint; + $transferredAt?: bigint; + $createdAtBlockHeight?: bigint; + $updatedAtBlockHeight?: bigint; + $transferredAtBlockHeight?: bigint; + $createdAtCoreBlockHeight?: number; + $updatedAtCoreBlockHeight?: number; + $transferredAtCoreBlockHeight?: number; + $dataContractId: Identifier; + $type: string; + [key: string]: unknown; +} + +/** + * Document serialized as JSON (with string identifiers). + * Note: u64 fields are stringified since JSON doesn't support BigInt. + */ +export interface DocumentJSON { + $id: string; + $ownerId: string; + $revision?: string; + $createdAt?: string; + $updatedAt?: string; + $transferredAt?: string; + $createdAtBlockHeight?: string; + $updatedAtBlockHeight?: string; + $transferredAtBlockHeight?: string; + $createdAtCoreBlockHeight?: number; + $updatedAtCoreBlockHeight?: number; + $transferredAtCoreBlockHeight?: number; + $dataContractId: string; + $type: string; + [key: string]: unknown; +} +"#; + /// DocumentWasm wraps a Document and adds metadata fields that are not part of the core Document. #[derive(Clone, serde::Serialize, Deserialize)] -#[wasm_bindgen(js_name = Document)] +#[wasm_bindgen(js_name = "Document")] pub struct DocumentWasm { #[serde(skip_serializing, skip_deserializing, default = "default_document")] pub(crate) document: Document, @@ -87,51 +158,79 @@ impl DocumentWasm { } } +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentOptions")] + pub type DocumentOptionsJs; + + #[wasm_bindgen(typescript_type = "DocumentObject")] + pub type DocumentObjectJs; + + #[wasm_bindgen(typescript_type = "DocumentJSON")] + pub type DocumentJSONJs; + + #[wasm_bindgen(typescript_type = "Record")] + pub type DocumentPropertiesJs; +} + +/// Serde struct for DocumentOptions (primitives only) +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct DocumentOptionsInput { + document_type_name: String, + #[serde(default)] + revision: Option, + #[serde(default)] + entropy: Option<[u8; 32]>, +} + #[wasm_bindgen(js_class = Document)] impl DocumentWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "Document".to_string() - } + #[wasm_bindgen(constructor)] + pub fn constructor(options: DocumentOptionsJs) -> WasmDppResult { + // Extract complex types first (borrows &options) + let data_contract_id: IdentifierWasm = try_from_options(&options, "dataContractId")?; + let data_contract_id: Identifier = data_contract_id.into(); - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "Document".to_string() - } + let owner_id: IdentifierWasm = try_from_options(&options, "ownerId")?; + let owner_id: Identifier = owner_id.into(); - #[wasm_bindgen(constructor)] - pub fn constructor( - js_raw_document: JsValue, - js_document_type_name: &str, - js_revision: u64, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_data_contract_id: &JsValue, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_owner_id: &JsValue, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_document_id: &JsValue, - ) -> WasmDppResult { - let data_contract_id: Identifier = IdentifierWasm::try_from(js_data_contract_id)?.into(); - let owner_id: Identifier = IdentifierWasm::try_from(js_owner_id)?.into(); - let revision = Revision::from(js_revision); - let properties = js_raw_document.with_serde_to_platform_value_map()?; - - let entropy = entropy_generator::DefaultEntropyGenerator - .generate() - .map_err(|err| WasmDppError::serialization(err.to_string()))?; - - let document_id: Identifier = match js_document_id.is_undefined() { - true => crate::utils::generate_document_id_v0( - &data_contract_id, - &owner_id, - js_document_type_name, - &entropy, - )?, - false => IdentifierWasm::try_from(js_document_id)?.into(), - }; + let id: Option = try_from_options_optional(&options, "id")?; + + let properties = try_from_options_with(&options, "properties", |v| { + v.with_serde_to_platform_value_map() + })?; + + // Deserialize primitive fields via serde last (consumes options) + let input: DocumentOptionsInput = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + + let document_type_name = input.document_type_name; + let revision = input.revision.unwrap_or(1); + + let entropy: [u8; 32] = input.entropy.map_or_else( + || { + entropy_generator::DefaultEntropyGenerator + .generate() + .map_err(|err| WasmDppError::serialization(err.to_string())) + }, + Ok, + )?; + + let doc_id: Identifier = id.map_or_else( + || { + crate::utils::generate_document_id_v0( + &data_contract_id, + &owner_id, + &document_type_name, + &entropy, + ) + }, + |id| Ok(id.into()), + )?; let document = Document::V0(DocumentV0 { - id: document_id, + id: doc_id, owner_id, properties, revision: Some(revision), @@ -150,33 +249,33 @@ impl DocumentWasm { Ok(DocumentWasm::new( document, data_contract_id, - js_document_type_name.to_string(), + document_type_name, Some(entropy), )) } - #[wasm_bindgen(getter=id)] - pub fn get_id(&self) -> IdentifierWasm { + #[wasm_bindgen(getter = id)] + pub fn id(&self) -> IdentifierWasm { self.document.id().into() } - #[wasm_bindgen(getter=entropy)] - pub fn get_entropy(&self) -> Option> { + #[wasm_bindgen(getter = entropy)] + pub fn entropy(&self) -> Option> { self.entropy.map(|entropy| entropy.to_vec()) } - #[wasm_bindgen(getter=dataContractId)] - pub fn get_data_contract_id(&self) -> IdentifierWasm { + #[wasm_bindgen(getter = dataContractId)] + pub fn data_contract_id(&self) -> IdentifierWasm { self.data_contract_id } - #[wasm_bindgen(getter=ownerId)] - pub fn get_owner_id(&self) -> IdentifierWasm { + #[wasm_bindgen(getter = ownerId)] + pub fn owner_id(&self) -> IdentifierWasm { self.document.owner_id().into() } - #[wasm_bindgen(getter=properties)] - pub fn get_properties(&self) -> WasmDppResult { + #[wasm_bindgen(getter = properties)] + pub fn properties(&self) -> WasmDppResult { let properties_value = Value::Map( self.document .properties() @@ -184,116 +283,112 @@ impl DocumentWasm { .map(|(k, v)| (Value::Text(k.clone()), v.clone())) .collect(), ); - serialization::platform_value_to_object(&properties_value) + let js_value = serialization::platform_value_to_object(&properties_value)?; + Ok(js_value.into()) } - #[wasm_bindgen(getter=revision)] - pub fn get_revision(&self) -> Option { + #[wasm_bindgen(getter = revision)] + pub fn revision(&self) -> Option { self.document.revision() } - #[wasm_bindgen(getter=createdAt)] - pub fn get_created_at(&self) -> Option { + #[wasm_bindgen(getter = createdAt)] + pub fn created_at(&self) -> Option { self.document.created_at() } - #[wasm_bindgen(getter=updatedAt)] - pub fn get_updated_at(&self) -> Option { + #[wasm_bindgen(getter = updatedAt)] + pub fn updated_at(&self) -> Option { self.document.updated_at() } - #[wasm_bindgen(getter=transferredAt)] - pub fn get_transferred_at(&self) -> Option { + #[wasm_bindgen(getter = transferredAt)] + pub fn transferred_at(&self) -> Option { self.document.transferred_at() } - #[wasm_bindgen(getter=createdAtBlockHeight)] - pub fn get_created_at_block_height(&self) -> Option { + #[wasm_bindgen(getter = createdAtBlockHeight)] + pub fn created_at_block_height(&self) -> Option { self.document.created_at_block_height() } - #[wasm_bindgen(getter=updatedAtBlockHeight)] - pub fn get_updated_at_block_height(&self) -> Option { + #[wasm_bindgen(getter = updatedAtBlockHeight)] + pub fn updated_at_block_height(&self) -> Option { self.document.updated_at_block_height() } - #[wasm_bindgen(getter=transferredAtBlockHeight)] - pub fn get_transferred_at_block_height(&self) -> Option { + #[wasm_bindgen(getter = transferredAtBlockHeight)] + pub fn transferred_at_block_height(&self) -> Option { self.document.transferred_at_block_height() } - #[wasm_bindgen(getter=createdAtCoreBlockHeight)] - pub fn get_created_at_core_block_height(&self) -> Option { + #[wasm_bindgen(getter = createdAtCoreBlockHeight)] + pub fn created_at_core_block_height(&self) -> Option { self.document.created_at_core_block_height() } - #[wasm_bindgen(getter=updatedAtCoreBlockHeight)] - pub fn get_updated_at_core_block_height(&self) -> Option { + #[wasm_bindgen(getter = updatedAtCoreBlockHeight)] + pub fn updated_at_core_block_height(&self) -> Option { self.document.updated_at_core_block_height() } - #[wasm_bindgen(getter=transferredAtCoreBlockHeight)] - pub fn get_transferred_at_core_block_height(&self) -> Option { + #[wasm_bindgen(getter = transferredAtCoreBlockHeight)] + pub fn transferred_at_core_block_height(&self) -> Option { self.document.transferred_at_core_block_height() } - #[wasm_bindgen(getter=documentTypeName)] - pub fn get_document_type_name(&self) -> String { + #[wasm_bindgen(getter = documentTypeName)] + pub fn document_type_name(&self) -> String { self.document_type_name.clone() } #[wasm_bindgen(setter=id)] - pub fn set_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] id: &JsValue, - ) -> WasmDppResult<()> { - let identifier: Identifier = IdentifierWasm::try_from(id)?.into(); - self.document.set_id(identifier); + pub fn set_id(&mut self, id: IdentifierLikeJs) -> WasmDppResult<()> { + self.document.set_id(id.try_into()?); Ok(()) } #[wasm_bindgen(setter=entropy)] - pub fn set_entropy(&mut self, entropy: JsValue) -> WasmDppResult<()> { - if entropy.is_undefined() { - self.entropy = None; - return Ok(()); + pub fn set_entropy(&mut self, entropy: Option>) -> WasmDppResult<()> { + match entropy { + None => { + self.entropy = None; + } + Some(bytes) => { + if bytes.len() != 32 { + return Err(WasmDppError::invalid_argument(format!( + "Entropy must be exactly 32 bytes, got {}", + bytes.len() + ))); + } + let mut entropy_bytes = [0u8; 32]; + entropy_bytes.copy_from_slice(&bytes); + self.entropy = Some(entropy_bytes); + } } - - let value = entropy.with_serde_to_platform_value()?; - let bytes = value.as_bytes().ok_or_else(|| { - WasmDppError::invalid_argument("Entropy must be provided as a byte array") - })?; - - let mut entropy_bytes = [0u8; 32]; - let len = bytes.len().min(32); - entropy_bytes[..len].copy_from_slice(&bytes[..len]); - self.entropy = Some(entropy_bytes); - Ok(()) } #[wasm_bindgen(setter=dataContractId)] - pub fn set_js_data_contract_id( + pub fn set_data_contract_id_js( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, + data_contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - self.data_contract_id = IdentifierWasm::try_from(js_contract_id)?; + self.data_contract_id = data_contract_id.try_into()?; Ok(()) } #[wasm_bindgen(setter=ownerId)] - pub fn set_owner_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] id: &JsValue, - ) -> WasmDppResult<()> { - let identifier: Identifier = IdentifierWasm::try_from(id)?.into(); - self.document.set_owner_id(identifier); + pub fn set_owner_id(&mut self, id: IdentifierLikeJs) -> WasmDppResult<()> { + self.document.set_owner_id(id.try_into()?); Ok(()) } #[wasm_bindgen(setter=properties)] - pub fn set_properties(&mut self, properties: JsValue) -> WasmDppResult<()> { + pub fn set_properties( + &mut self, + #[wasm_bindgen(unchecked_param_type = "Record")] properties: JsValue, + ) -> WasmDppResult<()> { let props = properties.with_serde_to_platform_value_map()?; *self.document.properties_mut() = props; Ok(()) @@ -305,46 +400,76 @@ impl DocumentWasm { } #[wasm_bindgen(setter=createdAt)] - pub fn set_created_at(&mut self, created_at: Option) { + pub fn set_created_at( + &mut self, + #[wasm_bindgen(js_name = "createdAt")] created_at: Option, + ) { self.document.set_created_at(created_at); } #[wasm_bindgen(setter=updatedAt)] - pub fn set_updated_at(&mut self, updated_at: Option) { + pub fn set_updated_at( + &mut self, + #[wasm_bindgen(js_name = "updatedAt")] updated_at: Option, + ) { self.document.set_updated_at(updated_at); } #[wasm_bindgen(setter=transferredAt)] - pub fn set_transferred_at(&mut self, transferred_at: Option) { + pub fn set_transferred_at( + &mut self, + #[wasm_bindgen(js_name = "transferredAt")] transferred_at: Option, + ) { self.document.set_transferred_at(transferred_at); } #[wasm_bindgen(setter=createdAtBlockHeight)] - pub fn set_created_at_block_height(&mut self, created_at_block_height: Option) { + pub fn set_created_at_block_height( + &mut self, + #[wasm_bindgen(js_name = "createdAtBlockHeight")] created_at_block_height: Option, + ) { self.document .set_created_at_block_height(created_at_block_height); } #[wasm_bindgen(setter=updatedAtBlockHeight)] - pub fn set_updated_at_block_height(&mut self, updated_at_block_height: Option) { + pub fn set_updated_at_block_height( + &mut self, + #[wasm_bindgen(js_name = "updatedAtBlockHeight")] updated_at_block_height: Option, + ) { self.document .set_updated_at_block_height(updated_at_block_height); } #[wasm_bindgen(setter=transferredAtBlockHeight)] - pub fn set_transferred_at_block_height(&mut self, transferred_at_block_height: Option) { + pub fn set_transferred_at_block_height( + &mut self, + #[wasm_bindgen(js_name = "transferredAtBlockHeight")] transferred_at_block_height: Option< + u64, + >, + ) { self.document .set_transferred_at_block_height(transferred_at_block_height); } #[wasm_bindgen(setter=createdAtCoreBlockHeight)] - pub fn set_created_at_core_block_height(&mut self, created_at_core_block_height: Option) { + pub fn set_created_at_core_block_height( + &mut self, + #[wasm_bindgen(js_name = "createdAtCoreBlockHeight")] created_at_core_block_height: Option< + u32, + >, + ) { self.document .set_created_at_core_block_height(created_at_core_block_height); } #[wasm_bindgen(setter=updatedAtCoreBlockHeight)] - pub fn set_updated_at_core_block_height(&mut self, updated_at_core_block_height: Option) { + pub fn set_updated_at_core_block_height( + &mut self, + #[wasm_bindgen(js_name = "updatedAtCoreBlockHeight")] updated_at_core_block_height: Option< + u32, + >, + ) { self.document .set_updated_at_core_block_height(updated_at_core_block_height); } @@ -352,20 +477,23 @@ impl DocumentWasm { #[wasm_bindgen(setter=transferredAtCoreBlockHeight)] pub fn set_transferred_at_core_block_height( &mut self, - transferred_at_core_block_height: Option, + #[wasm_bindgen(js_name = "transferredAtCoreBlockHeight")] transferred_at_core_block_height: Option, ) { self.document .set_transferred_at_core_block_height(transferred_at_core_block_height); } #[wasm_bindgen(setter=documentTypeName)] - pub fn set_document_type_name(&mut self, document_type_name: &str) { + pub fn set_document_type_name( + &mut self, + #[wasm_bindgen(js_name = "documentTypeName")] document_type_name: &str, + ) { self.document_type_name = document_type_name.to_string(); } /// Convert to a JS object with binary fields as Uint8Array. - #[wasm_bindgen(js_name = toObject)] - pub fn to_object(&self) -> WasmDppResult { + #[wasm_bindgen(js_name = "toObject")] + pub fn to_object(&self) -> WasmDppResult { let mut map = self.document.to_map_value()?; // Add metadata fields not in core Document let data_contract_id: Identifier = self.data_contract_id.into(); @@ -380,15 +508,16 @@ impl DocumentWasm { if let Some(entropy) = self.entropy { map.insert("$entropy".to_string(), Value::Bytes(entropy.to_vec())); } - serialization::platform_value_to_object(&Value::Map( + let js_value = serialization::platform_value_to_object(&Value::Map( map.into_iter().map(|(k, v)| (Value::Text(k), v)).collect(), - )) + ))?; + Ok(js_value.into()) } /// Create a Document from a JS object. - #[wasm_bindgen(js_name = fromObject)] - pub fn from_object(js_value: JsValue) -> WasmDppResult { - let platform_value = serialization::js_value_to_platform_value(&js_value)?; + #[wasm_bindgen(js_name = "fromObject")] + pub fn from_object(value: DocumentObjectJs) -> WasmDppResult { + let platform_value = serialization::js_value_to_platform_value(&value.into())?; let Value::Map(mut map) = platform_value else { return Err(WasmDppError::invalid_argument("Expected an object")); @@ -431,8 +560,8 @@ impl DocumentWasm { } /// Convert to a JSON-compatible JS object with binary fields as strings. - #[wasm_bindgen(js_name = toJSON)] - pub fn to_json(&self) -> WasmDppResult { + #[wasm_bindgen(js_name = "toJSON")] + pub fn to_json(&self) -> WasmDppResult { // Get document fields as JSON let mut json_value = self.document.to_json(PlatformVersion::latest())?; @@ -450,14 +579,15 @@ impl DocumentWasm { } } - serialization::json_to_js_value(&json_value) + let js_value = serialization::json_to_js_value(&json_value)?; + Ok(js_value.into()) } /// Create a Document from a JSON object. /// JSON format has identifiers as base58 strings. - #[wasm_bindgen(js_name = fromJSON)] - pub fn from_json(js_value: JsValue) -> WasmDppResult { - let mut json_value = serialization::js_value_to_json(&js_value)?; + #[wasm_bindgen(js_name = "fromJSON")] + pub fn from_json(value: DocumentJSONJs) -> WasmDppResult { + let mut json_value = serialization::js_value_to_json(&value.into())?; // Deserialize wrapper fields using serde let mut wrapper: DocumentWasm = serde_json::from_value(json_value.clone()) @@ -477,139 +607,106 @@ impl DocumentWasm { Ok(wrapper) } - #[wasm_bindgen(js_name=toBytes)] + #[wasm_bindgen(js_name = "toBytes")] pub fn to_bytes( &self, data_contract: &DataContractWasm, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult> { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; - - let document_type_ref = data_contract - .get_document_type_ref_by_name(self.get_document_type_name()) - .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; - - self.document - .serialize( - document_type_ref, - &data_contract.clone().into(), - &platform_version.into(), - ) - .map_err(Into::into) + self.to_bytes_internal(data_contract, platform_version) } - #[wasm_bindgen(js_name=toHex)] + #[wasm_bindgen(js_name = "toHex")] pub fn to_hex( &self, data_contract: &DataContractWasm, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { Ok(encode( - self.to_bytes(data_contract, js_platform_version)? + self.to_bytes_internal(data_contract, platform_version)? .as_slice(), Hex, )) } - #[wasm_bindgen(js_name=toBase64)] + #[wasm_bindgen(js_name = "toBase64")] pub fn to_base64( &self, data_contract: &DataContractWasm, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { Ok(encode( - self.to_bytes(data_contract, js_platform_version)? + self.to_bytes_internal(data_contract, platform_version)? .as_slice(), Base64, )) } - #[wasm_bindgen(js_name=fromBytes)] + #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes( bytes: Vec, - data_contract: &DataContractWasm, - type_name: String, - js_platform_version: JsValue, + #[wasm_bindgen(js_name = "dataContract")] data_contract: &DataContractWasm, + #[wasm_bindgen(js_name = "typeName")] type_name: String, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; - - let document_type_ref = data_contract - .get_document_type_ref_by_name(type_name.clone()) - .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; - - let document = Document::from_bytes( - bytes.as_slice(), - document_type_ref, - &platform_version.into(), - )?; - - Ok(DocumentWasm::new( - document, - data_contract.get_id().into(), - type_name, - None, - )) + Self::from_bytes_internal(bytes, data_contract, type_name, platform_version.into()) } - #[wasm_bindgen(js_name=fromHex)] + #[wasm_bindgen(js_name = "fromHex")] pub fn from_hex( hex: String, - data_contract: &DataContractWasm, - type_name: String, - js_platform_version: JsValue, + #[wasm_bindgen(js_name = "dataContract")] data_contract: &DataContractWasm, + #[wasm_bindgen(js_name = "typeName")] type_name: String, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { use dpp::platform_value::string_encoding::decode; - DocumentWasm::from_bytes( + Self::from_bytes_internal( decode(hex.as_str(), Hex) .map_err(|err| WasmDppError::serialization(err.to_string()))?, data_contract, type_name, - js_platform_version, + platform_version.into(), ) } - #[wasm_bindgen(js_name=fromBase64)] + #[wasm_bindgen(js_name = "fromBase64")] pub fn from_base64( base64: String, - data_contract: &DataContractWasm, - type_name: String, - js_platform_version: JsValue, + #[wasm_bindgen(js_name = "dataContract")] data_contract: &DataContractWasm, + #[wasm_bindgen(js_name = "typeName")] type_name: String, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { use dpp::platform_value::string_encoding::decode; - DocumentWasm::from_bytes( + Self::from_bytes_internal( decode(base64.as_str(), Base64) .map_err(|err| WasmDppError::serialization(err.to_string()))?, data_contract, type_name, - js_platform_version, + platform_version.into(), ) } - #[wasm_bindgen(js_name=generateId)] + #[wasm_bindgen(js_name = "generateId")] pub fn generate_id( - js_document_type_name: &str, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_owner_id: &JsValue, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_data_contract_id: &JsValue, - opt_entropy: Option>, + #[wasm_bindgen(js_name = "documentTypeName")] document_type_name: &str, + #[wasm_bindgen(js_name = "ownerId")] owner_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, + entropy: Option>, ) -> WasmDppResult> { - let owner_id: Identifier = IdentifierWasm::try_from(js_owner_id)?.into(); - let data_contract_id: Identifier = IdentifierWasm::try_from(js_data_contract_id)?.into(); + let owner_id: Identifier = owner_id.try_into()?; + let data_contract_id: Identifier = data_contract_id.try_into()?; - let entropy: [u8; 32] = match opt_entropy { + let entropy_bytes: [u8; 32] = match entropy { Some(entropy_vec) => { - let mut entropy = [0u8; 32]; - let bytes = entropy_vec.as_slice(); - let len = bytes.len().min(32); - entropy[..len].copy_from_slice(&bytes[..len]); - entropy + if entropy_vec.len() != 32 { + return Err(WasmDppError::invalid_argument(format!( + "Entropy must be exactly 32 bytes, got {}", + entropy_vec.len() + ))); + } + let mut arr = [0u8; 32]; + arr.copy_from_slice(&entropy_vec); + arr } None => entropy_generator::DefaultEntropyGenerator .generate() @@ -619,12 +716,62 @@ impl DocumentWasm { let identifier = crate::utils::generate_document_id_v0( &data_contract_id, &owner_id, - js_document_type_name, - &entropy, + document_type_name, + &entropy_bytes, )?; Ok(identifier.to_vec()) } } -impl_try_from_options!(DocumentWasm, "Document"); +impl DocumentWasm { + fn to_bytes_internal( + &self, + data_contract: &DataContractWasm, + platform_version: PlatformVersionLikeJs, + ) -> WasmDppResult> { + let platform_version: PlatformVersionWasm = platform_version.try_into()?; + + let document_type_ref = data_contract + .get_document_type_ref_by_name(self.document_type_name()) + .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; + + self.document + .serialize( + document_type_ref, + &data_contract.clone().into(), + &platform_version.into(), + ) + .map_err(Into::into) + } + + fn from_bytes_internal( + bytes: Vec, + data_contract: &DataContractWasm, + type_name: String, + platform_version: JsValue, + ) -> WasmDppResult { + let platform_version = PlatformVersionWasm::try_from(platform_version)?; + + let document_type_ref = data_contract + .get_document_type_ref_by_name(type_name.clone()) + .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; + + let document = Document::from_bytes( + bytes.as_slice(), + document_type_ref, + &platform_version.into(), + )?; + + Ok(DocumentWasm::new( + document, + data_contract.id().into(), + type_name, + None, + )) + } +} + +impl_try_from_js_value!(DocumentWasm, "Document"); +impl_try_from_options!(DocumentWasm); +impl_wasm_type_info!(DocumentWasm, Document); diff --git a/packages/wasm-dpp2/src/data_contract/model.rs b/packages/wasm-dpp2/src/data_contract/model.rs index c81023f2ff8..18fe46bc52f 100644 --- a/packages/wasm-dpp2/src/data_contract/model.rs +++ b/packages/wasm-dpp2/src/data_contract/model.rs @@ -1,11 +1,16 @@ -use crate::enums::platform::PlatformVersionWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use crate::serialization; use crate::tokens::configuration::TokenConfigurationWasm; use crate::tokens::configuration::group::GroupWasm; -use crate::utils::{IntoWasm, JsValueExt}; +use crate::utils::{ + IntoWasm, JsValueExt, try_from_options, try_from_options_optional, + try_from_options_optional_with, try_from_options_with, try_to_object, try_to_u16, try_to_u32, +}; +use crate::version::{PlatformVersionLikeJs, PlatformVersionWasm}; use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; use dpp::data_contract::accessors::v1::{DataContractV1Getters, DataContractV1Setters}; use dpp::data_contract::config::DataContractConfig; @@ -28,10 +33,101 @@ use dpp::serialization::{ }; use dpp::version::PlatformVersion; use js_sys::{Object, Reflect}; +use serde::Deserialize; use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct DataContractOptions { + identity_nonce: IdentityNonce, + #[serde(default = "default_full_validation")] + full_validation: bool, +} + +fn default_full_validation() -> bool { + true +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface DataContractOptions { + ownerId: IdentifierLike; + identityNonce: bigint; + schemas: object; + definitions?: object; + tokens?: Record; + fullValidation?: boolean; + platformVersion?: PlatformVersionLike; +} + +/** + * DataContract serialized as a plain object. + */ +export interface DataContractObject { + $format_version: string; + id: Identifier; + ownerId: Identifier; + version: number; + documentSchemas: Record; + config?: DataContractConfig; + groups?: Record; + tokens?: Record; + [key: string]: unknown; +} + +/** + * DataContract serialized as JSON (with string identifiers). + */ +export interface DataContractJSON { + $format_version: string; + id: string; + ownerId: string; + version: number; + documentSchemas: Record; + config?: DataContractConfig; + groups?: Record; + tokens?: Record; + [key: string]: unknown; +} + +/** + * DataContract configuration. + */ +export interface DataContractConfig { + canBeDeleted: boolean; + readonly: boolean; + keepsHistory: boolean; + documentsKeepHistoryContractDefault: boolean; + documentsMutableContractDefault: boolean; + documentsCanBeDeletedContractDefault: boolean; + requiresIdentityEncryptionBoundedKey?: number; + requiresIdentityDecryptionBoundedKey?: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DataContractOptions")] + pub type DataContractOptionsJs; + + #[wasm_bindgen(typescript_type = "DataContractObject")] + pub type DataContractObjectJs; + + #[wasm_bindgen(typescript_type = "DataContractJSON")] + pub type DataContractJSONJs; + + #[wasm_bindgen(typescript_type = "DataContractConfig")] + pub type DataContractConfigJs; + + #[wasm_bindgen(typescript_type = "Record")] + pub type DataContractSchemasJs; + + #[wasm_bindgen(typescript_type = "Record")] + pub type DataContractGroupsJs; +} + #[wasm_bindgen(js_name = "DataContract")] #[derive(Clone)] pub struct DataContractWasm(DataContract); @@ -49,77 +145,59 @@ impl From for DataContract { } pub fn tokens_configuration_from_js_value( - js_configuration: &JsValue, + configuration: &JsValue, ) -> WasmDppResult> { - let configuration_object = Object::from(js_configuration.clone()); + let configuration_object = try_to_object(configuration.clone(), "tokens")?; let configuration_keys = Object::keys(&configuration_object); - let mut configuration: BTreeMap = BTreeMap::new(); + let mut result: BTreeMap = BTreeMap::new(); for key in configuration_keys.iter() { - let contract_position = match key.as_string() { - None => Err(WasmDppError::invalid_argument( - "Cannot read timestamp in distribution rules", - )), - Some(contract_position) => Ok(contract_position - .parse::() - .map_err(|e| WasmDppError::serialization(e.to_string()))?), - }?; - - let js_config = Reflect::get(&configuration_object, &key) - .map_err(|err| { - let message = err.error_message(); - WasmDppError::invalid_argument(format!( - "unable to read token configuration at contract position '{}': {}", - contract_position, message - )) - })? - .to_wasm::("TokenConfiguration")? - .clone(); + let contract_position = try_to_u16(&key, "contract position")?; - configuration.insert(contract_position, js_config.into()); + let token_config: TokenConfigurationWasm = try_from_options( + &configuration_object.clone().into(), + &contract_position.to_string(), + )?; + + result.insert(contract_position, token_config.into()); } - Ok(configuration) + Ok(result) } #[wasm_bindgen(js_class = DataContract)] impl DataContractWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DataContract".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DataContract".to_string() - } - #[wasm_bindgen(constructor)] - pub fn from_js_values( - js_owner_id: &JsValue, - identity_nonce: IdentityNonce, - js_schema: JsValue, - js_definitions: Option, - js_tokens: &JsValue, - full_validation: bool, - js_platform_version: JsValue, - ) -> WasmDppResult { - let owner_id: IdentifierWasm = js_owner_id.clone().try_into()?; - - // Use object format deserializer (handles BigInt/Uint8Array) - let schema: Value = serialization::platform_value_from_object(js_schema)?; + pub fn constructor(options: DataContractOptionsJs) -> WasmDppResult { + // Extract complex types first (borrows &options) + let owner_id: IdentifierWasm = try_from_options(&options, "ownerId")?; + let owner_id: Identifier = owner_id.into(); + + let platform_version: PlatformVersion = + try_from_options_optional::(&options, "platformVersion")? + .map(Into::into) + .unwrap_or_else(|| PlatformVersionWasm::default().into()); + + let schema: Value = try_from_options_with(&options, "schemas", |v| { + serialization::platform_value_from_object(v) + })?; + + let definitions: Option = try_from_options_optional_with( + &options, + "definitions", + serialization::platform_value_from_object, + )?; let tokens: BTreeMap = - match js_tokens.is_undefined() { - true => BTreeMap::new(), - false => tokens_configuration_from_js_value(js_tokens)?, - }; - - let platform_version: PlatformVersion = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default().into(), - false => PlatformVersionWasm::try_from(js_platform_version)?.into(), - }; + try_from_options_optional_with(&options, "tokens", |v| { + tokens_configuration_from_js_value(v) + })? + .unwrap_or_default(); + + // Extract primitive fields via serde last (consumes options) + let opts: DataContractOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; let data_contract_structure_version_value = Value::from( platform_version @@ -129,14 +207,10 @@ impl DataContractWasm { .to_string(), ); - let definitions: Option = js_definitions - .map(|definitions| serialization::platform_value_from_object(definitions.into())) - .transpose()?; - let definitions_value = Value::from(definitions); let data_contract_id = - DataContract::generate_data_contract_id_v0(owner_id.to_bytes(), identity_nonce); + DataContract::generate_data_contract_id_v0(owner_id.to_buffer(), opts.identity_nonce); let data_contract_id_value = Value::Identifier(data_contract_id.to_buffer()); @@ -163,13 +237,8 @@ impl DataContractWasm { .set_value("version", Value::from(1u16)) .map_err(|err| WasmDppError::serialization(err.to_string()))?; - let owner_id_bytes: [u8; 32] = owner_id - .to_bytes() - .try_into() - .map_err(|_| WasmDppError::invalid_argument("Invalid owner ID length"))?; - contract_value - .set_value("ownerId", Value::Identifier(owner_id_bytes)) + .set_value("ownerId", Value::Identifier(owner_id.to_buffer())) .map_err(|err| WasmDppError::serialization(err.to_string()))?; contract_value @@ -181,7 +250,7 @@ impl DataContractWasm { .map_err(|err| WasmDppError::serialization(err.to_string()))?; let data_contract = - DataContract::from_value(contract_value, full_validation, &platform_version)?; + DataContract::from_value(contract_value, opts.full_validation, &platform_version)?; let data_contract_with_tokens = match data_contract { DataContract::V0(v0) => DataContract::from(v0), @@ -197,16 +266,13 @@ impl DataContractWasm { #[wasm_bindgen(js_name = "fromJSON")] pub fn from_json( - js_value: JsValue, + value: DataContractJSONJs, full_validation: bool, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; - let json_value = serialization::js_value_to_json(&js_value)?; + let json_value = serialization::js_value_to_json(&value.into())?; let contract = DataContract::from_json(json_value, full_validation, &platform_version.into())?; @@ -216,16 +282,14 @@ impl DataContractWasm { #[wasm_bindgen(js_name = "fromObject")] pub fn from_object( - js_value: JsValue, + value: DataContractObjectJs, full_validation: bool, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; - let platform_value: Value = serialization::platform_value_from_object(js_value)?; + let value: JsValue = value.into(); + let platform_value: Value = serialization::platform_value_from_object(&value)?; let contract = DataContract::from_value(platform_value, full_validation, &platform_version.into()) @@ -238,109 +302,106 @@ impl DataContractWasm { pub fn from_bytes( bytes: Vec, full_validation: bool, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; - - let rs_data_contract = DataContract::versioned_deserialize( - bytes.as_slice(), - full_validation, - &platform_version.into(), - )?; - - Ok(DataContractWasm(rs_data_contract)) + Self::from_bytes_internal(bytes, full_validation, platform_version.into()) } #[wasm_bindgen(js_name = "fromHex")] pub fn from_hex( hex: String, full_validation: bool, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { let bytes = decode(hex.as_str(), Hex).map_err(|e| WasmDppError::serialization(e.to_string()))?; - DataContractWasm::from_bytes(bytes, full_validation, js_platform_version) + Self::from_bytes_internal(bytes, full_validation, platform_version.into()) } #[wasm_bindgen(js_name = "fromBase64")] pub fn from_base64( base64: String, full_validation: bool, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { let bytes = decode(base64.as_str(), Base64) .map_err(|e| WasmDppError::serialization(e.to_string()))?; - DataContractWasm::from_bytes(bytes, full_validation, js_platform_version) + Self::from_bytes_internal(bytes, full_validation, platform_version.into()) } #[wasm_bindgen(js_name = "toBytes")] - pub fn to_bytes(&self, js_platform_version: JsValue) -> WasmDppResult> { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; - - let rs_data_contract: DataContract = self.0.clone(); - - Ok(rs_data_contract.serialize_to_bytes_with_platform_version(&platform_version.into())?) + pub fn to_bytes( + &self, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, + ) -> WasmDppResult> { + self.to_bytes_internal(platform_version.into()) } #[wasm_bindgen(js_name = "toHex")] - pub fn to_hex(&self, js_platform_version: JsValue) -> WasmDppResult { - Ok(encode(self.to_bytes(js_platform_version)?.as_slice(), Hex)) + pub fn to_hex( + &self, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, + ) -> WasmDppResult { + Ok(encode( + self.to_bytes_internal(platform_version.into())?.as_slice(), + Hex, + )) } #[wasm_bindgen(js_name = "toBase64")] - pub fn to_base64(&self, js_platform_version: JsValue) -> WasmDppResult { + pub fn to_base64( + &self, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, + ) -> WasmDppResult { Ok(encode( - self.to_bytes(js_platform_version)?.as_slice(), + self.to_bytes_internal(platform_version.into())?.as_slice(), Base64, )) } #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self, js_platform_version: JsValue) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + pub fn to_object( + &self, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, + ) -> WasmDppResult { + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let value = self.0.clone().to_value(&platform_version.into())?; - serialization::platform_value_to_object(&value) + let js_value = serialization::platform_value_to_object(&value)?; + Ok(js_value.into()) } - #[wasm_bindgen(js_name = "getSchemas")] - pub fn get_schemas(&self) -> WasmDppResult { - serialization::to_object(&self.0.document_schemas()) + #[wasm_bindgen(getter = "schemas")] + pub fn schemas(&self) -> WasmDppResult { + let js_value = serialization::to_object(&self.0.document_schemas())?; + Ok(js_value.into()) } #[wasm_bindgen(getter = "version")] - pub fn get_version(&self) -> u32 { + pub fn version(&self) -> u32 { self.0.version() } #[wasm_bindgen(getter = "id")] - pub fn get_id(&self) -> IdentifierWasm { + pub fn id(&self) -> IdentifierWasm { self.0.id().into() } #[wasm_bindgen(getter = "ownerId")] - pub fn get_owner_id(&self) -> IdentifierWasm { + pub fn owner_id(&self) -> IdentifierWasm { self.0.owner_id().into() } - #[wasm_bindgen(js_name = "getConfig")] - pub fn get_config(&self) -> WasmDppResult { - serialization::to_object(self.0.config()) + #[wasm_bindgen(getter = "config")] + pub fn config(&self) -> WasmDppResult { + let js_value = serialization::to_object(self.0.config())?; + Ok(js_value.into()) } #[wasm_bindgen(getter = "tokens")] - pub fn get_tokens(&self) -> WasmDppResult { + pub fn tokens(&self) -> WasmDppResult { let tokens_object = Object::new(); for (key, value) in self.0.tokens().iter() { @@ -362,7 +423,7 @@ impl DataContractWasm { } #[wasm_bindgen(getter = "groups")] - pub fn get_groups(&self) -> WasmDppResult { + pub fn groups(&self) -> WasmDppResult { let groups_object = Object::new(); for (key, value) in self.0.groups().iter() { @@ -380,48 +441,40 @@ impl DataContractWasm { })?; } - Ok(groups_object.into()) + Ok(JsValue::from(groups_object).into()) } #[wasm_bindgen(setter = "id")] - pub fn set_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_data_contract_id: &JsValue, - ) -> WasmDppResult<()> { - self.0 - .set_id(IdentifierWasm::try_from(js_data_contract_id)?.into()); + pub fn set_id(&mut self, id: IdentifierLikeJs) -> WasmDppResult<()> { + self.0.set_id(id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "ownerId")] pub fn set_owner_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_owner_id: &JsValue, + #[wasm_bindgen(js_name = "ownerId")] owner_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - self.0 - .set_owner_id(IdentifierWasm::try_from(js_owner_id)?.into()); + self.0.set_owner_id(owner_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "version")] - pub fn set_version(&mut self, version: u32) { - self.0.set_version(version) + pub fn set_version(&mut self, version: JsValue) -> WasmDppResult<()> { + self.0.set_version(try_to_u32(&version, "version")?); + Ok(()) } #[wasm_bindgen(js_name = "setConfig")] pub fn set_config( &mut self, - js_config: JsValue, - js_platform_version: JsValue, + config: DataContractConfigJs, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult<()> { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let config: JsValue = config.into(); + let platform_version = PlatformVersionWasm::try_from(platform_version)?; - let config_value: Value = serde_wasm_bindgen::from_value(js_config) + let config_value: Value = serde_wasm_bindgen::from_value(config) .map_err(|err| WasmDppError::serialization(err.to_string()))?; let config = DataContractConfig::from_value(config_value, &platform_version.into())?; @@ -434,25 +487,22 @@ impl DataContractWasm { #[wasm_bindgen(js_name = "setSchemas")] pub fn set_schemas( &mut self, - js_schema: JsValue, - js_definitions: Option, + #[wasm_bindgen(unchecked_param_type = "Record")] schemas: JsValue, + definitions: Option, full_validation: bool, - js_platform_version: JsValue, + platform_version: PlatformVersionLikeJs, ) -> WasmDppResult<()> { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; // Use platform_value_from_object to match getSchemas' to_object serialization // This preserves integer types properly (avoids JSON round-trip which converts to strings) - let schema_value = serialization::platform_value_from_object(js_schema)?; + let schema_value = serialization::platform_value_from_object(&schemas)?; let schema = schema_value .into_btree_string_map() .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; - let definitions: Option> = js_definitions - .map(|definitions| serde_wasm_bindgen::from_value(definitions.into())) + let definitions: Option> = definitions + .map(|defs| serde_wasm_bindgen::from_value(defs.into())) .transpose() .map_err(|err| WasmDppError::serialization(err.to_string()))?; @@ -468,15 +518,22 @@ impl DataContractWasm { } #[wasm_bindgen(setter = "tokens")] - pub fn set_tokens(&mut self, js_tokens: &JsValue) -> WasmDppResult<()> { + pub fn set_tokens( + &mut self, + #[wasm_bindgen(unchecked_param_type = "Record")] + tokens: &JsValue, + ) -> WasmDppResult<()> { self.0 - .set_tokens(tokens_configuration_from_js_value(js_tokens)?); + .set_tokens(tokens_configuration_from_js_value(tokens)?); Ok(()) } #[wasm_bindgen(setter = "groups")] - pub fn set_groups(&mut self, js_groups: &JsValue) -> WasmDppResult<()> { - let groups_object = Object::from(js_groups.clone()); + pub fn set_groups( + &mut self, + #[wasm_bindgen(unchecked_param_type = "Record")] groups: &JsValue, + ) -> WasmDppResult<()> { + let groups_object = try_to_object(groups.clone(), "groups")?; let mut groups: BTreeMap = BTreeMap::new(); @@ -514,24 +571,23 @@ impl DataContractWasm { } #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self, js_platform_version: JsValue) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + pub fn to_json( + &self, + platform_version: PlatformVersionLikeJs, + ) -> WasmDppResult { + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let json = self.0.to_json(&platform_version.into())?; - serialization::to_json(&json) + let js_value = serialization::to_json(&json)?; + Ok(js_value.into()) } #[wasm_bindgen(js_name = "generateId")] pub fn generate_id( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_owner_id: &JsValue, + owner_id: IdentifierLikeJs, identity_nonce: IdentityNonce, ) -> WasmDppResult { - let owner_id: Identifier = IdentifierWasm::try_from(js_owner_id)?.into(); - + let owner_id: Identifier = owner_id.try_into()?; Ok(DataContract::generate_data_contract_id_v0(owner_id.to_buffer(), identity_nonce).into()) } } @@ -543,6 +599,32 @@ impl DataContractWasm { ) -> Result, DataContractError> { self.0.document_type_for_name(name.as_str()).clone() } + + fn from_bytes_internal( + bytes: Vec, + full_validation: bool, + platform_version: JsValue, + ) -> WasmDppResult { + let platform_version = PlatformVersionWasm::try_from(platform_version)?; + + let rs_data_contract = DataContract::versioned_deserialize( + bytes.as_slice(), + full_validation, + &platform_version.into(), + )?; + + Ok(DataContractWasm(rs_data_contract)) + } + + fn to_bytes_internal(&self, platform_version: JsValue) -> WasmDppResult> { + let platform_version = PlatformVersionWasm::try_from(platform_version)?; + + let rs_data_contract: DataContract = self.0.clone(); + + Ok(rs_data_contract.serialize_to_bytes_with_platform_version(&platform_version.into())?) + } } -impl_try_from_options!(DataContractWasm, "DataContract"); +impl_try_from_js_value!(DataContractWasm, "DataContract"); +impl_try_from_options!(DataContractWasm); +impl_wasm_type_info!(DataContractWasm, DataContract); diff --git a/packages/wasm-dpp2/src/data_contract/transitions/create.rs b/packages/wasm-dpp2/src/data_contract/transitions/create.rs index dbdd2bbd3e7..c2257765c50 100644 --- a/packages/wasm-dpp2/src/data_contract/transitions/create.rs +++ b/packages/wasm-dpp2/src/data_contract/transitions/create.rs @@ -1,8 +1,9 @@ use crate::data_contract::DataContractWasm; -use crate::enums::platform::PlatformVersionWasm; use crate::error::{WasmDppError, WasmDppResult}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; +use crate::version::{PlatformVersionLikeJs, PlatformVersionWasm}; use dpp::data_contract::serialized_version::DataContractInSerializationFormat; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::{decode, encode}; @@ -17,36 +18,56 @@ use dpp::validation::operations::ProtocolValidationOperation; use dpp::version::{ FeatureVersion, ProtocolVersion, TryFromPlatformVersioned, TryIntoPlatformVersioned, }; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * DataContractCreateTransition serialized as a plain object. + */ +export interface DataContractCreateTransitionObject { + dataContract: DataContractObject; + identityNonce: bigint; + userFeeIncrease: number; + signaturePublicKeyId: number; + signature?: Uint8Array; +} + +/** + * DataContractCreateTransition serialized as JSON. + */ +export interface DataContractCreateTransitionJSON { + dataContract: DataContractJSON; + identityNonce: string; + userFeeIncrease: number; + signaturePublicKeyId: number; + signature?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DataContractCreateTransitionObject")] + pub type DataContractCreateTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "DataContractCreateTransitionJSON")] + pub type DataContractCreateTransitionJSONJs; +} + #[wasm_bindgen(js_name = "DataContractCreateTransition")] pub struct DataContractCreateTransitionWasm(DataContractCreateTransition); #[wasm_bindgen(js_class = DataContractCreateTransition)] impl DataContractCreateTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DataContractCreateTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DataContractCreateTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - data_contract: &DataContractWasm, - identity_nonce: IdentityNonce, - js_platform_version: JsValue, + pub fn constructor( + #[wasm_bindgen(js_name = "dataContract")] data_contract: &DataContractWasm, + #[wasm_bindgen(js_name = "identityNonce")] identity_nonce: IdentityNonce, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { let rs_data_contract: DataContract = data_contract.clone().into(); - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let rs_data_contract_create_transition_v0: DataContractCreateTransitionV0 = DataContractCreateTransitionV0 { @@ -108,14 +129,14 @@ impl DataContractCreateTransitionWasm { } #[wasm_bindgen(getter = "featureVersion")] - pub fn get_feature_version(&self) -> FeatureVersion { + pub fn feature_version(&self) -> FeatureVersion { self.0.feature_version() } #[wasm_bindgen(js_name = "verifyProtocolVersion")] pub fn verify_protocol_version( &self, - protocol_version: ProtocolVersion, + #[wasm_bindgen(js_name = "protocolVersion")] protocol_version: ProtocolVersion, ) -> WasmDppResult { self.0 .verify_protocol_version(protocol_version) @@ -125,13 +146,10 @@ impl DataContractCreateTransitionWasm { #[wasm_bindgen(js_name = "setDataContract")] pub fn set_data_contract( &mut self, - data_contract: &DataContractWasm, - js_platform_version: JsValue, + #[wasm_bindgen(js_name = "dataContract")] data_contract: &DataContractWasm, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult<()> { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let data_contract_serialization_format = DataContractInSerializationFormat::try_from_platform_versioned( @@ -145,20 +163,17 @@ impl DataContractCreateTransitionWasm { } #[wasm_bindgen(getter = "identityNonce")] - pub fn get_identity_nonce(&self) -> IdentityNonce { + pub fn identity_nonce(&self) -> IdentityNonce { self.0.identity_nonce() } #[wasm_bindgen(js_name = "getDataContract")] pub fn get_data_contract( &self, - js_platform_version: JsValue, - full_validation: Option, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, + #[wasm_bindgen(js_name = "fullValidation")] full_validation: Option, ) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let rs_data_contract_serialization_format = self.0.data_contract(); @@ -183,7 +198,7 @@ impl DataContractCreateTransitionWasm { #[wasm_bindgen(js_name = "fromStateTransition")] pub fn from_state_transition( - state_transition: &StateTransitionWasm, + #[wasm_bindgen(js_name = "stateTransition")] state_transition: &StateTransitionWasm, ) -> WasmDppResult { let rs_transition = StateTransition::from(state_transition.clone()); @@ -197,6 +212,12 @@ impl DataContractCreateTransitionWasm { } impl_wasm_conversions!( + DataContractCreateTransitionWasm, + DataContractCreateTransition, + DataContractCreateTransitionObjectJs, + DataContractCreateTransitionJSONJs +); +impl_wasm_type_info!( DataContractCreateTransitionWasm, DataContractCreateTransition ); diff --git a/packages/wasm-dpp2/src/data_contract/transitions/update.rs b/packages/wasm-dpp2/src/data_contract/transitions/update.rs index 2ba663a2019..f39faa2d884 100644 --- a/packages/wasm-dpp2/src/data_contract/transitions/update.rs +++ b/packages/wasm-dpp2/src/data_contract/transitions/update.rs @@ -1,8 +1,9 @@ use crate::data_contract::DataContractWasm; -use crate::enums::platform::PlatformVersionWasm; use crate::error::{WasmDppError, WasmDppResult}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; +use crate::version::{PlatformVersionLikeJs, PlatformVersionWasm}; use dpp::data_contract::serialized_version::DataContractInSerializationFormat; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::{decode, encode}; @@ -13,34 +14,54 @@ use dpp::state_transition::data_contract_update_transition::DataContractUpdateTr use dpp::state_transition::data_contract_update_transition::accessors::DataContractUpdateTransitionAccessorsV0; use dpp::validation::operations::ProtocolValidationOperation; use dpp::version::{FeatureVersion, ProtocolVersion, TryFromPlatformVersioned}; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * DataContractUpdateTransition serialized as a plain object. + */ +export interface DataContractUpdateTransitionObject { + dataContract: DataContractObject; + identityNonce: bigint; + userFeeIncrease: number; + signaturePublicKeyId: number; + signature?: Uint8Array; +} + +/** + * DataContractUpdateTransition serialized as JSON. + */ +export interface DataContractUpdateTransitionJSON { + dataContract: DataContractJSON; + identityNonce: string; + userFeeIncrease: number; + signaturePublicKeyId: number; + signature?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DataContractUpdateTransitionObject")] + pub type DataContractUpdateTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "DataContractUpdateTransitionJSON")] + pub type DataContractUpdateTransitionJSONJs; +} + #[wasm_bindgen(js_name = "DataContractUpdateTransition")] pub struct DataContractUpdateTransitionWasm(DataContractUpdateTransition); #[wasm_bindgen(js_class = DataContractUpdateTransition)] impl DataContractUpdateTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DataContractUpdateTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DataContractUpdateTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - data_contract: &DataContractWasm, - identity_nonce: IdentityNonce, - js_platform_version: JsValue, + pub fn constructor( + #[wasm_bindgen(js_name = "dataContract")] data_contract: &DataContractWasm, + #[wasm_bindgen(js_name = "identityNonce")] identity_nonce: IdentityNonce, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let rs_data_contract_update_transition = DataContractUpdateTransition::try_from_platform_versioned( @@ -95,14 +116,14 @@ impl DataContractUpdateTransitionWasm { } #[wasm_bindgen(getter = "featureVersion")] - pub fn get_feature_version(&self) -> FeatureVersion { + pub fn feature_version(&self) -> FeatureVersion { self.0.feature_version() } #[wasm_bindgen(js_name = "verifyProtocolVersion")] pub fn verify_protocol_version( &self, - protocol_version: ProtocolVersion, + #[wasm_bindgen(js_name = "protocolVersion")] protocol_version: ProtocolVersion, ) -> WasmDppResult { self.0 .verify_protocol_version(protocol_version) @@ -112,13 +133,10 @@ impl DataContractUpdateTransitionWasm { #[wasm_bindgen(js_name = "setDataContract")] pub fn set_data_contract( &mut self, - data_contract: &DataContractWasm, - js_platform_version: JsValue, + #[wasm_bindgen(js_name = "dataContract")] data_contract: &DataContractWasm, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult<()> { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let data_contract_serialization_format = DataContractInSerializationFormat::try_from_platform_versioned( @@ -132,20 +150,17 @@ impl DataContractUpdateTransitionWasm { } #[wasm_bindgen(getter = "identityContractNonce")] - pub fn get_identity_nonce(&self) -> IdentityNonce { + pub fn identity_contract_nonce(&self) -> IdentityNonce { self.0.identity_contract_nonce() } #[wasm_bindgen(js_name = "getDataContract")] pub fn get_data_contract( &self, - full_validation: Option, - js_platform_version: JsValue, + #[wasm_bindgen(js_name = "fullValidation")] full_validation: Option, + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, ) -> WasmDppResult { - let platform_version = match js_platform_version.is_undefined() { - true => PlatformVersionWasm::default(), - false => PlatformVersionWasm::try_from(js_platform_version)?, - }; + let platform_version = PlatformVersionWasm::try_from(platform_version)?; let data_contract_serialization_format = self.0.data_contract(); @@ -170,7 +185,7 @@ impl DataContractUpdateTransitionWasm { #[wasm_bindgen(js_name = "fromStateTransition")] pub fn from_state_transition( - state_transition: &StateTransitionWasm, + #[wasm_bindgen(js_name = "stateTransition")] state_transition: &StateTransitionWasm, ) -> WasmDppResult { let rs_transition = StateTransition::from(state_transition.clone()); @@ -184,6 +199,12 @@ impl DataContractUpdateTransitionWasm { } impl_wasm_conversions!( + DataContractUpdateTransitionWasm, + DataContractUpdateTransition, + DataContractUpdateTransitionObjectJs, + DataContractUpdateTransitionJSONJs +); +impl_wasm_type_info!( DataContractUpdateTransitionWasm, DataContractUpdateTransition ); diff --git a/packages/wasm-dpp2/src/enums/batch/batch_enum.rs b/packages/wasm-dpp2/src/enums/batch/batch_enum.rs index 65d66ae3518..ba475946d60 100644 --- a/packages/wasm-dpp2/src/enums/batch/batch_enum.rs +++ b/packages/wasm-dpp2/src/enums/batch/batch_enum.rs @@ -14,11 +14,12 @@ pub enum BatchTypeWasm { IgnoreWhileBumpingRevision, } -impl TryFrom for BatchTypeWasm { +impl TryFrom<&JsValue> for BatchTypeWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { - match value.is_string() { - true => match value.as_string() { + + fn try_from(value: &JsValue) -> Result { + if value.is_string() { + match value.as_string() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -35,8 +36,9 @@ impl TryFrom for BatchTypeWasm { enum_val ))), }, - }, - false => match value.as_f64() { + } + } else { + match value.as_f64() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -53,11 +55,19 @@ impl TryFrom for BatchTypeWasm { enum_val ))), }, - }, + } } } } +impl TryFrom for BatchTypeWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(value: BatchTypeWasm) -> Self { match value { diff --git a/packages/wasm-dpp2/src/enums/batch/gas_fees_paid_by.rs b/packages/wasm-dpp2/src/enums/batch/gas_fees_paid_by.rs index e6186061db3..0ca1205409a 100644 --- a/packages/wasm-dpp2/src/enums/batch/gas_fees_paid_by.rs +++ b/packages/wasm-dpp2/src/enums/batch/gas_fees_paid_by.rs @@ -3,6 +3,35 @@ use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export type GasFeesPaidByLike = GasFeesPaidBy | "documentOwner" | "contractOwner" | "preferContractOwner" | 0 | 1 | 2; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "GasFeesPaidByLike")] + pub type GasFeesPaidByLikeJs; +} + +impl TryFrom for GasFeesPaidByWasm { + type Error = WasmDppError; + + fn try_from(value: GasFeesPaidByLikeJs) -> Result { + let js_value: JsValue = value.into(); + GasFeesPaidByWasm::try_from(js_value) + } +} + +impl TryFrom for GasFeesPaidBy { + type Error = WasmDppError; + + fn try_from(value: GasFeesPaidByLikeJs) -> Result { + let wasm: GasFeesPaidByWasm = value.try_into()?; + Ok(GasFeesPaidBy::from(wasm)) + } +} + #[derive(Clone, Default)] #[wasm_bindgen(js_name = "GasFeesPaidBy")] pub enum GasFeesPaidByWasm { @@ -12,9 +41,10 @@ pub enum GasFeesPaidByWasm { PreferContractOwner = 2, } -impl TryFrom for GasFeesPaidByWasm { +impl TryFrom<&JsValue> for GasFeesPaidByWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { + + fn try_from(value: &JsValue) -> Result { if let Some(enum_val) = value.as_string() { return match enum_val.to_lowercase().as_str() { "documentowner" => Ok(GasFeesPaidByWasm::DocumentOwner), @@ -45,6 +75,14 @@ impl TryFrom for GasFeesPaidByWasm { } } +impl TryFrom for GasFeesPaidByWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(value: GasFeesPaidByWasm) -> Self { match value { diff --git a/packages/wasm-dpp2/src/enums/contested/vote_state_result_type.rs b/packages/wasm-dpp2/src/enums/contested/vote_state_result_type.rs index eab6da424ef..99d06a77ca9 100644 --- a/packages/wasm-dpp2/src/enums/contested/vote_state_result_type.rs +++ b/packages/wasm-dpp2/src/enums/contested/vote_state_result_type.rs @@ -12,12 +12,12 @@ pub enum VoteStateResultTypeWasm { DocumentsAndVoteTally = 2, } -impl TryFrom for VoteStateResultTypeWasm { +impl TryFrom<&JsValue> for VoteStateResultTypeWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { - match value.is_string() { - true => match value.as_string() { + fn try_from(value: &JsValue) -> Result { + if value.is_string() { + match value.as_string() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -27,8 +27,9 @@ impl TryFrom for VoteStateResultTypeWasm { "documentsandvotetally" => Ok(VoteStateResultTypeWasm::DocumentsAndVoteTally), _ => Err(WasmDppError::invalid_argument("unknown result type")), }, - }, - false => match value.as_f64() { + } + } else { + match value.as_f64() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -38,11 +39,19 @@ impl TryFrom for VoteStateResultTypeWasm { 2 => Ok(VoteStateResultTypeWasm::DocumentsAndVoteTally), _ => Err(WasmDppError::invalid_argument("unknown action type")), }, - }, + } } } } +impl TryFrom for VoteStateResultTypeWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(result_type: VoteStateResultTypeWasm) -> Self { match result_type { diff --git a/packages/wasm-dpp2/src/enums/keys/key_type.rs b/packages/wasm-dpp2/src/enums/keys/key_type.rs index 3e82da3aa86..d2a0ffdee83 100644 --- a/packages/wasm-dpp2/src/enums/keys/key_type.rs +++ b/packages/wasm-dpp2/src/enums/keys/key_type.rs @@ -3,6 +3,38 @@ use dpp::identity::KeyType; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Flexible input type for KeyType - accepts the enum, string name, or numeric value. + */ +export type KeyTypeLike = KeyType | "ecdsa_secp256k1" | "bls12_381" | "ecdsa_hash160" | "bip13_script_hash" | "eddsa_25519_hash160" | 0 | 1 | 2 | 3 | 4; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "KeyTypeLike")] + pub type KeyTypeLikeJs; +} + +impl TryFrom for KeyTypeWasm { + type Error = WasmDppError; + + fn try_from(value: KeyTypeLikeJs) -> Result { + let js_value: JsValue = value.into(); + KeyTypeWasm::try_from(js_value) + } +} + +impl TryFrom for KeyType { + type Error = WasmDppError; + + fn try_from(value: KeyTypeLikeJs) -> Result { + let wasm: KeyTypeWasm = value.try_into()?; + Ok(KeyType::from(wasm)) + } +} + #[allow(non_camel_case_types)] #[wasm_bindgen(js_name = "KeyType")] pub enum KeyTypeWasm { @@ -13,11 +45,12 @@ pub enum KeyTypeWasm { EDDSA_25519_HASH160 = 4, } -impl TryFrom for KeyTypeWasm { +impl TryFrom<&JsValue> for KeyTypeWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { - match value.is_string() { - true => match value.as_string() { + + fn try_from(value: &JsValue) -> Result { + if value.is_string() { + match value.as_string() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -32,8 +65,9 @@ impl TryFrom for KeyTypeWasm { enum_val ))), }, - }, - false => match value.as_f64() { + } + } else { + match value.as_f64() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -48,11 +82,19 @@ impl TryFrom for KeyTypeWasm { enum_val ))), }, - }, + } } } } +impl TryFrom for KeyTypeWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(value: KeyTypeWasm) -> Self { match value { diff --git a/packages/wasm-dpp2/src/enums/keys/purpose.rs b/packages/wasm-dpp2/src/enums/keys/purpose.rs index bdf1c2a0b22..7a250a65bcf 100644 --- a/packages/wasm-dpp2/src/enums/keys/purpose.rs +++ b/packages/wasm-dpp2/src/enums/keys/purpose.rs @@ -3,6 +3,38 @@ use dpp::identity::Purpose; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Flexible input type for Purpose - accepts the enum, string name, or numeric value. + */ +export type PurposeLike = Purpose | "authentication" | "encryption" | "decryption" | "transfer" | "system" | "voting" | "owner" | 0 | 1 | 2 | 3 | 4 | 5 | 6; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "PurposeLike")] + pub type PurposeLikeJs; +} + +impl TryFrom for PurposeWasm { + type Error = WasmDppError; + + fn try_from(value: PurposeLikeJs) -> Result { + let js_value: JsValue = value.into(); + PurposeWasm::try_from(js_value) + } +} + +impl TryFrom for Purpose { + type Error = WasmDppError; + + fn try_from(value: PurposeLikeJs) -> Result { + let wasm: PurposeWasm = value.try_into()?; + Ok(Purpose::from(wasm)) + } +} + #[wasm_bindgen(js_name = "Purpose")] pub enum PurposeWasm { AUTHENTICATION = 0, @@ -14,9 +46,10 @@ pub enum PurposeWasm { OWNER = 6, } -impl TryFrom for PurposeWasm { +impl TryFrom<&JsValue> for PurposeWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { + + fn try_from(value: &JsValue) -> Result { if let Some(enum_val) = value.as_string() { return match enum_val.to_lowercase().as_str() { "authentication" => Ok(PurposeWasm::AUTHENTICATION), @@ -55,6 +88,14 @@ impl TryFrom for PurposeWasm { } } +impl TryFrom for PurposeWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(value: PurposeWasm) -> Self { match value { diff --git a/packages/wasm-dpp2/src/enums/keys/security_level.rs b/packages/wasm-dpp2/src/enums/keys/security_level.rs index 9bc1c534724..f8b204efdde 100644 --- a/packages/wasm-dpp2/src/enums/keys/security_level.rs +++ b/packages/wasm-dpp2/src/enums/keys/security_level.rs @@ -3,7 +3,39 @@ use dpp::identity::SecurityLevel; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; -#[wasm_bindgen(js_name = SecurityLevel)] +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Flexible input type for SecurityLevel - accepts the enum, string name, or numeric value. + */ +export type SecurityLevelLike = SecurityLevel | "master" | "critical" | "high" | "medium" | 0 | 1 | 2 | 3; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "SecurityLevelLike")] + pub type SecurityLevelLikeJs; +} + +impl TryFrom for SecurityLevelWasm { + type Error = WasmDppError; + + fn try_from(value: SecurityLevelLikeJs) -> Result { + let js_value: JsValue = value.into(); + SecurityLevelWasm::try_from(js_value) + } +} + +impl TryFrom for SecurityLevel { + type Error = WasmDppError; + + fn try_from(value: SecurityLevelLikeJs) -> Result { + let wasm: SecurityLevelWasm = value.try_into()?; + Ok(SecurityLevel::from(wasm)) + } +} + +#[wasm_bindgen(js_name = "SecurityLevel")] pub enum SecurityLevelWasm { MASTER = 0, CRITICAL = 1, @@ -11,9 +43,10 @@ pub enum SecurityLevelWasm { MEDIUM = 3, } -impl TryFrom for SecurityLevelWasm { +impl TryFrom<&JsValue> for SecurityLevelWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { + + fn try_from(value: &JsValue) -> Result { if let Some(enum_val) = value.as_string() { return match enum_val.to_lowercase().as_str() { "master" => Ok(SecurityLevelWasm::MASTER), @@ -46,6 +79,14 @@ impl TryFrom for SecurityLevelWasm { } } +impl TryFrom for SecurityLevelWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(level: SecurityLevelWasm) -> String { match level { diff --git a/packages/wasm-dpp2/src/enums/lock_types.rs b/packages/wasm-dpp2/src/enums/lock_types.rs index dacb3f8ebea..cc240993903 100644 --- a/packages/wasm-dpp2/src/enums/lock_types.rs +++ b/packages/wasm-dpp2/src/enums/lock_types.rs @@ -8,21 +8,12 @@ pub enum AssetLockProofTypeWasm { Chain = 1, } -impl From for String { - fn from(value: AssetLockProofTypeWasm) -> Self { - match value { - AssetLockProofTypeWasm::Instant => String::from("Instant"), - AssetLockProofTypeWasm::Chain => String::from("Chain"), - } - } -} - -impl TryFrom for AssetLockProofTypeWasm { +impl TryFrom<&JsValue> for AssetLockProofTypeWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { - match value.is_string() { - true => match value.as_string() { + fn try_from(value: &JsValue) -> Result { + if value.is_string() { + match value.as_string() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -34,8 +25,9 @@ impl TryFrom for AssetLockProofTypeWasm { enum_val ))), }, - }, - false => match value.as_f64() { + } + } else { + match value.as_f64() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -47,7 +39,24 @@ impl TryFrom for AssetLockProofTypeWasm { enum_val ))), }, - }, + } + } + } +} + +impl TryFrom for AssetLockProofTypeWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + +impl From for String { + fn from(value: AssetLockProofTypeWasm) -> Self { + match value { + AssetLockProofTypeWasm::Instant => String::from("Instant"), + AssetLockProofTypeWasm::Chain => String::from("Chain"), } } } diff --git a/packages/wasm-dpp2/src/enums/mod.rs b/packages/wasm-dpp2/src/enums/mod.rs index 7f9e3e9ad16..1d34cbeb977 100644 --- a/packages/wasm-dpp2/src/enums/mod.rs +++ b/packages/wasm-dpp2/src/enums/mod.rs @@ -2,5 +2,4 @@ pub mod batch; pub mod contested; pub mod keys; pub mod lock_types; -pub mod platform; pub mod token; diff --git a/packages/wasm-dpp2/src/enums/token/action_goal.rs b/packages/wasm-dpp2/src/enums/token/action_goal.rs index ec7623bbe76..96598aaaccc 100644 --- a/packages/wasm-dpp2/src/enums/token/action_goal.rs +++ b/packages/wasm-dpp2/src/enums/token/action_goal.rs @@ -3,6 +3,17 @@ use dpp::group::action_taker::ActionGoal; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export type ActionGoalLike = ActionGoal | string | number; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ActionGoalLike")] + pub type ActionGoalLikeJs; +} + #[wasm_bindgen(js_name = "ActionGoal")] #[allow(non_camel_case_types)] #[derive(Default, Clone)] @@ -30,10 +41,10 @@ impl From for ActionGoalWasm { } } -impl TryFrom for ActionGoalWasm { +impl TryFrom<&JsValue> for ActionGoalWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { + fn try_from(value: &JsValue) -> Result { if let Some(enum_val) = value.as_string() { return match enum_val.to_lowercase().as_str() { "actioncompletion" => Ok(ActionGoalWasm::ActionCompletion), @@ -56,6 +67,14 @@ impl TryFrom for ActionGoalWasm { } } +impl TryFrom for ActionGoalWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(action_goal: ActionGoalWasm) -> Self { match action_goal { diff --git a/packages/wasm-dpp2/src/enums/token/distribution_type.rs b/packages/wasm-dpp2/src/enums/token/distribution_type.rs index dab69e8d00e..0c9d373c9ec 100644 --- a/packages/wasm-dpp2/src/enums/token/distribution_type.rs +++ b/packages/wasm-dpp2/src/enums/token/distribution_type.rs @@ -3,6 +3,17 @@ use dpp::data_contract::associated_token::token_distribution_key::TokenDistribut use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export type TokenDistributionTypeLike = TokenDistributionType | string | number; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenDistributionTypeLike")] + pub type TokenDistributionTypeLikeJs; +} + #[wasm_bindgen(js_name = "TokenDistributionType")] #[allow(non_camel_case_types)] #[derive(Default)] @@ -30,10 +41,10 @@ impl From for TokenDistributionTypeWasm { } } -impl TryFrom for TokenDistributionTypeWasm { +impl TryFrom<&JsValue> for TokenDistributionTypeWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { + fn try_from(value: &JsValue) -> Result { if let Some(enum_val) = value.as_string() { return match enum_val.to_lowercase().as_str() { "preprogrammed" => Ok(TokenDistributionTypeWasm::PreProgrammed), @@ -56,6 +67,14 @@ impl TryFrom for TokenDistributionTypeWasm { } } +impl TryFrom for TokenDistributionTypeWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(distribution_type: TokenDistributionTypeWasm) -> Self { match distribution_type { diff --git a/packages/wasm-dpp2/src/enums/token/emergency_action.rs b/packages/wasm-dpp2/src/enums/token/emergency_action.rs index 0781f7d6111..cee11b2da6c 100644 --- a/packages/wasm-dpp2/src/enums/token/emergency_action.rs +++ b/packages/wasm-dpp2/src/enums/token/emergency_action.rs @@ -30,10 +30,10 @@ impl From for TokenEmergencyActionWasm { } } -impl TryFrom for TokenEmergencyActionWasm { +impl TryFrom<&JsValue> for TokenEmergencyActionWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { + fn try_from(value: &JsValue) -> Result { if let Some(enum_val) = value.as_string() { return match enum_val.to_lowercase().as_str() { "pause" => Ok(TokenEmergencyActionWasm::Pause), @@ -60,6 +60,14 @@ impl TryFrom for TokenEmergencyActionWasm { } } +impl TryFrom for TokenEmergencyActionWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(distribution_type: TokenEmergencyActionWasm) -> Self { match distribution_type { diff --git a/packages/wasm-dpp2/src/epoch/extended_epoch_info.rs b/packages/wasm-dpp2/src/epoch/extended_epoch_info.rs index f4e8af8f0a7..fc75b288546 100644 --- a/packages/wasm-dpp2/src/epoch/extended_epoch_info.rs +++ b/packages/wasm-dpp2/src/epoch/extended_epoch_info.rs @@ -1,9 +1,72 @@ -use crate::impl_wasm_conversions; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::utils::{try_to_u16, try_to_u32, try_to_u64}; +use crate::{impl_wasm_conversions, impl_wasm_type_info}; use dpp::block::extended_epoch_info::ExtendedEpochInfo; use dpp::block::extended_epoch_info::v0::{ExtendedEpochInfoV0, ExtendedEpochInfoV0Getters}; use js_sys::BigInt; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const EXTENDED_EPOCH_INFO_OPTIONS_TS: &str = r#" +export interface ExtendedEpochInfoOptions { + index: number; + firstBlockTime: bigint; + firstBlockHeight: bigint; + firstCoreBlockHeight: number; + feeMultiplierPermille: bigint; + protocolVersion: number; +} + +/** + * ExtendedEpochInfo serialized as a plain object. + */ +export interface ExtendedEpochInfoObject { + index: number; + firstBlockTime: bigint; + firstBlockHeight: bigint; + firstCoreBlockHeight: number; + feeMultiplierPermille: bigint; + protocolVersion: number; +} + +/** + * ExtendedEpochInfo serialized as JSON. + */ +export interface ExtendedEpochInfoJSON { + index: number; + firstBlockTime: string; + firstBlockHeight: string; + firstCoreBlockHeight: number; + feeMultiplierPermille: string; + protocolVersion: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ExtendedEpochInfoOptions")] + pub type ExtendedEpochInfoOptionsJs; + + #[wasm_bindgen(typescript_type = "ExtendedEpochInfoObject")] + pub type ExtendedEpochInfoObjectJs; + + #[wasm_bindgen(typescript_type = "ExtendedEpochInfoJSON")] + pub type ExtendedEpochInfoJSONJs; +} + +/// Serde struct for ExtendedEpochInfoOptions +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct ExtendedEpochInfoOptionsInput { + index: u16, + first_block_time: u64, + first_block_height: u64, + first_core_block_height: u32, + fee_multiplier_permille: u64, + protocol_version: u32, +} + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "ExtendedEpochInfo")] pub struct ExtendedEpochInfoWasm(ExtendedEpochInfo); @@ -30,33 +93,24 @@ impl ExtendedEpochInfoWasm { #[wasm_bindgen(js_class = ExtendedEpochInfo)] impl ExtendedEpochInfoWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "ExtendedEpochInfo".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "ExtendedEpochInfo".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - index: u16, - first_block_time: u64, - first_block_height: u64, - first_core_block_height: u32, - fee_multiplier_permille: u64, - protocol_version: u32, - ) -> ExtendedEpochInfoWasm { - ExtendedEpochInfoWasm(ExtendedEpochInfo::V0(ExtendedEpochInfoV0 { - index, - first_block_time, - first_block_height, - first_core_block_height, - fee_multiplier_permille, - protocol_version, - })) + pub fn constructor( + options: ExtendedEpochInfoOptionsJs, + ) -> WasmDppResult { + let input: ExtendedEpochInfoOptionsInput = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + + Ok(ExtendedEpochInfoWasm(ExtendedEpochInfo::V0( + ExtendedEpochInfoV0 { + index: input.index, + first_block_time: input.first_block_time, + first_block_height: input.first_block_height, + first_core_block_height: input.first_core_block_height, + fee_multiplier_permille: input.fee_multiplier_permille, + protocol_version: input.protocol_version, + }, + ))) } #[wasm_bindgen(getter = "index")] @@ -95,34 +149,60 @@ impl ExtendedEpochInfoWasm { } #[wasm_bindgen(setter = "index")] - pub fn set_index(&mut self, index: u16) { - self.v0_mut().index = index; + pub fn set_index(&mut self, index: &js_sys::Number) -> WasmDppResult<()> { + self.v0_mut().index = try_to_u16(index, "index")?; + Ok(()) } #[wasm_bindgen(setter = "firstBlockTime")] - pub fn set_first_block_time(&mut self, first_block_time: u64) { - self.v0_mut().first_block_time = first_block_time; + pub fn set_first_block_time( + &mut self, + #[wasm_bindgen(js_name = "firstBlockTime")] first_block_time: &js_sys::BigInt, + ) -> WasmDppResult<()> { + self.v0_mut().first_block_time = try_to_u64(first_block_time, "firstBlockTime")?; + Ok(()) } #[wasm_bindgen(setter = "firstBlockHeight")] - pub fn set_first_block_height(&mut self, first_block_height: u64) { - self.v0_mut().first_block_height = first_block_height; + pub fn set_first_block_height( + &mut self, + #[wasm_bindgen(js_name = "firstBlockHeight")] first_block_height: &js_sys::BigInt, + ) -> WasmDppResult<()> { + self.v0_mut().first_block_height = try_to_u64(first_block_height, "firstBlockHeight")?; + Ok(()) } #[wasm_bindgen(setter = "firstCoreBlockHeight")] - pub fn set_first_core_block_height(&mut self, first_core_block_height: u32) { - self.v0_mut().first_core_block_height = first_core_block_height; + pub fn set_first_core_block_height( + &mut self, + #[wasm_bindgen(js_name = "firstCoreBlockHeight")] first_core_block_height: &js_sys::Number, + ) -> WasmDppResult<()> { + self.v0_mut().first_core_block_height = + try_to_u32(first_core_block_height, "firstCoreBlockHeight")?; + Ok(()) } #[wasm_bindgen(setter = "feeMultiplierPermille")] - pub fn set_fee_multiplier_permille(&mut self, fee_multiplier_permille: u64) { + pub fn set_fee_multiplier_permille( + &mut self, + #[wasm_bindgen(js_name = "feeMultiplierPermille")] fee_multiplier_permille: u64, + ) { self.v0_mut().fee_multiplier_permille = fee_multiplier_permille; } #[wasm_bindgen(setter = "protocolVersion")] - pub fn set_protocol_version(&mut self, protocol_version: u32) { + pub fn set_protocol_version( + &mut self, + #[wasm_bindgen(js_name = "protocolVersion")] protocol_version: u32, + ) { self.v0_mut().protocol_version = protocol_version; } } -impl_wasm_conversions!(ExtendedEpochInfoWasm, ExtendedEpochInfo); +impl_wasm_conversions!( + ExtendedEpochInfoWasm, + ExtendedEpochInfo, + ExtendedEpochInfoObjectJs, + ExtendedEpochInfoJSONJs +); +impl_wasm_type_info!(ExtendedEpochInfoWasm, ExtendedEpochInfo); diff --git a/packages/wasm-dpp2/src/epoch/finalized_epoch_info.rs b/packages/wasm-dpp2/src/epoch/finalized_epoch_info.rs index 2b23b6254de..b21cdf74e69 100644 --- a/packages/wasm-dpp2/src/epoch/finalized_epoch_info.rs +++ b/packages/wasm-dpp2/src/epoch/finalized_epoch_info.rs @@ -1,16 +1,110 @@ use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; -use crate::utils::{JsValueExt, try_to_u64}; +use crate::impl_from_for_extern_type; +use crate::impl_wasm_type_info; +use crate::utils::{JsMapExt, try_from_options_with, try_to_map, try_to_u64}; use dpp::block::finalized_epoch_info::FinalizedEpochInfo; use dpp::block::finalized_epoch_info::v0::FinalizedEpochInfoV0; use dpp::block::finalized_epoch_info::v0::getters::FinalizedEpochInfoGettersV0; -use dpp::platform_value::string_encoding::Encoding; use dpp::prelude::Identifier; -use js_sys::{BigInt, Object, Reflect}; +use js_sys::{BigInt, Map}; +use serde::Deserialize; use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct FinalizedEpochInfoOptions { + first_block_time: u64, + first_block_height: u64, + total_blocks_in_epoch: u64, + first_core_block_height: u32, + next_epoch_start_core_block_height: u32, + total_processing_fees: u64, + total_distributed_storage_fees: u64, + total_created_storage_fees: u64, + core_block_rewards: u64, + fee_multiplier_permille: u64, + protocol_version: u32, +} + +#[wasm_bindgen(typescript_custom_section)] +const FINALIZED_EPOCH_INFO_OPTIONS_TS: &str = r#" +/** + * Block proposers mapping: base58 Identifier string -> block count (bigint). + */ +export type BlockProposersMap = Map; + +export interface FinalizedEpochInfoOptions { + firstBlockTime: bigint; + firstBlockHeight: bigint; + totalBlocksInEpoch: bigint; + firstCoreBlockHeight: number; + nextEpochStartCoreBlockHeight: number; + totalProcessingFees: bigint; + totalDistributedStorageFees: bigint; + totalCreatedStorageFees: bigint; + coreBlockRewards: bigint; + blockProposers: BlockProposersMap; + feeMultiplierPermille: bigint; + protocolVersion: number; +} + +/** + * FinalizedEpochInfo serialized as a plain object. + */ +export interface FinalizedEpochInfoObject { + firstBlockTime: bigint; + firstBlockHeight: bigint; + totalBlocksInEpoch: bigint; + firstCoreBlockHeight: number; + nextEpochStartCoreBlockHeight: number; + totalProcessingFees: bigint; + totalDistributedStorageFees: bigint; + totalCreatedStorageFees: bigint; + coreBlockRewards: bigint; + blockProposers: BlockProposersMap; + feeMultiplierPermille: bigint; + protocolVersion: number; +} + +/** + * FinalizedEpochInfo serialized as JSON. + */ +export interface FinalizedEpochInfoJSON { + firstBlockTime: string; + firstBlockHeight: string; + totalBlocksInEpoch: string; + firstCoreBlockHeight: number; + nextEpochStartCoreBlockHeight: number; + totalProcessingFees: string; + totalDistributedStorageFees: string; + totalCreatedStorageFees: string; + coreBlockRewards: string; + blockProposers: Record; + feeMultiplierPermille: string; + protocolVersion: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "FinalizedEpochInfoOptions")] + pub type FinalizedEpochInfoOptionsJs; + + #[wasm_bindgen(typescript_type = "BlockProposersMap")] + pub type BlockProposersMapJs; + + #[wasm_bindgen(typescript_type = "FinalizedEpochInfoObject")] + pub type FinalizedEpochInfoObjectJs; + + #[wasm_bindgen(typescript_type = "FinalizedEpochInfoJSON")] + pub type FinalizedEpochInfoJSONJs; +} + +impl_from_for_extern_type!(BlockProposersMapJs, Map); + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "FinalizedEpochInfo")] pub struct FinalizedEpochInfoWasm(FinalizedEpochInfo); @@ -41,46 +135,25 @@ impl FinalizedEpochInfoWasm { } } -fn block_proposers_from_js(js_value: &JsValue) -> WasmDppResult> { - if js_value.is_undefined() || js_value.is_null() { - return Ok(BTreeMap::new()); - } - - if !js_value.is_object() { - return Err(WasmDppError::invalid_argument( - "blockProposers must be an object", - )); - } - - let object = Object::from(js_value.clone()); - let keys = Object::keys(&object); +fn block_proposers_from_map(js_map: &Map) -> WasmDppResult> { let mut map = BTreeMap::new(); - for key in keys.iter() { - let identifier = - Identifier::from(IdentifierWasm::try_from(key.clone()).map_err(|err| { - WasmDppError::invalid_argument(format!( - "invalid block proposer identifier: {}", - err - )) - })?); - - let value = Reflect::get(&object, &key).map_err(|err| { - let message = err.error_message(); - WasmDppError::generic(format!( - "unable to read block proposer '{}': {}", - identifier.to_string(Encoding::Base58), - message - )) + for entry in js_map.entries().into_iter() { + let entry = entry.map_err(|e| { + WasmDppError::invalid_argument(format!("Failed to iterate map entries: {:?}", e)) })?; - let credits = try_to_u64(value.clone()).map_err(|err| { - WasmDppError::invalid_argument(format!( - "block proposer value for '{}' is not a valid u64: {:#}", - identifier.to_string(Encoding::Base58), - err - )) - })?; + let entry_array = js_sys::Array::from(&entry); + let key = entry_array.get(0); + let value = entry_array.get(1); + + let identifier: Identifier = IdentifierWasm::try_from(key) + .map_err(|e| { + WasmDppError::invalid_argument(format!("Invalid block proposer identifier: {}", e)) + })? + .into(); + + let credits = try_to_u64(&value, "blockProposerCredits")?; map.insert(identifier, credits); } @@ -88,72 +161,44 @@ fn block_proposers_from_js(js_value: &JsValue) -> WasmDppResult) -> WasmDppResult { - let object = Object::new(); - - for (identifier, value) in map { - Reflect::set( - &object, - &JsValue::from(identifier.to_string(Encoding::Base58)), - &BigInt::from(*value).into(), - ) - .map_err(|err| { - let message = err.error_message(); - WasmDppError::generic(format!( - "unable to serialize block proposer '{}': {}", - identifier.to_string(Encoding::Base58), - message - )) - })?; - } - - Ok(object.into()) +fn block_proposers_to_map(map: &BTreeMap) -> BlockProposersMapJs { + Map::from_entries(map.iter().map(|(identifier, value)| { + let key: JsValue = IdentifierWasm::from(*identifier).to_base58().into(); + let value: JsValue = BigInt::from(*value).into(); + (key, value) + })) + .into() } #[wasm_bindgen(js_class = FinalizedEpochInfo)] impl FinalizedEpochInfoWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "FinalizedEpochInfo".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name(&self) -> String { - "FinalizedEpochInfo".to_string() - } - #[wasm_bindgen(constructor)] - #[allow(clippy::too_many_arguments)] - pub fn new( - first_block_time: u64, - first_block_height: u64, - total_blocks_in_epoch: u64, - first_core_block_height: u32, - next_epoch_start_core_block_height: u32, - total_processing_fees: u64, - total_distributed_storage_fees: u64, - total_created_storage_fees: u64, - core_block_rewards: u64, - block_proposers: &JsValue, - fee_multiplier_permille: u64, - protocol_version: u32, + pub fn constructor( + options: FinalizedEpochInfoOptionsJs, ) -> WasmDppResult { - let block_proposers = block_proposers_from_js(block_proposers)?; + // Extract complex types first (borrows &options) + let block_proposers = try_from_options_with(&options, "blockProposers", |v| { + block_proposers_from_map(&try_to_map(v.clone(), "blockProposers")?) + })?; + + // Deserialize primitive fields via serde last (consumes options) + let opts: FinalizedEpochInfoOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(FinalizedEpochInfoWasm(FinalizedEpochInfo::V0( FinalizedEpochInfoV0 { - first_block_time, - first_block_height, - total_blocks_in_epoch, - first_core_block_height, - next_epoch_start_core_block_height, - total_processing_fees, - total_distributed_storage_fees, - total_created_storage_fees, - core_block_rewards, + first_block_time: opts.first_block_time, + first_block_height: opts.first_block_height, + total_blocks_in_epoch: opts.total_blocks_in_epoch, + first_core_block_height: opts.first_core_block_height, + next_epoch_start_core_block_height: opts.next_epoch_start_core_block_height, + total_processing_fees: opts.total_processing_fees, + total_distributed_storage_fees: opts.total_distributed_storage_fees, + total_created_storage_fees: opts.total_created_storage_fees, + core_block_rewards: opts.core_block_rewards, block_proposers, - fee_multiplier_permille, - protocol_version, + fee_multiplier_permille: opts.fee_multiplier_permille, + protocol_version: opts.protocol_version, }, ))) } @@ -204,8 +249,8 @@ impl FinalizedEpochInfoWasm { } #[wasm_bindgen(getter = "blockProposers")] - pub fn block_proposers(&self) -> WasmDppResult { - block_proposers_to_js(self.v0().block_proposers()) + pub fn block_proposers(&self) -> BlockProposersMapJs { + block_proposers_to_map(self.v0().block_proposers()) } #[wasm_bindgen(getter = "feeMultiplierPermille")] @@ -224,69 +269,111 @@ impl FinalizedEpochInfoWasm { } #[wasm_bindgen(setter = "firstBlockTime")] - pub fn set_first_block_time(&mut self, first_block_time: u64) { + pub fn set_first_block_time( + &mut self, + #[wasm_bindgen(js_name = "firstBlockTime")] first_block_time: u64, + ) { self.v0_mut().first_block_time = first_block_time; } #[wasm_bindgen(setter = "firstBlockHeight")] - pub fn set_first_block_height(&mut self, first_block_height: u64) { + pub fn set_first_block_height( + &mut self, + #[wasm_bindgen(js_name = "firstBlockHeight")] first_block_height: u64, + ) { self.v0_mut().first_block_height = first_block_height; } #[wasm_bindgen(setter = "totalBlocksInEpoch")] - pub fn set_total_blocks_in_epoch(&mut self, total_blocks_in_epoch: u64) { + pub fn set_total_blocks_in_epoch( + &mut self, + #[wasm_bindgen(js_name = "totalBlocksInEpoch")] total_blocks_in_epoch: u64, + ) { self.v0_mut().total_blocks_in_epoch = total_blocks_in_epoch; } #[wasm_bindgen(setter = "firstCoreBlockHeight")] - pub fn set_first_core_block_height(&mut self, first_core_block_height: u32) { + pub fn set_first_core_block_height( + &mut self, + #[wasm_bindgen(js_name = "firstCoreBlockHeight")] first_core_block_height: u32, + ) { self.v0_mut().first_core_block_height = first_core_block_height; } #[wasm_bindgen(setter = "nextEpochStartCoreBlockHeight")] pub fn set_next_epoch_start_core_block_height( &mut self, + #[wasm_bindgen(js_name = "nextEpochStartCoreBlockHeight")] next_epoch_start_core_block_height: u32, ) { self.v0_mut().next_epoch_start_core_block_height = next_epoch_start_core_block_height; } #[wasm_bindgen(setter = "totalProcessingFees")] - pub fn set_total_processing_fees(&mut self, total_processing_fees: u64) { + pub fn set_total_processing_fees( + &mut self, + #[wasm_bindgen(js_name = "totalProcessingFees")] total_processing_fees: u64, + ) { self.v0_mut().total_processing_fees = total_processing_fees; } #[wasm_bindgen(setter = "totalDistributedStorageFees")] - pub fn set_total_distributed_storage_fees(&mut self, total_distributed_storage_fees: u64) { + pub fn set_total_distributed_storage_fees( + &mut self, + #[wasm_bindgen(js_name = "totalDistributedStorageFees")] + total_distributed_storage_fees: u64, + ) { self.v0_mut().total_distributed_storage_fees = total_distributed_storage_fees; } #[wasm_bindgen(setter = "totalCreatedStorageFees")] - pub fn set_total_created_storage_fees(&mut self, total_created_storage_fees: u64) { + pub fn set_total_created_storage_fees( + &mut self, + #[wasm_bindgen(js_name = "totalCreatedStorageFees")] total_created_storage_fees: u64, + ) { self.v0_mut().total_created_storage_fees = total_created_storage_fees; } #[wasm_bindgen(setter = "coreBlockRewards")] - pub fn set_core_block_rewards(&mut self, core_block_rewards: u64) { + pub fn set_core_block_rewards( + &mut self, + #[wasm_bindgen(js_name = "coreBlockRewards")] core_block_rewards: u64, + ) { self.v0_mut().core_block_rewards = core_block_rewards; } #[wasm_bindgen(setter = "blockProposers")] - pub fn set_block_proposers(&mut self, block_proposers: &JsValue) -> WasmDppResult<()> { - let block_proposers_map = block_proposers_from_js(block_proposers)?; + pub fn set_block_proposers( + &mut self, + #[wasm_bindgen(js_name = "blockProposers")] block_proposers: BlockProposersMapJs, + ) -> WasmDppResult<()> { + let block_proposers_map = + block_proposers_from_map(&try_to_map(block_proposers, "blockProposers")?)?; self.v0_mut().block_proposers = block_proposers_map; Ok(()) } #[wasm_bindgen(setter = "feeMultiplierPermille")] - pub fn set_fee_multiplier_permille(&mut self, fee_multiplier_permille: u64) { + pub fn set_fee_multiplier_permille( + &mut self, + #[wasm_bindgen(js_name = "feeMultiplierPermille")] fee_multiplier_permille: u64, + ) { self.v0_mut().fee_multiplier_permille = fee_multiplier_permille; } #[wasm_bindgen(setter = "protocolVersion")] - pub fn set_protocol_version(&mut self, protocol_version: u32) { + pub fn set_protocol_version( + &mut self, + #[wasm_bindgen(js_name = "protocolVersion")] protocol_version: u32, + ) { self.v0_mut().protocol_version = protocol_version; } } -crate::impl_wasm_conversions!(FinalizedEpochInfoWasm, FinalizedEpochInfo); +crate::impl_wasm_conversions!( + FinalizedEpochInfoWasm, + FinalizedEpochInfo, + FinalizedEpochInfoObjectJs, + FinalizedEpochInfoJSONJs +); +impl_wasm_type_info!(FinalizedEpochInfoWasm, FinalizedEpochInfo); diff --git a/packages/wasm-dpp2/src/error.rs b/packages/wasm-dpp2/src/error.rs index b4fa897c0fb..2a38ccc9f8d 100644 --- a/packages/wasm-dpp2/src/error.rs +++ b/packages/wasm-dpp2/src/error.rs @@ -30,11 +30,7 @@ pub struct WasmDppError { } impl WasmDppError { - pub(crate) fn new( - kind: WasmDppErrorKind, - message: impl Into, - code: Option, - ) -> Self { + fn new(kind: WasmDppErrorKind, message: impl Into, code: Option) -> Self { Self { kind, message: message.into(), @@ -46,21 +42,19 @@ impl WasmDppError { Self::new(WasmDppErrorKind::Protocol, message, None) } - #[allow(dead_code)] - pub(crate) fn invalid_argument(message: impl Into) -> Self { + pub fn invalid_argument(message: impl Into) -> Self { Self::new(WasmDppErrorKind::InvalidArgument, message, None) } - pub(crate) fn serialization(message: impl Into) -> Self { + pub fn serialization(message: impl Into) -> Self { Self::new(WasmDppErrorKind::Serialization, message, None) } - #[allow(dead_code)] - pub(crate) fn conversion(message: impl Into) -> Self { + pub fn conversion(message: impl Into) -> Self { Self::new(WasmDppErrorKind::Conversion, message, None) } - pub(crate) fn generic(message: impl Into) -> Self { + pub fn generic(message: impl Into) -> Self { Self::new(WasmDppErrorKind::Generic, message, None) } } diff --git a/packages/wasm-dpp2/src/group/action.rs b/packages/wasm-dpp2/src/group/action.rs index e97280a4052..60f6c4a1aba 100644 --- a/packages/wasm-dpp2/src/group/action.rs +++ b/packages/wasm-dpp2/src/group/action.rs @@ -1,10 +1,43 @@ use crate::group::action_event::GroupActionEventWasm; use crate::identifier::IdentifierWasm; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use dpp::data_contract::TokenContractPosition; use dpp::group::group_action::{GroupAction, GroupActionAccessors}; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * GroupAction serialized as a plain object. + */ +export interface GroupActionObject { + contractId: Uint8Array; + proposerId: Uint8Array; + tokenContractPosition: number; + event: GroupActionEventObject; +} + +/** + * GroupAction serialized as JSON. + */ +export interface GroupActionJSON { + contractId: string; + proposerId: string; + tokenContractPosition: number; + event: GroupActionEventJSON; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "GroupActionObject")] + pub type GroupActionObjectJs; + + #[wasm_bindgen(typescript_type = "GroupActionJSON")] + pub type GroupActionJSONJs; +} + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "GroupAction")] pub struct GroupActionWasm(GroupAction); @@ -23,16 +56,6 @@ impl From for GroupAction { #[wasm_bindgen(js_class = GroupAction)] impl GroupActionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "GroupAction".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "GroupAction".to_string() - } - #[wasm_bindgen(getter = "contractId")] pub fn contract_id(&self) -> IdentifierWasm { self.0.contract_id().into() @@ -54,4 +77,10 @@ impl GroupActionWasm { } } -impl_wasm_conversions!(GroupActionWasm, GroupAction); +impl_wasm_conversions!( + GroupActionWasm, + GroupAction, + GroupActionObjectJs, + GroupActionJSONJs +); +impl_wasm_type_info!(GroupActionWasm, GroupAction); diff --git a/packages/wasm-dpp2/src/group/action_event.rs b/packages/wasm-dpp2/src/group/action_event.rs index 01aa19d350d..0e75ad3169e 100644 --- a/packages/wasm-dpp2/src/group/action_event.rs +++ b/packages/wasm-dpp2/src/group/action_event.rs @@ -1,8 +1,37 @@ use crate::group::token_event::TokenEventWasm; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use dpp::group::action_event::GroupActionEvent; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * GroupActionEvent serialized as a plain object. + */ +export interface GroupActionEventObject { + variant: GroupActionEventVariant; + tokenEvent?: TokenEventObject; +} + +/** + * GroupActionEvent serialized as JSON. + */ +export interface GroupActionEventJSON { + variant: number; + tokenEvent?: TokenEventJSON; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "GroupActionEventObject")] + pub type GroupActionEventObjectJs; + + #[wasm_bindgen(typescript_type = "GroupActionEventJSON")] + pub type GroupActionEventJSONJs; +} + /// TypeScript enum for GroupActionEvent variants #[wasm_bindgen] #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -28,16 +57,6 @@ impl From for GroupActionEvent { #[wasm_bindgen(js_class = GroupActionEvent)] impl GroupActionEventWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "GroupActionEvent".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name(&self) -> String { - "GroupActionEvent".to_string() - } - #[wasm_bindgen(getter = "variant")] pub fn variant(&self) -> GroupActionEventVariant { match &self.0 { @@ -63,4 +82,10 @@ impl GroupActionEventWasm { } } -impl_wasm_conversions!(GroupActionEventWasm, GroupActionEvent); +impl_wasm_conversions!( + GroupActionEventWasm, + GroupActionEvent, + GroupActionEventObjectJs, + GroupActionEventJSONJs +); +impl_wasm_type_info!(GroupActionEventWasm, GroupActionEvent); diff --git a/packages/wasm-dpp2/src/group/token_event.rs b/packages/wasm-dpp2/src/group/token_event.rs index 6ff83d65b1c..147bcd42f05 100644 --- a/packages/wasm-dpp2/src/group/token_event.rs +++ b/packages/wasm-dpp2/src/group/token_event.rs @@ -1,7 +1,36 @@ use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use dpp::tokens::token_event::TokenEvent; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * TokenEvent serialized as a plain object. + */ +export interface TokenEventObject { + variant: TokenEventVariant; + [key: string]: unknown; +} + +/** + * TokenEvent serialized as JSON. + */ +export interface TokenEventJSON { + variant: number; + [key: string]: unknown; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenEventObject")] + pub type TokenEventObjectJs; + + #[wasm_bindgen(typescript_type = "TokenEventJSON")] + pub type TokenEventJSONJs; +} + /// TypeScript enum for TokenEvent variants #[wasm_bindgen] #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -37,16 +66,6 @@ impl From for TokenEvent { #[wasm_bindgen(js_class = TokenEvent)] impl TokenEventWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenEvent".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name(&self) -> String { - "TokenEvent".to_string() - } - #[wasm_bindgen(getter = "variant")] pub fn variant(&self) -> TokenEventVariant { match &self.0 { @@ -67,4 +86,10 @@ impl TokenEventWasm { } } -impl_wasm_conversions!(TokenEventWasm, TokenEvent); +impl_wasm_conversions!( + TokenEventWasm, + TokenEvent, + TokenEventObjectJs, + TokenEventJSONJs +); +impl_wasm_type_info!(TokenEventWasm, TokenEvent); diff --git a/packages/wasm-dpp2/src/identifier.rs b/packages/wasm-dpp2/src/identifier.rs index 5227184b1d1..cd2b494b6a4 100644 --- a/packages/wasm-dpp2/src/identifier.rs +++ b/packages/wasm-dpp2/src/identifier.rs @@ -1,4 +1,6 @@ use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use crate::utils::IntoWasm; use dpp::platform_value::string_encoding::Encoding::{Base58, Base64, Hex}; use dpp::platform_value::string_encoding::decode; @@ -15,10 +17,59 @@ use wasm_bindgen::prelude::*; pub struct IdentifierWasm(Identifier); #[wasm_bindgen(typescript_custom_section)] -const IDENTIFIER_TS_HELPERS: &'static str = r#" +const IDENTIFIER_TS_HELPERS: &str = r#" export type IdentifierLike = Identifier | Uint8Array | string; +export type IdentifierLikeArray = Array; +export type IdentifierLikeOrUndefined = Identifier | Uint8Array | string | undefined; "#; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentifierLike")] + pub type IdentifierLikeJs; + + #[wasm_bindgen(typescript_type = "IdentifierLikeArray")] + pub type IdentifierLikeArrayJs; + + #[wasm_bindgen(typescript_type = "IdentifierLikeOrUndefined")] + pub type IdentifierLikeOrUndefinedJs; +} + +impl TryFrom for IdentifierWasm { + type Error = WasmDppError; + fn try_from(value: IdentifierLikeJs) -> Result { + let js_value: JsValue = value.into(); + IdentifierWasm::try_from(js_value) + } +} + +impl TryFrom for Identifier { + type Error = WasmDppError; + fn try_from(value: IdentifierLikeJs) -> Result { + Ok(IdentifierWasm::try_from(value)?.into()) + } +} + +impl TryFrom for Option { + type Error = WasmDppError; + fn try_from(value: IdentifierLikeOrUndefinedJs) -> Result { + let js_value: JsValue = value.into(); + if js_value.is_undefined() || js_value.is_null() { + Ok(None) + } else { + IdentifierWasm::try_from(js_value).map(Some) + } + } +} + +impl TryFrom for Option { + type Error = WasmDppError; + fn try_from(value: IdentifierLikeOrUndefinedJs) -> Result { + let opt: Option = value.try_into()?; + Ok(opt.map(Identifier::from)) + } +} + impl From for Identifier { fn from(identifier: IdentifierWasm) -> Self { identifier.0 @@ -77,7 +128,7 @@ impl TryFrom for IdentifierWasm { return IdentifierWasm::try_from(string.as_str()); } - if value.is_instance_of::() || value.is_array() || value.is_object() { + if value.is_instance_of::() || value.is_array() { let uint8_array = Uint8Array::from(value.clone()); let bytes = uint8_array.to_vec(); @@ -87,7 +138,7 @@ impl TryFrom for IdentifierWasm { } Err(WasmDppError::invalid_argument( - "Invalid identifier. Expected Identifier, Uint8Array or string", + "Invalid identifier. Expected Identifier, Uint8Array, array or string", )) } } @@ -204,22 +255,9 @@ impl Serialize for IdentifierWasm { #[wasm_bindgen(js_class = Identifier)] impl IdentifierWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "Identifier".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "Identifier".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identifier: &JsValue, - ) -> WasmDppResult { - IdentifierWasm::try_from(identifier) + pub fn constructor(identifier: IdentifierLikeJs) -> WasmDppResult { + identifier.try_into() } #[wasm_bindgen(js_name = "toBase58")] @@ -293,24 +331,7 @@ impl IdentifierWasm { pub fn to_slice(&self) -> [u8; 32] { *self.0.as_bytes() } - - /// Try to extract an Identifier from an options object field. - /// - /// This helper reads the specified field from an options object and converts it - /// to an IdentifierWasm. Accepts Identifier, Uint8Array, or string (Base58/hex). - pub fn try_from_options(options: &JsValue, field_name: &str) -> WasmDppResult { - let id_js = - js_sys::Reflect::get(options, &JsValue::from_str(field_name)).map_err(|_| { - WasmDppError::invalid_argument(format!("Missing '{}' field", field_name)) - })?; - - if id_js.is_undefined() || id_js.is_null() { - return Err(WasmDppError::invalid_argument(format!( - "'{}' is required", - field_name - ))); - } - - IdentifierWasm::try_from(&id_js) - } } + +impl_try_from_options!(IdentifierWasm); +impl_wasm_type_info!(IdentifierWasm, Identifier); diff --git a/packages/wasm-dpp2/src/identity/mod.rs b/packages/wasm-dpp2/src/identity/mod.rs index 2bbbac6a005..8de29198056 100644 --- a/packages/wasm-dpp2/src/identity/mod.rs +++ b/packages/wasm-dpp2/src/identity/mod.rs @@ -6,7 +6,9 @@ pub mod transitions; pub use model::IdentityWasm; pub use partial_identity::PartialIdentityWasm; -pub use public_key::IdentityPublicKeyWasm; +pub use public_key::{ + IdentityPublicKeyOptionsJs, IdentityPublicKeyWasm, PublicKeyHashLikeJs, public_key_hash_from_js, +}; pub use signer::IdentitySignerWasm; pub use transitions::create_transition::IdentityCreateTransitionWasm; pub use transitions::credit_withdrawal_transition::IdentityCreditWithdrawalTransitionWasm; diff --git a/packages/wasm-dpp2/src/identity/model.rs b/packages/wasm-dpp2/src/identity/model.rs index e551cf374ba..8e6c3741cc9 100644 --- a/packages/wasm-dpp2/src/identity/model.rs +++ b/packages/wasm-dpp2/src/identity/model.rs @@ -1,8 +1,11 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::identity::public_key::IdentityPublicKeyWasm; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use crate::serialization; +use crate::utils::try_to_u64; use dpp::identity::accessors::{IdentityGettersV0, IdentitySettersV0}; use dpp::identity::{Identity, KeyID}; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; @@ -10,10 +13,43 @@ use dpp::platform_value::string_encoding::{decode, encode}; use dpp::prelude::Identifier; use dpp::serialization::{PlatformDeserializable, PlatformSerializable, ValueConvertible}; use dpp::version::{PlatformVersion, TryFromPlatformVersioned}; -use std::convert::TryFrom; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const IDENTITY_TYPES_TS: &str = r#" +/** + * Identity serialized as a plain object. + */ +export interface IdentityObject { + $version: string; + id: Identifier; + publicKeys: IdentityPublicKeyObject[]; + balance: bigint; + revision: bigint; +} + +/** + * Identity serialized as JSON (with string identifiers). + */ +export interface IdentityJSON { + $version: string; + id: string; + publicKeys: IdentityPublicKeyJSON[]; + balance: number; + revision: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityObject")] + pub type IdentityObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityJSON")] + pub type IdentityJSONJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "Identity")] pub struct IdentityWasm(Identity); @@ -32,80 +68,68 @@ impl From for Identity { #[wasm_bindgen(js_class = Identity)] impl IdentityWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "Identity".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "Identity".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identifier: &JsValue, - ) -> WasmDppResult { - let identifier: Identifier = IdentifierWasm::try_from(js_identifier)?.into(); - + pub fn constructor(id: IdentifierLikeJs) -> WasmDppResult { + let identifier: Identifier = id.try_into()?; let identity = Identity::create_basic_identity(identifier, PlatformVersion::first())?; - Ok(IdentityWasm(identity)) } #[wasm_bindgen(setter = "id")] - pub fn set_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identifier: &JsValue, - ) -> WasmDppResult<()> { - let identifier: Identifier = IdentifierWasm::try_from(js_identifier)?.into(); - self.0.set_id(identifier); + pub fn set_id(&mut self, id: IdentifierLikeJs) -> WasmDppResult<()> { + self.0.set_id(id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "balance")] - pub fn set_balance(&mut self, balance: u64) { - self.0.set_balance(balance); + pub fn set_balance(&mut self, balance: JsValue) -> WasmDppResult<()> { + self.0.set_balance(try_to_u64(&balance, "balance")?); + Ok(()) } #[wasm_bindgen(setter = "revision")] - pub fn set_revision(&mut self, revision: u64) { - self.0.set_revision(revision); + pub fn set_revision(&mut self, revision: JsValue) -> WasmDppResult<()> { + self.0.set_revision(try_to_u64(&revision, "revision")?); + Ok(()) } #[wasm_bindgen(js_name = "addPublicKey")] - pub fn add_public_key(&mut self, public_key: &IdentityPublicKeyWasm) { + pub fn add_public_key( + &mut self, + #[wasm_bindgen(js_name = "publicKey")] public_key: &IdentityPublicKeyWasm, + ) { self.0.add_public_key(public_key.clone().into()); } // GETTERS #[wasm_bindgen(getter = "id")] - pub fn get_id(&self) -> IdentifierWasm { + pub fn id(&self) -> IdentifierWasm { self.0.id().into() } #[wasm_bindgen(getter = "balance")] - pub fn get_balance(&self) -> u64 { + pub fn balance(&self) -> u64 { self.0.balance() } #[wasm_bindgen(getter = "revision")] - pub fn get_revision(&self) -> u64 { + pub fn revision(&self) -> u64 { self.0.revision() } #[wasm_bindgen(js_name = "getPublicKeyById")] - pub fn get_public_key_by_id(&self, key_id: KeyID) -> Option { + pub fn get_public_key_by_id( + &self, + #[wasm_bindgen(js_name = "keyId")] key_id: KeyID, + ) -> Option { self.0 .get_public_key_by_id(key_id) .map(|key| IdentityPublicKeyWasm::from(key.clone())) } - #[wasm_bindgen(js_name = "getPublicKeys")] - pub fn get_public_keys(&self) -> Vec { + #[wasm_bindgen(getter = "publicKeys")] + pub fn public_keys(&self) -> Vec { self.0 .public_keys() .values() @@ -147,27 +171,30 @@ impl IdentityWasm { } #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self) -> WasmDppResult { + pub fn to_object(&self) -> WasmDppResult { // Use platform_value conversion which handles BigInt for balance/revision // and outputs id as Uint8Array, publicKeys as plain objects let value = self.0.to_object()?; - serialization::platform_value_to_object(&value) + let js_value = serialization::platform_value_to_object(&value)?; + Ok(js_value.into()) } #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self) -> WasmDppResult { - serialization::to_json(&self.0) + pub fn to_json(&self) -> WasmDppResult { + let js_value = serialization::to_json(&self.0)?; + Ok(js_value.into()) } #[wasm_bindgen(js_name = "fromJSON")] - pub fn from_json(js_value: JsValue) -> WasmDppResult { - serialization::from_json(js_value).map(IdentityWasm) + pub fn from_json(value: IdentityJSONJs) -> WasmDppResult { + serialization::from_json(value.into()).map(IdentityWasm) } #[wasm_bindgen(js_name = "fromObject")] - pub fn from_object(js_value: JsValue) -> WasmDppResult { - let value = serialization::js_value_to_platform_value(&js_value)?; - let identity = Identity::try_from_platform_versioned(value, PlatformVersion::latest())?; + pub fn from_object(value: IdentityObjectJs) -> WasmDppResult { + let platform_value = serialization::js_value_to_platform_value(&value.into())?; + let identity = + Identity::try_from_platform_versioned(platform_value, PlatformVersion::latest())?; Ok(IdentityWasm(identity)) } @@ -178,4 +205,6 @@ impl IdentityWasm { } } -impl_try_from_options!(IdentityWasm, "Identity"); +impl_try_from_js_value!(IdentityWasm, "Identity"); +impl_try_from_options!(IdentityWasm); +impl_wasm_type_info!(IdentityWasm, Identity); diff --git a/packages/wasm-dpp2/src/identity/partial_identity.rs b/packages/wasm-dpp2/src/identity/partial_identity.rs index 2420f173c1e..26a3eab3117 100644 --- a/packages/wasm-dpp2/src/identity/partial_identity.rs +++ b/packages/wasm-dpp2/src/identity/partial_identity.rs @@ -1,15 +1,67 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::identity::public_key::IdentityPublicKeyWasm; -use crate::utils::{IntoWasm, JsValueExt}; +use crate::impl_wasm_type_info; +use crate::serialization; +use crate::utils::{ + JsValueExt, try_from_options, try_from_options_optional_with, try_from_options_with, + try_to_array, try_to_object, try_to_u32, try_to_u64, +}; use dpp::fee::Credits; use dpp::identity::{IdentityPublicKey, KeyID, PartialIdentity}; +use dpp::platform_value; use dpp::prelude::Revision; use js_sys::{Array, Object, Reflect}; use std::collections::{BTreeMap, BTreeSet}; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const PARTIAL_IDENTITY_OPTIONS_TS: &str = r#" +export interface PartialIdentityOptions { + id: IdentifierLike; + loadedPublicKeys: Record; + balance?: bigint; + revision?: bigint; + notFoundPublicKeys?: number[]; +} + +/** + * PartialIdentity serialized as a plain object. + */ +export interface PartialIdentityObject { + id: Uint8Array; + loadedPublicKeys: Record; + balance?: bigint; + revision?: bigint; + notFoundPublicKeys: number[]; +} + +/** + * PartialIdentity serialized as JSON. + * Note: JSON uses null for missing optional fields (JSON standard). + */ +export interface PartialIdentityJSON { + id: string; + loadedPublicKeys: Record; + balance: number | null; + revision: number | null; + notFoundPublicKeys: number[]; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "PartialIdentityOptions")] + pub type PartialIdentityOptionsJs; + + #[wasm_bindgen(typescript_type = "PartialIdentityObject")] + pub type PartialIdentityObjectJs; + + #[wasm_bindgen(typescript_type = "PartialIdentityJSON")] + pub type PartialIdentityJSONJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "PartialIdentity")] pub struct PartialIdentityWasm(PartialIdentity); @@ -23,25 +75,31 @@ impl From for PartialIdentityWasm { #[wasm_bindgen(js_class = PartialIdentity)] impl PartialIdentityWasm { #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] js_id: &JsValue, - js_loaded_public_keys: &JsValue, - balance: Option, - revision: Option, - js_not_found_public_keys: Option, - ) -> WasmDppResult { - let id = IdentifierWasm::try_from(js_id)?.into(); - let loaded_public_keys = js_value_to_loaded_public_keys(js_loaded_public_keys)?; - - let not_found_public_keys: BTreeSet = - option_array_to_not_found(js_not_found_public_keys)?; + pub fn constructor(options: PartialIdentityOptionsJs) -> WasmDppResult { + let id: IdentifierWasm = try_from_options(&options, "id")?; + + let loaded_public_keys = try_from_options_with(&options, "loadedPublicKeys", |v| { + value_to_loaded_public_keys(v) + })?; + + let balance: Option = + try_from_options_optional_with(&options, "balance", |v| try_to_u64(v, "balance"))?; + + let revision: Option = + try_from_options_optional_with(&options, "revision", |v| try_to_u64(v, "revision"))?; + + let not_found_public_keys: Option = + try_from_options_optional_with(&options, "notFoundPublicKeys", |v| { + try_to_array(v, "notFoundPublicKeys") + })?; + let not_found_keys: BTreeSet = option_array_to_not_found(not_found_public_keys)?; Ok(PartialIdentityWasm(PartialIdentity { - id, + id: id.into(), loaded_public_keys, balance, revision, - not_found_public_keys, + not_found_public_keys: not_found_keys, })) } @@ -94,20 +152,18 @@ impl PartialIdentityWasm { } #[wasm_bindgen(setter = "id")] - pub fn set_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] js_id: &JsValue, - ) -> WasmDppResult<()> { - let identifier = IdentifierWasm::try_from(js_id)?.into(); - - self.0.id = identifier; - + pub fn set_id(&mut self, id: IdentifierLikeJs) -> WasmDppResult<()> { + self.0.id = id.try_into()?; Ok(()) } #[wasm_bindgen(setter = "loadedPublicKeys")] - pub fn set_loaded_public_keys(&mut self, loaded_public_keys: &JsValue) -> WasmDppResult<()> { - self.0.loaded_public_keys = js_value_to_loaded_public_keys(loaded_public_keys)?; + pub fn set_loaded_public_keys( + &mut self, + #[wasm_bindgen(unchecked_param_type = "Record")] + loaded_public_keys: &JsValue, + ) -> WasmDppResult<()> { + self.0.loaded_public_keys = value_to_loaded_public_keys(loaded_public_keys)?; Ok(()) } @@ -130,140 +186,125 @@ impl PartialIdentityWasm { } #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self) -> WasmDppResult { - let obj = Object::new(); + pub fn to_json(&self) -> WasmDppResult { + // Convert to platform_value, which handles integer map keys by converting to strings + let value = platform_value::to_value(&self.0) + .map_err(|e| WasmDppError::serialization(format!("toJSON: {}", e)))?; + // platform_value_to_json converts Identifier to base58, bytes to base64 + let js_value = serialization::platform_value_to_json(&value)?; + Ok(js_value.into()) + } - Reflect::set(&obj, &"id".into(), &self.id().to_base58().into()) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; + #[wasm_bindgen(js_name = "toObject")] + pub fn to_object(&self) -> WasmDppResult { + // Convert to platform_value, which handles integer map keys by converting to strings + let value = platform_value::to_value(&self.0) + .map_err(|e| WasmDppError::serialization(format!("toObject: {}", e)))?; + // platform_value_to_object keeps bytes as Uint8Array, u64 as BigInt + let js_value = serialization::platform_value_to_object(&value)?; + Ok(js_value.into()) + } - // Serialize loaded public keys as object with string keys and JSON values - let loaded_keys_obj = Object::new(); - for (k, v) in self.0.loaded_public_keys.clone() { - let key_wasm = IdentityPublicKeyWasm::from(v); - Reflect::set( - &loaded_keys_obj, - &k.to_string().into(), - &key_wasm.to_json()?, - ) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; - } - Reflect::set(&obj, &"loadedPublicKeys".into(), &loaded_keys_obj.into()) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; - - match self.0.balance { - Some(b) => Reflect::set(&obj, &"balance".into(), &JsValue::from(b as f64)) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - None => Reflect::set(&obj, &"balance".into(), &JsValue::NULL) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - }; - - match self.0.revision { - Some(r) => Reflect::set(&obj, &"revision".into(), &JsValue::from(r as f64)) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - None => Reflect::set(&obj, &"revision".into(), &JsValue::NULL) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - }; - - let not_found_arr = Array::new(); - for k in self.0.not_found_public_keys.iter() { - not_found_arr.push(&JsValue::from(*k)); - } - Reflect::set(&obj, &"notFoundPublicKeys".into(), ¬_found_arr.into()) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; + #[wasm_bindgen(js_name = "fromObject")] + pub fn from_object(obj: PartialIdentityObjectJs) -> WasmDppResult { + let obj: JsValue = obj.into(); + + // id - can be Uint8Array or Identifier + let id: IdentifierWasm = try_from_options(&obj, "id")?; + + // loadedPublicKeys - values are plain objects + let loaded_public_keys = try_from_options_with(&obj, "loadedPublicKeys", |v| { + value_to_loaded_public_keys_from_object(v) + })?; + + // balance - can be BigInt, number, or undefined + let balance: Option = + try_from_options_optional_with(&obj, "balance", |v| try_to_u64(v, "balance"))?; + + // revision - can be BigInt, number, or undefined + let revision: Option = + try_from_options_optional_with(&obj, "revision", |v| try_to_u64(v, "revision"))?; - Ok(obj.into()) + // notFoundPublicKeys + let not_found_public_keys: Option = + try_from_options_optional_with(&obj, "notFoundPublicKeys", |v| { + try_to_array(v, "notFoundPublicKeys") + })?; + let not_found_keys: BTreeSet = option_array_to_not_found(not_found_public_keys)?; + + Ok(PartialIdentityWasm(PartialIdentity { + id: id.into(), + loaded_public_keys, + balance, + revision, + not_found_public_keys: not_found_keys, + })) } - #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self) -> WasmDppResult { - let obj = Object::new(); + #[wasm_bindgen(js_name = "fromJSON")] + pub fn from_json(json: PartialIdentityJSONJs) -> WasmDppResult { + let json: JsValue = json.into(); + + // id - base58 string + let id: IdentifierWasm = try_from_options(&json, "id")?; + + // loadedPublicKeys - values are JSON objects + let loaded_public_keys = try_from_options_with(&json, "loadedPublicKeys", |v| { + value_to_loaded_public_keys_from_json(v) + })?; + + // balance - can be BigInt, number, or string (JSON doesn't support BigInt natively) + let balance: Option = + try_from_options_optional_with(&json, "balance", |v| try_to_u64(v, "balance"))?; + + // revision - can be BigInt, number, or string (JSON doesn't support BigInt natively) + let revision: Option = + try_from_options_optional_with(&json, "revision", |v| try_to_u64(v, "revision"))?; + + // notFoundPublicKeys + let not_found_public_keys: Option = + try_from_options_optional_with(&json, "notFoundPublicKeys", |v| { + try_to_array(v, "notFoundPublicKeys") + })?; + let not_found_keys: BTreeSet = option_array_to_not_found(not_found_public_keys)?; - Reflect::set(&obj, &"id".into(), &JsValue::from(self.id())) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; - - Reflect::set( - &obj, - &"loadedPublicKeys".into(), - &self.loaded_public_keys()?.into(), - ) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; - - match self.0.balance { - Some(b) => Reflect::set(&obj, &"balance".into(), &js_sys::BigInt::from(b).into()) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - None => Reflect::set(&obj, &"balance".into(), &JsValue::NULL) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - }; - - match self.0.revision { - Some(r) => Reflect::set(&obj, &"revision".into(), &js_sys::BigInt::from(r).into()) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - None => Reflect::set(&obj, &"revision".into(), &JsValue::NULL) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?, - }; - - Reflect::set( - &obj, - &"notFoundPublicKeys".into(), - &self.not_found_public_keys().into(), - ) - .map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?; - - Ok(obj.into()) + Ok(PartialIdentityWasm(PartialIdentity { + id: id.into(), + loaded_public_keys, + balance, + revision, + not_found_public_keys: not_found_keys, + })) } } -pub fn js_value_to_loaded_public_keys( - js_loaded_public_keys: &JsValue, +impl_wasm_type_info!(PartialIdentityWasm, PartialIdentity); + +pub fn value_to_loaded_public_keys( + loaded_public_keys: &JsValue, ) -> WasmDppResult> { - match js_loaded_public_keys.is_object() { - false => Err(WasmDppError::invalid_argument( - "loaded_public_keys must be an object", - )), - true => { - let mut map = BTreeMap::new(); - - let pub_keys_object = Object::from(js_loaded_public_keys.clone()); - let keys = Object::keys(&pub_keys_object); - - for key in keys.iter() { - let key_val = key.as_f64().ok_or_else(|| { - WasmDppError::invalid_argument("Key identifier must be numeric") - })?; - - if key_val > u32::MAX as f64 { - return Err(WasmDppError::invalid_argument(format!( - "Key id '{:?}' exceeds the maximum limit for u32.", - key.as_string() - ))); - } - - let key_id = KeyID::from(key_val as u32); - - let js_key = Reflect::get(&pub_keys_object, &key).map_err(|err| { - let message = err.error_message(); - WasmDppError::invalid_argument(format!( - "unable to access loaded public key '{}': {}", - key_val as u32, message - )) - })?; - - let key = js_key - .to_wasm::("IdentityPublicKey")? - .clone(); - - map.insert(key_id, IdentityPublicKey::from(key)); - } - - Ok(map) - } + let mut map = BTreeMap::new(); + + let pub_keys_object = try_to_object(loaded_public_keys.clone(), "loadedPublicKeys")?; + let keys = Object::keys(&pub_keys_object); + + for key in keys.iter() { + // Object.keys() returns strings, try_to_u32 handles string parsing + let key_id = KeyID::from(try_to_u32(&key, "key identifier")?); + + let public_key: IdentityPublicKeyWasm = + try_from_options(&pub_keys_object.clone().into(), &key_id.to_string())?; + + map.insert(key_id, public_key.into()); } + + Ok(map) } pub fn option_array_to_not_found( - js_not_found_public_keys: Option, + not_found_public_keys: Option, ) -> WasmDppResult> { - match js_not_found_public_keys { + match not_found_public_keys { None => Ok(BTreeSet::new()), Some(keys) => { let keys_iter: Vec = keys @@ -289,3 +330,85 @@ pub fn option_array_to_not_found( } } } + +/// Parse loaded public keys from an object (where values are plain objects from toObject) +pub fn value_to_loaded_public_keys_from_object( + loaded_public_keys: &JsValue, +) -> WasmDppResult> { + let mut map = BTreeMap::new(); + let pub_keys_object = try_to_object(loaded_public_keys.clone(), "loadedPublicKeys")?; + let keys = Object::keys(&pub_keys_object); + + for key in keys.iter() { + let key_str = key + .as_string() + .ok_or_else(|| WasmDppError::invalid_argument("Key identifier must be a string"))?; + let key_val: f64 = key_str.parse().map_err(|_| { + WasmDppError::invalid_argument(format!("Key identifier '{}' must be numeric", key_str)) + })?; + + if key_val > u32::MAX as f64 { + return Err(WasmDppError::invalid_argument(format!( + "Key id '{}' exceeds the maximum limit for u32.", + key_str + ))); + } + + let key_id = KeyID::from(key_val as u32); + + let js_key = Reflect::get(&pub_keys_object, &key).map_err(|err| { + let message = err.error_message(); + WasmDppError::invalid_argument(format!( + "unable to access loaded public key '{}': {}", + key_val as u32, message + )) + })?; + + // fromObject receives plain objects, use IdentityPublicKeyWasm::from_object + let pub_key = IdentityPublicKeyWasm::from_object(js_key.into())?; + map.insert(key_id, IdentityPublicKey::from(pub_key)); + } + + Ok(map) +} + +/// Parse loaded public keys from JSON (where values are JSON objects from toJSON) +pub fn value_to_loaded_public_keys_from_json( + loaded_public_keys: &JsValue, +) -> WasmDppResult> { + let mut map = BTreeMap::new(); + let pub_keys_object = try_to_object(loaded_public_keys.clone(), "loadedPublicKeys")?; + let keys = Object::keys(&pub_keys_object); + + for key in keys.iter() { + let key_str = key + .as_string() + .ok_or_else(|| WasmDppError::invalid_argument("Key identifier must be a string"))?; + let key_val: f64 = key_str.parse().map_err(|_| { + WasmDppError::invalid_argument(format!("Key identifier '{}' must be numeric", key_str)) + })?; + + if key_val > u32::MAX as f64 { + return Err(WasmDppError::invalid_argument(format!( + "Key id '{}' exceeds the maximum limit for u32.", + key_str + ))); + } + + let key_id = KeyID::from(key_val as u32); + + let js_key = Reflect::get(&pub_keys_object, &key).map_err(|err| { + let message = err.error_message(); + WasmDppError::invalid_argument(format!( + "unable to access loaded public key '{}': {}", + key_val as u32, message + )) + })?; + + // fromJSON receives JSON objects, use IdentityPublicKeyWasm::from_json + let pub_key = IdentityPublicKeyWasm::from_json(js_key.into())?; + map.insert(key_id, IdentityPublicKey::from(pub_key)); + } + + Ok(map) +} diff --git a/packages/wasm-dpp2/src/identity/public_key.rs b/packages/wasm-dpp2/src/identity/public_key.rs index a414ba64b8c..dc81d1df4f6 100644 --- a/packages/wasm-dpp2/src/identity/public_key.rs +++ b/packages/wasm-dpp2/src/identity/public_key.rs @@ -1,12 +1,16 @@ -use crate::core::network::NetworkWasm; +use crate::core::network::NetworkLikeJs; use crate::data_contract::contract_bounds::ContractBoundsWasm; -use crate::enums::keys::key_type::KeyTypeWasm; -use crate::enums::keys::purpose::PurposeWasm; -use crate::enums::keys::security_level::SecurityLevelWasm; +use crate::enums::keys::key_type::{KeyTypeLikeJs, KeyTypeWasm}; +use crate::enums::keys::purpose::{PurposeLikeJs, PurposeWasm}; +use crate::enums::keys::security_level::{SecurityLevelLikeJs, SecurityLevelWasm}; use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use crate::serialization; -use crate::utils::IntoWasm; +use crate::utils::{ + try_from_options, try_from_options_optional, try_to_fixed_bytes, try_to_u32, try_to_u64, +}; use dpp::dashcore::Network; use dpp::dashcore::secp256k1::hashes::hex::{Case, DisplayHex}; use dpp::identity::contract_bounds::ContractBounds; @@ -23,13 +27,117 @@ use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::{decode, encode}; use dpp::serialization::{PlatformDeserializable, PlatformSerializable}; use dpp::version::PlatformVersion; +use hex; +use serde::Deserialize; use serde_json::Value as JsonValue; use serde_wasm_bindgen::from_value as serde_from_value; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IdentityPublicKeyOptions { + key_id: u32, + data: Vec, + #[serde(default)] + is_read_only: bool, + #[serde(default)] + disabled_at: Option, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export type PurposeLike = Purpose | string | number; +export type SecurityLevelLike = SecurityLevel | string | number; +export type KeyTypeLike = KeyType | string | number; + +export interface IdentityPublicKeyOptions { + keyId: number; + purpose: PurposeLike; + securityLevel: SecurityLevelLike; + keyType: KeyTypeLike; + isReadOnly?: boolean; + data: Uint8Array; + disabledAt?: number; + contractBounds?: ContractBounds; +} + +/** + * IdentityPublicKey serialized as a plain object. + */ +export interface IdentityPublicKeyObject { + $version: string; + id: number; + purpose: number; + securityLevel: number; + contractBounds?: ContractBounds; + type: number; + readOnly: boolean; + data: Uint8Array; + disabledAt?: number; +} + +/** + * IdentityPublicKey serialized as JSON. + */ +export interface IdentityPublicKeyJSON { + $version: string; + id: number; + purpose: number; + securityLevel: number; + contractBounds?: object; + type: number; + readOnly: boolean; + data: string; + disabledAt?: number; +} + +/** + * PublicKeyHash input type - accepts hex string or Uint8Array (20 bytes for HASH160) + */ +export type PublicKeyHashLike = string | Uint8Array; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityPublicKeyOptions")] + pub type IdentityPublicKeyOptionsJs; + + #[wasm_bindgen(typescript_type = "IdentityPublicKeyObject")] + pub type IdentityPublicKeyObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityPublicKeyJSON")] + pub type IdentityPublicKeyJSONJs; + + #[wasm_bindgen(typescript_type = "PublicKeyHashLike")] + pub type PublicKeyHashLikeJs; +} + +/// Convert PublicKeyHashLikeJs to Vec +/// Accepts hex string (40 chars) or Uint8Array (20 bytes) for HASH160 +pub fn public_key_hash_from_js(value: PublicKeyHashLikeJs) -> WasmDppResult> { + let js_value: JsValue = value.into(); + + if let Some(hex_str) = js_value.as_string() { + let bytes = hex::decode(&hex_str).map_err(|e| { + WasmDppError::invalid_argument(format!("Invalid hex string for public key hash: {}", e)) + })?; + if bytes.len() != 20 { + return Err(WasmDppError::invalid_argument(format!( + "Public key hash must be exactly 20 bytes (HASH160), got {}", + bytes.len() + ))); + } + Ok(bytes) + } else { + // Validate type is Uint8Array and length is 20 bytes + let bytes = try_to_fixed_bytes::<20>(js_value, "publicKeyHash")?; + Ok(bytes.to_vec()) + } +} + #[derive(Clone)] -#[wasm_bindgen(js_name = IdentityPublicKey)] +#[wasm_bindgen(js_name = "IdentityPublicKey")] pub struct IdentityPublicKeyWasm(IdentityPublicKey); impl From for IdentityPublicKeyWasm { @@ -46,53 +154,36 @@ impl From for IdentityPublicKey { #[wasm_bindgen(js_class = IdentityPublicKey)] impl IdentityPublicKeyWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentityPublicKey".to_string() - } + #[wasm_bindgen(constructor)] + pub fn constructor(options: IdentityPublicKeyOptionsJs) -> WasmDppResult { + // Extract purpose (required, complex type) + let purpose: PurposeWasm = try_from_options(&options, "purpose")?; - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentityPublicKey".to_string() - } + // Extract securityLevel (required, complex type) + let security_level: SecurityLevelWasm = try_from_options(&options, "securityLevel")?; - #[wasm_bindgen(constructor)] - #[allow(clippy::too_many_arguments)] - pub fn new( - id: u32, - js_purpose: JsValue, - js_security_level: JsValue, - js_key_type: JsValue, - read_only: bool, - binary_data: &str, - disabled_at: Option, - js_contract_bounds: &JsValue, - ) -> WasmDppResult { - let purpose = PurposeWasm::try_from(js_purpose)?; - let security_level = SecurityLevelWasm::try_from(js_security_level)?; - let key_type = KeyTypeWasm::try_from(js_key_type)?; + // Extract keyType (required, complex type) + let key_type: KeyTypeWasm = try_from_options(&options, "keyType")?; + + // Extract contractBounds (optional) let contract_bounds: Option = - match js_contract_bounds.is_undefined() | js_contract_bounds.is_null() { - true => None, - false => Some( - js_contract_bounds - .to_wasm::("ContractBounds")? - .clone() - .into(), - ), - }; + try_from_options_optional::(&options, "contractBounds")? + .map(Into::into); + + // Extract simple fields via serde + let opts: IdentityPublicKeyOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(IdentityPublicKeyWasm(IdentityPublicKey::from( IdentityPublicKeyV0 { - id, + id: opts.key_id, purpose: Purpose::from(purpose), security_level: SecurityLevel::from(security_level), contract_bounds, key_type: KeyType::from(key_type), - read_only, - data: BinaryData::from_string(binary_data, Hex) - .map_err(|e| WasmDppError::serialization(e.to_string()))?, - disabled_at, + read_only: opts.is_read_only, + data: BinaryData::new(opts.data), + disabled_at: opts.disabled_at, }, ))) } @@ -103,14 +194,19 @@ impl IdentityPublicKeyWasm { #[wasm_bindgen(js_name = "validatePrivateKey")] pub fn validate_private_key( &self, - js_private_key_bytes: Vec, - #[wasm_bindgen(unchecked_param_type = "NetworkLike")] network: JsValue, + private_key_bytes_input: Vec, + network: NetworkLikeJs, ) -> WasmDppResult { + if private_key_bytes_input.len() != 32 { + return Err(WasmDppError::invalid_argument(format!( + "Private key must be exactly 32 bytes, got {}", + private_key_bytes_input.len() + ))); + } let mut private_key_bytes = [0u8; 32]; - let len = js_private_key_bytes.len().min(32); - private_key_bytes[..len].copy_from_slice(&js_private_key_bytes[..len]); + private_key_bytes.copy_from_slice(&private_key_bytes_input); - let network = Network::from(NetworkWasm::try_from(network)?); + let network: Network = network.try_into()?; let is_valid = self .0 @@ -119,113 +215,109 @@ impl IdentityPublicKeyWasm { Ok(is_valid) } - #[wasm_bindgen(js_name = "getContractBounds")] - pub fn contract_bounds(&self) -> JsValue { - match self.0.contract_bounds() { - None => JsValue::undefined(), - Some(bounds) => JsValue::from(ContractBoundsWasm::from(bounds.clone())), - } + #[wasm_bindgen(getter = "contractBounds")] + pub fn contract_bounds(&self) -> Option { + self.0 + .contract_bounds() + .map(|b| ContractBoundsWasm::from(b.clone())) } #[wasm_bindgen(getter = keyId)] - pub fn get_key_id(&self) -> u32 { + pub fn key_id(&self) -> u32 { self.0.id() } #[wasm_bindgen(getter = purpose)] - pub fn get_purpose(&self) -> String { + pub fn purpose(&self) -> String { PurposeWasm::from(self.0.purpose()).into() } #[wasm_bindgen(getter = purposeNumber)] - pub fn get_purpose_number(&self) -> PurposeWasm { + pub fn purpose_number(&self) -> PurposeWasm { PurposeWasm::from(self.0.purpose()) } #[wasm_bindgen(getter = securityLevel)] - pub fn get_security_level(&self) -> String { + pub fn security_level(&self) -> String { SecurityLevelWasm::from(self.0.security_level()).into() } #[wasm_bindgen(getter = securityLevelNumber)] - pub fn get_security_level_number(&self) -> SecurityLevelWasm { + pub fn security_level_number(&self) -> SecurityLevelWasm { SecurityLevelWasm::from(self.0.security_level()) } #[wasm_bindgen(getter = keyType)] - pub fn get_key_type(&self) -> String { + pub fn key_type(&self) -> String { KeyTypeWasm::from(self.0.key_type()).into() } #[wasm_bindgen(getter = keyTypeNumber)] - pub fn get_key_type_number(&self) -> KeyTypeWasm { + pub fn key_type_number(&self) -> KeyTypeWasm { KeyTypeWasm::from(self.0.key_type()) } - #[wasm_bindgen(getter = readOnly)] - pub fn get_read_only(&self) -> bool { + #[wasm_bindgen(getter = "isReadOnly")] + pub fn is_read_only(&self) -> bool { self.0.read_only() } #[wasm_bindgen(getter = data)] - pub fn get_data(&self) -> String { + pub fn data(&self) -> String { self.0.data().to_string(Hex) } #[wasm_bindgen(getter = disabledAt)] - pub fn get_disabled_at(&self) -> Option { + pub fn disabled_at(&self) -> Option { self.0.disabled_at() } #[wasm_bindgen(setter = keyId)] - pub fn set_key_id(&mut self, key_id: u32) { - self.0.set_id(key_id) + pub fn set_key_id( + &mut self, + #[wasm_bindgen(js_name = "keyId")] key_id: JsValue, + ) -> WasmDppResult<()> { + self.0.set_id(try_to_u32(&key_id, "keyId")?); + Ok(()) } #[wasm_bindgen(setter = purpose)] - pub fn set_purpose(&mut self, purpose: JsValue) -> WasmDppResult<()> { - let purpose = PurposeWasm::try_from(purpose)?; - self.0.set_purpose(Purpose::from(purpose)); + pub fn set_purpose(&mut self, purpose: PurposeLikeJs) -> WasmDppResult<()> { + let purpose: Purpose = purpose.try_into()?; + self.0.set_purpose(purpose); Ok(()) } - #[wasm_bindgen(setter = purposeNumber)] - pub fn set_purpose_number(&mut self, purpose: JsValue) -> WasmDppResult<()> { - self.set_purpose(purpose) - } - #[wasm_bindgen(setter = securityLevel)] - pub fn set_security_level(&mut self, security_level: JsValue) -> WasmDppResult<()> { - let security_level = SecurityLevelWasm::try_from(security_level)?; - self.0 - .set_security_level(SecurityLevel::from(security_level)); + pub fn set_security_level( + &mut self, + #[wasm_bindgen(js_name = "securityLevel")] security_level: SecurityLevelLikeJs, + ) -> WasmDppResult<()> { + let security_level: SecurityLevel = security_level.try_into()?; + self.0.set_security_level(security_level); Ok(()) } - #[wasm_bindgen(setter = securityLevelNumber)] - pub fn set_security_level_number(&mut self, security_level: JsValue) -> WasmDppResult<()> { - self.set_security_level(security_level) - } - #[wasm_bindgen(setter = keyType)] - pub fn set_key_type(&mut self, key_type: JsValue) -> WasmDppResult<()> { - let key_type = KeyTypeWasm::try_from(key_type)?; - self.0.set_key_type(KeyType::from(key_type)); + pub fn set_key_type( + &mut self, + #[wasm_bindgen(js_name = "keyType")] key_type: KeyTypeLikeJs, + ) -> WasmDppResult<()> { + let key_type: KeyType = key_type.try_into()?; + self.0.set_key_type(key_type); Ok(()) } - #[wasm_bindgen(setter = keyTypeNumber)] - pub fn set_key_type_number(&mut self, key_type: JsValue) -> WasmDppResult<()> { - self.set_key_type(key_type) - } - - #[wasm_bindgen(setter = readOnly)] - pub fn set_read_only(&mut self, read_only: bool) { - self.0.set_read_only(read_only) + #[wasm_bindgen(setter = "isReadOnly")] + pub fn set_is_read_only(&mut self, #[wasm_bindgen(js_name = "isReadOnly")] is_read_only: bool) { + self.0.set_read_only(is_read_only) } #[wasm_bindgen(setter = data)] - pub fn set_data(&mut self, binary_data: &str) -> WasmDppResult<()> { + pub fn set_data( + &mut self, + #[wasm_bindgen(js_name = "binaryData")] binary_data: &str, + ) -> WasmDppResult<()> { let data = BinaryData::from_string(binary_data, Hex) .map_err(|e| WasmDppError::serialization(e.to_string()))?; @@ -234,8 +326,13 @@ impl IdentityPublicKeyWasm { } #[wasm_bindgen(setter = disabledAt)] - pub fn set_disabled_at(&mut self, disabled_at: u64) { - self.0.set_disabled_at(disabled_at) + pub fn set_disabled_at( + &mut self, + #[wasm_bindgen(js_name = "disabledAt")] disabled_at: JsValue, + ) -> WasmDppResult<()> { + self.0 + .set_disabled_at(try_to_u64(&disabled_at, "disabledAt")?); + Ok(()) } #[wasm_bindgen(js_name = "getPublicKeyHash")] @@ -249,7 +346,7 @@ impl IdentityPublicKeyWasm { Ok(hash) } - #[wasm_bindgen(js_name = "isMaster")] + #[wasm_bindgen(getter = "isMaster")] pub fn is_master(&self) -> bool { self.0.is_master() } @@ -259,24 +356,24 @@ impl IdentityPublicKeyWasm { Ok(self.0.serialize_to_bytes()?) } - #[wasm_bindgen(js_name = hex)] + #[wasm_bindgen(js_name = "hex")] pub fn to_hex(&self) -> WasmDppResult { Ok(encode(self.0.serialize_to_bytes()?.as_slice(), Hex)) } - #[wasm_bindgen(js_name = base64)] + #[wasm_bindgen(js_name = "base64")] pub fn to_base64(&self) -> WasmDppResult { Ok(encode(self.0.serialize_to_bytes()?.as_slice(), Base64)) } - #[wasm_bindgen(js_name = fromBytes)] + #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes(bytes: Vec) -> WasmDppResult { let public_key = IdentityPublicKey::deserialize_from_bytes(bytes.as_slice())?; Ok(IdentityPublicKeyWasm(public_key)) } - #[wasm_bindgen(js_name = fromHex)] + #[wasm_bindgen(js_name = "fromHex")] pub fn from_hex(hex: String) -> WasmDppResult { let bytes = decode(&hex, Hex).map_err(|err| WasmDppError::serialization(err.to_string()))?; @@ -286,7 +383,7 @@ impl IdentityPublicKeyWasm { Ok(IdentityPublicKeyWasm(public_key)) } - #[wasm_bindgen(js_name = fromBase64)] + #[wasm_bindgen(js_name = "fromBase64")] pub fn from_base64(hex: String) -> WasmDppResult { let bytes = decode(&hex, Base64).map_err(|err| WasmDppError::serialization(err.to_string()))?; @@ -301,17 +398,19 @@ impl IdentityPublicKeyWasm { /// Uses platform_value conversion which properly handles the tagged enum /// and removes None fields like disabledAt. #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self) -> WasmDppResult { + pub fn to_object(&self) -> WasmDppResult { let value = self.0.to_cleaned_object().map_err(WasmDppError::from)?; - serialization::platform_value_to_object(&value) + let js_value = serialization::platform_value_to_object(&value)?; + Ok(js_value.into()) } /// Deserialize from JS object (non-human-readable). /// /// Uses platform_value conversion which properly handles the tagged enum. #[wasm_bindgen(js_name = "fromObject")] - pub fn from_object(js_value: JsValue) -> WasmDppResult { - let platform_value = serialization::platform_value_from_object(js_value)?; + pub fn from_object(value: IdentityPublicKeyObjectJs) -> WasmDppResult { + let value: JsValue = value.into(); + let platform_value = serialization::platform_value_from_object(&value)?; let platform_version = PlatformVersion::latest(); let key = IdentityPublicKey::from_object(platform_value, platform_version) .map_err(WasmDppError::from)?; @@ -323,9 +422,10 @@ impl IdentityPublicKeyWasm { /// Uses serde_json conversion which properly handles the tagged enum /// and serializes binary data as base64 strings. #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self) -> WasmDppResult { + pub fn to_json(&self) -> WasmDppResult { let json_value = self.0.to_json_object().map_err(WasmDppError::from)?; - serialization::to_json(&json_value) + let js_value = serialization::to_json(&json_value)?; + Ok(js_value.into()) } /// Deserialize from JSON-compatible JS object (human-readable). @@ -333,8 +433,8 @@ impl IdentityPublicKeyWasm { /// Uses serde_json conversion which properly handles the tagged enum /// and deserializes base64 strings to binary data. #[wasm_bindgen(js_name = "fromJSON")] - pub fn from_json(js_value: JsValue) -> WasmDppResult { - let json_value: JsonValue = serde_from_value(js_value).map_err(|err| { + pub fn from_json(value: IdentityPublicKeyJSONJs) -> WasmDppResult { + let json_value: JsonValue = serde_from_value(value.into()).map_err(|err| { WasmDppError::serialization(format!( "IdentityPublicKey.fromJSON: unable to parse JSON: {}", err @@ -349,4 +449,6 @@ impl IdentityPublicKeyWasm { } } -impl_try_from_options!(IdentityPublicKeyWasm, "IdentityPublicKey"); +impl_try_from_js_value!(IdentityPublicKeyWasm, "IdentityPublicKey"); +impl_try_from_options!(IdentityPublicKeyWasm); +impl_wasm_type_info!(IdentityPublicKeyWasm, IdentityPublicKey); diff --git a/packages/wasm-dpp2/src/identity/signer.rs b/packages/wasm-dpp2/src/identity/signer.rs index 5019e95dc04..0add01a6c60 100644 --- a/packages/wasm-dpp2/src/identity/signer.rs +++ b/packages/wasm-dpp2/src/identity/signer.rs @@ -5,8 +5,9 @@ use crate::core::private_key::PrivateKeyWasm; use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; -use crate::utils::IntoWasm; +use crate::impl_wasm_type_info; use dpp::ProtocolError; use dpp::address_funds::{AddressWitness, PlatformAddress}; use dpp::dashcore::hashes::Hash; @@ -45,19 +46,9 @@ fn hash160(pubkey: &[u8]) -> [u8; 20] { #[wasm_bindgen(js_class = IdentitySigner)] impl IdentitySignerWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentitySigner".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentitySigner".to_string() - } - /// Creates a new empty IdentitySigner. #[wasm_bindgen(constructor)] - pub fn new() -> IdentitySignerWasm { + pub fn constructor() -> IdentitySignerWasm { IdentitySignerWasm { private_keys: BTreeMap::new(), } @@ -69,7 +60,10 @@ impl IdentitySignerWasm { /// /// @param privateKey - The PrivateKey object #[wasm_bindgen(js_name = "addKey")] - pub fn add_key(&mut self, private_key: &PrivateKeyWasm) -> WasmDppResult<()> { + pub fn add_key( + &mut self, + #[wasm_bindgen(js_name = "privateKey")] private_key: &PrivateKeyWasm, + ) -> WasmDppResult<()> { let private_key_bytes: [u8; 32] = private_key .to_bytes() .try_into() @@ -188,15 +182,6 @@ impl IdentitySignerWasm { } } -impl_try_from_options!(IdentitySignerWasm, "IdentitySigner", "signer"); - -impl TryFrom<&JsValue> for IdentitySignerWasm { - type Error = WasmDppError; - - fn try_from(value: &JsValue) -> Result { - value - .to_wasm::("IdentitySigner") - .map(|boxed| (*boxed).clone()) - .map_err(|_| WasmDppError::invalid_argument("Expected an IdentitySigner object")) - } -} +impl_try_from_js_value!(IdentitySignerWasm, "IdentitySigner"); +impl_try_from_options!(IdentitySignerWasm); +impl_wasm_type_info!(IdentitySignerWasm, IdentitySigner); diff --git a/packages/wasm-dpp2/src/identity/transitions/create_transition.rs b/packages/wasm-dpp2/src/identity/transitions/create_transition.rs index 98dde450bc4..b9fb8e572ff 100644 --- a/packages/wasm-dpp2/src/identity/transitions/create_transition.rs +++ b/packages/wasm-dpp2/src/identity/transitions/create_transition.rs @@ -1,10 +1,12 @@ use crate::asset_lock_proof::AssetLockProofWasm; -use crate::enums::platform::PlatformVersionWasm; use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; use crate::identity::transitions::public_key_in_creation::IdentityPublicKeyInCreationWasm; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; +use crate::utils::{try_from_options, try_from_options_with, try_to_array, try_to_u16}; +use crate::version::{PlatformVersionLikeJs, PlatformVersionWasm}; use dpp::identity::state_transition::AssetLockProved; use dpp::platform_value::BinaryData; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; @@ -16,9 +18,61 @@ use dpp::state_transition::identity_create_transition::accessors::IdentityCreate use dpp::state_transition::identity_create_transition::v0::IdentityCreateTransitionV0; use dpp::state_transition::public_key_in_creation::IdentityPublicKeyInCreation; use dpp::state_transition::{StateTransition, StateTransitionLike, StateTransitionSingleSigned}; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IdentityCreateTransitionOptions { + #[serde(default)] + signature: Option>, + #[serde(default)] + user_fee_increase: Option, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface IdentityCreateTransitionOptions { + publicKeys: IdentityPublicKeyInCreation[]; + assetLockProof: AssetLockProof; + signature?: Uint8Array; + userFeeIncrease?: number; +} + +/** + * IdentityCreateTransition serialized as a plain object. + */ +export interface IdentityCreateTransitionObject { + publicKeys: IdentityPublicKeyInCreationObject[]; + assetLockProof: AssetLockProofObject; + signature?: Uint8Array; + userFeeIncrease: number; +} + +/** + * IdentityCreateTransition serialized as JSON. + */ +export interface IdentityCreateTransitionJSON { + publicKeys: IdentityPublicKeyInCreationJSON[]; + assetLockProof: AssetLockProofJSON; + signature?: string; + userFeeIncrease: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityCreateTransitionOptions")] + pub type IdentityCreateTransitionOptionsJs; + + #[wasm_bindgen(typescript_type = "IdentityCreateTransitionObject")] + pub type IdentityCreateTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityCreateTransitionJSON")] + pub type IdentityCreateTransitionJSONJs; +} + #[wasm_bindgen(js_name = "IdentityCreateTransition")] #[derive(Clone)] pub struct IdentityCreateTransitionWasm(IdentityCreateTransition); @@ -37,40 +91,39 @@ impl From for IdentityCreateTransition { #[wasm_bindgen(js_class = IdentityCreateTransition)] impl IdentityCreateTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentityCreateTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentityCreateTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - js_public_keys: &js_sys::Array, - asset_lock: &AssetLockProofWasm, - signature: Option>, - user_fee_increase: Option, + pub fn constructor( + options: IdentityCreateTransitionOptionsJs, ) -> WasmDppResult { + // Extract publicKeys (required array) + let js_public_keys_array = + try_from_options_with(&options, "publicKeys", |v| try_to_array(v, "publicKeys"))?; let public_keys: Vec = - IdentityPublicKeyInCreationWasm::vec_from_js_value(js_public_keys)?; + IdentityPublicKeyInCreationWasm::vec_from_array(&js_public_keys_array)?; + + // Extract assetLockProof (required) + let asset_lock: AssetLockProofWasm = try_from_options(&options, "assetLockProof")?; + + // Extract simple fields via serde + let opts: IdentityCreateTransitionOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(IdentityCreateTransitionWasm(IdentityCreateTransition::V0( IdentityCreateTransitionV0 { public_keys: public_keys.iter().map(|key| key.clone().into()).collect(), asset_lock_proof: asset_lock.clone().into(), - user_fee_increase: user_fee_increase.unwrap_or(0), - signature: BinaryData::from(signature.unwrap_or_default()), + user_fee_increase: opts.user_fee_increase.unwrap_or(0), + signature: BinaryData::from(opts.signature.unwrap_or_default()), identity_id: asset_lock.create_identifier()?.into(), }, ))) } #[wasm_bindgen(js_name = "default")] - pub fn default(js_platform_version: JsValue) -> WasmDppResult { - let platform_version = PlatformVersionWasm::try_from(js_platform_version)?; + pub fn default( + #[wasm_bindgen(js_name = "platformVersion")] platform_version: PlatformVersionLikeJs, + ) -> WasmDppResult { + let platform_version = PlatformVersionWasm::try_from(platform_version)?; IdentityCreateTransition::default_versioned(&platform_version.into()) .map_err(|err| WasmDppError::generic(err.to_string())) @@ -106,7 +159,7 @@ impl IdentityCreateTransitionWasm { } #[wasm_bindgen(getter = "publicKeys")] - pub fn get_public_keys(&self) -> Vec { + pub fn public_keys(&self) -> Vec { self.0 .public_keys() .iter() @@ -114,18 +167,18 @@ impl IdentityCreateTransitionWasm { .collect() } - #[wasm_bindgen(js_name = "getIdentifier")] - pub fn get_identity_id(&self) -> IdentifierWasm { + #[wasm_bindgen(getter = "identityId")] + pub fn identity_id(&self) -> IdentifierWasm { self.0.identity_id().into() } #[wasm_bindgen(getter = "userFeeIncrease")] - pub fn get_user_fee_increase(&self) -> u16 { + pub fn user_fee_increase(&self) -> u16 { self.0.user_fee_increase() } #[wasm_bindgen(getter = "signature")] - pub fn get_signature(&self) -> Vec { + pub fn signature(&self) -> Vec { self.0.signature().to_vec() } @@ -134,18 +187,21 @@ impl IdentityCreateTransitionWasm { Ok(self.0.signable_bytes()?) } - #[wasm_bindgen(getter = "assetLock")] - pub fn get_asset_lock_proof(&self) -> AssetLockProofWasm { + #[wasm_bindgen(getter = "assetLockProof")] + pub fn asset_lock_proof(&self) -> AssetLockProofWasm { AssetLockProofWasm::from(self.0.asset_lock_proof().clone()) } #[wasm_bindgen(setter = "publicKeys")] - pub fn set_public_keys(&mut self, js_public_keys: &js_sys::Array) -> WasmDppResult<()> { - let public_keys: Vec = - IdentityPublicKeyInCreationWasm::vec_from_js_value(js_public_keys)?; + pub fn set_public_keys( + &mut self, + #[wasm_bindgen(js_name = "publicKeys")] public_keys: &js_sys::Array, + ) -> WasmDppResult<()> { + let public_keys_vec: Vec = + IdentityPublicKeyInCreationWasm::vec_from_array(public_keys)?; self.0.set_public_keys( - public_keys + public_keys_vec .iter() .map(|key| IdentityPublicKeyInCreation::from(key.clone())) .collect(), @@ -155,8 +211,10 @@ impl IdentityCreateTransitionWasm { } #[wasm_bindgen(setter = "userFeeIncrease")] - pub fn set_user_fee_increase(&mut self, amount: u16) { - self.0.set_user_fee_increase(amount) + pub fn set_user_fee_increase(&mut self, amount: JsValue) -> WasmDppResult<()> { + self.0 + .set_user_fee_increase(try_to_u16(&amount, "userFeeIncrease")?); + Ok(()) } #[wasm_bindgen(setter = "signature")] @@ -164,7 +222,7 @@ impl IdentityCreateTransitionWasm { self.0.set_signature_bytes(signature) } - #[wasm_bindgen(setter = "assetLock")] + #[wasm_bindgen(setter = "assetLockProof")] pub fn set_asset_lock_proof(&mut self, proof: AssetLockProofWasm) -> WasmDppResult<()> { self.0.set_asset_lock_proof(proof.into())?; Ok(()) @@ -200,4 +258,10 @@ impl IdentityCreateTransitionWasm { } } -impl_wasm_conversions!(IdentityCreateTransitionWasm, IdentityCreateTransition); +impl_wasm_conversions!( + IdentityCreateTransitionWasm, + IdentityCreateTransition, + IdentityCreateTransitionObjectJs, + IdentityCreateTransitionJSONJs +); +impl_wasm_type_info!(IdentityCreateTransitionWasm, IdentityCreateTransition); diff --git a/packages/wasm-dpp2/src/identity/transitions/credit_withdrawal_transition.rs b/packages/wasm-dpp2/src/identity/transitions/credit_withdrawal_transition.rs index ecc3963654f..7a65d780bea 100644 --- a/packages/wasm-dpp2/src/identity/transitions/credit_withdrawal_transition.rs +++ b/packages/wasm-dpp2/src/identity/transitions/credit_withdrawal_transition.rs @@ -1,16 +1,17 @@ -use super::pooling::PoolingWasm; +use super::pooling::{PoolingLikeJs, PoolingWasm}; use crate::asset_lock_proof::AssetLockProofWasm; use crate::core::core_script::CoreScriptWasm; use crate::enums::keys::purpose::PurposeWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; -use crate::utils::IntoWasm; +use crate::utils::{ + try_from_options, try_from_options_optional, try_to_u16, try_to_u32, try_to_u64, +}; use dpp::identity::KeyID; -use dpp::identity::core_script::CoreScript; use dpp::identity::state_transition::OptionallyAssetLockProved; -use dpp::platform_value::Identifier; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::{decode, encode}; use dpp::prelude::{IdentityNonce, UserFeeIncrease}; @@ -22,57 +23,110 @@ use dpp::state_transition::{ StateTransition, StateTransitionIdentitySigned, StateTransitionLike, StateTransitionSingleSigned, }; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const CREDIT_WITHDRAWAL_OPTIONS_TS: &str = r#" +export type CreditWithdrawalTransitionPoolingLike = CreditWithdrawalTransitionPooling | string | number; + +export interface IdentityCreditWithdrawalTransitionOptions { + identityId: IdentifierLike; + amount: bigint; + coreFeePerByte: number; + pooling: CreditWithdrawalTransitionPoolingLike; + outputScript?: CoreScript; + nonce?: bigint; + userFeeIncrease?: number; +} + +/** + * IdentityCreditWithdrawalTransition serialized as a plain object. + */ +export interface IdentityCreditWithdrawalTransitionObject { + identityId: Uint8Array; + amount: bigint; + coreFeePerByte: number; + pooling: CreditWithdrawalTransitionPooling; + outputScript?: Uint8Array; + nonce: bigint; + userFeeIncrease: number; + signature?: Uint8Array; + signaturePublicKeyId?: number; +} + +/** + * IdentityCreditWithdrawalTransition serialized as JSON. + */ +export interface IdentityCreditWithdrawalTransitionJSON { + identityId: string; + amount: string; + coreFeePerByte: number; + pooling: string; + outputScript?: string; + nonce: string; + userFeeIncrease: number; + signature?: string; + signaturePublicKeyId?: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityCreditWithdrawalTransitionOptions")] + pub type IdentityCreditWithdrawalTransitionOptionsJs; + + #[wasm_bindgen(typescript_type = "IdentityCreditWithdrawalTransitionObject")] + pub type IdentityCreditWithdrawalTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityCreditWithdrawalTransitionJSON")] + pub type IdentityCreditWithdrawalTransitionJSONJs; +} + +/// Serde struct for IdentityCreditWithdrawalTransitionOptions (primitives only) +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IdentityCreditWithdrawalTransitionOptionsInput { + amount: u64, + core_fee_per_byte: u32, + #[serde(default)] + nonce: IdentityNonce, + #[serde(default)] + user_fee_increase: UserFeeIncrease, +} + #[wasm_bindgen(js_name = "IdentityCreditWithdrawalTransition")] pub struct IdentityCreditWithdrawalTransitionWasm(IdentityCreditWithdrawalTransition); #[wasm_bindgen(js_class = IdentityCreditWithdrawalTransition)] impl IdentityCreditWithdrawalTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentityCreditWithdrawalTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentityCreditWithdrawalTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: JsValue, - amount: u64, - core_fee_per_byte: u32, - js_pooling: JsValue, - js_output_script: &JsValue, - nonce: Option, - user_fee_increase: Option, + pub fn constructor( + options: IdentityCreditWithdrawalTransitionOptionsJs, ) -> WasmDppResult { - let pooling = PoolingWasm::try_from(js_pooling)?; - let identity_id: Identifier = IdentifierWasm::try_from(&js_identity_id)?.into(); - - let output_script: Option = match js_output_script.is_undefined() { - true => None, - false => Some( - js_output_script - .to_wasm::("CoreScript")? - .clone() - .into(), - ), - }; + // Extract complex types first (borrows &options) + let identity_id: IdentifierWasm = try_from_options(&options, "identityId")?; + + let pooling: PoolingWasm = PoolingWasm::try_from_options(&options, "pooling")?; + + let output_script: Option = + try_from_options_optional(&options, "outputScript")?; + + // Deserialize primitive fields via serde last (consumes options) + let input: IdentityCreditWithdrawalTransitionOptionsInput = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(IdentityCreditWithdrawalTransitionWasm( IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { - amount, - identity_id, - output_script, - core_fee_per_byte, + amount: input.amount, + identity_id: identity_id.into(), + output_script: output_script.map(Into::into), + core_fee_per_byte: input.core_fee_per_byte, pooling: pooling.into(), - nonce: nonce.unwrap_or(0), - user_fee_increase: user_fee_increase.unwrap_or(0), + nonce: input.nonce, + user_fee_increase: input.user_fee_increase, signature_public_key_id: 0, signature: Default::default(), }), @@ -80,37 +134,37 @@ impl IdentityCreditWithdrawalTransitionWasm { } #[wasm_bindgen(getter = "outputScript")] - pub fn get_output_script(&self) -> Option { + pub fn output_script(&self) -> Option { self.0.output_script().map(|script| script.into()) } #[wasm_bindgen(getter = "pooling")] - pub fn get_pooling(&self) -> String { + pub fn pooling(&self) -> String { PoolingWasm::from(self.0.pooling()).into() } #[wasm_bindgen(getter = "identityId")] - pub fn get_identity_id(&self) -> IdentifierWasm { + pub fn identity_id(&self) -> IdentifierWasm { IdentifierWasm::from(self.0.identity_id()) } #[wasm_bindgen(getter = "userFeeIncrease")] - pub fn get_user_fee_increase(&self) -> UserFeeIncrease { + pub fn user_fee_increase(&self) -> UserFeeIncrease { self.0.user_fee_increase() } #[wasm_bindgen(getter = "nonce")] - pub fn get_nonce(&self) -> IdentityNonce { + pub fn nonce(&self) -> IdentityNonce { self.0.nonce() } #[wasm_bindgen(getter = "amount")] - pub fn get_amount(&self) -> u64 { + pub fn amount(&self) -> u64 { self.0.amount() } - #[wasm_bindgen(js_name = "getPurposeRequirement")] - pub fn get_purpose_requirement(&self) -> Vec { + #[wasm_bindgen(getter = "purposeRequirement")] + pub fn purpose_requirement(&self) -> Vec { self.0 .purpose_requirement() .iter() @@ -118,8 +172,8 @@ impl IdentityCreditWithdrawalTransitionWasm { .collect() } - #[wasm_bindgen(js_name = "getModifiedDataIds")] - pub fn get_modified_data_ids(&self) -> Vec { + #[wasm_bindgen(getter = "modifiedDataIds")] + pub fn modified_data_ids(&self) -> Vec { self.0 .modified_data_ids() .iter() @@ -127,72 +181,83 @@ impl IdentityCreditWithdrawalTransitionWasm { .collect() } - #[wasm_bindgen(js_name = "getOptionalAssetLockProof")] - pub fn get_optional_asset_lock_proof(&self) -> JsValue { - match self.0.optional_asset_lock_proof() { - Some(asset_lock) => JsValue::from(AssetLockProofWasm::from(asset_lock.clone())), - None => JsValue::null(), - } + #[wasm_bindgen(getter = "optionalAssetLockProof")] + pub fn optional_asset_lock_proof(&self) -> Option { + self.0 + .optional_asset_lock_proof() + .map(|asset_lock| AssetLockProofWasm::from(asset_lock.clone())) } #[wasm_bindgen(setter = "outputScript")] - pub fn set_output_script(&mut self, js_script: &JsValue) -> WasmDppResult<()> { - if js_script.is_undefined() { + pub fn set_output_script( + &mut self, + #[wasm_bindgen(unchecked_param_type = "CoreScript | undefined")] script: &JsValue, + ) -> WasmDppResult<()> { + if script.is_undefined() { self.0.set_output_script(None); } else { - let script: CoreScriptWasm = js_script.to_wasm::("CoreScript")?.clone(); - self.0.set_output_script(Some(script.clone().into())); + let script = CoreScriptWasm::try_from(script)?; + self.0.set_output_script(Some(script.into())); } Ok(()) } #[wasm_bindgen(setter = "pooling")] - pub fn set_pooling(&mut self, js_pooling: JsValue) -> WasmDppResult<()> { - let pooling: PoolingWasm = PoolingWasm::try_from(js_pooling)?; - self.0.set_pooling(pooling.into()); + pub fn set_pooling(&mut self, pooling: PoolingLikeJs) -> WasmDppResult<()> { + let pooling: dpp::withdrawal::Pooling = pooling.try_into()?; + self.0.set_pooling(pooling); Ok(()) } #[wasm_bindgen(setter = "identityId")] pub fn set_identity_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let identity_id = IdentifierWasm::try_from(&js_identity_id)?.into(); - - self.0.set_identity_id(identity_id); + self.0.set_identity_id(identity_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "userFeeIncrease")] - pub fn set_user_fee_increase(&mut self, user_fee_increase: UserFeeIncrease) { - self.0.set_user_fee_increase(user_fee_increase); + pub fn set_user_fee_increase( + &mut self, + #[wasm_bindgen(js_name = "userFeeIncrease")] user_fee_increase: &js_sys::Number, + ) -> WasmDppResult<()> { + self.0 + .set_user_fee_increase(try_to_u16(user_fee_increase, "userFeeIncrease")?); + Ok(()) } #[wasm_bindgen(setter = "nonce")] - pub fn set_nonce(&mut self, nonce: IdentityNonce) { - self.0.set_nonce(nonce) + pub fn set_nonce(&mut self, nonce: &js_sys::BigInt) -> WasmDppResult<()> { + self.0.set_nonce(try_to_u64(nonce, "nonce")?); + Ok(()) } #[wasm_bindgen(setter = "amount")] - pub fn set_amount(&mut self, amount: u64) { - self.0.set_amount(amount) + pub fn set_amount(&mut self, amount: &js_sys::BigInt) -> WasmDppResult<()> { + self.0.set_amount(try_to_u64(amount, "amount")?); + Ok(()) } #[wasm_bindgen(setter = "coreFeePerByte")] - pub fn set_core_fee_per_byte(&mut self, fee_per_byte: u32) { - self.0.set_core_fee_per_byte(fee_per_byte) + pub fn set_core_fee_per_byte( + &mut self, + #[wasm_bindgen(js_name = "coreFeePerByte")] core_fee_per_byte: &js_sys::Number, + ) -> WasmDppResult<()> { + self.0 + .set_core_fee_per_byte(try_to_u32(core_fee_per_byte, "coreFeePerByte")?); + Ok(()) } #[wasm_bindgen(getter = "signature")] - pub fn get_signature(&self) -> Vec { + pub fn signature(&self) -> Vec { self.0.signature().to_vec() } #[wasm_bindgen(getter = "coreFeePerByte")] - pub fn get_core_fee_per_byte(&self) -> u32 { + pub fn core_fee_per_byte(&self) -> u32 { self.0.core_fee_per_byte() } @@ -202,7 +267,7 @@ impl IdentityCreditWithdrawalTransitionWasm { } #[wasm_bindgen(getter = "signaturePublicKeyId")] - pub fn get_signature_public_key_id(&self) -> KeyID { + pub fn signature_public_key_id(&self) -> KeyID { self.0.signature_public_key_id() } @@ -212,7 +277,10 @@ impl IdentityCreditWithdrawalTransitionWasm { } #[wasm_bindgen(setter = "signaturePublicKeyId")] - pub fn set_signature_public_key_id(&mut self, signature_public_key_id: KeyID) { + pub fn set_signature_public_key_id( + &mut self, + #[wasm_bindgen(js_name = "signaturePublicKeyId")] signature_public_key_id: KeyID, + ) { self.0.set_signature_public_key_id(signature_public_key_id) } @@ -280,6 +348,13 @@ impl IdentityCreditWithdrawalTransitionWasm { } impl_wasm_conversions!( + IdentityCreditWithdrawalTransitionWasm, + IdentityCreditWithdrawalTransition, + IdentityCreditWithdrawalTransitionObjectJs, + IdentityCreditWithdrawalTransitionJSONJs +); + +impl_wasm_type_info!( IdentityCreditWithdrawalTransitionWasm, IdentityCreditWithdrawalTransition ); diff --git a/packages/wasm-dpp2/src/identity/transitions/identity_credit_transfer_transition.rs b/packages/wasm-dpp2/src/identity/transitions/identity_credit_transfer_transition.rs index 40e153e0463..be628c25490 100644 --- a/packages/wasm-dpp2/src/identity/transitions/identity_credit_transfer_transition.rs +++ b/packages/wasm-dpp2/src/identity/transitions/identity_credit_transfer_transition.rs @@ -1,11 +1,13 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; +use crate::utils::{try_from_options, try_to_u16, try_to_u32, try_to_u64}; use dpp::platform_value::BinaryData; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::{decode, encode}; -use dpp::prelude::{Identifier, UserFeeIncrease}; +use dpp::prelude::UserFeeIncrease; use dpp::serialization::{PlatformDeserializable, PlatformSerializable, Signable}; use dpp::state_transition::identity_credit_transfer_transition::IdentityCreditTransferTransition; use dpp::state_transition::identity_credit_transfer_transition::accessors::IdentityCreditTransferTransitionAccessorsV0; @@ -14,45 +16,94 @@ use dpp::state_transition::{ StateTransition, StateTransitionIdentitySigned, StateTransitionLike, StateTransitionSingleSigned, }; -use wasm_bindgen::JsValue; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; -#[wasm_bindgen(js_name = IdentityCreditTransfer)] +#[wasm_bindgen(typescript_custom_section)] +const CREDIT_TRANSFER_OPTIONS_TS: &str = r#" +export interface IdentityCreditTransferOptions { + amount: bigint; + senderId: IdentifierLike; + recipientId: IdentifierLike; + nonce: bigint; + userFeeIncrease?: number; +} + +/** + * IdentityCreditTransfer serialized as a plain object. + */ +export interface IdentityCreditTransferObject { + amount: bigint; + senderId: Uint8Array; + recipientId: Uint8Array; + nonce: bigint; + userFeeIncrease: number; + signature?: Uint8Array; + signaturePublicKeyId?: number; +} + +/** + * IdentityCreditTransfer serialized as JSON. + */ +export interface IdentityCreditTransferJSON { + amount: string; + senderId: string; + recipientId: string; + nonce: string; + userFeeIncrease: number; + signature?: string; + signaturePublicKeyId?: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityCreditTransferOptions")] + pub type IdentityCreditTransferOptionsJs; + + #[wasm_bindgen(typescript_type = "IdentityCreditTransferObject")] + pub type IdentityCreditTransferObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityCreditTransferJSON")] + pub type IdentityCreditTransferJSONJs; +} + +/// Serde struct for IdentityCreditTransferOptions (primitives only) +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IdentityCreditTransferOptionsInput { + amount: u64, + nonce: u64, + #[serde(default)] + user_fee_increase: UserFeeIncrease, +} + +#[wasm_bindgen(js_name = "IdentityCreditTransfer")] #[derive(Clone)] pub struct IdentityCreditTransferWasm(IdentityCreditTransferTransition); #[wasm_bindgen(js_class = IdentityCreditTransfer)] impl IdentityCreditTransferWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentityCreditTransfer".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentityCreditTransfer".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - amount: u64, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_sender: &JsValue, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_recipient: &JsValue, - nonce: u64, - user_fee_increase: Option, + pub fn constructor( + options: IdentityCreditTransferOptionsJs, ) -> WasmDppResult { - let sender: Identifier = IdentifierWasm::try_from(js_sender)?.into(); - let recipient: Identifier = IdentifierWasm::try_from(js_recipient)?.into(); + // Extract complex types first (borrows &options) + let sender_id: IdentifierWasm = try_from_options(&options, "senderId")?; + let recipient_id: IdentifierWasm = try_from_options(&options, "recipientId")?; + + // Deserialize primitive fields via serde last (consumes options) + let input: IdentityCreditTransferOptionsInput = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(IdentityCreditTransferWasm( IdentityCreditTransferTransition::V0(IdentityCreditTransferTransitionV0 { - identity_id: sender, - recipient_id: recipient, - amount, - nonce, - user_fee_increase: user_fee_increase.unwrap_or(0), + identity_id: sender_id.into(), + recipient_id: recipient_id.into(), + amount: input.amount, + nonce: input.nonce, + user_fee_increase: input.user_fee_increase, signature_public_key_id: 0, signature: Default::default(), }), @@ -99,37 +150,27 @@ impl IdentityCreditTransferWasm { } #[wasm_bindgen(setter = "recipientId")] - pub fn set_recipient_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_recipient: &JsValue, - ) -> WasmDppResult<()> { - let recipient: Identifier = IdentifierWasm::try_from(js_recipient)?.into(); - - self.0.set_recipient_id(recipient); + pub fn set_recipient_id(&mut self, recipient: IdentifierLikeJs) -> WasmDppResult<()> { + self.0.set_recipient_id(recipient.try_into()?); Ok(()) } #[wasm_bindgen(setter = "senderId")] - pub fn set_sender_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_sender: &JsValue, - ) -> WasmDppResult<()> { - let sender: Identifier = IdentifierWasm::try_from(js_sender)?.into(); - - self.0.set_identity_id(sender); + pub fn set_sender_id(&mut self, sender: IdentifierLikeJs) -> WasmDppResult<()> { + self.0.set_identity_id(sender.try_into()?); Ok(()) } #[wasm_bindgen(setter = "amount")] - pub fn set_amount(&mut self, amount: u64) { - self.0.set_amount(amount) + pub fn set_amount(&mut self, amount: &js_sys::BigInt) -> WasmDppResult<()> { + self.0.set_amount(try_to_u64(amount, "amount")?); + Ok(()) } #[wasm_bindgen(setter = "nonce")] - pub fn set_nonce(&mut self, nonce: u64) { - self.0.set_nonce(nonce) + pub fn set_nonce(&mut self, nonce: &js_sys::BigInt) -> WasmDppResult<()> { + self.0.set_nonce(try_to_u64(nonce, "nonce")?); + Ok(()) } #[wasm_bindgen(setter = "signature")] @@ -138,17 +179,24 @@ impl IdentityCreditTransferWasm { } #[wasm_bindgen(setter = "signaturePublicKeyId")] - pub fn set_signature_public_key_id(&mut self, public_key_id: u32) { - self.0.set_signature_public_key_id(public_key_id) + pub fn set_signature_public_key_id( + &mut self, + #[wasm_bindgen(js_name = "publicKeyId")] public_key_id: &js_sys::Number, + ) -> WasmDppResult<()> { + self.0 + .set_signature_public_key_id(try_to_u32(public_key_id, "signaturePublicKeyId")?); + Ok(()) } #[wasm_bindgen(setter = "userFeeIncrease")] - pub fn set_user_fee_increase(&mut self, amount: u16) { - self.0.set_user_fee_increase(amount) + pub fn set_user_fee_increase(&mut self, amount: &js_sys::Number) -> WasmDppResult<()> { + self.0 + .set_user_fee_increase(try_to_u16(amount, "userFeeIncrease")?); + Ok(()) } #[wasm_bindgen(getter = "signature")] - pub fn get_signature(&self) -> Vec { + pub fn signature(&self) -> Vec { self.0.signature().to_vec() } @@ -158,32 +206,32 @@ impl IdentityCreditTransferWasm { } #[wasm_bindgen(getter = "signaturePublicKeyId")] - pub fn get_signature_public_key_id(&self) -> u32 { + pub fn signature_public_key_id(&self) -> u32 { self.0.signature_public_key_id() } #[wasm_bindgen(getter = "userFeeIncrease")] - pub fn get_user_fee_increase(&self) -> u16 { + pub fn user_fee_increase(&self) -> u16 { self.0.user_fee_increase() } #[wasm_bindgen(getter = "recipientId")] - pub fn get_recipient_id(&self) -> IdentifierWasm { + pub fn recipient_id(&self) -> IdentifierWasm { self.0.recipient_id().into() } #[wasm_bindgen(getter = "senderId")] - pub fn get_identity_id(&self) -> IdentifierWasm { + pub fn sender_id(&self) -> IdentifierWasm { self.0.identity_id().into() } #[wasm_bindgen(getter = "amount")] - pub fn get_amount(&self) -> u64 { + pub fn amount(&self) -> u64 { self.0.amount() } #[wasm_bindgen(getter = "nonce")] - pub fn get_nonce(&self) -> u64 { + pub fn nonce(&self) -> u64 { self.0.nonce() } @@ -213,4 +261,11 @@ impl IdentityCreditTransferWasm { } } -impl_wasm_conversions!(IdentityCreditTransferWasm, IdentityCreditTransferTransition); +impl_wasm_conversions!( + IdentityCreditTransferWasm, + IdentityCreditTransferTransition, + IdentityCreditTransferObjectJs, + IdentityCreditTransferJSONJs +); + +impl_wasm_type_info!(IdentityCreditTransferWasm, IdentityCreditTransfer); diff --git a/packages/wasm-dpp2/src/identity/transitions/masternode_vote_transition.rs b/packages/wasm-dpp2/src/identity/transitions/masternode_vote_transition.rs index 07ca5dfb8b9..55ae8d70de4 100644 --- a/packages/wasm-dpp2/src/identity/transitions/masternode_vote_transition.rs +++ b/packages/wasm-dpp2/src/identity/transitions/masternode_vote_transition.rs @@ -1,9 +1,11 @@ use crate::VoteWasm; use crate::asset_lock_proof::AssetLockProofWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; +use crate::utils::{try_from_options, try_to_u16, try_to_u32, try_to_u64}; use dpp::identity::KeyID; use dpp::identity::state_transition::OptionallyAssetLockProved; use dpp::platform_value::BinaryData; @@ -18,9 +20,69 @@ use dpp::state_transition::{ StateTransition, StateTransitionIdentitySigned, StateTransitionLike, StateTransitionSingleSigned, }; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const MASTERNODE_VOTE_OPTIONS_TS: &str = r#" +export interface MasternodeVoteTransitionOptions { + proTxHash: IdentifierLike; + voterIdentityId: IdentifierLike; + vote: Vote; + nonce: bigint; + signaturePublicKeyId?: number; + signature?: Uint8Array; +} + +/** + * MasternodeVoteTransition serialized as a plain object. + */ +export interface MasternodeVoteTransitionObject { + proTxHash: Uint8Array; + voterIdentityId: Uint8Array; + vote: VoteObject; + nonce: bigint; + signaturePublicKeyId?: number; + signature?: Uint8Array; +} + +/** + * MasternodeVoteTransition serialized as JSON. + */ +export interface MasternodeVoteTransitionJSON { + proTxHash: string; + voterIdentityId: string; + vote: VoteJSON; + nonce: string; + signaturePublicKeyId?: number; + signature?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "MasternodeVoteTransitionOptions")] + pub type MasternodeVoteTransitionOptionsJs; + + #[wasm_bindgen(typescript_type = "MasternodeVoteTransitionObject")] + pub type MasternodeVoteTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "MasternodeVoteTransitionJSON")] + pub type MasternodeVoteTransitionJSONJs; +} + +/// Serde struct for MasternodeVoteTransitionOptions (primitives only) +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct MasternodeVoteTransitionOptionsInput { + nonce: IdentityNonce, + #[serde(default)] + signature_public_key_id: KeyID, + #[serde(default)] + signature: Vec, +} + #[wasm_bindgen(js_name = "MasternodeVoteTransition")] #[derive(Clone)] pub struct MasternodeVoteTransitionWasm(MasternodeVoteTransition); @@ -39,38 +101,29 @@ impl From for MasternodeVoteTransition { #[wasm_bindgen(js_class = MasternodeVoteTransition)] impl MasternodeVoteTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "MasternodeVoteTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "MasternodeVoteTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_pro_tx_hash: &JsValue, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_voter_identity_id: &JsValue, - vote: &VoteWasm, - nonce: IdentityNonce, - signature_public_key: Option, - signature: Option>, + pub fn constructor( + options: MasternodeVoteTransitionOptionsJs, ) -> WasmDppResult { - let pro_tx_hash = IdentifierWasm::try_from(js_pro_tx_hash)?.into(); - let voter_identity_id = IdentifierWasm::try_from(js_voter_identity_id)?.into(); + // Extract complex types first (borrows &options) + let pro_tx_hash: IdentifierWasm = try_from_options(&options, "proTxHash")?; + let voter_identity_id: IdentifierWasm = try_from_options(&options, "voterIdentityId")?; + + let vote: VoteWasm = try_from_options(&options, "vote")?; + + // Deserialize primitive fields via serde last (consumes options) + let input: MasternodeVoteTransitionOptionsInput = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(MasternodeVoteTransitionWasm(MasternodeVoteTransition::V0( MasternodeVoteTransitionV0 { - pro_tx_hash, - voter_identity_id, - vote: vote.clone().into(), - nonce, - signature_public_key_id: signature_public_key.unwrap_or(0), - signature: BinaryData::from(signature.unwrap_or_default()), + pro_tx_hash: pro_tx_hash.into(), + voter_identity_id: voter_identity_id.into(), + vote: vote.into(), + nonce: input.nonce, + signature_public_key_id: input.signature_public_key_id, + signature: BinaryData::from(input.signature), }, ))) } @@ -108,26 +161,18 @@ impl MasternodeVoteTransitionWasm { #[wasm_bindgen(setter = proTxHash)] pub fn set_pro_tx_hash( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_pro_tx_hash: &JsValue, + #[wasm_bindgen(js_name = "proTxHash")] pro_tx_hash: IdentifierLikeJs, ) -> WasmDppResult<()> { - let pro_tx_hash = IdentifierWasm::try_from(js_pro_tx_hash)?.into(); - - self.0.set_pro_tx_hash(pro_tx_hash); - + self.0.set_pro_tx_hash(pro_tx_hash.try_into()?); Ok(()) } #[wasm_bindgen(setter = voterIdentityId)] pub fn set_voter_identity_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_voter_identity_id: &JsValue, + #[wasm_bindgen(js_name = "voterIdentityId")] voter_identity_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let voter_identity_id = IdentifierWasm::try_from(js_voter_identity_id)?.into(); - - self.0.set_voter_identity_id(voter_identity_id); - + self.0.set_voter_identity_id(voter_identity_id.try_into()?); Ok(()) } @@ -137,19 +182,28 @@ impl MasternodeVoteTransitionWasm { } #[wasm_bindgen(setter = nonce)] - pub fn set_nonce(&mut self, nonce: IdentityNonce) { + pub fn set_nonce(&mut self, nonce: JsValue) -> WasmDppResult<()> { + let nonce = try_to_u64(&nonce, "nonce")?; self.0 = match self.0.clone() { MasternodeVoteTransition::V0(mut vote) => { vote.nonce = nonce; MasternodeVoteTransition::V0(vote) } - } + }; + Ok(()) } #[wasm_bindgen(setter=signaturePublicKeyId)] - pub fn set_signature_public_key_id(&mut self, signature_public_key_id: KeyID) { - self.0.set_signature_public_key_id(signature_public_key_id) + pub fn set_signature_public_key_id( + &mut self, + #[wasm_bindgen(js_name = "signaturePublicKeyId")] signature_public_key_id: JsValue, + ) -> WasmDppResult<()> { + self.0.set_signature_public_key_id(try_to_u32( + &signature_public_key_id, + "signaturePublicKeyId", + )?); + Ok(()) } #[wasm_bindgen(setter=signature)] @@ -186,7 +240,7 @@ impl MasternodeVoteTransitionWasm { } #[wasm_bindgen(getter = "userFeeIncrease")] - pub fn get_user_fee_increase(&self) -> u16 { + pub fn user_fee_increase(&self) -> u16 { self.0.user_fee_increase() } @@ -195,20 +249,22 @@ impl MasternodeVoteTransitionWasm { self.0.signable_bytes().map_err(Into::into) } - #[wasm_bindgen(getter = "assetLock")] - pub fn get_asset_lock_proof(&self) -> Option { + #[wasm_bindgen(getter = "assetLockProof")] + pub fn asset_lock_proof(&self) -> Option { self.0 .optional_asset_lock_proof() .map(|asset_lock_proof| AssetLockProofWasm::from(asset_lock_proof.clone())) } #[wasm_bindgen(setter = "userFeeIncrease")] - pub fn set_user_fee_increase(&mut self, amount: u16) { - self.0.set_user_fee_increase(amount) + pub fn set_user_fee_increase(&mut self, amount: JsValue) -> WasmDppResult<()> { + self.0 + .set_user_fee_increase(try_to_u16(&amount, "userFeeIncrease")?); + Ok(()) } #[wasm_bindgen(getter = "modifiedDataIds")] - pub fn get_modified_data_ids(&self) -> Vec { + pub fn modified_data_ids(&self) -> Vec { self.0 .modified_data_ids() .iter() @@ -248,4 +304,11 @@ impl MasternodeVoteTransitionWasm { } } -impl_wasm_conversions!(MasternodeVoteTransitionWasm, MasternodeVoteTransition); +impl_wasm_conversions!( + MasternodeVoteTransitionWasm, + MasternodeVoteTransition, + MasternodeVoteTransitionObjectJs, + MasternodeVoteTransitionJSONJs +); + +impl_wasm_type_info!(MasternodeVoteTransitionWasm, MasternodeVoteTransition); diff --git a/packages/wasm-dpp2/src/identity/transitions/pooling.rs b/packages/wasm-dpp2/src/identity/transitions/pooling.rs index dc8751e964f..3e5923c6bf5 100644 --- a/packages/wasm-dpp2/src/identity/transitions/pooling.rs +++ b/packages/wasm-dpp2/src/identity/transitions/pooling.rs @@ -1,9 +1,42 @@ use crate::error::WasmDppError; +use crate::impl_try_from_options; use dpp::withdrawal::Pooling; use serde::{Deserialize, Deserializer}; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Flexible input type for Pooling - accepts the enum, string name, or numeric value. + */ +export type CreditWithdrawalTransitionPoolingLike = Pooling | "never" | "ifavailable" | "standard" | 0 | 1 | 2; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "CreditWithdrawalTransitionPoolingLike")] + pub type PoolingLikeJs; +} + +impl TryFrom for PoolingWasm { + type Error = WasmDppError; + + fn try_from(value: PoolingLikeJs) -> Result { + let js_value: JsValue = value.into(); + PoolingWasm::try_from(js_value) + } +} + +impl TryFrom for Pooling { + type Error = WasmDppError; + + fn try_from(value: PoolingLikeJs) -> Result { + let wasm: PoolingWasm = value.try_into()?; + Ok(Pooling::from(wasm)) + } +} + #[wasm_bindgen] #[derive(Clone, Copy)] pub enum PoolingWasm { @@ -71,11 +104,12 @@ impl From for PoolingWasm { } } -impl TryFrom for PoolingWasm { +impl TryFrom<&JsValue> for PoolingWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { - match value.is_string() { - true => match value.as_string() { + + fn try_from(value: &JsValue) -> Result { + if value.is_string() { + match value.as_string() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -88,8 +122,9 @@ impl TryFrom for PoolingWasm { enum_val ))), }, - }, - false => match value.as_f64() { + } + } else { + match value.as_f64() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -102,11 +137,19 @@ impl TryFrom for PoolingWasm { enum_val ))), }, - }, + } } } } +impl TryFrom for PoolingWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(pooling_wasm: PoolingWasm) -> String { match pooling_wasm { @@ -116,3 +159,5 @@ impl From for String { } } } + +impl_try_from_options!(PoolingWasm); diff --git a/packages/wasm-dpp2/src/identity/transitions/public_key_in_creation.rs b/packages/wasm-dpp2/src/identity/transitions/public_key_in_creation.rs index f79012c6b56..83e9b45b574 100644 --- a/packages/wasm-dpp2/src/identity/transitions/public_key_in_creation.rs +++ b/packages/wasm-dpp2/src/identity/transitions/public_key_in_creation.rs @@ -1,24 +1,90 @@ use crate::data_contract::contract_bounds::ContractBoundsWasm; -use crate::enums::keys::key_type::KeyTypeWasm; -use crate::enums::keys::purpose::PurposeWasm; -use crate::enums::keys::security_level::SecurityLevelWasm; +use crate::enums::keys::key_type::{KeyTypeLikeJs, KeyTypeWasm}; +use crate::enums::keys::purpose::{PurposeLikeJs, PurposeWasm}; +use crate::enums::keys::security_level::{SecurityLevelLikeJs, SecurityLevelWasm}; use crate::error::{WasmDppError, WasmDppResult}; use crate::identity::public_key::IdentityPublicKeyWasm; +use crate::impl_try_from_js_value; use crate::impl_wasm_conversions; -use crate::utils::IntoWasm; -use dpp::identity::contract_bounds::ContractBounds; +use crate::impl_wasm_type_info; +use crate::utils::{try_from_options, try_from_options_optional, try_to_u32}; use dpp::identity::identity_public_key::v0::IdentityPublicKeyV0; use dpp::identity::{IdentityPublicKey, KeyType, Purpose, SecurityLevel}; use dpp::platform_value::BinaryData; -use dpp::platform_value::string_encoding::Encoding::Hex; use dpp::state_transition::public_key_in_creation::IdentityPublicKeyInCreation; use dpp::state_transition::public_key_in_creation::accessors::{ IdentityPublicKeyInCreationV0Getters, IdentityPublicKeyInCreationV0Setters, }; use dpp::state_transition::public_key_in_creation::v0::IdentityPublicKeyInCreationV0; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IdentityPublicKeyInCreationOptions { + key_id: u32, + data: Vec, + #[serde(default)] + is_read_only: bool, + #[serde(default)] + signature: Option>, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface IdentityPublicKeyInCreationOptions { + keyId: number; + purpose: PurposeLike; + securityLevel: SecurityLevelLike; + keyType: KeyTypeLike; + isReadOnly?: boolean; + data: Uint8Array; + signature?: Uint8Array; + contractBounds?: ContractBounds; +} + +/** + * IdentityPublicKeyInCreation serialized as a plain object. + */ +export interface IdentityPublicKeyInCreationObject { + keyId: number; + purpose: Purpose; + securityLevel: SecurityLevel; + keyType: KeyType; + isReadOnly: boolean; + data: Uint8Array; + signature?: Uint8Array; + contractBounds?: ContractBoundsObject; +} + +/** + * IdentityPublicKeyInCreation serialized as JSON. + */ +export interface IdentityPublicKeyInCreationJSON { + keyId: number; + purpose: string; + securityLevel: string; + keyType: string; + isReadOnly: boolean; + data: string; + signature?: string; + contractBounds?: ContractBoundsJSON; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityPublicKeyInCreationOptions")] + pub type IdentityPublicKeyInCreationOptionsJs; + + #[wasm_bindgen(typescript_type = "IdentityPublicKeyInCreationObject")] + pub type IdentityPublicKeyInCreationObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityPublicKeyInCreationJSON")] + pub type IdentityPublicKeyInCreationJSONJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "IdentityPublicKeyInCreation")] pub struct IdentityPublicKeyInCreationWasm(IdentityPublicKeyInCreation); @@ -35,16 +101,6 @@ impl From for IdentityPublicKeyInCreation { } } -impl TryFrom for IdentityPublicKeyInCreationWasm { - type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { - let value = - value.to_wasm::("IdentityPublicKeyInCreation")?; - - Ok(value.clone()) - } -} - impl From for IdentityPublicKey { fn from(value: IdentityPublicKeyInCreationWasm) -> Self { let contract_bounds = value.0.contract_bounds().cloned(); @@ -64,68 +120,46 @@ impl From for IdentityPublicKey { #[wasm_bindgen(js_class = IdentityPublicKeyInCreation)] impl IdentityPublicKeyInCreationWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentityPublicKeyInCreation".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentityPublicKeyInCreation".to_string() - } - #[wasm_bindgen(constructor)] - #[allow(clippy::too_many_arguments)] - pub fn new( - id: u32, - js_purpose: JsValue, - js_security_level: JsValue, - js_key_type: JsValue, - read_only: bool, - binary_data: Vec, - signature: Option>, - js_contract_bounds: &JsValue, + pub fn constructor( + options: IdentityPublicKeyInCreationOptionsJs, ) -> WasmDppResult { - let purpose = PurposeWasm::try_from(js_purpose)?; - let security_level = SecurityLevelWasm::try_from(js_security_level)?; - let key_type = KeyTypeWasm::try_from(js_key_type)?; - let contract_bounds: Option = - match js_contract_bounds.is_undefined() | js_contract_bounds.is_null() { - true => None, - false => Some( - js_contract_bounds - .to_wasm::("ContractBounds")? - .clone() - .into(), - ), - }; + // Extract purpose (required, complex type) + let purpose: PurposeWasm = try_from_options(&options, "purpose")?; + + // Extract securityLevel (required, complex type) + let security_level: SecurityLevelWasm = try_from_options(&options, "securityLevel")?; + + // Extract keyType (required, complex type) + let key_type: KeyTypeWasm = try_from_options(&options, "keyType")?; + + // Extract contractBounds (optional) + let contract_bounds: Option = + try_from_options_optional(&options, "contractBounds")?; + + // Extract simple fields via serde + let opts: IdentityPublicKeyInCreationOptions = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(IdentityPublicKeyInCreationWasm( IdentityPublicKeyInCreation::V0(IdentityPublicKeyInCreationV0 { - id, + id: opts.key_id, key_type: KeyType::from(key_type), purpose: Purpose::from(purpose), security_level: SecurityLevel::from(security_level), - contract_bounds, - read_only, - data: BinaryData::from(binary_data), - signature: BinaryData::from(signature.unwrap_or_default()), + contract_bounds: contract_bounds.map(Into::into), + read_only: opts.is_read_only, + data: BinaryData::new(opts.data), + signature: BinaryData::from(opts.signature.unwrap_or_default()), }), )) } - #[wasm_bindgen(js_name = toIdentityPublicKey)] - pub fn to_identity_public_key(&self) -> WasmDppResult { - IdentityPublicKeyWasm::new( - self.0.id(), - JsValue::from(PurposeWasm::from(self.0.purpose())), - JsValue::from(SecurityLevelWasm::from(self.0.security_level())), - JsValue::from(KeyTypeWasm::from(self.0.key_type())), - self.0.read_only(), - self.0.data().to_string(Hex).as_str(), - None, - &JsValue::from(self.get_contract_bounds().clone()), - ) + #[wasm_bindgen(js_name = "toIdentityPublicKey")] + pub fn to_identity_public_key(&self) -> IdentityPublicKeyWasm { + let key: IdentityPublicKey = IdentityPublicKey::from(&self.0); + IdentityPublicKeyWasm::from(key) } #[wasm_bindgen(js_name = "getHash")] @@ -135,119 +169,130 @@ impl IdentityPublicKeyInCreationWasm { } #[wasm_bindgen(getter = "contractBounds")] - pub fn get_contract_bounds(&self) -> Option { + pub fn contract_bounds(&self) -> Option { self.0 .contract_bounds() .map(|bounds| ContractBoundsWasm::from(bounds.clone())) } #[wasm_bindgen(getter = keyId)] - pub fn get_key_id(&self) -> u32 { + pub fn key_id(&self) -> u32 { self.0.id() } #[wasm_bindgen(getter = purpose)] - pub fn get_purpose(&self) -> String { + pub fn purpose(&self) -> String { PurposeWasm::from(self.0.purpose()).into() } #[wasm_bindgen(getter = securityLevel)] - pub fn get_security_level(&self) -> String { + pub fn security_level(&self) -> String { SecurityLevelWasm::from(self.0.security_level()).into() } #[wasm_bindgen(getter = keyType)] - pub fn get_key_type(&self) -> String { + pub fn key_type(&self) -> String { KeyTypeWasm::from(self.0.key_type()).into() } - #[wasm_bindgen(getter = readOnly)] - pub fn get_read_only(&self) -> bool { + #[wasm_bindgen(getter = "isReadOnly")] + pub fn is_read_only(&self) -> bool { self.0.read_only() } #[wasm_bindgen(getter = data)] - pub fn get_data(&self) -> Vec { + pub fn data(&self) -> Vec { self.0.data().to_vec() } #[wasm_bindgen(getter = signature)] - pub fn get_signature(&self) -> Vec { + pub fn signature(&self) -> Vec { self.0.signature().to_vec() } #[wasm_bindgen(setter = keyId)] - pub fn set_key_id(&mut self, key_id: u32) { - self.0.set_id(key_id) + pub fn set_key_id( + &mut self, + #[wasm_bindgen(js_name = "keyId")] key_id: JsValue, + ) -> WasmDppResult<()> { + self.0.set_id(try_to_u32(&key_id, "keyId")?); + Ok(()) } #[wasm_bindgen(setter = purpose)] - pub fn set_purpose(&mut self, js_purpose: JsValue) -> WasmDppResult<()> { - let purpose = PurposeWasm::try_from(js_purpose)?; - self.0.set_purpose(Purpose::from(purpose)); + pub fn set_purpose(&mut self, purpose: PurposeLikeJs) -> WasmDppResult<()> { + let purpose: Purpose = purpose.try_into()?; + self.0.set_purpose(purpose); Ok(()) } #[wasm_bindgen(setter = securityLevel)] - pub fn set_security_level(&mut self, js_security_level: JsValue) -> WasmDppResult<()> { - let security_level = SecurityLevelWasm::try_from(js_security_level)?; - self.0 - .set_security_level(SecurityLevel::from(security_level)); + pub fn set_security_level( + &mut self, + #[wasm_bindgen(js_name = "securityLevel")] security_level: SecurityLevelLikeJs, + ) -> WasmDppResult<()> { + let security_level: SecurityLevel = security_level.try_into()?; + self.0.set_security_level(security_level); Ok(()) } #[wasm_bindgen(setter = keyType)] - pub fn set_key_type(&mut self, key_type: JsValue) -> WasmDppResult<()> { - let key_type = KeyTypeWasm::try_from(key_type)?; - self.0.set_type(key_type.into()); + pub fn set_key_type( + &mut self, + #[wasm_bindgen(js_name = "keyType")] key_type: KeyTypeLikeJs, + ) -> WasmDppResult<()> { + let key_type: KeyType = key_type.try_into()?; + self.0.set_type(key_type); Ok(()) } - #[wasm_bindgen(setter = readOnly)] - pub fn set_read_only(&mut self, read_only: bool) { - self.0.set_read_only(read_only) + #[wasm_bindgen(setter = "isReadOnly")] + pub fn set_is_read_only(&mut self, #[wasm_bindgen(js_name = "isReadOnly")] is_read_only: bool) { + self.0.set_read_only(is_read_only) } #[wasm_bindgen(setter = data)] - pub fn set_data(&mut self, binary_data: Vec) { + pub fn set_data(&mut self, #[wasm_bindgen(js_name = "binaryData")] binary_data: Vec) { let data = BinaryData::from(binary_data); self.0.set_data(data) } #[wasm_bindgen(setter = signature)] - pub fn set_signature(&mut self, binary_data: Vec) { + pub fn set_signature( + &mut self, + #[wasm_bindgen(js_name = "signatureBytes")] binary_data: Vec, + ) { let signature = BinaryData::from(binary_data); self.0.set_signature(signature) } #[wasm_bindgen(setter = "contractBounds")] - pub fn set_contract_bounds(&mut self, js_bounds: &JsValue) -> WasmDppResult<()> { - match js_bounds.is_undefined() { - true => self.0.set_contract_bounds(None), - false => { - let bounds = js_bounds - .to_wasm::("ContractBounds")? - .clone(); - - self.0.set_contract_bounds(Some(bounds.into())) - } - }; - - Ok(()) + pub fn set_contract_bounds(&mut self, bounds: Option) { + self.0.set_contract_bounds(bounds.map(|b| b.into())); } } impl IdentityPublicKeyInCreationWasm { - pub fn vec_from_js_value( - js_add_public_keys: &js_sys::Array, + pub fn vec_from_array( + add_public_keys: &js_sys::Array, ) -> WasmDppResult> { - let add_public_keys: Vec = js_add_public_keys + let add_public_keys: Vec = add_public_keys .iter() - .map(IdentityPublicKeyInCreationWasm::try_from) + .map(|v| Self::try_from(&v)) .collect::, WasmDppError>>()?; Ok(add_public_keys) } } -impl_wasm_conversions!(IdentityPublicKeyInCreationWasm, IdentityPublicKeyInCreation); +impl_try_from_js_value!( + IdentityPublicKeyInCreationWasm, + "IdentityPublicKeyInCreation" +); +impl_wasm_conversions!( + IdentityPublicKeyInCreationWasm, + IdentityPublicKeyInCreation, + IdentityPublicKeyInCreationObjectJs, + IdentityPublicKeyInCreationJSONJs +); +impl_wasm_type_info!(IdentityPublicKeyInCreationWasm, IdentityPublicKeyInCreation); diff --git a/packages/wasm-dpp2/src/identity/transitions/top_up_transition.rs b/packages/wasm-dpp2/src/identity/transitions/top_up_transition.rs index 0f37b398b75..bcb143c4142 100644 --- a/packages/wasm-dpp2/src/identity/transitions/top_up_transition.rs +++ b/packages/wasm-dpp2/src/identity/transitions/top_up_transition.rs @@ -1,9 +1,10 @@ use crate::asset_lock_proof::AssetLockProofWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; -use dpp::identifier::Identifier; +use crate::utils::try_from_options; use dpp::identity::state_transition::{AssetLockProved, OptionallyAssetLockProved}; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::{decode, encode}; @@ -13,46 +14,91 @@ use dpp::state_transition::identity_topup_transition::IdentityTopUpTransition; use dpp::state_transition::identity_topup_transition::accessors::IdentityTopUpTransitionAccessorsV0; use dpp::state_transition::identity_topup_transition::v0::IdentityTopUpTransitionV0; use dpp::state_transition::{StateTransition, StateTransitionLike, StateTransitionSingleSigned}; -use wasm_bindgen::JsValue; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IdentityTopUpTransitionOptionsSerde { + #[serde(default)] + user_fee_increase: UserFeeIncrease, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Options for creating an IdentityTopUpTransition instance. + */ +export interface IdentityTopUpTransitionOptions { + assetLockProof: AssetLockProof; + identityId: IdentifierLike; + userFeeIncrease?: number; +} + +/** + * IdentityTopUpTransition serialized as a plain object. + */ +export interface IdentityTopUpTransitionObject { + identityId: Uint8Array; + assetLockProof: AssetLockProofObject; + userFeeIncrease: number; + signature?: Uint8Array; +} + +/** + * IdentityTopUpTransition serialized as JSON. + */ +export interface IdentityTopUpTransitionJSON { + identityId: string; + assetLockProof: AssetLockProofJSON; + userFeeIncrease: number; + signature?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityTopUpTransitionOptions")] + pub type IdentityTopUpTransitionOptionsJs; + + #[wasm_bindgen(typescript_type = "IdentityTopUpTransitionObject")] + pub type IdentityTopUpTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityTopUpTransitionJSON")] + pub type IdentityTopUpTransitionJSONJs; +} + #[wasm_bindgen(js_name = "IdentityTopUpTransition")] #[derive(Clone)] pub struct IdentityTopUpTransitionWasm(IdentityTopUpTransition); #[wasm_bindgen(js_class = IdentityTopUpTransition)] impl IdentityTopUpTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentityTopUpTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentityTopUpTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - asset_lock_proof: &AssetLockProofWasm, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: JsValue, - user_fee_increase: Option, + pub fn constructor( + options: IdentityTopUpTransitionOptionsJs, ) -> WasmDppResult { - let identity_id: Identifier = IdentifierWasm::try_from(&js_identity_id)?.into(); + // Extract complex types first (borrows &options) + let asset_lock_proof: AssetLockProofWasm = try_from_options(&options, "assetLockProof")?; + let identity_id: IdentifierWasm = try_from_options(&options, "identityId")?; + + // Deserialize primitive fields via serde (consumes options) + let opts: IdentityTopUpTransitionOptionsSerde = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(IdentityTopUpTransitionWasm(IdentityTopUpTransition::V0( IdentityTopUpTransitionV0 { - asset_lock_proof: asset_lock_proof.clone().into(), - identity_id, - user_fee_increase: user_fee_increase.unwrap_or(0), + asset_lock_proof: asset_lock_proof.into(), + identity_id: identity_id.into(), + user_fee_increase: opts.user_fee_increase, signature: Default::default(), }, ))) } - #[wasm_bindgen(js_name = "getModifiedDataIds")] - pub fn get_modified_data_ids(&self) -> Vec { + #[wasm_bindgen(getter = "modifiedDataIds")] + pub fn modified_data_ids(&self) -> Vec { self.0 .modified_data_ids() .iter() @@ -60,50 +106,49 @@ impl IdentityTopUpTransitionWasm { .collect() } - #[wasm_bindgen(js_name = "getOptionalAssetLockProof")] - pub fn get_optional_asset_lock_proof(&self) -> JsValue { - match self.0.optional_asset_lock_proof() { - Some(asset_lock) => JsValue::from(AssetLockProofWasm::from(asset_lock.clone())), - None => JsValue::null(), - } + #[wasm_bindgen(getter = "optionalAssetLockProof")] + pub fn optional_asset_lock_proof(&self) -> Option { + self.0 + .optional_asset_lock_proof() + .map(|asset_lock| AssetLockProofWasm::from(asset_lock.clone())) } #[wasm_bindgen(getter = "userFeeIncrease")] - pub fn get_user_fee_increase(&self) -> UserFeeIncrease { + pub fn user_fee_increase(&self) -> UserFeeIncrease { self.0.user_fee_increase() } #[wasm_bindgen(getter = "identityIdentifier")] - pub fn get_identity_identifier(&self) -> IdentifierWasm { + pub fn identity_identifier(&self) -> IdentifierWasm { (*self.0.identity_id()).into() } #[wasm_bindgen(getter = "assetLockProof")] - pub fn get_asset_lock_proof(&self) -> AssetLockProofWasm { + pub fn asset_lock_proof(&self) -> AssetLockProofWasm { self.0.asset_lock_proof().clone().into() } #[wasm_bindgen(setter = "userFeeIncrease")] - pub fn set_user_fee_increase(&mut self, user_fee_increase: UserFeeIncrease) { + pub fn set_user_fee_increase( + &mut self, + #[wasm_bindgen(js_name = "userFeeIncrease")] user_fee_increase: UserFeeIncrease, + ) { self.0.set_user_fee_increase(user_fee_increase); } #[wasm_bindgen(setter = "identityIdentifier")] pub fn set_identity_identifier( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_identifier: &JsValue, + #[wasm_bindgen(js_name = "identityIdentifier")] identity_identifier: IdentifierLikeJs, ) -> WasmDppResult<()> { - let identity_identifier: Identifier = - IdentifierWasm::try_from(js_identity_identifier)?.into(); - self.0.set_identity_id(identity_identifier); + self.0.set_identity_id(identity_identifier.try_into()?); Ok(()) } #[wasm_bindgen(setter = "assetLockProof")] pub fn set_asset_lock_proof( &mut self, - asset_lock_proof: &AssetLockProofWasm, + #[wasm_bindgen(js_name = "assetLockProof")] asset_lock_proof: &AssetLockProofWasm, ) -> WasmDppResult<()> { self.0 .set_asset_lock_proof(asset_lock_proof.clone().into())?; @@ -111,7 +156,7 @@ impl IdentityTopUpTransitionWasm { } #[wasm_bindgen(getter = "signature")] - pub fn get_signature(&self) -> Vec { + pub fn signature(&self) -> Vec { self.0.signature().to_vec() } @@ -183,4 +228,10 @@ impl IdentityTopUpTransitionWasm { } } -impl_wasm_conversions!(IdentityTopUpTransitionWasm, IdentityTopUpTransition); +impl_wasm_conversions!( + IdentityTopUpTransitionWasm, + IdentityTopUpTransition, + IdentityTopUpTransitionObjectJs, + IdentityTopUpTransitionJSONJs +); +impl_wasm_type_info!(IdentityTopUpTransitionWasm, IdentityTopUpTransition); diff --git a/packages/wasm-dpp2/src/identity/transitions/update_transition.rs b/packages/wasm-dpp2/src/identity/transitions/update_transition.rs index a1e423c14fa..e63d36ad725 100644 --- a/packages/wasm-dpp2/src/identity/transitions/update_transition.rs +++ b/packages/wasm-dpp2/src/identity/transitions/update_transition.rs @@ -1,10 +1,12 @@ use crate::asset_lock_proof::AssetLockProofWasm; use crate::enums::keys::purpose::PurposeWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::identity::transitions::public_key_in_creation::IdentityPublicKeyInCreationWasm; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::state_transitions::StateTransitionWasm; +use crate::utils::{try_from_options, try_from_options_with, try_to_array, try_to_u32, try_to_u64}; use dpp::identity::KeyID; use dpp::identity::state_transition::OptionallyAssetLockProved; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; @@ -19,52 +21,117 @@ use dpp::state_transition::{ StateTransition, StateTransitionIdentitySigned, StateTransitionLike, StateTransitionSingleSigned, }; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const IDENTITY_UPDATE_OPTIONS_TS: &str = r#" +export interface IdentityUpdateTransitionOptions { + identityId: IdentifierLike; + revision: bigint; + nonce: bigint; + addPublicKeys: IdentityPublicKeyInCreation[]; + disablePublicKeys: number[]; + userFeeIncrease?: number; +} + +/** + * IdentityUpdateTransition serialized as a plain object. + */ +export interface IdentityUpdateTransitionObject { + identityId: Uint8Array; + revision: bigint; + nonce: bigint; + addPublicKeys: IdentityPublicKeyInCreationObject[]; + disablePublicKeys: number[]; + userFeeIncrease: number; + signature?: Uint8Array; + signaturePublicKeyId?: number; +} + +/** + * IdentityUpdateTransition serialized as JSON. + */ +export interface IdentityUpdateTransitionJSON { + identityId: string; + revision: string; + nonce: string; + addPublicKeys: IdentityPublicKeyInCreationJSON[]; + disablePublicKeys: number[]; + userFeeIncrease: number; + signature?: string; + signaturePublicKeyId?: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IdentityUpdateTransitionOptions")] + pub type IdentityUpdateTransitionOptionsJs; + + #[wasm_bindgen(typescript_type = "IdentityUpdateTransitionObject")] + pub type IdentityUpdateTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "IdentityUpdateTransitionJSON")] + pub type IdentityUpdateTransitionJSONJs; +} + +/// Serde struct for IdentityUpdateTransitionOptions (primitives only) +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IdentityUpdateTransitionOptionsInput { + revision: Revision, + nonce: IdentityNonce, + #[serde(default)] + user_fee_increase: UserFeeIncrease, +} + #[wasm_bindgen(js_name = "IdentityUpdateTransition")] #[derive(Clone)] pub struct IdentityUpdateTransitionWasm(IdentityUpdateTransition); #[wasm_bindgen(js_class = IdentityUpdateTransition)] impl IdentityUpdateTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "IdentityUpdateTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "IdentityUpdateTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: &JsValue, - revision: Revision, - nonce: IdentityNonce, - js_add_public_keys: &js_sys::Array, - disable_public_keys: Vec, - user_fee_increase: Option, + pub fn constructor( + options: IdentityUpdateTransitionOptionsJs, ) -> WasmDppResult { - let identity_id = IdentifierWasm::try_from(js_identity_id)?.into(); + // Extract complex types first (borrows &options) + let identity_id: IdentifierWasm = try_from_options(&options, "identityId")?; + let add_public_keys_array = try_from_options_with(&options, "addPublicKeys", |v| { + try_to_array(v, "addPublicKeys") + })?; let add_public_keys: Vec = - IdentityPublicKeyInCreationWasm::vec_from_js_value(js_add_public_keys)?; + IdentityPublicKeyInCreationWasm::vec_from_array(&add_public_keys_array)?; + + let disable_public_keys_array = + try_from_options_with(&options, "disablePublicKeys", |v| { + try_to_array(v, "disablePublicKeys") + })?; + let disable_public_keys: Vec = disable_public_keys_array + .iter() + .enumerate() + .map(|(i, v)| try_to_u32(&v, &format!("disablePublicKeys[{}]", i))) + .collect::>>()?; + + // Deserialize primitive fields via serde last (consumes options) + let input: IdentityUpdateTransitionOptionsInput = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(IdentityUpdateTransitionWasm(IdentityUpdateTransition::V0( IdentityUpdateTransitionV0 { - identity_id, - revision, - nonce, + identity_id: identity_id.into(), + revision: input.revision, + nonce: input.nonce, add_public_keys: add_public_keys - .clone() .iter() .map(|key| key.clone().into()) .collect(), disable_public_keys, - user_fee_increase: user_fee_increase.unwrap_or(0), + user_fee_increase: input.user_fee_increase, signature_public_key_id: 0, signature: Default::default(), }, @@ -72,22 +139,22 @@ impl IdentityUpdateTransitionWasm { } #[wasm_bindgen(getter = "revision")] - pub fn get_revision(&self) -> Revision { + pub fn revision(&self) -> Revision { self.0.revision() } #[wasm_bindgen(getter = "nonce")] - pub fn get_nonce(&self) -> IdentityNonce { + pub fn nonce(&self) -> IdentityNonce { self.0.nonce() } #[wasm_bindgen(getter = "identityIdentifier")] - pub fn get_identity_identifier(&self) -> IdentifierWasm { + pub fn identity_identifier(&self) -> IdentifierWasm { self.0.identity_id().into() } - #[wasm_bindgen(js_name = "getPurposeRequirement")] - pub fn get_purpose_requirement(&self) -> Vec { + #[wasm_bindgen(getter = "purposeRequirement")] + pub fn purpose_requirement(&self) -> Vec { self.0 .purpose_requirement() .iter() @@ -95,8 +162,8 @@ impl IdentityUpdateTransitionWasm { .collect() } - #[wasm_bindgen(js_name = "getModifiedDataIds")] - pub fn get_modified_data_ids(&self) -> Vec { + #[wasm_bindgen(getter = "modifiedDataIds")] + pub fn modified_data_ids(&self) -> Vec { self.0 .modified_data_ids() .iter() @@ -104,21 +171,20 @@ impl IdentityUpdateTransitionWasm { .collect() } - #[wasm_bindgen(js_name = "getOptionalAssetLockProof")] - pub fn get_optional_asset_lock_proof(&self) -> JsValue { - match self.0.optional_asset_lock_proof() { - Some(asset_lock) => JsValue::from(AssetLockProofWasm::from(asset_lock.clone())), - None => JsValue::null(), - } + #[wasm_bindgen(getter = "optionalAssetLockProof")] + pub fn optional_asset_lock_proof(&self) -> Option { + self.0 + .optional_asset_lock_proof() + .map(|asset_lock| AssetLockProofWasm::from(asset_lock.clone())) } #[wasm_bindgen(getter = "publicKeyIdsToDisable")] - pub fn get_public_key_ids_to_disable(&self) -> Vec { + pub fn public_key_ids_to_disable(&self) -> Vec { self.0.public_key_ids_to_disable().to_vec() } #[wasm_bindgen(getter = "publicKeyIdsToAdd")] - pub fn get_public_key_ids_to_add(&self) -> Vec { + pub fn public_key_ids_to_add(&self) -> Vec { self.0 .public_keys_to_add() .to_vec() @@ -128,38 +194,38 @@ impl IdentityUpdateTransitionWasm { } #[wasm_bindgen(getter = "userFeeIncrease")] - pub fn get_user_fee_increase(&self) -> UserFeeIncrease { + pub fn user_fee_increase(&self) -> UserFeeIncrease { self.0.user_fee_increase() } #[wasm_bindgen(setter = "revision")] - pub fn set_revision(&mut self, revision: Revision) { - self.0.set_revision(revision); + pub fn set_revision(&mut self, revision: JsValue) -> WasmDppResult<()> { + self.0.set_revision(try_to_u64(&revision, "revision")?); + Ok(()) } #[wasm_bindgen(setter = "nonce")] - pub fn set_nonce(&mut self, nonce: IdentityNonce) { - self.0.set_nonce(nonce); + pub fn set_nonce(&mut self, nonce: JsValue) -> WasmDppResult<()> { + self.0.set_nonce(try_to_u64(&nonce, "nonce")?); + Ok(()) } #[wasm_bindgen(setter = "identityIdentifier")] pub fn set_identity_identifier( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: &JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let identity_id = IdentifierWasm::try_from(js_identity_id)?.into(); - self.0.set_identity_id(identity_id); + self.0.set_identity_id(identity_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "publicKeyIdsToAdd")] pub fn set_public_key_ids_to_add( &mut self, - js_add_public_keys: &js_sys::Array, + #[wasm_bindgen(js_name = "addPublicKeys")] add_public_keys: &js_sys::Array, ) -> WasmDppResult<()> { let add_public_keys: Vec = - IdentityPublicKeyInCreationWasm::vec_from_js_value(js_add_public_keys)?; + IdentityPublicKeyInCreationWasm::vec_from_array(add_public_keys)?; let keys: Vec = add_public_keys.iter().map(|id| id.clone().into()).collect(); @@ -169,17 +235,23 @@ impl IdentityUpdateTransitionWasm { } #[wasm_bindgen(setter = "publicKeyIdsToDisable")] - pub fn set_public_key_ids_to_disable(&mut self, public_keys: Vec) { + pub fn set_public_key_ids_to_disable( + &mut self, + #[wasm_bindgen(js_name = "publicKeys")] public_keys: Vec, + ) { self.0.set_public_key_ids_to_disable(public_keys) } #[wasm_bindgen(setter = "userFeeIncrease")] - pub fn set_user_fee_increase(&mut self, user_fee_increase: UserFeeIncrease) { + pub fn set_user_fee_increase( + &mut self, + #[wasm_bindgen(js_name = "userFeeIncrease")] user_fee_increase: UserFeeIncrease, + ) { self.0.set_user_fee_increase(user_fee_increase) } #[wasm_bindgen(getter = "signature")] - pub fn get_signature(&self) -> Vec { + pub fn signature(&self) -> Vec { self.0.signature().to_vec() } @@ -189,7 +261,7 @@ impl IdentityUpdateTransitionWasm { } #[wasm_bindgen(getter = "signaturePublicKeyId")] - pub fn get_signature_public_key_id(&self) -> KeyID { + pub fn signature_public_key_id(&self) -> KeyID { self.0.signature_public_key_id() } @@ -199,7 +271,10 @@ impl IdentityUpdateTransitionWasm { } #[wasm_bindgen(setter = "signaturePublicKeyId")] - pub fn set_signature_public_key_id(&mut self, signature_public_key_id: KeyID) { + pub fn set_signature_public_key_id( + &mut self, + #[wasm_bindgen(js_name = "signaturePublicKeyId")] signature_public_key_id: KeyID, + ) { self.0.set_signature_public_key_id(signature_public_key_id) } @@ -263,4 +338,10 @@ impl IdentityUpdateTransitionWasm { } } -impl_wasm_conversions!(IdentityUpdateTransitionWasm, IdentityUpdateTransition); +impl_wasm_conversions!( + IdentityUpdateTransitionWasm, + IdentityUpdateTransition, + IdentityUpdateTransitionObjectJs, + IdentityUpdateTransitionJSONJs +); +impl_wasm_type_info!(IdentityUpdateTransitionWasm, IdentityUpdateTransition); diff --git a/packages/wasm-dpp2/src/lib.rs b/packages/wasm-dpp2/src/lib.rs index 2bdb6751c60..9867a23faec 100644 --- a/packages/wasm-dpp2/src/lib.rs +++ b/packages/wasm-dpp2/src/lib.rs @@ -27,12 +27,15 @@ pub mod serialization; pub mod state_transitions; pub mod tokens; pub mod utils; +pub mod version; pub mod voting; pub use core::core_script::CoreScriptWasm; -pub use core::network::NetworkWasm; +pub use core::network::{NetworkLikeJs, NetworkWasm}; pub use core::private_key::PrivateKeyWasm; -pub use core::pro_tx_hash::ProTxHashWasm; +pub use core::pro_tx_hash::{ + ProTxHashLikeArrayJs, ProTxHashLikeJs, ProTxHashLikeNullableJs, ProTxHashWasm, +}; pub use identity::signer::IdentitySignerWasm; pub use identity::transitions::pooling::PoolingWasm; @@ -42,19 +45,25 @@ pub use data_contract::{ }; pub use epoch::*; pub use group::*; +pub use identifier::{ + IdentifierLikeArrayJs, IdentifierLikeJs, IdentifierLikeOrUndefinedJs, IdentifierWasm, +}; pub use identity::{ IdentityCreateTransitionWasm, IdentityCreditTransferWasm, - IdentityCreditWithdrawalTransitionWasm, IdentityPublicKeyInCreationWasm, IdentityPublicKeyWasm, - IdentityTopUpTransitionWasm, IdentityUpdateTransitionWasm, IdentityWasm, - MasternodeVoteTransitionWasm, PartialIdentityWasm, + IdentityCreditWithdrawalTransitionWasm, IdentityPublicKeyInCreationWasm, + IdentityPublicKeyOptionsJs, IdentityPublicKeyWasm, IdentityTopUpTransitionWasm, + IdentityUpdateTransitionWasm, IdentityWasm, MasternodeVoteTransitionWasm, PartialIdentityWasm, + PublicKeyHashLikeJs, public_key_hash_from_js, }; pub use platform_address::{ - FeeStrategyStepWasm, PlatformAddressInputWasm, PlatformAddressOutputWasm, - PlatformAddressSignerWasm, PlatformAddressWasm, default_fee_strategy, fee_strategy_from_steps, + FeeStrategyStepWasm, PlatformAddressInputWasm, PlatformAddressLikeArrayJs, + PlatformAddressLikeJs, PlatformAddressOutputWasm, PlatformAddressSignerWasm, + PlatformAddressWasm, default_fee_strategy, fee_strategy_from_steps, fee_strategy_from_steps_or_default, outputs_to_btree_map, outputs_to_optional_btree_map, }; pub use state_transitions::base::{GroupStateTransitionInfoWasm, StateTransitionWasm}; pub use tokens::*; +pub use version::{PlatformVersionLikeJs, PlatformVersionWasm}; pub use voting::{ ContenderWithSerializedDocumentWasm, ContestedDocumentVotePollWinnerInfoWasm, ResourceVoteChoiceWasm, ResourceVoteWasm, VotePollWasm, VoteWasm, diff --git a/packages/wasm-dpp2/src/platform_address/address.rs b/packages/wasm-dpp2/src/platform_address/address.rs index 0c05a42ce22..364808405ba 100644 --- a/packages/wasm-dpp2/src/platform_address/address.rs +++ b/packages/wasm-dpp2/src/platform_address/address.rs @@ -1,5 +1,6 @@ -use crate::core::network::NetworkWasm; +use crate::core::network::NetworkLikeJs; use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_wasm_type_info; use crate::utils::IntoWasm; use dpp::address_funds::PlatformAddress; use dpp::dashcore::Network; @@ -15,7 +16,7 @@ use wasm_bindgen::prelude::*; pub struct PlatformAddressWasm(PlatformAddress); #[wasm_bindgen(typescript_custom_section)] -const PLATFORM_ADDRESS_TS_HELPERS: &'static str = r#" +const PLATFORM_ADDRESS_TS_HELPERS: &str = r#" /** * A Platform address can be provided as: * - A PlatformAddress object @@ -23,8 +24,38 @@ const PLATFORM_ADDRESS_TS_HELPERS: &'static str = r#" * - A bech32m string (e.g., "evo1..." or "tevo1...") */ export type PlatformAddressLike = PlatformAddress | Uint8Array | string; + +/** + * An array of Platform addresses. + */ +export type PlatformAddressLikeArray = Array; "#; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "PlatformAddressLike")] + pub type PlatformAddressLikeJs; + + #[wasm_bindgen(typescript_type = "PlatformAddressLikeArray")] + pub type PlatformAddressLikeArrayJs; +} + +impl TryFrom for PlatformAddressWasm { + type Error = WasmDppError; + fn try_from(value: PlatformAddressLikeJs) -> Result { + let js_value: JsValue = value.into(); + PlatformAddressWasm::try_from(js_value) + } +} + +impl TryFrom for PlatformAddress { + type Error = WasmDppError; + fn try_from(value: PlatformAddressLikeJs) -> Result { + let wasm: PlatformAddressWasm = value.try_into()?; + Ok(PlatformAddress::from(wasm)) + } +} + impl From for PlatformAddress { fn from(address: PlatformAddressWasm) -> Self { address.0 @@ -194,16 +225,6 @@ impl Serialize for PlatformAddressWasm { #[wasm_bindgen(js_class = PlatformAddress)] impl PlatformAddressWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "PlatformAddress".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "PlatformAddress".to_string() - } - /// Creates a new PlatformAddress from various input types. /// /// Accepts: @@ -211,20 +232,14 @@ impl PlatformAddressWasm { /// - A Uint8Array (21 bytes: type byte + 20-byte hash) /// - An existing PlatformAddress object #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "PlatformAddress | Uint8Array | string")] - js_address: &JsValue, - ) -> WasmDppResult { - PlatformAddressWasm::try_from(js_address) + pub fn constructor(address: PlatformAddressLikeJs) -> WasmDppResult { + address.try_into() } /// Returns the bech32m-encoded address string for the specified network. #[wasm_bindgen(js_name = "toBech32m")] - pub fn to_bech32m( - &self, - #[wasm_bindgen(unchecked_param_type = "NetworkLike")] network: JsValue, - ) -> WasmDppResult { - let net: Network = NetworkWasm::try_from(&network)?.into(); + pub fn to_bech32m(&self, network: NetworkLikeJs) -> WasmDppResult { + let net: Network = network.try_into()?; Ok(self.0.to_bech32m_string(net)) } @@ -293,7 +308,9 @@ impl PlatformAddressWasm { /// Creates a PlatformAddress from a hex-encoded string. #[wasm_bindgen(js_name = "fromHex")] - pub fn from_hex(hex_string: &str) -> WasmDppResult { + pub fn from_hex( + #[wasm_bindgen(js_name = "hexString")] hex_string: &str, + ) -> WasmDppResult { let bytes = hex::decode(hex_string) .map_err(|e| WasmDppError::invalid_argument(format!("Invalid hex: {}", e)))?; PlatformAddress::from_bytes(&bytes) @@ -341,3 +358,5 @@ impl PlatformAddressWasm { self.0 } } + +impl_wasm_type_info!(PlatformAddressWasm, PlatformAddress); diff --git a/packages/wasm-dpp2/src/platform_address/input_output.rs b/packages/wasm-dpp2/src/platform_address/input_output.rs index b223d97a47d..dd130528a2c 100644 --- a/packages/wasm-dpp2/src/platform_address/input_output.rs +++ b/packages/wasm-dpp2/src/platform_address/input_output.rs @@ -1,5 +1,6 @@ -use super::PlatformAddressWasm; -use crate::error::{WasmDppError, WasmDppResult}; +use super::{PlatformAddressLikeJs, PlatformAddressWasm}; +use crate::error::WasmDppResult; +use crate::utils::try_to_u64; use dpp::address_funds::PlatformAddress; use dpp::fee::Credits; use dpp::prelude::AddressNonce; @@ -21,13 +22,6 @@ pub struct PlatformAddressInputWasm { amount: Credits, } -/// Helper to convert BigInt to u64 -fn bigint_to_u64(value: BigInt) -> Result { - value - .try_into() - .map_err(|_| WasmDppError::invalid_argument("value must be a valid u64")) -} - #[wasm_bindgen(js_class = PlatformAddressInput)] impl PlatformAddressInputWasm { /// Creates a new PlatformAddressInput. @@ -36,13 +30,13 @@ impl PlatformAddressInputWasm { /// @param nonce - The current nonce of the address (will be incremented for the transaction) /// @param amount - The amount of credits to spend from this address #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "PlatformAddressLike")] address: &JsValue, + pub fn constructor( + address: PlatformAddressLikeJs, nonce: u32, amount: BigInt, ) -> WasmDppResult { - let platform_address = PlatformAddressWasm::try_from(address)?; - let amount_u64 = bigint_to_u64(amount)?; + let platform_address: PlatformAddressWasm = address.try_into()?; + let amount_u64 = try_to_u64(&amount.into(), "amount")?; Ok(PlatformAddressInputWasm { address: platform_address, @@ -99,12 +93,14 @@ impl PlatformAddressOutputWasm { /// @param address - The Platform address (PlatformAddress, Uint8Array, or bech32m string) /// @param amount - The amount of credits to send to this address (optional for asset lock funding) #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "PlatformAddressLike")] address: &JsValue, + pub fn constructor( + address: PlatformAddressLikeJs, amount: Option, ) -> WasmDppResult { - let platform_address = PlatformAddressWasm::try_from(address)?; - let amount_u64 = amount.map(bigint_to_u64).transpose()?; + let platform_address: PlatformAddressWasm = address.try_into()?; + let amount_u64 = amount + .map(|v| try_to_u64(&v.into(), "amount")) + .transpose()?; Ok(PlatformAddressOutputWasm { address: platform_address, diff --git a/packages/wasm-dpp2/src/platform_address/mod.rs b/packages/wasm-dpp2/src/platform_address/mod.rs index 1ede35af35f..21e528da0b9 100644 --- a/packages/wasm-dpp2/src/platform_address/mod.rs +++ b/packages/wasm-dpp2/src/platform_address/mod.rs @@ -3,7 +3,7 @@ mod fee_strategy; mod input_output; mod signer; -pub use address::PlatformAddressWasm; +pub use address::{PlatformAddressLikeArrayJs, PlatformAddressLikeJs, PlatformAddressWasm}; pub use fee_strategy::{ FeeStrategyStepWasm, default_fee_strategy, fee_strategy_from_steps, fee_strategy_from_steps_or_default, diff --git a/packages/wasm-dpp2/src/platform_address/signer.rs b/packages/wasm-dpp2/src/platform_address/signer.rs index 3d11b9a0e85..e7e288ade5f 100644 --- a/packages/wasm-dpp2/src/platform_address/signer.rs +++ b/packages/wasm-dpp2/src/platform_address/signer.rs @@ -1,8 +1,9 @@ -use super::PlatformAddressWasm; +use super::{PlatformAddressLikeJs, PlatformAddressWasm}; use crate::core::private_key::PrivateKeyWasm; use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; use crate::impl_try_from_options; -use crate::utils::IntoWasm; +use crate::impl_wasm_type_info; use dpp::ProtocolError; use dpp::address_funds::{AddressWitness, PlatformAddress}; use dpp::dashcore::signer; @@ -35,7 +36,7 @@ impl fmt::Debug for PlatformAddressSignerWasm { impl PlatformAddressSignerWasm { /// Creates a new empty PlatformAddressSigner. #[wasm_bindgen(constructor)] - pub fn new() -> PlatformAddressSignerWasm { + pub fn constructor() -> PlatformAddressSignerWasm { PlatformAddressSignerWasm { private_keys: BTreeMap::new(), } @@ -48,7 +49,10 @@ impl PlatformAddressSignerWasm { /// @param privateKey - The PrivateKey object /// @returns The derived Platform address #[wasm_bindgen(js_name = "addKey")] - pub fn add_key(&mut self, private_key: &PrivateKeyWasm) -> WasmDppResult { + pub fn add_key( + &mut self, + #[wasm_bindgen(js_name = "privateKey")] private_key: &PrivateKeyWasm, + ) -> WasmDppResult { let platform_address = PlatformAddressWasm::from(PlatformAddress::from(private_key.inner())); self.private_keys @@ -56,17 +60,6 @@ impl PlatformAddressSignerWasm { Ok(platform_address) } - /// Returns the type name for WASM object identification (instance getter). - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "PlatformAddressSigner".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "PlatformAddressSigner".to_string() - } - /// Returns the number of keys in this signer. #[wasm_bindgen(getter = keyCount)] pub fn key_count(&self) -> usize { @@ -75,11 +68,8 @@ impl PlatformAddressSignerWasm { /// Returns true if this signer has a key for the given address. #[wasm_bindgen(js_name = "hasKey")] - pub fn has_key( - &self, - #[wasm_bindgen(unchecked_param_type = "PlatformAddressLike")] address: &JsValue, - ) -> WasmDppResult { - let platform_address = PlatformAddressWasm::try_from(address)?; + pub fn has_key(&self, address: PlatformAddressLikeJs) -> WasmDppResult { + let platform_address: PlatformAddressWasm = address.try_into()?; Ok(self.private_keys.contains_key(&platform_address)) } @@ -153,15 +143,6 @@ impl PlatformAddressSignerWasm { } } -impl_try_from_options!(PlatformAddressSignerWasm, "PlatformAddressSigner", "signer"); - -impl TryFrom<&JsValue> for PlatformAddressSignerWasm { - type Error = WasmDppError; - - fn try_from(value: &JsValue) -> Result { - value - .to_wasm::("PlatformAddressSigner") - .map(|boxed| (*boxed).clone()) - .map_err(|_| WasmDppError::invalid_argument("Expected a PlatformAddressSigner object")) - } -} +impl_try_from_js_value!(PlatformAddressSignerWasm, "PlatformAddressSigner"); +impl_try_from_options!(PlatformAddressSignerWasm); +impl_wasm_type_info!(PlatformAddressSignerWasm, PlatformAddressSigner); diff --git a/packages/wasm-dpp2/src/public_key.rs b/packages/wasm-dpp2/src/public_key.rs index 588e52895b9..abd1dfc8d01 100644 --- a/packages/wasm-dpp2/src/public_key.rs +++ b/packages/wasm-dpp2/src/public_key.rs @@ -1,4 +1,5 @@ use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_wasm_type_info; use dpp::dashcore::key::constants; use dpp::dashcore::{PublicKey, secp256k1}; use std::convert::TryInto; @@ -21,52 +22,38 @@ impl From for PublicKey { #[wasm_bindgen(js_class = PublicKey)] impl PublicKeyWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "PublicKey".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "PublicKey".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(compressed: bool, public_key_bytes: Vec) -> WasmDppResult { - let inner = match compressed { - true => { - if public_key_bytes.len() != constants::PUBLIC_KEY_SIZE { - return Err(WasmDppError::invalid_argument(format!( - "compressed public key size must be equal to {}", - constants::PUBLIC_KEY_SIZE - ))); - } - - let bytes: [u8; constants::PUBLIC_KEY_SIZE] = - public_key_bytes.try_into().map_err(|_| { - WasmDppError::invalid_argument( - "compressed public key must contain 33 bytes", - ) - })?; - secp256k1::PublicKey::from_byte_array_compressed(&bytes) + pub fn constructor( + compressed: bool, + #[wasm_bindgen(js_name = "publicKeyBytes")] public_key_bytes: Vec, + ) -> WasmDppResult { + let inner = if compressed { + if public_key_bytes.len() != constants::PUBLIC_KEY_SIZE { + return Err(WasmDppError::invalid_argument(format!( + "compressed public key size must be equal to {}", + constants::PUBLIC_KEY_SIZE + ))); } - false => { - if public_key_bytes.len() != constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { - return Err(WasmDppError::invalid_argument(format!( - "uncompressed public key size must be equal to {}", - constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - ))); - } - - let bytes: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = - public_key_bytes.try_into().map_err(|_| { - WasmDppError::invalid_argument( - "uncompressed public key must contain 65 bytes", - ) - })?; - - secp256k1::PublicKey::from_byte_array_uncompressed(&bytes) + + let bytes: [u8; constants::PUBLIC_KEY_SIZE] = + public_key_bytes.try_into().map_err(|_| { + WasmDppError::invalid_argument("compressed public key must contain 33 bytes") + })?; + secp256k1::PublicKey::from_byte_array_compressed(&bytes) + } else { + if public_key_bytes.len() != constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { + return Err(WasmDppError::invalid_argument(format!( + "uncompressed public key size must be equal to {}", + constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + ))); } + + let bytes: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = + public_key_bytes.try_into().map_err(|_| { + WasmDppError::invalid_argument("uncompressed public key must contain 65 bytes") + })?; + + secp256k1::PublicKey::from_byte_array_uncompressed(&bytes) } .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; @@ -80,9 +67,10 @@ impl PublicKeyWasm { #[wasm_bindgen(getter = "inner")] pub fn inner(&self) -> Vec { - match self.0.compressed { - true => self.0.inner.serialize().into(), - false => self.0.inner.serialize_uncompressed().into(), + if self.0.compressed { + self.0.inner.serialize().into() + } else { + self.0.inner.serialize_uncompressed().into() } } @@ -122,7 +110,7 @@ impl PublicKeyWasm { Ok(()) } - #[wasm_bindgen(js_name = getPublicKeyHash)] + #[wasm_bindgen(js_name = "getPublicKeyHash")] pub fn get_public_key_hash(&self) -> String { self.0.pubkey_hash().to_hex() } @@ -140,3 +128,5 @@ impl PublicKeyWasm { )) } } + +impl_wasm_type_info!(PublicKeyWasm, PublicKey); diff --git a/packages/wasm-dpp2/src/serialization/conversions.rs b/packages/wasm-dpp2/src/serialization/conversions.rs index a106b2f6cb7..a740036b8dc 100644 --- a/packages/wasm-dpp2/src/serialization/conversions.rs +++ b/packages/wasm-dpp2/src/serialization/conversions.rs @@ -44,7 +44,7 @@ fn try_call_to_json(value: &JsValue) -> Option { return None; } - let func: js_sys::Function = to_json_fn.unchecked_into(); + let func: js_sys::Function = to_json_fn.into(); func.call0(value).ok() } @@ -100,7 +100,7 @@ fn normalize_js_value_for_json(value: &JsValue) -> WasmDppResult { // Convert BigInt to string (JSON doesn't support BigInt) if value.is_bigint() { - let bigint: js_sys::BigInt = value.clone().unchecked_into(); + let bigint: js_sys::BigInt = value.clone().into(); let bigint_str = bigint .to_string(10) .map(|s| s.into()) @@ -110,7 +110,7 @@ fn normalize_js_value_for_json(value: &JsValue) -> WasmDppResult { // Convert Uint8Array to plain array for JSON compatibility if value.is_instance_of::() { - let uint8_array: js_sys::Uint8Array = value.clone().unchecked_into(); + let uint8_array: js_sys::Uint8Array = value.clone().into(); let plain_array = js_sys::Array::from(&uint8_array); return Ok(plain_array.into()); } @@ -181,7 +181,7 @@ fn map_key_to_string(key: &JsValue) -> String { // BigInt keys - convert to string if key.is_bigint() { - let bigint: js_sys::BigInt = key.clone().unchecked_into(); + let bigint: js_sys::BigInt = key.clone().into(); return bigint .to_string(10) .map(|s| s.into()) @@ -192,7 +192,7 @@ fn map_key_to_string(key: &JsValue) -> String { if let Ok(to_string_fn) = js_sys::Reflect::get(key, &JsValue::from_str("toString")) && to_string_fn.is_function() { - let func: js_sys::Function = to_string_fn.unchecked_into(); + let func: js_sys::Function = to_string_fn.into(); if let Ok(str_result) = func.call0(key) && let Some(s) = str_result.as_string() { @@ -206,7 +206,7 @@ fn map_key_to_string(key: &JsValue) -> String { /// Convert a JavaScript Map to a plain object for JSON serialization. fn normalize_map_for_json(value: &JsValue) -> WasmDppResult { - let map: js_sys::Map = value.clone().unchecked_into(); + let map: js_sys::Map = value.clone().into(); let new_obj = Object::new(); // We need to collect errors from the closure since for_each doesn't support Result @@ -354,8 +354,10 @@ fn convert_value_for_json(value: &platform_value::Value) -> platform_value::Valu /// /// serde-wasm-bindgen's deserialize_any handles Uint8Array via visit_byte_buf, which creates /// Value::Bytes. BigInt is handled via visit_i64/visit_u64. -pub fn platform_value_from_object(value: JsValue) -> WasmDppResult { - serde_wasm_bindgen::from_value(value) +/// +/// Takes `&JsValue` to allow Deref coercion from js_sys types. +pub fn platform_value_from_object(value: &JsValue) -> WasmDppResult { + serde_wasm_bindgen::from_value(value.clone()) .map_err(|e| WasmDppError::serialization(format!("platform_value_from_object: {}", e))) } @@ -386,7 +388,7 @@ pub fn js_value_to_platform_value(value: &JsValue) -> WasmDppResult WasmDppResult() { - let uint8_array: js_sys::Uint8Array = value.clone().unchecked_into(); + let uint8_array: js_sys::Uint8Array = value.clone().into(); let bytes = uint8_array.to_vec(); // Check for identifier (32 bytes) if bytes.len() == 32 { @@ -443,8 +445,8 @@ pub fn js_value_to_platform_value(value: &JsValue) -> WasmDppResult WasmDppResult Result { let json_value = js_value_to_json(value)?; json_to_js_value(&json_value) @@ -489,37 +491,39 @@ pub fn test_js_value_to_json(value: &JsValue) -> Result { /// # Usage /// /// ```ignore -/// // For newtype wrappers: WrapperType(InnerType) -/// // JS class name defaults to Rust type name without "Wasm" suffix +/// // Basic form: returns JsValue for all methods /// impl_wasm_conversions!(MyTypeWasm, MyType); +/// +/// // With typed return types for better TypeScript support: +/// impl_wasm_conversions!(MyTypeWasm, MyType, MyTypeObjectJs, MyTypeJSONJs); /// ``` /// /// The inner type must implement `Serialize` and `DeserializeOwned`. /// The wrapper type must implement `From` and have a `.0` field. #[macro_export] macro_rules! impl_wasm_conversions { - // Two-argument form: wrapper type and JS class name + // Two-argument form: wrapper type and JS class name (returns JsValue) ($wrapper:ty, $js_class:ident) => { #[wasm_bindgen::prelude::wasm_bindgen(js_class = $js_class)] impl $wrapper { - #[wasm_bindgen::prelude::wasm_bindgen(js_name = toObject)] + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "toObject")] pub fn to_object(&self) -> Result { $crate::serialization::conversions::to_object(&self.0) } - #[wasm_bindgen::prelude::wasm_bindgen(js_name = fromObject)] + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "fromObject")] pub fn from_object( obj: wasm_bindgen::JsValue, ) -> Result<$wrapper, $crate::error::WasmDppError> { $crate::serialization::conversions::from_object(obj).map(Self) } - #[wasm_bindgen::prelude::wasm_bindgen(js_name = toJSON)] + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "toJSON")] pub fn to_json(&self) -> Result { $crate::serialization::conversions::to_json(&self.0) } - #[wasm_bindgen::prelude::wasm_bindgen(js_name = fromJSON)] + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "fromJSON")] pub fn from_json( js: wasm_bindgen::JsValue, ) -> Result<$wrapper, $crate::error::WasmDppError> { @@ -527,4 +531,30 @@ macro_rules! impl_wasm_conversions { } } }; + + // Four-argument form: with typed Object and JSON return types + ($wrapper:ty, $js_class:ident, $object_type:ty, $json_type:ty) => { + #[wasm_bindgen::prelude::wasm_bindgen(js_class = $js_class)] + impl $wrapper { + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "toObject")] + pub fn to_object(&self) -> Result<$object_type, $crate::error::WasmDppError> { + $crate::serialization::conversions::to_object(&self.0).map(Into::into) + } + + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "fromObject")] + pub fn from_object(obj: $object_type) -> Result<$wrapper, $crate::error::WasmDppError> { + $crate::serialization::conversions::from_object(obj.into()).map(Self) + } + + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "toJSON")] + pub fn to_json(&self) -> Result<$json_type, $crate::error::WasmDppError> { + $crate::serialization::conversions::to_json(&self.0).map(Into::into) + } + + #[wasm_bindgen::prelude::wasm_bindgen(js_name = "fromJSON")] + pub fn from_json(js: $json_type) -> Result<$wrapper, $crate::error::WasmDppError> { + $crate::serialization::conversions::from_json(js.into()).map(Self) + } + } + }; } diff --git a/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info.rs b/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info.rs index 2e6e5ca29bb..54bc9f2dbec 100644 --- a/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info.rs +++ b/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info.rs @@ -1,12 +1,40 @@ -use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::utils::try_from_options; use dpp::group::GroupStateTransitionInfo; -use dpp::prelude::Identifier; -use wasm_bindgen::JsValue; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct GroupStateTransitionInfoOptionsSerde { + group_contract_position: u16, + #[serde(default)] + is_action_proposer: bool, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Options for creating a GroupStateTransitionInfo instance. + */ +export interface GroupStateTransitionInfoOptions { + groupContractPosition: number; + actionId: IdentifierLike; + isActionProposer?: boolean; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "GroupStateTransitionInfoOptions")] + pub type GroupStateTransitionInfoOptionsJs; +} + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=GroupStateTransitionInfo)] +#[wasm_bindgen(js_name = "GroupStateTransitionInfo")] pub struct GroupStateTransitionInfoWasm(GroupStateTransitionInfo); impl From for GroupStateTransitionInfo { @@ -23,64 +51,65 @@ impl From for GroupStateTransitionInfoWasm { #[wasm_bindgen(js_class = GroupStateTransitionInfo)] impl GroupStateTransitionInfoWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "GroupStateTransitionInfo".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "GroupStateTransitionInfo".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - group_contract_position: u16, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - action_id: &JsValue, - action_is_proposer: bool, + pub fn constructor( + options: GroupStateTransitionInfoOptionsJs, ) -> WasmDppResult { - let action_id: Identifier = IdentifierWasm::try_from(action_id)?.into(); + // Extract complex types first (borrows &options) + let action_id: IdentifierWasm = try_from_options(&options, "actionId")?; + + // Deserialize primitive fields via serde (consumes options) + let opts: GroupStateTransitionInfoOptionsSerde = + serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(GroupStateTransitionInfoWasm(GroupStateTransitionInfo { - group_contract_position, - action_id, - action_is_proposer, + group_contract_position: opts.group_contract_position, + action_id: action_id.into(), + action_is_proposer: opts.is_action_proposer, })) } #[wasm_bindgen(setter = "groupContractPosition")] - pub fn set_group_contract_position(&mut self, group_contract_position: u16) { + pub fn set_group_contract_position( + &mut self, + #[wasm_bindgen(js_name = "groupContractPosition")] group_contract_position: u16, + ) { self.0.group_contract_position = group_contract_position; } #[wasm_bindgen(setter = "actionId")] pub fn set_action_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - action_id: &JsValue, + #[wasm_bindgen(js_name = "actionId")] action_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - self.0.action_id = IdentifierWasm::try_from(action_id)?.into(); + self.0.action_id = action_id.try_into()?; Ok(()) } - #[wasm_bindgen(setter = "actionIsProposer")] - pub fn set_action_is_proposer(&mut self, action_is_proposer: bool) { - self.0.action_is_proposer = action_is_proposer; + #[wasm_bindgen(setter = "isActionProposer")] + pub fn set_is_action_proposer( + &mut self, + #[wasm_bindgen(js_name = "isActionProposer")] is_action_proposer: bool, + ) { + self.0.action_is_proposer = is_action_proposer; } #[wasm_bindgen(getter = "groupContractPosition")] - pub fn get_group_contract_position(&mut self) -> u16 { + pub fn group_contract_position(&self) -> u16 { self.0.group_contract_position } #[wasm_bindgen(getter = "actionId")] - pub fn get_action_id(&self) -> IdentifierWasm { + pub fn action_id(&self) -> IdentifierWasm { self.0.action_id.into() } - #[wasm_bindgen(getter = "actionIsProposer")] - pub fn get_action_is_proposer(&self) -> bool { + #[wasm_bindgen(getter = "isActionProposer")] + pub fn is_action_proposer(&self) -> bool { self.0.action_is_proposer } } + +impl_try_from_js_value!(GroupStateTransitionInfoWasm, "GroupStateTransitionInfo"); +impl_wasm_type_info!(GroupStateTransitionInfoWasm, GroupStateTransitionInfo); diff --git a/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info_status.rs b/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info_status.rs index 1e7a68cea5e..81d1c2bf60a 100644 --- a/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info_status.rs +++ b/packages/wasm-dpp2/src/state_transitions/base/group_state_transition_info_status.rs @@ -3,14 +3,15 @@ //! This module provides WASM bindings for the GroupStateTransitionInfoStatus enum, //! which represents group action context for state transitions. -use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::error::WasmDppResult; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_try_from_options; +use crate::impl_wasm_type_info; use crate::state_transitions::base::GroupStateTransitionInfoWasm; -use crate::utils::IntoWasm; use dpp::data_contract::GroupContractPosition; use dpp::group::{GroupStateTransitionInfo, GroupStateTransitionInfoStatus}; use dpp::prelude::Identifier; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; /// Wrapper for GroupStateTransitionInfoStatus enum. @@ -19,7 +20,7 @@ use wasm_bindgen::prelude::wasm_bindgen; /// - Proposer: The identity proposing a new group action /// - OtherSigner: The identity signing/voting on an existing group action #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name = GroupStateTransitionInfoStatus)] +#[wasm_bindgen(js_name = "GroupStateTransitionInfoStatus")] pub struct GroupStateTransitionInfoStatusWasm(GroupStateTransitionInfoStatus); impl From for GroupStateTransitionInfoStatus { @@ -36,16 +37,6 @@ impl From for GroupStateTransitionInfoStatusWasm #[wasm_bindgen(js_class = GroupStateTransitionInfoStatus)] impl GroupStateTransitionInfoStatusWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "GroupStateTransitionInfoStatus".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "GroupStateTransitionInfoStatus".to_string() - } - /// Create a new proposer status for initiating a group action. /// /// Use this when the identity is proposing a new group action. @@ -53,7 +44,9 @@ impl GroupStateTransitionInfoStatusWasm { /// @param groupContractPosition - The position of the group in the contract /// @returns GroupStateTransitionInfoStatus for a proposer #[wasm_bindgen(js_name = "proposer")] - pub fn proposer(group_contract_position: u16) -> GroupStateTransitionInfoStatusWasm { + pub fn proposer( + #[wasm_bindgen(js_name = "groupContractPosition")] group_contract_position: u16, + ) -> GroupStateTransitionInfoStatusWasm { GroupStateTransitionInfoStatusWasm( GroupStateTransitionInfoStatus::GroupStateTransitionInfoProposer( group_contract_position, @@ -70,11 +63,10 @@ impl GroupStateTransitionInfoStatusWasm { /// @returns GroupStateTransitionInfoStatus for an other signer #[wasm_bindgen(js_name = "otherSigner")] pub fn other_signer( - group_contract_position: u16, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - action_id: &JsValue, + #[wasm_bindgen(js_name = "groupContractPosition")] group_contract_position: u16, + #[wasm_bindgen(js_name = "actionId")] action_id: IdentifierLikeJs, ) -> WasmDppResult { - let action_id: Identifier = IdentifierWasm::try_from(action_id)?.into(); + let action_id: Identifier = action_id.try_into()?; Ok(GroupStateTransitionInfoStatusWasm( GroupStateTransitionInfoStatus::GroupStateTransitionInfoOtherSigner( @@ -127,39 +119,12 @@ impl GroupStateTransitionInfoStatusWasm { } } -impl GroupStateTransitionInfoStatusWasm { - /// Try to extract a GroupStateTransitionInfoStatus from an options object field. - pub fn try_from_options(options: &JsValue, field_name: &str) -> WasmDppResult { - let field_value = js_sys::Reflect::get(options, &JsValue::from_str(field_name)) - .map_err(|_| WasmDppError::invalid_argument(format!("{} is required", field_name)))?; - - if field_value.is_undefined() || field_value.is_null() { - return Err(WasmDppError::invalid_argument(format!( - "'{}' is required", - field_name - ))); - } - - // Try to convert using the IntoWasm helper - field_value - .to_wasm::("GroupStateTransitionInfoStatus") - .map(|boxed| boxed.clone()) - } - - /// Try to extract an optional GroupStateTransitionInfoStatus from an options object field. - pub fn try_from_optional_options( - options: &JsValue, - field_name: &str, - ) -> WasmDppResult> { - let field_value = - js_sys::Reflect::get(options, &JsValue::from_str(field_name)).map_err(|_| { - WasmDppError::invalid_argument(format!("Failed to access {}", field_name)) - })?; - - if field_value.is_undefined() || field_value.is_null() { - return Ok(None); - } - - Self::try_from_options(options, field_name).map(Some) - } -} +impl_try_from_js_value!( + GroupStateTransitionInfoStatusWasm, + "GroupStateTransitionInfoStatus" +); +impl_try_from_options!(GroupStateTransitionInfoStatusWasm); +impl_wasm_type_info!( + GroupStateTransitionInfoStatusWasm, + GroupStateTransitionInfoStatus +); diff --git a/packages/wasm-dpp2/src/state_transitions/base/state_transition.rs b/packages/wasm-dpp2/src/state_transitions/base/state_transition.rs index fbd2a28ce35..604bcdea71e 100644 --- a/packages/wasm-dpp2/src/state_transitions/base/state_transition.rs +++ b/packages/wasm-dpp2/src/state_transitions/base/state_transition.rs @@ -3,8 +3,9 @@ use crate::enums::keys::key_type::KeyTypeWasm; use crate::enums::keys::purpose::PurposeWasm; use crate::enums::keys::security_level::SecurityLevelWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::identity::public_key::IdentityPublicKeyWasm; +use crate::impl_wasm_type_info; use crate::mock_bls::MockBLS; use dpp::dashcore::secp256k1::hashes::hex::Case::Lower; use dpp::dashcore::secp256k1::hashes::hex::DisplayHex; @@ -67,21 +68,11 @@ impl From<&StateTransitionWasm> for StateTransition { #[wasm_bindgen(js_class = StateTransition)] impl StateTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "StateTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "StateTransition".to_string() - } - #[wasm_bindgen(js_name = "sign")] pub fn sign( &mut self, - private_key: &PrivateKeyWasm, - public_key: &IdentityPublicKeyWasm, + #[wasm_bindgen(js_name = "privateKey")] private_key: &PrivateKeyWasm, + #[wasm_bindgen(js_name = "publicKey")] public_key: &IdentityPublicKeyWasm, ) -> WasmDppResult> { self.0.sign( &public_key.clone().into(), @@ -110,14 +101,14 @@ impl StateTransitionWasm { #[wasm_bindgen(js_name = "signByPrivateKey")] pub fn sign_by_private_key( &mut self, - private_key: &PrivateKeyWasm, - key_id: Option, - js_key_type: JsValue, + #[wasm_bindgen(js_name = "privateKey")] private_key: &PrivateKeyWasm, + #[wasm_bindgen(js_name = "keyId")] key_id: Option, + #[wasm_bindgen(js_name = "keyType")] key_type: JsValue, ) -> WasmDppResult> { - let key_type = if js_key_type.is_undefined() { + let key_type = if key_type.is_undefined() { KeyTypeWasm::ECDSA_SECP256K1 } else { - KeyTypeWasm::try_from(js_key_type)? + KeyTypeWasm::try_from(key_type)? }; self.0.sign_by_private_key( @@ -136,13 +127,15 @@ impl StateTransitionWasm { #[wasm_bindgen(js_name = "verifyPublicKey")] pub fn verify_public_key( &self, - public_key: &IdentityPublicKeyWasm, - js_allow_signing_with_any_security_level: Option, - js_allow_signing_with_any_purpose: Option, + #[wasm_bindgen(js_name = "publicKey")] public_key: &IdentityPublicKeyWasm, + #[wasm_bindgen(js_name = "allowSigningWithAnySecurityLevel")] + allow_signing_with_any_security_level: Option, + #[wasm_bindgen(js_name = "allowSigningWithAnyPurpose")] + allow_signing_with_any_purpose: Option, ) -> WasmDppResult<()> { let allow_signing_with_any_security_level = - js_allow_signing_with_any_security_level.unwrap_or(false); - let allow_signing_with_any_purpose = js_allow_signing_with_any_purpose.unwrap_or(false); + allow_signing_with_any_security_level.unwrap_or(false); + let allow_signing_with_any_purpose = allow_signing_with_any_purpose.unwrap_or(false); match &self.0 { DataContractCreate(st) => { @@ -229,24 +222,20 @@ impl StateTransitionWasm { } #[wasm_bindgen(js_name = "toBytes")] - pub fn to_bytes(&self) -> WasmDppResult { - let bytes = self.0.serialize_to_bytes()?; - - Ok(JsValue::from(bytes.clone())) + pub fn to_bytes(&self) -> WasmDppResult> { + Ok(self.0.serialize_to_bytes()?) } #[wasm_bindgen(js_name = "toHex")] - pub fn to_hex(&self) -> WasmDppResult { + pub fn to_hex(&self) -> WasmDppResult { let bytes = self.0.serialize_to_bytes()?; - - Ok(JsValue::from(encode(bytes.as_slice(), Encoding::Hex))) + Ok(encode(bytes.as_slice(), Encoding::Hex)) } #[wasm_bindgen(js_name = "toBase64")] - pub fn to_base64(&self) -> WasmDppResult { + pub fn to_base64(&self) -> WasmDppResult { let bytes = self.0.serialize_to_bytes()?; - - Ok(JsValue::from(encode(bytes.as_slice(), Encoding::Base64))) + Ok(encode(bytes.as_slice(), Encoding::Base64)) } #[wasm_bindgen(js_name = "fromBytes")] @@ -277,7 +266,10 @@ impl StateTransitionWasm { } #[wasm_bindgen(js_name = "hash")] - pub fn get_hash(&self, skip_signature: bool) -> WasmDppResult { + pub fn get_hash( + &self, + #[wasm_bindgen(js_name = "skipSignature")] skip_signature: bool, + ) -> WasmDppResult { let payload = if skip_signature { self.0.signable_bytes()? } else { @@ -287,13 +279,13 @@ impl StateTransitionWasm { Ok(Sha256::digest(payload).to_hex_string(Lower)) } - #[wasm_bindgen(js_name = "getActionType")] - pub fn get_action_type(&self) -> String { + #[wasm_bindgen(getter = "actionType")] + pub fn action_type(&self) -> String { self.0.name() } - #[wasm_bindgen(js_name = "getActionTypeNumber")] - pub fn get_action_type_number(&self) -> u8 { + #[wasm_bindgen(getter = "actionTypeNumber")] + pub fn action_type_number(&self) -> u8 { use StateTransition::*; match self.0 { DataContractCreate(_) => 0, @@ -314,28 +306,28 @@ impl StateTransitionWasm { } } - #[wasm_bindgen(js_name = "getOwnerId")] - pub fn get_owner_id(&self) -> Option { + #[wasm_bindgen(getter = "ownerId")] + pub fn owner_id(&self) -> Option { self.0.owner_id().map(Into::into) } #[wasm_bindgen(getter = "signature")] - pub fn get_signature(&self) -> Option> { + pub fn signature(&self) -> Option> { self.0.signature().map(BinaryData::to_vec) } #[wasm_bindgen(getter = "signaturePublicKeyId")] - pub fn get_signature_public_key_id(&self) -> Option { + pub fn signature_public_key_id(&self) -> Option { self.0.signature_public_key_id() } #[wasm_bindgen(getter = "userFeeIncrease")] - pub fn get_user_fee_increase(&self) -> UserFeeIncrease { + pub fn user_fee_increase(&self) -> UserFeeIncrease { self.0.user_fee_increase() } - #[wasm_bindgen(js_name = "getPurposeRequirement")] - pub fn get_purpose_requirement(&self) -> Option> { + #[wasm_bindgen(getter = "purposeRequirement")] + pub fn purpose_requirement(&self) -> Option> { let requirements = self.0.purpose_requirement(); requirements.map(|req| { @@ -349,9 +341,9 @@ impl StateTransitionWasm { #[wasm_bindgen(js_name = "getKeyLevelRequirement")] pub fn get_key_level_requirement( &self, - js_purpose: &JsValue, + purpose: &JsValue, ) -> WasmDppResult>> { - let purpose = PurposeWasm::try_from(js_purpose.clone())?; + let purpose = PurposeWasm::try_from(purpose.clone())?; let requirements = self.0.security_level_requirement(purpose.into()); @@ -366,8 +358,8 @@ impl StateTransitionWasm { } } - #[wasm_bindgen(js_name = "getIdentityContractNonce")] - pub fn get_identity_contract_nonce(&self) -> Option { + #[wasm_bindgen(getter = "identityContractNonce")] + pub fn identity_contract_nonce(&self) -> Option { use StateTransition::*; match &self.0 { DataContractCreate(_) => None, @@ -398,8 +390,8 @@ impl StateTransitionWasm { } } - #[wasm_bindgen(js_name = "getIdentityNonce")] - pub fn get_identity_nonce(&self) -> Option { + #[wasm_bindgen(getter = "identityNonce")] + pub fn identity_nonce(&self) -> Option { use StateTransition::*; match &self.0 { DataContractCreate(contract_create) => Some(contract_create.identity_nonce()), @@ -426,23 +418,28 @@ impl StateTransitionWasm { } #[wasm_bindgen(setter = "signaturePublicKeyId")] - pub fn set_signature_public_key_id(&mut self, key_id: KeyID) { + pub fn set_signature_public_key_id( + &mut self, + #[wasm_bindgen(js_name = "keyId")] key_id: KeyID, + ) { self.0.set_signature_public_key_id(key_id) } #[wasm_bindgen(setter = "userFeeIncrease")] - pub fn set_user_fee_increase(&mut self, user_fee_increase: UserFeeIncrease) { + pub fn set_user_fee_increase( + &mut self, + #[wasm_bindgen(js_name = "userFeeIncrease")] user_fee_increase: UserFeeIncrease, + ) { self.0.set_user_fee_increase(user_fee_increase) } #[wasm_bindgen(js_name = "setOwnerId")] pub fn set_owner_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_owner_id: &JsValue, + #[wasm_bindgen(js_name = "ownerId")] owner_id: IdentifierLikeJs, ) -> WasmDppResult<()> { use dpp::state_transition::StateTransition::*; - let owner_id: Identifier = IdentifierWasm::try_from(js_owner_id)?.into(); + let owner_id: Identifier = owner_id.try_into()?; match self.0.clone() { DataContractCreate(mut contract_create) => { @@ -555,7 +552,9 @@ impl StateTransitionWasm { } #[wasm_bindgen(js_name = "setIdentityContractNonce")] - pub fn set_identity_contract_nonce(&mut self, nonce: IdentityNonce) -> WasmDppResult<()> { + pub fn set_identity_contract_nonce(&mut self, nonce: JsValue) -> WasmDppResult<()> { + use crate::utils::try_to_u64; + let nonce: IdentityNonce = try_to_u64(&nonce, "identityContractNonce")?; use StateTransition::*; self.0 = match self.0.clone() { DataContractCreate(_) => { @@ -621,7 +620,9 @@ impl StateTransitionWasm { } #[wasm_bindgen(js_name = "setIdentityNonce")] - pub fn set_identity_nonce(&mut self, nonce: IdentityNonce) -> WasmDppResult<()> { + pub fn set_identity_nonce(&mut self, nonce: JsValue) -> WasmDppResult<()> { + use crate::utils::try_to_u64; + let nonce: IdentityNonce = try_to_u64(&nonce, "identityNonce")?; use StateTransition::*; self.0 = match self.0.clone() { DataContractCreate(mut contract_create) => { @@ -706,3 +707,5 @@ impl StateTransitionWasm { Ok(()) } } + +impl_wasm_type_info!(StateTransitionWasm, StateTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/batch_transition.rs b/packages/wasm-dpp2/src/state_transitions/batch/batch_transition.rs index 5496004bc46..65800ce2209 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/batch_transition.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/batch_transition.rs @@ -1,15 +1,16 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_wasm_type_info; use crate::serialization; use crate::state_transitions::StateTransitionWasm; use crate::state_transitions::batch::batched_transition::BatchedTransitionWasm; -use crate::utils::IntoWasm; +use crate::utils::{IntoWasm, try_to_u32, try_to_u64}; use dpp::fee::Credits; use dpp::identity::KeyID; use dpp::platform_value::BinaryData; use dpp::platform_value::string_encoding::Encoding::{Base64, Hex}; use dpp::platform_value::string_encoding::{decode, encode}; -use dpp::prelude::{IdentityNonce, UserFeeIncrease}; +use dpp::prelude::UserFeeIncrease; use dpp::serialization::{PlatformDeserializable, PlatformSerializable}; use dpp::state_transition::batch_transition::accessors::DocumentsBatchTransitionAccessorsV0; use dpp::state_transition::batch_transition::batched_transition::BatchedTransition; @@ -21,8 +22,45 @@ use dpp::state_transition::{ }; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * BatchTransition serialized as a plain object. + */ +export interface BatchTransitionObject { + $formatVersion: string; + ownerId: Uint8Array; + transitions: BatchedTransitionObject[]; + userFeeIncrease: number; + signaturePublicKeyId: number; + signature: Uint8Array; +} + +/** + * BatchTransition serialized as JSON. + */ +export interface BatchTransitionJSON { + $formatVersion: string; + ownerId: string; + transitions: BatchedTransitionJSON[]; + userFeeIncrease: number; + signaturePublicKeyId: number; + signature: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "BatchTransitionObject")] + pub type BatchTransitionObjectJs; + + #[wasm_bindgen(typescript_type = "BatchTransitionJSON")] + pub type BatchTransitionJSONJs; +} + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=BatchTransition)] +#[wasm_bindgen(js_name = "BatchTransition")] pub struct BatchTransitionWasm(BatchTransition); impl From for BatchTransitionWasm { @@ -38,16 +76,16 @@ impl From for BatchTransition { } fn convert_array_to_vec_batched( - js_batched_transitions: &js_sys::Array, + batched_transitions: &js_sys::Array, ) -> WasmDppResult> { - let mut transitions = Vec::with_capacity(js_batched_transitions.length() as usize); + let mut transitions = Vec::with_capacity(batched_transitions.length() as usize); - for js_batched_transition in js_batched_transitions.iter() { - let batched_transition: BatchedTransitionWasm = js_batched_transition + for batched_transition in batched_transitions.iter() { + let transition: BatchedTransitionWasm = batched_transition .to_wasm::("BatchedTransition")? .clone(); - transitions.push(BatchedTransition::from(batched_transition)); + transitions.push(BatchedTransition::from(transition)); } Ok(transitions) @@ -55,28 +93,17 @@ fn convert_array_to_vec_batched( #[wasm_bindgen(js_class = BatchTransition)] impl BatchTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "BatchTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "BatchTransition".to_string() - } - #[wasm_bindgen(js_name = "fromBatchedTransitions")] pub fn from_batched_transitions( - js_batched_transitions: &js_sys::Array, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - owner_id: &JsValue, - user_fee_increase: UserFeeIncrease, + #[wasm_bindgen(js_name = "batchedTransitions")] batched_transitions: &js_sys::Array, + #[wasm_bindgen(js_name = "ownerId")] owner_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "userFeeIncrease")] user_fee_increase: UserFeeIncrease, ) -> WasmDppResult { - let transitions = convert_array_to_vec_batched(js_batched_transitions)?; + let transitions = convert_array_to_vec_batched(batched_transitions)?; Ok(BatchTransitionWasm(BatchTransition::V1( BatchTransitionV1 { - owner_id: IdentifierWasm::try_from(owner_id)?.into(), + owner_id: owner_id.try_into()?, transitions, user_fee_increase, signature_public_key_id: 0u32, @@ -86,7 +113,7 @@ impl BatchTransitionWasm { } #[wasm_bindgen(getter = "transitions")] - pub fn get_batched_transitions(&self) -> Vec { + pub fn batched_transitions(&self) -> Vec { self.0 .transitions_iter() .map(|transition| BatchedTransitionWasm::from(transition.to_owned_transition())) @@ -94,35 +121,38 @@ impl BatchTransitionWasm { } #[wasm_bindgen(setter = "transitions")] - pub fn set_transitions(&mut self, js_batched_transitions: &js_sys::Array) -> WasmDppResult<()> { - let transitions = convert_array_to_vec_batched(js_batched_transitions)?; + pub fn set_transitions( + &mut self, + #[wasm_bindgen(js_name = "batchedTransitions")] batched_transitions: &js_sys::Array, + ) -> WasmDppResult<()> { + let transitions = convert_array_to_vec_batched(batched_transitions)?; self.0.set_transitions(transitions); Ok(()) } #[wasm_bindgen(getter = "signature")] - pub fn get_signature(&self) -> Vec { + pub fn signature(&self) -> Vec { self.0.signature().to_vec() } #[wasm_bindgen(getter = "signaturePublicKeyId")] - pub fn get_signature_public_key_id(&self) -> KeyID { + pub fn signature_public_key_id(&self) -> KeyID { self.0.signature_public_key_id() } #[wasm_bindgen(getter = "allPurchasesAmount")] - pub fn get_all_purchases_amount(&self) -> WasmDppResult> { + pub fn all_purchases_amount(&self) -> WasmDppResult> { self.0.all_document_purchases_amount().map_err(Into::into) } #[wasm_bindgen(getter = "ownerId")] - pub fn get_owner_id(&self) -> IdentifierWasm { + pub fn owner_id(&self) -> IdentifierWasm { self.0.owner_id().into() } #[wasm_bindgen(getter = "modifiedDataIds")] - pub fn get_modified_data_ids(&self) -> Vec { + pub fn modified_data_ids(&self) -> Vec { self.0 .modified_data_ids() .iter() @@ -131,27 +161,32 @@ impl BatchTransitionWasm { } #[wasm_bindgen(getter = "allConflictingIndexCollateralVotingFunds")] - pub fn get_all_conflicting_index_collateral_voting_funds( - &self, - ) -> WasmDppResult> { + pub fn all_conflicting_index_collateral_voting_funds(&self) -> WasmDppResult> { self.0 .all_conflicting_index_collateral_voting_funds() .map_err(Into::into) } #[wasm_bindgen(setter = "signature")] - pub fn set_signature(&mut self, js_signature: Vec) { - self.0.set_signature(BinaryData::from(js_signature)) + pub fn set_signature(&mut self, signature: Vec) { + self.0.set_signature(BinaryData::from(signature)) } #[wasm_bindgen(setter = "signaturePublicKeyId")] - pub fn set_signature_public_key_id(&mut self, key_id: KeyID) { - self.0.set_signature_public_key_id(key_id) + pub fn set_signature_public_key_id( + &mut self, + #[wasm_bindgen(js_name = "keyId")] key_id: JsValue, + ) -> WasmDppResult<()> { + self.0 + .set_signature_public_key_id(try_to_u32(&key_id, "signaturePublicKeyId")?); + Ok(()) } #[wasm_bindgen(js_name = "setIdentityContractNonce")] - pub fn set_identity_contract_nonce(&mut self, nonce: IdentityNonce) { - self.0.set_identity_contract_nonce(nonce) + pub fn set_identity_contract_nonce(&mut self, nonce: JsValue) -> WasmDppResult<()> { + self.0 + .set_identity_contract_nonce(try_to_u64(&nonce, "identityContractNonce")?); + Ok(()) } #[wasm_bindgen(js_name = "toStateTransition")] @@ -181,13 +216,13 @@ impl BatchTransitionWasm { } #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self) -> WasmDppResult { - serialization::to_object(&self.0) + pub fn to_object(&self) -> WasmDppResult { + serialization::to_object(&self.0).map(Into::into) } #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self) -> WasmDppResult { - serialization::to_json(&self.0) + pub fn to_json(&self) -> WasmDppResult { + serialization::to_json(&self.0).map(Into::into) } #[wasm_bindgen(js_name = "toHex")] @@ -208,13 +243,13 @@ impl BatchTransitionWasm { } #[wasm_bindgen(js_name = "fromObject")] - pub fn from_object(js_value: JsValue) -> WasmDppResult { - serialization::from_object(js_value).map(BatchTransitionWasm) + pub fn from_object(object: BatchTransitionObjectJs) -> WasmDppResult { + serialization::from_object(object.into()).map(BatchTransitionWasm) } #[wasm_bindgen(js_name = "fromJSON")] - pub fn from_json(js_value: JsValue) -> WasmDppResult { - serialization::from_json(js_value).map(BatchTransitionWasm) + pub fn from_json(object: BatchTransitionJSONJs) -> WasmDppResult { + serialization::from_json(object.into()).map(BatchTransitionWasm) } #[wasm_bindgen(js_name = "fromBase64")] @@ -233,3 +268,5 @@ impl BatchTransitionWasm { ) } } + +impl_wasm_type_info!(BatchTransitionWasm, BatchTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/batched_transition.rs b/packages/wasm-dpp2/src/state_transitions/batch/batched_transition.rs index 6092ee8ef17..3fbbf9b8065 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/batched_transition.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/batched_transition.rs @@ -1,8 +1,10 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_from_for_extern_type; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::document_transition::DocumentTransitionWasm; use crate::state_transitions::batch::token_transition::TokenTransitionWasm; -use crate::utils::{IntoWasm, get_class_type}; +use crate::utils::get_class_type; use dpp::prelude::Identifier; use dpp::state_transition::batch_transition::batched_transition::BatchedTransition; use dpp::state_transition::batch_transition::batched_transition::document_transition::{ @@ -14,8 +16,26 @@ use dpp::state_transition::batch_transition::batched_transition::token_transitio use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const BATCHED_TRANSITION_TYPES_TS: &str = r#" +export type BatchedTransitionLike = DocumentTransition | TokenTransition; +"#; + +/// Extern type for flexible BatchedTransition input +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "BatchedTransitionLike")] + pub type BatchedTransitionLikeJs; +} + +impl_from_for_extern_type!( + BatchedTransitionLikeJs, + DocumentTransitionWasm, + TokenTransitionWasm +); + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=BatchedTransition)] +#[wasm_bindgen(js_name = "BatchedTransition")] pub struct BatchedTransitionWasm(BatchedTransition); impl From for BatchedTransitionWasm { @@ -32,43 +52,28 @@ impl From for BatchedTransition { #[wasm_bindgen(js_class = BatchedTransition)] impl BatchedTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "BatchedTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "BatchedTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(js_transition: &JsValue) -> WasmDppResult { + pub fn constructor( + transition: BatchedTransitionLikeJs, + ) -> WasmDppResult { + let js_transition: JsValue = transition.into(); if js_transition.is_undefined() || !js_transition.is_object() { return Err(WasmDppError::invalid_argument("transition is undefined")); } - match get_class_type(js_transition)?.as_str() { + match get_class_type(&js_transition)?.as_str() { "TokenTransition" => Ok(BatchedTransitionWasm::from(BatchedTransition::from( - TokenTransition::from( - js_transition - .to_wasm::("TokenTransition")? - .clone(), - ), + TokenTransition::from(TokenTransitionWasm::try_from(&js_transition)?), ))), "DocumentTransition" => Ok(BatchedTransitionWasm(BatchedTransition::Document( - DocumentTransition::from( - js_transition - .to_wasm::("DocumentTransition")? - .clone(), - ), + DocumentTransition::from(DocumentTransitionWasm::try_from(&js_transition)?), ))), _ => Err(WasmDppError::invalid_argument("Invalid transition type")), } } #[wasm_bindgen(js_name = "toTransition")] - pub fn to_transition(&self) -> JsValue { + pub fn to_transition(&self) -> BatchedTransitionLikeJs { match &self.0 { BatchedTransition::Document(document_transition) => { DocumentTransitionWasm::from(document_transition.clone()).into() @@ -94,10 +99,9 @@ impl BatchedTransitionWasm { #[wasm_bindgen(setter = "dataContractId")] pub fn set_data_contract_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let contract_id: Identifier = IdentifierWasm::try_from(js_contract_id)?.into(); + let contract_id: Identifier = contract_id.try_into()?; self.0 = match self.0.clone() { BatchedTransition::Document(mut document_transition) => { @@ -115,3 +119,5 @@ impl BatchedTransitionWasm { Ok(()) } } + +impl_wasm_type_info!(BatchedTransitionWasm, BatchedTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_base_transition.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_base_transition.rs index eddfa28be99..8a30c76e58a 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_base_transition.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_base_transition.rs @@ -1,16 +1,42 @@ -use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::token_payment_info::TokenPaymentInfoWasm; -use crate::utils::IntoWasm; +use crate::utils::{try_from_options, try_from_options_optional, try_to_u64}; use dpp::prelude::IdentityNonce; use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use dpp::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; use dpp::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; use dpp::state_transition::batch_transition::document_base_transition::v1::v1_methods::DocumentBaseTransitionV1Methods; use dpp::tokens::token_payment_info::TokenPaymentInfo; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct DocumentBaseTransitionOptions { + identity_contract_nonce: IdentityNonce, + document_type_name: String, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface DocumentBaseTransitionOptions { + documentId: IdentifierLike; + identityContractNonce: bigint; + documentTypeName: string; + dataContractId: IdentifierLike; + tokenPaymentInfo?: TokenPaymentInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentBaseTransitionOptions")] + pub type DocumentBaseTransitionOptionsJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "DocumentBaseTransition")] pub struct DocumentBaseTransitionWasm(DocumentBaseTransition); @@ -29,42 +55,30 @@ impl From for DocumentBaseTransition { #[wasm_bindgen(js_class = DocumentBaseTransition)] impl DocumentBaseTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentBaseTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentBaseTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_document_id: &JsValue, - identity_contract_nonce: IdentityNonce, - document_type_name: String, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_data_contract_id: &JsValue, - js_token_payment_info: &JsValue, + pub fn constructor( + options: DocumentBaseTransitionOptionsJs, ) -> WasmDppResult { + // Extract documentId (required) + let document_id: IdentifierWasm = try_from_options(&options, "documentId")?; + + // Extract dataContractId (required) + let data_contract_id: IdentifierWasm = try_from_options(&options, "dataContractId")?; + + // Extract tokenPaymentInfo (optional) let token_payment_info: Option = - match js_token_payment_info.is_null() | js_token_payment_info.is_undefined() { - true => None, - false => Some( - js_token_payment_info - .to_wasm::("TokenPaymentInfo")? - .clone() - .into(), - ), - }; + try_from_options_optional::(&options, "tokenPaymentInfo")? + .map(Into::into); + + // Extract simple fields via serde + let opts: DocumentBaseTransitionOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; let rs_base_v1 = DocumentBaseTransitionV1 { - id: IdentifierWasm::try_from(js_document_id)?.into(), - identity_contract_nonce, - document_type_name, - data_contract_id: IdentifierWasm::try_from(js_data_contract_id)?.into(), + id: document_id.into(), + identity_contract_nonce: opts.identity_contract_nonce, + document_type_name: opts.document_type_name, + data_contract_id: data_contract_id.into(), token_payment_info, }; @@ -74,63 +88,72 @@ impl DocumentBaseTransitionWasm { } #[wasm_bindgen(getter = "id")] - pub fn get_id(&self) -> IdentifierWasm { + pub fn id(&self) -> IdentifierWasm { self.0.id().into() } #[wasm_bindgen(getter = "identityContractNonce")] - pub fn get_identity_contract_nonce(&self) -> IdentityNonce { + pub fn identity_contract_nonce(&self) -> IdentityNonce { self.0.identity_contract_nonce() } #[wasm_bindgen(getter = "dataContractId")] - pub fn get_data_contract_id(&self) -> IdentifierWasm { + pub fn data_contract_id(&self) -> IdentifierWasm { self.0.data_contract_id().into() } #[wasm_bindgen(getter = "documentTypeName")] - pub fn get_document_type_name(&self) -> String { + pub fn document_type_name(&self) -> String { self.0.document_type_name().to_string() } #[wasm_bindgen(getter = "tokenPaymentInfo")] - pub fn get_token_payment_info(&self) -> Option { + pub fn token_payment_info(&self) -> Option { self.0.token_payment_info().map(|info| info.into()) } #[wasm_bindgen(setter = "id")] - pub fn set_id( - &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] js_id: &JsValue, - ) -> WasmDppResult<()> { - self.0.set_id(IdentifierWasm::try_from(js_id)?.into()); + pub fn set_id(&mut self, id: IdentifierLikeJs) -> WasmDppResult<()> { + self.0.set_id(id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "identityContractNonce")] - pub fn set_identity_contract_nonce(&mut self, nonce: IdentityNonce) { - self.0.set_identity_contract_nonce(nonce) + pub fn set_identity_contract_nonce(&mut self, nonce: JsValue) -> WasmDppResult<()> { + self.0 + .set_identity_contract_nonce(try_to_u64(&nonce, "identityContractNonce")?); + Ok(()) } #[wasm_bindgen(setter = "dataContractId")] pub fn set_data_contract_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_data_contract_id: &JsValue, + data_contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - self.0 - .set_data_contract_id(IdentifierWasm::try_from(js_data_contract_id)?.into()); + self.0.set_data_contract_id(data_contract_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "documentTypeName")] - pub fn set_document_type_name(&mut self, document_type_name: String) { + pub fn set_document_type_name( + &mut self, + #[wasm_bindgen(js_name = "documentTypeName")] document_type_name: String, + ) { self.0.set_document_type_name(document_type_name) } #[wasm_bindgen(setter = "tokenPaymentInfo")] - pub fn set_token_payment_info(&mut self, token_payment_info: &TokenPaymentInfoWasm) { - self.0 - .set_token_payment_info(token_payment_info.clone().into()) + pub fn set_token_payment_info( + &mut self, + #[wasm_bindgen(js_name = "tokenPaymentInfo")] token_payment_info: Option< + TokenPaymentInfoWasm, + >, + ) { + match token_payment_info { + Some(info) => self.0.set_token_payment_info(info.into()), + None => self.0.clear_token_payment_info(), + } } } + +impl_wasm_type_info!(DocumentBaseTransitionWasm, DocumentBaseTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_transition.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_transition.rs index d3aa3f25568..26e0808507f 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_transition.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_transition.rs @@ -6,7 +6,9 @@ use crate::state_transitions::batch::document_transitions::transfer::DocumentTra use crate::state_transitions::batch::document_transitions::update_price::DocumentUpdatePriceTransitionWasm; use crate::enums::batch::batch_enum::BatchTypeWasm; use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use dpp::prelude::{IdentityNonce, Revision}; use dpp::state_transition::batch_transition::batched_transition::document_transition::{ DocumentTransition, DocumentTransitionV0Methods, @@ -14,8 +16,9 @@ use dpp::state_transition::batch_transition::batched_transition::document_transi use dpp::state_transition::batch_transition::batched_transition::document_transition_action_type::{ DocumentTransitionActionType, DocumentTransitionActionTypeGetter, }; -use wasm_bindgen::prelude::wasm_bindgen; +use crate::utils::try_to_u64; use wasm_bindgen::JsValue; +use wasm_bindgen::prelude::wasm_bindgen; #[derive(Clone)] #[wasm_bindgen(js_name = "DocumentTransition")] @@ -35,23 +38,13 @@ impl From for DocumentTransition { #[wasm_bindgen(js_class = DocumentTransition)] impl DocumentTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentTransition".to_string() - } - #[wasm_bindgen(getter = "actionType")] - pub fn get_action_type(&self) -> String { + pub fn action_type(&self) -> String { BatchTypeWasm::from(self.0.action_type()).into() } #[wasm_bindgen(getter = "actionTypeNumber")] - pub fn get_action_type_number(&self) -> u8 { + pub fn action_type_number(&self) -> u8 { match self.0.action_type() { DocumentTransitionActionType::Create => 0, DocumentTransitionActionType::Replace => 1, @@ -64,37 +57,37 @@ impl DocumentTransitionWasm { } #[wasm_bindgen(getter = "dataContractId")] - pub fn get_data_contract_id(&self) -> IdentifierWasm { + pub fn data_contract_id(&self) -> IdentifierWasm { self.0.data_contract_id().into() } #[wasm_bindgen(getter = "id")] - pub fn get_id(&self) -> IdentifierWasm { + pub fn id(&self) -> IdentifierWasm { self.0.get_id().into() } #[wasm_bindgen(getter = "documentTypeName")] - pub fn get_document_type_name(&self) -> String { + pub fn document_type_name(&self) -> String { self.0.document_type_name().clone() } #[wasm_bindgen(getter = "identityContractNonce")] - pub fn get_identity_contract_nonce(&self) -> IdentityNonce { + pub fn identity_contract_nonce(&self) -> IdentityNonce { self.0.identity_contract_nonce() } #[wasm_bindgen(getter = "revision")] - pub fn get_revision(&self) -> Option { + pub fn revision(&self) -> Option { self.0.revision() } #[wasm_bindgen(getter = "entropy")] - pub fn get_entropy(&self) -> Option> { + pub fn entropy(&self) -> Option> { self.0.entropy() } #[wasm_bindgen(getter = "createTransition")] - pub fn get_create_transition(&self) -> WasmDppResult { + pub fn create_transition(&self) -> WasmDppResult { match self.0.clone() { DocumentTransition::Create(create) => Ok(DocumentCreateTransitionWasm::from(create)), _ => Err(WasmDppError::invalid_argument( @@ -104,7 +97,7 @@ impl DocumentTransitionWasm { } #[wasm_bindgen(getter = "replaceTransition")] - pub fn get_replace_transition(&self) -> WasmDppResult { + pub fn replace_transition(&self) -> WasmDppResult { match self.0.clone() { DocumentTransition::Replace(replace) => { Ok(DocumentReplaceTransitionWasm::from(replace)) @@ -116,7 +109,7 @@ impl DocumentTransitionWasm { } #[wasm_bindgen(getter = "deleteTransition")] - pub fn get_delete_transition(&self) -> WasmDppResult { + pub fn delete_transition(&self) -> WasmDppResult { match self.0.clone() { DocumentTransition::Delete(delete) => Ok(DocumentDeleteTransitionWasm::from(delete)), _ => Err(WasmDppError::invalid_argument( @@ -126,7 +119,7 @@ impl DocumentTransitionWasm { } #[wasm_bindgen(getter = "purchaseTransition")] - pub fn get_purchase_transition(&self) -> WasmDppResult { + pub fn purchase_transition(&self) -> WasmDppResult { match self.0.clone() { DocumentTransition::Purchase(purchase) => { Ok(DocumentPurchaseTransitionWasm::from(purchase)) @@ -138,7 +131,7 @@ impl DocumentTransitionWasm { } #[wasm_bindgen(getter = "transferTransition")] - pub fn get_transfer_transition(&self) -> WasmDppResult { + pub fn transfer_transition(&self) -> WasmDppResult { match self.0.clone() { DocumentTransition::Transfer(transfer) => { Ok(DocumentTransferTransitionWasm::from(transfer)) @@ -150,7 +143,7 @@ impl DocumentTransitionWasm { } #[wasm_bindgen(getter = "updatePriceTransition")] - pub fn get_update_price_transition(&self) -> WasmDppResult { + pub fn update_price_transition(&self) -> WasmDppResult { match self.0.clone() { DocumentTransition::UpdatePrice(update_price) => { Ok(DocumentUpdatePriceTransitionWasm::from(update_price)) @@ -164,21 +157,30 @@ impl DocumentTransitionWasm { #[wasm_bindgen(setter = "dataContractId")] pub fn set_data_contract_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_data_contract_id: &JsValue, + data_contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - self.0 - .set_data_contract_id(IdentifierWasm::try_from(js_data_contract_id)?.into()); + self.0.set_data_contract_id(data_contract_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "revision")] - pub fn set_revision(&mut self, revision: Revision) { - self.0.set_revision(revision) + pub fn set_revision(&mut self, revision: JsValue) -> WasmDppResult<()> { + self.0.set_revision(try_to_u64(&revision, "revision")?); + Ok(()) } #[wasm_bindgen(setter = "identityContractNonce")] - pub fn set_identity_contract_nonce(&mut self, identity_contract_nonce: IdentityNonce) { - self.0.set_identity_contract_nonce(identity_contract_nonce) + pub fn set_identity_contract_nonce( + &mut self, + #[wasm_bindgen(js_name = "identityContractNonce")] identity_contract_nonce: JsValue, + ) -> WasmDppResult<()> { + self.0.set_identity_contract_nonce(try_to_u64( + &identity_contract_nonce, + "identityContractNonce", + )?); + Ok(()) } } + +impl_try_from_js_value!(DocumentTransitionWasm, "DocumentTransition"); +impl_wasm_type_info!(DocumentTransitionWasm, DocumentTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/create.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/create.rs index 5ea2568586f..bb45538218f 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/create.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/create.rs @@ -1,12 +1,16 @@ +use crate::data_contract::document::DocumentWasm; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_wasm_type_info; +use crate::serialization; use crate::state_transitions::batch::document_base_transition::DocumentBaseTransitionWasm; use crate::state_transitions::batch::document_transition::DocumentTransitionWasm; use crate::state_transitions::batch::generators::generate_create_transition; use crate::state_transitions::batch::prefunded_voting_balance::PrefundedVotingBalanceWasm; use crate::state_transitions::batch::token_payment_info::TokenPaymentInfoWasm; -use crate::data_contract::document::DocumentWasm; -use crate::error::WasmDppResult; -use crate::serialization; -use crate::utils::{IntoWasm, ToSerdeJSONExt}; +use crate::utils::{ + try_from_options, try_from_options_optional, try_from_options_with, try_to_u64, + ToSerdeJSONExt, +}; use dpp::prelude::IdentityNonce; use dpp::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; use dpp::state_transition::batch_transition::document_base_transition::document_base_transition_trait::DocumentBaseTransitionAccessors; @@ -15,6 +19,25 @@ use dpp::state_transition::batch_transition::DocumentCreateTransition; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; +#[wasm_bindgen(typescript_custom_section)] +const DOCUMENT_CREATE_OPTIONS_TS: &str = r#" +export interface DocumentCreateTransitionOptions { + document: Document; + identityContractNonce: bigint; + prefundedVotingBalance?: PrefundedVotingBalance; + tokenPaymentInfo?: TokenPaymentInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentCreateTransitionOptions")] + pub type DocumentCreateTransitionOptionsJs; + + #[wasm_bindgen(typescript_type = "Record")] + pub type DocumentTransitionDataJs; +} + #[wasm_bindgen(js_name = "DocumentCreateTransition")] #[derive(Clone)] pub struct DocumentCreateTransitionWasm(DocumentCreateTransition); @@ -33,48 +56,27 @@ impl From for DocumentCreateTransitionWasm { #[wasm_bindgen(js_class = DocumentCreateTransition)] impl DocumentCreateTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentCreateTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentCreateTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - document: &DocumentWasm, - identity_contract_nonce: IdentityNonce, - js_prefunded_voting_balance: &JsValue, - js_token_payment_info: &JsValue, + pub fn constructor( + options: DocumentCreateTransitionOptionsJs, ) -> WasmDppResult { - let prefunded_voting_balance = match js_prefunded_voting_balance.is_undefined() - | js_prefunded_voting_balance.is_null() - { - true => None, - false => Some( - js_prefunded_voting_balance - .to_wasm::("PrefundedVotingBalance")? - .clone(), - ), - }; - - let token_payment_info = - match js_token_payment_info.is_null() | js_token_payment_info.is_undefined() { - true => None, - false => Some( - js_token_payment_info - .to_wasm::("TokenPaymentInfo")? - .clone(), - ), - }; + let document: DocumentWasm = try_from_options(&options, "document")?; + + let identity_contract_nonce: IdentityNonce = + try_from_options_with(&options, "identityContractNonce", |v| { + try_to_u64(v, "identityContractNonce") + })?; + + let prefunded_voting_balance: Option = + try_from_options_optional(&options, "prefundedVotingBalance")?; + + let token_payment_info: Option = + try_from_options_optional(&options, "tokenPaymentInfo")?; let rs_create_transition = generate_create_transition( - document, + &document, identity_contract_nonce, - document.get_document_type_name().to_string(), + document.document_type_name().to_string(), prefunded_voting_balance, token_payment_info, ); @@ -83,23 +85,27 @@ impl DocumentCreateTransitionWasm { } #[wasm_bindgen(getter = "data")] - pub fn get_data(&self) -> WasmDppResult { - serialization::to_object(self.0.data()) + pub fn data(&self) -> WasmDppResult { + let js_value = serialization::to_object(self.0.data())?; + Ok(js_value.into()) } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> DocumentBaseTransitionWasm { + pub fn base(&self) -> DocumentBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "entropy")] - pub fn get_entropy(&self) -> Vec { + pub fn entropy(&self) -> Vec { self.0.entropy().to_vec() } #[wasm_bindgen(setter = "data")] - pub fn set_data(&mut self, js_data: JsValue) -> WasmDppResult<()> { - let data = js_data.with_serde_to_platform_value_map()?; + pub fn set_data( + &mut self, + #[wasm_bindgen(unchecked_param_type = "Record")] data: JsValue, + ) -> WasmDppResult<()> { + let data = data.with_serde_to_platform_value_map()?; self.0.set_data(data); Ok(()) @@ -111,18 +117,22 @@ impl DocumentCreateTransitionWasm { } #[wasm_bindgen(setter = "entropy")] - pub fn set_entropy(&mut self, js_entropy: Vec) -> WasmDppResult<()> { - let mut entropy = [0u8; 32]; - let bytes = js_entropy.as_slice(); - let len = bytes.len().min(32); - entropy[..len].copy_from_slice(&bytes[..len]); - - self.0.set_entropy(entropy); + pub fn set_entropy(&mut self, entropy: Vec) -> WasmDppResult<()> { + if entropy.len() != 32 { + return Err(WasmDppError::invalid_argument(format!( + "Entropy must be exactly 32 bytes, got {}", + entropy.len() + ))); + } + let mut entropy_bytes = [0u8; 32]; + entropy_bytes.copy_from_slice(&entropy); + + self.0.set_entropy(entropy_bytes); Ok(()) } #[wasm_bindgen(getter = "prefundedVotingBalance")] - pub fn get_prefunded_voting_balance(&self) -> Option { + pub fn prefunded_voting_balance(&self) -> Option { let rs_balance = self.0.prefunded_voting_balance(); rs_balance.as_ref().map(|balance| balance.clone().into()) @@ -131,6 +141,7 @@ impl DocumentCreateTransitionWasm { #[wasm_bindgen(setter = "prefundedVotingBalance")] pub fn set_prefunded_voting_balance( &mut self, + #[wasm_bindgen(js_name = "prefundedVotingBalance")] prefunded_voting_balance: &PrefundedVotingBalanceWasm, ) { self.0.set_prefunded_voting_balance( @@ -153,8 +164,10 @@ impl DocumentCreateTransitionWasm { #[wasm_bindgen(js_name = "fromDocumentTransition")] pub fn from_document_transition( - js_transition: DocumentTransitionWasm, + transition: &DocumentTransitionWasm, ) -> WasmDppResult { - js_transition.get_create_transition() + transition.create_transition() } } + +impl_wasm_type_info!(DocumentCreateTransitionWasm, DocumentCreateTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/delete.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/delete.rs index 1131cc2fca6..22935a38988 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/delete.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/delete.rs @@ -1,16 +1,31 @@ +use crate::data_contract::document::DocumentWasm; +use crate::error::WasmDppResult; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::document_base_transition::DocumentBaseTransitionWasm; use crate::state_transitions::batch::document_transition::DocumentTransitionWasm; use crate::state_transitions::batch::generators::generate_delete_transition; use crate::state_transitions::batch::token_payment_info::TokenPaymentInfoWasm; -use crate::data_contract::document::DocumentWasm; -use crate::error::WasmDppResult; -use crate::utils::IntoWasm; +use crate::utils::{try_from_options, try_from_options_optional, try_from_options_with, try_to_u64}; use dpp::prelude::IdentityNonce; use dpp::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; use dpp::state_transition::batch_transition::document_base_transition::document_base_transition_trait::DocumentBaseTransitionAccessors; use dpp::state_transition::batch_transition::DocumentDeleteTransition; use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::JsValue; + +#[wasm_bindgen(typescript_custom_section)] +const DOCUMENT_DELETE_OPTIONS_TS: &str = r#" +export interface DocumentDeleteTransitionOptions { + document: Document; + identityContractNonce: bigint; + tokenPaymentInfo?: TokenPaymentInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentDeleteTransitionOptions")] + pub type DocumentDeleteTransitionOptionsJs; +} #[wasm_bindgen(js_name = "DocumentDeleteTransition")] pub struct DocumentDeleteTransitionWasm(DocumentDeleteTransition); @@ -23,36 +38,24 @@ impl From for DocumentDeleteTransitionWasm { #[wasm_bindgen(js_class = DocumentDeleteTransition)] impl DocumentDeleteTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentDeleteTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentDeleteTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - document: &DocumentWasm, - identity_contract_nonce: IdentityNonce, - js_token_payment_info: &JsValue, + pub fn constructor( + options: DocumentDeleteTransitionOptionsJs, ) -> WasmDppResult { - let token_payment_info = - match js_token_payment_info.is_null() | js_token_payment_info.is_undefined() { - true => None, - false => Some( - js_token_payment_info - .to_wasm::("TokenPaymentInfo")? - .clone(), - ), - }; + let document: DocumentWasm = try_from_options(&options, "document")?; + + let identity_contract_nonce: IdentityNonce = + try_from_options_with(&options, "identityContractNonce", |v| { + try_to_u64(v, "identityContractNonce") + })?; + + let token_payment_info: Option = + try_from_options_optional(&options, "tokenPaymentInfo")?; let rs_delete_transition = generate_delete_transition( - document, + &document, identity_contract_nonce, - document.get_document_type_name().to_string(), + document.document_type_name().to_string(), token_payment_info, ); @@ -60,7 +63,7 @@ impl DocumentDeleteTransitionWasm { } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> DocumentBaseTransitionWasm { + pub fn base(&self) -> DocumentBaseTransitionWasm { self.0.base().clone().into() } @@ -78,9 +81,9 @@ impl DocumentDeleteTransitionWasm { #[wasm_bindgen(js_name = "fromDocumentTransition")] pub fn from_document_transition( - js_transition: DocumentTransitionWasm, + transition: &DocumentTransitionWasm, ) -> WasmDppResult { - js_transition.get_delete_transition() + transition.delete_transition() } } @@ -89,3 +92,5 @@ impl From for DocumentDeleteTransition { document_delete_transition.0 } } + +impl_wasm_type_info!(DocumentDeleteTransitionWasm, DocumentDeleteTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/purchase.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/purchase.rs index c4db86bc46c..7edd1690bcc 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/purchase.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/purchase.rs @@ -1,10 +1,11 @@ +use crate::data_contract::document::DocumentWasm; +use crate::error::WasmDppResult; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::document_base_transition::DocumentBaseTransitionWasm; use crate::state_transitions::batch::document_transition::DocumentTransitionWasm; use crate::state_transitions::batch::generators::generate_purchase_transition; use crate::state_transitions::batch::token_payment_info::TokenPaymentInfoWasm; -use crate::data_contract::document::DocumentWasm; -use crate::error::WasmDppResult; -use crate::utils::IntoWasm; +use crate::utils::{try_from_options, try_from_options_optional, try_from_options_with, try_to_u64}; use dpp::fee::Credits; use dpp::prelude::{IdentityNonce, Revision}; use dpp::state_transition::batch_transition::batched_transition::document_purchase_transition::v0::v0_methods::DocumentPurchaseTransitionV0Methods; @@ -14,6 +15,22 @@ use dpp::state_transition::batch_transition::document_base_transition::document_ use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; +#[wasm_bindgen(typescript_custom_section)] +const DOCUMENT_PURCHASE_OPTIONS_TS: &str = r#" +export interface DocumentPurchaseTransitionOptions { + document: Document; + identityContractNonce: bigint; + amount: bigint; + tokenPaymentInfo?: TokenPaymentInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentPurchaseTransitionOptions")] + pub type DocumentPurchaseTransitionOptionsJs; +} + #[wasm_bindgen(js_name = "DocumentPurchaseTransition")] pub struct DocumentPurchaseTransitionWasm(DocumentPurchaseTransition); @@ -31,37 +48,27 @@ impl From for DocumentPurchaseTransitionWasm { #[wasm_bindgen(js_class = DocumentPurchaseTransition)] impl DocumentPurchaseTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentPurchaseTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentPurchaseTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - document: &DocumentWasm, - identity_contract_nonce: IdentityNonce, - amount: Credits, - js_token_payment_info: &JsValue, + pub fn constructor( + options: DocumentPurchaseTransitionOptionsJs, ) -> WasmDppResult { - let token_payment_info = - match js_token_payment_info.is_null() | js_token_payment_info.is_undefined() { - true => None, - false => Some( - js_token_payment_info - .to_wasm::("TokenPaymentInfo")? - .clone(), - ), - }; + let document: DocumentWasm = try_from_options(&options, "document")?; + + let identity_contract_nonce: IdentityNonce = + try_from_options_with(&options, "identityContractNonce", |v| { + try_to_u64(v, "identityContractNonce") + })?; + + let amount: Credits = + try_from_options_with(&options, "amount", |v| try_to_u64(v, "amount"))?; + + let token_payment_info: Option = + try_from_options_optional(&options, "tokenPaymentInfo")?; let rs_purchase_transition = generate_purchase_transition( - document, + &document, identity_contract_nonce, - document.get_document_type_name().to_string(), + document.document_type_name().to_string(), amount, token_payment_info, ); @@ -70,17 +77,17 @@ impl DocumentPurchaseTransitionWasm { } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> DocumentBaseTransitionWasm { + pub fn base(&self) -> DocumentBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "price")] - pub fn get_price(&self) -> Credits { + pub fn price(&self) -> Credits { self.0.price() } #[wasm_bindgen(getter = "revision")] - pub fn get_revision(&self) -> Revision { + pub fn revision(&self) -> Revision { self.0.revision() } @@ -90,15 +97,20 @@ impl DocumentPurchaseTransitionWasm { } #[wasm_bindgen(setter = "price")] - pub fn set_price(&mut self, price: Credits) { + pub fn set_price(&mut self, price: JsValue) -> WasmDppResult<()> { + use crate::utils::try_to_u64; + let price = try_to_u64(&price, "price")?; match self.0 { DocumentPurchaseTransition::V0(ref mut v0) => v0.price = price, } + Ok(()) } #[wasm_bindgen(setter = "revision")] - pub fn set_revision(&mut self, revision: Revision) { - self.0.set_revision(revision); + pub fn set_revision(&mut self, revision: JsValue) -> WasmDppResult<()> { + use crate::utils::try_to_u64; + self.0.set_revision(try_to_u64(&revision, "revision")?); + Ok(()) } #[wasm_bindgen(js_name = "toDocumentTransition")] @@ -110,8 +122,10 @@ impl DocumentPurchaseTransitionWasm { #[wasm_bindgen(js_name = "fromDocumentTransition")] pub fn from_document_transition( - js_transition: DocumentTransitionWasm, + transition: &DocumentTransitionWasm, ) -> WasmDppResult { - js_transition.get_purchase_transition() + transition.purchase_transition() } } + +impl_wasm_type_info!(DocumentPurchaseTransitionWasm, DocumentPurchaseTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/replace.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/replace.rs index 3b4ffc29b9d..926b85f30c6 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/replace.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/replace.rs @@ -1,11 +1,12 @@ +use crate::data_contract::document::DocumentWasm; +use crate::error::WasmDppResult; +use crate::impl_wasm_type_info; +use crate::serialization; use crate::state_transitions::batch::document_base_transition::DocumentBaseTransitionWasm; use crate::state_transitions::batch::document_transition::DocumentTransitionWasm; use crate::state_transitions::batch::generators::generate_replace_transition; use crate::state_transitions::batch::token_payment_info::TokenPaymentInfoWasm; -use crate::data_contract::document::DocumentWasm; -use crate::error::WasmDppResult; -use crate::serialization; -use crate::utils::{IntoWasm, ToSerdeJSONExt}; +use crate::utils::{try_from_options, try_from_options_optional, try_from_options_with, try_to_u64, ToSerdeJSONExt}; use dpp::prelude::{IdentityNonce, Revision}; use dpp::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; use dpp::state_transition::batch_transition::document_base_transition::document_base_transition_trait::DocumentBaseTransitionAccessors; @@ -14,6 +15,24 @@ use dpp::state_transition::batch_transition::DocumentReplaceTransition; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; +#[wasm_bindgen(typescript_custom_section)] +const DOCUMENT_REPLACE_OPTIONS_TS: &str = r#" +export interface DocumentReplaceTransitionOptions { + document: Document; + identityContractNonce: bigint; + tokenPaymentInfo?: TokenPaymentInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentReplaceTransitionOptions")] + pub type DocumentReplaceTransitionOptionsJs; + + #[wasm_bindgen(typescript_type = "Record")] + pub type DocumentTransitionDataJs; +} + #[wasm_bindgen(js_name = "DocumentReplaceTransition")] pub struct DocumentReplaceTransitionWasm(DocumentReplaceTransition); @@ -31,36 +50,24 @@ impl From for DocumentReplaceTransition { #[wasm_bindgen(js_class = DocumentReplaceTransition)] impl DocumentReplaceTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentReplaceTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentReplaceTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - document: &DocumentWasm, - identity_contract_nonce: IdentityNonce, - js_token_payment_info: &JsValue, + pub fn constructor( + options: DocumentReplaceTransitionOptionsJs, ) -> WasmDppResult { - let token_payment_info = - match js_token_payment_info.is_null() | js_token_payment_info.is_undefined() { - true => None, - false => Some( - js_token_payment_info - .to_wasm::("TokenPaymentInfo")? - .clone(), - ), - }; + let document: DocumentWasm = try_from_options(&options, "document")?; + + let identity_contract_nonce: IdentityNonce = + try_from_options_with(&options, "identityContractNonce", |v| { + try_to_u64(v, "identityContractNonce") + })?; + + let token_payment_info: Option = + try_from_options_optional(&options, "tokenPaymentInfo")?; let rs_update_transition = generate_replace_transition( - document, + &document, identity_contract_nonce, - document.get_document_type_name().to_string(), + document.document_type_name().to_string(), token_payment_info, ); @@ -68,23 +75,27 @@ impl DocumentReplaceTransitionWasm { } #[wasm_bindgen(getter = "data")] - pub fn get_data(&self) -> WasmDppResult { - serialization::to_object(self.0.data()) + pub fn data(&self) -> WasmDppResult { + let js_value = serialization::to_object(self.0.data())?; + Ok(js_value.into()) } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> DocumentBaseTransitionWasm { + pub fn base(&self) -> DocumentBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "revision")] - pub fn get_revision(&self) -> Revision { + pub fn revision(&self) -> Revision { self.0.revision() } #[wasm_bindgen(setter = "data")] - pub fn set_data(&mut self, js_data: JsValue) -> WasmDppResult<()> { - let data = js_data.with_serde_to_platform_value_map()?; + pub fn set_data( + &mut self, + #[wasm_bindgen(unchecked_param_type = "Record")] data: JsValue, + ) -> WasmDppResult<()> { + let data = data.with_serde_to_platform_value_map()?; self.0.set_data(data); Ok(()) @@ -96,8 +107,10 @@ impl DocumentReplaceTransitionWasm { } #[wasm_bindgen(setter = "revision")] - pub fn set_revision(&mut self, revision: Revision) { - self.0.set_revision(revision); + pub fn set_revision(&mut self, revision: JsValue) -> WasmDppResult<()> { + use crate::utils::try_to_u64; + self.0.set_revision(try_to_u64(&revision, "revision")?); + Ok(()) } #[wasm_bindgen(js_name = "toDocumentTransition")] @@ -109,8 +122,10 @@ impl DocumentReplaceTransitionWasm { #[wasm_bindgen(js_name = "fromDocumentTransition")] pub fn from_document_transition( - js_transition: DocumentTransitionWasm, + transition: &DocumentTransitionWasm, ) -> WasmDppResult { - js_transition.get_replace_transition() + transition.replace_transition() } } + +impl_wasm_type_info!(DocumentReplaceTransitionWasm, DocumentReplaceTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/transfer.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/transfer.rs index cf3a78a04f3..a80a4ea85dd 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/transfer.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/transfer.rs @@ -1,18 +1,34 @@ +use crate::data_contract::document::DocumentWasm; +use crate::error::WasmDppResult; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::document_base_transition::DocumentBaseTransitionWasm; use crate::state_transitions::batch::document_transition::DocumentTransitionWasm; use crate::state_transitions::batch::generators::generate_transfer_transition; use crate::state_transitions::batch::token_payment_info::TokenPaymentInfoWasm; -use crate::data_contract::document::DocumentWasm; -use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; -use crate::utils::IntoWasm; +use crate::utils::{try_from_options, try_from_options_optional, try_from_options_with, try_to_u64}; use dpp::prelude::IdentityNonce; use dpp::state_transition::batch_transition::batched_transition::document_transfer_transition::v0::v0_methods::DocumentTransferTransitionV0Methods; use dpp::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; use dpp::state_transition::batch_transition::batched_transition::DocumentTransferTransition; use dpp::state_transition::batch_transition::document_base_transition::document_base_transition_trait::DocumentBaseTransitionAccessors; use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::JsValue; + +#[wasm_bindgen(typescript_custom_section)] +const DOCUMENT_TRANSFER_OPTIONS_TS: &str = r#" +export interface DocumentTransferTransitionOptions { + document: Document; + identityContractNonce: bigint; + recipientOwnerId: IdentifierLike; + tokenPaymentInfo?: TokenPaymentInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentTransferTransitionOptions")] + pub type DocumentTransferTransitionOptionsJs; +} #[wasm_bindgen(js_name = "DocumentTransferTransition")] pub struct DocumentTransferTransitionWasm(DocumentTransferTransition); @@ -31,39 +47,27 @@ impl From for DocumentTransferTransition { #[wasm_bindgen(js_class = DocumentTransferTransition)] impl DocumentTransferTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentTransferTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentTransferTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - document: &DocumentWasm, - identity_contract_nonce: IdentityNonce, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_recipient_owner_id: &JsValue, - js_token_payment_info: &JsValue, + pub fn constructor( + options: DocumentTransferTransitionOptionsJs, ) -> WasmDppResult { - let token_payment_info = - match js_token_payment_info.is_null() | js_token_payment_info.is_undefined() { - true => None, - false => Some( - js_token_payment_info - .to_wasm::("TokenPaymentInfo")? - .clone(), - ), - }; + let document: DocumentWasm = try_from_options(&options, "document")?; + + let identity_contract_nonce: IdentityNonce = + try_from_options_with(&options, "identityContractNonce", |v| { + try_to_u64(v, "identityContractNonce") + })?; + + let recipient_owner_id: IdentifierWasm = try_from_options(&options, "recipientOwnerId")?; + + let token_payment_info: Option = + try_from_options_optional(&options, "tokenPaymentInfo")?; let rs_transfer_transition = generate_transfer_transition( - document, + &document, identity_contract_nonce, - document.get_document_type_name().to_string(), - IdentifierWasm::try_from(js_recipient_owner_id)?.into(), + document.document_type_name().to_string(), + recipient_owner_id.into(), token_payment_info, ); @@ -71,12 +75,12 @@ impl DocumentTransferTransitionWasm { } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> DocumentBaseTransitionWasm { + pub fn base(&self) -> DocumentBaseTransitionWasm { self.0.base().clone().into() } - #[wasm_bindgen(getter = "recipientId")] - pub fn get_recipient_owner_id(&self) -> IdentifierWasm { + #[wasm_bindgen(getter = "recipientOwnerId")] + pub fn recipient_owner_id(&self) -> IdentifierWasm { self.0.recipient_owner_id().into() } @@ -85,14 +89,13 @@ impl DocumentTransferTransitionWasm { self.0.set_base(base.clone().into()) } - #[wasm_bindgen(setter = "recipientId")] + #[wasm_bindgen(setter = "recipientOwnerId")] pub fn set_recipient_owner_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_recipient_owner_id: &JsValue, + #[wasm_bindgen(js_name = "recipientOwnerId")] recipient_owner_id: IdentifierLikeJs, ) -> WasmDppResult<()> { self.0 - .set_recipient_owner_id(IdentifierWasm::try_from(js_recipient_owner_id)?.into()); + .set_recipient_owner_id(recipient_owner_id.try_into()?); Ok(()) } @@ -105,8 +108,10 @@ impl DocumentTransferTransitionWasm { #[wasm_bindgen(js_name = "fromDocumentTransition")] pub fn from_document_transition( - js_transition: DocumentTransitionWasm, + transition: &DocumentTransitionWasm, ) -> WasmDppResult { - js_transition.get_transfer_transition() + transition.transfer_transition() } } + +impl_wasm_type_info!(DocumentTransferTransitionWasm, DocumentTransferTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/update_price.rs b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/update_price.rs index 89160085764..4ac69d3ce36 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/update_price.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/document_transitions/update_price.rs @@ -1,10 +1,11 @@ +use crate::data_contract::document::DocumentWasm; +use crate::error::WasmDppResult; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::document_base_transition::DocumentBaseTransitionWasm; use crate::state_transitions::batch::document_transition::DocumentTransitionWasm; use crate::state_transitions::batch::generators::generate_update_price_transition; use crate::state_transitions::batch::token_payment_info::TokenPaymentInfoWasm; -use crate::data_contract::document::DocumentWasm; -use crate::error::WasmDppResult; -use crate::utils::IntoWasm; +use crate::utils::{try_from_options, try_from_options_optional, try_from_options_with, try_to_u64}; use dpp::fee::Credits; use dpp::prelude::IdentityNonce; use dpp::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; @@ -14,6 +15,22 @@ use dpp::state_transition::batch_transition::document_base_transition::document_ use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; +#[wasm_bindgen(typescript_custom_section)] +const DOCUMENT_UPDATE_PRICE_OPTIONS_TS: &str = r#" +export interface DocumentUpdatePriceTransitionOptions { + document: Document; + identityContractNonce: bigint; + price: bigint; + tokenPaymentInfo?: TokenPaymentInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DocumentUpdatePriceTransitionOptions")] + pub type DocumentUpdatePriceTransitionOptionsJs; +} + #[wasm_bindgen(js_name = "DocumentUpdatePriceTransition")] pub struct DocumentUpdatePriceTransitionWasm(DocumentUpdatePriceTransition); @@ -25,37 +42,26 @@ impl From for DocumentUpdatePriceTransitionWasm { #[wasm_bindgen(js_class = DocumentUpdatePriceTransition)] impl DocumentUpdatePriceTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DocumentUpdatePriceTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DocumentUpdatePriceTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - document: &DocumentWasm, - identity_contract_nonce: IdentityNonce, - price: Credits, - js_token_payment_info: &JsValue, + pub fn constructor( + options: DocumentUpdatePriceTransitionOptionsJs, ) -> WasmDppResult { - let token_payment_info = - match js_token_payment_info.is_null() | js_token_payment_info.is_undefined() { - true => None, - false => Some( - js_token_payment_info - .to_wasm::("TokenPaymentInfo")? - .clone(), - ), - }; + let document: DocumentWasm = try_from_options(&options, "document")?; + + let identity_contract_nonce: IdentityNonce = + try_from_options_with(&options, "identityContractNonce", |v| { + try_to_u64(v, "identityContractNonce") + })?; + + let price: Credits = try_from_options_with(&options, "price", |v| try_to_u64(v, "price"))?; + + let token_payment_info: Option = + try_from_options_optional(&options, "tokenPaymentInfo")?; let rs_document_update_price_transition = generate_update_price_transition( - document, + &document, identity_contract_nonce, - document.get_document_type_name().to_string(), + document.document_type_name().to_string(), price, token_payment_info, ); @@ -66,12 +72,12 @@ impl DocumentUpdatePriceTransitionWasm { } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> DocumentBaseTransitionWasm { + pub fn base(&self) -> DocumentBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "price")] - pub fn get_price(&self) -> Credits { + pub fn price(&self) -> Credits { self.0.price() } @@ -81,8 +87,10 @@ impl DocumentUpdatePriceTransitionWasm { } #[wasm_bindgen(setter = "price")] - pub fn set_price(&mut self, price: Credits) { - self.0.set_price(price) + pub fn set_price(&mut self, price: JsValue) -> WasmDppResult<()> { + use crate::utils::try_to_u64; + self.0.set_price(try_to_u64(&price, "price")?); + Ok(()) } #[wasm_bindgen(js_name = "toDocumentTransition")] @@ -94,8 +102,13 @@ impl DocumentUpdatePriceTransitionWasm { #[wasm_bindgen(js_name = "fromDocumentTransition")] pub fn from_document_transition( - js_transition: DocumentTransitionWasm, + transition: &DocumentTransitionWasm, ) -> WasmDppResult { - js_transition.get_update_price_transition() + transition.update_price_transition() } } + +impl_wasm_type_info!( + DocumentUpdatePriceTransitionWasm, + DocumentUpdatePriceTransition +); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/prefunded_voting_balance.rs b/packages/wasm-dpp2/src/state_transitions/batch/prefunded_voting_balance.rs index 4369ec2b4c9..18d8ed597dd 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/prefunded_voting_balance.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/prefunded_voting_balance.rs @@ -1,6 +1,34 @@ +use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use dpp::fee::Credits; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct PrefundedVotingBalanceOptions { + index_name: String, + credits: Credits, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Options for creating a PrefundedVotingBalance instance. + */ +export interface PrefundedVotingBalanceOptions { + indexName: string; + credits: bigint; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "PrefundedVotingBalanceOptions")] + pub type PrefundedVotingBalanceOptionsJs; +} + #[wasm_bindgen(js_name = "PrefundedVotingBalance")] #[derive(Clone)] pub struct PrefundedVotingBalanceWasm { @@ -25,22 +53,17 @@ impl From for (String, Credits) { #[wasm_bindgen(js_class = PrefundedVotingBalance)] impl PrefundedVotingBalanceWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "PrefundedVotingBalance".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "PrefundedVotingBalance".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(index_name: String, credits: Credits) -> PrefundedVotingBalanceWasm { - PrefundedVotingBalanceWasm { - index_name, - credits, - } + pub fn constructor( + options: PrefundedVotingBalanceOptionsJs, + ) -> WasmDppResult { + let opts: PrefundedVotingBalanceOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + + Ok(PrefundedVotingBalanceWasm { + index_name: opts.index_name, + credits: opts.credits, + }) } #[wasm_bindgen(getter, js_name = "indexName")] @@ -53,3 +76,6 @@ impl PrefundedVotingBalanceWasm { self.credits } } + +impl_try_from_js_value!(PrefundedVotingBalanceWasm, "PrefundedVotingBalance"); +impl_wasm_type_info!(PrefundedVotingBalanceWasm, PrefundedVotingBalance); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_base_transition.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_base_transition.rs index 65be899b332..c215db93a75 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_base_transition.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_base_transition.rs @@ -1,7 +1,11 @@ use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::state_transitions::GroupStateTransitionInfoWasm; -use crate::utils::IntoWasm; +use crate::utils::{ + try_from_options, try_from_options_optional, try_from_options_with, try_to_u16, try_to_u64, +}; use dpp::group::GroupStateTransitionInfo; use dpp::prelude::IdentityNonce; use dpp::state_transition::batch_transition::token_base_transition::TokenBaseTransition; @@ -10,8 +14,25 @@ use dpp::state_transition::batch_transition::token_base_transition::v0::v0_metho use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_BASE_TRANSITION_OPTIONS_TS: &str = r#" +export interface TokenBaseTransitionOptions { + identityContractNonce: bigint; + tokenContractPosition: number; + dataContractId: IdentifierLike; + tokenId: IdentifierLike; + usingGroupInfo?: GroupStateTransitionInfo; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenBaseTransitionOptions")] + pub type TokenBaseTransitionOptionsJs; +} + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenBaseTransition)] +#[wasm_bindgen(js_name = "TokenBaseTransition")] pub struct TokenBaseTransitionWasm(TokenBaseTransition); impl From for TokenBaseTransitionWasm { @@ -28,123 +49,116 @@ impl From for TokenBaseTransition { #[wasm_bindgen(js_class = TokenBaseTransition)] impl TokenBaseTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenBaseTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenBaseTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - identity_contract_nonce: IdentityNonce, - token_contract_position: u16, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_data_contract_id: &JsValue, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_token_id: &JsValue, - js_using_group_info: &JsValue, + pub fn constructor( + options: TokenBaseTransitionOptionsJs, ) -> WasmDppResult { - let using_group_info: Option = - match js_using_group_info.is_undefined() { - false => Some( - js_using_group_info - .to_wasm::("GroupStateTransitionInfo")? - .clone() - .into(), - ), - true => None, - }; + let identity_contract_nonce = + try_from_options_with(&options, "identityContractNonce", |v| { + try_to_u64(v, "identityContractNonce") + })?; + + let token_contract_position = + try_from_options_with(&options, "tokenContractPosition", |v| { + try_to_u16(v, "tokenContractPosition") + })?; + + let data_contract_id: IdentifierWasm = try_from_options(&options, "dataContractId")?; + + let token_id: IdentifierWasm = try_from_options(&options, "tokenId")?; + + let group_info: Option = + try_from_options_optional(&options, "usingGroupInfo")?; Ok(TokenBaseTransitionWasm(TokenBaseTransition::V0( TokenBaseTransitionV0 { identity_contract_nonce, token_contract_position, - data_contract_id: IdentifierWasm::try_from(js_data_contract_id)?.into(), - token_id: IdentifierWasm::try_from(js_token_id)?.into(), - using_group_info, + data_contract_id: data_contract_id.into(), + token_id: token_id.into(), + using_group_info: group_info.map(Into::into), }, ))) } #[wasm_bindgen(getter = identityContractNonce)] - pub fn get_identity_contract_nonce(&self) -> IdentityNonce { + pub fn identity_contract_nonce(&self) -> IdentityNonce { self.0.identity_contract_nonce() } #[wasm_bindgen(getter = tokenContractPosition)] - pub fn get_token_contract_position(&self) -> u16 { + pub fn token_contract_position(&self) -> u16 { self.0.token_contract_position() } #[wasm_bindgen(getter = dataContractId)] - pub fn get_data_contract_id(&self) -> IdentifierWasm { + pub fn data_contract_id(&self) -> IdentifierWasm { self.0.data_contract_id().into() } #[wasm_bindgen(getter = tokenId)] - pub fn get_token_id(&self) -> IdentifierWasm { + pub fn token_id(&self) -> IdentifierWasm { self.0.token_id().into() } #[wasm_bindgen(getter = usingGroupInfo)] - pub fn get_using_group_info(&self) -> Option { + pub fn using_group_info(&self) -> Option { self.0 .using_group_info() .map(|using_group_info| using_group_info.into()) } #[wasm_bindgen(setter = identityContractNonce)] - pub fn set_identity_contract_nonce(&mut self, identity_contract_nonce: IdentityNonce) { + pub fn set_identity_contract_nonce( + &mut self, + #[wasm_bindgen(js_name = "identityContractNonce")] identity_contract_nonce: IdentityNonce, + ) { self.0.set_identity_contract_nonce(identity_contract_nonce) } #[wasm_bindgen(setter = tokenContractPosition)] - pub fn set_token_contract_position(&mut self, pos: u16) { - self.0.set_token_contract_position(pos) + pub fn set_token_contract_position(&mut self, pos: JsValue) -> WasmDppResult<()> { + self.0 + .set_token_contract_position(try_to_u16(&pos, "tokenContractPosition")?); + Ok(()) } #[wasm_bindgen(setter = dataContractId)] pub fn set_data_contract_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identifier: &JsValue, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - self.0 - .set_data_contract_id(IdentifierWasm::try_from(js_identifier)?.into()); + self.0.set_data_contract_id(data_contract_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = tokenId)] pub fn set_token_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identifier: &JsValue, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - self.0 - .set_token_id(IdentifierWasm::try_from(js_identifier)?.into()); + self.0.set_token_id(token_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = usingGroupInfo)] - pub fn set_using_group_info(&mut self, js_using_group_info: &JsValue) -> WasmDppResult<()> { - let using_group_info: Option = - match js_using_group_info.is_undefined() { - false => Some( - js_using_group_info - .to_wasm::("GroupStateTransitionInfo")? - .clone() - .into(), - ), - true => None, - }; - - self.0.set_using_group_info(using_group_info); + pub fn set_using_group_info( + &mut self, + #[wasm_bindgen(unchecked_param_type = "GroupStateTransitionInfo | undefined")] + using_group_info: &JsValue, + ) -> WasmDppResult<()> { + let group_info: Option = if using_group_info.is_undefined() { + None + } else { + Some(GroupStateTransitionInfoWasm::try_from(using_group_info)?.into()) + }; + + self.0.set_using_group_info(group_info); Ok(()) } } + +impl_try_from_js_value!(TokenBaseTransitionWasm, "TokenBaseTransition"); +impl_wasm_type_info!(TokenBaseTransitionWasm, TokenBaseTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_payment_info.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_payment_info.rs index 3fc1c62baf2..f4ebf394f5e 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_payment_info.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_payment_info.rs @@ -1,16 +1,45 @@ -use crate::enums::batch::gas_fees_paid_by::GasFeesPaidByWasm; -use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::enums::batch::gas_fees_paid_by::{GasFeesPaidByLikeJs, GasFeesPaidByWasm}; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::identifier::{IdentifierLikeOrUndefinedJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::utils::try_from_options_optional; use dpp::balances::credits::TokenAmount; use dpp::data_contract::TokenContractPosition; -use dpp::prelude::Identifier; use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; use dpp::tokens::token_payment_info::TokenPaymentInfo; use dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0; use dpp::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; -use wasm_bindgen::JsValue; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct TokenPaymentInfoOptions { + token_contract_position: TokenContractPosition, + #[serde(default)] + minimum_token_cost: Option, + #[serde(default)] + maximum_token_cost: Option, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface TokenPaymentInfoOptions { + paymentTokenContractId?: IdentifierLike; + tokenContractPosition: number; + minimumTokenCost?: bigint; + maximumTokenCost?: bigint; + gasFeesPaidBy?: GasFeesPaidByLike; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenPaymentInfoOptions")] + pub type TokenPaymentInfoOptionsJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "TokenPaymentInfo")] pub struct TokenPaymentInfoWasm(TokenPaymentInfo); @@ -29,47 +58,27 @@ impl From for TokenPaymentInfo { #[wasm_bindgen(js_class = TokenPaymentInfo)] impl TokenPaymentInfoWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenPaymentInfo".to_string() - } + #[wasm_bindgen(constructor)] + pub fn constructor(options: TokenPaymentInfoOptionsJs) -> WasmDppResult { + // Extract complex types first (borrows &options) + let payment_token_contract_id: Option = + try_from_options_optional(&options, "paymentTokenContractId")?; - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenPaymentInfo".to_string() - } + let gas_fees_paid_by: GasFeesPaidBy = + try_from_options_optional::(&options, "gasFeesPaidBy")? + .map(Into::into) + .unwrap_or_default(); - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_payment_token_contract_id: &JsValue, - token_contract_position: TokenContractPosition, - minimum_token_cost: Option, - maximum_token_cost: Option, - js_gas_fees_paid_by: &JsValue, - ) -> WasmDppResult { - let payment_token_contract_id: Option = match js_payment_token_contract_id - .is_null() - | js_payment_token_contract_id.is_undefined() - { - true => None, - false => Some(IdentifierWasm::try_from(js_payment_token_contract_id)?.into()), - }; - - let gas_fees_paid_by = - match js_gas_fees_paid_by.is_undefined() | js_gas_fees_paid_by.is_null() { - true => GasFeesPaidBy::default(), - false => GasFeesPaidByWasm::try_from(js_gas_fees_paid_by.clone())? - .clone() - .into(), - }; + // Deserialize primitive fields via serde last (consumes options) + let opts: TokenPaymentInfoOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(TokenPaymentInfoWasm(TokenPaymentInfo::V0( TokenPaymentInfoV0 { - payment_token_contract_id, - token_contract_position, - minimum_token_cost, - maximum_token_cost, + payment_token_contract_id: payment_token_contract_id.map(Into::into), + token_contract_position: opts.token_contract_position, + minimum_token_cost: opts.minimum_token_cost, + maximum_token_cost: opts.maximum_token_cost, gas_fees_paid_by, }, ))) @@ -103,50 +112,48 @@ impl TokenPaymentInfoWasm { #[wasm_bindgen(setter = "paymentTokenContractId")] pub fn set_payment_token_contract_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_payment_token_contract_id: &JsValue, + payment_token_contract_id: IdentifierLikeOrUndefinedJs, ) -> WasmDppResult<()> { - let payment_token_contract_id: Option = match js_payment_token_contract_id - .is_null() - | js_payment_token_contract_id.is_undefined() - { - true => None, - false => Some(IdentifierWasm::try_from(js_payment_token_contract_id)?.into()), - }; - self.0 - .set_payment_token_contract_id(payment_token_contract_id); + .set_payment_token_contract_id(payment_token_contract_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "tokenContractPosition")] - pub fn set_token_contract_position(&mut self, token_contract_position: TokenContractPosition) { + pub fn set_token_contract_position( + &mut self, + #[wasm_bindgen(js_name = "tokenContractPosition")] + token_contract_position: TokenContractPosition, + ) { self.0.set_token_contract_position(token_contract_position) } #[wasm_bindgen(setter = "minimumTokenCost")] - pub fn set_minimum_token_cost(&mut self, minimum_cost: Option) { - self.0.set_maximum_token_cost(minimum_cost); + pub fn set_minimum_token_cost( + &mut self, + #[wasm_bindgen(js_name = "minimumCost")] minimum_cost: Option, + ) { + self.0.set_minimum_token_cost(minimum_cost); } #[wasm_bindgen(setter = "maximumTokenCost")] - pub fn set_maximum_token_cost(&mut self, maximum_cost: Option) { + pub fn set_maximum_token_cost( + &mut self, + #[wasm_bindgen(js_name = "maximumCost")] maximum_cost: Option, + ) { self.0.set_maximum_token_cost(maximum_cost) } #[wasm_bindgen(setter = "gasFeesPaidBy")] - pub fn set_gas_fees_paid_by(&mut self, js_gas_fees_paid_by: &JsValue) -> WasmDppResult<()> { - let gas_fees_paid_by = - match js_gas_fees_paid_by.is_undefined() | js_gas_fees_paid_by.is_null() { - true => GasFeesPaidBy::default(), - false => GasFeesPaidByWasm::try_from(js_gas_fees_paid_by.clone())? - .clone() - .into(), - }; - - self.0.set_gas_fees_paid_by(gas_fees_paid_by); - + pub fn set_gas_fees_paid_by( + &mut self, + #[wasm_bindgen(js_name = "gasFeesPaidBy")] gas_fees_paid_by: GasFeesPaidByLikeJs, + ) -> WasmDppResult<()> { + self.0.set_gas_fees_paid_by(gas_fees_paid_by.try_into()?); Ok(()) } } + +impl_try_from_js_value!(TokenPaymentInfoWasm, "TokenPaymentInfo"); +impl_wasm_type_info!(TokenPaymentInfoWasm, TokenPaymentInfo); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_pricing_schedule.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_pricing_schedule.rs index 16b52fa3213..af831e588c8 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_pricing_schedule.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_pricing_schedule.rs @@ -1,4 +1,6 @@ use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::utils::{JsValueExt, ToSerdeJSONExt}; use dpp::balances::credits::TokenAmount; use dpp::fee::Credits; @@ -8,6 +10,12 @@ use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "bigint | Record")] + pub type TokenPricingScheduleValueJs; +} + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "TokenPricingSchedule")] pub struct TokenPricingScheduleWasm(TokenPricingSchedule); @@ -26,24 +34,16 @@ impl From for TokenPricingScheduleWasm { #[wasm_bindgen(js_class = TokenPricingSchedule)] impl TokenPricingScheduleWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenPricingSchedule".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenPricingSchedule".to_string() - } - #[wasm_bindgen(js_name = "SinglePrice")] pub fn single_price(credits: Credits) -> Self { Self(TokenPricingSchedule::SinglePrice(credits)) } #[wasm_bindgen(js_name = "SetPrices")] - pub fn set_prices(js_prices: &JsValue) -> WasmDppResult { - let raw_prices = js_prices.with_serde_to_platform_value_map()?; + pub fn set_prices( + #[wasm_bindgen(unchecked_param_type = "Record")] prices: &JsValue, + ) -> WasmDppResult { + let raw_prices = prices.with_serde_to_platform_value_map()?; let mut prices: BTreeMap = BTreeMap::new(); @@ -68,19 +68,19 @@ impl TokenPricingScheduleWasm { Ok(Self(TokenPricingSchedule::SetPrices(prices))) } - #[wasm_bindgen(js_name = "getScheduleType")] - pub fn get_scheduled_type(&self) -> String { + #[wasm_bindgen(getter = "scheduleType")] + pub fn schedule_type(&self) -> String { match &self.0 { TokenPricingSchedule::SinglePrice(_) => String::from("SinglePrice"), TokenPricingSchedule::SetPrices(_) => String::from("SetPrices"), } } - #[wasm_bindgen(js_name = "getValue")] - pub fn get_value(&self) -> WasmDppResult { - match &self.0 { + #[wasm_bindgen(getter = "value")] + pub fn value(&self) -> WasmDppResult { + let js_value = match &self.0 { TokenPricingSchedule::SinglePrice(credits) => { - Ok(JsValue::bigint_from_str(&credits.to_string())) + JsValue::bigint_from_str(&credits.to_string()) } TokenPricingSchedule::SetPrices(prices) => { let price_object = Object::new(); @@ -89,7 +89,7 @@ impl TokenPricingScheduleWasm { Reflect::set( &price_object, &JsValue::from(key.to_string()), - &(*value).into(), + &JsValue::bigint_from_str(&value.to_string()), ) .map_err(|err| { let message = err.error_message(); @@ -100,8 +100,12 @@ impl TokenPricingScheduleWasm { })?; } - Ok(price_object.into()) + price_object.into() } - } + }; + Ok(js_value.into()) } } + +impl_try_from_js_value!(TokenPricingScheduleWasm, "TokenPricingSchedule"); +impl_wasm_type_info!(TokenPricingScheduleWasm, TokenPricingSchedule); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transition.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transition.rs index 4b76a9168f3..99cc918feaf 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transition.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transition.rs @@ -1,5 +1,8 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_from_for_extern_type; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::token_transitions::config_update::TokenConfigUpdateTransitionWasm; use crate::state_transitions::batch::token_transitions::direct_purchase::TokenDirectPurchaseTransitionWasm; use crate::state_transitions::batch::token_transitions::set_price_for_direct_purchase::TokenSetPriceForDirectPurchaseTransitionWasm; @@ -11,8 +14,8 @@ use crate::state_transitions::batch::token_transitions::token_freeze::TokenFreez use crate::state_transitions::batch::token_transitions::token_mint::TokenMintTransitionWasm; use crate::state_transitions::batch::token_transitions::token_transfer::TokenTransferTransitionWasm; use crate::state_transitions::batch::token_transitions::token_unfreeze::TokenUnFreezeTransitionWasm; -use crate::utils::{IntoWasm, get_class_type}; -use dpp::prelude::IdentityNonce; +use crate::utils::get_class_type; +use dpp::prelude::{Identifier, IdentityNonce}; use dpp::state_transition::batch_transition::batched_transition::token_transition::{ TokenTransition, TokenTransitionV0Methods, }; @@ -25,8 +28,35 @@ use dpp::state_transition::batch_transition::{ use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_TRANSITION_TYPES_TS: &str = r#" +export type TokenTransitionLike = TokenMintTransition | TokenBurnTransition | TokenTransferTransition | TokenFreezeTransition | TokenUnFreezeTransition | TokenDestroyFrozenFundsTransition | TokenClaimTransition | TokenEmergencyActionTransition | TokenConfigUpdateTransition | TokenDirectPurchaseTransition | TokenSetPriceForDirectPurchaseTransition; +"#; + +/// Extern type for flexible TokenTransition input +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenTransitionLike")] + pub type TokenTransitionLikeJs; +} + +impl_from_for_extern_type!( + TokenTransitionLikeJs, + TokenMintTransitionWasm, + TokenBurnTransitionWasm, + TokenTransferTransitionWasm, + TokenFreezeTransitionWasm, + TokenUnFreezeTransitionWasm, + TokenDestroyFrozenFundsTransitionWasm, + TokenClaimTransitionWasm, + TokenEmergencyActionTransitionWasm, + TokenConfigUpdateTransitionWasm, + TokenDirectPurchaseTransitionWasm, + TokenSetPriceForDirectPurchaseTransitionWasm, +); + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenTransition)] +#[wasm_bindgen(js_name = "TokenTransition")] pub struct TokenTransitionWasm(TokenTransition); impl From for TokenTransitionWasm { @@ -43,94 +73,55 @@ impl From for TokenTransition { #[wasm_bindgen(js_class = TokenTransition)] impl TokenTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(js_transition: &JsValue) -> WasmDppResult { - if !js_transition.is_object() { + pub fn constructor(transition: TokenTransitionLikeJs) -> WasmDppResult { + let transition: JsValue = transition.into(); + if !transition.is_object() { return Err(WasmDppError::invalid_argument("Bad token transition input")); } - let transition = match get_class_type(js_transition)?.as_str() { + let transition = match get_class_type(&transition)?.as_str() { "TokenMintTransition" => TokenTransition::from(TokenMintTransition::from( - js_transition - .to_wasm::("TokenMintTransition")? - .clone(), + TokenMintTransitionWasm::try_from(&transition)?, )), "TokenUnFreezeTransition" => TokenTransition::from(TokenUnfreezeTransition::from( - js_transition - .to_wasm::("TokenUnFreezeTransition")? - .clone(), + TokenUnFreezeTransitionWasm::try_from(&transition)?, )), "TokenTransferTransition" => TokenTransition::from(TokenTransferTransition::from( - js_transition - .to_wasm::("TokenTransferTransition")? - .clone(), + TokenTransferTransitionWasm::try_from(&transition)?, )), "TokenFreezeTransition" => TokenTransition::from(TokenFreezeTransition::from( - js_transition - .to_wasm::("TokenFreezeTransition")? - .clone(), + TokenFreezeTransitionWasm::try_from(&transition)?, )), "TokenDestroyFrozenFundsTransition" => { TokenTransition::from(TokenDestroyFrozenFundsTransition::from( - js_transition - .to_wasm::( - "TokenDestroyFrozenFundsTransition", - )? - .clone(), + TokenDestroyFrozenFundsTransitionWasm::try_from(&transition)?, )) } "TokenClaimTransition" => TokenTransition::from(TokenClaimTransition::from( - js_transition - .to_wasm::("TokenClaimTransition")? - .clone(), + TokenClaimTransitionWasm::try_from(&transition)?, )), "TokenBurnTransition" => TokenTransition::from(TokenBurnTransition::from( - js_transition - .to_wasm::("TokenBurnTransition")? - .clone(), + TokenBurnTransitionWasm::try_from(&transition)?, )), "TokenSetPriceForDirectPurchaseTransition" => { TokenTransition::from(TokenSetPriceForDirectPurchaseTransition::from( - js_transition - .to_wasm::( - "TokenSetPriceForDirectPurchaseTransition", - )? - .clone(), + TokenSetPriceForDirectPurchaseTransitionWasm::try_from(&transition)?, )) } "TokenDirectPurchaseTransition" => { TokenTransition::from(TokenDirectPurchaseTransition::from( - js_transition - .to_wasm::( - "TokenDirectPurchaseTransition", - )? - .clone(), + TokenDirectPurchaseTransitionWasm::try_from(&transition)?, )) } "TokenConfigUpdateTransition" => { TokenTransition::from(TokenConfigUpdateTransition::from( - js_transition - .to_wasm::("TokenConfigUpdateTransition")? - .clone(), + TokenConfigUpdateTransitionWasm::try_from(&transition)?, )) } "TokenEmergencyActionTransition" => { TokenTransition::from(TokenEmergencyActionTransition::from( - js_transition - .to_wasm::( - "TokenEmergencyActionTransition", - )? - .clone(), + TokenEmergencyActionTransitionWasm::try_from(&transition)?, )) } _ => { @@ -141,8 +132,8 @@ impl TokenTransitionWasm { Ok(TokenTransitionWasm(transition)) } - #[wasm_bindgen(js_name = "getTransition")] - pub fn to_transition(&self) -> JsValue { + #[wasm_bindgen(getter = "transition")] + pub fn transition(&self) -> TokenTransitionLikeJs { match self.clone().0 { TokenTransition::Burn(token_transition) => { TokenBurnTransitionWasm::from(token_transition).into() @@ -180,8 +171,8 @@ impl TokenTransitionWasm { } } - #[wasm_bindgen(js_name = "getTransitionTypeNumber")] - pub fn get_transition_type_number(&self) -> u8 { + #[wasm_bindgen(getter = "transitionTypeNumber")] + pub fn transition_type_number(&self) -> u8 { match self.clone().0 { TokenTransition::Burn(_) => 0, TokenTransition::Mint(_) => 1, @@ -197,8 +188,8 @@ impl TokenTransitionWasm { } } - #[wasm_bindgen(js_name = "getTransitionType")] - pub fn get_transition_type(&self) -> String { + #[wasm_bindgen(getter = "transitionType")] + pub fn transition_type(&self) -> String { match self.clone().0 { TokenTransition::Burn(_) => "Burn".to_string(), TokenTransition::Mint(_) => "Mint".to_string(), @@ -216,49 +207,51 @@ impl TokenTransitionWasm { } } - #[wasm_bindgen(js_name = "getHistoricalDocumentTypeName")] - pub fn get_historical_document_type_name(&self) -> String { + #[wasm_bindgen(getter = "historicalDocumentTypeName")] + pub fn historical_document_type_name(&self) -> String { self.0.historical_document_type_name().to_string() } #[wasm_bindgen(js_name = "getHistoricalDocumentId")] pub fn get_historical_document_id( &self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_owner: &JsValue, + owner: IdentifierLikeJs, ) -> WasmDppResult { - let owner = IdentifierWasm::try_from(js_owner)?.into(); + let owner: Identifier = owner.try_into()?; Ok(self.0.historical_document_id(owner).into()) } #[wasm_bindgen(getter = "identityContractNonce")] - pub fn get_identity_contract_nonce(&self) -> IdentityNonce { + pub fn identity_contract_nonce(&self) -> IdentityNonce { self.0.identity_contract_nonce() } #[wasm_bindgen(getter = "tokenId")] - pub fn get_token_id(&self) -> IdentifierWasm { + pub fn token_id(&self) -> IdentifierWasm { self.0.token_id().into() } #[wasm_bindgen(getter = "contractId")] - pub fn get_contract_id(&self) -> IdentifierWasm { + pub fn contract_id(&self) -> IdentifierWasm { self.0.data_contract_id().into() } #[wasm_bindgen(setter = "identityContractNonce")] - pub fn set_identity_contract_nonce(&mut self, nonce: IdentityNonce) { - self.0.set_identity_contract_nonce(nonce) + pub fn set_identity_contract_nonce(&mut self, nonce: JsValue) -> WasmDppResult<()> { + use crate::utils::try_to_u64; + self.0 + .set_identity_contract_nonce(try_to_u64(&nonce, "identityContractNonce")?); + Ok(()) } #[wasm_bindgen(setter = "tokenId")] pub fn set_token_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] js_id: &JsValue, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let id = IdentifierWasm::try_from(js_id)?.into(); + let token_id: Identifier = token_id.try_into()?; - self.0.set_token_id(id); + self.0.set_token_id(token_id); Ok(()) } @@ -266,12 +259,15 @@ impl TokenTransitionWasm { #[wasm_bindgen(setter = "contractId")] pub fn set_contract_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] js_id: &JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let id = IdentifierWasm::try_from(js_id)?.into(); + let contract_id: Identifier = contract_id.try_into()?; - self.0.set_data_contract_id(id); + self.0.set_data_contract_id(contract_id); Ok(()) } } + +impl_try_from_js_value!(TokenTransitionWasm, "TokenTransition"); +impl_wasm_type_info!(TokenTransitionWasm, TokenTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/config_update.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/config_update.rs index 4d82c2a6c67..500ef70d360 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/config_update.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/config_update.rs @@ -1,12 +1,30 @@ -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::error::WasmDppResult; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::tokens::configuration_change_item::TokenConfigurationChangeItemWasm; +use crate::utils::{try_from_options, try_from_options_optional_with, try_to_string}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_config_update_transition::v0::v0_methods::TokenConfigUpdateTransitionV0Methods; use dpp::state_transition::batch_transition::token_config_update_transition::TokenConfigUpdateTransitionV0; use dpp::state_transition::batch_transition::TokenConfigUpdateTransition; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_CONFIG_UPDATE_OPTIONS_TS: &str = r#" +export interface TokenConfigUpdateTransitionOptions { + base: TokenBaseTransition; + updateTokenConfigurationItem: TokenConfigurationChangeItem; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenConfigUpdateTransitionOptions")] + pub type TokenConfigUpdateTransitionOptionsJs; +} + #[derive(Debug, Clone, PartialEq)] #[wasm_bindgen(js_name = "TokenConfigUpdateTransition")] pub struct TokenConfigUpdateTransitionWasm(TokenConfigUpdateTransition); @@ -25,43 +43,41 @@ impl From for TokenConfigUpdateTransitionWasm { #[wasm_bindgen(js_class = TokenConfigUpdateTransition)] impl TokenConfigUpdateTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenConfigUpdateTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenConfigUpdateTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - update_token_configuration_item: &TokenConfigurationChangeItemWasm, - public_note: Option, + pub fn constructor( + options: TokenConfigUpdateTransitionOptionsJs, ) -> WasmDppResult { + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let update_token_configuration_item: TokenConfigurationChangeItemWasm = + try_from_options(&options, "updateTokenConfigurationItem")?; + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; + Ok(TokenConfigUpdateTransitionWasm( TokenConfigUpdateTransition::V0(TokenConfigUpdateTransitionV0 { - base: base.clone().into(), - update_token_configuration_item: update_token_configuration_item.clone().into(), + base: base.into(), + update_token_configuration_item: update_token_configuration_item.into(), public_note, }), )) } #[wasm_bindgen(getter = base)] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = publicNote)] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = updateTokenConfigurationItem)] - pub fn get_update_token_configuration_item(&self) -> TokenConfigurationChangeItemWasm { + pub fn update_token_configuration_item(&self) -> TokenConfigurationChangeItemWasm { self.0.update_token_configuration_item().clone().into() } @@ -81,3 +97,9 @@ impl TokenConfigUpdateTransitionWasm { .set_update_token_configuration_item(item.clone().into()) } } + +impl_try_from_js_value!( + TokenConfigUpdateTransitionWasm, + "TokenConfigUpdateTransition" +); +impl_wasm_type_info!(TokenConfigUpdateTransitionWasm, TokenConfigUpdateTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/direct_purchase.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/direct_purchase.rs index d2b131606f7..b736eca2c13 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/direct_purchase.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/direct_purchase.rs @@ -1,14 +1,33 @@ +use crate::error::WasmDppResult; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; +use crate::utils::{try_from_options, try_from_options_with, try_to_u64}; use dpp::balances::credits::TokenAmount; use dpp::fee::Credits; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; -use dpp::state_transition::batch_transition::token_direct_purchase_transition::TokenDirectPurchaseTransitionV0; use dpp::state_transition::batch_transition::token_direct_purchase_transition::v0::v0_methods::TokenDirectPurchaseTransitionV0Methods; +use dpp::state_transition::batch_transition::token_direct_purchase_transition::TokenDirectPurchaseTransitionV0; use dpp::state_transition::batch_transition::TokenDirectPurchaseTransition; use wasm_bindgen::prelude::wasm_bindgen; -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; + +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_DIRECT_PURCHASE_OPTIONS_TS: &str = r#" +export interface TokenDirectPurchaseTransitionOptions { + base: TokenBaseTransition; + tokenCount: bigint; + totalAgreedPrice: bigint; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenDirectPurchaseTransitionOptions")] + pub type TokenDirectPurchaseTransitionOptionsJs; +} #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenDirectPurchaseTransition)] +#[wasm_bindgen(js_name = "TokenDirectPurchaseTransition")] pub struct TokenDirectPurchaseTransitionWasm(TokenDirectPurchaseTransition); impl From for TokenDirectPurchaseTransition { @@ -25,43 +44,41 @@ impl From for TokenDirectPurchaseTransitionWasm { #[wasm_bindgen(js_class = TokenDirectPurchaseTransition)] impl TokenDirectPurchaseTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenDirectPurchaseTransition".to_string() - } + #[wasm_bindgen(constructor)] + pub fn constructor( + options: TokenDirectPurchaseTransitionOptionsJs, + ) -> WasmDppResult { + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenDirectPurchaseTransition".to_string() - } + let token_count: TokenAmount = + try_from_options_with(&options, "tokenCount", |v| try_to_u64(v, "tokenCount"))?; - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - token_count: TokenAmount, - total_agreed_price: Credits, - ) -> Self { - TokenDirectPurchaseTransitionWasm(TokenDirectPurchaseTransition::V0( - TokenDirectPurchaseTransitionV0 { - base: base.clone().into(), + let total_agreed_price: Credits = + try_from_options_with(&options, "totalAgreedPrice", |v| { + try_to_u64(v, "totalAgreedPrice") + })?; + + Ok(TokenDirectPurchaseTransitionWasm( + TokenDirectPurchaseTransition::V0(TokenDirectPurchaseTransitionV0 { + base: base.into(), token_count, total_agreed_price, - }, + }), )) } #[wasm_bindgen(getter = base)] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = tokenCount)] - pub fn get_token_count(&self) -> TokenAmount { + pub fn token_count(&self) -> TokenAmount { self.0.token_count() } #[wasm_bindgen(getter = totalAgreedPrice)] - pub fn get_total_agreed_price(&self) -> Credits { + pub fn total_agreed_price(&self) -> Credits { self.0.total_agreed_price() } @@ -71,12 +88,27 @@ impl TokenDirectPurchaseTransitionWasm { } #[wasm_bindgen(setter = tokenCount)] - pub fn set_token_count(&mut self, token_count: TokenAmount) { + pub fn set_token_count( + &mut self, + #[wasm_bindgen(js_name = "tokenCount")] token_count: TokenAmount, + ) { self.0.set_token_count(token_count) } #[wasm_bindgen(setter = totalAgreedPrice)] - pub fn set_total_agreed_price(&mut self, total_agreed_price: Credits) { + pub fn set_total_agreed_price( + &mut self, + #[wasm_bindgen(js_name = "totalAgreedPrice")] total_agreed_price: Credits, + ) { self.0.set_total_agreed_price(total_agreed_price) } } + +impl_try_from_js_value!( + TokenDirectPurchaseTransitionWasm, + "TokenDirectPurchaseTransition" +); +impl_wasm_type_info!( + TokenDirectPurchaseTransitionWasm, + TokenDirectPurchaseTransition +); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/set_price_for_direct_purchase.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/set_price_for_direct_purchase.rs index 0ff21ff5740..cfb0003a9c0 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/set_price_for_direct_purchase.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/set_price_for_direct_purchase.rs @@ -1,17 +1,33 @@ +use crate::error::WasmDppResult; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::state_transitions::batch::token_pricing_schedule::TokenPricingScheduleWasm; -use crate::error::WasmDppResult; -use crate::utils::IntoWasm; +use crate::utils::{try_from_options, try_from_options_optional, try_from_options_optional_with, try_to_string}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_set_price_for_direct_purchase_transition::v0::v0_methods::TokenSetPriceForDirectPurchaseTransitionV0Methods; use dpp::state_transition::batch_transition::token_set_price_for_direct_purchase_transition::TokenSetPriceForDirectPurchaseTransitionV0; use dpp::state_transition::batch_transition::TokenSetPriceForDirectPurchaseTransition; use dpp::tokens::token_pricing_schedule::TokenPricingSchedule; use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::JsValue; + +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_SET_PRICE_OPTIONS_TS: &str = r#" +export interface TokenSetPriceForDirectPurchaseTransitionOptions { + base: TokenBaseTransition; + price?: TokenPricingSchedule; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenSetPriceForDirectPurchaseTransitionOptions")] + pub type TokenSetPriceForDirectPurchaseTransitionOptionsJs; +} #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenSetPriceForDirectPurchaseTransition)] +#[wasm_bindgen(js_name = "TokenSetPriceForDirectPurchaseTransition")] pub struct TokenSetPriceForDirectPurchaseTransitionWasm(TokenSetPriceForDirectPurchaseTransition); impl From @@ -32,36 +48,25 @@ impl From #[wasm_bindgen(js_class = TokenSetPriceForDirectPurchaseTransition)] impl TokenSetPriceForDirectPurchaseTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenSetPriceForDirectPurchaseTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenSetPriceForDirectPurchaseTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - js_price: &JsValue, - public_note: Option, + pub fn constructor( + options: TokenSetPriceForDirectPurchaseTransitionOptionsJs, ) -> WasmDppResult { - let price: Option = match js_price.is_undefined() { - true => None, - false => Some( - js_price - .to_wasm::("TokenPricingSchedule")? - .clone() - .into(), - ), - }; + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let price: Option = + try_from_options_optional::(&options, "price")? + .map(Into::into); + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; Ok(TokenSetPriceForDirectPurchaseTransitionWasm( TokenSetPriceForDirectPurchaseTransition::V0( TokenSetPriceForDirectPurchaseTransitionV0 { - base: base.clone().into(), + base: base.into(), price, public_note, }, @@ -70,21 +75,18 @@ impl TokenSetPriceForDirectPurchaseTransitionWasm { } #[wasm_bindgen(getter = base)] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "publicNote")] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = "price")] - pub fn get_price(&self) -> JsValue { - match self.0.price() { - None => JsValue::null(), - Some(price) => JsValue::from(TokenPricingScheduleWasm::from(price.clone())), - } + pub fn price(&self) -> Option { + self.0.price().map(|p| p.clone().into()) } #[wasm_bindgen(setter = "base")] @@ -98,18 +100,16 @@ impl TokenSetPriceForDirectPurchaseTransitionWasm { } #[wasm_bindgen(setter = "price")] - pub fn set_price(&mut self, js_price: &JsValue) -> WasmDppResult<()> { - let price: Option = match js_price.is_undefined() { - true => None, - false => Some( - js_price - .to_wasm::("TokenPricingSchedule")? - .clone() - .into(), - ), - }; - - self.0.set_price(price); - Ok(()) + pub fn set_price(&mut self, price: Option) { + self.0.set_price(price.map(|p| p.into())); } } + +impl_try_from_js_value!( + TokenSetPriceForDirectPurchaseTransitionWasm, + "TokenSetPriceForDirectPurchaseTransition" +); +impl_wasm_type_info!( + TokenSetPriceForDirectPurchaseTransitionWasm, + TokenSetPriceForDirectPurchaseTransition +); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_burn.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_burn.rs index 3d60bbff39e..26bf37fc15f 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_burn.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_burn.rs @@ -1,13 +1,32 @@ -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::error::WasmDppResult; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; +use crate::utils::{try_from_options, try_from_options_optional_with, try_from_options_with, try_to_string, try_to_u64}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_burn_transition::v0::v0_methods::TokenBurnTransitionV0Methods; use dpp::state_transition::batch_transition::token_burn_transition::TokenBurnTransitionV0; use dpp::state_transition::batch_transition::TokenBurnTransition; +use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_BURN_OPTIONS_TS: &str = r#" +export interface TokenBurnTransitionOptions { + base: TokenBaseTransition; + burnAmount: bigint; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenBurnTransitionOptions")] + pub type TokenBurnTransitionOptionsJs; +} + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenBurnTransition)] +#[wasm_bindgen(js_name = "TokenBurnTransition")] pub struct TokenBurnTransitionWasm(TokenBurnTransition); impl From for TokenBurnTransitionWasm { @@ -24,25 +43,23 @@ impl From for TokenBurnTransition { #[wasm_bindgen(js_class = TokenBurnTransition)] impl TokenBurnTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenBurnTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenBurnTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - burn_amount: u64, - public_note: Option, + pub fn constructor( + options: TokenBurnTransitionOptionsJs, ) -> WasmDppResult { + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let burn_amount = + try_from_options_with(&options, "burnAmount", |v| try_to_u64(v, "burnAmount"))?; + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; + Ok(TokenBurnTransitionWasm(TokenBurnTransition::V0( TokenBurnTransitionV0 { - base: base.clone().into(), + base: base.into(), burn_amount, public_note, }, @@ -50,23 +67,24 @@ impl TokenBurnTransitionWasm { } #[wasm_bindgen(getter = burnAmount)] - pub fn get_burn_amount(&self) -> u64 { + pub fn burn_amount(&self) -> u64 { self.0.burn_amount() } #[wasm_bindgen(getter = base)] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = publicNote)] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(setter = burnAmount)] - pub fn set_burn_amount(&mut self, amount: u64) { - self.0.set_burn_amount(amount) + pub fn set_burn_amount(&mut self, amount: JsValue) -> WasmDppResult<()> { + self.0.set_burn_amount(try_to_u64(&amount, "burnAmount")?); + Ok(()) } #[wasm_bindgen(setter = base)] @@ -79,3 +97,6 @@ impl TokenBurnTransitionWasm { self.0.set_public_note(note) } } + +impl_try_from_js_value!(TokenBurnTransitionWasm, "TokenBurnTransition"); +impl_wasm_type_info!(TokenBurnTransitionWasm, TokenBurnTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_claim.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_claim.rs index b78ab15a300..6240c9a2b14 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_claim.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_claim.rs @@ -1,6 +1,9 @@ -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::enums::token::distribution_type::TokenDistributionTypeWasm; use crate::error::WasmDppResult; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; +use crate::utils::{try_from_options, try_from_options_optional, try_from_options_optional_with, try_to_string}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_claim_transition::v0::v0_methods::TokenClaimTransitionV0Methods; use dpp::state_transition::batch_transition::token_claim_transition::TokenClaimTransitionV0; @@ -8,6 +11,21 @@ use dpp::state_transition::batch_transition::TokenClaimTransition; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_CLAIM_OPTIONS_TS: &str = r#" +export interface TokenClaimTransitionOptions { + base: TokenBaseTransition; + distributionType?: TokenDistributionTypeLike; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenClaimTransitionOptions")] + pub type TokenClaimTransitionOptionsJs; +} + #[derive(Debug, Clone, PartialEq)] #[wasm_bindgen(js_name = "TokenClaimTransition")] pub struct TokenClaimTransitionWasm(TokenClaimTransition); @@ -26,30 +44,23 @@ impl From for TokenClaimTransition { #[wasm_bindgen(js_class = TokenClaimTransition)] impl TokenClaimTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenClaimTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenClaimTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - js_distribution_type: &JsValue, - public_note: Option, + pub fn constructor( + options: TokenClaimTransitionOptionsJs, ) -> WasmDppResult { - let distribution_type = match js_distribution_type.is_undefined() { - true => TokenDistributionTypeWasm::default(), - false => TokenDistributionTypeWasm::try_from(js_distribution_type.clone())?, - }; + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let distribution_type: TokenDistributionTypeWasm = + try_from_options_optional(&options, "distributionType")?.unwrap_or_default(); + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; Ok(TokenClaimTransitionWasm(TokenClaimTransition::V0( TokenClaimTransitionV0 { - base: base.clone().into(), + base: base.into(), distribution_type: distribution_type.into(), public_note, }, @@ -57,17 +68,17 @@ impl TokenClaimTransitionWasm { } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "publicNote")] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = "distributionType")] - pub fn get_distribution_type(&self) -> String { + pub fn distribution_type(&self) -> String { TokenDistributionTypeWasm::from(self.0.distribution_type()).into() } @@ -82,13 +93,21 @@ impl TokenClaimTransitionWasm { } #[wasm_bindgen(setter = "distributionType")] - pub fn set_distribution_type(&mut self, js_distribution_type: &JsValue) -> WasmDppResult<()> { - let distribution_type = match js_distribution_type.is_undefined() { - true => TokenDistributionTypeWasm::default(), - false => TokenDistributionTypeWasm::try_from(js_distribution_type.clone())?, + pub fn set_distribution_type( + &mut self, + #[wasm_bindgen(unchecked_param_type = "TokenDistributionTypeLike | undefined")] + distribution_type: &JsValue, + ) -> WasmDppResult<()> { + let distribution_type = if distribution_type.is_undefined() { + TokenDistributionTypeWasm::default() + } else { + TokenDistributionTypeWasm::try_from(distribution_type.clone())? }; self.0.set_distribution_type(distribution_type.into()); Ok(()) } } + +impl_try_from_js_value!(TokenClaimTransitionWasm, "TokenClaimTransition"); +impl_wasm_type_info!(TokenClaimTransitionWasm, TokenClaimTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_destroy_frozen_funds.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_destroy_frozen_funds.rs index 2194629890b..3c595592627 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_destroy_frozen_funds.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_destroy_frozen_funds.rs @@ -1,16 +1,32 @@ -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; -use dpp::identifier::Identifier; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; +use crate::utils::{try_from_options, try_from_options_optional_with, try_to_string}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_destroy_frozen_funds_transition::v0::v0_methods::TokenDestroyFrozenFundsTransitionV0Methods; use dpp::state_transition::batch_transition::token_destroy_frozen_funds_transition::TokenDestroyFrozenFundsTransitionV0; use dpp::state_transition::batch_transition::TokenDestroyFrozenFundsTransition; use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::JsValue; + +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_DESTROY_FROZEN_FUNDS_OPTIONS_TS: &str = r#" +export interface TokenDestroyFrozenFundsTransitionOptions { + base: TokenBaseTransition; + frozenIdentityId: IdentifierLike; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenDestroyFrozenFundsTransitionOptions")] + pub type TokenDestroyFrozenFundsTransitionOptionsJs; +} #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenDestroyFrozenFundsTransition)] +#[wasm_bindgen(js_name = "TokenDestroyFrozenFundsTransition")] pub struct TokenDestroyFrozenFundsTransitionWasm(TokenDestroyFrozenFundsTransition); impl From for TokenDestroyFrozenFundsTransitionWasm { @@ -27,47 +43,40 @@ impl From for TokenDestroyFrozenFundsTran #[wasm_bindgen(js_class = TokenDestroyFrozenFundsTransition)] impl TokenDestroyFrozenFundsTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenDestroyFrozenFundsTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenDestroyFrozenFundsTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_frozen_identity_id: &JsValue, - public_note: Option, + pub fn constructor( + options: TokenDestroyFrozenFundsTransitionOptionsJs, ) -> WasmDppResult { - let frozen_identity_id: Identifier = - IdentifierWasm::try_from(js_frozen_identity_id)?.into(); + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let frozen_identity_id: IdentifierWasm = try_from_options(&options, "frozenIdentityId")?; + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; Ok(TokenDestroyFrozenFundsTransitionWasm( TokenDestroyFrozenFundsTransition::V0(TokenDestroyFrozenFundsTransitionV0 { - base: base.clone().into(), - frozen_identity_id, + base: base.into(), + frozen_identity_id: frozen_identity_id.into(), public_note, }), )) } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "publicNote")] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = "frozenIdentityId")] - pub fn get_frozen_identity_id(&self) -> IdentifierWasm { + pub fn frozen_identity_id(&self) -> IdentifierWasm { self.0.frozen_identity_id().into() } @@ -84,11 +93,19 @@ impl TokenDestroyFrozenFundsTransitionWasm { #[wasm_bindgen(setter = "frozenIdentityId")] pub fn set_frozen_identity_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_frozen_identity_id: &JsValue, + #[wasm_bindgen(js_name = "frozenIdentityId")] frozen_identity_id: IdentifierLikeJs, ) -> WasmDppResult<()> { self.0 - .set_frozen_identity_id(IdentifierWasm::try_from(js_frozen_identity_id)?.into()); + .set_frozen_identity_id(frozen_identity_id.try_into()?); Ok(()) } } + +impl_try_from_js_value!( + TokenDestroyFrozenFundsTransitionWasm, + "TokenDestroyFrozenFundsTransition" +); +impl_wasm_type_info!( + TokenDestroyFrozenFundsTransitionWasm, + TokenDestroyFrozenFundsTransition +); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_emergency_action.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_emergency_action.rs index c308fb2adda..324174b7a4d 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_emergency_action.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_emergency_action.rs @@ -1,10 +1,29 @@ +use crate::enums::token::emergency_action::TokenEmergencyActionWasm; +use crate::error::WasmDppResult; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; +use crate::utils::{try_from_options, try_from_options_optional_with, try_to_string}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; -use dpp::state_transition::batch_transition::token_emergency_action_transition::TokenEmergencyActionTransitionV0; use dpp::state_transition::batch_transition::token_emergency_action_transition::v0::v0_methods::TokenEmergencyActionTransitionV0Methods; +use dpp::state_transition::batch_transition::token_emergency_action_transition::TokenEmergencyActionTransitionV0; use dpp::state_transition::batch_transition::TokenEmergencyActionTransition; use wasm_bindgen::prelude::wasm_bindgen; -use crate::enums::token::emergency_action::TokenEmergencyActionWasm; -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; + +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_EMERGENCY_ACTION_OPTIONS_TS: &str = r#" +export interface TokenEmergencyActionTransitionOptions { + base: TokenBaseTransition; + emergencyAction: TokenEmergencyActionLike; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenEmergencyActionTransitionOptions")] + pub type TokenEmergencyActionTransitionOptionsJs; +} #[derive(Debug, Clone, PartialEq)] #[wasm_bindgen(js_name = "TokenEmergencyActionTransition")] @@ -24,43 +43,41 @@ impl From for TokenEmergencyActionTransitionWasm #[wasm_bindgen(js_class = TokenEmergencyActionTransition)] impl TokenEmergencyActionTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenEmergencyActionTransition".to_string() - } + #[wasm_bindgen(constructor)] + pub fn constructor( + options: TokenEmergencyActionTransitionOptionsJs, + ) -> WasmDppResult { + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenEmergencyActionTransition".to_string() - } + let emergency_action: TokenEmergencyActionWasm = + try_from_options(&options, "emergencyAction")?; - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - emergency_action: TokenEmergencyActionWasm, - public_note: Option, - ) -> TokenEmergencyActionTransitionWasm { - TokenEmergencyActionTransitionWasm(TokenEmergencyActionTransition::V0( - TokenEmergencyActionTransitionV0 { - base: base.clone().into(), + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; + + Ok(TokenEmergencyActionTransitionWasm( + TokenEmergencyActionTransition::V0(TokenEmergencyActionTransitionV0 { + base: base.into(), emergency_action: emergency_action.into(), public_note, - }, + }), )) } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "publicNote")] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = "emergencyAction")] - pub fn get_emergency_action(&self) -> String { + pub fn emergency_action(&self) -> String { TokenEmergencyActionWasm::from(self.0.emergency_action()).into() } @@ -79,3 +96,12 @@ impl TokenEmergencyActionTransitionWasm { self.0.set_emergency_action(action.into()) } } + +impl_try_from_js_value!( + TokenEmergencyActionTransitionWasm, + "TokenEmergencyActionTransition" +); +impl_wasm_type_info!( + TokenEmergencyActionTransitionWasm, + TokenEmergencyActionTransition +); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_freeze.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_freeze.rs index a9bd2c9daed..d4982aceb7c 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_freeze.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_freeze.rs @@ -1,16 +1,32 @@ -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; -use dpp::identifier::Identifier; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; +use crate::utils::{try_from_options, try_from_options_optional_with, try_to_string}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_freeze_transition::v0::v0_methods::TokenFreezeTransitionV0Methods; use dpp::state_transition::batch_transition::token_freeze_transition::TokenFreezeTransitionV0; use dpp::state_transition::batch_transition::TokenFreezeTransition; use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::JsValue; + +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_FREEZE_OPTIONS_TS: &str = r#" +export interface TokenFreezeTransitionOptions { + base: TokenBaseTransition; + identityToFreezeId: IdentifierLike; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenFreezeTransitionOptions")] + pub type TokenFreezeTransitionOptionsJs; +} #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenFreezeTransition)] +#[wasm_bindgen(js_name = "TokenFreezeTransition")] pub struct TokenFreezeTransitionWasm(TokenFreezeTransition); impl From for TokenFreezeTransition { @@ -27,47 +43,41 @@ impl From for TokenFreezeTransitionWasm { #[wasm_bindgen(js_class = TokenFreezeTransition)] impl TokenFreezeTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenFreezeTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenFreezeTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_to_freeze_id: &JsValue, - public_note: Option, + pub fn constructor( + options: TokenFreezeTransitionOptionsJs, ) -> WasmDppResult { - let identity_to_freeze_id: Identifier = - IdentifierWasm::try_from(js_identity_to_freeze_id)?.into(); + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let identity_to_freeze_id: IdentifierWasm = + try_from_options(&options, "identityToFreezeId")?; + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; Ok(TokenFreezeTransitionWasm(TokenFreezeTransition::V0( TokenFreezeTransitionV0 { - base: base.clone().into(), - identity_to_freeze_id, + base: base.into(), + identity_to_freeze_id: identity_to_freeze_id.into(), public_note, }, ))) } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "publicNote")] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = "frozenIdentityId")] - pub fn get_frozen_identity_id(&self) -> IdentifierWasm { + pub fn frozen_identity_id(&self) -> IdentifierWasm { self.0.frozen_identity_id().into() } @@ -84,11 +94,13 @@ impl TokenFreezeTransitionWasm { #[wasm_bindgen(setter = "frozenIdentityId")] pub fn set_frozen_identity_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_frozen_identity_id: &JsValue, + #[wasm_bindgen(js_name = "frozenIdentityId")] frozen_identity_id: IdentifierLikeJs, ) -> WasmDppResult<()> { self.0 - .set_frozen_identity_id(IdentifierWasm::try_from(js_frozen_identity_id)?.into()); + .set_frozen_identity_id(frozen_identity_id.try_into()?); Ok(()) } } + +impl_try_from_js_value!(TokenFreezeTransitionWasm, "TokenFreezeTransition"); +impl_wasm_type_info!(TokenFreezeTransitionWasm, TokenFreezeTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_mint.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_mint.rs index b644b95440d..d67bc89db27 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_mint.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_mint.rs @@ -1,7 +1,13 @@ -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeOrUndefinedJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::tokens::configuration::TokenConfigurationWasm; +use crate::utils::{ + try_from_options, try_from_options_optional, try_from_options_optional_with, + try_from_options_with, try_to_string, try_to_u64, +}; use dpp::prelude::Identifier; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_mint_transition::v0::v0_methods::TokenMintTransitionV0Methods; @@ -10,8 +16,24 @@ use dpp::state_transition::batch_transition::TokenMintTransition; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_MINT_OPTIONS_TS: &str = r#" +export interface TokenMintTransitionOptions { + base: TokenBaseTransition; + amount: bigint; + issuedToIdentityId?: IdentifierLike; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenMintTransitionOptions")] + pub type TokenMintTransitionOptionsJs; +} + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenMintTransition)] +#[wasm_bindgen(js_name = "TokenMintTransition")] pub struct TokenMintTransitionWasm(TokenMintTransition); impl From for TokenMintTransitionWasm { @@ -28,34 +50,26 @@ impl From for TokenMintTransition { #[wasm_bindgen(js_class = TokenMintTransition)] impl TokenMintTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenMintTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenMintTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_issued_to_identity_id: &JsValue, - amount: u64, - public_note: Option, + pub fn constructor( + options: TokenMintTransitionOptionsJs, ) -> WasmDppResult { - let issued_to_identity_id: Option = - match js_issued_to_identity_id.is_undefined() { - false => Some(IdentifierWasm::try_from(js_issued_to_identity_id)?.into()), - true => None, - }; + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let amount = try_from_options_with(&options, "amount", |v| try_to_u64(v, "amount"))?; + + let issued_to_identity_id: Option = + try_from_options_optional(&options, "issuedToIdentityId")?; + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; Ok(TokenMintTransitionWasm(TokenMintTransition::V0( TokenMintTransitionV0 { - base: base.clone().into(), - issued_to_identity_id, + base: base.into(), + issued_to_identity_id: issued_to_identity_id.map(Into::into), amount, public_note, }, @@ -68,21 +82,21 @@ impl TokenMintTransitionWasm { } #[wasm_bindgen(getter = amount)] - pub fn get_amount(&self) -> u64 { + pub fn amount(&self) -> u64 { self.0.amount() } #[wasm_bindgen(getter = base)] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = publicNote)] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } - #[wasm_bindgen(js_name = getRecipientId)] + #[wasm_bindgen(js_name = "getRecipientId")] pub fn recipient_id(&self, config: &TokenConfigurationWasm) -> WasmDppResult { Ok(self.0.recipient_id(&config.clone().into())?.into()) } @@ -90,25 +104,17 @@ impl TokenMintTransitionWasm { #[wasm_bindgen(setter = issuedToIdentityId)] pub fn set_issued_to_identity_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] js_id: &JsValue, + identifier: IdentifierLikeOrUndefinedJs, ) -> WasmDppResult<()> { - match js_id.is_undefined() { - true => { - self.0.set_issued_to_identity_id(None); - } - false => { - let id = IdentifierWasm::try_from(js_id)?.into(); - - self.0.set_issued_to_identity_id(Some(id)); - } - } - + let identifier: Option = identifier.try_into()?; + self.0.set_issued_to_identity_id(identifier); Ok(()) } #[wasm_bindgen(setter = amount)] - pub fn set_amount(&mut self, amount: u64) { - self.0.set_amount(amount) + pub fn set_amount(&mut self, amount: JsValue) -> WasmDppResult<()> { + self.0.set_amount(try_to_u64(&amount, "amount")?); + Ok(()) } #[wasm_bindgen(setter = base)] @@ -121,3 +127,6 @@ impl TokenMintTransitionWasm { self.0.set_public_note(note) } } + +impl_try_from_js_value!(TokenMintTransitionWasm, "TokenMintTransition"); +impl_wasm_type_info!(TokenMintTransitionWasm, TokenMintTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_transfer.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_transfer.rs index f80b9cc6f54..913aff4b2d1 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_transfer.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_transfer.rs @@ -1,10 +1,14 @@ +use crate::error::WasmDppResult; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::tokens::encrypted_note::private_encrypted_note::PrivateEncryptedNoteWasm; use crate::tokens::encrypted_note::shared_encrypted_note::SharedEncryptedNoteWasm; -use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; -use crate::utils::IntoWasm; -use dpp::prelude::Identifier; +use crate::utils::{ + try_from_options, try_from_options_optional, try_from_options_optional_with, + try_from_options_with, try_to_string, try_to_u64, +}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_transfer_transition::v0::v0_methods::TokenTransferTransitionV0Methods; use dpp::state_transition::batch_transition::token_transfer_transition::TokenTransferTransitionV0; @@ -13,8 +17,26 @@ use dpp::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_TRANSFER_OPTIONS_TS: &str = r#" +export interface TokenTransferTransitionOptions { + base: TokenBaseTransition; + recipientId: IdentifierLike; + amount: bigint; + publicNote?: string; + sharedEncryptedNote?: SharedEncryptedNote; + privateEncryptedNote?: PrivateEncryptedNote; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenTransferTransitionOptions")] + pub type TokenTransferTransitionOptionsJs; +} + #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenTransferTransition)] +#[wasm_bindgen(js_name = "TokenTransferTransition")] pub struct TokenTransferTransitionWasm(TokenTransferTransition); impl From for TokenTransferTransitionWasm { @@ -31,79 +53,56 @@ impl From for TokenTransferTransition { #[wasm_bindgen(js_class = TokenTransferTransition)] impl TokenTransferTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenTransferTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenTransferTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_recipient_id: &JsValue, - amount: u64, - public_note: Option, - js_shared_encrypted_note: &JsValue, - js_private_encrypted_note: &JsValue, + pub fn constructor( + options: TokenTransferTransitionOptionsJs, ) -> WasmDppResult { - let recipient_id: Identifier = IdentifierWasm::try_from(js_recipient_id)?.into(); + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; - let shared_encrypted_note: Option = - match js_shared_encrypted_note.is_undefined() { - true => None, - false => Some( - js_shared_encrypted_note - .to_wasm::("SharedEncryptedNote")? - .clone() - .into(), - ), - }; + let recipient_id: IdentifierWasm = try_from_options(&options, "recipientId")?; - let private_encrypted_note: Option = - match js_private_encrypted_note.is_undefined() { - true => None, - false => Some( - js_private_encrypted_note - .to_wasm::("PrivateEncryptedNote")? - .clone() - .into(), - ), - }; + let amount = try_from_options_with(&options, "amount", |v| try_to_u64(v, "amount"))?; + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; + + let shared_encrypted_note: Option = + try_from_options_optional(&options, "sharedEncryptedNote")?; + + let private_encrypted_note: Option = + try_from_options_optional(&options, "privateEncryptedNote")?; Ok(TokenTransferTransitionWasm(TokenTransferTransition::V0( TokenTransferTransitionV0 { - base: base.clone().into(), - recipient_id, + base: base.into(), + recipient_id: recipient_id.into(), amount, public_note, - shared_encrypted_note, - private_encrypted_note, + shared_encrypted_note: shared_encrypted_note.map(Into::into), + private_encrypted_note: private_encrypted_note.map(Into::into), }, ))) } #[wasm_bindgen(getter = "amount")] - pub fn get_amount(&self) -> u64 { + pub fn amount(&self) -> u64 { self.0.amount() } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "publicNote")] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = "sharedEncryptedNote")] - pub fn get_shared_encrypted_note(&self) -> Option { + pub fn shared_encrypted_note(&self) -> Option { self.clone() .0 .shared_encrypted_note_owned() @@ -111,7 +110,7 @@ impl TokenTransferTransitionWasm { } #[wasm_bindgen(getter = "privateEncryptedNote")] - pub fn get_private_encrypted_note(&self) -> Option { + pub fn private_encrypted_note(&self) -> Option { self.clone() .0 .private_encrypted_note_owned() @@ -126,19 +125,16 @@ impl TokenTransferTransitionWasm { #[wasm_bindgen(setter = recipientId)] pub fn set_recipient_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_recipient: &JsValue, + #[wasm_bindgen(js_name = "recipientId")] recipient_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let recipient = IdentifierWasm::try_from(js_recipient)?.into(); - - self.0.set_recipient_id(recipient); - + self.0.set_recipient_id(recipient_id.try_into()?); Ok(()) } #[wasm_bindgen(setter = "amount")] - pub fn set_amount(&mut self, amount: u64) { - self.0.set_amount(amount) + pub fn set_amount(&mut self, amount: JsValue) -> WasmDppResult<()> { + self.0.set_amount(try_to_u64(&amount, "amount")?); + Ok(()) } #[wasm_bindgen(setter = "base")] @@ -154,17 +150,13 @@ impl TokenTransferTransitionWasm { #[wasm_bindgen(setter = "sharedEncryptedNote")] pub fn set_shared_encrypted_note( &mut self, - js_shared_encrypted_note: &JsValue, + #[wasm_bindgen(js_name = "sharedEncryptedNote")] shared_encrypted_note: &JsValue, ) -> WasmDppResult<()> { let shared_encrypted_note: Option = - match js_shared_encrypted_note.is_undefined() { - true => None, - false => Some( - js_shared_encrypted_note - .to_wasm::("SharedEncryptedNote")? - .clone() - .into(), - ), + if shared_encrypted_note.is_undefined() { + None + } else { + Some(SharedEncryptedNoteWasm::try_from(shared_encrypted_note)?.into()) }; self.0.set_shared_encrypted_note(shared_encrypted_note); @@ -174,20 +166,19 @@ impl TokenTransferTransitionWasm { #[wasm_bindgen(setter = "privateEncryptedNote")] pub fn set_private_encrypted_note( &mut self, - js_private_encrypted_note: &JsValue, + #[wasm_bindgen(js_name = "privateEncryptedNote")] private_encrypted_note: &JsValue, ) -> WasmDppResult<()> { let private_encrypted_note: Option = - match js_private_encrypted_note.is_undefined() { - true => None, - false => Some( - js_private_encrypted_note - .to_wasm::("PrivateEncryptedNote")? - .clone() - .into(), - ), + if private_encrypted_note.is_undefined() { + None + } else { + Some(PrivateEncryptedNoteWasm::try_from(private_encrypted_note)?.into()) }; self.0.set_private_encrypted_note(private_encrypted_note); Ok(()) } } + +impl_try_from_js_value!(TokenTransferTransitionWasm, "TokenTransferTransition"); +impl_wasm_type_info!(TokenTransferTransitionWasm, TokenTransferTransition); diff --git a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_unfreeze.rs b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_unfreeze.rs index 399ba91b10a..87ab030f5a1 100644 --- a/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_unfreeze.rs +++ b/packages/wasm-dpp2/src/state_transitions/batch/token_transitions/token_unfreeze.rs @@ -1,16 +1,32 @@ -use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; -use dpp::identifier::Identifier; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::state_transitions::batch::token_base_transition::TokenBaseTransitionWasm; +use crate::utils::{try_from_options, try_from_options_optional_with, try_to_string}; use dpp::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use dpp::state_transition::batch_transition::token_unfreeze_transition::v0::v0_methods::TokenUnfreezeTransitionV0Methods; use dpp::state_transition::batch_transition::token_unfreeze_transition::TokenUnfreezeTransitionV0; use dpp::state_transition::batch_transition::TokenUnfreezeTransition; use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::JsValue; + +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_UNFREEZE_OPTIONS_TS: &str = r#" +export interface TokenUnFreezeTransitionOptions { + base: TokenBaseTransition; + frozenIdentityId: IdentifierLike; + publicNote?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenUnFreezeTransitionOptions")] + pub type TokenUnFreezeTransitionOptionsJs; +} #[derive(Debug, Clone, PartialEq)] -#[wasm_bindgen(js_name=TokenUnFreezeTransition)] +#[wasm_bindgen(js_name = "TokenUnFreezeTransition")] pub struct TokenUnFreezeTransitionWasm(TokenUnfreezeTransition); impl From for TokenUnFreezeTransitionWasm { @@ -27,47 +43,40 @@ impl From for TokenUnfreezeTransition { #[wasm_bindgen(js_class = TokenUnFreezeTransition)] impl TokenUnFreezeTransitionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenUnFreezeTransition".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenUnFreezeTransition".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - base: &TokenBaseTransitionWasm, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_frozen_identity_id: &JsValue, - public_note: Option, + pub fn constructor( + options: TokenUnFreezeTransitionOptionsJs, ) -> WasmDppResult { - let frozen_identity_id: Identifier = - IdentifierWasm::try_from(js_frozen_identity_id)?.into(); + let base: TokenBaseTransitionWasm = try_from_options(&options, "base")?; + + let frozen_identity_id: IdentifierWasm = try_from_options(&options, "frozenIdentityId")?; + + let public_note: Option = + try_from_options_optional_with(&options, "publicNote", |v| { + try_to_string(v, "publicNote") + })?; Ok(TokenUnFreezeTransitionWasm(TokenUnfreezeTransition::V0( TokenUnfreezeTransitionV0 { - base: base.clone().into(), - frozen_identity_id, + base: base.into(), + frozen_identity_id: frozen_identity_id.into(), public_note, }, ))) } #[wasm_bindgen(getter = "base")] - pub fn get_base(&self) -> TokenBaseTransitionWasm { + pub fn base(&self) -> TokenBaseTransitionWasm { self.0.base().clone().into() } #[wasm_bindgen(getter = "publicNote")] - pub fn get_public_note(&self) -> Option { + pub fn public_note(&self) -> Option { self.clone().0.public_note_owned() } #[wasm_bindgen(getter = "frozenIdentityId")] - pub fn get_frozen_identity_id(&self) -> IdentifierWasm { + pub fn frozen_identity_id(&self) -> IdentifierWasm { self.0.frozen_identity_id().into() } @@ -84,11 +93,13 @@ impl TokenUnFreezeTransitionWasm { #[wasm_bindgen(setter = "frozenIdentityId")] pub fn set_frozen_identity_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_frozen_identity_id: &JsValue, + #[wasm_bindgen(js_name = "frozenIdentityId")] frozen_identity_id: IdentifierLikeJs, ) -> WasmDppResult<()> { self.0 - .set_frozen_identity_id(IdentifierWasm::try_from(js_frozen_identity_id)?.into()); + .set_frozen_identity_id(frozen_identity_id.try_into()?); Ok(()) } } + +impl_try_from_js_value!(TokenUnFreezeTransitionWasm, "TokenUnFreezeTransition"); +impl_wasm_type_info!(TokenUnFreezeTransitionWasm, TokenUnFreezeTransition); diff --git a/packages/wasm-dpp2/src/tokens/configuration/action_taker.rs b/packages/wasm-dpp2/src/tokens/configuration/action_taker.rs index f67b798de78..ec8137ec2f7 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/action_taker.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/action_taker.rs @@ -1,5 +1,8 @@ use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; +use crate::impl_from_for_extern_type; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use dpp::group::action_taker::ActionTaker; use dpp::prelude::Identifier; use js_sys::Array; @@ -7,6 +10,19 @@ use std::collections::BTreeSet; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const ACTION_TAKER_TYPES_TS: &str = r#" +export type ActionTakerValue = IdentifierLike | IdentifierLike[]; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ActionTakerValue")] + pub type ActionTakerValueJs; +} + +impl_from_for_extern_type!(ActionTakerValueJs, IdentifierWasm, Array); + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "ActionTaker")] pub struct ActionTakerWasm(ActionTaker); @@ -25,18 +41,9 @@ impl From for ActionTaker { #[wasm_bindgen(js_class = ActionTaker)] impl ActionTakerWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "ActionTaker".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "ActionTaker".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(value: &JsValue) -> WasmDppResult { + pub fn constructor(value: ActionTakerValueJs) -> WasmDppResult { + let value: JsValue = value.into(); if let Ok(identifier) = IdentifierWasm::try_from(value.clone()) { return Ok(ActionTakerWasm(ActionTaker::SingleIdentity( identifier.into(), @@ -49,7 +56,7 @@ impl ActionTakerWasm { )); } - let array = Array::from(value); + let array = Array::from(&value); let mut identifiers = BTreeSet::new(); for js_value in array.to_vec() { @@ -68,8 +75,8 @@ impl ActionTakerWasm { ))) } - #[wasm_bindgen(js_name = "getType")] - pub fn get_type(&self) -> String { + #[wasm_bindgen(getter = "takerType")] + pub fn taker_type(&self) -> String { match &self.0 { ActionTaker::SpecifiedIdentities(_) => "SpecifiedIdentities".to_string(), ActionTaker::SingleIdentity(_) => "SingleIdentity".to_string(), @@ -77,9 +84,9 @@ impl ActionTakerWasm { } #[wasm_bindgen(getter = "value")] - pub fn get_value(&self) -> JsValue { + pub fn value(&self) -> ActionTakerValueJs { match &self.0 { - ActionTaker::SingleIdentity(value) => JsValue::from(IdentifierWasm::from(*value)), + ActionTaker::SingleIdentity(value) => IdentifierWasm::from(*value).into(), ActionTaker::SpecifiedIdentities(value) => { let array = Array::new(); for identifier in value.iter() { @@ -91,9 +98,12 @@ impl ActionTakerWasm { } #[wasm_bindgen(setter = "value")] - pub fn set_value(&mut self, value: &JsValue) -> WasmDppResult<()> { - self.0 = Self::new(value)?.0; + pub fn set_value(&mut self, value: ActionTakerValueJs) -> WasmDppResult<()> { + self.0 = Self::constructor(value)?.0; Ok(()) } } + +impl_try_from_js_value!(ActionTakerWasm, "ActionTaker"); +impl_wasm_type_info!(ActionTakerWasm, ActionTaker); diff --git a/packages/wasm-dpp2/src/tokens/configuration/authorized_action_takers.rs b/packages/wasm-dpp2/src/tokens/configuration/authorized_action_takers.rs index b4921133bce..a3224fc18d6 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/authorized_action_takers.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/authorized_action_takers.rs @@ -1,11 +1,19 @@ use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use dpp::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers; use dpp::platform_value::string_encoding::Encoding::Base58; use dpp::platform_value::string_encoding::encode; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "Identifier | number | undefined")] + pub type AuthorizedActionTakersValue; +} + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "AuthorizedActionTakers")] pub struct AuthorizedActionTakersWasm(AuthorizedActionTakers); @@ -24,16 +32,6 @@ impl From for AuthorizedActionTakers { #[wasm_bindgen(js_class = AuthorizedActionTakers)] impl AuthorizedActionTakersWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "AuthorizedActionTakers".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "AuthorizedActionTakers".to_string() - } - #[wasm_bindgen(js_name = "NoOne")] pub fn no_one() -> Self { AuthorizedActionTakersWasm(AuthorizedActionTakers::NoOne) @@ -45,14 +43,9 @@ impl AuthorizedActionTakersWasm { } #[wasm_bindgen(js_name = "Identity")] - pub fn identity( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: &JsValue, - ) -> WasmDppResult { - let identity_id = IdentifierWasm::try_from(js_identity_id)?.into(); - + pub fn identity(identity_id: IdentifierLikeJs) -> WasmDppResult { Ok(AuthorizedActionTakersWasm( - AuthorizedActionTakers::Identity(identity_id), + AuthorizedActionTakers::Identity(identity_id.try_into()?), )) } @@ -66,7 +59,7 @@ impl AuthorizedActionTakersWasm { AuthorizedActionTakersWasm(AuthorizedActionTakers::Group(group_contract_position)) } - #[wasm_bindgen(js_name = "getTakerType")] + #[wasm_bindgen(getter = "takerType")] pub fn taker_type(&self) -> String { match self.0 { AuthorizedActionTakers::NoOne => "NoOne".to_string(), @@ -79,9 +72,9 @@ impl AuthorizedActionTakersWasm { } } - #[wasm_bindgen(js_name = "getValue")] - pub fn get_value(&self) -> JsValue { - match self.0 { + #[wasm_bindgen(getter = "value")] + pub fn value(&self) -> AuthorizedActionTakersValue { + let js_value = match self.0 { AuthorizedActionTakers::NoOne => JsValue::undefined(), AuthorizedActionTakers::ContractOwner => JsValue::undefined(), AuthorizedActionTakers::Identity(identifier) => { @@ -89,6 +82,10 @@ impl AuthorizedActionTakersWasm { } AuthorizedActionTakers::MainGroup => JsValue::undefined(), AuthorizedActionTakers::Group(position) => JsValue::from(position), - } + }; + js_value.into() } } + +impl_try_from_js_value!(AuthorizedActionTakersWasm, "AuthorizedActionTakers"); +impl_wasm_type_info!(AuthorizedActionTakersWasm, AuthorizedActionTakers); diff --git a/packages/wasm-dpp2/src/tokens/configuration/change_control_rules.rs b/packages/wasm-dpp2/src/tokens/configuration/change_control_rules.rs index 769b2f9573f..c697ff880a0 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/change_control_rules.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/change_control_rules.rs @@ -1,20 +1,65 @@ use crate::enums::token::action_goal::ActionGoalWasm; use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::tokens::configuration::action_taker::ActionTakerWasm; use crate::tokens::configuration::authorized_action_takers::AuthorizedActionTakersWasm; use crate::tokens::configuration::group::GroupWasm; -use crate::utils::{IntoWasm, JsValueExt}; +use crate::utils::{ + try_from_options, try_from_options_optional_with, try_from_options_with, try_to_u16, +}; use dpp::data_contract::GroupContractPosition; use dpp::data_contract::change_control_rules::ChangeControlRules; use dpp::data_contract::change_control_rules::v0::ChangeControlRulesV0; use dpp::data_contract::group::Group; use dpp::prelude::Identifier; -use js_sys::{Object, Reflect}; +use js_sys::Object; +use serde::Deserialize; use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct ChangeControlRulesOptions { + #[serde(default)] + is_changing_authorized_action_takers_to_no_one_allowed: bool, + #[serde(default)] + is_changing_admin_action_takers_to_no_one_allowed: bool, + #[serde(default)] + is_self_changing_admin_action_takers_allowed: bool, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface ChangeControlRulesOptions { + authorizedToMakeChange: AuthorizedActionTakers; + adminActionTakers: AuthorizedActionTakers; + isChangingAuthorizedActionTakersToNoOneAllowed?: boolean; + isChangingAdminActionTakersToNoOneAllowed?: boolean; + isSelfChangingAdminActionTakersAllowed?: boolean; +} + +export interface CanChangeAdminActionTakersOptions { + adminActionTakers: AuthorizedActionTakers; + contractOwnerId: IdentifierLike; + mainGroup?: number; + groups: Record; + actionTaker: ActionTaker; + goal: ActionGoalLike; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ChangeControlRulesOptions")] + pub type ChangeControlRulesOptionsJs; + + #[wasm_bindgen(typescript_type = "CanChangeAdminActionTakersOptions")] + pub type CanChangeAdminActionTakersOptionsJs; +} + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "ChangeControlRules")] pub struct ChangeControlRulesWasm(ChangeControlRules); @@ -33,59 +78,59 @@ impl From for ChangeControlRules { #[wasm_bindgen(js_class = ChangeControlRules)] impl ChangeControlRulesWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "ChangeControlRules".to_string() - } + #[wasm_bindgen(constructor)] + pub fn constructor(options: ChangeControlRulesOptionsJs) -> WasmDppResult { + // Extract AuthorizedActionTakers objects which need special handling + let authorized_to_make_change: AuthorizedActionTakersWasm = + try_from_options(&options, "authorizedToMakeChange")?; - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "ChangeControlRules".to_string() - } + let admin_action_takers: AuthorizedActionTakersWasm = + try_from_options(&options, "adminActionTakers")?; - #[wasm_bindgen(constructor)] - pub fn new( - authorized_to_make_change: &AuthorizedActionTakersWasm, - admin_action_takers: &AuthorizedActionTakersWasm, - changing_authorized_action_takers_to_no_one_allowed: bool, - changing_admin_action_takers_to_no_one_allowed: bool, - self_changing_admin_action_takers_allowed: bool, - ) -> Self { - ChangeControlRulesWasm(ChangeControlRules::V0(ChangeControlRulesV0 { - authorized_to_make_change: authorized_to_make_change.clone().into(), - admin_action_takers: admin_action_takers.clone().into(), - changing_authorized_action_takers_to_no_one_allowed, - changing_admin_action_takers_to_no_one_allowed, - self_changing_admin_action_takers_allowed, - })) + // Extract boolean options with serde (they have defaults) + let opts: ChangeControlRulesOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + + Ok(ChangeControlRulesWasm(ChangeControlRules::V0( + ChangeControlRulesV0 { + authorized_to_make_change: authorized_to_make_change.into(), + admin_action_takers: admin_action_takers.into(), + changing_authorized_action_takers_to_no_one_allowed: opts + .is_changing_authorized_action_takers_to_no_one_allowed, + changing_admin_action_takers_to_no_one_allowed: opts + .is_changing_admin_action_takers_to_no_one_allowed, + self_changing_admin_action_takers_allowed: opts + .is_self_changing_admin_action_takers_allowed, + }, + ))) } #[wasm_bindgen(getter = "authorizedToMakeChange")] - pub fn get_authorized_to_make_change(&self) -> AuthorizedActionTakersWasm { + pub fn authorized_to_make_change(&self) -> AuthorizedActionTakersWasm { (*self.0.authorized_to_make_change_action_takers()).into() } #[wasm_bindgen(getter = "adminActionTakers")] - pub fn get_admin_action_takers(&self) -> AuthorizedActionTakersWasm { + pub fn admin_action_takers(&self) -> AuthorizedActionTakersWasm { (*self.0.admin_action_takers()).into() } - #[wasm_bindgen(getter = "changingAuthorizedActionTakersToNoOneAllowed")] - pub fn get_changing_authorized_action_takers_to_no_one_allowed(&self) -> bool { + #[wasm_bindgen(getter = "isChangingAuthorizedActionTakersToNoOneAllowed")] + pub fn is_changing_authorized_action_takers_to_no_one_allowed(&self) -> bool { match self.0.clone() { ChangeControlRules::V0(v0) => v0.changing_authorized_action_takers_to_no_one_allowed, } } - #[wasm_bindgen(getter = "changingAdminActionTakersToNoOneAllowed")] - pub fn get_changing_admin_action_takers_to_no_one_allowed(&self) -> bool { + #[wasm_bindgen(getter = "isChangingAdminActionTakersToNoOneAllowed")] + pub fn is_changing_admin_action_takers_to_no_one_allowed(&self) -> bool { match self.0.clone() { ChangeControlRules::V0(v0) => v0.changing_admin_action_takers_to_no_one_allowed, } } - #[wasm_bindgen(getter = "selfChangingAdminActionTakersAllowed")] - pub fn get_self_changing_admin_action_takers_allowed(&self) -> bool { + #[wasm_bindgen(getter = "isSelfChangingAdminActionTakersAllowed")] + pub fn is_self_changing_admin_action_takers_allowed(&self) -> bool { match self.0.clone() { ChangeControlRules::V0(v0) => v0.self_changing_admin_action_takers_allowed, } @@ -94,6 +139,7 @@ impl ChangeControlRulesWasm { #[wasm_bindgen(setter = "authorizedToMakeChange")] pub fn set_authorized_to_make_change( &mut self, + #[wasm_bindgen(js_name = "authorizedToMakeChange")] authorized_to_make_change: &AuthorizedActionTakersWasm, ) { self.0 @@ -101,20 +147,25 @@ impl ChangeControlRulesWasm { } #[wasm_bindgen(setter = "adminActionTakers")] - pub fn set_admin_action_takers(&mut self, admin_action_takers: &AuthorizedActionTakersWasm) { + pub fn set_admin_action_takers( + &mut self, + #[wasm_bindgen(js_name = "adminActionTakers")] + admin_action_takers: &AuthorizedActionTakersWasm, + ) { self.0 .set_admin_action_takers(admin_action_takers.clone().into()); } - #[wasm_bindgen(setter = "changingAuthorizedActionTakersToNoOneAllowed")] - pub fn set_changing_authorized_action_takers_to_no_one_allowed( + #[wasm_bindgen(setter = "isChangingAuthorizedActionTakersToNoOneAllowed")] + pub fn set_is_changing_authorized_action_takers_to_no_one_allowed( &mut self, - changing_authorized_action_takers_to_no_one_allowed: bool, + #[wasm_bindgen(js_name = "isChangingAuthorizedActionTakersToNoOneAllowed")] + is_changing_authorized_action_takers_to_no_one_allowed: bool, ) { let v0 = match self.0.clone() { ChangeControlRules::V0(mut v0) => { v0.changing_authorized_action_takers_to_no_one_allowed = - changing_authorized_action_takers_to_no_one_allowed; + is_changing_authorized_action_takers_to_no_one_allowed; v0 } }; @@ -122,15 +173,16 @@ impl ChangeControlRulesWasm { self.0 = ChangeControlRules::V0(v0); } - #[wasm_bindgen(setter = "changingAdminActionTakersToNoOneAllowed")] - pub fn set_changing_admin_action_takers_to_no_one_allowed( + #[wasm_bindgen(setter = "isChangingAdminActionTakersToNoOneAllowed")] + pub fn set_is_changing_admin_action_takers_to_no_one_allowed( &mut self, - changing_admin_action_takers_to_no_one_allowed: bool, + #[wasm_bindgen(js_name = "isChangingAdminActionTakersToNoOneAllowed")] + is_changing_admin_action_takers_to_no_one_allowed: bool, ) { let v0 = match self.0.clone() { ChangeControlRules::V0(mut v0) => { v0.changing_admin_action_takers_to_no_one_allowed = - changing_admin_action_takers_to_no_one_allowed; + is_changing_admin_action_takers_to_no_one_allowed; v0 } }; @@ -138,15 +190,16 @@ impl ChangeControlRulesWasm { self.0 = ChangeControlRules::V0(v0) } - #[wasm_bindgen(setter = "selfChangingAdminActionTakersAllowed")] - pub fn set_self_changing_admin_action_takers_allowed( + #[wasm_bindgen(setter = "isSelfChangingAdminActionTakersAllowed")] + pub fn set_is_self_changing_admin_action_takers_allowed( &mut self, - self_changing_admin_action_takers_allowed: bool, + #[wasm_bindgen(js_name = "isSelfChangingAdminActionTakersAllowed")] + is_self_changing_admin_action_takers_allowed: bool, ) { let v0 = match self.0.clone() { ChangeControlRules::V0(mut v0) => { v0.self_changing_admin_action_takers_allowed = - self_changing_admin_action_takers_allowed; + is_self_changing_admin_action_takers_allowed; v0 } }; @@ -157,54 +210,51 @@ impl ChangeControlRulesWasm { #[wasm_bindgen(js_name = "canChangeAdminActionTakers")] pub fn can_change_admin_action_takers( &self, - admin_action_takers: &AuthorizedActionTakersWasm, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_owner_id: &JsValue, - main_group: Option, - js_groups: &JsValue, - action_taker: &ActionTakerWasm, - js_goal: &JsValue, + options: CanChangeAdminActionTakersOptionsJs, ) -> WasmDppResult { - let contract_owner_id: Identifier = IdentifierWasm::try_from(js_contract_owner_id)?.into(); - let goal = ActionGoalWasm::try_from(js_goal.clone())?; + let admin_action_takers: AuthorizedActionTakersWasm = + try_from_options(&options, "adminActionTakers")?; - let groups_object = Object::from(js_groups.clone()); + let contract_owner_id: Identifier = + try_from_options::(&options, "contractOwnerId")?.into(); + + let main_group: Option = + try_from_options_optional_with(&options, "mainGroup", |v| try_to_u16(v, "mainGroup"))?; + + let action_taker: ActionTakerWasm = try_from_options(&options, "actionTaker")?; + + let goal = + try_from_options_with(&options, "goal", |v| ActionGoalWasm::try_from(v.clone()))?; + + // Extract groups - need Object for Object::keys + let groups_value: JsValue = + try_from_options_with(&options, "groups", |v| Ok::<_, WasmDppError>(v.clone()))?; + let groups_object = Object::from(groups_value); let groups_keys = Object::keys(&groups_object); let mut groups: BTreeMap = BTreeMap::new(); for key in groups_keys.iter() { - let key_str = key.as_string().ok_or_else(|| { - WasmDppError::invalid_argument("Cannot read group contract position") - })?; - - let contract_position = key_str.parse::().map_err(|err| { - WasmDppError::invalid_argument(format!( - "Invalid group contract position '{}': {}", - key_str, err - )) - })?; - - let group_value = Reflect::get(js_groups, &key).map_err(|err| { - let message = err.error_message(); - WasmDppError::invalid_argument(format!( - "unable to read group at contract position '{}': {}", - key_str, message - )) - })?; - - let group = group_value.to_wasm::("Group")?.clone(); + let contract_position = try_to_u16(&key, "group contract position")?; + + let group: GroupWasm = try_from_options( + &groups_object.clone().into(), + &contract_position.to_string(), + )?; groups.insert(contract_position, group.into()); } Ok(self.0.can_change_admin_action_takers( - &admin_action_takers.clone().into(), + &admin_action_takers.into(), &contract_owner_id, main_group, &groups, - &action_taker.clone().into(), - goal.clone().into(), + &action_taker.into(), + goal.into(), )) } } + +impl_try_from_js_value!(ChangeControlRulesWasm, "ChangeControlRules"); +impl_wasm_type_info!(ChangeControlRulesWasm, ChangeControlRules); diff --git a/packages/wasm-dpp2/src/tokens/configuration/configuration_convention.rs b/packages/wasm-dpp2/src/tokens/configuration/configuration_convention.rs index d8e772c8557..82c46abcecf 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/configuration_convention.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/configuration_convention.rs @@ -1,6 +1,8 @@ use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::tokens::configuration::localization::TokenConfigurationLocalizationWasm; -use crate::utils::JsValueExt; +use crate::utils::{JsValueExt, try_from_options, try_to_object, try_to_string, try_to_u8}; use dpp::data_contract::associated_token::token_configuration_convention::TokenConfigurationConvention; use dpp::data_contract::associated_token::token_configuration_convention::accessors::v0::{ TokenConfigurationConventionV0Getters, TokenConfigurationConventionV0Setters, @@ -12,6 +14,12 @@ use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "Record")] + pub type TokenConfigurationLocalizationsJs; +} + #[derive(Debug, Clone, PartialEq)] #[wasm_bindgen(js_name = "TokenConfigurationConvention")] pub struct TokenConfigurationConventionWasm(TokenConfigurationConvention); @@ -30,23 +38,13 @@ impl From for TokenConfigurationConvention { #[wasm_bindgen(js_class = TokenConfigurationConvention)] impl TokenConfigurationConventionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenConfigurationConvention".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenConfigurationConvention".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - js_localizations: &JsValue, + pub fn constructor( + localizations: &JsValue, decimals: u8, ) -> WasmDppResult { let localizations: BTreeMap = - js_value_to_localizations(js_localizations)?; + value_to_localizations(localizations)?; Ok(TokenConfigurationConventionWasm( TokenConfigurationConvention::V0(TokenConfigurationConventionV0 { @@ -62,7 +60,7 @@ impl TokenConfigurationConventionWasm { } #[wasm_bindgen(getter = "localizations")] - pub fn localizations(&self) -> WasmDppResult { + pub fn localizations(&self) -> WasmDppResult { let object = Object::new(); for (key, value) in &self.0.localizations().clone() { @@ -80,47 +78,52 @@ impl TokenConfigurationConventionWasm { })?; } - Ok(object.into()) + Ok(JsValue::from(object).into()) } #[wasm_bindgen(setter = "decimals")] - pub fn set_decimals(&mut self, decimals: u8) { - self.0.set_decimals(decimals) + pub fn set_decimals(&mut self, decimals: &js_sys::Number) -> WasmDppResult<()> { + self.0.set_decimals(try_to_u8(decimals, "decimals")?); + Ok(()) } #[wasm_bindgen(setter = "localizations")] - pub fn set_localizations(&mut self, js_localizations: &JsValue) -> WasmDppResult<()> { + pub fn set_localizations( + &mut self, + #[wasm_bindgen(unchecked_param_type = "Record")] + localizations: &JsValue, + ) -> WasmDppResult<()> { let localizations: BTreeMap = - js_value_to_localizations(js_localizations)?; + value_to_localizations(localizations)?; self.0.set_localizations(localizations); Ok(()) } } -fn js_value_to_localizations( - js_localizations: &JsValue, +fn value_to_localizations( + localizations_value: &JsValue, ) -> WasmDppResult> { - let js_object = Object::from(js_localizations.clone()); + let js_object = try_to_object(localizations_value.clone(), "localizations")?; let mut localizations = BTreeMap::new(); for key in Object::keys(&js_object) { - let key_str = key - .as_string() - .ok_or_else(|| WasmDppError::invalid_argument("Localization key must be string"))?; + let key_str = try_to_string(&key, "localization key")?; - let js_value = Reflect::get(&js_object, &key).map_err(|err| { - let message = err.error_message(); - WasmDppError::invalid_argument(format!( - "unable to read localization '{}': {}", - key_str, message - )) - })?; + let localization: TokenConfigurationLocalizationWasm = + try_from_options(&js_object.clone().into(), &key_str)?; - let localization = TokenConfigurationLocalizationWasm::from_js_value(&js_value)?; - - localizations.insert(key_str, localization); + localizations.insert(key_str, localization.into()); } Ok(localizations) } + +impl_try_from_js_value!( + TokenConfigurationConventionWasm, + "TokenConfigurationConvention" +); +impl_wasm_type_info!( + TokenConfigurationConventionWasm, + TokenConfigurationConvention +); diff --git a/packages/wasm-dpp2/src/tokens/configuration/distribution_function.rs b/packages/wasm-dpp2/src/tokens/configuration/distribution_function.rs index 30ea9824daf..513df2fc089 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/distribution_function.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/distribution_function.rs @@ -1,10 +1,12 @@ use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_from_for_extern_type; +use crate::impl_wasm_type_info; use crate::tokens::configuration::distribution_structs::{ DistributionExponentialWasm, DistributionFixedAmountWasm, DistributionInvertedLogarithmicWasm, DistributionLinearWasm, DistributionLogarithmicWasm, DistributionPolynomialWasm, DistributionRandomWasm, DistributionStepDecreasingAmountWasm, }; -use crate::utils::{JsValueExt, try_to_u64}; +use crate::utils::{JsValueExt, try_to_object, try_to_u64}; use dpp::balances::credits::TokenAmount; use dpp::data_contract::associated_token::token_perpetual_distribution::distribution_function::DistributionFunction; use js_sys::{BigInt, Object, Reflect}; @@ -12,6 +14,28 @@ use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen( + typescript_type = "DistributionFixedAmount | DistributionRandom | DistributionStepDecreasingAmount | Record | DistributionLinear | DistributionPolynomial | DistributionExponential | DistributionLogarithmic | DistributionInvertedLogarithmic" + )] + pub type DistributionFunctionValue; +} + +// Source types only (wasm_bindgen provides From) +impl_from_for_extern_type!( + DistributionFunctionValue, + DistributionFixedAmountWasm, + DistributionRandomWasm, + DistributionStepDecreasingAmountWasm, + DistributionLinearWasm, + DistributionPolynomialWasm, + DistributionExponentialWasm, + DistributionLogarithmicWasm, + DistributionInvertedLogarithmicWasm, + Object, +); + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "DistributionFunction")] pub struct DistributionFunctionWasm(DistributionFunction); @@ -30,53 +54,42 @@ impl From for DistributionFunctionWasm { #[wasm_bindgen(js_class = DistributionFunction)] impl DistributionFunctionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "DistributionFunction".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "DistributionFunction".to_string() - } - #[wasm_bindgen(js_name = "FixedAmountDistribution")] - pub fn fixed_amount_distribution(amount: TokenAmount) -> DistributionFunctionWasm { - DistributionFunctionWasm(DistributionFunction::FixedAmount { amount }) + pub fn fixed_amount_distribution( + opts: DistributionFixedAmountWasm, + ) -> DistributionFunctionWasm { + DistributionFunctionWasm(DistributionFunction::FixedAmount { + amount: opts.amount, + }) } #[wasm_bindgen(js_name = "Random")] - pub fn random(min: TokenAmount, max: TokenAmount) -> Self { - DistributionFunctionWasm(DistributionFunction::Random { min, max }) + pub fn random(opts: DistributionRandomWasm) -> Self { + DistributionFunctionWasm(DistributionFunction::Random { + min: opts.min, + max: opts.max, + }) } #[wasm_bindgen(js_name = "StepDecreasingAmount")] - #[allow(clippy::too_many_arguments)] - pub fn step_decreasing_amount( - step_count: u32, - decrease_per_interval_numerator: u16, - decrease_per_interval_denominator: u16, - start_decreasing_offset: Option, - max_interval_count: Option, - distribution_start_amount: TokenAmount, - trailing_distribution_interval_amount: TokenAmount, - min_value: Option, - ) -> Self { + pub fn step_decreasing_amount(opts: DistributionStepDecreasingAmountWasm) -> Self { DistributionFunctionWasm(DistributionFunction::StepDecreasingAmount { - step_count, - decrease_per_interval_numerator, - decrease_per_interval_denominator, - start_decreasing_offset, - max_interval_count, - distribution_start_amount, - trailing_distribution_interval_amount, - min_value, + step_count: opts.step_count, + decrease_per_interval_numerator: opts.decrease_per_interval_numerator, + decrease_per_interval_denominator: opts.decrease_per_interval_denominator, + start_decreasing_offset: opts.start_decreasing_offset, + max_interval_count: opts.max_interval_count, + distribution_start_amount: opts.distribution_start_amount, + trailing_distribution_interval_amount: opts.trailing_distribution_interval_amount, + min_value: opts.min_value, }) } #[wasm_bindgen(js_name = "Stepwise")] - pub fn stepwise(js_steps_with_amount: JsValue) -> WasmDppResult { - let obj = Object::from(js_steps_with_amount); + pub fn stepwise( + #[wasm_bindgen(unchecked_param_type = "Record")] steps_with_amount: JsValue, + ) -> WasmDppResult { + let obj = try_to_object(steps_with_amount, "stepsWithAmount")?; let mut steps_with_amount: BTreeMap = BTreeMap::new(); @@ -97,8 +110,7 @@ impl DistributionFunctionWasm { )) })?; - let amount = try_to_u64(amount_js) - .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; + let amount = try_to_u64(&amount_js, &format!("step[{}]", key_str))?; steps_with_amount.insert(step, amount); } @@ -109,130 +121,81 @@ impl DistributionFunctionWasm { } #[wasm_bindgen(js_name = "Linear")] - pub fn linear( - a: i64, - d: u64, - start_step: Option, - starting_amount: TokenAmount, - min_value: Option, - max_value: Option, - ) -> DistributionFunctionWasm { + pub fn linear(opts: DistributionLinearWasm) -> DistributionFunctionWasm { DistributionFunctionWasm(DistributionFunction::Linear { - a, - d, - start_step, - starting_amount, - min_value, - max_value, + a: opts.a, + d: opts.d, + start_step: opts.start_step, + starting_amount: opts.starting_amount, + min_value: opts.min_value, + max_value: opts.max_value, }) } #[wasm_bindgen(js_name = "Polynomial")] - #[allow(clippy::too_many_arguments)] - pub fn polynomial( - a: i64, - d: u64, - m: i64, - n: u64, - o: i64, - start_moment: Option, - b: TokenAmount, - min_value: Option, - max_value: Option, - ) -> DistributionFunctionWasm { + pub fn polynomial(opts: DistributionPolynomialWasm) -> DistributionFunctionWasm { DistributionFunctionWasm(DistributionFunction::Polynomial { - a, - d, - m, - n, - o, - start_moment, - b, - min_value, - max_value, + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, }) } #[wasm_bindgen(js_name = "Exponential")] - #[allow(clippy::too_many_arguments)] - pub fn exponential( - a: u64, - d: u64, - m: i64, - n: u64, - o: i64, - start_moment: Option, - b: TokenAmount, - min_value: Option, - max_value: Option, - ) -> DistributionFunctionWasm { + pub fn exponential(opts: DistributionExponentialWasm) -> DistributionFunctionWasm { DistributionFunctionWasm(DistributionFunction::Exponential { - a, - d, - m, - n, - o, - start_moment, - b, - min_value, - max_value, + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, }) } #[wasm_bindgen(js_name = "Logarithmic")] - #[allow(clippy::too_many_arguments)] - pub fn logarithmic( - a: i64, - d: u64, - m: u64, - n: u64, - o: i64, - start_moment: Option, - b: TokenAmount, - min_value: Option, - max_value: Option, - ) -> DistributionFunctionWasm { + pub fn logarithmic(opts: DistributionLogarithmicWasm) -> DistributionFunctionWasm { DistributionFunctionWasm(DistributionFunction::Logarithmic { - a, - d, - m, - n, - o, - start_moment, - b, - min_value, - max_value, + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, }) } #[wasm_bindgen(js_name = "InvertedLogarithmic")] - #[allow(clippy::too_many_arguments)] pub fn inverted_logarithmic( - a: i64, - d: u64, - m: u64, - n: u64, - o: i64, - start_moment: Option, - b: TokenAmount, - min_value: Option, - max_value: Option, + opts: DistributionInvertedLogarithmicWasm, ) -> DistributionFunctionWasm { DistributionFunctionWasm(DistributionFunction::InvertedLogarithmic { - a, - d, - m, - n, - o, - start_moment, - b, - min_value, - max_value, + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, }) } - #[wasm_bindgen(js_name = "getFunctionName")] - pub fn get_function_name(&self) -> String { + #[wasm_bindgen(getter = "functionName")] + pub fn function_name(&self) -> String { match self.0 { DistributionFunction::FixedAmount { .. } => String::from("FixedAmount"), DistributionFunction::Random { .. } => String::from("Random"), @@ -248,15 +211,13 @@ impl DistributionFunctionWasm { } } - #[wasm_bindgen(js_name = "getFunctionValue")] - pub fn get_function_values(&self) -> WasmDppResult { - match self.0.clone() { + #[wasm_bindgen(getter = "functionValue")] + pub fn function_value(&self) -> WasmDppResult { + let js_value: JsValue = match self.0.clone() { DistributionFunction::FixedAmount { amount } => { - Ok(JsValue::from(DistributionFixedAmountWasm { amount })) - } - DistributionFunction::Random { min, max } => { - Ok(JsValue::from(DistributionRandomWasm { min, max })) + DistributionFixedAmountWasm { amount }.into() } + DistributionFunction::Random { min, max } => DistributionRandomWasm { min, max }.into(), DistributionFunction::StepDecreasingAmount { step_count, decrease_per_interval_numerator, @@ -266,7 +227,7 @@ impl DistributionFunctionWasm { distribution_start_amount, trailing_distribution_interval_amount, min_value, - } => Ok(JsValue::from(DistributionStepDecreasingAmountWasm { + } => DistributionStepDecreasingAmountWasm { step_count, decrease_per_interval_numerator, decrease_per_interval_denominator, @@ -275,7 +236,8 @@ impl DistributionFunctionWasm { distribution_start_amount, trailing_distribution_interval_amount, min_value, - })), + } + .into(), DistributionFunction::Stepwise(map) => { let object = Object::new(); @@ -294,7 +256,7 @@ impl DistributionFunctionWasm { })?; } - Ok(object.into()) + object.into() } DistributionFunction::Linear { a, @@ -303,14 +265,15 @@ impl DistributionFunctionWasm { starting_amount, min_value, max_value, - } => Ok(JsValue::from(DistributionLinearWasm { + } => DistributionLinearWasm { a, d, start_step, starting_amount, min_value, max_value, - })), + } + .into(), DistributionFunction::Polynomial { a, d, @@ -321,7 +284,7 @@ impl DistributionFunctionWasm { b, min_value, max_value, - } => Ok(JsValue::from(DistributionPolynomialWasm { + } => DistributionPolynomialWasm { a, d, m, @@ -331,7 +294,8 @@ impl DistributionFunctionWasm { b, min_value, max_value, - })), + } + .into(), DistributionFunction::Exponential { a, d, @@ -342,7 +306,7 @@ impl DistributionFunctionWasm { b, min_value, max_value, - } => Ok(JsValue::from(DistributionExponentialWasm { + } => DistributionExponentialWasm { a, d, m, @@ -352,7 +316,8 @@ impl DistributionFunctionWasm { b, min_value, max_value, - })), + } + .into(), DistributionFunction::Logarithmic { a, d, @@ -363,7 +328,7 @@ impl DistributionFunctionWasm { b, min_value, max_value, - } => Ok(JsValue::from(DistributionLogarithmicWasm { + } => DistributionLogarithmicWasm { a, d, m, @@ -373,7 +338,8 @@ impl DistributionFunctionWasm { b, min_value, max_value, - })), + } + .into(), DistributionFunction::InvertedLogarithmic { a, d, @@ -384,7 +350,7 @@ impl DistributionFunctionWasm { b, min_value, max_value, - } => Ok(JsValue::from(DistributionInvertedLogarithmicWasm { + } => DistributionInvertedLogarithmicWasm { a, d, m, @@ -394,7 +360,11 @@ impl DistributionFunctionWasm { b, min_value, max_value, - })), - } + } + .into(), + }; + Ok(js_value.into()) } } + +impl_wasm_type_info!(DistributionFunctionWasm, DistributionFunction); diff --git a/packages/wasm-dpp2/src/tokens/configuration/distribution_recipient.rs b/packages/wasm-dpp2/src/tokens/configuration/distribution_recipient.rs index 94ba5ccf447..63490e41862 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/distribution_recipient.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/distribution_recipient.rs @@ -1,9 +1,16 @@ use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_wasm_type_info; use dpp::data_contract::associated_token::token_perpetual_distribution::distribution_recipient::TokenDistributionRecipient; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "Identifier | undefined")] + pub type TokenDistributionRecipientValue; +} + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "TokenDistributionRecipient")] pub struct TokenDistributionRecipientWasm(TokenDistributionRecipient); @@ -22,16 +29,6 @@ impl From for TokenDistributionRecipient { #[wasm_bindgen(js_class = TokenDistributionRecipient)] impl TokenDistributionRecipientWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenDistributionRecipient".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenDistributionRecipient".to_string() - } - #[wasm_bindgen(js_name = "ContractOwner")] pub fn contract_owner() -> TokenDistributionRecipientWasm { TokenDistributionRecipientWasm(TokenDistributionRecipient::ContractOwner) @@ -39,13 +36,10 @@ impl TokenDistributionRecipientWasm { #[wasm_bindgen(js_name = "Identity")] pub fn identity( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: &JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> WasmDppResult { - let identity_id = IdentifierWasm::try_from(js_identity_id)?.into(); - Ok(TokenDistributionRecipientWasm( - TokenDistributionRecipient::Identity(identity_id), + TokenDistributionRecipient::Identity(identity_id.try_into()?), )) } @@ -54,8 +48,8 @@ impl TokenDistributionRecipientWasm { TokenDistributionRecipientWasm(TokenDistributionRecipient::EvonodesByParticipation) } - #[wasm_bindgen(js_name = "getType")] - pub fn get_type(&self) -> String { + #[wasm_bindgen(getter = "recipientType")] + pub fn recipient_type(&self) -> String { match self.0 { TokenDistributionRecipient::EvonodesByParticipation => { String::from("EvonodesByParticipation") @@ -67,14 +61,17 @@ impl TokenDistributionRecipientWasm { } } - #[wasm_bindgen(js_name = "getValue")] - pub fn get_value(&self) -> JsValue { - match self.0 { + #[wasm_bindgen(getter = "value")] + pub fn value(&self) -> TokenDistributionRecipientValue { + let js_value = match self.0 { TokenDistributionRecipient::EvonodesByParticipation => JsValue::undefined(), TokenDistributionRecipient::ContractOwner => JsValue::undefined(), TokenDistributionRecipient::Identity(identifier) => { IdentifierWasm::from(identifier).into() } - } + }; + js_value.into() } } + +impl_wasm_type_info!(TokenDistributionRecipientWasm, TokenDistributionRecipient); diff --git a/packages/wasm-dpp2/src/tokens/configuration/distribution_rules.rs b/packages/wasm-dpp2/src/tokens/configuration/distribution_rules.rs index 6d4716477e7..2386fa0a091 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/distribution_rules.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/distribution_rules.rs @@ -1,9 +1,11 @@ -use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::identifier::{IdentifierLikeOrUndefinedJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::tokens::configuration::change_control_rules::ChangeControlRulesWasm; use crate::tokens::configuration::perpetual_distribution::TokenPerpetualDistributionWasm; use crate::tokens::configuration::pre_programmed_distribution::TokenPreProgrammedDistributionWasm; -use crate::utils::IntoWasm; +use crate::utils::{IntoWasm, try_from_options, try_from_options_optional, try_from_options_with}; use dpp::data_contract::associated_token::token_distribution_rules::TokenDistributionRules; use dpp::data_contract::associated_token::token_distribution_rules::accessors::v0::{ TokenDistributionRulesV0Getters, TokenDistributionRulesV0Setters, @@ -12,6 +14,26 @@ use dpp::data_contract::associated_token::token_distribution_rules::v0::TokenDis use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_DISTRIBUTION_RULES_OPTIONS_TS: &str = r#" +export interface TokenDistributionRulesOptions { + perpetualDistribution?: TokenPerpetualDistribution; + perpetualDistributionRules: ChangeControlRules; + preProgrammedDistribution?: TokenPreProgrammedDistribution; + newTokensDestinationIdentity?: IdentifierLike; + newTokensDestinationIdentityRules: ChangeControlRules; + mintingAllowChoosingDestination: boolean; + mintingAllowChoosingDestinationRules: ChangeControlRules; + changeDirectPurchasePricingRules: ChangeControlRules; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenDistributionRulesOptions")] + pub type TokenDistributionRulesOptionsJs; +} + #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "TokenDistributionRules")] pub struct TokenDistributionRulesWasm(TokenDistributionRules); @@ -30,107 +52,89 @@ impl From for TokenDistributionRulesWasm { #[wasm_bindgen(js_class = TokenDistributionRules)] impl TokenDistributionRulesWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenDistributionRules".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenDistributionRules".to_string() - } - #[wasm_bindgen(constructor)] - #[allow(clippy::too_many_arguments)] - pub fn new( - js_perpetual_distribution: &JsValue, - perpetual_distribution_rules: &ChangeControlRulesWasm, - js_pre_programmed_distribution: &JsValue, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_new_tokens_destination_identity: &JsValue, - new_tokens_destination_identity_rules: &ChangeControlRulesWasm, - minting_allow_choosing_destination: bool, - minting_allow_choosing_destination_rules: &ChangeControlRulesWasm, - change_direct_purchase_pricing_rules: &ChangeControlRulesWasm, + pub fn constructor( + options: TokenDistributionRulesOptionsJs, ) -> WasmDppResult { - let perpetual_distribution = if js_perpetual_distribution.is_undefined() { - None - } else { - Some( - js_perpetual_distribution - .to_wasm::("TokenPerpetualDistribution")? - .clone() - .into(), - ) - }; - - let pre_programmed_distribution = if js_pre_programmed_distribution.is_undefined() { - None - } else { - Some( - js_pre_programmed_distribution - .to_wasm::( - "TokenPreProgrammedDistribution", - )? - .clone() - .into(), - ) - }; - - let new_tokens_destination_identity = if js_new_tokens_destination_identity.is_undefined() { - None - } else { - Some(IdentifierWasm::try_from(js_new_tokens_destination_identity)?.into()) - }; + let perpetual_distribution = try_from_options_optional::( + &options, + "perpetualDistribution", + )? + .map(Into::into); + + let perpetual_distribution_rules: ChangeControlRulesWasm = + try_from_options(&options, "perpetualDistributionRules")?; + + let pre_programmed_distribution = try_from_options_optional::< + TokenPreProgrammedDistributionWasm, + >(&options, "preProgrammedDistribution")? + .map(Into::into); + + let new_tokens_destination_identity = + try_from_options_optional::(&options, "newTokensDestinationIdentity")? + .map(Into::into); + + let new_tokens_destination_identity_rules: ChangeControlRulesWasm = + try_from_options(&options, "newTokensDestinationIdentityRules")?; + + let minting_allow_choosing_destination = + try_from_options_with(&options, "mintingAllowChoosingDestination", |v| { + v.as_bool().ok_or_else(|| { + WasmDppError::invalid_argument( + "mintingAllowChoosingDestination must be a boolean", + ) + }) + })?; + + let minting_allow_choosing_destination_rules: ChangeControlRulesWasm = + try_from_options(&options, "mintingAllowChoosingDestinationRules")?; + + let change_direct_purchase_pricing_rules: ChangeControlRulesWasm = + try_from_options(&options, "changeDirectPurchasePricingRules")?; Ok(TokenDistributionRulesWasm(TokenDistributionRules::V0( TokenDistributionRulesV0 { perpetual_distribution, - perpetual_distribution_rules: perpetual_distribution_rules.clone().into(), + perpetual_distribution_rules: perpetual_distribution_rules.into(), pre_programmed_distribution, new_tokens_destination_identity, - new_tokens_destination_identity_rules: new_tokens_destination_identity_rules - .clone() - .into(), + new_tokens_destination_identity_rules: new_tokens_destination_identity_rules.into(), minting_allow_choosing_destination, minting_allow_choosing_destination_rules: minting_allow_choosing_destination_rules - .clone() - .into(), - change_direct_purchase_pricing_rules: change_direct_purchase_pricing_rules - .clone() .into(), + change_direct_purchase_pricing_rules: change_direct_purchase_pricing_rules.into(), }, ))) } #[wasm_bindgen(getter = "perpetualDistribution")] - pub fn get_perpetual_distribution(&self) -> Option { + pub fn perpetual_distribution(&self) -> Option { self.0 .perpetual_distribution() .map(|perp| perp.clone().into()) } #[wasm_bindgen(getter = "perpetualDistributionRules")] - pub fn get_perpetual_distribution_rules(&self) -> ChangeControlRulesWasm { + pub fn perpetual_distribution_rules(&self) -> ChangeControlRulesWasm { self.0.perpetual_distribution_rules().clone().into() } #[wasm_bindgen(getter = "preProgrammedDistribution")] - pub fn get_pre_programmed_distribution(&self) -> Option { + pub fn pre_programmed_distribution(&self) -> Option { self.0 .pre_programmed_distribution() .map(|pre| pre.clone().into()) } - #[wasm_bindgen(getter = "newTokenDestinationIdentity")] - pub fn get_new_tokens_destination_identity(&self) -> Option { + #[wasm_bindgen(getter = "newTokensDestinationIdentity")] + pub fn new_tokens_destination_identity(&self) -> Option { self.0 .new_tokens_destination_identity() .map(|id| IdentifierWasm::from(*id)) } - #[wasm_bindgen(getter = "newTokenDestinationIdentityRules")] - pub fn get_new_tokens_destination_identity_rules(&self) -> ChangeControlRulesWasm { + #[wasm_bindgen(getter = "newTokensDestinationIdentityRules")] + pub fn new_tokens_destination_identity_rules(&self) -> ChangeControlRulesWasm { self.0 .new_tokens_destination_identity_rules() .clone() @@ -138,12 +142,12 @@ impl TokenDistributionRulesWasm { } #[wasm_bindgen(getter = "mintingAllowChoosingDestination")] - pub fn get_minting_allow_choosing_destination(&self) -> bool { + pub fn is_minting_allowing_choosing_destination(&self) -> bool { self.0.minting_allow_choosing_destination() } #[wasm_bindgen(getter = "mintingAllowChoosingDestinationRules")] - pub fn get_minting_allow_choosing_destination_rules(&self) -> ChangeControlRulesWasm { + pub fn minting_allow_choosing_destination_rules(&self) -> ChangeControlRulesWasm { self.0 .minting_allow_choosing_destination_rules() .clone() @@ -151,23 +155,24 @@ impl TokenDistributionRulesWasm { } #[wasm_bindgen(getter = "changeDirectPurchasePricingRules")] - pub fn get_change_direct_purchase_pricing_rules(&self) -> ChangeControlRulesWasm { + pub fn change_direct_purchase_pricing_rules(&self) -> ChangeControlRulesWasm { self.0.change_direct_purchase_pricing_rules().clone().into() } #[wasm_bindgen(setter = "perpetualDistribution")] pub fn set_perpetual_distribution( &mut self, - js_perpetual_distribution: &JsValue, + perpetual_distribution: &JsValue, ) -> WasmDppResult<()> { - let perpetual_distribution = match js_perpetual_distribution.is_undefined() { - true => None, - false => Some( - js_perpetual_distribution + let perpetual_distribution = if perpetual_distribution.is_undefined() { + None + } else { + Some( + perpetual_distribution .to_wasm::("TokenPerpetualDistribution")? .clone() .into(), - ), + ) }; self.0.set_perpetual_distribution(perpetual_distribution); @@ -181,51 +186,47 @@ impl TokenDistributionRulesWasm { } #[wasm_bindgen(setter = "preProgrammedDistribution")] - pub fn set_pre_programmed_distribution( - &mut self, - js_distribution: &JsValue, - ) -> WasmDppResult<()> { - let distribution = match js_distribution.is_undefined() { - true => None, - false => Some( - js_distribution + pub fn set_pre_programmed_distribution(&mut self, distribution: &JsValue) -> WasmDppResult<()> { + let distribution = if distribution.is_undefined() { + None + } else { + Some( + distribution .to_wasm::( "TokenPreProgrammedDistribution", )? .clone() .into(), - ), + ) }; self.0.set_pre_programmed_distribution(distribution); Ok(()) } - #[wasm_bindgen(setter = "newTokenDestinationIdentity")] + #[wasm_bindgen(setter = "newTokensDestinationIdentity")] pub fn set_new_tokens_destination_identity( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identifier: &JsValue, + identifier: IdentifierLikeOrUndefinedJs, ) -> WasmDppResult<()> { - let identifier = match js_identifier.is_undefined() { - true => None, - false => Some(IdentifierWasm::try_from(js_identifier)?.into()), - }; - + let identifier: Option = identifier.try_into()?; self.0.set_new_tokens_destination_identity(identifier); - Ok(()) } - #[wasm_bindgen(setter = "newTokenDestinationIdentityRules")] + #[wasm_bindgen(setter = "newTokensDestinationIdentityRules")] pub fn set_new_tokens_destination_identity_rules(&mut self, rules: &ChangeControlRulesWasm) { self.0 .set_new_tokens_destination_identity_rules(rules.clone().into()); } #[wasm_bindgen(setter = "mintingAllowChoosingDestination")] - pub fn set_minting_allow_choosing_destination(&mut self, flag: bool) { - self.0.set_minting_allow_choosing_destination(flag); + pub fn set_is_minting_allowing_choosing_destination( + &mut self, + is_minting_allowing_choosing_destination: bool, + ) { + self.0 + .set_minting_allow_choosing_destination(is_minting_allowing_choosing_destination); } #[wasm_bindgen(setter = "mintingAllowChoosingDestinationRules")] @@ -240,3 +241,6 @@ impl TokenDistributionRulesWasm { .set_change_direct_purchase_pricing_rules(rules.clone().into()); } } + +impl_try_from_js_value!(TokenDistributionRulesWasm, "TokenDistributionRules"); +impl_wasm_type_info!(TokenDistributionRulesWasm, TokenDistributionRules); diff --git a/packages/wasm-dpp2/src/tokens/configuration/distribution_structs.rs b/packages/wasm-dpp2/src/tokens/configuration/distribution_structs.rs index b3952154879..db3e03f284e 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/distribution_structs.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/distribution_structs.rs @@ -1,111 +1,984 @@ +use crate::error::{WasmDppError, WasmDppResult}; use dpp::balances::credits::TokenAmount; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const DISTRIBUTION_OPTIONS_TS: &str = r#" +export interface DistributionFixedAmountOptions { + amount: bigint; +} + +export interface DistributionRandomOptions { + min: bigint; + max: bigint; +} + +export interface DistributionStepDecreasingAmountOptions { + stepCount: number; + decreasePerIntervalNumerator: number; + decreasePerIntervalDenominator: number; + startDecreasingOffset?: bigint; + maxIntervalCount?: number; + distributionStartAmount: bigint; + trailingDistributionIntervalAmount: bigint; + minValue?: bigint; +} + +export interface DistributionLinearOptions { + a: bigint; + d: bigint; + startStep?: bigint; + startingAmount: bigint; + minValue?: bigint; + maxValue?: bigint; +} + +export interface DistributionPolynomialOptions { + a: bigint; + d: bigint; + m: bigint; + n: bigint; + o: bigint; + startMoment?: bigint; + b: bigint; + minValue?: bigint; + maxValue?: bigint; +} + +export interface DistributionExponentialOptions { + a: bigint; + d: bigint; + m: bigint; + n: bigint; + o: bigint; + startMoment?: bigint; + b: bigint; + minValue?: bigint; + maxValue?: bigint; +} + +export interface DistributionLogarithmicOptions { + a: bigint; + d: bigint; + m: bigint; + n: bigint; + o: bigint; + startMoment?: bigint; + b: bigint; + minValue?: bigint; + maxValue?: bigint; +} + +export interface DistributionInvertedLogarithmicOptions { + a: bigint; + d: bigint; + m: bigint; + n: bigint; + o: bigint; + startMoment?: bigint; + b: bigint; + minValue?: bigint; + maxValue?: bigint; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "DistributionFixedAmountOptions")] + pub type DistributionFixedAmountOptionsJs; + + #[wasm_bindgen(typescript_type = "DistributionRandomOptions")] + pub type DistributionRandomOptionsJs; + + #[wasm_bindgen(typescript_type = "DistributionStepDecreasingAmountOptions")] + pub type DistributionStepDecreasingAmountOptionsJs; + + #[wasm_bindgen(typescript_type = "DistributionLinearOptions")] + pub type DistributionLinearOptionsJs; + + #[wasm_bindgen(typescript_type = "DistributionPolynomialOptions")] + pub type DistributionPolynomialOptionsJs; + + #[wasm_bindgen(typescript_type = "DistributionExponentialOptions")] + pub type DistributionExponentialOptionsJs; + + #[wasm_bindgen(typescript_type = "DistributionLogarithmicOptions")] + pub type DistributionLogarithmicOptionsJs; + + #[wasm_bindgen(typescript_type = "DistributionInvertedLogarithmicOptions")] + pub type DistributionInvertedLogarithmicOptionsJs; +} + +// DistributionFixedAmount + #[wasm_bindgen(js_name = "DistributionFixedAmount")] pub struct DistributionFixedAmountWasm { - pub amount: TokenAmount, + pub(crate) amount: TokenAmount, +} + +#[wasm_bindgen(js_class = DistributionFixedAmount)] +impl DistributionFixedAmountWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionFixedAmountOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + struct Options { + amount: TokenAmount, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + amount: opts.amount, + }) + } + + #[wasm_bindgen(getter)] + pub fn amount(&self) -> TokenAmount { + self.amount + } + + #[wasm_bindgen(setter)] + pub fn set_amount(&mut self, value: TokenAmount) { + self.amount = value; + } } +// DistributionRandom + #[wasm_bindgen(js_name = "DistributionRandom")] pub struct DistributionRandomWasm { - pub min: TokenAmount, - pub max: TokenAmount, + pub(crate) min: TokenAmount, + pub(crate) max: TokenAmount, } +#[wasm_bindgen(js_class = DistributionRandom)] +impl DistributionRandomWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionRandomOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + struct Options { + min: TokenAmount, + max: TokenAmount, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + min: opts.min, + max: opts.max, + }) + } + + #[wasm_bindgen(getter)] + pub fn min(&self) -> TokenAmount { + self.min + } + + #[wasm_bindgen(setter)] + pub fn set_min(&mut self, value: TokenAmount) { + self.min = value; + } + + #[wasm_bindgen(getter)] + pub fn max(&self) -> TokenAmount { + self.max + } + + #[wasm_bindgen(setter)] + pub fn set_max(&mut self, value: TokenAmount) { + self.max = value; + } +} + +// DistributionStepDecreasingAmount + #[wasm_bindgen(js_name = "DistributionStepDecreasingAmount")] pub struct DistributionStepDecreasingAmountWasm { - #[wasm_bindgen(js_name = "stepCount")] - pub step_count: u32, - #[wasm_bindgen(js_name = "decreasePerIntervalNumerator")] - pub decrease_per_interval_numerator: u16, - #[wasm_bindgen(js_name = "decreasePerIntervalDenominator")] - pub decrease_per_interval_denominator: u16, - #[wasm_bindgen(js_name = "startDecreasingOffset")] - pub start_decreasing_offset: Option, - #[wasm_bindgen(js_name = "maxIntervalCount")] - pub max_interval_count: Option, - #[wasm_bindgen(js_name = "distributionStartAmount")] - pub distribution_start_amount: TokenAmount, - #[wasm_bindgen(js_name = "trailingDistributionIntervalAmount")] - pub trailing_distribution_interval_amount: TokenAmount, - #[wasm_bindgen(js_name = "minValue")] - pub min_value: Option, + pub(crate) step_count: u32, + pub(crate) decrease_per_interval_numerator: u16, + pub(crate) decrease_per_interval_denominator: u16, + pub(crate) start_decreasing_offset: Option, + pub(crate) max_interval_count: Option, + pub(crate) distribution_start_amount: TokenAmount, + pub(crate) trailing_distribution_interval_amount: TokenAmount, + pub(crate) min_value: Option, +} + +#[wasm_bindgen(js_class = DistributionStepDecreasingAmount)] +impl DistributionStepDecreasingAmountWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionStepDecreasingAmountOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct Options { + step_count: u32, + decrease_per_interval_numerator: u16, + decrease_per_interval_denominator: u16, + #[serde(default)] + start_decreasing_offset: Option, + #[serde(default)] + max_interval_count: Option, + distribution_start_amount: TokenAmount, + trailing_distribution_interval_amount: TokenAmount, + #[serde(default)] + min_value: Option, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + step_count: opts.step_count, + decrease_per_interval_numerator: opts.decrease_per_interval_numerator, + decrease_per_interval_denominator: opts.decrease_per_interval_denominator, + start_decreasing_offset: opts.start_decreasing_offset, + max_interval_count: opts.max_interval_count, + distribution_start_amount: opts.distribution_start_amount, + trailing_distribution_interval_amount: opts.trailing_distribution_interval_amount, + min_value: opts.min_value, + }) + } + + #[wasm_bindgen(getter = "stepCount")] + pub fn step_count(&self) -> u32 { + self.step_count + } + + #[wasm_bindgen(setter = "stepCount")] + pub fn set_step_count(&mut self, value: u32) { + self.step_count = value; + } + + #[wasm_bindgen(getter = "decreasePerIntervalNumerator")] + pub fn decrease_per_interval_numerator(&self) -> u16 { + self.decrease_per_interval_numerator + } + + #[wasm_bindgen(setter = "decreasePerIntervalNumerator")] + pub fn set_decrease_per_interval_numerator(&mut self, value: u16) { + self.decrease_per_interval_numerator = value; + } + + #[wasm_bindgen(getter = "decreasePerIntervalDenominator")] + pub fn decrease_per_interval_denominator(&self) -> u16 { + self.decrease_per_interval_denominator + } + + #[wasm_bindgen(setter = "decreasePerIntervalDenominator")] + pub fn set_decrease_per_interval_denominator(&mut self, value: u16) { + self.decrease_per_interval_denominator = value; + } + + #[wasm_bindgen(getter = "startDecreasingOffset")] + pub fn start_decreasing_offset(&self) -> Option { + self.start_decreasing_offset + } + + #[wasm_bindgen(setter = "startDecreasingOffset")] + pub fn set_start_decreasing_offset(&mut self, value: Option) { + self.start_decreasing_offset = value; + } + + #[wasm_bindgen(getter = "maxIntervalCount")] + pub fn max_interval_count(&self) -> Option { + self.max_interval_count + } + + #[wasm_bindgen(setter = "maxIntervalCount")] + pub fn set_max_interval_count(&mut self, value: Option) { + self.max_interval_count = value; + } + + #[wasm_bindgen(getter = "distributionStartAmount")] + pub fn distribution_start_amount(&self) -> TokenAmount { + self.distribution_start_amount + } + + #[wasm_bindgen(setter = "distributionStartAmount")] + pub fn set_distribution_start_amount(&mut self, value: TokenAmount) { + self.distribution_start_amount = value; + } + + #[wasm_bindgen(getter = "trailingDistributionIntervalAmount")] + pub fn trailing_distribution_interval_amount(&self) -> TokenAmount { + self.trailing_distribution_interval_amount + } + + #[wasm_bindgen(setter = "trailingDistributionIntervalAmount")] + pub fn set_trailing_distribution_interval_amount(&mut self, value: TokenAmount) { + self.trailing_distribution_interval_amount = value; + } + + #[wasm_bindgen(getter = "minValue")] + pub fn min_value(&self) -> Option { + self.min_value + } + + #[wasm_bindgen(setter = "minValue")] + pub fn set_min_value(&mut self, value: Option) { + self.min_value = value; + } } +// DistributionLinear + #[wasm_bindgen(js_name = "DistributionLinear")] pub struct DistributionLinearWasm { - pub a: i64, - pub d: u64, - #[wasm_bindgen(js_name = "startStep")] - pub start_step: Option, - #[wasm_bindgen(js_name = "startingAmount")] - pub starting_amount: TokenAmount, - #[wasm_bindgen(js_name = "minValue")] - pub min_value: Option, - #[wasm_bindgen(js_name = "maxValue")] - pub max_value: Option, + pub(crate) a: i64, + pub(crate) d: u64, + pub(crate) start_step: Option, + pub(crate) starting_amount: TokenAmount, + pub(crate) min_value: Option, + pub(crate) max_value: Option, } +#[wasm_bindgen(js_class = DistributionLinear)] +impl DistributionLinearWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionLinearOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct Options { + a: i64, + d: u64, + #[serde(default)] + start_step: Option, + starting_amount: TokenAmount, + #[serde(default)] + min_value: Option, + #[serde(default)] + max_value: Option, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + a: opts.a, + d: opts.d, + start_step: opts.start_step, + starting_amount: opts.starting_amount, + min_value: opts.min_value, + max_value: opts.max_value, + }) + } + + #[wasm_bindgen(getter)] + pub fn a(&self) -> i64 { + self.a + } + + #[wasm_bindgen(setter)] + pub fn set_a(&mut self, value: i64) { + self.a = value; + } + + #[wasm_bindgen(getter)] + pub fn d(&self) -> u64 { + self.d + } + + #[wasm_bindgen(setter)] + pub fn set_d(&mut self, value: u64) { + self.d = value; + } + + #[wasm_bindgen(getter = "startStep")] + pub fn start_step(&self) -> Option { + self.start_step + } + + #[wasm_bindgen(setter = "startStep")] + pub fn set_start_step(&mut self, value: Option) { + self.start_step = value; + } + + #[wasm_bindgen(getter = "startingAmount")] + pub fn starting_amount(&self) -> TokenAmount { + self.starting_amount + } + + #[wasm_bindgen(setter = "startingAmount")] + pub fn set_starting_amount(&mut self, value: TokenAmount) { + self.starting_amount = value; + } + + #[wasm_bindgen(getter = "minValue")] + pub fn min_value(&self) -> Option { + self.min_value + } + + #[wasm_bindgen(setter = "minValue")] + pub fn set_min_value(&mut self, value: Option) { + self.min_value = value; + } + + #[wasm_bindgen(getter = "maxValue")] + pub fn max_value(&self) -> Option { + self.max_value + } + + #[wasm_bindgen(setter = "maxValue")] + pub fn set_max_value(&mut self, value: Option) { + self.max_value = value; + } +} + +// DistributionPolynomial + #[wasm_bindgen(js_name = "DistributionPolynomial")] pub struct DistributionPolynomialWasm { - pub a: i64, - pub d: u64, - pub m: i64, - pub n: u64, - pub o: i64, - #[wasm_bindgen(js_name = "startMoment")] - pub start_moment: Option, - pub b: TokenAmount, - #[wasm_bindgen(js_name = "minValue")] - pub min_value: Option, - #[wasm_bindgen(js_name = "maxValue")] - pub max_value: Option, + pub(crate) a: i64, + pub(crate) d: u64, + pub(crate) m: i64, + pub(crate) n: u64, + pub(crate) o: i64, + pub(crate) start_moment: Option, + pub(crate) b: TokenAmount, + pub(crate) min_value: Option, + pub(crate) max_value: Option, } +#[wasm_bindgen(js_class = DistributionPolynomial)] +impl DistributionPolynomialWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionPolynomialOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct Options { + a: i64, + d: u64, + m: i64, + n: u64, + o: i64, + #[serde(default)] + start_moment: Option, + b: TokenAmount, + #[serde(default)] + min_value: Option, + #[serde(default)] + max_value: Option, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, + }) + } + + #[wasm_bindgen(getter)] + pub fn a(&self) -> i64 { + self.a + } + + #[wasm_bindgen(setter)] + pub fn set_a(&mut self, value: i64) { + self.a = value; + } + + #[wasm_bindgen(getter)] + pub fn d(&self) -> u64 { + self.d + } + + #[wasm_bindgen(setter)] + pub fn set_d(&mut self, value: u64) { + self.d = value; + } + + #[wasm_bindgen(getter)] + pub fn m(&self) -> i64 { + self.m + } + + #[wasm_bindgen(setter)] + pub fn set_m(&mut self, value: i64) { + self.m = value; + } + + #[wasm_bindgen(getter)] + pub fn n(&self) -> u64 { + self.n + } + + #[wasm_bindgen(setter)] + pub fn set_n(&mut self, value: u64) { + self.n = value; + } + + #[wasm_bindgen(getter)] + pub fn o(&self) -> i64 { + self.o + } + + #[wasm_bindgen(setter)] + pub fn set_o(&mut self, value: i64) { + self.o = value; + } + + #[wasm_bindgen(getter = "startMoment")] + pub fn start_moment(&self) -> Option { + self.start_moment + } + + #[wasm_bindgen(setter = "startMoment")] + pub fn set_start_moment(&mut self, value: Option) { + self.start_moment = value; + } + + #[wasm_bindgen(getter)] + pub fn b(&self) -> TokenAmount { + self.b + } + + #[wasm_bindgen(setter)] + pub fn set_b(&mut self, value: TokenAmount) { + self.b = value; + } + + #[wasm_bindgen(getter = "minValue")] + pub fn min_value(&self) -> Option { + self.min_value + } + + #[wasm_bindgen(setter = "minValue")] + pub fn set_min_value(&mut self, value: Option) { + self.min_value = value; + } + + #[wasm_bindgen(getter = "maxValue")] + pub fn max_value(&self) -> Option { + self.max_value + } + + #[wasm_bindgen(setter = "maxValue")] + pub fn set_max_value(&mut self, value: Option) { + self.max_value = value; + } +} + +// DistributionExponential + #[wasm_bindgen(js_name = "DistributionExponential")] pub struct DistributionExponentialWasm { - pub a: u64, - pub d: u64, - pub m: i64, - pub n: u64, - pub o: i64, - #[wasm_bindgen(js_name = "startMoment")] - pub start_moment: Option, - pub b: TokenAmount, - #[wasm_bindgen(js_name = "minValue")] - pub min_value: Option, - #[wasm_bindgen(js_name = "maxValue")] - pub max_value: Option, + pub(crate) a: u64, + pub(crate) d: u64, + pub(crate) m: i64, + pub(crate) n: u64, + pub(crate) o: i64, + pub(crate) start_moment: Option, + pub(crate) b: TokenAmount, + pub(crate) min_value: Option, + pub(crate) max_value: Option, } +#[wasm_bindgen(js_class = DistributionExponential)] +impl DistributionExponentialWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionExponentialOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct Options { + a: u64, + d: u64, + m: i64, + n: u64, + o: i64, + #[serde(default)] + start_moment: Option, + b: TokenAmount, + #[serde(default)] + min_value: Option, + #[serde(default)] + max_value: Option, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, + }) + } + + #[wasm_bindgen(getter)] + pub fn a(&self) -> u64 { + self.a + } + + #[wasm_bindgen(setter)] + pub fn set_a(&mut self, value: u64) { + self.a = value; + } + + #[wasm_bindgen(getter)] + pub fn d(&self) -> u64 { + self.d + } + + #[wasm_bindgen(setter)] + pub fn set_d(&mut self, value: u64) { + self.d = value; + } + + #[wasm_bindgen(getter)] + pub fn m(&self) -> i64 { + self.m + } + + #[wasm_bindgen(setter)] + pub fn set_m(&mut self, value: i64) { + self.m = value; + } + + #[wasm_bindgen(getter)] + pub fn n(&self) -> u64 { + self.n + } + + #[wasm_bindgen(setter)] + pub fn set_n(&mut self, value: u64) { + self.n = value; + } + + #[wasm_bindgen(getter)] + pub fn o(&self) -> i64 { + self.o + } + + #[wasm_bindgen(setter)] + pub fn set_o(&mut self, value: i64) { + self.o = value; + } + + #[wasm_bindgen(getter = "startMoment")] + pub fn start_moment(&self) -> Option { + self.start_moment + } + + #[wasm_bindgen(setter = "startMoment")] + pub fn set_start_moment(&mut self, value: Option) { + self.start_moment = value; + } + + #[wasm_bindgen(getter)] + pub fn b(&self) -> TokenAmount { + self.b + } + + #[wasm_bindgen(setter)] + pub fn set_b(&mut self, value: TokenAmount) { + self.b = value; + } + + #[wasm_bindgen(getter = "minValue")] + pub fn min_value(&self) -> Option { + self.min_value + } + + #[wasm_bindgen(setter = "minValue")] + pub fn set_min_value(&mut self, value: Option) { + self.min_value = value; + } + + #[wasm_bindgen(getter = "maxValue")] + pub fn max_value(&self) -> Option { + self.max_value + } + + #[wasm_bindgen(setter = "maxValue")] + pub fn set_max_value(&mut self, value: Option) { + self.max_value = value; + } +} + +// DistributionLogarithmic + #[wasm_bindgen(js_name = "DistributionLogarithmic")] pub struct DistributionLogarithmicWasm { - pub a: i64, - pub d: u64, - pub m: u64, - pub n: u64, - pub o: i64, - #[wasm_bindgen(js_name = "startMoment")] - pub start_moment: Option, - pub b: TokenAmount, - #[wasm_bindgen(js_name = "minValue")] - pub min_value: Option, - #[wasm_bindgen(js_name = "maxValue")] - pub max_value: Option, + pub(crate) a: i64, + pub(crate) d: u64, + pub(crate) m: u64, + pub(crate) n: u64, + pub(crate) o: i64, + pub(crate) start_moment: Option, + pub(crate) b: TokenAmount, + pub(crate) min_value: Option, + pub(crate) max_value: Option, } +#[wasm_bindgen(js_class = DistributionLogarithmic)] +impl DistributionLogarithmicWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionLogarithmicOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct Options { + a: i64, + d: u64, + m: u64, + n: u64, + o: i64, + #[serde(default)] + start_moment: Option, + b: TokenAmount, + #[serde(default)] + min_value: Option, + #[serde(default)] + max_value: Option, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, + }) + } + + #[wasm_bindgen(getter)] + pub fn a(&self) -> i64 { + self.a + } + + #[wasm_bindgen(setter)] + pub fn set_a(&mut self, value: i64) { + self.a = value; + } + + #[wasm_bindgen(getter)] + pub fn d(&self) -> u64 { + self.d + } + + #[wasm_bindgen(setter)] + pub fn set_d(&mut self, value: u64) { + self.d = value; + } + + #[wasm_bindgen(getter)] + pub fn m(&self) -> u64 { + self.m + } + + #[wasm_bindgen(setter)] + pub fn set_m(&mut self, value: u64) { + self.m = value; + } + + #[wasm_bindgen(getter)] + pub fn n(&self) -> u64 { + self.n + } + + #[wasm_bindgen(setter)] + pub fn set_n(&mut self, value: u64) { + self.n = value; + } + + #[wasm_bindgen(getter)] + pub fn o(&self) -> i64 { + self.o + } + + #[wasm_bindgen(setter)] + pub fn set_o(&mut self, value: i64) { + self.o = value; + } + + #[wasm_bindgen(getter = "startMoment")] + pub fn start_moment(&self) -> Option { + self.start_moment + } + + #[wasm_bindgen(setter = "startMoment")] + pub fn set_start_moment(&mut self, value: Option) { + self.start_moment = value; + } + + #[wasm_bindgen(getter)] + pub fn b(&self) -> TokenAmount { + self.b + } + + #[wasm_bindgen(setter)] + pub fn set_b(&mut self, value: TokenAmount) { + self.b = value; + } + + #[wasm_bindgen(getter = "minValue")] + pub fn min_value(&self) -> Option { + self.min_value + } + + #[wasm_bindgen(setter = "minValue")] + pub fn set_min_value(&mut self, value: Option) { + self.min_value = value; + } + + #[wasm_bindgen(getter = "maxValue")] + pub fn max_value(&self) -> Option { + self.max_value + } + + #[wasm_bindgen(setter = "maxValue")] + pub fn set_max_value(&mut self, value: Option) { + self.max_value = value; + } +} + +// DistributionInvertedLogarithmic + #[wasm_bindgen(js_name = "DistributionInvertedLogarithmic")] pub struct DistributionInvertedLogarithmicWasm { - pub a: i64, - pub d: u64, - pub m: u64, - pub n: u64, - pub o: i64, - #[wasm_bindgen(js_name = "startMoment")] - pub start_moment: Option, - pub b: TokenAmount, - #[wasm_bindgen(js_name = "minValue")] - pub min_value: Option, - #[wasm_bindgen(js_name = "maxValue")] - pub max_value: Option, + pub(crate) a: i64, + pub(crate) d: u64, + pub(crate) m: u64, + pub(crate) n: u64, + pub(crate) o: i64, + pub(crate) start_moment: Option, + pub(crate) b: TokenAmount, + pub(crate) min_value: Option, + pub(crate) max_value: Option, +} + +#[wasm_bindgen(js_class = DistributionInvertedLogarithmic)] +impl DistributionInvertedLogarithmicWasm { + #[wasm_bindgen(constructor)] + pub fn new(options: DistributionInvertedLogarithmicOptionsJs) -> WasmDppResult { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct Options { + a: i64, + d: u64, + m: u64, + n: u64, + o: i64, + #[serde(default)] + start_moment: Option, + b: TokenAmount, + #[serde(default)] + min_value: Option, + #[serde(default)] + max_value: Option, + } + let opts: Options = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + Ok(Self { + a: opts.a, + d: opts.d, + m: opts.m, + n: opts.n, + o: opts.o, + start_moment: opts.start_moment, + b: opts.b, + min_value: opts.min_value, + max_value: opts.max_value, + }) + } + + #[wasm_bindgen(getter)] + pub fn a(&self) -> i64 { + self.a + } + + #[wasm_bindgen(setter)] + pub fn set_a(&mut self, value: i64) { + self.a = value; + } + + #[wasm_bindgen(getter)] + pub fn d(&self) -> u64 { + self.d + } + + #[wasm_bindgen(setter)] + pub fn set_d(&mut self, value: u64) { + self.d = value; + } + + #[wasm_bindgen(getter)] + pub fn m(&self) -> u64 { + self.m + } + + #[wasm_bindgen(setter)] + pub fn set_m(&mut self, value: u64) { + self.m = value; + } + + #[wasm_bindgen(getter)] + pub fn n(&self) -> u64 { + self.n + } + + #[wasm_bindgen(setter)] + pub fn set_n(&mut self, value: u64) { + self.n = value; + } + + #[wasm_bindgen(getter)] + pub fn o(&self) -> i64 { + self.o + } + + #[wasm_bindgen(setter)] + pub fn set_o(&mut self, value: i64) { + self.o = value; + } + + #[wasm_bindgen(getter = "startMoment")] + pub fn start_moment(&self) -> Option { + self.start_moment + } + + #[wasm_bindgen(setter = "startMoment")] + pub fn set_start_moment(&mut self, value: Option) { + self.start_moment = value; + } + + #[wasm_bindgen(getter)] + pub fn b(&self) -> TokenAmount { + self.b + } + + #[wasm_bindgen(setter)] + pub fn set_b(&mut self, value: TokenAmount) { + self.b = value; + } + + #[wasm_bindgen(getter = "minValue")] + pub fn min_value(&self) -> Option { + self.min_value + } + + #[wasm_bindgen(setter = "minValue")] + pub fn set_min_value(&mut self, value: Option) { + self.min_value = value; + } + + #[wasm_bindgen(getter = "maxValue")] + pub fn max_value(&self) -> Option { + self.max_value + } + + #[wasm_bindgen(setter = "maxValue")] + pub fn set_max_value(&mut self, value: Option) { + self.max_value = value; + } } diff --git a/packages/wasm-dpp2/src/tokens/configuration/group.rs b/packages/wasm-dpp2/src/tokens/configuration/group.rs index 32f6dd8bc67..f250b3dfdb7 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/group.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/group.rs @@ -1,18 +1,59 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_from_for_extern_type; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::serialization; -use crate::utils::JsValueExt; +use crate::utils::{JsMapExt, try_to_map}; use dpp::data_contract::group::accessors::v0::{GroupV0Getters, GroupV0Setters}; use dpp::data_contract::group::v0::GroupV0; use dpp::data_contract::group::{Group, GroupMemberPower, GroupRequiredPower}; -use dpp::platform_value::string_encoding::Encoding; use dpp::prelude::Identifier; -use js_sys::Object; -use js_sys::Reflect; +use js_sys::Map; use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Group members mapping: base58 Identifier string -> power. + */ +export type GroupMembersMap = Map; + +/** + * Group serialized as a plain object. + */ +export interface GroupObject { + $formatVersion: string; + members: Record; + requiredPower: number; +} + +/** + * Group serialized as JSON. + */ +export interface GroupJSON { + $formatVersion: string; + members: Record; + requiredPower: number; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "GroupMembersMap")] + pub type GroupMembersMapJs; + + #[wasm_bindgen(typescript_type = "GroupObject")] + pub type GroupObjectJs; + + #[wasm_bindgen(typescript_type = "GroupJSON")] + pub type GroupJSONJs; +} + +impl_from_for_extern_type!(GroupMembersMapJs, Map); + #[derive(Clone, PartialEq, Debug)] #[wasm_bindgen(js_name = "Group")] pub struct GroupWasm(Group); @@ -29,30 +70,25 @@ impl From for Group { } } -pub fn js_members_to_map( - js_members: &JsValue, +pub fn members_map_to_btree( + members_map: &Map, ) -> WasmDppResult> { - let members_object = Object::from(js_members.clone()); - let members_keys = Object::keys(&members_object); - let mut members = BTreeMap::new(); - for key in members_keys.iter() { - let key_str = key - .as_string() - .ok_or_else(|| WasmDppError::invalid_argument("cannot convert key to string"))?; + for entry in members_map.entries().into_iter() { + let entry = entry.map_err(|e| { + WasmDppError::invalid_argument(format!("Failed to iterate map entries: {:?}", e)) + })?; + + let entry_array = js_sys::Array::from(&entry); + let key = entry_array.get(0); + let value = entry_array.get(1); - let identifier: Identifier = IdentifierWasm::try_from(key.clone()) - .map_err(|_| { - WasmDppError::invalid_argument(format!("Invalid identifier: {}", key_str)) - })? + let identifier: Identifier = IdentifierWasm::try_from(key) + .map_err(|e| WasmDppError::invalid_argument(format!("Invalid identifier key: {}", e)))? .into(); - let val = Reflect::get(js_members, &key).map_err(|_| { - WasmDppError::invalid_argument(format!("Invalid value at key '{}'", key_str)) - })?; - - let power: GroupMemberPower = serde_wasm_bindgen::from_value(val) + let power: GroupMemberPower = serde_wasm_bindgen::from_value(value) .map_err(|err| WasmDppError::serialization(err.to_string()))?; members.insert(identifier, power); @@ -63,22 +99,12 @@ pub fn js_members_to_map( #[wasm_bindgen(js_class = Group)] impl GroupWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "Group".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "Group".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - js_members: &JsValue, - required_power: GroupRequiredPower, + pub fn constructor( + members: GroupMembersMapJs, + #[wasm_bindgen(js_name = "requiredPower")] required_power: GroupRequiredPower, ) -> WasmDppResult { - let members = js_members_to_map(js_members)?; + let members = members_map_to_btree(&try_to_map(members, "members")?)?; Ok(GroupWasm(Group::V0(GroupV0 { members, @@ -87,38 +113,25 @@ impl GroupWasm { } #[wasm_bindgen(getter = "members")] - pub fn get_members(&self) -> WasmDppResult { + pub fn members(&self) -> WasmDppResult { let members = self.0.members(); - let js_members = Object::new(); - - for (k, v) in members { - Reflect::set( - &js_members, - &JsValue::from(k.to_string(Encoding::Base58)), - &JsValue::from(*v), - ) - .map_err(|err| { - let message = err.error_message(); - WasmDppError::generic(format!( - "unable to write group member '{}' into JS object: {}", - k.to_string(Encoding::Base58), - message - )) - })?; - } - - Ok(js_members.into()) + Ok(Map::from_entries(members.iter().map(|(k, v)| { + let key: JsValue = IdentifierWasm::from(*k).to_base58().into(); + let value = JsValue::from(*v); + (key, value) + })) + .into()) } #[wasm_bindgen(getter = "requiredPower")] - pub fn get_required_power(&self) -> GroupRequiredPower { + pub fn required_power(&self) -> GroupRequiredPower { self.0.required_power() } #[wasm_bindgen(setter = "members")] - pub fn set_members(&mut self, js_members: &JsValue) -> WasmDppResult<()> { - let members = js_members_to_map(js_members)?; + pub fn set_members(&mut self, members: GroupMembersMapJs) -> WasmDppResult<()> { + let members = members_map_to_btree(&try_to_map(members, "members")?)?; self.0.set_members(members); @@ -126,44 +139,47 @@ impl GroupWasm { } #[wasm_bindgen(setter = "requiredPower")] - pub fn set_required_power(&mut self, required_power: GroupRequiredPower) { + pub fn set_required_power( + &mut self, + #[wasm_bindgen(js_name = "requiredPower")] required_power: GroupRequiredPower, + ) { self.0.set_required_power(required_power); } #[wasm_bindgen(js_name = "setMemberRequiredPower")] pub fn set_member_required_power( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_member: &JsValue, - member_required_power: GroupRequiredPower, + member: IdentifierLikeJs, + #[wasm_bindgen(js_name = "memberRequiredPower")] member_required_power: GroupRequiredPower, ) -> WasmDppResult<()> { - let member: Identifier = IdentifierWasm::try_from(js_member)?.into(); - - self.0.set_member_power(member, member_required_power); - + self.0 + .set_member_power(member.try_into()?, member_required_power); Ok(()) } #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self) -> WasmDppResult { - serialization::to_json(&self.0) + pub fn to_json(&self) -> WasmDppResult { + serialization::to_json(&self.0).map(Into::into) } #[wasm_bindgen(js_name = "fromJSON")] - pub fn from_json(js_value: JsValue) -> WasmDppResult { - serialization::from_json(js_value).map(GroupWasm) + pub fn from_json(object: GroupJSONJs) -> WasmDppResult { + serialization::from_json(object.into()).map(GroupWasm) } #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self) -> WasmDppResult { + pub fn to_object(&self) -> WasmDppResult { // Use toJSON for serialization because it handles BTreeMap // correctly (Identifier becomes base58 string in human-readable mode). // This ensures all fields are automatically included when new versions are added. - serialization::to_json(&self.0) + serialization::to_json(&self.0).map(Into::into) } #[wasm_bindgen(js_name = "fromObject")] - pub fn from_object(js_value: JsValue) -> WasmDppResult { - serialization::from_object(js_value).map(GroupWasm) + pub fn from_object(value: GroupObjectJs) -> WasmDppResult { + serialization::from_object(value.into()).map(GroupWasm) } } + +impl_try_from_js_value!(GroupWasm, "Group"); +impl_wasm_type_info!(GroupWasm, Group); diff --git a/packages/wasm-dpp2/src/tokens/configuration/keeps_history_rules.rs b/packages/wasm-dpp2/src/tokens/configuration/keeps_history_rules.rs index 8578d708223..822f3fff3da 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/keeps_history_rules.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/keeps_history_rules.rs @@ -1,10 +1,49 @@ +use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use dpp::data_contract::associated_token::token_keeps_history_rules::TokenKeepsHistoryRules; use dpp::data_contract::associated_token::token_keeps_history_rules::accessors::v0::{ TokenKeepsHistoryRulesV0Getters, TokenKeepsHistoryRulesV0Setters, }; use dpp::data_contract::associated_token::token_keeps_history_rules::v0::TokenKeepsHistoryRulesV0; +use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct TokenKeepsHistoryRulesOptions { + #[serde(default)] + is_keeping_transfer_history: bool, + #[serde(default)] + is_keeping_freezing_history: bool, + #[serde(default)] + is_keeping_minting_history: bool, + #[serde(default)] + is_keeping_burning_history: bool, + #[serde(default)] + is_keeping_direct_pricing_history: bool, + #[serde(default)] + is_keeping_direct_purchase_history: bool, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface TokenKeepsHistoryRulesOptions { + isKeepingTransferHistory?: boolean; + isKeepingFreezingHistory?: boolean; + isKeepingMintingHistory?: boolean; + isKeepingBurningHistory?: boolean; + isKeepingDirectPricingHistory?: boolean; + isKeepingDirectPurchaseHistory?: boolean; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenKeepsHistoryRulesOptions")] + pub type TokenKeepsHistoryRulesOptionsJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "TokenKeepsHistoryRules")] pub struct TokenKeepsHistoryRulesWasm(TokenKeepsHistoryRules); @@ -23,94 +62,95 @@ impl From for TokenKeepsHistoryRulesWasm { #[wasm_bindgen(js_class = TokenKeepsHistoryRules)] impl TokenKeepsHistoryRulesWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenKeepsHistoryRules".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenKeepsHistoryRules".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - keeps_transfer_history: bool, - keeps_freezing_history: bool, - keeps_minting_history: bool, - keeps_burning_history: bool, - keeps_direct_pricing_history: bool, - keeps_direct_purchase_history: bool, - ) -> TokenKeepsHistoryRulesWasm { - TokenKeepsHistoryRulesWasm(TokenKeepsHistoryRules::V0(TokenKeepsHistoryRulesV0 { - keeps_transfer_history, - keeps_freezing_history, - keeps_minting_history, - keeps_burning_history, - keeps_direct_pricing_history, - keeps_direct_purchase_history, - })) - } - - #[wasm_bindgen(getter = "keepsTransferHistory")] - pub fn get_keeps_transfer_history(&self) -> bool { + pub fn constructor( + options: TokenKeepsHistoryRulesOptionsJs, + ) -> WasmDppResult { + let opts: TokenKeepsHistoryRulesOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + + Ok(TokenKeepsHistoryRulesWasm(TokenKeepsHistoryRules::V0( + TokenKeepsHistoryRulesV0 { + keeps_transfer_history: opts.is_keeping_transfer_history, + keeps_freezing_history: opts.is_keeping_freezing_history, + keeps_minting_history: opts.is_keeping_minting_history, + keeps_burning_history: opts.is_keeping_burning_history, + keeps_direct_pricing_history: opts.is_keeping_direct_pricing_history, + keeps_direct_purchase_history: opts.is_keeping_direct_purchase_history, + }, + ))) + } + + #[wasm_bindgen(getter = "isKeepingTransferHistory")] + pub fn is_keeping_transfer_history(&self) -> bool { self.0.keeps_transfer_history() } - #[wasm_bindgen(getter = "keepsFreezingHistory")] - pub fn get_keeps_freezing_history(&self) -> bool { + #[wasm_bindgen(getter = "isKeepingFreezingHistory")] + pub fn is_keeping_freezing_history(&self) -> bool { self.0.keeps_freezing_history() } - #[wasm_bindgen(getter = "keepsMintingHistory")] - pub fn get_keeps_minting_history(&self) -> bool { + #[wasm_bindgen(getter = "isKeepingMintingHistory")] + pub fn is_keeping_minting_history(&self) -> bool { self.0.keeps_minting_history() } - #[wasm_bindgen(getter = "keepsBurningHistory")] - pub fn get_keeps_burning_history(&self) -> bool { + #[wasm_bindgen(getter = "isKeepingBurningHistory")] + pub fn is_keeping_burning_history(&self) -> bool { self.0.keeps_burning_history() } - #[wasm_bindgen(getter = "keepsDirectPricingHistory")] - pub fn get_keeps_direct_pricing_history(&self) -> bool { + #[wasm_bindgen(getter = "isKeepingDirectPricingHistory")] + pub fn is_keeping_direct_pricing_history(&self) -> bool { self.0.keeps_direct_pricing_history() } - #[wasm_bindgen(getter = "keepsDirectPurchaseHistory")] - pub fn get_keeps_direct_purchase_history(&self) -> bool { + #[wasm_bindgen(getter = "isKeepingDirectPurchaseHistory")] + pub fn is_keeping_direct_purchase_history(&self) -> bool { self.0.keeps_direct_purchase_history() } - #[wasm_bindgen(setter = "keepsTransferHistory")] - pub fn set_keeps_transfer_history(&mut self, keeps_transfer_history: bool) { - self.0.set_keeps_transfer_history(keeps_transfer_history); + #[wasm_bindgen(setter = "isKeepingTransferHistory")] + pub fn set_is_keeping_transfer_history(&mut self, is_keeping_transfer_history: bool) { + self.0 + .set_keeps_transfer_history(is_keeping_transfer_history); } - #[wasm_bindgen(setter = "keepsFreezingHistory")] - pub fn set_keeps_freezing_history(&mut self, keeps_freezing_history: bool) { - self.0.set_keeps_freezing_history(keeps_freezing_history); + #[wasm_bindgen(setter = "isKeepingFreezingHistory")] + pub fn set_is_keeping_freezing_history(&mut self, is_keeping_freezing_history: bool) { + self.0 + .set_keeps_freezing_history(is_keeping_freezing_history); } - #[wasm_bindgen(setter = "keepsMintingHistory")] - pub fn set_keeps_minting_history(&mut self, keeps_minting_history: bool) { - self.0.set_keeps_minting_history(keeps_minting_history); + #[wasm_bindgen(setter = "isKeepingMintingHistory")] + pub fn set_is_keeping_minting_history(&mut self, is_keeping_minting_history: bool) { + self.0.set_keeps_minting_history(is_keeping_minting_history); } - #[wasm_bindgen(setter = "keepsBurningHistory")] - pub fn set_keeps_burning_history(&mut self, keeps_burning_history: bool) { - self.0.set_keeps_burning_history(keeps_burning_history); + #[wasm_bindgen(setter = "isKeepingBurningHistory")] + pub fn set_is_keeping_burning_history(&mut self, is_keeping_burning_history: bool) { + self.0.set_keeps_burning_history(is_keeping_burning_history); } - #[wasm_bindgen(setter = "keepsDirectPricingHistory")] - pub fn set_keeps_direct_pricing_history(&mut self, keeps_direct_pricing_history: bool) { + #[wasm_bindgen(setter = "isKeepingDirectPricingHistory")] + pub fn set_is_keeping_direct_pricing_history( + &mut self, + is_keeping_direct_pricing_history: bool, + ) { self.0 - .set_keeps_direct_pricing_history(keeps_direct_pricing_history); + .set_keeps_direct_pricing_history(is_keeping_direct_pricing_history); } - #[wasm_bindgen(setter = "keepsDirectPurchaseHistory")] - pub fn set_keeps_direct_purchase_history(&mut self, keeps_direct_purchase_history: bool) { + #[wasm_bindgen(setter = "isKeepingDirectPurchaseHistory")] + pub fn set_is_keeping_direct_purchase_history( + &mut self, + is_keeping_direct_purchase_history: bool, + ) { self.0 - .set_keeps_direct_purchase_history(keeps_direct_purchase_history); + .set_keeps_direct_purchase_history(is_keeping_direct_purchase_history); } } + +impl_try_from_js_value!(TokenKeepsHistoryRulesWasm, "TokenKeepsHistoryRules"); +impl_wasm_type_info!(TokenKeepsHistoryRulesWasm, TokenKeepsHistoryRules); diff --git a/packages/wasm-dpp2/src/tokens/configuration/localization.rs b/packages/wasm-dpp2/src/tokens/configuration/localization.rs index f5f2715c627..1a6892cc3f1 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/localization.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/localization.rs @@ -1,4 +1,5 @@ -use crate::error::WasmDppResult; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::impl_wasm_type_info; use crate::serialization; use crate::utils::IntoWasm; use dpp::data_contract::associated_token::token_configuration_localization::TokenConfigurationLocalization; @@ -9,8 +10,40 @@ use dpp::data_contract::associated_token::token_configuration_localization::v0:: use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * TokenConfigurationLocalization serialized as a plain object. + */ +export interface TokenConfigurationLocalizationObject { + $formatVersion: string; + shouldCapitalize: boolean; + singularForm: string; + pluralForm: string; +} + +/** + * TokenConfigurationLocalization serialized as JSON. + */ +export interface TokenConfigurationLocalizationJSON { + $formatVersion: string; + shouldCapitalize: boolean; + singularForm: string; + pluralForm: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenConfigurationLocalizationObject")] + pub type TokenConfigurationLocalizationObjectJs; + + #[wasm_bindgen(typescript_type = "TokenConfigurationLocalizationJSON")] + pub type TokenConfigurationLocalizationJSONJs; +} + #[derive(Clone, Debug, PartialEq)] -#[wasm_bindgen(js_name = TokenConfigurationLocalization)] +#[wasm_bindgen(js_name = "TokenConfigurationLocalization")] pub struct TokenConfigurationLocalizationWasm(TokenConfigurationLocalization); impl From for TokenConfigurationLocalizationWasm { @@ -27,21 +60,11 @@ impl From for TokenConfigurationLocalization #[wasm_bindgen(js_class = TokenConfigurationLocalization)] impl TokenConfigurationLocalizationWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenConfigurationLocalization".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenConfigurationLocalization".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - should_capitalize: bool, - singular_form: String, - plural_form: String, + pub fn constructor( + #[wasm_bindgen(js_name = "shouldCapitalize")] should_capitalize: bool, + #[wasm_bindgen(js_name = "singularForm")] singular_form: String, + #[wasm_bindgen(js_name = "pluralForm")] plural_form: String, ) -> TokenConfigurationLocalizationWasm { TokenConfigurationLocalizationWasm(TokenConfigurationLocalization::V0( TokenConfigurationLocalizationV0 { @@ -53,17 +76,17 @@ impl TokenConfigurationLocalizationWasm { } #[wasm_bindgen(getter = "shouldCapitalize")] - pub fn get_should_capitalize(&self) -> bool { + pub fn should_capitalize(&self) -> bool { self.0.should_capitalize() } #[wasm_bindgen(getter = "pluralForm")] - pub fn get_plural_form(&self) -> String { + pub fn plural_form(&self) -> String { self.0.plural_form().to_string() } #[wasm_bindgen(getter = "singularForm")] - pub fn get_singular_form(&self) -> String { + pub fn singular_form(&self) -> String { self.0.singular_form().to_string() } @@ -83,40 +106,47 @@ impl TokenConfigurationLocalizationWasm { } #[wasm_bindgen(js_name = "toJSON")] - pub fn to_json(&self) -> WasmDppResult { - serialization::to_json(&self.0) + pub fn to_json(&self) -> WasmDppResult { + serialization::to_json(&self.0).map(Into::into) } #[wasm_bindgen(js_name = "fromJSON")] - pub fn from_json(js_value: JsValue) -> WasmDppResult { - serialization::from_json(js_value).map(TokenConfigurationLocalizationWasm) + pub fn from_json( + value: TokenConfigurationLocalizationJSONJs, + ) -> WasmDppResult { + serialization::from_json(value.into()).map(TokenConfigurationLocalizationWasm) } #[wasm_bindgen(js_name = "toObject")] - pub fn to_object(&self) -> WasmDppResult { - serialization::to_object(&self.0) + pub fn to_object(&self) -> WasmDppResult { + serialization::to_object(&self.0).map(Into::into) } #[wasm_bindgen(js_name = "fromObject")] - pub fn from_object(js_value: JsValue) -> WasmDppResult { - serialization::from_object(js_value).map(TokenConfigurationLocalizationWasm) + pub fn from_object( + value: TokenConfigurationLocalizationObjectJs, + ) -> WasmDppResult { + serialization::from_object(value.into()).map(TokenConfigurationLocalizationWasm) } } -impl TokenConfigurationLocalizationWasm { - pub(crate) fn from_js_value( - js_value: &JsValue, - ) -> WasmDppResult { +impl TryFrom<&JsValue> for TokenConfigurationLocalizationWasm { + type Error = WasmDppError; + + fn try_from(value: &JsValue) -> Result { // First, check if it's already a WASM wrapper if let Ok(wasm_localization) = - js_value.to_wasm::("TokenConfigurationLocalization") + value.to_wasm::("TokenConfigurationLocalization") { - return Ok(TokenConfigurationLocalization::from( - wasm_localization.clone(), - )); + return Ok(wasm_localization.clone()); } // Deserialize as a versioned object (with $format_version) - serialization::from_object(js_value.clone()) + serialization::from_object(value.clone()).map(TokenConfigurationLocalizationWasm) } } + +impl_wasm_type_info!( + TokenConfigurationLocalizationWasm, + TokenConfigurationLocalization +); diff --git a/packages/wasm-dpp2/src/tokens/configuration/marketplace_rules.rs b/packages/wasm-dpp2/src/tokens/configuration/marketplace_rules.rs index 91d7dadf676..3827ab0956a 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/marketplace_rules.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/marketplace_rules.rs @@ -1,3 +1,5 @@ +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::tokens::configuration::change_control_rules::ChangeControlRulesWasm; use crate::tokens::configuration::trade_mode::TokenTradeModeWasm; use dpp::data_contract::associated_token::token_marketplace_rules::TokenMarketplaceRules; @@ -25,19 +27,10 @@ impl From for TokenMarketplaceRules { #[wasm_bindgen(js_class = TokenMarketplaceRules)] impl TokenMarketplaceRulesWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenMarketplaceRules".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenMarketplaceRules".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - trade_mode: &TokenTradeModeWasm, + pub fn constructor( + #[wasm_bindgen(js_name = "tradeMode")] trade_mode: &TokenTradeModeWasm, + #[wasm_bindgen(js_name = "tradeModeChangeRules")] trade_mode_change_rules: &ChangeControlRulesWasm, ) -> TokenMarketplaceRulesWasm { TokenMarketplaceRulesWasm(TokenMarketplaceRules::V0({ @@ -72,3 +65,6 @@ impl TokenMarketplaceRulesWasm { .set_trade_mode_change_rules(trade_mode_change_rules.clone().into()); } } + +impl_try_from_js_value!(TokenMarketplaceRulesWasm, "TokenMarketplaceRules"); +impl_wasm_type_info!(TokenMarketplaceRulesWasm, TokenMarketplaceRules); diff --git a/packages/wasm-dpp2/src/tokens/configuration/perpetual_distribution.rs b/packages/wasm-dpp2/src/tokens/configuration/perpetual_distribution.rs index e983b024c68..7de4c404fd7 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/perpetual_distribution.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/perpetual_distribution.rs @@ -1,3 +1,5 @@ +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::tokens::configuration::distribution_recipient::TokenDistributionRecipientWasm; use crate::tokens::configuration::reward_distribution_type::RewardDistributionTypeWasm; use dpp::data_contract::associated_token::token_perpetual_distribution::TokenPerpetualDistribution; @@ -23,18 +25,9 @@ impl From for TokenPerpetualDistributionWasm { #[wasm_bindgen(js_class = TokenPerpetualDistribution)] impl TokenPerpetualDistributionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenPerpetualDistribution".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenPerpetualDistribution".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( + pub fn constructor( + #[wasm_bindgen(js_name = "distributionType")] distribution_type: &RewardDistributionTypeWasm, recipient: &TokenDistributionRecipientWasm, ) -> Self { @@ -57,14 +50,25 @@ impl TokenPerpetualDistributionWasm { } #[wasm_bindgen(setter = distributionType)] - pub fn set_distribution_type(&mut self, distribution_type: &RewardDistributionTypeWasm) { + pub fn set_distribution_type( + &mut self, + #[wasm_bindgen(js_name = "distributionType")] + distribution_type: &RewardDistributionTypeWasm, + ) { self.0 .set_distribution_type(distribution_type.clone().into()); } #[wasm_bindgen(setter = distributionRecipient)] - pub fn set_recipient(&mut self, distribution_recipient: &TokenDistributionRecipientWasm) { + pub fn set_recipient( + &mut self, + #[wasm_bindgen(js_name = "distributionRecipient")] + distribution_recipient: &TokenDistributionRecipientWasm, + ) { self.0 .set_distribution_recipient(distribution_recipient.clone().into()); } } + +impl_try_from_js_value!(TokenPerpetualDistributionWasm, "TokenPerpetualDistribution"); +impl_wasm_type_info!(TokenPerpetualDistributionWasm, TokenPerpetualDistribution); diff --git a/packages/wasm-dpp2/src/tokens/configuration/pre_programmed_distribution.rs b/packages/wasm-dpp2/src/tokens/configuration/pre_programmed_distribution.rs index b0f435e4ac3..8bc14f23931 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/pre_programmed_distribution.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/pre_programmed_distribution.rs @@ -1,16 +1,44 @@ use crate::error::{WasmDppError, WasmDppResult}; use crate::identifier::IdentifierWasm; -use crate::utils::{JsValueExt, try_to_u64}; +use crate::impl_from_for_extern_type; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; +use crate::utils::{try_to_map, try_to_u64}; use dpp::balances::credits::TokenAmount; use dpp::data_contract::associated_token::token_pre_programmed_distribution::TokenPreProgrammedDistribution; use dpp::data_contract::associated_token::token_pre_programmed_distribution::accessors::v0::TokenPreProgrammedDistributionV0Methods; use dpp::data_contract::associated_token::token_pre_programmed_distribution::v0::TokenPreProgrammedDistributionV0; use dpp::prelude::{Identifier, TimestampMillis}; -use js_sys::{BigInt, Object, Reflect}; +use js_sys::{BigInt, Map}; use std::collections::BTreeMap; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Distribution amounts per identity: base58 Identifier string -> token amount (bigint). + */ +export type DistributionAmountsMap = Map; + +/** + * Pre-programmed distributions: timestamp (string) -> distribution amounts map. + */ +export type PreProgrammedDistributionsMap = Map; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "PreProgrammedDistributionsMap")] + pub type PreProgrammedDistributionsMapJs; + + #[wasm_bindgen(typescript_type = "DistributionAmountsMap")] + pub type DistributionAmountsMapJs; +} + +impl_from_for_extern_type!(PreProgrammedDistributionsMapJs, Map); +impl_from_for_extern_type!(DistributionAmountsMapJs, Map); + #[derive(Clone, PartialEq, Debug)] #[wasm_bindgen(js_name = "TokenPreProgrammedDistribution")] pub struct TokenPreProgrammedDistributionWasm(TokenPreProgrammedDistribution); @@ -27,15 +55,46 @@ impl From for TokenPreProgrammedDistributionWasm } } -pub fn js_distributions_to_distributions( - js_distributions: &JsValue, -) -> WasmDppResult>> { - let distributions_object = Object::from(js_distributions.clone()); - let distributions_keys = Object::keys(&distributions_object); +fn distribution_amounts_from_map( + amounts_map: &Map, +) -> WasmDppResult> { + let mut amounts = BTreeMap::new(); + + for entry in amounts_map.entries().into_iter() { + let entry = entry.map_err(|e| { + WasmDppError::invalid_argument(format!("Failed to iterate map entries: {:?}", e)) + })?; + + let entry_array = js_sys::Array::from(&entry); + let key = entry_array.get(0); + let value = entry_array.get(1); + + let identifier: Identifier = IdentifierWasm::try_from(key) + .map_err(|e| WasmDppError::invalid_argument(format!("Invalid identifier: {}", e)))? + .into(); + let token_amount = try_to_u64(&value, "tokenAmount")?; + + amounts.insert(identifier, token_amount); + } + + Ok(amounts) +} + +pub fn distributions_from_map( + distributions_map: &Map, +) -> WasmDppResult>> { let mut distributions = BTreeMap::new(); - for key in distributions_keys.iter() { + for entry in distributions_map.entries().into_iter() { + let entry = entry.map_err(|e| { + WasmDppError::invalid_argument(format!("Failed to iterate map entries: {:?}", e)) + })?; + + let entry_array = js_sys::Array::from(&entry); + let key = entry_array.get(0); + let value = entry_array.get(1); + let timestamp_str = key.as_string().ok_or_else(|| { WasmDppError::invalid_argument("Cannot read timestamp in distribution rules") })?; @@ -47,105 +106,84 @@ pub fn js_distributions_to_distributions( )) })?; - let identifiers_js = Reflect::get(&distributions_object, &key).map_err(|err| { - let message = err.error_message(); - WasmDppError::invalid_argument(format!( - "unable to access distribution entry for timestamp '{}': {}", - timestamp_str, message - )) - })?; - let identifiers_object = Object::from(identifiers_js); - let identifiers_keys = Object::keys(&identifiers_object); + let inner_map = try_to_map(value, "distribution amounts")?; + let amounts = distribution_amounts_from_map(&inner_map)?; - let mut ids = BTreeMap::new(); + distributions.insert(timestamp, amounts); + } - for id_key in identifiers_keys.iter() { - let identifier = IdentifierWasm::try_from(id_key.clone())?.into(); + Ok(distributions) +} - let amount_js = Reflect::get(&identifiers_object, &id_key).map_err(|err| { - let message = err.error_message(); - WasmDppError::invalid_argument(format!( - "unable to access distribution amount for identity '{}' at '{}': {}", - identifier, timestamp, message - )) - })?; +fn distribution_amounts_to_map( + amounts: &BTreeMap, +) -> DistributionAmountsMapJs { + let js_map = Map::new(); + + for (identifier, amount) in amounts { + let identifier_wasm = IdentifierWasm::from(*identifier); + js_map.set( + &identifier_wasm.to_base58().into(), + &BigInt::from(*amount).into(), + ); + } - let token_amount = try_to_u64(amount_js) - .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; + js_map.into() +} - ids.insert(identifier, token_amount); - } +fn distributions_to_map( + distributions: &BTreeMap>, +) -> PreProgrammedDistributionsMapJs { + let js_map = Map::new(); - distributions.insert(timestamp, ids); + for (timestamp, amounts) in distributions { + let amounts_map = distribution_amounts_to_map(amounts); + js_map.set(&JsValue::from(timestamp.to_string()), &amounts_map.into()); } - Ok(distributions) + js_map.into() } #[wasm_bindgen(js_class = TokenPreProgrammedDistribution)] impl TokenPreProgrammedDistributionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenPreProgrammedDistribution".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenPreProgrammedDistribution".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(js_distributions: &JsValue) -> WasmDppResult { - let distributions = js_distributions_to_distributions(js_distributions)?; + pub fn constructor( + distributions: PreProgrammedDistributionsMapJs, + ) -> WasmDppResult { + let distributions_map = + distributions_from_map(&try_to_map(distributions, "distributions")?)?; Ok(TokenPreProgrammedDistributionWasm( - TokenPreProgrammedDistribution::V0(TokenPreProgrammedDistributionV0 { distributions }), + TokenPreProgrammedDistribution::V0(TokenPreProgrammedDistributionV0 { + distributions: distributions_map, + }), )) } #[wasm_bindgen(getter = "distributions")] - pub fn get_distributions(&self) -> WasmDppResult { - let obj = Object::new(); - - for (key, value) in self.0.distributions() { - let identifiers_obj = Object::new(); - // &BigInt::from(key.clone()).into() - - for (identifiers_key, identifiers_value) in value { - Reflect::set( - &identifiers_obj, - &IdentifierWasm::from(*identifiers_key).to_base58().into(), - &BigInt::from(*identifiers_value).into(), - ) - .map_err(|err| { - let message = err.error_message(); - WasmDppError::generic(format!( - "unable to serialize distribution amount for identity '{}' at '{}': {}", - identifiers_key, key, message - )) - })?; - } - - Reflect::set(&obj, &key.to_string().into(), &identifiers_obj.into()).map_err( - |err| { - let message = err.error_message(); - WasmDppError::generic(format!( - "unable to serialize distribution for timestamp '{}': {}", - key, message - )) - }, - )?; - } - - Ok(obj.into()) + pub fn distributions(&self) -> PreProgrammedDistributionsMapJs { + distributions_to_map(self.0.distributions()) } #[wasm_bindgen(setter = "distributions")] - pub fn set_distributions(&mut self, js_distributions: &JsValue) -> WasmDppResult<()> { - let distributions = js_distributions_to_distributions(js_distributions)?; + pub fn set_distributions( + &mut self, + distributions: PreProgrammedDistributionsMapJs, + ) -> WasmDppResult<()> { + let distributions_map = + distributions_from_map(&try_to_map(distributions, "distributions")?)?; - self.0.set_distributions(distributions); + self.0.set_distributions(distributions_map); Ok(()) } } + +impl_try_from_js_value!( + TokenPreProgrammedDistributionWasm, + "TokenPreProgrammedDistribution" +); +impl_wasm_type_info!( + TokenPreProgrammedDistributionWasm, + TokenPreProgrammedDistribution +); diff --git a/packages/wasm-dpp2/src/tokens/configuration/reward_distribution_type.rs b/packages/wasm-dpp2/src/tokens/configuration/reward_distribution_type.rs index cfd6091e4e2..7a8046b8c33 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/reward_distribution_type.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/reward_distribution_type.rs @@ -1,9 +1,27 @@ +use crate::impl_from_for_extern_type; +use crate::impl_wasm_type_info; +use crate::tokens::configuration::distribution_function::DistributionFunctionWasm; use dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_type::RewardDistributionType; use dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_type::RewardDistributionType::{BlockBasedDistribution, EpochBasedDistribution, TimeBasedDistribution}; use dpp::prelude::{BlockHeightInterval, EpochInterval, TimestampMillisInterval}; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; -use crate::tokens::configuration::distribution_function::DistributionFunctionWasm; + +#[wasm_bindgen(typescript_custom_section)] +const REWARD_DISTRIBUTION_TS: &str = r#" +/** + * Union type for reward distribution variants. + */ +export type RewardDistributionValue = + | BlockBasedDistribution + | TimeBasedDistribution + | EpochBasedDistribution; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "RewardDistributionValue")] + pub type RewardDistributionValueJs; +} #[derive(Clone, Debug, PartialEq)] #[wasm_bindgen(js_name = "RewardDistributionType")] @@ -23,16 +41,6 @@ impl From for RewardDistributionType { #[wasm_bindgen(js_class = RewardDistributionType)] impl RewardDistributionTypeWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "RewardDistributionType".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "RewardDistributionType".to_string() - } - #[wasm_bindgen(js_name = "BlockBasedDistribution")] pub fn block_based_distribution( interval: BlockHeightInterval, @@ -66,26 +74,29 @@ impl RewardDistributionTypeWasm { }) } - #[wasm_bindgen(js_name = "getDistribution")] - pub fn get_distribution(&self) -> JsValue { + #[wasm_bindgen(getter = "distribution")] + pub fn distribution(&self) -> RewardDistributionValueJs { match self.0.clone() { RewardDistributionType::BlockBasedDistribution { interval, function } => { - JsValue::from(BlockBasedDistributionWasm { + BlockBasedDistributionWasm { interval, function: function.clone().into(), - }) + } + .into() } RewardDistributionType::TimeBasedDistribution { interval, function } => { - JsValue::from(TimeBasedDistributionWasm { + TimeBasedDistributionWasm { interval, function: function.clone().into(), - }) + } + .into() } RewardDistributionType::EpochBasedDistribution { interval, function } => { - JsValue::from(EpochBasedDistributionWasm { + EpochBasedDistributionWasm { interval, function: function.clone().into(), - }) + } + .into() } } } @@ -114,18 +125,8 @@ pub struct EpochBasedDistributionWasm { #[wasm_bindgen(js_class = BlockBasedDistribution)] impl BlockBasedDistributionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "BlockBasedDistribution".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "BlockBasedDistribution".to_string() - } - #[wasm_bindgen(getter = "function")] - pub fn get_function(&self) -> DistributionFunctionWasm { + pub fn function(&self) -> DistributionFunctionWasm { self.function.clone() } @@ -137,18 +138,8 @@ impl BlockBasedDistributionWasm { #[wasm_bindgen(js_class = TimeBasedDistribution)] impl TimeBasedDistributionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TimeBasedDistribution".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TimeBasedDistribution".to_string() - } - #[wasm_bindgen(getter = "function")] - pub fn get_function(&self) -> DistributionFunctionWasm { + pub fn function(&self) -> DistributionFunctionWasm { self.function.clone() } @@ -160,18 +151,8 @@ impl TimeBasedDistributionWasm { #[wasm_bindgen(js_class = EpochBasedDistribution)] impl EpochBasedDistributionWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "EpochBasedDistribution".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "EpochBasedDistribution".to_string() - } - #[wasm_bindgen(getter = "function")] - pub fn get_function(&self) -> DistributionFunctionWasm { + pub fn function(&self) -> DistributionFunctionWasm { self.function.clone() } @@ -180,3 +161,15 @@ impl EpochBasedDistributionWasm { self.function = function.clone() } } + +impl_wasm_type_info!(RewardDistributionTypeWasm, RewardDistributionType); +impl_wasm_type_info!(BlockBasedDistributionWasm, BlockBasedDistribution); +impl_wasm_type_info!(TimeBasedDistributionWasm, TimeBasedDistribution); +impl_wasm_type_info!(EpochBasedDistributionWasm, EpochBasedDistribution); + +impl_from_for_extern_type!( + RewardDistributionValueJs, + BlockBasedDistributionWasm, + TimeBasedDistributionWasm, + EpochBasedDistributionWasm, +); diff --git a/packages/wasm-dpp2/src/tokens/configuration/token_configuration.rs b/packages/wasm-dpp2/src/tokens/configuration/token_configuration.rs index 1849a4f2332..a6bab734c88 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/token_configuration.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/token_configuration.rs @@ -1,11 +1,14 @@ -use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::error::{WasmDppError, WasmDppResult}; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::tokens::configuration::authorized_action_takers::AuthorizedActionTakersWasm; use crate::tokens::configuration::change_control_rules::ChangeControlRulesWasm; use crate::tokens::configuration::configuration_convention::TokenConfigurationConventionWasm; use crate::tokens::configuration::distribution_rules::TokenDistributionRulesWasm; use crate::tokens::configuration::keeps_history_rules::TokenKeepsHistoryRulesWasm; use crate::tokens::configuration::marketplace_rules::TokenMarketplaceRulesWasm; +use crate::utils::{try_from_options, try_to_u64}; use dpp::balances::credits::TokenAmount; use dpp::data_contract::associated_token::token_configuration::accessors::v0::{ TokenConfigurationV0Getters, TokenConfigurationV0Setters, @@ -14,8 +17,57 @@ use dpp::data_contract::associated_token::token_configuration::v0::TokenConfigur use dpp::data_contract::{GroupContractPosition, TokenConfiguration, TokenContractPosition}; use dpp::prelude::Identifier; use dpp::tokens::calculate_token_id; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct TokenConfigurationOptions { + base_supply: TokenAmount, + #[serde(default)] + max_supply: Option, + #[serde(default)] + is_started_as_paused: bool, + #[serde(default)] + is_allowed_transfer_to_frozen_balance: bool, + #[serde(default)] + main_control_group: Option, + #[serde(default)] + description: Option, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface TokenConfigurationOptions { + conventions: TokenConfigurationConvention; + conventionsChangeRules: ChangeControlRules; + baseSupply: bigint; + maxSupply?: bigint; + keepsHistory: TokenKeepsHistoryRules; + isStartedAsPaused?: boolean; + isAllowedTransferToFrozenBalance?: boolean; + maxSupplyChangeRules: ChangeControlRules; + distributionRules: TokenDistributionRules; + marketplaceRules: TokenMarketplaceRules; + manualMintingRules: ChangeControlRules; + manualBurningRules: ChangeControlRules; + freezeRules: ChangeControlRules; + unfreezeRules: ChangeControlRules; + destroyFrozenFundsRules: ChangeControlRules; + emergencyActionRules: ChangeControlRules; + mainControlGroup?: number; + mainControlGroupCanBeModified: AuthorizedActionTakers; + description?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenConfigurationOptions")] + pub type TokenConfigurationOptionsJs; +} + #[derive(Clone, PartialEq, Debug)] #[wasm_bindgen(js_name = "TokenConfiguration")] pub struct TokenConfigurationWasm(TokenConfiguration); @@ -32,158 +84,162 @@ impl From for TokenConfiguration { } } +impl_try_from_js_value!(TokenConfigurationWasm, "TokenConfiguration"); + #[wasm_bindgen(js_class = TokenConfiguration)] impl TokenConfigurationWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenConfiguration".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenConfiguration".to_string() - } - #[wasm_bindgen(constructor)] - #[allow(clippy::too_many_arguments)] - pub fn new( - conventions: &TokenConfigurationConventionWasm, - conventions_change_rules: &ChangeControlRulesWasm, - base_supply: TokenAmount, - max_supply: Option, - keeps_history: &TokenKeepsHistoryRulesWasm, - start_as_paused: bool, - allow_transfer_to_frozen_balance: bool, - max_supply_change_rules: &ChangeControlRulesWasm, - distribution_rules: &TokenDistributionRulesWasm, - marketplace_rules: &TokenMarketplaceRulesWasm, - manual_minting_rules: &ChangeControlRulesWasm, - manual_burning_rules: &ChangeControlRulesWasm, - freeze_rules: &ChangeControlRulesWasm, - unfreeze_rules: &ChangeControlRulesWasm, - destroy_frozen_funds_rules: &ChangeControlRulesWasm, - emergency_action_rules: &ChangeControlRulesWasm, - main_control_group: Option, - main_control_group_can_be_modified: &AuthorizedActionTakersWasm, - description: Option, - ) -> TokenConfigurationWasm { - TokenConfigurationWasm(TokenConfiguration::V0(TokenConfigurationV0 { - conventions: conventions.clone().into(), - conventions_change_rules: conventions_change_rules.clone().into(), - base_supply, - max_supply, - keeps_history: keeps_history.clone().into(), - start_as_paused, - allow_transfer_to_frozen_balance, - max_supply_change_rules: max_supply_change_rules.clone().into(), - distribution_rules: distribution_rules.clone().into(), - marketplace_rules: marketplace_rules.clone().into(), - manual_minting_rules: manual_minting_rules.clone().into(), - manual_burning_rules: manual_burning_rules.clone().into(), - freeze_rules: freeze_rules.clone().into(), - unfreeze_rules: unfreeze_rules.clone().into(), - destroy_frozen_funds_rules: destroy_frozen_funds_rules.clone().into(), - emergency_action_rules: emergency_action_rules.clone().into(), - main_control_group, - main_control_group_can_be_modified: main_control_group_can_be_modified.clone().into(), - description, - })) + pub fn constructor( + options: TokenConfigurationOptionsJs, + ) -> WasmDppResult { + // Extract complex types first (borrows &options) + let conventions: TokenConfigurationConventionWasm = + try_from_options(&options, "conventions")?; + let conventions_change_rules: ChangeControlRulesWasm = + try_from_options(&options, "conventionsChangeRules")?; + let keeps_history: TokenKeepsHistoryRulesWasm = try_from_options(&options, "keepsHistory")?; + let max_supply_change_rules: ChangeControlRulesWasm = + try_from_options(&options, "maxSupplyChangeRules")?; + let distribution_rules: TokenDistributionRulesWasm = + try_from_options(&options, "distributionRules")?; + let marketplace_rules: TokenMarketplaceRulesWasm = + try_from_options(&options, "marketplaceRules")?; + let manual_minting_rules: ChangeControlRulesWasm = + try_from_options(&options, "manualMintingRules")?; + let manual_burning_rules: ChangeControlRulesWasm = + try_from_options(&options, "manualBurningRules")?; + let freeze_rules: ChangeControlRulesWasm = try_from_options(&options, "freezeRules")?; + let unfreeze_rules: ChangeControlRulesWasm = try_from_options(&options, "unfreezeRules")?; + let destroy_frozen_funds_rules: ChangeControlRulesWasm = + try_from_options(&options, "destroyFrozenFundsRules")?; + let emergency_action_rules: ChangeControlRulesWasm = + try_from_options(&options, "emergencyActionRules")?; + let main_control_group_can_be_modified: AuthorizedActionTakersWasm = + try_from_options(&options, "mainControlGroupCanBeModified")?; + + // Deserialize primitive fields via serde last (consumes options) + let opts: TokenConfigurationOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; + + Ok(TokenConfigurationWasm(TokenConfiguration::V0( + TokenConfigurationV0 { + conventions: conventions.into(), + conventions_change_rules: conventions_change_rules.into(), + base_supply: opts.base_supply, + max_supply: opts.max_supply, + keeps_history: keeps_history.into(), + start_as_paused: opts.is_started_as_paused, + allow_transfer_to_frozen_balance: opts.is_allowed_transfer_to_frozen_balance, + max_supply_change_rules: max_supply_change_rules.into(), + distribution_rules: distribution_rules.into(), + marketplace_rules: marketplace_rules.into(), + manual_minting_rules: manual_minting_rules.into(), + manual_burning_rules: manual_burning_rules.into(), + freeze_rules: freeze_rules.into(), + unfreeze_rules: unfreeze_rules.into(), + destroy_frozen_funds_rules: destroy_frozen_funds_rules.into(), + emergency_action_rules: emergency_action_rules.into(), + main_control_group: opts.main_control_group, + main_control_group_can_be_modified: main_control_group_can_be_modified.into(), + description: opts.description, + }, + ))) } #[wasm_bindgen(getter = "conventions")] - pub fn get_conventions(&self) -> TokenConfigurationConventionWasm { + pub fn conventions(&self) -> TokenConfigurationConventionWasm { self.0.conventions().clone().into() } #[wasm_bindgen(getter = "conventionsChangeRules")] - pub fn get_conventions_change_rules(&self) -> ChangeControlRulesWasm { + pub fn conventions_change_rules(&self) -> ChangeControlRulesWasm { self.0.conventions_change_rules().clone().into() } #[wasm_bindgen(getter = "baseSupply")] - pub fn get_base_supply(&self) -> TokenAmount { + pub fn base_supply(&self) -> TokenAmount { self.0.base_supply() } #[wasm_bindgen(getter = "keepsHistory")] - pub fn get_keeps_history(&self) -> TokenKeepsHistoryRulesWasm { + pub fn keeps_history(&self) -> TokenKeepsHistoryRulesWasm { (*self.0.keeps_history()).into() } - #[wasm_bindgen(getter = "startAsPaused")] - pub fn get_start_as_paused(&self) -> bool { + #[wasm_bindgen(getter = "isStartedAsPaused")] + pub fn is_started_as_paused(&self) -> bool { self.0.start_as_paused() } #[wasm_bindgen(getter = "isAllowedTransferToFrozenBalance")] - pub fn get_is_allowed_transfer_to_frozen_balance(&self) -> bool { + pub fn is_allowed_transfer_to_frozen_balance(&self) -> bool { self.0.is_allowed_transfer_to_frozen_balance() } #[wasm_bindgen(getter = "maxSupply")] - pub fn get_max_supply(&self) -> Option { + pub fn max_supply(&self) -> Option { self.0.max_supply() } #[wasm_bindgen(getter = "maxSupplyChangeRules")] - pub fn get_max_supply_change_rules(&self) -> ChangeControlRulesWasm { + pub fn max_supply_change_rules(&self) -> ChangeControlRulesWasm { self.0.max_supply_change_rules().clone().into() } #[wasm_bindgen(getter = "distributionRules")] - pub fn get_distribution_rules(&self) -> TokenDistributionRulesWasm { + pub fn distribution_rules(&self) -> TokenDistributionRulesWasm { self.0.distribution_rules().clone().into() } #[wasm_bindgen(getter = "marketplaceRules")] - pub fn get_marketplace_rules(&self) -> TokenMarketplaceRulesWasm { + pub fn marketplace_rules(&self) -> TokenMarketplaceRulesWasm { match self.0.clone() { TokenConfiguration::V0(v0) => v0.marketplace_rules.clone().into(), } } #[wasm_bindgen(getter = "manualMintingRules")] - pub fn get_manual_minting_rules(&self) -> ChangeControlRulesWasm { + pub fn manual_minting_rules(&self) -> ChangeControlRulesWasm { self.0.manual_minting_rules().clone().into() } #[wasm_bindgen(getter = "manualBurningRules")] - pub fn get_manual_burning_rules(&self) -> ChangeControlRulesWasm { + pub fn manual_burning_rules(&self) -> ChangeControlRulesWasm { self.0.manual_burning_rules().clone().into() } #[wasm_bindgen(getter = "freezeRules")] - pub fn get_freeze_rules(&self) -> ChangeControlRulesWasm { + pub fn freeze_rules(&self) -> ChangeControlRulesWasm { self.0.freeze_rules().clone().into() } #[wasm_bindgen(getter = "unfreezeRules")] - pub fn get_unfreeze_rules(&self) -> ChangeControlRulesWasm { + pub fn unfreeze_rules(&self) -> ChangeControlRulesWasm { self.0.unfreeze_rules().clone().into() } #[wasm_bindgen(getter = "destroyFrozenFundsRules")] - pub fn get_destroy_frozen_funds_rules(&self) -> ChangeControlRulesWasm { + pub fn destroy_frozen_funds_rules(&self) -> ChangeControlRulesWasm { self.0.destroy_frozen_funds_rules().clone().into() } #[wasm_bindgen(getter = "emergencyActionRules")] - pub fn get_emergency_action_rules(&self) -> ChangeControlRulesWasm { + pub fn emergency_action_rules(&self) -> ChangeControlRulesWasm { self.0.emergency_action_rules().clone().into() } #[wasm_bindgen(getter = "mainControlGroup")] - pub fn get_main_control_group(&self) -> Option { + pub fn main_control_group(&self) -> Option { self.0.main_control_group() } #[wasm_bindgen(getter = "mainControlGroupCanBeModified")] - pub fn get_main_control_group_can_be_modified(&self) -> AuthorizedActionTakersWasm { + pub fn main_control_group_can_be_modified(&self) -> AuthorizedActionTakersWasm { (*self.0.main_control_group_can_be_modified()).into() } #[wasm_bindgen(getter = "description")] - pub fn get_description(&self) -> Option { + pub fn description(&self) -> Option { self.0.description().clone() } @@ -198,8 +254,10 @@ impl TokenConfigurationWasm { } #[wasm_bindgen(setter = "baseSupply")] - pub fn set_base_supply(&mut self, base_supply: TokenAmount) { - self.0.set_base_supply(base_supply) + pub fn set_base_supply(&mut self, base_supply: JsValue) -> WasmDppResult<()> { + self.0 + .set_base_supply(try_to_u64(&base_supply, "baseSupply")?); + Ok(()) } #[wasm_bindgen(setter = "keepsHistory")] @@ -207,9 +265,9 @@ impl TokenConfigurationWasm { *self.0.keeps_history_mut() = keeps_history.clone().into(); } - #[wasm_bindgen(setter = "startAsPaused")] - pub fn set_start_as_paused(&mut self, start_as_paused: bool) { - self.0.set_start_as_paused(start_as_paused) + #[wasm_bindgen(setter = "isStartedAsPaused")] + pub fn set_is_started_as_paused(&mut self, is_started_as_paused: bool) { + self.0.set_start_as_paused(is_started_as_paused) } #[wasm_bindgen(setter = "isAllowedTransferToFrozenBalance")] @@ -222,8 +280,14 @@ impl TokenConfigurationWasm { } #[wasm_bindgen(setter = "maxSupply")] - pub fn set_max_supply(&mut self, max_supply: Option) { - self.0.set_max_supply(max_supply) + pub fn set_max_supply(&mut self, max_supply: JsValue) -> WasmDppResult<()> { + let max_supply = if max_supply.is_undefined() || max_supply.is_null() { + None + } else { + Some(try_to_u64(&max_supply, "maxSupply")?) + }; + self.0.set_max_supply(max_supply); + Ok(()) } #[wasm_bindgen(setter = "maxSupplyChangeRules")] @@ -298,11 +362,10 @@ impl TokenConfigurationWasm { #[wasm_bindgen(js_name = "calculateTokenId")] pub fn calculate_token_id( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, - token_pos: TokenContractPosition, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "tokenPos")] token_pos: TokenContractPosition, ) -> WasmDppResult { - let contract_id: Identifier = IdentifierWasm::try_from(js_contract_id)?.into(); + let contract_id: Identifier = contract_id.try_into()?; Ok(IdentifierWasm::from(calculate_token_id( contract_id.as_bytes(), @@ -310,3 +373,5 @@ impl TokenConfigurationWasm { ))) } } + +impl_wasm_type_info!(TokenConfigurationWasm, TokenConfiguration); diff --git a/packages/wasm-dpp2/src/tokens/configuration/trade_mode.rs b/packages/wasm-dpp2/src/tokens/configuration/trade_mode.rs index e16b38463f1..484f231b349 100644 --- a/packages/wasm-dpp2/src/tokens/configuration/trade_mode.rs +++ b/packages/wasm-dpp2/src/tokens/configuration/trade_mode.rs @@ -1,3 +1,4 @@ +use crate::impl_wasm_type_info; use dpp::data_contract::associated_token::token_marketplace_rules::v0::TokenTradeMode; use wasm_bindgen::prelude::wasm_bindgen; @@ -19,25 +20,17 @@ impl From for TokenTradeMode { #[wasm_bindgen(js_class = TokenTradeMode)] impl TokenTradeModeWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenTradeMode".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenTradeMode".to_string() - } - #[wasm_bindgen(js_name = "NotTradeable")] pub fn not_tradeable() -> TokenTradeModeWasm { TokenTradeModeWasm(TokenTradeMode::NotTradeable) } - #[wasm_bindgen(js_name = "getValue")] - pub fn get_value(&self) -> String { + #[wasm_bindgen(getter = "value")] + pub fn value(&self) -> String { match self.0 { TokenTradeMode::NotTradeable => String::from("NotTradeable"), } } } + +impl_wasm_type_info!(TokenTradeModeWasm, TokenTradeMode); diff --git a/packages/wasm-dpp2/src/tokens/configuration_change_item/items/new_tokens_destination_identity.rs b/packages/wasm-dpp2/src/tokens/configuration_change_item/items/new_tokens_destination_identity.rs index 9c03f6653ae..42ce0c40e80 100644 --- a/packages/wasm-dpp2/src/tokens/configuration_change_item/items/new_tokens_destination_identity.rs +++ b/packages/wasm-dpp2/src/tokens/configuration_change_item/items/new_tokens_destination_identity.rs @@ -1,23 +1,19 @@ use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeOrUndefinedJs, IdentifierWasm}; use crate::tokens::configuration::authorized_action_takers::AuthorizedActionTakersWasm; use crate::tokens::configuration_change_item::TokenConfigurationChangeItemWasm; use dpp::data_contract::associated_token::token_configuration_item::TokenConfigurationChangeItem; use dpp::prelude::Identifier; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; #[wasm_bindgen(js_class = TokenConfigurationChangeItem)] impl TokenConfigurationChangeItemWasm { #[wasm_bindgen(js_name = "NewTokensDestinationIdentityItem")] pub fn new_tokens_destination_identity_item( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_identity_id: &JsValue, + identity_id: IdentifierLikeOrUndefinedJs, ) -> WasmDppResult { - let identity_id: Option = match js_identity_id.is_undefined() { - true => None, - false => Some(IdentifierWasm::try_from(js_identity_id)?.into()), - }; + let identity_id: Option = + Option::::try_from(identity_id)?.map(Into::into); Ok(TokenConfigurationChangeItemWasm( TokenConfigurationChangeItem::NewTokensDestinationIdentity(identity_id), diff --git a/packages/wasm-dpp2/src/tokens/configuration_change_item/items/perpetual_distribution.rs b/packages/wasm-dpp2/src/tokens/configuration_change_item/items/perpetual_distribution.rs index fcbc9c62123..ed93dd3dc5f 100644 --- a/packages/wasm-dpp2/src/tokens/configuration_change_item/items/perpetual_distribution.rs +++ b/packages/wasm-dpp2/src/tokens/configuration_change_item/items/perpetual_distribution.rs @@ -1,30 +1,17 @@ use crate::tokens::configuration::authorized_action_takers::AuthorizedActionTakersWasm; use crate::tokens::configuration::perpetual_distribution::TokenPerpetualDistributionWasm; use crate::tokens::configuration_change_item::TokenConfigurationChangeItemWasm; -use crate::utils::IntoWasm; use dpp::data_contract::associated_token::token_configuration_item::TokenConfigurationChangeItem; -use dpp::data_contract::associated_token::token_perpetual_distribution::TokenPerpetualDistribution; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; #[wasm_bindgen(js_class = TokenConfigurationChangeItem)] impl TokenConfigurationChangeItemWasm { #[wasm_bindgen(js_name = "PerpetualDistributionConfigurationItem")] - pub fn perpetual_distribution_item(js_perpetual_distribution_value: JsValue) -> Self { - let perpetual_distribution_value: Option = - match js_perpetual_distribution_value.is_undefined() { - true => None, - false => Some( - js_perpetual_distribution_value - .to_wasm::("TokenPerpetualDistribution") - .unwrap() - .clone() - .into(), - ), - }; - + pub fn perpetual_distribution_item( + perpetual_distribution: Option, + ) -> Self { TokenConfigurationChangeItemWasm(TokenConfigurationChangeItem::PerpetualDistribution( - perpetual_distribution_value, + perpetual_distribution.map(|p| p.into()), )) } diff --git a/packages/wasm-dpp2/src/tokens/configuration_change_item/token_configuration_change_item.rs b/packages/wasm-dpp2/src/tokens/configuration_change_item/token_configuration_change_item.rs index 4c15b08f79d..e43f8786948 100644 --- a/packages/wasm-dpp2/src/tokens/configuration_change_item/token_configuration_change_item.rs +++ b/packages/wasm-dpp2/src/tokens/configuration_change_item/token_configuration_change_item.rs @@ -1,4 +1,6 @@ use crate::identifier::IdentifierWasm; +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use crate::tokens::configuration::authorized_action_takers::AuthorizedActionTakersWasm; use crate::tokens::configuration::configuration_convention::TokenConfigurationConventionWasm; use crate::tokens::configuration::perpetual_distribution::TokenPerpetualDistributionWasm; @@ -7,6 +9,31 @@ use dpp::data_contract::associated_token::token_configuration_item::TokenConfigu use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TOKEN_CONFIGURATION_CHANGE_ITEM_TS: &str = r#" +/** + * Union type for token configuration change item values. + * Use `itemName` getter to determine which variant it is. + */ +export type TokenConfigurationChangeItemValue = + | "TokenConfigurationNoChange" + | TokenConfigurationConvention + | AuthorizedActionTakers + | bigint + | TokenPerpetualDistribution + | Identifier + | boolean + | TokenTradeMode + | number + | null; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "TokenConfigurationChangeItemValue")] + pub type TokenConfigurationChangeItemValueJs; +} + #[derive(Debug, Clone, PartialEq)] #[wasm_bindgen(js_name = "TokenConfigurationChangeItem")] pub struct TokenConfigurationChangeItemWasm(pub(crate) TokenConfigurationChangeItem); @@ -25,18 +52,8 @@ impl From for TokenConfigurationChangeItemWasm { #[wasm_bindgen(js_class = TokenConfigurationChangeItem)] impl TokenConfigurationChangeItemWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "TokenConfigurationChangeItem".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "TokenConfigurationChangeItem".to_string() - } - - #[wasm_bindgen(js_name = "getItemName")] - pub fn get_item_name(&self) -> String { + #[wasm_bindgen(getter = "itemName")] + pub fn item_name(&self) -> String { match self.0.clone() { TokenConfigurationChangeItem::TokenConfigurationNoChange => { String::from("TokenConfigurationNoChange") @@ -119,9 +136,9 @@ impl TokenConfigurationChangeItemWasm { } } - #[wasm_bindgen(js_name = "getItem")] - pub fn get_item(&self) -> JsValue { - match self.0.clone() { + #[wasm_bindgen(getter = "item")] + pub fn item(&self) -> TokenConfigurationChangeItemValueJs { + let js_value: JsValue = match self.0.clone() { TokenConfigurationChangeItem::TokenConfigurationNoChange => { JsValue::from_str("TokenConfigurationNoChange") } @@ -224,6 +241,16 @@ impl TokenConfigurationChangeItemWasm { TokenConfigurationChangeItem::MainControlGroup(group_contract_position) => { JsValue::from(group_contract_position) } - } + }; + js_value.into() } } + +impl_try_from_js_value!( + TokenConfigurationChangeItemWasm, + "TokenConfigurationChangeItem" +); +impl_wasm_type_info!( + TokenConfigurationChangeItemWasm, + TokenConfigurationChangeItem +); diff --git a/packages/wasm-dpp2/src/tokens/contract_info.rs b/packages/wasm-dpp2/src/tokens/contract_info.rs index 3053b3a073a..7b2238dbc78 100644 --- a/packages/wasm-dpp2/src/tokens/contract_info.rs +++ b/packages/wasm-dpp2/src/tokens/contract_info.rs @@ -1,4 +1,5 @@ use crate::identifier::IdentifierWasm; +use crate::impl_wasm_type_info; use dpp::data_contract::TokenContractPosition; use dpp::tokens::contract_info::TokenContractInfo; use dpp::tokens::contract_info::v0::TokenContractInfoV0Accessors; @@ -36,3 +37,5 @@ impl TokenContractInfoWasm { } } } + +impl_wasm_type_info!(TokenContractInfoWasm, TokenContractInfo); diff --git a/packages/wasm-dpp2/src/tokens/encrypted_note/private_encrypted_note.rs b/packages/wasm-dpp2/src/tokens/encrypted_note/private_encrypted_note.rs index e04ea38607a..b9db0fdd595 100644 --- a/packages/wasm-dpp2/src/tokens/encrypted_note/private_encrypted_note.rs +++ b/packages/wasm-dpp2/src/tokens/encrypted_note/private_encrypted_note.rs @@ -1,3 +1,5 @@ +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use dpp::prelude::{DerivationEncryptionKeyIndex, RootEncryptionKeyIndex}; use dpp::tokens::PrivateEncryptedNote; use wasm_bindgen::prelude::wasm_bindgen; @@ -20,19 +22,11 @@ impl From for PrivateEncryptedNote { #[wasm_bindgen(js_class = PrivateEncryptedNote)] impl PrivateEncryptedNoteWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "PrivateEncryptedNote".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "PrivateEncryptedNote".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( + pub fn constructor( + #[wasm_bindgen(js_name = "rootEncryptionKeyIndex")] root_encryption_key_index: RootEncryptionKeyIndex, + #[wasm_bindgen(js_name = "derivationEncryptionKeyIndex")] derivation_encryption_key_index: DerivationEncryptionKeyIndex, value: Vec, ) -> PrivateEncryptedNoteWasm { @@ -73,3 +67,6 @@ impl PrivateEncryptedNoteWasm { self.0.2 = value; } } + +impl_try_from_js_value!(PrivateEncryptedNoteWasm, "PrivateEncryptedNote"); +impl_wasm_type_info!(PrivateEncryptedNoteWasm, PrivateEncryptedNote); diff --git a/packages/wasm-dpp2/src/tokens/encrypted_note/shared_encrypted_note.rs b/packages/wasm-dpp2/src/tokens/encrypted_note/shared_encrypted_note.rs index 63ea8b80c70..f51aee61f91 100644 --- a/packages/wasm-dpp2/src/tokens/encrypted_note/shared_encrypted_note.rs +++ b/packages/wasm-dpp2/src/tokens/encrypted_note/shared_encrypted_note.rs @@ -1,3 +1,5 @@ +use crate::impl_try_from_js_value; +use crate::impl_wasm_type_info; use dpp::prelude::{RecipientKeyIndex, SenderKeyIndex}; use dpp::tokens::SharedEncryptedNote; use wasm_bindgen::prelude::wasm_bindgen; @@ -20,20 +22,10 @@ impl From for SharedEncryptedNote { #[wasm_bindgen(js_class = SharedEncryptedNote)] impl SharedEncryptedNoteWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "SharedEncryptedNote".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "SharedEncryptedNote".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - sender_key_index: SenderKeyIndex, - recipient_key_index: RecipientKeyIndex, + pub fn constructor( + #[wasm_bindgen(js_name = "senderKeyIndex")] sender_key_index: SenderKeyIndex, + #[wasm_bindgen(js_name = "recipientKeyIndex")] recipient_key_index: RecipientKeyIndex, value: Vec, ) -> Self { SharedEncryptedNoteWasm((sender_key_index, recipient_key_index, value)) @@ -69,3 +61,6 @@ impl SharedEncryptedNoteWasm { self.0.2 = value; } } + +impl_try_from_js_value!(SharedEncryptedNoteWasm, "SharedEncryptedNote"); +impl_wasm_type_info!(SharedEncryptedNoteWasm, SharedEncryptedNote); diff --git a/packages/wasm-dpp2/src/tokens/info.rs b/packages/wasm-dpp2/src/tokens/info.rs index b6365408772..28bec06d8d5 100644 --- a/packages/wasm-dpp2/src/tokens/info.rs +++ b/packages/wasm-dpp2/src/tokens/info.rs @@ -1,3 +1,4 @@ +use crate::impl_wasm_type_info; use dpp::tokens::info::IdentityTokenInfo; use dpp::tokens::info::v0::IdentityTokenInfoV0Accessors; use wasm_bindgen::prelude::wasm_bindgen; @@ -20,10 +21,12 @@ impl From for IdentityTokenInfo { #[wasm_bindgen(js_class = IdentityTokenInfo)] impl IdentityTokenInfoWasm { - #[wasm_bindgen(getter = "frozen")] - pub fn frozen(&self) -> bool { + #[wasm_bindgen(getter = "isFrozen")] + pub fn is_frozen(&self) -> bool { match &self.0 { IdentityTokenInfo::V0(v0) => v0.frozen(), } } } + +impl_wasm_type_info!(IdentityTokenInfoWasm, IdentityTokenInfo); diff --git a/packages/wasm-dpp2/src/tokens/status.rs b/packages/wasm-dpp2/src/tokens/status.rs index d63f4bee074..ea39a7d0d77 100644 --- a/packages/wasm-dpp2/src/tokens/status.rs +++ b/packages/wasm-dpp2/src/tokens/status.rs @@ -1,3 +1,4 @@ +use crate::impl_wasm_type_info; use dpp::tokens::status::TokenStatus; use dpp::tokens::status::v0::TokenStatusV0Accessors; use wasm_bindgen::prelude::wasm_bindgen; @@ -20,10 +21,12 @@ impl From for TokenStatus { #[wasm_bindgen(js_class = TokenStatus)] impl TokenStatusWasm { - #[wasm_bindgen(getter = "paused")] - pub fn paused(&self) -> bool { + #[wasm_bindgen(getter = "isPaused")] + pub fn is_paused(&self) -> bool { match &self.0 { TokenStatus::V0(v0) => v0.paused(), } } } + +impl_wasm_type_info!(TokenStatusWasm, TokenStatus); diff --git a/packages/wasm-dpp2/src/utils.rs b/packages/wasm-dpp2/src/utils.rs index 5aa9f75ea44..256f72ec352 100644 --- a/packages/wasm-dpp2/src/utils.rs +++ b/packages/wasm-dpp2/src/utils.rs @@ -1,9 +1,8 @@ use crate::error::{WasmDppError, WasmDppResult}; -use anyhow::{anyhow, bail}; use dpp::identifier::Identifier; use dpp::platform_value::Value; use dpp::util::hash::hash_double_to_vec; -use js_sys::Error as JsError; +use js_sys::{Error as JsError, Map, Object}; use serde_json::Value as JsonValue; use std::collections::BTreeMap; use std::convert::TryInto; @@ -36,6 +35,47 @@ impl JsValueExt for JsValue { } } +/// Extension trait for building a js_sys::Map from an iterator +/// +/// Similar to JavaScript's `new Map(entries)` constructor. +/// +/// # Example +/// +/// ```ignore +/// use js_sys::Map; +/// use wasm_dpp2::utils::JsMapExt; +/// +/// let items = vec![("key1", 1), ("key2", 2)]; +/// let map = Map::from_entries(items.into_iter().map(|(k, v)| { +/// (JsValue::from(k), JsValue::from(v)) +/// })); +/// ``` +pub trait JsMapExt { + /// Create a Map from an iterator of key-value pairs. + /// + /// Both key and value types must implement `Into`. + fn from_entries(iter: I) -> Self + where + K: Into, + V: Into, + I: IntoIterator; +} + +impl JsMapExt for Map { + fn from_entries(iter: I) -> Self + where + K: Into, + V: Into, + I: IntoIterator, + { + let map = Map::new(); + for (key, value) in iter { + map.set(&key.into(), &value.into()); + } + map + } +} + /// Extension trait for converting JsValue to serde/platform values pub trait ToSerdeJSONExt { fn with_serde_to_json_value(&self) -> WasmDppResult; @@ -121,40 +161,518 @@ pub fn get_class_type(value: &JsValue) -> WasmDppResult { Ok(class_type.as_string().unwrap_or_default()) } -/// Convert a JS Number or BigInt to u64 -pub fn try_to_u64(value: JsValue) -> Result { +/// Extract a required property from a JS value/object and convert it using TryFrom. +/// +/// Returns `Err` if the property is undefined, null, or conversion fails. +/// +/// This function works with types that implement `TryFrom<&JsValue>`. +/// +/// # Example +/// +/// ```ignore +/// let id: IdentifierWasm = try_from_options(&options, "id")?; +/// ``` +pub fn try_from_options(options: &JsValue, property_name: &str) -> WasmDppResult +where + for<'a> T: TryFrom<&'a JsValue>, + for<'a> >::Error: Into, +{ + let value = + js_sys::Reflect::get(options, &JsValue::from_str(property_name)).map_err(|err| { + let message = err.error_message(); + WasmDppError::generic(format!( + "failed to read '{}' from options: {}", + property_name, message + )) + })?; + + if value.is_undefined() || value.is_null() { + return Err(WasmDppError::invalid_argument(format!( + "'{}' is required", + property_name + ))); + } + + T::try_from(&value).map_err(Into::into) +} + +/// Extract a required property from a JS value/object and convert it with a custom converter. +/// +/// Returns `Err` if the property is undefined, null, or conversion fails. +/// +/// Use this for primitive types (u64, etc.) that don't have TryFrom<&JsValue>. +/// +/// # Example +/// +/// ```ignore +/// let balance: u64 = try_from_options_with(&options, "balance", |v| { +/// try_to_u64(v, "balance") +/// })?; +/// ``` +pub fn try_from_options_with( + options: &JsValue, + property_name: &str, + converter: F, +) -> WasmDppResult +where + F: FnOnce(&JsValue) -> WasmDppResult, +{ + let value = + js_sys::Reflect::get(options, &JsValue::from_str(property_name)).map_err(|err| { + let message = err.error_message(); + WasmDppError::generic(format!( + "failed to read '{}' from options: {}", + property_name, message + )) + })?; + + if value.is_undefined() || value.is_null() { + return Err(WasmDppError::invalid_argument(format!( + "'{}' is required", + property_name + ))); + } + + converter(&value) +} + +/// Extract an optional property from a JS object and convert it using TryFrom. +/// +/// Returns `Ok(None)` if the property is undefined or null. +/// Returns `Ok(Some(T))` if the property exists and conversion succeeds. +/// Returns `Err` if the property exists but conversion fails. +/// +/// This function works with types that implement `TryFrom<&JsValue>`. +/// +/// # Example +/// +/// ```ignore +/// let id: Option = try_from_options_optional(&options, "id")?; +/// ``` +pub fn try_from_options_optional( + options: &JsValue, + property_name: &str, +) -> WasmDppResult> +where + for<'a> T: TryFrom<&'a JsValue>, + for<'a> >::Error: Into, +{ + let value = + js_sys::Reflect::get(options, &JsValue::from_str(property_name)).map_err(|err| { + let message = err.error_message(); + WasmDppError::generic(format!( + "failed to read '{}' from options: {}", + property_name, message + )) + })?; + + if value.is_undefined() || value.is_null() { + Ok(None) + } else { + T::try_from(&value).map(Some).map_err(Into::into) + } +} + +/// Extract an optional property from a JS object and convert it with a custom converter. +/// +/// Returns `Ok(None)` if the property is undefined or null. +/// Returns `Ok(Some(T))` if the property exists and conversion succeeds. +/// Returns `Err` if the property exists but conversion fails. +/// +/// Use this for primitive types (u64, etc.) that don't have TryFrom<&JsValue>. +/// +/// # Example +/// +/// ```ignore +/// let balance: Option = try_from_options_optional_with(&options, "balance", |v| { +/// try_to_u64(v, "balance") +/// })?; +/// ``` +pub fn try_from_options_optional_with( + options: &JsValue, + property_name: &str, + converter: F, +) -> WasmDppResult> +where + F: FnOnce(&JsValue) -> WasmDppResult, +{ + let value = + js_sys::Reflect::get(options, &JsValue::from_str(property_name)).map_err(|err| { + let message = err.error_message(); + WasmDppError::generic(format!( + "failed to read '{}' from options: {}", + property_name, message + )) + })?; + + if value.is_undefined() || value.is_null() { + Ok(None) + } else { + converter(&value).map(Some) + } +} + +/// Convert a JS value to u64 with validation. +/// +/// Accepts: +/// - BigInt: Native JavaScript BigInt values +/// - Number: JavaScript numbers (note: precision loss for values > 2^53-1) +/// - String: Numeric strings (useful for JSON serialization of large numbers) +/// +/// This flexibility is needed because JSON doesn't support BigInt natively. +/// Large numbers may be serialized as strings to preserve precision. +/// +/// Takes `&JsValue` to allow Deref coercion from `js_sys::BigInt` and `js_sys::Number`. +pub fn try_to_u64(value: &JsValue, field_name: &str) -> WasmDppResult { if value.is_bigint() { - js_sys::BigInt::new(&value) - .map_err(|e| anyhow!("unable to create bigInt: {}", e.to_string()))? - .try_into() - .map_err(|e| anyhow!("conversion of BigInt to u64 failed: {:#}", e)) - } else if value.as_f64().is_some() { - let number = js_sys::Number::from(value); - convert_number_to_u64(number) + let bigint = js_sys::BigInt::new(value).map_err(|_| { + WasmDppError::invalid_argument(format!("'{}' is not a valid BigInt", field_name)) + })?; + bigint.try_into().map_err(|_| { + WasmDppError::invalid_argument(format!( + "'{}' BigInt value is out of u64 range", + field_name + )) + }) + } else if let Some(num) = value.as_f64() { + if num.is_nan() || num.is_infinite() { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be a finite number, got {}", + field_name, + if num.is_nan() { "NaN" } else { "Infinity" } + ))); + } + if num.fract() != 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be an integer, got {}", + field_name, num + ))); + } + if num < 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be non-negative, got {}", + field_name, num + ))); + } + if num > u64::MAX as f64 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be at most {}, got {}", + field_name, + u64::MAX, + num + ))); + } + Ok(num as u64) + } else if let Some(s) = value.as_string() { + s.parse::().map_err(|_| { + WasmDppError::invalid_argument(format!( + "'{}' string value '{}' is not a valid u64", + field_name, s + )) + }) + } else { + Err(WasmDppError::invalid_argument(format!( + "'{}' must be a BigInt, number, or numeric string", + field_name + ))) + } +} + +/// Convert a JS value to Object with validation. +/// +/// Uses `dyn_into()` to safely convert, returning an error if the value is not an object. +/// Accepts any type that implements `Into` for flexibility. +pub fn try_to_object(value: impl Into, field_name: &str) -> WasmDppResult { + value + .into() + .dyn_into() + .map_err(|_| WasmDppError::invalid_argument(format!("'{}' must be an object", field_name))) +} + +/// Convert a JS value to Array with validation. +/// +/// Validates that the value is an array using `Array::is_array()`. +/// Returns an error if the value is not an array. +pub fn try_to_array(value: &JsValue, field_name: &str) -> WasmDppResult { + if !js_sys::Array::is_array(value) { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be an array", + field_name + ))); + } + Ok(js_sys::Array::from(value)) +} + +/// Convert a JS array to a Vec of Rust types via WASM wrappers. +/// +/// This generic function converts a JavaScript array where each element can be converted +/// to a WASM wrapper type `W`, which is then converted to the final Rust type `T`. +/// +/// # Type Parameters +/// +/// - `W`: The WASM wrapper type that implements `TryFrom` +/// - `T`: The final Rust type that implements `From` +/// - `A`: The array input type that implements `Into` +/// +/// # Example +/// +/// ```ignore +/// // Convert JS array of identifiers to Vec +/// let identifiers: Vec = try_to_vec::( +/// js_array, "identifiers", "identifier" +/// )?; +/// ``` +pub fn try_to_vec(array: A, field_name: &str, type_name: &str) -> WasmDppResult> +where + A: Into, + W: TryFrom, + T: From, +{ + let array_value: JsValue = array.into(); + let js_array = try_to_array(&array_value, field_name)?; + js_array + .iter() + .map(|v| { + W::try_from(v).map(T::from).map_err(|err| { + WasmDppError::invalid_argument(format!("Invalid {}: {}", type_name, err)) + }) + }) + .collect() +} + +/// Convert a JS value to Map with validation. +/// +/// Uses `dyn_into()` to safely convert, returning an error if the value is not a Map. +/// This is preferred over `Map::from()` which unsafely casts any JsValue without validation. +/// Accepts any type that implements `Into` for flexibility. +pub fn try_to_map(value: impl Into, field_name: &str) -> WasmDppResult { + value + .into() + .dyn_into() + .map_err(|_| WasmDppError::invalid_argument(format!("'{}' must be a Map", field_name))) +} + +/// Convert a JS value to a String. +/// +/// Uses `JsValue::as_string()` to extract the string value. +/// Returns an error if the value is not a string. +/// +/// Takes `&JsValue` to allow Deref coercion from js_sys types. +pub fn try_to_string(value: &JsValue, field_name: &str) -> WasmDppResult { + value + .as_string() + .ok_or_else(|| WasmDppError::invalid_argument(format!("'{}' must be a string", field_name))) +} + +/// Convert a JS value to bytes (Vec) with type validation. +/// +/// Validates that the value is a Uint8Array using `dyn_into()`. +/// Returns an error if the value is not a Uint8Array. +/// Accepts any type that implements `Into` for flexibility. +pub fn try_to_bytes(value: impl Into, field_name: &str) -> WasmDppResult> { + let array: js_sys::Uint8Array = value.into().dyn_into().map_err(|_| { + WasmDppError::invalid_argument(format!("'{}' must be a Uint8Array", field_name)) + })?; + Ok(array.to_vec()) +} + +/// Convert a JS value to a fixed-size byte array with type and length validation. +/// +/// Validates that: +/// - The value is a Uint8Array +/// - The length is exactly N bytes +/// +/// Accepts any type that implements `Into` for flexibility. +pub fn try_to_fixed_bytes( + value: impl Into, + field_name: &str, +) -> WasmDppResult<[u8; N]> { + let bytes = try_to_bytes(value, field_name)?; + if bytes.len() != N { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be exactly {} bytes, got {}", + field_name, + N, + bytes.len() + ))); + } + let mut arr = [0u8; N]; + arr.copy_from_slice(&bytes); + Ok(arr) +} + +/// Convert a JS value to u32 with validation. +/// +/// Validates that the value is: +/// - A finite number (not NaN or Infinity) +/// - An integer (no fractional part) +/// - Non-negative +/// - Within u32 range (0..=4294967295) +/// +/// Takes `&JsValue` to allow Deref coercion from `js_sys::Number`. +pub fn try_to_u32(value: &JsValue, field_name: &str) -> WasmDppResult { + if let Some(num) = value.as_f64() { + if num.is_nan() || num.is_infinite() { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be a finite number, got {}", + field_name, + if num.is_nan() { "NaN" } else { "Infinity" } + ))); + } + + if num.fract() != 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be an integer, got {}", + field_name, num + ))); + } + + if num < 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be non-negative, got {}", + field_name, num + ))); + } + + if num > u32::MAX as f64 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be at most {}, got {}", + field_name, + u32::MAX, + num + ))); + } + + Ok(num as u32) + } else if let Some(s) = value.as_string() { + s.parse::().map_err(|_| { + WasmDppError::invalid_argument(format!( + "'{}' string value '{}' is not a valid u32", + field_name, s + )) + }) } else { - bail!("supported types are Number or BigInt") + Err(WasmDppError::invalid_argument(format!( + "'{}' must be a number or numeric string", + field_name + ))) } } -/// Convert a JS Number to u64 with validation -fn convert_number_to_u64(js_number: js_sys::Number) -> Result { - if let Some(float_number) = js_number.as_f64() { - if float_number.is_nan() || float_number.is_infinite() { - bail!("received an invalid number: the number is either NaN or Inf") +/// Convert a JS value to u8 with validation. +/// +/// Validates that the value is: +/// - A finite number (not NaN or Infinity) +/// - An integer (no fractional part) +/// - Non-negative +/// - Within u8 range (0..=255) +/// +/// Takes `&JsValue` to allow Deref coercion from `js_sys::Number`. +pub fn try_to_u8(value: &JsValue, field_name: &str) -> WasmDppResult { + if let Some(num) = value.as_f64() { + if num.is_nan() || num.is_infinite() { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be a finite number, got {}", + field_name, + if num.is_nan() { "NaN" } else { "Infinity" } + ))); } - if float_number < 0. { - bail!("received an invalid number: the number is negative"); + + if num.fract() != 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be an integer, got {}", + field_name, num + ))); } - if float_number.fract() != 0. { - bail!("received an invalid number: the number is fractional") + + if num < 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be non-negative, got {}", + field_name, num + ))); } - if float_number > u64::MAX as f64 { - bail!("received an invalid number: the number is > u64::max") + + if num > u8::MAX as f64 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be at most {}, got {}", + field_name, + u8::MAX, + num + ))); } - return Ok(float_number as u64); + Ok(num as u8) + } else if let Some(s) = value.as_string() { + s.parse::().map_err(|_| { + WasmDppError::invalid_argument(format!( + "'{}' string value '{}' is not a valid u8", + field_name, s + )) + }) + } else { + Err(WasmDppError::invalid_argument(format!( + "'{}' must be a number or numeric string", + field_name + ))) + } +} + +/// Convert a JS value to u16 with validation. +/// +/// Validates that the value is: +/// - A finite number (not NaN or Infinity) +/// - An integer (no fractional part) +/// - Non-negative +/// - Within u16 range (0..=65535) +/// +/// Takes `&JsValue` to allow Deref coercion from `js_sys::Number`. +pub fn try_to_u16(value: &JsValue, field_name: &str) -> WasmDppResult { + if let Some(num) = value.as_f64() { + if num.is_nan() || num.is_infinite() { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be a finite number, got {}", + field_name, + if num.is_nan() { "NaN" } else { "Infinity" } + ))); + } + + if num.fract() != 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be an integer, got {}", + field_name, num + ))); + } + + if num < 0.0 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be non-negative, got {}", + field_name, num + ))); + } + + if num > u16::MAX as f64 { + return Err(WasmDppError::invalid_argument(format!( + "'{}' must be at most {}, got {}", + field_name, + u16::MAX, + num + ))); + } + + Ok(num as u16) + } else if let Some(s) = value.as_string() { + s.parse::().map_err(|_| { + WasmDppError::invalid_argument(format!( + "'{}' string value '{}' is not a valid u16", + field_name, s + )) + }) + } else { + Err(WasmDppError::invalid_argument(format!( + "'{}' must be a number or numeric string", + field_name + ))) } - bail!("the value is not a number") } /// Generate a document ID using the v0 algorithm @@ -175,130 +693,183 @@ pub fn generate_document_id_v0( .map_err(|err| WasmDppError::invalid_argument(err.to_string())) } -/// Macro to implement `try_from_options` helper method for extracting a WASM type from an options object. +/// Macro to implement `TryFrom<&JsValue>` for WASM wrapper types using `IntoWasm`. /// -/// This generates a method that reads a named field from a JsValue options object and converts it -/// to the WASM wrapper type using `to_wasm`. +/// This is for complex types that can only be instantiated from their WASM class objects +/// (not from strings, numbers, or bytes). The implementation reads the internal `__wbg_ptr` +/// from the JavaScript object. /// /// # Usage /// /// ```ignore -/// // Basic form: requires field_name parameter -/// impl_try_from_options!(MyTypeWasm, "MyType"); +/// impl_try_from_js_value!(DocumentWasm, "Document"); +/// impl_try_from_js_value!(DataContractWasm, "DataContract"); +/// ``` +#[macro_export] +macro_rules! impl_try_from_js_value { + ($wrapper:ty, $type_name:expr) => { + impl TryFrom<&wasm_bindgen::JsValue> for $wrapper { + type Error = $crate::error::WasmDppError; + + fn try_from(value: &wasm_bindgen::JsValue) -> Result { + $crate::utils::IntoWasm::to_wasm::<$wrapper>(value, $type_name) + .map(|boxed| (*boxed).clone()) + } + } + }; +} + +/// Macro to implement `__type` and `__struct` getters for WASM type identification. +/// +/// These getters are used by `get_class_type()` and `to_wasm()` to verify that a JsValue +/// is the expected WASM class before extracting its internal pointer. This is necessary +/// because wasm-bindgen doesn't support `instanceof` or `JsCast` for exported structs. +/// +/// Using explicit `__type` properties instead of `constructor.name` ensures the type +/// identification works correctly even when the code is bundled and minified by consumers. +/// +/// # Usage /// -/// // With default field name: generates both try_from_options() and try_from_options_with_field() -/// impl_try_from_options!(MySignerWasm, "MySigner", "signer"); +/// ```ignore +/// impl_wasm_type_info!(IdentifierWasm, Identifier); +/// impl_wasm_type_info!(DataContractWasm, DataContract); /// ``` /// -/// The basic form generates: +/// This generates: /// ```ignore -/// impl MyTypeWasm { -/// pub fn try_from_options(options: &JsValue, field_name: &str) -> WasmDppResult { ... } +/// #[wasm_bindgen(js_class = Identifier)] +/// impl IdentifierWasm { +/// #[wasm_bindgen(getter = __type)] +/// pub fn type_name(&self) -> String { "Identifier".to_string() } +/// +/// #[wasm_bindgen(getter = __struct)] +/// pub fn struct_name() -> String { "Identifier".to_string() } /// } /// ``` +#[macro_export] +macro_rules! impl_wasm_type_info { + ($wrapper:ty, $js_class:ident) => { + #[wasm_bindgen::prelude::wasm_bindgen(js_class = $js_class)] + impl $wrapper { + #[wasm_bindgen::prelude::wasm_bindgen(getter = __type)] + pub fn type_name(&self) -> String { + stringify!($js_class).to_string() + } + + #[wasm_bindgen::prelude::wasm_bindgen(getter = __struct)] + pub fn struct_name() -> String { + stringify!($js_class).to_string() + } + } + }; +} + +/// Macro to implement `try_from_options` static methods for WASM wrapper types. +/// +/// This adds static methods for extracting values from JS option objects. +/// The type must already implement `TryFrom<&JsValue>`. +/// +/// # Usage +/// +/// ```ignore +/// impl_try_from_options!(IdentityWasm); +/// ``` /// -/// The form with default field name generates: +/// This generates: /// ```ignore -/// impl MySignerWasm { -/// pub fn try_from_options(options: &JsValue) -> WasmDppResult { ... } -/// pub fn try_from_options_with_field(options: &JsValue, field_name: &str) -> WasmDppResult { ... } +/// impl IdentityWasm { +/// pub fn try_from_options(options: &JsValue, field_name: &str) -> WasmDppResult { ... } +/// pub fn try_from_optional_options(options: &JsValue, field_name: &str) -> WasmDppResult> { ... } /// } /// ``` #[macro_export] macro_rules! impl_try_from_options { - // Basic form: requires field_name parameter - ($wrapper:ty, $type_name:expr) => { + ($wrapper:ty) => { impl $wrapper { - /// Try to extract this type from an options object field. + /// Extract this type from a JS options object by field name. /// - /// This helper reads the specified field from an options object and converts it - /// to the WASM wrapper type. + /// Returns `Err` if the property is missing, null, or conversion fails. pub fn try_from_options( options: &wasm_bindgen::JsValue, field_name: &str, ) -> $crate::error::WasmDppResult { - let value_js = - js_sys::Reflect::get(options, &wasm_bindgen::JsValue::from_str(field_name)) - .map_err(|_| { - $crate::error::WasmDppError::invalid_argument(format!( - "Missing '{}' field", - field_name - )) - })?; - - if value_js.is_undefined() || value_js.is_null() { - return Err($crate::error::WasmDppError::invalid_argument(format!( - "'{}' is required", - field_name - ))); - } - - $crate::utils::IntoWasm::to_wasm::<$wrapper>(&value_js, $type_name) - .map(|boxed| (*boxed).clone()) + $crate::utils::try_from_options(options, field_name) } - /// Try to extract this type from an options object field, returning None if not present. + /// Extract this type from a JS options object by field name, returning None if missing. /// - /// This helper reads the specified field from an options object and converts it - /// to the WASM wrapper type. Returns Ok(None) if the field is undefined or null. + /// Returns `Ok(None)` if the property is undefined or null. + /// Returns `Ok(Some(T))` if the property exists and conversion succeeds. + /// Returns `Err` if the property exists but conversion fails. pub fn try_from_optional_options( options: &wasm_bindgen::JsValue, field_name: &str, ) -> $crate::error::WasmDppResult> { - let value_js = - js_sys::Reflect::get(options, &wasm_bindgen::JsValue::from_str(field_name)) - .unwrap_or(wasm_bindgen::JsValue::UNDEFINED); - - if value_js.is_undefined() || value_js.is_null() { - return Ok(None); - } - - $crate::utils::IntoWasm::to_wasm::<$wrapper>(&value_js, $type_name) - .map(|boxed| Some((*boxed).clone())) + $crate::utils::try_from_options_optional(options, field_name) } } }; +} - // Form with default field name: generates try_from_options() with default and try_from_options_with_field() - ($wrapper:ty, $type_name:expr, $default_field:expr) => { - impl $wrapper { - /// Try to extract this type from an options object using the default field name. - /// - /// This helper reads the default field from an options object and converts it - /// to the WASM wrapper type. - pub fn try_from_options( - options: &wasm_bindgen::JsValue, - ) -> $crate::error::WasmDppResult { - Self::try_from_options_with_field(options, $default_field) +/// Macro to implement `From` traits for wasm-bindgen extern types. +/// +/// This macro helps convert Rust/WASM types to JavaScript extern types, +/// which are typically used for union type returns in wasm-bindgen. +/// +/// # Usage +/// +/// Basic form - implements `From` for the extern type: +/// ```ignore +/// impl_from_for_extern_type!(MyExternTypeJs); +/// ``` +/// +/// With source types - implements `From` for each source type: +/// ```ignore +/// impl_from_for_extern_type!(MyExternTypeJs, MyWasmType1, MyWasmType2); +/// ``` +/// +/// Combined form - implements both `From` and `From` for source types: +/// ```ignore +/// impl_from_for_extern_type!(MyExternTypeJs; MyWasmType1, MyWasmType2); +/// ``` +#[macro_export] +macro_rules! impl_from_for_extern_type { + // Just the extern type - implements From + ($extern_type:ty) => { + impl From for $extern_type { + fn from(value: wasm_bindgen::JsValue) -> Self { + wasm_bindgen::JsCast::unchecked_into(value) } + } + }; - /// Try to extract this type from an options object with a custom field name. - /// - /// This helper reads the specified field from an options object and converts it - /// to the WASM wrapper type. - pub fn try_from_options_with_field( - options: &wasm_bindgen::JsValue, - field_name: &str, - ) -> $crate::error::WasmDppResult { - let value_js = - js_sys::Reflect::get(options, &wasm_bindgen::JsValue::from_str(field_name)) - .map_err(|_| { - $crate::error::WasmDppError::invalid_argument(format!( - "Missing '{}' field", - field_name - )) - })?; - - if value_js.is_undefined() || value_js.is_null() { - return Err($crate::error::WasmDppError::invalid_argument(format!( - "'{}' is required", - field_name - ))); + // Extern type with source types (comma-separated) - implements From for each source only + ($extern_type:ty, $($source_type:ty),+ $(,)?) => { + $( + impl From<$source_type> for $extern_type { + fn from(value: $source_type) -> Self { + let js_value: wasm_bindgen::JsValue = value.into(); + wasm_bindgen::JsCast::unchecked_into(js_value) } + } + )+ + }; - $crate::utils::IntoWasm::to_wasm::<$wrapper>(&value_js, $type_name) - .map(|boxed| (*boxed).clone()) + // Combined form (semicolon-separated) - implements From AND From for source types + ($extern_type:ty; $($source_type:ty),+ $(,)?) => { + impl From for $extern_type { + fn from(value: wasm_bindgen::JsValue) -> Self { + wasm_bindgen::JsCast::unchecked_into(value) } } + + $( + impl From<$source_type> for $extern_type { + fn from(value: $source_type) -> Self { + let js_value: wasm_bindgen::JsValue = value.into(); + wasm_bindgen::JsCast::unchecked_into(js_value) + } + } + )+ }; } diff --git a/packages/wasm-dpp2/src/enums/platform.rs b/packages/wasm-dpp2/src/version.rs similarity index 77% rename from packages/wasm-dpp2/src/enums/platform.rs rename to packages/wasm-dpp2/src/version.rs index 259ee590c32..3b14430dc75 100644 --- a/packages/wasm-dpp2/src/enums/platform.rs +++ b/packages/wasm-dpp2/src/version.rs @@ -13,6 +13,33 @@ use dpp::version::v10::PLATFORM_V10; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const PLATFORM_VERSION_LIKE_TS: &str = r#" +export type PlatformVersionLike = PlatformVersion | string | number; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "PlatformVersionLike")] + pub type PlatformVersionLikeJs; +} + +impl TryFrom for PlatformVersionWasm { + type Error = WasmDppError; + fn try_from(value: PlatformVersionLikeJs) -> Result { + let js_value: JsValue = value.into(); + PlatformVersionWasm::try_from(js_value) + } +} + +impl TryFrom for PlatformVersion { + type Error = WasmDppError; + fn try_from(value: PlatformVersionLikeJs) -> Result { + let wasm: PlatformVersionWasm = value.try_into()?; + Ok(PlatformVersion::from(wasm)) + } +} + #[wasm_bindgen(js_name = "PlatformVersion")] #[derive(Default)] #[allow(non_camel_case_types)] @@ -30,11 +57,17 @@ pub enum PlatformVersionWasm { PLATFORM_V10 = 10, } -impl TryFrom for PlatformVersionWasm { +impl TryFrom<&JsValue> for PlatformVersionWasm { type Error = WasmDppError; - fn try_from(value: JsValue) -> Result { - match value.is_string() { - true => match value.as_string() { + + fn try_from(value: &JsValue) -> Result { + // Return default for undefined/null + if value.is_undefined() || value.is_null() { + return Ok(Self::default()); + } + + if value.is_string() { + match value.as_string() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -54,8 +87,9 @@ impl TryFrom for PlatformVersionWasm { enum_val ))), }, - }, - false => match value.as_f64() { + } + } else { + match value.as_f64() { None => Err(WasmDppError::invalid_argument( "cannot read value from enum", )), @@ -75,11 +109,19 @@ impl TryFrom for PlatformVersionWasm { enum_val ))), }, - }, + } } } } +impl TryFrom for PlatformVersionWasm { + type Error = WasmDppError; + + fn try_from(value: JsValue) -> Result { + Self::try_from(&value) + } +} + impl From for String { fn from(version: PlatformVersionWasm) -> String { match version { diff --git a/packages/wasm-dpp2/src/voting/contender.rs b/packages/wasm-dpp2/src/voting/contender.rs index 0d1f1d918ae..77a6e076c94 100644 --- a/packages/wasm-dpp2/src/voting/contender.rs +++ b/packages/wasm-dpp2/src/voting/contender.rs @@ -1,14 +1,48 @@ use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use dpp::prelude::Identifier; use dpp::voting::contender_structs::{ ContenderWithSerializedDocument, ContenderWithSerializedDocumentV0, }; use js_sys::Uint8Array; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * ContenderWithSerializedDocument serialized as a plain object. + */ +export interface ContenderWithSerializedDocumentObject { + v0: { + identityId: Uint8Array; + serializedDocument: Uint8Array | null; + voteTally: number | null; + }; +} + +/** + * ContenderWithSerializedDocument serialized as JSON. + */ +export interface ContenderWithSerializedDocumentJSON { + v0: { + identityId: string; + serializedDocument: string | null; + voteTally: number | null; + }; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ContenderWithSerializedDocumentObject")] + pub type ContenderWithSerializedDocumentObjectJs; + + #[wasm_bindgen(typescript_type = "ContenderWithSerializedDocumentJSON")] + pub type ContenderWithSerializedDocumentJSONJs; +} + #[derive(Clone)] #[wasm_bindgen(js_name = "ContenderWithSerializedDocument")] pub struct ContenderWithSerializedDocumentWasm(ContenderWithSerializedDocument); @@ -28,13 +62,12 @@ impl From for ContenderWithSerializedDocume #[wasm_bindgen(js_class = ContenderWithSerializedDocument)] impl ContenderWithSerializedDocumentWasm { #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: &JsValue, - serialized_document: Option>, - vote_tally: Option, + pub fn constructor( + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "serializedDocument")] serialized_document: Option>, + #[wasm_bindgen(js_name = "voteTally")] vote_tally: Option, ) -> WasmDppResult { - let identity: Identifier = IdentifierWasm::try_from(identity_id)?.into(); + let identity: Identifier = identity_id.try_into()?; let inner = ContenderWithSerializedDocument::V0(ContenderWithSerializedDocumentV0 { identity_id: identity, @@ -51,11 +84,11 @@ impl ContenderWithSerializedDocumentWasm { } #[wasm_bindgen(getter = serializedDocument)] - pub fn serialized_document(&self) -> JsValue { - match self.0.serialized_document() { - Some(bytes) => Uint8Array::from(bytes.as_slice()).into(), - None => JsValue::NULL, - } + pub fn serialized_document(&self) -> Option { + self.0 + .serialized_document() + .as_ref() + .map(|bytes| Uint8Array::from(bytes.as_slice())) } #[wasm_bindgen(getter = voteTally)] @@ -75,6 +108,13 @@ impl ContenderWithSerializedDocumentWasm { } impl_wasm_conversions!( + ContenderWithSerializedDocumentWasm, + ContenderWithSerializedDocument, + ContenderWithSerializedDocumentObjectJs, + ContenderWithSerializedDocumentJSONJs +); + +impl_wasm_type_info!( ContenderWithSerializedDocumentWasm, ContenderWithSerializedDocument ); diff --git a/packages/wasm-dpp2/src/voting/resource_vote.rs b/packages/wasm-dpp2/src/voting/resource_vote.rs index 9734d65061a..cf2b16725f0 100644 --- a/packages/wasm-dpp2/src/voting/resource_vote.rs +++ b/packages/wasm-dpp2/src/voting/resource_vote.rs @@ -1,4 +1,5 @@ use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::voting::resource_vote_choice::ResourceVoteChoiceWasm; use crate::voting::vote_poll::VotePollWasm; use dpp::voting::votes::resource_vote::ResourceVote; @@ -6,8 +7,38 @@ use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::resource_vote::v0::ResourceVoteV0; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * ResourceVote serialized as a plain object. + */ +export interface ResourceVoteObject { + $version: string; + votePoll: VotePollObject; + resourceVoteChoice: ResourceVoteChoiceObject; +} + +/** + * ResourceVote serialized as JSON. + */ +export interface ResourceVoteJSON { + $version: string; + votePoll: VotePollJSON; + resourceVoteChoice: ResourceVoteChoiceJSON; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ResourceVoteObject")] + pub type ResourceVoteObjectJs; + + #[wasm_bindgen(typescript_type = "ResourceVoteJSON")] + pub type ResourceVoteJSONJs; +} + #[derive(Clone)] -#[wasm_bindgen(js_name = ResourceVote)] +#[wasm_bindgen(js_name = "ResourceVote")] pub struct ResourceVoteWasm(ResourceVote); impl From for ResourceVoteWasm { @@ -24,26 +55,16 @@ impl From for ResourceVote { #[wasm_bindgen(js_class = ResourceVote)] impl ResourceVoteWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "ResourceVote".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "ResourceVote".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(vote_poll: &VotePollWasm, choice: &ResourceVoteChoiceWasm) -> Self { + pub fn constructor(poll: &VotePollWasm, choice: &ResourceVoteChoiceWasm) -> Self { ResourceVoteWasm(ResourceVote::V0(ResourceVoteV0 { - vote_poll: vote_poll.clone().into(), + vote_poll: poll.clone().into(), resource_vote_choice: choice.clone().into(), })) } - #[wasm_bindgen(getter = votePoll)] - pub fn vote_poll(&self) -> VotePollWasm { + #[wasm_bindgen(getter = poll)] + pub fn poll(&self) -> VotePollWasm { self.0.vote_poll().clone().into() } @@ -52,15 +73,15 @@ impl ResourceVoteWasm { self.0.resource_vote_choice().into() } - #[wasm_bindgen(setter = votePoll)] - pub fn set_vote_poll(&mut self, vote_poll: &VotePollWasm) { + #[wasm_bindgen(setter = poll)] + pub fn set_poll(&mut self, poll: &VotePollWasm) { let ResourceVote::V0(ResourceVoteV0 { resource_vote_choice, .. }) = self.0.clone(); self.0 = ResourceVote::V0(ResourceVoteV0 { - vote_poll: vote_poll.clone().into(), + vote_poll: poll.clone().into(), resource_vote_choice, }); } @@ -76,4 +97,10 @@ impl ResourceVoteWasm { } } -impl_wasm_conversions!(ResourceVoteWasm, ResourceVote); +impl_wasm_conversions!( + ResourceVoteWasm, + ResourceVote, + ResourceVoteObjectJs, + ResourceVoteJSONJs +); +impl_wasm_type_info!(ResourceVoteWasm, ResourceVote); diff --git a/packages/wasm-dpp2/src/voting/resource_vote_choice.rs b/packages/wasm-dpp2/src/voting/resource_vote_choice.rs index a0a4cf7e11a..b24a5a13f33 100644 --- a/packages/wasm-dpp2/src/voting/resource_vote_choice.rs +++ b/packages/wasm-dpp2/src/voting/resource_vote_choice.rs @@ -1,12 +1,41 @@ use crate::error::WasmDppResult; -use crate::identifier::IdentifierWasm; -use crate::{impl_try_from_options, impl_wasm_conversions}; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::{ + impl_try_from_js_value, impl_try_from_options, impl_wasm_conversions, impl_wasm_type_info, +}; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * ResourceVoteChoice serialized as a plain object. + */ +export interface ResourceVoteChoiceObject { + voteType: "TowardsIdentity" | "Abstain" | "Lock"; + value?: Uint8Array; +} + +/** + * ResourceVoteChoice serialized as JSON. + */ +export interface ResourceVoteChoiceJSON { + voteType: "TowardsIdentity" | "Abstain" | "Lock"; + value?: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ResourceVoteChoiceObject")] + pub type ResourceVoteChoiceObjectJs; + + #[wasm_bindgen(typescript_type = "ResourceVoteChoiceJSON")] + pub type ResourceVoteChoiceJSONJs; +} + #[derive(Clone)] -#[wasm_bindgen(js_name = ResourceVoteChoice)] +#[wasm_bindgen(js_name = "ResourceVoteChoice")] pub struct ResourceVoteChoiceWasm(ResourceVoteChoice); impl From for ResourceVoteChoiceWasm { @@ -23,24 +52,10 @@ impl From for ResourceVoteChoice { #[wasm_bindgen(js_class = ResourceVoteChoice)] impl ResourceVoteChoiceWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "ResourceVoteChoice".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "ResourceVoteChoice".to_string() - } - #[wasm_bindgen(js_name = "TowardsIdentity")] - pub fn towards_identity( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] js_id: &JsValue, - ) -> WasmDppResult { - let id = IdentifierWasm::try_from(js_id)?.into(); - + pub fn towards_identity(id: IdentifierLikeJs) -> WasmDppResult { Ok(ResourceVoteChoiceWasm(ResourceVoteChoice::TowardsIdentity( - id, + id.try_into()?, ))) } @@ -54,17 +69,17 @@ impl ResourceVoteChoiceWasm { ResourceVoteChoiceWasm(ResourceVoteChoice::Lock) } - #[wasm_bindgen(js_name = "getValue")] - pub fn get_value(&self) -> JsValue { + #[wasm_bindgen(getter = "value")] + pub fn value(&self) -> Option { match self.0 { - ResourceVoteChoice::TowardsIdentity(id) => JsValue::from(IdentifierWasm::from(id)), - ResourceVoteChoice::Abstain => JsValue::undefined(), - ResourceVoteChoice::Lock => JsValue::undefined(), + ResourceVoteChoice::TowardsIdentity(id) => Some(IdentifierWasm::from(id)), + ResourceVoteChoice::Abstain => None, + ResourceVoteChoice::Lock => None, } } - #[wasm_bindgen(js_name = "getType")] - pub fn get_type(&self) -> String { + #[wasm_bindgen(getter = "voteType")] + pub fn vote_type(&self) -> String { match self.0 { ResourceVoteChoice::TowardsIdentity(_) => "TowardsIdentity".to_string(), ResourceVoteChoice::Abstain => "Abstain".to_string(), @@ -73,5 +88,12 @@ impl ResourceVoteChoiceWasm { } } -impl_try_from_options!(ResourceVoteChoiceWasm, "ResourceVoteChoice"); -impl_wasm_conversions!(ResourceVoteChoiceWasm, ResourceVoteChoice); +impl_try_from_js_value!(ResourceVoteChoiceWasm, "ResourceVoteChoice"); +impl_try_from_options!(ResourceVoteChoiceWasm); +impl_wasm_conversions!( + ResourceVoteChoiceWasm, + ResourceVoteChoice, + ResourceVoteChoiceObjectJs, + ResourceVoteChoiceJSONJs +); +impl_wasm_type_info!(ResourceVoteChoiceWasm, ResourceVoteChoice); diff --git a/packages/wasm-dpp2/src/voting/vote.rs b/packages/wasm-dpp2/src/voting/vote.rs index 2e605d63848..32d0d981fb2 100644 --- a/packages/wasm-dpp2/src/voting/vote.rs +++ b/packages/wasm-dpp2/src/voting/vote.rs @@ -1,4 +1,6 @@ +use crate::impl_try_from_js_value; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use crate::voting::resource_vote_choice::ResourceVoteChoiceWasm; use crate::voting::vote_poll::VotePollWasm; use dpp::voting::votes::Vote; @@ -7,8 +9,42 @@ use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::resource_vote::v0::ResourceVoteV0; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * Vote serialized as a plain object. + */ +export interface VoteObject { + resourceVote: { + $version: string; + votePoll: VotePollObject; + resourceVoteChoice: ResourceVoteChoiceObject; + }; +} + +/** + * Vote serialized as JSON. + */ +export interface VoteJSON { + resourceVote: { + $version: string; + votePoll: VotePollJSON; + resourceVoteChoice: ResourceVoteChoiceJSON; + }; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "VoteObject")] + pub type VoteObjectJs; + + #[wasm_bindgen(typescript_type = "VoteJSON")] + pub type VoteJSONJs; +} + #[derive(Clone)] -#[wasm_bindgen(js_name=Vote)] +#[wasm_bindgen(js_name = "Vote")] pub struct VoteWasm(Vote); impl From for VoteWasm { @@ -25,57 +61,53 @@ impl From for Vote { #[wasm_bindgen(js_class = Vote)] impl VoteWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "Vote".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "Vote".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new(vote_poll: &VotePollWasm, resource_vote_choice: &ResourceVoteChoiceWasm) -> Self { + pub fn constructor( + #[wasm_bindgen(js_name = "votePoll")] vote_poll: &VotePollWasm, + #[wasm_bindgen(js_name = "resourceVoteChoice")] + resource_vote_choice: &ResourceVoteChoiceWasm, + ) -> Self { VoteWasm(Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { vote_poll: vote_poll.clone().into(), resource_vote_choice: resource_vote_choice.clone().into(), }))) } - #[wasm_bindgen(getter = votePoll)] - pub fn vote_poll(&self) -> VotePollWasm { + #[wasm_bindgen(getter = poll)] + pub fn poll(&self) -> VotePollWasm { match &self.0 { Vote::ResourceVote(vote) => vote.vote_poll().clone().into(), } } - #[wasm_bindgen(getter = resourceVoteChoice)] - pub fn resource_vote_choice(&self) -> ResourceVoteChoiceWasm { + #[wasm_bindgen(getter = choice)] + pub fn choice(&self) -> ResourceVoteChoiceWasm { match &self.0 { Vote::ResourceVote(vote) => vote.resource_vote_choice().into(), } } - #[wasm_bindgen(setter = votePoll)] - pub fn set_vote_poll(&mut self, vote_poll: &VotePollWasm) { + #[wasm_bindgen(setter = poll)] + pub fn set_poll(&mut self, poll: &VotePollWasm) { self.0 = match self.0.clone() { Vote::ResourceVote(vote) => Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { - vote_poll: vote_poll.clone().into(), + vote_poll: poll.clone().into(), resource_vote_choice: vote.resource_vote_choice(), })), } } - #[wasm_bindgen(setter = resourceVoteChoice)] - pub fn set_resource_vote_choice(&mut self, resource_vote_choice: &ResourceVoteChoiceWasm) { + #[wasm_bindgen(setter = choice)] + pub fn set_choice(&mut self, choice: &ResourceVoteChoiceWasm) { self.0 = match self.0.clone() { Vote::ResourceVote(vote) => Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { vote_poll: vote.vote_poll().clone(), - resource_vote_choice: resource_vote_choice.clone().into(), + resource_vote_choice: choice.clone().into(), })), } } } -impl_wasm_conversions!(VoteWasm, Vote); +impl_try_from_js_value!(VoteWasm, "Vote"); +impl_wasm_conversions!(VoteWasm, Vote, VoteObjectJs, VoteJSONJs); +impl_wasm_type_info!(VoteWasm, Vote); diff --git a/packages/wasm-dpp2/src/voting/vote_poll.rs b/packages/wasm-dpp2/src/voting/vote_poll.rs index d15666b9ebd..284a0844d06 100644 --- a/packages/wasm-dpp2/src/voting/vote_poll.rs +++ b/packages/wasm-dpp2/src/voting/vote_poll.rs @@ -1,16 +1,68 @@ use crate::error::{WasmDppError, WasmDppResult}; -use crate::identifier::IdentifierWasm; -use crate::utils::ToSerdeJSONExt; -use crate::{impl_try_from_options, impl_wasm_conversions}; +use crate::identifier::{IdentifierLikeJs, IdentifierWasm}; +use crate::utils::{ToSerdeJSONExt, try_from_options, try_from_options_with}; +use crate::{ + impl_try_from_js_value, impl_try_from_options, impl_wasm_conversions, impl_wasm_type_info, +}; use dpp::bincode; use dpp::voting::vote_polls::VotePoll; use dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll; use js_sys::Array; +use serde::Deserialize; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct VotePollOptions { + document_type_name: String, + index_name: String, +} + +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +export interface VotePollOptions { + contractId: IdentifierLike; + documentTypeName: string; + indexName: string; + indexValues: any[]; +} + +/** + * VotePoll serialized as a plain object. + */ +export interface VotePollObject { + contractId: Uint8Array; + documentTypeName: string; + indexName: string; + indexValues: any[]; +} + +/** + * VotePoll serialized as JSON. + */ +export interface VotePollJSON { + contractId: string; + documentTypeName: string; + indexName: string; + indexValues: any[]; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "VotePollOptions")] + pub type VotePollOptionsJs; + + #[wasm_bindgen(typescript_type = "VotePollObject")] + pub type VotePollObjectJs; + + #[wasm_bindgen(typescript_type = "VotePollJSON")] + pub type VotePollJSONJs; +} + #[derive(Clone)] -#[wasm_bindgen(js_name = VotePoll)] +#[wasm_bindgen(js_name = "VotePoll")] pub struct VotePollWasm(VotePoll); impl From for VotePollWasm { @@ -27,36 +79,28 @@ impl From for VotePoll { #[wasm_bindgen(js_class = VotePoll)] impl VotePollWasm { - #[wasm_bindgen(getter = __type)] - pub fn type_name(&self) -> String { - "VotePoll".to_string() - } - - #[wasm_bindgen(getter = __struct)] - pub fn struct_name() -> String { - "VotePoll".to_string() - } - #[wasm_bindgen(constructor)] - pub fn new( - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, - document_type_name: String, - index_name: String, - js_index_values: JsValue, - ) -> WasmDppResult { - let contract_id = IdentifierWasm::try_from(js_contract_id)?.into(); - - let index_values_value = js_index_values.with_serde_to_platform_value()?; - let index_values = index_values_value - .into_array() - .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; + pub fn constructor(options: VotePollOptionsJs) -> WasmDppResult { + // Extract contractId (required) + let contract_id: IdentifierWasm = try_from_options(&options, "contractId")?; + + // Extract indexValues (required) + let index_values = try_from_options_with(&options, "indexValues", |v| { + let index_values_value = v.with_serde_to_platform_value()?; + index_values_value + .into_array() + .map_err(|err| WasmDppError::invalid_argument(err.to_string())) + })?; + + // Extract simple fields via serde + let opts: VotePollOptions = serde_wasm_bindgen::from_value(options.into()) + .map_err(|e| WasmDppError::invalid_argument(e.to_string()))?; Ok(VotePollWasm(VotePoll::ContestedDocumentResourceVotePoll( ContestedDocumentResourceVotePoll { - contract_id, - document_type_name, - index_name, + contract_id: contract_id.into(), + document_type_name: opts.document_type_name, + index_name: opts.index_name, index_values, }, ))) @@ -121,10 +165,9 @@ impl VotePollWasm { #[wasm_bindgen(setter = "contractId")] pub fn set_contract_id( &mut self, - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - js_contract_id: &JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> WasmDppResult<()> { - let contract_id = IdentifierWasm::try_from(js_contract_id)?.into(); + let contract_id = contract_id.try_into()?; self.0 = match self.0.clone() { VotePoll::ContestedDocumentResourceVotePoll(mut poll) => { @@ -138,7 +181,10 @@ impl VotePollWasm { } #[wasm_bindgen(setter = "documentTypeName")] - pub fn set_document_type_name(&mut self, document_type_name: String) { + pub fn set_document_type_name( + &mut self, + #[wasm_bindgen(js_name = "documentTypeName")] document_type_name: String, + ) { self.0 = match self.0.clone() { VotePoll::ContestedDocumentResourceVotePoll(mut poll) => { poll.document_type_name = document_type_name; @@ -149,7 +195,7 @@ impl VotePollWasm { } #[wasm_bindgen(setter = "indexName")] - pub fn set_index_name(&mut self, index_name: String) { + pub fn set_index_name(&mut self, #[wasm_bindgen(js_name = "indexName")] index_name: String) { self.0 = match self.0.clone() { VotePoll::ContestedDocumentResourceVotePoll(mut poll) => { poll.index_name = index_name; @@ -160,15 +206,19 @@ impl VotePollWasm { } #[wasm_bindgen(setter = "indexValues")] - pub fn set_index_values(&mut self, js_index_values: JsValue) -> WasmDppResult<()> { - let index_values = js_index_values + pub fn set_index_values( + &mut self, + #[wasm_bindgen(js_name = "indexValues")] index_values: js_sys::Array, + ) -> WasmDppResult<()> { + let js_value: JsValue = index_values.into(); + let values = js_value .with_serde_to_platform_value()? .into_array() .map_err(|err| WasmDppError::invalid_argument(err.to_string()))?; self.0 = match self.0.clone() { VotePoll::ContestedDocumentResourceVotePoll(mut poll) => { - poll.index_values = index_values; + poll.index_values = values; VotePoll::ContestedDocumentResourceVotePoll(poll) } @@ -178,5 +228,7 @@ impl VotePollWasm { } } -impl_try_from_options!(VotePollWasm, "VotePoll"); -impl_wasm_conversions!(VotePollWasm, VotePoll); +impl_try_from_js_value!(VotePollWasm, "VotePoll"); +impl_try_from_options!(VotePollWasm); +impl_wasm_conversions!(VotePollWasm, VotePoll, VotePollObjectJs, VotePollJSONJs); +impl_wasm_type_info!(VotePollWasm, VotePoll); diff --git a/packages/wasm-dpp2/src/voting/winner_info.rs b/packages/wasm-dpp2/src/voting/winner_info.rs index 858d84d8d3e..7d41453be31 100644 --- a/packages/wasm-dpp2/src/voting/winner_info.rs +++ b/packages/wasm-dpp2/src/voting/winner_info.rs @@ -1,9 +1,40 @@ use crate::identifier::IdentifierWasm; use crate::impl_wasm_conversions; +use crate::impl_wasm_type_info; use dpp::voting::vote_info_storage::contested_document_vote_poll_winner_info::ContestedDocumentVotePollWinnerInfo; use wasm_bindgen::JsValue; use wasm_bindgen::prelude::wasm_bindgen; +#[wasm_bindgen(typescript_custom_section)] +const TS_TYPES: &str = r#" +/** + * ContestedDocumentVotePollWinnerInfo serialized as a plain object. + * Simple variants serialize as strings, tuple variant as { WonByIdentity: value }. + */ +export type ContestedDocumentVotePollWinnerInfoObject = + | "NoWinner" + | "Locked" + | { WonByIdentity: Uint8Array }; + +/** + * ContestedDocumentVotePollWinnerInfo serialized as JSON. + * Simple variants serialize as strings, tuple variant as { WonByIdentity: value }. + */ +export type ContestedDocumentVotePollWinnerInfoJSON = + | "NoWinner" + | "Locked" + | { WonByIdentity: string }; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ContestedDocumentVotePollWinnerInfoObject")] + pub type ContestedDocumentVotePollWinnerInfoObjectJs; + + #[wasm_bindgen(typescript_type = "ContestedDocumentVotePollWinnerInfoJSON")] + pub type ContestedDocumentVotePollWinnerInfoJSONJs; +} + #[derive(Clone, Copy)] #[wasm_bindgen(js_name = "ContestedDocumentVotePollWinnerInfo")] pub struct ContestedDocumentVotePollWinnerInfoWasm(ContestedDocumentVotePollWinnerInfo); @@ -23,9 +54,9 @@ impl From for ContestedDocumentVotePoll #[wasm_bindgen(js_class = ContestedDocumentVotePollWinnerInfo)] impl ContestedDocumentVotePollWinnerInfoWasm { #[wasm_bindgen(constructor)] - pub fn new( + pub fn constructor( kind: &str, - identity_id: Option, + #[wasm_bindgen(js_name = "identityId")] identity_id: Option, ) -> Result { match kind { "NoWinner" | "noWinner" | "no_winner" | "none" | "NO_WINNER" => { @@ -68,12 +99,12 @@ impl ContestedDocumentVotePollWinnerInfoWasm { } } - #[wasm_bindgen(js_name = "isLocked")] + #[wasm_bindgen(getter = "isLocked")] pub fn is_locked(&self) -> bool { matches!(self.0, ContestedDocumentVotePollWinnerInfo::Locked) } - #[wasm_bindgen(js_name = "isWonByIdentity")] + #[wasm_bindgen(getter = "isWonByIdentity")] pub fn is_won_by_identity(&self) -> bool { matches!( self.0, @@ -81,13 +112,20 @@ impl ContestedDocumentVotePollWinnerInfoWasm { ) } - #[wasm_bindgen(js_name = "isNoWinner")] + #[wasm_bindgen(getter = "isNoWinner")] pub fn is_no_winner(&self) -> bool { matches!(self.0, ContestedDocumentVotePollWinnerInfo::NoWinner) } } impl_wasm_conversions!( + ContestedDocumentVotePollWinnerInfoWasm, + ContestedDocumentVotePollWinnerInfo, + ContestedDocumentVotePollWinnerInfoObjectJs, + ContestedDocumentVotePollWinnerInfoJSONJs +); + +impl_wasm_type_info!( ContestedDocumentVotePollWinnerInfoWasm, ContestedDocumentVotePollWinnerInfo ); diff --git a/packages/wasm-dpp2/tests/.eslintrc.yml b/packages/wasm-dpp2/tests/.eslintrc.yml deleted file mode 100644 index 2a3dfdadb80..00000000000 --- a/packages/wasm-dpp2/tests/.eslintrc.yml +++ /dev/null @@ -1,40 +0,0 @@ -extends: - - airbnb-base - - plugin:jsdoc/recommended -env: - es2020: true - node: true - mocha: true -parserOptions: - ecmaVersion: 2024 -rules: - eol-last: - - error - - always - import/extensions: off - class-methods-use-this: off - import/no-extraneous-dependencies: off - import/no-named-as-default: off - import/named: off - import/prefer-default-export: off - max-len: off - no-bitwise: off - no-underscore-dangle: off - no-unused-expressions: off - jsdoc/require-returns: off - comma-dangle: off - func-names: off - import/newline-after-import: off - prefer-arrow-callback: off - semi: off - curly: - - error - - all - no-restricted-syntax: - - error - - selector: "LabeledStatement" - message: Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand. - - selector: "WithStatement" - message: "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." -globals: - expect: true diff --git a/packages/wasm-dpp2/tests/karma/karma.conf.cjs b/packages/wasm-dpp2/tests/karma/karma.conf.cjs index 60f9d58a839..5c5dc822196 100644 --- a/packages/wasm-dpp2/tests/karma/karma.conf.cjs +++ b/packages/wasm-dpp2/tests/karma/karma.conf.cjs @@ -5,11 +5,11 @@ module.exports = (config) => { ...options, files: [ '../bootstrap.cjs', - '../unit/**/*.spec.mjs', + '../unit/**/*.spec.ts', ], preprocessors: { '../bootstrap.cjs': ['webpack'], - '../unit/**/*.spec.mjs': ['webpack'], + '../unit/**/*.spec.ts': ['webpack'], }, }); }; diff --git a/packages/wasm-dpp2/tests/karma/options.cjs b/packages/wasm-dpp2/tests/karma/options.cjs index 1e80694a7fa..4c477d2fd3f 100644 --- a/packages/wasm-dpp2/tests/karma/options.cjs +++ b/packages/wasm-dpp2/tests/karma/options.cjs @@ -1,4 +1,4 @@ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable import-x/no-extraneous-dependencies */ const webpack = require('webpack'); const karmaMocha = require('karma-mocha'); const karmaMochaReporter = require('karma-mocha-reporter'); @@ -12,6 +12,21 @@ module.exports = { webpack: { mode: 'development', devtool: 'eval', + module: { + rules: [ + { + test: /\.ts$/, + use: { + loader: 'ts-loader', + options: { + transpileOnly: true, + configFile: require.resolve('../tsconfig.json'), + }, + }, + exclude: /node_modules/, + }, + ], + }, plugins: [ new webpack.ProvidePlugin({ Buffer: [require.resolve('buffer/'), 'Buffer'], @@ -19,7 +34,7 @@ module.exports = { }), ], resolve: { - extensions: ['.mjs', '.js'], + extensions: ['.ts', '.mjs', '.js'], fallback: { fs: false, path: require.resolve('path-browserify'), diff --git a/packages/wasm-dpp2/tests/tsconfig.json b/packages/wasm-dpp2/tests/tsconfig.json new file mode 100644 index 00000000000..a459d1c1da5 --- /dev/null +++ b/packages/wasm-dpp2/tests/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "declaration": false, + "noEmit": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "types": ["mocha", "chai", "node"], + "baseUrl": ".", + "paths": { + "@dashevo/wasm-dpp2": ["../dist/dpp.d.ts"] + } + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "node_modules", + "karma" + ] +} diff --git a/packages/wasm-dpp2/tests/unit/AddressFundsTransfer.spec.mjs b/packages/wasm-dpp2/tests/unit/AddressFundsTransfer.spec.ts similarity index 87% rename from packages/wasm-dpp2/tests/unit/AddressFundsTransfer.spec.mjs rename to packages/wasm-dpp2/tests/unit/AddressFundsTransfer.spec.ts index 0533f0dfd42..e510d44623c 100644 --- a/packages/wasm-dpp2/tests/unit/AddressFundsTransfer.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/AddressFundsTransfer.spec.ts @@ -1,38 +1,39 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('FeeStrategyStep', () => { - describe('construction', () => { + describe('deductFromInput()', () => { it('should create deductFromInput step', () => { const step = wasm.FeeStrategyStep.deductFromInput(0); - expect(step).to.exist; - expect(step.isDeductFromInput).to.be.true; - expect(step.isReduceOutput).to.be.false; + expect(step).to.exist(); + expect(step.isDeductFromInput).to.be.true(); + expect(step.isReduceOutput).to.be.false(); expect(step.index).to.equal(0); }); it('should create deductFromInput step with non-zero index', () => { const step = wasm.FeeStrategyStep.deductFromInput(5); - expect(step.isDeductFromInput).to.be.true; + expect(step.isDeductFromInput).to.be.true(); expect(step.index).to.equal(5); }); + }); + describe('reduceOutput()', () => { it('should create reduceOutput step', () => { const step = wasm.FeeStrategyStep.reduceOutput(0); - expect(step).to.exist; - expect(step.isDeductFromInput).to.be.false; - expect(step.isReduceOutput).to.be.true; + expect(step).to.exist(); + expect(step.isDeductFromInput).to.be.false(); + expect(step.isReduceOutput).to.be.true(); expect(step.index).to.equal(0); }); it('should create reduceOutput step with non-zero index', () => { const step = wasm.FeeStrategyStep.reduceOutput(3); - expect(step.isReduceOutput).to.be.true; + expect(step.isReduceOutput).to.be.true(); expect(step.index).to.equal(3); }); }); @@ -44,7 +45,7 @@ describe.skip('AddressFundsTransferTransition', () => { const testPrivateKeyHex = 'c9d9d0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd'; const testPrivateKeyHex2 = 'a9d9d0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd'; - describe('build', () => { + describe('build()', () => { it('should build a transfer transition with single input and output', () => { // Create output address const outputAddrBytes = new Uint8Array([0x00, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]); @@ -66,8 +67,8 @@ describe.skip('AddressFundsTransferTransition', () => { signer, }); - expect(transition).to.exist; - expect(transition.__wbg_ptr).to.not.equal(0); + expect(transition).to.exist(); + expect(transition).to.be.an.instanceof(wasm.AddressFundsTransferTransition); }); it('should build a transfer transition with multiple inputs and outputs', () => { @@ -100,7 +101,7 @@ describe.skip('AddressFundsTransferTransition', () => { signer, }); - expect(transition).to.exist; + expect(transition).to.exist(); }); it('should build with custom fee strategy', () => { @@ -124,7 +125,7 @@ describe.skip('AddressFundsTransferTransition', () => { feeStrategy, }); - expect(transition).to.exist; + expect(transition).to.exist(); }); it('should build with user fee increase', () => { @@ -145,7 +146,7 @@ describe.skip('AddressFundsTransferTransition', () => { userFeeIncrease: 100, }); - expect(transition).to.exist; + expect(transition).to.exist(); }); it('should fail without inputs', () => { @@ -163,7 +164,7 @@ describe.skip('AddressFundsTransferTransition', () => { }); expect.fail('Should have thrown error for missing inputs'); } catch (error) { - expect(error.message).to.include('input'); + expect((error as Error).message).to.include('input'); } }); @@ -182,7 +183,7 @@ describe.skip('AddressFundsTransferTransition', () => { }); expect.fail('Should have thrown error for missing outputs'); } catch (error) { - expect(error.message).to.include('output'); + expect((error as Error).message).to.include('output'); } }); @@ -202,7 +203,7 @@ describe.skip('AddressFundsTransferTransition', () => { }); expect.fail('Should have thrown error for missing signer'); } catch (error) { - expect(error.message).to.include('signer'); + expect((error as Error).message).to.include('signer'); } }); }); diff --git a/packages/wasm-dpp2/tests/unit/AssetLockProof.spec.mjs b/packages/wasm-dpp2/tests/unit/AssetLockProof.spec.ts similarity index 64% rename from packages/wasm-dpp2/tests/unit/AssetLockProof.spec.mjs rename to packages/wasm-dpp2/tests/unit/AssetLockProof.spec.ts index 2c043033097..289819ceaaa 100644 --- a/packages/wasm-dpp2/tests/unit/AssetLockProof.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/AssetLockProof.spec.ts @@ -1,55 +1,77 @@ -import getWasm from './helpers/wasm.js'; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; import { instantLockBytes, transactionBytes } from './mocks/Locks/index.js'; -let wasm; - before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('AssetLockProof', () => { - describe('serialization / deserialization', () => { + describe('constructor()', () => { it('should allow to get instant lock proof via constructor', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); const chainlock = new wasm.ChainAssetLockProof(11, outpoint); - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); const instantAssetLock = new wasm.AssetLockProof(instantLockProof); const chainAssetLock = new wasm.AssetLockProof(chainlock); expect(instantAssetLock.constructor.name).to.equal('AssetLockProof'); - expect(instantAssetLock.__wbg_ptr).to.not.equal(0); + expect(instantAssetLock).to.be.an.instanceof(wasm.AssetLockProof); expect(chainAssetLock.constructor.name).to.equal('AssetLockProof'); - expect(chainAssetLock.__wbg_ptr).to.not.equal(0); + expect(chainAssetLock).to.be.an.instanceof(wasm.AssetLockProof); }); - it('shouldn\'t allow to get chain lock proof via constructor', () => { + it('should not allow to get chain lock proof via constructor with invalid argument', () => { try { - // eslint-disable-next-line - new wasm.AssetLockProof('chain') - } catch (e) { - expect(true).to.be.ok; + new (wasm.AssetLockProof as any)('chain'); + } catch { + expect(true).to.be.ok(); return; } expect.fail('Expected an error to be thrown'); }); + }); + describe('createInstantAssetLockProof()', () => { it('should allow to create instant lock proof from values', () => { - const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof(instantLockBytes, transactionBytes, 0); + const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); expect(instantLockProof.constructor.name).to.equal('AssetLockProof'); }); + }); + describe('createChainAssetLockProof()', () => { it('should allow to create chain lock proof from values', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); expect(chainLockProof.constructor.name).to.equal('AssetLockProof'); }); + }); + describe('toHex()', () => { it('should allow to serialize and deserialize asset lock in hex', () => { - const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof(instantLockBytes, transactionBytes, 0); + const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); const newInstantLockProof = wasm.AssetLockProof.fromHex(instantLockProof.toHex()); @@ -60,7 +82,10 @@ describe('AssetLockProof', () => { }); it('should allow to serialize and deserialize asset lock in hex for chain proofs', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); const newChainLockProof = wasm.AssetLockProof.fromHex(chainLockProof.toHex()); @@ -70,9 +95,15 @@ describe('AssetLockProof', () => { expect(newChainLockProof.toObject()).to.deep.equal(chainLockProof.toObject()); }); + }); + describe('toBytes()', () => { it('should round-trip asset lock via bytes for instant proofs', () => { - const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof(instantLockBytes, transactionBytes, 0); + const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); const bytes = instantLockProof.toBytes(); const restored = wasm.AssetLockProof.fromBytes(bytes); @@ -81,7 +112,10 @@ describe('AssetLockProof', () => { }); it('should round-trip asset lock via bytes for chain proofs', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); const bytes = chainLockProof.toBytes(); @@ -89,9 +123,15 @@ describe('AssetLockProof', () => { expect(restored.toObject()).to.deep.equal(chainLockProof.toObject()); }); + }); + describe('toObject()', () => { it('should recreate asset lock proof from object', () => { - const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof(instantLockBytes, transactionBytes, 0); + const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); const objectRepresentation = instantLockProof.toObject(); const restoredProof = wasm.AssetLockProof.fromObject(objectRepresentation); @@ -99,37 +139,12 @@ describe('AssetLockProof', () => { expect(restoredProof.toObject()).to.deep.equal(objectRepresentation); }); - it('should recreate asset lock proof from JSON', () => { - const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof(instantLockBytes, transactionBytes, 0); - const jsonRepresentation = instantLockProof.toJSON(); - - // Should have type field (0 = Instant) - expect(jsonRepresentation.type).to.equal(0); - expect(jsonRepresentation.instantLock).to.be.a('string'); - expect(jsonRepresentation.transaction).to.be.a('string'); - expect(Buffer.from(jsonRepresentation.instantLock, 'base64')).to.deep.equal(Buffer.from(instantLockBytes)); - expect(Buffer.from(jsonRepresentation.transaction, 'base64')).to.deep.equal(Buffer.from(transactionBytes)); - - const restoredProof = wasm.AssetLockProof.fromJSON(jsonRepresentation); - - expect(restoredProof.toObject()).to.deep.equal(instantLockProof.toObject()); - }); - - it('should recreate chain asset lock proof from JSON', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); - const jsonRepresentation = chainLockProof.toJSON(); - - // Should have type field (1 = Chain) - expect(jsonRepresentation.type).to.equal(1); - - const restoredProof = wasm.AssetLockProof.fromJSON(jsonRepresentation); - - expect(restoredProof.toObject()).to.deep.equal(chainLockProof.toObject()); - }); - it('should export binary fields as Uint8Array in object form with type field', () => { - const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof(instantLockBytes, transactionBytes, 0); + const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); const objectRepresentation = instantLockProof.toObject(); @@ -142,7 +157,10 @@ describe('AssetLockProof', () => { }); it('should export chain lock proof object with type field', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); const objectRepresentation = chainLockProof.toObject(); @@ -152,36 +170,16 @@ describe('AssetLockProof', () => { expect(objectRepresentation.coreChainLockedHeight).to.equal(1); // outPoint is {txid, vout} object expect(objectRepresentation.outPoint).to.be.an('object'); - expect(objectRepresentation.outPoint.txid).to.exist; + expect(objectRepresentation.outPoint.txid).to.exist(); expect(objectRepresentation.outPoint.vout).to.equal(1); }); - }); - - describe('getters', () => { - it('should allow to get lock type', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - const instantAssetLockProof = new wasm.AssetLockProof(instantLockProof); - const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); - - expect(instantAssetLockProof.getLockType()).to.equal('Instant'); - expect(chainLockProof.getLockType()).to.equal('Chain'); - }); - - it('should allow to get lock instances', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); - const instantAssetLockProof = new wasm.AssetLockProof(instantLockProof); - - expect(chainLockProof.getChainLockProof().constructor.name).to.equal('ChainAssetLockProof'); - expect(instantAssetLockProof.getInstantLockProof().constructor.name).to.equal('InstantAssetLockProof'); - }); it('should allow to return object of lock', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); const instantAssetLockProof = new wasm.AssetLockProof(instantLockProof); @@ -202,4 +200,95 @@ describe('AssetLockProof', () => { expect(instantAssetLockProof.toObject()).to.deep.equal(expectedOuter); }); }); + + describe('toJSON()', () => { + it('should recreate asset lock proof from JSON', () => { + const instantLockProof = wasm.AssetLockProof.createInstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + const jsonRepresentation = instantLockProof.toJSON(); + + // Should have type field (0 = Instant) + expect(jsonRepresentation.type).to.equal(0); + expect(jsonRepresentation.instantLock).to.be.a('string'); + expect(jsonRepresentation.transaction).to.be.a('string'); + expect(Buffer.from(jsonRepresentation.instantLock, 'base64')).to.deep.equal( + Buffer.from(instantLockBytes), + ); + expect(Buffer.from(jsonRepresentation.transaction, 'base64')).to.deep.equal( + Buffer.from(transactionBytes), + ); + + const restoredProof = wasm.AssetLockProof.fromJSON(jsonRepresentation); + + expect(restoredProof.toObject()).to.deep.equal(instantLockProof.toObject()); + }); + + it('should recreate chain asset lock proof from JSON', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); + const jsonRepresentation = chainLockProof.toJSON(); + + // Should have type field (1 = Chain) + expect(jsonRepresentation.type).to.equal(1); + + const restoredProof = wasm.AssetLockProof.fromJSON(jsonRepresentation); + + expect(restoredProof.toObject()).to.deep.equal(chainLockProof.toObject()); + }); + }); + + describe('lockTypeName', () => { + it('should allow to get lock type', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const instantAssetLockProof = new wasm.AssetLockProof(instantLockProof); + const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); + + expect(instantAssetLockProof.lockTypeName).to.equal('Instant'); + expect(chainLockProof.lockTypeName).to.equal('Chain'); + }); + }); + + describe('chainLockProof', () => { + it('should allow to get chain lock proof instance', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + + const chainLockProof = wasm.AssetLockProof.createChainAssetLockProof(1, outpoint); + + expect(chainLockProof.chainLockProof.constructor.name).to.equal('ChainAssetLockProof'); + }); + }); + + describe('instantLockProof', () => { + it('should allow to get instant lock proof instance', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const instantAssetLockProof = new wasm.AssetLockProof(instantLockProof); + + expect(instantAssetLockProof.instantLockProof.constructor.name).to.equal( + 'InstantAssetLockProof', + ); + }); + }); }); diff --git a/packages/wasm-dpp2/tests/unit/AuthorizedActionTakers.spec.mjs b/packages/wasm-dpp2/tests/unit/AuthorizedActionTakers.spec.mjs deleted file mode 100644 index a4bdb274b1d..00000000000 --- a/packages/wasm-dpp2/tests/unit/AuthorizedActionTakers.spec.mjs +++ /dev/null @@ -1,79 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { identifier } from './mocks/Identity/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('AuthorizedActionTakers', () => { - describe('serialization / deserialization', () => { - it('should allows to create AuthorizedActionTakers with NoOne', () => { - const actionTaker = wasm.AuthorizedActionTakers.NoOne(); - - expect(actionTaker.__wbg_ptr).to.not.equal(0); - expect(actionTaker.getTakerType()).to.deep.equal('NoOne'); - }); - - it('should allows to create AuthorizedActionTakers with ContractOwner', () => { - const actionTaker = wasm.AuthorizedActionTakers.ContractOwner(); - - expect(actionTaker.__wbg_ptr).to.not.equal(0); - expect(actionTaker.getTakerType()).to.deep.equal('ContractOwner'); - }); - - it('should allows to create AuthorizedActionTakers with Identity', () => { - const actionTaker = wasm.AuthorizedActionTakers.Identity(identifier); - - expect(actionTaker.__wbg_ptr).to.not.equal(0); - expect(actionTaker.getTakerType()).to.deep.equal(`Identity(${identifier})`); - }); - - it('should allows to create AuthorizedActionTakers with MainGroup', () => { - const actionTaker = wasm.AuthorizedActionTakers.MainGroup(); - - expect(actionTaker.__wbg_ptr).to.not.equal(0); - expect(actionTaker.getTakerType()).to.deep.equal('MainGroup'); - }); - - it('should allows to create AuthorizedActionTakers with Group', () => { - const actionTaker = wasm.AuthorizedActionTakers.Group(12); - - expect(actionTaker.__wbg_ptr).to.not.equal(0); - expect(actionTaker.getTakerType()).to.deep.equal('Group(12)'); - }); - }); - - describe('getters', () => { - it('should allows to get value with NoOne', () => { - const actionTaker = wasm.AuthorizedActionTakers.NoOne(); - - expect(actionTaker.getValue()).to.deep.equal(undefined); - }); - - it('should allows to get value with ContractOwner', () => { - const actionTaker = wasm.AuthorizedActionTakers.ContractOwner(); - - expect(actionTaker.getValue()).to.deep.equal(undefined); - }); - - it('should allows to get value with Identity', () => { - const actionTaker = wasm.AuthorizedActionTakers.Identity(identifier); - - expect(actionTaker.getValue().toBase58()).to.deep.equal(identifier); - }); - - it('should allows to get value with MainGroup', () => { - const actionTaker = wasm.AuthorizedActionTakers.MainGroup(); - - expect(actionTaker.getValue()).to.deep.equal(undefined); - }); - - it('should allows to get value with Group', () => { - const actionTaker = wasm.AuthorizedActionTakers.Group(12); - - expect(actionTaker.getValue()).to.deep.equal(12); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/AuthorizedActionTakers.spec.ts b/packages/wasm-dpp2/tests/unit/AuthorizedActionTakers.spec.ts new file mode 100644 index 00000000000..d373447e889 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/AuthorizedActionTakers.spec.ts @@ -0,0 +1,86 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { identifier } from './mocks/Identity/index.js'; + +before(async () => { + await initWasm(); +}); + +describe('AuthorizedActionTakers', () => { + describe('NoOne()', () => { + it('should allow to create AuthorizedActionTakers with NoOne', () => { + const actionTaker = wasm.AuthorizedActionTakers.NoOne(); + + expect(actionTaker).to.be.an.instanceof(wasm.AuthorizedActionTakers); + expect(actionTaker.takerType).to.deep.equal('NoOne'); + }); + }); + + describe('ContractOwner()', () => { + it('should allow to create AuthorizedActionTakers with ContractOwner', () => { + const actionTaker = wasm.AuthorizedActionTakers.ContractOwner(); + + expect(actionTaker).to.be.an.instanceof(wasm.AuthorizedActionTakers); + expect(actionTaker.takerType).to.deep.equal('ContractOwner'); + }); + }); + + describe('Identity()', () => { + it('should allow to create AuthorizedActionTakers with Identity', () => { + const actionTaker = wasm.AuthorizedActionTakers.Identity(identifier); + + expect(actionTaker).to.be.an.instanceof(wasm.AuthorizedActionTakers); + expect(actionTaker.takerType).to.deep.equal(`Identity(${identifier})`); + }); + }); + + describe('MainGroup()', () => { + it('should allow to create AuthorizedActionTakers with MainGroup', () => { + const actionTaker = wasm.AuthorizedActionTakers.MainGroup(); + + expect(actionTaker).to.be.an.instanceof(wasm.AuthorizedActionTakers); + expect(actionTaker.takerType).to.deep.equal('MainGroup'); + }); + }); + + describe('Group()', () => { + it('should allow to create AuthorizedActionTakers with Group', () => { + const actionTaker = wasm.AuthorizedActionTakers.Group(12); + + expect(actionTaker).to.be.an.instanceof(wasm.AuthorizedActionTakers); + expect(actionTaker.takerType).to.deep.equal('Group(12)'); + }); + }); + + describe('value', () => { + it('should allow to get value with NoOne', () => { + const actionTaker = wasm.AuthorizedActionTakers.NoOne(); + + expect(actionTaker.value).to.deep.equal(undefined); + }); + + it('should allow to get value with ContractOwner', () => { + const actionTaker = wasm.AuthorizedActionTakers.ContractOwner(); + + expect(actionTaker.value).to.deep.equal(undefined); + }); + + it('should allow to get value with Identity', () => { + const actionTaker = wasm.AuthorizedActionTakers.Identity(identifier); + + expect(actionTaker.value.toBase58()).to.deep.equal(identifier); + }); + + it('should allow to get value with MainGroup', () => { + const actionTaker = wasm.AuthorizedActionTakers.MainGroup(); + + expect(actionTaker.value).to.deep.equal(undefined); + }); + + it('should allow to get value with Group', () => { + const actionTaker = wasm.AuthorizedActionTakers.Group(12); + + expect(actionTaker.value).to.deep.equal(12); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/BatchTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/BatchTransition.spec.mjs deleted file mode 100644 index 66b2d066a56..00000000000 --- a/packages/wasm-dpp2/tests/unit/BatchTransition.spec.mjs +++ /dev/null @@ -1,199 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { - document, documentTypeName, revision, dataContractId, ownerId, id, -} from './mocks/Document/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('BatchTransition', () => { - describe('serialization / deserialization', () => { - describe('documents', () => { - it('should allow to create from v0 transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchedTransition = new wasm.BatchedTransition(documentTransition); - - const batch = wasm.BatchTransition.fromBatchedTransitions([batchedTransition, batchedTransition], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(createTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batch.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create from v1 transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchedTransition = new wasm.BatchedTransition(documentTransition); - - const batch = wasm.BatchTransition.fromBatchedTransitions([batchedTransition, batchedTransition], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(createTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchedTransition.__wbg_ptr).to.not.equal(0); - expect(batch.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to convert batch transition to base64 and back', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchedTransition = new wasm.BatchedTransition(documentTransition); - - const batch = wasm.BatchTransition.fromBatchedTransitions([batchedTransition], documentInstance.ownerId, 1); - - const base64 = batch.toBase64(); - const bytes = batch.toBytes(); - - expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); - - const restoredBatch = wasm.BatchTransition.fromBase64(base64); - - expect(Buffer.from(restoredBatch.toBytes())).to.deep.equal(Buffer.from(bytes)); - }); - - it('should round-trip via object and JSON', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - const batchedTransition = new wasm.BatchedTransition(documentTransition); - - const batch = wasm.BatchTransition.fromBatchedTransitions([batchedTransition], documentInstance.ownerId, 1); - - const object = batch.toObject(); - expect(object.signature).to.be.instanceOf(Uint8Array); - - // Note: fromObject with complex nested structures containing Value fields - // requires special handling due to serde_wasm_bindgen byte serialization. - // Use fromJSON for reliable round-trip serialization. - - const json = batch.toJSON(); - expect(json.signature).to.be.a('string'); - - const fromJson = wasm.BatchTransition.fromJSON(json); - expect(Buffer.from(fromJson.toBytes())).to.deep.equal(Buffer.from(batch.toBytes())); - }); - }); - describe('tokens', () => { - it('should allow to create from v1 transition', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId); - - const mintTransition = new wasm.TokenMintTransition(baseTransition, ownerId, BigInt(9999), 'bbbbbb'); - - const transition = new wasm.TokenTransition(mintTransition); - - const batchedTransition = new wasm.BatchedTransition(transition); - - const batch = wasm.BatchTransition.fromBatchedTransitions([batchedTransition, batchedTransition], ownerId, 1); - - expect(baseTransition.__wbg_ptr).to.not.equal(0); - expect(mintTransition.__wbg_ptr).to.not.equal(0); - expect(transition.__wbg_ptr).to.not.equal(0); - expect(batchedTransition.__wbg_ptr).to.not.equal(0); - expect(batch.__wbg_ptr).to.not.equal(0); - }); - }); - }); - - describe('getters', () => { - it('should allow to get transitions', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchedTransition = new wasm.BatchedTransition(documentTransition); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([batchedTransition, batchedTransition], documentInstance.ownerId, 1); - - expect(batchTransition.transitions.length).to.equal(2); - }); - - it('should allow to get signature', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchedTransition = new wasm.BatchedTransition(documentTransition); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([batchedTransition, batchedTransition], documentInstance.ownerId, 1); - - expect(batchTransition.signature).to.deep.equal(new Uint8Array(0)); - }); - - it('should allow to get signature public key id', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchedTransition = new wasm.BatchedTransition(documentTransition); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([batchedTransition, batchedTransition], documentInstance.ownerId, 1); - batchTransition.signaturePublicKeyId = 1; - - expect(batchTransition.signaturePublicKeyId).to.equal(1); - }); - - it('should allow to get all purchases amount', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - const documentTransition = createTransition.toDocumentTransition(); - const documentTransition2 = purchaseTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition2)], documentInstance.ownerId, 1); - - expect(batchTransition.allPurchasesAmount).to.deep.equal(BigInt(100)); - }); - - it('should allow to get owner id', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(batchTransition.ownerId.toBase58()).to.deep.equal(documentInstance.ownerId.toBase58()); - }); - - it('should allow to get modified data ids', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(batchTransition.modifiedDataIds.map((identifier) => identifier.toBase58())).to.deep.equal([documentTransition.id.toBase58(), documentTransition.id.toBase58()]); - }); - - it('should allow to get allConflictingIndexCollateralVotingFunds', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(batchTransition.allConflictingIndexCollateralVotingFunds).to.deep.equal(undefined); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/BatchTransition.spec.ts b/packages/wasm-dpp2/tests/unit/BatchTransition.spec.ts new file mode 100644 index 00000000000..e1f8707609f --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/BatchTransition.spec.ts @@ -0,0 +1,342 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { + document, documentTypeName, revision, dataContractId, ownerId, id, +} from './mocks/Document/index.js'; + +before(async () => { + await initWasm(); +}); + +interface DocumentOptions { + properties?: Record; + documentTypeName?: string; + dataContractId?: InstanceType; + ownerId?: InstanceType; + revision?: bigint; + id?: InstanceType; +} + +interface TokenBaseTransitionOptions { + identityContractNonce?: bigint; + tokenContractPosition?: number; + dataContractId?: InstanceType; + tokenId?: InstanceType; +} + +describe('BatchTransition', () => { + // Helper to create a document with options object + function createDocument(options: DocumentOptions = {}) { + return new wasm.Document({ + properties: options.properties ?? document, + documentTypeName: options.documentTypeName ?? documentTypeName, + dataContractId: options.dataContractId ?? dataContractId, + ownerId: options.ownerId ?? ownerId, + revision: options.revision ?? BigInt(revision), + id: options.id ?? id, + }); + } + + // Helper to create a token base transition with options object + function createTokenBaseTransition(options: TokenBaseTransitionOptions = {}) { + return new wasm.TokenBaseTransition({ + identityContractNonce: options.identityContractNonce ?? BigInt(1), + tokenContractPosition: options.tokenContractPosition ?? 1, + dataContractId: options.dataContractId ?? dataContractId, + tokenId: options.tokenId ?? ownerId, + }); + } + + describe('fromBatchedTransitions()', () => { + describe('documents', () => { + it('should create batch transition from document transitions', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batch = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition, batchedTransition], + documentInstance.ownerId, + 1, + ); + + expect(documentInstance).to.be.an.instanceof(wasm.Document); + expect(createTransition).to.be.an.instanceof(wasm.DocumentCreateTransition); + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + expect(batchedTransition).to.be.an.instanceof(wasm.BatchedTransition); + expect(batch).to.be.an.instanceof(wasm.BatchTransition); + }); + }); + + describe('tokens', () => { + it('should create batch transition from v1 transition', () => { + const baseTransition = createTokenBaseTransition(); + + const mintTransition = new wasm.TokenMintTransition({ base: baseTransition, issuedToIdentityId: ownerId, amount: BigInt(9999), publicNote: 'bbbbbb' }); + + const transition = new wasm.TokenTransition(mintTransition); + + const batchedTransition = new wasm.BatchedTransition(transition); + + const batch = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition, batchedTransition], + ownerId, + 1, + ); + + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + expect(mintTransition).to.be.an.instanceof(wasm.TokenMintTransition); + expect(transition).to.be.an.instanceof(wasm.TokenTransition); + expect(batchedTransition).to.be.an.instanceof(wasm.BatchedTransition); + expect(batch).to.be.an.instanceof(wasm.BatchTransition); + }); + }); + }); + + describe('toBase64()', () => { + it('should convert batch transition to base64', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batch = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition], + documentInstance.ownerId, + 1, + ); + + const base64 = batch.toBase64(); + const bytes = batch.toBytes(); + + expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('fromBase64()', () => { + it('should create batch transition from base64', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batch = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition], + documentInstance.ownerId, + 1, + ); + + const base64 = batch.toBase64(); + const bytes = batch.toBytes(); + + const restoredBatch = wasm.BatchTransition.fromBase64(base64); + + expect(Buffer.from(restoredBatch.toBytes())).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('toObject()', () => { + it('should convert batch transition to object', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batch = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition], + documentInstance.ownerId, + 1, + ); + + const object = batch.toObject(); + expect(object.signature).to.be.instanceOf(Uint8Array); + }); + }); + + describe('toJSON()', () => { + it('should convert batch transition to JSON', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batch = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition], + documentInstance.ownerId, + 1, + ); + + const json = batch.toJSON(); + expect(json.signature).to.be.a('string'); + }); + }); + + describe('fromJSON()', () => { + it('should create batch transition from JSON', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batch = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition], + documentInstance.ownerId, + 1, + ); + + // Note: fromObject with complex nested structures containing Value fields + // requires special handling due to serde_wasm_bindgen byte serialization. + // Use fromJSON for reliable round-trip serialization. + + const json = batch.toJSON(); + + const fromJson = wasm.BatchTransition.fromJSON(json); + expect(Buffer.from(fromJson.toBytes())).to.deep.equal(Buffer.from(batch.toBytes())); + }); + }); + + describe('transitions', () => { + it('should return transitions', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition, batchedTransition], + documentInstance.ownerId, + 1, + ); + + expect(batchTransition.transitions.length).to.equal(2); + }); + }); + + describe('signature', () => { + it('should return signature', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition, batchedTransition], + documentInstance.ownerId, + 1, + ); + + expect(batchTransition.signature).to.deep.equal(new Uint8Array(0)); + }); + }); + + describe('signaturePublicKeyId', () => { + it('should return signaturePublicKeyId', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchedTransition = new wasm.BatchedTransition(documentTransition); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [batchedTransition, batchedTransition], + documentInstance.ownerId, + 1, + ); + batchTransition.signaturePublicKeyId = 1; + + expect(batchTransition.signaturePublicKeyId).to.equal(1); + }); + }); + + describe('allPurchasesAmount', () => { + it('should return allPurchasesAmount', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + const documentTransition = createTransition.toDocumentTransition(); + const documentTransition2 = purchaseTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition2)], + documentInstance.ownerId, + 1, + ); + + expect(batchTransition.allPurchasesAmount).to.deep.equal(BigInt(100)); + }); + }); + + describe('ownerId', () => { + it('should return ownerId', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + expect(batchTransition.ownerId.toBase58()).to.deep.equal(documentInstance.ownerId.toBase58()); + }); + }); + + describe('modifiedDataIds', () => { + it('should return modifiedDataIds', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + const ids = batchTransition.modifiedDataIds.map( + (identifier: InstanceType) => identifier.toBase58(), + ); + expect(ids).to.deep.equal([documentTransition.id.toBase58(), documentTransition.id.toBase58()]); + }); + }); + + describe('allConflictingIndexCollateralVotingFunds', () => { + it('should return allConflictingIndexCollateralVotingFunds', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + expect(batchTransition.allConflictingIndexCollateralVotingFunds).to.deep.equal(undefined); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/BlockInfo.spec.mjs b/packages/wasm-dpp2/tests/unit/BlockInfo.spec.ts similarity index 68% rename from packages/wasm-dpp2/tests/unit/BlockInfo.spec.mjs rename to packages/wasm-dpp2/tests/unit/BlockInfo.spec.ts index f8603eaca85..eb80e12b303 100644 --- a/packages/wasm-dpp2/tests/unit/BlockInfo.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/BlockInfo.spec.ts @@ -1,15 +1,14 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('BlockInfo', () => { - describe('constructor', () => { + describe('constructor()', () => { it('should create BlockInfo with all parameters', () => { - const blockInfo = new wasm.BlockInfo(1000n, 100n, 50, 5); + const blockInfo = new wasm.BlockInfo({ timeMs: 1000n, height: 100n, coreHeight: 50, epochIndex: 5 }); expect(blockInfo.timeMs).to.equal(1000n); expect(blockInfo.height).to.equal(100n); @@ -18,7 +17,7 @@ describe('BlockInfo', () => { }); it('should create BlockInfo with zero values', () => { - const blockInfo = new wasm.BlockInfo(0n, 0n, 0, 0); + const blockInfo = new wasm.BlockInfo({ timeMs: 0n, height: 0n, coreHeight: 0, epochIndex: 0 }); expect(blockInfo.timeMs).to.equal(0n); expect(blockInfo.height).to.equal(0n); @@ -27,9 +26,9 @@ describe('BlockInfo', () => { }); }); - describe('serialization / deserialization', () => { + describe('toJSON()', () => { it('should round-trip via toJSON/fromJSON', () => { - const blockInfo = new wasm.BlockInfo(1234567890n, 999n, 500, 10); + const blockInfo = new wasm.BlockInfo({ timeMs: 1234567890n, height: 999n, coreHeight: 500, epochIndex: 10 }); const json = blockInfo.toJSON(); // serde uses snake_case by default @@ -44,9 +43,11 @@ describe('BlockInfo', () => { expect(restored.coreHeight).to.equal(blockInfo.coreHeight); expect(restored.epochIndex).to.equal(blockInfo.epochIndex); }); + }); + describe('toObject()', () => { it('should round-trip via toObject/fromObject', () => { - const blockInfo = new wasm.BlockInfo(1234567890n, 999n, 500, 10); + const blockInfo = new wasm.BlockInfo({ timeMs: 1234567890n, height: 999n, coreHeight: 500, epochIndex: 10 }); const obj = blockInfo.toObject(); // serde uses snake_case by default @@ -67,7 +68,7 @@ describe('BlockInfo', () => { // Test with BigInt-sized values const largeTimeMs = 1702500000000n; // realistic timestamp in ms const largeHeight = 1000000n; - const blockInfo = new wasm.BlockInfo(largeTimeMs, largeHeight, 800000, 100); + const blockInfo = new wasm.BlockInfo({ timeMs: largeTimeMs, height: largeHeight, coreHeight: 800000, epochIndex: 100 }); // JSON round-trip const json = blockInfo.toJSON(); @@ -83,24 +84,30 @@ describe('BlockInfo', () => { }); }); - describe('getters', () => { + describe('timeMs', () => { it('should return timeMs', () => { - const blockInfo = new wasm.BlockInfo(5000n, 100n, 50, 5); + const blockInfo = new wasm.BlockInfo({ timeMs: 5000n, height: 100n, coreHeight: 50, epochIndex: 5 }); expect(blockInfo.timeMs).to.equal(5000n); }); + }); + describe('height', () => { it('should return height', () => { - const blockInfo = new wasm.BlockInfo(5000n, 100n, 50, 5); + const blockInfo = new wasm.BlockInfo({ timeMs: 5000n, height: 100n, coreHeight: 50, epochIndex: 5 }); expect(blockInfo.height).to.equal(100n); }); + }); + describe('coreHeight', () => { it('should return coreHeight', () => { - const blockInfo = new wasm.BlockInfo(5000n, 100n, 50, 5); + const blockInfo = new wasm.BlockInfo({ timeMs: 5000n, height: 100n, coreHeight: 50, epochIndex: 5 }); expect(blockInfo.coreHeight).to.equal(50); }); + }); + describe('epochIndex', () => { it('should return epochIndex', () => { - const blockInfo = new wasm.BlockInfo(5000n, 100n, 50, 5); + const blockInfo = new wasm.BlockInfo({ timeMs: 5000n, height: 100n, coreHeight: 50, epochIndex: 5 }); expect(blockInfo.epochIndex).to.equal(5); }); }); diff --git a/packages/wasm-dpp2/tests/unit/ChainLockProof.spec.mjs b/packages/wasm-dpp2/tests/unit/ChainLockProof.spec.mjs deleted file mode 100644 index e0f06d902b0..00000000000 --- a/packages/wasm-dpp2/tests/unit/ChainLockProof.spec.mjs +++ /dev/null @@ -1,105 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('InstantLock', () => { - describe('serialization / deserialization', () => { - it('should allow to create chain lock proof from values', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const chainlock = new wasm.ChainAssetLockProof(11, outpoint); - - expect(chainlock.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create chain lock proof from object', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - - // In non-human-readable serde, txid is serialized as Uint8Array - const txidBytes = Buffer.from(outpoint.getTXID(), 'hex'); - - const chainlock = wasm.ChainAssetLockProof.fromObject({ - coreChainLockedHeight: 11, - outPoint: { - txid: txidBytes, - vout: outpoint.getVOUT(), - }, - }); - - expect(chainlock.__wbg_ptr).to.not.equal(0); - expect(chainlock.coreChainLockedHeight).to.equal(11); - expect(chainlock.outPoint.getVOUT()).to.equal(1); - }); - - it('should round-trip via object/json/bytes', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const chainlock = new wasm.ChainAssetLockProof(11, outpoint); - - const object = chainlock.toObject(); - expect(object.coreChainLockedHeight).to.equal(11); - expect(object.outPoint).to.be.an('object'); - expect(object.outPoint.txid).to.exist; - expect(object.outPoint.vout).to.equal(1); - - const fromObject = wasm.ChainAssetLockProof.fromObject(object); - expect(fromObject.coreChainLockedHeight).to.equal(11); - expect(Array.from(fromObject.outPoint.toBytes())).to.deep.equal(Array.from(outpoint.toBytes())); - - const json = chainlock.toJSON(); - expect(json.coreChainLockedHeight).to.equal(11); - expect(json.outPoint).to.be.a('string'); - expect(json.outPoint).to.include(':'); // "txid:vout" format - - const fromJson = wasm.ChainAssetLockProof.fromJSON(json); - expect(fromJson.coreChainLockedHeight).to.equal(11); - expect(Array.from(fromJson.outPoint.toBytes())).to.deep.equal(Array.from(outpoint.toBytes())); - - const bytes = chainlock.toBytes(); - const fromBytes = wasm.ChainAssetLockProof.fromBytes(bytes); - expect(fromBytes.coreChainLockedHeight).to.equal(11); - expect(Array.from(fromBytes.outPoint.toBytes())).to.deep.equal(Array.from(outpoint.toBytes())); - }); - }); - - describe('getters', () => { - it('should allow to get coreChainLockedHeight', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const chainlock = new wasm.ChainAssetLockProof(11, outpoint); - - expect(chainlock.coreChainLockedHeight).to.equal(11); - }); - - it('should allow to get outPoint', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const chainlock = new wasm.ChainAssetLockProof(11, outpoint); - - expect(chainlock.outPoint.constructor.name).to.equal('OutPoint'); - }); - }); - - describe('setters', () => { - it('should allow to set coreChainLockedHeight', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const chainlock = new wasm.ChainAssetLockProof(11, outpoint); - - chainlock.coreChainLockedHeight = 33; - - expect(chainlock.coreChainLockedHeight).to.equal(33); - }); - - it('should allow to get outPoint', () => { - const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - const chainlock = new wasm.ChainAssetLockProof(11, outpoint); - - const newOutpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 222); - - chainlock.outPoint = newOutpoint; - - expect(chainlock.outPoint.getVOUT()).to.equal(222); - expect(newOutpoint.__wbg_ptr).to.not.equal(0); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/ChainLockProof.spec.ts b/packages/wasm-dpp2/tests/unit/ChainLockProof.spec.ts new file mode 100644 index 00000000000..67fe8b79c3f --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/ChainLockProof.spec.ts @@ -0,0 +1,156 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('ChainAssetLockProof', () => { + describe('constructor()', () => { + it('should allow to create chain lock proof from values', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + expect(chainlock).to.be.an.instanceof(wasm.ChainAssetLockProof); + }); + }); + + describe('fromObject()', () => { + it('should allow to create chain lock proof from object', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + + // In non-human-readable serde, txid is serialized as Uint8Array + const txidBytes = Buffer.from(outpoint.txid, 'hex'); + + const chainlock = wasm.ChainAssetLockProof.fromObject({ + coreChainLockedHeight: 11, + outPoint: { + txid: txidBytes, + vout: outpoint.vout, + }, + }); + + expect(chainlock).to.be.an.instanceof(wasm.ChainAssetLockProof); + expect(chainlock.coreChainLockedHeight).to.equal(11); + expect(chainlock.outPoint.vout).to.equal(1); + }); + }); + + describe('toObject()', () => { + it('should round-trip via object', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + const object = chainlock.toObject(); + expect(object.coreChainLockedHeight).to.equal(11); + expect(object.outPoint).to.be.an('object'); + expect(object.outPoint.txid).to.exist(); + expect(object.outPoint.vout).to.equal(1); + + const fromObject = wasm.ChainAssetLockProof.fromObject(object); + expect(fromObject.coreChainLockedHeight).to.equal(11); + expect(Array.from(fromObject.outPoint.toBytes())).to.deep.equal( + Array.from(outpoint.toBytes()), + ); + }); + }); + + describe('toJSON()', () => { + it('should round-trip via JSON', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + const json = chainlock.toJSON(); + expect(json.coreChainLockedHeight).to.equal(11); + expect(json.outPoint).to.be.a('string'); + expect(json.outPoint).to.include(':'); // "txid:vout" format + + const fromJson = wasm.ChainAssetLockProof.fromJSON(json); + expect(fromJson.coreChainLockedHeight).to.equal(11); + expect(Array.from(fromJson.outPoint.toBytes())).to.deep.equal(Array.from(outpoint.toBytes())); + }); + }); + + describe('toBytes()', () => { + it('should round-trip via bytes', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + const bytes = chainlock.toBytes(); + const fromBytes = wasm.ChainAssetLockProof.fromBytes(bytes); + expect(fromBytes.coreChainLockedHeight).to.equal(11); + expect(Array.from(fromBytes.outPoint.toBytes())).to.deep.equal( + Array.from(outpoint.toBytes()), + ); + }); + }); + + describe('coreChainLockedHeight', () => { + it('should allow to get coreChainLockedHeight', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + expect(chainlock.coreChainLockedHeight).to.equal(11); + }); + + it('should allow to set coreChainLockedHeight', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + chainlock.coreChainLockedHeight = 33; + + expect(chainlock.coreChainLockedHeight).to.equal(33); + }); + }); + + describe('outPoint', () => { + it('should allow to get outPoint', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + expect(chainlock.outPoint.constructor.name).to.equal('OutPoint'); + }); + + it('should allow to set outPoint', () => { + const outpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 1, + ); + const chainlock = new wasm.ChainAssetLockProof(11, outpoint); + + const newOutpoint = new wasm.OutPoint( + 'e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', + 222, + ); + + chainlock.outPoint = newOutpoint; + + expect(chainlock.outPoint.vout).to.equal(222); + expect(newOutpoint).to.be.an.instanceof(wasm.OutPoint); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/ChangeControlRules.spec.mjs b/packages/wasm-dpp2/tests/unit/ChangeControlRules.spec.mjs deleted file mode 100644 index e005ddfeb2f..00000000000 --- a/packages/wasm-dpp2/tests/unit/ChangeControlRules.spec.mjs +++ /dev/null @@ -1,188 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('ChangeControlRules', () => { - describe('serialization / deserialization', () => { - it('should allow to create rules from values', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - expect(noOne.__wbg_ptr).to.not.equal(0); - expect(changeRules.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to get authorizedToMakeChange', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - expect(changeRules.authorizedToMakeChange.constructor.name).to.deep.equal('AuthorizedActionTakers'); - }); - - it('should allow to get adminActionTakers', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - expect(changeRules.adminActionTakers.constructor.name).to.deep.equal('AuthorizedActionTakers'); - }); - - it('should allow to get changingAuthorizedActionTakersToNoOneAllowed', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - expect(changeRules.changingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(true); - }); - - it('should allow to get changingAdminActionTakersToNoOneAllowed', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - expect(changeRules.changingAdminActionTakersToNoOneAllowed).to.deep.equal(true); - }); - - it('should allow to get selfChangingAdminActionTakersAllowed', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - expect(changeRules.selfChangingAdminActionTakersAllowed).to.deep.equal(true); - }); - }); - - describe('setters', () => { - it('should allow to set authorizedToMakeChange', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - const newActionTaker = wasm.AuthorizedActionTakers.ContractOwner(); - - changeRules.authorizedToMakeChange = newActionTaker; - - expect(changeRules.authorizedToMakeChange.constructor.name).to.deep.equal('AuthorizedActionTakers'); - expect(changeRules.authorizedToMakeChange.getTakerType()).to.deep.equal('ContractOwner'); - expect(newActionTaker.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to set adminActionTakers', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - const newActionTaker = wasm.AuthorizedActionTakers.ContractOwner(); - - changeRules.adminActionTakers = newActionTaker; - - expect(changeRules.adminActionTakers.constructor.name).to.deep.equal('AuthorizedActionTakers'); - expect(changeRules.adminActionTakers.getTakerType()).to.deep.equal('ContractOwner'); - expect(newActionTaker.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to set changingAuthorizedActionTakersToNoOneAllowed', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - changeRules.changingAuthorizedActionTakersToNoOneAllowed = false; - - expect(changeRules.changingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(false); - }); - - it('should allow to set changingAdminActionTakersToNoOneAllowed', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - changeRules.changingAdminActionTakersToNoOneAllowed = false; - - expect(changeRules.changingAdminActionTakersToNoOneAllowed).to.deep.equal(false); - }); - - it('should allow to set selfChangingAdminActionTakersAllowed', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - changeRules.selfChangingAdminActionTakersAllowed = false; - - expect(changeRules.selfChangingAdminActionTakersAllowed).to.deep.equal(false); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/ChangeControlRules.spec.ts b/packages/wasm-dpp2/tests/unit/ChangeControlRules.spec.ts new file mode 100644 index 00000000000..1615a394160 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/ChangeControlRules.spec.ts @@ -0,0 +1,148 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +interface ChangeControlRulesOptions { + isChangingAuthorizedActionTakersToNoOneAllowed?: boolean; + isChangingAdminActionTakersToNoOneAllowed?: boolean; + isSelfChangingAdminActionTakersAllowed?: boolean; +} + +describe('ChangeControlRules', () => { + // Helper function to create ChangeControlRules with default options + function createChangeControlRules( + authorizedToMakeChange: InstanceType, + adminActionTakers: InstanceType, + options: ChangeControlRulesOptions = {}, + ) { + return new wasm.ChangeControlRules({ + authorizedToMakeChange, + adminActionTakers, + isChangingAuthorizedActionTakersToNoOneAllowed: options.isChangingAuthorizedActionTakersToNoOneAllowed ?? true, + isChangingAdminActionTakersToNoOneAllowed: options.isChangingAdminActionTakersToNoOneAllowed ?? true, + isSelfChangingAdminActionTakersAllowed: options.isSelfChangingAdminActionTakersAllowed ?? true, + }); + } + + describe('constructor()', () => { + it('should create rules from values', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + expect(noOne).to.be.an.instanceof(wasm.AuthorizedActionTakers); + expect(changeRules).to.be.an.instanceof(wasm.ChangeControlRules); + }); + }); + + describe('authorizedToMakeChange', () => { + it('should return authorizedToMakeChange', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + expect(changeRules.authorizedToMakeChange.constructor.name).to.deep.equal('AuthorizedActionTakers'); + }); + + it('should set authorizedToMakeChange', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + const newActionTaker = wasm.AuthorizedActionTakers.ContractOwner(); + + changeRules.authorizedToMakeChange = newActionTaker; + + expect(changeRules.authorizedToMakeChange.constructor.name).to.deep.equal('AuthorizedActionTakers'); + expect(changeRules.authorizedToMakeChange.takerType).to.deep.equal('ContractOwner'); + expect(newActionTaker).to.be.an.instanceof(wasm.AuthorizedActionTakers); + }); + }); + + describe('adminActionTakers', () => { + it('should return adminActionTakers', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + expect(changeRules.adminActionTakers.constructor.name).to.deep.equal('AuthorizedActionTakers'); + }); + + it('should set adminActionTakers', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + const newActionTaker = wasm.AuthorizedActionTakers.ContractOwner(); + + changeRules.adminActionTakers = newActionTaker; + + expect(changeRules.adminActionTakers.constructor.name).to.deep.equal('AuthorizedActionTakers'); + expect(changeRules.adminActionTakers.takerType).to.deep.equal('ContractOwner'); + expect(newActionTaker).to.be.an.instanceof(wasm.AuthorizedActionTakers); + }); + }); + + describe('isChangingAuthorizedActionTakersToNoOneAllowed', () => { + it('should return isChangingAuthorizedActionTakersToNoOneAllowed', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + expect(changeRules.isChangingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(true); + }); + + it('should set isChangingAuthorizedActionTakersToNoOneAllowed', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + changeRules.isChangingAuthorizedActionTakersToNoOneAllowed = false; + + expect(changeRules.isChangingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(false); + }); + }); + + describe('isChangingAdminActionTakersToNoOneAllowed', () => { + it('should return isChangingAdminActionTakersToNoOneAllowed', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + expect(changeRules.isChangingAdminActionTakersToNoOneAllowed).to.deep.equal(true); + }); + + it('should set isChangingAdminActionTakersToNoOneAllowed', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + changeRules.isChangingAdminActionTakersToNoOneAllowed = false; + + expect(changeRules.isChangingAdminActionTakersToNoOneAllowed).to.deep.equal(false); + }); + }); + + describe('isSelfChangingAdminActionTakersAllowed', () => { + it('should return isSelfChangingAdminActionTakersAllowed', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + expect(changeRules.isSelfChangingAdminActionTakersAllowed).to.deep.equal(true); + }); + + it('should set isSelfChangingAdminActionTakersAllowed', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + changeRules.isSelfChangingAdminActionTakersAllowed = false; + + expect(changeRules.isSelfChangingAdminActionTakersAllowed).to.deep.equal(false); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/ContestedDocumentVotePollWinnerInfo.spec.mjs b/packages/wasm-dpp2/tests/unit/ContestedDocumentVotePollWinnerInfo.spec.ts similarity index 79% rename from packages/wasm-dpp2/tests/unit/ContestedDocumentVotePollWinnerInfo.spec.mjs rename to packages/wasm-dpp2/tests/unit/ContestedDocumentVotePollWinnerInfo.spec.ts index cc5432095ef..bacf23c0926 100644 --- a/packages/wasm-dpp2/tests/unit/ContestedDocumentVotePollWinnerInfo.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/ContestedDocumentVotePollWinnerInfo.spec.ts @@ -1,23 +1,22 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('ContestedDocumentVotePollWinnerInfo', () => { const identityIdHex = '1111111111111111111111111111111111111111111111111111111111111111'; - describe('constructor', () => { + describe('constructor()', () => { it('should create NoWinner info', () => { const info = new wasm.ContestedDocumentVotePollWinnerInfo('NoWinner'); expect(info.kind).to.equal('NoWinner'); - expect(info.identityId).to.be.null; - expect(info.isNoWinner()).to.be.true; - expect(info.isWonByIdentity()).to.be.false; - expect(info.isLocked()).to.be.false; + expect(info.identityId).to.be.undefined(); + expect(info.isNoWinner).to.be.true(); + expect(info.isWonByIdentity).to.be.false(); + expect(info.isLocked).to.be.false(); }); it('should create WonByIdentity info', () => { @@ -26,37 +25,37 @@ describe('ContestedDocumentVotePollWinnerInfo', () => { const info = new wasm.ContestedDocumentVotePollWinnerInfo('WonByIdentity', identityId); expect(info.kind).to.equal('WonByIdentity'); - expect(info.identityId).to.not.be.null; + expect(info.identityId).to.not.be.undefined(); expect(info.identityId.toBase58()).to.equal(identityIdBase58); - expect(info.isNoWinner()).to.be.false; - expect(info.isWonByIdentity()).to.be.true; - expect(info.isLocked()).to.be.false; + expect(info.isNoWinner).to.be.false(); + expect(info.isWonByIdentity).to.be.true(); + expect(info.isLocked).to.be.false(); }); it('should create Locked info', () => { const info = new wasm.ContestedDocumentVotePollWinnerInfo('Locked'); expect(info.kind).to.equal('Locked'); - expect(info.identityId).to.be.null; - expect(info.isNoWinner()).to.be.false; - expect(info.isWonByIdentity()).to.be.false; - expect(info.isLocked()).to.be.true; + expect(info.identityId).to.be.undefined(); + expect(info.isNoWinner).to.be.false(); + expect(info.isWonByIdentity).to.be.false(); + expect(info.isLocked).to.be.true(); }); it('should accept alternative kind names', () => { const noWinner = new wasm.ContestedDocumentVotePollWinnerInfo('noWinner'); - expect(noWinner.isNoWinner()).to.be.true; + expect(noWinner.isNoWinner).to.be.true(); const locked = new wasm.ContestedDocumentVotePollWinnerInfo('LOCKED'); - expect(locked.isLocked()).to.be.true; + expect(locked.isLocked).to.be.true(); const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); const identity = new wasm.ContestedDocumentVotePollWinnerInfo('Identity', identityId); - expect(identity.isWonByIdentity()).to.be.true; + expect(identity.isWonByIdentity).to.be.true(); }); }); - describe('conversion methods', () => { + describe('toJSON()', () => { it('should round-trip NoWinner via toJSON/fromJSON', () => { const info = new wasm.ContestedDocumentVotePollWinnerInfo('NoWinner'); @@ -66,7 +65,7 @@ describe('ContestedDocumentVotePollWinnerInfo', () => { const restored = wasm.ContestedDocumentVotePollWinnerInfo.fromJSON(json); expect(restored.kind).to.equal(info.kind); - expect(restored.isNoWinner()).to.be.true; + expect(restored.isNoWinner).to.be.true(); }); it('should round-trip WonByIdentity via toJSON/fromJSON', () => { @@ -92,9 +91,11 @@ describe('ContestedDocumentVotePollWinnerInfo', () => { const restored = wasm.ContestedDocumentVotePollWinnerInfo.fromJSON(json); expect(restored.kind).to.equal(info.kind); - expect(restored.isLocked()).to.be.true; + expect(restored.isLocked).to.be.true(); }); + }); + describe('toObject()', () => { it('should round-trip NoWinner via toObject/fromObject', () => { const info = new wasm.ContestedDocumentVotePollWinnerInfo('NoWinner'); @@ -113,7 +114,7 @@ describe('ContestedDocumentVotePollWinnerInfo', () => { const obj = info.toObject(); expect(obj).to.be.an('object'); // Serde serializes tuple variants as { VariantName: value } - expect(obj.WonByIdentity).to.not.be.undefined; + expect(obj.WonByIdentity).to.not.be.undefined(); const restored = wasm.ContestedDocumentVotePollWinnerInfo.fromObject(obj); expect(restored.kind).to.equal(info.kind); diff --git a/packages/wasm-dpp2/tests/unit/ContractBounds.spec.mjs b/packages/wasm-dpp2/tests/unit/ContractBounds.spec.ts similarity index 78% rename from packages/wasm-dpp2/tests/unit/ContractBounds.spec.mjs rename to packages/wasm-dpp2/tests/unit/ContractBounds.spec.ts index 19594b74e33..c8162e934cb 100644 --- a/packages/wasm-dpp2/tests/unit/ContractBounds.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/ContractBounds.spec.ts @@ -1,15 +1,14 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('ContractBounds', () => { const contractIdHex = '1111111111111111111111111111111111111111111111111111111111111111'; - describe('constructor', () => { + describe('constructor()', () => { it('should create SingleContract bounds without document type', () => { const bounds = new wasm.ContractBounds( Buffer.from(contractIdHex, 'hex'), @@ -17,7 +16,7 @@ describe('ContractBounds', () => { // contractBoundsType returns the serde string representation from rs-dpp expect(bounds.contractBoundsType).to.equal('singleContract'); - expect(bounds.documentTypeName).to.be.null; + expect(bounds.documentTypeName).to.be.undefined(); }); it('should create SingleContractDocumentType bounds with document type', () => { @@ -32,7 +31,7 @@ describe('ContractBounds', () => { }); }); - describe('static constructors', () => { + describe('SingleContract()', () => { it('should create SingleContract via static method', () => { const bounds = wasm.ContractBounds.SingleContract( Buffer.from(contractIdHex, 'hex'), @@ -40,7 +39,9 @@ describe('ContractBounds', () => { expect(bounds.contractBoundsType).to.equal('singleContract'); }); + }); + describe('SingleContractDocumentType()', () => { it('should create SingleContractDocumentType via static method', () => { const bounds = wasm.ContractBounds.SingleContractDocumentType( Buffer.from(contractIdHex, 'hex'), @@ -52,7 +53,7 @@ describe('ContractBounds', () => { }); }); - describe('conversion methods', () => { + describe('toJSON()', () => { it('should round-trip SingleContract via toJSON/fromJSON', () => { const bounds = wasm.ContractBounds.SingleContract( Buffer.from(contractIdHex, 'hex'), @@ -84,7 +85,7 @@ describe('ContractBounds', () => { }); }); - describe('getters', () => { + describe('identifier', () => { it('should return identifier', () => { const bounds = new wasm.ContractBounds( Buffer.from(contractIdHex, 'hex'), @@ -94,6 +95,22 @@ describe('ContractBounds', () => { expect(bounds.identifier.__type).to.equal('Identifier'); }); + it('should throw an error when setting invalid identifier via setter', () => { + const bounds = new wasm.ContractBounds( + Buffer.from(contractIdHex, 'hex'), + ); + + // This setter returns WasmDppResult<()> in Rust + // Let's test what happens when we pass an invalid identifier (wrong length) + const invalidIdentifier = Buffer.from('invalid', 'utf8'); // Only 7 bytes, need 32 + + expect(() => { + bounds.identifier = invalidIdentifier; + }).to.throw(); + }); + }); + + describe('contractBoundsTypeNumber', () => { it('should return contractBoundsTypeNumber', () => { const singleContract = wasm.ContractBounds.SingleContract( Buffer.from(contractIdHex, 'hex'), diff --git a/packages/wasm-dpp2/tests/unit/CoreScript.spec.mjs b/packages/wasm-dpp2/tests/unit/CoreScript.spec.ts similarity index 56% rename from packages/wasm-dpp2/tests/unit/CoreScript.spec.mjs rename to packages/wasm-dpp2/tests/unit/CoreScript.spec.ts index 8eedbfde6a1..a52a3eedfb8 100644 --- a/packages/wasm-dpp2/tests/unit/CoreScript.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/CoreScript.spec.ts @@ -1,43 +1,59 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('CoreScript', () => { - describe('serialization / deserialization', () => { + // Common test data + const pubKeyHash = [ + 195, 219, 253, 64, 231, 248, 164, 132, + 92, 47, 142, 134, 138, 22, 124, 152, 64, 73, 118, 73, + ]; + + describe('fromBytes()', () => { it('should allow to create from bytes', () => { - const script = wasm.CoreScript.fromBytes(Buffer.from('76a914c3dbfd40e7f8a4845c2f8e868a167c984049764988ac', 'hex')); + const scriptHex = '76a914c3dbfd40e7f8a4845c2f8e868a167c984049764988ac'; + const script = wasm.CoreScript.fromBytes(Buffer.from(scriptHex, 'hex')); expect(script._wbg_ptr).to.not.equal(0); }); + }); + describe('fromP2PKH()', () => { it('should allow to create P2PKH', () => { - const script = wasm.CoreScript.newP2PKH([195, 219, 253, 64, 231, 248, 164, 132, 92, 47, 142, 134, 138, 22, 124, 152, 64, 73, 118, 73]); + const script = wasm.CoreScript.fromP2PKH(pubKeyHash); expect(script._wbg_ptr).to.not.equal(0); }); + }); + describe('fromP2SH()', () => { it('should allow to create P2SH', () => { - const script = wasm.CoreScript.newP2SH([195, 219, 253, 64, 231, 248, 164, 132, 92, 47, 142, 134, 138, 22, 124, 152, 64, 73, 118, 73]); + const script = wasm.CoreScript.fromP2SH(pubKeyHash); expect(script._wbg_ptr).to.not.equal(0); }); + }); + describe('toASMString()', () => { it('should allow to convert to asm P2PKH', () => { - const script = wasm.CoreScript.newP2PKH([195, 219, 253, 64, 231, 248, 164, 132, 92, 47, 142, 134, 138, 22, 124, 152, 64, 73, 118, 73]); + const script = wasm.CoreScript.fromP2PKH(pubKeyHash); expect(script.toASMString()).to.equal('OP_DUP OP_HASH160 OP_PUSHBYTES_20 c3dbfd40e7f8a4845c2f8e868a167c9840497649 OP_EQUALVERIFY OP_CHECKSIG'); }); + }); - it('should allow to convert to adddress', () => { + describe('toAddress()', () => { + it('should allow to convert to address', () => { const script = wasm.CoreScript.fromBytes(Buffer.from('76a9142de40f87177f6e167fb9fcda9a3b3c64fc42468f88ac', 'hex')); expect(script.toAddress(wasm.Network.Testnet)).to.equal('yQW6TmUFef5CDyhEYwjoN8aUTMmKLYYNDm'); }); + }); + describe('toBase64()', () => { it('should allow to get base64 representation', () => { const script = wasm.CoreScript.fromBytes(Buffer.from('76a9142de40f87177f6e167fb9fcda9a3b3c64fc42468f88ac', 'hex')); diff --git a/packages/wasm-dpp2/tests/unit/DataContract.spec.mjs b/packages/wasm-dpp2/tests/unit/DataContract.spec.mjs deleted file mode 100644 index 2f438db7dfc..00000000000 --- a/packages/wasm-dpp2/tests/unit/DataContract.spec.mjs +++ /dev/null @@ -1,218 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { - json, object, id, ownerId -} from './mocks/DataContract/index.js'; -import { fromHexString } from './utils/hex.js'; - -let wasm; -let PlatformVersion; - -before(async () => { - wasm = await getWasm(); - ({ PlatformVersion } = wasm); -}); - -let dataContractsBytes; - -describe('DataContract', () => { - before(async () => { - dataContractsBytes = ['003662bb61e17fae3ea294cf603197fb0aab6d51180bd8b6104c4944a62fe2d97f00000000000101000001000000000000000000000000000000000000000000000000000000000000000000010a7769746864726177616c1607120b6465736372697074696f6e12805769746864726177616c20646f63756d656e7420746f20747261636b20756e6465726c79696e67207769746864726177616c207472616e73616374696f6e732e205769746864726177616c732073686f756c6420626520637265617465642077697468204964656e746974795769746864726177616c5472616e736974696f6e12176372656174696f6e5265737472696374696f6e4d6f6465020212047479706512066f626a6563741207696e64696365731504160312046e616d65120e6964656e74697479537461747573120a70726f70657274696573150316011208246f776e6572496412036173631601120673746174757312036173631601120a2463726561746564417412036173631206756e697175651300160312046e616d65120e6964656e74697479526563656e74120a70726f70657274696573150316011208246f776e6572496412036173631601120a2475706461746564417412036173631601120673746174757312036173631206756e697175651300160312046e616d651207706f6f6c696e67120a70726f70657274696573150416011206737461747573120361736316011207706f6f6c696e6712036173631601120e636f72654665655065724279746512036173631601120a2475706461746564417412036173631206756e697175651300160312046e616d65120b7472616e73616374696f6e120a70726f706572746965731502160112067374617475731203617363160112107472616e73616374696f6e496e64657812036173631206756e697175651300120a70726f70657274696573160712107472616e73616374696f6e496e64657816041204747970651207696e7465676572120b6465736372697074696f6e127953657175656e7469616c20696e646578206f6620617373657420756e6c6f636b20287769746864726177616c29207472616e73616374696f6e2e20506f70756c61746564207768656e2061207769746864726177616c20706f6f6c656420696e746f207769746864726177616c207472616e73616374696f6e12076d696e696d756d02011208706f736974696f6e020012157472616e73616374696f6e5369676e48656967687416041204747970651207696e7465676572120b6465736372697074696f6e122f54686520436f726520686569676874206f6e207768696368207472616e73616374696f6e20776173207369676e656412076d696e696d756d02011208706f736974696f6e02011206616d6f756e7416041204747970651207696e7465676572120b6465736372697074696f6e121a54686520616d6f756e7420746f2062652077697468647261776e12076d696e696d756d02fb03e81208706f736974696f6e0202120e636f72654665655065724279746516051204747970651207696e7465676572120b6465736372697074696f6e1250546869732069732074686520666565207468617420796f75206172652077696c6c696e6720746f207370656e6420666f722074686973207472616e73616374696f6e20696e2044756666732f4279746512076d696e696d756d020112076d6178696d756d02fcffffffff1208706f736974696f6e02031207706f6f6c696e6716041204747970651207696e7465676572120b6465736372697074696f6e124e5468697320696e6469636174656420746865206c6576656c20617420776869636820506c6174666f726d2073686f756c642074727920746f20706f6f6c2074686973207472616e73616374696f6e1204656e756d15030200020102021208706f736974696f6e0204120c6f75747075745363726970741605120474797065120561727261791209627974654172726179130112086d696e4974656d73021712086d61784974656d7302191208706f736974696f6e0205120673746174757316041204747970651207696e74656765721204656e756d150502000201020202030204120b6465736372697074696f6e124330202d2050656e64696e672c2031202d205369676e65642c2032202d2042726f61646361737465642c2033202d20436f6d706c6574652c2034202d20457870697265641208706f736974696f6e020612146164646974696f6e616c50726f706572746965731300120872657175697265641507120a24637265617465644174120a247570646174656441741206616d6f756e74120e636f7265466565506572427974651207706f6f6c696e67120c6f75747075745363726970741206737461747573']; - }); - - describe('serialization / deserialization', () => { - it('should allows to create DataContract from schema without full validation', () => { - const identifier = new wasm.Identifier(object.ownerId); - - // Constructor accepts object format (with BigInt for integers) - const dataContract = new wasm.DataContract(identifier, BigInt(2), object.documentSchemas, null, false); - - expect(dataContract.__wbg_ptr).to.not.equal(0); - }); - - it('should allows to create DataContract from schema with full validation', () => { - const identifier = new wasm.Identifier(object.ownerId); - - // Constructor accepts object format (with BigInt for integers) - const dataContract = new wasm.DataContract(identifier, BigInt(2), object.documentSchemas, null, true); - - expect(dataContract.__wbg_ptr).to.not.equal(0); - }); - - it('should allows to create DataContract from value with full validation and without platform version', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - expect(dataContract.__wbg_ptr).to.not.equal(0); - }); - - it('should allows to convert DataContract to bytes and from bytes', () => { - const [dataContractBytes] = dataContractsBytes; - - const dataContract = wasm.DataContract.fromJSON(json, true); - - expect(dataContract.toBytes()).to.deep.equal(fromHexString(dataContractBytes)); - - const dataContractFromBytes = wasm.DataContract.fromBytes(dataContract.toBytes(), false, PlatformVersion.PLATFORM_V1); - - expect(dataContract.__wbg_ptr).to.not.equal(0); - - expect(dataContractFromBytes.toBytes()).to.deep.equal(fromHexString(dataContractBytes)); - }); - - it('should allows to create DataContract from bytes without full validation', () => { - const [dataContractBytes] = dataContractsBytes; - - const dataContractFromBytes = wasm.DataContract.fromBytes(fromHexString(dataContractBytes), false, PlatformVersion.PLATFORM_V1); - const dataContractFromValue = wasm.DataContract.fromJSON(json, true); - - expect(dataContractFromBytes.toObject()).to.deep.equal(dataContractFromValue.toObject()); - }); - - it('should allows to create DataContract from bytes with full validation and without version', () => { - const [dataContractBytes] = dataContractsBytes; - - const dataContractFromBytes = wasm.DataContract.fromBytes(fromHexString(dataContractBytes), true); - const dataContractFromValue = wasm.DataContract.fromJSON(json, true); - - expect(dataContractFromBytes.toObject()).to.deep.equal(dataContractFromValue.toObject()); - }); - - it('should allow to create DataContract from object produced by toObject', () => { - const originalContract = wasm.DataContract.fromJSON(json, true); - const objectRepresentation = originalContract.toObject(PlatformVersion.PLATFORM_V1); - - const reconstructedContract = wasm.DataContract.fromObject( - objectRepresentation, - true, - PlatformVersion.PLATFORM_V1, - ); - - expect(reconstructedContract.toObject(PlatformVersion.PLATFORM_V1)).to.deep.equal(objectRepresentation); - }); - - it('should allow to convert DataContract to base64 and from base64', () => { - const [dataContractBytes] = dataContractsBytes; - - const dataContract = wasm.DataContract.fromBytes(fromHexString(dataContractBytes), true, PlatformVersion.PLATFORM_V1); - - const base64 = dataContract.toBase64(PlatformVersion.PLATFORM_V1); - const bytes = dataContract.toBytes(PlatformVersion.PLATFORM_V1); - const bytesFromBase64 = Buffer.from(base64, 'base64'); - - expect(bytesFromBase64).to.deep.equal(Buffer.from(bytes)); - - const dataContractFromBase64 = wasm.DataContract.fromBase64(base64, true, PlatformVersion.PLATFORM_V1); - - expect(Buffer.from(dataContractFromBase64.toBytes(PlatformVersion.PLATFORM_V1))).to.deep.equal(Buffer.from(bytes)); - }); - - it('should allow to get json', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - expect(dataContract.toJSON()).to.deep.equal(json); - }); - }); - - describe('getters', () => { - it('should allow to get schemas', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - const schemas = dataContract.getSchemas(); - - expect(schemas).to.deep.equal(object.documentSchemas); - }); - - it('should allow to get version', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - expect(dataContract.version).to.deep.equal(json.version); - }); - - it('should allow to get id', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - expect(dataContract.id.toBase58()).to.deep.equal(id); - }); - - it('should allow to get owner id', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - expect(dataContract.ownerId.toBase58()).to.deep.equal(ownerId); - }); - - it('should allow to get config', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - const config = dataContract.getConfig(); - - expect(config).to.deep.equal(object.config); - }); - }); - - describe('setters', () => { - it('should allow to set id', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - dataContract.id = new wasm.Identifier('7ckT6Y19HnjfqoPFmfL995i4z2HwgZ8UttNmP99LtCBH'); - - expect(dataContract.id.toBase58()).to.deep.equal('7ckT6Y19HnjfqoPFmfL995i4z2HwgZ8UttNmP99LtCBH'); - }); - - it('should allow to set owner id', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - dataContract.ownerId = new wasm.Identifier('3bx13Wd5k4LwHAvXJrayc5HdKPyiccKWYECPQGGYfnVL'); - - expect(dataContract.ownerId.toBase58()).to.deep.equal('3bx13Wd5k4LwHAvXJrayc5HdKPyiccKWYECPQGGYfnVL'); - }); - - it('should allow to set version', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - dataContract.version = 20; - - expect(dataContract.version).to.equal(20); - }); - - it('should allow to set config', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - const oldConfig = dataContract.getConfig(); - - const newConfig = { ...oldConfig, canBeDeleted: !oldConfig.canBeDeleted }; - - dataContract.setConfig(newConfig); - - expect(dataContract.getConfig()).to.deep.equal(newConfig); - }); - - it('should allow to set schema', () => { - const dataContract = wasm.DataContract.fromJSON(json, true); - - // Use JSON fixture for setting (numbers, not BigInt) - const newSchema = { - pupup: json.documentSchemas.withdrawal, - }; - - dataContract.setSchemas(newSchema); - - const schemas = dataContract.getSchemas(); - - // getSchemas returns object format (BigInt), so compare with object fixture - const expectedSchema = { - pupup: object.documentSchemas.withdrawal, - }; - - expect(schemas).to.deep.equal(expectedSchema); - }); - }); - - describe('static', () => { - it('should allow to generate id', () => { - const identifier = new wasm.Identifier('3bx13Wd5k4LwHAvXJrayc5HdKPyiccKWYECPQGGYfnVL'); - - const generatedId = wasm.DataContract.generateId(identifier, BigInt(4)); - - expect(generatedId.toBase58()).to.deep.equal('7ckT6Y19HnjfqoPFmfL995i4z2HwgZ8UttNmP99LtCBH'); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/DataContract.spec.ts b/packages/wasm-dpp2/tests/unit/DataContract.spec.ts new file mode 100644 index 00000000000..ce2ac9d9c68 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/DataContract.spec.ts @@ -0,0 +1,272 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { + json, object, id, ownerId, +} from './mocks/DataContract/index.js'; +import { fromHexString } from './utils/hex.ts'; + +let PlatformVersion: typeof wasm.PlatformVersion; + +before(async () => { + await initWasm(); + ({ PlatformVersion } = wasm); +}); + +let dataContractsBytes: string[]; + +describe('DataContract', () => { + before(async () => { + dataContractsBytes = [ + '003662bb61e17fae3ea294cf603197fb0aab6d51180bd8b6104c4944a62fe2d97f00000000000101000001000000000000000000000000000000000000000000000000000000000000000000010a7769746864726177616c1607120b6465736372697074696f6e12805769746864726177616c20646f63756d656e7420746f20747261636b20756e6465726c79696e67207769746864726177616c207472616e73616374696f6e732e205769746864726177616c732073686f756c6420626520637265617465642077697468204964656e746974795769746864726177616c5472616e736974696f6e12176372656174696f6e5265737472696374696f6e4d6f6465020212047479706512066f626a6563741207696e64696365731504160312046e616d65120e6964656e74697479537461747573120a70726f70657274696573150316011208246f776e6572496412036173631601120673746174757312036173631601120a2463726561746564417412036173631206756e697175651300160312046e616d65120e6964656e74697479526563656e74120a70726f70657274696573150316011208246f776e6572496412036173631601120a2475706461746564417412036173631601120673746174757312036173631206756e697175651300160312046e616d651207706f6f6c696e67120a70726f70657274696573150416011206737461747573120361736316011207706f6f6c696e6712036173631601120e636f72654665655065724279746512036173631601120a2475706461746564417412036173631206756e697175651300160312046e616d65120b7472616e73616374696f6e120a70726f706572746965731502160112067374617475731203617363160112107472616e73616374696f6e496e64657812036173631206756e697175651300120a70726f70657274696573160712107472616e73616374696f6e496e64657816041204747970651207696e7465676572120b6465736372697074696f6e127953657175656e7469616c20696e646578206f6620617373657420756e6c6f636b20287769746864726177616c29207472616e73616374696f6e2e20506f70756c61746564207768656e2061207769746864726177616c20706f6f6c656420696e746f207769746864726177616c207472616e73616374696f6e12076d696e696d756d02011208706f736974696f6e020012157472616e73616374696f6e5369676e48656967687416041204747970651207696e7465676572120b6465736372697074696f6e122f54686520436f726520686569676874206f6e207768696368207472616e73616374696f6e20776173207369676e656412076d696e696d756d02011208706f736974696f6e02011206616d6f756e7416041204747970651207696e7465676572120b6465736372697074696f6e121a54686520616d6f756e7420746f2062652077697468647261776e12076d696e696d756d02fb03e81208706f736974696f6e0202120e636f72654665655065724279746516051204747970651207696e7465676572120b6465736372697074696f6e1250546869732069732074686520666565207468617420796f75206172652077696c6c696e6720746f207370656e6420666f722074686973207472616e73616374696f6e20696e2044756666732f4279746512076d696e696d756d020112076d6178696d756d02fcffffffff1208706f736974696f6e02031207706f6f6c696e6716041204747970651207696e7465676572120b6465736372697074696f6e124e5468697320696e6469636174656420746865206c6576656c20617420776869636820506c6174666f726d2073686f756c642074727920746f20706f6f6c2074686973207472616e73616374696f6e1204656e756d15030200020102021208706f736974696f6e0204120c6f75747075745363726970741605120474797065120561727261791209627974654172726179130112086d696e4974656d73021712086d61784974656d7302191208706f736974696f6e0205120673746174757316041204747970651207696e74656765721204656e756d150502000201020202030204120b6465736372697074696f6e124330202d2050656e64696e672c2031202d205369676e65642c2032202d2042726f61646361737465642c2033202d20436f6d706c6574652c2034202d20457870697265641208706f736974696f6e020612146164646974696f6e616c50726f706572746965731300120872657175697265641507120a24637265617465644174120a247570646174656441741206616d6f756e74120e636f7265466565506572427974651207706f6f6c696e67120c6f75747075745363726970741206737461747573', + ]; + }); + + describe('constructor()', () => { + it('should allow to create DataContract from schema without full validation', () => { + const dataContract = new wasm.DataContract({ + ownerId: object.ownerId, + identityNonce: BigInt(2), + schemas: object.documentSchemas, + definitions: null, + fullValidation: false, + }); + + expect(dataContract).to.be.an.instanceof(wasm.DataContract); + }); + + it('should allow to create DataContract from schema with full validation', () => { + const dataContract = new wasm.DataContract({ + ownerId: object.ownerId, + identityNonce: BigInt(2), + schemas: object.documentSchemas, + definitions: null, + fullValidation: true, + }); + + expect(dataContract).to.be.an.instanceof(wasm.DataContract); + }); + }); + + describe('fromJSON()', () => { + it('should allow to create DataContract from value with full validation and without platform version', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + expect(dataContract).to.be.an.instanceof(wasm.DataContract); + }); + }); + + describe('fromBytes()', () => { + it('should allow to convert DataContract to bytes and from bytes', () => { + const [dataContractBytes] = dataContractsBytes; + + const dataContract = wasm.DataContract.fromJSON(json, true); + + expect(dataContract.toBytes()).to.deep.equal(fromHexString(dataContractBytes)); + + const dataContractFromBytes = wasm.DataContract.fromBytes( + dataContract.toBytes(), + false, + PlatformVersion.PLATFORM_V1, + ); + + expect(dataContract).to.be.an.instanceof(wasm.DataContract); + + expect(dataContractFromBytes.toBytes()).to.deep.equal(fromHexString(dataContractBytes)); + }); + + it('should allow to create DataContract from bytes without full validation', () => { + const [dataContractBytes] = dataContractsBytes; + + const dataContractFromBytes = wasm.DataContract.fromBytes( + fromHexString(dataContractBytes), + false, + PlatformVersion.PLATFORM_V1, + ); + const dataContractFromValue = wasm.DataContract.fromJSON(json, true); + + expect(dataContractFromBytes.toObject()).to.deep.equal(dataContractFromValue.toObject()); + }); + + it('should allow to create DataContract from bytes with full validation and without version', () => { + const [dataContractBytes] = dataContractsBytes; + + const dataContractFromBytes = wasm.DataContract.fromBytes( + fromHexString(dataContractBytes), + true, + ); + const dataContractFromValue = wasm.DataContract.fromJSON(json, true); + + expect(dataContractFromBytes.toObject()).to.deep.equal(dataContractFromValue.toObject()); + }); + }); + + describe('fromObject()', () => { + it('should allow to create DataContract from object produced by toObject', () => { + const originalContract = wasm.DataContract.fromJSON(json, true); + const objectRepresentation = originalContract.toObject(PlatformVersion.PLATFORM_V1); + + const reconstructedContract = wasm.DataContract.fromObject( + objectRepresentation, + true, + PlatformVersion.PLATFORM_V1, + ); + + expect(reconstructedContract.toObject(PlatformVersion.PLATFORM_V1)).to.deep.equal( + objectRepresentation, + ); + }); + }); + + describe('toBase64()', () => { + it('should allow to convert DataContract to base64 and from base64', () => { + const [dataContractBytes] = dataContractsBytes; + + const dataContract = wasm.DataContract.fromBytes( + fromHexString(dataContractBytes), + true, + PlatformVersion.PLATFORM_V1, + ); + + const base64 = dataContract.toBase64(PlatformVersion.PLATFORM_V1); + const bytes = dataContract.toBytes(PlatformVersion.PLATFORM_V1); + const bytesFromBase64 = Buffer.from(base64, 'base64'); + + expect(bytesFromBase64).to.deep.equal(Buffer.from(bytes)); + + const dataContractFromBase64 = wasm.DataContract.fromBase64( + base64, + true, + PlatformVersion.PLATFORM_V1, + ); + + const actualBytes = Buffer.from( + dataContractFromBase64.toBytes(PlatformVersion.PLATFORM_V1), + ); + expect(actualBytes).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('toJSON()', () => { + it('should allow to get json', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + expect(dataContract.toJSON()).to.deep.equal(json); + }); + }); + + describe('schemas', () => { + it('should allow to get schemas', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + const { schemas } = dataContract; + + expect(schemas).to.deep.equal(object.documentSchemas); + }); + }); + + describe('version', () => { + it('should allow to get version', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + expect(dataContract.version).to.deep.equal(json.version); + }); + + it('should allow to set version', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + dataContract.version = 20; + + expect(dataContract.version).to.equal(20); + }); + }); + + describe('id', () => { + it('should allow to get id', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + expect(dataContract.id.toBase58()).to.deep.equal(id); + }); + + it('should allow to set id', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + dataContract.id = new wasm.Identifier('7ckT6Y19HnjfqoPFmfL995i4z2HwgZ8UttNmP99LtCBH'); + + expect(dataContract.id.toBase58()).to.deep.equal('7ckT6Y19HnjfqoPFmfL995i4z2HwgZ8UttNmP99LtCBH'); + }); + }); + + describe('ownerId', () => { + it('should allow to get owner id', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + expect(dataContract.ownerId.toBase58()).to.deep.equal(ownerId); + }); + + it('should allow to set owner id', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + dataContract.ownerId = new wasm.Identifier('3bx13Wd5k4LwHAvXJrayc5HdKPyiccKWYECPQGGYfnVL'); + + expect(dataContract.ownerId.toBase58()).to.deep.equal( + '3bx13Wd5k4LwHAvXJrayc5HdKPyiccKWYECPQGGYfnVL', + ); + }); + }); + + describe('config', () => { + it('should allow to get config', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + const { config } = dataContract; + + expect(config).to.deep.equal(object.config); + }); + }); + + describe('setConfig()', () => { + it('should allow to set config', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + const oldConfig = dataContract.config; + + const newConfig = { ...oldConfig, canBeDeleted: !oldConfig.canBeDeleted }; + + dataContract.setConfig(newConfig, PlatformVersion.PLATFORM_V1); + + expect(dataContract.config).to.deep.equal(newConfig); + }); + }); + + describe('setSchemas()', () => { + it('should allow to set schema', () => { + const dataContract = wasm.DataContract.fromJSON(json, true); + + // Use JSON fixture for setting (numbers, not BigInt) + const newSchema = { + pupup: json.documentSchemas.withdrawal, + }; + + dataContract.setSchemas(newSchema, null, true, PlatformVersion.PLATFORM_V1); + + const { schemas } = dataContract; + + // schemas returns object format (BigInt), so compare with object fixture + const expectedSchema = { + pupup: object.documentSchemas.withdrawal, + }; + + expect(schemas).to.deep.equal(expectedSchema); + }); + }); + + describe('generateId()', () => { + it('should allow to generate id', () => { + const identifier = new wasm.Identifier('3bx13Wd5k4LwHAvXJrayc5HdKPyiccKWYECPQGGYfnVL'); + + const generatedId = wasm.DataContract.generateId(identifier, BigInt(4)); + + expect(generatedId.toBase58()).to.deep.equal('7ckT6Y19HnjfqoPFmfL995i4z2HwgZ8UttNmP99LtCBH'); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/DataContractCreateStateTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/DataContractCreateStateTransition.spec.ts similarity index 55% rename from packages/wasm-dpp2/tests/unit/DataContractCreateStateTransition.spec.mjs rename to packages/wasm-dpp2/tests/unit/DataContractCreateStateTransition.spec.ts index e0e24974434..89dd2a2c98c 100644 --- a/packages/wasm-dpp2/tests/unit/DataContractCreateStateTransition.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/DataContractCreateStateTransition.spec.ts @@ -1,27 +1,42 @@ -import getWasm from './helpers/wasm.js'; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; import { value, dataContractsBytes } from './mocks/DataContract/index.js'; -import { fromHexString } from './utils/hex.js'; +import { fromHexString } from './utils/hex.ts'; -let wasm; -let PlatformVersion; +let PlatformVersion: typeof wasm.PlatformVersion; before(async () => { - wasm = await getWasm(); + await initWasm(); ({ PlatformVersion } = wasm); }); -describe('DataContract Create Transition', () => { - describe('serialization / deserialization', () => { - it('should allow to create document_transitions from data contract', () => { +describe('DataContractCreateTransition', () => { + describe('constructor()', () => { + it('should create transition from data contract', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); - expect(dataContractTransition.__wbg_ptr).to.not.equal(0); - expect(dataContract.__wbg_ptr).to.not.equal(0); + expect(dataContractTransition).to.be.an.instanceof(wasm.DataContractCreateTransition); + expect(dataContract).to.be.an.instanceof(wasm.DataContract); }); + }); - it('should allow to convert document_transitions to bytes and create from bytes', () => { + describe('toBytes()', () => { + it('should convert transition to bytes', () => { + const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); + + const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); + + const bytes = dataContractTransition.toBytes(); + + expect(bytes).to.be.an.instanceof(Uint8Array); + expect(bytes.length).to.be.greaterThan(0); + }); + }); + + describe('fromBytes()', () => { + it('should create transition from bytes', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); @@ -31,12 +46,14 @@ describe('DataContract Create Transition', () => { const newDataContractTransition = wasm.DataContractCreateTransition.fromBytes(bytes); expect(newDataContractTransition.toBytes()).to.deep.equal(bytes); - expect(newDataContractTransition.__wbg_ptr).to.not.equal(0); - expect(dataContractTransition.__wbg_ptr).to.not.equal(0); - expect(dataContract.__wbg_ptr).to.not.equal(0); + expect(newDataContractTransition).to.be.an.instanceof(wasm.DataContractCreateTransition); + expect(dataContractTransition).to.be.an.instanceof(wasm.DataContractCreateTransition); + expect(dataContract).to.be.an.instanceof(wasm.DataContract); }); + }); - it('should allow to convert data contract transition to state document_transitions and create data contract transition from state transition', () => { + describe('toStateTransition()', () => { + it('should convert to state transition', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); @@ -49,16 +66,32 @@ describe('DataContract Create Transition', () => { }); }); - describe('getters', () => { - it('should allow to get feature version', () => { + describe('fromStateTransition()', () => { + it('should create transition from state transition', () => { + const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); + + const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); + + const stateTransition = dataContractTransition.toStateTransition(); + + const newDataContractTransition = wasm.DataContractCreateTransition.fromStateTransition(stateTransition); + + expect(dataContractTransition.toBytes()).to.deep.equal(newDataContractTransition.toBytes()); + }); + }); + + describe('featureVersion', () => { + it('should return feature version', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); expect(dataContractTransition.featureVersion).to.equal(0); }); + }); - it('should allow to verify protocol version', () => { + describe('verifyProtocolVersion()', () => { + it('should return true for valid protocol version', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); @@ -66,7 +99,7 @@ describe('DataContract Create Transition', () => { expect(dataContractTransition.verifyProtocolVersion(1)).to.equal(true); }); - it('should allow to verify incorrect protocol version', () => { + it('should throw for invalid protocol version', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); @@ -74,12 +107,14 @@ describe('DataContract Create Transition', () => { try { dataContractTransition.verifyProtocolVersion(20); expect(true).to.equal(false); - } catch (error) { + } catch { expect(false).to.equal(false); } }); + }); - it('should allow to get data contract', () => { + describe('getDataContract()', () => { + it('should return data contract', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractCreateTransition(dataContract, BigInt(1)); @@ -90,8 +125,8 @@ describe('DataContract Create Transition', () => { }); }); - describe('setters', () => { - it('should allow to set the data contract', () => { + describe('setDataContract()', () => { + it('should set the data contract', () => { const [dataContractBytes] = dataContractsBytes; const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); diff --git a/packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransition.spec.ts similarity index 55% rename from packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransition.spec.mjs rename to packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransition.spec.ts index 615406ac095..65064c2f776 100644 --- a/packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransition.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransition.spec.ts @@ -1,27 +1,42 @@ -import getWasm from './helpers/wasm.js'; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; import { value, dataContractsBytes } from './mocks/DataContract/index.js'; -import { fromHexString } from './utils/hex.js'; +import { fromHexString } from './utils/hex.ts'; -let wasm; -let PlatformVersion; +let PlatformVersion: typeof wasm.PlatformVersion; before(async () => { - wasm = await getWasm(); + await initWasm(); ({ PlatformVersion } = wasm); }); -describe('DataContract Update Transition', () => { - describe('serialization / deserialization', () => { - it('should allow to create document_transitions from data contract', () => { +describe('DataContractUpdateTransition', () => { + describe('constructor()', () => { + it('should create transition from data contract', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); - expect(dataContractTransition.__wbg_ptr).to.not.equal(0); - expect(dataContract.__wbg_ptr).to.not.equal(0); + expect(dataContractTransition).to.be.an.instanceof(wasm.DataContractUpdateTransition); + expect(dataContract).to.be.an.instanceof(wasm.DataContract); }); + }); - it('should allow to convert document_transitions to bytes and create from bytes', () => { + describe('toBytes()', () => { + it('should convert transition to bytes', () => { + const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); + + const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); + + const bytes = dataContractTransition.toBytes(); + + expect(bytes).to.be.an.instanceof(Uint8Array); + expect(bytes.length).to.be.greaterThan(0); + }); + }); + + describe('fromBytes()', () => { + it('should create transition from bytes', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); @@ -31,12 +46,14 @@ describe('DataContract Update Transition', () => { const newDataContractTransition = wasm.DataContractUpdateTransition.fromBytes(bytes); expect(newDataContractTransition.toBytes()).to.deep.equal(bytes); - expect(newDataContractTransition.__wbg_ptr).to.not.equal(0); - expect(dataContractTransition.__wbg_ptr).to.not.equal(0); - expect(dataContract.__wbg_ptr).to.not.equal(0); + expect(newDataContractTransition).to.be.an.instanceof(wasm.DataContractUpdateTransition); + expect(dataContractTransition).to.be.an.instanceof(wasm.DataContractUpdateTransition); + expect(dataContract).to.be.an.instanceof(wasm.DataContract); }); + }); - it('should allow to convert data contract transition to state document_transitions and create data contract transition from state transition', () => { + describe('toStateTransition()', () => { + it('should convert to state transition', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); @@ -49,16 +66,32 @@ describe('DataContract Update Transition', () => { }); }); - describe('getters', () => { - it('should allow to get feature version', () => { + describe('fromStateTransition()', () => { + it('should create transition from state transition', () => { + const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); + + const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); + + const stateTransition = dataContractTransition.toStateTransition(); + + const newDataContractTransition = wasm.DataContractUpdateTransition.fromStateTransition(stateTransition); + + expect(dataContractTransition.toBytes()).to.deep.equal(newDataContractTransition.toBytes()); + }); + }); + + describe('featureVersion', () => { + it('should return feature version', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); expect(dataContractTransition.featureVersion).to.equal(0); }); + }); - it('should allow to verify protocol version', () => { + describe('verifyProtocolVersion()', () => { + it('should return true for valid protocol version', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); @@ -66,7 +99,7 @@ describe('DataContract Update Transition', () => { expect(dataContractTransition.verifyProtocolVersion(1)).to.equal(true); }); - it('should allow to verify incorrect protocol version', () => { + it('should throw for invalid protocol version', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); @@ -74,12 +107,14 @@ describe('DataContract Update Transition', () => { try { dataContractTransition.verifyProtocolVersion(20); expect(true).to.equal(false); - } catch (error) { + } catch { expect(false).to.equal(false); } }); + }); - it('should allow to get data contract', () => { + describe('getDataContract()', () => { + it('should return data contract', () => { const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); const dataContractTransition = new wasm.DataContractUpdateTransition(dataContract, BigInt(1)); @@ -90,8 +125,8 @@ describe('DataContract Update Transition', () => { }); }); - describe('setters', () => { - it('should allow to set the data contract', () => { + describe('setDataContract()', () => { + it('should set the data contract', () => { const [dataContractBytes] = dataContractsBytes; const dataContract = wasm.DataContract.fromJSON(value, false, PlatformVersion.PLATFORM_V1); diff --git a/packages/wasm-dpp2/tests/unit/DistributionFunction.spec.mjs b/packages/wasm-dpp2/tests/unit/DistributionFunction.spec.mjs deleted file mode 100644 index 65168b43b4e..00000000000 --- a/packages/wasm-dpp2/tests/unit/DistributionFunction.spec.mjs +++ /dev/null @@ -1,420 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('DistributionFunction', function () { - describe('serialization / deserialization', function () { - it('should allow to create FixedAmountDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111) - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create Random', () => { - const distributionFunction = wasm.DistributionFunction.Random( - BigInt(111), - BigInt(113) - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create StepDecreasingAmount', () => { - const distributionFunction = wasm.DistributionFunction.StepDecreasingAmount( - 11, - 11, - 11, - undefined, - undefined, - BigInt(111), - BigInt(113), - BigInt(1) - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create Stepwise', () => { - const distributionFunction = wasm.DistributionFunction.Stepwise( - { - 11111111121: BigInt(111) - } - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create Linear', () => { - const distributionFunction = wasm.DistributionFunction.Linear( - BigInt(111), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create Polynomial', () => { - const distributionFunction = wasm.DistributionFunction.Polynomial( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create Exponential', () => { - const distributionFunction = wasm.DistributionFunction.Exponential( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create Logarithmic', () => { - const distributionFunction = wasm.DistributionFunction.Logarithmic( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - - it('should allow to create InvertedLogarithmic', () => { - const distributionFunction = wasm.DistributionFunction.InvertedLogarithmic( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.__wbg_ptr).to.not.equal(0) - }) - }) - - describe('getters', function () { - describe('function name', function () { - it('FixedAmountDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111) - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('FixedAmount') - }) - - it('Random', () => { - const distributionFunction = wasm.DistributionFunction.Random( - BigInt(111), - BigInt(113) - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('Random') - }) - - it('StepDecreasingAmount', () => { - const distributionFunction = wasm.DistributionFunction.StepDecreasingAmount( - 11, - 11, - 11, - undefined, - undefined, - BigInt(111), - BigInt(113), - BigInt(1) - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('StepDecreasingAmount') - }) - - it('Stepwise', () => { - const distributionFunction = wasm.DistributionFunction.Stepwise( - { - 11111111121: BigInt(111) - } - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('Stepwise') - }) - - it('Linear', () => { - const distributionFunction = wasm.DistributionFunction.Linear( - BigInt(111), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('Linear') - }) - - it('Polynomial', () => { - const distributionFunction = wasm.DistributionFunction.Polynomial( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('Polynomial') - }) - - it('Exponential', () => { - const distributionFunction = wasm.DistributionFunction.Exponential( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('Exponential') - }) - - it('Logarithmic', () => { - const distributionFunction = wasm.DistributionFunction.Logarithmic( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('Logarithmic') - }) - - it('InvertedLogarithmic', () => { - const distributionFunction = wasm.DistributionFunction.InvertedLogarithmic( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionName()).to.deep.equal('InvertedLogarithmic') - }) - }) - describe('function value', function () { - it('FixedAmountDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111) - ) - - expect(distributionFunction.getFunctionValue().amount).to.deep.equal(111n) - }) - - it('Random', () => { - const distributionFunction = wasm.DistributionFunction.Random( - BigInt(111), - BigInt(113) - ) - - expect(distributionFunction.getFunctionValue().min).to.deep.equal(111n) - expect(distributionFunction.getFunctionValue().max).to.deep.equal(113n) - }) - - it('StepDecreasingAmount', () => { - const distributionFunction = wasm.DistributionFunction.StepDecreasingAmount( - 11, - 11, - 11, - undefined, - undefined, - BigInt(111), - BigInt(113), - BigInt(1) - ) - - expect(distributionFunction.getFunctionValue().stepCount).to.deep.equal(11) - expect(distributionFunction.getFunctionValue().decreasePerIntervalNumerator).to.deep.equal(11) - expect(distributionFunction.getFunctionValue().decreasePerIntervalDenominator).to.deep.equal(11) - expect(distributionFunction.getFunctionValue().startDecreasingOffset).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().maxIntervalCount).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().distributionStartAmount).to.deep.equal(111n) - expect(distributionFunction.getFunctionValue().trailingDistributionIntervalAmount).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().minValue).to.deep.equal(1n) - }) - - it('Stepwise', () => { - const distributionFunction = wasm.DistributionFunction.Stepwise( - { - 11111111121: BigInt(111) - } - ) - - expect(distributionFunction.getFunctionValue()).to.deep.equal({ - 11111111121: BigInt(111) - }) - }) - - it('Linear', () => { - const distributionFunction = wasm.DistributionFunction.Linear( - BigInt(111), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionValue().a).to.deep.equal(111n) - expect(distributionFunction.getFunctionValue().d).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().startStep).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().startingAmount).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().minValue).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().maxValue).to.deep.equal(undefined) - }) - - it('Polynomial', () => { - const distributionFunction = wasm.DistributionFunction.Polynomial( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionValue().a).to.deep.equal(111n) - expect(distributionFunction.getFunctionValue().d).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().m).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().n).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().o).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().startMoment).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().b).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().minValue).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().maxValue).to.deep.equal(undefined) - }) - - it('Exponential', () => { - const distributionFunction = wasm.DistributionFunction.Exponential( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionValue().a).to.deep.equal(111n) - expect(distributionFunction.getFunctionValue().d).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().m).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().n).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().o).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().startMoment).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().b).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().minValue).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().maxValue).to.deep.equal(undefined) - }) - - it('Logarithmic', () => { - const distributionFunction = wasm.DistributionFunction.Logarithmic( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionValue().a).to.deep.equal(111n) - expect(distributionFunction.getFunctionValue().d).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().m).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().n).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().o).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().startMoment).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().b).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().minValue).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().maxValue).to.deep.equal(undefined) - }) - - it('InvertedLogarithmic', () => { - const distributionFunction = wasm.DistributionFunction.InvertedLogarithmic( - BigInt(111), - BigInt(113), - BigInt(113), - BigInt(113), - BigInt(113), - undefined, - BigInt(113), - undefined, - undefined - ) - - expect(distributionFunction.getFunctionValue().a).to.deep.equal(111n) - expect(distributionFunction.getFunctionValue().d).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().m).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().n).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().o).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().startMoment).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().b).to.deep.equal(113n) - expect(distributionFunction.getFunctionValue().minValue).to.deep.equal(undefined) - expect(distributionFunction.getFunctionValue().maxValue).to.deep.equal(undefined) - }) - }) - }) -}) diff --git a/packages/wasm-dpp2/tests/unit/DistributionFunction.spec.ts b/packages/wasm-dpp2/tests/unit/DistributionFunction.spec.ts new file mode 100644 index 00000000000..cd3a5b1c2c1 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/DistributionFunction.spec.ts @@ -0,0 +1,400 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('DistributionFunction', () => { + describe('FixedAmountDistribution()', () => { + it('should create FixedAmountDistribution', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return FixedAmount for functionName', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + expect(distributionFunction.functionName).to.deep.equal('FixedAmount'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + expect(distributionFunction.functionValue.amount).to.deep.equal(111n); + }); + }); + + describe('Random()', () => { + it('should create Random', () => { + const distributionFunction = wasm.DistributionFunction.Random( + new wasm.DistributionRandom({ min: BigInt(111), max: BigInt(113) }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return Random for functionName', () => { + const distributionFunction = wasm.DistributionFunction.Random( + new wasm.DistributionRandom({ min: BigInt(111), max: BigInt(113) }), + ); + + expect(distributionFunction.functionName).to.deep.equal('Random'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.Random( + new wasm.DistributionRandom({ min: BigInt(111), max: BigInt(113) }), + ); + + expect(distributionFunction.functionValue.min).to.deep.equal(111n); + expect(distributionFunction.functionValue.max).to.deep.equal(113n); + }); + }); + + describe('StepDecreasingAmount()', () => { + it('should create StepDecreasingAmount', () => { + const distributionFunction = wasm.DistributionFunction.StepDecreasingAmount( + new wasm.DistributionStepDecreasingAmount({ + stepCount: 11, + decreasePerIntervalNumerator: 11, + decreasePerIntervalDenominator: 11, + distributionStartAmount: BigInt(111), + trailingDistributionIntervalAmount: BigInt(113), + minValue: BigInt(1), + }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return StepDecreasingAmount for functionName', () => { + const distributionFunction = wasm.DistributionFunction.StepDecreasingAmount( + new wasm.DistributionStepDecreasingAmount({ + stepCount: 11, + decreasePerIntervalNumerator: 11, + decreasePerIntervalDenominator: 11, + distributionStartAmount: BigInt(111), + trailingDistributionIntervalAmount: BigInt(113), + minValue: BigInt(1), + }), + ); + + expect(distributionFunction.functionName).to.deep.equal('StepDecreasingAmount'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.StepDecreasingAmount( + new wasm.DistributionStepDecreasingAmount({ + stepCount: 11, + decreasePerIntervalNumerator: 11, + decreasePerIntervalDenominator: 11, + distributionStartAmount: BigInt(111), + trailingDistributionIntervalAmount: BigInt(113), + minValue: BigInt(1), + }), + ); + + expect(distributionFunction.functionValue.stepCount).to.deep.equal(11); + expect(distributionFunction.functionValue.decreasePerIntervalNumerator).to.deep.equal(11); + expect(distributionFunction.functionValue.decreasePerIntervalDenominator).to.deep.equal(11); + expect(distributionFunction.functionValue.startDecreasingOffset).to.deep.equal(undefined); + expect(distributionFunction.functionValue.maxIntervalCount).to.deep.equal(undefined); + expect(distributionFunction.functionValue.distributionStartAmount).to.deep.equal(111n); + expect(distributionFunction.functionValue.trailingDistributionIntervalAmount).to.deep.equal(113n); + expect(distributionFunction.functionValue.minValue).to.deep.equal(1n); + }); + }); + + describe('Stepwise()', () => { + it('should create Stepwise', () => { + const distributionFunction = wasm.DistributionFunction.Stepwise( + { + 11111111121: BigInt(111), + }, + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return Stepwise for functionName', () => { + const distributionFunction = wasm.DistributionFunction.Stepwise( + { + 11111111121: BigInt(111), + }, + ); + + expect(distributionFunction.functionName).to.deep.equal('Stepwise'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.Stepwise( + { + 11111111121: BigInt(111), + }, + ); + + expect(distributionFunction.functionValue).to.deep.equal({ + 11111111121: BigInt(111), + }); + }); + }); + + describe('Linear()', () => { + it('should create Linear', () => { + const distributionFunction = wasm.DistributionFunction.Linear( + new wasm.DistributionLinear({ a: BigInt(111), d: BigInt(113), startingAmount: BigInt(113) }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return Linear for functionName', () => { + const distributionFunction = wasm.DistributionFunction.Linear( + new wasm.DistributionLinear({ a: BigInt(111), d: BigInt(113), startingAmount: BigInt(113) }), + ); + + expect(distributionFunction.functionName).to.deep.equal('Linear'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.Linear( + new wasm.DistributionLinear({ a: BigInt(111), d: BigInt(113), startingAmount: BigInt(113) }), + ); + + expect(distributionFunction.functionValue.a).to.deep.equal(111n); + expect(distributionFunction.functionValue.d).to.deep.equal(113n); + expect(distributionFunction.functionValue.startStep).to.deep.equal(undefined); + expect(distributionFunction.functionValue.startingAmount).to.deep.equal(113n); + expect(distributionFunction.functionValue.minValue).to.deep.equal(undefined); + expect(distributionFunction.functionValue.maxValue).to.deep.equal(undefined); + }); + }); + + describe('Polynomial()', () => { + it('should create Polynomial', () => { + const distributionFunction = wasm.DistributionFunction.Polynomial( + new wasm.DistributionPolynomial({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return Polynomial for functionName', () => { + const distributionFunction = wasm.DistributionFunction.Polynomial( + new wasm.DistributionPolynomial({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionName).to.deep.equal('Polynomial'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.Polynomial( + new wasm.DistributionPolynomial({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionValue.a).to.deep.equal(111n); + expect(distributionFunction.functionValue.d).to.deep.equal(113n); + expect(distributionFunction.functionValue.m).to.deep.equal(113n); + expect(distributionFunction.functionValue.n).to.deep.equal(113n); + expect(distributionFunction.functionValue.o).to.deep.equal(113n); + expect(distributionFunction.functionValue.startMoment).to.deep.equal(undefined); + expect(distributionFunction.functionValue.b).to.deep.equal(113n); + expect(distributionFunction.functionValue.minValue).to.deep.equal(undefined); + expect(distributionFunction.functionValue.maxValue).to.deep.equal(undefined); + }); + }); + + describe('Exponential()', () => { + it('should create Exponential', () => { + const distributionFunction = wasm.DistributionFunction.Exponential( + new wasm.DistributionExponential({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return Exponential for functionName', () => { + const distributionFunction = wasm.DistributionFunction.Exponential( + new wasm.DistributionExponential({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionName).to.deep.equal('Exponential'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.Exponential( + new wasm.DistributionExponential({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionValue.a).to.deep.equal(111n); + expect(distributionFunction.functionValue.d).to.deep.equal(113n); + expect(distributionFunction.functionValue.m).to.deep.equal(113n); + expect(distributionFunction.functionValue.n).to.deep.equal(113n); + expect(distributionFunction.functionValue.o).to.deep.equal(113n); + expect(distributionFunction.functionValue.startMoment).to.deep.equal(undefined); + expect(distributionFunction.functionValue.b).to.deep.equal(113n); + expect(distributionFunction.functionValue.minValue).to.deep.equal(undefined); + expect(distributionFunction.functionValue.maxValue).to.deep.equal(undefined); + }); + }); + + describe('Logarithmic()', () => { + it('should create Logarithmic', () => { + const distributionFunction = wasm.DistributionFunction.Logarithmic( + new wasm.DistributionLogarithmic({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return Logarithmic for functionName', () => { + const distributionFunction = wasm.DistributionFunction.Logarithmic( + new wasm.DistributionLogarithmic({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionName).to.deep.equal('Logarithmic'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.Logarithmic( + new wasm.DistributionLogarithmic({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionValue.a).to.deep.equal(111n); + expect(distributionFunction.functionValue.d).to.deep.equal(113n); + expect(distributionFunction.functionValue.m).to.deep.equal(113n); + expect(distributionFunction.functionValue.n).to.deep.equal(113n); + expect(distributionFunction.functionValue.o).to.deep.equal(113n); + expect(distributionFunction.functionValue.startMoment).to.deep.equal(undefined); + expect(distributionFunction.functionValue.b).to.deep.equal(113n); + expect(distributionFunction.functionValue.minValue).to.deep.equal(undefined); + expect(distributionFunction.functionValue.maxValue).to.deep.equal(undefined); + }); + }); + + describe('InvertedLogarithmic()', () => { + it('should create InvertedLogarithmic', () => { + const distributionFunction = wasm.DistributionFunction.InvertedLogarithmic( + new wasm.DistributionInvertedLogarithmic({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + }); + + it('should return InvertedLogarithmic for functionName', () => { + const distributionFunction = wasm.DistributionFunction.InvertedLogarithmic( + new wasm.DistributionInvertedLogarithmic({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionName).to.deep.equal('InvertedLogarithmic'); + }); + + it('should return correct functionValue', () => { + const distributionFunction = wasm.DistributionFunction.InvertedLogarithmic( + new wasm.DistributionInvertedLogarithmic({ + a: BigInt(111), +d: BigInt(113), +m: BigInt(113), + n: BigInt(113), +o: BigInt(113), +b: BigInt(113), + }), + ); + + expect(distributionFunction.functionValue.a).to.deep.equal(111n); + expect(distributionFunction.functionValue.d).to.deep.equal(113n); + expect(distributionFunction.functionValue.m).to.deep.equal(113n); + expect(distributionFunction.functionValue.n).to.deep.equal(113n); + expect(distributionFunction.functionValue.o).to.deep.equal(113n); + expect(distributionFunction.functionValue.startMoment).to.deep.equal(undefined); + expect(distributionFunction.functionValue.b).to.deep.equal(113n); + expect(distributionFunction.functionValue.minValue).to.deep.equal(undefined); + expect(distributionFunction.functionValue.maxValue).to.deep.equal(undefined); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/Document.spec.mjs b/packages/wasm-dpp2/tests/unit/Document.spec.ts similarity index 54% rename from packages/wasm-dpp2/tests/unit/Document.spec.mjs rename to packages/wasm-dpp2/tests/unit/Document.spec.ts index 5c56086fc1b..7fd275ee194 100644 --- a/packages/wasm-dpp2/tests/unit/Document.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/Document.spec.ts @@ -1,53 +1,97 @@ -import getWasm from './helpers/wasm.js'; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; import { - document, dataContractId, ownerId, documentTypeName, revision, dataContractValue, id, document2, documentBytes, + document, + dataContractId, + ownerId, + documentTypeName, + revision, + dataContractValue, + id, + document2, + documentBytes, } from './mocks/Document/index.js'; -import { fromHexString } from './utils/hex.js'; +import { fromHexString } from './utils/hex.ts'; -let wasm; -let PlatformVersion; +let PlatformVersion: typeof wasm.PlatformVersion; before(async () => { - wasm = await getWasm(); + await initWasm(); ({ PlatformVersion } = wasm); }); describe('Document', () => { - describe('serialization / deserialization', () => { - it('should allows to create Document from values', () => { - const dataContractIdentifier = new wasm.Identifier(dataContractId); - const ownerIdentifier = new wasm.Identifier(ownerId); + // Helper to create a document with options object + function createDocument( + options: { + properties?: Record; + documentTypeName?: string; + dataContractId?: string; + ownerId?: string; + revision?: bigint; + id?: string; + entropy?: Uint8Array; + } = {}, + ) { + return new wasm.Document({ + properties: options.properties ?? document, + documentTypeName: options.documentTypeName ?? documentTypeName, + dataContractId: options.dataContractId ?? dataContractId, + ownerId: options.ownerId ?? ownerId, + revision: options.revision ?? BigInt(revision), + id: options.id, + entropy: options.entropy, + }); + } - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractIdentifier, ownerIdentifier); + describe('constructor()', () => { + it('should create Document from values', () => { + const documentInstance = createDocument(); - expect(documentInstance.__wbg_ptr).to.not.equal(0); + expect(documentInstance).to.be.an.instanceof(wasm.Document); }); - it('should allows to create Document from values with custom id', () => { - const dataContractIdentifier = new wasm.Identifier(dataContractId); - const ownerIdentifier = new wasm.Identifier(ownerId); - const identifier = new wasm.Identifier(id); - - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractIdentifier, ownerIdentifier, identifier); + it('should create Document from values with custom id', () => { + const documentInstance = createDocument({ id }); - expect(documentInstance.__wbg_ptr).to.not.equal(0); + expect(documentInstance).to.be.an.instanceof(wasm.Document); }); + }); - it('should allows to create Document from bytes and convert to bytes', () => { + describe('toBytes()', () => { + it('should convert Document to bytes', () => { const dataContract = wasm.DataContract.fromJSON(dataContractValue, false); - const documentInstance = wasm.Document.fromBytes(fromHexString(documentBytes), dataContract, 'note'); + const documentInstance = wasm.Document.fromBytes( + fromHexString(documentBytes), + dataContract, + 'note', + PlatformVersion.PLATFORM_V1, + ); const bytes = documentInstance.toBytes(dataContract, PlatformVersion.PLATFORM_V1); - expect(documentInstance.dataContractId.toBase58()).to.equal(dataContract.id.toBase58()); expect(bytes).to.deep.equal(fromHexString(documentBytes)); - expect(dataContract.__wbg_ptr).to.not.equal(0); }); }); - describe('toObject / fromObject', () => { + describe('fromBytes()', () => { + it('should create Document from bytes', () => { + const dataContract = wasm.DataContract.fromJSON(dataContractValue, false); + const documentInstance = wasm.Document.fromBytes( + fromHexString(documentBytes), + dataContract, + 'note', + PlatformVersion.PLATFORM_V1, + ); + + expect(documentInstance.dataContractId.toBase58()).to.equal(dataContract.id.toBase58()); + expect(dataContract).to.be.an.instanceof(wasm.DataContract); + }); + }); + + describe('toObject()', () => { it('should convert to object with binary fields as Uint8Array', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + const documentInstance = createDocument({ id }); const obj = documentInstance.toObject(); @@ -58,9 +102,11 @@ describe('Document', () => { // toObject uses BigInt for u64 values like revision to preserve precision expect(BigInt(obj.$revision)).to.equal(revision); }); + }); + describe('fromObject()', () => { it('should roundtrip through toObject / fromObject', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + const documentInstance = createDocument({ id }); const obj = documentInstance.toObject(); const restored = wasm.Document.fromObject(obj); @@ -73,9 +119,9 @@ describe('Document', () => { }); }); - describe('toJSON / fromJSON', () => { + describe('toJSON()', () => { it('should convert to JSON with identifiers as Base58 strings', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + const documentInstance = createDocument({ id }); const json = documentInstance.toJSON(); @@ -85,9 +131,11 @@ describe('Document', () => { expect(json.$type).to.equal(documentTypeName); expect(json.$revision).to.equal(Number(revision)); }); + }); + describe('fromJSON()', () => { it('should roundtrip through toJSON / fromJSON', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + const documentInstance = createDocument({ id }); const json = documentInstance.toJSON(); const restored = wasm.Document.fromJSON(json); @@ -100,75 +148,79 @@ describe('Document', () => { }); }); - describe('getters', () => { - it('should return document id', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - - expect(documentInstance.id.toBase58()).to.deep.equal(id); - }); - - it('should return owner id', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('generateId()', () => { + it('should generate id', () => { + const generatedId = wasm.Document.generateId('note', ownerId, dataContractId); - expect(documentInstance.ownerId.toBase58()).to.deep.equal(ownerId); + expect(Array.from(generatedId).length).to.equal(32); }); + }); - it('should return data contract id', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('id', () => { + it('should return document id', () => { + const documentInstance = createDocument({ id }); - expect(documentInstance.dataContractId.toBase58()).to.deep.equal(dataContractId); + expect(documentInstance.id.toBase58()).to.deep.equal(id); }); - it('should return properties', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - - expect(documentInstance.properties).to.deep.equal(document); - }); + it('should set document id', () => { + const documentInstance = createDocument({ id }); - it('should return revision', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + documentInstance.id = ownerId; - expect(documentInstance.revision).to.deep.equal(revision); + expect(documentInstance.id.toBase58()).to.deep.equal(ownerId); }); }); - describe('setters', () => { - it('should allow to set document id', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - - documentInstance.id = ownerId; + describe('ownerId', () => { + it('should return owner id', () => { + const documentInstance = createDocument({ id }); - expect(documentInstance.id.toBase58()).to.deep.equal(ownerId); + expect(documentInstance.ownerId.toBase58()).to.deep.equal(ownerId); }); - it('should allow to set document owner id', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + it('should set document owner id', () => { + const documentInstance = createDocument({ id }); documentInstance.ownerId = id; expect(documentInstance.ownerId.toBase58()).to.deep.equal(id); }); + }); - it('should allow to set entropy', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('dataContractId', () => { + it('should return data contract id', () => { + const documentInstance = createDocument({ id }); - const newEntropy = new Array(documentInstance.entropy.length).fill(0); + expect(documentInstance.dataContractId.toBase58()).to.deep.equal(dataContractId); + }); + }); - documentInstance.entropy = newEntropy; + describe('properties', () => { + it('should return properties', () => { + const documentInstance = createDocument({ id }); - expect(Array.from(documentInstance.entropy)).to.deep.equal(newEntropy); + expect(documentInstance.properties).to.deep.equal(document); }); - it('should allow to set properties', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + it('should set properties', () => { + const documentInstance = createDocument({ id }); documentInstance.properties = document2; expect(documentInstance.properties).to.deep.equal(document2); }); + }); + + describe('revision', () => { + it('should return revision', () => { + const documentInstance = createDocument({ id }); + + expect(documentInstance.revision).to.deep.equal(revision); + }); - it('should allow to set revision', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + it('should set revision', () => { + const documentInstance = createDocument({ id }); const newRevision = BigInt(1000); @@ -176,9 +228,23 @@ describe('Document', () => { expect(documentInstance.revision).to.deep.equal(newRevision); }); + }); + + describe('entropy', () => { + it('should set entropy', () => { + const documentInstance = createDocument({ id }); + + const newEntropy = new Array(documentInstance.entropy.length).fill(0); + + documentInstance.entropy = newEntropy; + + expect(Array.from(documentInstance.entropy)).to.deep.equal(newEntropy); + }); + }); - it('should allow to set created at', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('createdAt', () => { + it('should set created at', () => { + const documentInstance = createDocument({ id }); const createdAt = BigInt(new Date(1123).getTime()); @@ -186,9 +252,11 @@ describe('Document', () => { expect(documentInstance.createdAt).to.deep.equal(createdAt); }); + }); - it('should allow to set updated at', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('updatedAt', () => { + it('should set updated at', () => { + const documentInstance = createDocument({ id }); const updatedAt = BigInt(new Date(1123).getTime()); @@ -196,9 +264,11 @@ describe('Document', () => { expect(documentInstance.updatedAt).to.deep.equal(updatedAt); }); + }); - it('should allow to set transferred at', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('transferredAt', () => { + it('should set transferred at', () => { + const documentInstance = createDocument({ id }); const transferredAt = BigInt(new Date(11231).getTime()); @@ -206,9 +276,11 @@ describe('Document', () => { expect(documentInstance.transferredAt).to.deep.equal(transferredAt); }); + }); - it('should allow to set create at Block Height', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('createdAtBlockHeight', () => { + it('should set created at Block Height', () => { + const documentInstance = createDocument({ id }); const createdAtHeight = BigInt(9172); @@ -216,9 +288,11 @@ describe('Document', () => { expect(documentInstance.createdAtBlockHeight).to.deep.equal(createdAtHeight); }); + }); - it('should allow to set updated at Block Height', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('updatedAtBlockHeight', () => { + it('should set updated at Block Height', () => { + const documentInstance = createDocument({ id }); const updatedAtHeight = BigInt(9172); @@ -226,9 +300,11 @@ describe('Document', () => { expect(documentInstance.updatedAtBlockHeight).to.deep.equal(updatedAtHeight); }); + }); - it('should allow to set transferred at Block Height', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('transferredAtBlockHeight', () => { + it('should set transferred at Block Height', () => { + const documentInstance = createDocument({ id }); const transferredAtHeight = BigInt(9172); @@ -236,9 +312,11 @@ describe('Document', () => { expect(documentInstance.transferredAtBlockHeight).to.deep.equal(transferredAtHeight); }); + }); - it('should allow to set create at core Block Height', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('createdAtCoreBlockHeight', () => { + it('should set created at core Block Height', () => { + const documentInstance = createDocument({ id }); const createdAtHeight = 91721; @@ -246,9 +324,11 @@ describe('Document', () => { expect(documentInstance.createdAtCoreBlockHeight).to.deep.equal(createdAtHeight); }); + }); - it('should allow to set updated at Block Height', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('updatedAtCoreBlockHeight', () => { + it('should set updated at core Block Height', () => { + const documentInstance = createDocument({ id }); const updatedAtHeight = 91722; @@ -256,9 +336,11 @@ describe('Document', () => { expect(documentInstance.updatedAtCoreBlockHeight).to.deep.equal(updatedAtHeight); }); + }); - it('should allow to set transferred at Block Height', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('transferredAtCoreBlockHeight', () => { + it('should set transferred at core Block Height', () => { + const documentInstance = createDocument({ id }); const transferredAtHeight = 91723; @@ -266,9 +348,11 @@ describe('Document', () => { expect(documentInstance.transferredAtCoreBlockHeight).to.deep.equal(transferredAtHeight); }); + }); - it('should allow to set document type name', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); + describe('documentTypeName', () => { + it('should set document type name', () => { + const documentInstance = createDocument({ id }); const newDocumentTypeName = 'bbbb'; @@ -277,12 +361,4 @@ describe('Document', () => { expect(documentInstance.documentTypeName).to.deep.equal(newDocumentTypeName); }); }); - - describe('static', () => { - it('should allow to generate id', () => { - const generatedId = wasm.Document.generateId('note', ownerId, dataContractId); - - expect(Array.from(generatedId).length).to.equal(32); - }); - }); }); diff --git a/packages/wasm-dpp2/tests/unit/DocumentTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/DocumentTransition.spec.mjs deleted file mode 100644 index 7ca9b9f7afe..00000000000 --- a/packages/wasm-dpp2/tests/unit/DocumentTransition.spec.mjs +++ /dev/null @@ -1,100 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { - document, documentTypeName, revision, dataContractId, ownerId, id, -} from './mocks/Document/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -let documentInstance; -let createTransition; -let replaceTransition; - -describe('DocumentTransition', () => { - before(async () => { - documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - }); - - describe('serialization / deserialization', () => { - it('should allow to create from documents document_transitions', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to get action type', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.actionType).to.equal('create'); - }); - - it('should allow to get dataContractId', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.dataContractId.toBase58()).to.deep.equal(documentInstance.dataContractId.toBase58()); - }); - - it('should allow to get id', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.id.toBase58()).to.deep.equal(documentInstance.id.toBase58()); - }); - - it('should allow to get documentTypeName', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.documentTypeName).to.equal(documentTypeName); - }); - - it('should allow to get identityContractNonce', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.identityContractNonce).to.equal(BigInt(1)); - }); - - it('should allow to get revision', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.revision).to.equal(BigInt(1)); - }); - - it('should allow to get entropy', () => { - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentTransition.entropy).to.deep.equal(documentInstance.entropy); - }); - }); - - describe('setters', () => { - it('should allow to set dataContractId', () => { - const documentTransition = createTransition.toDocumentTransition(); - - documentTransition.dataContractId = new Uint8Array(32); - - expect(documentTransition.dataContractId.toBytes()).to.deep.equal(new Uint8Array(32)); - }); - - it('should allow to set identityContractNonce', () => { - const documentTransition = createTransition.toDocumentTransition(); - - documentTransition.identityContractNonce = BigInt(3333); - - expect(documentTransition.identityContractNonce).to.equal(BigInt(3333)); - }); - - it('should allow to set revision', () => { - const documentTransition = replaceTransition.toDocumentTransition(); - - documentTransition.revision = BigInt(123); - - expect(documentTransition.revision).to.equal(BigInt(123)); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/DocumentTransition.spec.ts b/packages/wasm-dpp2/tests/unit/DocumentTransition.spec.ts new file mode 100644 index 00000000000..a87d5d0d7c3 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/DocumentTransition.spec.ts @@ -0,0 +1,130 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { + document, documentTypeName, revision, dataContractId, ownerId, id, +} from './mocks/Document/index.js'; + +before(async () => { + await initWasm(); +}); + +interface DocumentOptions { + properties?: Record; + documentTypeName?: string; + dataContractId?: InstanceType; + ownerId?: InstanceType; + revision?: bigint; + id?: InstanceType; +} + +let documentInstance: InstanceType; +let createTransition: InstanceType; +let replaceTransition: InstanceType; + +describe('DocumentTransition', () => { + // Helper to create a document with options object + function createDocument(options: DocumentOptions = {}) { + return new wasm.Document({ + properties: options.properties ?? document, + documentTypeName: options.documentTypeName ?? documentTypeName, + dataContractId: options.dataContractId ?? dataContractId, + ownerId: options.ownerId ?? ownerId, + revision: options.revision ?? BigInt(revision), + id: options.id ?? id, + }); + } + + before(async () => { + documentInstance = createDocument(); + createTransition = new wasm.DocumentCreateTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + replaceTransition = new wasm.DocumentReplaceTransition({ document: documentInstance, identityContractNonce: BigInt(1) }); + }); + + describe('toDocumentTransition()', () => { + it('should create DocumentTransition from create transition', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + }); + }); + + describe('actionType', () => { + it('should return action type', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition.actionType).to.equal('create'); + }); + }); + + describe('dataContractId', () => { + it('should return dataContractId', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition.dataContractId.toBase58()).to.deep.equal(documentInstance.dataContractId.toBase58()); + }); + + it('should set dataContractId', () => { + const documentTransition = createTransition.toDocumentTransition(); + + documentTransition.dataContractId = new Uint8Array(32); + + expect(documentTransition.dataContractId.toBytes()).to.deep.equal(new Uint8Array(32)); + }); + }); + + describe('id', () => { + it('should return id', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition.id.toBase58()).to.deep.equal(documentInstance.id.toBase58()); + }); + }); + + describe('documentTypeName', () => { + it('should return documentTypeName', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition.documentTypeName).to.equal(documentTypeName); + }); + }); + + describe('identityContractNonce', () => { + it('should return identityContractNonce', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition.identityContractNonce).to.equal(BigInt(1)); + }); + + it('should set identityContractNonce', () => { + const documentTransition = createTransition.toDocumentTransition(); + + documentTransition.identityContractNonce = BigInt(3333); + + expect(documentTransition.identityContractNonce).to.equal(BigInt(3333)); + }); + }); + + describe('revision', () => { + it('should return revision', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition.revision).to.equal(BigInt(1)); + }); + + it('should set revision', () => { + const documentTransition = replaceTransition.toDocumentTransition(); + + documentTransition.revision = BigInt(123); + + expect(documentTransition.revision).to.equal(BigInt(123)); + }); + }); + + describe('entropy', () => { + it('should return entropy', () => { + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition.entropy).to.deep.equal(documentInstance.entropy); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/DocumentsTransitions.spec.mjs b/packages/wasm-dpp2/tests/unit/DocumentsTransitions.spec.mjs deleted file mode 100644 index f6275eb1790..00000000000 --- a/packages/wasm-dpp2/tests/unit/DocumentsTransitions.spec.mjs +++ /dev/null @@ -1,705 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { - document, documentTypeName, revision, dataContractId, ownerId, id, -} from './mocks/Document/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('DocumentsTransitions', () => { - describe('serialization / deserialization', () => { - describe('document Create transition', () => { - it('should allow to create CreateTransition from document', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(createTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Transition from Create transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(createTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Batch Transition from Document Transitions', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(createTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create state document_transitions from document and convert state transition to document batch', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const documentTransition = createTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - const st = batchTransition.toStateTransition(); - - const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); - - const deserializedTransitions = deserializedBatch.transitions; - - expect(deserializedTransitions.length).to.equal(2); - - const deserializedPurchaseTransition = deserializedTransitions[0].toTransition().createTransition; - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(createTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - expect(st.__wbg_ptr).to.not.equal(0); - expect(deserializedBatch.__wbg_ptr).to.not.equal(0); - expect(deserializedPurchaseTransition.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('document Delete transition', () => { - it('should allow to create DeleteTransition from document', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const deleteTransition = new wasm.DocumentDeleteTransition(documentInstance, BigInt(1)); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(deleteTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Transition from Delete transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const deleteTransition = new wasm.DocumentDeleteTransition(documentInstance, BigInt(1)); - - const documentTransition = deleteTransition.toDocumentTransition(); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(deleteTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Batch Transition from Document Transitions', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const deleteTransition = new wasm.DocumentDeleteTransition(documentInstance, BigInt(1)); - - const documentTransition = deleteTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(deleteTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create state document_transitions from document and convert state transition to document batch', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const deleteTransition = new wasm.DocumentDeleteTransition(documentInstance, BigInt(1)); - - const documentTransition = deleteTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - const st = batchTransition.toStateTransition(); - - const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); - - const deserializedTransitions = deserializedBatch.transitions; - - expect(deserializedTransitions.length).to.equal(2); - - const deserializedPurchaseTransition = deserializedTransitions[0].toTransition().deleteTransition; - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(deleteTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - expect(st.__wbg_ptr).to.not.equal(0); - expect(deserializedBatch.__wbg_ptr).to.not.equal(0); - expect(deserializedPurchaseTransition.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('document Replace transition', () => { - it('should allow to create ReplaceTransition from document', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(replaceTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Transition from Replace transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - const documentTransition = replaceTransition.toDocumentTransition(); - - expect(replaceTransition.__wbg_ptr).to.not.equal(0); - expect(replaceTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Batch Transition from Document Transitions', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - const documentTransition = replaceTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(replaceTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create state document_transitions from document and convert state transition to document batch', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - const documentTransition = replaceTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - const st = batchTransition.toStateTransition(); - - const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); - - const deserializedTransitions = deserializedBatch.transitions; - - expect(deserializedTransitions.length).to.equal(2); - - const deserializedPurchaseTransition = deserializedTransitions[0].toTransition().replaceTransition; - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(replaceTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - expect(st.__wbg_ptr).to.not.equal(0); - expect(deserializedBatch.__wbg_ptr).to.not.equal(0); - expect(deserializedPurchaseTransition.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('document Transfer transition', () => { - it('should allow to create ReplaceTransition from document', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(transferTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Transition from Replace transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - const documentTransition = transferTransition.toDocumentTransition(); - - expect(transferTransition.__wbg_ptr).to.not.equal(0); - expect(transferTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Batch Transition from Document Transitions', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - const documentTransition = transferTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(transferTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create state document_transitions from document and convert state transition to document batch', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - const documentTransition = transferTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - const st = batchTransition.toStateTransition(); - - const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); - - const deserializedTransitions = deserializedBatch.transitions; - - expect(deserializedTransitions.length).to.equal(2); - - const deserializedPurchaseTransition = deserializedTransitions[0].toTransition().transferTransition; - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(transferTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - expect(st.__wbg_ptr).to.not.equal(0); - expect(deserializedBatch.__wbg_ptr).to.not.equal(0); - expect(deserializedPurchaseTransition.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('document UpdatePrice transition', () => { - it('should allow to create UpdatePriceTransition from document', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(updatePriceTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Transition from UpdatePrice transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - const documentTransition = updatePriceTransition.toDocumentTransition(); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(updatePriceTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Batch Transition from Document Transitions', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - const documentTransition = updatePriceTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(updatePriceTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create state document_transitions from document and convert state transition to document batch', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - const documentTransition = updatePriceTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - const st = batchTransition.toStateTransition(); - - const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); - - const deserializedTransitions = deserializedBatch.transitions; - - expect(deserializedTransitions.length).to.equal(2); - - const deserializedPurchaseTransition = deserializedTransitions[0].toTransition().updatePriceTransition; - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(updatePriceTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - expect(st.__wbg_ptr).to.not.equal(0); - expect(deserializedBatch.__wbg_ptr).to.not.equal(0); - expect(deserializedPurchaseTransition.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('document Purchase transition', () => { - it('should allow to create PurchaseTransition from document', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(purchaseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Transition from PurchaseTransition transition', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - const documentTransition = purchaseTransition.toDocumentTransition(); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(purchaseTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create Document Batch Transition from Document Transitions', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - const documentTransition = purchaseTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(purchaseTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create state document_transitions from document and convert state transition to document batch', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - const documentTransition = purchaseTransition.toDocumentTransition(); - - const batchTransition = wasm.BatchTransition.fromBatchedTransitions([new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], documentInstance.ownerId, 1); - - const st = batchTransition.toStateTransition(); - - const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); - - const deserializedTransitions = deserializedBatch.transitions; - - expect(deserializedTransitions.length).to.equal(2); - - const deserializedPurchaseTransition = deserializedTransitions[0].toTransition().purchaseTransition; - - expect(documentInstance.__wbg_ptr).to.not.equal(0); - expect(purchaseTransition.__wbg_ptr).to.not.equal(0); - expect(documentTransition.__wbg_ptr).to.not.equal(0); - expect(batchTransition.__wbg_ptr).to.not.equal(0); - expect(st.__wbg_ptr).to.not.equal(0); - expect(deserializedBatch.__wbg_ptr).to.not.equal(0); - expect(deserializedPurchaseTransition.__wbg_ptr).to.not.equal(0); - }); - }); - }); - describe('getters', () => { - describe('document Create transition', () => { - it('get data', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - expect(createTransition.data).to.deep.equal(document); - }); - - it('get base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - expect(createTransition.base.constructor.name).to.equal('DocumentBaseTransition'); - }); - - it('get entropy', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - expect(createTransition.entropy).to.deep.equal(documentInstance.entropy); - }); - - it('get prefunded voting balance', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - expect(createTransition.prefundedVotingBalance).to.equal(undefined); - }); - }); - - describe('document Delete transition', () => { - it('get base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const deleteTransition = new wasm.DocumentDeleteTransition(documentInstance, BigInt(1)); - - expect(deleteTransition.base.constructor.name).to.equal('DocumentBaseTransition'); - }); - }); - - describe('document Replace transition', () => { - it('get data', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - expect(replaceTransition.data).to.deep.equal(document); - }); - - it('get base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - expect(replaceTransition.base.constructor.name).to.equal('DocumentBaseTransition'); - }); - - it('get revision', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - expect(replaceTransition.revision).to.equal(BigInt(2)); - }); - }); - - describe('document Transfer transition', () => { - it('get base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - expect(transferTransition.base.constructor.name).to.equal('DocumentBaseTransition'); - }); - - it('get recipient', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - expect(transferTransition.recipientId.toBase58()).to.deep.equal(documentInstance.ownerId.toBase58()); - }); - }); - - describe('document Update Price transition', () => { - it('get base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - expect(updatePriceTransition.base.constructor.name).to.equal('DocumentBaseTransition'); - }); - - it('get price', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - expect(updatePriceTransition.price).to.deep.equal(BigInt(100)); - }); - }); - - describe('document Purchase transition', () => { - it('get base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - expect(purchaseTransition.base.constructor.name).to.equal('DocumentBaseTransition'); - }); - - it('get price', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - expect(purchaseTransition.price).to.deep.equal(BigInt(100)); - }); - }); - }); - - describe('setters', () => { - describe('document Create transition', () => { - it('set data', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const newData = { message: 'bebra' }; - - createTransition.data = newData; - - expect(createTransition.data).to.deep.equal(newData); - }); - - it('set base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const newBase = new wasm.DocumentBaseTransition( - documentInstance.id, - BigInt(12350), - 'bbbbb', - dataContractId, - ); - - createTransition.base = newBase; - - expect(createTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); - expect(newBase.__wbg_ptr).to.not.equal(0); - }); - - it('set entropy', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const newEntropy = new Uint8Array(32); - - createTransition.entropy = newEntropy; - - expect(createTransition.entropy).to.deep.equal(newEntropy); - }); - - it('set prefunded voting balance', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const createTransition = new wasm.DocumentCreateTransition(documentInstance, BigInt(1)); - - const newPrefundedVotingBalance = new wasm.PrefundedVotingBalance('note', BigInt(9999)); - - createTransition.prefundedVotingBalance = newPrefundedVotingBalance; - - expect(createTransition.prefundedVotingBalance.indexName).to.equal(newPrefundedVotingBalance.indexName); - expect(createTransition.prefundedVotingBalance.credits).to.equal(newPrefundedVotingBalance.credits); - }); - }); - - describe('document Delete transition', () => { - it('set base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const deleteTransition = new wasm.DocumentDeleteTransition(documentInstance, BigInt(1)); - - const newBase = new wasm.DocumentBaseTransition( - documentInstance.id, - BigInt(12350), - 'bbbbb', - dataContractId, - ); - - deleteTransition.base = newBase; - - expect(deleteTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); - expect(newBase.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('document Replace transition', () => { - it('set data', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - const newData = { message: 'bebra' }; - - replaceTransition.data = newData; - - expect(replaceTransition.data).to.deep.equal(newData); - }); - - it('set base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - const newBase = new wasm.DocumentBaseTransition( - documentInstance.id, - BigInt(12350), - 'bbbbb', - dataContractId, - ); - - replaceTransition.base = newBase; - - expect(replaceTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); - expect(newBase.__wbg_ptr).to.not.equal(0); - }); - - it('set revision', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const replaceTransition = new wasm.DocumentReplaceTransition(documentInstance, BigInt(1)); - - replaceTransition.revision = BigInt(11); - - expect(replaceTransition.revision).to.equal(BigInt(11)); - }); - }); - - describe('document Transfer transition', () => { - it('set base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - const newBase = new wasm.DocumentBaseTransition( - documentInstance.id, - BigInt(12350), - 'bbbbb', - dataContractId, - ); - - transferTransition.base = newBase; - - expect(transferTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); - expect(newBase.__wbg_ptr).to.not.equal(0); - }); - - it('set recipient', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const transferTransition = new wasm.DocumentTransferTransition(documentInstance, BigInt(1), documentInstance.ownerId); - - const newRecipient = new Uint8Array(32); - - transferTransition.recipientId = newRecipient; - - expect(transferTransition.recipientId.toBytes()).to.deep.equal(newRecipient); - }); - }); - - describe('document Update Price transition', () => { - it('set base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - const newBase = new wasm.DocumentBaseTransition( - documentInstance.id, - BigInt(12350), - 'bbbbb', - dataContractId, - ); - - updatePriceTransition.base = newBase; - - expect(updatePriceTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); - expect(newBase.__wbg_ptr).to.not.equal(0); - }); - - it('set price', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const updatePriceTransition = new wasm.DocumentUpdatePriceTransition(documentInstance, BigInt(1), BigInt(100)); - - updatePriceTransition.price = BigInt(1111); - - expect(updatePriceTransition.price).to.deep.equal(BigInt(1111)); - }); - }); - - describe('document Purchase transition', () => { - it('set base', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - const newBase = new wasm.DocumentBaseTransition( - documentInstance.id, - BigInt(12350), - 'bbbbb', - dataContractId, - ); - - purchaseTransition.base = newBase; - - expect(purchaseTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); - expect(newBase.__wbg_ptr).to.not.equal(0); - }); - - it('set price', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - purchaseTransition.price = BigInt(1111); - - expect(purchaseTransition.price).to.deep.equal(BigInt(1111)); - }); - - it('set revision', () => { - const documentInstance = new wasm.Document(document, documentTypeName, revision, dataContractId, ownerId, id); - const purchaseTransition = new wasm.DocumentPurchaseTransition(documentInstance, BigInt(1), BigInt(100)); - - purchaseTransition.revision = BigInt(1111); - - expect(purchaseTransition.revision).to.deep.equal(BigInt(1111)); - }); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/DocumentsTransitions.spec.ts b/packages/wasm-dpp2/tests/unit/DocumentsTransitions.spec.ts new file mode 100644 index 00000000000..425cb75df51 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/DocumentsTransitions.spec.ts @@ -0,0 +1,837 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { + document, documentTypeName, revision, dataContractId, ownerId, id, +} from './mocks/Document/index.js'; + +before(async () => { + await initWasm(); +}); + +interface DocumentOptions { + properties?: Record; + documentTypeName?: string; + dataContractId?: InstanceType; + ownerId?: InstanceType; + revision?: bigint; + id?: InstanceType; +} + +describe('DocumentsTransitions', () => { + // Helper to create a document with options object + function createDocument(options: DocumentOptions = {}) { + return new wasm.Document({ + properties: options.properties ?? document, + documentTypeName: options.documentTypeName ?? documentTypeName, + dataContractId: options.dataContractId ?? dataContractId, + ownerId: options.ownerId ?? ownerId, + revision: options.revision ?? BigInt(revision), + id: options.id ?? id, + }); + } + + describe('DocumentCreateTransition', () => { + describe('constructor', () => { + it('should create instance from document', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(documentInstance).to.be.an.instanceof(wasm.Document); + expect(createTransition).to.be.an.instanceof(wasm.DocumentCreateTransition); + }); + }); + + describe('toDocumentTransition()', () => { + it('should create DocumentTransition from CreateTransition', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const documentTransition = createTransition.toDocumentTransition(); + + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + }); + }); + + describe('data', () => { + it('should return data', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(createTransition.data).to.deep.equal(document); + }); + + it('should set data', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const newData = { message: 'bebra' }; + + createTransition.data = newData; + + expect(createTransition.data).to.deep.equal(newData); + }); + }); + + describe('base', () => { + it('should return base', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(createTransition.base.constructor.name).to.equal('DocumentBaseTransition'); + }); + + it('should set base', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const newBase = new wasm.DocumentBaseTransition({ + documentId: documentInstance.id, + identityContractNonce: BigInt(12350), + documentTypeName: 'bbbbb', + dataContractId, + }); + + createTransition.base = newBase; + + expect(createTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); + expect(newBase).to.be.an.instanceof(wasm.DocumentBaseTransition); + }); + }); + + describe('entropy', () => { + it('should return entropy', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(createTransition.entropy).to.deep.equal(documentInstance.entropy); + }); + + it('should set entropy', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const newEntropy = new Uint8Array(32); + + createTransition.entropy = newEntropy; + + expect(createTransition.entropy).to.deep.equal(newEntropy); + }); + }); + + describe('prefundedVotingBalance', () => { + it('should return prefunded voting balance', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(createTransition.prefundedVotingBalance).to.equal(undefined); + }); + + it('should set prefunded voting balance', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const newPrefundedVotingBalance = new wasm.PrefundedVotingBalance({ indexName: 'note', credits: BigInt(9999) }); + + createTransition.prefundedVotingBalance = newPrefundedVotingBalance; + + expect(createTransition.prefundedVotingBalance.indexName).to.equal(newPrefundedVotingBalance.indexName); + expect(createTransition.prefundedVotingBalance.credits).to.equal(newPrefundedVotingBalance.credits); + }); + }); + + describe('BatchTransition.fromBatchedTransitions()', () => { + it('should create BatchTransition from document transitions', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + expect(batchTransition).to.be.an.instanceof(wasm.BatchTransition); + }); + }); + + describe('BatchTransition serialization roundtrip', () => { + it('should serialize and deserialize through state transition', () => { + const documentInstance = createDocument(); + const createTransition = new wasm.DocumentCreateTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const documentTransition = createTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + const st = batchTransition.toStateTransition(); + + const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); + + const deserializedTransitions = deserializedBatch.transitions; + + expect(deserializedTransitions.length).to.equal(2); + + const deserializedCreateTransition = deserializedTransitions[0].toTransition().createTransition; + + expect(deserializedCreateTransition).to.be.an.instanceof(wasm.DocumentCreateTransition); + }); + }); + }); + + describe('DocumentDeleteTransition', () => { + describe('constructor', () => { + it('should create instance from document', () => { + const documentInstance = createDocument(); + const deleteTransition = new wasm.DocumentDeleteTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(documentInstance).to.be.an.instanceof(wasm.Document); + expect(deleteTransition).to.be.an.instanceof(wasm.DocumentDeleteTransition); + }); + }); + + describe('toDocumentTransition()', () => { + it('should create DocumentTransition from DeleteTransition', () => { + const documentInstance = createDocument(); + const deleteTransition = new wasm.DocumentDeleteTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const documentTransition = deleteTransition.toDocumentTransition(); + + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const documentInstance = createDocument(); + const deleteTransition = new wasm.DocumentDeleteTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(deleteTransition.base.constructor.name).to.equal('DocumentBaseTransition'); + }); + + it('should set base', () => { + const documentInstance = createDocument(); + const deleteTransition = new wasm.DocumentDeleteTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const newBase = new wasm.DocumentBaseTransition({ + documentId: documentInstance.id, + identityContractNonce: BigInt(12350), + documentTypeName: 'bbbbb', + dataContractId, + }); + + deleteTransition.base = newBase; + + expect(deleteTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); + expect(newBase).to.be.an.instanceof(wasm.DocumentBaseTransition); + }); + }); + + describe('BatchTransition serialization roundtrip', () => { + it('should serialize and deserialize through state transition', () => { + const documentInstance = createDocument(); + const deleteTransition = new wasm.DocumentDeleteTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const documentTransition = deleteTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + const st = batchTransition.toStateTransition(); + + const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); + + const deserializedTransitions = deserializedBatch.transitions; + + expect(deserializedTransitions.length).to.equal(2); + + const deserializedDeleteTransition = deserializedTransitions[0].toTransition().deleteTransition; + + expect(deserializedDeleteTransition).to.be.an.instanceof(wasm.DocumentDeleteTransition); + }); + }); + }); + + describe('DocumentReplaceTransition', () => { + describe('constructor', () => { + it('should create instance from document', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(documentInstance).to.be.an.instanceof(wasm.Document); + expect(replaceTransition).to.be.an.instanceof(wasm.DocumentReplaceTransition); + }); + }); + + describe('toDocumentTransition()', () => { + it('should create DocumentTransition from ReplaceTransition', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const documentTransition = replaceTransition.toDocumentTransition(); + + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + }); + }); + + describe('data', () => { + it('should return data', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(replaceTransition.data).to.deep.equal(document); + }); + + it('should set data', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const newData = { message: 'bebra' }; + + replaceTransition.data = newData; + + expect(replaceTransition.data).to.deep.equal(newData); + }); + }); + + describe('base', () => { + it('should return base', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(replaceTransition.base.constructor.name).to.equal('DocumentBaseTransition'); + }); + + it('should set base', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const newBase = new wasm.DocumentBaseTransition({ + documentId: documentInstance.id, + identityContractNonce: BigInt(12350), + documentTypeName: 'bbbbb', + dataContractId, + }); + + replaceTransition.base = newBase; + + expect(replaceTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); + expect(newBase).to.be.an.instanceof(wasm.DocumentBaseTransition); + }); + }); + + describe('revision', () => { + it('should return revision', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + expect(replaceTransition.revision).to.equal(BigInt(2)); + }); + + it('should set revision', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + replaceTransition.revision = BigInt(11); + + expect(replaceTransition.revision).to.equal(BigInt(11)); + }); + }); + + describe('BatchTransition serialization roundtrip', () => { + it('should serialize and deserialize through state transition', () => { + const documentInstance = createDocument(); + const replaceTransition = new wasm.DocumentReplaceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + }); + + const documentTransition = replaceTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + const st = batchTransition.toStateTransition(); + + const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); + + const deserializedTransitions = deserializedBatch.transitions; + + expect(deserializedTransitions.length).to.equal(2); + + const deserializedReplaceTransition = deserializedTransitions[0].toTransition().replaceTransition; + + expect(deserializedReplaceTransition).to.be.an.instanceof(wasm.DocumentReplaceTransition); + }); + }); + }); + + describe('DocumentTransferTransition', () => { + describe('constructor', () => { + it('should create instance from document', () => { + const documentInstance = createDocument(); + const transferTransition = new wasm.DocumentTransferTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + recipientOwnerId: documentInstance.ownerId, + }); + + expect(documentInstance).to.be.an.instanceof(wasm.Document); + expect(transferTransition).to.be.an.instanceof(wasm.DocumentTransferTransition); + }); + }); + + describe('toDocumentTransition()', () => { + it('should create DocumentTransition from TransferTransition', () => { + const documentInstance = createDocument(); + const transferTransition = new wasm.DocumentTransferTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + recipientOwnerId: documentInstance.ownerId, + }); + + const documentTransition = transferTransition.toDocumentTransition(); + + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const documentInstance = createDocument(); + const transferTransition = new wasm.DocumentTransferTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + recipientOwnerId: documentInstance.ownerId, + }); + + expect(transferTransition.base.constructor.name).to.equal('DocumentBaseTransition'); + }); + + it('should set base', () => { + const documentInstance = createDocument(); + const transferTransition = new wasm.DocumentTransferTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + recipientOwnerId: documentInstance.ownerId, + }); + + const newBase = new wasm.DocumentBaseTransition({ + documentId: documentInstance.id, + identityContractNonce: BigInt(12350), + documentTypeName: 'bbbbb', + dataContractId, + }); + + transferTransition.base = newBase; + + expect(transferTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); + expect(newBase).to.be.an.instanceof(wasm.DocumentBaseTransition); + }); + }); + + describe('recipientOwnerId', () => { + it('should return recipient', () => { + const documentInstance = createDocument(); + const transferTransition = new wasm.DocumentTransferTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + recipientOwnerId: documentInstance.ownerId, + }); + + expect(transferTransition.recipientOwnerId.toBase58()).to.deep.equal(documentInstance.ownerId.toBase58()); + }); + + it('should set recipient', () => { + const documentInstance = createDocument(); + const transferTransition = new wasm.DocumentTransferTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + recipientOwnerId: documentInstance.ownerId, + }); + + const newRecipient = new Uint8Array(32); + + transferTransition.recipientOwnerId = newRecipient; + + expect(transferTransition.recipientOwnerId.toBytes()).to.deep.equal(newRecipient); + }); + }); + + describe('BatchTransition serialization roundtrip', () => { + it('should serialize and deserialize through state transition', () => { + const documentInstance = createDocument(); + const transferTransition = new wasm.DocumentTransferTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + recipientOwnerId: documentInstance.ownerId, + }); + + const documentTransition = transferTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + const st = batchTransition.toStateTransition(); + + const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); + + const deserializedTransitions = deserializedBatch.transitions; + + expect(deserializedTransitions.length).to.equal(2); + + const deserializedTransferTransition = deserializedTransitions[0].toTransition().transferTransition; + + expect(deserializedTransferTransition).to.be.an.instanceof(wasm.DocumentTransferTransition); + }); + }); + }); + + describe('DocumentUpdatePriceTransition', () => { + describe('constructor', () => { + it('should create instance from document', () => { + const documentInstance = createDocument(); + const updatePriceTransition = new wasm.DocumentUpdatePriceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + price: BigInt(100), + }); + + expect(documentInstance).to.be.an.instanceof(wasm.Document); + expect(updatePriceTransition).to.be.an.instanceof(wasm.DocumentUpdatePriceTransition); + }); + }); + + describe('toDocumentTransition()', () => { + it('should create DocumentTransition from UpdatePriceTransition', () => { + const documentInstance = createDocument(); + const updatePriceTransition = new wasm.DocumentUpdatePriceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + price: BigInt(100), + }); + + const documentTransition = updatePriceTransition.toDocumentTransition(); + + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const documentInstance = createDocument(); + const updatePriceTransition = new wasm.DocumentUpdatePriceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + price: BigInt(100), + }); + + expect(updatePriceTransition.base.constructor.name).to.equal('DocumentBaseTransition'); + }); + + it('should set base', () => { + const documentInstance = createDocument(); + const updatePriceTransition = new wasm.DocumentUpdatePriceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + price: BigInt(100), + }); + + const newBase = new wasm.DocumentBaseTransition({ + documentId: documentInstance.id, + identityContractNonce: BigInt(12350), + documentTypeName: 'bbbbb', + dataContractId, + }); + + updatePriceTransition.base = newBase; + + expect(updatePriceTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); + expect(newBase).to.be.an.instanceof(wasm.DocumentBaseTransition); + }); + }); + + describe('price', () => { + it('should return price', () => { + const documentInstance = createDocument(); + const updatePriceTransition = new wasm.DocumentUpdatePriceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + price: BigInt(100), + }); + + expect(updatePriceTransition.price).to.deep.equal(BigInt(100)); + }); + + it('should set price', () => { + const documentInstance = createDocument(); + const updatePriceTransition = new wasm.DocumentUpdatePriceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + price: BigInt(100), + }); + + updatePriceTransition.price = BigInt(1111); + + expect(updatePriceTransition.price).to.deep.equal(BigInt(1111)); + }); + }); + + describe('BatchTransition serialization roundtrip', () => { + it('should serialize and deserialize through state transition', () => { + const documentInstance = createDocument(); + const updatePriceTransition = new wasm.DocumentUpdatePriceTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + price: BigInt(100), + }); + + const documentTransition = updatePriceTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + const st = batchTransition.toStateTransition(); + + const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); + + const deserializedTransitions = deserializedBatch.transitions; + + expect(deserializedTransitions.length).to.equal(2); + + const deserializedUpdatePriceTransition = deserializedTransitions[0].toTransition().updatePriceTransition; + + expect(deserializedUpdatePriceTransition).to.be.an.instanceof(wasm.DocumentUpdatePriceTransition); + }); + }); + }); + + describe('DocumentPurchaseTransition', () => { + describe('constructor', () => { + it('should create instance from document', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + expect(documentInstance).to.be.an.instanceof(wasm.Document); + expect(purchaseTransition).to.be.an.instanceof(wasm.DocumentPurchaseTransition); + }); + }); + + describe('toDocumentTransition()', () => { + it('should create DocumentTransition from PurchaseTransition', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + const documentTransition = purchaseTransition.toDocumentTransition(); + + expect(documentTransition).to.be.an.instanceof(wasm.DocumentTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + expect(purchaseTransition.base.constructor.name).to.equal('DocumentBaseTransition'); + }); + + it('should set base', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + const newBase = new wasm.DocumentBaseTransition({ + documentId: documentInstance.id, + identityContractNonce: BigInt(12350), + documentTypeName: 'bbbbb', + dataContractId, + }); + + purchaseTransition.base = newBase; + + expect(purchaseTransition.base.identityContractNonce).to.equal(newBase.identityContractNonce); + expect(newBase).to.be.an.instanceof(wasm.DocumentBaseTransition); + }); + }); + + describe('price', () => { + it('should return price', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + expect(purchaseTransition.price).to.deep.equal(BigInt(100)); + }); + + it('should set price', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + purchaseTransition.price = BigInt(1111); + + expect(purchaseTransition.price).to.deep.equal(BigInt(1111)); + }); + }); + + describe('revision', () => { + it('should set revision', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + purchaseTransition.revision = BigInt(1111); + + expect(purchaseTransition.revision).to.deep.equal(BigInt(1111)); + }); + }); + + describe('BatchTransition serialization roundtrip', () => { + it('should serialize and deserialize through state transition', () => { + const documentInstance = createDocument(); + const purchaseTransition = new wasm.DocumentPurchaseTransition({ + document: documentInstance, + identityContractNonce: BigInt(1), + amount: BigInt(100), + }); + + const documentTransition = purchaseTransition.toDocumentTransition(); + + const batchTransition = wasm.BatchTransition.fromBatchedTransitions( + [new wasm.BatchedTransition(documentTransition), new wasm.BatchedTransition(documentTransition)], + documentInstance.ownerId, + 1, + ); + + const st = batchTransition.toStateTransition(); + + const deserializedBatch = wasm.BatchTransition.fromStateTransition(st); + + const deserializedTransitions = deserializedBatch.transitions; + + expect(deserializedTransitions.length).to.equal(2); + + const deserializedPurchaseTransition = deserializedTransitions[0].toTransition().purchaseTransition; + + expect(deserializedPurchaseTransition).to.be.an.instanceof(wasm.DocumentPurchaseTransition); + }); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/Group.spec.mjs b/packages/wasm-dpp2/tests/unit/Group.spec.ts similarity index 53% rename from packages/wasm-dpp2/tests/unit/Group.spec.mjs rename to packages/wasm-dpp2/tests/unit/Group.spec.ts index f21a51bb456..5c92aaa7ac7 100644 --- a/packages/wasm-dpp2/tests/unit/Group.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/Group.spec.ts @@ -1,35 +1,39 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('Group', () => { const memberIdHex = '1111111111111111111111111111111111111111111111111111111111111111'; const member2IdHex = '2222222222222222222222222222222222222222222222222222222222222222'; - - describe('constructor', () => { + function createMembersMap(membersArray: Array<[InstanceType, number]>) { + const map = new Map, number>(); + for (const [identifier, power] of membersArray) { + map.set(identifier, power); + } + return map; + } + + describe('constructor()', () => { it('should create Group with members and required power', () => { const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); - const members = { - [memberId.toBase58()]: 100, - }; + const members = createMembersMap([[memberId, 100]]); const group = new wasm.Group(members, 50); expect(group.requiredPower).to.equal(50); - expect(group.members).to.be.an('object'); + expect(group.members).to.be.instanceOf(Map); }); it('should create Group with multiple members', () => { const memberId1 = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); const memberId2 = wasm.Identifier.fromBytes(Buffer.from(member2IdHex, 'hex')); - const members = { - [memberId1.toBase58()]: 100, - [memberId2.toBase58()]: 50, - }; + const members = createMembersMap([ + [memberId1, 100], + [memberId2, 50], + ]); const group = new wasm.Group(members, 75); @@ -37,85 +41,88 @@ describe('Group', () => { }); }); - describe('getters and setters', () => { - it('should get and set members', () => { + describe('members', () => { + it('should return members', () => { const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); - const members = { - [memberId.toBase58()]: 100, - }; + const members = createMembersMap([[memberId, 100]]); const group = new wasm.Group(members, 50); const fetchedMembers = group.members; - expect(fetchedMembers).to.be.an('object'); - expect(fetchedMembers[memberId.toBase58()]).to.equal(100); + expect(fetchedMembers).to.be.instanceOf(Map); + // Map keys are now base58 strings for value-based lookups + const foundPower = fetchedMembers.get(memberId.toBase58()); + expect(foundPower).to.equal(100); }); + }); - it('should get and set required power', () => { + describe('requiredPower', () => { + it('should return required power', () => { const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); - const members = { - [memberId.toBase58()]: 100, - }; + const members = createMembersMap([[memberId, 100]]); const group = new wasm.Group(members, 50); expect(group.requiredPower).to.equal(50); + }); + + it('should set required power', () => { + const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); + const members = createMembersMap([[memberId, 100]]); + + const group = new wasm.Group(members, 50); group.requiredPower = 75; expect(group.requiredPower).to.equal(75); }); + }); + describe('setMemberRequiredPower()', () => { it('should set member required power', () => { const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); - const members = { - [memberId.toBase58()]: 100, - }; + const members = createMembersMap([[memberId, 100]]); const group = new wasm.Group(members, 50); group.setMemberRequiredPower(memberId, 200); const updatedMembers = group.members; - expect(updatedMembers[memberId.toBase58()]).to.equal(200); + // Map keys are now base58 strings for value-based lookups + const foundPower = updatedMembers.get(memberId.toBase58()); + expect(foundPower).to.equal(200); }); }); - describe('conversion methods', () => { - it('should round-trip via toJSON/fromJSON', () => { + describe('toJSON()', () => { + it('should convert to JSON', () => { const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); - const members = { - [memberId.toBase58()]: 100, - }; + const members = createMembersMap([[memberId, 100]]); const group = new wasm.Group(members, 50); const json = group.toJSON(); expect(json).to.be.an('object'); - - const restored = wasm.Group.fromJSON(json); - expect(restored.requiredPower).to.equal(group.requiredPower); }); + }); - it('should export toObject', () => { + describe('fromJSON()', () => { + it('should roundtrip via toJSON/fromJSON', () => { const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); - const members = { - [memberId.toBase58()]: 100, - }; + const members = createMembersMap([[memberId, 100]]); const group = new wasm.Group(members, 50); - const obj = group.toObject(); - // toObject exports as Map type in serde_wasm_bindgen which doesn't round-trip - // but it should at least be defined - expect(obj).to.not.be.undefined; + const json = group.toJSON(); + const restored = wasm.Group.fromJSON(json); + expect(restored.requiredPower).to.equal(group.requiredPower); }); - it('should round-trip Group with multiple members via toJSON/fromJSON', () => { + it('should roundtrip Group with multiple members via toJSON/fromJSON', () => { const memberId1 = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); const memberId2 = wasm.Identifier.fromBytes(Buffer.from(member2IdHex, 'hex')); - const members = { - [memberId1.toBase58()]: 100, - [memberId2.toBase58()]: 50, - }; + const members = createMembersMap([ + [memberId1, 100], + [memberId2, 50], + ]); const group = new wasm.Group(members, 75); @@ -126,12 +133,24 @@ describe('Group', () => { }); }); - describe('type properties', () => { + describe('toObject()', () => { + it('should export toObject', () => { + const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); + const members = createMembersMap([[memberId, 100]]); + + const group = new wasm.Group(members, 50); + + const obj = group.toObject(); + // toObject exports as Map type in serde_wasm_bindgen which doesn't round-trip + // but it should at least be defined + expect(obj).to.not.be.undefined(); + }); + }); + + describe('__type', () => { it('should return correct __type', () => { const memberId = wasm.Identifier.fromBytes(Buffer.from(memberIdHex, 'hex')); - const members = { - [memberId.toBase58()]: 100, - }; + const members = createMembersMap([[memberId, 100]]); const group = new wasm.Group(members, 50); diff --git a/packages/wasm-dpp2/tests/unit/Identifier.spec.mjs b/packages/wasm-dpp2/tests/unit/Identifier.spec.ts similarity index 54% rename from packages/wasm-dpp2/tests/unit/Identifier.spec.mjs rename to packages/wasm-dpp2/tests/unit/Identifier.spec.ts index 62922673761..4e76c4e5da7 100644 --- a/packages/wasm-dpp2/tests/unit/Identifier.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/Identifier.spec.ts @@ -1,83 +1,103 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); -let identifierBytes; +let identifierBytes: Uint8Array; describe('Identifier', () => { before(async () => { - identifierBytes = Uint8Array.from([9, 40, 40, 237, 192, 129, 211, 186, 26, 84, 240, 67, 37, 155, 148, 19, 104, 242, 199, 24, 136, 27, 6, 169, 211, 71, 136, 59, 33, 191, 227, 19]); + identifierBytes = Uint8Array.from([ + 9, 40, 40, 237, 192, 129, 211, 186, 26, 84, 240, 67, 37, 155, 148, 19, 104, 242, 199, 24, 136, + 27, 6, 169, 211, 71, 136, 59, 33, 191, 227, 19, + ]); }); - describe('serialization / deserialization', () => { - it('should allows to create Identifier from base58', () => { - const identifier = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); + describe('constructor()', () => { + it('should create Identifier from bytes in constructor', () => { + const identifier = new wasm.Identifier(identifierBytes); expect(identifier.toBytes()).to.deep.equal(identifierBytes); }); - it('should allows to create Identifier from base64', () => { - const identifier = wasm.Identifier.fromBase64('CSgo7cCB07oaVPBDJZuUE2jyxxiIGwap00eIOyG/4xM='); + it('should create Identifier from base58 in constructor', () => { + const identifier = new wasm.Identifier('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); expect(identifier.toBytes()).to.deep.equal(identifierBytes); }); - it('should allows to create Identifier from hex', () => { - const identifier = wasm.Identifier.fromHex('092828edc081d3ba1a54f043259b941368f2c718881b06a9d347883b21bfe313'); + it('should create Identifier from Identifier', () => { + const identifier = wasm.Identifier.fromBytes(identifierBytes); + const identifier2 = new wasm.Identifier(identifier); - expect(identifier.toBytes()).to.deep.equal(identifierBytes); + expect(identifier2.toBytes()).to.deep.equal(identifierBytes); }); + }); - it('should allows to create Identifier from bytes', () => { - const identifier = wasm.Identifier.fromBytes(identifierBytes); + describe('fromBase58()', () => { + it('should create Identifier from base58', () => { + const identifier = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); expect(identifier.toBytes()).to.deep.equal(identifierBytes); }); + }); - it('should allows to create Identifier from Identifier', () => { - const identifier = wasm.Identifier.fromBytes(identifierBytes); - const identifier2 = new wasm.Identifier(identifier); + describe('fromBase64()', () => { + it('should create Identifier from base64', () => { + const identifier = wasm.Identifier.fromBase64('CSgo7cCB07oaVPBDJZuUE2jyxxiIGwap00eIOyG/4xM='); - expect(identifier2.toBytes()).to.deep.equal(identifierBytes); + expect(identifier.toBytes()).to.deep.equal(identifierBytes); }); + }); - it('should allows to create Identifier from bytes in constructor', () => { - const identifier = new wasm.Identifier(identifierBytes); + describe('fromHex()', () => { + it('should create Identifier from hex', () => { + const identifier = wasm.Identifier.fromHex( + '092828edc081d3ba1a54f043259b941368f2c718881b06a9d347883b21bfe313', + ); expect(identifier.toBytes()).to.deep.equal(identifierBytes); }); + }); - it('should allows to create Identifier from base58 in constructor', () => { - const identifier = new wasm.Identifier('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); + describe('fromBytes()', () => { + it('should create Identifier from bytes', () => { + const identifier = wasm.Identifier.fromBytes(identifierBytes); expect(identifier.toBytes()).to.deep.equal(identifierBytes); }); }); - describe('getters', () => { - it('should allow to get identifier base58', () => { + describe('toBase58()', () => { + it('should return identifier base58', () => { const identifier = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); expect(identifier.toBase58()).to.equal('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); }); + }); - it('should allow to get identifier base64', () => { + describe('toBase64()', () => { + it('should return identifier base64', () => { const identifier = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); expect(identifier.toBase64()).to.equal('CSgo7cCB07oaVPBDJZuUE2jyxxiIGwap00eIOyG/4xM='); }); + }); - it('should allow to get identifier hex', () => { + describe('toHex()', () => { + it('should return identifier hex', () => { const identifier = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); - expect(identifier.toHex()).to.equal('092828edc081d3ba1a54f043259b941368f2c718881b06a9d347883b21bfe313'); + expect(identifier.toHex()).to.equal( + '092828edc081d3ba1a54f043259b941368f2c718881b06a9d347883b21bfe313', + ); }); + }); - it('should allow to get identifier bytes', () => { + describe('toBytes()', () => { + it('should return identifier bytes', () => { const identifier = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); expect(identifier.toBytes()).to.deep.equal(identifierBytes); diff --git a/packages/wasm-dpp2/tests/unit/Identity.spec.mjs b/packages/wasm-dpp2/tests/unit/Identity.spec.mjs deleted file mode 100644 index 69950494137..00000000000 --- a/packages/wasm-dpp2/tests/unit/Identity.spec.mjs +++ /dev/null @@ -1,145 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { - identifier, identityBytesWithoutKeys, identifierBytes, balance, revision, -} from './mocks/Identity/index.js'; -import { - keyId, purpose, securityLevel, keyType, binaryData, -} from './mocks/PublicKey/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('Identity', () => { - describe('serialization / deserialization', () => { - it('should generate identity from identifier', async () => { - const identity = new wasm.Identity(identifier); - - expect(identity.__wbg_ptr).to.not.equal(0); - }); - - it('should generate identity from identifier and return bytes', async () => { - const identity = new wasm.Identity(identifier); - - expect(Array.from(identity.toBytes())).to.deep.equal(identityBytesWithoutKeys); - - const newIdentity = wasm.Identity.fromBytes(identity.toBytes()); - - expect(identity.__wbg_ptr).to.not.equal(0); - expect(newIdentity.__wbg_ptr).to.not.equal(0); - }); - - it('should recreate identity from JSON output', () => { - const identity = new wasm.Identity(identifier); - const identityJson = identity.toJSON(); - - const restoredIdentity = wasm.Identity.fromJSON(identityJson); - - expect(Array.from(restoredIdentity.toBytes())).to.deep.equal(Array.from(identity.toBytes())); - }); - - it('should recreate identity from object output', () => { - const identity = new wasm.Identity(identifier); - const identityObject = identity.toObject(); - - // toObject returns plain JS values (Uint8Array for id, not Identifier instance) - expect(identityObject.id.constructor.name).to.equal('Uint8Array'); - expect(identityObject.id.length).to.equal(32); - expect(Array.isArray(identityObject.publicKeys)).to.equal(true); - expect(identityObject.balance).to.equal(BigInt(0)); - expect(identityObject.revision).to.equal(BigInt(0)); - - const restoredIdentity = wasm.Identity.fromObject(identityObject); - - expect(Array.from(restoredIdentity.toBytes())).to.deep.equal(Array.from(identity.toBytes())); - expect(restoredIdentity.id.toBytes()).to.deep.equal(identity.id.toBytes()); - expect(restoredIdentity.getPublicKeys().length).to.equal(identity.getPublicKeys().length); - }); - }); - - describe('getters', () => { - it('should get id buffer', () => { - const identity = new wasm.Identity(identifier); - - expect(identity.id.toBytes()).to.deep.equal(Uint8Array.from(identifierBytes)); - }); - - it('should get balance', () => { - const identity = new wasm.Identity(identifier); - - expect(identity.balance).to.deep.equal(BigInt(0)); - }); - - it('should get revision', () => { - const identity = new wasm.Identity(identifier); - - expect(identity.revision).to.deep.equal(BigInt(0)); - }); - - it('should get public keys', () => { - const identity = new wasm.Identity(identifier); - - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - const pubKey2 = new wasm.IdentityPublicKey( - keyId + 1, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - identity.addPublicKey(pubKey); - identity.addPublicKey(pubKey2); - - expect(identity.getPublicKeys().length).to.equal(2); - }); - }); - - describe('setters', () => { - it('should allows to set public key', () => { - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - const identity = new wasm.Identity(identifier); - - identity.addPublicKey(pubKey); - - expect(identity.__wbg_ptr).to.not.equal(0); - - expect(identity.getPublicKeyById(keyId).toBytes()).to.deep.equal(pubKey.toBytes()); - }); - - it('should allows to set balance', () => { - const identity = new wasm.Identity(identifier); - - identity.balance = balance; - - expect(identity.balance).to.equal(balance); - }); - - it('should allows to set revision', () => { - const identity = new wasm.Identity(identifier); - - identity.revision = revision; - - expect(identity.revision).to.equal(revision); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/Identity.spec.ts b/packages/wasm-dpp2/tests/unit/Identity.spec.ts new file mode 100644 index 00000000000..5f4b107ad9f --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/Identity.spec.ts @@ -0,0 +1,199 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { + identifier, + identityBytesWithoutKeys, + identifierBytes, + balance, + revision, +} from './mocks/Identity/index.js'; +import { + keyId, purpose, securityLevel, keyType, binaryData, +} from './mocks/PublicKey/index.js'; + +before(async () => { + await initWasm(); +}); + +describe('Identity', () => { + describe('constructor()', () => { + it('should create identity from identifier', async () => { + const identity = new wasm.Identity(identifier); + + expect(identity).to.be.an.instanceof(wasm.Identity); + }); + }); + + describe('toBytes()', () => { + it('should return identity as bytes', async () => { + const identity = new wasm.Identity(identifier); + + expect(Array.from(identity.toBytes())).to.deep.equal(identityBytesWithoutKeys); + }); + }); + + describe('fromBytes()', () => { + it('should recreate identity from bytes', async () => { + const identity = new wasm.Identity(identifier); + const newIdentity = wasm.Identity.fromBytes(identity.toBytes()); + + expect(identity).to.be.an.instanceof(wasm.Identity); + expect(newIdentity).to.be.an.instanceof(wasm.Identity); + expect(Array.from(newIdentity.toBytes())).to.deep.equal(identityBytesWithoutKeys); + }); + }); + + describe('toJSON()', () => { + it('should serialize identity to JSON', () => { + const identity = new wasm.Identity(identifier); + const identityJson = identity.toJSON(); + + expect(identityJson).to.be.an('object'); + }); + }); + + describe('fromJSON()', () => { + it('should recreate identity from JSON', () => { + const identity = new wasm.Identity(identifier); + const identityJson = identity.toJSON(); + + const restoredIdentity = wasm.Identity.fromJSON(identityJson); + + expect(Array.from(restoredIdentity.toBytes())).to.deep.equal(Array.from(identity.toBytes())); + }); + }); + + describe('toObject()', () => { + it('should serialize identity to plain JS object', () => { + const identity = new wasm.Identity(identifier); + const identityObject = identity.toObject(); + + // toObject returns plain JS values (Uint8Array for id, not Identifier instance) + expect(identityObject.id.constructor.name).to.equal('Uint8Array'); + expect(identityObject.id.length).to.equal(32); + expect(Array.isArray(identityObject.publicKeys)).to.equal(true); + expect(identityObject.balance).to.equal(BigInt(0)); + expect(identityObject.revision).to.equal(BigInt(0)); + }); + }); + + describe('fromObject()', () => { + it('should recreate identity from object', () => { + const identity = new wasm.Identity(identifier); + const identityObject = identity.toObject(); + + const restoredIdentity = wasm.Identity.fromObject(identityObject); + + expect(Array.from(restoredIdentity.toBytes())).to.deep.equal(Array.from(identity.toBytes())); + expect(restoredIdentity.id.toBytes()).to.deep.equal(identity.id.toBytes()); + expect(restoredIdentity.publicKeys.length).to.equal(identity.publicKeys.length); + }); + }); + + describe('id', () => { + it('should return id as Identifier', () => { + const identity = new wasm.Identity(identifier); + + expect(identity.id.toBytes()).to.deep.equal(Uint8Array.from(identifierBytes)); + }); + }); + + describe('balance', () => { + it('should return balance', () => { + const identity = new wasm.Identity(identifier); + + expect(identity.balance).to.deep.equal(BigInt(0)); + }); + + it('should set balance', () => { + const identity = new wasm.Identity(identifier); + + identity.balance = balance; + + expect(identity.balance).to.equal(balance); + }); + }); + + describe('revision', () => { + it('should return revision', () => { + const identity = new wasm.Identity(identifier); + + expect(identity.revision).to.deep.equal(BigInt(0)); + }); + + it('should set revision', () => { + const identity = new wasm.Identity(identifier); + + identity.revision = revision; + + expect(identity.revision).to.equal(revision); + }); + }); + + describe('publicKeys', () => { + it('should return public keys array', () => { + const identity = new wasm.Identity(identifier); + + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const pubKey2 = new wasm.IdentityPublicKey({ + keyId: keyId + 1, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + identity.addPublicKey(pubKey); + identity.addPublicKey(pubKey2); + + expect(identity.publicKeys.length).to.equal(2); + }); + }); + + describe('addPublicKey()', () => { + it('should add public key to identity', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const identity = new wasm.Identity(identifier); + + identity.addPublicKey(pubKey); + + expect(identity).to.be.an.instanceof(wasm.Identity); + expect(identity.getPublicKeyById(keyId).toBytes()).to.deep.equal(pubKey.toBytes()); + }); + }); + + describe('getPublicKeyById()', () => { + it('should return public key by id', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const identity = new wasm.Identity(identifier); + identity.addPublicKey(pubKey); + + expect(identity.getPublicKeyById(keyId).toBytes()).to.deep.equal(pubKey.toBytes()); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityCreateTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/IdentityCreateTransition.spec.mjs deleted file mode 100644 index 0aac24b94ca..00000000000 --- a/packages/wasm-dpp2/tests/unit/IdentityCreateTransition.spec.mjs +++ /dev/null @@ -1,131 +0,0 @@ -import getWasm from './helpers/wasm.js'; -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('IdentityCreateTransition', () => { - describe('serialization / deserialization', () => { - it('should allow to create transition', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - expect(transition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to serialize to bytes', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - const bytes = transition.toBytes(); - - expect(bytes.length > 0).to.equal(true); - }); - - it('should allow to deserialize to bytes', () => { - const bytes = [0, 0, 0, 162, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - - const transition = wasm.IdentityCreateTransition.fromBytes(bytes); - - expect(transition.__wbg_ptr).to.not.equal(0); - }); - - it('should serialize to JSON', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - const json = transition.toJSON(); - // JSON uses camelCase (serde rename_all) - expect(json).to.have.property('publicKeys'); - expect(json).to.have.property('assetLockProof'); - expect(json).to.have.property('userFeeIncrease'); - expect(json).to.have.property('signature'); - expect(json.userFeeIncrease).to.equal(0); - }); - - it('should serialize to object', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - const obj = transition.toObject(); - expect(obj).to.have.property('publicKeys'); - expect(obj).to.have.property('assetLockProof'); - expect(obj).to.have.property('userFeeIncrease'); - expect(obj).to.have.property('signature'); - }); - - it('should serialize to hex and base64', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - const hex = transition.toHex(); - expect(hex).to.be.a('string'); - expect(hex.length).to.be.greaterThan(0); - - const base64 = transition.toBase64(); - expect(base64).to.be.a('string'); - expect(base64.length).to.be.greaterThan(0); - - // Verify they can be deserialized back - const fromHex = wasm.IdentityCreateTransition.fromHex(hex); - expect(fromHex.getIdentifier().toBase58()).to.equal(transition.getIdentifier().toBase58()); - - const fromBase64 = wasm.IdentityCreateTransition.fromBase64(base64); - expect(fromBase64.getIdentifier().toBase58()).to.equal(transition.getIdentifier().toBase58()); - }); - }); - - describe('getters', () => { - it('should allow to get userFeeIncrease', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - expect(transition.userFeeIncrease).to.equal(0); - }); - - it('should allow to get AssetLock', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - expect(transition.assetLock.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to get Identifier', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - expect(transition.getIdentifier().toBase58()).to.equal('11111111111111111111111111111111'); - }); - - it('should allow to get PublicKeys', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - expect(transition.publicKeys.length).to.equal(0); - }); - - it('should allow to get signature', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - expect(transition.signature).to.deep.equal(Uint8Array.from([])); - }); - - it('should allow to get signable bytes', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - expect(transition.getSignableBytes().length).to.equal(229); - }); - }); - - describe('setters', () => { - it('should allow to set the userFeeIncrease', () => { - const transition = wasm.IdentityCreateTransition.default(1); - - transition.userFeeIncrease = 100; - - expect(transition.userFeeIncrease).to.equal(100); - }); - - // TODO: Implement publickeys in creation setter - // it('should allow to set the publicKeys', function () { - // - // }) - - // TODO: Implement asset lock setter - // it('should allow to set the asset lock', function () { - // - // }) - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityCreateTransition.spec.ts b/packages/wasm-dpp2/tests/unit/IdentityCreateTransition.spec.ts new file mode 100644 index 00000000000..77be1056285 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/IdentityCreateTransition.spec.ts @@ -0,0 +1,182 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('IdentityCreateTransition', () => { + describe('default()', () => { + it('should create transition with default values', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + expect(transition).to.be.an.instanceof(wasm.IdentityCreateTransition); + }); + }); + + describe('toBytes()', () => { + it('should serialize transition to bytes', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + const bytes = transition.toBytes(); + + expect(bytes.length > 0).to.equal(true); + }); + }); + + describe('fromBytes()', () => { + it('should deserialize transition from bytes', () => { + // prettier-ignore + const bytes = [ + 0, 0, 0, 162, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 1, 255, 255, 255, + 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + + const transition = wasm.IdentityCreateTransition.fromBytes(bytes); + + expect(transition).to.be.an.instanceof(wasm.IdentityCreateTransition); + }); + }); + + describe('toJSON()', () => { + it('should serialize transition to JSON', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + const json = transition.toJSON(); + // JSON uses camelCase (serde rename_all) + expect(json).to.have.property('publicKeys'); + expect(json).to.have.property('assetLockProof'); + expect(json).to.have.property('userFeeIncrease'); + expect(json).to.have.property('signature'); + expect(json.userFeeIncrease).to.equal(0); + }); + }); + + describe('toObject()', () => { + it('should serialize transition to object', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + const obj = transition.toObject(); + expect(obj).to.have.property('publicKeys'); + expect(obj).to.have.property('assetLockProof'); + expect(obj).to.have.property('userFeeIncrease'); + expect(obj).to.have.property('signature'); + }); + }); + + describe('toHex()', () => { + it('should serialize transition to hex string', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + const hex = transition.toHex(); + expect(hex).to.be.a('string'); + expect(hex.length).to.be.greaterThan(0); + }); + }); + + describe('fromHex()', () => { + it('should deserialize transition from hex string', () => { + const transition = wasm.IdentityCreateTransition.default(1); + const hex = transition.toHex(); + + const fromHex = wasm.IdentityCreateTransition.fromHex(hex); + expect(fromHex.identityId.toBase58()).to.equal(transition.identityId.toBase58()); + }); + }); + + describe('toBase64()', () => { + it('should serialize transition to base64 string', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + const base64 = transition.toBase64(); + expect(base64).to.be.a('string'); + expect(base64.length).to.be.greaterThan(0); + }); + }); + + describe('fromBase64()', () => { + it('should deserialize transition from base64 string', () => { + const transition = wasm.IdentityCreateTransition.default(1); + const base64 = transition.toBase64(); + + const fromBase64 = wasm.IdentityCreateTransition.fromBase64(base64); + expect(fromBase64.identityId.toBase58()).to.equal(transition.identityId.toBase58()); + }); + }); + + describe('userFeeIncrease', () => { + it('should return userFeeIncrease', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + expect(transition.userFeeIncrease).to.equal(0); + }); + + it('should set userFeeIncrease', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + transition.userFeeIncrease = 100; + + expect(transition.userFeeIncrease).to.equal(100); + }); + }); + + describe('assetLockProof', () => { + it('should return AssetLockProof instance', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + expect(transition.assetLockProof).to.be.an.instanceof(wasm.AssetLockProof); + }); + }); + + describe('identityId', () => { + it('should return identity Identifier', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + expect(transition.identityId.toBase58()).to.equal('11111111111111111111111111111111'); + }); + }); + + describe('publicKeys', () => { + it('should return public keys array', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + expect(transition.publicKeys.length).to.equal(0); + }); + }); + + describe('signature', () => { + it('should return signature bytes', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + expect(transition.signature).to.deep.equal(Uint8Array.from([])); + }); + }); + + describe('getSignableBytes()', () => { + it('should return signable bytes', () => { + const transition = wasm.IdentityCreateTransition.default(1); + + expect(transition.getSignableBytes().length).to.equal(229); + }); + }); + + // TODO: Implement publickeys in creation setter + // describe('setPublicKeys()', () => { + // it('should set public keys', () => { + // }); + // }); + + // TODO: Implement asset lock setter + // describe('setAssetLockProof()', () => { + // it('should set asset lock proof', () => { + // }); + // }); +}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityCreditTransferTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/IdentityCreditTransferTransition.spec.mjs deleted file mode 100644 index 9d9048d5302..00000000000 --- a/packages/wasm-dpp2/tests/unit/IdentityCreditTransferTransition.spec.mjs +++ /dev/null @@ -1,157 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('IdentityCreditTransferTransition', () => { - describe('serialization / deserialization', () => { - it('Should create IdentityCreditTransferTransition with empty platform version', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.__wbg_ptr).to.not.equal(0); - }); - - it('Should create IdentityCreditTransferTransition with non empty platform version', async () => { - const sender = new wasm.Identifier('11111111111111111111111111111111'); - const recipient = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - - const transition = new wasm.IdentityCreditTransfer(BigInt(100), sender, recipient, BigInt(199), 'platform_v1'); - - expect(transition.__wbg_ptr).to.not.equal(0); - expect(sender.__wbg_ptr).to.not.equal(0); - expect(recipient.__wbg_ptr).to.not.equal(0); - }); - - it('Should convert IdentityCreditTransferTransition to base64 and back', () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - const base64 = transition.toBase64(); - const bytes = transition.toBytes(); - - expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); - - const restored = wasm.IdentityCreditTransfer.fromBase64(base64); - - expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); - }); - }); - - describe('getters', () => { - it('Should return recipientId', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.recipientId.toBase58()).to.deep.equal('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - }); - - it('Should return senderId', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.senderId.toBase58()).to.deep.equal('11111111111111111111111111111111'); - }); - - it('Should return amount', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.amount).to.deep.equal(BigInt(100)); - }); - - it('Should return nonce', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.nonce).to.deep.equal(BigInt(199)); - }); - - it('Should return signature', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.signature).to.deep.equal(Uint8Array.from([])); - }); - - it('Should return signaturePublicKeyId', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.signaturePublicKeyId).to.deep.equal(0); - }); - - it('Should return userFeeIncrease', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - expect(transition.userFeeIncrease).to.deep.equal(0); - }); - }); - - describe('setters', () => { - it('Should allow to set recipientId', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - const recipient = new wasm.Identifier('11111111111111111111111111111111'); - - transition.recipientId = recipient; - - expect(transition.recipientId.toBase58()).to.deep.equal('11111111111111111111111111111111'); - - transition.recipientId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; - - expect(transition.recipientId.toBase58()).to.deep.equal('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - expect(recipient.__wbg_ptr).to.not.equal(0); - }); - - it('Should return senderId', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - const sender = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - - transition.senderId = sender; - - expect(transition.senderId.toBase58()).to.deep.equal('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - - transition.senderId = '11111111111111111111111111111111'; - - expect(sender.__wbg_ptr).to.not.equal(0); - expect(transition.senderId.toBase58()).to.deep.equal('11111111111111111111111111111111'); - }); - - it('Should return amount', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - transition.amount = BigInt(199); - - expect(transition.amount).to.deep.equal(BigInt(199)); - }); - - it('Should return nonce', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - transition.nonce = BigInt(1); - - expect(transition.nonce).to.deep.equal(BigInt(1)); - }); - - it('Should return signature', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - transition.signature = [1, 1]; - - expect(transition.signature).to.deep.equal(Uint8Array.from([1, 1])); - }); - - it('Should return signaturePublicKeyId', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - transition.signaturePublicKeyId = 11; - - expect(transition.signaturePublicKeyId).to.deep.equal(11); - }); - - it('Should return userFeeIncrease', async () => { - const transition = new wasm.IdentityCreditTransfer(BigInt(100), '11111111111111111111111111111111', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', BigInt(199)); - - transition.userFeeIncrease = 11; - - expect(transition.userFeeIncrease).to.deep.equal(11); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityCreditTransferTransition.spec.ts b/packages/wasm-dpp2/tests/unit/IdentityCreditTransferTransition.spec.ts new file mode 100644 index 00000000000..35fa9fbeed9 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/IdentityCreditTransferTransition.spec.ts @@ -0,0 +1,285 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('IdentityCreditTransfer', () => { + describe('constructor()', () => { + it('should create IdentityCreditTransfer with string identifiers', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition).to.be.an.instanceof(wasm.IdentityCreditTransfer); + }); + + it('should create IdentityCreditTransfer with Identifier objects', async () => { + const sender = new wasm.Identifier('11111111111111111111111111111111'); + const recipient = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: sender, + recipientId: recipient, + nonce: BigInt(199), + }); + + expect(transition).to.be.an.instanceof(wasm.IdentityCreditTransfer); + expect(sender).to.be.an.instanceof(wasm.Identifier); + expect(recipient).to.be.an.instanceof(wasm.Identifier); + }); + }); + + describe('toBase64()', () => { + it('should convert IdentityCreditTransfer to base64', () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('fromBase64()', () => { + it('should create IdentityCreditTransfer from base64', () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + const restored = wasm.IdentityCreditTransfer.fromBase64(base64); + + expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('recipientId', () => { + it('should return recipientId', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition.recipientId.toBase58()).to.deep.equal('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + }); + + it('should set recipientId with Identifier', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + const recipient = new wasm.Identifier('11111111111111111111111111111111'); + + transition.recipientId = recipient; + + expect(transition.recipientId.toBase58()).to.deep.equal('11111111111111111111111111111111'); + expect(recipient).to.be.an.instanceof(wasm.Identifier); + }); + + it('should set recipientId with string', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: '11111111111111111111111111111111', + nonce: BigInt(199), + }); + + transition.recipientId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; + + expect(transition.recipientId.toBase58()).to.deep.equal('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + }); + }); + + describe('senderId', () => { + it('should return senderId', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition.senderId.toBase58()).to.deep.equal('11111111111111111111111111111111'); + }); + + it('should set senderId with Identifier', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + const sender = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + + transition.senderId = sender; + + expect(transition.senderId.toBase58()).to.deep.equal('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + expect(sender).to.be.an.instanceof(wasm.Identifier); + }); + + it('should set senderId with string', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + transition.senderId = '11111111111111111111111111111111'; + + expect(transition.senderId.toBase58()).to.deep.equal('11111111111111111111111111111111'); + }); + }); + + describe('amount', () => { + it('should return amount', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition.amount).to.deep.equal(BigInt(100)); + }); + + it('should set amount', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + transition.amount = BigInt(199); + + expect(transition.amount).to.deep.equal(BigInt(199)); + }); + }); + + describe('nonce', () => { + it('should return nonce', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition.nonce).to.deep.equal(BigInt(199)); + }); + + it('should set nonce', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + transition.nonce = BigInt(1); + + expect(transition.nonce).to.deep.equal(BigInt(1)); + }); + }); + + describe('signature', () => { + it('should return signature', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition.signature).to.deep.equal(Uint8Array.from([])); + }); + + it('should set signature', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + transition.signature = [1, 1]; + + expect(transition.signature).to.deep.equal(Uint8Array.from([1, 1])); + }); + }); + + describe('signaturePublicKeyId', () => { + it('should return signaturePublicKeyId', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition.signaturePublicKeyId).to.deep.equal(0); + }); + + it('should set signaturePublicKeyId', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + transition.signaturePublicKeyId = 11; + + expect(transition.signaturePublicKeyId).to.deep.equal(11); + }); + }); + + describe('userFeeIncrease', () => { + it('should return userFeeIncrease', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + expect(transition.userFeeIncrease).to.deep.equal(0); + }); + + it('should set userFeeIncrease', async () => { + const transition = new wasm.IdentityCreditTransfer({ + amount: BigInt(100), + senderId: '11111111111111111111111111111111', + recipientId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + nonce: BigInt(199), + }); + + transition.userFeeIncrease = 11; + + expect(transition.userFeeIncrease).to.deep.equal(11); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityCreditWithdrawalTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/IdentityCreditWithdrawalTransition.spec.mjs deleted file mode 100644 index f575bde23e5..00000000000 --- a/packages/wasm-dpp2/tests/unit/IdentityCreditWithdrawalTransition.spec.mjs +++ /dev/null @@ -1,206 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('IdentityCreditWithdrawalTransition', () => { - describe('serialization / deserialization', () => { - it('Should allow to create IdentityCreditWithdrawalTransition', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(identifier.__wbg_ptr).to.not.equal(0); - expect(script.__wbg_ptr).to.not.equal(0); - expect(transition.__wbg_ptr).to.not.equal(0); - }); - - it('Should convert IdentityCreditWithdrawalTransition to base64 and back', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - const base64 = transition.toBase64(); - const bytes = transition.toBytes(); - - expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); - - const restored = wasm.IdentityCreditWithdrawalTransition.fromBase64(base64); - - expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); - }); - }); - - describe('getters', () => { - it('Should allow to get outputScript', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.outputScript.toString()).to.deep.equal('dqkUAQEBAQEBAQEBAQEBAQEBAQEBAQGIrA=='); - }); - - it('Should allow to get pooling', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.pooling).to.deep.equal('Never'); - }); - - it('Should allow to get identityId', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.identityId.toBase58()).to.deep.equal(identifier.toBase58()); - }); - - it('Should allow to get userFeeIncrease', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.userFeeIncrease).to.deep.equal(1); - }); - - it('Should allow to get nonce', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.nonce).to.deep.equal(BigInt(1)); - }); - - it('Should allow to get amount', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.amount).to.deep.equal(BigInt(111)); - }); - - it('Should allow to get signature', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.signature).to.deep.equal(Uint8Array.from([])); - }); - - it('Should allow to get signaturePublicKeyId', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - expect(transition.signaturePublicKeyId).to.deep.equal(0); - }); - }); - - describe('setters', () => { - it('Should allow to set outputScript', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - const script2 = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - transition.outputScript = script2; - - expect(transition.outputScript.toString()).to.deep.equal(script2.toString()); - }); - - it('Should allow to set pooling', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - transition.pooling = 'Standard'; - - expect(transition.pooling).to.deep.equal('Standard'); - }); - - it('Should allow to set identityId', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - const identifier2 = new wasm.Identifier('11SAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - - transition.identityId = identifier2; - - expect(transition.identityId.toBase58()).to.deep.equal(identifier2.toBase58()); - }); - - it('Should allow to set userFeeIncrease', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - transition.userFeeIncrease = 999; - - expect(transition.userFeeIncrease).to.deep.equal(999); - }); - - it('Should allow to set nonce', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - transition.nonce = BigInt(1111); - - expect(transition.nonce).to.deep.equal(BigInt(1111)); - }); - - it('Should allow to get amount', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - transition.amount = BigInt(2222); - - expect(transition.amount).to.deep.equal(BigInt(2222)); - }); - - it('Should allow to get signature', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - transition.signature = Uint8Array.from([1, 2, 3]); - - expect(transition.signature).to.deep.equal(Uint8Array.from([1, 2, 3])); - }); - - it('Should allow to get signaturePublicKeyId', () => { - const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); - const script = wasm.CoreScript.newP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - - const transition = new wasm.IdentityCreditWithdrawalTransition(identifier, BigInt(111), 1, 'never', script, BigInt(1), 1); - - transition.signaturePublicKeyId = 11; - - expect(transition.signaturePublicKeyId).to.deep.equal(11); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityCreditWithdrawalTransition.spec.ts b/packages/wasm-dpp2/tests/unit/IdentityCreditWithdrawalTransition.spec.ts new file mode 100644 index 00000000000..a9516e6a898 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/IdentityCreditWithdrawalTransition.spec.ts @@ -0,0 +1,386 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('IdentityCreditWithdrawalTransition', () => { + describe('constructor()', () => { + it('should create IdentityCreditWithdrawalTransition', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(identifier).to.be.an.instanceof(wasm.Identifier); + expect(script).to.be.an.instanceof(wasm.CoreScript); + expect(transition).to.be.an.instanceof(wasm.IdentityCreditWithdrawalTransition); + }); + }); + + describe('toBase64()', () => { + it('should convert IdentityCreditWithdrawalTransition to base64', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('fromBase64()', () => { + it('should create IdentityCreditWithdrawalTransition from base64', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + const restored = wasm.IdentityCreditWithdrawalTransition.fromBase64(base64); + + expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('outputScript', () => { + it('should return outputScript', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.outputScript.toString()).to.deep.equal('dqkUAQEBAQEBAQEBAQEBAQEBAQEBAQGIrA=='); + }); + + it('should set outputScript', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + const script2 = wasm.CoreScript.fromP2PKH([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]); + + expect(transition.outputScript.toString()).to.deep.equal(script.toString()); + + transition.outputScript = script2; + + expect(transition.outputScript.toString()).to.deep.equal(script2.toString()); + expect(transition.outputScript.toString()).to.not.deep.equal(script.toString()); + }); + }); + + describe('pooling', () => { + it('should return pooling', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.pooling).to.deep.equal('Never'); + }); + + it('should set pooling', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + transition.pooling = 'Standard'; + + expect(transition.pooling).to.deep.equal('Standard'); + }); + }); + + describe('identityId', () => { + it('should return identityId', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.identityId.toBase58()).to.deep.equal(identifier.toBase58()); + }); + + it('should set identityId', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + const identifier2 = new wasm.Identifier('11SAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + + transition.identityId = identifier2; + + expect(transition.identityId.toBase58()).to.deep.equal(identifier2.toBase58()); + }); + }); + + describe('userFeeIncrease', () => { + it('should return userFeeIncrease', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.userFeeIncrease).to.deep.equal(1); + }); + + it('should set userFeeIncrease', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + transition.userFeeIncrease = 999; + + expect(transition.userFeeIncrease).to.deep.equal(999); + }); + }); + + describe('nonce', () => { + it('should return nonce', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.nonce).to.deep.equal(BigInt(1)); + }); + + it('should set nonce', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + transition.nonce = BigInt(1111); + + expect(transition.nonce).to.deep.equal(BigInt(1111)); + }); + }); + + describe('amount', () => { + it('should return amount', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.amount).to.deep.equal(BigInt(111)); + }); + + it('should set amount', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + transition.amount = BigInt(2222); + + expect(transition.amount).to.deep.equal(BigInt(2222)); + }); + }); + + describe('signature', () => { + it('should return signature', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.signature).to.deep.equal(Uint8Array.from([])); + }); + + it('should set signature', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + transition.signature = Uint8Array.from([1, 2, 3]); + + expect(transition.signature).to.deep.equal(Uint8Array.from([1, 2, 3])); + }); + }); + + describe('signaturePublicKeyId', () => { + it('should return signaturePublicKeyId', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + expect(transition.signaturePublicKeyId).to.deep.equal(0); + }); + + it('should set signaturePublicKeyId', () => { + const identifier = new wasm.Identifier('GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'); + const script = wasm.CoreScript.fromP2PKH([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + const transition = new wasm.IdentityCreditWithdrawalTransition({ + identityId: identifier, + amount: BigInt(111), + coreFeePerByte: 1, + pooling: 'never', + outputScript: script, + nonce: BigInt(1), + userFeeIncrease: 1, + }); + + transition.signaturePublicKeyId = 11; + + expect(transition.signaturePublicKeyId).to.deep.equal(11); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityPublicKey.spec.mjs b/packages/wasm-dpp2/tests/unit/IdentityPublicKey.spec.mjs deleted file mode 100644 index 9caa63bc1ae..00000000000 --- a/packages/wasm-dpp2/tests/unit/IdentityPublicKey.spec.mjs +++ /dev/null @@ -1,135 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { wif } from './mocks/PrivateKey/index.js'; -import { - keyId, purpose, securityLevel, keyType, binaryData, securityLevelSet, keyIdSet, purposeSet, keyTypeSet, binaryDataSet, -} from './mocks/PublicKey/index.js'; -import { toHexString } from './utils/hex.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('PublicKey', () => { - describe('serialization / deserialization', () => { - it('should generate public key from values with type ECDSA_SECP256K1', () => { - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - expect(pubKey.__wbg_ptr).to.not.equal(0); - }); - - it('should generate public key from values with type ECDSA_SECP256K1 and generate new from self bytes', () => { - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - const bytes = pubKey.toBytes(); - - const newPubKey = wasm.IdentityPublicKey.fromBytes(Array.from(bytes)); - - expect(pubKey.__wbg_ptr).to.not.equal(0); - expect(newPubKey.__wbg_ptr).to.not.equal(0); - - expect(pubKey.keyId).to.equal(newPubKey.keyId); - expect(pubKey.purpose).to.equal(newPubKey.purpose); - expect(pubKey.securityLevel).to.equal(newPubKey.securityLevel); - expect(pubKey.keyType).to.equal(newPubKey.keyType); - expect(pubKey.readOnly).to.equal(newPubKey.readOnly); - expect(pubKey.data).to.equal(newPubKey.data); - - expect(pubKey.toBytes()).to.deep.equal(newPubKey.toBytes()); - - expect(pubKey.__wbg_ptr).to.not.equal(0); - expect(newPubKey.__wbg_ptr).to.not.equal(0); - }); - - it('should return hash of key', () => { - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - const hash = pubKey.getPublicKeyHash(); - - expect(hash).to.deep.equal(toHexString([211, 114, 240, 150, 37, 159, 114, 104, 110, 24, 102, 61, 125, 181, 248, 98, 52, 221, 111, 85])); - }); - }); - describe('getters', () => { - it('should generate public key from values with type ECDSA_SECP256K1 and return all fields', () => { - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - expect(pubKey.keyId).to.equal(keyId); - expect(pubKey.purpose).to.equal('AUTHENTICATION'); - expect(pubKey.securityLevel).to.equal('CRITICAL'); - expect(pubKey.keyType).to.equal('ECDSA_SECP256K1'); - expect(pubKey.readOnly).to.equal(false); - expect(pubKey.data).to.equal(binaryData); - }); - - it('should allow to validate private key', () => { - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - const privateKey = wasm.PrivateKey.fromWIF(wif); - - expect(pubKey.validatePrivateKey(privateKey.toBytes(), wasm.Network.Mainnet)).to.equal(false); - }); - }); - - describe('setters', () => { - it('should generate public key from values with type ECDSA_SECP256K1 and return all fields and set another fields', () => { - const pubKey = new wasm.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - false, - binaryData, - ); - - pubKey.keyId = keyIdSet; - pubKey.purpose = purposeSet; - pubKey.securityLevel = securityLevelSet; - pubKey.keyType = keyTypeSet; - pubKey.readOnly = true; - pubKey.data = binaryDataSet; - - expect(pubKey.keyId).to.equal(keyIdSet); - expect(pubKey.purpose).to.equal('ENCRYPTION'); - expect(pubKey.securityLevel).to.equal('HIGH'); - expect(pubKey.keyType).to.equal('ECDSA_HASH160'); - expect(pubKey.readOnly).to.equal(true); - expect(pubKey.data).to.equal(binaryDataSet); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityPublicKey.spec.ts b/packages/wasm-dpp2/tests/unit/IdentityPublicKey.spec.ts new file mode 100644 index 00000000000..7422cde399a --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/IdentityPublicKey.spec.ts @@ -0,0 +1,302 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { wif } from './mocks/PrivateKey/index.js'; +import { + keyId, + purpose, + securityLevel, + keyType, + binaryData, + binaryDataHex, + securityLevelSet, + keyIdSet, + purposeSet, + keyTypeSet, + binaryDataSetHex, +} from './mocks/PublicKey/index.js'; +import { toHexString } from './utils/hex.ts'; + +before(async () => { + await initWasm(); +}); + +describe('IdentityPublicKey', () => { + describe('constructor()', () => { + it('should create public key from values with type ECDSA_SECP256K1', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + expect(pubKey).to.be.an.instanceof(wasm.IdentityPublicKey); + }); + }); + + describe('toBytes()', () => { + it('should serialize public key to bytes', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const bytes = pubKey.toBytes(); + + expect(bytes.length).to.be.greaterThan(0); + }); + }); + + describe('fromBytes()', () => { + it('should deserialize public key from bytes', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const bytes = pubKey.toBytes(); + const newPubKey = wasm.IdentityPublicKey.fromBytes(Array.from(bytes)); + + expect(pubKey).to.be.an.instanceof(wasm.IdentityPublicKey); + expect(newPubKey).to.be.an.instanceof(wasm.IdentityPublicKey); + + expect(pubKey.keyId).to.equal(newPubKey.keyId); + expect(pubKey.purpose).to.equal(newPubKey.purpose); + expect(pubKey.securityLevel).to.equal(newPubKey.securityLevel); + expect(pubKey.keyType).to.equal(newPubKey.keyType); + expect(pubKey.isReadOnly).to.equal(newPubKey.isReadOnly); + expect(pubKey.data).to.equal(newPubKey.data); + + expect(pubKey.toBytes()).to.deep.equal(newPubKey.toBytes()); + }); + }); + + describe('getPublicKeyHash()', () => { + it('should return hash of public key', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const hash = pubKey.getPublicKeyHash(); + + expect(hash).to.deep.equal( + toHexString([ + 211, 114, 240, 150, 37, 159, 114, 104, 110, 24, 102, 61, 125, 181, 248, 98, 52, 221, 111, + 85, + ]), + ); + }); + }); + + describe('keyId', () => { + it('should return keyId', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + expect(pubKey.keyId).to.equal(keyId); + }); + + it('should set keyId', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + pubKey.keyId = keyIdSet; + + expect(pubKey.keyId).to.equal(keyIdSet); + }); + }); + + describe('purpose', () => { + it('should return purpose', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + expect(pubKey.purpose).to.equal('AUTHENTICATION'); + }); + + it('should set purpose', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + pubKey.purpose = purposeSet; + + expect(pubKey.purpose).to.equal('ENCRYPTION'); + }); + }); + + describe('securityLevel', () => { + it('should return securityLevel', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + expect(pubKey.securityLevel).to.equal('CRITICAL'); + }); + + it('should set securityLevel', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + pubKey.securityLevel = securityLevelSet; + + expect(pubKey.securityLevel).to.equal('HIGH'); + }); + }); + + describe('keyType', () => { + it('should return keyType', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + expect(pubKey.keyType).to.equal('ECDSA_SECP256K1'); + }); + + it('should set keyType', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + pubKey.keyType = keyTypeSet; + + expect(pubKey.keyType).to.equal('ECDSA_HASH160'); + }); + }); + + describe('isReadOnly', () => { + it('should return isReadOnly', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + expect(pubKey.isReadOnly).to.equal(false); + }); + + it('should set isReadOnly', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + pubKey.isReadOnly = true; + + expect(pubKey.isReadOnly).to.equal(true); + }); + }); + + describe('data', () => { + it('should return data', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + expect(pubKey.data).to.equal(binaryDataHex); + }); + + it('should set data', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + pubKey.data = binaryDataSetHex; + + expect(pubKey.data).to.equal(binaryDataSetHex); + }); + }); + + describe('validatePrivateKey()', () => { + it('should validate private key against public key', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const privateKey = wasm.PrivateKey.fromWIF(wif); + + expect(pubKey.validatePrivateKey(privateKey.toBytes(), wasm.Network.Mainnet)).to.equal(false); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/IdentitySigner.spec.mjs b/packages/wasm-dpp2/tests/unit/IdentitySigner.spec.ts similarity index 85% rename from packages/wasm-dpp2/tests/unit/IdentitySigner.spec.mjs rename to packages/wasm-dpp2/tests/unit/IdentitySigner.spec.ts index 35fc0686f04..811240c9960 100644 --- a/packages/wasm-dpp2/tests/unit/IdentitySigner.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/IdentitySigner.spec.ts @@ -1,9 +1,8 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('IdentitySigner', () => { @@ -12,15 +11,15 @@ describe('IdentitySigner', () => { // Same key in hex format (32 bytes) const testPrivateKeyHex = '67ad1669d882da256b6fa05e1b0ae384a6ac8aed146ea53602b8ff0e1e9c18e9'; - describe('construction', () => { + describe('constructor()', () => { it('should create empty signer', () => { const signer = new wasm.IdentitySigner(); - expect(signer).to.exist; + expect(signer).to.exist(); expect(signer.keyCount).to.equal(0); }); }); - describe('addKey', () => { + describe('addKey()', () => { it('should add key from PrivateKey created from WIF', () => { const signer = new wasm.IdentitySigner(); const privateKey = wasm.PrivateKey.fromWIF(testPrivateKeyWif); @@ -50,7 +49,10 @@ describe('IdentitySigner', () => { const signer = new wasm.IdentitySigner(); const privateKey1 = wasm.PrivateKey.fromHex(testPrivateKeyHex, 'testnet'); - const privateKey2 = wasm.PrivateKey.fromHex('a9d9d0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd', 'testnet'); + const privateKey2 = wasm.PrivateKey.fromHex( + 'a9d9d0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd', + 'testnet', + ); signer.addKey(privateKey1); signer.addKey(privateKey2); @@ -71,7 +73,7 @@ describe('IdentitySigner', () => { }); }); - describe('addKeyFromWif', () => { + describe('addKeyFromWif()', () => { it('should add key from WIF string', () => { const signer = new wasm.IdentitySigner(); diff --git a/packages/wasm-dpp2/tests/unit/IdentityTopUpTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/IdentityTopUpTransition.spec.mjs deleted file mode 100644 index 92f88d61998..00000000000 --- a/packages/wasm-dpp2/tests/unit/IdentityTopUpTransition.spec.mjs +++ /dev/null @@ -1,148 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('IdentityTopUpTransition', () => { - describe('serialization / deserialization', () => { - it('should allow to create IdentityTopUpTransition', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - // instant lock - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - // transaction - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - // output index - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - expect(transition.__wbg_ptr).to.not.equal(0); - expect(assetLockProof.__wbg_ptr).to.not.equal(0); - }); - - it('should convert IdentityTopUpTransition to base64 and back', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - const base64 = transition.toBase64(); - const bytes = transition.toBytes(); - - expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); - - const restored = wasm.IdentityTopUpTransition.fromBase64(base64); - - expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); - }); - }); - - describe('getters', () => { - it('should allow to return userFeeIncrease', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - // instant lock - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - // transaction - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - // output index - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - expect(transition.userFeeIncrease).to.deep.equal(11); - }); - - it('should allow to return identityIdentifier', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - // instant lock - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - // transaction - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - // output index - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - expect(transition.identityIdentifier.toBase58()).to.deep.equal('B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH'); - }); - - it('should allow to return signature', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - // instant lock - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - // transaction - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - // output index - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - expect(transition.signature).to.deep.equal(Uint8Array.from([])); - }); - }); - - describe('setters', () => { - it('should allow to set userFeeIncrease', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - // instant lock - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - // transaction - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - // output index - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - transition.userFeeIncrease = 21; - - expect(transition.userFeeIncrease).to.deep.equal(21); - }); - - it('should allow to set identityIdentifier', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - // instant lock - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - // transaction - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - // output index - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - const identifier = new wasm.Identifier('777cE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH'); - - transition.identityIdentifier = identifier; - - expect(transition.identityIdentifier.toBase58()).to.deep.equal('777cE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH'); - }); - - it('should allow to set signature', () => { - const assetLockProof = wasm.AssetLockProof.createInstantAssetLockProof( - // instant lock - [1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19], - // transaction - [3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172], - // output index - 0, - ); - - const transition = new wasm.IdentityTopUpTransition(assetLockProof, 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', 11); - - transition.signature = Uint8Array.from([1, 1, 1]); - - expect(transition.signature).to.deep.equal(Uint8Array.from([1, 1, 1])); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityTopUpTransition.spec.ts b/packages/wasm-dpp2/tests/unit/IdentityTopUpTransition.spec.ts new file mode 100644 index 00000000000..cb1ea160abc --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/IdentityTopUpTransition.spec.ts @@ -0,0 +1,148 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('IdentityTopUpTransition', () => { + // Shared test data - instant lock bytes + // prettier-ignore + const instantLockBytes = [ + 1, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, 210, 53, + 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 177, 215, 65, + 96, 204, 228, 86, 13, 14, 185, 46, 65, 241, 38, 226, 172, 59, 96, 158, 15, 126, 90, 225, + 3, 140, 221, 96, 131, 254, 12, 236, 26, 48, 124, 31, 23, 184, 202, 122, 231, 123, 59, 43, + 118, 27, 214, 225, 58, 44, 191, 232, 10, 33, 35, 8, 113, 145, 159, 158, 88, 80, 0, 0, 0, + 173, 103, 128, 160, 29, 226, 161, 219, 167, 194, 158, 38, 19, 51, 143, 248, 161, 87, 126, + 32, 143, 209, 152, 44, 174, 6, 25, 210, 101, 127, 131, 65, 202, 241, 47, 166, 132, 10, + 199, 15, 187, 136, 11, 217, 237, 13, 173, 64, 11, 6, 112, 188, 234, 239, 204, 29, 3, 6, + 35, 154, 44, 106, 44, 183, 171, 126, 146, 240, 153, 210, 187, 56, 133, 161, 11, 4, 151, + 63, 89, 20, 44, 66, 153, 242, 97, 207, 44, 110, 208, 51, 198, 113, 104, 79, 154, 19, + ]; + + // Shared test data - transaction bytes + // prettier-ignore + const transactionBytes = [ + 3, 0, 8, 0, 1, 193, 219, 244, 102, 77, 20, 251, 187, 201, 109, 168, 125, 7, 244, 118, 119, + 210, 53, 238, 105, 138, 31, 7, 73, 30, 128, 131, 175, 114, 76, 187, 37, 0, 0, 0, 0, 106, + 71, 48, 68, 2, 32, 2, 146, 73, 163, 223, 124, 140, 225, 109, 126, 239, 87, 105, 184, 118, + 87, 182, 100, 182, 6, 15, 200, 26, 44, 33, 215, 165, 110, 211, 232, 245, 233, 2, 32, 69, + 161, 168, 128, 101, 26, 171, 20, 63, 30, 219, 87, 23, 4, 142, 115, 73, 73, 170, 203, 46, + 187, 149, 32, 210, 171, 46, 136, 253, 188, 36, 12, 1, 33, 2, 144, 231, 28, 153, 30, 92, + 52, 10, 111, 47, 107, 74, 225, 237, 151, 33, 188, 184, 247, 121, 70, 135, 174, 31, 160, + 16, 216, 239, 225, 103, 88, 112, 255, 255, 255, 255, 2, 64, 66, 15, 0, 0, 0, 0, 0, 2, + 106, 0, 216, 154, 230, 5, 0, 0, 0, 0, 25, 118, 169, 20, 229, 154, 45, 140, 145, 114, 18, + 52, 205, 13, 179, 84, 94, 174, 149, 207, 101, 115, 51, 240, 136, 172, 0, 0, 0, 0, 36, 1, + 1, 64, 66, 15, 0, 0, 0, 0, 0, 25, 118, 169, 20, 176, 213, 107, 82, 203, 147, 209, 128, + 255, 63, 69, 219, 41, 250, 232, 254, 185, 168, 85, 184, 136, 172, + ]; + + const testIdentityId = 'B7kcE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH'; + + function createAssetLockProof() { + return wasm.AssetLockProof.createInstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + } + + function createTransition() { + return new wasm.IdentityTopUpTransition({ + assetLockProof: createAssetLockProof(), + identityId: testIdentityId, + userFeeIncrease: 11, + }); + } + + describe('constructor()', () => { + it('should create IdentityTopUpTransition', () => { + const assetLockProof = createAssetLockProof(); + const transition = new wasm.IdentityTopUpTransition({ + assetLockProof, + identityId: testIdentityId, + userFeeIncrease: 11, + }); + + expect(transition).to.be.an.instanceof(wasm.IdentityTopUpTransition); + expect(assetLockProof).to.be.an.instanceof(wasm.AssetLockProof); + }); + }); + + describe('toBase64()', () => { + it('should convert IdentityTopUpTransition to base64', () => { + const transition = createTransition(); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('fromBase64()', () => { + it('should restore IdentityTopUpTransition from base64', () => { + const transition = createTransition(); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + const restored = wasm.IdentityTopUpTransition.fromBase64(base64); + + expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('userFeeIncrease', () => { + it('should return userFeeIncrease', () => { + const transition = createTransition(); + + expect(transition.userFeeIncrease).to.deep.equal(11); + }); + + it('should set userFeeIncrease', () => { + const transition = createTransition(); + + transition.userFeeIncrease = 21; + + expect(transition.userFeeIncrease).to.deep.equal(21); + }); + }); + + describe('identityIdentifier', () => { + it('should return identityIdentifier', () => { + const transition = createTransition(); + + expect(transition.identityIdentifier.toBase58()).to.deep.equal(testIdentityId); + }); + + it('should set identityIdentifier', () => { + const transition = createTransition(); + + const identifier = new wasm.Identifier('777cE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH'); + + transition.identityIdentifier = identifier; + + expect(transition.identityIdentifier.toBase58()).to.deep.equal( + '777cE1juMBWEWkuYRJhVdAE2e6RaevrGxRsa1DrLCpQH', + ); + }); + }); + + describe('signature', () => { + it('should return signature', () => { + const transition = createTransition(); + + expect(transition.signature).to.deep.equal(Uint8Array.from([])); + }); + + it('should set signature', () => { + const transition = createTransition(); + + transition.signature = Uint8Array.from([1, 1, 1]); + + expect(transition.signature).to.deep.equal(Uint8Array.from([1, 1, 1])); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityUpdateTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/IdentityUpdateTransition.spec.mjs deleted file mode 100644 index 128fc59c4ef..00000000000 --- a/packages/wasm-dpp2/tests/unit/IdentityUpdateTransition.spec.mjs +++ /dev/null @@ -1,152 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('IdentityUpdateTransition', () => { - describe('serialization / deserialization', () => { - it('Should create IdentityUpdateTransition', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), 1, [], []); - - expect(transition.__wbg_ptr).to.not.equal(0); - }); - - it('Should create IdentityUpdateTransition with key', () => { - const key = new wasm.IdentityPublicKeyInCreation(1, 'system', 'master', 'ECDSA_SECP256K1', false, [], []); - - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), 1, [key], []); - - expect(transition.__wbg_ptr).to.not.equal(0); - expect(key.__wbg_ptr).to.not.equal(0); - }); - - it('Should convert IdentityUpdateTransition to base64 and back', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), 1, [], []); - - const base64 = transition.toBase64(); - const bytes = transition.toBytes(); - - expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); - - const restored = wasm.IdentityUpdateTransition.fromBase64(base64); - - expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); - }); - }); - - describe('getters', () => { - it('Should return revision', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), 1, [], []); - - expect(transition.revision).to.deep.equal(BigInt(1)); - }); - - it('Should return nonce', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), 1, [], []); - - expect(transition.nonce).to.deep.equal(BigInt(1)); - }); - - it('Should return identityIdentifier', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), 1, [], []); - - expect(transition.identityIdentifier.toBase58()).to.deep.equal('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3'); - }); - - it('Should return publicKeyIdsToDisable', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - expect(Array.from(transition.publicKeyIdsToDisable)).to.deep.equal([11]); - }); - - it('Should return publicKeyIdsToAdd', () => { - const key = new wasm.IdentityPublicKeyInCreation(1, 'system', 'master', 'ECDSA_SECP256K1', false, [], []); - - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [key], [11]); - - expect(transition.publicKeyIdsToAdd.length).to.deep.equal(1); - }); - - it('Should return userFeeIncrease', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11], 1); - - expect(transition.userFeeIncrease).to.deep.equal(1); - }); - - it('Should return signature', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11], 1); - - expect(transition.signature).to.deep.equal(Uint8Array.from([])); - }); - - it('Should return signature public key id', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - expect(transition.signaturePublicKeyId).to.deep.equal(0); - }); - }); - - describe('setters', () => { - it('Should allow to set identityIdentifier', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - transition.identityIdentifier = '11Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3'; - - expect(transition.identityIdentifier.toBase58()).to.deep.equal('11Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3'); - }); - - it('Should allow to set revision', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - transition.revision = BigInt(11111); - - expect(transition.revision).to.deep.equal(BigInt(11111)); - }); - - it('Should allow to set nonce', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - transition.nonce = BigInt(11111); - - expect(transition.nonce).to.deep.equal(BigInt(11111)); - }); - - it('Should allow to set publicKeyIdsToDisable', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - transition.publicKeyIdsToDisable = [1, 2, 3, 4]; - - expect(transition.publicKeyIdsToDisable).to.deep.equal(Uint32Array.from([1, 2, 3, 4])); - }); - - it('Should allow to set publicKeyIdsToAdd', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - const key = new wasm.IdentityPublicKeyInCreation(1, 'system', 'master', 'ECDSA_SECP256K1', false, [], []); - - transition.publicKeyIdsToAdd = [key, key]; - - expect(transition.publicKeyIdsToAdd.length).to.deep.equal(2); - expect(key.__wbg_ptr).to.not.equal(0); - }); - - it('Should allow to set signature', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - transition.signature = [0, 1, 2, 3, 5]; - - expect(transition.signature).to.deep.equal(Uint8Array.from([0, 1, 2, 3, 5])); - }); - - it('Should allow to set signature public key id', () => { - const transition = new wasm.IdentityUpdateTransition('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', BigInt(1), BigInt(1), [], [11]); - - transition.signaturePublicKeyId = 11; - - expect(transition.signaturePublicKeyId).to.deep.equal(11); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/IdentityUpdateTransition.spec.ts b/packages/wasm-dpp2/tests/unit/IdentityUpdateTransition.spec.ts new file mode 100644 index 00000000000..80ee11f3602 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/IdentityUpdateTransition.spec.ts @@ -0,0 +1,219 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { fromHexString } from './utils/hex.ts'; + +before(async () => { + await initWasm(); +}); + +interface PublicKeyInCreationOptions { + keyId?: number; + purpose?: string; + securityLevel?: string; + keyType?: string; + isReadOnly?: boolean; + data?: Uint8Array; + signature?: number[]; +} + +interface UpdateTransitionOptions { + identityId?: string; + revision?: bigint; + nonce?: bigint; + addPublicKeys?: unknown[]; + disablePublicKeys?: number[]; + userFeeIncrease?: number; +} + +describe('IdentityUpdateTransition', () => { + // Helper to create a public key in creation + function createPublicKeyInCreation(options: PublicKeyInCreationOptions = {}) { + return new wasm.IdentityPublicKeyInCreation({ + keyId: options.keyId ?? 1, + purpose: options.purpose ?? 'SYSTEM', + securityLevel: options.securityLevel ?? 'master', + keyType: options.keyType ?? 'ECDSA_SECP256K1', + isReadOnly: options.isReadOnly ?? false, + data: options.data ?? fromHexString('036a394312e40e81d928fde2bde7880070e4fa9c1d1d9b168da707ea468afa2b48'), + signature: options.signature ?? [], + }); + } + + // Helper to create an update transition + function createUpdateTransition(options: UpdateTransitionOptions = {}) { + return new wasm.IdentityUpdateTransition({ + identityId: options.identityId ?? 'GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3', + revision: options.revision ?? BigInt(1), + nonce: options.nonce ?? BigInt(1), + addPublicKeys: options.addPublicKeys ?? [], + disablePublicKeys: options.disablePublicKeys ?? [], + userFeeIncrease: options.userFeeIncrease ?? 0, + }); + } + + describe('constructor()', () => { + it('should create IdentityUpdateTransition', () => { + const transition = createUpdateTransition(); + + expect(transition).to.be.an.instanceof(wasm.IdentityUpdateTransition); + }); + + it('should create IdentityUpdateTransition with key', () => { + const key = createPublicKeyInCreation(); + + const transition = createUpdateTransition({ addPublicKeys: [key] }); + + expect(transition).to.be.an.instanceof(wasm.IdentityUpdateTransition); + expect(key).to.be.an.instanceof(wasm.IdentityPublicKeyInCreation); + }); + }); + + describe('toBase64()', () => { + it('should convert IdentityUpdateTransition to base64', () => { + const transition = createUpdateTransition(); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('fromBase64()', () => { + it('should restore IdentityUpdateTransition from base64', () => { + const transition = createUpdateTransition(); + + const base64 = transition.toBase64(); + const bytes = transition.toBytes(); + + const restored = wasm.IdentityUpdateTransition.fromBase64(base64); + + expect(Buffer.from(restored.toBytes())).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('revision', () => { + it('should return revision', () => { + const transition = createUpdateTransition(); + + expect(transition.revision).to.deep.equal(BigInt(1)); + }); + + it('should set revision', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + transition.revision = BigInt(11111); + + expect(transition.revision).to.deep.equal(BigInt(11111)); + }); + }); + + describe('nonce', () => { + it('should return nonce', () => { + const transition = createUpdateTransition(); + + expect(transition.nonce).to.deep.equal(BigInt(1)); + }); + + it('should set nonce', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + transition.nonce = BigInt(11111); + + expect(transition.nonce).to.deep.equal(BigInt(11111)); + }); + }); + + describe('identityIdentifier', () => { + it('should return identityIdentifier', () => { + const transition = createUpdateTransition(); + + expect(transition.identityIdentifier.toBase58()).to.deep.equal('GL2Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3'); + }); + + it('should set identityIdentifier', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + transition.identityIdentifier = '11Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3'; + + expect(transition.identityIdentifier.toBase58()).to.deep.equal('11Rq8L3VuBEQfCAZykmUaiXXrsd1Bwub2gcaMmtNbn3'); + }); + }); + + describe('publicKeyIdsToDisable', () => { + it('should return publicKeyIdsToDisable', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + expect(Array.from(transition.publicKeyIdsToDisable)).to.deep.equal([11]); + }); + + it('should set publicKeyIdsToDisable', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + transition.publicKeyIdsToDisable = [1, 2, 3, 4]; + + expect(transition.publicKeyIdsToDisable).to.deep.equal(Uint32Array.from([1, 2, 3, 4])); + }); + }); + + describe('publicKeyIdsToAdd', () => { + it('should return publicKeyIdsToAdd', () => { + const key = createPublicKeyInCreation(); + + const transition = createUpdateTransition({ addPublicKeys: [key], disablePublicKeys: [11] }); + + expect(transition.publicKeyIdsToAdd.length).to.deep.equal(1); + }); + + it('should set publicKeyIdsToAdd', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + const key = createPublicKeyInCreation(); + + transition.publicKeyIdsToAdd = [key, key]; + + expect(transition.publicKeyIdsToAdd.length).to.deep.equal(2); + expect(key).to.be.an.instanceof(wasm.IdentityPublicKeyInCreation); + }); + }); + + describe('userFeeIncrease', () => { + it('should return userFeeIncrease', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11], userFeeIncrease: 1 }); + + expect(transition.userFeeIncrease).to.deep.equal(1); + }); + }); + + describe('signature', () => { + it('should return signature', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11], userFeeIncrease: 1 }); + + expect(transition.signature).to.deep.equal(Uint8Array.from([])); + }); + + it('should set signature', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + transition.signature = [0, 1, 2, 3, 5]; + + expect(transition.signature).to.deep.equal(Uint8Array.from([0, 1, 2, 3, 5])); + }); + }); + + describe('signaturePublicKeyId', () => { + it('should return signaturePublicKeyId', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + expect(transition.signaturePublicKeyId).to.deep.equal(0); + }); + + it('should set signaturePublicKeyId', () => { + const transition = createUpdateTransition({ disablePublicKeys: [11] }); + + transition.signaturePublicKeyId = 11; + + expect(transition.signaturePublicKeyId).to.deep.equal(11); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/InstantLockProof.spec.mjs b/packages/wasm-dpp2/tests/unit/InstantLockProof.spec.mjs deleted file mode 100644 index bd3e233501d..00000000000 --- a/packages/wasm-dpp2/tests/unit/InstantLockProof.spec.mjs +++ /dev/null @@ -1,126 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { instantLockBytes, transactionBytes } from './mocks/Locks/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('InstantLock', () => { - describe('serialization / deserialization', () => { - it('should allow to create InstantLock from values', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - expect(instantLockProof.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to convert to object', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - const expected = { - instantLock: instantLockBytes, - transaction: transactionBytes, - outputIndex: 0, - }; - - expect(instantLockProof.toObject()).to.deep.equal(expected); - }); - - it('should allow to create from object', () => { - const lockObject = { - instantLock: instantLockBytes, - transaction: transactionBytes, - outputIndex: 0, - }; - - const instantLockProof = wasm.InstantAssetLockProof.fromObject(lockObject); - - expect(instantLockProof.__wbg_ptr).to.not.equal(0); - }); - - it('should round-trip via toJSON/fromJSON', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - const json = instantLockProof.toJSON(); - - // JSON format should have base64 strings - expect(json.instantLock).to.be.a('string'); - expect(json.transaction).to.be.a('string'); - expect(json.outputIndex).to.equal(0); - - // Verify base64 decodes to original bytes - expect(Buffer.from(json.instantLock, 'base64')).to.deep.equal(Buffer.from(instantLockBytes)); - expect(Buffer.from(json.transaction, 'base64')).to.deep.equal(Buffer.from(transactionBytes)); - - // Round-trip via fromJSON - const restored = wasm.InstantAssetLockProof.fromJSON(json); - - expect(restored.toObject()).to.deep.equal(instantLockProof.toObject()); - }); - - it('should round-trip via toObject/fromObject', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - const obj = instantLockProof.toObject(); - - // Object format should have Uint8Array - expect(obj.instantLock).to.be.instanceOf(Uint8Array); - expect(obj.transaction).to.be.instanceOf(Uint8Array); - expect(obj.outputIndex).to.equal(0); - - // Round-trip via fromObject - const restored = wasm.InstantAssetLockProof.fromObject(obj); - - expect(restored.toObject()).to.deep.equal(obj); - }); - }); - - describe('getters', () => { - it('should allow to get output as bytes', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - const output = instantLockProof.getOutput(); - expect(output).to.be.instanceOf(Uint8Array); - expect(output.length).to.be.greaterThan(0); - }); - - it('should allow to convert to get OutPoint', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - expect(instantLockProof.getOutPoint().constructor.name).to.deep.equal('OutPoint'); - }); - - it('should allow to get output index', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - expect(instantLockProof.outputIndex).to.deep.equal(0); - }); - - it('should allow to get instant lock as bytes', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - expect(instantLockProof.instantLock).to.be.instanceOf(Uint8Array); - expect(instantLockProof.instantLock).to.deep.equal(instantLockBytes); - }); - }); - - describe('setters', () => { - it('should allow to set output index', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - instantLockProof.outputIndex = 12; - - expect(instantLockProof.outputIndex).to.deep.equal(12); - }); - - it('should allow to set instant lock from bytes', () => { - const instantLockProof = new wasm.InstantAssetLockProof(instantLockBytes, transactionBytes, 0); - - // Set and verify the instant lock bytes round-trip - instantLockProof.instantLock = instantLockBytes; - - expect(instantLockProof.instantLock).to.deep.equal(instantLockBytes); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/InstantLockProof.spec.ts b/packages/wasm-dpp2/tests/unit/InstantLockProof.spec.ts new file mode 100644 index 00000000000..7d8d289fb40 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/InstantLockProof.spec.ts @@ -0,0 +1,193 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { instantLockBytes, transactionBytes } from './mocks/Locks/index.js'; + +before(async () => { + await initWasm(); +}); + +describe('InstantAssetLockProof', () => { + describe('constructor()', () => { + it('should create InstantAssetLockProof from values', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + expect(instantLockProof).to.be.an.instanceof(wasm.InstantAssetLockProof); + }); + }); + + describe('toObject()', () => { + it('should convert to object with Uint8Array values', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const expected = { + instantLock: instantLockBytes, + transaction: transactionBytes, + outputIndex: 0, + }; + + expect(instantLockProof.toObject()).to.deep.equal(expected); + }); + + it('should return object with Uint8Array for bytes fields', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const obj = instantLockProof.toObject(); + + // Object format should have Uint8Array + expect(obj.instantLock).to.be.instanceOf(Uint8Array); + expect(obj.transaction).to.be.instanceOf(Uint8Array); + expect(obj.outputIndex).to.equal(0); + }); + }); + + describe('fromObject()', () => { + it('should create from object', () => { + const lockObject = { + instantLock: instantLockBytes, + transaction: transactionBytes, + outputIndex: 0, + }; + + const instantLockProof = wasm.InstantAssetLockProof.fromObject(lockObject); + + expect(instantLockProof).to.be.an.instanceof(wasm.InstantAssetLockProof); + }); + + it('should round-trip via toObject/fromObject', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const obj = instantLockProof.toObject(); + const restored = wasm.InstantAssetLockProof.fromObject(obj); + + expect(restored.toObject()).to.deep.equal(obj); + }); + }); + + describe('toJSON()', () => { + it('should convert to JSON with base64 strings', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const json = instantLockProof.toJSON(); + + // JSON format should have base64 strings + expect(json.instantLock).to.be.a('string'); + expect(json.transaction).to.be.a('string'); + expect(json.outputIndex).to.equal(0); + + // Verify base64 decodes to original bytes + expect(Buffer.from(json.instantLock, 'base64')).to.deep.equal(Buffer.from(instantLockBytes)); + expect(Buffer.from(json.transaction, 'base64')).to.deep.equal(Buffer.from(transactionBytes)); + }); + }); + + describe('fromJSON()', () => { + it('should round-trip via toJSON/fromJSON', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const json = instantLockProof.toJSON(); + const restored = wasm.InstantAssetLockProof.fromJSON(json); + + expect(restored.toObject()).to.deep.equal(instantLockProof.toObject()); + }); + }); + + describe('output', () => { + it('should return output as bytes', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + const { output } = instantLockProof; + expect(output).to.be.instanceOf(Uint8Array); + expect(output.length).to.be.greaterThan(0); + }); + }); + + describe('outPoint', () => { + it('should return OutPoint instance', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + expect(instantLockProof.outPoint.constructor.name).to.deep.equal('OutPoint'); + }); + }); + + describe('outputIndex', () => { + it('should return output index', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + expect(instantLockProof.outputIndex).to.deep.equal(0); + }); + + it('should set output index', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + instantLockProof.outputIndex = 12; + + expect(instantLockProof.outputIndex).to.deep.equal(12); + }); + }); + + describe('instantLock', () => { + it('should return instant lock as bytes', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + expect(instantLockProof.instantLock).to.be.instanceOf(Uint8Array); + expect(instantLockProof.instantLock).to.deep.equal(instantLockBytes); + }); + + it('should set instant lock from bytes', () => { + const instantLockProof = new wasm.InstantAssetLockProof( + instantLockBytes, + transactionBytes, + 0, + ); + + // Set and verify the instant lock bytes round-trip + instantLockProof.instantLock = instantLockBytes; + + expect(instantLockProof.instantLock).to.deep.equal(instantLockBytes); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/OutPoint.spec.mjs b/packages/wasm-dpp2/tests/unit/OutPoint.spec.ts similarity index 56% rename from packages/wasm-dpp2/tests/unit/OutPoint.spec.mjs rename to packages/wasm-dpp2/tests/unit/OutPoint.spec.ts index 41d0ab37f8b..4280f62def7 100644 --- a/packages/wasm-dpp2/tests/unit/OutPoint.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/OutPoint.spec.ts @@ -1,20 +1,21 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('OutPoint', () => { - describe('serialization / deserialization', () => { - it('should allow to create from values', () => { + describe('constructor()', () => { + it('should create OutPoint from txid and vout', () => { const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - expect(outpoint.__wbg_ptr).to.not.equal(0); + expect(outpoint).to.be.an.instanceof(wasm.OutPoint); }); + }); - it('should allow to create from bytes', () => { + describe('fromBytes()', () => { + it('should create OutPoint from bytes', () => { const txIdBytes = Buffer.from('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 'hex'); // 32 bytes for txId and 4 bytes for vout @@ -22,24 +23,28 @@ describe('OutPoint', () => { const outpoint = wasm.OutPoint.fromBytes(bytes); - expect(outpoint.__wbg_ptr).to.not.equal(0); + expect(outpoint).to.be.an.instanceof(wasm.OutPoint); }); }); - describe('getters', () => { - it('should allow to get txid', () => { + describe('txid', () => { + it('should return transaction id', () => { const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - expect(outpoint.getTXID()).to.equal('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d'); + expect(outpoint.txid).to.equal('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d'); }); + }); - it('should allow to get VOUT', () => { + describe('vout', () => { + it('should return output index', () => { const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); - expect(outpoint.getVOUT()).to.equal(1); + expect(outpoint.vout).to.equal(1); }); + }); - it('should allow to get bytes', () => { + describe('toBytes()', () => { + it('should return bytes representation', () => { const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); const txIdBytes = Buffer.from('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 'hex'); @@ -49,14 +54,26 @@ describe('OutPoint', () => { expect(outpoint.toBytes()).to.deep.equal(Uint8Array.from(bytes)); }); + }); - it('should allow to get base64 representation', () => { + describe('toBase64()', () => { + it('should return base64 representation', () => { const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); const base64 = outpoint.toBase64(); const bytes = outpoint.toBytes(); expect(Buffer.from(base64, 'base64')).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('fromBase64()', () => { + it('should create OutPoint from base64 string', () => { + const outpoint = new wasm.OutPoint('e8b43025641eea4fd21190f01bd870ef90f1a8b199d8fc3376c5b62c0b1a179d', 1); + + const base64 = outpoint.toBase64(); + const bytes = outpoint.toBytes(); + expect(Buffer.from(wasm.OutPoint.fromBase64(base64).toBytes())).to.deep.equal(Buffer.from(bytes)); }); }); diff --git a/packages/wasm-dpp2/tests/unit/PartialIdentity.spec.ts b/packages/wasm-dpp2/tests/unit/PartialIdentity.spec.ts new file mode 100644 index 00000000000..6e7faa1cb6f --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/PartialIdentity.spec.ts @@ -0,0 +1,381 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { identifier, identifierBytes } from './mocks/Identity/index.js'; +import { + keyId, purpose, securityLevel, keyType, binaryData, +} from './mocks/PublicKey/index.js'; + +before(async () => { + await initWasm(); +}); + +describe('PartialIdentity', () => { + describe('constructor()', () => { + it('should create PartialIdentity with minimal options', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + expect(partialIdentity).to.be.an.instanceof(wasm.PartialIdentity); + expect(partialIdentity.id.toBase58()).to.equal(identifier); + }); + + it('should create PartialIdentity with all options', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: { [keyId]: pubKey }, + balance: BigInt(1000), + revision: BigInt(5), + notFoundPublicKeys: [10, 20], + }); + + expect(partialIdentity).to.be.an.instanceof(wasm.PartialIdentity); + expect(partialIdentity.id.toBase58()).to.equal(identifier); + expect(partialIdentity.balance).to.equal(BigInt(1000)); + expect(partialIdentity.revision).to.equal(BigInt(5)); + expect(Array.from(partialIdentity.notFoundPublicKeys)).to.deep.equal([10, 20]); + }); + }); + + describe('toJSON()', () => { + it('should serialize to JSON with minimal data', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + const json = partialIdentity.toJSON(); + + expect(json.id).to.equal(identifier); + expect(json.loadedPublicKeys).to.deep.equal({}); + // JSON uses null for missing optional fields (JSON standard) + expect(json.balance).to.equal(null); + expect(json.revision).to.equal(null); + expect(json.notFoundPublicKeys).to.deep.equal([]); + }); + + it('should serialize to JSON with all data', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: { [keyId]: pubKey }, + balance: BigInt(1000), + revision: BigInt(5), + notFoundPublicKeys: [10, 20], + }); + + const json = partialIdentity.toJSON(); + + expect(json.id).to.equal(identifier); + expect(Object.keys(json.loadedPublicKeys)).to.deep.equal([String(keyId)]); + expect(json.loadedPublicKeys[String(keyId)]).to.be.an('object'); + // IdentityPublicKey JSON uses 'id' field not 'keyId' + expect(json.loadedPublicKeys[String(keyId)].id).to.equal(keyId); + expect(json.balance).to.equal(1000); + expect(json.revision).to.equal(5); + expect(json.notFoundPublicKeys).to.deep.equal([10, 20]); + }); + }); + + describe('toObject()', () => { + it('should serialize to object with minimal data', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + const obj = partialIdentity.toObject(); + + // toObject returns Uint8Array for id (consistent with other toObject implementations) + expect(obj.id.constructor.name).to.equal('Uint8Array'); + expect(Array.from(obj.id)).to.deep.equal(identifierBytes); + expect(obj.loadedPublicKeys).to.deep.equal({}); + expect(obj.balance).to.equal(undefined); + expect(obj.revision).to.equal(undefined); + expect(Array.from(obj.notFoundPublicKeys)).to.deep.equal([]); + }); + + it('should serialize to object with all data', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: { [keyId]: pubKey }, + balance: BigInt(1000), + revision: BigInt(5), + notFoundPublicKeys: [10, 20], + }); + + const obj = partialIdentity.toObject(); + + // toObject returns Uint8Array for id + expect(obj.id.constructor.name).to.equal('Uint8Array'); + expect(Array.from(obj.id)).to.deep.equal(identifierBytes); + expect(Object.keys(obj.loadedPublicKeys)).to.deep.equal([String(keyId)]); + // loadedPublicKeys values should be plain objects (from toObject), not WASM instances + expect(obj.loadedPublicKeys[String(keyId)]).to.be.an('object'); + expect(obj.loadedPublicKeys[String(keyId)].id).to.equal(keyId); + expect(obj.balance).to.equal(BigInt(1000)); + expect(obj.revision).to.equal(BigInt(5)); + expect(Array.from(obj.notFoundPublicKeys)).to.deep.equal([10, 20]); + }); + }); + + describe('id', () => { + it('should get id', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + expect(partialIdentity.id.toBase58()).to.equal(identifier); + }); + + it('should set id', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + const newId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; + partialIdentity.id = newId; + + expect(partialIdentity.id.toBase58()).to.equal(newId); + }); + }); + + describe('loadedPublicKeys', () => { + it('should get loadedPublicKeys', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: { [keyId]: pubKey }, + }); + + const keys = partialIdentity.loadedPublicKeys; + expect(Object.keys(keys)).to.deep.equal([String(keyId)]); + expect(keys[String(keyId)].__type).to.equal('IdentityPublicKey'); + }); + + it('should set loadedPublicKeys', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + partialIdentity.loadedPublicKeys = { [keyId]: pubKey }; + + const keys = partialIdentity.loadedPublicKeys; + expect(Object.keys(keys)).to.deep.equal([String(keyId)]); + expect(keys[String(keyId)].__type).to.equal('IdentityPublicKey'); + }); + }); + + describe('balance', () => { + it('should get balance', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + balance: BigInt(500), + }); + + expect(partialIdentity.balance).to.equal(BigInt(500)); + }); + + it('should set balance', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + partialIdentity.balance = BigInt(999); + + expect(partialIdentity.balance).to.equal(BigInt(999)); + }); + }); + + describe('revision', () => { + it('should get revision', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + revision: BigInt(10), + }); + + expect(partialIdentity.revision).to.equal(BigInt(10)); + }); + + it('should set revision', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + partialIdentity.revision = BigInt(42); + + expect(partialIdentity.revision).to.equal(BigInt(42)); + }); + }); + + describe('notFoundPublicKeys', () => { + it('should get notFoundPublicKeys', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + notFoundPublicKeys: [5, 15, 25], + }); + + expect(Array.from(partialIdentity.notFoundPublicKeys)).to.deep.equal([5, 15, 25]); + }); + + it('should set notFoundPublicKeys', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + partialIdentity.notFoundPublicKeys = [100, 200]; + + expect(Array.from(partialIdentity.notFoundPublicKeys)).to.deep.equal([100, 200]); + }); + }); + + describe('fromObject()', () => { + it('should deserialize from object with minimal data', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + const obj = partialIdentity.toObject(); + const restored = wasm.PartialIdentity.fromObject(obj); + + expect(restored.id.toBase58()).to.equal(identifier); + expect(restored.loadedPublicKeys).to.deep.equal({}); + // Getters return undefined for missing optional values (Option -> undefined) + expect(restored.balance).to.equal(undefined); + expect(restored.revision).to.equal(undefined); + expect(Array.from(restored.notFoundPublicKeys)).to.deep.equal([]); + }); + + it('should deserialize from object with all data', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: { [keyId]: pubKey }, + balance: BigInt(1000), + revision: BigInt(5), + notFoundPublicKeys: [10, 20], + }); + + const obj = partialIdentity.toObject(); + const restored = wasm.PartialIdentity.fromObject(obj); + + expect(restored.id.toBase58()).to.equal(identifier); + expect(Object.keys(restored.loadedPublicKeys)).to.deep.equal([String(keyId)]); + expect(restored.loadedPublicKeys[String(keyId)].__type).to.equal('IdentityPublicKey'); + expect(restored.balance).to.equal(BigInt(1000)); + expect(restored.revision).to.equal(BigInt(5)); + expect(Array.from(restored.notFoundPublicKeys)).to.deep.equal([10, 20]); + }); + }); + + describe('fromJSON()', () => { + it('should deserialize from JSON with minimal data', () => { + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: {}, + }); + + const json = partialIdentity.toJSON(); + const restored = wasm.PartialIdentity.fromJSON(json); + + expect(restored.id.toBase58()).to.equal(identifier); + expect(restored.loadedPublicKeys).to.deep.equal({}); + // Getters return undefined for missing optional values (Option -> undefined) + expect(restored.balance).to.equal(undefined); + expect(restored.revision).to.equal(undefined); + expect(Array.from(restored.notFoundPublicKeys)).to.deep.equal([]); + }); + + it('should deserialize from JSON with all data', () => { + const pubKey = new wasm.IdentityPublicKey({ + keyId, + purpose, + securityLevel, + keyType, + isReadOnly: false, + data: binaryData, + }); + + const partialIdentity = new wasm.PartialIdentity({ + id: identifier, + loadedPublicKeys: { [keyId]: pubKey }, + balance: BigInt(1000), + revision: BigInt(5), + notFoundPublicKeys: [10, 20], + }); + + const json = partialIdentity.toJSON(); + const restored = wasm.PartialIdentity.fromJSON(json); + + expect(restored.id.toBase58()).to.equal(identifier); + expect(Object.keys(restored.loadedPublicKeys)).to.deep.equal([String(keyId)]); + expect(restored.loadedPublicKeys[String(keyId)].__type).to.equal('IdentityPublicKey'); + // Note: balance/revision come back as numbers in JSON (not BigInt) + expect(restored.balance).to.equal(BigInt(1000)); + expect(restored.revision).to.equal(BigInt(5)); + expect(Array.from(restored.notFoundPublicKeys)).to.deep.equal([10, 20]); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/PlatformAddress.spec.mjs b/packages/wasm-dpp2/tests/unit/PlatformAddress.spec.ts similarity index 59% rename from packages/wasm-dpp2/tests/unit/PlatformAddress.spec.mjs rename to packages/wasm-dpp2/tests/unit/PlatformAddress.spec.ts index af63965a66f..990d12dd858 100644 --- a/packages/wasm-dpp2/tests/unit/PlatformAddress.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/PlatformAddress.spec.ts @@ -1,38 +1,43 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('PlatformAddress', () => { - describe('fromBytes', () => { + describe('fromBytes()', () => { it('should create P2PKH address from bytes', () => { - const p2pkhBytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const p2pkhBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(p2pkhBytes); - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2PKH'); - expect(addr.isP2pkh).to.be.true; - expect(addr.isP2sh).to.be.false; + expect(addr.isP2pkh).to.be.true(); + expect(addr.isP2sh).to.be.false(); }); it('should create P2SH address from bytes', () => { - const p2shBytes = new Uint8Array([0x80, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const p2shBytes = new Uint8Array([ + 0x80, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(p2shBytes); - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2SH'); - expect(addr.isP2pkh).to.be.false; - expect(addr.isP2sh).to.be.true; + expect(addr.isP2pkh).to.be.false(); + expect(addr.isP2sh).to.be.true(); }); it('should reject invalid address type', () => { - const invalidBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const invalidBytes = new Uint8Array([ + 0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); try { wasm.PlatformAddress.fromBytes(invalidBytes); expect.fail('Should have thrown error for invalid address type'); - } catch (error) { - expect(error.message).to.include('type'); + } catch (error: unknown) { + expect((error as Error).message).to.include('type'); } }); @@ -41,36 +46,40 @@ describe('PlatformAddress', () => { try { wasm.PlatformAddress.fromBytes(shortBytes); expect.fail('Should have thrown error for wrong length'); - } catch (error) { - expect(error.message).to.include('21'); + } catch (error: unknown) { + expect((error as Error).message).to.include('21'); } }); }); - describe('fromBech32m', () => { + describe('fromBech32m()', () => { it('should create address from testnet bech32m string', () => { // First create an address and get its bech32m - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const originalAddr = wasm.PlatformAddress.fromBytes(bytes); const bech32m = originalAddr.toBech32m('testnet'); - expect(bech32m.startsWith('tevo1')).to.be.true; + expect(bech32m.startsWith('tevo1')).to.be.true(); // Parse it back const parsedAddr = wasm.PlatformAddress.fromBech32m(bech32m); - expect(parsedAddr).to.exist; + expect(parsedAddr).to.exist(); expect(parsedAddr.addressType).to.equal('P2PKH'); }); it('should create address from mainnet bech32m string', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const originalAddr = wasm.PlatformAddress.fromBytes(bytes); const bech32m = originalAddr.toBech32m('mainnet'); - expect(bech32m.startsWith('evo1')).to.be.true; + expect(bech32m.startsWith('evo1')).to.be.true(); const parsedAddr = wasm.PlatformAddress.fromBech32m(bech32m); - expect(parsedAddr).to.exist; + expect(parsedAddr).to.exist(); expect(parsedAddr.addressType).to.equal('P2PKH'); }); @@ -78,17 +87,17 @@ describe('PlatformAddress', () => { try { wasm.PlatformAddress.fromBech32m('invalid-address'); expect.fail('Should have thrown error for invalid bech32m'); - } catch (error) { - expect(error).to.exist; + } catch (error: unknown) { + expect(error).to.exist(); } }); }); - describe('fromHex', () => { + describe('fromHex()', () => { it('should create address from hex string', () => { const hexString = `b0${'01020304050607080910111213141516171819'.padEnd(40, '0').substring(0, 40)}`; const addr = wasm.PlatformAddress.fromHex(hexString); - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2PKH'); }); @@ -96,19 +105,19 @@ describe('PlatformAddress', () => { try { wasm.PlatformAddress.fromHex('not-valid-hex'); expect.fail('Should have thrown error for invalid hex'); - } catch (error) { - expect(error.message).to.include('hex'); + } catch (error: unknown) { + expect((error as Error).message).to.include('hex'); } }); }); - describe('fromP2pkhHash', () => { + describe('fromP2pkhHash()', () => { it('should create P2PKH address from 20-byte hash', () => { const hash = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); const addr = wasm.PlatformAddress.fromP2pkhHash(hash); - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2PKH'); - expect(addr.isP2pkh).to.be.true; + expect(addr.isP2pkh).to.be.true(); }); it('should reject wrong hash length', () => { @@ -116,19 +125,19 @@ describe('PlatformAddress', () => { try { wasm.PlatformAddress.fromP2pkhHash(shortHash); expect.fail('Should have thrown error for wrong length'); - } catch (error) { - expect(error.message).to.include('20 bytes'); + } catch (error: unknown) { + expect((error as Error).message).to.include('20 bytes'); } }); }); - describe('fromP2shHash', () => { + describe('fromP2shHash()', () => { it('should create P2SH address from 20-byte hash', () => { const hash = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); const addr = wasm.PlatformAddress.fromP2shHash(hash); - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2SH'); - expect(addr.isP2sh).to.be.true; + expect(addr.isP2sh).to.be.true(); }); it('should reject wrong hash length', () => { @@ -136,42 +145,50 @@ describe('PlatformAddress', () => { try { wasm.PlatformAddress.fromP2shHash(shortHash); expect.fail('Should have thrown error for wrong length'); - } catch (error) { - expect(error.message).to.include('20 bytes'); + } catch (error: unknown) { + expect((error as Error).message).to.include('20 bytes'); } }); }); - describe('constructor', () => { + describe('constructor()', () => { it('should accept PlatformAddress object', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const original = wasm.PlatformAddress.fromBytes(bytes); const copy = new wasm.PlatformAddress(original); - expect(copy).to.exist; + expect(copy).to.exist(); expect(copy.addressType).to.equal(original.addressType); }); it('should accept Uint8Array', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = new wasm.PlatformAddress(bytes); - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2PKH'); }); it('should accept bech32m string', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const original = wasm.PlatformAddress.fromBytes(bytes); const bech32m = original.toBech32m('testnet'); const addr = new wasm.PlatformAddress(bech32m); - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2PKH'); }); }); - describe('toBytes', () => { + describe('toBytes()', () => { it('should return 21-byte array', () => { - const inputBytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const inputBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(inputBytes); const outputBytes = addr.toBytes(); expect(outputBytes.length).to.equal(21); @@ -179,9 +196,11 @@ describe('PlatformAddress', () => { }); }); - describe('toHex', () => { + describe('toHex()', () => { it('should return hex string', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(bytes); const hex = addr.toHex(); expect(hex).to.be.a('string'); @@ -189,19 +208,25 @@ describe('PlatformAddress', () => { }); }); - describe('hash', () => { + describe('hash()', () => { it('should return 20-byte hash', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(bytes); const hash = addr.hash(); expect(hash.length).to.equal(20); - expect(Array.from(hash)).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + expect(Array.from(hash)).to.deep.equal([ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); }); }); - describe('hashToHex', () => { + describe('hashToHex()', () => { it('should return hex string of hash', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(bytes); const hashHex = addr.hashToHex(); expect(hashHex).to.be.a('string'); @@ -209,25 +234,31 @@ describe('PlatformAddress', () => { }); }); - describe('toBech32m', () => { + describe('toBech32m()', () => { it('should convert to testnet bech32m', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(bytes); const bech32m = addr.toBech32m('testnet'); expect(bech32m).to.be.a('string'); - expect(bech32m.startsWith('tevo1')).to.be.true; + expect(bech32m.startsWith('tevo1')).to.be.true(); }); it('should convert to mainnet bech32m', () => { - const bytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const bytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(bytes); const bech32m = addr.toBech32m('mainnet'); expect(bech32m).to.be.a('string'); - expect(bech32m.startsWith('evo1')).to.be.true; + expect(bech32m.startsWith('evo1')).to.be.true(); }); it('should roundtrip through bech32m', () => { - const originalBytes = new Uint8Array([0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + const originalBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(originalBytes); const bech32m = addr.toBech32m('testnet'); diff --git a/packages/wasm-dpp2/tests/unit/PlatformAddressInput.spec.mjs b/packages/wasm-dpp2/tests/unit/PlatformAddressInput.spec.ts similarity index 57% rename from packages/wasm-dpp2/tests/unit/PlatformAddressInput.spec.mjs rename to packages/wasm-dpp2/tests/unit/PlatformAddressInput.spec.ts index 256bcf56a7f..019f296030b 100644 --- a/packages/wasm-dpp2/tests/unit/PlatformAddressInput.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/PlatformAddressInput.spec.ts @@ -1,45 +1,56 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('PlatformAddressInput', () => { - describe('construction', () => { + describe('constructor()', () => { it('should create from PlatformAddress object', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const input = new wasm.PlatformAddressInput(platformAddr, 5, BigInt(500000)); - expect(input).to.exist; + expect(input).to.exist(); expect(input.nonce).to.equal(5); expect(input.amount).to.equal(BigInt(500000)); }); it('should create from bech32m address string', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const bech32m = platformAddr.toBech32m('testnet'); const input = new wasm.PlatformAddressInput(bech32m, 1, BigInt(100000)); - expect(input).to.exist; + expect(input).to.exist(); expect(input.nonce).to.equal(1); expect(input.amount).to.equal(BigInt(100000)); }); it('should create from Uint8Array', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const input = new wasm.PlatformAddressInput(addressBytes, 0, BigInt(100000)); - expect(input).to.exist; + expect(input).to.exist(); expect(input.nonce).to.equal(0); expect(input.amount).to.equal(BigInt(100000)); }); it('should handle zero nonce', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const input = new wasm.PlatformAddressInput(platformAddr, 0, BigInt(100000)); @@ -47,7 +58,10 @@ describe('PlatformAddressInput', () => { }); it('should handle large amounts', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const largeAmount = BigInt('10000000000000000'); // 10 quadrillion @@ -56,7 +70,10 @@ describe('PlatformAddressInput', () => { }); it('should handle max u32 nonce', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const maxU32 = 4294967295; // u32::MAX @@ -65,27 +82,40 @@ describe('PlatformAddressInput', () => { }); }); - describe('getters', () => { + describe('address', () => { it('should return the address', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const input = new wasm.PlatformAddressInput(platformAddr, 1, BigInt(100000)); const addr = input.address; - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2PKH'); }); + }); + describe('nonce', () => { it('should return the nonce', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const input = new wasm.PlatformAddressInput(platformAddr, 42, BigInt(100000)); expect(input.nonce).to.equal(42); }); + }); + describe('amount', () => { it('should return the amount', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const input = new wasm.PlatformAddressInput(platformAddr, 1, BigInt(123456)); diff --git a/packages/wasm-dpp2/tests/unit/PlatformAddressOutput.spec.mjs b/packages/wasm-dpp2/tests/unit/PlatformAddressOutput.spec.ts similarity index 56% rename from packages/wasm-dpp2/tests/unit/PlatformAddressOutput.spec.mjs rename to packages/wasm-dpp2/tests/unit/PlatformAddressOutput.spec.ts index ca14b2605d5..3dea3510878 100644 --- a/packages/wasm-dpp2/tests/unit/PlatformAddressOutput.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/PlatformAddressOutput.spec.ts @@ -1,42 +1,53 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('PlatformAddressOutput', () => { - describe('construction', () => { + describe('constructor()', () => { it('should create from PlatformAddress object', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const output = new wasm.PlatformAddressOutput(platformAddr, BigInt(500000)); - expect(output).to.exist; + expect(output).to.exist(); expect(output.amount).to.equal(BigInt(500000)); }); it('should create from bech32m address string', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const bech32m = platformAddr.toBech32m('testnet'); const output = new wasm.PlatformAddressOutput(bech32m, BigInt(90000)); - expect(output).to.exist; + expect(output).to.exist(); expect(output.amount).to.equal(BigInt(90000)); }); it('should create from Uint8Array', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const output = new wasm.PlatformAddressOutput(addressBytes, BigInt(100000)); - expect(output).to.exist; + expect(output).to.exist(); expect(output.amount).to.equal(BigInt(100000)); }); it('should handle large amounts', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const largeAmount = BigInt('10000000000000000'); @@ -45,7 +56,10 @@ describe('PlatformAddressOutput', () => { }); it('should handle zero amount', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const output = new wasm.PlatformAddressOutput(platformAddr, BigInt(0)); @@ -53,29 +67,39 @@ describe('PlatformAddressOutput', () => { }); it('should reject negative amount', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); expect(() => { - // eslint-disable-next-line no-new new wasm.PlatformAddressOutput(platformAddr, BigInt(-1)); }).to.throw(); }); }); - describe('getters', () => { + describe('address', () => { it('should return the address', () => { - const addressBytes = new Uint8Array([0x01, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0x80 is P2SH address type + const addressBytes = new Uint8Array([ + 0x80, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const output = new wasm.PlatformAddressOutput(platformAddr, BigInt(100000)); const addr = output.address; - expect(addr).to.exist; + expect(addr).to.exist(); expect(addr.addressType).to.equal('P2SH'); }); + }); + describe('amount', () => { it('should return the amount', () => { - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const platformAddr = wasm.PlatformAddress.fromBytes(addressBytes); const output = new wasm.PlatformAddressOutput(platformAddr, BigInt(999999)); diff --git a/packages/wasm-dpp2/tests/unit/PlatformAddressSigner.spec.mjs b/packages/wasm-dpp2/tests/unit/PlatformAddressSigner.spec.ts similarity index 82% rename from packages/wasm-dpp2/tests/unit/PlatformAddressSigner.spec.mjs rename to packages/wasm-dpp2/tests/unit/PlatformAddressSigner.spec.ts index e3f88c80764..0c4d36b49da 100644 --- a/packages/wasm-dpp2/tests/unit/PlatformAddressSigner.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/PlatformAddressSigner.spec.ts @@ -1,9 +1,8 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('PlatformAddressSigner', () => { @@ -12,22 +11,22 @@ describe('PlatformAddressSigner', () => { // Same key in hex format (32 bytes) const testPrivateKeyHex = '67ad1669d882da256b6fa05e1b0ae384a6ac8aed146ea53602b8ff0e1e9c18e9'; - describe('construction', () => { + describe('constructor()', () => { it('should create empty signer', () => { const signer = new wasm.PlatformAddressSigner(); - expect(signer).to.exist; + expect(signer).to.exist(); expect(signer.keyCount).to.equal(0); }); }); - describe('addKey', () => { + describe('addKey()', () => { it('should add key and return derived address from PrivateKey created from WIF', () => { const signer = new wasm.PlatformAddressSigner(); const privateKey = wasm.PrivateKey.fromWIF(testPrivateKeyWif); const derivedAddr = signer.addKey(privateKey); expect(signer.keyCount).to.equal(1); - expect(derivedAddr).to.exist; + expect(derivedAddr).to.exist(); expect(derivedAddr.addressType).to.equal('P2PKH'); }); @@ -37,7 +36,7 @@ describe('PlatformAddressSigner', () => { const derivedAddr = signer.addKey(privateKey); expect(signer.keyCount).to.equal(1); - expect(derivedAddr).to.exist; + expect(derivedAddr).to.exist(); expect(derivedAddr.addressType).to.equal('P2PKH'); }); @@ -48,7 +47,7 @@ describe('PlatformAddressSigner', () => { const derivedAddr = signer.addKey(privateKey); expect(signer.keyCount).to.equal(1); - expect(derivedAddr).to.exist; + expect(derivedAddr).to.exist(); expect(derivedAddr.addressType).to.equal('P2PKH'); }); @@ -56,7 +55,10 @@ describe('PlatformAddressSigner', () => { const signer = new wasm.PlatformAddressSigner(); const privateKey1 = wasm.PrivateKey.fromHex(testPrivateKeyHex, 'testnet'); - const privateKey2 = wasm.PrivateKey.fromHex('a9d9d0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd', 'testnet'); + const privateKey2 = wasm.PrivateKey.fromHex( + 'a9d9d0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd', + 'testnet', + ); const addr1 = signer.addKey(privateKey1); const addr2 = signer.addKey(privateKey2); @@ -80,21 +82,24 @@ describe('PlatformAddressSigner', () => { }); }); - describe('hasKey', () => { + describe('hasKey()', () => { it('should return true for derived address', () => { const signer = new wasm.PlatformAddressSigner(); const privateKey = wasm.PrivateKey.fromHex(testPrivateKeyHex, 'testnet'); const derivedAddr = signer.addKey(privateKey); - expect(signer.hasKey(derivedAddr)).to.be.true; + expect(signer.hasKey(derivedAddr)).to.be.true(); }); it('should return false for unknown address', () => { const signer = new wasm.PlatformAddressSigner(); - const addressBytes = new Uint8Array([0x00, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); + // 0xb0 is P2PKH address type + const addressBytes = new Uint8Array([ + 0xb0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + ]); const addr = wasm.PlatformAddress.fromBytes(addressBytes); - expect(signer.hasKey(addr)).to.be.false; + expect(signer.hasKey(addr)).to.be.false(); }); it('should accept derived address as bech32m string', () => { @@ -103,11 +108,11 @@ describe('PlatformAddressSigner', () => { const derivedAddr = signer.addKey(privateKey); const bech32m = derivedAddr.toBech32m('testnet'); - expect(signer.hasKey(bech32m)).to.be.true; + expect(signer.hasKey(bech32m)).to.be.true(); }); }); - describe('getPrivateKeysBytes', () => { + describe('getPrivateKeysBytes()', () => { it('should return empty array for empty signer', () => { const signer = new wasm.PlatformAddressSigner(); const keys = signer.getPrivateKeysBytes(); diff --git a/packages/wasm-dpp2/tests/unit/PrivateKey.spec.mjs b/packages/wasm-dpp2/tests/unit/PrivateKey.spec.ts similarity index 51% rename from packages/wasm-dpp2/tests/unit/PrivateKey.spec.mjs rename to packages/wasm-dpp2/tests/unit/PrivateKey.spec.ts index c500a6324dd..e8021e05c51 100644 --- a/packages/wasm-dpp2/tests/unit/PrivateKey.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/PrivateKey.spec.ts @@ -1,68 +1,71 @@ -import getWasm from './helpers/wasm.js'; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; import { wif, bytes, publicKeyHash } from './mocks/PrivateKey/index.js'; -import { fromHexString, toHexString } from './utils/hex.js'; - -let wasm; +import { fromHexString, toHexString } from './utils/hex.ts'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('PrivateKey', () => { - describe('serialization / deserialization', () => { - it('should allows to create PrivateKey from wif', () => { + describe('fromWIF()', () => { + it('should create PrivateKey from WIF', () => { const pkey = wasm.PrivateKey.fromWIF(wif); - expect(pkey.__wbg_ptr).to.not.equal(0); + expect(pkey).to.be.an.instanceof(wasm.PrivateKey); }); + }); - it('should allows to create PrivateKey from bytes', () => { + describe('fromBytes()', () => { + it('should create PrivateKey from bytes', () => { const pkey = wasm.PrivateKey.fromBytes(fromHexString(bytes), 'Mainnet'); - expect(pkey.__wbg_ptr).to.not.equal(0); + expect(pkey).to.be.an.instanceof(wasm.PrivateKey); }); + }); - it('should allows to create PrivateKey from hex', () => { + describe('fromHex()', () => { + it('should create PrivateKey from hex', () => { const pkey = wasm.PrivateKey.fromBytes(fromHexString(bytes), 'Mainnet'); const pkeyFromHex = wasm.PrivateKey.fromHex(bytes, 'Mainnet'); expect(pkey.toBytes()).to.deep.equal(pkeyFromHex.toBytes()); }); + }); - it('should allow to create PrivateKey from wif and read value in wif', () => { - const pkey = wasm.PrivateKey.fromWIF(wif); - - expect(pkey.WIF()).to.equal(wif); - }); - - it('should allow to create PrivateKey from wif and write value in bytes', () => { + describe('toWIF()', () => { + it('should return key as WIF', () => { const pkey = wasm.PrivateKey.fromWIF(wif); - expect(pkey.toBytes()).to.deep.equal(fromHexString(bytes)); + expect(pkey.toWIF()).to.equal(wif); }); }); - describe('getters', () => { - it('should allow to get key wif', () => { + describe('toBytes()', () => { + it('should return key as bytes', () => { const pkey = wasm.PrivateKey.fromWIF(wif); - expect(pkey.WIF()).to.equal(wif); + expect(pkey.toBytes()).to.deep.equal(fromHexString(bytes)); }); - it('should allow to get key bytes', () => { + it('should return key bytes matching hex string', () => { const pkey = wasm.PrivateKey.fromWIF(wif); expect(toHexString(pkey.toBytes())).to.equal(bytes); }); + }); - it('should allow to get key hex', () => { + describe('toHex()', () => { + it('should return key as hex', () => { const pkey = wasm.PrivateKey.fromWIF(wif); expect(pkey.toHex().toLowerCase()).to.equal(bytes); }); + }); - it('should allow to get public key hash', () => { + describe('getPublicKeyHash()', () => { + it('should return public key hash', () => { const pkey = wasm.PrivateKey.fromWIF(wif); expect(pkey.getPublicKeyHash()).to.deep.equal(publicKeyHash); diff --git a/packages/wasm-dpp2/tests/unit/PublicKeyInCreation.spec.mjs b/packages/wasm-dpp2/tests/unit/PublicKeyInCreation.spec.mjs deleted file mode 100644 index 45dcf5e153a..00000000000 --- a/packages/wasm-dpp2/tests/unit/PublicKeyInCreation.spec.mjs +++ /dev/null @@ -1,303 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('IdentityPublicKeyInCreation', () => { - describe('serialization / deserialization', () => { - it('should allow to create from values', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect(publicKeyInCreation.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create from values and convert to identity public key', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - const publicKey = publicKeyInCreation.toIdentityPublicKey(); - - expect(publicKeyInCreation.__wbg_ptr).to.not.equal(0); - expect(publicKey.constructor.name).to.equal('IdentityPublicKey'); - }); - }); - - describe('getters', () => { - it('should allow to get key id', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect(publicKeyInCreation.keyId).to.equal(0); - }); - - it('should allow to get purpose', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect(publicKeyInCreation.purpose).to.equal('AUTHENTICATION'); - }); - - it('should allow to get security level', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect(publicKeyInCreation.securityLevel).to.equal('MASTER'); - }); - - it('should allow to get key type', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect(publicKeyInCreation.keyType).to.equal('ECDSA_SECP256K1'); - }); - - it('should allow to get read only', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect(publicKeyInCreation.readOnly).to.equal(false); - }); - - it('should allow to get data', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect(Buffer.from(publicKeyInCreation.data)).to.deep.equal(Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex')); - }); - - it('should allow to get signature', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - expect([...publicKeyInCreation.signature]).to.deep.equal([]); - }); - }); - - describe('setters', () => { - it('should allow to set key id', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - publicKeyInCreation.keyId = 123; - - expect(publicKeyInCreation.keyId).to.equal(123); - }); - - it('should allow to set purpose', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - publicKeyInCreation.purpose = 'OWNER'; - - expect(publicKeyInCreation.purpose).to.equal('OWNER'); - }); - - it('should allow to set security level', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - publicKeyInCreation.securityLevel = 'critical'; - - expect(publicKeyInCreation.securityLevel).to.equal('CRITICAL'); - }); - - it('should allow to set key type', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - publicKeyInCreation.keyType = 'ECDSA_HASH160'; - - expect(publicKeyInCreation.keyType).to.equal('ECDSA_HASH160'); - }); - - it('should allow to set read only', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - publicKeyInCreation.readOnly = true; - - expect(publicKeyInCreation.readOnly).to.equal(true); - }); - - it('should allow to set data', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - publicKeyInCreation.data = Buffer.from('333333333334001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'); - - expect(Buffer.from(publicKeyInCreation.data)).to.deep.equal(Buffer.from('333333333334001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex')); - }); - - it('should allow to set signature', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - publicKeyInCreation.signature = [1, 2, 3, 4, 5, 6]; - - expect([...publicKeyInCreation.signature]).to.deep.equal([1, 2, 3, 4, 5, 6]); - }); - }); - - describe('conversion methods', () => { - it('should round-trip via toJSON/fromJSON', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - const json = publicKeyInCreation.toJSON(); - expect(json).to.be.an('object'); - expect(json.id).to.equal(0); - expect(json.purpose).to.equal(0); // AUTHENTICATION = 0 - expect(json.securityLevel).to.equal(0); // MASTER = 0 - expect(json.type).to.equal(0); // ECDSA_SECP256K1 = 0 - expect(json.readOnly).to.equal(false); - - const restored = wasm.IdentityPublicKeyInCreation.fromJSON(json); - expect(restored.keyId).to.equal(publicKeyInCreation.keyId); - expect(restored.purpose).to.equal(publicKeyInCreation.purpose); - expect(restored.securityLevel).to.equal(publicKeyInCreation.securityLevel); - expect(restored.keyType).to.equal(publicKeyInCreation.keyType); - expect(restored.readOnly).to.equal(publicKeyInCreation.readOnly); - }); - - it('should export toObject', () => { - const publicKeyInCreation = new wasm.IdentityPublicKeyInCreation( - 0, - 'AUTHENTICATION', - 'master', - 'ECDSA_SECP256K1', - false, - Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), - [], - ); - - const obj = publicKeyInCreation.toObject(); - // toObject exports with byte arrays which don't round-trip in serde_wasm_bindgen - // but it should at least be defined - expect(obj).to.not.be.undefined; - expect(obj).to.be.an('object'); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/PublicKeyInCreation.spec.ts b/packages/wasm-dpp2/tests/unit/PublicKeyInCreation.spec.ts new file mode 100644 index 00000000000..3a85f325b64 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/PublicKeyInCreation.spec.ts @@ -0,0 +1,195 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +interface PublicKeyInCreationOptions { + keyId?: number; + purpose?: string; + securityLevel?: string; + keyType?: string; + isReadOnly?: boolean; + data?: Uint8Array | Buffer; + signature?: number[]; +} + +describe('IdentityPublicKeyInCreation', () => { + // Helper function to create a public key in creation with options object + function createPublicKeyInCreation(options: PublicKeyInCreationOptions = {}) { + return new wasm.IdentityPublicKeyInCreation({ + keyId: options.keyId ?? 0, + purpose: options.purpose ?? 'AUTHENTICATION', + securityLevel: options.securityLevel ?? 'master', + keyType: options.keyType ?? 'ECDSA_SECP256K1', + isReadOnly: options.isReadOnly ?? false, + data: options.data ?? Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'), + signature: options.signature ?? [], + }); + } + + describe('constructor()', () => { + it('should create from values', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect(publicKeyInCreation).to.be.an.instanceof(wasm.IdentityPublicKeyInCreation); + }); + }); + + describe('toIdentityPublicKey()', () => { + it('should convert to IdentityPublicKey', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + const publicKey = publicKeyInCreation.toIdentityPublicKey(); + + expect(publicKeyInCreation).to.be.an.instanceof(wasm.IdentityPublicKeyInCreation); + expect(publicKey.constructor.name).to.equal('IdentityPublicKey'); + }); + }); + + describe('keyId', () => { + it('should get keyId', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect(publicKeyInCreation.keyId).to.equal(0); + }); + + it('should set keyId', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + publicKeyInCreation.keyId = 123; + + expect(publicKeyInCreation.keyId).to.equal(123); + }); + }); + + describe('purpose', () => { + it('should get purpose', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect(publicKeyInCreation.purpose).to.equal('AUTHENTICATION'); + }); + + it('should set purpose', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + publicKeyInCreation.purpose = 'OWNER'; + + expect(publicKeyInCreation.purpose).to.equal('OWNER'); + }); + }); + + describe('securityLevel', () => { + it('should get securityLevel', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect(publicKeyInCreation.securityLevel).to.equal('MASTER'); + }); + + it('should set securityLevel', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + publicKeyInCreation.securityLevel = 'critical'; + + expect(publicKeyInCreation.securityLevel).to.equal('CRITICAL'); + }); + }); + + describe('keyType', () => { + it('should get keyType', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect(publicKeyInCreation.keyType).to.equal('ECDSA_SECP256K1'); + }); + + it('should set keyType', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + publicKeyInCreation.keyType = 'ECDSA_HASH160'; + + expect(publicKeyInCreation.keyType).to.equal('ECDSA_HASH160'); + }); + }); + + describe('isReadOnly', () => { + it('should get isReadOnly', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect(publicKeyInCreation.isReadOnly).to.equal(false); + }); + + it('should set isReadOnly', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + publicKeyInCreation.isReadOnly = true; + + expect(publicKeyInCreation.isReadOnly).to.equal(true); + }); + }); + + describe('data', () => { + it('should get data', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect(Buffer.from(publicKeyInCreation.data)).to.deep.equal(Buffer.from('0333d5cf3674001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex')); + }); + + it('should set data', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + publicKeyInCreation.data = Buffer.from('333333333334001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex'); + + expect(Buffer.from(publicKeyInCreation.data)).to.deep.equal(Buffer.from('333333333334001d2f64c55617b7b11a2e8fc62aab09708b49355e30c7205bdb2e', 'hex')); + }); + }); + + describe('signature', () => { + it('should get signature', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + expect([...publicKeyInCreation.signature]).to.deep.equal([]); + }); + + it('should set signature', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + publicKeyInCreation.signature = [1, 2, 3, 4, 5, 6]; + + expect([...publicKeyInCreation.signature]).to.deep.equal([1, 2, 3, 4, 5, 6]); + }); + }); + + describe('toJSON()', () => { + it('should convert to JSON and back via fromJSON()', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + const json = publicKeyInCreation.toJSON(); + expect(json).to.be.an('object'); + expect(json.id).to.equal(0); + expect(json.purpose).to.equal(0); // AUTHENTICATION = 0 + expect(json.securityLevel).to.equal(0); // MASTER = 0 + expect(json.type).to.equal(0); // ECDSA_SECP256K1 = 0 + expect(json.readOnly).to.equal(false); + + const restored = wasm.IdentityPublicKeyInCreation.fromJSON(json); + expect(restored.keyId).to.equal(publicKeyInCreation.keyId); + expect(restored.purpose).to.equal(publicKeyInCreation.purpose); + expect(restored.securityLevel).to.equal(publicKeyInCreation.securityLevel); + expect(restored.keyType).to.equal(publicKeyInCreation.keyType); + expect(restored.isReadOnly).to.equal(publicKeyInCreation.isReadOnly); + }); + }); + + describe('toObject()', () => { + it('should export to object', () => { + const publicKeyInCreation = createPublicKeyInCreation(); + + const obj = publicKeyInCreation.toObject(); + // toObject exports with byte arrays which don't round-trip in serde_wasm_bindgen + // but it should at least be defined + expect(obj).to.not.be.undefined(); + expect(obj).to.be.an('object'); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/ResourceVoteChoice.spec.mjs b/packages/wasm-dpp2/tests/unit/ResourceVoteChoice.spec.mjs deleted file mode 100644 index a545a1cef01..00000000000 --- a/packages/wasm-dpp2/tests/unit/ResourceVoteChoice.spec.mjs +++ /dev/null @@ -1,114 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('ResourceVoteChoice', () => { - const identityIdHex = '1111111111111111111111111111111111111111111111111111111111111111'; - - describe('static constructors', () => { - it('should create TowardsIdentity choice', () => { - const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); - const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); - - expect(choice.getType()).to.equal('TowardsIdentity'); - expect(choice.getValue()).to.not.be.undefined; - }); - - it('should create Abstain choice', () => { - const choice = wasm.ResourceVoteChoice.Abstain(); - - expect(choice.getType()).to.equal('Abstain'); - expect(choice.getValue()).to.be.undefined; - }); - - it('should create Lock choice', () => { - const choice = wasm.ResourceVoteChoice.Lock(); - - expect(choice.getType()).to.equal('Lock'); - expect(choice.getValue()).to.be.undefined; - }); - }); - - describe('type properties', () => { - it('should return correct __type', () => { - const choice = wasm.ResourceVoteChoice.Abstain(); - - expect(choice.__type).to.equal('ResourceVoteChoice'); - }); - }); - - describe('conversion methods', () => { - it('should round-trip TowardsIdentity via toJSON/fromJSON', () => { - const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); - const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); - - const json = choice.toJSON(); - expect(json).to.be.an('object'); - - const restored = wasm.ResourceVoteChoice.fromJSON(json); - expect(restored.getType()).to.equal(choice.getType()); - }); - - it('should round-trip Abstain via toJSON/fromJSON', () => { - const choice = wasm.ResourceVoteChoice.Abstain(); - - const json = choice.toJSON(); - // Simple enum variants serialize to strings in serde - expect(json).to.equal('abstain'); - - const restored = wasm.ResourceVoteChoice.fromJSON(json); - expect(restored.getType()).to.equal('Abstain'); - }); - - it('should round-trip Lock via toJSON/fromJSON', () => { - const choice = wasm.ResourceVoteChoice.Lock(); - - const json = choice.toJSON(); - // Simple enum variants serialize to strings in serde - expect(json).to.equal('lock'); - - const restored = wasm.ResourceVoteChoice.fromJSON(json); - expect(restored.getType()).to.equal('Lock'); - }); - - it('should round-trip TowardsIdentity via toObject/fromObject', () => { - const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); - const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); - - const obj = choice.toObject(); - expect(obj).to.be.an('object'); - // Serde serializes enum variants as { variantName: value } with camelCase - expect(obj.towardsIdentity).to.not.be.undefined; - - const restored = wasm.ResourceVoteChoice.fromObject(obj); - expect(restored.getType()).to.equal(choice.getType()); - expect(restored.getValue().toBase58()).to.equal(identityId.toBase58()); - }); - - it('should round-trip Abstain via toObject/fromObject', () => { - const choice = wasm.ResourceVoteChoice.Abstain(); - - const obj = choice.toObject(); - // Simple enum variants serialize to strings in serde - expect(obj).to.equal('abstain'); - - const restored = wasm.ResourceVoteChoice.fromObject(obj); - expect(restored.getType()).to.equal('Abstain'); - }); - - it('should round-trip Lock via toObject/fromObject', () => { - const choice = wasm.ResourceVoteChoice.Lock(); - - const obj = choice.toObject(); - // Simple enum variants serialize to strings in serde - expect(obj).to.equal('lock'); - - const restored = wasm.ResourceVoteChoice.fromObject(obj); - expect(restored.getType()).to.equal('Lock'); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/ResourceVoteChoice.spec.ts b/packages/wasm-dpp2/tests/unit/ResourceVoteChoice.spec.ts new file mode 100644 index 00000000000..c1ea82c0927 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/ResourceVoteChoice.spec.ts @@ -0,0 +1,176 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('ResourceVoteChoice', () => { + const identityIdHex = '1111111111111111111111111111111111111111111111111111111111111111'; + + describe('TowardsIdentity()', () => { + it('should create TowardsIdentity choice', () => { + const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); + const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); + + expect(choice.voteType).to.equal('TowardsIdentity'); + expect(choice.value).to.not.be.undefined(); + }); + }); + + describe('Abstain()', () => { + it('should create Abstain choice', () => { + const choice = wasm.ResourceVoteChoice.Abstain(); + + expect(choice.voteType).to.equal('Abstain'); + expect(choice.value).to.be.undefined(); + }); + }); + + describe('Lock()', () => { + it('should create Lock choice', () => { + const choice = wasm.ResourceVoteChoice.Lock(); + + expect(choice.voteType).to.equal('Lock'); + expect(choice.value).to.be.undefined(); + }); + }); + + describe('__type', () => { + it('should return correct __type', () => { + const choice = wasm.ResourceVoteChoice.Abstain(); + + expect(choice.__type).to.equal('ResourceVoteChoice'); + }); + }); + + describe('voteType', () => { + it('should return TowardsIdentity for TowardsIdentity choice', () => { + const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); + const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); + + expect(choice.voteType).to.equal('TowardsIdentity'); + }); + + it('should return Abstain for Abstain choice', () => { + const choice = wasm.ResourceVoteChoice.Abstain(); + + expect(choice.voteType).to.equal('Abstain'); + }); + + it('should return Lock for Lock choice', () => { + const choice = wasm.ResourceVoteChoice.Lock(); + + expect(choice.voteType).to.equal('Lock'); + }); + }); + + describe('toJSON()', () => { + it('should serialize TowardsIdentity to JSON object', () => { + const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); + const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); + + const json = choice.toJSON(); + expect(json).to.be.an('object'); + }); + + it('should serialize Abstain to JSON string', () => { + const choice = wasm.ResourceVoteChoice.Abstain(); + + const json = choice.toJSON(); + // Simple enum variants serialize to strings in serde + expect(json).to.equal('abstain'); + }); + + it('should serialize Lock to JSON string', () => { + const choice = wasm.ResourceVoteChoice.Lock(); + + const json = choice.toJSON(); + // Simple enum variants serialize to strings in serde + expect(json).to.equal('lock'); + }); + }); + + describe('fromJSON()', () => { + it('should deserialize TowardsIdentity from JSON', () => { + const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); + const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); + + const json = choice.toJSON(); + const restored = wasm.ResourceVoteChoice.fromJSON(json); + expect(restored.voteType).to.equal(choice.voteType); + }); + + it('should deserialize Abstain from JSON', () => { + const choice = wasm.ResourceVoteChoice.Abstain(); + + const json = choice.toJSON(); + const restored = wasm.ResourceVoteChoice.fromJSON(json); + expect(restored.voteType).to.equal('Abstain'); + }); + + it('should deserialize Lock from JSON', () => { + const choice = wasm.ResourceVoteChoice.Lock(); + + const json = choice.toJSON(); + const restored = wasm.ResourceVoteChoice.fromJSON(json); + expect(restored.voteType).to.equal('Lock'); + }); + }); + + describe('toObject()', () => { + it('should serialize TowardsIdentity to object', () => { + const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); + const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); + + const obj = choice.toObject(); + expect(obj).to.be.an('object'); + // Serde serializes enum variants as { variantName: value } with camelCase + expect(obj.towardsIdentity).to.not.be.undefined(); + }); + + it('should serialize Abstain to object string', () => { + const choice = wasm.ResourceVoteChoice.Abstain(); + + const obj = choice.toObject(); + // Simple enum variants serialize to strings in serde + expect(obj).to.equal('abstain'); + }); + + it('should serialize Lock to object string', () => { + const choice = wasm.ResourceVoteChoice.Lock(); + + const obj = choice.toObject(); + // Simple enum variants serialize to strings in serde + expect(obj).to.equal('lock'); + }); + }); + + describe('fromObject()', () => { + it('should deserialize TowardsIdentity from object', () => { + const identityId = wasm.Identifier.fromBytes(Buffer.from(identityIdHex, 'hex')); + const choice = wasm.ResourceVoteChoice.TowardsIdentity(identityId); + + const obj = choice.toObject(); + const restored = wasm.ResourceVoteChoice.fromObject(obj); + expect(restored.voteType).to.equal(choice.voteType); + expect(restored.value.toBase58()).to.equal(identityId.toBase58()); + }); + + it('should deserialize Abstain from object', () => { + const choice = wasm.ResourceVoteChoice.Abstain(); + + const obj = choice.toObject(); + const restored = wasm.ResourceVoteChoice.fromObject(obj); + expect(restored.voteType).to.equal('Abstain'); + }); + + it('should deserialize Lock from object', () => { + const choice = wasm.ResourceVoteChoice.Lock(); + + const obj = choice.toObject(); + const restored = wasm.ResourceVoteChoice.fromObject(obj); + expect(restored.voteType).to.equal('Lock'); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/RewardDistributionType.spec.mjs b/packages/wasm-dpp2/tests/unit/RewardDistributionType.spec.mjs deleted file mode 100644 index b481e9e6efd..00000000000 --- a/packages/wasm-dpp2/tests/unit/RewardDistributionType.spec.mjs +++ /dev/null @@ -1,94 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('RewardDistributionType', () => { - describe('serialization / deserialization', () => { - it('should allow to create BlockBasedDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( - BigInt(111), - distributionFunction, - ); - - expect(distributionFunction.__wbg_ptr).to.not.equal(0); - expect(distributionType.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create TimeBasedDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.TimeBasedDistribution( - BigInt(111), - distributionFunction, - ); - - expect(distributionFunction.__wbg_ptr).to.not.equal(0); - expect(distributionType.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create EpochBasedDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.EpochBasedDistribution( - 111, - distributionFunction, - ); - - expect(distributionFunction.__wbg_ptr).to.not.equal(0); - expect(distributionType.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow return value BlockBasedDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( - BigInt(111), - distributionFunction, - ); - - expect(distributionType.getDistribution().constructor.name).to.equal('BlockBasedDistribution'); - }); - - it('should allow return value TimeBasedDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.TimeBasedDistribution( - BigInt(111), - distributionFunction, - ); - - expect(distributionType.getDistribution().constructor.name).to.equal('TimeBasedDistribution'); - }); - - it('should allow return value EpochBasedDistribution', () => { - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.EpochBasedDistribution( - 111, - distributionFunction, - ); - - expect(distributionType.getDistribution().constructor.name).to.equal('EpochBasedDistribution'); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/RewardDistributionType.spec.ts b/packages/wasm-dpp2/tests/unit/RewardDistributionType.spec.ts new file mode 100644 index 00000000000..35338cc79ef --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/RewardDistributionType.spec.ts @@ -0,0 +1,97 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('RewardDistributionType', () => { + describe('BlockBasedDistribution()', () => { + it('should create BlockBasedDistribution', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( + BigInt(111), + distributionFunction, + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + expect(distributionType).to.be.an.instanceof(wasm.RewardDistributionType); + }); + }); + + describe('TimeBasedDistribution()', () => { + it('should create TimeBasedDistribution', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + const distributionType = wasm.RewardDistributionType.TimeBasedDistribution( + BigInt(111), + distributionFunction, + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + expect(distributionType).to.be.an.instanceof(wasm.RewardDistributionType); + }); + }); + + describe('EpochBasedDistribution()', () => { + it('should create EpochBasedDistribution', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + const distributionType = wasm.RewardDistributionType.EpochBasedDistribution( + 111, + distributionFunction, + ); + + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + expect(distributionType).to.be.an.instanceof(wasm.RewardDistributionType); + }); + }); + + describe('distribution', () => { + it('should return BlockBasedDistribution for block-based type', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( + BigInt(111), + distributionFunction, + ); + + expect(distributionType.distribution.constructor.name).to.equal('BlockBasedDistribution'); + }); + + it('should return TimeBasedDistribution for time-based type', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + const distributionType = wasm.RewardDistributionType.TimeBasedDistribution( + BigInt(111), + distributionFunction, + ); + + expect(distributionType.distribution.constructor.name).to.equal('TimeBasedDistribution'); + }); + + it('should return EpochBasedDistribution for epoch-based type', () => { + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + const distributionType = wasm.RewardDistributionType.EpochBasedDistribution( + 111, + distributionFunction, + ); + + expect(distributionType.distribution.constructor.name).to.equal('EpochBasedDistribution'); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/TokenBaseTransition.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenBaseTransition.spec.mjs deleted file mode 100644 index 5728ab4030c..00000000000 --- a/packages/wasm-dpp2/tests/unit/TokenBaseTransition.spec.mjs +++ /dev/null @@ -1,100 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { dataContractId, ownerId } from './mocks/Document/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('TokenBaseTransition', function () { - describe('serialization / deserialization', function () { - it('should allow to create from values', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - expect(baseTransition.__wbg_ptr).to.not.equal(0) - }) - }) - - describe('getters', function () { - it('should allow to get identityContractNonce', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - expect(baseTransition.identityContractNonce).to.deep.equal(1n) - }) - - it('should allow to get tokenContractPosition', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - expect(baseTransition.tokenContractPosition).to.deep.equal(1) - }) - - it('should allow to get dataContractId', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - expect(baseTransition.dataContractId.toBase58()).to.deep.equal(dataContractId) - }) - - it('should allow to get tokenId', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - expect(baseTransition.tokenId.toBase58()).to.deep.equal(ownerId) - }) - - it('should allow to get usingGroupInfo', () => { - const groupStInfo = new wasm.GroupStateTransitionInfo(2, dataContractId, false) - - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId, groupStInfo) - - expect(groupStInfo.__wbg_ptr).to.not.equal(0) - expect(baseTransition.usingGroupInfo.constructor.name).to.deep.equal('GroupStateTransitionInfo') - }) - }) - - describe('setters', function () { - it('should allow to set identityContractNonce', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - baseTransition.identityContractNonce = 3n - - expect(baseTransition.identityContractNonce).to.deep.equal(3n) - }) - - it('should allow to set tokenContractPosition', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - baseTransition.tokenContractPosition = 3 - - expect(baseTransition.tokenContractPosition).to.deep.equal(3) - }) - - it('should allow to set dataContractId', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - baseTransition.dataContractId = ownerId - - expect(baseTransition.dataContractId.toBase58()).to.deep.equal(ownerId) - }) - - it('should allow to set tokenId', () => { - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - baseTransition.tokenId = dataContractId - - expect(baseTransition.tokenId.toBase58()).to.deep.equal(dataContractId) - }) - - it('should allow to set usingGroupInfo', () => { - const groupStInfo = new wasm.GroupStateTransitionInfo(2, dataContractId, false) - - const baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId) - - expect(baseTransition.usingGroupInfo).to.deep.equal(undefined) - - baseTransition.usingGroupInfo = groupStInfo - - expect(groupStInfo.__wbg_ptr).to.not.equal(0) - expect(baseTransition.usingGroupInfo.constructor.name).to.deep.equal('GroupStateTransitionInfo') - }) - }) -}) diff --git a/packages/wasm-dpp2/tests/unit/TokenBaseTransition.spec.ts b/packages/wasm-dpp2/tests/unit/TokenBaseTransition.spec.ts new file mode 100644 index 00000000000..e9530f617cd --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/TokenBaseTransition.spec.ts @@ -0,0 +1,131 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { dataContractId, ownerId } from './mocks/Document/index.js'; + +before(async () => { + await initWasm(); +}); + +interface BaseTransitionOptions { + identityContractNonce?: bigint; + tokenContractPosition?: number; + dataContractId?: string; + tokenId?: string; + usingGroupInfo?: unknown; +} + +describe('TokenBaseTransition', () => { + function createBaseTransition(options: BaseTransitionOptions = {}) { + return new wasm.TokenBaseTransition({ + identityContractNonce: options.identityContractNonce ?? BigInt(1), + tokenContractPosition: options.tokenContractPosition ?? 1, + dataContractId: options.dataContractId ?? dataContractId, + tokenId: options.tokenId ?? ownerId, + usingGroupInfo: options.usingGroupInfo, + }); + } + + describe('constructor', () => { + it('should create instance from values', () => { + const baseTransition = createBaseTransition(); + + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('identityContractNonce', () => { + it('should return identityContractNonce', () => { + const baseTransition = createBaseTransition(); + + expect(baseTransition.identityContractNonce).to.deep.equal(1n); + }); + + it('should set identityContractNonce', () => { + const baseTransition = createBaseTransition(); + + baseTransition.identityContractNonce = 3n; + + expect(baseTransition.identityContractNonce).to.deep.equal(3n); + }); + }); + + describe('tokenContractPosition', () => { + it('should return tokenContractPosition', () => { + const baseTransition = createBaseTransition(); + + expect(baseTransition.tokenContractPosition).to.deep.equal(1); + }); + + it('should set tokenContractPosition', () => { + const baseTransition = createBaseTransition(); + + baseTransition.tokenContractPosition = 3; + + expect(baseTransition.tokenContractPosition).to.deep.equal(3); + }); + }); + + describe('dataContractId', () => { + it('should return dataContractId', () => { + const baseTransition = createBaseTransition(); + + expect(baseTransition.dataContractId.toBase58()).to.deep.equal(dataContractId); + }); + + it('should set dataContractId', () => { + const baseTransition = createBaseTransition(); + + baseTransition.dataContractId = ownerId; + + expect(baseTransition.dataContractId.toBase58()).to.deep.equal(ownerId); + }); + }); + + describe('tokenId', () => { + it('should return tokenId', () => { + const baseTransition = createBaseTransition(); + + expect(baseTransition.tokenId.toBase58()).to.deep.equal(ownerId); + }); + + it('should set tokenId', () => { + const baseTransition = createBaseTransition(); + + baseTransition.tokenId = dataContractId; + + expect(baseTransition.tokenId.toBase58()).to.deep.equal(dataContractId); + }); + }); + + describe('usingGroupInfo', () => { + it('should return usingGroupInfo', () => { + const groupStInfo = new wasm.GroupStateTransitionInfo({ + groupContractPosition: 2, + actionId: dataContractId, + isActionProposer: false, + }); + + const baseTransition = createBaseTransition({ usingGroupInfo: groupStInfo }); + + expect(groupStInfo).to.be.an.instanceof(wasm.GroupStateTransitionInfo); + expect(baseTransition.usingGroupInfo.constructor.name).to.deep.equal('GroupStateTransitionInfo'); + }); + + it('should set usingGroupInfo', () => { + const groupStInfo = new wasm.GroupStateTransitionInfo({ + groupContractPosition: 2, + actionId: dataContractId, + isActionProposer: false, + }); + + const baseTransition = createBaseTransition(); + + expect(baseTransition.usingGroupInfo).to.deep.equal(undefined); + + baseTransition.usingGroupInfo = groupStInfo; + + expect(groupStInfo).to.be.an.instanceof(wasm.GroupStateTransitionInfo); + expect(baseTransition.usingGroupInfo.constructor.name).to.deep.equal('GroupStateTransitionInfo'); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/TokenConfiguration.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenConfiguration.spec.mjs deleted file mode 100644 index 5ece4fccd22..00000000000 --- a/packages/wasm-dpp2/tests/unit/TokenConfiguration.spec.mjs +++ /dev/null @@ -1,196 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('TokenConfiguration', () => { - describe('serialization / deserialization', () => { - it('Should allow to create from values', () => { - const convention = new wasm.TokenConfigurationConvention( - { - ru: { - $format_version: '0', - shouldCapitalize: true, - singularForm: 'TOKEN', - pluralForm: 'TOKENS', - }, - }, - 1, - ); - - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - const keepHistory = new wasm.TokenKeepsHistoryRules( - true, - true, - true, - true, - true, - true, - ); - - const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10000), - }, - }, - ); - - const distributionRules = new wasm.TokenDistributionRules( - undefined, - changeRules, - preProgrammedDistribution, - undefined, - changeRules, - true, - changeRules, - changeRules, - ); - - const tradeMode = wasm.TokenTradeMode.NotTradeable(); - - const marketplaceRules = new wasm.TokenMarketplaceRules( - tradeMode, - changeRules, - ); - - const config = new wasm.TokenConfiguration( - convention, - changeRules, - BigInt(999999999), - undefined, - keepHistory, - false, - false, - changeRules, - distributionRules, - marketplaceRules, - changeRules, - changeRules, - changeRules, - changeRules, - changeRules, - changeRules, - undefined, - noOne, - 'note', - ); - - expect(config.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to get getters', () => { - const convention = new wasm.TokenConfigurationConvention( - { - ru: { - $format_version: '0', - shouldCapitalize: true, - singularForm: 'TOKEN', - pluralForm: 'TOKENS', - }, - }, - 1, - ); - - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - const keepHistory = new wasm.TokenKeepsHistoryRules( - true, - true, - true, - true, - true, - true, - ); - - const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10000), - }, - }, - ); - - const distributionRules = new wasm.TokenDistributionRules( - undefined, - changeRules, - preProgrammedDistribution, - undefined, - changeRules, - true, - changeRules, - changeRules, - ); - - const tradeMode = wasm.TokenTradeMode.NotTradeable(); - - const marketplaceRules = new wasm.TokenMarketplaceRules( - tradeMode, - changeRules, - ); - - const config = new wasm.TokenConfiguration( - convention, - changeRules, - BigInt(999999999), - undefined, - keepHistory, - false, - false, - changeRules, - distributionRules, - marketplaceRules, - changeRules, - changeRules, - changeRules, - changeRules, - changeRules, - changeRules, - undefined, - noOne, - 'note', - ); - - expect(config.conventions.constructor.name).to.equal('TokenConfigurationConvention'); - expect(config.conventionsChangeRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.baseSupply.constructor.name).to.equal('BigInt'); - expect(config.keepsHistory.constructor.name).to.equal('TokenKeepsHistoryRules'); - expect(config.startAsPaused.constructor.name).to.equal('Boolean'); - expect(config.isAllowedTransferToFrozenBalance.constructor.name).to.equal('Boolean'); - expect(config.maxSupply).to.equal(undefined); - expect(config.maxSupplyChangeRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.distributionRules.constructor.name).to.equal('TokenDistributionRules'); - expect(config.marketplaceRules.constructor.name).to.equal('TokenMarketplaceRules'); - expect(config.manualMintingRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.manualBurningRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.freezeRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.unfreezeRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.destroyFrozenFundsRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.emergencyActionRules.constructor.name).to.equal('ChangeControlRules'); - expect(config.mainControlGroup).to.equal(undefined); - expect(config.description.constructor.name).to.equal('String'); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/TokenConfiguration.spec.ts b/packages/wasm-dpp2/tests/unit/TokenConfiguration.spec.ts new file mode 100644 index 00000000000..32cd7e5b568 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/TokenConfiguration.spec.ts @@ -0,0 +1,206 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +interface ChangeControlRulesOptions { + authorizedToMakeChange?: unknown; + adminActionTakers?: unknown; + isChangingAuthorizedActionTakersToNoOneAllowed?: boolean; + isChangingAdminActionTakersToNoOneAllowed?: boolean; + isSelfChangingAdminActionTakersAllowed?: boolean; +} + +interface KeepsHistoryRulesOptions { + isKeepingTransferHistory?: boolean; + isKeepingFreezingHistory?: boolean; + isKeepingMintingHistory?: boolean; + isKeepingBurningHistory?: boolean; + isKeepingDestroyedFrozenFundsHistory?: boolean; + isKeepingEmergencyActionHistory?: boolean; +} + +describe('TokenConfiguration', () => { + function createChangeControlRules(options: ChangeControlRulesOptions = {}) { + // AuthorizedActionTakers defaults to NoOne if not specified + const noOne = wasm.AuthorizedActionTakers.NoOne(); + return new wasm.ChangeControlRules({ + authorizedToMakeChange: options.authorizedToMakeChange ?? noOne, + adminActionTakers: options.adminActionTakers ?? noOne, + isChangingAuthorizedActionTakersToNoOneAllowed: options.isChangingAuthorizedActionTakersToNoOneAllowed ?? true, + isChangingAdminActionTakersToNoOneAllowed: options.isChangingAdminActionTakersToNoOneAllowed ?? true, + isSelfChangingAdminActionTakersAllowed: options.isSelfChangingAdminActionTakersAllowed ?? true, + }); + } + function createKeepsHistoryRules(options: KeepsHistoryRulesOptions = {}) { + return new wasm.TokenKeepsHistoryRules({ + isKeepingTransferHistory: options.isKeepingTransferHistory ?? true, + isKeepingFreezingHistory: options.isKeepingFreezingHistory ?? true, + isKeepingMintingHistory: options.isKeepingMintingHistory ?? true, + isKeepingBurningHistory: options.isKeepingBurningHistory ?? true, + isKeepingDestroyedFrozenFundsHistory: options.isKeepingDestroyedFrozenFundsHistory ?? true, + isKeepingEmergencyActionHistory: options.isKeepingEmergencyActionHistory ?? true, + }); + } + function createPreProgrammedDistribution(timestamp: number, identifierBase58: string, amount: bigint) { + const identifier = new wasm.Identifier(identifierBase58); + const innerMap = new Map(); + innerMap.set(identifier, amount); + const outerMap = new Map(); + outerMap.set(timestamp.toString(), innerMap); + return new wasm.TokenPreProgrammedDistribution(outerMap); + } + + describe('constructor', () => { + it('should create instance from values', () => { + const convention = new wasm.TokenConfigurationConvention( + { + ru: { + $format_version: '0', + shouldCapitalize: true, + singularForm: 'TOKEN', + pluralForm: 'TOKENS', + }, + }, + 1, + ); + + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(); + const keepHistory = createKeepsHistoryRules(); + + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution: undefined, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + const tradeMode = wasm.TokenTradeMode.NotTradeable(); + + const marketplaceRules = new wasm.TokenMarketplaceRules( + tradeMode, + changeRules, + ); + + const config = new wasm.TokenConfiguration({ + conventions: convention, + conventionsChangeRules: changeRules, + baseSupply: BigInt(999999999), + maxSupply: undefined, + keepsHistory: keepHistory, + isStartedAsPaused: false, + isAllowedTransferToFrozenBalance: false, + maxSupplyChangeRules: changeRules, + distributionRules, + marketplaceRules, + manualMintingRules: changeRules, + manualBurningRules: changeRules, + freezeRules: changeRules, + unfreezeRules: changeRules, + destroyFrozenFundsRules: changeRules, + emergencyActionRules: changeRules, + mainControlGroup: undefined, + mainControlGroupCanBeModified: noOne, + description: 'note', + }); + + expect(config).to.be.an.instanceof(wasm.TokenConfiguration); + }); + }); + + describe('conventions', () => { + it('should return conventions', () => { + const convention = new wasm.TokenConfigurationConvention( + { + ru: { + $format_version: '0', + shouldCapitalize: true, + singularForm: 'TOKEN', + pluralForm: 'TOKENS', + }, + }, + 1, + ); + + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(); + const keepHistory = createKeepsHistoryRules(); + + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution: undefined, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + const tradeMode = wasm.TokenTradeMode.NotTradeable(); + + const marketplaceRules = new wasm.TokenMarketplaceRules( + tradeMode, + changeRules, + ); + + const config = new wasm.TokenConfiguration({ + conventions: convention, + conventionsChangeRules: changeRules, + baseSupply: BigInt(999999999), + maxSupply: undefined, + keepsHistory: keepHistory, + isStartedAsPaused: false, + isAllowedTransferToFrozenBalance: false, + maxSupplyChangeRules: changeRules, + distributionRules, + marketplaceRules, + manualMintingRules: changeRules, + manualBurningRules: changeRules, + freezeRules: changeRules, + unfreezeRules: changeRules, + destroyFrozenFundsRules: changeRules, + emergencyActionRules: changeRules, + mainControlGroup: undefined, + mainControlGroupCanBeModified: noOne, + description: 'note', + }); + + expect(config.conventions.constructor.name).to.equal('TokenConfigurationConvention'); + expect(config.conventionsChangeRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.baseSupply.constructor.name).to.equal('BigInt'); + expect(config.keepsHistory.constructor.name).to.equal('TokenKeepsHistoryRules'); + expect(config.isStartedAsPaused.constructor.name).to.equal('Boolean'); + expect(config.isAllowedTransferToFrozenBalance.constructor.name).to.equal('Boolean'); + expect(config.maxSupply).to.equal(undefined); + expect(config.maxSupplyChangeRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.distributionRules.constructor.name).to.equal('TokenDistributionRules'); + expect(config.marketplaceRules.constructor.name).to.equal('TokenMarketplaceRules'); + expect(config.manualMintingRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.manualBurningRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.freezeRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.unfreezeRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.destroyFrozenFundsRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.emergencyActionRules.constructor.name).to.equal('ChangeControlRules'); + expect(config.mainControlGroup).to.equal(undefined); + expect(config.description.constructor.name).to.equal('String'); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/TokenConfigurationConvention.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenConfigurationConvention.spec.ts similarity index 74% rename from packages/wasm-dpp2/tests/unit/TokenConfigurationConvention.spec.mjs rename to packages/wasm-dpp2/tests/unit/TokenConfigurationConvention.spec.ts index 60766ba9925..18cb8a52a6e 100644 --- a/packages/wasm-dpp2/tests/unit/TokenConfigurationConvention.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/TokenConfigurationConvention.spec.ts @@ -1,15 +1,14 @@ -import getWasm from './helpers/wasm.js'; -import { tokenLocalization } from './mocks/TokenConfiguration/index.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import tokenLocalization from './mocks/TokenConfiguration/index.ts'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('TokenConfigurationConvention', () => { - describe('serialization / deserialization', () => { - it('Should allow to create from object', () => { + describe('constructor', () => { + it('should create instance from object', () => { const convention = new wasm.TokenConfigurationConvention( { ru: tokenLocalization, @@ -17,12 +16,12 @@ describe('TokenConfigurationConvention', () => { 1, ); - expect(convention.__wbg_ptr).to.not.equal(0); + expect(convention).to.be.an.instanceof(wasm.TokenConfigurationConvention); }); }); - describe('getters', () => { - it('Should allow to get object of convention in JSON', () => { + describe('localizations', () => { + it('should return localizations as JSON', () => { const convention = new wasm.TokenConfigurationConvention( { ru: tokenLocalization, @@ -33,7 +32,7 @@ describe('TokenConfigurationConvention', () => { expect(convention.localizations.ru.toJSON()).to.deep.equal(tokenLocalization); }); - it('Should allow to get object of convention in wasm instance', () => { + it('should return localizations as wasm instance', () => { const convention = new wasm.TokenConfigurationConvention( { ru: tokenLocalization, @@ -45,20 +44,7 @@ describe('TokenConfigurationConvention', () => { expect(convention.localizations.ru.constructor.name).to.deep.equal('TokenConfigurationLocalization'); }); - it('Should allow to get decimals', () => { - const convention = new wasm.TokenConfigurationConvention( - { - ru: tokenLocalization, - }, - 1, - ); - - expect(convention.decimals).to.deep.equal(1); - }); - }); - - describe('setters', () => { - it('Should allow to set localizations object ', () => { + it('should set localizations object', () => { const convention = new wasm.TokenConfigurationConvention( { ru: tokenLocalization, @@ -75,7 +61,7 @@ describe('TokenConfigurationConvention', () => { expect(convention.localizations.en.constructor.name).to.deep.equal('TokenConfigurationLocalization'); }); - it('Should allow to set localizations object with wasm ', () => { + it('should set localizations object with wasm instance', () => { const convention = new wasm.TokenConfigurationConvention( { ru: tokenLocalization, @@ -98,7 +84,20 @@ describe('TokenConfigurationConvention', () => { singularForm: 'singularForm', pluralForm: 'pluralForm', }); - expect(localization.__wbg_ptr).to.not.equal(0); + expect(localization).to.be.an.instanceof(wasm.TokenConfigurationLocalization); + }); + }); + + describe('decimals', () => { + it('should return decimals', () => { + const convention = new wasm.TokenConfigurationConvention( + { + ru: tokenLocalization, + }, + 1, + ); + + expect(convention.decimals).to.deep.equal(1); }); }); }); diff --git a/packages/wasm-dpp2/tests/unit/TokenConfigurationLocalization.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenConfigurationLocalization.spec.ts similarity index 61% rename from packages/wasm-dpp2/tests/unit/TokenConfigurationLocalization.spec.mjs rename to packages/wasm-dpp2/tests/unit/TokenConfigurationLocalization.spec.ts index 6ae96277d11..ba0f758ab0b 100644 --- a/packages/wasm-dpp2/tests/unit/TokenConfigurationLocalization.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/TokenConfigurationLocalization.spec.ts @@ -1,20 +1,35 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('TokenConfigurationLocalization', () => { - describe('serialization / deserialization', () => { - it('should allow to create from values', () => { + describe('constructor', () => { + it('should create instance from values', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); - expect(localization.__wbg_ptr).to.not.equal(0); + expect(localization).to.be.an.instanceof(wasm.TokenConfigurationLocalization); }); + }); - it('should recreate localization from JSON', () => { + describe('toJSON()', () => { + it('should convert to JSON', () => { + const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); + const json = localization.toJSON(); + + expect(json).to.deep.equal({ + $format_version: '0', + shouldCapitalize: false, + singularForm: 'singularForm', + pluralForm: 'pluralForm', + }); + }); + }); + + describe('fromJSON()', () => { + it('should create instance from JSON', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); const json = localization.toJSON(); @@ -22,8 +37,10 @@ describe('TokenConfigurationLocalization', () => { expect(restored.toJSON()).to.deep.equal(json); }); + }); - it('should recreate localization from object', () => { + describe('fromObject()', () => { + it('should create instance from object', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); const object = localization.toJSON(); @@ -33,44 +50,46 @@ describe('TokenConfigurationLocalization', () => { }); }); - describe('getters', () => { - it('should allow to get shouldCapitalize', () => { + describe('shouldCapitalize', () => { + it('should return shouldCapitalize', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); expect(localization.shouldCapitalize).to.equal(false); }); - it('should allow to get pluralForm', () => { + it('should set shouldCapitalize', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); - expect(localization.pluralForm).to.equal('pluralForm'); - }); - - it('should allow to get singularForm', () => { - const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); + localization.shouldCapitalize = true; - expect(localization.singularForm).to.equal('singularForm'); + expect(localization.shouldCapitalize).to.equal(true); }); }); - describe('setters', () => { - it('should allow to set shouldCapitalize', () => { + describe('pluralForm', () => { + it('should return pluralForm', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); - localization.shouldCapitalize = true; - - expect(localization.shouldCapitalize).to.equal(true); + expect(localization.pluralForm).to.equal('pluralForm'); }); - it('should allow to set pluralForm', () => { + it('should set pluralForm', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); localization.pluralForm = 'pluralForm1212'; expect(localization.pluralForm).to.equal('pluralForm1212'); }); + }); + + describe('singularForm', () => { + it('should return singularForm', () => { + const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); + + expect(localization.singularForm).to.equal('singularForm'); + }); - it('should allow to set singularForm', () => { + it('should set singularForm', () => { const localization = new wasm.TokenConfigurationLocalization(false, 'singularForm', 'pluralForm'); localization.singularForm = 'singularForm12121'; diff --git a/packages/wasm-dpp2/tests/unit/TokenDistributionRecipient.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenDistributionRecipient.spec.mjs deleted file mode 100644 index 5674cbacc87..00000000000 --- a/packages/wasm-dpp2/tests/unit/TokenDistributionRecipient.spec.mjs +++ /dev/null @@ -1,53 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { identifier } from './mocks/Identity/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('TokenDistributionRecipient', () => { - describe('serialization / deserialization', () => { - it('should allow to create from values ContractOwner', () => { - const recipient = wasm.TokenDistributionRecipient.ContractOwner(); - - expect(recipient.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create from values Identity', () => { - const recipient = wasm.TokenDistributionRecipient.Identity(identifier); - - expect(recipient.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create from values EvonodesByParticipation', () => { - const recipient = wasm.TokenDistributionRecipient.EvonodesByParticipation(); - - expect(recipient.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to get values ContractOwner', () => { - const recipient = wasm.TokenDistributionRecipient.ContractOwner(); - - expect(recipient.getType()).to.equal('ContractOwner'); - expect(recipient.getValue()).to.equal(undefined); - }); - - it('should allow to get values Identity', () => { - const recipient = wasm.TokenDistributionRecipient.Identity(identifier); - - expect(recipient.getType()).to.equal(`Identity(${identifier})`); - expect(recipient.getValue().toBase58()).to.equal(identifier); - }); - - it('should allow to get values EvonodesByParticipation', () => { - const recipient = wasm.TokenDistributionRecipient.EvonodesByParticipation(); - - expect(recipient.getType()).to.equal('EvonodesByParticipation'); - expect(recipient.getValue()).to.equal(undefined); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/TokenDistributionRecipient.spec.ts b/packages/wasm-dpp2/tests/unit/TokenDistributionRecipient.spec.ts new file mode 100644 index 00000000000..9f5f5468609 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/TokenDistributionRecipient.spec.ts @@ -0,0 +1,73 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { identifier } from './mocks/Identity/index.js'; + +before(async () => { + await initWasm(); +}); + +describe('TokenDistributionRecipient', () => { + describe('ContractOwner()', () => { + it('should create ContractOwner recipient', () => { + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + + expect(recipient).to.be.an.instanceof(wasm.TokenDistributionRecipient); + }); + }); + + describe('Identity()', () => { + it('should create Identity recipient', () => { + const recipient = wasm.TokenDistributionRecipient.Identity(identifier); + + expect(recipient).to.be.an.instanceof(wasm.TokenDistributionRecipient); + }); + }); + + describe('EvonodesByParticipation()', () => { + it('should create EvonodesByParticipation recipient', () => { + const recipient = wasm.TokenDistributionRecipient.EvonodesByParticipation(); + + expect(recipient).to.be.an.instanceof(wasm.TokenDistributionRecipient); + }); + }); + + describe('recipientType', () => { + it('should return ContractOwner for ContractOwner recipient', () => { + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + + expect(recipient.recipientType).to.equal('ContractOwner'); + }); + + it('should return Identity type for Identity recipient', () => { + const recipient = wasm.TokenDistributionRecipient.Identity(identifier); + + expect(recipient.recipientType).to.equal(`Identity(${identifier})`); + }); + + it('should return EvonodesByParticipation for EvonodesByParticipation recipient', () => { + const recipient = wasm.TokenDistributionRecipient.EvonodesByParticipation(); + + expect(recipient.recipientType).to.equal('EvonodesByParticipation'); + }); + }); + + describe('value', () => { + it('should return undefined for ContractOwner recipient', () => { + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + + expect(recipient.value).to.equal(undefined); + }); + + it('should return identifier for Identity recipient', () => { + const recipient = wasm.TokenDistributionRecipient.Identity(identifier); + + expect(recipient.value.toBase58()).to.equal(identifier); + }); + + it('should return undefined for EvonodesByParticipation recipient', () => { + const recipient = wasm.TokenDistributionRecipient.EvonodesByParticipation(); + + expect(recipient.value).to.equal(undefined); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/TokenDistributionRules.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenDistributionRules.spec.mjs deleted file mode 100644 index af70551feae..00000000000 --- a/packages/wasm-dpp2/tests/unit/TokenDistributionRules.spec.mjs +++ /dev/null @@ -1,317 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { identifier } from './mocks/Identity/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('TokenDistributionRules', () => { - describe('serialization / deserialization', () => { - it('should allow to create with undefined values', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - const distributionRules = new wasm.TokenDistributionRules( - undefined, - changeRules, - undefined, - undefined, - changeRules, - true, - changeRules, - changeRules, - ); - - expect(distributionRules.__wbg_ptr).to.not.equal(0); - expect(changeRules.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create without undefined values', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10000), - }, - }, - ); - - const recipient = wasm.TokenDistributionRecipient.ContractOwner(); - - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( - BigInt(111), - distributionFunction, - ); - - const perpetualDistribution = new wasm.TokenPerpetualDistribution( - distributionType, - recipient, - ); - - const distributionRules = new wasm.TokenDistributionRules( - perpetualDistribution, - changeRules, - preProgrammedDistribution, - identifier, - changeRules, - true, - changeRules, - changeRules, - ); - - expect(distributionRules.__wbg_ptr).to.not.equal(0); - expect(perpetualDistribution.__wbg_ptr).to.not.equal(0); - expect(preProgrammedDistribution.__wbg_ptr).to.not.equal(0); - expect(changeRules.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to get values', () => { - const noOne = wasm.AuthorizedActionTakers.NoOne(); - - const changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - - const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10000), - }, - }, - ); - - const recipient = wasm.TokenDistributionRecipient.ContractOwner(); - - const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - - const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( - BigInt(111), - distributionFunction, - ); - - const perpetualDistribution = new wasm.TokenPerpetualDistribution( - distributionType, - recipient, - ); - - const distributionRules = new wasm.TokenDistributionRules( - perpetualDistribution, - changeRules, - preProgrammedDistribution, - identifier, - changeRules, - true, - changeRules, - changeRules, - ); - - expect(distributionRules.perpetualDistribution.constructor.name).to.deep.equal('TokenPerpetualDistribution'); - expect(distributionRules.perpetualDistributionRules.constructor.name).to.deep.equal('ChangeControlRules'); - expect(distributionRules.preProgrammedDistribution.constructor.name).to.deep.equal('TokenPreProgrammedDistribution'); - expect(distributionRules.newTokenDestinationIdentity.constructor.name).to.deep.equal('Identifier'); - expect(distributionRules.newTokenDestinationIdentityRules.constructor.name).to.deep.equal('ChangeControlRules'); - expect(distributionRules.mintingAllowChoosingDestination).to.deep.equal(true); - expect(distributionRules.mintingAllowChoosingDestinationRules.constructor.name).to.deep.equal('ChangeControlRules'); - expect(distributionRules.changeDirectPurchasePricingRules.constructor.name).to.deep.equal('ChangeControlRules'); - }); - }); - - describe('setters', () => { - let noOne; - - let changeRules; - - let preProgrammedDistribution; - - let recipient; - - let distributionFunction; - - let distributionType; - - let perpetualDistribution; - - let distributionRules; - - before(() => { - noOne = wasm.AuthorizedActionTakers.NoOne(); - changeRules = new wasm.ChangeControlRules( - noOne, - noOne, - true, - true, - true, - ); - preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10000), - }, - }, - ); - recipient = wasm.TokenDistributionRecipient.ContractOwner(); - distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), - ); - distributionType = wasm.RewardDistributionType.BlockBasedDistribution( - BigInt(111), - distributionFunction, - ); - perpetualDistribution = new wasm.TokenPerpetualDistribution( - distributionType, - recipient, - ); - distributionRules = new wasm.TokenDistributionRules( - perpetualDistribution, - changeRules, - preProgrammedDistribution, - identifier, - changeRules, - true, - changeRules, - changeRules, - ); - }); - - it('should allow to set mintingAllowChoosingDestination', () => { - distributionRules.mintingAllowChoosingDestination = false; - - expect(distributionRules.mintingAllowChoosingDestination).to.deep.equal(false); - }); - - it('should allow to set changeDirectPurchasePricingRules', () => { - const newRules = new wasm.ChangeControlRules( - noOne, - noOne, - false, - false, - false, - ); - - distributionRules.changeDirectPurchasePricingRules = newRules; - - expect(newRules.__wbg_ptr).to.not.equal(0); - expect(distributionRules.changeDirectPurchasePricingRules.selfChangingAdminActionTakersAllowed).to.deep.equal(false); - expect(distributionRules.changeDirectPurchasePricingRules.changingAdminActionTakersToNoOneAllowed).to.deep.equal(false); - expect(distributionRules.changeDirectPurchasePricingRules.changingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(false); - }); - - it('should allow to set mintingAllowChoosingDestinationRules', () => { - const newRules = new wasm.ChangeControlRules( - noOne, - noOne, - false, - false, - false, - ); - - distributionRules.mintingAllowChoosingDestinationRules = newRules; - - expect(newRules.__wbg_ptr).to.not.equal(0); - expect(distributionRules.mintingAllowChoosingDestinationRules.selfChangingAdminActionTakersAllowed).to.deep.equal(false); - expect(distributionRules.mintingAllowChoosingDestinationRules.changingAdminActionTakersToNoOneAllowed).to.deep.equal(false); - expect(distributionRules.mintingAllowChoosingDestinationRules.changingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(false); - }); - - it('should allow to set newTokenDestinationIdentityRules', () => { - const newRules = new wasm.ChangeControlRules( - noOne, - noOne, - false, - false, - false, - ); - - distributionRules.newTokenDestinationIdentityRules = newRules; - - expect(newRules.__wbg_ptr).to.not.equal(0); - expect(distributionRules.newTokenDestinationIdentityRules.selfChangingAdminActionTakersAllowed).to.deep.equal(false); - expect(distributionRules.newTokenDestinationIdentityRules.changingAdminActionTakersToNoOneAllowed).to.deep.equal(false); - expect(distributionRules.newTokenDestinationIdentityRules.changingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(false); - }); - - it('should allow to set newTokenDestinationIdentity', () => { - distributionRules.newTokenDestinationIdentity = '12p3355tKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; - - expect(distributionRules.newTokenDestinationIdentity.toBase58()).to.deep.equal('12p3355tKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); - }); - - it('should allow to set preProgrammedDistribution', () => { - const newPreProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416411: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10011120), - }, - }, - ); - - distributionRules.preProgrammedDistribution = newPreProgrammedDistribution; - - expect(newPreProgrammedDistribution.__wbg_ptr).to.not.equal(0); - expect(distributionRules.preProgrammedDistribution.distributions).to.deep.equal({ - 1750140416411: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10011120), - }, - }); - }); - - it('should allow to set perpetualDistributionRules', () => { - const newPerpetualDistributionRules = new wasm.ChangeControlRules( - noOne, - noOne, - false, - false, - false, - ); - - distributionRules.perpetualDistributionRules = newPerpetualDistributionRules; - - expect(newPerpetualDistributionRules.__wbg_ptr).to.not.equal(0); - expect(distributionRules.perpetualDistributionRules.changingAuthorizedActionTakersToNoOneAllowed).to.deep.equal(false); - }); - - it('should allow to set perpetualDistribution', () => { - const newRecipient = wasm.TokenDistributionRecipient.EvonodesByParticipation(); - - const newPerpetualDistribution = new wasm.TokenPerpetualDistribution( - distributionType, - newRecipient, - ); - - distributionRules.perpetualDistribution = newPerpetualDistribution; - - expect(newPerpetualDistribution.__wbg_ptr).to.not.equal(0); - expect(distributionRules.perpetualDistribution.distributionRecipient.getType()).to.deep.equal('EvonodesByParticipation'); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/TokenDistributionRules.spec.ts b/packages/wasm-dpp2/tests/unit/TokenDistributionRules.spec.ts new file mode 100644 index 00000000000..7f2cf5fc132 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/TokenDistributionRules.spec.ts @@ -0,0 +1,357 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { identifier } from './mocks/Identity/index.js'; + +before(async () => { + await initWasm(); +}); + +interface ChangeControlRulesOptions { + isChangingAuthorizedActionTakersToNoOneAllowed?: boolean; + isChangingAdminActionTakersToNoOneAllowed?: boolean; + isSelfChangingAdminActionTakersAllowed?: boolean; +} + +// Helper function to create ChangeControlRules with default options +function createChangeControlRules( + authorizedToMakeChange: unknown, + adminActionTakers: unknown, + options: ChangeControlRulesOptions = {}, +) { + return new wasm.ChangeControlRules({ + authorizedToMakeChange, + adminActionTakers, + isChangingAuthorizedActionTakersToNoOneAllowed: options.isChangingAuthorizedActionTakersToNoOneAllowed ?? true, + isChangingAdminActionTakersToNoOneAllowed: options.isChangingAdminActionTakersToNoOneAllowed ?? true, + isSelfChangingAdminActionTakersAllowed: options.isSelfChangingAdminActionTakersAllowed ?? true, + }); +} + +// Helper to create pre-programmed distribution with proper Map format +function createPreProgrammedDistribution(timestamp: number, identifierBase58: string, amount: bigint) { + const id = new wasm.Identifier(identifierBase58); + const innerMap = new Map(); + innerMap.set(id, amount); + const outerMap = new Map(); + outerMap.set(timestamp.toString(), innerMap); + return new wasm.TokenPreProgrammedDistribution(outerMap); +} + +describe('TokenDistributionRules', () => { + describe('constructor', () => { + it('should create instance with undefined values', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution: undefined, + perpetualDistributionRules: changeRules, + preProgrammedDistribution: undefined, + newTokensDestinationIdentity: undefined, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + expect(distributionRules).to.be.an.instanceof(wasm.TokenDistributionRules); + expect(changeRules).to.be.an.instanceof(wasm.ChangeControlRules); + }); + + it('should create instance without undefined values', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + + const changeRules = createChangeControlRules(noOne, noOne); + + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), + ); + + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( + BigInt(111), + distributionFunction, + ); + + const perpetualDistribution = new wasm.TokenPerpetualDistribution( + distributionType, + recipient, + ); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + expect(distributionRules).to.be.an.instanceof(wasm.TokenDistributionRules); + expect(perpetualDistribution).to.be.an.instanceof(wasm.TokenPerpetualDistribution); + expect(preProgrammedDistribution).to.be.an.instanceof(wasm.TokenPreProgrammedDistribution); + expect(changeRules).to.be.an.instanceof(wasm.ChangeControlRules); + }); + }); + + describe('perpetualDistribution', () => { + it('should return perpetualDistribution', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + expect(distributionRules.perpetualDistribution.constructor.name).to.deep.equal('TokenPerpetualDistribution'); + }); + + it('should set perpetualDistribution', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + const newRecipient = wasm.TokenDistributionRecipient.EvonodesByParticipation(); + const newPerpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, newRecipient); + + distributionRules.perpetualDistribution = newPerpetualDistribution; + + expect(newPerpetualDistribution).to.be.an.instanceof(wasm.TokenPerpetualDistribution); + expect(distributionRules.perpetualDistribution.distributionRecipient.recipientType).to.deep.equal('EvonodesByParticipation'); + }); + }); + + describe('mintingAllowChoosingDestination', () => { + it('should return mintingAllowChoosingDestination', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + expect(distributionRules.mintingAllowChoosingDestination).to.deep.equal(true); + }); + + it('should set mintingAllowChoosingDestination', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + distributionRules.mintingAllowChoosingDestination = false; + + expect(distributionRules.mintingAllowChoosingDestination).to.deep.equal(false); + }); + }); + + describe('newTokensDestinationIdentity', () => { + it('should return newTokensDestinationIdentity', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + expect(distributionRules.newTokensDestinationIdentity.constructor.name).to.deep.equal('Identifier'); + }); + + it('should set newTokensDestinationIdentity', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + distributionRules.newTokensDestinationIdentity = '12p3355tKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + + expect(distributionRules.newTokensDestinationIdentity.toBase58()).to.deep.equal('12p3355tKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); + }); + }); + + describe('preProgrammedDistribution', () => { + it('should return preProgrammedDistribution', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + expect(distributionRules.preProgrammedDistribution.constructor.name).to.deep.equal('TokenPreProgrammedDistribution'); + }); + + it('should set preProgrammedDistribution', () => { + const noOne = wasm.AuthorizedActionTakers.NoOne(); + const changeRules = createChangeControlRules(noOne, noOne); + const preProgrammedDistribution = createPreProgrammedDistribution( + 1750140416485, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + const recipient = wasm.TokenDistributionRecipient.ContractOwner(); + const fixedAmount = new wasm.DistributionFixedAmount({ amount: BigInt(111) }); + const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution(fixedAmount); + const distributionType = wasm.RewardDistributionType.BlockBasedDistribution(BigInt(111), distributionFunction); + const perpetualDistribution = new wasm.TokenPerpetualDistribution(distributionType, recipient); + + const distributionRules = new wasm.TokenDistributionRules({ + perpetualDistribution, + perpetualDistributionRules: changeRules, + preProgrammedDistribution, + newTokensDestinationIdentity: identifier, + newTokensDestinationIdentityRules: changeRules, + mintingAllowChoosingDestination: true, + mintingAllowChoosingDestinationRules: changeRules, + changeDirectPurchasePricingRules: changeRules, + }); + + const newPreProgrammedDistribution = createPreProgrammedDistribution( + 1750140416411, + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10011120), + ); + + distributionRules.preProgrammedDistribution = newPreProgrammedDistribution; + + expect(newPreProgrammedDistribution).to.be.an.instanceof(wasm.TokenPreProgrammedDistribution); + expect(distributionRules.preProgrammedDistribution.distributions).to.not.equal(undefined); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/TokenKeepsHistoryRules.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenKeepsHistoryRules.spec.mjs deleted file mode 100644 index 8f081561138..00000000000 --- a/packages/wasm-dpp2/tests/unit/TokenKeepsHistoryRules.spec.mjs +++ /dev/null @@ -1,71 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('TokenKeepsHistoryRules', () => { - describe('serialization / deserialization', () => { - it('should allow to create TokenKeepsHistoryRules from values', () => { - const keepHistory = new wasm.TokenKeepsHistoryRules( - true, - true, - true, - true, - true, - true, - ); - - expect(keepHistory.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to get values', () => { - const keepHistory = new wasm.TokenKeepsHistoryRules( - true, - true, - true, - true, - true, - true, - ); - - expect(keepHistory.keepsTransferHistory).to.equal(true); - expect(keepHistory.keepsFreezingHistory).to.equal(true); - expect(keepHistory.keepsMintingHistory).to.equal(true); - expect(keepHistory.keepsBurningHistory).to.equal(true); - expect(keepHistory.keepsDirectPricingHistory).to.equal(true); - expect(keepHistory.keepsDirectPurchaseHistory).to.equal(true); - }); - }); - - describe('setters', () => { - it('should allow to set values', () => { - const keepHistory = new wasm.TokenKeepsHistoryRules( - true, - true, - true, - true, - true, - true, - ); - - keepHistory.keepsTransferHistory = false; - keepHistory.keepsFreezingHistory = false; - keepHistory.keepsMintingHistory = false; - keepHistory.keepsBurningHistory = false; - keepHistory.keepsDirectPricingHistory = false; - keepHistory.keepsDirectPurchaseHistory = false; - - expect(keepHistory.keepsTransferHistory).to.equal(false); - expect(keepHistory.keepsFreezingHistory).to.equal(false); - expect(keepHistory.keepsMintingHistory).to.equal(false); - expect(keepHistory.keepsBurningHistory).to.equal(false); - expect(keepHistory.keepsDirectPricingHistory).to.equal(false); - expect(keepHistory.keepsDirectPurchaseHistory).to.equal(false); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/TokenKeepsHistoryRules.spec.ts b/packages/wasm-dpp2/tests/unit/TokenKeepsHistoryRules.spec.ts new file mode 100644 index 00000000000..766bea1fe7e --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/TokenKeepsHistoryRules.spec.ts @@ -0,0 +1,133 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +interface KeepsHistoryRulesOptions { + isKeepingTransferHistory?: boolean; + isKeepingFreezingHistory?: boolean; + isKeepingMintingHistory?: boolean; + isKeepingBurningHistory?: boolean; + isKeepingDirectPricingHistory?: boolean; + isKeepingDirectPurchaseHistory?: boolean; +} + +describe('TokenKeepsHistoryRules', () => { + // Helper function to create TokenKeepsHistoryRules with default options + function createKeepsHistoryRules(options: KeepsHistoryRulesOptions = {}) { + return new wasm.TokenKeepsHistoryRules({ + isKeepingTransferHistory: options.isKeepingTransferHistory ?? true, + isKeepingFreezingHistory: options.isKeepingFreezingHistory ?? true, + isKeepingMintingHistory: options.isKeepingMintingHistory ?? true, + isKeepingBurningHistory: options.isKeepingBurningHistory ?? true, + isKeepingDirectPricingHistory: options.isKeepingDirectPricingHistory ?? true, + isKeepingDirectPurchaseHistory: options.isKeepingDirectPurchaseHistory ?? true, + }); + } + + describe('constructor', () => { + it('should create instance from values', () => { + const keepHistory = createKeepsHistoryRules(); + + expect(keepHistory).to.be.an.instanceof(wasm.TokenKeepsHistoryRules); + }); + }); + + describe('isKeepingTransferHistory', () => { + it('should return isKeepingTransferHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + expect(keepHistory.isKeepingTransferHistory).to.equal(true); + }); + + it('should set isKeepingTransferHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + keepHistory.isKeepingTransferHistory = false; + + expect(keepHistory.isKeepingTransferHistory).to.equal(false); + }); + }); + + describe('isKeepingFreezingHistory', () => { + it('should return isKeepingFreezingHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + expect(keepHistory.isKeepingFreezingHistory).to.equal(true); + }); + + it('should set isKeepingFreezingHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + keepHistory.isKeepingFreezingHistory = false; + + expect(keepHistory.isKeepingFreezingHistory).to.equal(false); + }); + }); + + describe('isKeepingMintingHistory', () => { + it('should return isKeepingMintingHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + expect(keepHistory.isKeepingMintingHistory).to.equal(true); + }); + + it('should set isKeepingMintingHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + keepHistory.isKeepingMintingHistory = false; + + expect(keepHistory.isKeepingMintingHistory).to.equal(false); + }); + }); + + describe('isKeepingBurningHistory', () => { + it('should return isKeepingBurningHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + expect(keepHistory.isKeepingBurningHistory).to.equal(true); + }); + + it('should set isKeepingBurningHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + keepHistory.isKeepingBurningHistory = false; + + expect(keepHistory.isKeepingBurningHistory).to.equal(false); + }); + }); + + describe('isKeepingDirectPricingHistory', () => { + it('should return isKeepingDirectPricingHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + expect(keepHistory.isKeepingDirectPricingHistory).to.equal(true); + }); + + it('should set isKeepingDirectPricingHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + keepHistory.isKeepingDirectPricingHistory = false; + + expect(keepHistory.isKeepingDirectPricingHistory).to.equal(false); + }); + }); + + describe('isKeepingDirectPurchaseHistory', () => { + it('should return isKeepingDirectPurchaseHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + expect(keepHistory.isKeepingDirectPurchaseHistory).to.equal(true); + }); + + it('should set isKeepingDirectPurchaseHistory', () => { + const keepHistory = createKeepsHistoryRules(); + + keepHistory.isKeepingDirectPurchaseHistory = false; + + expect(keepHistory.isKeepingDirectPurchaseHistory).to.equal(false); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/TokenPerpetualDistribution.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenPerpetualDistribution.spec.ts similarity index 65% rename from packages/wasm-dpp2/tests/unit/TokenPerpetualDistribution.spec.mjs rename to packages/wasm-dpp2/tests/unit/TokenPerpetualDistribution.spec.ts index 55e708e373f..2c684c210e9 100644 --- a/packages/wasm-dpp2/tests/unit/TokenPerpetualDistribution.spec.mjs +++ b/packages/wasm-dpp2/tests/unit/TokenPerpetualDistribution.spec.ts @@ -1,18 +1,17 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; before(async () => { - wasm = await getWasm(); + await initWasm(); }); describe('TokenPerpetualDistribution', () => { - describe('serialization / deserialization', () => { - it('should allow to create from values', () => { + describe('constructor', () => { + it('should create instance from values', () => { const recipient = wasm.TokenDistributionRecipient.ContractOwner(); const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), ); const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( @@ -25,19 +24,19 @@ describe('TokenPerpetualDistribution', () => { recipient, ); - expect(recipient.__wbg_ptr).to.not.equal(0); - expect(distributionFunction.__wbg_ptr).to.not.equal(0); - expect(distributionType.__wbg_ptr).to.not.equal(0); - expect(distribution.__wbg_ptr).to.not.equal(0); + expect(recipient).to.be.an.instanceof(wasm.TokenDistributionRecipient); + expect(distributionFunction).to.be.an.instanceof(wasm.DistributionFunction); + expect(distributionType).to.be.an.instanceof(wasm.RewardDistributionType); + expect(distribution).to.be.an.instanceof(wasm.TokenPerpetualDistribution); }); }); - describe('getters', () => { - it('should allow to get distributionType', () => { + describe('distributionType', () => { + it('should return distributionType', () => { const recipient = wasm.TokenDistributionRecipient.ContractOwner(); const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), ); const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( @@ -53,11 +52,11 @@ describe('TokenPerpetualDistribution', () => { expect(distribution.distributionType.constructor.name).to.deep.equal('RewardDistributionType'); }); - it('should allow to get distributionRecipient', () => { + it('should set distributionType', () => { const recipient = wasm.TokenDistributionRecipient.ContractOwner(); const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), ); const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( @@ -70,17 +69,25 @@ describe('TokenPerpetualDistribution', () => { recipient, ); - expect(distribution.distributionRecipient.constructor.name).to.deep.equal('TokenDistributionRecipient'); - expect(distribution.distributionRecipient.getType()).to.deep.equal('ContractOwner'); + const newDistribution = wasm.RewardDistributionType.TimeBasedDistribution( + BigInt(111), + distributionFunction, + ); + + distribution.distributionType = newDistribution; + + expect(newDistribution).to.be.an.instanceof(wasm.RewardDistributionType); + expect(distribution.distributionType.constructor.name).to.deep.equal('RewardDistributionType'); + expect(distribution.distributionType.distribution.constructor.name).to.deep.equal('TimeBasedDistribution'); }); }); - describe('setters', () => { - it('should allow to set distributionType', () => { + describe('distributionRecipient', () => { + it('should return distributionRecipient', () => { const recipient = wasm.TokenDistributionRecipient.ContractOwner(); const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), ); const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( @@ -93,23 +100,15 @@ describe('TokenPerpetualDistribution', () => { recipient, ); - const newDistribution = wasm.RewardDistributionType.TimeBasedDistribution( - BigInt(111), - distributionFunction, - ); - - distribution.distributionType = newDistribution; - - expect(newDistribution.__wbg_ptr).to.not.equal(0); - expect(distribution.distributionType.constructor.name).to.deep.equal('RewardDistributionType'); - expect(distribution.distributionType.getDistribution().constructor.name).to.deep.equal('TimeBasedDistribution'); + expect(distribution.distributionRecipient.constructor.name).to.deep.equal('TokenDistributionRecipient'); + expect(distribution.distributionRecipient.recipientType).to.deep.equal('ContractOwner'); }); - it('should allow to set distributionRecipient', () => { + it('should set distributionRecipient', () => { const recipient = wasm.TokenDistributionRecipient.ContractOwner(); const distributionFunction = wasm.DistributionFunction.FixedAmountDistribution( - BigInt(111), + new wasm.DistributionFixedAmount({ amount: BigInt(111) }), ); const distributionType = wasm.RewardDistributionType.BlockBasedDistribution( @@ -126,9 +125,9 @@ describe('TokenPerpetualDistribution', () => { distribution.distributionRecipient = newRecipient; - expect(newRecipient.__wbg_ptr).to.not.equal(0); + expect(newRecipient).to.be.an.instanceof(wasm.TokenDistributionRecipient); expect(distribution.distributionRecipient.constructor.name).to.deep.equal('TokenDistributionRecipient'); - expect(distribution.distributionRecipient.getType()).to.deep.equal('EvonodesByParticipation'); + expect(distribution.distributionRecipient.recipientType).to.deep.equal('EvonodesByParticipation'); }); }); }); diff --git a/packages/wasm-dpp2/tests/unit/TokenPreProgrammedDistribution.spec.mjs b/packages/wasm-dpp2/tests/unit/TokenPreProgrammedDistribution.spec.mjs deleted file mode 100644 index ef11317f92e..00000000000 --- a/packages/wasm-dpp2/tests/unit/TokenPreProgrammedDistribution.spec.mjs +++ /dev/null @@ -1,65 +0,0 @@ -import getWasm from './helpers/wasm.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -describe('TokenPreProgrammedDistribution', () => { - describe('serialization / deserialization', () => { - it('should allow to create from values', () => { - const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10000), - }, - }, - ); - - expect(preProgrammedDistribution.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to get distributions', () => { - const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10100), - }, - }, - ); - - expect(preProgrammedDistribution.distributions).to.deep.equal({ - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10100), - }, - }); - }); - }); - - describe('setters', () => { - it('should allow to set distributions', () => { - const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution( - { - 1750140416485: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(10100), - }, - }, - ); - - preProgrammedDistribution.distributions = { - 1750140416415: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(9999999), - }, - }; - - expect(preProgrammedDistribution.distributions).to.deep.equal({ - 1750140416415: { - PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB: BigInt(9999999), - }, - }); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/TokenPreProgrammedDistribution.spec.ts b/packages/wasm-dpp2/tests/unit/TokenPreProgrammedDistribution.spec.ts new file mode 100644 index 00000000000..1c97e14982d --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/TokenPreProgrammedDistribution.spec.ts @@ -0,0 +1,81 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +before(async () => { + await initWasm(); +}); + +describe('TokenPreProgrammedDistribution', () => { + // Helper to create an Identifier object for testing + function createIdentifier(base58String: string) { + return new wasm.Identifier(base58String); + } + + // Helper to create distributions Map in the expected format + function createDistributionsMap(timestamp: string, identifierStr: string, amount: bigint) { + const innerMap = new Map(); + innerMap.set(createIdentifier(identifierStr), amount); + + const outerMap = new Map(); + outerMap.set(timestamp.toString(), innerMap); + + return outerMap; + } + + describe('constructor', () => { + it('should create instance from values', () => { + const distributions = createDistributionsMap( + '1750140416485', + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10000), + ); + + const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution(distributions); + + expect(preProgrammedDistribution).to.be.an.instanceof(wasm.TokenPreProgrammedDistribution); + }); + }); + + describe('distributions', () => { + it('should return distributions', () => { + const distributions = createDistributionsMap( + '1750140416485', + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10100), + ); + + const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution(distributions); + + // The getter returns a Map, check it has the expected structure + const result = preProgrammedDistribution.distributions; + expect(result instanceof Map).to.equal(true); + expect(result.has('1750140416485')).to.equal(true); + + const innerMap = result.get('1750140416485'); + expect(innerMap instanceof Map).to.equal(true); + expect(innerMap.size).to.equal(1); + }); + + it('should set distributions', () => { + const distributions = createDistributionsMap( + '1750140416485', + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(10100), + ); + + const preProgrammedDistribution = new wasm.TokenPreProgrammedDistribution(distributions); + + const newDistributions = createDistributionsMap( + '1750140416415', + 'PJUBWbXWmzEYCs99rAAbnCiHRzrnhKLQrXbmSsuPBYB', + BigInt(9999999), + ); + + preProgrammedDistribution.distributions = newDistributions; + + const result = preProgrammedDistribution.distributions; + expect(result instanceof Map).to.equal(true); + expect(result.has('1750140416415')).to.equal(true); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/TokensTransitions.spec.mjs b/packages/wasm-dpp2/tests/unit/TokensTransitions.spec.mjs deleted file mode 100644 index 8f90d900e20..00000000000 --- a/packages/wasm-dpp2/tests/unit/TokensTransitions.spec.mjs +++ /dev/null @@ -1,513 +0,0 @@ -import getWasm from './helpers/wasm.js'; -import { dataContractId, ownerId } from './mocks/Document/index.js'; - -let wasm; - -before(async () => { - wasm = await getWasm(); -}); - -let baseTransition; - -describe('TokenTransitions', () => { - before(async () => { - baseTransition = new wasm.TokenBaseTransition(BigInt(1), 1, dataContractId, ownerId); - }); - - describe('serialize/deserialize', () => { - it('should allow to create burn transition', () => { - const burnTransition = new wasm.TokenBurnTransition(baseTransition, BigInt(11), 'bbbb'); - - expect(burnTransition.constructor.name).to.equal('TokenBurnTransition'); - expect(burnTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create mint transition', () => { - const mintTransition = new wasm.TokenMintTransition(baseTransition, ownerId, BigInt(11), 'bbbb'); - - expect(mintTransition.constructor.name).to.equal('TokenMintTransition'); - expect(mintTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create transfer transition', () => { - const transferTransition = new wasm.TokenTransferTransition( - baseTransition, - ownerId, - BigInt(11), - 'bbbb', - ); - - expect(transferTransition.constructor.name).to.equal('TokenTransferTransition'); - expect(transferTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create transfer transition with shared encrypted note', () => { - const sharedEncryptedNote = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); - - const transferTransition = new wasm.TokenTransferTransition( - baseTransition, - ownerId, - BigInt(11), - 'bbbb', - sharedEncryptedNote, - ); - - expect(sharedEncryptedNote.constructor.name).to.equal('SharedEncryptedNote'); - expect(transferTransition.constructor.name).to.equal('TokenTransferTransition'); - expect(transferTransition.__wbg_ptr).to.not.equal(0); - expect(sharedEncryptedNote.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create transfer transition with private encrypted note', () => { - const privateEncryptedNote = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); - - const transferTransition = new wasm.TokenTransferTransition( - baseTransition, - ownerId, - BigInt(11), - 'bbbb', - undefined, - privateEncryptedNote, - ); - - expect(privateEncryptedNote.constructor.name).to.equal('PrivateEncryptedNote'); - expect(transferTransition.constructor.name).to.equal('TokenTransferTransition'); - expect(transferTransition.__wbg_ptr).to.not.equal(0); - expect(privateEncryptedNote.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create freeze transition', () => { - const freezeTransition = new wasm.TokenFreezeTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - expect(freezeTransition.constructor.name).to.equal('TokenFreezeTransition'); - expect(freezeTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create unfreeze transition', () => { - const unfreezeTransition = new wasm.TokenUnFreezeTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - expect(unfreezeTransition.constructor.name).to.equal('TokenUnFreezeTransition'); - expect(unfreezeTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create destroy frozen funds transition', () => { - const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - expect(tokenDestroyFrozenFundsTransition.constructor.name).to.equal('TokenDestroyFrozenFundsTransition'); - expect(tokenDestroyFrozenFundsTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create claim transition', () => { - const claimTransition = new wasm.TokenClaimTransition( - baseTransition, - wasm.TokenDistributionType.PreProgrammed, - 'bbbb', - ); - - expect(claimTransition.constructor.name).to.equal('TokenClaimTransition'); - expect(claimTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create claim transition without distribution type', () => { - const claimTransition = new wasm.TokenClaimTransition( - baseTransition, - ); - - expect(claimTransition.constructor.name).to.equal('TokenClaimTransition'); - expect(claimTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create emergency action transition', () => { - const emergencyActionTransition = new wasm.TokenEmergencyActionTransition( - baseTransition, - wasm.TokenDistributionType.PreProgrammed, - 'bbbb', - ); - - expect(emergencyActionTransition.constructor.name).to.equal('TokenEmergencyActionTransition'); - expect(emergencyActionTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create config update transition', () => { - const tradeMode = wasm.TokenTradeMode.NotTradeable(); - - const configUpdateTransition = new wasm.TokenConfigUpdateTransition( - baseTransition, - wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), - 'bbbb', - ); - - expect(configUpdateTransition.constructor.name).to.equal('TokenConfigUpdateTransition'); - expect(configUpdateTransition.__wbg_ptr).to.not.equal(0); - expect(tradeMode.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create direct purchase transition', () => { - const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition( - baseTransition, - BigInt(111), - BigInt(111), - ); - - expect(directPurchaseTransition.constructor.name).to.equal('TokenDirectPurchaseTransition'); - expect(directPurchaseTransition.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to create set price direct purchase transition', () => { - const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); - - const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition( - baseTransition, - price, - 'bbbb', - ); - - expect(price.constructor.name).to.equal('TokenPricingSchedule'); - expect(setPriceDirectPurchaseTransition.constructor.name).to.equal('TokenSetPriceForDirectPurchaseTransition'); - expect(setPriceDirectPurchaseTransition.__wbg_ptr).to.not.equal(0); - expect(price.__wbg_ptr).to.not.equal(0); - expect(baseTransition.__wbg_ptr).to.not.equal(0); - }); - }); - - describe('getters', () => { - it('should allow to read getters burn transition', () => { - const burnTransition = new wasm.TokenBurnTransition(baseTransition, BigInt(11), 'bbbb'); - - expect(burnTransition.burnAmount).to.equal(BigInt(11)); - expect(burnTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(burnTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters mint transition', () => { - const mintTransition = new wasm.TokenMintTransition(baseTransition, ownerId, BigInt(11), 'bbbb'); - - expect(mintTransition.amount).to.equal(BigInt(11)); - expect(mintTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(mintTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters transfer transition', () => { - const sharedEncryptedNote = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); - const privateEncryptedNote = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); - - const transferTransition = new wasm.TokenTransferTransition( - baseTransition, - ownerId, - BigInt(11), - 'bbbb', - sharedEncryptedNote, - privateEncryptedNote, - ); - - expect(transferTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(transferTransition.amount).to.equal(BigInt(11)); - expect(transferTransition.publicNote).to.equal('bbbb'); - expect(transferTransition.sharedEncryptedNote.constructor.name).to.equal('SharedEncryptedNote'); - expect(transferTransition.privateEncryptedNote.constructor.name).to.equal('PrivateEncryptedNote'); - }); - - it('should allow to read getters freeze transition', () => { - const freezeTransition = new wasm.TokenFreezeTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - expect(freezeTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(freezeTransition.frozenIdentityId.toBase58()).to.equal(ownerId); - expect(freezeTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters unfreeze transition', () => { - const unfreezeTransition = new wasm.TokenUnFreezeTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - expect(unfreezeTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(unfreezeTransition.frozenIdentityId.toBase58()).to.equal(ownerId); - expect(unfreezeTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters destroy frozen funds transition', () => { - const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - expect(tokenDestroyFrozenFundsTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(tokenDestroyFrozenFundsTransition.frozenIdentityId.toBase58()).to.equal(ownerId); - expect(tokenDestroyFrozenFundsTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters claim transition', () => { - const claimTransition = new wasm.TokenClaimTransition( - baseTransition, - wasm.TokenDistributionType.PreProgrammed, - 'bbbb', - ); - - expect(claimTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(claimTransition.distributionType).to.equal('PreProgrammed'); - expect(claimTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters emergency action transition', () => { - const emergencyActionTransition = new wasm.TokenEmergencyActionTransition( - baseTransition, - wasm.TokenEmergencyAction.Pause, - 'bbbb', - ); - - expect(emergencyActionTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(emergencyActionTransition.emergencyAction).to.equal('Pause'); - expect(emergencyActionTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters config update transition', () => { - const tradeMode = wasm.TokenTradeMode.NotTradeable(); - - const configUpdateTransition = new wasm.TokenConfigUpdateTransition( - baseTransition, - wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), - 'bbbb', - ); - - expect(configUpdateTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(configUpdateTransition.updateTokenConfigurationItem.constructor.name).to.equal('TokenConfigurationChangeItem'); - expect(configUpdateTransition.publicNote).to.equal('bbbb'); - }); - - it('should allow to read getters direct purchase transition', () => { - const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition( - baseTransition, - BigInt(111), - BigInt(111), - ); - - expect(directPurchaseTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(directPurchaseTransition.tokenCount).to.equal(BigInt(111)); - expect(directPurchaseTransition.totalAgreedPrice).to.equal(BigInt(111)); - }); - - it('should allow to read getters set price direct purchase transition', () => { - const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); - - const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition( - baseTransition, - price, - 'bbbb', - ); - - expect(setPriceDirectPurchaseTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(setPriceDirectPurchaseTransition.price.constructor.name).to.equal('TokenPricingSchedule'); - expect(setPriceDirectPurchaseTransition.publicNote).to.equal('bbbb'); - }); - }); - - describe('setters', () => { - it('should allow to set values burn transition', () => { - const burnTransition = new wasm.TokenBurnTransition(baseTransition, BigInt(11), 'bbbb'); - - burnTransition.burnAmount = BigInt(222); - burnTransition.publicNote = 'aaaa'; - - expect(burnTransition.burnAmount).to.equal(BigInt(222)); - expect(burnTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(burnTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values mint transition', () => { - const mintTransition = new wasm.TokenMintTransition(baseTransition, ownerId, BigInt(11), 'bbbb'); - - mintTransition.amount = BigInt(222); - mintTransition.publicNote = 'aaaa'; - - expect(mintTransition.amount).to.equal(BigInt(222)); - expect(mintTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(mintTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values transfer transition', () => { - const sharedEncryptedNote = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); - const privateEncryptedNote = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); - - const transferTransition = new wasm.TokenTransferTransition( - baseTransition, - ownerId, - BigInt(11), - 'bbbb', - sharedEncryptedNote, - privateEncryptedNote, - ); - - const sharedEncryptedNote2 = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); - const privateEncryptedNote2 = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); - - transferTransition.sharedEncryptedNote = sharedEncryptedNote2; - transferTransition.privateEncryptedNote = privateEncryptedNote2; - transferTransition.amount = BigInt(222); - transferTransition.publicNote = 'aaaa'; - - expect(transferTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(transferTransition.amount).to.equal(BigInt(222)); - expect(transferTransition.publicNote).to.equal('aaaa'); - expect(transferTransition.sharedEncryptedNote.constructor.name).to.equal('SharedEncryptedNote'); - expect(transferTransition.privateEncryptedNote.constructor.name).to.equal('PrivateEncryptedNote'); - expect(sharedEncryptedNote2.__wbg_ptr).to.not.equal(0); - expect(privateEncryptedNote2.__wbg_ptr).to.not.equal(0); - }); - - it('should allow to set values freeze transition', () => { - const freezeTransition = new wasm.TokenFreezeTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - freezeTransition.frozenIdentityId = dataContractId; - freezeTransition.publicNote = 'aaaa'; - - expect(freezeTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(freezeTransition.frozenIdentityId.toBase58()).to.equal(dataContractId); - expect(freezeTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values unfreeze transition', () => { - const unfreezeTransition = new wasm.TokenUnFreezeTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - unfreezeTransition.frozenIdentityId = dataContractId; - unfreezeTransition.publicNote = 'aaaa'; - - expect(unfreezeTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(unfreezeTransition.frozenIdentityId.toBase58()).to.equal(dataContractId); - expect(unfreezeTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values destroy frozen funds transition', () => { - const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition( - baseTransition, - ownerId, - 'bbbb', - ); - - tokenDestroyFrozenFundsTransition.frozenIdentityId = dataContractId; - tokenDestroyFrozenFundsTransition.publicNote = 'aaaa'; - - expect(tokenDestroyFrozenFundsTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(tokenDestroyFrozenFundsTransition.frozenIdentityId.toBase58()).to.equal(dataContractId); - expect(tokenDestroyFrozenFundsTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values claim transition', () => { - const claimTransition = new wasm.TokenClaimTransition( - baseTransition, - wasm.TokenDistributionType.Perpetual, - 'bbbb', - ); - - claimTransition.distributionType = wasm.TokenDistributionType.Perpetual; - claimTransition.publicNote = 'aaaa'; - - expect(claimTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(claimTransition.distributionType).to.equal('Perpetual'); - expect(claimTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values emergency action transition', () => { - const emergencyActionTransition = new wasm.TokenEmergencyActionTransition( - baseTransition, - wasm.TokenEmergencyAction.Pause, - 'bbbb', - ); - - emergencyActionTransition.emergencyAction = wasm.TokenEmergencyAction.Resume; - emergencyActionTransition.publicNote = 'aaaa'; - - expect(emergencyActionTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(emergencyActionTransition.emergencyAction).to.equal('Resume'); - expect(emergencyActionTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values config update transition', () => { - // At this moment available only one trade mode - const tradeMode = wasm.TokenTradeMode.NotTradeable(); - - const configUpdateTransition = new wasm.TokenConfigUpdateTransition( - baseTransition, - wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), - 'bbbb', - ); - - configUpdateTransition.publicNote = 'aaaa'; - - expect(configUpdateTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(configUpdateTransition.updateTokenConfigurationItem.constructor.name).to.equal('TokenConfigurationChangeItem'); - expect(configUpdateTransition.publicNote).to.equal('aaaa'); - }); - - it('should allow to set values direct purchase transition', () => { - const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition( - baseTransition, - BigInt(111), - BigInt(111), - ); - - directPurchaseTransition.tokenCount = BigInt(222); - directPurchaseTransition.totalAgreedPrice = BigInt(222); - - expect(directPurchaseTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(directPurchaseTransition.tokenCount).to.equal(BigInt(222)); - expect(directPurchaseTransition.totalAgreedPrice).to.equal(BigInt(222)); - }); - - it('should allow to set values set price direct purchase transition', () => { - const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); - - const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition( - baseTransition, - price, - 'bbbb', - ); - - setPriceDirectPurchaseTransition.price = wasm.TokenPricingSchedule.SetPrices({ 101: 1010 }); - setPriceDirectPurchaseTransition.publicNote = 'aaaa'; - - expect(setPriceDirectPurchaseTransition.base.constructor.name).to.equal('TokenBaseTransition'); - expect(setPriceDirectPurchaseTransition.price.constructor.name).to.equal('TokenPricingSchedule'); - expect(setPriceDirectPurchaseTransition.publicNote).to.equal('aaaa'); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/TokensTransitions.spec.ts b/packages/wasm-dpp2/tests/unit/TokensTransitions.spec.ts new file mode 100644 index 00000000000..b7b468c4fd8 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/TokensTransitions.spec.ts @@ -0,0 +1,786 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; +import { dataContractId, ownerId } from './mocks/Document/index.js'; + +before(async () => { + await initWasm(); +}); + +let baseTransition: InstanceType; + +describe('TokenTransitions', () => { + before(async () => { + baseTransition = new wasm.TokenBaseTransition({ + identityContractNonce: BigInt(1), + tokenContractPosition: 1, + dataContractId, + tokenId: ownerId, + }); + }); + + describe('TokenBurnTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const burnTransition = new wasm.TokenBurnTransition({ base: baseTransition, burnAmount: BigInt(11), publicNote: 'bbbb' }); + + expect(burnTransition.constructor.name).to.equal('TokenBurnTransition'); + expect(burnTransition).to.be.an.instanceof(wasm.TokenBurnTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('burnAmount', () => { + it('should return burnAmount', () => { + const burnTransition = new wasm.TokenBurnTransition({ base: baseTransition, burnAmount: BigInt(11), publicNote: 'bbbb' }); + + expect(burnTransition.burnAmount).to.equal(BigInt(11)); + }); + + it('should set burnAmount', () => { + const burnTransition = new wasm.TokenBurnTransition({ base: baseTransition, burnAmount: BigInt(11), publicNote: 'bbbb' }); + + burnTransition.burnAmount = BigInt(222); + + expect(burnTransition.burnAmount).to.equal(BigInt(222)); + }); + }); + + describe('base', () => { + it('should return base', () => { + const burnTransition = new wasm.TokenBurnTransition({ base: baseTransition, burnAmount: BigInt(11), publicNote: 'bbbb' }); + + expect(burnTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const burnTransition = new wasm.TokenBurnTransition({ base: baseTransition, burnAmount: BigInt(11), publicNote: 'bbbb' }); + + expect(burnTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const burnTransition = new wasm.TokenBurnTransition({ base: baseTransition, burnAmount: BigInt(11), publicNote: 'bbbb' }); + + burnTransition.publicNote = 'aaaa'; + + expect(burnTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenMintTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const mintTransition = new wasm.TokenMintTransition({ base: baseTransition, issuedToIdentityId: ownerId, amount: BigInt(11), publicNote: 'bbbb' }); + + expect(mintTransition.constructor.name).to.equal('TokenMintTransition'); + expect(mintTransition).to.be.an.instanceof(wasm.TokenMintTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('amount', () => { + it('should return amount', () => { + const mintTransition = new wasm.TokenMintTransition({ base: baseTransition, issuedToIdentityId: ownerId, amount: BigInt(11), publicNote: 'bbbb' }); + + expect(mintTransition.amount).to.equal(BigInt(11)); + }); + + it('should set amount', () => { + const mintTransition = new wasm.TokenMintTransition({ base: baseTransition, issuedToIdentityId: ownerId, amount: BigInt(11), publicNote: 'bbbb' }); + + mintTransition.amount = BigInt(222); + + expect(mintTransition.amount).to.equal(BigInt(222)); + }); + }); + + describe('base', () => { + it('should return base', () => { + const mintTransition = new wasm.TokenMintTransition({ base: baseTransition, issuedToIdentityId: ownerId, amount: BigInt(11), publicNote: 'bbbb' }); + + expect(mintTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const mintTransition = new wasm.TokenMintTransition({ base: baseTransition, issuedToIdentityId: ownerId, amount: BigInt(11), publicNote: 'bbbb' }); + + expect(mintTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const mintTransition = new wasm.TokenMintTransition({ base: baseTransition, issuedToIdentityId: ownerId, amount: BigInt(11), publicNote: 'bbbb' }); + + mintTransition.publicNote = 'aaaa'; + + expect(mintTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenTransferTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + }); + + expect(transferTransition.constructor.name).to.equal('TokenTransferTransition'); + expect(transferTransition).to.be.an.instanceof(wasm.TokenTransferTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + + it('should create instance with shared encrypted note', () => { + const sharedEncryptedNote = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); + + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + sharedEncryptedNote, + }); + + expect(sharedEncryptedNote.constructor.name).to.equal('SharedEncryptedNote'); + expect(transferTransition.constructor.name).to.equal('TokenTransferTransition'); + expect(transferTransition).to.be.an.instanceof(wasm.TokenTransferTransition); + expect(sharedEncryptedNote).to.be.an.instanceof(wasm.SharedEncryptedNote); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + + it('should create instance with private encrypted note', () => { + const privateEncryptedNote = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); + + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + privateEncryptedNote, + }); + + expect(privateEncryptedNote.constructor.name).to.equal('PrivateEncryptedNote'); + expect(transferTransition.constructor.name).to.equal('TokenTransferTransition'); + expect(transferTransition).to.be.an.instanceof(wasm.TokenTransferTransition); + expect(privateEncryptedNote).to.be.an.instanceof(wasm.PrivateEncryptedNote); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + }); + + expect(transferTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('amount', () => { + it('should return amount', () => { + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + }); + + expect(transferTransition.amount).to.equal(BigInt(11)); + }); + + it('should set amount', () => { + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + }); + + transferTransition.amount = BigInt(222); + + expect(transferTransition.amount).to.equal(BigInt(222)); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + }); + + expect(transferTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + }); + + transferTransition.publicNote = 'aaaa'; + + expect(transferTransition.publicNote).to.equal('aaaa'); + }); + }); + + describe('sharedEncryptedNote', () => { + it('should return sharedEncryptedNote', () => { + const sharedEncryptedNote = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); + + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + sharedEncryptedNote, + }); + + expect(transferTransition.sharedEncryptedNote.constructor.name).to.equal('SharedEncryptedNote'); + }); + + it('should set sharedEncryptedNote', () => { + const sharedEncryptedNote = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); + + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + sharedEncryptedNote, + }); + + const sharedEncryptedNote2 = new wasm.SharedEncryptedNote(0, 0, [0, 0, 0]); + transferTransition.sharedEncryptedNote = sharedEncryptedNote2; + + expect(transferTransition.sharedEncryptedNote.constructor.name).to.equal('SharedEncryptedNote'); + expect(sharedEncryptedNote2).to.be.an.instanceof(wasm.SharedEncryptedNote); + }); + }); + + describe('privateEncryptedNote', () => { + it('should return privateEncryptedNote', () => { + const privateEncryptedNote = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); + + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + privateEncryptedNote, + }); + + expect(transferTransition.privateEncryptedNote.constructor.name).to.equal('PrivateEncryptedNote'); + }); + + it('should set privateEncryptedNote', () => { + const privateEncryptedNote = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); + + const transferTransition = new wasm.TokenTransferTransition({ + base: baseTransition, + recipientId: ownerId, + amount: BigInt(11), + publicNote: 'bbbb', + privateEncryptedNote, + }); + + const privateEncryptedNote2 = new wasm.PrivateEncryptedNote(0, 0, [0, 0, 0]); + transferTransition.privateEncryptedNote = privateEncryptedNote2; + + expect(transferTransition.privateEncryptedNote.constructor.name).to.equal('PrivateEncryptedNote'); + expect(privateEncryptedNote2).to.be.an.instanceof(wasm.PrivateEncryptedNote); + }); + }); + }); + + describe('TokenFreezeTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const freezeTransition = new wasm.TokenFreezeTransition({ base: baseTransition, identityToFreezeId: ownerId, publicNote: 'bbbb' }); + + expect(freezeTransition.constructor.name).to.equal('TokenFreezeTransition'); + expect(freezeTransition).to.be.an.instanceof(wasm.TokenFreezeTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const freezeTransition = new wasm.TokenFreezeTransition({ base: baseTransition, identityToFreezeId: ownerId, publicNote: 'bbbb' }); + + expect(freezeTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('frozenIdentityId', () => { + it('should return frozenIdentityId', () => { + const freezeTransition = new wasm.TokenFreezeTransition({ base: baseTransition, identityToFreezeId: ownerId, publicNote: 'bbbb' }); + + expect(freezeTransition.frozenIdentityId.toBase58()).to.equal(ownerId); + }); + + it('should set frozenIdentityId', () => { + const freezeTransition = new wasm.TokenFreezeTransition({ base: baseTransition, identityToFreezeId: ownerId, publicNote: 'bbbb' }); + + freezeTransition.frozenIdentityId = dataContractId; + + expect(freezeTransition.frozenIdentityId.toBase58()).to.equal(dataContractId); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const freezeTransition = new wasm.TokenFreezeTransition({ base: baseTransition, identityToFreezeId: ownerId, publicNote: 'bbbb' }); + + expect(freezeTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const freezeTransition = new wasm.TokenFreezeTransition({ base: baseTransition, identityToFreezeId: ownerId, publicNote: 'bbbb' }); + + freezeTransition.publicNote = 'aaaa'; + + expect(freezeTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenUnFreezeTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const unfreezeTransition = new wasm.TokenUnFreezeTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(unfreezeTransition.constructor.name).to.equal('TokenUnFreezeTransition'); + expect(unfreezeTransition).to.be.an.instanceof(wasm.TokenUnFreezeTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const unfreezeTransition = new wasm.TokenUnFreezeTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(unfreezeTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('frozenIdentityId', () => { + it('should return frozenIdentityId', () => { + const unfreezeTransition = new wasm.TokenUnFreezeTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(unfreezeTransition.frozenIdentityId.toBase58()).to.equal(ownerId); + }); + + it('should set frozenIdentityId', () => { + const unfreezeTransition = new wasm.TokenUnFreezeTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + unfreezeTransition.frozenIdentityId = dataContractId; + + expect(unfreezeTransition.frozenIdentityId.toBase58()).to.equal(dataContractId); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const unfreezeTransition = new wasm.TokenUnFreezeTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(unfreezeTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const unfreezeTransition = new wasm.TokenUnFreezeTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + unfreezeTransition.publicNote = 'aaaa'; + + expect(unfreezeTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenDestroyFrozenFundsTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(tokenDestroyFrozenFundsTransition.constructor.name).to.equal('TokenDestroyFrozenFundsTransition'); + expect(tokenDestroyFrozenFundsTransition).to.be.an.instanceof(wasm.TokenDestroyFrozenFundsTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(tokenDestroyFrozenFundsTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('frozenIdentityId', () => { + it('should return frozenIdentityId', () => { + const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(tokenDestroyFrozenFundsTransition.frozenIdentityId.toBase58()).to.equal(ownerId); + }); + + it('should set frozenIdentityId', () => { + const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + tokenDestroyFrozenFundsTransition.frozenIdentityId = dataContractId; + + expect(tokenDestroyFrozenFundsTransition.frozenIdentityId.toBase58()).to.equal(dataContractId); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + expect(tokenDestroyFrozenFundsTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const tokenDestroyFrozenFundsTransition = new wasm.TokenDestroyFrozenFundsTransition({ base: baseTransition, frozenIdentityId: ownerId, publicNote: 'bbbb' }); + + tokenDestroyFrozenFundsTransition.publicNote = 'aaaa'; + + expect(tokenDestroyFrozenFundsTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenClaimTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const claimTransition = new wasm.TokenClaimTransition({ + base: baseTransition, + distributionType: wasm.TokenDistributionType.PreProgrammed, + publicNote: 'bbbb', + }); + + expect(claimTransition.constructor.name).to.equal('TokenClaimTransition'); + expect(claimTransition).to.be.an.instanceof(wasm.TokenClaimTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + + it('should create instance without distribution type', () => { + const claimTransition = new wasm.TokenClaimTransition({ + base: baseTransition, + }); + + expect(claimTransition.constructor.name).to.equal('TokenClaimTransition'); + expect(claimTransition).to.be.an.instanceof(wasm.TokenClaimTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const claimTransition = new wasm.TokenClaimTransition({ base: baseTransition, distributionType: wasm.TokenDistributionType.PreProgrammed, publicNote: 'bbbb' }); + + expect(claimTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('distributionType', () => { + it('should return distributionType', () => { + const claimTransition = new wasm.TokenClaimTransition({ base: baseTransition, distributionType: wasm.TokenDistributionType.PreProgrammed, publicNote: 'bbbb' }); + + expect(claimTransition.distributionType).to.equal('PreProgrammed'); + }); + + it('should set distributionType', () => { + const claimTransition = new wasm.TokenClaimTransition({ base: baseTransition, distributionType: wasm.TokenDistributionType.Perpetual, publicNote: 'bbbb' }); + + claimTransition.distributionType = wasm.TokenDistributionType.Perpetual; + + expect(claimTransition.distributionType).to.equal('Perpetual'); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const claimTransition = new wasm.TokenClaimTransition({ base: baseTransition, distributionType: wasm.TokenDistributionType.PreProgrammed, publicNote: 'bbbb' }); + + expect(claimTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const claimTransition = new wasm.TokenClaimTransition({ base: baseTransition, distributionType: wasm.TokenDistributionType.Perpetual, publicNote: 'bbbb' }); + + claimTransition.publicNote = 'aaaa'; + + expect(claimTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenEmergencyActionTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const emergencyActionTransition = new wasm.TokenEmergencyActionTransition({ + base: baseTransition, + emergencyAction: wasm.TokenEmergencyAction.Pause, + publicNote: 'bbbb', + }); + + expect(emergencyActionTransition.constructor.name).to.equal('TokenEmergencyActionTransition'); + expect(emergencyActionTransition).to.be.an.instanceof(wasm.TokenEmergencyActionTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const emergencyActionTransition = new wasm.TokenEmergencyActionTransition({ base: baseTransition, emergencyAction: wasm.TokenEmergencyAction.Pause, publicNote: 'bbbb' }); + + expect(emergencyActionTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('emergencyAction', () => { + it('should return emergencyAction', () => { + const emergencyActionTransition = new wasm.TokenEmergencyActionTransition({ base: baseTransition, emergencyAction: wasm.TokenEmergencyAction.Pause, publicNote: 'bbbb' }); + + expect(emergencyActionTransition.emergencyAction).to.equal('Pause'); + }); + + it('should set emergencyAction', () => { + const emergencyActionTransition = new wasm.TokenEmergencyActionTransition({ base: baseTransition, emergencyAction: wasm.TokenEmergencyAction.Pause, publicNote: 'bbbb' }); + + emergencyActionTransition.emergencyAction = wasm.TokenEmergencyAction.Resume; + + expect(emergencyActionTransition.emergencyAction).to.equal('Resume'); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const emergencyActionTransition = new wasm.TokenEmergencyActionTransition({ base: baseTransition, emergencyAction: wasm.TokenEmergencyAction.Pause, publicNote: 'bbbb' }); + + expect(emergencyActionTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const emergencyActionTransition = new wasm.TokenEmergencyActionTransition({ base: baseTransition, emergencyAction: wasm.TokenEmergencyAction.Pause, publicNote: 'bbbb' }); + + emergencyActionTransition.publicNote = 'aaaa'; + + expect(emergencyActionTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenConfigUpdateTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const tradeMode = wasm.TokenTradeMode.NotTradeable(); + + const configUpdateTransition = new wasm.TokenConfigUpdateTransition({ base: baseTransition, updateTokenConfigurationItem: wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), publicNote: 'bbbb' }); + + expect(configUpdateTransition.constructor.name).to.equal('TokenConfigUpdateTransition'); + expect(configUpdateTransition).to.be.an.instanceof(wasm.TokenConfigUpdateTransition); + expect(tradeMode).to.be.an.instanceof(wasm.TokenTradeMode); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const tradeMode = wasm.TokenTradeMode.NotTradeable(); + + const configUpdateTransition = new wasm.TokenConfigUpdateTransition({ base: baseTransition, updateTokenConfigurationItem: wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), publicNote: 'bbbb' }); + + expect(configUpdateTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('updateTokenConfigurationItem', () => { + it('should return updateTokenConfigurationItem', () => { + const tradeMode = wasm.TokenTradeMode.NotTradeable(); + + const configUpdateTransition = new wasm.TokenConfigUpdateTransition({ base: baseTransition, updateTokenConfigurationItem: wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), publicNote: 'bbbb' }); + + expect(configUpdateTransition.updateTokenConfigurationItem.constructor.name).to.equal('TokenConfigurationChangeItem'); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const tradeMode = wasm.TokenTradeMode.NotTradeable(); + + const configUpdateTransition = new wasm.TokenConfigUpdateTransition({ base: baseTransition, updateTokenConfigurationItem: wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), publicNote: 'bbbb' }); + + expect(configUpdateTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + // At this moment available only one trade mode + const tradeMode = wasm.TokenTradeMode.NotTradeable(); + + const configUpdateTransition = new wasm.TokenConfigUpdateTransition({ base: baseTransition, updateTokenConfigurationItem: wasm.TokenConfigurationChangeItem.MarketplaceTradeModeItem(tradeMode), publicNote: 'bbbb' }); + + configUpdateTransition.publicNote = 'aaaa'; + + expect(configUpdateTransition.publicNote).to.equal('aaaa'); + }); + }); + }); + + describe('TokenDirectPurchaseTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition({ + base: baseTransition, + tokenCount: BigInt(111), + totalAgreedPrice: BigInt(111), + }); + + expect(directPurchaseTransition.constructor.name).to.equal('TokenDirectPurchaseTransition'); + expect(directPurchaseTransition).to.be.an.instanceof(wasm.TokenDirectPurchaseTransition); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition({ + base: baseTransition, + tokenCount: BigInt(111), + totalAgreedPrice: BigInt(111), + }); + + expect(directPurchaseTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('tokenCount', () => { + it('should return tokenCount', () => { + const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition({ + base: baseTransition, + tokenCount: BigInt(111), + totalAgreedPrice: BigInt(111), + }); + + expect(directPurchaseTransition.tokenCount).to.equal(BigInt(111)); + }); + + it('should set tokenCount', () => { + const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition({ + base: baseTransition, + tokenCount: BigInt(111), + totalAgreedPrice: BigInt(111), + }); + + directPurchaseTransition.tokenCount = BigInt(222); + + expect(directPurchaseTransition.tokenCount).to.equal(BigInt(222)); + }); + }); + + describe('totalAgreedPrice', () => { + it('should return totalAgreedPrice', () => { + const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition({ + base: baseTransition, + tokenCount: BigInt(111), + totalAgreedPrice: BigInt(111), + }); + + expect(directPurchaseTransition.totalAgreedPrice).to.equal(BigInt(111)); + }); + + it('should set totalAgreedPrice', () => { + const directPurchaseTransition = new wasm.TokenDirectPurchaseTransition({ + base: baseTransition, + tokenCount: BigInt(111), + totalAgreedPrice: BigInt(111), + }); + + directPurchaseTransition.totalAgreedPrice = BigInt(222); + + expect(directPurchaseTransition.totalAgreedPrice).to.equal(BigInt(222)); + }); + }); + }); + + describe('TokenSetPriceForDirectPurchaseTransition', () => { + describe('constructor', () => { + it('should create instance from values', () => { + const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); + + const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition({ base: baseTransition, price, publicNote: 'bbbb' }); + + expect(price.constructor.name).to.equal('TokenPricingSchedule'); + expect(setPriceDirectPurchaseTransition.constructor.name).to.equal('TokenSetPriceForDirectPurchaseTransition'); + expect(setPriceDirectPurchaseTransition).to.be.an.instanceof(wasm.TokenSetPriceForDirectPurchaseTransition); + expect(price).to.be.an.instanceof(wasm.TokenPricingSchedule); + expect(baseTransition).to.be.an.instanceof(wasm.TokenBaseTransition); + }); + }); + + describe('base', () => { + it('should return base', () => { + const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); + + const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition({ base: baseTransition, price, publicNote: 'bbbb' }); + + expect(setPriceDirectPurchaseTransition.base.constructor.name).to.equal('TokenBaseTransition'); + }); + }); + + describe('price', () => { + it('should return price', () => { + const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); + + const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition({ base: baseTransition, price, publicNote: 'bbbb' }); + + expect(setPriceDirectPurchaseTransition.price.constructor.name).to.equal('TokenPricingSchedule'); + }); + + it('should set price', () => { + const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); + + const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition({ base: baseTransition, price, publicNote: 'bbbb' }); + + setPriceDirectPurchaseTransition.price = wasm.TokenPricingSchedule.SetPrices({ 101: 1010 }); + + expect(setPriceDirectPurchaseTransition.price.constructor.name).to.equal('TokenPricingSchedule'); + }); + }); + + describe('publicNote', () => { + it('should return publicNote', () => { + const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); + + const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition({ base: baseTransition, price, publicNote: 'bbbb' }); + + expect(setPriceDirectPurchaseTransition.publicNote).to.equal('bbbb'); + }); + + it('should set publicNote', () => { + const price = wasm.TokenPricingSchedule.SetPrices({ 100: 1000 }); + + const setPriceDirectPurchaseTransition = new wasm.TokenSetPriceForDirectPurchaseTransition({ base: baseTransition, price, publicNote: 'bbbb' }); + + setPriceDirectPurchaseTransition.publicNote = 'aaaa'; + + expect(setPriceDirectPurchaseTransition.publicNote).to.equal('aaaa'); + }); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/helpers/chai.ts b/packages/wasm-dpp2/tests/unit/helpers/chai.ts new file mode 100644 index 00000000000..fb49541b171 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/helpers/chai.ts @@ -0,0 +1,9 @@ +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import dirtyChai from 'dirty-chai'; + +chai.use(chaiAsPromised); +chai.use(dirtyChai); + +export const { expect } = chai; +export default chai; diff --git a/packages/wasm-dpp2/tests/unit/helpers/wasm.js b/packages/wasm-dpp2/tests/unit/helpers/wasm.js deleted file mode 100644 index f0e65f36c57..00000000000 --- a/packages/wasm-dpp2/tests/unit/helpers/wasm.js +++ /dev/null @@ -1,30 +0,0 @@ -import init, * as wasmModule from '../../../dist/dpp.compressed.js'; - -let initialized = false; -let initPromise; - -/** - * - */ -async function ensureInitialized() { - if (initialized) { - return; - } - - if (!initPromise) { - initPromise = init(); - } - - await initPromise; - initialized = true; -} - -/** - * - */ -export async function getWasm() { - await ensureInitialized(); - return wasmModule; -} - -export default getWasm; diff --git a/packages/wasm-dpp2/tests/unit/js-value-to-json.spec.mjs b/packages/wasm-dpp2/tests/unit/js-value-to-json.spec.mjs deleted file mode 100644 index c4709f5d072..00000000000 --- a/packages/wasm-dpp2/tests/unit/js-value-to-json.spec.mjs +++ /dev/null @@ -1,467 +0,0 @@ -import { getWasm } from './helpers/wasm.js'; - -/** - * Tests for JavaScript value to JSON conversion via testJsValueToJson. - * - * These tests verify that normalize_js_value_for_json correctly handles - * various JavaScript types for JSON serialization: - * - * - Maps: converted to plain objects (keys become strings) - * - BigInt: converted to strings (JSON doesn't support BigInt) - * - Uint8Array: converted to regular arrays - * - WASM objects: their toJSON() method is called - * - Nested structures: recursively normalized - * - Primitives: passed through unchanged - */ - -describe('JS value to JSON conversion (testJsValueToJson)', () => { - let wasm; - - before(async () => { - wasm = await getWasm(); - }); - - describe('Map with string keys', () => { - it('should serialize empty Map to empty object', () => { - const emptyMap = new Map(); - - const json = wasm.testJsValueToJson(emptyMap); - - expect(json).to.deep.equal({}); - }); - - it('should serialize Map with string keys and primitive values', () => { - const map = new Map([ - ['key1', 'value1'], - ['key2', 42], - ['key3', true], - ['key4', null], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json).to.deep.equal({ - key1: 'value1', - key2: 42, - key3: true, - key4: null, - }); - }); - - it('should serialize Map with string keys and object values', () => { - const map = new Map([ - ['epoch1', { index: 1, startTime: 1000 }], - ['epoch2', { index: 2, startTime: 2000 }], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json).to.deep.equal({ - epoch1: { index: 1, startTime: 1000 }, - epoch2: { index: 2, startTime: 2000 }, - }); - }); - - it('should serialize Map with string keys and array values', () => { - const map = new Map([ - ['items1', [1, 2, 3]], - ['items2', ['a', 'b', 'c']], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json).to.deep.equal({ - items1: [1, 2, 3], - items2: ['a', 'b', 'c'], - }); - }); - }); - - describe('Map with numeric keys', () => { - it('should serialize Map with number keys (converted to strings)', () => { - // This simulates getEpochsInfo which returns Map - const map = new Map([ - [0, { index: 0, name: 'epoch0' }], - [1, { index: 1, name: 'epoch1' }], - [100, { index: 100, name: 'epoch100' }], - ]); - - const json = wasm.testJsValueToJson(map); - - // Keys should be strings in JSON - expect(json).to.have.property('0'); - expect(json).to.have.property('1'); - expect(json).to.have.property('100'); - expect(json['0']).to.deep.equal({ index: 0, name: 'epoch0' }); - expect(json['1']).to.deep.equal({ index: 1, name: 'epoch1' }); - expect(json['100']).to.deep.equal({ index: 100, name: 'epoch100' }); - }); - - it('should serialize Map with negative number keys', () => { - const map = new Map([ - [-1, 'negative one'], - [0, 'zero'], - [1, 'one'], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json).to.have.property('-1'); - expect(json).to.have.property('0'); - expect(json).to.have.property('1'); - expect(json['-1']).to.equal('negative one'); - }); - - it('should serialize Map with floating point keys', () => { - const map = new Map([ - [1.5, 'one point five'], - [2.7, 'two point seven'], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json).to.have.property('1.5'); - expect(json).to.have.property('2.7'); - }); - }); - - describe('Map with BigInt keys', () => { - it('should serialize Map with BigInt keys (converted to strings)', () => { - const map = new Map([ - [1n, 'one'], - [9007199254740993n, 'large number'], // > MAX_SAFE_INTEGER - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json).to.have.property('1'); - expect(json).to.have.property('9007199254740993'); - expect(json['1']).to.equal('one'); - expect(json['9007199254740993']).to.equal('large number'); - }); - }); - - describe('Map with BigInt values', () => { - it('should serialize Map with BigInt values (converted to strings)', () => { - // This simulates token balances or credit amounts - const map = new Map([ - ['balance1', 1000000000n], - ['balance2', 9007199254740993n], // > MAX_SAFE_INTEGER - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json.balance1).to.equal('1000000000'); - expect(json.balance2).to.equal('9007199254740993'); - }); - }); - - describe('Map with Identifier keys', () => { - it('should serialize Map with Identifier keys using toString()', () => { - const id1 = wasm.Identifier.fromBase58('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); - const id2 = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); - - // This simulates getEvonodesProposedEpochBlocksByIds which returns Map - const map = new Map([ - [id1, 100n], - [id2, 200n], - ]); - - const json = wasm.testJsValueToJson(map); - - // Keys should be the string representation of Identifier (Base58) - expect(json).to.have.property('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); - expect(json).to.have.property('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); - // Values are BigInt, should be strings - expect(json.H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1).to.equal('100'); - expect(json.ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U).to.equal('200'); - }); - }); - - describe('Map with WASM object values', () => { - it('should serialize Map with Identity values by calling their toJSON()', () => { - const identity = new wasm.Identity('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); - identity.balance = 1000000000n; - identity.revision = 5n; - - const map = new Map([ - ['identity1', identity], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json).to.have.property('identity1'); - expect(json.identity1).to.have.property('id'); - expect(json.identity1.id).to.equal('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); - expect(json.identity1.balance).to.equal(1000000000); - expect(json.identity1.revision).to.equal(5); - }); - - it('should serialize Map with Identifier values', () => { - const id1 = wasm.Identifier.fromBase58('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); - const id2 = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); - - const map = new Map([ - ['id1', id1], - ['id2', id2], - ]); - - const json = wasm.testJsValueToJson(map); - - // Identifier.toJSON() returns base58 string - expect(json.id1).to.equal('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); - expect(json.id2).to.equal('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); - }); - - it('should serialize Map with undefined/null values', () => { - // This simulates queries that return Map - const map = new Map([ - [0, { epoch: 0 }], - [1, undefined], - [2, null], - [3, { epoch: 3 }], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json['0']).to.deep.equal({ epoch: 0 }); - // Note: In JSON, undefined becomes null (JSON doesn't have undefined) - expect(json['1']).to.satisfy((v) => v === null || v === undefined); - expect(json['2']).to.equal(null); - expect(json['3']).to.deep.equal({ epoch: 3 }); - }); - }); - - describe('Nested Maps', () => { - it('should serialize nested Map as value', () => { - const innerMap = new Map([ - ['a', 1], - ['b', 2], - ]); - const outerMap = new Map([ - ['inner', innerMap], - ]); - - const json = wasm.testJsValueToJson(outerMap); - - expect(json).to.have.property('inner'); - expect(json.inner).to.deep.equal({ a: 1, b: 2 }); - }); - - it('should serialize deeply nested Maps', () => { - const level3 = new Map([['deep', 'value']]); - const level2 = new Map([['level3', level3]]); - const level1 = new Map([['level2', level2]]); - - const json = wasm.testJsValueToJson(level1); - - expect(json.level2.level3.deep).to.equal('value'); - }); - - it('should serialize Map inside array inside Map', () => { - const innerMap = new Map([['key', 'value']]); - const outerMap = new Map([ - ['items', [innerMap, { plain: 'object' }]], - ]); - - const json = wasm.testJsValueToJson(outerMap); - - expect(json.items[0]).to.deep.equal({ key: 'value' }); - expect(json.items[1]).to.deep.equal({ plain: 'object' }); - }); - }); - - describe('Map inside array', () => { - it('should serialize array containing Maps', () => { - const map1 = new Map([['a', 1]]); - const map2 = new Map([['b', 2]]); - const arrayWithMaps = [map1, map2]; - - const json = wasm.testJsValueToJson(arrayWithMaps); - - expect(json).to.be.an('array'); - expect(json[0]).to.deep.equal({ a: 1 }); - expect(json[1]).to.deep.equal({ b: 2 }); - }); - }); - - describe('Map inside object', () => { - it('should serialize object containing Map property', () => { - const map = new Map([['key', 'value']]); - const objectWithMap = { - normalProp: 'normal', - mapProp: map, - }; - - const json = wasm.testJsValueToJson(objectWithMap); - - expect(json.normalProp).to.equal('normal'); - expect(json.mapProp).to.deep.equal({ key: 'value' }); - }); - }); - - describe('Map with Uint8Array values', () => { - it('should serialize Map with Uint8Array values to arrays', () => { - const map = new Map([ - ['bytes1', new Uint8Array([1, 2, 3])], - ['bytes2', new Uint8Array([4, 5, 6])], - ]); - - const json = wasm.testJsValueToJson(map); - - // Uint8Array should be converted to regular arrays for JSON - expect(json.bytes1).to.deep.equal([1, 2, 3]); - expect(json.bytes2).to.deep.equal([4, 5, 6]); - }); - }); - - describe('Real-world epoch query simulation', () => { - it('should serialize epoch info Map like getEpochsInfoWithProofInfo returns', () => { - // Simulating the structure returned by getEpochsInfoWithProofInfo - const epochsMap = new Map([ - [0, { - index: 0, - firstBlockHeight: 1n, - firstCoreBlockHeight: 100, - startTime: 1609459200000n, - feeMultiplier: 1.0, - }], - [1, { - index: 1, - firstBlockHeight: 1000n, - firstCoreBlockHeight: 200, - startTime: 1609545600000n, - feeMultiplier: 1.1, - }], - [2, undefined], // Some epochs might not exist - ]); - - const json = wasm.testJsValueToJson(epochsMap); - - expect(json).to.have.property('0'); - expect(json).to.have.property('1'); - expect(json).to.have.property('2'); - - expect(json['0'].index).to.equal(0); - expect(json['0'].firstBlockHeight).to.equal('1'); // BigInt -> string - expect(json['0'].startTime).to.equal('1609459200000'); // BigInt -> string - - expect(json['1'].index).to.equal(1); - // Note: In JSON, undefined becomes null (JSON doesn't have undefined) - expect(json['2']).to.satisfy((v) => v === null || v === undefined); - }); - }); - - describe('Edge cases', () => { - it('should handle Map with special string keys', () => { - const map = new Map([ - ['', 'empty key'], - ['with spaces', 'spaced'], - ['with.dots', 'dotted'], - ['with/slash', 'slashed'], - ['with\\backslash', 'backslashed'], - ['unicode: \u00e9', 'accented'], - ]); - - const json = wasm.testJsValueToJson(map); - - expect(json['']).to.equal('empty key'); - expect(json['with spaces']).to.equal('spaced'); - expect(json['with.dots']).to.equal('dotted'); - expect(json['with/slash']).to.equal('slashed'); - expect(json['with\\backslash']).to.equal('backslashed'); - expect(json['unicode: \u00e9']).to.equal('accented'); - }); - - it('should preserve key order in Map', () => { - const map = new Map([ - ['z', 1], - ['a', 2], - ['m', 3], - ]); - - const json = wasm.testJsValueToJson(map); - const keys = Object.keys(json); - - // Maps preserve insertion order - expect(keys).to.deep.equal(['z', 'a', 'm']); - }); - - it('should handle large Maps', () => { - const map = new Map(); - for (let i = 0; i < 1000; i += 1) { - map.set(i, { index: i, value: `item${i}` }); - } - - const json = wasm.testJsValueToJson(map); - - expect(Object.keys(json).length).to.equal(1000); - expect(json['0']).to.deep.equal({ index: 0, value: 'item0' }); - expect(json['999']).to.deep.equal({ index: 999, value: 'item999' }); - }); - }); - - describe('Primitive values', () => { - it('should pass through strings', () => { - const result = wasm.testJsValueToJson('hello'); - expect(result).to.equal('hello'); - }); - - it('should pass through numbers', () => { - const result = wasm.testJsValueToJson(42); - expect(result).to.equal(42); - }); - - it('should pass through booleans', () => { - expect(wasm.testJsValueToJson(true)).to.equal(true); - expect(wasm.testJsValueToJson(false)).to.equal(false); - }); - - it('should pass through null', () => { - const result = wasm.testJsValueToJson(null); - expect(result).to.equal(null); - }); - - it('should convert BigInt to string', () => { - const result = wasm.testJsValueToJson(9007199254740993n); - expect(result).to.equal('9007199254740993'); - }); - - it('should convert Uint8Array to array', () => { - const result = wasm.testJsValueToJson(new Uint8Array([1, 2, 3])); - expect(result).to.deep.equal([1, 2, 3]); - }); - }); - - describe('Plain objects and arrays', () => { - it('should pass through plain objects', () => { - const obj = { a: 1, b: 'two', c: true }; - const result = wasm.testJsValueToJson(obj); - expect(result).to.deep.equal(obj); - }); - - it('should pass through arrays', () => { - const arr = [1, 'two', true, null]; - const result = wasm.testJsValueToJson(arr); - expect(result).to.deep.equal(arr); - }); - - it('should recursively handle nested objects with BigInt', () => { - const obj = { - outer: { - inner: { - value: 9007199254740993n, - }, - }, - }; - const result = wasm.testJsValueToJson(obj); - expect(result.outer.inner.value).to.equal('9007199254740993'); - }); - - it('should recursively handle arrays with BigInt', () => { - const arr = [1n, 2n, 9007199254740993n]; - const result = wasm.testJsValueToJson(arr); - expect(result).to.deep.equal(['1', '2', '9007199254740993']); - }); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/js-value-to-json.spec.ts b/packages/wasm-dpp2/tests/unit/js-value-to-json.spec.ts new file mode 100644 index 00000000000..fbcd211b9e7 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/js-value-to-json.spec.ts @@ -0,0 +1,478 @@ +import { expect } from './helpers/chai.ts'; +import { initWasm, wasm } from '../../dist/dpp.compressed.js'; + +/** + * Tests for JavaScript value to JSON conversion via testJsValueToJson. + * + * These tests verify that normalize_js_value_for_json correctly handles + * various JavaScript types for JSON serialization: + * + * - Maps: converted to plain objects (keys become strings) + * - BigInt: converted to strings (JSON doesn't support BigInt) + * - Uint8Array: converted to regular arrays + * - WASM objects: their toJSON() method is called + * - Nested structures: recursively normalized + * - Primitives: passed through unchanged + */ + +before(async () => { + await initWasm(); +}); + +describe('testJsValueToJson', () => { + describe('testJsValueToJson()', () => { + describe('Map with string keys', () => { + it('should serialize empty Map to empty object', () => { + const emptyMap = new Map(); + + const json = wasm.testJsValueToJson(emptyMap); + + expect(json).to.deep.equal({}); + }); + + it('should serialize Map with string keys and primitive values', () => { + const map = new Map([ + ['key1', 'value1'], + ['key2', 42], + ['key3', true], + ['key4', null], + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json).to.deep.equal({ + key1: 'value1', + key2: 42, + key3: true, + key4: null, + }); + }); + + it('should serialize Map with string keys and object values', () => { + const map = new Map([ + ['epoch1', { index: 1, startTime: 1000 }], + ['epoch2', { index: 2, startTime: 2000 }], + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json).to.deep.equal({ + epoch1: { index: 1, startTime: 1000 }, + epoch2: { index: 2, startTime: 2000 }, + }); + }); + + it('should serialize Map with string keys and array values', () => { + const map = new Map([ + ['items1', [1, 2, 3]], + ['items2', ['a', 'b', 'c']], + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json).to.deep.equal({ + items1: [1, 2, 3], + items2: ['a', 'b', 'c'], + }); + }); + }); + + describe('Map with numeric keys', () => { + it('should serialize Map with number keys (converted to strings)', () => { + // This simulates getEpochsInfo which returns Map + const map = new Map([ + [0, { index: 0, name: 'epoch0' }], + [1, { index: 1, name: 'epoch1' }], + [100, { index: 100, name: 'epoch100' }], + ]); + + const json = wasm.testJsValueToJson(map); + + // Keys should be strings in JSON + expect(json).to.have.property('0'); + expect(json).to.have.property('1'); + expect(json).to.have.property('100'); + expect(json['0']).to.deep.equal({ index: 0, name: 'epoch0' }); + expect(json['1']).to.deep.equal({ index: 1, name: 'epoch1' }); + expect(json['100']).to.deep.equal({ index: 100, name: 'epoch100' }); + }); + + it('should serialize Map with negative number keys', () => { + const map = new Map([ + [-1, 'negative one'], + [0, 'zero'], + [1, 'one'], + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json).to.have.property('-1'); + expect(json).to.have.property('0'); + expect(json).to.have.property('1'); + expect(json['-1']).to.equal('negative one'); + }); + + it('should serialize Map with floating point keys', () => { + const map = new Map([ + [1.5, 'one point five'], + [2.7, 'two point seven'], + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json).to.have.property('1.5'); + expect(json).to.have.property('2.7'); + }); + }); + + describe('Map with BigInt keys', () => { + it('should serialize Map with BigInt keys (converted to strings)', () => { + const map = new Map([ + [1n, 'one'], + [9007199254740993n, 'large number'], // > MAX_SAFE_INTEGER + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json).to.have.property('1'); + expect(json).to.have.property('9007199254740993'); + expect(json['1']).to.equal('one'); + expect(json['9007199254740993']).to.equal('large number'); + }); + }); + + describe('Map with BigInt values', () => { + it('should serialize Map with BigInt values (converted to strings)', () => { + // This simulates token balances or credit amounts + const map = new Map([ + ['balance1', 1000000000n], + ['balance2', 9007199254740993n], // > MAX_SAFE_INTEGER + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json.balance1).to.equal('1000000000'); + expect(json.balance2).to.equal('9007199254740993'); + }); + }); + + describe('Map with Identifier keys', () => { + it('should serialize Map with Identifier keys using toString()', () => { + const id1 = wasm.Identifier.fromBase58('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); + const id2 = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); + + // This simulates getEvonodesProposedEpochBlocksByIds which returns Map + const map = new Map([ + [id1, 100n], + [id2, 200n], + ]); + + const json = wasm.testJsValueToJson(map); + + // Keys should be the string representation of Identifier (Base58) + expect(json).to.have.property('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); + expect(json).to.have.property('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); + // Values are BigInt, should be strings + expect(json.H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1).to.equal('100'); + expect(json.ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U).to.equal('200'); + }); + }); + + describe('Map with WASM object values', () => { + it('should serialize Map with Identity values by calling their toJSON()', () => { + const identity = new wasm.Identity('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); + identity.balance = 1000000000n; + identity.revision = 5n; + + const map = new Map([['identity1', identity]]); + + const json = wasm.testJsValueToJson(map); + + expect(json).to.have.property('identity1'); + expect(json.identity1).to.have.property('id'); + expect(json.identity1.id).to.equal('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); + expect(json.identity1.balance).to.equal(1000000000); + expect(json.identity1.revision).to.equal(5); + }); + + it('should serialize Map with Identifier values', () => { + const id1 = wasm.Identifier.fromBase58('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); + const id2 = wasm.Identifier.fromBase58('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); + + const map = new Map([ + ['id1', id1], + ['id2', id2], + ]); + + const json = wasm.testJsValueToJson(map); + + // Identifier.toJSON() returns base58 string + expect(json.id1).to.equal('H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'); + expect(json.id2).to.equal('ckBqfQe7LU7vwrwXopyCB4n5phZShjA16BGhNGpsD5U'); + }); + + it('should serialize Map with undefined/null values', () => { + // This simulates queries that return Map + const map = new Map([ + [0, { epoch: 0 }], + [1, undefined], + [2, null], + [3, { epoch: 3 }], + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json['0']).to.deep.equal({ epoch: 0 }); + // Note: In JSON, undefined becomes null (JSON doesn't have undefined) + expect(json['1']).to.satisfy((v: unknown) => v === null || v === undefined); + expect(json['2']).to.equal(null); + expect(json['3']).to.deep.equal({ epoch: 3 }); + }); + }); + + describe('Nested Maps', () => { + it('should serialize nested Map as value', () => { + const innerMap = new Map([ + ['a', 1], + ['b', 2], + ]); + const outerMap = new Map([['inner', innerMap]]); + + const json = wasm.testJsValueToJson(outerMap); + + expect(json).to.have.property('inner'); + expect(json.inner).to.deep.equal({ a: 1, b: 2 }); + }); + + it('should serialize deeply nested Maps', () => { + const level3 = new Map([['deep', 'value']]); + const level2 = new Map([['level3', level3]]); + const level1 = new Map([['level2', level2]]); + + const json = wasm.testJsValueToJson(level1); + + expect(json.level2.level3.deep).to.equal('value'); + }); + + it('should serialize Map inside array inside Map', () => { + const innerMap = new Map([['key', 'value']]); + const outerMap = new Map([['items', [innerMap, { plain: 'object' }]]]); + + const json = wasm.testJsValueToJson(outerMap); + + expect(json.items[0]).to.deep.equal({ key: 'value' }); + expect(json.items[1]).to.deep.equal({ plain: 'object' }); + }); + }); + + describe('Map inside array', () => { + it('should serialize array containing Maps', () => { + const map1 = new Map([['a', 1]]); + const map2 = new Map([['b', 2]]); + const arrayWithMaps = [map1, map2]; + + const json = wasm.testJsValueToJson(arrayWithMaps); + + expect(json).to.be.an('array'); + expect(json[0]).to.deep.equal({ a: 1 }); + expect(json[1]).to.deep.equal({ b: 2 }); + }); + }); + + describe('Map inside object', () => { + it('should serialize object containing Map property', () => { + const map = new Map([['key', 'value']]); + const objectWithMap = { + normalProp: 'normal', + mapProp: map, + }; + + const json = wasm.testJsValueToJson(objectWithMap); + + expect(json.normalProp).to.equal('normal'); + expect(json.mapProp).to.deep.equal({ key: 'value' }); + }); + }); + + describe('Map with Uint8Array values', () => { + it('should serialize Map with Uint8Array values to arrays', () => { + const map = new Map([ + ['bytes1', new Uint8Array([1, 2, 3])], + ['bytes2', new Uint8Array([4, 5, 6])], + ]); + + const json = wasm.testJsValueToJson(map); + + // Uint8Array should be converted to regular arrays for JSON + expect(json.bytes1).to.deep.equal([1, 2, 3]); + expect(json.bytes2).to.deep.equal([4, 5, 6]); + }); + }); + + describe('Real-world epoch query simulation', () => { + it('should serialize epoch info Map like getEpochsInfoWithProofInfo returns', () => { + // Simulating the structure returned by getEpochsInfoWithProofInfo + const epochsMap = new Map< + number, + | { + index: number; + firstBlockHeight: bigint; + firstCoreBlockHeight: number; + startTime: bigint; + feeMultiplier: number; + } + | undefined + >([ + [ + 0, + { + index: 0, + firstBlockHeight: 1n, + firstCoreBlockHeight: 100, + startTime: 1609459200000n, + feeMultiplier: 1.0, + }, + ], + [ + 1, + { + index: 1, + firstBlockHeight: 1000n, + firstCoreBlockHeight: 200, + startTime: 1609545600000n, + feeMultiplier: 1.1, + }, + ], + [2, undefined], // Some epochs might not exist + ]); + + const json = wasm.testJsValueToJson(epochsMap); + + expect(json).to.have.property('0'); + expect(json).to.have.property('1'); + expect(json).to.have.property('2'); + + expect(json['0'].index).to.equal(0); + expect(json['0'].firstBlockHeight).to.equal('1'); // BigInt -> string + expect(json['0'].startTime).to.equal('1609459200000'); // BigInt -> string + + expect(json['1'].index).to.equal(1); + // Note: In JSON, undefined becomes null (JSON doesn't have undefined) + expect(json['2']).to.satisfy((v: unknown) => v === null || v === undefined); + }); + }); + + describe('Edge cases', () => { + it('should handle Map with special string keys', () => { + const map = new Map([ + ['', 'empty key'], + ['with spaces', 'spaced'], + ['with.dots', 'dotted'], + ['with/slash', 'slashed'], + ['with\\backslash', 'backslashed'], + ['unicode: \u00e9', 'accented'], + ]); + + const json = wasm.testJsValueToJson(map); + + expect(json['']).to.equal('empty key'); + expect(json['with spaces']).to.equal('spaced'); + expect(json['with.dots']).to.equal('dotted'); + expect(json['with/slash']).to.equal('slashed'); + expect(json['with\\backslash']).to.equal('backslashed'); + expect(json['unicode: \u00e9']).to.equal('accented'); + }); + + it('should preserve key order in Map', () => { + const map = new Map([ + ['z', 1], + ['a', 2], + ['m', 3], + ]); + + const json = wasm.testJsValueToJson(map); + const keys = Object.keys(json); + + // Maps preserve insertion order + expect(keys).to.deep.equal(['z', 'a', 'm']); + }); + + it('should handle large Maps', () => { + const map = new Map(); + for (let i = 0; i < 1000; i += 1) { + map.set(i, { index: i, value: `item${i}` }); + } + + const json = wasm.testJsValueToJson(map); + + expect(Object.keys(json).length).to.equal(1000); + expect(json['0']).to.deep.equal({ index: 0, value: 'item0' }); + expect(json['999']).to.deep.equal({ index: 999, value: 'item999' }); + }); + }); + + describe('Primitive values', () => { + it('should pass through strings', () => { + const result = wasm.testJsValueToJson('hello'); + expect(result).to.equal('hello'); + }); + + it('should pass through numbers', () => { + const result = wasm.testJsValueToJson(42); + expect(result).to.equal(42); + }); + + it('should pass through booleans', () => { + expect(wasm.testJsValueToJson(true)).to.equal(true); + expect(wasm.testJsValueToJson(false)).to.equal(false); + }); + + it('should pass through null', () => { + const result = wasm.testJsValueToJson(null); + expect(result).to.equal(null); + }); + + it('should convert BigInt to string', () => { + const result = wasm.testJsValueToJson(9007199254740993n); + expect(result).to.equal('9007199254740993'); + }); + + it('should convert Uint8Array to array', () => { + const result = wasm.testJsValueToJson(new Uint8Array([1, 2, 3])); + expect(result).to.deep.equal([1, 2, 3]); + }); + }); + + describe('Plain objects and arrays', () => { + it('should pass through plain objects', () => { + const obj = { a: 1, b: 'two', c: true }; + const result = wasm.testJsValueToJson(obj); + expect(result).to.deep.equal(obj); + }); + + it('should pass through arrays', () => { + const arr = [1, 'two', true, null]; + const result = wasm.testJsValueToJson(arr); + expect(result).to.deep.equal(arr); + }); + + it('should recursively handle nested objects with BigInt', () => { + const obj = { + outer: { + inner: { + value: 9007199254740993n, + }, + }, + }; + const result = wasm.testJsValueToJson(obj); + expect(result.outer.inner.value).to.equal('9007199254740993'); + }); + + it('should recursively handle arrays with BigInt', () => { + const arr = [1n, 2n, 9007199254740993n]; + const result = wasm.testJsValueToJson(arr); + expect(result).to.deep.equal(['1', '2', '9007199254740993']); + }); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/mocks/DataContract/index.ts b/packages/wasm-dpp2/tests/unit/mocks/DataContract/index.ts new file mode 100644 index 00000000000..bbcc40c5e7e --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/DataContract/index.ts @@ -0,0 +1,10 @@ +import json from './json.js'; +import object from './object.js'; + +// Keep 'value' as alias to json for backward compatibility with existing tests +export { json as value, json, object }; +export const id = '4fJLR2GYTPFdomuTVvNy3VRrvWgvkKPzqehEBpNf2nk6'; +export const ownerId = '11111111111111111111111111111111'; +export const dataContractsBytes = [ + '00ea8920edea52fa400de2ccc43052b2821f45585241a2875d4250e35d4ce937c800000000000101000001ab321b19457b1c16b12762509276d47d952f582d978cbd8b50bbfc2fd8a7767d0001046e6f7465160312047479706512066f626a656374120a70726f70657274696573160112076d65737361676516021204747970651206737472696e671208706f736974696f6e030012146164646974696f6e616c50726f706572746965731300', +]; diff --git a/packages/wasm-dpp2/tests/unit/mocks/DataContract/json.ts b/packages/wasm-dpp2/tests/unit/mocks/DataContract/json.ts new file mode 100644 index 00000000000..ad1ac34bfb4 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/DataContract/json.ts @@ -0,0 +1,110 @@ +export default { + $format_version: '0', + id: '4fJLR2GYTPFdomuTVvNy3VRrvWgvkKPzqehEBpNf2nk6', + config: { + $format_version: '0', + canBeDeleted: false, + readonly: false, + keepsHistory: false, + documentsKeepHistoryContractDefault: false, + documentsMutableContractDefault: true, + documentsCanBeDeletedContractDefault: true, + requiresIdentityEncryptionBoundedKey: null, + requiresIdentityDecryptionBoundedKey: null, + }, + version: 1, + ownerId: '11111111111111111111111111111111', + schemaDefs: null, + documentSchemas: { + withdrawal: { + description: + 'Withdrawal document to track underlying withdrawal transactions. Withdrawals should be created with IdentityWithdrawalTransition', + creationRestrictionMode: 2, + type: 'object', + indices: [ + { + name: 'identityStatus', + properties: [{ $ownerId: 'asc' }, { status: 'asc' }, { $createdAt: 'asc' }], + unique: false, + }, + { + name: 'identityRecent', + properties: [{ $ownerId: 'asc' }, { $updatedAt: 'asc' }, { status: 'asc' }], + unique: false, + }, + { + name: 'pooling', + properties: [ + { status: 'asc' }, + { pooling: 'asc' }, + { coreFeePerByte: 'asc' }, + { $updatedAt: 'asc' }, + ], + unique: false, + }, + { + name: 'transaction', + properties: [{ status: 'asc' }, { transactionIndex: 'asc' }], + unique: false, + }, + ], + properties: { + transactionIndex: { + type: 'integer', + description: + 'Sequential index of asset unlock (withdrawal) transaction. Populated when a withdrawal pooled into withdrawal transaction', + minimum: 1, + position: 0, + }, + transactionSignHeight: { + type: 'integer', + description: 'The Core height on which transaction was signed', + minimum: 1, + position: 1, + }, + amount: { + type: 'integer', + description: 'The amount to be withdrawn', + minimum: 1000, + position: 2, + }, + coreFeePerByte: { + type: 'integer', + description: 'This is the fee that you are willing to spend for this transaction in Duffs/Byte', + minimum: 1, + maximum: 4294967295, + position: 3, + }, + pooling: { + type: 'integer', + description: 'This indicated the level at which Platform should try to pool this transaction', + enum: [0, 1, 2], + position: 4, + }, + outputScript: { + type: 'array', + byteArray: true, + minItems: 23, + maxItems: 25, + position: 5, + }, + status: { + type: 'integer', + enum: [0, 1, 2, 3, 4], + description: '0 - Pending, 1 - Signed, 2 - Broadcasted, 3 - Complete, 4 - Expired', + position: 6, + }, + }, + additionalProperties: false, + required: [ + '$createdAt', + '$updatedAt', + 'amount', + 'coreFeePerByte', + 'pooling', + 'outputScript', + 'status', + ], + }, + }, +}; diff --git a/packages/wasm-dpp2/tests/unit/mocks/DataContract/object.ts b/packages/wasm-dpp2/tests/unit/mocks/DataContract/object.ts new file mode 100644 index 00000000000..d672ee52c19 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/DataContract/object.ts @@ -0,0 +1,113 @@ +import bs58 from 'bs58'; + +// Object format uses Uint8Array for identifiers and BigInt for integers +export default { + $format_version: '0', + id: bs58.decode('4fJLR2GYTPFdomuTVvNy3VRrvWgvkKPzqehEBpNf2nk6'), + config: { + $format_version: '0', + canBeDeleted: false, + readonly: false, + keepsHistory: false, + documentsKeepHistoryContractDefault: false, + documentsMutableContractDefault: true, + documentsCanBeDeletedContractDefault: true, + requiresIdentityEncryptionBoundedKey: undefined, + requiresIdentityDecryptionBoundedKey: undefined, + }, + version: 1n, + ownerId: bs58.decode('11111111111111111111111111111111'), + schemaDefs: null, + documentSchemas: { + withdrawal: { + description: + 'Withdrawal document to track underlying withdrawal transactions. Withdrawals should be created with IdentityWithdrawalTransition', + creationRestrictionMode: 2n, + type: 'object', + indices: [ + { + name: 'identityStatus', + properties: [{ $ownerId: 'asc' }, { status: 'asc' }, { $createdAt: 'asc' }], + unique: false, + }, + { + name: 'identityRecent', + properties: [{ $ownerId: 'asc' }, { $updatedAt: 'asc' }, { status: 'asc' }], + unique: false, + }, + { + name: 'pooling', + properties: [ + { status: 'asc' }, + { pooling: 'asc' }, + { coreFeePerByte: 'asc' }, + { $updatedAt: 'asc' }, + ], + unique: false, + }, + { + name: 'transaction', + properties: [{ status: 'asc' }, { transactionIndex: 'asc' }], + unique: false, + }, + ], + properties: { + transactionIndex: { + type: 'integer', + description: + 'Sequential index of asset unlock (withdrawal) transaction. Populated when a withdrawal pooled into withdrawal transaction', + minimum: 1n, + position: 0n, + }, + transactionSignHeight: { + type: 'integer', + description: 'The Core height on which transaction was signed', + minimum: 1n, + position: 1n, + }, + amount: { + type: 'integer', + description: 'The amount to be withdrawn', + minimum: 1000n, + position: 2n, + }, + coreFeePerByte: { + type: 'integer', + description: 'This is the fee that you are willing to spend for this transaction in Duffs/Byte', + minimum: 1n, + maximum: 4294967295n, + position: 3n, + }, + pooling: { + type: 'integer', + description: 'This indicated the level at which Platform should try to pool this transaction', + enum: [0n, 1n, 2n], + position: 4n, + }, + outputScript: { + type: 'array', + byteArray: true, + minItems: 23n, + maxItems: 25n, + position: 5n, + }, + status: { + type: 'integer', + enum: [0n, 1n, 2n, 3n, 4n], + description: '0 - Pending, 1 - Signed, 2 - Broadcasted, 3 - Complete, 4 - Expired', + position: 6n, + }, + }, + additionalProperties: false, + required: [ + '$createdAt', + '$updatedAt', + 'amount', + 'coreFeePerByte', + 'pooling', + 'outputScript', + 'status', + ], + }, + }, +}; diff --git a/packages/wasm-dpp2/tests/unit/mocks/Document/dataContract.ts b/packages/wasm-dpp2/tests/unit/mocks/Document/dataContract.ts new file mode 100644 index 00000000000..17063d052c5 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/Document/dataContract.ts @@ -0,0 +1,23 @@ +export default { + $format_version: '0', + version: 1, + ownerId: '11111111111111111111111111111111', + schemaDefs: null, + id: '4fJLR2GYTPFdomuTVvNy3VRrvWgvkKPzqehEBpNf2nk6', + documentSchemas: { + note: { + type: 'object', + properties: { + author: { + type: 'string', + position: 1, + }, + message: { + type: 'string', + position: 0, + }, + }, + additionalProperties: false, + }, + }, +}; diff --git a/packages/wasm-dpp2/tests/unit/mocks/Document/document.ts b/packages/wasm-dpp2/tests/unit/mocks/Document/document.ts new file mode 100644 index 00000000000..53332a2649a --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/Document/document.ts @@ -0,0 +1,3 @@ +export default { + message: 'Tutorial CI Test @ Tue, 07 Jan 2025 15:27:50 GMT', +}; diff --git a/packages/wasm-dpp2/tests/unit/mocks/Document/document2.ts b/packages/wasm-dpp2/tests/unit/mocks/Document/document2.ts new file mode 100644 index 00000000000..bad011749ef --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/Document/document2.ts @@ -0,0 +1,3 @@ +export default { + message: 'bb', +}; diff --git a/packages/wasm-dpp2/tests/unit/mocks/Document/index.ts b/packages/wasm-dpp2/tests/unit/mocks/Document/index.ts new file mode 100644 index 00000000000..19d959a4e46 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/Document/index.ts @@ -0,0 +1,12 @@ +import document from './document.js'; +import document2 from './document2.js'; +import dataContractValue from './dataContract.js'; + +export { document, document2, dataContractValue }; + +export const documentTypeName = 'note'; +export const revision = BigInt(1); +export const dataContractId = 'GnXgMaiqAwTxh44ccQe8AoCgFvcseHK5CncH3sUorW4X'; +export const ownerId = 'CXH2kZCATjvDTnQAPVg28EgPg9WySUvwvnR5ZkmNqY5i'; +export const id = '9tSsCqKHTZ8ro16MydChSxgHBukFW36eMLJKKRtebJEn'; +export const documentBytes = '00840b5cec9f0401b1950610e85dcb26829122ac8853464e1e2c7e38ed22b48903ab321b19457b1c16b12762509276d47d952f582d978cbd8b50bbfc2fd8a7767d01000001305475746f7269616c20434920546573742040205475652c203037204a616e20323032352031353a32373a353020474d5400'; diff --git a/packages/wasm-dpp2/tests/unit/mocks/Identity/index.ts b/packages/wasm-dpp2/tests/unit/mocks/Identity/index.ts new file mode 100644 index 00000000000..488a7f08911 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/Identity/index.ts @@ -0,0 +1,11 @@ +export const identifier = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; +export const identifierBytes = [ + 238, 50, 96, 211, 63, 140, 169, 225, 76, 97, 8, 6, 212, 109, 184, 253, 51, 67, 82, 42, 208, 228, + 72, 192, 215, 137, 161, 88, 144, 55, 244, 230, +]; +export const balance = BigInt(100); +export const revision = BigInt(99111); +export const identityBytesWithoutKeys = [ + 0, 238, 50, 96, 211, 63, 140, 169, 225, 76, 97, 8, 6, 212, 109, 184, 253, 51, 67, 82, 42, 208, + 228, 72, 192, 215, 137, 161, 88, 144, 55, 244, 230, 0, 0, 0, +]; diff --git a/packages/wasm-dpp2/tests/unit/mocks/Locks/index.ts b/packages/wasm-dpp2/tests/unit/mocks/Locks/index.ts new file mode 100644 index 00000000000..a9488486d86 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/Locks/index.ts @@ -0,0 +1,25 @@ +export const instantLockBytes = new Uint8Array([ + 1, 1, 89, 68, 206, 254, 139, 111, 183, 115, 169, 122, 19, 26, 29, 175, 97, 14, 156, 207, 215, 16, + 92, 152, 110, 29, 167, 34, 91, 149, 243, 48, 250, 217, 0, 0, 0, 0, 61, 111, 50, 237, 225, 255, 25, + 159, 133, 89, 244, 234, 150, 19, 61, 198, 218, 144, 144, 44, 45, 189, 109, 187, 247, 117, 93, 95, + 156, 46, 12, 216, 1, 49, 33, 55, 67, 236, 100, 131, 20, 54, 98, 71, 159, 60, 21, 2, 116, 197, 18, + 154, 171, 227, 15, 30, 21, 0, 0, 0, 0, 0, 0, 0, 169, 241, 49, 98, 108, 73, 162, 241, 131, 183, + 162, 245, 99, 173, 29, 197, 10, 200, 34, 1, 144, 219, 237, 184, 5, 32, 155, 96, 142, 184, 100, + 224, 29, 98, 241, 139, 201, 250, 166, 10, 139, 138, 39, 245, 160, 199, 200, 185, 20, 250, 58, 20, + 54, 10, 47, 37, 85, 142, 224, 224, 166, 147, 177, 143, 172, 203, 181, 158, 195, 155, 155, 60, 174, + 67, 14, 11, 118, 235, 8, 7, 82, 206, 16, 61, 247, 101, 55, 161, 165, 131, 104, 10, 89, 20, 82, + 157, +]); +export const transactionBytes = new Uint8Array([ + 3, 0, 8, 0, 1, 89, 68, 206, 254, 139, 111, 183, 115, 169, 122, 19, 26, 29, 175, 97, 14, 156, 207, + 215, 16, 92, 152, 110, 29, 167, 34, 91, 149, 243, 48, 250, 217, 0, 0, 0, 0, 107, 72, 48, 69, 2, + 33, 0, 157, 215, 234, 11, 75, 36, 23, 153, 82, 143, 163, 76, 75, 118, 142, 19, 6, 13, 64, 50, 24, + 199, 141, 199, 163, 14, 86, 81, 67, 150, 240, 28, 2, 32, 105, 238, 106, 123, 228, 237, 166, 210, + 251, 103, 249, 36, 15, 233, 177, 30, 40, 125, 67, 108, 224, 183, 4, 5, 18, 239, 231, 185, 223, + 195, 92, 240, 1, 33, 3, 238, 76, 67, 141, 205, 25, 38, 200, 164, 105, 53, 55, 189, 36, 52, 232, + 121, 166, 108, 186, 227, 161, 55, 7, 105, 135, 102, 219, 224, 117, 213, 70, 255, 255, 255, 255, 2, + 128, 29, 44, 4, 0, 0, 0, 0, 2, 106, 0, 48, 232, 38, 1, 0, 0, 0, 0, 25, 118, 169, 20, 232, 101, + 217, 39, 144, 120, 74, 135, 230, 203, 134, 239, 207, 15, 238, 152, 16, 172, 45, 177, 136, 172, 0, + 0, 0, 0, 36, 1, 1, 128, 29, 44, 4, 0, 0, 0, 0, 25, 118, 169, 20, 12, 182, 70, 130, 142, 161, 106, + 83, 94, 200, 33, 4, 251, 5, 50, 93, 28, 107, 159, 168, 136, 172, +]); diff --git a/packages/wasm-dpp2/tests/unit/mocks/PrivateKey/index.ts b/packages/wasm-dpp2/tests/unit/mocks/PrivateKey/index.ts new file mode 100644 index 00000000000..6750212b433 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/PrivateKey/index.ts @@ -0,0 +1,5 @@ +export const wif = 'cR4EZ2nAvCmn2cFepKn7UgSSQFgFTjkySAchvcoiEVdm48eWjQGn'; + +export const bytes = '67ad1669d882da256b6fa05e1b0ae384a6ac8aed146ea53602b8ff0e1e9c18e9'; + +export const publicKeyHash = '622fd260c35f0d826d05983d1f0524b02dec27a0'; diff --git a/packages/wasm-dpp2/tests/unit/mocks/PublicKey/index.js b/packages/wasm-dpp2/tests/unit/mocks/PublicKey/index.js index b61580480b3..6c0ff3d0068 100644 --- a/packages/wasm-dpp2/tests/unit/mocks/PublicKey/index.js +++ b/packages/wasm-dpp2/tests/unit/mocks/PublicKey/index.js @@ -2,10 +2,12 @@ export const keyId = 2; export const purpose = 'AUTHENTICATION'; export const securityLevel = 'CRITICAL'; export const keyType = 'ECDSA_SECP256K1'; -export const binaryData = '036a394312e40e81d928fde2bde7880070e4fa9c1d1d9b168da707ea468afa2b48'; +export const binaryDataHex = '036a394312e40e81d928fde2bde7880070e4fa9c1d1d9b168da707ea468afa2b48'; +export const binaryData = Buffer.from(binaryDataHex, 'hex'); export const keyIdSet = 3; export const purposeSet = 'ENCRYPTION'; export const securityLevelSet = 'HIGH'; export const keyTypeSet = 'ECDSA_HASH160'; -export const binaryDataSet = '0300000002e40e81d928fde2bde7880070e4fa9c1d1d9b168da707ea468afa2b48'; +export const binaryDataSetHex = '0300000002e40e81d928fde2bde7880070e4fa9c1d1d9b168da707ea468afa2b48'; +export const binaryDataSet = Buffer.from(binaryDataSetHex, 'hex'); diff --git a/packages/wasm-dpp2/tests/unit/mocks/PublicKey/index.ts b/packages/wasm-dpp2/tests/unit/mocks/PublicKey/index.ts new file mode 100644 index 00000000000..6c0ff3d0068 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/PublicKey/index.ts @@ -0,0 +1,13 @@ +export const keyId = 2; +export const purpose = 'AUTHENTICATION'; +export const securityLevel = 'CRITICAL'; +export const keyType = 'ECDSA_SECP256K1'; +export const binaryDataHex = '036a394312e40e81d928fde2bde7880070e4fa9c1d1d9b168da707ea468afa2b48'; +export const binaryData = Buffer.from(binaryDataHex, 'hex'); + +export const keyIdSet = 3; +export const purposeSet = 'ENCRYPTION'; +export const securityLevelSet = 'HIGH'; +export const keyTypeSet = 'ECDSA_HASH160'; +export const binaryDataSetHex = '0300000002e40e81d928fde2bde7880070e4fa9c1d1d9b168da707ea468afa2b48'; +export const binaryDataSet = Buffer.from(binaryDataSetHex, 'hex'); diff --git a/packages/wasm-dpp2/tests/unit/mocks/TokenConfiguration/index.ts b/packages/wasm-dpp2/tests/unit/mocks/TokenConfiguration/index.ts new file mode 100644 index 00000000000..893c659dc79 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/mocks/TokenConfiguration/index.ts @@ -0,0 +1,8 @@ +const tokenLocalization = { + $format_version: '0', + shouldCapitalize: true, + singularForm: 'TOKEN', + pluralForm: 'TOKENS', +}; + +export default tokenLocalization; diff --git a/packages/wasm-dpp2/tests/unit/module-load.spec.mjs b/packages/wasm-dpp2/tests/unit/module-load.spec.mjs deleted file mode 100644 index 8e749ac8e1f..00000000000 --- a/packages/wasm-dpp2/tests/unit/module-load.spec.mjs +++ /dev/null @@ -1,19 +0,0 @@ -import init, { - StateTransition, - ConsensusError, -} from '../../dist/dpp.compressed.js'; - -describe('wasm-dpp2 module', () => { - before(async () => { - await init(); - }); - - it('exposes state transition bindings', () => { - expect(StateTransition).to.be.a('function'); - }); - - it('exposes consensus error helpers', () => { - expect(ConsensusError).to.be.a('function'); - expect(ConsensusError.deserialize).to.be.a('function'); - }); -}); diff --git a/packages/wasm-dpp2/tests/unit/module-load.spec.ts b/packages/wasm-dpp2/tests/unit/module-load.spec.ts new file mode 100644 index 00000000000..90cacca38b0 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/module-load.spec.ts @@ -0,0 +1,26 @@ +import { expect } from './helpers/chai.ts'; +import init, { StateTransition, ConsensusError } from '../../dist/dpp.compressed.js'; + +before(async () => { + await init(); +}); + +describe('wasm-dpp2 module', () => { + describe('StateTransition', () => { + it('should be exposed as a function', () => { + expect(StateTransition).to.be.a('function'); + }); + }); + + describe('ConsensusError', () => { + it('should be exposed as a function', () => { + expect(ConsensusError).to.be.a('function'); + }); + + describe('deserialize()', () => { + it('should be exposed as a function', () => { + expect(ConsensusError.deserialize).to.be.a('function'); + }); + }); + }); +}); diff --git a/packages/wasm-dpp2/tests/unit/utils/hex.js b/packages/wasm-dpp2/tests/unit/utils/hex.js deleted file mode 100644 index 5a6f148655d..00000000000 --- a/packages/wasm-dpp2/tests/unit/utils/hex.js +++ /dev/null @@ -1,10 +0,0 @@ -export const toHexString = (byteArray) => Array.prototype.map.call(byteArray, (byte) => (`0${(byte & 0xFF).toString(16)}`).slice(-2)).join(''); - -export const fromHexString = (str) => { - const bytes = []; - for (let i = 0; i < str.length; i += 2) { - bytes.push(parseInt(str.slice(i, i + 2), 16)); - } - - return Uint8Array.from(bytes); -}; diff --git a/packages/wasm-dpp2/tests/unit/utils/hex.ts b/packages/wasm-dpp2/tests/unit/utils/hex.ts new file mode 100644 index 00000000000..f0c582c8c03 --- /dev/null +++ b/packages/wasm-dpp2/tests/unit/utils/hex.ts @@ -0,0 +1,12 @@ +export const toHexString = (byteArray: ArrayLike): string => Array.prototype.map + .call(byteArray, (byte: number) => `0${(byte & 0xff).toString(16)}`.slice(-2)) + .join(''); + +export const fromHexString = (str: string): Uint8Array => { + const bytes: number[] = []; + for (let i = 0; i < str.length; i += 2) { + bytes.push(parseInt(str.slice(i, i + 2), 16)); + } + + return Uint8Array.from(bytes); +}; diff --git a/packages/wasm-sdk/.mocharc.yml b/packages/wasm-sdk/.mocharc.yml index e82067f393b..d41059d3e45 100644 --- a/packages/wasm-sdk/.mocharc.yml +++ b/packages/wasm-sdk/.mocharc.yml @@ -1,3 +1,5 @@ +node-option: + - import=ts-node/esm require: tests/bootstrap.cjs recursive: true timeout: 8000 diff --git a/packages/wasm-sdk/eslint.config.mjs b/packages/wasm-sdk/eslint.config.mjs new file mode 100644 index 00000000000..51db40b6e11 --- /dev/null +++ b/packages/wasm-sdk/eslint.config.mjs @@ -0,0 +1,20 @@ +import baseConfig from '../../eslint/base.mjs'; +import typescriptConfig from '../../eslint/typescript.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; +import wasmConfig from '../../eslint/wasm.mjs'; + +export default [ + ...baseConfig, + ...typescriptConfig, + { + files: ['tests/**/*.ts'], + rules: { + ...wasmConfig.rules, + 'import-x/extensions': ['error', 'ignorePackages'], + }, + }, + mochaTestConfig, + { + ignores: ['dist/**', 'pkg/**', '*.d.ts', 'tests/karma/**', 'node_modules/**'], + }, +]; diff --git a/packages/wasm-sdk/package.json b/packages/wasm-sdk/package.json index a81af30aaab..4b9d21f0475 100644 --- a/packages/wasm-sdk/package.json +++ b/packages/wasm-sdk/package.json @@ -31,9 +31,9 @@ "build": "./scripts/build.sh && node ./scripts/bundle.cjs", "build:release": "./scripts/build-optimized.sh && node ./scripts/bundle.cjs", "test": "yarn run test:unit", - "test:unit": "mocha tests/unit/**/*.spec.mjs && karma start ./tests/karma/karma.conf.cjs --single-run", - "test:functional": "mocha --require tests/functional-bootstrap.cjs tests/functional/**/*.spec.mjs && karma start ./tests/karma/karma.functional.conf.cjs --single-run", - "lint": "eslint tests/**/*.*js" + "test:unit": "mocha --import ts-node/esm tests/unit/**/*.spec.ts && karma start ./tests/karma/karma.conf.cjs --single-run", + "test:functional": "mocha --import ts-node/esm --require tests/functional-bootstrap.cjs tests/functional/**/*.spec.ts && karma start ./tests/karma/karma.functional.conf.cjs --single-run", + "lint": "eslint tests/**/*.ts" }, "ultra": { "concurrent": [ @@ -41,15 +41,15 @@ ] }, "devDependencies": { + "@types/chai": "^4.3.11", + "@types/mocha": "^10.0.6", + "@types/node": "^20.10.0", "assert": "^2.0.0", "buffer": "^6.0.3", "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-jsdoc": "^46.9.0", + "eslint": "^9.18.0", "events": "^3.3.0", "karma": "^6.4.3", "karma-chai": "^0.1.0", @@ -62,6 +62,9 @@ "path-browserify": "^1.0.1", "process": "^0.11.10", "string_decoder": "^1.3.0", + "ts-loader": "^9.5.0", + "ts-node": "^10.9.2", + "typescript": "^5.7.3", "url": "^0.11.3", "util": "^0.12.4", "webpack": "^5.94.0", diff --git a/packages/wasm-sdk/scripts/bundle.cjs b/packages/wasm-sdk/scripts/bundle.cjs index c5e7915029f..86c5155a02b 100644 --- a/packages/wasm-sdk/scripts/bundle.cjs +++ b/packages/wasm-sdk/scripts/bundle.cjs @@ -58,7 +58,7 @@ const wasmGzipBase64 = wasmGzip.toString('base64'); const wrapper = `// Single-file ESM wrapper around wasm-bindgen output.\n// - Inlines WASM bytes as base64.\n// - Exposes async default init() for both Node and browser.\n// - Browser compiles in a Web Worker and instantiates on main thread (fallback to async compile).\n// - Node uses initSync with inlined bytes (still awaitable for uniform API).\n\nimport rawInit, { initSync as rawInitSync } from './raw/wasm_sdk.no_url.js';\n\nexport * from './raw/wasm_sdk.no_url.js';\nexport { initSync } from './raw/wasm_sdk.no_url.js';\n\nconst __WASM_BASE64 = '${wasmBase64}';\nfunction __wasmBytes() {\n if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {\n return Buffer.from(__WASM_BASE64, 'base64');\n }\n const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);\n const bin = atobFn(__WASM_BASE64);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nfunction __supportsWorker() {\n return typeof Worker !== 'undefined' && typeof Blob !== 'undefined' && typeof URL !== 'undefined';\n}\n\nasync function __compileInWorker(bytes) {\n if (!__supportsWorker()) {\n return WebAssembly.compile(bytes);\n }\n const src = 'self.onmessage=async(e)=>{try{const m=await WebAssembly.compile(e.data);self.postMessage({ok:1,mod:m});}catch(err){self.postMessage({ok:0,err:String(err)});}}';\n const blob = new Blob([src], { type: 'application/javascript' });\n const url = URL.createObjectURL(blob);\n return new Promise((resolve) => {\n const w = new Worker(url);\n w.onmessage = (ev) => {\n URL.revokeObjectURL(url);\n w.terminate();\n const d = ev.data || {};\n if (d.ok && d.mod) {\n resolve(d.mod);\n } else {\n resolve(WebAssembly.compile(bytes));\n }\n };\n // Transfer the underlying buffer to avoid copy\n try {\n w.postMessage(bytes.buffer, [bytes.buffer]);\n } catch (_) {\n // If transfer fails (detached), send a copy\n w.postMessage(new Uint8Array(bytes));\n }\n });\n}\n\nconst isNode = typeof window === 'undefined' && typeof process !== 'undefined' && !!(process.versions && process.versions.node);\n\nexport default async function init(moduleOrPath) {\n if (isNode) {\n if (typeof moduleOrPath === 'undefined') {\n const bytes = __wasmBytes();\n return rawInitSync({ module: bytes });\n }\n return rawInit(moduleOrPath);\n }\n if (typeof moduleOrPath === 'undefined') {\n const bytes = __wasmBytes();\n let mod;\n try {\n mod = await __compileInWorker(bytes);\n } catch (_) {\n mod = await WebAssembly.compile(bytes);\n }\n return rawInit({ module_or_path: mod });\n }\n return rawInit(moduleOrPath);\n}\n`; fs.writeFileSync(path.join(distDir, 'sdk.js'), wrapper); -const compressedWrapper = `// Gzip-compressed single-file ESM wrapper around wasm-bindgen output.\n// - Inlines WASM as base64 gzip payload to reduce bundle size.\n// - Decompresses off-thread when possible to minimize main-thread work.\n// - Preserves async init() API shape.\n\nimport rawInit, { initSync as rawInitSync } from './raw/wasm_sdk.no_url.js';\n\nexport * from './raw/wasm_sdk.no_url.js';\nexport { initSync } from './raw/wasm_sdk.no_url.js';\n\nconst __WASM_COMPRESSED_BASE64 = '${wasmGzipBase64}';\nconst __WASM_COMPRESSION = 'gzip';\nconst isNode = typeof window === 'undefined' && typeof process !== 'undefined' && !!(process.versions && process.versions.node);\n\nfunction __decodeBase64(source) {\n if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {\n return Buffer.from(source, 'base64');\n }\n const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);\n const bin = atobFn(source);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nlet __nodeZlibPromise;\nfunction __loadNodeZlib() {\n if (!__nodeZlibPromise) {\n const importer = new Function('return import(\"node:zlib\")');\n __nodeZlibPromise = importer();\n }\n return __nodeZlibPromise;\n}\n\nasync function __decompress(bytes) {\n if (!__WASM_COMPRESSION) {\n return bytes;\n }\n if (isNode) {\n const { gunzipSync } = await __loadNodeZlib();\n const out = gunzipSync(bytes);\n return out instanceof Uint8Array\n ? out\n : new Uint8Array(out.buffer, out.byteOffset, out.byteLength);\n }\n if (typeof Blob === 'function' && typeof Response === 'function' && typeof DecompressionStream === 'function') {\n const res = new Response(\n new Blob([bytes]).stream().pipeThrough(new DecompressionStream(__WASM_COMPRESSION))\n );\n const buf = await res.arrayBuffer();\n return new Uint8Array(buf);\n }\n throw new Error('Gzip decompression not supported in this environment.');\n}\n\nasync function __wasmBytes(options = {}) {\n const { decompress = true } = options;\n if (!__WASM_COMPRESSION) {\n throw new Error('Compression metadata missing.');\n }\n const compressed = __decodeBase64(__WASM_COMPRESSED_BASE64);\n if (!decompress) {\n return compressed;\n }\n return __decompress(compressed);\n}\n\nfunction __supportsWorker() {\n return typeof Worker !== 'undefined' && typeof Blob !== 'undefined' && typeof URL !== 'undefined';\n}\n\nasync function __compileInWorker(compressedBytes) {\n const bytes = compressedBytes instanceof Uint8Array ? compressedBytes : new Uint8Array(compressedBytes);\n if (!__supportsWorker()) {\n const decompressed = await __decompress(bytes);\n return WebAssembly.compile(decompressed);\n }\n const src = "self.onmessage=async(event)=>{try{const data=event.data||{};let bytes=data.compressed;const compression=data.compression||null;if(!(bytes instanceof Uint8Array)){bytes=bytes?new Uint8Array(bytes):new Uint8Array();}if(compression){if(typeof Blob==='function'&&typeof Response==='function'&&typeof DecompressionStream==='function'){const res=new Response(new Blob([bytes]).stream().pipeThrough(new DecompressionStream(compression)));const buf=await res.arrayBuffer();bytes=new Uint8Array(buf);}else{throw new Error('DecompressionStream not available');}}const mod=await WebAssembly.compile(bytes);self.postMessage({ok:1,mod});}catch(err){self.postMessage({ok:0,err:String(err)})}}";\n const blob = new Blob([src], { type: 'application/javascript' });\n const url = URL.createObjectURL(blob);\n return new Promise((resolve, reject) => {\n const worker = new Worker(url);\n const cleanup = () => {\n URL.revokeObjectURL(url);\n worker.terminate();\n };\n worker.onmessage = (ev) => {\n const d = ev.data || {};\n if (d.ok && d.mod) {\n cleanup();\n resolve(d.mod);\n } else {\n cleanup();\n reject(new Error(d.err || 'Worker failed to compile WASM.'));\n }\n };\n worker.onerror = (err) => {\n cleanup();\n reject(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));\n };\n try {\n worker.postMessage({ compressed: bytes, compression: __WASM_COMPRESSION });\n } catch (postErr) {\n cleanup();\n reject(postErr);\n }\n });\n}\n\nexport default async function init(moduleOrPath) {\n if (isNode) {\n if (typeof moduleOrPath === 'undefined') {\n const bytes = await __wasmBytes();\n return rawInitSync({ module: bytes });\n }\n return rawInit(moduleOrPath);\n }\n if (typeof moduleOrPath === 'undefined') {\n const compressedBytes = await __wasmBytes({ decompress: false });\n let mod;\n try {\n mod = await __compileInWorker(compressedBytes);\n } catch (_) {\n const decompressed = await __decompress(compressedBytes);\n mod = await WebAssembly.compile(decompressed);\n }\n return rawInit({ module_or_path: mod });\n }\n return rawInit(moduleOrPath);\n}\n` +const compressedWrapper = `// Gzip-compressed single-file ESM wrapper around wasm-bindgen output.\n// - Inlines WASM as base64 gzip payload to reduce bundle size.\n// - Decompresses off-thread when possible to minimize main-thread work.\n// - Preserves async init() API shape.\n\nimport rawInit, { initSync as rawInitSync } from './raw/wasm_sdk.no_url.js';\n\nexport * from './raw/wasm_sdk.no_url.js';\nexport { initSync } from './raw/wasm_sdk.no_url.js';\n\nconst __WASM_COMPRESSED_BASE64 = '${wasmGzipBase64}';\nconst __WASM_COMPRESSION = 'gzip';\nconst isNode = typeof window === 'undefined' && typeof process !== 'undefined' && !!(process.versions && process.versions.node);\n\nfunction __decodeBase64(source) {\n if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {\n return Buffer.from(source, 'base64');\n }\n const atobFn = (typeof atob === 'function') ? atob : (s) => globalThis.atob(s);\n const bin = atobFn(source);\n const len = bin.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nlet __nodeZlibPromise;\nfunction __loadNodeZlib() {\n if (!__nodeZlibPromise) {\n const importer = new Function('return import("node:zlib")');\n __nodeZlibPromise = importer();\n }\n return __nodeZlibPromise;\n}\n\nasync function __decompress(bytes) {\n if (!__WASM_COMPRESSION) {\n return bytes;\n }\n if (isNode) {\n const { gunzipSync } = await __loadNodeZlib();\n const out = gunzipSync(bytes);\n return out instanceof Uint8Array\n ? out\n : new Uint8Array(out.buffer, out.byteOffset, out.byteLength);\n }\n if (typeof Blob === 'function' && typeof Response === 'function' && typeof DecompressionStream === 'function') {\n const res = new Response(\n new Blob([bytes]).stream().pipeThrough(new DecompressionStream(__WASM_COMPRESSION))\n );\n const buf = await res.arrayBuffer();\n return new Uint8Array(buf);\n }\n throw new Error('Gzip decompression not supported in this environment.');\n}\n\nasync function __wasmBytes(options = {}) {\n const { decompress = true } = options;\n if (!__WASM_COMPRESSION) {\n throw new Error('Compression metadata missing.');\n }\n const compressed = __decodeBase64(__WASM_COMPRESSED_BASE64);\n if (!decompress) {\n return compressed;\n }\n return __decompress(compressed);\n}\n\nfunction __supportsWorker() {\n return typeof Worker !== 'undefined' && typeof Blob !== 'undefined' && typeof URL !== 'undefined';\n}\n\nasync function __compileInWorker(compressedBytes) {\n const bytes = compressedBytes instanceof Uint8Array ? compressedBytes : new Uint8Array(compressedBytes);\n if (!__supportsWorker()) {\n const decompressed = await __decompress(bytes);\n return WebAssembly.compile(decompressed);\n }\n const src = "self.onmessage=async(event)=>{try{const data=event.data||{};let bytes=data.compressed;const compression=data.compression||null;if(!(bytes instanceof Uint8Array)){bytes=bytes?new Uint8Array(bytes):new Uint8Array();}if(compression){if(typeof Blob==='function'&&typeof Response==='function'&&typeof DecompressionStream==='function'){const res=new Response(new Blob([bytes]).stream().pipeThrough(new DecompressionStream(compression)));const buf=await res.arrayBuffer();bytes=new Uint8Array(buf);}else{throw new Error('DecompressionStream not available');}}const mod=await WebAssembly.compile(bytes);self.postMessage({ok:1,mod});}catch(err){self.postMessage({ok:0,err:String(err)})}}";\n const blob = new Blob([src], { type: 'application/javascript' });\n const url = URL.createObjectURL(blob);\n return new Promise((resolve, reject) => {\n const worker = new Worker(url);\n const cleanup = () => {\n URL.revokeObjectURL(url);\n worker.terminate();\n };\n worker.onmessage = (ev) => {\n const d = ev.data || {};\n if (d.ok && d.mod) {\n cleanup();\n resolve(d.mod);\n } else {\n cleanup();\n reject(new Error(d.err || 'Worker failed to compile WASM.'));\n }\n };\n worker.onerror = (err) => {\n cleanup();\n reject(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));\n };\n try {\n worker.postMessage({ compressed: bytes, compression: __WASM_COMPRESSION });\n } catch (postErr) {\n cleanup();\n reject(postErr);\n }\n });\n}\n\nexport default async function init(moduleOrPath) {\n if (isNode) {\n if (typeof moduleOrPath === 'undefined') {\n const bytes = await __wasmBytes();\n return rawInitSync({ module: bytes });\n }\n return rawInit(moduleOrPath);\n }\n if (typeof moduleOrPath === 'undefined') {\n const compressedBytes = await __wasmBytes({ decompress: false });\n let mod;\n try {\n mod = await __compileInWorker(compressedBytes);\n } catch (_) {\n const decompressed = await __decompress(compressedBytes);\n mod = await WebAssembly.compile(decompressed);\n }\n return rawInit({ module_or_path: mod });\n }\n return rawInit(moduleOrPath);\n}\n` fs.writeFileSync(path.join(distDir, 'sdk.compressed.js'), compressedWrapper); const sdkJsPath = path.join(distDir, 'sdk.js'); diff --git a/packages/wasm-sdk/src/dpns.rs b/packages/wasm-sdk/src/dpns.rs index da27f7f9628..251e4acf74a 100644 --- a/packages/wasm-sdk/src/dpns.rs +++ b/packages/wasm-sdk/src/dpns.rs @@ -1,6 +1,6 @@ use crate::error::WasmSdkError; use crate::impl_wasm_serde_conversions; -use crate::queries::utils::{deserialize_required_query, identifier_from_js}; +use crate::queries::utils::deserialize_required_query; use crate::queries::ProofMetadataResponseWasm; use crate::sdk::WasmSdk; use dash_sdk::dpp::data_contract::DataContract; @@ -21,15 +21,16 @@ use serde::{Deserialize, Serialize}; use std::sync::Arc; use wasm_bindgen::prelude::*; use wasm_dpp2::data_contract::document::DocumentWasm; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::identifier::{IdentifierLikeJs, IdentifierWasm}; use wasm_dpp2::identity::IdentityPublicKeyWasm; use wasm_dpp2::identity::IdentityWasm; +use wasm_dpp2::utils::{try_from_options_optional_with, try_from_options_with, try_to_string}; use wasm_dpp2::IdentitySignerWasm; #[wasm_bindgen(js_name = "RegisterDpnsNameResult")] #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct RegisterDpnsNameResult { +pub struct RegisterDpnsNameResultWasm { #[wasm_bindgen(getter_with_clone, js_name = "preorderDocumentId")] pub preorder_document_id: IdentifierWasm, #[wasm_bindgen(getter_with_clone, js_name = "domainDocumentId")] @@ -41,7 +42,7 @@ pub struct RegisterDpnsNameResult { #[wasm_bindgen(js_name = "DpnsUsernameInfo")] #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct DpnsUsernameInfo { +pub struct DpnsUsernameInfoWasm { #[wasm_bindgen(getter_with_clone)] pub username: String, #[wasm_bindgen(getter_with_clone, js_name = "identityId")] @@ -51,9 +52,13 @@ pub struct DpnsUsernameInfo { } #[wasm_bindgen(js_class = DpnsUsernameInfo)] -impl DpnsUsernameInfo { +impl DpnsUsernameInfoWasm { #[wasm_bindgen(constructor)] - pub fn new(username: String, identity_id: IdentifierWasm, document_id: IdentifierWasm) -> Self { + pub fn constructor( + username: String, + identity_id: IdentifierWasm, + document_id: IdentifierWasm, + ) -> Self { Self { username, identity_id, @@ -62,8 +67,8 @@ impl DpnsUsernameInfo { } } -impl_wasm_serde_conversions!(RegisterDpnsNameResult); -impl_wasm_serde_conversions!(DpnsUsernameInfo); +impl_wasm_serde_conversions!(RegisterDpnsNameResultWasm, RegisterDpnsNameResult); +impl_wasm_serde_conversions!(DpnsUsernameInfoWasm, DpnsUsernameInfo); const DEFAULT_DPNS_USERNAMES_LIMIT: u32 = 10; @@ -191,36 +196,19 @@ fn parse_dpns_usernames_query( }) } -/// Extracts a string field from a JS options object. -fn extract_string_from_options( - options: &JsValue, - field_name: &str, -) -> Result { - let value = js_sys::Reflect::get(options, &JsValue::from_str(field_name)) - .map_err(|_| WasmSdkError::invalid_argument(format!("{} is required", field_name)))?; - - value - .as_string() - .ok_or_else(|| WasmSdkError::invalid_argument(format!("{} must be a string", field_name))) -} - /// Extracts an optional JS function from options. fn extract_callback_from_options( options: &JsValue, field_name: &str, ) -> Result, WasmSdkError> { - let value = js_sys::Reflect::get(options, &JsValue::from_str(field_name)) - .map_err(|_| WasmSdkError::invalid_argument(format!("Failed to get {}", field_name)))?; - - if value.is_undefined() || value.is_null() { - return Ok(None); - } - - let func = value.dyn_into::().map_err(|_| { - WasmSdkError::invalid_argument(format!("{} must be a function", field_name)) - })?; - - Ok(Some(func)) + Ok(try_from_options_optional_with(options, field_name, |v| { + v.clone().dyn_into::().map_err(|_| { + wasm_dpp2::error::WasmDppError::invalid_argument(format!( + "{} must be a function", + field_name + )) + }) + })?) } /// DPNS contract ID constant @@ -336,25 +324,23 @@ impl WasmSdk { pub async fn dpns_register_name( &self, options: DpnsRegisterNameOptionsJs, - ) -> Result { - let options_value: JsValue = options.into(); - + ) -> Result { // Extract label from options - let label = extract_string_from_options(&options_value, "label")?; + let label: String = + try_from_options_with(&options, "label", |v| try_to_string(v, "label"))?; // Extract identity from options - let identity: Identity = IdentityWasm::try_from_options(&options_value, "identity")?.into(); + let identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_public_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Extract optional preorder callback - let preorder_callback = extract_callback_from_options(&options_value, "preorderCallback")?; + let preorder_callback = extract_callback_from_options(&options, "preorderCallback")?; // Set up the callback if provided thread_local! { @@ -405,7 +391,7 @@ impl WasmSdk { *cb.borrow_mut() = None; }); - Ok(RegisterDpnsNameResult { + Ok(RegisterDpnsNameResultWasm { preorder_document_id: IdentifierWasm::from(result.preorder_document.id()), domain_document_id: IdentifierWasm::from(result.domain_document.id()), full_domain_name: result.full_domain_name, @@ -431,7 +417,7 @@ impl WasmSdk { pub async fn get_dpns_username_by_name( &self, username: &str, - ) -> Result, WasmSdkError> { + ) -> Result, WasmSdkError> { let parts: Vec<&str> = username.split('.').collect(); if parts.len() != 2 { return Err(WasmSdkError::invalid_argument( @@ -459,7 +445,7 @@ impl WasmSdk { let documents = Document::fetch_many(self.as_ref(), query).await?; if let Some((_, Some(document))) = documents.into_iter().next() { - Ok(Some(DpnsUsernameInfo { + Ok(Some(DpnsUsernameInfoWasm { username: username.to_string(), identity_id: IdentifierWasm::from(document.owner_id()), document_id: IdentifierWasm::from(document.id()), @@ -505,7 +491,7 @@ impl WasmSdk { Document::fetch_many_with_metadata_and_proof(self.as_ref(), query, None).await?; let data = if let Some((_, Some(document))) = documents.into_iter().next() { - let result = DpnsUsernameInfo { + let result = DpnsUsernameInfoWasm { username: username.to_string(), identity_id: IdentifierWasm::from(document.owner_id()), document_id: IdentifierWasm::from(document.id()), @@ -538,11 +524,9 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getDpnsUsername")] pub async fn get_dpns_username( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "IdentifierLike")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result, WasmSdkError> { - let identity_id_parsed = identifier_from_js(&identity_id, "identity ID")?; + let identity_id_parsed = IdentifierWasm::try_from(identity_id)?.into(); let array = self .fetch_dpns_usernames(identity_id_parsed, Some(1)) @@ -578,11 +562,9 @@ impl WasmSdk { )] pub async fn get_dpns_username_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "IdentifierLike")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { - let identity_id_parsed = identifier_from_js(&identity_id, "identity ID")?; + let identity_id_parsed = IdentifierWasm::try_from(identity_id)?.into(); let mut response = self .fetch_dpns_usernames_with_proof(identity_id_parsed, Some(1)) diff --git a/packages/wasm-sdk/src/error.rs b/packages/wasm-sdk/src/error.rs index 55e3a45ef19..6f0af6d813b 100644 --- a/packages/wasm-sdk/src/error.rs +++ b/packages/wasm-sdk/src/error.rs @@ -48,7 +48,7 @@ pub struct WasmSdkError { /// Optional numeric code for some errors (e.g., broadcast error code). code: i32, /// Indicates if the operation can be retried safely. - retriable: bool, + is_retriable: bool, } // wasm-bindgen getters defined below in the second impl block @@ -58,13 +58,13 @@ impl WasmSdkError { kind: WasmSdkErrorKind, message: M, code: Option, - retriable: bool, + is_retriable: bool, ) -> Self { Self { kind, message: message.into(), code: code.unwrap_or(-1), - retriable, + is_retriable, } } @@ -273,8 +273,8 @@ impl WasmSdkError { } /// Whether the error is retryable - #[wasm_bindgen(getter)] - pub fn retriable(&self) -> bool { - self.retriable + #[wasm_bindgen(getter = "isRetriable")] + pub fn is_retriable(&self) -> bool { + self.is_retriable } } diff --git a/packages/wasm-sdk/src/lib.rs b/packages/wasm-sdk/src/lib.rs index d9a9bd80b88..14a662bb7c3 100644 --- a/packages/wasm-sdk/src/lib.rs +++ b/packages/wasm-sdk/src/lib.rs @@ -9,7 +9,6 @@ pub mod sdk; pub mod serialization; pub mod settings; pub mod state_transitions; -pub mod utils; pub mod wallet; // Re-export commonly used items diff --git a/packages/wasm-sdk/src/queries/address.rs b/packages/wasm-sdk/src/queries/address.rs index d034f74a427..18b85bf3bf2 100644 --- a/packages/wasm-sdk/src/queries/address.rs +++ b/packages/wasm-sdk/src/queries/address.rs @@ -10,7 +10,8 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; -use wasm_dpp2::PlatformAddressWasm; +use wasm_dpp2::utils::try_to_vec; +use wasm_dpp2::{PlatformAddressLikeArrayJs, PlatformAddressLikeJs, PlatformAddressWasm}; /// Information about a Platform address including its nonce and balance. #[wasm_bindgen(js_name = "PlatformAddressInfo")] @@ -64,13 +65,11 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getAddressInfo")] pub async fn get_address_info( &self, - #[wasm_bindgen(unchecked_param_type = "PlatformAddressLike")] address: JsValue, + address: PlatformAddressLikeJs, ) -> Result, WasmSdkError> { - let platform_address: PlatformAddress = PlatformAddressWasm::try_from(&address) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid platform address: {}", err)) - })? - .into(); + let platform_address: PlatformAddress = address.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid platform address: {}", err)) + })?; let address_info = AddressInfo::fetch(self.as_ref(), platform_address).await?; @@ -87,13 +86,11 @@ impl WasmSdk { )] pub async fn get_address_info_with_proof_info( &self, - #[wasm_bindgen(unchecked_param_type = "PlatformAddressLike")] address: JsValue, + address: PlatformAddressLikeJs, ) -> Result { - let platform_address: PlatformAddress = PlatformAddressWasm::try_from(&address) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid platform address: {}", err)) - })? - .into(); + let platform_address: PlatformAddress = address.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid platform address: {}", err)) + })?; let (address_info, metadata, proof) = AddressInfo::fetch_with_metadata_and_proof(self.as_ref(), platform_address, None) @@ -122,20 +119,12 @@ impl WasmSdk { )] pub async fn get_addresses_infos( &self, - #[wasm_bindgen(unchecked_param_type = "Array")] addresses: Vec< - JsValue, - >, + addresses: PlatformAddressLikeArrayJs, ) -> Result { - let platform_addresses: BTreeSet = addresses - .into_iter() - .map(|value| { - PlatformAddressWasm::try_from(&value) - .map(PlatformAddress::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid platform address: {}", err)) - }) - }) - .collect::, _>>()?; + let platform_addresses: BTreeSet = + try_to_vec::(addresses, "addresses", "address")? + .into_iter() + .collect(); let address_infos: AddressInfos = AddressInfo::fetch_many(self.as_ref(), platform_addresses.clone()).await?; @@ -167,20 +156,12 @@ impl WasmSdk { )] pub async fn get_addresses_infos_with_proof_info( &self, - #[wasm_bindgen(unchecked_param_type = "Array")] addresses: Vec< - JsValue, - >, + addresses: PlatformAddressLikeArrayJs, ) -> Result { - let platform_addresses: BTreeSet = addresses - .into_iter() - .map(|value| { - PlatformAddressWasm::try_from(&value) - .map(PlatformAddress::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid platform address: {}", err)) - }) - }) - .collect::, _>>()?; + let platform_addresses: BTreeSet = + try_to_vec::(addresses, "addresses", "address")? + .into_iter() + .collect(); let (address_infos, metadata, proof): (AddressInfos, _, _) = AddressInfo::fetch_many_with_metadata_and_proof( diff --git a/packages/wasm-sdk/src/queries/data_contract.rs b/packages/wasm-sdk/src/queries/data_contract.rs index b14637f686d..a199a21670b 100644 --- a/packages/wasm-sdk/src/queries/data_contract.rs +++ b/packages/wasm-sdk/src/queries/data_contract.rs @@ -9,7 +9,8 @@ use js_sys::{BigInt, Map}; use serde::Deserialize; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::identifier::{IdentifierLikeArrayJs, IdentifierLikeJs, IdentifierWasm}; +use wasm_dpp2::utils::try_to_vec; use wasm_dpp2::DataContractWasm; #[wasm_bindgen(typescript_custom_section)] @@ -95,15 +96,11 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getDataContract")] pub async fn get_data_contract( &self, - #[wasm_bindgen(js_name = "contractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - contract_id: JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> Result, WasmSdkError> { - let id: Identifier = IdentifierWasm::try_from(&contract_id) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) - })? - .into(); + let id: Identifier = contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) + })?; let data_contract = DataContract::fetch_by_identifier(self.as_ref(), id) .await? @@ -118,15 +115,11 @@ impl WasmSdk { )] pub async fn get_data_contract_with_proof_info( &self, - #[wasm_bindgen(js_name = "contractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - contract_id: JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> Result { - let id: Identifier = IdentifierWasm::try_from(&contract_id) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) - })? - .into(); + let id: Identifier = contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) + })?; let (contract, metadata, proof) = DataContract::fetch_with_metadata_and_proof(self.as_ref(), id, None).await?; @@ -175,22 +168,11 @@ impl WasmSdk { )] pub async fn get_data_contracts( &self, - #[wasm_bindgen(unchecked_param_type = "Array")] ids: Vec< - JsValue, - >, + ids: IdentifierLikeArrayJs, ) -> Result { // Parse all contract IDs - let identifiers: Result, WasmSdkError> = ids - .into_iter() - .map(|id| { - IdentifierWasm::try_from(&id) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) - }) - }) - .collect(); - let identifiers = identifiers?; + let identifiers: Vec = + try_to_vec::(ids, "ids", "identifier")?; // Fetch all contracts let contracts_result: DataContracts = @@ -248,22 +230,11 @@ impl WasmSdk { )] pub async fn get_data_contracts_with_proof_info( &self, - #[wasm_bindgen(unchecked_param_type = "Array")] ids: Vec< - JsValue, - >, + ids: IdentifierLikeArrayJs, ) -> Result { // Parse all contract IDs - let identifiers: Result, WasmSdkError> = ids - .into_iter() - .map(|id| { - IdentifierWasm::try_from(&id) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) - }) - }) - .collect(); - let identifiers = identifiers?; + let identifiers: Vec = + try_to_vec::(ids, "ids", "identifier")?; // Fetch all contracts with proof let (contracts_result, metadata, proof) = diff --git a/packages/wasm-sdk/src/queries/document.rs b/packages/wasm-sdk/src/queries/document.rs index 7025e78ed87..4f9665885d7 100644 --- a/packages/wasm-sdk/src/queries/document.rs +++ b/packages/wasm-sdk/src/queries/document.rs @@ -16,7 +16,7 @@ use serde_json::Value as JsonValue; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use wasm_dpp2::data_contract::document::DocumentWasm; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::identifier::{IdentifierLikeJs, IdentifierWasm}; #[wasm_bindgen(typescript_custom_section)] const DOCUMENTS_QUERY_TS: &'static str = r#" @@ -395,24 +395,18 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getDocument")] pub async fn get_document( &self, - #[wasm_bindgen(js_name = "dataContractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - data_contract_id: JsValue, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, #[wasm_bindgen(js_name = "documentType")] document_type: &str, - #[wasm_bindgen(js_name = "documentId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - document_id: JsValue, + #[wasm_bindgen(js_name = "documentId")] document_id: IdentifierLikeJs, ) -> Result, WasmSdkError> { // Parse IDs - let contract_id: Identifier = IdentifierWasm::try_from(&data_contract_id) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) - })? - .into(); + let contract_id: Identifier = data_contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) + })?; - let doc_id: Identifier = IdentifierWasm::try_from(&document_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid document ID: {}", err)))? - .into(); + let doc_id: Identifier = document_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid document ID: {}", err)) + })?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; @@ -439,24 +433,18 @@ impl WasmSdk { )] pub async fn get_document_with_proof_info( &self, - #[wasm_bindgen(js_name = "dataContractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - data_contract_id: JsValue, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, #[wasm_bindgen(js_name = "documentType")] document_type: &str, - #[wasm_bindgen(js_name = "documentId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - document_id: JsValue, + #[wasm_bindgen(js_name = "documentId")] document_id: IdentifierLikeJs, ) -> Result { // Parse IDs - let contract_id: Identifier = IdentifierWasm::try_from(&data_contract_id) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) - })? - .into(); - - let doc_id: Identifier = IdentifierWasm::try_from(&document_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid document ID: {}", err)))? - .into(); + let contract_id: Identifier = data_contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid data contract ID: {}", err)) + })?; + + let doc_id: Identifier = document_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid document ID: {}", err)) + })?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; diff --git a/packages/wasm-sdk/src/queries/epoch.rs b/packages/wasm-sdk/src/queries/epoch.rs index 0235b49d05d..17d88708848 100644 --- a/packages/wasm-sdk/src/queries/epoch.rs +++ b/packages/wasm-sdk/src/queries/epoch.rs @@ -14,7 +14,10 @@ use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use wasm_dpp2::epoch::{ExtendedEpochInfoWasm, FinalizedEpochInfoWasm}; use wasm_dpp2::identifier::IdentifierWasm; -use wasm_dpp2::ProTxHashWasm; +use wasm_dpp2::utils::try_from_options_optional; +use wasm_dpp2::utils::try_to_vec; +use wasm_dpp2::utils::JsMapExt; +use wasm_dpp2::{ProTxHashLikeArrayJs, ProTxHashWasm}; #[wasm_bindgen(typescript_custom_section)] const EPOCHS_QUERY_TS: &'static str = r#" @@ -160,10 +163,10 @@ export interface EvonodeProposedBlocksRangeQuery { limit?: number; /** - * ProTxHash (hex string) to resume from (exclusive by default). + * ProTxHash to resume from (exclusive by default). * @default undefined */ - startAfter?: string; + startAfter?: ProTxHashLike; } "#; @@ -179,8 +182,6 @@ struct EvonodeProposedBlocksRangeQueryInput { epoch: u16, #[serde(default)] limit: Option, - #[serde(default)] - start_after: Option, } struct EvonodeProposedBlocksRangeQueryParsed { @@ -192,14 +193,19 @@ struct EvonodeProposedBlocksRangeQueryParsed { fn parse_evonode_range_query( query: EvonodeProposedBlocksRangeQueryJs, ) -> Result { + let query_js: JsValue = query.into(); + + // Extract startAfter before serde since it accepts ProTxHashLike (string, Uint8Array, or ProTxHash object) + let start_after: Option = try_from_options_optional(&query_js, "startAfter")?; + let input: EvonodeProposedBlocksRangeQueryInput = deserialize_required_query( - query, + query_js, "Query object is required", "evonode proposed blocks range query", )?; - let start_info = if let Some(start) = input.start_after { - let pro_tx_hash: ProTxHash = ProTxHashWasm::from_hex(&start)?.into(); + let start_info = if let Some(pro_tx_hash_wasm) = start_after { + let pro_tx_hash: ProTxHash = pro_tx_hash_wasm.into(); Some(QueryStartInfo { start_key: pro_tx_hash.to_byte_array().to_vec(), start_included: false, @@ -242,15 +248,13 @@ impl WasmSdk { let epochs_result: drive_proof_verifier::types::ExtendedEpochInfos = ExtendedEpochInfo::fetch_many(self.as_ref(), query).await?; - let epochs_map = Map::new(); - - for (epoch_index, epoch_info) in epochs_result { - let key = Number::from(epoch_index as u32); - let value = epoch_info.map(ExtendedEpochInfoWasm::from); - epochs_map.set(&key.into(), &JsValue::from(value)); - } - - Ok(epochs_map) + Ok(Map::from_entries(epochs_result.into_iter().map( + |(epoch_index, epoch_info)| { + let key: JsValue = Number::from(epoch_index as u32).into(); + let value = JsValue::from(epoch_info.map(ExtendedEpochInfoWasm::from)); + (key, value) + }, + ))) } #[wasm_bindgen( @@ -300,14 +304,13 @@ impl WasmSdk { ) .await?; - let epochs_map = Map::new(); - for (epoch_index, epoch_info) in epochs_result { - let key = Number::from(epoch_index as u32); - let value = epoch_info.map(FinalizedEpochInfoWasm::from); - epochs_map.set(&key.into(), &JsValue::from(value)); - } - - Ok(epochs_map) + Ok(Map::from_entries(epochs_result.into_iter().map( + |(epoch_index, epoch_info)| { + let key: JsValue = Number::from(epoch_index as u32).into(); + let value = JsValue::from(epoch_info.map(FinalizedEpochInfoWasm::from)); + (key, value) + }, + ))) } #[wasm_bindgen( @@ -317,28 +320,25 @@ impl WasmSdk { pub async fn get_evonodes_proposed_epoch_blocks_by_ids( &self, epoch: u16, - #[wasm_bindgen(unchecked_param_type = "ProTxHashLike[]")] ids: Vec, + ids: ProTxHashLikeArrayJs, ) -> Result { use drive_proof_verifier::types::ProposerBlockCountById; - // Parse the ProTxHash values using centralized wrapper - let pro_tx_hashes: Vec = ids - .into_iter() - .map(|hash_js| ProTxHashWasm::try_from(&hash_js).map(|w| w.into())) - .collect::, _>>()?; + // Parse the ProTxHash values using helper function + let pro_tx_hashes: Vec = + try_to_vec::(ids, "proTxHashes", "proTxHash")?; // Use FetchMany to get block counts for specific IDs let counts = ProposerBlockCountById::fetch_many(self.as_ref(), (epoch, pro_tx_hashes)).await?; - let map = Map::new(); - - for (identifier, count) in counts.0 { - let key = JsValue::from(IdentifierWasm::from(identifier)); - map.set(&key, &JsValue::from(BigInt::from(count))); - } - - Ok(map) + Ok(Map::from_entries(counts.0.into_iter().map( + |(identifier, count)| { + let key = JsValue::from(IdentifierWasm::from(identifier)); + let value = JsValue::from(BigInt::from(count)); + (key, value) + }, + ))) } #[wasm_bindgen( @@ -365,13 +365,13 @@ impl WasmSdk { ) .await?; - let map = Map::new(); - for (identifier, count) in counts_result.0 { - let key = JsValue::from(IdentifierWasm::from(identifier)); - map.set(&key, &JsValue::from(BigInt::from(count))); - } - - Ok(map) + Ok(Map::from_entries(counts_result.0.into_iter().map( + |(identifier, count)| { + let key = JsValue::from(IdentifierWasm::from(identifier)); + let value = JsValue::from(BigInt::from(count)); + (key, value) + }, + ))) } #[wasm_bindgen(js_name = "getCurrentEpoch")] @@ -410,12 +410,12 @@ impl WasmSdk { ExtendedEpochInfo::fetch_many_with_metadata_and_proof(self.as_ref(), query, None) .await?; - let epochs_map = Map::new(); - for (epoch_index, epoch_info) in epochs_result { - let key = Number::from(epoch_index as u32); - let value = epoch_info.map(ExtendedEpochInfoWasm::from); - epochs_map.set(&key.into(), &JsValue::from(value)); - } + let epochs_map = + Map::from_entries(epochs_result.into_iter().map(|(epoch_index, epoch_info)| { + let key: JsValue = Number::from(epoch_index as u32).into(); + let value = JsValue::from(epoch_info.map(ExtendedEpochInfoWasm::from)); + (key, value) + })); Ok(ProofMetadataResponseWasm::from_sdk_parts( epochs_map, metadata, proof, @@ -483,12 +483,12 @@ impl WasmSdk { let (epochs_result, metadata, proof) = dash_sdk::dpp::block::finalized_epoch_info::FinalizedEpochInfo::fetch_many_with_metadata_and_proof(self.as_ref(), query, None) .await?; - let epochs_map = Map::new(); - for (index, epoch) in epochs_result { - let key = Number::from(index as u32); - let value = epoch.map(FinalizedEpochInfoWasm::from); - epochs_map.set(&key.into(), &JsValue::from(value)); - } + let epochs_map = + Map::from_entries(epochs_result.into_iter().map(|(epoch_index, epoch_info)| { + let key: JsValue = Number::from(epoch_index as u32).into(); + let value = JsValue::from(epoch_info.map(FinalizedEpochInfoWasm::from)); + (key, value) + })); Ok(ProofMetadataResponseWasm::from_sdk_parts( epochs_map, metadata, proof, @@ -502,17 +502,13 @@ impl WasmSdk { pub async fn get_evonodes_proposed_epoch_blocks_by_ids_with_proof_info( &self, epoch: u16, - #[wasm_bindgen(js_name = "proTxHashes")] - #[wasm_bindgen(unchecked_param_type = "ProTxHashLike[]")] - pro_tx_hashes: Vec, + #[wasm_bindgen(js_name = "proTxHashes")] pro_tx_hashes: ProTxHashLikeArrayJs, ) -> Result { use drive_proof_verifier::types::ProposerBlockCountById; - // Parse the ProTxHash values using centralized wrapper - let parsed_hashes: Vec = pro_tx_hashes - .into_iter() - .map(|hash_js| ProTxHashWasm::try_from(&hash_js).map(|w| w.into())) - .collect::, _>>()?; + // Parse the ProTxHash values using helper function + let parsed_hashes: Vec = + try_to_vec::(pro_tx_hashes, "proTxHashes", "proTxHash")?; // Use FetchMany with proof to get block counts for specific IDs let (counts, metadata, proof) = ProposerBlockCountById::fetch_many_with_metadata_and_proof( @@ -522,11 +518,11 @@ impl WasmSdk { ) .await?; - let map = Map::new(); - for (identifier, count) in counts.0 { + let map = Map::from_entries(counts.0.into_iter().map(|(identifier, count)| { let key = JsValue::from(IdentifierWasm::from(identifier)); - map.set(&key, &JsValue::from(BigInt::from(count))); - } + let value = JsValue::from(BigInt::from(count)); + (key, value) + })); Ok(ProofMetadataResponseWasm::from_sdk_parts( map, metadata, proof, @@ -564,11 +560,11 @@ impl WasmSdk { ) .await?; - let map = Map::new(); - for (identifier, count) in counts.0 { + let map = Map::from_entries(counts.0.into_iter().map(|(identifier, count)| { let key = JsValue::from(IdentifierWasm::from(identifier)); - map.set(&key, &JsValue::from(BigInt::from(count))); - } + let value = JsValue::from(BigInt::from(count)); + (key, value) + })); Ok(ProofMetadataResponseWasm::from_sdk_parts( map, metadata, proof, diff --git a/packages/wasm-sdk/src/queries/group.rs b/packages/wasm-sdk/src/queries/group.rs index 8d1e2b131bf..8b1292771a0 100644 --- a/packages/wasm-sdk/src/queries/group.rs +++ b/packages/wasm-sdk/src/queries/group.rs @@ -1,7 +1,5 @@ use crate::error::WasmSdkError; -use crate::queries::utils::{ - convert_optional_limit, deserialize_required_query, identifiers_from_js, -}; +use crate::queries::utils::{convert_optional_limit, deserialize_required_query}; use crate::queries::ProofMetadataResponseWasm; use crate::sdk::WasmSdk; use dash_sdk::dpp::data_contract::group::accessors::v0::GroupV0Getters; @@ -19,21 +17,25 @@ use serde::Deserialize; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use wasm_dpp2::group::GroupActionWasm; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::identifier::{IdentifierLikeArrayJs, IdentifierLikeJs, IdentifierWasm}; use wasm_dpp2::tokens::GroupWasm; +use wasm_dpp2::utils::JsMapExt; // Proof info functions are now included below #[wasm_bindgen(js_name = "IdentityGroupInfo")] pub struct IdentityGroupInfoWasm { - data_contract_id: String, - group_contract_position: u32, - role: String, + #[wasm_bindgen(getter_with_clone, js_name = "dataContractId")] + pub data_contract_id: String, + #[wasm_bindgen(getter_with_clone, js_name = "groupContractPosition")] + pub group_contract_position: u32, + #[wasm_bindgen(getter_with_clone)] + pub role: String, power: Option, } impl IdentityGroupInfoWasm { - fn new( + pub(crate) fn new( data_contract_id: String, group_contract_position: u32, role: String, @@ -50,22 +52,7 @@ impl IdentityGroupInfoWasm { #[wasm_bindgen(js_class = IdentityGroupInfo)] impl IdentityGroupInfoWasm { - #[wasm_bindgen(getter = "dataContractId")] - pub fn data_contract_id(&self) -> String { - self.data_contract_id.clone() - } - - #[wasm_bindgen(getter = "groupContractPosition")] - pub fn group_contract_position(&self) -> u32 { - self.group_contract_position - } - - #[wasm_bindgen(getter = "role")] - pub fn role(&self) -> String { - self.role.clone() - } - - #[wasm_bindgen(getter = "power")] + #[wasm_bindgen(getter)] pub fn power(&self) -> Option { self.power.map(|value| BigInt::from(value as u64)) } @@ -592,15 +579,13 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getGroupInfo")] pub async fn get_group_info( &self, - #[wasm_bindgen(js_name = "dataContractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - data_contract_id: JsValue, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, #[wasm_bindgen(js_name = "groupContractPosition")] group_contract_position: u32, ) -> Result, WasmSdkError> { // Parse data contract ID - let contract_id: Identifier = IdentifierWasm::try_from(&data_contract_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)))? - .into(); + let contract_id: Identifier = data_contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; // Create group query let query = GroupQuery { @@ -722,15 +707,13 @@ impl WasmSdk { // Fetch groups let groups_result = Group::fetch_many(self.as_ref(), query).await?; - // Convert result to response format - let infos_map = Map::new(); - for (position, group_opt) in groups_result { - let key = Number::from(position as u32); - let value = JsValue::from(group_opt.map(GroupWasm::from)); - infos_map.set(&key.into(), &value); - } - - Ok(infos_map) + Ok(Map::from_entries(groups_result.into_iter().map( + |(position, group_opt)| { + let key: JsValue = Number::from(position as u32).into(); + let value = JsValue::from(group_opt.map(GroupWasm::from)); + (key, value) + }, + ))) } #[wasm_bindgen( @@ -752,14 +735,13 @@ impl WasmSdk { // Fetch actions let actions_result = GroupAction::fetch_many(self.as_ref(), query).await?; - let actions_map = Map::new(); - for (action_id, action_opt) in actions_result { - let key = JsValue::from(IdentifierWasm::from(action_id)); - let value = JsValue::from(action_opt.map(GroupActionWasm::from)); - actions_map.set(&key, &value); - } - - Ok(actions_map) + Ok(Map::from_entries(actions_result.into_iter().map( + |(action_id, action_opt)| { + let key = JsValue::from(IdentifierWasm::from(action_id)); + let value = JsValue::from(action_opt.map(GroupActionWasm::from)); + (key, value) + }, + ))) } #[wasm_bindgen( @@ -783,16 +765,15 @@ impl WasmSdk { // Fetch signers let signers_result = GroupMemberPower::fetch_many(self.as_ref(), query).await?; - let signers_map = Map::new(); - for (signer_id, power_opt) in signers_result { - if let Some(power) = power_opt { - let key = JsValue::from(IdentifierWasm::from(signer_id)); - let value = JsValue::from(BigInt::from(power as u64)); - signers_map.set(&key, &value); - } - } - - Ok(signers_map) + Ok(Map::from_entries(signers_result.into_iter().filter_map( + |(signer_id, power_opt)| { + power_opt.map(|power| { + let key = JsValue::from(IdentifierWasm::from(signer_id)); + let value = JsValue::from(BigInt::from(power as u64)); + (key, value) + }) + }, + ))) } #[wasm_bindgen( @@ -801,19 +782,16 @@ impl WasmSdk { )] pub async fn get_groups_data_contracts( &self, - #[wasm_bindgen(js_name = "dataContractIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - data_contract_ids: Vec, + #[wasm_bindgen(js_name = "dataContractIds")] data_contract_ids: IdentifierLikeArrayJs, ) -> Result { - let contracts_map = Map::new(); + use wasm_dpp2::utils::try_to_vec; + + let contract_identifiers: Vec = + try_to_vec::(data_contract_ids, "dataContractIds", "identifier")?; - for contract_js in data_contract_ids { - let contract_id: Identifier = IdentifierWasm::try_from(&contract_js) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) - })? - .into(); + let contracts_map = Map::new(); + for contract_id in contract_identifiers { let contract_key = JsValue::from(IdentifierWasm::from(contract_id)); // Fetch all groups for this contract @@ -825,13 +803,12 @@ impl WasmSdk { let groups_result = Group::fetch_many(self.as_ref(), query).await?; - let groups_map = Map::new(); - - for (position, group_opt) in groups_result { - let key = Number::from(position as u32); - let value = JsValue::from(group_opt.map(GroupWasm::from)); - groups_map.set(&key.into(), &value); - } + let groups_map = + Map::from_entries(groups_result.into_iter().map(|(position, group_opt)| { + let key: JsValue = Number::from(position as u32).into(); + let value = JsValue::from(group_opt.map(GroupWasm::from)); + (key, value) + })); contracts_map.set(&contract_key, &JsValue::from(groups_map)); } @@ -847,15 +824,13 @@ impl WasmSdk { )] pub async fn get_group_info_with_proof_info( &self, - #[wasm_bindgen(js_name = "dataContractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - data_contract_id: JsValue, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, #[wasm_bindgen(js_name = "groupContractPosition")] group_contract_position: u32, ) -> Result { // Parse data contract ID - let contract_id: Identifier = IdentifierWasm::try_from(&data_contract_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)))? - .into(); + let contract_id: Identifier = data_contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; // Create group query let query = GroupQuery { @@ -897,16 +872,16 @@ impl WasmSdk { let (groups_result, metadata, proof) = Group::fetch_many_with_metadata_and_proof(self.as_ref(), query, None).await?; - let infos_map = Map::new(); - for (position, group_opt) in groups_result { - let key = Number::from(position as u32); - let value = JsValue::from(group_opt.map(GroupWasm::from)); - infos_map.set(&key.into(), &value); - } - - let response = ProofMetadataResponseWasm::from_sdk_parts(infos_map, metadata, proof); + let infos_map = + Map::from_entries(groups_result.into_iter().map(|(position, group_opt)| { + let key: JsValue = Number::from(position as u32).into(); + let value = JsValue::from(group_opt.map(GroupWasm::from)); + (key, value) + })); - Ok(response) + Ok(ProofMetadataResponseWasm::from_sdk_parts( + infos_map, metadata, proof, + )) } // Additional proof info versions for remaining group queries @@ -1045,16 +1020,18 @@ impl WasmSdk { let (actions_result, metadata, proof) = GroupAction::fetch_many_with_metadata_and_proof(self.as_ref(), query, None).await?; - let actions_map = Map::new(); - for (action_id, action_opt) in actions_result { - let key = JsValue::from(IdentifierWasm::from(action_id)); - let value = JsValue::from(action_opt.map(GroupActionWasm::from)); - actions_map.set(&key, &value); - } - - let response = ProofMetadataResponseWasm::from_sdk_parts(actions_map, metadata, proof); + let actions_map = + Map::from_entries(actions_result.into_iter().map(|(action_id, action_opt)| { + let key = JsValue::from(IdentifierWasm::from(action_id)); + let value = JsValue::from(action_opt.map(GroupActionWasm::from)); + (key, value) + })); - Ok(response) + Ok(ProofMetadataResponseWasm::from_sdk_parts( + actions_map, + metadata, + proof, + )) } #[wasm_bindgen( @@ -1078,18 +1055,21 @@ impl WasmSdk { GroupMemberPower::fetch_many_with_metadata_and_proof(self.as_ref(), query, None) .await?; - let signers_map = Map::new(); - for (signer_id, power_opt) in signers_result { - if let Some(power) = power_opt { - let key = JsValue::from(IdentifierWasm::from(signer_id)); - let value = JsValue::from(BigInt::from(power as u64)); - signers_map.set(&key, &value); - } - } - - let response = ProofMetadataResponseWasm::from_sdk_parts(signers_map, metadata, proof); - - Ok(response) + let signers_map = Map::from_entries(signers_result.into_iter().filter_map( + |(signer_id, power_opt)| { + power_opt.map(|power| { + let key = JsValue::from(IdentifierWasm::from(signer_id)); + let value = JsValue::from(BigInt::from(power as u64)); + (key, value) + }) + }, + )); + + Ok(ProofMetadataResponseWasm::from_sdk_parts( + signers_map, + metadata, + proof, + )) } #[wasm_bindgen( @@ -1098,15 +1078,16 @@ impl WasmSdk { )] pub async fn get_groups_data_contracts_with_proof_info( &self, - #[wasm_bindgen(js_name = "dataContractIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - data_contract_ids: Vec, + #[wasm_bindgen(js_name = "dataContractIds")] data_contract_ids: IdentifierLikeArrayJs, ) -> Result { + use wasm_dpp2::utils::try_to_vec; + let contracts_map = Map::new(); let mut combined_metadata: Option = None; let mut combined_proof: Option = None; - let contract_identifiers = identifiers_from_js(data_contract_ids, "contract ID")?; + let contract_identifiers: Vec = + try_to_vec::(data_contract_ids, "dataContractIds", "identifier")?; for contract_id in contract_identifiers { let contract_key = JsValue::from(IdentifierWasm::from(contract_id)); @@ -1126,12 +1107,12 @@ impl WasmSdk { combined_proof = Some(proof.clone()); } - let groups_map = Map::new(); - for (position, group_opt) in groups_result { - let key = Number::from(position as u32); - let value = JsValue::from(group_opt.map(GroupWasm::from)); - groups_map.set(&key.into(), &value); - } + let groups_map = + Map::from_entries(groups_result.into_iter().map(|(position, group_opt)| { + let key: JsValue = Number::from(position as u32).into(); + let value = JsValue::from(group_opt.map(GroupWasm::from)); + (key, value) + })); contracts_map.set(&contract_key, &JsValue::from(groups_map)); } diff --git a/packages/wasm-sdk/src/queries/identity.rs b/packages/wasm-sdk/src/queries/identity.rs index ad13284e68b..651388acb5b 100644 --- a/packages/wasm-sdk/src/queries/identity.rs +++ b/packages/wasm-sdk/src/queries/identity.rs @@ -10,41 +10,33 @@ use dash_sdk::dpp::identity::Purpose; use dash_sdk::platform::identities_contract_keys_query::IdentitiesContractKeysQuery; use dash_sdk::platform::{Fetch, FetchMany, Identifier, Identity, IdentityKeysQuery}; use drive_proof_verifier::types::{IdentityPublicKeys, IndexMap}; -use js_sys::{Array, BigInt, Map, Uint8Array}; +use js_sys::{Array, BigInt, Map}; use rs_dapi_client::IntoInner; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::identifier::{ + IdentifierLikeArrayJs, IdentifierLikeJs, IdentifierLikeOrUndefinedJs, IdentifierWasm, +}; use wasm_dpp2::identity::public_key::IdentityPublicKeyWasm; use wasm_dpp2::identity::IdentityWasm; +use wasm_dpp2::{public_key_hash_from_js, PublicKeyHashLikeJs}; #[wasm_bindgen(js_name = "IdentityContractKeys")] pub struct IdentityContractKeysWasm { - identity_id: IdentifierWasm, - keys: Vec, + #[wasm_bindgen(getter_with_clone, js_name = "identityId")] + pub identity_id: IdentifierWasm, + #[wasm_bindgen(getter_with_clone)] + pub keys: Vec, } impl IdentityContractKeysWasm { - fn new(identity_id: IdentifierWasm, keys: Vec) -> Self { + pub(crate) fn new(identity_id: IdentifierWasm, keys: Vec) -> Self { IdentityContractKeysWasm { identity_id, keys } } } -#[wasm_bindgen(js_class = IdentityContractKeys)] -impl IdentityContractKeysWasm { - #[wasm_bindgen(getter = "identityId")] - pub fn identity_id(&self) -> IdentifierWasm { - self.identity_id - } - - #[wasm_bindgen(getter = "keys")] - pub fn keys(&self) -> Vec { - self.keys.clone() - } -} - #[wasm_bindgen(js_name = "IdentityBalanceAndRevision")] #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -319,13 +311,11 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getIdentity")] pub async fn get_identity( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result, WasmSdkError> { - let id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let identity = Identity::fetch_by_identifier(self.as_ref(), id).await?; @@ -338,13 +328,11 @@ impl WasmSdk { )] pub async fn get_identity_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { - let id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let (identity, metadata, proof) = Identity::fetch_with_metadata_and_proof(self.as_ref(), id, None).await?; @@ -362,9 +350,7 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getIdentityUnproved")] pub async fn get_identity_unproved( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::proto::get_identity_request::{ GetIdentityRequestV0, Version as GetIdentityRequestVersion, @@ -375,9 +361,9 @@ impl WasmSdk { use dash_sdk::platform::proto::{GetIdentityRequest, GetIdentityResponse}; use rs_dapi_client::{DapiRequest, RequestSettings}; - let id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let request = GetIdentityRequest { version: Some(GetIdentityRequestVersion::V0(GetIdentityRequestV0 { @@ -547,26 +533,21 @@ impl WasmSdk { Ok(array) } - #[wasm_bindgen(js_name = "getIdentityNonce", unchecked_return_type = "bigint | null")] + #[wasm_bindgen(js_name = "getIdentityNonce")] pub async fn get_identity_nonce( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - ) -> Result { + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + ) -> Result, WasmSdkError> { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityNonceFetcher; - let id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let nonce_result = IdentityNonceFetcher::fetch(self.as_ref(), id).await?; - match nonce_result { - Some(fetcher) => Ok(BigInt::from(fetcher.0).into()), - None => Ok(JsValue::NULL), - } + Ok(nonce_result.map(|fetcher| BigInt::from(fetcher.0))) } #[wasm_bindgen( @@ -575,16 +556,14 @@ impl WasmSdk { )] pub async fn get_identity_nonce_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityNonceFetcher; - let id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let (nonce_result, metadata, proof) = IdentityNonceFetcher::fetch_with_metadata_and_proof(self.as_ref(), id, None).await?; @@ -599,36 +578,26 @@ impl WasmSdk { )) } - #[wasm_bindgen( - js_name = "getIdentityContractNonce", - unchecked_return_type = "bigint | null" - )] + #[wasm_bindgen(js_name = "getIdentityContractNonce")] pub async fn get_identity_contract_nonce( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "contractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - contract_id: JsValue, - ) -> Result { + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, + ) -> Result, WasmSdkError> { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityContractNonceFetcher; - let identity_id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); - let contract_id: Identifier = IdentifierWasm::try_from(&contract_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)))? - .into(); + let identity_id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; + let contract_id: Identifier = contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; let nonce_result = IdentityContractNonceFetcher::fetch(self.as_ref(), (identity_id, contract_id)).await?; - match nonce_result { - Some(fetcher) => Ok(BigInt::from(fetcher.0).into()), - None => Ok(JsValue::NULL), - } + Ok(nonce_result.map(|fetcher| BigInt::from(fetcher.0))) } #[wasm_bindgen( @@ -637,22 +606,18 @@ impl WasmSdk { )] pub async fn get_identity_contract_nonce_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "contractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - contract_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityContractNonceFetcher; - let identity_id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); - let contract_id: Identifier = IdentifierWasm::try_from(&contract_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)))? - .into(); + let identity_id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; + let contract_id: Identifier = contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; let (nonce_result, metadata, proof) = IdentityContractNonceFetcher::fetch_with_metadata_and_proof( @@ -672,29 +637,21 @@ impl WasmSdk { )) } - #[wasm_bindgen( - js_name = "getIdentityBalance", - unchecked_return_type = "bigint | null" - )] + #[wasm_bindgen(js_name = "getIdentityBalance")] pub async fn get_identity_balance( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - ) -> Result { + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + ) -> Result, WasmSdkError> { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityBalance; - let identity_id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let identity_id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let balance_result = IdentityBalance::fetch(self.as_ref(), identity_id).await?; - match balance_result { - Some(balance) => Ok(BigInt::from(balance).into()), - None => Ok(JsValue::NULL), - } + Ok(balance_result.map(BigInt::from)) } #[wasm_bindgen( @@ -703,23 +660,14 @@ impl WasmSdk { )] pub async fn get_identities_balances( &self, - #[wasm_bindgen(js_name = "identityIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - identity_ids: Vec, + #[wasm_bindgen(js_name = "identityIds")] identity_ids: IdentifierLikeArrayJs, ) -> Result { use drive_proof_verifier::types::IdentityBalance; + use wasm_dpp2::utils::try_to_vec; // Convert JS identifiers to native Identifiers - let identifiers: Vec = identity_ids - .into_iter() - .map(|value| { - IdentifierWasm::try_from(&value) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) - }) - }) - .collect::, _>>()?; + let identifiers: Vec = + try_to_vec::(identity_ids, "identityIds", "identifier")?; let balances_result: drive_proof_verifier::types::IdentityBalances = IdentityBalance::fetch_many(self.as_ref(), identifiers.clone()).await?; @@ -738,52 +686,33 @@ impl WasmSdk { Ok(results_map) } - #[wasm_bindgen( - js_name = "getIdentityBalanceAndRevision", - unchecked_return_type = "IdentityBalanceAndRevision | null" - )] + #[wasm_bindgen(js_name = "getIdentityBalanceAndRevision")] pub async fn get_identity_balance_and_revision( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - ) -> Result { + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + ) -> Result, WasmSdkError> { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityBalanceAndRevision; - let id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let result = IdentityBalanceAndRevision::fetch(self.as_ref(), id).await?; - match result { - Some((balance, revision)) => { - Ok(IdentityBalanceAndRevisionWasm::new(balance, revision).into()) - } - None => Ok(JsValue::NULL), - } + Ok( + result + .map(|(balance, revision)| IdentityBalanceAndRevisionWasm::new(balance, revision)), + ) } - #[wasm_bindgen( - js_name = "getIdentityByPublicKeyHash", - unchecked_return_type = "Identity | null" - )] + #[wasm_bindgen(js_name = "getIdentityByPublicKeyHash")] pub async fn get_identity_by_public_key_hash( &self, - #[wasm_bindgen(js_name = "publicKeyHash")] - #[wasm_bindgen(unchecked_param_type = "string | Uint8Array")] - public_key_hash: JsValue, - ) -> Result { + #[wasm_bindgen(js_name = "publicKeyHash")] public_key_hash: PublicKeyHashLikeJs, + ) -> Result, WasmSdkError> { use dash_sdk::platform::types::identity::PublicKeyHash; - let hash_bytes: Vec = if let Some(hex_str) = public_key_hash.as_string() { - hex::decode(&hex_str).map_err(|e| { - WasmSdkError::invalid_argument(format!("Invalid public key hash hex: {}", e)) - })? - } else { - let arr = Uint8Array::new(&public_key_hash); - arr.to_vec() - }; + let hash_bytes: Vec = public_key_hash_from_js(public_key_hash)?; if hash_bytes.len() != 20 { return Err(WasmSdkError::invalid_argument( "Public key hash must be 20 bytes (40 hex characters)", @@ -795,10 +724,7 @@ impl WasmSdk { let result = Identity::fetch(self.as_ref(), PublicKeyHash(hash_array)).await?; - match result { - Some(identity) => Ok(IdentityWasm::from(identity).into()), - None => Ok(JsValue::NULL), - } + Ok(result.map(IdentityWasm::from)) } #[wasm_bindgen( @@ -845,21 +771,10 @@ impl WasmSdk { )] pub async fn get_identity_by_non_unique_public_key_hash( &self, - #[wasm_bindgen(js_name = "publicKeyHash")] - #[wasm_bindgen(unchecked_param_type = "string | Uint8Array")] - public_key_hash: JsValue, - #[wasm_bindgen(js_name = "startAfterId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string | undefined")] - start_after_id: JsValue, + #[wasm_bindgen(js_name = "publicKeyHash")] public_key_hash: PublicKeyHashLikeJs, + #[wasm_bindgen(js_name = "startAfterId")] start_after_id: IdentifierLikeOrUndefinedJs, ) -> Result { - let hash_bytes: Vec = if let Some(hex_str) = public_key_hash.as_string() { - hex::decode(&hex_str).map_err(|e| { - WasmSdkError::invalid_argument(format!("Invalid public key hash hex: {}", e)) - })? - } else { - let arr = Uint8Array::new(&public_key_hash); - arr.to_vec() - }; + let hash_bytes: Vec = public_key_hash_from_js(public_key_hash)?; if hash_bytes.len() != 20 { return Err(WasmSdkError::invalid_argument( "Public key hash must be 20 bytes (40 hex characters)", @@ -870,20 +785,9 @@ impl WasmSdk { hash_array.copy_from_slice(&hash_bytes); // Convert start_after if provided - let start_id = if start_after_id.is_undefined() || start_after_id.is_null() { - None - } else { - Some( - IdentifierWasm::try_from(&start_after_id) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!( - "Invalid startAfter identity ID: {}", - err - )) - })?, - ) - }; + let start_id: Option = start_after_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid startAfter identity ID: {}", err)) + })?; use dash_sdk::platform::types::identity::NonUniquePublicKeyHashQuery; @@ -907,31 +811,20 @@ impl WasmSdk { )] pub async fn get_identity_token_balances( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { use dash_sdk::dpp::balances::credits::TokenAmount; use dash_sdk::platform::tokens::identity_token_balances::IdentityTokenBalancesQuery; + use wasm_dpp2::utils::try_to_vec; - let identity_id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let identity_id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; // Convert token IDs to Identifiers - let token_identifiers: Vec = token_ids - .into_iter() - .map(|value| { - IdentifierWasm::try_from(&value) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)) - }) - }) - .collect::, _>>()?; + let token_identifiers: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; let query = IdentityTokenBalancesQuery { identity_id, @@ -1021,16 +914,14 @@ impl WasmSdk { )] pub async fn get_identity_balance_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityBalance; - let identity_id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let identity_id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let (balance_result, metadata, proof) = IdentityBalance::fetch_with_metadata_and_proof(self.as_ref(), identity_id, None) @@ -1052,23 +943,14 @@ impl WasmSdk { )] pub async fn get_identities_balances_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - identity_ids: Vec, + #[wasm_bindgen(js_name = "identityIds")] identity_ids: IdentifierLikeArrayJs, ) -> Result { use drive_proof_verifier::types::IdentityBalance; + use wasm_dpp2::utils::try_to_vec; // Convert JS identifiers to native Identifiers - let identifiers: Vec = identity_ids - .into_iter() - .map(|value| { - IdentifierWasm::try_from(&value) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) - }) - }) - .collect::, _>>()?; + let identifiers: Vec = + try_to_vec::(identity_ids, "identityIds", "identifier")?; let (balances_result, metadata, proof): ( drive_proof_verifier::types::IdentityBalances, @@ -1104,16 +986,14 @@ impl WasmSdk { )] pub async fn get_identity_balance_and_revision_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::IdentityBalanceAndRevision; - let id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; let (result, metadata, proof) = IdentityBalanceAndRevision::fetch_with_metadata_and_proof(self.as_ref(), id, None) @@ -1137,19 +1017,10 @@ impl WasmSdk { )] pub async fn get_identity_by_public_key_hash_with_proof_info( &self, - #[wasm_bindgen(js_name = "publicKeyHash")] - #[wasm_bindgen(unchecked_param_type = "string | Uint8Array")] - public_key_hash: JsValue, + #[wasm_bindgen(js_name = "publicKeyHash")] public_key_hash: PublicKeyHashLikeJs, ) -> Result { use dash_sdk::platform::types::identity::PublicKeyHash; - let hash_bytes: Vec = if let Some(hex_str) = public_key_hash.as_string() { - hex::decode(&hex_str).map_err(|e| { - WasmSdkError::invalid_argument(format!("Invalid public key hash hex: {}", e)) - })? - } else { - let arr = Uint8Array::new(&public_key_hash); - arr.to_vec() - }; + let hash_bytes: Vec = public_key_hash_from_js(public_key_hash)?; if hash_bytes.len() != 20 { return Err(WasmSdkError::invalid_argument( "Public key hash must be 20 bytes (40 hex characters)", @@ -1179,21 +1050,10 @@ impl WasmSdk { )] pub async fn get_identity_by_non_unique_public_key_hash_with_proof_info( &self, - #[wasm_bindgen(js_name = "publicKeyHash")] - #[wasm_bindgen(unchecked_param_type = "string | Uint8Array")] - public_key_hash: JsValue, - #[wasm_bindgen(js_name = "startAfterId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string | undefined")] - start_after_id: JsValue, + #[wasm_bindgen(js_name = "publicKeyHash")] public_key_hash: PublicKeyHashLikeJs, + #[wasm_bindgen(js_name = "startAfterId")] start_after_id: IdentifierLikeOrUndefinedJs, ) -> Result { - let hash_bytes: Vec = if let Some(hex_str) = public_key_hash.as_string() { - hex::decode(&hex_str).map_err(|e| { - WasmSdkError::invalid_argument(format!("Invalid public key hash hex: {}", e)) - })? - } else { - let arr = Uint8Array::new(&public_key_hash); - arr.to_vec() - }; + let hash_bytes: Vec = public_key_hash_from_js(public_key_hash)?; if hash_bytes.len() != 20 { return Err(WasmSdkError::invalid_argument( "Public key hash must be 20 bytes (40 hex characters)", @@ -1204,20 +1064,9 @@ impl WasmSdk { hash_array.copy_from_slice(&hash_bytes); // Convert start_after if provided - let start_id = if start_after_id.is_undefined() || start_after_id.is_null() { - None - } else { - Some( - IdentifierWasm::try_from(&start_after_id) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!( - "Invalid startAfter identity ID: {}", - err - )) - })?, - ) - }; + let start_id: Option = start_after_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid startAfter identity ID: {}", err)) + })?; use dash_sdk::platform::types::identity::NonUniquePublicKeyHashQuery; @@ -1290,31 +1139,20 @@ impl WasmSdk { )] pub async fn get_identity_token_balances_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { use dash_sdk::dpp::balances::credits::TokenAmount; use dash_sdk::platform::tokens::identity_token_balances::IdentityTokenBalancesQuery; + use wasm_dpp2::utils::try_to_vec; - let identity_id: Identifier = IdentifierWasm::try_from(&identity_id) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)))? - .into(); + let identity_id: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; // Convert token IDs to Identifiers - let token_identifiers: Vec = token_ids - .into_iter() - .map(|value| { - IdentifierWasm::try_from(&value) - .map(Identifier::from) - .map_err(|err| { - WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)) - }) - }) - .collect::, _>>()?; + let token_identifiers: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; let query = IdentityTokenBalancesQuery { identity_id, diff --git a/packages/wasm-sdk/src/queries/mod.rs b/packages/wasm-sdk/src/queries/mod.rs index 95fd6a19ade..6181cb61aea 100644 --- a/packages/wasm-sdk/src/queries/mod.rs +++ b/packages/wasm-sdk/src/queries/mod.rs @@ -40,7 +40,7 @@ pub struct ResponseMetadataWasm { #[wasm_bindgen(js_class = ResponseMetadata)] impl ResponseMetadataWasm { #[wasm_bindgen(constructor)] - pub fn new( + pub fn constructor( height: u64, #[wasm_bindgen(js_name = "coreChainLockedHeight")] core_chain_locked_height: u32, epoch: u32, @@ -128,7 +128,7 @@ pub struct ProofInfoWasm { #[wasm_bindgen(js_class = ProofInfo)] impl ProofInfoWasm { #[wasm_bindgen(constructor)] - pub fn new( + pub fn constructor( #[wasm_bindgen(js_name = "grovedbProof")] grovedb_proof: Uint8Array, #[wasm_bindgen(js_name = "quorumHash")] quorum_hash: Uint8Array, signature: Uint8Array, @@ -253,7 +253,11 @@ impl ProofMetadataResponseWasm { } #[wasm_bindgen(constructor)] - pub fn new(data: JsValue, metadata: ResponseMetadataWasm, proof: ProofInfoWasm) -> Self { + pub fn constructor( + data: JsValue, + metadata: ResponseMetadataWasm, + proof: ProofInfoWasm, + ) -> Self { // Store data as-is. Conversion to JSON happens in to_serde()/toJSON(). // This allows WASM objects (like DataContractWasm) to be stored directly // and their toJSON() method will be called when serializing. @@ -301,9 +305,9 @@ impl ProofMetadataResponseWasm { } #[wasm_bindgen(js_name = "fromJSON")] - pub fn from_json(js: JsValue) -> Result { + pub fn from_json(js: js_sys::Object) -> Result { let serde_struct: ProofMetadataResponseSerde = - serialization::from_json(js).map_err(WasmSdkError::from)?; + serialization::from_json(js.into()).map_err(WasmSdkError::from)?; ProofMetadataResponseWasm::from_serde(serde_struct) } @@ -314,9 +318,9 @@ impl ProofMetadataResponseWasm { } #[wasm_bindgen(js_name = "fromObject")] - pub fn from_object(obj: JsValue) -> Result { + pub fn from_object(obj: js_sys::Object) -> Result { let serde_struct: ProofMetadataResponseSerde = - serialization::from_object(obj).map_err(WasmSdkError::from)?; + serialization::from_object(obj.into()).map_err(WasmSdkError::from)?; ProofMetadataResponseWasm::from_serde(serde_struct) } } @@ -335,7 +339,7 @@ impl ProofMetadataResponseWasm { metadata: dash_sdk::platform::proto::ResponseMetadata, proof: dash_sdk::platform::proto::Proof, ) -> Self { - ProofMetadataResponseWasm::new(data.into(), metadata.into(), proof.into()) + ProofMetadataResponseWasm::constructor(data.into(), metadata.into(), proof.into()) } } diff --git a/packages/wasm-sdk/src/queries/protocol.rs b/packages/wasm-sdk/src/queries/protocol.rs index 37ea2a6e7c8..56c593b6e0e 100644 --- a/packages/wasm-sdk/src/queries/protocol.rs +++ b/packages/wasm-sdk/src/queries/protocol.rs @@ -2,11 +2,12 @@ use crate::error::WasmSdkError; use crate::impl_wasm_serde_conversions; use crate::queries::ProofMetadataResponseWasm; use crate::sdk::WasmSdk; +use dash_sdk::dpp::dashcore::ProTxHash; use js_sys::Map; use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; -use wasm_dpp2::ProTxHashWasm; +use wasm_dpp2::{ProTxHashLikeNullableJs, ProTxHashWasm}; #[wasm_bindgen(js_name = "ProtocolVersionUpgradeState")] #[derive(Clone, Serialize, Deserialize)] @@ -16,7 +17,8 @@ pub struct ProtocolVersionUpgradeStateWasm { next_protocol_version: Option, activation_height: Option, vote_count: Option, - threshold_reached: bool, + #[serde(rename = "thresholdReached")] + is_threshold_reached: bool, } impl ProtocolVersionUpgradeStateWasm { @@ -25,14 +27,14 @@ impl ProtocolVersionUpgradeStateWasm { next_protocol_version: Option, activation_height: Option, vote_count: Option, - threshold_reached: bool, + is_threshold_reached: bool, ) -> Self { Self { current_protocol_version, next_protocol_version, activation_height, vote_count, - threshold_reached, + is_threshold_reached, } } } @@ -59,24 +61,23 @@ impl ProtocolVersionUpgradeStateWasm { self.vote_count } - #[wasm_bindgen(getter = "thresholdReached")] - pub fn threshold_reached(&self) -> bool { - self.threshold_reached + #[wasm_bindgen(getter = "isThresholdReached")] + pub fn is_threshold_reached(&self) -> bool { + self.is_threshold_reached } } #[wasm_bindgen(js_name = "ProtocolVersionUpgradeVoteStatus")] -#[derive(Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] +#[derive(Clone)] pub struct ProtocolVersionUpgradeVoteStatusWasm { - pro_tx_hash: String, + pro_tx_hash: ProTxHashWasm, version: u32, } impl ProtocolVersionUpgradeVoteStatusWasm { - fn new(pro_tx_hash: String, version: u32) -> Self { + pub(crate) fn new(pro_tx_hash: ProTxHash, version: u32) -> Self { Self { - pro_tx_hash, + pro_tx_hash: ProTxHashWasm::from(pro_tx_hash), version, } } @@ -85,21 +86,17 @@ impl ProtocolVersionUpgradeVoteStatusWasm { #[wasm_bindgen(js_class = ProtocolVersionUpgradeVoteStatus)] impl ProtocolVersionUpgradeVoteStatusWasm { #[wasm_bindgen(getter = "proTxHash")] - pub fn pro_tx_hash(&self) -> String { - self.pro_tx_hash.clone() + pub fn pro_tx_hash(&self) -> ProTxHashWasm { + self.pro_tx_hash } - #[wasm_bindgen(getter = "version")] + #[wasm_bindgen(getter)] pub fn version(&self) -> u32 { self.version } } impl_wasm_serde_conversions!(ProtocolVersionUpgradeStateWasm, ProtocolVersionUpgradeState); -impl_wasm_serde_conversions!( - ProtocolVersionUpgradeVoteStatusWasm, - ProtocolVersionUpgradeVoteStatus -); #[wasm_bindgen] impl WasmSdk { @@ -149,26 +146,14 @@ impl WasmSdk { )] pub async fn get_protocol_version_upgrade_vote_status( &self, - #[wasm_bindgen(js_name = "startProTxHash")] - #[wasm_bindgen(unchecked_param_type = "ProTxHashLike | null")] - start_pro_tx_hash: JsValue, + #[wasm_bindgen(js_name = "startProTxHash")] start_pro_tx_hash: ProTxHashLikeNullableJs, count: u32, ) -> Result { use dash_sdk::platform::types::version_votes::MasternodeProtocolVoteEx; use drive_proof_verifier::types::MasternodeProtocolVote; - // Parse the ProTxHash using centralized helper - let start_hash = if start_pro_tx_hash.is_null() || start_pro_tx_hash.is_undefined() { - None - } else if let Some(s) = start_pro_tx_hash.as_string() { - if s.is_empty() { - None - } else { - Some(ProTxHashWasm::try_from(&start_pro_tx_hash)?.into()) - } - } else { - Some(ProTxHashWasm::try_from(&start_pro_tx_hash)?.into()) - }; + // Parse the ProTxHash using extern type + let start_hash: Option = start_pro_tx_hash.try_into()?; let votes_result = MasternodeProtocolVote::fetch_votes(self.as_ref(), start_hash, Some(count)).await?; @@ -179,7 +164,7 @@ impl WasmSdk { if let Some(vote) = vote_opt { let key = JsValue::from_str(&pro_tx_hash.to_string()); let value = JsValue::from(ProtocolVersionUpgradeVoteStatusWasm::new( - pro_tx_hash.to_string(), + pro_tx_hash, vote.voted_version, )); votes_map.set(&key, &value); @@ -246,26 +231,14 @@ impl WasmSdk { )] pub async fn get_protocol_version_upgrade_vote_status_with_proof_info( &self, - #[wasm_bindgen(js_name = "startProTxHash")] - #[wasm_bindgen(unchecked_param_type = "ProTxHashLike | null")] - start_pro_tx_hash: JsValue, + #[wasm_bindgen(js_name = "startProTxHash")] start_pro_tx_hash: ProTxHashLikeNullableJs, count: u32, ) -> Result { use dash_sdk::platform::{FetchMany, LimitQuery}; use drive_proof_verifier::types::MasternodeProtocolVote; - // Parse the ProTxHash using centralized helper - let start_hash = if start_pro_tx_hash.is_null() || start_pro_tx_hash.is_undefined() { - None - } else if let Some(s) = start_pro_tx_hash.as_string() { - if s.is_empty() { - None - } else { - Some(ProTxHashWasm::try_from(&start_pro_tx_hash)?.into()) - } - } else { - Some(ProTxHashWasm::try_from(&start_pro_tx_hash)?.into()) - }; + // Parse the ProTxHash using extern type + let start_hash: Option = start_pro_tx_hash.try_into()?; // Create a LimitQuery with the start hash and count let query = LimitQuery { @@ -284,7 +257,7 @@ impl WasmSdk { if let Some(vote) = vote_opt { let key = JsValue::from_str(&pro_tx_hash.to_string()); let value = JsValue::from(ProtocolVersionUpgradeVoteStatusWasm::new( - pro_tx_hash.to_string(), + pro_tx_hash, vote.voted_version, )); votes_map.set(&key, &value); diff --git a/packages/wasm-sdk/src/queries/system.rs b/packages/wasm-sdk/src/queries/system.rs index 81010fce868..6f36d37f1ed 100644 --- a/packages/wasm-sdk/src/queries/system.rs +++ b/packages/wasm-sdk/src/queries/system.rs @@ -1,14 +1,15 @@ use crate::error::WasmSdkError; use crate::impl_wasm_serde_conversions; -use crate::queries::utils::identifier_from_js; use crate::queries::ProofMetadataResponseWasm; use crate::sdk::WasmSdk; use dash_sdk::dpp::core_types::validator_set::v0::ValidatorSetV0Getters; +use dash_sdk::platform::Identifier; use js_sys::{Array, BigInt}; use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::identifier::{IdentifierLikeJs, IdentifierWasm}; +use wasm_dpp2::ProTxHashWasm; #[wasm_bindgen(js_name = "StatusSoftware")] #[derive(Clone, Serialize, Deserialize)] @@ -100,10 +101,8 @@ impl StatusVersionWasm { #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct StatusNodeWasm { - #[wasm_bindgen(getter_with_clone)] - pub id: String, - #[wasm_bindgen(getter_with_clone)] - pub pro_tx_hash: Option, + pub(crate) id: String, + pub(crate) pro_tx_hash: Option, } impl StatusNodeWasm { @@ -112,12 +111,27 @@ impl StatusNodeWasm { } } +#[wasm_bindgen(js_class = StatusNode)] +impl StatusNodeWasm { + #[wasm_bindgen(getter)] + pub fn id(&self) -> String { + self.id.clone() + } + + #[wasm_bindgen(getter = "proTxHash")] + pub fn pro_tx_hash(&self) -> Option { + self.pro_tx_hash + .as_ref() + .and_then(|hex| ProTxHashWasm::from_hex(hex).ok()) + } +} + #[wasm_bindgen(js_name = "StatusChain")] #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct StatusChainWasm { - #[wasm_bindgen(getter_with_clone)] - pub catching_up: bool, + #[wasm_bindgen(getter_with_clone, js_name = "isCatchingUp")] + pub is_catching_up: bool, #[wasm_bindgen(getter_with_clone)] pub latest_block_hash: String, #[wasm_bindgen(getter_with_clone)] @@ -139,7 +153,7 @@ pub struct StatusChainWasm { impl StatusChainWasm { #[allow(clippy::too_many_arguments)] fn new( - catching_up: bool, + is_catching_up: bool, latest_block_hash: String, latest_app_hash: String, latest_block_height: String, @@ -150,7 +164,7 @@ impl StatusChainWasm { core_chain_locked_height: Option, ) -> Self { Self { - catching_up, + is_catching_up, latest_block_hash, latest_app_hash, latest_block_height, @@ -171,16 +185,16 @@ pub struct StatusNetworkWasm { pub chain_id: String, #[wasm_bindgen(getter_with_clone)] pub peers_count: u32, - #[wasm_bindgen(getter_with_clone)] - pub listening: bool, + #[wasm_bindgen(getter_with_clone, js_name = "isListening")] + pub is_listening: bool, } impl StatusNetworkWasm { - fn new(chain_id: String, peers_count: u32, listening: bool) -> Self { + fn new(chain_id: String, peers_count: u32, is_listening: bool) -> Self { Self { chain_id, peers_count, - listening, + is_listening, } } } @@ -296,15 +310,20 @@ impl_wasm_serde_conversions!(StateTransitionResultWasm, StateTransitionResult); #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct QuorumInfoWasm { - quorum_hash: String, - quorum_type: String, - member_count: u32, - threshold: u32, - is_verified: bool, + #[wasm_bindgen(getter_with_clone, js_name = "quorumHash")] + pub quorum_hash: String, + #[wasm_bindgen(getter_with_clone, js_name = "quorumType")] + pub quorum_type: String, + #[wasm_bindgen(getter_with_clone, js_name = "memberCount")] + pub member_count: u32, + #[wasm_bindgen(getter_with_clone)] + pub threshold: u32, + #[wasm_bindgen(getter_with_clone, js_name = "isVerified")] + pub is_verified: bool, } impl QuorumInfoWasm { - fn new( + pub(crate) fn new( quorum_hash: String, quorum_type: String, member_count: u32, @@ -321,34 +340,6 @@ impl QuorumInfoWasm { } } -#[wasm_bindgen(js_class = QuorumInfo)] -impl QuorumInfoWasm { - #[wasm_bindgen(getter = "quorumHash")] - pub fn quorum_hash(&self) -> String { - self.quorum_hash.clone() - } - - #[wasm_bindgen(getter = "quorumType")] - pub fn quorum_type(&self) -> String { - self.quorum_type.clone() - } - - #[wasm_bindgen(getter = "memberCount")] - pub fn member_count(&self) -> u32 { - self.member_count - } - - #[wasm_bindgen(getter = "threshold")] - pub fn threshold(&self) -> u32 { - self.threshold - } - - #[wasm_bindgen(getter = "isVerified")] - pub fn is_verified(&self) -> bool { - self.is_verified - } -} - #[wasm_bindgen(js_name = "CurrentQuorumsInfo")] #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -415,18 +406,19 @@ impl PrefundedSpecializedBalanceWasm { #[serde(rename_all = "camelCase")] pub struct PathElementWasm { path: Vec, - value: Option, + #[wasm_bindgen(getter_with_clone)] + pub value: Option, } impl PathElementWasm { - fn new(path: Vec, value: Option) -> Self { + pub(crate) fn new(path: Vec, value: Option) -> Self { Self { path, value } } } #[wasm_bindgen(js_class = PathElement)] impl PathElementWasm { - #[wasm_bindgen(getter = "path")] + #[wasm_bindgen(getter)] pub fn path(&self) -> Array { let array = Array::new(); for segment in &self.path { @@ -434,11 +426,6 @@ impl PathElementWasm { } array } - - #[wasm_bindgen(getter = "value")] - pub fn value(&self) -> Option { - self.value.clone() - } } #[wasm_bindgen(js_name = "StateTransitionResult")] @@ -796,14 +783,14 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getPrefundedSpecializedBalance")] pub async fn get_prefunded_specialized_balance( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::PrefundedSpecializedBalance as PrefundedBalance; - let identity_identifier = identifier_from_js(&identity_id, "identity ID")?; + let identity_identifier: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; // Fetch prefunded specialized balance let balance_result = PrefundedBalance::fetch(self.as_ref(), identity_identifier).await?; @@ -977,14 +964,14 @@ impl WasmSdk { )] pub async fn get_prefunded_specialized_balance_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::Fetch; use drive_proof_verifier::types::PrefundedSpecializedBalance as PrefundedBalance; - let identity_identifier = identifier_from_js(&identity_id, "identity ID")?; + let identity_identifier: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; // Fetch prefunded specialized balance with proof let (balance_result, metadata, proof) = PrefundedBalance::fetch_with_metadata_and_proof( diff --git a/packages/wasm-sdk/src/queries/token.rs b/packages/wasm-sdk/src/queries/token.rs index 69de5fdbeb3..a7bb8b68aad 100644 --- a/packages/wasm-sdk/src/queries/token.rs +++ b/packages/wasm-sdk/src/queries/token.rs @@ -1,11 +1,10 @@ use crate::error::WasmSdkError; use crate::impl_wasm_serde_conversions; -use crate::queries::utils::{identifier_from_js, identifiers_from_js}; use crate::queries::ProofMetadataResponseWasm; use crate::sdk::WasmSdk; use dash_sdk::dpp::balances::credits::TokenAmount; -use dash_sdk::dpp::tokens::calculate_token_id; use dash_sdk::dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_moment::RewardDistributionMoment; +use dash_sdk::dpp::tokens::calculate_token_id; use dash_sdk::dpp::tokens::info::IdentityTokenInfo; use dash_sdk::dpp::tokens::status::TokenStatus; use dash_sdk::dpp::tokens::token_pricing_schedule::TokenPricingSchedule; @@ -15,20 +14,24 @@ use js_sys::{BigInt, Map}; use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::identifier::{IdentifierLikeArrayJs, IdentifierLikeJs, IdentifierWasm}; +use wasm_dpp2::utils::try_to_vec; use wasm_dpp2::tokens::{IdentityTokenInfoWasm, TokenContractInfoWasm, TokenStatusWasm}; #[wasm_bindgen(js_name = "TokenPriceInfo")] #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TokenPriceInfoWasm { - token_id: IdentifierWasm, - current_price: String, - base_price: String, + #[wasm_bindgen(getter_with_clone, js_name = "tokenId")] + pub token_id: IdentifierWasm, + #[wasm_bindgen(getter_with_clone, js_name = "currentPrice")] + pub current_price: String, + #[wasm_bindgen(getter_with_clone, js_name = "basePrice")] + pub base_price: String, } impl TokenPriceInfoWasm { - fn new(token_id: IdentifierWasm, current_price: String, base_price: String) -> Self { + pub(crate) fn new(token_id: IdentifierWasm, current_price: String, base_price: String) -> Self { Self { token_id, current_price, @@ -37,24 +40,6 @@ impl TokenPriceInfoWasm { } } -#[wasm_bindgen(js_class = TokenPriceInfo)] -impl TokenPriceInfoWasm { - #[wasm_bindgen(getter = "tokenId")] - pub fn token_id(&self) -> IdentifierWasm { - self.token_id - } - - #[wasm_bindgen(getter = "currentPrice")] - pub fn current_price(&self) -> String { - self.current_price.clone() - } - - #[wasm_bindgen(getter = "basePrice")] - pub fn base_price(&self) -> String { - self.base_price.clone() - } -} - #[wasm_bindgen(js_name = "RewardDistributionMoment")] pub struct RewardDistributionMomentWasm(RewardDistributionMoment); @@ -148,13 +133,13 @@ impl WasmSdk { /// ``` #[wasm_bindgen(js_name = "calculateTokenIdFromContract")] pub fn calculate_token_id_from_contract( - #[wasm_bindgen(js_name = "contractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - contract_id: JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, #[wasm_bindgen(js_name = "tokenPosition")] token_position: u16, ) -> Result { // Parse contract ID - let contract_identifier = identifier_from_js(&contract_id, "contract ID")?; + let contract_identifier: Identifier = contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; // Calculate token ID let token_id = Identifier::from(calculate_token_id( @@ -194,13 +179,13 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getTokenPriceByContract")] pub async fn get_token_price_by_contract( &self, - #[wasm_bindgen(js_name = "contractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - contract_id: JsValue, + #[wasm_bindgen(js_name = "contractId")] contract_id: IdentifierLikeJs, #[wasm_bindgen(js_name = "tokenPosition")] token_position: u16, ) -> Result { // Parse contract ID - let contract_identifier = identifier_from_js(&contract_id, "contract ID")?; + let contract_identifier: Identifier = contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; // Calculate token ID let token_identifier = Identifier::from(calculate_token_id( @@ -263,21 +248,20 @@ impl WasmSdk { )] pub async fn get_identities_token_balances( &self, - #[wasm_bindgen(js_name = "identityIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - identity_ids: Vec, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "identityIds")] identity_ids: IdentifierLikeArrayJs, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::tokens::identity_token_balances::IdentitiesTokenBalancesQuery; use drive_proof_verifier::types::identity_token_balance::IdentitiesTokenBalances; // Parse token ID - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Parse identity IDs - let identities = identifiers_from_js(identity_ids, "identity ID")?; + let identities: Vec = + try_to_vec::(identity_ids, "identityIds", "identifier")?; // Create query let query = IdentitiesTokenBalancesQuery { @@ -307,21 +291,20 @@ impl WasmSdk { )] pub async fn get_identity_token_infos( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { use dash_sdk::platform::tokens::token_info::IdentityTokenInfosQuery; use drive_proof_verifier::types::token_info::IdentityTokenInfos; // Parse identity ID - let identity_identifier = identifier_from_js(&identity_id, "identity ID")?; + let identity_identifier: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; // Parse token IDs - let tokens = identifiers_from_js(token_ids, "token ID")?; + let tokens: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; // Create query let query = IdentityTokenInfosQuery { @@ -352,21 +335,20 @@ impl WasmSdk { )] pub async fn get_identities_token_infos( &self, - #[wasm_bindgen(js_name = "identityIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - identity_ids: Vec, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "identityIds")] identity_ids: IdentifierLikeArrayJs, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::tokens::token_info::IdentitiesTokenInfosQuery; use drive_proof_verifier::types::token_info::IdentitiesTokenInfos; // Parse token ID - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Parse identity IDs - let identities = identifiers_from_js(identity_ids, "identity ID")?; + let identities: Vec = + try_to_vec::(identity_ids, "identityIds", "identifier")?; // Create query let query = IdentitiesTokenInfosQuery { @@ -397,14 +379,13 @@ impl WasmSdk { )] pub async fn get_token_statuses( &self, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { use drive_proof_verifier::types::token_status::TokenStatuses; // Parse token IDs - let tokens = identifiers_from_js(token_ids, "token ID")?; + let tokens: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; // Fetch token statuses let statuses_result: TokenStatuses = @@ -428,14 +409,13 @@ impl WasmSdk { )] pub async fn get_token_direct_purchase_prices( &self, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { use drive_proof_verifier::types::TokenDirectPurchasePrices; // Parse token IDs - let tokens = identifiers_from_js(token_ids, "token ID")?; + let tokens: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; // Fetch token prices - use slice reference let prices_result: TokenDirectPurchasePrices = @@ -479,15 +459,15 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getTokenContractInfo")] pub async fn get_token_contract_info( &self, - #[wasm_bindgen(js_name = "dataContractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - data_contract_id: JsValue, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, ) -> Result, WasmSdkError> { use dash_sdk::dpp::tokens::contract_info::TokenContractInfo; use dash_sdk::platform::Fetch; // Parse contract ID - let contract_id = identifier_from_js(&data_contract_id, "contract ID")?; + let contract_id: Identifier = data_contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; // Fetch token contract info let info_result = TokenContractInfo::fetch(self.as_ref(), contract_id).await?; @@ -498,16 +478,16 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getTokenPerpetualDistributionLastClaim")] pub async fn get_token_perpetual_distribution_last_claim( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result, WasmSdkError> { // Parse IDs - let identity_identifier = identifier_from_js(&identity_id, "identity ID")?; - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let identity_identifier: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Prefetch token configuration and add to context provider cache // This is required for proof verification to work @@ -527,15 +507,15 @@ impl WasmSdk { #[wasm_bindgen(js_name = "getTokenTotalSupply")] pub async fn get_token_total_supply( &self, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result, WasmSdkError> { use dash_sdk::dpp::balances::total_single_token_balance::TotalSingleTokenBalance; use dash_sdk::platform::Fetch; // Parse token ID - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Fetch total supply let supply_result = TotalSingleTokenBalance::fetch(self.as_ref(), token_identifier).await?; @@ -551,20 +531,19 @@ impl WasmSdk { )] pub async fn get_identities_token_balances_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - identity_ids: Vec, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "identityIds")] identity_ids: IdentifierLikeArrayJs, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::tokens::identity_token_balances::IdentitiesTokenBalancesQuery; // Parse token ID - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Parse identity IDs - let identities = identifiers_from_js(identity_ids, "identity ID")?; + let identities: Vec = + try_to_vec::(identity_ids, "identityIds", "identifier")?; // Create query let query = IdentitiesTokenBalancesQuery { @@ -601,12 +580,11 @@ impl WasmSdk { )] pub async fn get_token_statuses_with_proof_info( &self, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { // Parse token IDs - let tokens = identifiers_from_js(token_ids, "token ID")?; + let tokens: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; // Fetch token statuses with proof let (statuses_result, metadata, proof) = @@ -635,15 +613,15 @@ impl WasmSdk { )] pub async fn get_token_total_supply_with_proof_info( &self, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result { use dash_sdk::dpp::balances::total_single_token_balance::TotalSingleTokenBalance; use dash_sdk::platform::Fetch; // Parse token ID - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Fetch total supply with proof let (supply_result, metadata, proof) = @@ -671,21 +649,20 @@ impl WasmSdk { )] pub async fn get_identity_token_infos_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { use dash_sdk::platform::tokens::token_info::IdentityTokenInfosQuery; use drive_proof_verifier::types::token_info::IdentityTokenInfos; // Parse identity ID - let identity_identifier = identifier_from_js(&identity_id, "identity ID")?; + let identity_identifier: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; // Parse token IDs - let tokens = identifiers_from_js(token_ids, "token ID")?; + let tokens: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; // Create query let query = IdentityTokenInfosQuery { @@ -719,21 +696,20 @@ impl WasmSdk { )] pub async fn get_identities_token_infos_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - identity_ids: Vec, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "identityIds")] identity_ids: IdentifierLikeArrayJs, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result { use dash_sdk::platform::tokens::token_info::IdentitiesTokenInfosQuery; use drive_proof_verifier::types::token_info::IdentitiesTokenInfos; // Parse token ID - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Parse identity IDs - let identities = identifiers_from_js(identity_ids, "identity ID")?; + let identities: Vec = + try_to_vec::(identity_ids, "identityIds", "identifier")?; // Create query let query = IdentitiesTokenInfosQuery { @@ -767,14 +743,13 @@ impl WasmSdk { )] pub async fn get_token_direct_purchase_prices_with_proof_info( &self, - #[wasm_bindgen(js_name = "tokenIds")] - #[wasm_bindgen(unchecked_param_type = "Array")] - token_ids: Vec, + #[wasm_bindgen(js_name = "tokenIds")] token_ids: IdentifierLikeArrayJs, ) -> Result { use drive_proof_verifier::types::TokenDirectPurchasePrices; // Parse token IDs - let tokens = identifiers_from_js(token_ids, "token ID")?; + let tokens: Vec = + try_to_vec::(token_ids, "tokenIds", "identifier")?; // Fetch token prices with proof - use slice reference let (prices_result, metadata, proof): (TokenDirectPurchasePrices, _, _) = @@ -827,15 +802,15 @@ impl WasmSdk { )] pub async fn get_token_contract_info_with_proof_info( &self, - #[wasm_bindgen(js_name = "dataContractId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - data_contract_id: JsValue, + #[wasm_bindgen(js_name = "dataContractId")] data_contract_id: IdentifierLikeJs, ) -> Result { use dash_sdk::dpp::tokens::contract_info::TokenContractInfo; use dash_sdk::platform::Fetch; // Parse contract ID - let contract_id = identifier_from_js(&data_contract_id, "contract ID")?; + let contract_id: Identifier = data_contract_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid contract ID: {}", err)) + })?; // Fetch token contract info with proof let (info_result, metadata, proof) = @@ -857,20 +832,20 @@ impl WasmSdk { )] pub async fn get_token_perpetual_distribution_last_claim_with_proof_info( &self, - #[wasm_bindgen(js_name = "identityId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - identity_id: JsValue, - #[wasm_bindgen(js_name = "tokenId")] - #[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")] - token_id: JsValue, + #[wasm_bindgen(js_name = "identityId")] identity_id: IdentifierLikeJs, + #[wasm_bindgen(js_name = "tokenId")] token_id: IdentifierLikeJs, ) -> Result { - use dash_sdk::platform::query::TokenLastClaimQuery; use dash_sdk::dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_moment::RewardDistributionMoment; + use dash_sdk::platform::query::TokenLastClaimQuery; use dash_sdk::platform::Fetch; // Parse IDs - let identity_identifier = identifier_from_js(&identity_id, "identity ID")?; - let token_identifier = identifier_from_js(&token_id, "token ID")?; + let identity_identifier: Identifier = identity_id.try_into().map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid identity ID: {}", err)) + })?; + let token_identifier: Identifier = token_id + .try_into() + .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid token ID: {}", err)))?; // Prefetch token configuration and add to context provider cache // This is required for proof verification to work diff --git a/packages/wasm-sdk/src/queries/utils.rs b/packages/wasm-sdk/src/queries/utils.rs index 02f8b48d1c9..24012a5069b 100644 --- a/packages/wasm-sdk/src/queries/utils.rs +++ b/packages/wasm-sdk/src/queries/utils.rs @@ -1,11 +1,10 @@ -use dash_sdk::dpp::platform_value::{Identifier, Value as PlatformValue}; +use dash_sdk::dpp::platform_value::Value as PlatformValue; use serde::de::DeserializeOwned; use serde::Serialize; use serde_json::Value as JsonValue; use wasm_bindgen::JsValue; -use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::serialization::conversions::{from_object, js_value_to_platform_value}; -use crate::utils::js_values_to_platform_values; use crate::WasmSdkError; pub(crate) fn deserialize_required_query( @@ -23,8 +22,8 @@ where return Err(WasmSdkError::invalid_argument(missing_error.to_string())); } - serde_wasm_bindgen::from_value(value) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid {}: {}", context, err))) + from_object(value) + .map_err(|e| WasmSdkError::invalid_argument(format!("Invalid {}: {}", context, e))) } pub(crate) fn deserialize_query_with_default( @@ -41,8 +40,8 @@ where return Ok(T::default()); } - serde_wasm_bindgen::from_value(value) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid {}: {}", context, err))) + from_object(value) + .map_err(|e| WasmSdkError::invalid_argument(format!("Invalid {}: {}", context, e))) } pub(crate) fn convert_optional_limit( @@ -71,33 +70,18 @@ pub(crate) fn convert_json_values_to_platform_values( values: Option>, field_name: &str, ) -> Result, WasmSdkError> { - let js_values = values + values .unwrap_or_default() .into_iter() .map(|value| { // Use json_compatible() to ensure objects become plain JS objects (not Maps) let serializer = serde_wasm_bindgen::Serializer::json_compatible(); - value.serialize(&serializer).map_err(|err| { + let js_value = value.serialize(&serializer).map_err(|err| { + WasmSdkError::invalid_argument(format!("Invalid {} entry: {}", field_name, err)) + })?; + js_value_to_platform_value(&js_value).map_err(|err| { WasmSdkError::invalid_argument(format!("Invalid {} entry: {}", field_name, err)) }) }) - .collect::, _>>()?; - - js_values_to_platform_values(js_values) -} - -pub(crate) fn identifier_from_js(value: &JsValue, field: &str) -> Result { - IdentifierWasm::try_from(value) - .map(Identifier::from) - .map_err(|err| WasmSdkError::invalid_argument(format!("Invalid {}: {}", field, err))) -} - -pub(crate) fn identifiers_from_js( - values: Vec, - field: &str, -) -> Result, WasmSdkError> { - values - .into_iter() - .map(|value| identifier_from_js(&value, field)) .collect() } diff --git a/packages/wasm-sdk/src/queries/voting/resources.rs b/packages/wasm-sdk/src/queries/voting/resources.rs index d7d12462994..b9b40996594 100644 --- a/packages/wasm-sdk/src/queries/voting/resources.rs +++ b/packages/wasm-sdk/src/queries/voting/resources.rs @@ -3,7 +3,6 @@ use crate::queries::utils::{ }; use crate::queries::ProofMetadataResponseWasm; use crate::sdk::WasmSdk; -use crate::utils::js_value_to_platform_value; use crate::WasmSdkError; use dash_sdk::dpp::platform_value::Identifier; use dash_sdk::platform::FetchMany; @@ -14,6 +13,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_dpp2::identifier::IdentifierWasm; +use wasm_dpp2::serialization::conversions::js_value_to_platform_value; #[wasm_bindgen(typescript_custom_section)] const VOTE_POLLS_BY_DOCUMENT_TYPE_QUERY_TS: &'static str = r#" @@ -122,7 +122,7 @@ fn create_vote_polls_by_document_type_query( let start_at_value = match start_at_value { Some(value) => { - let platform_value = js_value_to_platform_value(value).map_err(|err| { + let platform_value = js_value_to_platform_value(&value).map_err(|err| { WasmSdkError::invalid_argument(format!("Invalid startAtValue: {}", err)) })?; Some((platform_value, start_at_value_included.unwrap_or(true))) @@ -169,16 +169,14 @@ fn contested_resources_into_wasm( fn parse_vote_polls_by_document_type_query( query: VotePollsByDocumentTypeQueryJs, ) -> Result<(VotePollsByDocumentTypeQueryInput, Option), WasmSdkError> { - let value: JsValue = query.into(); - - if value.is_null() || value.is_undefined() { + if query.is_null() || query.is_undefined() { return Err(WasmSdkError::invalid_argument( "Query object is required".to_string(), )); } let start_at_value = - Reflect::get(&value, &JsValue::from_str("startAtValue")).map_err(|err| { + Reflect::get(&query, &JsValue::from_str("startAtValue")).map_err(|err| { let message = err .as_string() .unwrap_or_else(|| "unable to access property".to_string()); @@ -196,7 +194,7 @@ fn parse_vote_polls_by_document_type_query( }; let query_input = deserialize_required_query( - value, + query, "Query object is required", "vote polls by document type options", )?; diff --git a/packages/wasm-sdk/src/queries/voting/state.rs b/packages/wasm-sdk/src/queries/voting/state.rs index bff33ea675c..af46ba08b27 100644 --- a/packages/wasm-sdk/src/queries/voting/state.rs +++ b/packages/wasm-sdk/src/queries/voting/state.rs @@ -90,12 +90,17 @@ extern "C" { #[wasm_bindgen(js_name = "ContestedResourceVoteWinner")] #[derive(Clone)] pub struct ContestedResourceVoteWinnerWasm { - info: ContestedDocumentVotePollWinnerInfoWasm, - block: BlockInfoWasm, + #[wasm_bindgen(getter_with_clone)] + pub info: ContestedDocumentVotePollWinnerInfoWasm, + #[wasm_bindgen(getter_with_clone)] + pub block: BlockInfoWasm, } impl ContestedResourceVoteWinnerWasm { - fn from_parts(info: ContestedDocumentVotePollWinnerInfo, block: BlockInfoWasm) -> Self { + pub(crate) fn from_parts( + info: ContestedDocumentVotePollWinnerInfo, + block: BlockInfoWasm, + ) -> Self { Self { info: info.into(), block, @@ -105,36 +110,30 @@ impl ContestedResourceVoteWinnerWasm { #[wasm_bindgen(js_class = ContestedResourceVoteWinner)] impl ContestedResourceVoteWinnerWasm { - #[wasm_bindgen(getter = kind)] + #[wasm_bindgen(getter)] pub fn kind(&self) -> String { self.info.kind() } - #[wasm_bindgen(getter = identityId)] + #[wasm_bindgen(getter = "identityId")] pub fn identity_id(&self) -> Option { self.info.identity_id() } - - #[wasm_bindgen(getter = block)] - pub fn block(&self) -> BlockInfoWasm { - self.block.clone() - } - - #[wasm_bindgen(getter = info)] - pub fn info(&self) -> ContestedDocumentVotePollWinnerInfoWasm { - self.info - } } #[wasm_bindgen(js_name = "ContestedResourceContender")] #[derive(Clone)] pub struct ContestedResourceContenderWasm { identity_id: Identifier, - contender: ContenderWithSerializedDocumentWasm, + #[wasm_bindgen(getter_with_clone)] + pub contender: ContenderWithSerializedDocumentWasm, } impl ContestedResourceContenderWasm { - fn from_parts(identity: Identifier, contender: ContenderWithSerializedDocument) -> Self { + pub(crate) fn from_parts( + identity: Identifier, + contender: ContenderWithSerializedDocument, + ) -> Self { Self { identity_id: identity, contender: contender.into(), @@ -144,25 +143,20 @@ impl ContestedResourceContenderWasm { #[wasm_bindgen(js_class = ContestedResourceContender)] impl ContestedResourceContenderWasm { - #[wasm_bindgen(getter = identityId)] + #[wasm_bindgen(getter = "identityId")] pub fn identity_id(&self) -> IdentifierWasm { IdentifierWasm::from(self.identity_id) } - #[wasm_bindgen(getter = serializedDocument)] - pub fn serialized_document(&self) -> JsValue { + #[wasm_bindgen(getter = "serializedDocument")] + pub fn serialized_document(&self) -> Option { self.contender.serialized_document() } - #[wasm_bindgen(getter = voteTally)] + #[wasm_bindgen(getter = "voteTally")] pub fn vote_tally(&self) -> Option { self.contender.vote_tally() } - - #[wasm_bindgen(getter = contender)] - pub fn contender(&self) -> ContenderWithSerializedDocumentWasm { - self.contender.clone() - } } #[wasm_bindgen(js_name = "ContestedResourceVoteState")] diff --git a/packages/wasm-sdk/src/serialization.rs b/packages/wasm-sdk/src/serialization.rs index 9935b921eef..48266cf7bb8 100644 --- a/packages/wasm-sdk/src/serialization.rs +++ b/packages/wasm-sdk/src/serialization.rs @@ -28,8 +28,9 @@ macro_rules! impl_wasm_serde_conversions { } #[wasm_bindgen::prelude::wasm_bindgen(js_name = fromObject)] - pub fn from_object(obj: wasm_bindgen::JsValue) -> Result<$ty, $crate::WasmSdkError> { - wasm_dpp2::serialization::from_object(obj).map_err($crate::WasmSdkError::from) + pub fn from_object(obj: js_sys::Object) -> Result<$ty, $crate::WasmSdkError> { + wasm_dpp2::serialization::from_object(obj.into()) + .map_err($crate::WasmSdkError::from) } #[wasm_bindgen::prelude::wasm_bindgen(js_name = toJSON)] @@ -38,8 +39,8 @@ macro_rules! impl_wasm_serde_conversions { } #[wasm_bindgen::prelude::wasm_bindgen(js_name = fromJSON)] - pub fn from_json(js: wasm_bindgen::JsValue) -> Result<$ty, $crate::WasmSdkError> { - wasm_dpp2::serialization::from_json(js).map_err($crate::WasmSdkError::from) + pub fn from_json(js: js_sys::Object) -> Result<$ty, $crate::WasmSdkError> { + wasm_dpp2::serialization::from_json(js.into()).map_err($crate::WasmSdkError::from) } } }; @@ -53,8 +54,9 @@ macro_rules! impl_wasm_serde_conversions { } #[wasm_bindgen::prelude::wasm_bindgen(js_name = fromObject)] - pub fn from_object(obj: wasm_bindgen::JsValue) -> Result<$ty, $crate::WasmSdkError> { - wasm_dpp2::serialization::from_object(obj).map_err($crate::WasmSdkError::from) + pub fn from_object(obj: js_sys::Object) -> Result<$ty, $crate::WasmSdkError> { + wasm_dpp2::serialization::from_object(obj.into()) + .map_err($crate::WasmSdkError::from) } #[wasm_bindgen::prelude::wasm_bindgen(js_name = toJSON)] @@ -63,8 +65,8 @@ macro_rules! impl_wasm_serde_conversions { } #[wasm_bindgen::prelude::wasm_bindgen(js_name = fromJSON)] - pub fn from_json(js: wasm_bindgen::JsValue) -> Result<$ty, $crate::WasmSdkError> { - wasm_dpp2::serialization::from_json(js).map_err($crate::WasmSdkError::from) + pub fn from_json(js: js_sys::Object) -> Result<$ty, $crate::WasmSdkError> { + wasm_dpp2::serialization::from_json(js.into()).map_err($crate::WasmSdkError::from) } } }; diff --git a/packages/wasm-sdk/src/settings.rs b/packages/wasm-sdk/src/settings.rs index 22d6cf1a4c3..b08f609fb53 100644 --- a/packages/wasm-sdk/src/settings.rs +++ b/packages/wasm-sdk/src/settings.rs @@ -9,6 +9,7 @@ use rs_dapi_client::RequestSettings; use serde::Deserialize; use std::time::Duration; use wasm_bindgen::prelude::*; +use wasm_dpp2::serialization::conversions::from_object; // ============================================================================ // RequestSettings - for queries and basic requests @@ -90,15 +91,11 @@ pub fn parse_request_settings( return Ok(None); }; - let js_value: JsValue = settings_js.into(); - - if js_value.is_undefined() || js_value.is_null() { + if settings_js.is_undefined() || settings_js.is_null() { return Ok(None); } - let input: RequestSettingsInput = serde_wasm_bindgen::from_value(js_value).map_err(|e| { - WasmSdkError::serialization(format!("Failed to parse request settings: {}", e)) - })?; + let input: RequestSettingsInput = from_object(settings_js.into())?; Ok(Some(input.into())) } @@ -188,10 +185,11 @@ struct StateTransitionCreationOptionsInput { allow_signing_with_any_purpose: bool, } -/// Internal struct for deserializing PutSettings from JavaScript. +/// Struct for deserializing PutSettings from JavaScript. +/// Used with `try_from_options_optional::(...).map(Into::into)`. #[derive(Deserialize, Default)] #[serde(rename_all = "camelCase")] -struct PutSettingsInput { +pub struct PutSettingsInput { #[serde(flatten)] request: RequestSettingsInput, // Put-specific fields @@ -201,6 +199,14 @@ struct PutSettingsInput { state_transition_creation_options: Option, } +impl TryFrom<&JsValue> for PutSettingsInput { + type Error = wasm_dpp2::error::WasmDppError; + + fn try_from(value: &JsValue) -> Result { + from_object(value.clone()) + } +} + impl From for PutSettings { fn from(input: PutSettingsInput) -> Self { use dash_sdk::dpp::state_transition::batch_transition::methods::StateTransitionCreationOptions; @@ -243,34 +249,12 @@ pub fn parse_put_settings( return Ok(None); }; - let js_value: JsValue = settings_js.into(); - - if js_value.is_undefined() || js_value.is_null() { - return Ok(None); - } - - let input: PutSettingsInput = serde_wasm_bindgen::from_value(js_value) - .map_err(|e| WasmSdkError::serialization(format!("Failed to parse put settings: {}", e)))?; - Ok(Some(input.into())) -} - -/// Extracts PutSettings from the 'settings' field of an options object. -/// -/// This helper is useful when you have a typed options JS object and want to -/// extract the optional settings field. -pub fn extract_settings_from_options( - options: &JsValue, -) -> Result, WasmSdkError> { - let settings_js = js_sys::Reflect::get(options, &JsValue::from_str("settings")) - .map_err(|e| WasmSdkError::generic(format!("Failed to extract settings: {:?}", e)))?; - if settings_js.is_undefined() || settings_js.is_null() { return Ok(None); } - // Convert JsValue to PutSettingsJs and parse - let settings_typed: PutSettingsJs = settings_js.into(); - parse_put_settings(Some(settings_typed)) + let input: PutSettingsInput = from_object(settings_js.into())?; + Ok(Some(input.into())) } /// Extracts user_fee_increase from optional PutSettings, defaulting to 0. diff --git a/packages/wasm-sdk/src/state_transitions/addresses.rs b/packages/wasm-sdk/src/state_transitions/addresses.rs index a003ead0a67..81417be7338 100644 --- a/packages/wasm-sdk/src/state_transitions/addresses.rs +++ b/packages/wasm-sdk/src/state_transitions/addresses.rs @@ -8,7 +8,7 @@ use crate::error::WasmSdkError; use crate::queries::address::PlatformAddressInfoWasm; use crate::queries::utils::deserialize_required_query; use crate::sdk::WasmSdk; -use crate::settings::{parse_put_settings, PutSettingsJs}; +use crate::settings::PutSettingsInput; use dash_sdk::dpp::address_funds::PlatformAddress; use dash_sdk::dpp::fee::Credits; use dash_sdk::dpp::identity::core_script::CoreScript; @@ -23,6 +23,7 @@ use drive_proof_verifier::types::{AddressInfo, IndexMap}; use js_sys::{BigInt, Map}; use serde::Deserialize; use wasm_bindgen::prelude::*; +use wasm_dpp2::utils::try_from_options_optional; use wasm_dpp2::{ fee_strategy_from_steps_or_default, outputs_to_btree_map, outputs_to_optional_btree_map, CoreScriptWasm, FeeStrategyStepWasm, IdentitySignerWasm, IdentityWasm, @@ -89,22 +90,6 @@ fn deserialize_transfer_options( Ok(parsed) } -/// Extracts PutSettings from the 'settings' field of an options object. -fn extract_settings_from_options( - options: &JsValue, -) -> Result, WasmSdkError> { - let settings_js = js_sys::Reflect::get(options, &JsValue::from_str("settings")) - .map_err(|e| WasmSdkError::generic(format!("Failed to extract settings: {:?}", e)))?; - - if settings_js.is_undefined() || settings_js.is_null() { - return Ok(None); - } - - // Convert JsValue to PutSettingsJs and parse - let settings_typed: PutSettingsJs = settings_js.into(); - parse_put_settings(Some(settings_typed)) -} - /// TypeScript interface for address transfer options #[wasm_bindgen(typescript_custom_section)] const ADDRESS_TRANSFER_OPTIONS_TS: &'static str = r#" @@ -170,24 +155,21 @@ impl WasmSdk { &self, options: AddressFundsTransferOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let signer = PlatformAddressSignerWasm::try_from_options(&options, "signer")?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize and validate options - let parsed = deserialize_transfer_options(options_value.clone())?; + // Deserialize simple fields last (consumes options) + let parsed = deserialize_transfer_options(options.into())?; // Convert inputs and outputs to maps let inputs_map = outputs_to_btree_map(parsed.inputs); let outputs_map = outputs_to_btree_map(parsed.outputs); - // Extract signer from options - let signer = PlatformAddressSignerWasm::try_from_options(&options_value)?; - // Convert fee strategy from input using wasm-dpp2 helper let fee_strategy = fee_strategy_from_steps_or_default(parsed.fee_strategy); - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Use the SDK's transfer_address_funds method which handles nonces, building, and broadcasting let address_infos = self .inner_sdk() @@ -300,23 +282,18 @@ impl WasmSdk { &self, options: IdentityTopUpFromAddressesOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); + let signer = PlatformAddressSignerWasm::try_from_options(&options, "signer")?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize and validate options - let parsed = deserialize_identity_top_up_options(options_value.clone())?; - - // Extract identity from options - let identity: Identity = IdentityWasm::try_from_options(&options_value, "identity")?.into(); + // Deserialize simple fields last (consumes options) + let parsed = deserialize_identity_top_up_options(options.into())?; // Convert inputs to map let inputs_map = outputs_to_btree_map(parsed.inputs); - // Extract signer from options - let signer = PlatformAddressSignerWasm::try_from_options(&options_value)?; - - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Use the SDK's top_up_from_addresses method let (address_infos, new_balance) = identity .top_up_from_addresses(self.inner_sdk(), inputs_map, &signer, settings) @@ -448,10 +425,15 @@ impl WasmSdk { &self, options: AddressFundsWithdrawOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let output_script: CoreScript = + CoreScriptWasm::try_from_options(&options, "outputScript")?.into(); + let signer = PlatformAddressSignerWasm::try_from_options(&options, "signer")?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize and validate options - let parsed = deserialize_withdraw_options(options_value.clone())?; + // Deserialize simple fields last (consumes options) + let parsed = deserialize_withdraw_options(options.into())?; // Convert inputs to map let inputs_map = outputs_to_btree_map(parsed.inputs); @@ -459,22 +441,12 @@ impl WasmSdk { // Convert change output if provided let change_output = parsed.change_output.map(|output| output.into_inner()); - // Extract output script from options - let output_script: CoreScript = - CoreScriptWasm::try_from_options(&options_value, "outputScript")?.into(); - - // Extract signer from options - let signer = PlatformAddressSignerWasm::try_from_options(&options_value)?; - // Convert fee strategy from input using wasm-dpp2 helper let fee_strategy = fee_strategy_from_steps_or_default(parsed.fee_strategy); // Convert pooling let pooling = parsed.pooling.into(); - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Use the SDK's withdraw_address_funds method which handles nonces, building, and broadcasting let address_infos = self .inner_sdk() @@ -508,13 +480,14 @@ impl WasmSdk { &self, options: IdentityTransferToAddressesOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_identity_transfer_options(options_value.clone())?; + // Extract complex types first (borrows &options) + let identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Extract identity from options - let identity: Identity = IdentityWasm::try_from_options(&options_value, "identity")?.into(); + // Deserialize simple fields last (consumes options) + let parsed = deserialize_identity_transfer_options(options.into())?; // Convert outputs to map (recipient addresses with amounts) let outputs_map = outputs_to_btree_map(parsed.outputs); @@ -530,12 +503,6 @@ impl WasmSdk { }) .transpose()?; - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; - - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Use the SDK's transfer_credits_to_addresses method let (address_infos, new_balance) = identity .transfer_credits_to_addresses( @@ -756,31 +723,24 @@ impl WasmSdk { use wasm_dpp2::asset_lock_proof::AssetLockProofWasm; use wasm_dpp2::PrivateKeyWasm; - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_address_funding_options(options_value.clone())?; - - // Extract asset lock proof from options + // Extract complex types first (borrows &options) let asset_lock_proof: dash_sdk::dpp::prelude::AssetLockProof = - AssetLockProofWasm::try_from_options(&options_value, "assetLockProof")?.into(); - - // Extract asset lock private key from options + AssetLockProofWasm::try_from_options(&options, "assetLockProof")?.into(); let asset_lock_private_key: dash_sdk::dpp::dashcore::PrivateKey = - PrivateKeyWasm::try_from_options(&options_value, "assetLockPrivateKey")?.into(); + PrivateKeyWasm::try_from_options(&options, "assetLockPrivateKey")?.into(); + let signer = PlatformAddressSignerWasm::try_from_options(&options, "signer")?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); + + // Deserialize simple fields last (consumes options) + let parsed = deserialize_address_funding_options(options.into())?; // Convert outputs to map (address -> optional amount) let outputs_map = outputs_to_optional_btree_map(parsed.outputs); - // Extract signer from options - let signer = PlatformAddressSignerWasm::try_from_options(&options_value)?; - // Convert fee strategy from input using wasm-dpp2 helper let fee_strategy = fee_strategy_from_steps_or_default(parsed.fee_strategy); - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Use the SDK's top_up method for addresses let address_infos = outputs_map .top_up( @@ -927,20 +887,18 @@ impl WasmSdk { options: IdentityCreateFromAddressesOptionsJs, ) -> Result { use dash_sdk::platform::transition::put_identity::PutIdentity; - use wasm_dpp2::utils::IntoWasm; - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity: Identity = + wasm_dpp2::IdentityWasm::try_from_options(&options, "identity")?.into(); + let identity_signer = IdentitySignerWasm::try_from_options(&options, "identitySigner")?; + let address_signer = + PlatformAddressSignerWasm::try_from_options(&options, "addressSigner")?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize and validate options - let parsed = deserialize_identity_create_options(options_value.clone())?; - - // Extract identity from options - let identity_js = js_sys::Reflect::get(&options_value, &JsValue::from_str("identity")) - .map_err(|_| WasmSdkError::invalid_argument("identity is required"))?; - let identity: Identity = identity_js - .to_wasm::("Identity")? - .clone() - .into(); + // Deserialize simple fields last (consumes options) + let parsed = deserialize_identity_create_options(options.into())?; // Convert inputs to map (address -> amount) let inputs_map = outputs_to_btree_map(parsed.inputs); @@ -949,17 +907,6 @@ impl WasmSdk { // Convert change output if provided let change_output = parsed.change_output.map(|output| output.into_inner()); - // Extract signers from options using helper methods - let identity_signer = - IdentitySignerWasm::try_from_options_with_field(&options_value, "identitySigner")?; - let address_signer = PlatformAddressSignerWasm::try_from_options_with_field( - &options_value, - "addressSigner", - )?; - - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Use the SDK's put_with_address_funding method let (created_identity, address_infos) = identity .put_with_address_funding( diff --git a/packages/wasm-sdk/src/state_transitions/broadcast.rs b/packages/wasm-sdk/src/state_transitions/broadcast.rs index bc5289ef736..1c01c120530 100644 --- a/packages/wasm-sdk/src/state_transitions/broadcast.rs +++ b/packages/wasm-sdk/src/state_transitions/broadcast.rs @@ -10,8 +10,22 @@ use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; use dash_sdk::dpp::state_transition::StateTransition; use dash_sdk::platform::transition::broadcast::BroadcastStateTransition; use wasm_bindgen::prelude::*; +use wasm_dpp2::serialization::conversions::to_object; use wasm_dpp2::StateTransitionWasm; +// TODO: Create proper WASM wrappers for StateTransitionProofResult variants. +// Currently returns serde-serialized JSON. Should have typed wrappers like: +// - VerifiedDataContractResult with DataContractWasm +// - VerifiedIdentityResult with IdentityWasm +// - VerifiedDocumentsResult with Map +// etc. + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "unknown")] + pub type StateTransitionProofResultJs; +} + #[wasm_bindgen] impl WasmSdk { /// Broadcasts a state transition to the network. @@ -49,13 +63,13 @@ impl WasmSdk { /// /// @param stateTransition - The state transition that was broadcast /// @param settings - Optional put settings (retries, timeout, waitTimeoutMs) - /// @returns JSON representation of the state transition result + /// @returns The verified state transition result #[wasm_bindgen(js_name = "waitForResponse")] pub async fn wait_for_response( &self, #[wasm_bindgen(js_name = "stateTransition")] state_transition: &StateTransitionWasm, settings: Option, - ) -> Result { + ) -> Result { let st: StateTransition = state_transition.into(); let put_settings = parse_put_settings(settings)?; @@ -66,9 +80,7 @@ impl WasmSdk { WasmSdkError::generic(format!("Failed to wait for state transition result: {}", e)) })?; - // Convert result to a JsValue representation - let result_str = format!("{:?}", result); - Ok(JsValue::from_str(&result_str)) + Ok(to_object(&result).map(Into::into)?) } /// Broadcasts a state transition and waits for the result. @@ -80,13 +92,13 @@ impl WasmSdk { /// /// @param stateTransition - The state transition to broadcast /// @param settings - Optional put settings (retries, timeout, waitTimeoutMs) - /// @returns JSON representation of the state transition result + /// @returns The verified state transition result #[wasm_bindgen(js_name = "broadcastAndWait")] pub async fn broadcast_and_wait( &self, #[wasm_bindgen(js_name = "stateTransition")] state_transition: &StateTransitionWasm, settings: Option, - ) -> Result { + ) -> Result { let st: StateTransition = state_transition.into(); let put_settings = parse_put_settings(settings)?; @@ -95,8 +107,6 @@ impl WasmSdk { .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast: {}", e)))?; - // Convert result to a JsValue representation - let result_str = format!("{:?}", result); - Ok(JsValue::from_str(&result_str)) + Ok(to_object(&result).map(Into::into)?) } } diff --git a/packages/wasm-sdk/src/state_transitions/contract.rs b/packages/wasm-sdk/src/state_transitions/contract.rs index 92c0f450755..23deb5aedff 100644 --- a/packages/wasm-sdk/src/state_transitions/contract.rs +++ b/packages/wasm-sdk/src/state_transitions/contract.rs @@ -4,7 +4,7 @@ use crate::error::WasmSdkError; use crate::sdk::WasmSdk; -use crate::settings::{extract_settings_from_options, get_user_fee_increase}; +use crate::settings::{get_user_fee_increase, PutSettingsInput}; use dash_sdk::dpp::data_contract::accessors::v0::DataContractV0Getters; use dash_sdk::dpp::data_contract::DataContract; use dash_sdk::dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; @@ -18,6 +18,7 @@ use std::collections::BTreeMap; use wasm_bindgen::prelude::*; use wasm_dpp2::data_contract::DataContractWasm; use wasm_dpp2::identity::IdentityPublicKeyWasm; +use wasm_dpp2::utils::try_from_options_optional; use wasm_dpp2::IdentitySignerWasm; // ============================================================================ @@ -82,23 +83,20 @@ impl WasmSdk { &self, options: ContractPublishOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - // Extract data contract from options - let data_contract_wasm = - DataContractWasm::try_from_options(&options_value, "dataContract")?; + let data_contract_wasm = DataContractWasm::try_from_options(&options, "dataContract")?; let data_contract: DataContract = data_contract_wasm.into(); // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Create and broadcast the contract // Note: The SDK will set the actual contract ID based on the identity nonce @@ -178,11 +176,8 @@ impl WasmSdk { &self, options: ContractUpdateOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract data contract from options - let data_contract_wasm = - DataContractWasm::try_from_options(&options_value, "dataContract")?; + let data_contract_wasm = DataContractWasm::try_from_options(&options, "dataContract")?; let updated_contract: DataContract = data_contract_wasm.into(); // Get identifiers from the contract @@ -190,15 +185,15 @@ impl WasmSdk { let owner_id: Identifier = updated_contract.owner_id(); // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Get identity contract nonce let identity_contract_nonce = self diff --git a/packages/wasm-sdk/src/state_transitions/document.rs b/packages/wasm-sdk/src/state_transitions/document.rs index 44197daf1f9..be6dc603a00 100644 --- a/packages/wasm-sdk/src/state_transitions/document.rs +++ b/packages/wasm-sdk/src/state_transitions/document.rs @@ -4,7 +4,7 @@ use crate::error::WasmSdkError; use crate::sdk::WasmSdk; -use crate::settings::extract_settings_from_options; +use crate::settings::PutSettingsInput; use dash_sdk::dpp::data_contract::accessors::v0::DataContractV0Getters; use dash_sdk::dpp::data_contract::document_type::DocumentType; use dash_sdk::dpp::document::{Document, DocumentV0Getters}; @@ -21,22 +21,12 @@ use wasm_bindgen::prelude::*; use wasm_dpp2::data_contract::document::DocumentWasm; use wasm_dpp2::identifier::IdentifierWasm; use wasm_dpp2::identity::IdentityPublicKeyWasm; -use wasm_dpp2::utils::{get_class_type, try_to_u64, IntoWasm}; +use wasm_dpp2::utils::{ + get_class_type, try_from_options_optional, try_from_options_with, try_to_string, try_to_u64, + IntoWasm, +}; use wasm_dpp2::IdentitySignerWasm; -/// Extracts a string field from a JS options object. -fn extract_string_from_options( - options: &JsValue, - field_name: &str, -) -> Result { - let value = js_sys::Reflect::get(options, &JsValue::from_str(field_name)) - .map_err(|_| WasmSdkError::invalid_argument(format!("{} is required", field_name)))?; - - value - .as_string() - .ok_or_else(|| WasmSdkError::invalid_argument(format!("{} must be a string", field_name))) -} - // ============================================================================ // Document Create // ============================================================================ @@ -98,18 +88,16 @@ impl WasmSdk { &self, options: DocumentCreateOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract document from options - let document_wasm = DocumentWasm::try_from_options(&options_value, "document")?; + let document_wasm = DocumentWasm::try_from_options(&options, "document")?; let document: Document = document_wasm.clone().into(); // Get metadata from document - let contract_id: Identifier = document_wasm.get_data_contract_id().into(); - let document_type_name = document_wasm.get_document_type_name(); + let contract_id: Identifier = document_wasm.data_contract_id().into(); + let document_type_name = document_wasm.document_type_name(); // Get entropy from document - let entropy = document_wasm.get_entropy().ok_or_else(|| { + let entropy = document_wasm.entropy().ok_or_else(|| { WasmSdkError::invalid_argument("Document must have entropy set for creation") })?; @@ -123,12 +111,11 @@ impl WasmSdk { entropy_array.copy_from_slice(&entropy); // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; @@ -137,7 +124,8 @@ impl WasmSdk { let document_type = get_document_type(&data_contract, &document_type_name)?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Use PutDocument trait for creation document @@ -217,23 +205,20 @@ impl WasmSdk { &self, options: DocumentReplaceOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract document from options - let document_wasm = DocumentWasm::try_from_options(&options_value, "document")?; + let document_wasm = DocumentWasm::try_from_options(&options, "document")?; let document: Document = document_wasm.clone().into(); // Get metadata from document - let contract_id: Identifier = document_wasm.get_data_contract_id().into(); - let document_type_name = document_wasm.get_document_type_name(); + let contract_id: Identifier = document_wasm.data_contract_id().into(); + let document_type_name = document_wasm.document_type_name(); // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; @@ -242,7 +227,8 @@ impl WasmSdk { let document_type = get_document_type(&data_contract, &document_type_name)?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Use PutDocument trait for replacement (revision > INITIAL_REVISION triggers replace) document @@ -331,10 +317,8 @@ impl WasmSdk { &self, options: DocumentDeleteOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract document field - can be either a Document instance or plain object - let document_js = js_sys::Reflect::get(&options_value, &JsValue::from_str("document")) + let document_js = js_sys::Reflect::get(&options, &JsValue::from_str("document")) .map_err(|_| WasmSdkError::invalid_argument("document is required"))?; if document_js.is_undefined() || document_js.is_null() { @@ -354,10 +338,10 @@ impl WasmSdk { .map(|boxed| (*boxed).clone())?; let doc_inner: Document = doc.clone().into(); ( - doc.get_id().into(), + doc.id().into(), doc_inner.owner_id(), - doc.get_data_contract_id().into(), - doc.get_document_type_name(), + doc.data_contract_id().into(), + doc.document_type_name(), ) } else { // It's a plain object - extract individual fields @@ -365,23 +349,25 @@ impl WasmSdk { IdentifierWasm::try_from_options(&document_js, "id")?.into(), IdentifierWasm::try_from_options(&document_js, "ownerId")?.into(), IdentifierWasm::try_from_options(&document_js, "dataContractId")?.into(), - extract_string_from_options(&document_js, "documentTypeName")?, + try_from_options_with(&document_js, "documentTypeName", |v| { + try_to_string(v, "documentTypeName") + })?, ) }; // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Build and execute delete transition using DocumentDeleteTransitionBuilder let builder = DocumentDeleteTransitionBuilder::new( @@ -469,20 +455,18 @@ impl WasmSdk { &self, options: DocumentTransferOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract document from options - let document_wasm = DocumentWasm::try_from_options(&options_value, "document")?; + let document_wasm = DocumentWasm::try_from_options(&options, "document")?; let document: Document = document_wasm.clone().into(); // Get metadata from document - let contract_id: Identifier = document_wasm.get_data_contract_id().into(); + let contract_id: Identifier = document_wasm.data_contract_id().into(); let owner_id: Identifier = document.owner_id(); - let document_type_name = document_wasm.get_document_type_name(); + let document_type_name = document_wasm.document_type_name(); // Extract recipient ID from options let recipient_id: Identifier = - IdentifierWasm::try_from_options(&options_value, "recipientId")?.into(); + IdentifierWasm::try_from_options(&options, "recipientId")?.into(); // Validate not transferring to self if owner_id == recipient_id { @@ -492,12 +476,11 @@ impl WasmSdk { } // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; @@ -506,7 +489,8 @@ impl WasmSdk { let document_type = get_document_type(&data_contract, &document_type_name)?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Use TransferDocument trait document @@ -551,7 +535,7 @@ export interface DocumentPurchaseOptions { * The purchase price in credits. * Must match the document's listed price. */ - price: bigint | number; + price: bigint; /** * The public key to use for signing the transition. @@ -595,34 +579,26 @@ impl WasmSdk { &self, options: DocumentPurchaseOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract document from options - let document_wasm = DocumentWasm::try_from_options(&options_value, "document")?; + let document_wasm = DocumentWasm::try_from_options(&options, "document")?; let document: Document = document_wasm.clone().into(); // Get metadata from document - let contract_id: Identifier = document_wasm.get_data_contract_id().into(); - let document_type_name = document_wasm.get_document_type_name(); + let contract_id: Identifier = document_wasm.data_contract_id().into(); + let document_type_name = document_wasm.document_type_name(); // Extract buyer ID from options - let buyer_id: Identifier = - IdentifierWasm::try_from_options(&options_value, "buyerId")?.into(); + let buyer_id: Identifier = IdentifierWasm::try_from_options(&options, "buyerId")?.into(); // Extract price from options - let price_js = js_sys::Reflect::get(&options_value, &JsValue::from_str("price")) - .map_err(|_| WasmSdkError::invalid_argument("price is required"))?; - let price: Credits = try_to_u64(price_js).map_err(|e| { - WasmSdkError::invalid_argument(format!("price must be a valid u64: {}", e)) - })?; + let price: Credits = try_from_options_with(&options, "price", |v| try_to_u64(v, "price"))?; // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; @@ -631,7 +607,8 @@ impl WasmSdk { let document_type = get_document_type(&data_contract, &document_type_name)?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Use PurchaseDocument trait document @@ -672,7 +649,7 @@ export interface DocumentSetPriceOptions { * The price in credits. * Set to 0 to remove the price and make the document not for sale. */ - price: bigint | number; + price: bigint; /** * The identity public key to use for signing the transition. @@ -716,30 +693,23 @@ impl WasmSdk { &self, options: DocumentSetPriceOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract document from options - let document_wasm = DocumentWasm::try_from_options(&options_value, "document")?; + let document_wasm = DocumentWasm::try_from_options(&options, "document")?; let document: Document = document_wasm.clone().into(); // Get metadata from document - let contract_id: Identifier = document_wasm.get_data_contract_id().into(); - let document_type_name = document_wasm.get_document_type_name(); + let contract_id: Identifier = document_wasm.data_contract_id().into(); + let document_type_name = document_wasm.document_type_name(); // Extract price from options - let price_js = js_sys::Reflect::get(&options_value, &JsValue::from_str("price")) - .map_err(|_| WasmSdkError::invalid_argument("price is required"))?; - let price: Credits = try_to_u64(price_js).map_err(|e| { - WasmSdkError::invalid_argument(format!("price must be a valid u64: {}", e)) - })?; + let price: Credits = try_from_options_with(&options, "price", |v| try_to_u64(v, "price"))?; // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Fetch the data contract (using cache) let data_contract = self.get_or_fetch_contract(contract_id).await?; @@ -748,7 +718,8 @@ impl WasmSdk { let document_type = get_document_type(&data_contract, &document_type_name)?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Use UpdatePriceOfDocument trait document diff --git a/packages/wasm-sdk/src/state_transitions/identity.rs b/packages/wasm-sdk/src/state_transitions/identity.rs index 792ede2548d..9d1bdb1b8a9 100644 --- a/packages/wasm-sdk/src/state_transitions/identity.rs +++ b/packages/wasm-sdk/src/state_transitions/identity.rs @@ -6,7 +6,7 @@ use crate::error::WasmSdkError; use crate::queries::utils::deserialize_required_query; use crate::sdk::WasmSdk; -use crate::settings::extract_settings_from_options; +use crate::settings::PutSettingsInput; use dash_sdk::dpp::identity::accessors::IdentityGettersV0; use dash_sdk::dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dash_sdk::dpp::identity::signer::Signer; @@ -21,7 +21,10 @@ use wasm_bindgen::prelude::*; use wasm_dpp2::asset_lock_proof::AssetLockProofWasm; use wasm_dpp2::identifier::IdentifierWasm; use wasm_dpp2::identity::IdentityPublicKeyWasm; -use wasm_dpp2::utils::IntoWasm; +use wasm_dpp2::utils::{ + try_from_options_optional, try_from_options_optional_with, try_from_options_with, try_to_array, + try_to_u64, IntoWasm, +}; use wasm_dpp2::PrivateKeyWasm; use wasm_dpp2::{IdentityPublicKeyInCreationWasm, IdentitySignerWasm, IdentityWasm}; @@ -91,24 +94,23 @@ impl WasmSdk { &self, options: IdentityCreateOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); - // Extract identity from options - let identity: Identity = IdentityWasm::try_from_options(&options_value, "identity")?.into(); + let identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); // Extract asset lock proof from options let asset_lock_proof: dash_sdk::dpp::prelude::AssetLockProof = - AssetLockProofWasm::try_from_options(&options_value, "assetLockProof")?.into(); + AssetLockProofWasm::try_from_options(&options, "assetLockProof")?.into(); // Extract asset lock private key from options let asset_lock_private_key: dash_sdk::dpp::dashcore::PrivateKey = - PrivateKeyWasm::try_from_options(&options_value, "assetLockPrivateKey")?.into(); + PrivateKeyWasm::try_from_options(&options, "assetLockPrivateKey")?.into(); // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Put identity to platform and wait identity @@ -184,21 +186,20 @@ impl WasmSdk { &self, options: IdentityTopUpOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - // Extract identity from options - let identity: Identity = IdentityWasm::try_from_options(&options_value, "identity")?.into(); + let identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); // Extract asset lock proof from options let asset_lock_proof: dash_sdk::dpp::prelude::AssetLockProof = - AssetLockProofWasm::try_from_options(&options_value, "assetLockProof")?.into(); + AssetLockProofWasm::try_from_options(&options, "assetLockProof")?.into(); // Extract asset lock private key from options let asset_lock_private_key: dash_sdk::dpp::dashcore::PrivateKey = - PrivateKeyWasm::try_from_options(&options_value, "assetLockPrivateKey")?.into(); + PrivateKeyWasm::try_from_options(&options, "assetLockPrivateKey")?.into(); // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Top up the identity let new_balance = identity @@ -240,7 +241,7 @@ export interface IdentityCreditTransferOptions { /** * The amount of credits to transfer. */ - amount: bigint | number; + amount: bigint; /** * Signer containing the private key for the sender's transfer key. @@ -308,31 +309,27 @@ impl WasmSdk { ) -> Result { use dash_sdk::platform::transition::transfer::TransferToIdentity; - let options_value: JsValue = options.into(); - // Extract identity from options - let identity: Identity = IdentityWasm::try_from_options(&options_value, "identity")?.into(); + let identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); // Extract recipient ID from options let recipient_id: Identifier = - IdentifierWasm::try_from_options(&options_value, "recipientId")?.into(); + IdentifierWasm::try_from_options(&options, "recipientId")?.into(); // Extract amount from options - let amount_js = js_sys::Reflect::get(&options_value, &JsValue::from_str("amount")) - .map_err(|_| WasmSdkError::invalid_argument("amount is required"))?; - let amount = wasm_dpp2::utils::try_to_u64(amount_js) - .map_err(|e| WasmSdkError::invalid_argument(format!("Invalid amount: {}", e)))?; + let amount: u64 = try_from_options_with(&options, "amount", |v| try_to_u64(v, "amount"))?; // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; // Extract optional signing key from options let signing_key: Option = - IdentityPublicKeyWasm::try_from_optional_options(&options_value, "signingKey")? + IdentityPublicKeyWasm::try_from_optional_options(&options, "signingKey")? .map(|k| k.into()); // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); // Transfer credits using rs-sdk method let (sender_balance, recipient_balance) = identity @@ -372,7 +369,7 @@ export interface IdentityCreditWithdrawalOptions { /** * The amount of credits to withdraw. */ - amount: bigint | number; + amount: bigint; /** * Optional Dash address to send the withdrawn credits to. @@ -454,10 +451,17 @@ impl WasmSdk { use dash_sdk::platform::transition::withdraw_from_identity::WithdrawFromIdentity; use std::str::FromStr; - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let signing_key: Option = + IdentityPublicKeyWasm::try_from_optional_options(&options, "signingKey")? + .map(|k| k.into()); + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize simple fields using serde - let parsed = deserialize_withdrawal_options(options_value.clone())?; + // Deserialize simple fields last (consumes options) + let parsed = deserialize_withdrawal_options(options.into())?; // Validate amount if parsed.amount == 0 { @@ -466,9 +470,6 @@ impl WasmSdk { )); } - // Extract identity from options (WASM type) - let identity: Identity = IdentityWasm::try_from_options(&options_value, "identity")?.into(); - // Parse address if provided let address = parsed .to_address @@ -481,17 +482,6 @@ impl WasmSdk { }) .transpose()?; - // Extract signer from options (WASM type) - let signer = IdentitySignerWasm::try_from_options(&options_value)?; - - // Extract optional signing key from options (WASM type) - let signing_key: Option = - IdentityPublicKeyWasm::try_from_optional_options(&options_value, "signingKey")? - .map(|k| k.into()); - - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Perform the withdrawal let remaining_balance = identity .withdraw( @@ -593,14 +583,44 @@ impl WasmSdk { &self, options: IdentityUpdateOptionsJs, ) -> Result<(), WasmSdkError> { - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let mut identity: Identity = IdentityWasm::try_from_options(&options, "identity")?.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let keys_to_add: Vec = if let Some(keys_array) = + try_from_options_optional_with(&options, "addPublicKeys", |v| { + try_to_array(v, "addPublicKeys") + })? { + let max_existing_key_id = identity.public_keys().keys().max().copied().unwrap_or(0); + let mut next_key_id = max_existing_key_id.checked_add(1).ok_or_else(|| { + WasmSdkError::invalid_argument("Key ID overflow: identity has too many keys") + })?; + + keys_array + .iter() + .map(|key_js| { + let mut key_in_creation = key_js + .to_wasm::("IdentityPublicKeyInCreation")? + .clone(); + + // Set the key ID to the next available ID + key_in_creation.set_key_id(next_key_id.into())?; - // Deserialize and validate options - let parsed = deserialize_identity_update_options(options_value.clone())?; + // Convert to IdentityPublicKey using From impl + let public_key: IdentityPublicKey = key_in_creation.into(); + next_key_id = next_key_id.checked_add(1).ok_or_else(|| { + WasmSdkError::invalid_argument("Key ID overflow: too many keys to add") + })?; + Ok(public_key) + }) + .collect::, WasmSdkError>>()? + } else { + Vec::new() + }; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Extract identity from options (WASM type) - let mut identity: Identity = - IdentityWasm::try_from_options(&options_value, "identity")?.into(); + // Deserialize simple fields last (consumes options) + let parsed = deserialize_identity_update_options(options.into())?; // Increment the identity revision for the update transition // The platform expects the new revision (current + 1) in the state transition @@ -608,9 +628,6 @@ impl WasmSdk { let original_revision = identity.revision(); identity.set_revision(original_revision + 1); - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; - // Find all valid master keys (AUTHENTICATION + MASTER + supported key type) let master_keys: Vec<_> = identity .public_keys() @@ -641,48 +658,9 @@ impl WasmSdk { ) })?; - // Parse keys to add from options - let add_public_keys_js = - js_sys::Reflect::get(&options_value, &JsValue::from_str("addPublicKeys")) - .unwrap_or(JsValue::UNDEFINED); - - let keys_to_add: Vec = if !add_public_keys_js.is_undefined() - && !add_public_keys_js.is_null() - { - let keys_array = js_sys::Array::from(&add_public_keys_js); - let max_existing_key_id = identity.public_keys().keys().max().copied().unwrap_or(0); - let mut next_key_id = max_existing_key_id.checked_add(1).ok_or_else(|| { - WasmSdkError::invalid_argument("Key ID overflow: identity has too many keys") - })?; - - keys_array - .iter() - .map(|key_js| { - let mut key_in_creation = key_js - .to_wasm::("IdentityPublicKeyInCreation")? - .clone(); - - // Set the key ID to the next available ID - key_in_creation.set_key_id(next_key_id); - - // Convert to IdentityPublicKey using From impl - let public_key: IdentityPublicKey = key_in_creation.into(); - next_key_id = next_key_id.checked_add(1).ok_or_else(|| { - WasmSdkError::invalid_argument("Key ID overflow: too many keys to add") - })?; - Ok(public_key) - }) - .collect::, WasmSdkError>>()? - } else { - Vec::new() - }; - // Get keys to disable let keys_to_disable = parsed.disable_public_keys.unwrap_or_default(); - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Get identity nonce let identity_nonce = self .inner_sdk() @@ -809,28 +787,22 @@ impl WasmSdk { use wasm_dpp2::voting::resource_vote_choice::ResourceVoteChoiceWasm; use wasm_dpp2::voting::vote_poll::VotePollWasm; - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_masternode_vote_options(options_value.clone())?; - - // Convert ProTxHash - let pro_tx_hash: Identifier = parsed.masternode_pro_tx_hash.into(); - - // Extract vote poll from options + // Extract complex types first (borrows &options) let vote_poll: dash_sdk::dpp::voting::vote_polls::VotePoll = - VotePollWasm::try_from_options(&options_value, "votePoll")?.into(); - - // Extract vote choice from options + VotePollWasm::try_from_options(&options, "votePoll")?.into(); let resource_vote_choice: dash_sdk::dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice = - ResourceVoteChoiceWasm::try_from_options(&options_value, "voteChoice")?.into(); - - // Extract voting key from options + ResourceVoteChoiceWasm::try_from_options(&options, "voteChoice")?.into(); let voting_public_key: IdentityPublicKey = - IdentityPublicKeyWasm::try_from_options(&options_value, "votingKey")?.into(); + IdentityPublicKeyWasm::try_from_options(&options, "votingKey")?.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + // Deserialize simple fields last (consumes options) + let parsed = deserialize_masternode_vote_options(options.into())?; + + // Convert ProTxHash + let pro_tx_hash: Identifier = parsed.masternode_pro_tx_hash.into(); // Create the resource vote use dash_sdk::dpp::voting::votes::resource_vote::v0::ResourceVoteV0; @@ -844,9 +816,6 @@ impl WasmSdk { use dash_sdk::dpp::voting::votes::Vote; let vote = Vote::ResourceVote(resource_vote); - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Submit the vote using PutVote trait use dash_sdk::platform::transition::vote::PutVote; diff --git a/packages/wasm-sdk/src/state_transitions/token.rs b/packages/wasm-sdk/src/state_transitions/token.rs index 1c33734838a..a33eae8cffd 100644 --- a/packages/wasm-sdk/src/state_transitions/token.rs +++ b/packages/wasm-sdk/src/state_transitions/token.rs @@ -3,9 +3,10 @@ //! This module provides WASM bindings for token operations like mint, burn, transfer, etc. use crate::error::WasmSdkError; +use crate::impl_wasm_serde_conversions; use crate::queries::utils::deserialize_required_query; use crate::sdk::WasmSdk; -use crate::settings::{extract_settings_from_options, get_user_fee_increase}; +use crate::settings::{get_user_fee_increase, PutSettingsInput}; use dash_sdk::dpp::balances::credits::TokenAmount; use dash_sdk::dpp::document::Document; use dash_sdk::dpp::identity::IdentityPublicKey; @@ -22,8 +23,9 @@ use dash_sdk::platform::tokens::transitions::{ BurnResult, ClaimResult, DestroyFrozenFundsResult, DirectPurchaseResult, EmergencyActionResult, FreezeResult, MintResult, SetPriceResult, TransferResult, UnfreezeResult, }; +use dash_sdk::platform::transition::put_settings::PutSettings; use js_sys::BigInt; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::sync::Arc; use wasm_bindgen::prelude::*; use wasm_dpp2::data_contract::document::DocumentWasm; @@ -31,6 +33,7 @@ use wasm_dpp2::identifier::IdentifierWasm; use wasm_dpp2::identity::IdentityPublicKeyWasm; use wasm_dpp2::state_transitions::base::GroupStateTransitionInfoStatusWasm; use wasm_dpp2::state_transitions::batch::token_pricing_schedule::TokenPricingScheduleWasm; +use wasm_dpp2::utils::{try_from_options, try_from_options_optional}; use wasm_dpp2::IdentitySignerWasm; /// Helper function to convert a Document to DocumentWasm with the required metadata. @@ -67,7 +70,7 @@ export interface TokenMintOptions { /** * The amount of tokens to mint. */ - amount: bigint | number; + amount: bigint; /** * The identity ID of the minter. @@ -118,16 +121,12 @@ extern "C" { pub type TokenMintOptionsJs; } -/// Main input struct for token mint options. +/// Main input struct for token mint options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenMintOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, amount: u64, - identity_id: IdentifierWasm, - #[serde(default)] - recipient_id: Option, #[serde(default)] public_note: Option, } @@ -145,78 +144,63 @@ fn deserialize_token_mint_options(options: JsValue) -> Result, + #[wasm_bindgen(getter_with_clone, js_name = "recipientId")] + pub recipient_id: Option, /// For TokenBalance or GroupActionWithBalance - the new balance new_balance: Option, /// For group actions - accumulated group power - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// For GroupActionWithBalance - action status - group_action_status: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupActionStatus")] + pub group_action_status: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } #[wasm_bindgen(js_class = TokenMintResult)] impl TokenMintResultWasm { - /// The recipient's identity ID (for balance results). - #[wasm_bindgen(getter = "recipientId")] - pub fn recipient_id(&self) -> Option { - self.recipient_id - } - /// The new token balance after minting. #[wasm_bindgen(getter = "newBalance")] pub fn new_balance(&self) -> Option { self.new_balance.map(BigInt::from) } - - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The group action status (for group actions). - #[wasm_bindgen(getter = "groupActionStatus")] - pub fn group_action_status(&self) -> Option { - self.group_action_status.clone() - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } } +impl_wasm_serde_conversions!(TokenMintResultWasm, TokenMintResult); + impl TokenMintResultWasm { /// Convert from SDK MintResult with the required contract context - fn from_result(result: MintResult, contract_id: Identifier) -> Self { + pub(crate) fn from_result(result: MintResult, contract_id: Identifier) -> Self { match result { - MintResult::TokenBalance(recipient_id, balance) => TokenMintResultWasm { + MintResult::TokenBalance(recipient_id, balance) => Self { recipient_id: Some(recipient_id.into()), new_balance: Some(balance), group_power: None, group_action_status: None, document: None, }, - MintResult::HistoricalDocument(doc) => TokenMintResultWasm { + MintResult::HistoricalDocument(doc) => Self { recipient_id: None, new_balance: None, group_power: None, group_action_status: None, document: Some(document_to_wasm(doc, contract_id, "mint")), }, - MintResult::GroupActionWithDocument(power, doc) => TokenMintResultWasm { + MintResult::GroupActionWithDocument(power, doc) => Self { recipient_id: None, new_balance: None, group_power: Some(power), group_action_status: None, document: doc.map(|d| document_to_wasm(d, contract_id, "mint")), }, - MintResult::GroupActionWithBalance(power, status, balance) => TokenMintResultWasm { + MintResult::GroupActionWithBalance(power, status, balance) => Self { recipient_id: None, new_balance: balance, group_power: Some(power), @@ -238,30 +222,31 @@ impl WasmSdk { &self, options: TokenMintOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_token_mint_options(options_value.clone())?; - - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let identity_id: Identifier = parsed.identity_id.into(); - let amount = parsed.amount as TokenAmount; - - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); + let group_info = + GroupStateTransitionInfoStatusWasm::try_from_optional_options(&options, "groupInfo")?; + + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let identity_id: Identifier = + try_from_options::(&options, "identityId")?.into(); + let recipient_id: Option = + try_from_options_optional::(&options, "recipientId")?.map(Into::into); + + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_mint_options(options.into())?; - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let amount = parsed.amount as TokenAmount; // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the mint transition using rs-sdk builder let mut builder = TokenMintTransitionBuilder::new( Arc::new(data_contract), @@ -271,8 +256,8 @@ impl WasmSdk { ); // Add optional recipient - if let Some(recipient_id) = parsed.recipient_id { - builder = builder.issued_to_identity_id(recipient_id.into()); + if let Some(recipient_id) = recipient_id { + builder = builder.issued_to_identity_id(recipient_id); } // Add optional public note @@ -281,21 +266,15 @@ impl WasmSdk { } // Add optional group info - if let Some(group_info) = GroupStateTransitionInfoStatusWasm::try_from_optional_options( - &options_value, - "groupInfo", - )? { + if let Some(group_info) = group_info { builder = builder.with_using_group_info(group_info.into()); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -335,7 +314,7 @@ export interface TokenBurnOptions { /** * The amount of tokens to burn. */ - amount: bigint | number; + amount: bigint; /** * The identity ID of the token holder burning tokens. @@ -379,14 +358,12 @@ extern "C" { pub type TokenBurnOptionsJs; } -/// Main input struct for token burn options. +/// Main input struct for token burn options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenBurnOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, amount: u64, - identity_id: IdentifierWasm, #[serde(default)] public_note: Option, } @@ -404,76 +381,61 @@ fn deserialize_token_burn_options(options: JsValue) -> Result, + #[wasm_bindgen(getter_with_clone, js_name = "ownerId")] + pub owner_id: Option, remaining_balance: Option, /// For group actions - group_power: Option, - group_action_status: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupActionStatus")] + pub group_action_status: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } #[wasm_bindgen(js_class = TokenBurnResult)] impl TokenBurnResultWasm { - /// The owner's identity ID (for balance results). - #[wasm_bindgen(getter = "ownerId")] - pub fn owner_id(&self) -> Option { - self.owner_id - } - /// The remaining token balance after burning. #[wasm_bindgen(getter = "remainingBalance")] pub fn remaining_balance(&self) -> Option { self.remaining_balance.map(BigInt::from) } - - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The group action status (for group actions). - #[wasm_bindgen(getter = "groupActionStatus")] - pub fn group_action_status(&self) -> Option { - self.group_action_status.clone() - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } } +impl_wasm_serde_conversions!(TokenBurnResultWasm, TokenBurnResult); + impl TokenBurnResultWasm { /// Convert from SDK BurnResult with the required contract context - fn from_result(result: BurnResult, contract_id: Identifier) -> Self { + pub(crate) fn from_result(result: BurnResult, contract_id: Identifier) -> Self { match result { - BurnResult::TokenBalance(owner_id, balance) => TokenBurnResultWasm { + BurnResult::TokenBalance(owner_id, balance) => Self { owner_id: Some(owner_id.into()), remaining_balance: Some(balance), group_power: None, group_action_status: None, document: None, }, - BurnResult::HistoricalDocument(doc) => TokenBurnResultWasm { + BurnResult::HistoricalDocument(doc) => Self { owner_id: None, remaining_balance: None, group_power: None, group_action_status: None, document: Some(document_to_wasm(doc, contract_id, "burn")), }, - BurnResult::GroupActionWithDocument(power, doc) => TokenBurnResultWasm { + BurnResult::GroupActionWithDocument(power, doc) => Self { owner_id: None, remaining_balance: None, group_power: Some(power), group_action_status: None, document: doc.map(|d| document_to_wasm(d, contract_id, "burn")), }, - BurnResult::GroupActionWithBalance(power, status, balance) => TokenBurnResultWasm { + BurnResult::GroupActionWithBalance(power, status, balance) => Self { owner_id: None, remaining_balance: balance, group_power: Some(power), @@ -495,30 +457,29 @@ impl WasmSdk { &self, options: TokenBurnOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; + let identity_key: IdentityPublicKey = identity_key_wasm.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); + let group_info = + GroupStateTransitionInfoStatusWasm::try_from_optional_options(&options, "groupInfo")?; - // Deserialize and validate options - let parsed = deserialize_token_burn_options(options_value.clone())?; + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let identity_id: Identifier = + try_from_options::(&options, "identityId")?.into(); - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let identity_id: Identifier = parsed.identity_id.into(); - let amount = parsed.amount as TokenAmount; + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_burn_options(options.into())?; - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; - let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let amount = parsed.amount as TokenAmount; // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the burn transition using rs-sdk builder let mut builder = TokenBurnTransitionBuilder::new( Arc::new(data_contract), @@ -533,21 +494,15 @@ impl WasmSdk { } // Add optional group info - if let Some(group_info) = GroupStateTransitionInfoStatusWasm::try_from_optional_options( - &options_value, - "groupInfo", - )? { + if let Some(group_info) = group_info { builder = builder.with_using_group_info(group_info.into()); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -587,7 +542,7 @@ export interface TokenTransferOptions { /** * The amount of tokens to transfer. */ - amount: bigint | number; + amount: bigint; /** * The sender's identity ID. @@ -629,15 +584,12 @@ extern "C" { pub type TokenTransferOptionsJs; } -/// Main input struct for token transfer options. +/// Main input struct for token transfer options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenTransferOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, amount: u64, - sender_id: IdentifierWasm, - recipient_id: IdentifierWasm, #[serde(default)] public_note: Option, } @@ -661,15 +613,20 @@ fn deserialize_token_transfer_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenTransferResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenTransferResultWasm { /// For IdentitiesBalances result - sender's new balance sender_balance: Option, /// For IdentitiesBalances result - recipient's new balance recipient_balance: Option, /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } #[wasm_bindgen(js_class = TokenTransferResult)] @@ -685,23 +642,13 @@ impl TokenTransferResultWasm { pub fn recipient_balance(&self) -> Option { self.recipient_balance.map(BigInt::from) } - - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } } +impl_wasm_serde_conversions!(TokenTransferResultWasm, TokenTransferResult); + impl TokenTransferResultWasm { /// Convert from SDK TransferResult with the required contract context - fn from_result( + pub(crate) fn from_result( result: TransferResult, contract_id: Identifier, sender_id: Identifier, @@ -711,20 +658,20 @@ impl TokenTransferResultWasm { TransferResult::IdentitiesBalances(balances) => { // Look up balances by their specific identity IDs // (BTreeMap iteration order is by key, not insertion order) - TokenTransferResultWasm { + Self { sender_balance: balances.get(&sender_id).copied(), recipient_balance: balances.get(&recipient_id).copied(), group_power: None, document: None, } } - TransferResult::HistoricalDocument(doc) => TokenTransferResultWasm { + TransferResult::HistoricalDocument(doc) => Self { sender_balance: None, recipient_balance: None, group_power: None, document: Some(document_to_wasm(doc, contract_id, "transfer")), }, - TransferResult::GroupActionWithDocument(power, doc) => TokenTransferResultWasm { + TransferResult::GroupActionWithDocument(power, doc) => Self { sender_balance: None, recipient_balance: None, group_power: Some(power), @@ -745,15 +692,24 @@ impl WasmSdk { &self, options: TokenTransferOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; + let identity_key: IdentityPublicKey = identity_key_wasm.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize and validate options - let parsed = deserialize_token_transfer_options(options_value.clone())?; + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let sender_id: Identifier = + try_from_options::(&options, "senderId")?.into(); + let recipient_id: Identifier = + try_from_options::(&options, "recipientId")?.into(); + + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_transfer_options(options.into())?; - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let sender_id: Identifier = parsed.sender_id.into(); - let recipient_id: Identifier = parsed.recipient_id.into(); let amount = parsed.amount as TokenAmount; // Validate not transferring to self @@ -763,20 +719,9 @@ impl WasmSdk { )); } - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; - let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; - // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the transfer transition using rs-sdk builder let mut builder = TokenTransferTransitionBuilder::new( Arc::new(data_contract), @@ -791,14 +736,11 @@ impl WasmSdk { builder = builder.with_public_note(note); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -887,14 +829,11 @@ extern "C" { pub type TokenFreezeOptionsJs; } -/// Main input struct for token freeze options. +/// Main input struct for token freeze options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenFreezeOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, - authority_id: IdentifierWasm, - frozen_identity_id: IdentifierWasm, #[serde(default)] public_note: Option, } @@ -918,56 +857,43 @@ fn deserialize_token_freeze_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenFreezeResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenFreezeResultWasm { /// For IdentityInfo result - frozen_identity_id: Option, + #[wasm_bindgen(getter_with_clone, js_name = "frozenIdentityId")] + pub frozen_identity_id: Option, /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } -#[wasm_bindgen(js_class = TokenFreezeResult)] -impl TokenFreezeResultWasm { - /// The identity ID that was frozen. - #[wasm_bindgen(getter = "frozenIdentityId")] - pub fn frozen_identity_id(&self) -> Option { - self.frozen_identity_id - } - - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } -} +impl_wasm_serde_conversions!(TokenFreezeResultWasm, TokenFreezeResult); impl TokenFreezeResultWasm { /// Convert from SDK FreezeResult with the required contract context - fn from_result(result: FreezeResult, contract_id: Identifier) -> Self { + pub(crate) fn from_result(result: FreezeResult, contract_id: Identifier) -> Self { match result { - FreezeResult::IdentityInfo(frozen_id, _info) => TokenFreezeResultWasm { + FreezeResult::IdentityInfo(frozen_id, _info) => Self { frozen_identity_id: Some(frozen_id.into()), group_power: None, document: None, }, - FreezeResult::HistoricalDocument(doc) => TokenFreezeResultWasm { + FreezeResult::HistoricalDocument(doc) => Self { frozen_identity_id: None, group_power: None, document: Some(document_to_wasm(doc, contract_id, "freeze")), }, - FreezeResult::GroupActionWithDocument(power, doc) => TokenFreezeResultWasm { + FreezeResult::GroupActionWithDocument(power, doc) => Self { frozen_identity_id: None, group_power: Some(power), document: doc.map(|d| document_to_wasm(d, contract_id, "freeze")), }, - FreezeResult::GroupActionWithIdentityInfo(power, _info) => TokenFreezeResultWasm { + FreezeResult::GroupActionWithIdentityInfo(power, _info) => Self { frozen_identity_id: None, group_power: Some(power), document: None, @@ -987,30 +913,29 @@ impl WasmSdk { &self, options: TokenFreezeOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_token_freeze_options(options_value.clone())?; - - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let authority_id: Identifier = parsed.authority_id.into(); - let frozen_identity_id: Identifier = parsed.frozen_identity_id.into(); - - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); + let group_info = + GroupStateTransitionInfoStatusWasm::try_from_optional_options(&options, "groupInfo")?; + + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let authority_id: Identifier = + try_from_options::(&options, "authorityId")?.into(); + let frozen_identity_id: Identifier = + try_from_options::(&options, "frozenIdentityId")?.into(); + + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_freeze_options(options.into())?; // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the freeze transition using rs-sdk builder let mut builder = TokenFreezeTransitionBuilder::new( Arc::new(data_contract), @@ -1025,21 +950,15 @@ impl WasmSdk { } // Add optional group info - if let Some(group_info) = GroupStateTransitionInfoStatusWasm::try_from_optional_options( - &options_value, - "groupInfo", - )? { + if let Some(group_info) = group_info { builder = builder.with_using_group_info(group_info.into()); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -1123,14 +1042,11 @@ extern "C" { pub type TokenUnfreezeOptionsJs; } -/// Main input struct for token unfreeze options. +/// Main input struct for token unfreeze options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenUnfreezeOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, - authority_id: IdentifierWasm, - frozen_identity_id: IdentifierWasm, #[serde(default)] public_note: Option, } @@ -1154,35 +1070,22 @@ fn deserialize_token_unfreeze_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenUnfreezeResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenUnfreezeResultWasm { /// For IdentityInfo result - unfrozen_identity_id: Option, + #[wasm_bindgen(getter_with_clone, js_name = "unfrozenIdentityId")] + pub unfrozen_identity_id: Option, /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } -#[wasm_bindgen(js_class = TokenUnfreezeResult)] -impl TokenUnfreezeResultWasm { - /// The identity ID that was unfrozen. - #[wasm_bindgen(getter = "unfrozenIdentityId")] - pub fn unfrozen_identity_id(&self) -> Option { - self.unfrozen_identity_id - } - - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } -} +impl_wasm_serde_conversions!(TokenUnfreezeResultWasm, TokenUnfreezeResult); impl TokenUnfreezeResultWasm { /// Convert from SDK UnfreezeResult with the required contract context @@ -1223,30 +1126,29 @@ impl WasmSdk { &self, options: TokenUnfreezeOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_token_unfreeze_options(options_value.clone())?; - - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let authority_id: Identifier = parsed.authority_id.into(); - let frozen_identity_id: Identifier = parsed.frozen_identity_id.into(); - - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); + let group_info = + GroupStateTransitionInfoStatusWasm::try_from_optional_options(&options, "groupInfo")?; + + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let authority_id: Identifier = + try_from_options::(&options, "authorityId")?.into(); + let frozen_identity_id: Identifier = + try_from_options::(&options, "frozenIdentityId")?.into(); + + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_unfreeze_options(options.into())?; // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the unfreeze transition using rs-sdk builder let mut builder = TokenUnfreezeTransitionBuilder::new( Arc::new(data_contract), @@ -1261,21 +1163,15 @@ impl WasmSdk { } // Add optional group info - if let Some(group_info) = GroupStateTransitionInfoStatusWasm::try_from_optional_options( - &options_value, - "groupInfo", - )? { + if let Some(group_info) = group_info { builder = builder.with_using_group_info(group_info.into()); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -1359,14 +1255,11 @@ extern "C" { pub type TokenDestroyFrozenOptionsJs; } -/// Main input struct for token destroy frozen options. +/// Main input struct for token destroy frozen options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenDestroyFrozenOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, - authority_id: IdentifierWasm, - frozen_identity_id: IdentifierWasm, #[serde(default)] public_note: Option, } @@ -1389,27 +1282,19 @@ fn deserialize_token_destroy_frozen_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenDestroyFrozenResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenDestroyFrozenResultWasm { /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } -#[wasm_bindgen(js_class = TokenDestroyFrozenResult)] -impl TokenDestroyFrozenResultWasm { - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } -} +impl_wasm_serde_conversions!(TokenDestroyFrozenResultWasm, TokenDestroyFrozenResult); impl TokenDestroyFrozenResultWasm { /// Convert from SDK DestroyFrozenFundsResult with the required contract context @@ -1440,30 +1325,29 @@ impl WasmSdk { &self, options: TokenDestroyFrozenOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_token_destroy_frozen_options(options_value.clone())?; - - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let authority_id: Identifier = parsed.authority_id.into(); - let frozen_identity_id: Identifier = parsed.frozen_identity_id.into(); - - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); + let group_info = + GroupStateTransitionInfoStatusWasm::try_from_optional_options(&options, "groupInfo")?; + + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let authority_id: Identifier = + try_from_options::(&options, "authorityId")?.into(); + let frozen_identity_id: Identifier = + try_from_options::(&options, "frozenIdentityId")?.into(); + + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_destroy_frozen_options(options.into())?; // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the destroy frozen transition using rs-sdk builder let mut builder = TokenDestroyFrozenFundsTransitionBuilder::new( Arc::new(data_contract), @@ -1478,21 +1362,15 @@ impl WasmSdk { } // Add optional group info - if let Some(group_info) = GroupStateTransitionInfoStatusWasm::try_from_optional_options( - &options_value, - "groupInfo", - )? { + if let Some(group_info) = group_info { builder = builder.with_using_group_info(group_info.into()); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -1581,13 +1459,11 @@ extern "C" { pub type TokenEmergencyActionOptionsJs; } -/// Main input struct for token emergency action options. +/// Main input struct for token emergency action options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenEmergencyActionOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, - authority_id: IdentifierWasm, action: String, #[serde(default)] public_note: Option, @@ -1611,27 +1487,19 @@ fn deserialize_token_emergency_action_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenEmergencyActionResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenEmergencyActionResultWasm { /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// The document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } -#[wasm_bindgen(js_class = TokenEmergencyActionResult)] -impl TokenEmergencyActionResultWasm { - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The document. - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } -} +impl_wasm_serde_conversions!(TokenEmergencyActionResultWasm, TokenEmergencyActionResult); impl TokenEmergencyActionResultWasm { /// Convert from SDK EmergencyActionResult with the required contract context @@ -1662,29 +1530,27 @@ impl WasmSdk { &self, options: TokenEmergencyActionOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); - - // Deserialize and validate options - let parsed = deserialize_token_emergency_action_options(options_value.clone())?; - - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let authority_id: Identifier = parsed.authority_id.into(); - - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; let identity_key: IdentityPublicKey = identity_key_wasm.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); + let group_info = + GroupStateTransitionInfoStatusWasm::try_from_optional_options(&options, "groupInfo")?; + + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let authority_id: Identifier = + try_from_options::(&options, "authorityId")?.into(); - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_emergency_action_options(options.into())?; // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the emergency action transition using rs-sdk builder // Use the appropriate constructor based on the action let mut builder = match parsed.action.to_lowercase().as_str() { @@ -1711,21 +1577,15 @@ impl WasmSdk { } // Add optional group info - if let Some(group_info) = GroupStateTransitionInfoStatusWasm::try_from_optional_options( - &options_value, - "groupInfo", - )? { + if let Some(group_info) = group_info { builder = builder.with_using_group_info(group_info.into()); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -1807,13 +1667,11 @@ extern "C" { pub type TokenClaimOptionsJs; } -/// Main input struct for token claim options. +/// Main input struct for token claim options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenClaimOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, - identity_id: IdentifierWasm, distribution_type: String, #[serde(default)] public_note: Option, @@ -1833,27 +1691,19 @@ fn deserialize_token_claim_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenClaimResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenClaimResultWasm { /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// The document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } -#[wasm_bindgen(js_class = TokenClaimResult)] -impl TokenClaimResultWasm { - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The document. - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } -} +impl_wasm_serde_conversions!(TokenClaimResultWasm, TokenClaimResult); impl TokenClaimResultWasm { /// Convert from SDK ClaimResult with the required contract context @@ -1884,14 +1734,21 @@ impl WasmSdk { ) -> Result { use dash_sdk::dpp::data_contract::associated_token::token_distribution_key::TokenDistributionType; - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; + let identity_key: IdentityPublicKey = identity_key_wasm.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize and validate options - let parsed = deserialize_token_claim_options(options_value.clone())?; + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let identity_id: Identifier = + try_from_options::(&options, "identityId")?.into(); - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let identity_id: Identifier = parsed.identity_id.into(); + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_claim_options(options.into())?; // Parse the distribution type let distribution_type = match parsed.distribution_type.to_lowercase().as_str() { @@ -1904,20 +1761,9 @@ impl WasmSdk { } }; - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; - let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; - // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the claim transition using rs-sdk builder let mut builder = TokenClaimTransitionBuilder::new( Arc::new(data_contract), @@ -1931,14 +1777,11 @@ impl WasmSdk { builder = builder.with_public_note(note); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -1984,7 +1827,7 @@ export interface TokenSetPriceOptions { * The price in credits for one token. * Set to null to disable direct purchases. */ - price: bigint | number | null; + price: bigint | null; /** * Optional public note for the price change. @@ -2023,13 +1866,11 @@ extern "C" { pub type TokenSetPriceOptionsJs; } -/// Main input struct for token set price options. +/// Main input struct for token set price options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenSetPriceOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, - authority_id: IdentifierWasm, #[serde(default)] price: Option, #[serde(default)] @@ -2055,51 +1896,29 @@ fn deserialize_token_set_price_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenSetPriceResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenSetPriceResultWasm { /// For PricingSchedule - the identity that set the price - owner_id: Option, + #[wasm_bindgen(getter_with_clone, js_name = "ownerId")] + pub owner_id: Option, /// For PricingSchedule or GroupActionWithPricingSchedule - the pricing schedule - pricing_schedule: Option, + #[wasm_bindgen(getter_with_clone, js_name = "pricingSchedule")] + #[serde(skip)] + pub pricing_schedule: Option, /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// Group action status - group_action_status: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupActionStatus")] + pub group_action_status: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } -#[wasm_bindgen(js_class = TokenSetPriceResult)] -impl TokenSetPriceResultWasm { - /// The identity that set the price (for standard tokens). - #[wasm_bindgen(getter = "ownerId")] - pub fn owner_id(&self) -> Option { - self.owner_id - } - - /// The pricing schedule (for standard tokens or group actions without history). - #[wasm_bindgen(getter = "pricingSchedule")] - pub fn pricing_schedule(&self) -> Option { - self.pricing_schedule.clone() - } - - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The group action status (for group actions). - #[wasm_bindgen(getter = "groupActionStatus")] - pub fn group_action_status(&self) -> Option { - self.group_action_status.clone() - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } -} +impl_wasm_serde_conversions!(TokenSetPriceResultWasm, TokenSetPriceResult); impl TokenSetPriceResultWasm { /// Convert from SDK SetPriceResult with the required contract context @@ -2152,32 +1971,30 @@ impl WasmSdk { ) -> Result { use dash_sdk::dpp::tokens::token_pricing_schedule::TokenPricingSchedule; - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; + let identity_key: IdentityPublicKey = identity_key_wasm.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); + let group_info = + GroupStateTransitionInfoStatusWasm::try_from_optional_options(&options, "groupInfo")?; - // Deserialize and validate options - let parsed = deserialize_token_set_price_options(options_value.clone())?; + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let authority_id: Identifier = + try_from_options::(&options, "authorityId")?.into(); - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let authority_id: Identifier = parsed.authority_id.into(); + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_set_price_options(options.into())?; // Convert price to pricing schedule let pricing_schedule = parsed.price.map(TokenPricingSchedule::SinglePrice); - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; - let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; - // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the set price transition using rs-sdk builder let mut builder = TokenChangeDirectPurchasePriceTransitionBuilder::new( Arc::new(data_contract), @@ -2196,21 +2013,15 @@ impl WasmSdk { } // Add optional group info - if let Some(group_info) = GroupStateTransitionInfoStatusWasm::try_from_optional_options( - &options_value, - "groupInfo", - )? { + if let Some(group_info) = group_info { builder = builder.with_using_group_info(group_info.into()); } - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } @@ -2255,13 +2066,13 @@ export interface TokenDirectPurchaseOptions { /** * The amount of tokens to purchase. */ - amount: bigint | number; + amount: bigint; /** * The maximum total credits the buyer is willing to pay. * The actual cost may be less if the token price is lower. */ - maxTotalCost: bigint | number; + maxTotalCost: bigint; /** * The identity public key to use for signing the transition. @@ -2288,13 +2099,11 @@ extern "C" { pub type TokenDirectPurchaseOptionsJs; } -/// Main input struct for token direct purchase options. +/// Main input struct for token direct purchase options (primitives only). #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TokenDirectPurchaseOptionsInput { - data_contract_id: IdentifierWasm, token_position: u16, - buyer_id: IdentifierWasm, amount: u64, max_total_cost: u64, } @@ -2318,44 +2127,34 @@ fn deserialize_token_direct_purchase_options( /// /// Check which optional fields are present to determine the result type. #[wasm_bindgen(js_name = "TokenDirectPurchaseResult")] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct TokenDirectPurchaseResultWasm { /// For TokenBalance result - buyer_id: Option, + #[wasm_bindgen(getter_with_clone, js_name = "buyerId")] + pub buyer_id: Option, /// New balance after purchase new_balance: Option, /// For group actions - group_power: Option, + #[wasm_bindgen(getter_with_clone, js_name = "groupPower")] + pub group_power: Option, /// For HistoricalDocument or GroupActionWithDocument - the document - document: Option, + #[wasm_bindgen(getter_with_clone)] + #[serde(skip)] + pub document: Option, } #[wasm_bindgen(js_class = TokenDirectPurchaseResult)] impl TokenDirectPurchaseResultWasm { - /// The buyer's identity ID. - #[wasm_bindgen(getter = "buyerId")] - pub fn buyer_id(&self) -> Option { - self.buyer_id - } - /// The buyer's new balance after purchase. #[wasm_bindgen(getter = "newBalance")] pub fn new_balance(&self) -> Option { self.new_balance.map(BigInt::from) } - - /// The accumulated group power (for group actions). - #[wasm_bindgen(getter = "groupPower")] - pub fn group_power(&self) -> Option { - self.group_power - } - - /// The historical document (for tokens with history tracking). - #[wasm_bindgen(getter)] - pub fn document(&self) -> Option { - self.document.clone() - } } +impl_wasm_serde_conversions!(TokenDirectPurchaseResultWasm, TokenDirectPurchaseResult); + impl TokenDirectPurchaseResultWasm { /// Convert from SDK DirectPurchaseResult with the required contract context fn from_result(result: DirectPurchaseResult, contract_id: Identifier) -> Self { @@ -2397,31 +2196,27 @@ impl WasmSdk { &self, options: TokenDirectPurchaseOptionsJs, ) -> Result { - let options_value: JsValue = options.into(); + // Extract complex types first (borrows &options) + let identity_key_wasm = IdentityPublicKeyWasm::try_from_options(&options, "identityKey")?; + let identity_key: IdentityPublicKey = identity_key_wasm.into(); + let signer = IdentitySignerWasm::try_from_options(&options, "signer")?; + let settings: Option = + try_from_options_optional::(&options, "settings")?.map(Into::into); - // Deserialize and validate options - let parsed = deserialize_token_direct_purchase_options(options_value.clone())?; + // Extract identifier fields (borrows &options) + let contract_id: Identifier = + try_from_options::(&options, "dataContractId")?.into(); + let buyer_id: Identifier = try_from_options::(&options, "buyerId")?.into(); + + // Deserialize primitive fields last (consumes options) + let parsed = deserialize_token_direct_purchase_options(options.into())?; - // Convert identifiers - let contract_id: Identifier = parsed.data_contract_id.into(); - let buyer_id: Identifier = parsed.buyer_id.into(); let amount = parsed.amount as TokenAmount; let max_total_cost = parsed.max_total_cost; - // Extract identity key from options - let identity_key_wasm = - IdentityPublicKeyWasm::try_from_options(&options_value, "identityKey")?; - let identity_key: IdentityPublicKey = identity_key_wasm.into(); - - // Extract signer from options - let signer = IdentitySignerWasm::try_from_options(&options_value)?; - // Fetch and cache the data contract let data_contract = self.get_or_fetch_contract(contract_id).await?; - // Extract settings from options - let settings = extract_settings_from_options(&options_value)?; - // Build the direct purchase transition using rs-sdk builder let mut builder = TokenDirectPurchaseTransitionBuilder::new( Arc::new(data_contract), @@ -2431,14 +2226,11 @@ impl WasmSdk { max_total_cost, ); - // Add settings - if let Some(settings) = settings { - builder = builder.with_settings(settings); + // Add settings and user fee increase + if let Some(ref settings) = settings { + builder = builder.with_settings(*settings); } - - // Add user fee increase from settings - let user_fee_increase = - get_user_fee_increase(extract_settings_from_options(&options_value)?.as_ref()); + let user_fee_increase = get_user_fee_increase(settings.as_ref()); if user_fee_increase > 0 { builder = builder.with_user_fee_increase(user_fee_increase); } diff --git a/packages/wasm-sdk/src/utils.rs b/packages/wasm-sdk/src/utils.rs deleted file mode 100644 index caed879cc9e..00000000000 --- a/packages/wasm-sdk/src/utils.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::WasmSdkError; -use platform_value::Value; -use wasm_bindgen::JsValue; -use wasm_dpp2::serialization::conversions; - -/// Convert a `JsValue` coming from JavaScript into a Platform `Value`. -/// -/// Uses object-format conversion which properly handles BigInt and Uint8Array. -pub fn js_value_to_platform_value(value: JsValue) -> Result { - conversions::js_value_to_platform_value(&value).map_err(|err| { - WasmSdkError::invalid_argument(format!( - "Failed to convert JS value to platform value: {err}" - )) - }) -} - -/// Convert an iterable collection of `JsValue` into Platform `Value`s. -pub fn js_values_to_platform_values(values: I) -> Result, WasmSdkError> -where - I: IntoIterator, -{ - values.into_iter().map(js_value_to_platform_value).collect() -} diff --git a/packages/wasm-sdk/src/wallet/key_generation.rs b/packages/wasm-sdk/src/wallet/key_generation.rs index c7c44173511..95b907a73ce 100644 --- a/packages/wasm-sdk/src/wallet/key_generation.rs +++ b/packages/wasm-sdk/src/wallet/key_generation.rs @@ -11,7 +11,8 @@ use dash_sdk::dpp::dashcore::{Address, Network, PrivateKey, PublicKey}; use serde::{Deserialize, Serialize}; use std::str::FromStr; use wasm_bindgen::prelude::*; -use wasm_dpp2::NetworkWasm; +use wasm_dpp2::serialization::conversions::to_object; +use wasm_dpp2::{NetworkLikeJs, NetworkWasm}; /// Key pair information #[derive(Debug, Clone, Serialize, Deserialize)] @@ -80,14 +81,10 @@ impl WasmSdk { }) } - /// Generate a new random key pair - #[wasm_bindgen(js_name = "generateKeyPair")] - pub fn generate_key_pair( - #[wasm_bindgen(unchecked_param_type = "NetworkLike")] network: JsValue, + fn generate_key_pair_internal( + net: Network, + network_wasm: &NetworkWasm, ) -> Result { - let network_wasm = NetworkWasm::try_from(&network)?; - let net: Network = network_wasm.into(); - // Generate random 32 bytes let mut key_bytes = [0u8; 32]; getrandom::getrandom(&mut key_bytes).map_err(|e| { @@ -106,10 +103,18 @@ impl WasmSdk { Ok(KeyPairWasm::from(key_pair)) } + /// Generate a new random key pair + #[wasm_bindgen(js_name = "generateKeyPair")] + pub fn generate_key_pair(network: NetworkLikeJs) -> Result { + let network_wasm: NetworkWasm = network.try_into()?; + let net: Network = network_wasm.into(); + Self::generate_key_pair_internal(net, &network_wasm) + } + /// Generate multiple key pairs #[wasm_bindgen(js_name = "generateKeyPairs")] pub fn generate_key_pairs( - #[wasm_bindgen(unchecked_param_type = "NetworkLike")] network: JsValue, + network: NetworkLikeJs, count: u32, ) -> Result, WasmSdkError> { if count == 0 || count > 100 { @@ -118,9 +123,12 @@ impl WasmSdk { )); } + let network_wasm: NetworkWasm = network.try_into()?; + let net: Network = network_wasm.into(); + let mut pairs = Vec::new(); for _ in 0..count { - pairs.push(Self::generate_key_pair(network.clone())?); + pairs.push(Self::generate_key_pair_internal(net, &network_wasm)?); } Ok(pairs) } @@ -143,7 +151,7 @@ impl WasmSdk { #[wasm_bindgen(js_name = "keyPairFromHex")] pub fn key_pair_from_hex( #[wasm_bindgen(js_name = "privateKeyHex")] private_key_hex: &str, - #[wasm_bindgen(unchecked_param_type = "NetworkLike")] network: JsValue, + network: NetworkLikeJs, ) -> Result { if private_key_hex.len() != 64 { return Err(WasmSdkError::invalid_argument( @@ -151,7 +159,7 @@ impl WasmSdk { )); } - let network_wasm = NetworkWasm::try_from(&network)?; + let network_wasm: NetworkWasm = network.try_into()?; let net: Network = network_wasm.into(); let key_bytes = hex::decode(private_key_hex) @@ -171,9 +179,9 @@ impl WasmSdk { #[wasm_bindgen(js_name = "pubkeyToAddress")] pub fn pubkey_to_address( #[wasm_bindgen(js_name = "pubkeyHex")] pubkey_hex: &str, - #[wasm_bindgen(unchecked_param_type = "NetworkLike")] network: JsValue, + network: NetworkLikeJs, ) -> Result { - let network_wasm = NetworkWasm::try_from(&network)?; + let network_wasm: NetworkWasm = network.try_into()?; let net: Network = network_wasm.into(); let pubkey_bytes = hex::decode(pubkey_hex) @@ -188,11 +196,8 @@ impl WasmSdk { /// Validate a Dash address #[wasm_bindgen(js_name = "validateAddress")] - pub fn validate_address( - address: &str, - #[wasm_bindgen(unchecked_param_type = "NetworkLike")] network: JsValue, - ) -> bool { - let Ok(network_wasm) = NetworkWasm::try_from(&network) else { + pub fn validate_address(address: &str, network: NetworkLikeJs) -> bool { + let Ok(network_wasm): Result = network.try_into() else { return false; }; let net: Network = network_wasm.into(); @@ -289,7 +294,6 @@ impl WasmSdk { }) .collect(); - serde_wasm_bindgen::to_value(&result) - .map_err(|e| WasmSdkError::generic(format!("Serialization error: {}", e))) + Ok(to_object(&result)?) } } diff --git a/packages/wasm-sdk/tests/.eslintrc.yml b/packages/wasm-sdk/tests/.eslintrc.yml deleted file mode 100644 index 7dfe891dcb5..00000000000 --- a/packages/wasm-sdk/tests/.eslintrc.yml +++ /dev/null @@ -1,27 +0,0 @@ -extends: - - airbnb-base - - plugin:jsdoc/recommended -env: - es2020: true - node: true - mocha: true -parserOptions: - ecmaVersion: 2024 -rules: - eol-last: - - error - - always - import/extensions: off - class-methods-use-this: off - import/no-extraneous-dependencies: off - curly: - - error - - all - no-restricted-syntax: - - error - - selector: "LabeledStatement" - message: Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand. - - selector: "WithStatement" - message: "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." -globals: - expect: true diff --git a/packages/wasm-sdk/tests/functional/addresses.spec.mjs b/packages/wasm-sdk/tests/functional/addresses.spec.mjs deleted file mode 100644 index 8a347606bd3..00000000000 --- a/packages/wasm-sdk/tests/functional/addresses.spec.mjs +++ /dev/null @@ -1,96 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Platform address queries', function describePlatformAddressQueries() { - this.timeout(60000); - - wasmFunctionalTestRequirements(); - - let client; - let testHash1; // P2pkh hash for address with balance - let testHash2; // P2sh hash for address with balance - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - const builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - - // Use the test addresses created by SDK_TEST_DATA=true during genesis - // These correspond to: - // - PLATFORM_ADDRESS_1 = P2pkh([10; 20]) with nonce=5, balance=1_000_000 - // - PLATFORM_ADDRESS_2 = P2sh([11; 20]) with nonce=7, balance=2_000_000 - testHash1 = new Uint8Array(20).fill(10); - testHash2 = new Uint8Array(20).fill(11); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('getAddressInfo() returns address info for funded address', async () => { - const testAddress = sdk.PlatformAddress.fromP2pkhHash(testHash1); - const res = await client.getAddressInfo(testAddress); - // PLATFORM_ADDRESS_1 has nonce=5, balance=1_000_000 - expect(res).to.be.ok(); - expect(res.nonce).to.equal(5n); - expect(res.balance).to.equal(1000000n); - }); - - it('getAddressInfoWithProofInfo() returns proof info for address query', async () => { - const testAddress = sdk.PlatformAddress.fromP2pkhHash(testHash1); - const res = await client.getAddressInfoWithProofInfo(testAddress); - expect(res).to.be.ok(); - expect(res.proof).to.be.ok(); - expect(res.metadata).to.be.ok(); - // data should be present for funded address - expect(res.data).to.be.ok(); - expect(res.data.nonce).to.equal(5n); - expect(res.data.balance).to.equal(1000000n); - }); - - it('getAddressesInfos() returns map of address infos', async () => { - const testAddress1 = sdk.PlatformAddress.fromP2pkhHash(testHash1); - const testAddress2 = sdk.PlatformAddress.fromP2shHash(testHash2); - const testAddresses = [testAddress1, testAddress2]; - - const res = await client.getAddressesInfos(testAddresses); - expect(res).to.be.instanceOf(Map); - expect(res.size).to.equal(testAddresses.length); - - // Check values for both funded addresses - // Note: Map keys are stringified addresses, so we need to check values - const entries = Array.from(res.entries()); - expect(entries.length).to.equal(2); - - // Find entries by checking their nonce values (5n and 7n - BigInt) - const info1 = entries.find(([, v]) => v && v.nonce === 5n); - const info2 = entries.find(([, v]) => v && v.nonce === 7n); - expect(info1).to.be.ok(); - expect(info1[1].balance).to.equal(1000000n); - expect(info2).to.be.ok(); - expect(info2[1].balance).to.equal(2000000n); - }); - - it('getAddressesInfosWithProofInfo() returns proof info for multiple addresses', async () => { - const testAddress1 = sdk.PlatformAddress.fromP2pkhHash(testHash1); - const testAddress2 = sdk.PlatformAddress.fromP2shHash(testHash2); - const testAddresses = [testAddress1, testAddress2]; - - const res = await client.getAddressesInfosWithProofInfo(testAddresses); - expect(res).to.be.ok(); - expect(res.proof).to.be.ok(); - expect(res.metadata).to.be.ok(); - expect(res.data).to.be.instanceOf(Map); - expect(res.data.size).to.equal(2); - - // Check data values (nonce is BigInt) - const entries = Array.from(res.data.entries()); - const info1 = entries.find(([, v]) => v && v.nonce === 5n); - const info2 = entries.find(([, v]) => v && v.nonce === 7n); - expect(info1).to.be.ok(); - expect(info1[1].balance).to.equal(1000000n); - expect(info2).to.be.ok(); - expect(info2[1].balance).to.equal(2000000n); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/addresses.spec.ts b/packages/wasm-sdk/tests/functional/addresses.spec.ts new file mode 100644 index 00000000000..fb8b9d091c0 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/addresses.spec.ts @@ -0,0 +1,110 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('Platform Address Queries', function describePlatformAddressQueries() { + this.timeout(60000); + + wasmFunctionalTestRequirements(); + + let client: sdk.WasmSdk; + let testHash1: Uint8Array; // P2pkh hash for address with balance + let testHash2: Uint8Array; // P2sh hash for address with balance + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + const builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + + // Use the test addresses created by SDK_TEST_DATA=true during genesis + // These correspond to: + // - PLATFORM_ADDRESS_1 = P2pkh([10; 20]) with nonce=5, balance=1_000_000 + // - PLATFORM_ADDRESS_2 = P2sh([11; 20]) with nonce=7, balance=2_000_000 + testHash1 = new Uint8Array(20).fill(10); + testHash2 = new Uint8Array(20).fill(11); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getAddressInfo()', () => { + it('should return address info for funded address', async () => { + const testAddress = sdk.PlatformAddress.fromP2pkhHash(testHash1); + const res = await client.getAddressInfo(testAddress); + // PLATFORM_ADDRESS_1 has nonce=5, balance=1_000_000 + expect(res).to.be.ok(); + expect(res.nonce).to.equal(5n); + expect(res.balance).to.equal(1000000n); + }); + }); + + describe('getAddressInfoWithProofInfo()', () => { + it('should return proof info for address query', async () => { + const testAddress = sdk.PlatformAddress.fromP2pkhHash(testHash1); + const res = await client.getAddressInfoWithProofInfo(testAddress); + expect(res).to.be.ok(); + expect(res.proof).to.be.ok(); + expect(res.metadata).to.be.ok(); + // data should be present for funded address + expect(res.data).to.be.ok(); + expect(res.data.nonce).to.equal(5n); + expect(res.data.balance).to.equal(1000000n); + }); + }); + + describe('getAddressesInfos()', () => { + it('should return map of address infos', async () => { + const testAddress1 = sdk.PlatformAddress.fromP2pkhHash(testHash1); + const testAddress2 = sdk.PlatformAddress.fromP2shHash(testHash2); + const testAddresses = [testAddress1, testAddress2]; + + const res = await client.getAddressesInfos(testAddresses); + expect(res).to.be.instanceOf(Map); + expect(res.size).to.equal(testAddresses.length); + + // Check values for both funded addresses + // Note: Map keys are stringified addresses, so we need to check values + const entries = Array.from(res.entries()); + expect(entries.length).to.equal(2); + + // Find entries by checking their nonce values (5n and 7n - BigInt) + const info1 = entries.find(([, v]) => v && v.nonce === 5n); + const info2 = entries.find(([, v]) => v && v.nonce === 7n); + expect(info1).to.be.ok(); + expect(info1[1].balance).to.equal(1000000n); + expect(info2).to.be.ok(); + expect(info2[1].balance).to.equal(2000000n); + }); + }); + + describe('getAddressesInfosWithProofInfo()', () => { + it('should return proof info for multiple addresses', async () => { + const testAddress1 = sdk.PlatformAddress.fromP2pkhHash(testHash1); + const testAddress2 = sdk.PlatformAddress.fromP2shHash(testHash2); + const testAddresses = [testAddress1, testAddress2]; + + const res = await client.getAddressesInfosWithProofInfo(testAddresses); + expect(res).to.be.ok(); + expect(res.proof).to.be.ok(); + expect(res.metadata).to.be.ok(); + expect(res.data).to.be.instanceOf(Map); + expect(res.data.size).to.equal(2); + + // Check data values (nonce may be BigInt or number depending on serialization) + const entries = Array.from(res.data.entries()); + // Use loose equality (==) to handle both BigInt and number + // eslint-disable-next-line eqeqeq + const info1 = entries.find(([, v]) => v && v.nonce == 5); + // eslint-disable-next-line eqeqeq + const info2 = entries.find(([, v]) => v && v.nonce == 7); + expect(info1).to.be.ok(); + // eslint-disable-next-line eqeqeq + expect(info1[1].balance == 1000000).to.be.true(); + expect(info2).to.be.ok(); + // eslint-disable-next-line eqeqeq + expect(info2[1].balance == 2000000).to.be.true(); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/contracts.spec.mjs b/packages/wasm-sdk/tests/functional/contracts.spec.mjs deleted file mode 100644 index d35acadad13..00000000000 --- a/packages/wasm-sdk/tests/functional/contracts.spec.mjs +++ /dev/null @@ -1,68 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Data contract queries', function describeDataContractQueries() { - this.timeout(60000); - - const { dpnsContractId, tokenContracts } = wasmFunctionalTestRequirements(); - - let client; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - const builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('getDataContract() returns data contract', async () => { - const res = await client.getDataContract(dpnsContractId); - expect(res).to.be.ok(); - expect(res.id.toString()).to.equal(dpnsContractId); - }); - - it('getDataContractWithProofInfo() returns proof info', async () => { - const res = await client.getDataContractWithProofInfo(dpnsContractId); - expect(res).to.be.ok(); - expect(res.data).to.be.ok(); - expect(res.metadata).to.be.ok(); - expect(res.proof).to.be.ok(); - }); - - it('getDataContracts() returns multiple contracts', async () => { - const contractIds = [dpnsContractId]; - if (tokenContracts.length > 0) { - contractIds.push(tokenContracts[0].contractId); - } - - const res = await client.getDataContracts(contractIds); - expect(res).to.be.instanceOf(Map); - expect(res.size).to.be.at.least(1); - }); - - it('getDataContractsWithProofInfo() returns proof info for multiple contracts', async () => { - const contractIds = [dpnsContractId]; - - const res = await client.getDataContractsWithProofInfo(contractIds); - expect(res).to.be.ok(); - expect(res.data).to.be.instanceOf(Map); - expect(res.metadata).to.be.ok(); - expect(res.proof).to.be.ok(); - }); - - // TODO: Fix proof verification error: dash drive: proof: corrupted error: - // we did not get back an element for the correct path for the historical contract - it.skip('getDataContractHistory() returns history for contract', async () => { - // Use DPNS contract to test history retrieval - // Note: This may return an empty map if the contract has no history (version = 1) - const res = await client.getDataContractHistory({ - dataContractId: dpnsContractId, - limit: 10, - }); - expect(res).to.be.instanceOf(Map); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/contracts.spec.ts b/packages/wasm-sdk/tests/functional/contracts.spec.ts new file mode 100644 index 00000000000..0e8a6463b8c --- /dev/null +++ b/packages/wasm-sdk/tests/functional/contracts.spec.ts @@ -0,0 +1,79 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('Data Contract Queries', function describeDataContractQueries() { + this.timeout(60000); + + const { dpnsContractId, tokenContracts } = wasmFunctionalTestRequirements(); + + let client: sdk.WasmSdk; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + const builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getDataContract()', () => { + it('should return data contract', async () => { + const res = await client.getDataContract(dpnsContractId); + expect(res).to.be.ok(); + expect(res.id.toString()).to.equal(dpnsContractId); + }); + }); + + describe('getDataContractWithProofInfo()', () => { + it('should return proof info', async () => { + const res = await client.getDataContractWithProofInfo(dpnsContractId); + expect(res).to.be.ok(); + expect(res.data).to.be.ok(); + expect(res.metadata).to.be.ok(); + expect(res.proof).to.be.ok(); + }); + }); + + describe('getDataContracts()', () => { + it('should return multiple contracts', async () => { + const contractIds = [dpnsContractId]; + if (tokenContracts.length > 0) { + contractIds.push(tokenContracts[0].contractId); + } + + const res = await client.getDataContracts(contractIds); + expect(res).to.be.instanceOf(Map); + expect(res.size).to.be.at.least(1); + }); + }); + + describe('getDataContractsWithProofInfo()', () => { + it('should return proof info for multiple contracts', async () => { + const contractIds = [dpnsContractId]; + + const res = await client.getDataContractsWithProofInfo(contractIds); + expect(res).to.be.ok(); + expect(res.data).to.be.instanceOf(Map); + expect(res.metadata).to.be.ok(); + expect(res.proof).to.be.ok(); + }); + }); + + describe('getDataContractHistory()', () => { + // TODO: Fix proof verification error: dash drive: proof: corrupted error: + // we did not get back an element for the correct path for the historical contract + it.skip('should return history for contract', async () => { + // Use DPNS contract to test history retrieval + // Note: This may return an empty map if the contract has no history (version = 1) + const res = await client.getDataContractHistory({ + dataContractId: dpnsContractId, + limit: 10, + }); + expect(res).to.be.instanceOf(Map); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/dpns.spec.mjs b/packages/wasm-sdk/tests/functional/dpns.spec.mjs deleted file mode 100644 index ec76926ceb4..00000000000 --- a/packages/wasm-sdk/tests/functional/dpns.spec.mjs +++ /dev/null @@ -1,83 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Document queries', function describeDocumentQueries() { - this.timeout(60000); - - const { dpnsContractId, identityId } = wasmFunctionalTestRequirements(); - - let client; - let builder; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('lists DPNS documents (no filters)', async () => { - const docs = await client.getDocuments({ - dataContractId: dpnsContractId, - documentTypeName: 'domain', - limit: 5, - }); - expect(docs).to.be.instanceOf(Map); - }); - - it('queries with where clause', async () => { - const docs = await client.getDocuments({ - dataContractId: dpnsContractId, - documentTypeName: 'domain', - where: [ - ['normalizedParentDomainName', '==', 'dash'], - ], - limit: 5, - }); - expect(docs).to.be.instanceOf(Map); - }); - - it('queries with orderBy', async () => { - const docs = await client.getDocuments({ - dataContractId: dpnsContractId, - documentTypeName: 'domain', - orderBy: [ - ['normalizedParentDomainName', 'asc'], - ], - limit: 5, - }); - expect(docs).to.be.instanceOf(Map); - }); - - it('complex where + orderBy', async () => { - const docs = await client.getDocuments({ - dataContractId: dpnsContractId, - documentTypeName: 'domain', - where: [ - ['normalizedLabel', 'startsWith', 'test'], - ['normalizedParentDomainName', '==', 'dash'], - ], - orderBy: [ - ['normalizedParentDomainName', 'asc'], - ['normalizedLabel', 'asc'], - ], - limit: 5, - }); - expect(docs).to.be.instanceOf(Map); - }); - - it('getDocument by id (should handle invalid id gracefully)', async () => { - await expect( - client.getDocument(dpnsContractId, 'domain', 'invalidDocumentId'), - ).to.be.rejected(); - }); - - it('fetches usernames for a known identity and verifies fields', async () => { - const list = await client.getDpnsUsernames({ identityId, limit: 10 }); - expect(list).to.be.an('array'); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/dpns.spec.ts b/packages/wasm-sdk/tests/functional/dpns.spec.ts new file mode 100644 index 00000000000..6bc67132ee2 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/dpns.spec.ts @@ -0,0 +1,90 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('Document Queries', function describeDocumentQueries() { + this.timeout(60000); + + const { dpnsContractId, identityId } = wasmFunctionalTestRequirements(); + + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getDocuments()', () => { + it('should list DPNS documents with no filters', async () => { + const docs = await client.getDocuments({ + dataContractId: dpnsContractId, + documentTypeName: 'domain', + limit: 5, + }); + expect(docs).to.be.instanceOf(Map); + }); + + it('should query with where clause', async () => { + const docs = await client.getDocuments({ + dataContractId: dpnsContractId, + documentTypeName: 'domain', + where: [ + ['normalizedParentDomainName', '==', 'dash'], + ], + limit: 5, + }); + expect(docs).to.be.instanceOf(Map); + }); + + it('should query with orderBy', async () => { + const docs = await client.getDocuments({ + dataContractId: dpnsContractId, + documentTypeName: 'domain', + orderBy: [ + ['normalizedParentDomainName', 'asc'], + ], + limit: 5, + }); + expect(docs).to.be.instanceOf(Map); + }); + + it('should query with complex where and orderBy', async () => { + const docs = await client.getDocuments({ + dataContractId: dpnsContractId, + documentTypeName: 'domain', + where: [ + ['normalizedLabel', 'startsWith', 'test'], + ['normalizedParentDomainName', '==', 'dash'], + ], + orderBy: [ + ['normalizedParentDomainName', 'asc'], + ['normalizedLabel', 'asc'], + ], + limit: 5, + }); + expect(docs).to.be.instanceOf(Map); + }); + }); + + describe('getDocument()', () => { + it('should handle invalid id gracefully', async () => { + await expect( + client.getDocument(dpnsContractId, 'domain', 'invalidDocumentId'), + ).to.be.rejected(); + }); + }); + + describe('getDpnsUsernames()', () => { + it('should fetch usernames for a known identity and verify fields', async () => { + const list = await client.getDpnsUsernames({ identityId, limit: 10 }); + expect(list).to.be.an('array'); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/epochs-blocks.spec.mjs b/packages/wasm-sdk/tests/functional/epochs-blocks.spec.mjs deleted file mode 100644 index 57cdedac7e4..00000000000 --- a/packages/wasm-sdk/tests/functional/epochs-blocks.spec.mjs +++ /dev/null @@ -1,115 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('Epochs and evonode blocks', function describeEpochs() { - this.timeout(60000); - - let client; - let evonodeProTxHash; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - const builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - - // Get the proTxHash from the node status - const status = await client.getStatus(); - evonodeProTxHash = status.node.proTxHash; - }); - - after(async () => { - // Wait briefly to ensure any pending async operations complete - await new Promise((resolve) => { setTimeout(resolve, 100); }); - if (client) { client.free(); } - }); - - it('gets epochs info and finalized epochs', async () => { - // Get current epoch info - const current = await client.getCurrentEpoch().catch(() => null); - const currentIndex = current ? Number(current.index) : 0; - const start = Math.max(0, currentIndex - 5); - - const infos = await client.getEpochsInfo({ - startEpoch: start, - count: 5, - ascending: true, - }); - expect(infos).to.be.instanceOf(Map); - - const finalized = await client.getFinalizedEpochInfos({ - startEpoch: start, - count: 5, - }); - expect(finalized).to.be.instanceOf(Map); - }); - - it('queries evonode proposed blocks by id/range', async () => { - // Get current epoch - const current = await client.getCurrentEpoch().catch(() => null); - const epochIndex = current ? Number(current.index) : 0; - - // Query by range (doesn't require a specific proTxHash) - const byRange = await client.getEvonodesProposedEpochBlocksByRange({ - epoch: epochIndex, - limit: 50, - }); - expect(byRange).to.be.instanceOf(Map); - - // Query by specific IDs only if we have a proTxHash - if (evonodeProTxHash) { - const byIds = await client - .getEvonodesProposedEpochBlocksByIds(epochIndex, [evonodeProTxHash]); - expect(byIds).to.be.instanceOf(Map); - } - }); - - it('queries evonode proposed blocks by ids with proof', async () => { - const current = await client.getCurrentEpoch().catch(() => null); - const epochIndex = current ? Number(current.index) : 0; - - // Get at least one proTxHash from the range query results - const byRange = await client.getEvonodesProposedEpochBlocksByRange({ - epoch: epochIndex, - limit: 1, - }); - expect(byRange).to.be.instanceOf(Map); - - // Get a proTxHash from the results (or use node's proTxHash if available) - let testProTxHash = evonodeProTxHash; - if (!testProTxHash && byRange.size > 0) { - // The keys in the map are Identifier objects - // Need to convert to hex for the API (ProTxHash requires 64 hex chars) - const firstKey = byRange.keys().next().value; - if (firstKey) { - // Convert Identifier bytes to hex string using toBytes() - testProTxHash = Array.from(firstKey.toBytes()) - .map((b) => b.toString(16).padStart(2, '0')) - .join(''); - } - } - - // Only test by IDs if we have a valid proTxHash - if (testProTxHash) { - const res = await client - .getEvonodesProposedEpochBlocksByIdsWithProofInfo(epochIndex, [testProTxHash]); - expect(res).to.be.ok(); - expect(res.data).to.be.instanceOf(Map); - expect(res.proof).to.be.ok(); - expect(res.metadata).to.be.ok(); - } - }); - - it('queries evonode proposed blocks by range with proof', async () => { - const current = await client.getCurrentEpoch().catch(() => null); - const epochIndex = current ? Number(current.index) : 0; - - const res = await client.getEvonodesProposedEpochBlocksByRangeWithProofInfo({ - epoch: epochIndex, - limit: 50, - }); - expect(res).to.be.ok(); - expect(res.data).to.be.instanceOf(Map); - expect(res.proof).to.be.ok(); - expect(res.metadata).to.be.ok(); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/epochs-blocks.spec.ts b/packages/wasm-sdk/tests/functional/epochs-blocks.spec.ts new file mode 100644 index 00000000000..c04fbe0ae23 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/epochs-blocks.spec.ts @@ -0,0 +1,141 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('Epochs and Evonode Blocks', function describeEpochs() { + this.timeout(60000); + + let client: sdk.WasmSdk; + let evonodeProTxHash: string; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + const builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + + // Get the proTxHash from the node status + const status = await client.getStatus(); + evonodeProTxHash = status.node.proTxHash; + }); + + after(async () => { + // Wait briefly to ensure any pending async operations complete + await new Promise((resolve) => { setTimeout(resolve, 100); }); + if (client) { client.free(); } + }); + + describe('getEpochsInfo()', () => { + it('should get epochs info and finalized epochs', async () => { + // Get current epoch info + const current = await client.getCurrentEpoch().catch(() => null); + const currentIndex = current ? Number(current.index) : 0; + const start = Math.max(0, currentIndex - 5); + + const infos = await client.getEpochsInfo({ + startEpoch: start, + count: 5, + ascending: true, + }); + expect(infos).to.be.instanceOf(Map); + }); + }); + + describe('getFinalizedEpochInfos()', () => { + it('should get finalized epoch infos', async () => { + // Get current epoch info + const current = await client.getCurrentEpoch().catch(() => null); + const currentIndex = current ? Number(current.index) : 0; + const start = Math.max(0, currentIndex - 5); + + const finalized = await client.getFinalizedEpochInfos({ + startEpoch: start, + count: 5, + }); + expect(finalized).to.be.instanceOf(Map); + }); + }); + + describe('getEvonodesProposedEpochBlocksByIds()', () => { + it('should query evonode proposed blocks by ids', async () => { + // Get current epoch + const current = await client.getCurrentEpoch().catch(() => null); + const epochIndex = current ? Number(current.index) : 0; + + // Query by specific IDs only if we have a proTxHash + if (evonodeProTxHash) { + const byIds = await client + .getEvonodesProposedEpochBlocksByIds(epochIndex, [evonodeProTxHash]); + expect(byIds).to.be.instanceOf(Map); + } + }); + }); + + describe('getEvonodesProposedEpochBlocksByRange()', () => { + it('should query evonode proposed blocks by range', async () => { + // Get current epoch + const current = await client.getCurrentEpoch().catch(() => null); + const epochIndex = current ? Number(current.index) : 0; + + // Query by range (doesn't require a specific proTxHash) + const byRange = await client.getEvonodesProposedEpochBlocksByRange({ + epoch: epochIndex, + limit: 50, + }); + expect(byRange).to.be.instanceOf(Map); + }); + }); + + describe('getEvonodesProposedEpochBlocksByIdsWithProofInfo()', () => { + it('should query evonode proposed blocks by ids with proof', async () => { + const current = await client.getCurrentEpoch().catch(() => null); + const epochIndex = current ? Number(current.index) : 0; + + // Get at least one proTxHash from the range query results + const byRange = await client.getEvonodesProposedEpochBlocksByRange({ + epoch: epochIndex, + limit: 1, + }); + expect(byRange).to.be.instanceOf(Map); + + // Get a proTxHash from the results (or use node's proTxHash if available) + let testProTxHash = evonodeProTxHash; + if (!testProTxHash && byRange.size > 0) { + // The keys in the map are Identifier objects + // Need to convert to hex for the API (ProTxHash requires 64 hex chars) + const firstKey = byRange.keys().next().value; + if (firstKey) { + // Convert Identifier bytes to hex string using toBytes() + testProTxHash = Array.from(firstKey.toBytes() as Uint8Array) + .map((b: number) => b.toString(16).padStart(2, '0')) + .join(''); + } + } + + // Only test by IDs if we have a valid proTxHash + if (testProTxHash) { + const res = await client + .getEvonodesProposedEpochBlocksByIdsWithProofInfo(epochIndex, [testProTxHash]); + expect(res).to.be.ok(); + expect(res.data).to.be.instanceOf(Map); + expect(res.proof).to.be.ok(); + expect(res.metadata).to.be.ok(); + } + }); + }); + + describe('getEvonodesProposedEpochBlocksByRangeWithProofInfo()', () => { + it('should query evonode proposed blocks by range with proof', async () => { + const current = await client.getCurrentEpoch().catch(() => null); + const epochIndex = current ? Number(current.index) : 0; + + const res = await client.getEvonodesProposedEpochBlocksByRangeWithProofInfo({ + epoch: epochIndex, + limit: 50, + }); + expect(res).to.be.ok(); + expect(res.data).to.be.instanceOf(Map); + expect(res.proof).to.be.ok(); + expect(res.metadata).to.be.ok(); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/fixtures/requiredTestData.mjs b/packages/wasm-sdk/tests/functional/fixtures/requiredTestData.ts similarity index 65% rename from packages/wasm-sdk/tests/functional/fixtures/requiredTestData.mjs rename to packages/wasm-sdk/tests/functional/fixtures/requiredTestData.ts index a942a275cf0..081682e9cc9 100644 --- a/packages/wasm-sdk/tests/functional/fixtures/requiredTestData.mjs +++ b/packages/wasm-sdk/tests/functional/fixtures/requiredTestData.ts @@ -1,10 +1,23 @@ +/** + * Convert a hex string to Uint8Array. + * @param {string} hex - Hex string to convert + * @returns {Uint8Array} The bytes + */ +function hexToBytes(hex: string): Uint8Array { + const bytes = new Uint8Array(hex.length / 2); + for (let i = 0; i < hex.length; i += 2) { + bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16); + } + return bytes; +} + /** * Requirements for wasm-sdk functional tests. * These IDs/contracts should exist on the target network * (seeded via SDK_TEST_DATA=true yarn start). * @returns {object} Test requirements object */ -// eslint-disable-next-line import/prefer-default-export +// eslint-disable-next-line import-x/prefer-default-export export function wasmFunctionalTestRequirements() { return { // Seeded via SDK_TEST_DATA=true (identity id = 32 bytes of 0x01) @@ -54,62 +67,32 @@ export function createTestSignerAndKey(sdkModule, seed, keyIndex = 2) { const keys = sdkModule.WasmSdk.generateTestIdentityKeys(BigInt(seed)); const keyInfo = keys[keyIndex]; - // serde_wasm_bindgen returns Maps, so use .get() to access properties - const privateKeyHex = keyInfo.get('privateKeyHex'); - const keyId = keyInfo.get('keyId'); - const publicKeyData = keyInfo.get('publicKeyData'); - const keyTypeStr = keyInfo.get('keyType'); - const purposeStr = keyInfo.get('purpose'); - const securityLevelStr = keyInfo.get('securityLevel'); + // serde_wasm_bindgen with serialize_maps_as_objects(true) returns plain objects + const { privateKeyHex } = keyInfo; + const { keyId } = keyInfo; + const { publicKeyData } = keyInfo; + const keyTypeStr = keyInfo.keyType; + const purposeStr = keyInfo.purpose; + const securityLevelStr = keyInfo.securityLevel; // Create the signer and add the private key using PrivateKey.fromHex const signer = new sdkModule.IdentitySigner(); const privateKey = sdkModule.PrivateKey.fromHex(privateKeyHex, 'testnet'); signer.addKey(privateKey); - // Key types: ECDSA_SECP256K1 = 0, BLS12_381 = 1, ECDSA_HASH160 = 2, BIP13_SCRIPT_HASH = 3 - const keyTypeMap = { - ECDSA_SECP256K1: 0, - BLS12_381: 1, - ECDSA_HASH160: 2, - BIP13_SCRIPT_HASH: 3, - }; - const keyType = keyTypeMap[keyTypeStr] ?? 0; - - // Purposes: AUTHENTICATION = 0, ENCRYPTION = 1, DECRYPTION = 2, TRANSFER = 3, ... - const purposeMap = { - AUTHENTICATION: 0, - ENCRYPTION: 1, - DECRYPTION: 2, - TRANSFER: 3, - SYSTEM: 4, - VOTING: 5, - OWNER: 6, - }; - const purpose = purposeMap[purposeStr] ?? 0; - - // Security levels: MASTER = 0, CRITICAL = 1, HIGH = 2, MEDIUM = 3 - const securityLevelMap = { - MASTER: 0, - CRITICAL: 1, - HIGH: 2, - MEDIUM: 3, - }; - const securityLevel = securityLevelMap[securityLevelStr] ?? keyIndex; - // Determine read_only based on key type (transfer keys are read_only) const readOnly = purposeStr === 'TRANSFER'; - const identityKey = new sdkModule.IdentityPublicKey( - keyId, - purpose, - securityLevel, - keyType, - readOnly, - publicKeyData, // hex string (66 chars for ECDSA_SECP256K1, 40 chars for ECDSA_HASH160) - undefined, // disabled_at - undefined, // contract_bounds - ); + // IdentityPublicKey constructor expects an options object with string enum values + // keyId might be BigInt from serialization, convert to number (u32) + const identityKey = new sdkModule.IdentityPublicKey({ + keyId: Number(keyId), + purpose: purposeStr, // string like 'AUTHENTICATION', 'TRANSFER' + securityLevel: securityLevelStr, // string like 'MASTER', 'CRITICAL', 'HIGH' + keyType: keyTypeStr, // string like 'ECDSA_SECP256K1', 'ECDSA_HASH160' + isReadOnly: readOnly, + data: hexToBytes(publicKeyData), // Uint8Array + }); return { signer, identityKey, keyInfo }; } diff --git a/packages/wasm-sdk/tests/functional/groups.spec.mjs b/packages/wasm-sdk/tests/functional/groups.spec.mjs deleted file mode 100644 index d16950d18ee..00000000000 --- a/packages/wasm-sdk/tests/functional/groups.spec.mjs +++ /dev/null @@ -1,41 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Group queries', function describeGroupQueries() { - this.timeout(60000); - - let client; - let builder; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('fetches identity groups and group members', async () => { - const { dpnsContractId: DPNS_CONTRACT, identityId: IDENTITY } = ( - wasmFunctionalTestRequirements() - ); - // These calls may fail in offline runs; permit network errors - await client.getIdentityGroups({ - identityId: IDENTITY, - memberDataContracts: [DPNS_CONTRACT], - }); - await client.getGroupMembers({ - dataContractId: DPNS_CONTRACT, - groupContractPosition: 0, - limit: 10, - }); - }); - - it('fetches groups data contracts', async () => { - const { dpnsContractId: DPNS_CONTRACT } = wasmFunctionalTestRequirements(); - await client.getGroupsDataContracts([DPNS_CONTRACT]); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/groups.spec.ts b/packages/wasm-sdk/tests/functional/groups.spec.ts new file mode 100644 index 00000000000..b91bae5c929 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/groups.spec.ts @@ -0,0 +1,51 @@ +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('Groups', function describeGroups() { + this.timeout(60000); + + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getIdentityGroups()', () => { + it('should fetch identity groups', async () => { + const { dpnsContractId: DPNS_CONTRACT, identityId: IDENTITY } = ( + wasmFunctionalTestRequirements() + ); + // These calls may fail in offline runs; permit network errors + await client.getIdentityGroups({ + identityId: IDENTITY, + memberDataContracts: [DPNS_CONTRACT], + }); + }); + }); + + describe('getGroupMembers()', () => { + it('should fetch group members', async () => { + const { dpnsContractId: DPNS_CONTRACT } = wasmFunctionalTestRequirements(); + await client.getGroupMembers({ + dataContractId: DPNS_CONTRACT, + groupContractPosition: 0, + limit: 10, + }); + }); + }); + + describe('getGroupsDataContracts()', () => { + it('should fetch groups data contracts', async () => { + const { dpnsContractId: DPNS_CONTRACT } = wasmFunctionalTestRequirements(); + await client.getGroupsDataContracts([DPNS_CONTRACT]); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/helpers/chai.ts b/packages/wasm-sdk/tests/functional/helpers/chai.ts new file mode 100644 index 00000000000..fb49541b171 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/helpers/chai.ts @@ -0,0 +1,9 @@ +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import dirtyChai from 'dirty-chai'; + +chai.use(chaiAsPromised); +chai.use(dirtyChai); + +export const { expect } = chai; +export default chai; diff --git a/packages/wasm-sdk/tests/functional/identities.spec.mjs b/packages/wasm-sdk/tests/functional/identities.spec.mjs deleted file mode 100644 index e3dc2c2cece..00000000000 --- a/packages/wasm-sdk/tests/functional/identities.spec.mjs +++ /dev/null @@ -1,220 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Identity queries', function describeBlock() { - this.timeout(90000); - - const { - identityId: TEST_IDENTITY, - dpnsContractId: DPNS_CONTRACT, - tokenContracts, - } = wasmFunctionalTestRequirements(); - - let client; - let builder; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('fetches identity and basic fields', async () => { - const r = await client.getIdentity(TEST_IDENTITY); - expect(r).to.be.ok(); - }); - - it('fetches identity with proof and toJSON returns full structure', async () => { - const response = await client.getIdentityWithProofInfo(TEST_IDENTITY); - - // Basic shape check - expect(response).to.be.ok(); - expect(response.data).to.be.ok(); - expect(response.metadata).to.be.ok(); - expect(response.proof).to.be.ok(); - - // Call toJSON and verify structure - const json = response.toJSON(); - - // Verify top-level structure - expect(json).to.have.property('data'); - expect(json).to.have.property('metadata'); - expect(json).to.have.property('proof'); - - // Verify identity data - id should be Base58 string in JSON - expect(json.data).to.have.property('id'); - expect(json.data.id).to.be.a('string'); - expect(json.data.id).to.equal(TEST_IDENTITY); - expect(json.data).to.have.property('balance'); - expect(json.data).to.have.property('revision'); - expect(json.data).to.have.property('publicKeys'); - expect(json.data.publicKeys).to.be.an('array'); - - // Verify metadata structure - expect(json.metadata).to.have.property('height'); - expect(json.metadata).to.have.property('coreChainLockedHeight'); - expect(json.metadata).to.have.property('epoch'); - expect(json.metadata).to.have.property('timeMs'); - expect(json.metadata).to.have.property('protocolVersion'); - expect(json.metadata).to.have.property('chainId'); - expect(json.metadata.chainId).to.be.a('string'); // base64 - - // Verify proof structure - expect(json.proof).to.have.property('grovedbProof'); - expect(json.proof.grovedbProof).to.be.a('string'); // base64 - expect(json.proof).to.have.property('quorumHash'); - expect(json.proof).to.have.property('signature'); - expect(json.proof).to.have.property('round'); - expect(json.proof).to.have.property('blockIdHash'); - expect(json.proof).to.have.property('quorumType'); - }); - - it('fetches data contract with proof and toJSON returns full structure', async () => { - const response = await client.getDataContractWithProofInfo(DPNS_CONTRACT); - - // Basic shape check - expect(response).to.be.ok(); - expect(response.data).to.be.ok(); - expect(response.metadata).to.be.ok(); - expect(response.proof).to.be.ok(); - - // Call toJSON and verify structure - const json = response.toJSON(); - - // Verify top-level structure - expect(json).to.have.property('data'); - expect(json).to.have.property('metadata'); - expect(json).to.have.property('proof'); - - // Verify data contract data - id should be Base58 string in JSON - expect(json.data).to.have.property('id'); - expect(json.data.id).to.be.a('string'); - expect(json.data.id).to.equal(DPNS_CONTRACT); - expect(json.data).to.have.property('ownerId'); - expect(json.data.ownerId).to.be.a('string'); - expect(json.data).to.have.property('version'); - expect(json.data).to.have.property('documentSchemas'); - expect(json.data.documentSchemas).to.be.an('object'); - - // Verify metadata structure - expect(json.metadata).to.have.property('height'); - expect(json.metadata).to.have.property('coreChainLockedHeight'); - expect(json.metadata).to.have.property('epoch'); - expect(json.metadata).to.have.property('timeMs'); - expect(json.metadata).to.have.property('protocolVersion'); - expect(json.metadata).to.have.property('chainId'); - expect(json.metadata.chainId).to.be.a('string'); // base64 - - // Verify proof structure - expect(json.proof).to.have.property('grovedbProof'); - expect(json.proof.grovedbProof).to.be.a('string'); // base64 - expect(json.proof).to.have.property('quorumHash'); - expect(json.proof).to.have.property('signature'); - expect(json.proof).to.have.property('round'); - expect(json.proof).to.have.property('blockIdHash'); - expect(json.proof).to.have.property('quorumType'); - }); - - it('gets identity balance and nonce', async () => { - // getIdentityBalance returns bigint | null, but for existing identity it should be present - const balance = await client.getIdentityBalance(TEST_IDENTITY); - expect(typeof balance).to.equal('bigint'); - expect(String(balance)).to.match(/^\d+$/); - - // getIdentityNonce returns bigint | null, but for existing identity it should be present - const nonce = await client.getIdentityNonce(TEST_IDENTITY); - expect(typeof nonce).to.equal('bigint'); - expect(String(nonce)).to.match(/^\d+$/); - }); - - it('gets contract nonce and keys', async () => { - // getIdentityContractNonce returns bigint | null - // null if identity never interacted with the contract - // Note: On a fresh platform, nonce would be null. But after running tests - // that create documents, the nonce will be a bigint. We accept both. - const nonce = await client.getIdentityContractNonce(TEST_IDENTITY, DPNS_CONTRACT); - // Nonce is either null (never used) or a bigint (has been used) - expect(nonce === null || typeof nonce === 'bigint').to.be.true(); - - const keys = await client.getIdentityKeys({ - identityId: TEST_IDENTITY, - request: { type: 'all' }, - }); - expect(keys).to.be.an('array'); - }); - - it('batch identity balances and balance+revision', async () => { - // getIdentitiesBalances returns Map - const balances = await client.getIdentitiesBalances([TEST_IDENTITY]); - expect(balances).to.be.instanceOf(Map); - expect(balances.size).to.equal(1); - // For existing identity, balance should be present - const balance = Array.from(balances.values())[0]; - expect(typeof balance).to.equal('bigint'); - - // getIdentityBalanceAndRevision returns IdentityBalanceAndRevision | null - // For existing identity, it should be present - const br = await client.getIdentityBalanceAndRevision(TEST_IDENTITY); - expect(br).to.be.ok(); - expect(typeof br.balance).to.equal('bigint'); - expect(typeof br.revision === 'number' || typeof br.revision === 'bigint').to.be.true(); - }); - - it('contract keys for identity', async () => { - const r = await client.getIdentitiesContractKeys({ - identityIds: [TEST_IDENTITY], - contractId: DPNS_CONTRACT, - }); - expect(r).to.be.an('array'); - }); - - it('contract keys filtered by purpose and with proof', async () => { - const response = await client.getIdentitiesContractKeysWithProofInfo({ - identityIds: [TEST_IDENTITY], - contractId: DPNS_CONTRACT, - purposes: [0], // authentication - }); - - // Basic shape - expect(response).to.be.ok(); - expect(response.metadata).to.be.ok(); - expect(response.proof).to.be.ok(); - - // Data sanity: if keys are returned, all should match the requested purpose set - const keysArray = response.data; - if (Array.isArray(keysArray) && keysArray.length > 0) { - for (const entry of keysArray) { - const { keys } = entry; - for (const key of keys) { - expect(key.purpose).to.match(/Authentication/i); - } - } - } - }); - - it('contract keys batch handles multiple identities', async () => { - const r = await client.getIdentitiesContractKeys({ - identityIds: [TEST_IDENTITY, TEST_IDENTITY], - contractId: DPNS_CONTRACT, - }); - expect(r).to.be.an('array'); - if (r.length > 0) { - expect(r[0].identityId).to.be.instanceOf(sdk.Identifier); // IdentifierWasm - } - }); - - it('token balances/infos for identity and batches', async () => { - const TOKEN_CONTRACT = tokenContracts[0].contractId; - const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT, 1); - - await client.getIdentityTokenBalances(TEST_IDENTITY, [tokenId]); - await client.getIdentitiesTokenBalances([TEST_IDENTITY], tokenId); - await client.getIdentityTokenInfos(TEST_IDENTITY, [tokenId]); - await client.getIdentitiesTokenInfos([TEST_IDENTITY], tokenContracts[0].contractId); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/identities.spec.ts b/packages/wasm-sdk/tests/functional/identities.spec.ts new file mode 100644 index 00000000000..6b5d86cb1c7 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/identities.spec.ts @@ -0,0 +1,272 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('Identities', function describeIdentities() { + this.timeout(90000); + + const { + identityId: TEST_IDENTITY, + dpnsContractId: DPNS_CONTRACT, + tokenContracts, + } = wasmFunctionalTestRequirements(); + + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getIdentity()', () => { + it('should fetch identity and basic fields', async () => { + const r = await client.getIdentity(TEST_IDENTITY); + expect(r).to.be.ok(); + }); + }); + + describe('getIdentityWithProofInfo()', () => { + it('should fetch identity with proof and toJSON returns full structure', async () => { + const response = await client.getIdentityWithProofInfo(TEST_IDENTITY); + + // Basic shape check + expect(response).to.be.ok(); + expect(response.data).to.be.ok(); + expect(response.metadata).to.be.ok(); + expect(response.proof).to.be.ok(); + + // Call toJSON and verify structure + const json = response.toJSON(); + + // Verify top-level structure + expect(json).to.have.property('data'); + expect(json).to.have.property('metadata'); + expect(json).to.have.property('proof'); + + // Verify identity data - id should be Base58 string in JSON + expect(json.data).to.have.property('id'); + expect(json.data.id).to.be.a('string'); + expect(json.data.id).to.equal(TEST_IDENTITY); + expect(json.data).to.have.property('balance'); + expect(json.data).to.have.property('revision'); + expect(json.data).to.have.property('publicKeys'); + expect(json.data.publicKeys).to.be.an('array'); + + // Verify metadata structure + expect(json.metadata).to.have.property('height'); + expect(json.metadata).to.have.property('coreChainLockedHeight'); + expect(json.metadata).to.have.property('epoch'); + expect(json.metadata).to.have.property('timeMs'); + expect(json.metadata).to.have.property('protocolVersion'); + expect(json.metadata).to.have.property('chainId'); + expect(json.metadata.chainId).to.be.a('string'); // base64 + + // Verify proof structure + expect(json.proof).to.have.property('grovedbProof'); + expect(json.proof.grovedbProof).to.be.a('string'); // base64 + expect(json.proof).to.have.property('quorumHash'); + expect(json.proof).to.have.property('signature'); + expect(json.proof).to.have.property('round'); + expect(json.proof).to.have.property('blockIdHash'); + expect(json.proof).to.have.property('quorumType'); + }); + }); + + describe('getDataContractWithProofInfo()', () => { + it('should fetch data contract with proof and toJSON returns full structure', async () => { + const response = await client.getDataContractWithProofInfo(DPNS_CONTRACT); + + // Basic shape check + expect(response).to.be.ok(); + expect(response.data).to.be.ok(); + expect(response.metadata).to.be.ok(); + expect(response.proof).to.be.ok(); + + // Call toJSON and verify structure + const json = response.toJSON(); + + // Verify top-level structure + expect(json).to.have.property('data'); + expect(json).to.have.property('metadata'); + expect(json).to.have.property('proof'); + + // Verify data contract data - id should be Base58 string in JSON + expect(json.data).to.have.property('id'); + expect(json.data.id).to.be.a('string'); + expect(json.data.id).to.equal(DPNS_CONTRACT); + expect(json.data).to.have.property('ownerId'); + expect(json.data.ownerId).to.be.a('string'); + expect(json.data).to.have.property('version'); + expect(json.data).to.have.property('documentSchemas'); + expect(json.data.documentSchemas).to.be.an('object'); + + // Verify metadata structure + expect(json.metadata).to.have.property('height'); + expect(json.metadata).to.have.property('coreChainLockedHeight'); + expect(json.metadata).to.have.property('epoch'); + expect(json.metadata).to.have.property('timeMs'); + expect(json.metadata).to.have.property('protocolVersion'); + expect(json.metadata).to.have.property('chainId'); + expect(json.metadata.chainId).to.be.a('string'); // base64 + + // Verify proof structure + expect(json.proof).to.have.property('grovedbProof'); + expect(json.proof.grovedbProof).to.be.a('string'); // base64 + expect(json.proof).to.have.property('quorumHash'); + expect(json.proof).to.have.property('signature'); + expect(json.proof).to.have.property('round'); + expect(json.proof).to.have.property('blockIdHash'); + expect(json.proof).to.have.property('quorumType'); + }); + }); + + describe('getIdentityBalance()', () => { + it('should get identity balance', async () => { + // getIdentityBalance returns bigint | null, but for existing identity it should be present + const balance = await client.getIdentityBalance(TEST_IDENTITY); + expect(typeof balance).to.equal('bigint'); + expect(String(balance)).to.match(/^\d+$/); + }); + }); + + describe('getIdentityNonce()', () => { + it('should get identity nonce', async () => { + // getIdentityNonce returns bigint | null, but for existing identity it should be present + const nonce = await client.getIdentityNonce(TEST_IDENTITY); + expect(typeof nonce).to.equal('bigint'); + expect(String(nonce)).to.match(/^\d+$/); + }); + }); + + describe('getIdentityContractNonce()', () => { + it('should get contract nonce', async () => { + // getIdentityContractNonce returns bigint | null | undefined + // null/undefined if identity never interacted with the contract + // Note: On a fresh platform, nonce would be null/undefined. But after running tests + // that create documents, the nonce will be a bigint. We accept all three. + const nonce = await client.getIdentityContractNonce(TEST_IDENTITY, DPNS_CONTRACT); + // Nonce is either null/undefined (never used) or a bigint (has been used) + expect(nonce == null || typeof nonce === 'bigint').to.be.true(); + }); + }); + + describe('getIdentityKeys()', () => { + it('should get identity keys', async () => { + const keys = await client.getIdentityKeys({ + identityId: TEST_IDENTITY, + request: { type: 'all' }, + }); + expect(keys).to.be.an('array'); + }); + }); + + describe('getIdentitiesBalances()', () => { + it('should get batch identity balances', async () => { + // getIdentitiesBalances returns Map + const balances = await client.getIdentitiesBalances([TEST_IDENTITY]); + expect(balances).to.be.instanceOf(Map); + expect(balances.size).to.equal(1); + // For existing identity, balance should be present + const balance = Array.from(balances.values())[0]; + expect(typeof balance).to.equal('bigint'); + }); + }); + + describe('getIdentityBalanceAndRevision()', () => { + it('should get identity balance and revision', async () => { + // getIdentityBalanceAndRevision returns IdentityBalanceAndRevision | null + // For existing identity, it should be present + const br = await client.getIdentityBalanceAndRevision(TEST_IDENTITY); + expect(br).to.be.ok(); + expect(typeof br.balance).to.equal('bigint'); + expect(typeof br.revision === 'number' || typeof br.revision === 'bigint').to.be.true(); + }); + }); + + describe('getIdentitiesContractKeys()', () => { + it('should get contract keys for identity', async () => { + const r = await client.getIdentitiesContractKeys({ + identityIds: [TEST_IDENTITY], + contractId: DPNS_CONTRACT, + }); + expect(r).to.be.an('array'); + }); + + it('should handle multiple identities in contract keys batch', async () => { + const r = await client.getIdentitiesContractKeys({ + identityIds: [TEST_IDENTITY, TEST_IDENTITY], + contractId: DPNS_CONTRACT, + }); + expect(r).to.be.an('array'); + if (r.length > 0) { + expect(r[0].identityId).to.be.instanceOf(sdk.Identifier); // IdentifierWasm + } + }); + }); + + describe('getIdentitiesContractKeysWithProofInfo()', () => { + it('should get contract keys filtered by purpose and with proof', async () => { + const response = await client.getIdentitiesContractKeysWithProofInfo({ + identityIds: [TEST_IDENTITY], + contractId: DPNS_CONTRACT, + purposes: [0], // authentication + }); + + // Basic shape + expect(response).to.be.ok(); + expect(response.metadata).to.be.ok(); + expect(response.proof).to.be.ok(); + + // Data sanity: if keys are returned, all should match the requested purpose set + const keysArray = response.data; + if (Array.isArray(keysArray) && keysArray.length > 0) { + for (const entry of keysArray) { + const { keys } = entry; + for (const key of keys) { + expect(key.purpose).to.match(/Authentication/i); + } + } + } + }); + }); + + describe('getIdentityTokenBalances()', () => { + it('should get token balances for identity', async () => { + const TOKEN_CONTRACT = tokenContracts[0].contractId; + const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT, 1); + + await client.getIdentityTokenBalances(TEST_IDENTITY, [tokenId]); + }); + }); + + describe('getIdentitiesTokenBalances()', () => { + it('should get token balances for multiple identities', async () => { + const TOKEN_CONTRACT = tokenContracts[0].contractId; + const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT, 1); + + await client.getIdentitiesTokenBalances([TEST_IDENTITY], tokenId); + }); + }); + + describe('getIdentityTokenInfos()', () => { + it('should get token infos for identity', async () => { + const TOKEN_CONTRACT = tokenContracts[0].contractId; + const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT, 1); + + await client.getIdentityTokenInfos(TEST_IDENTITY, [tokenId]); + }); + }); + + describe('getIdentitiesTokenInfos()', () => { + it('should get token infos for multiple identities', async () => { + await client.getIdentitiesTokenInfos([TEST_IDENTITY], tokenContracts[0].contractId); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/protocol.spec.mjs b/packages/wasm-sdk/tests/functional/protocol.spec.mjs deleted file mode 100644 index b2d5d9a52e3..00000000000 --- a/packages/wasm-sdk/tests/functional/protocol.spec.mjs +++ /dev/null @@ -1,53 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('Protocol versions', function describeProtocolVersions() { - this.timeout(60000); - - let client; - let evonodeProTxHash; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - const builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - - // Get the proTxHash from the node status - const status = await client.getStatus(); - evonodeProTxHash = status.node.proTxHash; - }); - - after(() => { - if (client) { client.free(); } - }); - - it('fetches protocol upgrade state', async () => { - const state = await client.getProtocolVersionUpgradeState(); - expect(state).to.be.ok(); - }); - - it('fetches protocol upgrade state with proof', async () => { - const res = await client.getProtocolVersionUpgradeStateWithProofInfo(); - expect(res).to.be.ok(); - expect(res.data).to.be.ok(); - expect(res.proof).to.be.ok(); - expect(res.metadata).to.be.ok(); - }); - - it('lists protocol upgrade vote statuses', async () => { - // Use evonodeProTxHash if available, otherwise start from beginning with empty string - const startProTxHash = evonodeProTxHash || ''; - const res = await client.getProtocolVersionUpgradeVoteStatus(startProTxHash, 50); - expect(res).to.be.instanceOf(Map); - }); - - it('lists protocol upgrade vote statuses with proof', async () => { - // Use evonodeProTxHash if available, otherwise start from beginning with empty string - const startProTxHash = evonodeProTxHash || ''; - const res = await client.getProtocolVersionUpgradeVoteStatusWithProofInfo(startProTxHash, 50); - expect(res).to.be.ok(); - expect(res.data).to.be.instanceOf(Map); - expect(res.proof).to.be.ok(); - expect(res.metadata).to.be.ok(); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/protocol.spec.ts b/packages/wasm-sdk/tests/functional/protocol.spec.ts new file mode 100644 index 00000000000..da651ca6efd --- /dev/null +++ b/packages/wasm-sdk/tests/functional/protocol.spec.ts @@ -0,0 +1,62 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('Protocol', function describeProtocol() { + this.timeout(60000); + + let client: sdk.WasmSdk; + let evonodeProTxHash: string; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + const builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + + // Get the proTxHash from the node status + const status = await client.getStatus(); + evonodeProTxHash = status.node.proTxHash; + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getProtocolVersionUpgradeState()', () => { + it('should fetch protocol upgrade state', async () => { + const state = await client.getProtocolVersionUpgradeState(); + expect(state).to.be.ok(); + }); + }); + + describe('getProtocolVersionUpgradeStateWithProofInfo()', () => { + it('should fetch protocol upgrade state with proof', async () => { + const res = await client.getProtocolVersionUpgradeStateWithProofInfo(); + expect(res).to.be.ok(); + expect(res.data).to.be.ok(); + expect(res.proof).to.be.ok(); + expect(res.metadata).to.be.ok(); + }); + }); + + describe('getProtocolVersionUpgradeVoteStatus()', () => { + it('should list protocol upgrade vote statuses', async () => { + // Use evonodeProTxHash if available, otherwise start from beginning with empty string + const startProTxHash = evonodeProTxHash || ''; + const res = await client.getProtocolVersionUpgradeVoteStatus(startProTxHash, 50); + expect(res).to.be.instanceOf(Map); + }); + }); + + describe('getProtocolVersionUpgradeVoteStatusWithProofInfo()', () => { + it('should list protocol upgrade vote statuses with proof', async () => { + // Use evonodeProTxHash if available, otherwise start from beginning with empty string + const startProTxHash = evonodeProTxHash || ''; + const res = await client.getProtocolVersionUpgradeVoteStatusWithProofInfo(startProTxHash, 50); + expect(res).to.be.ok(); + expect(res.data).to.be.instanceOf(Map); + expect(res.proof).to.be.ok(); + expect(res.metadata).to.be.ok(); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/status.spec.mjs b/packages/wasm-sdk/tests/functional/status.spec.ts similarity index 51% rename from packages/wasm-sdk/tests/functional/status.spec.mjs rename to packages/wasm-sdk/tests/functional/status.spec.ts index 6b46f57d575..b0d11350197 100644 --- a/packages/wasm-sdk/tests/functional/status.spec.mjs +++ b/packages/wasm-sdk/tests/functional/status.spec.ts @@ -1,10 +1,11 @@ +import { expect } from './helpers/chai.ts'; import init, * as sdk from '../../dist/sdk.compressed.js'; -describe('Status endpoint', function describeBlock() { +describe('Status', function describeStatus() { this.timeout(30000); - let client; - let builder; + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; before(async () => { await init(); @@ -17,8 +18,10 @@ describe('Status endpoint', function describeBlock() { if (client) { client.free(); } }); - it('getStatus', async () => { - const status = await client.getStatus(); - expect(status).to.be.ok(); + describe('getStatus()', () => { + it('should get status', async () => { + const status = await client.getStatus(); + expect(status).to.be.ok(); + }); }); }); diff --git a/packages/wasm-sdk/tests/functional/system.spec.mjs b/packages/wasm-sdk/tests/functional/system.spec.mjs deleted file mode 100644 index 8d1e0597693..00000000000 --- a/packages/wasm-sdk/tests/functional/system.spec.mjs +++ /dev/null @@ -1,30 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('System info', function describeSystemInfo() { - this.timeout(60000); - - let client; - let builder; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('getCurrentQuorumsInfo', async () => { - const r = await client.getCurrentQuorumsInfo(); - expect(r).to.be.ok(); - }); - - it('getTotalCreditsInPlatform', async () => { - const r = await client.getTotalCreditsInPlatform(); - expect(typeof r).to.equal('bigint'); - expect(String(r)).to.match(/^\d+$/); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/system.spec.ts b/packages/wasm-sdk/tests/functional/system.spec.ts new file mode 100644 index 00000000000..8bc92446932 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/system.spec.ts @@ -0,0 +1,35 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('System', function describeSystem() { + this.timeout(60000); + + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getCurrentQuorumsInfo()', () => { + it('should get current quorums info', async () => { + const r = await client.getCurrentQuorumsInfo(); + expect(r).to.be.ok(); + }); + }); + + describe('getTotalCreditsInPlatform()', () => { + it('should get total credits in platform', async () => { + const r = await client.getTotalCreditsInPlatform(); + expect(typeof r).to.equal('bigint'); + expect(String(r)).to.match(/^\d+$/); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/token-pricing.spec.mjs b/packages/wasm-sdk/tests/functional/token-pricing.spec.mjs deleted file mode 100644 index dbc1f54d9e4..00000000000 --- a/packages/wasm-sdk/tests/functional/token-pricing.spec.mjs +++ /dev/null @@ -1,34 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Token pricing', function describeTokenPricing() { - this.timeout(60000); - - let client; - let builder; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('calculates token id and fetches price by contract', async () => { - const CONTRACT_ID = wasmFunctionalTestRequirements().tokenContracts[0].contractId; - const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(CONTRACT_ID, 0); - expect(tokenId).to.be.a('string'); - try { - const info = await client.getTokenPriceByContract(CONTRACT_ID, 0); - expect(info).to.be.ok(); - } catch (e) { - if (!(e.message.includes('No pricing schedule'))) { - throw e; - } - } - }); -}); diff --git a/packages/wasm-sdk/tests/functional/token-pricing.spec.ts b/packages/wasm-sdk/tests/functional/token-pricing.spec.ts new file mode 100644 index 00000000000..4c96ea6d70f --- /dev/null +++ b/packages/wasm-sdk/tests/functional/token-pricing.spec.ts @@ -0,0 +1,43 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('TokenPricing', function describeTokenPricing() { + this.timeout(60000); + + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('calculateTokenIdFromContract()', () => { + it('should calculate token id from contract', async () => { + const CONTRACT_ID = wasmFunctionalTestRequirements().tokenContracts[0].contractId; + const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(CONTRACT_ID, 0); + expect(tokenId).to.be.a('string'); + }); + }); + + describe('getTokenPriceByContract()', () => { + it('should fetch price by contract', async () => { + const CONTRACT_ID = wasmFunctionalTestRequirements().tokenContracts[0].contractId; + try { + const info = await client.getTokenPriceByContract(CONTRACT_ID, 0); + expect(info).to.be.ok(); + } catch (e) { + if (!(e.message.includes('No pricing schedule'))) { + throw e; + } + } + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/tokens.spec.mjs b/packages/wasm-sdk/tests/functional/tokens.spec.mjs deleted file mode 100644 index 29cc1e5ffd3..00000000000 --- a/packages/wasm-sdk/tests/functional/tokens.spec.mjs +++ /dev/null @@ -1,50 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Token queries', function describeTokenQueries() { - this.timeout(60000); - - const req = wasmFunctionalTestRequirements(); - const TEST_IDENTITY = req.identityId; - const TOKEN_CONTRACT = req.tokenContracts[0].contractId; - const TOKEN_CONTRACT_2 = TOKEN_CONTRACT; - const TOKEN_CONTRACT_3 = TOKEN_CONTRACT; - - let client; - let builder; - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { client.free(); } - }); - - it('getTokenTotalSupply using derived token id', async () => { - const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT, 0); - const total = await client.getTokenTotalSupply(tokenId); - // Returns total supply (might be 0 for tokens without minting) - expect(total).to.exist(); - }); - - it('getTokenStatuses for multiple tokens', async () => { - await client.getTokenStatuses([TOKEN_CONTRACT]); - }); - - it('getTokenDirectPurchasePrices', async () => { - await client.getTokenDirectPurchasePrices([TOKEN_CONTRACT_2]); - }); - - it('getTokenContractInfo', async () => { - await client.getTokenContractInfo(TOKEN_CONTRACT_3); - }); - - it('getTokenPerpetualDistributionLastClaim', async () => { - const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT_3, 0); - await client.getTokenPerpetualDistributionLastClaim(TEST_IDENTITY, tokenId); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/tokens.spec.ts b/packages/wasm-sdk/tests/functional/tokens.spec.ts new file mode 100644 index 00000000000..3068995aab4 --- /dev/null +++ b/packages/wasm-sdk/tests/functional/tokens.spec.ts @@ -0,0 +1,61 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('Tokens', function describeTokens() { + this.timeout(60000); + + const req = wasmFunctionalTestRequirements(); + const TEST_IDENTITY = req.identityId; + const TOKEN_CONTRACT = req.tokenContracts[0].contractId; + const TOKEN_CONTRACT_2 = TOKEN_CONTRACT; + const TOKEN_CONTRACT_3 = TOKEN_CONTRACT; + + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { client.free(); } + }); + + describe('getTokenTotalSupply()', () => { + it('should return token total supply', async () => { + const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT, 0); + const total = await client.getTokenTotalSupply(tokenId); + // Returns total supply (might be 0 for tokens without minting) + expect(total).to.exist(); + }); + }); + + describe('getTokenStatuses()', () => { + it('should return token statuses for multiple tokens', async () => { + await client.getTokenStatuses([TOKEN_CONTRACT]); + }); + }); + + describe('getTokenDirectPurchasePrices()', () => { + it('should return token direct purchase prices', async () => { + await client.getTokenDirectPurchasePrices([TOKEN_CONTRACT_2]); + }); + }); + + describe('getTokenContractInfo()', () => { + it('should return token contract info', async () => { + await client.getTokenContractInfo(TOKEN_CONTRACT_3); + }); + }); + + describe('getTokenPerpetualDistributionLastClaim()', () => { + it('should return token perpetual distribution last claim', async () => { + const tokenId = sdk.WasmSdk.calculateTokenIdFromContract(TOKEN_CONTRACT_3, 0); + await client.getTokenPerpetualDistributionLastClaim(TEST_IDENTITY, tokenId); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/transitions/contracts.spec.mjs b/packages/wasm-sdk/tests/functional/transitions/contracts.spec.ts similarity index 87% rename from packages/wasm-sdk/tests/functional/transitions/contracts.spec.mjs rename to packages/wasm-sdk/tests/functional/transitions/contracts.spec.ts index 348bed5147c..3cd36d15c26 100644 --- a/packages/wasm-sdk/tests/functional/transitions/contracts.spec.mjs +++ b/packages/wasm-sdk/tests/functional/transitions/contracts.spec.ts @@ -1,5 +1,6 @@ +import { expect } from '../helpers/chai.ts'; import init, * as sdk from '../../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.mjs'; +import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.ts'; /** * Contract state transition tests for wasm-sdk. @@ -16,7 +17,7 @@ import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtu describe('Contract State Transitions', function describeContractStateTransitions() { this.timeout(120000); - let client; + let client: sdk.WasmSdk; const testData = wasmFunctionalTestRequirements(); // Store contract ID for use across tests @@ -33,8 +34,8 @@ describe('Contract State Transitions', function describeContractStateTransitions if (client) { client.free(); } }); - describe('contractPublish', () => { - it('creates a new data contract', async () => { + describe('contractPublish()', () => { + it('should create a new data contract', async () => { // Contract operations require at least HIGH security level (key index 2) const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 2); @@ -59,15 +60,12 @@ describe('Contract State Transitions', function describeContractStateTransitions // Create the data contract // Note: We use nonce 0 as a placeholder - the actual contract ID will be // assigned by the SDK during publishing based on the current identity nonce - const dataContract = new sdk.DataContract( - testData.identityId, // owner ID - 0n, // placeholder nonce (SDK will assign actual ID during publish) - schema, // document schemas - undefined, // definitions (optional) - undefined, // tokens (optional) - true, // full validation - undefined, // platform version (use default) - ); + const dataContract = new sdk.DataContract({ + ownerId: testData.identityId, + identityNonce: 0n, // placeholder nonce (SDK will assign actual ID during publish) + schemas: schema, + fullValidation: true, + }); // Publish the contract and get the published version with actual ID const publishedContract = await client.contractPublish({ @@ -87,8 +85,8 @@ describe('Contract State Transitions', function describeContractStateTransitions }); }); - describe('contractUpdate', () => { - it('updates an existing data contract', async () => { + describe('contractUpdate()', () => { + it('should update an existing data contract', async () => { // Requires contract from previous test expect(createdContractId).to.exist(); @@ -111,7 +109,7 @@ describe('Contract State Transitions', function describeContractStateTransitions const currentVersion = existingContract.version; // Get existing schemas and add a new one - const existingSchemas = existingContract.getSchemas(); + const existingSchemas = existingContract.schemas; const updatedSchemas = { ...existingSchemas, task: { diff --git a/packages/wasm-sdk/tests/functional/transitions/documents.spec.mjs b/packages/wasm-sdk/tests/functional/transitions/documents.spec.ts similarity index 73% rename from packages/wasm-sdk/tests/functional/transitions/documents.spec.mjs rename to packages/wasm-sdk/tests/functional/transitions/documents.spec.ts index 5bfe5f19499..a6dc19c393d 100644 --- a/packages/wasm-sdk/tests/functional/transitions/documents.spec.mjs +++ b/packages/wasm-sdk/tests/functional/transitions/documents.spec.ts @@ -1,5 +1,6 @@ +import { expect } from '../helpers/chai.ts'; import init, * as sdk from '../../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.mjs'; +import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.ts'; /** * Document state transition tests for wasm-sdk. @@ -21,7 +22,7 @@ import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtu describe('Document State Transitions', function describeDocumentStateTransitions() { this.timeout(180000); - let client; + let client: sdk.WasmSdk; const testData = wasmFunctionalTestRequirements(); // Store contract and document IDs for use across tests @@ -40,8 +41,8 @@ describe('Document State Transitions', function describeDocumentStateTransitions if (client) { client.free(); } }); - describe('documentCreate', () => { - it('creates a new document', async () => { + describe('documentCreate()', () => { + it('should create a new document', async () => { // Document operations require at least HIGH security level (key index 2) for signing const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 2); @@ -49,18 +50,17 @@ describe('Document State Transitions', function describeDocumentStateTransitions // Using hash of salted domain label const saltedDomainHash = `${Date.now()}`.padStart(64, '0'); - const document = new sdk.Document( - { + const document = new sdk.Document({ + properties: { saltedDomainHash: Uint8Array.from( saltedDomainHash.match(/.{2}/g).map((byte) => parseInt(byte, 16)), ), }, - 'preorder', - BigInt(1), // Revision must be BigInt - testData.dpnsContractId, - testData.identityId, - undefined, // Document ID will be generated - ); + documentTypeName: 'preorder', + revision: 1, + dataContractId: testData.dpnsContractId, + ownerId: testData.identityId, + }); await client.documentCreate({ document, @@ -74,7 +74,7 @@ describe('Document State Transitions', function describeDocumentStateTransitions }); describe('Custom contract for mutable documents', () => { - it('creates a contract with mutable document types', async () => { + it('should create a contract with mutable document types', async () => { // Contract operations require at least HIGH security level (key index 2) const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 2); @@ -120,15 +120,12 @@ describe('Document State Transitions', function describeDocumentStateTransitions // Create the data contract // Note: We use nonce 0 as a placeholder - the actual contract ID will be // assigned by the SDK during publishing based on the current identity nonce - const dataContract = new sdk.DataContract( - testData.identityId, // owner ID - 0n, // placeholder nonce (SDK will assign actual ID during publish) - schema, // document schemas - undefined, // definitions (optional) - undefined, // tokens (optional) - true, // full validation - undefined, // platform version (use default) - ); + const dataContract = new sdk.DataContract({ + ownerId: testData.identityId, + identityNonce: 0n, // placeholder nonce (SDK will assign actual ID during publish) + schemas: schema, + fullValidation: true, + }); // Publish the contract and get the published version with actual ID const publishedContract = await client.contractPublish({ @@ -147,22 +144,21 @@ describe('Document State Transitions', function describeDocumentStateTransitions }); }); - describe('documentReplace', () => { - it('replaces an existing document', async () => { + describe('documentReplace()', () => { + it('should replace an existing document', async () => { // Requires contract from previous test expect(testContractId).to.exist(); const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 2); // First, create a mutable document - const document = new sdk.Document( - { message: 'Original message' }, - 'mutableNote', - BigInt(1), // Revision 1 for creation - testContractId, - testData.identityId, - undefined, // Document ID will be generated - ); + const document = new sdk.Document({ + properties: { message: 'Original message' }, + documentTypeName: 'mutableNote', + revision: 1, + dataContractId: testContractId, + ownerId: testData.identityId, + }); await client.documentCreate({ document, @@ -178,14 +174,14 @@ describe('Document State Transitions', function describeDocumentStateTransitions // Now replace the document with updated content // Increment revision to 2 for the update - const updatedDocument = new sdk.Document( - { message: 'Updated message' }, - 'mutableNote', - BigInt(2), // Revision 2 for replacement - testContractId, - testData.identityId, - mutableDocumentId, // Use the same document ID - ); + const updatedDocument = new sdk.Document({ + properties: { message: 'Updated message' }, + documentTypeName: 'mutableNote', + revision: 2, // Revision 2 for replacement + dataContractId: testContractId, + ownerId: testData.identityId, + id: mutableDocumentId, // Use the same document ID + }); await client.documentReplace({ document: updatedDocument, @@ -195,22 +191,21 @@ describe('Document State Transitions', function describeDocumentStateTransitions }); }); - describe('documentDelete', () => { - it('deletes a document', async () => { + describe('documentDelete()', () => { + it('should delete a document', async () => { // Requires contract from previous test expect(testContractId).to.exist(); const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 2); // First, create a document to delete - const document = new sdk.Document( - { message: 'Document to be deleted' }, - 'mutableNote', - BigInt(1), - testContractId, - testData.identityId, - undefined, - ); + const document = new sdk.Document({ + properties: { message: 'Document to be deleted' }, + documentTypeName: 'mutableNote', + revision: 1, + dataContractId: testContractId, + ownerId: testData.identityId, + }); await client.documentCreate({ document, @@ -238,22 +233,21 @@ describe('Document State Transitions', function describeDocumentStateTransitions }); }); - describe('documentTransfer', () => { - it('transfers document ownership', async () => { + describe('documentTransfer()', () => { + it('should transfer document ownership', async () => { // Requires contract from previous test expect(testContractId).to.exist(); const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 2); // First, create a transferable document - const document = new sdk.Document( - { name: 'Transferable Item' }, - 'transferableItem', - BigInt(1), - testContractId, - testData.identityId, - undefined, - ); + const document = new sdk.Document({ + properties: { name: 'Transferable Item' }, + documentTypeName: 'transferableItem', + revision: 1, + dataContractId: testContractId, + ownerId: testData.identityId, + }); await client.documentCreate({ document, @@ -268,14 +262,14 @@ describe('Document State Transitions', function describeDocumentStateTransitions await new Promise((resolve) => { setTimeout(resolve, 2000); }); // Create document object for transfer (revision incremented) - const documentForTransfer = new sdk.Document( - { name: 'Transferable Item' }, - 'transferableItem', - BigInt(2), // Increment revision for transfer - testContractId, - testData.identityId, - documentId, - ); + const documentForTransfer = new sdk.Document({ + properties: { name: 'Transferable Item' }, + documentTypeName: 'transferableItem', + revision: 2, // Increment revision for transfer + dataContractId: testContractId, + ownerId: testData.identityId, + id: documentId, + }); // Transfer the document to Identity 2 await client.documentTransfer({ diff --git a/packages/wasm-sdk/tests/functional/transitions/dpns.spec.mjs b/packages/wasm-sdk/tests/functional/transitions/dpns.spec.ts similarity index 63% rename from packages/wasm-sdk/tests/functional/transitions/dpns.spec.mjs rename to packages/wasm-sdk/tests/functional/transitions/dpns.spec.ts index d72daff7cc1..b353af4eb72 100644 --- a/packages/wasm-sdk/tests/functional/transitions/dpns.spec.mjs +++ b/packages/wasm-sdk/tests/functional/transitions/dpns.spec.ts @@ -1,5 +1,6 @@ +import { expect } from '../helpers/chai.ts'; import init, * as sdk from '../../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.mjs'; +import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.ts'; /** * DPNS state transition tests for wasm-sdk. @@ -21,7 +22,7 @@ import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtu describe('DPNS State Transitions', function describeDpnsStateTransitions() { this.timeout(180000); - let client; + let client: sdk.WasmSdk; const testData = wasmFunctionalTestRequirements(); // Store results for verification @@ -38,8 +39,8 @@ describe('DPNS State Transitions', function describeDpnsStateTransitions() { if (client) { client.free(); } }); - describe('dpnsRegisterName', () => { - it('registers a DPNS username', async () => { + describe('dpnsRegisterName()', () => { + it('should register a DPNS username', async () => { // DPNS registration requires HIGH security level (key index 2) const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 2); @@ -82,7 +83,7 @@ describe('DPNS State Transitions', function describeDpnsStateTransitions() { registeredUsername = result.fullDomainName; }); - it('resolves a registered username to identity', async () => { + it('should resolve a registered username to identity', async () => { // Skip if previous test didn't register a username if (!registeredUsername) { // eslint-disable-next-line no-console @@ -100,15 +101,15 @@ describe('DPNS State Transitions', function describeDpnsStateTransitions() { }); }); - describe('dpnsIsNameAvailable', () => { - it('returns true for an available name', async () => { + describe('dpnsIsNameAvailable()', () => { + it('should return true for an available name', async () => { const uniqueName = `available${Date.now()}`; const isAvailable = await client.dpnsIsNameAvailable(uniqueName); expect(isAvailable).to.be.true(); }); - it('returns false for a taken name', async () => { + it('should return false for a taken name', async () => { // Skip if previous test didn't register a username if (!registeredUsername) { // eslint-disable-next-line no-console @@ -127,38 +128,44 @@ describe('DPNS State Transitions', function describeDpnsStateTransitions() { }); }); - describe('DPNS utility functions', () => { - it('validates usernames correctly', async () => { - // Valid usernames - expect(sdk.WasmSdk.dpnsIsValidUsername('alice')).to.be.true(); - expect(sdk.WasmSdk.dpnsIsValidUsername('test-user')).to.be.true(); - expect(sdk.WasmSdk.dpnsIsValidUsername('user123')).to.be.true(); - - // Invalid usernames - expect(sdk.WasmSdk.dpnsIsValidUsername('ab')).to.be.false(); // too short - expect(sdk.WasmSdk.dpnsIsValidUsername('-invalid')).to.be.false(); // starts with hyphen - expect(sdk.WasmSdk.dpnsIsValidUsername('invalid-')).to.be.false(); // ends with hyphen - expect(sdk.WasmSdk.dpnsIsValidUsername('has space')).to.be.false(); // contains space + describe('DPNS Utility Functions', () => { + describe('dpnsIsValidUsername()', () => { + it('should validate usernames correctly', async () => { + // Valid usernames + expect(sdk.WasmSdk.dpnsIsValidUsername('alice')).to.be.true(); + expect(sdk.WasmSdk.dpnsIsValidUsername('test-user')).to.be.true(); + expect(sdk.WasmSdk.dpnsIsValidUsername('user123')).to.be.true(); + + // Invalid usernames + expect(sdk.WasmSdk.dpnsIsValidUsername('ab')).to.be.false(); // too short + expect(sdk.WasmSdk.dpnsIsValidUsername('-invalid')).to.be.false(); // starts with hyphen + expect(sdk.WasmSdk.dpnsIsValidUsername('invalid-')).to.be.false(); // ends with hyphen + expect(sdk.WasmSdk.dpnsIsValidUsername('has space')).to.be.false(); // contains space + }); }); - it('converts to homograph-safe characters', async () => { - const result = sdk.WasmSdk.dpnsConvertToHomographSafe('alice'); - expect(result).to.equal('a11ce'); // 'l' and 'i' become '1' + describe('dpnsConvertToHomographSafe()', () => { + it('should convert to homograph-safe characters', async () => { + const result = sdk.WasmSdk.dpnsConvertToHomographSafe('alice'); + expect(result).to.equal('a11ce'); // 'l' and 'i' become '1' - const result2 = sdk.WasmSdk.dpnsConvertToHomographSafe('bob'); - expect(result2).to.equal('b0b'); // 'o' becomes '0' + const result2 = sdk.WasmSdk.dpnsConvertToHomographSafe('bob'); + expect(result2).to.equal('b0b'); // 'o' becomes '0' + }); }); - it('identifies contested usernames', async () => { - // Contested usernames (3-19 chars, only [a-z01-] after normalization) - expect(sdk.WasmSdk.dpnsIsContestedUsername('abc')).to.be.true(); - expect(sdk.WasmSdk.dpnsIsContestedUsername('dash')).to.be.true(); + describe('dpnsIsContestedUsername()', () => { + it('should identify contested usernames', async () => { + // Contested usernames (3-19 chars, only [a-z01-] after normalization) + expect(sdk.WasmSdk.dpnsIsContestedUsername('abc')).to.be.true(); + expect(sdk.WasmSdk.dpnsIsContestedUsername('dash')).to.be.true(); - // Not contested - too long - expect(sdk.WasmSdk.dpnsIsContestedUsername('twentycharacterslongname')).to.be.false(); + // Not contested - too long + expect(sdk.WasmSdk.dpnsIsContestedUsername('twentycharacterslongname')).to.be.false(); - // Not contested - contains invalid characters after normalization - expect(sdk.WasmSdk.dpnsIsContestedUsername('test123')).to.be.false(); // contains '2' and '3' + // Not contested - contains invalid characters after normalization + expect(sdk.WasmSdk.dpnsIsContestedUsername('test123')).to.be.false(); // contains '2' and '3' + }); }); }); }); diff --git a/packages/wasm-sdk/tests/functional/transitions/identity.spec.mjs b/packages/wasm-sdk/tests/functional/transitions/identity.spec.ts similarity index 83% rename from packages/wasm-sdk/tests/functional/transitions/identity.spec.mjs rename to packages/wasm-sdk/tests/functional/transitions/identity.spec.ts index 5db1500d3cb..b2ef718b3c0 100644 --- a/packages/wasm-sdk/tests/functional/transitions/identity.spec.mjs +++ b/packages/wasm-sdk/tests/functional/transitions/identity.spec.ts @@ -1,5 +1,6 @@ +import { expect } from '../helpers/chai.ts'; import init, * as sdk from '../../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.mjs'; +import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.ts'; /** * Identity state transition tests for wasm-sdk. @@ -22,7 +23,7 @@ import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtu describe('Identity State Transitions', function describeIdentityStateTransitions() { this.timeout(60000); - let client; + let client: sdk.WasmSdk; const testData = wasmFunctionalTestRequirements(); before(async () => { @@ -42,13 +43,13 @@ describe('Identity State Transitions', function describeIdentityStateTransitions // Ignore errors from double-free or borrow issues // These can happen if a test timed out with pending operations // eslint-disable-next-line no-console - console.log('Note: client.free() error (may be harmless):', err.message); + console.log('Note: client.free() error (may be harmless):', (err as Error).message); } } }); - describe('identityCreditTransfer', () => { - it('transfers credits between identities', async () => { + describe('identityCreditTransfer()', () => { + it('should transfer credits between identities', async () => { // Identity 1 transfers credits to Identity 2 // Key index 3 is the TRANSFER purpose key (ECDSA_HASH160) const { signer } = createTestSignerAndKey(sdk, 1, 3); @@ -73,8 +74,8 @@ describe('Identity State Transitions', function describeIdentityStateTransitions }); }); - describe('identityUpdate', () => { - it('adds a new public key to identity', async () => { + describe('identityUpdate()', () => { + it('should add a new public key to identity', async () => { // Wait for previous operations to be fully processed await new Promise((resolve) => { setTimeout(resolve, 2000); }); @@ -86,13 +87,13 @@ describe('Identity State Transitions', function describeIdentityStateTransitions expect(identity).to.exist(); // Get the current number of public keys - const publicKeysBefore = identity.getPublicKeys(); + const publicKeysBefore = identity.publicKeys; const keyCountBefore = publicKeysBefore.length; // Generate a new random key pair for the new public key const newKeyPair = sdk.WasmSdk.generateKeyPair('testnet'); const newPublicKeyData = Uint8Array.from( - newKeyPair.publicKey.match(/.{2}/g).map((byte) => parseInt(byte, 16)), + newKeyPair.publicKey.match(/.{2}/g).map((byte: string) => parseInt(byte, 16)), ); // IMPORTANT: The signer must also have the new key's private key @@ -101,16 +102,14 @@ describe('Identity State Transitions', function describeIdentityStateTransitions signer.addKey(newPrivateKey); // Create a new public key to add - const newPublicKeyInCreation = new sdk.IdentityPublicKeyInCreation( - 0, // keyId - will be overwritten by SDK to next available - 'AUTHENTICATION', - 'MEDIUM', // MEDIUM so it can be disabled later if needed - 'ECDSA_SECP256K1', - false, // read only - newPublicKeyData, - undefined, // signature - undefined, // contract bounds - ); + const newPublicKeyInCreation = new sdk.IdentityPublicKeyInCreation({ + keyId: 0, // will be overwritten by SDK to next available + purpose: 'AUTHENTICATION', + securityLevel: 'MEDIUM', // MEDIUM so it can be disabled later if needed + keyType: 'ECDSA_SECP256K1', + isReadOnly: false, + data: newPublicKeyData, + }); await client.identityUpdate({ identity, @@ -123,11 +122,11 @@ describe('Identity State Transitions', function describeIdentityStateTransitions // Verify the update by fetching the identity again const updatedIdentity = await client.getIdentity(testData.identityId); - const publicKeysAfter = updatedIdentity.getPublicKeys(); + const publicKeysAfter = updatedIdentity.publicKeys; expect(publicKeysAfter.length).to.equal(keyCountBefore + 1); }); - it('disables a public key on identity', async () => { + it('should disable a public key on identity', async () => { // Identity update requires MASTER key (key index 0) const { signer } = createTestSignerAndKey(sdk, 1, 0); @@ -136,7 +135,7 @@ describe('Identity State Transitions', function describeIdentityStateTransitions expect(identity).to.exist(); // Find a key that can be disabled (MEDIUM or lower security level, not master) - const publicKeys = identity.getPublicKeys(); + const { publicKeys } = identity; const keyToDisable = publicKeys.find( (key) => key.securityLevel === 'MEDIUM' && key.purpose === 'AUTHENTICATION', ); @@ -157,7 +156,7 @@ describe('Identity State Transitions', function describeIdentityStateTransitions // Verify the key was disabled by fetching the identity again const updatedIdentity = await client.getIdentity(testData.identityId); - const disabledKey = updatedIdentity.getPublicKeys() + const disabledKey = updatedIdentity.publicKeys .find((key) => key.keyId === keyIdToDisable); // The key should still exist but have a disabledAt timestamp @@ -166,8 +165,8 @@ describe('Identity State Transitions', function describeIdentityStateTransitions }); }); - describe('identityWithdrawal', () => { - it('withdraws credits from platform', async () => { + describe('identityCreditWithdrawal()', () => { + it('should withdraw credits from platform', async () => { // Use the TRANSFER key (index 3) for withdrawal const { signer } = createTestSignerAndKey(sdk, 1, 3); @@ -195,8 +194,8 @@ describe('Identity State Transitions', function describeIdentityStateTransitions }); }); - describe('identityTopUp', () => { - it.skip('tops up identity balance', async () => { + describe('identityTopUp()', () => { + it.skip('should top up identity balance', async () => { // This test requires an asset lock proof which needs: // 1. A funded wallet with Dash // 2. Creating an asset lock transaction on core chain @@ -205,8 +204,8 @@ describe('Identity State Transitions', function describeIdentityStateTransitions }); }); - describe('identityCreate', () => { - it.skip('creates a new identity', async () => { + describe('identityCreate()', () => { + it.skip('should create a new identity', async () => { // This test requires an asset lock proof from core blockchain // Similar complexity to identityTopUp }); diff --git a/packages/wasm-sdk/tests/functional/transitions/key-generation.spec.mjs b/packages/wasm-sdk/tests/functional/transitions/key-generation.spec.mjs deleted file mode 100644 index d9fb27d0e25..00000000000 --- a/packages/wasm-sdk/tests/functional/transitions/key-generation.spec.mjs +++ /dev/null @@ -1,92 +0,0 @@ -import init, * as sdk from '../../../dist/sdk.compressed.js'; -import { createTestSignerAndKey } from '../fixtures/requiredTestData.mjs'; - -/** - * Key generation tests for wasm-sdk. - * - * These tests verify that deterministic key generation works correctly. - * Keys are generated using seeded RNG to match the keys created in genesis state. - * - * Key indices: - * - 0: MASTER level AUTHENTICATION key (ECDSA_SECP256K1) - * - 1: CRITICAL level AUTHENTICATION key (ECDSA_SECP256K1) - * - 2: HIGH level AUTHENTICATION key (ECDSA_SECP256K1) - * - 3: CRITICAL level TRANSFER key (ECDSA_HASH160) - for credit transfers - */ - -describe('Key Generation Tests', function describeKeyGeneration() { - this.timeout(30000); - - before(async () => { - await init(); - }); - - describe('generateTestIdentityKeys', () => { - it('generates deterministic keys for seed 1', () => { - const keys = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); - - expect(keys).to.be.an('array'); - expect(keys.length).to.equal(4); // 3 authentication keys + 1 transfer key - - // serde_wasm_bindgen returns Maps, so use .get() to access properties - // Check structure of first key - expect(keys[0].has('keyId')).to.be.true(); - expect(keys[0].has('privateKeyHex')).to.be.true(); - expect(keys[0].has('publicKeyData')).to.be.true(); - expect(keys[0].has('keyType')).to.be.true(); - expect(keys[0].has('purpose')).to.be.true(); - expect(keys[0].has('securityLevel')).to.be.true(); - - // Verify key types for authentication keys (ECDSA_SECP256K1) - expect(keys[0].get('keyType')).to.equal('ECDSA_SECP256K1'); - expect(keys[1].get('keyType')).to.equal('ECDSA_SECP256K1'); - expect(keys[2].get('keyType')).to.equal('ECDSA_SECP256K1'); - // Key 3 is the transfer key (ECDSA_HASH160) - expect(keys[3].get('keyType')).to.equal('ECDSA_HASH160'); - - // Verify purposes - expect(keys[0].get('purpose')).to.equal('AUTHENTICATION'); - expect(keys[1].get('purpose')).to.equal('AUTHENTICATION'); - expect(keys[2].get('purpose')).to.equal('AUTHENTICATION'); - expect(keys[3].get('purpose')).to.equal('TRANSFER'); - - // Verify security levels - expect(keys[0].get('securityLevel')).to.equal('MASTER'); - expect(keys[1].get('securityLevel')).to.equal('CRITICAL'); - expect(keys[2].get('securityLevel')).to.equal('HIGH'); - expect(keys[3].get('securityLevel')).to.equal('CRITICAL'); - }); - - it('generates different keys for different seeds', () => { - const keys1 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); - const keys2 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(2)); - - expect(keys1[0].get('privateKeyHex')).to.not.equal(keys2[0].get('privateKeyHex')); - expect(keys1[0].get('publicKeyData')).to.not.equal(keys2[0].get('publicKeyData')); - }); - - it('generates same keys for same seed (deterministic)', () => { - const keys1 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); - const keys2 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); - - expect(keys1[0].get('privateKeyHex')).to.equal(keys2[0].get('privateKeyHex')); - expect(keys1[0].get('publicKeyData')).to.equal(keys2[0].get('publicKeyData')); - }); - }); - - describe('createTestSignerAndKey', () => { - it('creates a signer and identity key', () => { - const { signer, identityKey, keyInfo } = createTestSignerAndKey(sdk, 1, 2); - - expect(signer).to.exist(); - expect(identityKey).to.exist(); - expect(keyInfo).to.exist(); - - // Check signer has the key - expect(signer.keyCount).to.equal(1); - - // Check identity key properties (keyInfo is a Map) - expect(identityKey.keyId).to.equal(keyInfo.get('keyId')); - }); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/transitions/key-generation.spec.ts b/packages/wasm-sdk/tests/functional/transitions/key-generation.spec.ts new file mode 100644 index 00000000000..0c269c0289a --- /dev/null +++ b/packages/wasm-sdk/tests/functional/transitions/key-generation.spec.ts @@ -0,0 +1,94 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; +import { createTestSignerAndKey } from '../fixtures/requiredTestData.ts'; + +/** + * Key generation tests for wasm-sdk. + * + * These tests verify that deterministic key generation works correctly. + * Keys are generated using seeded RNG to match the keys created in genesis state. + * + * Key indices: + * - 0: MASTER level AUTHENTICATION key (ECDSA_SECP256K1) + * - 1: CRITICAL level AUTHENTICATION key (ECDSA_SECP256K1) + * - 2: HIGH level AUTHENTICATION key (ECDSA_SECP256K1) + * - 3: CRITICAL level TRANSFER key (ECDSA_HASH160) - for credit transfers + */ + +describe('Key Generation', function describeKeyGeneration() { + this.timeout(30000); + + before(async () => { + await init(); + }); + + describe('generateTestIdentityKeys()', () => { + it('should generate deterministic keys for seed 1', () => { + const keys = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); + + expect(keys).to.be.an('array'); + expect(keys.length).to.equal(4); // 3 authentication keys + 1 transfer key + + // serde_wasm_bindgen with serialize_maps_as_objects(true) returns plain objects + // Check structure of first key + expect(keys[0].keyId).to.exist(); + expect(keys[0].privateKeyHex).to.exist(); + expect(keys[0].publicKeyData).to.exist(); + expect(keys[0].keyType).to.exist(); + expect(keys[0].purpose).to.exist(); + expect(keys[0].securityLevel).to.exist(); + + // Verify key types for authentication keys (ECDSA_SECP256K1) + expect(keys[0].keyType).to.equal('ECDSA_SECP256K1'); + expect(keys[1].keyType).to.equal('ECDSA_SECP256K1'); + expect(keys[2].keyType).to.equal('ECDSA_SECP256K1'); + // Key 3 is the transfer key (ECDSA_HASH160) + expect(keys[3].keyType).to.equal('ECDSA_HASH160'); + + // Verify purposes + expect(keys[0].purpose).to.equal('AUTHENTICATION'); + expect(keys[1].purpose).to.equal('AUTHENTICATION'); + expect(keys[2].purpose).to.equal('AUTHENTICATION'); + expect(keys[3].purpose).to.equal('TRANSFER'); + + // Verify security levels + expect(keys[0].securityLevel).to.equal('MASTER'); + expect(keys[1].securityLevel).to.equal('CRITICAL'); + expect(keys[2].securityLevel).to.equal('HIGH'); + expect(keys[3].securityLevel).to.equal('CRITICAL'); + }); + + it('should generate different keys for different seeds', () => { + const keys1 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); + const keys2 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(2)); + + expect(keys1[0].privateKeyHex).to.not.equal(keys2[0].privateKeyHex); + expect(keys1[0].publicKeyData).to.not.equal(keys2[0].publicKeyData); + }); + + it('should generate same keys for same seed (deterministic)', () => { + const keys1 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); + const keys2 = sdk.WasmSdk.generateTestIdentityKeys(BigInt(1)); + + expect(keys1[0].privateKeyHex).to.equal(keys2[0].privateKeyHex); + expect(keys1[0].publicKeyData).to.equal(keys2[0].publicKeyData); + }); + }); + + describe('createTestSignerAndKey()', () => { + it('should create a signer and identity key', () => { + const { signer, identityKey, keyInfo } = createTestSignerAndKey(sdk, 1, 2); + + expect(signer).to.exist(); + expect(identityKey).to.exist(); + expect(keyInfo).to.exist(); + + // Check signer has the key + expect(signer.keyCount).to.equal(1); + + // Check identity key properties (keyInfo is a plain object) + // keyInfo.keyId might be BigInt from serialization, convert for comparison + expect(identityKey.keyId).to.equal(Number(keyInfo.keyId)); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/transitions/tokens.spec.mjs b/packages/wasm-sdk/tests/functional/transitions/tokens.spec.ts similarity index 89% rename from packages/wasm-sdk/tests/functional/transitions/tokens.spec.mjs rename to packages/wasm-sdk/tests/functional/transitions/tokens.spec.ts index 24946e3920c..9b24e120418 100644 --- a/packages/wasm-sdk/tests/functional/transitions/tokens.spec.mjs +++ b/packages/wasm-sdk/tests/functional/transitions/tokens.spec.ts @@ -1,5 +1,6 @@ +import { expect } from '../helpers/chai.ts'; import init, * as sdk from '../../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.mjs'; +import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtures/requiredTestData.ts'; /** * Token state transition tests for wasm-sdk. @@ -26,7 +27,7 @@ import { wasmFunctionalTestRequirements, createTestSignerAndKey } from '../fixtu describe('Token State Transitions', function describeTokenStateTransitions() { this.timeout(120000); - let client; + let client: sdk.WasmSdk; const testData = wasmFunctionalTestRequirements(); before(async () => { @@ -40,8 +41,8 @@ describe('Token State Transitions', function describeTokenStateTransitions() { if (client) { client.free(); } }); - describe('tokenTransfer', () => { - it('transfers tokens between identities', async () => { + describe('tokenTransfer()', () => { + it('should transfer tokens between identities', async () => { // Identity 1 transfers to Identity 3 (which exists in genesis state) // Identity 1 has 100 tokens on TOKEN_0 // Token operations require CRITICAL security level (key index 1) @@ -64,8 +65,8 @@ describe('Token State Transitions', function describeTokenStateTransitions() { }); }); - describe('tokenBurn', () => { - it('burns tokens via group action', async () => { + describe('tokenBurn()', () => { + it('should burn tokens via group action', async () => { // Token 2 has group burning with Group 2 (Identity 1 and 3, required power = 1) // Identity 1 has power 1, so can burn alone as proposer // Token operations require CRITICAL security level (key index 1) @@ -90,8 +91,8 @@ describe('Token State Transitions', function describeTokenStateTransitions() { }); }); - describe('tokenMint', () => { - it('mints tokens via group action', async () => { + describe('tokenMint()', () => { + it('should mint tokens via group action', async () => { // Token 0 has group minting with Group 0 (Identity 1 and 2, required power = 1) // Identity 1 has power 1, so can mint alone as proposer // Token operations require CRITICAL security level (key index 1) @@ -117,8 +118,8 @@ describe('Token State Transitions', function describeTokenStateTransitions() { }); }); - describe('tokenFreeze', () => { - it('freezes an identity token balance', async () => { + describe('tokenFreeze()', () => { + it('should freeze an identity token balance', async () => { // Contract owner (Identity 1) can freeze tokens // Token operations require CRITICAL security level (key index 1) const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 1); @@ -136,8 +137,8 @@ describe('Token State Transitions', function describeTokenStateTransitions() { }); }); - describe('tokenUnfreeze', () => { - it('unfreezes an identity token balance', async () => { + describe('tokenUnfreeze()', () => { + it('should unfreeze an identity token balance', async () => { // Wait for previous freeze to be processed await new Promise((resolve) => { setTimeout(resolve, 2000); }); @@ -159,8 +160,8 @@ describe('Token State Transitions', function describeTokenStateTransitions() { }); }); - describe('tokenEmergencyAction', () => { - it('pauses a token', async () => { + describe('tokenEmergencyAction()', () => { + it('should pause a token', async () => { // Contract owner (Identity 1) can pause/resume tokens // Token operations require CRITICAL security level (key index 1) const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 1); @@ -177,7 +178,7 @@ describe('Token State Transitions', function describeTokenStateTransitions() { expect(result).to.exist(); }); - it('resumes a paused token', async () => { + it('should resume a paused token', async () => { // Wait for previous pause to be processed await new Promise((resolve) => { setTimeout(resolve, 2000); }); @@ -198,8 +199,8 @@ describe('Token State Transitions', function describeTokenStateTransitions() { }); }); - describe('tokenSetPrice', () => { - it('sets a direct purchase price for tokens', async () => { + describe('tokenSetPrice()', () => { + it('should set a direct purchase price for tokens', async () => { // Contract owner (Identity 1) can set token prices // Token operations require CRITICAL security level (key index 1) const { signer, identityKey } = createTestSignerAndKey(sdk, 1, 1); diff --git a/packages/wasm-sdk/tests/functional/utilities.spec.mjs b/packages/wasm-sdk/tests/functional/utilities.spec.mjs deleted file mode 100644 index 81644e183a6..00000000000 --- a/packages/wasm-sdk/tests/functional/utilities.spec.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('Utilities', function describeUtilities() { - before(async () => { await init(); }); - this.timeout(60000); - - it('prefetches trusted quorums for local', async () => { - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - }); - - it('testSerialization method (if present) returns object', async () => { - const builder = sdk.WasmSdkBuilder.local(); - const client = await builder.build(); - if (typeof client.testSerialization === 'function') { - const res = client.testSerialization('simple'); - expect(res).to.be.an('object'); - } - client.free(); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/utilities.spec.ts b/packages/wasm-sdk/tests/functional/utilities.spec.ts new file mode 100644 index 00000000000..9221098fbad --- /dev/null +++ b/packages/wasm-sdk/tests/functional/utilities.spec.ts @@ -0,0 +1,26 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('Utilities', function describeUtilities() { + this.timeout(60000); + + before(async () => { await init(); }); + + describe('prefetchTrustedQuorumsLocal()', () => { + it('should prefetch trusted quorums for local', async () => { + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + }); + }); + + describe('testSerialization()', () => { + it('should return object from testSerialization method (if present)', async () => { + const builder = sdk.WasmSdkBuilder.local(); + const client = await builder.build(); + if (typeof client.testSerialization === 'function') { + const res = client.testSerialization('simple'); + expect(res).to.be.an('object'); + } + client.free(); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/functional/voting.spec.mjs b/packages/wasm-sdk/tests/functional/voting.spec.mjs deleted file mode 100644 index 11389aa6258..00000000000 --- a/packages/wasm-sdk/tests/functional/voting.spec.mjs +++ /dev/null @@ -1,46 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.mjs'; - -describe('Contested resources & voting', function describeContestedResources() { - this.timeout(60000); - - let client; - let builder; - const { dpnsContractId, dpnsDomain } = wasmFunctionalTestRequirements(); - - before(async () => { - await init(); - await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); - builder = sdk.WasmSdkBuilder.localTrusted(); - client = await builder.build(); - }); - - after(() => { - if (client) { - client.free(); - } - }); - - it('lists contested resources and vote state', async () => { - const DPNS_CONTRACT = dpnsContractId; - const PARENT = dpnsDomain.parent; - const LABEL = dpnsDomain.label; - - await client.getContestedResources({ - dataContractId: DPNS_CONTRACT, - documentTypeName: 'domain', - indexName: 'parentNameAndLabel', - orderAscending: true, - }); - - await client.getContestedResourceVoteState({ - dataContractId: DPNS_CONTRACT, - documentTypeName: 'domain', - indexName: 'parentNameAndLabel', - indexValues: [PARENT, LABEL], - resultType: 'documents', - limit: 50, - includeLockedAndAbstaining: true, - }); - }); -}); diff --git a/packages/wasm-sdk/tests/functional/voting.spec.ts b/packages/wasm-sdk/tests/functional/voting.spec.ts new file mode 100644 index 00000000000..0b85960330f --- /dev/null +++ b/packages/wasm-sdk/tests/functional/voting.spec.ts @@ -0,0 +1,54 @@ +import init, * as sdk from '../../dist/sdk.compressed.js'; +import { wasmFunctionalTestRequirements } from './fixtures/requiredTestData.ts'; + +describe('Voting', function describeVoting() { + this.timeout(60000); + + let client: sdk.WasmSdk; + let builder: sdk.WasmSdkBuilder; + const { dpnsContractId, dpnsDomain } = wasmFunctionalTestRequirements(); + + before(async () => { + await init(); + await sdk.WasmSdk.prefetchTrustedQuorumsLocal(); + builder = sdk.WasmSdkBuilder.localTrusted(); + client = await builder.build(); + }); + + after(() => { + if (client) { + client.free(); + } + }); + + describe('getContestedResources()', () => { + it('should list contested resources', async () => { + const DPNS_CONTRACT = dpnsContractId; + + await client.getContestedResources({ + dataContractId: DPNS_CONTRACT, + documentTypeName: 'domain', + indexName: 'parentNameAndLabel', + orderAscending: true, + }); + }); + }); + + describe('getContestedResourceVoteState()', () => { + it('should get contested resource vote state', async () => { + const DPNS_CONTRACT = dpnsContractId; + const PARENT = dpnsDomain.parent; + const LABEL = dpnsDomain.label; + + await client.getContestedResourceVoteState({ + dataContractId: DPNS_CONTRACT, + documentTypeName: 'domain', + indexName: 'parentNameAndLabel', + indexValues: [PARENT, LABEL], + resultType: 'documents', + limit: 50, + includeLockedAndAbstaining: true, + }); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/karma/karma.conf.cjs b/packages/wasm-sdk/tests/karma/karma.conf.cjs index 98bceeb9526..b8ca6eeed24 100644 --- a/packages/wasm-sdk/tests/karma/karma.conf.cjs +++ b/packages/wasm-sdk/tests/karma/karma.conf.cjs @@ -6,11 +6,11 @@ module.exports = (config) => { files: [ // Load bootstrap first to initialize chai and globals '../bootstrap.cjs', - '../unit/**/*.spec.mjs', + '../unit/**/*.spec.ts', ], preprocessors: { '../bootstrap.cjs': ['webpack'], - '../unit/**/*.spec.mjs': ['webpack'], + '../unit/**/*.spec.ts': ['webpack'], }, }); }; diff --git a/packages/wasm-sdk/tests/karma/karma.functional.conf.cjs b/packages/wasm-sdk/tests/karma/karma.functional.conf.cjs index ec63d75de67..ee53fd8a02e 100644 --- a/packages/wasm-sdk/tests/karma/karma.functional.conf.cjs +++ b/packages/wasm-sdk/tests/karma/karma.functional.conf.cjs @@ -6,11 +6,11 @@ module.exports = (config) => { files: [ // Load functional bootstrap first (sets TLS override and initializes chai/globals) '../functional-bootstrap.cjs', - '../functional/**/*.spec.mjs', + '../functional/**/*.spec.ts', ], preprocessors: { '../functional-bootstrap.cjs': ['webpack'], - '../functional/**/*.spec.mjs': ['webpack'], + '../functional/**/*.spec.ts': ['webpack'], }, }); }; diff --git a/packages/wasm-sdk/tests/karma/options.cjs b/packages/wasm-sdk/tests/karma/options.cjs index bcc05f28d0b..5bbc1b27841 100644 --- a/packages/wasm-sdk/tests/karma/options.cjs +++ b/packages/wasm-sdk/tests/karma/options.cjs @@ -1,4 +1,4 @@ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable import-x/no-extraneous-dependencies */ const webpack = require('webpack'); const karmaMocha = require('karma-mocha'); const karmaMochaReporter = require('karma-mocha-reporter'); @@ -12,6 +12,21 @@ module.exports = { webpack: { mode: 'development', devtool: 'eval', + module: { + rules: [ + { + test: /\.ts$/, + use: { + loader: 'ts-loader', + options: { + transpileOnly: true, + configFile: require.resolve('../tsconfig.json'), + }, + }, + exclude: /node_modules/, + }, + ], + }, // No special wasm handling needed (WASM is inlined in dist/sdk.js) plugins: [ new webpack.ProvidePlugin({ @@ -20,7 +35,7 @@ module.exports = { }), ], resolve: { - extensions: ['.mjs', '.js'], + extensions: ['.ts', '.mjs', '.js'], fallback: { fs: false, path: require.resolve('path-browserify'), diff --git a/packages/wasm-sdk/tests/tsconfig.json b/packages/wasm-sdk/tests/tsconfig.json new file mode 100644 index 00000000000..ab50285d990 --- /dev/null +++ b/packages/wasm-sdk/tests/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "declaration": false, + "noEmit": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "types": ["mocha", "chai", "node"], + "baseUrl": ".", + "paths": { + "@dashevo/wasm-sdk": ["../dist/sdk.d.ts"] + } + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "node_modules", + "karma" + ] +} diff --git a/packages/wasm-sdk/tests/unit/address-validation.spec.mjs b/packages/wasm-sdk/tests/unit/address-validation.spec.mjs deleted file mode 100644 index 93ff6f3bc7a..00000000000 --- a/packages/wasm-sdk/tests/unit/address-validation.spec.mjs +++ /dev/null @@ -1,26 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('Address validation', () => { - before(async () => { - await init(); - }); - - it('validates known malformed prefixes correctly', () => { - const mainnetAddress = 'XdRhagDMpNbHZSvgMXqkcCCWmrDYYty5Nh'; - const testnetAddress = 'yXdRhagDMpNbHZSvgMXqkcCCWmrDYYty5Nh'; - expect(sdk.WasmSdk.validateAddress(mainnetAddress, 'mainnet')).to.be.a('boolean'); - expect(sdk.WasmSdk.validateAddress(testnetAddress, 'testnet')).to.be.a('boolean'); - }); - - it('validates generated addresses for each network', () => { - const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; - const kM = sdk.WasmSdk.deriveKeyFromSeedWithPath({ - mnemonic, passphrase: null, path: "m/44'/5'/0'/0/0", network: 'mainnet', - }); - const kT = sdk.WasmSdk.deriveKeyFromSeedWithPath({ - mnemonic, passphrase: null, path: "m/44'/1'/0'/0/0", network: 'testnet', - }); - expect(sdk.WasmSdk.validateAddress(kM.address, 'mainnet')).to.equal(true); - expect(sdk.WasmSdk.validateAddress(kT.address, 'testnet')).to.equal(true); - }); -}); diff --git a/packages/wasm-sdk/tests/unit/address-validation.spec.ts b/packages/wasm-sdk/tests/unit/address-validation.spec.ts new file mode 100644 index 00000000000..b881c14b951 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/address-validation.spec.ts @@ -0,0 +1,29 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('Address Validation', () => { + before(async () => { + await init(); + }); + + describe('validateAddress()', () => { + it('should validate known malformed prefixes correctly', () => { + const mainnetAddress = 'XdRhagDMpNbHZSvgMXqkcCCWmrDYYty5Nh'; + const testnetAddress = 'yXdRhagDMpNbHZSvgMXqkcCCWmrDYYty5Nh'; + expect(sdk.WasmSdk.validateAddress(mainnetAddress, 'mainnet')).to.be.a('boolean'); + expect(sdk.WasmSdk.validateAddress(testnetAddress, 'testnet')).to.be.a('boolean'); + }); + + it('should validate generated addresses for each network', () => { + const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; + const kM = sdk.WasmSdk.deriveKeyFromSeedWithPath({ + mnemonic, passphrase: null, path: "m/44'/5'/0'/0/0", network: 'mainnet', + }); + const kT = sdk.WasmSdk.deriveKeyFromSeedWithPath({ + mnemonic, passphrase: null, path: "m/44'/1'/0'/0/0", network: 'testnet', + }); + expect(sdk.WasmSdk.validateAddress(kM.address, 'mainnet')).to.equal(true); + expect(sdk.WasmSdk.validateAddress(kT.address, 'testnet')).to.equal(true); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/api-availability.spec.mjs b/packages/wasm-sdk/tests/unit/api-availability.spec.mjs deleted file mode 100644 index a6e9c4a7d38..00000000000 --- a/packages/wasm-sdk/tests/unit/api-availability.spec.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('API availability (exports and methods)', () => { - before(async () => { - await init(); - }); - it('query methods are available on WasmSdk instance', () => { - const instanceFns = [ - // Identity - 'getIdentity', 'getIdentityUnproved', 'getIdentityKeys', 'getIdentityNonce', 'getIdentityContractNonce', 'getIdentityBalance', 'getIdentitiesBalances', 'getIdentityBalanceAndRevision', 'getIdentityByPublicKeyHash', 'getIdentityByNonUniquePublicKeyHash', 'getIdentitiesContractKeys', 'getIdentityTokenBalances', 'getIdentityTokenInfos', 'getIdentitiesTokenInfos', - // Documents / contracts - 'getDocuments', 'getDocument', 'getDataContract', 'getDataContractHistory', 'getDataContracts', - // Tokens - 'getTokenStatuses', 'getTokenDirectPurchasePrices', 'getTokenContractInfo', 'getTokenPerpetualDistributionLastClaim', 'getTokenTotalSupply', - // Epochs / System / Protocol - 'getEpochsInfo', 'getFinalizedEpochInfos', 'getCurrentEpoch', 'getEvonodesProposedEpochBlocksByIds', 'getEvonodesProposedEpochBlocksByRange', 'getProtocolVersionUpgradeState', 'getProtocolVersionUpgradeVoteStatus', 'getStatus', 'getCurrentQuorumsInfo', 'getTotalCreditsInPlatform', 'getPrefundedSpecializedBalance', 'getPathElements', - // Voting / Groups - 'getContestedResources', 'getContestedResourceVoteState', 'getContestedResourceVotersForIdentity', 'getContestedResourceIdentityVotes', 'getVotePollsByEndDate', 'getGroupInfo', 'getGroupInfos', 'getGroupMembers', 'getIdentityGroups', 'getGroupActions', 'getGroupActionSigners', 'getGroupsDataContracts', - // DPNS queries - 'dpnsRegisterName', 'dpnsIsNameAvailable', 'dpnsResolveName', 'getDpnsUsernameByName', 'getDpnsUsernames', 'getDpnsUsername', - // Utils - 'waitForStateTransitionResult', - ]; - for (const fn of instanceFns) { - expect(typeof sdk.WasmSdk.prototype[fn]).to.be.oneOf(['function', 'undefined']); - } - }); -}); diff --git a/packages/wasm-sdk/tests/unit/api-availability.spec.ts b/packages/wasm-sdk/tests/unit/api-availability.spec.ts new file mode 100644 index 00000000000..8db9f401ec8 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/api-availability.spec.ts @@ -0,0 +1,80 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('API Availability', () => { + before(async () => { + await init(); + }); + + describe('WasmSdk.prototype', () => { + it('should have query methods available on WasmSdk instance', () => { + const instanceFns = [ + // Identity + 'getIdentity', + 'getIdentityUnproved', + 'getIdentityKeys', + 'getIdentityNonce', + 'getIdentityContractNonce', + 'getIdentityBalance', + 'getIdentitiesBalances', + 'getIdentityBalanceAndRevision', + 'getIdentityByPublicKeyHash', + 'getIdentityByNonUniquePublicKeyHash', + 'getIdentitiesContractKeys', + 'getIdentityTokenBalances', + 'getIdentityTokenInfos', + 'getIdentitiesTokenInfos', + // Documents / contracts + 'getDocuments', + 'getDocument', + 'getDataContract', + 'getDataContractHistory', + 'getDataContracts', + // Tokens + 'getTokenStatuses', + 'getTokenDirectPurchasePrices', + 'getTokenContractInfo', + 'getTokenPerpetualDistributionLastClaim', + 'getTokenTotalSupply', + // Epochs / System / Protocol + 'getEpochsInfo', + 'getFinalizedEpochInfos', + 'getCurrentEpoch', + 'getEvonodesProposedEpochBlocksByIds', + 'getEvonodesProposedEpochBlocksByRange', + 'getProtocolVersionUpgradeState', + 'getProtocolVersionUpgradeVoteStatus', + 'getStatus', + 'getCurrentQuorumsInfo', + 'getTotalCreditsInPlatform', + 'getPrefundedSpecializedBalance', + 'getPathElements', + // Voting / Groups + 'getContestedResources', + 'getContestedResourceVoteState', + 'getContestedResourceVotersForIdentity', + 'getContestedResourceIdentityVotes', + 'getVotePollsByEndDate', + 'getGroupInfo', + 'getGroupInfos', + 'getGroupMembers', + 'getIdentityGroups', + 'getGroupActions', + 'getGroupActionSigners', + 'getGroupsDataContracts', + // DPNS queries + 'dpnsRegisterName', + 'dpnsIsNameAvailable', + 'dpnsResolveName', + 'getDpnsUsernameByName', + 'getDpnsUsernames', + 'getDpnsUsername', + // Utils + 'waitForStateTransitionResult', + ]; + for (const fn of instanceFns) { + expect(typeof sdk.WasmSdk.prototype[fn]).to.be.oneOf(['function', 'undefined']); + } + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/builder-with-addresses.spec.mjs b/packages/wasm-sdk/tests/unit/builder-with-addresses.spec.mjs deleted file mode 100644 index 7c27acbb446..00000000000 --- a/packages/wasm-sdk/tests/unit/builder-with-addresses.spec.mjs +++ /dev/null @@ -1,190 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -// Test addresses (RFC 6761 reserved test domain - no network calls in unit tests) -const TEST_ADDRESS_1 = 'https://node-1.test:1443'; -const TEST_ADDRESS_2 = 'https://node-2.test:1443'; -const TEST_ADDRESS_3 = 'https://node-3.test:1443'; - -describe('WasmSdkBuilder.withAddresses()', () => { - before(async () => { - await init(); - }); - - it('withAddresses() method exists', () => { - expect(sdk.WasmSdkBuilder.withAddresses).to.be.a('function'); - }); - - describe('valid configurations', () => { - it('builds with single testnet address', async () => { - const builder = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'testnet', - ); - expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); - - const built = await builder.build(); - expect(built).to.be.an.instanceof(sdk.WasmSdk); - expect(built.version()).to.be.a('number'); - expect(built.version()).to.be.greaterThan(0); - built.free(); - }); - - it('builds with multiple testnet addresses', async () => { - const builder = sdk.WasmSdkBuilder.withAddresses( - [ - TEST_ADDRESS_1, - TEST_ADDRESS_2, - TEST_ADDRESS_3, - ], - 'testnet', - ); - expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); - const built = await builder.build(); - expect(built).to.be.an.instanceof(sdk.WasmSdk); - built.free(); - }); - - it('builds with mainnet address', async () => { - const builder = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'mainnet', - ); - expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); - const built = await builder.build(); - expect(built).to.be.an.instanceof(sdk.WasmSdk); - built.free(); - }); - - it('builds with local address', async () => { - const builder = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'local', - ); - expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); - const built = await builder.build(); - expect(built).to.be.an.instanceof(sdk.WasmSdk); - built.free(); - }); - }); - - describe('network validation', () => { - it('rejects devnet', async () => { - try { - sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'devnet', - ); - expect.fail('Should have thrown error for devnet'); - } catch (error) { - expect(error.message).to.include('mainnet, testnet or local'); - } - }); - - it('rejects invalid network name', async () => { - try { - sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'invalid-network', - ); - expect.fail('Should have thrown error for invalid network'); - } catch (error) { - expect(error.message).to.include('mainnet, testnet or local'); - } - }); - - it('is case-insensitive for network names', async () => { - const builder1 = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'TESTNET', - ); - expect(builder1).to.be.an.instanceof(sdk.WasmSdkBuilder); - - const builder2 = sdk.WasmSdkBuilder.withAddresses( - ['https://149.28.241.190:443'], - 'Mainnet', - ); - expect(builder2).to.be.an.instanceof(sdk.WasmSdkBuilder); - - const builder3 = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'LOCAL', - ); - expect(builder3).to.be.an.instanceof(sdk.WasmSdkBuilder); - }); - }); - - describe('address validation', () => { - it('fails to build with empty address array', () => { - try { - sdk.WasmSdkBuilder.withAddresses( - [], - 'testnet', - ); - expect.fail('Should have thrown error for empty URI'); - } catch (error) { - expect(error.message).to.equal('Addresses must be a non-empty array'); - } - }); - - it('rejects URI without host', () => { - try { - sdk.WasmSdkBuilder.withAddresses( - ['https://'], - 'testnet', - ); - expect.fail('Should have thrown error for URI without host'); - } catch (error) { - expect(error.message).to.include('Invalid URI'); - expect(error.message).to.include('https://'); - } - }); - }); - - describe('builder method chaining', () => { - it('chains with withSettings()', async () => { - let builder = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'testnet', - ); - builder = builder.withSettings(5000, 10000, 3, false); - expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); - const built = await builder.build(); - expect(built).to.be.an.instanceof(sdk.WasmSdk); - expect(built.version()).to.be.a('number'); - expect(built.version()).to.be.greaterThan(0); - built.free(); - }); - - it('chains with withVersion()', async () => { - let builder = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'testnet', - ); - builder = builder.withVersion(1); - expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); - const built = await builder.build(); - expect(built).to.be.an.instanceof(sdk.WasmSdk); - expect(built.version()).to.be.a('number'); - expect(built.version()).to.equal(1); - built.free(); - }); - - it('chains multiple methods', async () => { - let builder = sdk.WasmSdkBuilder.withAddresses( - [TEST_ADDRESS_1], - 'testnet', - ); - builder = builder - .withVersion(1) - .withProofs(true) - .withSettings(5000, 10000, 3, false) - .withLogs('debug'); - expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); - const built = await builder.build(); - expect(built).to.be.an.instanceof(sdk.WasmSdk); - expect(built.version()).to.be.a('number'); - expect(built.version()).to.equal(1); - built.free(); - }); - }); -}); diff --git a/packages/wasm-sdk/tests/unit/builder-with-addresses.spec.ts b/packages/wasm-sdk/tests/unit/builder-with-addresses.spec.ts new file mode 100644 index 00000000000..92f27be78ab --- /dev/null +++ b/packages/wasm-sdk/tests/unit/builder-with-addresses.spec.ts @@ -0,0 +1,197 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +// Test addresses (RFC 6761 reserved test domain - no network calls in unit tests) +const TEST_ADDRESS_1 = 'https://node-1.test:1443'; +const TEST_ADDRESS_2 = 'https://node-2.test:1443'; +const TEST_ADDRESS_3 = 'https://node-3.test:1443'; + +describe('WasmSdkBuilder', () => { + before(async () => { + await init(); + }); + + describe('withAddresses()', () => { + it('should be a function', () => { + expect(sdk.WasmSdkBuilder.withAddresses).to.be.a('function'); + }); + + describe('valid configurations', () => { + it('should build with single testnet address', async () => { + const builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'testnet', + ); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + + const built = await builder.build(); + expect(built).to.be.an.instanceof(sdk.WasmSdk); + expect(built.version()).to.be.a('number'); + expect(built.version()).to.be.greaterThan(0); + built.free(); + }); + + it('should build with multiple testnet addresses', async () => { + const builder = sdk.WasmSdkBuilder.withAddresses( + [ + TEST_ADDRESS_1, + TEST_ADDRESS_2, + TEST_ADDRESS_3, + ], + 'testnet', + ); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + const built = await builder.build(); + expect(built).to.be.an.instanceof(sdk.WasmSdk); + built.free(); + }); + + it('should build with mainnet address', async () => { + const builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'mainnet', + ); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + const built = await builder.build(); + expect(built).to.be.an.instanceof(sdk.WasmSdk); + built.free(); + }); + + it('should build with local address', async () => { + const builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'local', + ); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + const built = await builder.build(); + expect(built).to.be.an.instanceof(sdk.WasmSdk); + built.free(); + }); + }); + + describe('network validation', () => { + it('should reject devnet', async () => { + try { + sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'devnet', + ); + expect.fail('Should have thrown error for devnet'); + } catch (error) { + expect(error.message).to.include('mainnet, testnet or local'); + } + }); + + it('should reject invalid network name', async () => { + try { + sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'invalid-network', + ); + expect.fail('Should have thrown error for invalid network'); + } catch (error) { + expect(error.message).to.include('mainnet, testnet or local'); + } + }); + + it('should be case-insensitive for TESTNET', async () => { + const builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'TESTNET', + ); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + }); + + it('should be case-insensitive for Mainnet', async () => { + const builder = sdk.WasmSdkBuilder.withAddresses( + ['https://149.28.241.190:443'], + 'Mainnet', + ); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + }); + + it('should be case-insensitive for LOCAL', async () => { + const builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'LOCAL', + ); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + }); + }); + + describe('address validation', () => { + it('should fail to build with empty address array', () => { + try { + sdk.WasmSdkBuilder.withAddresses( + [], + 'testnet', + ); + expect.fail('Should have thrown error for empty URI'); + } catch (error) { + expect(error.message).to.equal('Addresses must be a non-empty array'); + } + }); + + it('should reject URI without host', () => { + try { + sdk.WasmSdkBuilder.withAddresses( + ['https://'], + 'testnet', + ); + expect.fail('Should have thrown error for URI without host'); + } catch (error) { + expect(error.message).to.include('Invalid URI'); + expect(error.message).to.include('https://'); + } + }); + }); + + describe('builder method chaining', () => { + it('should chain with withSettings()', async () => { + let builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'testnet', + ); + builder = builder.withSettings(5000, 10000, 3, false); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + const built = await builder.build(); + expect(built).to.be.an.instanceof(sdk.WasmSdk); + expect(built.version()).to.be.a('number'); + expect(built.version()).to.be.greaterThan(0); + built.free(); + }); + + it('should chain with withVersion()', async () => { + let builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'testnet', + ); + builder = builder.withVersion(1); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + const built = await builder.build(); + expect(built).to.be.an.instanceof(sdk.WasmSdk); + expect(built.version()).to.be.a('number'); + expect(built.version()).to.equal(1); + built.free(); + }); + + it('should chain multiple methods', async () => { + let builder = sdk.WasmSdkBuilder.withAddresses( + [TEST_ADDRESS_1], + 'testnet', + ); + builder = builder + .withVersion(1) + .withProofs(true) + .withSettings(5000, 10000, 3, false) + .withLogs('debug'); + expect(builder).to.be.an.instanceof(sdk.WasmSdkBuilder); + const built = await builder.build(); + expect(built).to.be.an.instanceof(sdk.WasmSdk); + expect(built.version()).to.be.a('number'); + expect(built.version()).to.equal(1); + built.free(); + }); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/builder.spec.mjs b/packages/wasm-sdk/tests/unit/builder.spec.mjs deleted file mode 100644 index 11f8d0ecd57..00000000000 --- a/packages/wasm-sdk/tests/unit/builder.spec.mjs +++ /dev/null @@ -1,35 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('WasmSdkBuilder', () => { - before(async () => { - await init(); - }); - - it('WasmSdkBuilder static methods exist', () => { - expect(sdk.WasmSdkBuilder).to.be.a('function'); - expect(sdk.WasmSdkBuilder.getLatestVersionNumber).to.be.a('function'); - expect(sdk.WasmSdkBuilder.mainnet).to.be.a('function'); - expect(sdk.WasmSdkBuilder.testnet).to.be.a('function'); - expect(sdk.WasmSdkBuilder.mainnetTrusted).to.be.a('function'); - expect(sdk.WasmSdkBuilder.testnetTrusted).to.be.a('function'); - }); - - it('builds testnet builder and sets version', async () => { - let builder = sdk.WasmSdkBuilder.testnet(); - expect(builder).to.be.ok(); - // note: builder methods consume and return a new builder - builder = builder.withVersion(1); - const built = await builder.build(); - expect(built).to.be.ok(); - built.free(); - }); - - it('applies custom settings (timeouts, retries, ban flag)', async () => { - // withSettings(connect_timeout_ms, timeout_ms, retries, ban_failed_address) - let builder = sdk.WasmSdkBuilder.testnet(); - builder = builder.withSettings(5000, 10000, 3, true); - const built = await builder.build(); - expect(built).to.be.ok(); - built.free(); - }); -}); diff --git a/packages/wasm-sdk/tests/unit/builder.spec.ts b/packages/wasm-sdk/tests/unit/builder.spec.ts new file mode 100644 index 00000000000..4b047478041 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/builder.spec.ts @@ -0,0 +1,70 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('WasmSdkBuilder', () => { + before(async () => { + await init(); + }); + + describe('static methods', () => { + it('should expose WasmSdkBuilder as a function', () => { + expect(sdk.WasmSdkBuilder).to.be.a('function'); + }); + + it('should expose getLatestVersionNumber method', () => { + expect(sdk.WasmSdkBuilder.getLatestVersionNumber).to.be.a('function'); + }); + + it('should expose mainnet method', () => { + expect(sdk.WasmSdkBuilder.mainnet).to.be.a('function'); + }); + + it('should expose testnet method', () => { + expect(sdk.WasmSdkBuilder.testnet).to.be.a('function'); + }); + + it('should expose mainnetTrusted method', () => { + expect(sdk.WasmSdkBuilder.mainnetTrusted).to.be.a('function'); + }); + + it('should expose testnetTrusted method', () => { + expect(sdk.WasmSdkBuilder.testnetTrusted).to.be.a('function'); + }); + }); + + describe('testnet()', () => { + it('should create a builder instance', () => { + const builder = sdk.WasmSdkBuilder.testnet(); + expect(builder).to.be.ok(); + }); + }); + + describe('withVersion()', () => { + it('should set version and return a new builder', async () => { + let builder = sdk.WasmSdkBuilder.testnet(); + builder = builder.withVersion(1); + const built = await builder.build(); + expect(built).to.be.ok(); + built.free(); + }); + }); + + describe('withSettings()', () => { + it('should apply custom settings (timeouts, retries, ban flag)', async () => { + let builder = sdk.WasmSdkBuilder.testnet(); + builder = builder.withSettings(5000, 10000, 3, true); + const built = await builder.build(); + expect(built).to.be.ok(); + built.free(); + }); + }); + + describe('build()', () => { + it('should build a WasmSdk instance', async () => { + const builder = sdk.WasmSdkBuilder.testnet(); + const built = await builder.build(); + expect(built).to.be.ok(); + built.free(); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/conversion.spec.mjs b/packages/wasm-sdk/tests/unit/conversion.spec.mjs deleted file mode 100644 index c8bf52e5d4f..00000000000 --- a/packages/wasm-sdk/tests/unit/conversion.spec.mjs +++ /dev/null @@ -1,223 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('serde conversions (unit)', () => { - before(async () => { - await init(); - }); - - describe('ProofMetadataResponse BigInt serialization', () => { - it('should serialize BigInt data to JSON as string', () => { - const chainId = new Uint8Array([1, 2, 3, 4]); - const metadata = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); - const proof = new sdk.ProofInfo( - new Uint8Array([1, 2, 3]), - new Uint8Array([4, 5, 6]), - new Uint8Array([7, 8, 9]), - 1, - new Uint8Array([10, 11, 12]), - 100, - ); - - // Create ProofMetadataResponse with BigInt data (simulating large credit balance) - const largeBigInt = 23522425453263151n; // Value > Number.MAX_SAFE_INTEGER - const response = new sdk.ProofMetadataResponse(largeBigInt, metadata, proof); - - // toJSON should not throw and should convert BigInt to string - const json = response.toJSON(); - expect(json).to.have.property('data'); - expect(json).to.have.property('metadata'); - expect(json).to.have.property('proof'); - - // BigInt should be serialized as string - expect(json.data).to.equal('23522425453263151'); - }); - - it('should serialize object with BigInt properties to JSON', () => { - const chainId = new Uint8Array([1, 2, 3, 4]); - const metadata = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); - const proof = new sdk.ProofInfo( - new Uint8Array([1, 2, 3]), - new Uint8Array([4, 5, 6]), - new Uint8Array([7, 8, 9]), - 1, - new Uint8Array([10, 11, 12]), - 100, - ); - - // Create ProofMetadataResponse with object containing BigInt - const dataWithBigInt = { - totalCredits: 23522425453263151n, - count: 42, - nested: { - balance: 9007199254740992n, // Exactly MAX_SAFE_INTEGER + 1 - }, - }; - const response = new sdk.ProofMetadataResponse(dataWithBigInt, metadata, proof); - - // toJSON should not throw - const json = response.toJSON(); - expect(json.data.totalCredits).to.equal('23522425453263151'); - expect(json.data.count).to.equal(42); - expect(json.data.nested.balance).to.equal('9007199254740992'); - }); - - it('should serialize array with BigInt values to JSON', () => { - const chainId = new Uint8Array([1, 2, 3, 4]); - const metadata = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); - const proof = new sdk.ProofInfo( - new Uint8Array([1, 2, 3]), - new Uint8Array([4, 5, 6]), - new Uint8Array([7, 8, 9]), - 1, - new Uint8Array([10, 11, 12]), - 100, - ); - - // Create ProofMetadataResponse with array containing BigInt - const dataWithBigIntArray = [1n, 2n, 23522425453263151n]; - const response = new sdk.ProofMetadataResponse(dataWithBigIntArray, metadata, proof); - - // toJSON should not throw - const json = response.toJSON(); - expect(json.data).to.deep.equal(['1', '2', '23522425453263151']); - }); - }); - - it('ResponseMetadata: getter returns Uint8Array, toJSON returns base64', () => { - const chainId = new Uint8Array([1, 2, 3, 4]); - const meta = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); - - const chainFromGetter = meta.chainId; - expect(chainFromGetter).to.be.instanceOf(Uint8Array); - expect([...chainFromGetter]).to.deep.equal([...chainId]); - - const json = meta.toJSON(); - expect(json.chainId).to.be.a('string'); - expect(json.chainId).to.equal(Buffer.from(chainId).toString('base64')); - - const metaFromJson = sdk.ResponseMetadata.fromJSON(json); - expect([...metaFromJson.chainId]).to.deep.equal([...chainId]); - }); - - describe('ProofMetadataResponse with Identity data', () => { - it('should serialize Identity as data with full JSON including metadata, proof, and identity', () => { - // Create metadata and proof - const chainId = new Uint8Array([1, 2, 3, 4]); - const metadata = new sdk.ResponseMetadata(100n, 50, 10, 1234567890n, 1, chainId); - const proof = new sdk.ProofInfo( - new Uint8Array([10, 20, 30]), // grovedbProof - new Uint8Array([40, 50, 60]), // quorumHash - new Uint8Array([70, 80, 90]), // signature - 5, // round - new Uint8Array([100, 110, 120]), // blockIdHash - 200, // quorumType - ); - - // Create an Identity - const identifierId = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; - const identity = new sdk.Identity(identifierId); - identity.balance = 1000000000n; // 10 DASH in credits - identity.revision = 5n; - - // Create ProofMetadataResponse with Identity.toJSON() as data - // Using toJSON() ensures all nested objects (like Identifier) - // are converted to JSON-safe values - const identityJson = identity.toJSON(); - const response = new sdk.ProofMetadataResponse(identityJson, metadata, proof); - - // Call toJSON - should produce full JSON representation - const json = response.toJSON(); - - // Verify structure - expect(json).to.have.property('data'); - expect(json).to.have.property('metadata'); - expect(json).to.have.property('proof'); - - // Verify metadata - expect(json.metadata.height).to.equal(100); - expect(json.metadata.coreChainLockedHeight).to.equal(50); - expect(json.metadata.epoch).to.equal(10); - expect(json.metadata.timeMs).to.equal(1234567890); - expect(json.metadata.protocolVersion).to.equal(1); - expect(json.metadata.chainId).to.equal(Buffer.from(chainId).toString('base64')); - - // Verify proof - expect(json.proof.grovedbProof).to.equal(Buffer.from([10, 20, 30]).toString('base64')); - expect(json.proof.quorumHash).to.equal(Buffer.from([40, 50, 60]).toString('base64')); - expect(json.proof.signature).to.equal(Buffer.from([70, 80, 90]).toString('base64')); - expect(json.proof.round).to.equal(5); - expect(json.proof.blockIdHash).to.equal(Buffer.from([100, 110, 120]).toString('base64')); - expect(json.proof.quorumType).to.equal(200); - - // Verify identity data - id should be Base58 in JSON - expect(json.data).to.have.property('id'); - expect(json.data.id).to.equal(identifierId); - // Values within safe integer range are numbers, large values would be strings - expect(json.data.balance).to.equal(1000000000); - expect(json.data.revision).to.equal(5); - expect(json.data.publicKeys).to.be.an('array'); - }); - - it('should round-trip ProofMetadataResponse with Identity data through JSON', () => { - const chainId = new Uint8Array([5, 6, 7, 8]); - const metadata = new sdk.ResponseMetadata(200n, 100, 20, 9876543210n, 2, chainId); - const proof = new sdk.ProofInfo( - new Uint8Array([1, 2, 3, 4, 5]), - new Uint8Array([6, 7, 8, 9, 10]), - new Uint8Array([11, 12, 13, 14, 15]), - 10, - new Uint8Array([16, 17, 18, 19, 20]), - 300, - ); - - const identifierId = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; - const identity = new sdk.Identity(identifierId); - identity.balance = 5000000000n; - identity.revision = 10n; - - // Use toJSON() to get JSON-safe representation of identity - const response = new sdk.ProofMetadataResponse(identity.toJSON(), metadata, proof); - const json = response.toJSON(); - - // Round-trip through JSON - const restored = sdk.ProofMetadataResponse.fromJSON(json); - const restoredJson = restored.toJSON(); - - // Verify JSON matches - expect(restoredJson).to.deep.equal(json); - - // Verify we can access the data - expect(restored.data.id).to.equal(identifierId); - // metadata.height getter returns BigInt - expect(restored.metadata.height).to.equal(200n); - expect(restored.proof.round).to.equal(10); - }); - }); - - it('Identifier-backed structs: toObject returns bytes, toJSON returns Base58', () => { - const bytes = new Uint8Array(32).fill(7); - const expectedBase58 = sdk.Identifier.fromBytes(Array.from(bytes)).toBase58(); - const identifier = sdk.Identifier.fromBase58(expectedBase58); - const identifier2 = sdk.Identifier.fromBase58(expectedBase58); - const info = new sdk.DpnsUsernameInfo('alice', identifier, identifier2); - - const identityBytes = info.identityId.toBytes(); - const documentBytes = info.documentId.toBytes(); - expect(identityBytes.length).to.equal(32); - expect(documentBytes.length).to.equal(32); - expect(Buffer.from(identityBytes)).to.deep.equal(Buffer.from(bytes)); - expect(Buffer.from(documentBytes)).to.deep.equal(Buffer.from(bytes)); - - const object = info.toObject(); - expect(Buffer.from(object.identityId)).to.deep.equal(Buffer.from(bytes)); - expect(Buffer.from(object.documentId)).to.deep.equal(Buffer.from(bytes)); - - const json = info.toJSON(); - expect(json.identityId).to.equal(expectedBase58); - expect(json.documentId).to.equal(expectedBase58); - - const roundtrip = sdk.DpnsUsernameInfo.fromJSON(json); - expect(roundtrip.identityId.toBase58()).to.equal(expectedBase58); - expect(roundtrip.documentId.toBase58()).to.equal(expectedBase58); - }); -}); diff --git a/packages/wasm-sdk/tests/unit/conversion.spec.ts b/packages/wasm-sdk/tests/unit/conversion.spec.ts new file mode 100644 index 00000000000..15ce97ec32c --- /dev/null +++ b/packages/wasm-sdk/tests/unit/conversion.spec.ts @@ -0,0 +1,272 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('Serde Conversions', () => { + before(async () => { + await init(); + }); + + describe('ProofMetadataResponse', () => { + describe('toJSON()', () => { + it('should serialize BigInt data to JSON as string', () => { + const chainId = new Uint8Array([1, 2, 3, 4]); + const metadata = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); + const proof = new sdk.ProofInfo( + new Uint8Array([1, 2, 3]), + new Uint8Array([4, 5, 6]), + new Uint8Array([7, 8, 9]), + 1, + new Uint8Array([10, 11, 12]), + 100, + ); + + // Create ProofMetadataResponse with BigInt data (simulating large credit balance) + const largeBigInt = 23522425453263151n; // Value > Number.MAX_SAFE_INTEGER + const response = new sdk.ProofMetadataResponse(largeBigInt, metadata, proof); + + // toJSON should not throw and should convert BigInt to string + const json = response.toJSON(); + expect(json).to.have.property('data'); + expect(json).to.have.property('metadata'); + expect(json).to.have.property('proof'); + + // BigInt should be serialized as string + expect(json.data).to.equal('23522425453263151'); + }); + + it('should serialize object with BigInt properties to JSON', () => { + const chainId = new Uint8Array([1, 2, 3, 4]); + const metadata = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); + const proof = new sdk.ProofInfo( + new Uint8Array([1, 2, 3]), + new Uint8Array([4, 5, 6]), + new Uint8Array([7, 8, 9]), + 1, + new Uint8Array([10, 11, 12]), + 100, + ); + + // Create ProofMetadataResponse with object containing BigInt + const dataWithBigInt = { + totalCredits: 23522425453263151n, + count: 42, + nested: { + balance: 9007199254740992n, // Exactly MAX_SAFE_INTEGER + 1 + }, + }; + const response = new sdk.ProofMetadataResponse(dataWithBigInt, metadata, proof); + + // toJSON should not throw + const json = response.toJSON(); + expect(json.data.totalCredits).to.equal('23522425453263151'); + expect(json.data.count).to.equal(42); + expect(json.data.nested.balance).to.equal('9007199254740992'); + }); + + it('should serialize array with BigInt values to JSON', () => { + const chainId = new Uint8Array([1, 2, 3, 4]); + const metadata = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); + const proof = new sdk.ProofInfo( + new Uint8Array([1, 2, 3]), + new Uint8Array([4, 5, 6]), + new Uint8Array([7, 8, 9]), + 1, + new Uint8Array([10, 11, 12]), + 100, + ); + + // Create ProofMetadataResponse with array containing BigInt + const dataWithBigIntArray = [1n, 2n, 23522425453263151n]; + const response = new sdk.ProofMetadataResponse(dataWithBigIntArray, metadata, proof); + + // toJSON should not throw + const json = response.toJSON(); + expect(json.data).to.deep.equal(['1', '2', '23522425453263151']); + }); + + it('should serialize Identity as data with full JSON including metadata, proof, and identity', () => { + // Create metadata and proof + const chainId = new Uint8Array([1, 2, 3, 4]); + const metadata = new sdk.ResponseMetadata(100n, 50, 10, 1234567890n, 1, chainId); + const proof = new sdk.ProofInfo( + new Uint8Array([10, 20, 30]), // grovedbProof + new Uint8Array([40, 50, 60]), // quorumHash + new Uint8Array([70, 80, 90]), // signature + 5, // round + new Uint8Array([100, 110, 120]), // blockIdHash + 200, // quorumType + ); + + // Create an Identity + const identifierId = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + const identity = new sdk.Identity(identifierId); + identity.balance = 1000000000n; // 10 DASH in credits + identity.revision = 5n; + + // Create ProofMetadataResponse with Identity.toJSON() as data + // Using toJSON() ensures all nested objects (like Identifier) + // are converted to JSON-safe values + const identityJson = identity.toJSON(); + const response = new sdk.ProofMetadataResponse(identityJson, metadata, proof); + + // Call toJSON - should produce full JSON representation + const json = response.toJSON(); + + // Verify structure + expect(json).to.have.property('data'); + expect(json).to.have.property('metadata'); + expect(json).to.have.property('proof'); + + // Verify metadata + expect(json.metadata.height).to.equal(100); + expect(json.metadata.coreChainLockedHeight).to.equal(50); + expect(json.metadata.epoch).to.equal(10); + expect(json.metadata.timeMs).to.equal(1234567890); + expect(json.metadata.protocolVersion).to.equal(1); + expect(json.metadata.chainId).to.equal(Buffer.from(chainId).toString('base64')); + + // Verify proof + expect(json.proof.grovedbProof).to.equal(Buffer.from([10, 20, 30]).toString('base64')); + expect(json.proof.quorumHash).to.equal(Buffer.from([40, 50, 60]).toString('base64')); + expect(json.proof.signature).to.equal(Buffer.from([70, 80, 90]).toString('base64')); + expect(json.proof.round).to.equal(5); + expect(json.proof.blockIdHash).to.equal(Buffer.from([100, 110, 120]).toString('base64')); + expect(json.proof.quorumType).to.equal(200); + + // Verify identity data - id should be Base58 in JSON + expect(json.data).to.have.property('id'); + expect(json.data.id).to.equal(identifierId); + // Values within safe integer range are numbers, large values would be strings + expect(json.data.balance).to.equal(1000000000); + expect(json.data.revision).to.equal(5); + expect(json.data.publicKeys).to.be.an('array'); + }); + }); + + describe('fromJSON()', () => { + it('should round-trip ProofMetadataResponse with Identity data through JSON', () => { + const chainId = new Uint8Array([5, 6, 7, 8]); + const metadata = new sdk.ResponseMetadata(200n, 100, 20, 9876543210n, 2, chainId); + const proof = new sdk.ProofInfo( + new Uint8Array([1, 2, 3, 4, 5]), + new Uint8Array([6, 7, 8, 9, 10]), + new Uint8Array([11, 12, 13, 14, 15]), + 10, + new Uint8Array([16, 17, 18, 19, 20]), + 300, + ); + + const identifierId = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + const identity = new sdk.Identity(identifierId); + identity.balance = 5000000000n; + identity.revision = 10n; + + // Use toJSON() to get JSON-safe representation of identity + const response = new sdk.ProofMetadataResponse(identity.toJSON(), metadata, proof); + const json = response.toJSON(); + + // Round-trip through JSON + const restored = sdk.ProofMetadataResponse.fromJSON(json); + const restoredJson = restored.toJSON(); + + // Verify JSON matches + expect(restoredJson).to.deep.equal(json); + + // Verify we can access the data + expect(restored.data.id).to.equal(identifierId); + // metadata.height getter returns BigInt + expect(restored.metadata.height).to.equal(200n); + expect(restored.proof.round).to.equal(10); + }); + }); + }); + + describe('ResponseMetadata', () => { + describe('chainId getter', () => { + it('should return Uint8Array from getter', () => { + const chainId = new Uint8Array([1, 2, 3, 4]); + const meta = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); + + const chainFromGetter = meta.chainId; + expect(chainFromGetter).to.be.instanceOf(Uint8Array); + expect([...chainFromGetter]).to.deep.equal([...chainId]); + }); + }); + + describe('toJSON()', () => { + it('should return base64 for chainId', () => { + const chainId = new Uint8Array([1, 2, 3, 4]); + const meta = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); + + const json = meta.toJSON(); + expect(json.chainId).to.be.a('string'); + expect(json.chainId).to.equal(Buffer.from(chainId).toString('base64')); + }); + }); + + describe('fromJSON()', () => { + it('should round-trip chainId through JSON', () => { + const chainId = new Uint8Array([1, 2, 3, 4]); + const meta = new sdk.ResponseMetadata(1n, 2, 3, 4n, 5, chainId); + + const json = meta.toJSON(); + const metaFromJson = sdk.ResponseMetadata.fromJSON(json); + expect([...metaFromJson.chainId]).to.deep.equal([...chainId]); + }); + }); + }); + + describe('DpnsUsernameInfo', () => { + const bytes = new Uint8Array(32).fill(7); + let expectedBase58; + let info; + + beforeEach(() => { + expectedBase58 = sdk.Identifier.fromBytes(Array.from(bytes)).toBase58(); + const identifier = sdk.Identifier.fromBase58(expectedBase58); + const identifier2 = sdk.Identifier.fromBase58(expectedBase58); + info = new sdk.DpnsUsernameInfo('alice', identifier, identifier2); + }); + + describe('identityId getter', () => { + it('should return bytes from toBytes()', () => { + const identityBytes = info.identityId.toBytes(); + expect(identityBytes.length).to.equal(32); + expect(Buffer.from(identityBytes)).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('documentId getter', () => { + it('should return bytes from toBytes()', () => { + const documentBytes = info.documentId.toBytes(); + expect(documentBytes.length).to.equal(32); + expect(Buffer.from(documentBytes)).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('toObject()', () => { + it('should return bytes for Identifier fields', () => { + const object = info.toObject(); + expect(Buffer.from(object.identityId)).to.deep.equal(Buffer.from(bytes)); + expect(Buffer.from(object.documentId)).to.deep.equal(Buffer.from(bytes)); + }); + }); + + describe('toJSON()', () => { + it('should return Base58 for Identifier fields', () => { + const json = info.toJSON(); + expect(json.identityId).to.equal(expectedBase58); + expect(json.documentId).to.equal(expectedBase58); + }); + }); + + describe('fromJSON()', () => { + it('should round-trip through JSON', () => { + const json = info.toJSON(); + const roundtrip = sdk.DpnsUsernameInfo.fromJSON(json); + expect(roundtrip.identityId.toBase58()).to.equal(expectedBase58); + expect(roundtrip.documentId.toBase58()).to.equal(expectedBase58); + }); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs b/packages/wasm-sdk/tests/unit/data-contract.spec.mjs deleted file mode 100644 index 57a60ac54e2..00000000000 --- a/packages/wasm-sdk/tests/unit/data-contract.spec.mjs +++ /dev/null @@ -1,351 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; -import contractFixtureV0 from './fixtures/data-contract-v0-crypto-card-game.mjs'; -import contractFixtureV1 from './fixtures/data-contract-v1-with-docs-tokens-groups.mjs'; - -// Platform version constants -const PLATFORM_VERSION_CONTRACT_V0 = 1; -const PLATFORM_VERSION_CONTRACT_V1 = 9; // V1 contracts introduced in Platform v9 - -// Platform version compatibility ranges -const V0_COMPATIBLE_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // V0 supported versions -const V1_COMPATIBLE_VERSIONS = [9, 10]; // V1 starts at platform version 9 -const V0_ONLY_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8]; // Versions that only support V0 -const LATEST_KNOWN_VERSION = Math.max(...V0_COMPATIBLE_VERSIONS); - -// Helper function for testing contract compatibility across versions -const testContractAcrossVersions = ( - contractFixture, - contractName, - compatibleVersions, - incompatibleVersions = [], -) => { - compatibleVersions.forEach((version) => { - it(`should work with platform version ${version}`, () => { - const contract = sdk.DataContract.fromJSON(contractFixture, true, version); - expect(contract).to.be.ok(); - expect(contract.id.toBase58()).to.equal(contractFixture.id); - - const roundTripped = contract.toJSON(version); - expect(roundTripped.id).to.equal(contractFixture.id); - - contract.free(); - }); - }); - - incompatibleVersions.forEach((version) => { - it(`should fail with platform version ${version}`, () => { - expect(() => { - sdk.DataContract.fromJSON(contractFixture, true, version); - }).to.throw(/unknown version|dpp unknown version/); - }); - }); -}; - -describe('DataContract', () => { - before(async () => { - await init(); - }); - - describe('Contract Creation', () => { - it('should create a V0 contract from JSON and expose all properties', async () => { - const contract = sdk.DataContract.fromJSON( - contractFixtureV0, - true, - PLATFORM_VERSION_CONTRACT_V0, - ); - - expect(contract).to.be.ok(); - expect(contract.id.toBase58()).to.equal(contractFixtureV0.id); - - const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); - expect(roundTripped).to.be.an('object'); - expect(roundTripped.id).to.equal(contractFixtureV0.id); - expect(roundTripped.ownerId).to.equal(contractFixtureV0.ownerId); - expect(roundTripped.version).to.equal(contractFixtureV0.version); - expect(roundTripped.$format_version).to.equal(contractFixtureV0.$format_version); - expect(roundTripped.config).to.deep.equal(contractFixtureV0.config); - expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV0.documentSchemas); - - // Verify document schema structure - expect(roundTripped.documentSchemas.card).to.exist(); - expect(roundTripped.documentSchemas.card.properties.name).to.exist(); - expect(roundTripped.documentSchemas.card.properties.rarity.enum) - .to.deep.equal(['common', 'uncommon', 'rare', 'legendary']); - expect(roundTripped.documentSchemas.card.indices).to.have.length(2); - - contract.free(); - }); - - it('should create a V1 contract from JSON and expose all properties including tokens and groups', async () => { - const contract = sdk.DataContract.fromJSON( - contractFixtureV1, - true, - PLATFORM_VERSION_CONTRACT_V1, - ); - - expect(contract).to.be.ok(); - expect(contract.id.toBase58()).to.equal(contractFixtureV1.id); - - const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); - expect(roundTripped).to.be.an('object'); - expect(roundTripped.id).to.equal(contractFixtureV1.id); - expect(roundTripped.ownerId).to.equal(contractFixtureV1.ownerId); - expect(roundTripped.version).to.equal(contractFixtureV1.version); - expect(roundTripped.$format_version).to.equal(contractFixtureV1.$format_version); - expect(roundTripped.config.sizedIntegerTypes).to.be.true(); - expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV1.documentSchemas); - - // Verify V1-specific features - expect(roundTripped.tokens).to.exist(); - expect(roundTripped.tokens['0']).to.exist(); - expect(roundTripped.tokens['0'].baseSupply).to.equal(100); - expect(roundTripped.tokens['0'].conventions.decimals).to.equal(0); - - expect(roundTripped.groups).to.exist(); - expect(roundTripped.groups['0']).to.exist(); - expect(roundTripped.groups['0'].required_power).to.equal(2); - - expect(roundTripped.keywords).to.deep.equal(contractFixtureV1.keywords); - - contract.free(); - }); - - it('should create a contract with only document schemas (no tokens)', () => { - // V0 fixture already has only documents, no tokens - verify it works - const contract = sdk.DataContract.fromJSON( - contractFixtureV0, - true, - PLATFORM_VERSION_CONTRACT_V0, - ); - const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); - - expect(roundTripped.documentSchemas.card).to.exist(); - expect(roundTripped.tokens).to.equal(undefined); - - contract.free(); - }); - - it('should create a contract with only tokens (no documents)', () => { - // Use V1 fixture but remove documentSchemas - const contractWithOnlyTokens = { - ...contractFixtureV1, - documentSchemas: {}, - }; - - const contract = sdk.DataContract.fromJSON( - contractWithOnlyTokens, - true, - PLATFORM_VERSION_CONTRACT_V1, - ); - const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); - - expect(roundTripped.documentSchemas).to.deep.equal({}); - - contract.free(); - }); - }); - - describe('Version Compatibility', () => { - it('should fail to create a V1 contract with V0 platform version', async () => { - expect(() => { - sdk.DataContract.fromJSON( - contractFixtureV1, - true, - PLATFORM_VERSION_CONTRACT_V0, - ); - }).to.throw(/dpp unknown version.*known versions.*\[0\].*received.*1/); - }); - }); - - describe('Validation', () => { - it('should handle invalid JSON input gracefully', () => { - expect(() => { - sdk.DataContract.fromJSON(null, true, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - - expect(() => { - sdk.DataContract.fromJSON({}, true, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - - expect(() => { - sdk.DataContract.fromJSON({ id: 'invalid' }, true, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - }); - - it('should reject contracts with invalid property values', () => { - // Test invalid Base58 ID - expect(() => { - sdk.DataContract.fromValue({ - ...contractFixtureV0, - id: 'invalid-not-base58!', - }, true, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - - // Test negative version number - expect(() => { - sdk.DataContract.fromValue({ - ...contractFixtureV0, - version: -1, - }, true, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - - // Test invalid ownerId - expect(() => { - sdk.DataContract.fromValue({ - ...contractFixtureV0, - ownerId: 'not-a-valid-id', - }, true, PLATFORM_VERSION_CONTRACT_V0); - }).to.throw(); - }); - - it('should require at least one document type or token', () => { - const contractWithEmptySchemas = { - $format_version: '0', - id: contractFixtureV0.id, - ownerId: contractFixtureV0.ownerId, - version: 1, - config: contractFixtureV0.config, - documentSchemas: {}, - }; - - expect(() => { - sdk.DataContract.fromJSON( - contractWithEmptySchemas, - true, - PLATFORM_VERSION_CONTRACT_V0, - ); - }).to.throw(/must have at least one document type or token defined/); - }); - }); - - describe('Data Preservation', () => { - it('should preserve all data through JSON round-trip for V0 contract', async () => { - const contract = sdk.DataContract.fromJSON( - contractFixtureV0, - true, - PLATFORM_VERSION_CONTRACT_V0, - ); - const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); - - // Create a new contract from the round-tripped JSON - const contract2 = sdk.DataContract.fromJSON( - roundTripped, - true, - PLATFORM_VERSION_CONTRACT_V0, - ); - const roundTripped2 = contract2.toJSON(PLATFORM_VERSION_CONTRACT_V0); - - expect(roundTripped2).to.deep.equal(roundTripped); - - contract.free(); - contract2.free(); - }); - - it('should preserve all data through JSON round-trip for V1 contract', async () => { - const contract = sdk.DataContract.fromJSON( - contractFixtureV1, - true, - PLATFORM_VERSION_CONTRACT_V1, - ); - const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); - - // Create a new contract from the round-tripped JSON - const contract2 = sdk.DataContract.fromJSON( - roundTripped, - true, - PLATFORM_VERSION_CONTRACT_V1, - ); - const roundTripped2 = contract2.toJSON(PLATFORM_VERSION_CONTRACT_V1); - - expect(roundTripped2).to.deep.equal(roundTripped); - - contract.free(); - contract2.free(); - }); - - it('should preserve all data through JSON round-trip for V1 contract (object output)', async () => { - const contract = sdk.DataContract.fromJSON( - contractFixtureV1, - true, - PLATFORM_VERSION_CONTRACT_V1, - ); - const jsonRepresentation = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); - - const contract2 = sdk.DataContract.fromJSON( - jsonRepresentation, - true, - PLATFORM_VERSION_CONTRACT_V1, - ); - - expect(contract2.toJSON(PLATFORM_VERSION_CONTRACT_V1)).to.deep.equal(jsonRepresentation); - - contract.free(); - contract2.free(); - }); - }); - - describe('Memory Management', () => { - it('should handle memory management properly with multiple contracts', async () => { - const contract1 = sdk.DataContract.fromJSON( - contractFixtureV0, - true, - PLATFORM_VERSION_CONTRACT_V0, - ); - const contract2 = sdk.DataContract.fromJSON( - contractFixtureV1, - true, - PLATFORM_VERSION_CONTRACT_V1, - ); - - expect(contract1.id.toBase58()).to.equal(contractFixtureV0.id); - expect(contract2.id.toBase58()).to.equal(contractFixtureV1.id); - - contract1.free(); - contract2.free(); - }); - }); - - describe('Platform Version Compatibility Matrix', () => { - describe('V0 Contract Compatibility', () => { - testContractAcrossVersions(contractFixtureV0, 'V0', V0_COMPATIBLE_VERSIONS); - }); - - describe('V1 Contract Compatibility', () => { - testContractAcrossVersions(contractFixtureV1, 'V1', V1_COMPATIBLE_VERSIONS, V0_ONLY_VERSIONS); - }); - - describe('Edge Cases', () => { - it('should fail with invalid version numbers', () => { - const invalidVersions = [ - 0, // Zero version - -1, // Negative version - LATEST_KNOWN_VERSION + 1, // One beyond latest known - LATEST_KNOWN_VERSION * 10, // Far beyond reasonable range - ]; - - invalidVersions.forEach((version) => { - expect(() => { - sdk.DataContract.fromJSON(contractFixtureV0, true, version); - }).to.throw(/unknown version|unknown platform version value/); - }); - }); - - it('should handle version boundary correctly at V9 transition', () => { - // V0 contract should work in V9 (backward compatibility) - const contract = sdk.DataContract.fromJSON(contractFixtureV0, true, 9); - expect(contract.id.toBase58()).to.equal(contractFixtureV0.id); - contract.free(); - - // V1 contract should work in V9 (first supported version) - const contractV1 = sdk.DataContract.fromJSON(contractFixtureV1, true, 9); - expect(contractV1.id.toBase58()).to.equal(contractFixtureV1.id); - contractV1.free(); - - // V1 contract should fail in V8 (last unsupported version) - expect(() => { - sdk.DataContract.fromJSON(contractFixtureV1, true, 8); - }).to.throw(/dpp unknown version/); - }); - }); - }); -}); diff --git a/packages/wasm-sdk/tests/unit/data-contract.spec.ts b/packages/wasm-sdk/tests/unit/data-contract.spec.ts new file mode 100644 index 00000000000..1f5657b744b --- /dev/null +++ b/packages/wasm-sdk/tests/unit/data-contract.spec.ts @@ -0,0 +1,553 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; +import contractFixtureV0 from './fixtures/data-contract-v0-crypto-card-game.ts'; +import contractFixtureV1 from './fixtures/data-contract-v1-with-docs-tokens-groups.ts'; + +// Platform version constants +const PLATFORM_VERSION_CONTRACT_V0 = 1; +const PLATFORM_VERSION_CONTRACT_V1 = 9; // V1 contracts introduced in Platform v9 + +// Platform version compatibility ranges +const V0_COMPATIBLE_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // V0 supported versions +const V1_COMPATIBLE_VERSIONS = [9, 10]; // V1 starts at platform version 9 +const V0_ONLY_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8]; // Versions that only support V0 +const LATEST_KNOWN_VERSION = Math.max(...V0_COMPATIBLE_VERSIONS); + +// Helper function for testing contract compatibility across versions +const testContractAcrossVersions = ( + contractFixture, + contractName, + compatibleVersions, + incompatibleVersions = [], +) => { + compatibleVersions.forEach((version) => { + it(`should work with platform version ${version}`, () => { + const contract = sdk.DataContract.fromJSON(contractFixture, true, version); + expect(contract).to.be.ok(); + expect(contract.id.toBase58()).to.equal(contractFixture.id); + + const roundTripped = contract.toJSON(version); + expect(roundTripped.id).to.equal(contractFixture.id); + + contract.free(); + }); + }); + + incompatibleVersions.forEach((version) => { + it(`should fail with platform version ${version}`, () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixture, true, version); + }).to.throw(/unknown version|dpp unknown version/); + }); + }); +}; + +describe('DataContract', () => { + before(async () => { + await init(); + }); + + describe('fromJSON()', () => { + describe('V0 contract creation', () => { + it('should create a V0 contract and expose id', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + + expect(contract).to.be.ok(); + expect(contract.id.toBase58()).to.equal(contractFixtureV0.id); + contract.free(); + }); + + it('should create a V0 contract with correct ownerId', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.ownerId).to.equal(contractFixtureV0.ownerId); + contract.free(); + }); + + it('should create a V0 contract with correct version', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.version).to.equal(contractFixtureV0.version); + contract.free(); + }); + + it('should create a V0 contract with correct format version', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.$format_version).to.equal(contractFixtureV0.$format_version); + contract.free(); + }); + + it('should create a V0 contract with correct config', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.config).to.deep.equal(contractFixtureV0.config); + contract.free(); + }); + + it('should create a V0 contract with correct document schemas', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV0.documentSchemas); + contract.free(); + }); + + it('should create a V0 contract with card document schema', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.documentSchemas.card).to.exist(); + expect(roundTripped.documentSchemas.card.properties.name).to.exist(); + contract.free(); + }); + + it('should create a V0 contract with correct rarity enum', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.documentSchemas.card.properties.rarity.enum) + .to.deep.equal(['common', 'uncommon', 'rare', 'legendary']); + contract.free(); + }); + + it('should create a V0 contract with correct indices', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + expect(roundTripped.documentSchemas.card.indices).to.have.length(2); + contract.free(); + }); + }); + + describe('V1 contract creation', () => { + it('should create a V1 contract and expose id', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + + expect(contract).to.be.ok(); + expect(contract.id.toBase58()).to.equal(contractFixtureV1.id); + contract.free(); + }); + + it('should create a V1 contract with correct ownerId', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.ownerId).to.equal(contractFixtureV1.ownerId); + contract.free(); + }); + + it('should create a V1 contract with correct version', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.version).to.equal(contractFixtureV1.version); + contract.free(); + }); + + it('should create a V1 contract with correct format version', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.$format_version).to.equal(contractFixtureV1.$format_version); + contract.free(); + }); + + it('should create a V1 contract with sizedIntegerTypes enabled', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.config.sizedIntegerTypes).to.be.true(); + contract.free(); + }); + + it('should create a V1 contract with correct document schemas', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.documentSchemas).to.deep.equal(contractFixtureV1.documentSchemas); + contract.free(); + }); + + it('should create a V1 contract with tokens', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.tokens).to.exist(); + expect(roundTripped.tokens['0']).to.exist(); + contract.free(); + }); + + it('should create a V1 contract with correct token baseSupply', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.tokens['0'].baseSupply).to.equal(100); + contract.free(); + }); + + it('should create a V1 contract with correct token decimals', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.tokens['0'].conventions.decimals).to.equal(0); + contract.free(); + }); + + it('should create a V1 contract with groups', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.groups).to.exist(); + expect(roundTripped.groups['0']).to.exist(); + contract.free(); + }); + + it('should create a V1 contract with correct group required_power', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.groups['0'].required_power).to.equal(2); + contract.free(); + }); + + it('should create a V1 contract with correct keywords', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + expect(roundTripped.keywords).to.deep.equal(contractFixtureV1.keywords); + contract.free(); + }); + }); + + describe('document-only contracts', () => { + it('should create a contract with only document schemas (no tokens)', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + + expect(roundTripped.documentSchemas.card).to.exist(); + expect(roundTripped.tokens).to.equal(undefined); + + contract.free(); + }); + }); + + describe('token-only contracts', () => { + it('should create a contract with only tokens (no documents)', () => { + const contractWithOnlyTokens = { + ...contractFixtureV1, + documentSchemas: {}, + }; + + const contract = sdk.DataContract.fromJSON( + contractWithOnlyTokens, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + + expect(roundTripped.documentSchemas).to.deep.equal({}); + + contract.free(); + }); + }); + + describe('version compatibility', () => { + it('should fail to create a V1 contract with V0 platform version', () => { + expect(() => { + sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + }).to.throw(/dpp unknown version.*known versions.*\[0\].*received.*1/); + }); + }); + + describe('input validation', () => { + it('should throw for null input', () => { + expect(() => { + sdk.DataContract.fromJSON(null, true, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should throw for empty object input', () => { + expect(() => { + sdk.DataContract.fromJSON({}, true, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should throw for object with only invalid id', () => { + expect(() => { + sdk.DataContract.fromJSON({ id: 'invalid' }, true, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + }); + }); + + describe('fromValue()', () => { + describe('input validation', () => { + it('should reject invalid Base58 ID', () => { + expect(() => { + sdk.DataContract.fromValue({ + ...contractFixtureV0, + id: 'invalid-not-base58!', + }, true, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should reject negative version number', () => { + expect(() => { + sdk.DataContract.fromValue({ + ...contractFixtureV0, + version: -1, + }, true, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should reject invalid ownerId', () => { + expect(() => { + sdk.DataContract.fromValue({ + ...contractFixtureV0, + ownerId: 'not-a-valid-id', + }, true, PLATFORM_VERSION_CONTRACT_V0); + }).to.throw(); + }); + + it('should require at least one document type or token', () => { + const contractWithEmptySchemas = { + $format_version: '0', + id: contractFixtureV0.id, + ownerId: contractFixtureV0.ownerId, + version: 1, + config: contractFixtureV0.config, + documentSchemas: {}, + }; + + expect(() => { + sdk.DataContract.fromJSON( + contractWithEmptySchemas, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + }).to.throw(/must have at least one document type or token defined/); + }); + }); + }); + + describe('toJSON()', () => { + describe('V0 contract round-trip', () => { + it('should preserve all data through JSON round-trip', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V0); + + const contract2 = sdk.DataContract.fromJSON( + roundTripped, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const roundTripped2 = contract2.toJSON(PLATFORM_VERSION_CONTRACT_V0); + + expect(roundTripped2).to.deep.equal(roundTripped); + + contract.free(); + contract2.free(); + }); + }); + + describe('V1 contract round-trip', () => { + it('should preserve all data through JSON round-trip', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + + const contract2 = sdk.DataContract.fromJSON( + roundTripped, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const roundTripped2 = contract2.toJSON(PLATFORM_VERSION_CONTRACT_V1); + + expect(roundTripped2).to.deep.equal(roundTripped); + + contract.free(); + contract2.free(); + }); + + it('should preserve all data through JSON round-trip (object output)', () => { + const contract = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + const jsonRepresentation = contract.toJSON(PLATFORM_VERSION_CONTRACT_V1); + + const contract2 = sdk.DataContract.fromJSON( + jsonRepresentation, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + + expect(contract2.toJSON(PLATFORM_VERSION_CONTRACT_V1)).to.deep.equal(jsonRepresentation); + + contract.free(); + contract2.free(); + }); + }); + }); + + describe('free()', () => { + it('should handle memory management properly with multiple contracts', () => { + const contract1 = sdk.DataContract.fromJSON( + contractFixtureV0, + true, + PLATFORM_VERSION_CONTRACT_V0, + ); + const contract2 = sdk.DataContract.fromJSON( + contractFixtureV1, + true, + PLATFORM_VERSION_CONTRACT_V1, + ); + + expect(contract1.id.toBase58()).to.equal(contractFixtureV0.id); + expect(contract2.id.toBase58()).to.equal(contractFixtureV1.id); + + contract1.free(); + contract2.free(); + }); + }); + + describe('Platform Version Compatibility Matrix', () => { + describe('V0 Contract Compatibility', () => { + testContractAcrossVersions(contractFixtureV0, 'V0', V0_COMPATIBLE_VERSIONS); + }); + + describe('V1 Contract Compatibility', () => { + testContractAcrossVersions(contractFixtureV1, 'V1', V1_COMPATIBLE_VERSIONS, V0_ONLY_VERSIONS); + }); + + describe('Edge Cases', () => { + it('should fail with zero version', () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV0, true, 0); + }).to.throw(/unknown version|unknown platform version value/); + }); + + it('should fail with negative version', () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV0, true, -1); + }).to.throw(/unknown version|unknown platform version value/); + }); + + it('should fail with version beyond latest known', () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV0, true, LATEST_KNOWN_VERSION + 1); + }).to.throw(/unknown version|unknown platform version value/); + }); + + it('should fail with version far beyond reasonable range', () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV0, true, LATEST_KNOWN_VERSION * 10); + }).to.throw(/unknown version|unknown platform version value/); + }); + + it('should support V0 contract at V9 transition (backward compatibility)', () => { + const contract = sdk.DataContract.fromJSON(contractFixtureV0, true, 9); + expect(contract.id.toBase58()).to.equal(contractFixtureV0.id); + contract.free(); + }); + + it('should support V1 contract at V9 (first supported version)', () => { + const contractV1 = sdk.DataContract.fromJSON(contractFixtureV1, true, 9); + expect(contractV1.id.toBase58()).to.equal(contractFixtureV1.id); + contractV1.free(); + }); + + it('should fail V1 contract at V8 (last unsupported version)', () => { + expect(() => { + sdk.DataContract.fromJSON(contractFixtureV1, true, 8); + }).to.throw(/dpp unknown version/); + }); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/derivation.spec.mjs b/packages/wasm-sdk/tests/unit/derivation.spec.ts similarity index 76% rename from packages/wasm-sdk/tests/unit/derivation.spec.mjs rename to packages/wasm-sdk/tests/unit/derivation.spec.ts index 8a7c8c434b7..f60ad5119e3 100644 --- a/packages/wasm-sdk/tests/unit/derivation.spec.mjs +++ b/packages/wasm-sdk/tests/unit/derivation.spec.ts @@ -1,12 +1,13 @@ +import { expect } from './helpers/chai.ts'; import init, * as sdk from '../../dist/sdk.compressed.js'; -describe('Key derivation', () => { +describe('Key Derivation', () => { before(async () => { await init(); }); - describe('Path helpers (BIP44/DIP9/DIP13)', () => { - it('BIP44 mainnet/testnet', () => { + describe('derivationPathBip44Mainnet()', () => { + it('should derive BIP44 mainnet paths', () => { const m = sdk.WasmSdk.derivationPathBip44Mainnet(0, 0, 0); expect(m.purpose).to.equal(44); expect(m.coinType).to.equal(5); @@ -15,42 +16,58 @@ describe('Key derivation', () => { expect(m.index).to.equal(0); const expectedMain = `m/${m.purpose}'/${m.coinType}'/${m.account}'/${m.change}/${m.index}`; expect(expectedMain).to.equal("m/44'/5'/0'/0/0"); + }); + }); + describe('derivationPathBip44Testnet()', () => { + it('should derive BIP44 testnet paths', () => { const t = sdk.WasmSdk.derivationPathBip44Testnet(0, 0, 0); expect(t.coinType).to.equal(1); const expectedTest = `m/${t.purpose}'/${t.coinType}'/${t.account}'/${t.change}/${t.index}`; expect(expectedTest).to.equal("m/44'/1'/0'/0/0"); }); + }); - it('DIP9 mainnet/testnet', () => { + describe('derivationPathDip9Mainnet()', () => { + it('should derive DIP9 mainnet paths', () => { const m = sdk.WasmSdk.derivationPathDip9Mainnet(5, 0, 0); expect(m.purpose).to.equal(9); expect(m.coinType).to.equal(5); expect(m.account).to.equal(5); const expectedMain = `m/${m.purpose}'/${m.coinType}'/${m.account}'/${m.change}/${m.index}`; expect(expectedMain).to.equal("m/9'/5'/5'/0/0"); + }); + }); + describe('derivationPathDip9Testnet()', () => { + it('should derive DIP9 testnet paths', () => { const t = sdk.WasmSdk.derivationPathDip9Testnet(5, 0, 0); expect(t.coinType).to.equal(1); const expectedTest = `m/${t.purpose}'/${t.coinType}'/${t.account}'/${t.change}/${t.index}`; expect(expectedTest).to.equal("m/9'/1'/5'/0/0"); }); + }); - it('DIP13 mainnet/testnet', () => { + describe('derivationPathDip13Mainnet()', () => { + it('should derive DIP13 mainnet paths', () => { const m = sdk.WasmSdk.derivationPathDip13Mainnet(0); expect(m.path).to.equal("m/9'/5'/0'"); expect(m.purpose).to.equal(9); expect(m.description).to.equal('DIP13 HD identity key path'); + }); + }); + describe('derivationPathDip13Testnet()', () => { + it('should derive DIP13 testnet paths', () => { const t = sdk.WasmSdk.derivationPathDip13Testnet(0); expect(t.path).to.equal("m/9'/1'/0'"); }); }); - describe('Derive by path', () => { + describe('deriveKeyFromSeedWithPath()', () => { const seed = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; - it('BIP44 mainnet key', () => { + it('should derive BIP44 mainnet key', () => { const path = "m/44'/5'/0'/0/0"; const r = sdk.WasmSdk.deriveKeyFromSeedWithPath({ mnemonic: seed, passphrase: null, path, network: 'mainnet', @@ -61,7 +78,7 @@ describe('Key derivation', () => { expect(r.network).to.equal('mainnet'); }); - it('DIP13 authentication key', () => { + it('should derive DIP13 authentication key', () => { const path = "m/9'/5'/5'/0'/0'/0'/0'"; const r = sdk.WasmSdk.deriveKeyFromSeedWithPath({ mnemonic: seed, passphrase: null, path, network: 'mainnet', @@ -72,7 +89,7 @@ describe('Key derivation', () => { expect(r.address).to.be.a('string'); }); - it('with passphrase produces different address', () => { + it('should produce different address with passphrase', () => { const path = "m/44'/5'/0'/0/0"; const withPass = sdk.WasmSdk.deriveKeyFromSeedWithPath({ mnemonic: seed, passphrase: 'test passphrase', path, network: 'mainnet', @@ -83,7 +100,7 @@ describe('Key derivation', () => { expect(withPass.address).to.not.equal(withoutPass.address); }); - it('testnet address prefix', () => { + it('should use correct testnet address prefix', () => { const path = "m/44'/1'/0'/0/0"; const r = sdk.WasmSdk.deriveKeyFromSeedWithPath({ mnemonic: seed, passphrase: null, path, network: 'testnet', @@ -92,7 +109,7 @@ describe('Key derivation', () => { expect(r.address.startsWith('y')).to.equal(true); }); - it('DIP9 hardened vs non-hardened differ', () => { + it('should produce different keys for DIP9 hardened vs non-hardened', () => { const hardened = sdk.WasmSdk.deriveKeyFromSeedWithPath({ mnemonic: seed, passphrase: null, path: "m/9'/5'/5'/0/0", network: 'mainnet', }); @@ -103,11 +120,13 @@ describe('Key derivation', () => { }); }); - describe('DIP14 extended vectors', () => { + describe('deriveKeyFromSeedWithExtendedPath()', () => { const mnemonic = 'birth kingdom trash renew flavor utility donkey gasp regular alert pave layer'; - it('Vector 1: mixed hardened/non-hardened', () => { - const path = "m/0x775d3854c910b7dee436869c4724bed2fe0784e198b8a39f02bbb49d8ebcfc3b/0xf537439f36d04a15474ff7423e4b904a14373fafb37a41db74c84f1dbb5c89a6'/0x4c4592ca670c983fc43397dfd21a6f427fac9b4ac53cb4dcdc6522ec51e81e79/0"; + it('should derive DIP14 Vector 1: mixed hardened/non-hardened', () => { + const path = 'm/0x775d3854c910b7dee436869c4724bed2fe0784e198b8a39f02bbb49d8ebcfc3b' + + "/0xf537439f36d04a15474ff7423e4b904a14373fafb37a41db74c84f1dbb5c89a6'" + + '/0x4c4592ca670c983fc43397dfd21a6f427fac9b4ac53cb4dcdc6522ec51e81e79/0'; const r = sdk.WasmSdk.deriveKeyFromSeedWithExtendedPath({ mnemonic, passphrase: null, path, network: 'testnet', }); @@ -115,8 +134,10 @@ describe('Key derivation', () => { expect(r.xpub).to.be.a('string'); }); - it('Vector 2: multiple hardened with final non-hardened', () => { - const path = "m/9'/5'/15'/0'/0x555d3854c910b7dee436869c4724bed2fe0784e198b8a39f02bbb49d8ebcfc3a'/0xa137439f36d04a15474ff7423e4b904a14373fafb37a41db74c84f1dbb5c89b5'/0"; + it('should derive DIP14 Vector 2: multiple hardened with final non-hardened', () => { + const path = "m/9'/5'/15'/0'" + + "/0x555d3854c910b7dee436869c4724bed2fe0784e198b8a39f02bbb49d8ebcfc3a'" + + "/0xa137439f36d04a15474ff7423e4b904a14373fafb37a41db74c84f1dbb5c89b5'/0"; const r = sdk.WasmSdk.deriveKeyFromSeedWithExtendedPath({ mnemonic, passphrase: null, path, network: 'testnet', }); @@ -125,13 +146,13 @@ describe('Key derivation', () => { }); }); - describe('DIP15 DashPay contact keys', () => { + describe('deriveDashpayContactKey()', () => { const mnemonic = 'birth kingdom trash renew flavor utility donkey gasp regular alert pave layer'; // Hex without 0x prefix (we don't use 0x) const sender = '555d3854c910b7dee436869c4724bed2fe0784e198b8a39f02bbb49d8ebcfc3a'; const receiver = 'a137439f36d04a15474ff7423e4b904a14373fafb37a41db74c84f1dbb5c89b5'; - it('deterministic contact key for testnet', () => { + it('should derive deterministic DIP15 contact key for testnet', () => { const r1 = sdk.WasmSdk.deriveDashpayContactKey({ mnemonic, passphrase: null, senderIdentityId: sender, receiverIdentityId: receiver, account: 0, addressIndex: 0, network: 'testnet', }); @@ -158,7 +179,7 @@ describe('Key derivation', () => { expect(r1.xpub.startsWith('tpub')).to.equal(true); }); - it('changes when sender/receiver are swapped', () => { + it('should change DIP15 contact key when sender/receiver are swapped', () => { const a = sdk.WasmSdk.deriveDashpayContactKey({ mnemonic, passphrase: null, senderIdentityId: sender, receiverIdentityId: receiver, account: 0, addressIndex: 0, network: 'testnet', }); @@ -168,7 +189,7 @@ describe('Key derivation', () => { expect(a.privateKeyHex).to.not.equal(b.privateKeyHex); }); - it('differs between networks (testnet vs mainnet)', () => { + it('should differ DIP15 contact key between networks (testnet vs mainnet)', () => { const t = sdk.WasmSdk.deriveDashpayContactKey({ mnemonic, passphrase: null, senderIdentityId: sender, receiverIdentityId: receiver, account: 0, addressIndex: 0, network: 'testnet', }); diff --git a/packages/wasm-sdk/tests/unit/dpns-utils.spec.mjs b/packages/wasm-sdk/tests/unit/dpns-utils.spec.mjs deleted file mode 100644 index a7a9712d9a8..00000000000 --- a/packages/wasm-sdk/tests/unit/dpns-utils.spec.mjs +++ /dev/null @@ -1,33 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('DPNS utils (homograph + validation)', () => { - before(async () => { - await init(); - }); - it('convert to homograph safe retains allowed chars', () => { - expect(sdk.WasmSdk.dpnsConvertToHomographSafe('test')).to.equal('test'); - expect(sdk.WasmSdk.dpnsConvertToHomographSafe('test123')).to.equal('test123'); - expect(sdk.WasmSdk.dpnsConvertToHomographSafe('test-name')).to.equal('test-name'); - expect(sdk.WasmSdk.dpnsConvertToHomographSafe('TestName')).to.equal('testname'); - }); - - it('homograph conversions for o,i,l to 0/1/1', () => { - const input = 'IlIooLi'; - expect(sdk.WasmSdk.dpnsConvertToHomographSafe(input)).to.equal('1110011'); - }); - - it('preserves non-homograph unicode (lowercased)', () => { - expect(sdk.WasmSdk.dpnsConvertToHomographSafe('tеst')).to.equal('tеst'); - }); - - it('username validation basic rules', () => { - expect(sdk.WasmSdk.dpnsIsValidUsername('alice')).to.equal(true); - expect(sdk.WasmSdk.dpnsIsValidUsername('alice123')).to.equal(true); - expect(sdk.WasmSdk.dpnsIsValidUsername('alice-bob')).to.equal(true); - expect(sdk.WasmSdk.dpnsIsValidUsername('ab')).to.equal(false); - expect(sdk.WasmSdk.dpnsIsValidUsername('a'.repeat(64))).to.equal(false); - expect(sdk.WasmSdk.dpnsIsValidUsername('-alice')).to.equal(false); - expect(sdk.WasmSdk.dpnsIsValidUsername('alice-')).to.equal(false); - expect(sdk.WasmSdk.dpnsIsValidUsername('alice--bob')).to.equal(false); - }); -}); diff --git a/packages/wasm-sdk/tests/unit/dpns-utils.spec.ts b/packages/wasm-sdk/tests/unit/dpns-utils.spec.ts new file mode 100644 index 00000000000..cb671adc5b3 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/dpns-utils.spec.ts @@ -0,0 +1,69 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('WasmSdk', () => { + before(async () => { + await init(); + }); + + describe('dpnsConvertToHomographSafe()', () => { + it('should retain lowercase letters', () => { + expect(sdk.WasmSdk.dpnsConvertToHomographSafe('test')).to.equal('test'); + }); + + it('should retain numbers', () => { + expect(sdk.WasmSdk.dpnsConvertToHomographSafe('test123')).to.equal('test123'); + }); + + it('should retain hyphens', () => { + expect(sdk.WasmSdk.dpnsConvertToHomographSafe('test-name')).to.equal('test-name'); + }); + + it('should convert uppercase to lowercase', () => { + expect(sdk.WasmSdk.dpnsConvertToHomographSafe('TestName')).to.equal('testname'); + }); + + it('should convert homographs o, i, l to 0/1/1', () => { + const input = 'IlIooLi'; + expect(sdk.WasmSdk.dpnsConvertToHomographSafe(input)).to.equal('1110011'); + }); + + it('should preserve non-homograph unicode (lowercased)', () => { + expect(sdk.WasmSdk.dpnsConvertToHomographSafe('tеst')).to.equal('tеst'); + }); + }); + + describe('dpnsIsValidUsername()', () => { + it('should accept valid lowercase username', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('alice')).to.equal(true); + }); + + it('should accept username with numbers', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('alice123')).to.equal(true); + }); + + it('should accept username with hyphen in middle', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('alice-bob')).to.equal(true); + }); + + it('should reject username shorter than 3 characters', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('ab')).to.equal(false); + }); + + it('should reject username longer than 63 characters', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('a'.repeat(64))).to.equal(false); + }); + + it('should reject username starting with hyphen', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('-alice')).to.equal(false); + }); + + it('should reject username ending with hyphen', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('alice-')).to.equal(false); + }); + + it('should reject username with consecutive hyphens', () => { + expect(sdk.WasmSdk.dpnsIsValidUsername('alice--bob')).to.equal(false); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/errors.spec.mjs b/packages/wasm-sdk/tests/unit/errors.spec.mjs deleted file mode 100644 index fe506f2121d..00000000000 --- a/packages/wasm-sdk/tests/unit/errors.spec.mjs +++ /dev/null @@ -1,49 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('WasmSdkError shape (unit)', () => { - before(async () => { - await init(); - }); - - it('invalid network on generateKeyPair exposes InvalidArgument', () => { - try { - sdk.WasmSdk.generateKeyPair('invalid_network'); - expect.fail('expected to throw'); - } catch (e) { - // wasm-bindgen returns our WasmSdkError as an object, not necessarily instanceof Error - expect(e).to.be.instanceOf(sdk.WasmSdkError); - expect(e.name).to.equal('InvalidArgument'); - expect(e.message).to.match(/unsupported network name/i); - expect(e.retriable).to.equal(false); - expect(e.code).to.equal(-1); - } - }); - - it('invalid hex on keyPairFromHex exposes InvalidArgument', () => { - try { - sdk.WasmSdk.keyPairFromHex('zzzz', 'mainnet'); - expect.fail('expected to throw'); - } catch (e) { - expect(e).to.be.instanceOf(sdk.WasmSdkError); - expect(e.name).to.equal('InvalidArgument'); - expect(e.retriable).to.equal(false); - // either length or content validation may trigger first - expect(e.message).to.match(/Invalid hex|must be exactly 64/i); - } - }); - - it('invalid derivation path network exposes InvalidArgument', () => { - const seed = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; - const path = "m/44'/5'/0'/0/0"; - try { - sdk.WasmSdk.deriveKeyFromSeedWithPath({ - mnemonic: seed, passphrase: null, path, network: 'bogus', - }); - expect.fail('expected to throw'); - } catch (e) { - expect(e).to.be.instanceOf(sdk.WasmSdkError); - expect(e.name).to.equal('InvalidArgument'); - expect(e.message).to.match(/unsupported network name/i); - } - }); -}); diff --git a/packages/wasm-sdk/tests/unit/errors.spec.ts b/packages/wasm-sdk/tests/unit/errors.spec.ts new file mode 100644 index 00000000000..379306b1f86 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/errors.spec.ts @@ -0,0 +1,56 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('WasmSdkError', () => { + before(async () => { + await init(); + }); + + describe('generateKeyPair()', () => { + it('should expose InvalidArgument for invalid network', () => { + try { + sdk.WasmSdk.generateKeyPair('invalid_network'); + expect.fail('expected to throw'); + } catch (e) { + // wasm-bindgen returns our WasmSdkError as an object, not necessarily instanceof Error + expect(e).to.be.instanceOf(sdk.WasmSdkError); + expect(e.name).to.equal('InvalidArgument'); + expect(e.message).to.match(/unsupported network name/i); + expect(e.retriable).to.not.be.ok(); + expect(e.code).to.equal(-1); + } + }); + }); + + describe('keyPairFromHex()', () => { + it('should expose InvalidArgument for invalid hex', () => { + try { + sdk.WasmSdk.keyPairFromHex('zzzz', 'mainnet'); + expect.fail('expected to throw'); + } catch (e) { + expect(e).to.be.instanceOf(sdk.WasmSdkError); + expect(e.name).to.equal('InvalidArgument'); + expect(e.retriable).to.not.be.ok(); + // either length or content validation may trigger first + expect(e.message).to.match(/Invalid hex|must be exactly 64/i); + } + }); + }); + + describe('deriveKeyFromSeedWithPath()', () => { + it('should expose InvalidArgument for invalid network', () => { + const seed = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; + const path = "m/44'/5'/0'/0/0"; + try { + sdk.WasmSdk.deriveKeyFromSeedWithPath({ + mnemonic: seed, passphrase: null, path, network: 'bogus', + }); + expect.fail('expected to throw'); + } catch (e) { + expect(e).to.be.instanceOf(sdk.WasmSdkError); + expect(e.name).to.equal('InvalidArgument'); + expect(e.message).to.match(/unsupported network name/i); + } + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/extended-keys.spec.mjs b/packages/wasm-sdk/tests/unit/extended-keys.spec.ts similarity index 78% rename from packages/wasm-sdk/tests/unit/extended-keys.spec.mjs rename to packages/wasm-sdk/tests/unit/extended-keys.spec.ts index 326f154e5f7..68ea59fe6ec 100644 --- a/packages/wasm-sdk/tests/unit/extended-keys.spec.mjs +++ b/packages/wasm-sdk/tests/unit/extended-keys.spec.ts @@ -1,14 +1,15 @@ +import { expect } from './helpers/chai.ts'; import init, * as sdk from '../../dist/sdk.compressed.js'; -describe('Extended keys', () => { +describe('Extended Keys', () => { const TEST_MNEMONIC = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; before(async () => { await init(); }); - describe('deriveChildPublicKey - basic functionality', () => { - it('derives non-hardened child xpubs that differ by index', () => { + describe('deriveChildPublicKey()', () => { + it('should derive non-hardened child xpubs that differ by index', () => { const master = sdk.WasmSdk.deriveKeyFromSeedWithExtendedPath({ mnemonic: TEST_MNEMONIC, passphrase: null, @@ -25,25 +26,8 @@ describe('Extended keys', () => { expect(child1).to.be.a('string'); expect(child1).to.not.equal(child0); }); - }); - - describe('xprvToXpub - basic functionality', () => { - it('converts xprv to the expected xpub', () => { - const master = sdk.WasmSdk.deriveKeyFromSeedWithExtendedPath({ - mnemonic: TEST_MNEMONIC, - passphrase: null, - path: "m/44'/5'/0'", - network: 'mainnet', - }); - - const derivedXpub = sdk.WasmSdk.xprvToXpub(master.xprv); - expect(derivedXpub).to.be.a('string'); - expect(derivedXpub).to.equal(master.xpub); - }); - }); - describe('deriveChildPublicKey - error handling', () => { - it('throws when hardened=true', () => { + it('should throw when hardened=true', () => { const master = sdk.WasmSdk.deriveKeyFromSeedWithExtendedPath({ mnemonic: TEST_MNEMONIC, passphrase: null, @@ -55,7 +39,7 @@ describe('Extended keys', () => { .to.throw('Cannot derive hardened child from extended public key'); }); - it('throws when index is in hardened range', () => { + it('should throw when index is in hardened range', () => { const master = sdk.WasmSdk.deriveKeyFromSeedWithExtendedPath({ mnemonic: TEST_MNEMONIC, passphrase: null, @@ -68,14 +52,27 @@ describe('Extended keys', () => { .to.throw('Index is in hardened range'); }); - it('throws for invalid xpub input', () => { + it('should throw for invalid xpub input', () => { expect(() => sdk.WasmSdk.deriveChildPublicKey('invalid_xpub', 0, false)) .to.throw('Invalid extended public key'); }); }); - describe('xprvToXpub - error handling', () => { - it('throws for invalid xprv input', () => { + describe('xprvToXpub()', () => { + it('should convert xprv to the expected xpub', () => { + const master = sdk.WasmSdk.deriveKeyFromSeedWithExtendedPath({ + mnemonic: TEST_MNEMONIC, + passphrase: null, + path: "m/44'/5'/0'", + network: 'mainnet', + }); + + const derivedXpub = sdk.WasmSdk.xprvToXpub(master.xprv); + expect(derivedXpub).to.be.a('string'); + expect(derivedXpub).to.equal(master.xpub); + }); + + it('should throw for invalid xprv input', () => { expect(() => sdk.WasmSdk.xprvToXpub('invalid_xprv')) .to.throw('Invalid extended private key'); }); diff --git a/packages/wasm-sdk/tests/unit/fixtures/data-contract-v0-crypto-card-game.mjs b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v0-crypto-card-game.ts similarity index 100% rename from packages/wasm-sdk/tests/unit/fixtures/data-contract-v0-crypto-card-game.mjs rename to packages/wasm-sdk/tests/unit/fixtures/data-contract-v0-crypto-card-game.ts diff --git a/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs b/packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.ts similarity index 100% rename from packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.mjs rename to packages/wasm-sdk/tests/unit/fixtures/data-contract-v1-with-docs-tokens-groups.ts diff --git a/packages/wasm-sdk/tests/unit/helpers/chai.ts b/packages/wasm-sdk/tests/unit/helpers/chai.ts new file mode 100644 index 00000000000..fb49541b171 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/helpers/chai.ts @@ -0,0 +1,9 @@ +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import dirtyChai from 'dirty-chai'; + +chai.use(chaiAsPromised); +chai.use(dirtyChai); + +export const { expect } = chai; +export default chai; diff --git a/packages/wasm-sdk/tests/unit/key-generation.spec.mjs b/packages/wasm-sdk/tests/unit/key-generation.spec.mjs deleted file mode 100644 index 51e92a07062..00000000000 --- a/packages/wasm-sdk/tests/unit/key-generation.spec.mjs +++ /dev/null @@ -1,62 +0,0 @@ -import init, * as sdk from '../../dist/sdk.compressed.js'; - -describe('Keys and mnemonics', () => { - const TEST_MNEMONIC = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; - - before(async () => { - await init(); - }); - - describe('mnemonic', () => { - it('generates 12 and 24 words and validates', () => { - const m12 = sdk.WasmSdk.generateMnemonic({ wordCount: 12 }); - expect(m12.split(' ').length).to.equal(12); - expect(sdk.WasmSdk.validateMnemonic(m12)).to.equal(true); - - const m24 = sdk.WasmSdk.generateMnemonic({ wordCount: 24 }); - expect(m24.split(' ').length).to.equal(24); - expect(sdk.WasmSdk.validateMnemonic(m24)).to.equal(true); - }); - - it('supports language wordlists', () => { - const langs = ['en', 'es', 'fr', 'it', 'ja', 'ko', 'pt', 'cs']; - for (const lang of langs) { - const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: lang }); - expect(sdk.WasmSdk.validateMnemonic(m, lang)).to.equal(true); - } - }); - - it('converts mnemonic to seed (with/without passphrase)', () => { - const seed = sdk.WasmSdk.mnemonicToSeed(TEST_MNEMONIC); - expect(seed && seed.length).to.equal(64); - - const seed2 = sdk.WasmSdk.mnemonicToSeed(TEST_MNEMONIC, 'passphrase'); - expect(seed2 && seed2.length).to.equal(64); - expect(Buffer.from(seed2).toString('hex')).to.not.equal(Buffer.from(seed).toString('hex')); - }); - }); - - describe('key pairs and addresses', () => { - it('generates key pairs for mainnet/testnet', () => { - const kpM = sdk.WasmSdk.generateKeyPair('mainnet'); - expect(kpM.address.startsWith('X')).to.equal(true); - const kpT = sdk.WasmSdk.generateKeyPair('testnet'); - expect(kpT.address.startsWith('y')).to.equal(true); - }); - - it('derives address from pubkey equals generated address', () => { - const kp = sdk.WasmSdk.generateKeyPair('mainnet'); - const addr = sdk.WasmSdk.pubkeyToAddress(kp.publicKey, 'mainnet'); - expect(addr).to.equal(kp.address); - }); - - it('signs messages deterministically for same inputs', () => { - const kp = sdk.WasmSdk.generateKeyPair('mainnet'); - const msg = 'Hello, Dash!'; - const s1 = sdk.WasmSdk.signMessage(msg, kp.privateKeyWif); - const s2 = sdk.WasmSdk.signMessage(msg, kp.privateKeyWif); - expect(s1).to.be.a('string'); - expect(s1).to.equal(s2); - }); - }); -}); diff --git a/packages/wasm-sdk/tests/unit/key-generation.spec.ts b/packages/wasm-sdk/tests/unit/key-generation.spec.ts new file mode 100644 index 00000000000..d7902b3a593 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/key-generation.spec.ts @@ -0,0 +1,133 @@ +import { expect } from './helpers/chai.ts'; +import init, * as sdk from '../../dist/sdk.compressed.js'; + +describe('WasmSdk', () => { + const TEST_MNEMONIC = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; + + before(async () => { + await init(); + }); + + describe('generateMnemonic()', () => { + it('should generate a 12-word mnemonic', () => { + const m12 = sdk.WasmSdk.generateMnemonic({ wordCount: 12 }); + expect(m12.split(' ').length).to.equal(12); + }); + + it('should generate a 24-word mnemonic', () => { + const m24 = sdk.WasmSdk.generateMnemonic({ wordCount: 24 }); + expect(m24.split(' ').length).to.equal(24); + }); + + it('should generate valid 12-word mnemonic', () => { + const m12 = sdk.WasmSdk.generateMnemonic({ wordCount: 12 }); + expect(sdk.WasmSdk.validateMnemonic(m12)).to.equal(true); + }); + + it('should generate valid 24-word mnemonic', () => { + const m24 = sdk.WasmSdk.generateMnemonic({ wordCount: 24 }); + expect(sdk.WasmSdk.validateMnemonic(m24)).to.equal(true); + }); + + it('should support English wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'en' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'en')).to.equal(true); + }); + + it('should support Spanish wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'es' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'es')).to.equal(true); + }); + + it('should support French wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'fr' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'fr')).to.equal(true); + }); + + it('should support Italian wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'it' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'it')).to.equal(true); + }); + + it('should support Japanese wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'ja' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'ja')).to.equal(true); + }); + + it('should support Korean wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'ko' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'ko')).to.equal(true); + }); + + it('should support Portuguese wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'pt' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'pt')).to.equal(true); + }); + + it('should support Czech wordlist', () => { + const m = sdk.WasmSdk.generateMnemonic({ wordCount: 12, languageCode: 'cs' }); + expect(sdk.WasmSdk.validateMnemonic(m, 'cs')).to.equal(true); + }); + }); + + describe('validateMnemonic()', () => { + it('should validate a correct mnemonic', () => { + expect(sdk.WasmSdk.validateMnemonic(TEST_MNEMONIC)).to.equal(true); + }); + }); + + describe('mnemonicToSeed()', () => { + it('should convert mnemonic to 64-byte seed', () => { + const seed = sdk.WasmSdk.mnemonicToSeed(TEST_MNEMONIC); + expect(seed && seed.length).to.equal(64); + }); + + it('should convert mnemonic to seed with passphrase', () => { + const seed = sdk.WasmSdk.mnemonicToSeed(TEST_MNEMONIC, 'passphrase'); + expect(seed && seed.length).to.equal(64); + }); + + it('should produce different seeds with and without passphrase', () => { + const seed = sdk.WasmSdk.mnemonicToSeed(TEST_MNEMONIC); + const seed2 = sdk.WasmSdk.mnemonicToSeed(TEST_MNEMONIC, 'passphrase'); + expect(Buffer.from(seed2).toString('hex')).to.not.equal(Buffer.from(seed).toString('hex')); + }); + }); + + describe('generateKeyPair()', () => { + it('should generate mainnet address starting with X', () => { + const kp = sdk.WasmSdk.generateKeyPair('mainnet'); + expect(kp.address.startsWith('X')).to.equal(true); + }); + + it('should generate testnet address starting with y', () => { + const kp = sdk.WasmSdk.generateKeyPair('testnet'); + expect(kp.address.startsWith('y')).to.equal(true); + }); + }); + + describe('pubkeyToAddress()', () => { + it('should derive address from pubkey equal to generated address', () => { + const kp = sdk.WasmSdk.generateKeyPair('mainnet'); + const addr = sdk.WasmSdk.pubkeyToAddress(kp.publicKey, 'mainnet'); + expect(addr).to.equal(kp.address); + }); + }); + + describe('signMessage()', () => { + it('should return a string signature', () => { + const kp = sdk.WasmSdk.generateKeyPair('mainnet'); + const msg = 'Hello, Dash!'; + const sig = sdk.WasmSdk.signMessage(msg, kp.privateKeyWif); + expect(sig).to.be.a('string'); + }); + + it('should produce deterministic signatures for same inputs', () => { + const kp = sdk.WasmSdk.generateKeyPair('mainnet'); + const msg = 'Hello, Dash!'; + const s1 = sdk.WasmSdk.signMessage(msg, kp.privateKeyWif); + const s2 = sdk.WasmSdk.signMessage(msg, kp.privateKeyWif); + expect(s1).to.equal(s2); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenBurnResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenBurnResult.spec.ts new file mode 100644 index 00000000000..e51b6ef4d5f --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenBurnResult.spec.ts @@ -0,0 +1,93 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenBurnResult', () => { + const testIdentifier = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with all fields', () => { + const data = { + ownerId: testIdentifier, + remainingBalance: 500000n, + groupPower: 100, + groupActionStatus: 'ActionNeeded', + }; + + const result = sdk.TokenBurnResult.fromObject(data); + + expect(result.ownerId.toBase58()).to.equal(testIdentifier); + expect(result.remainingBalance).to.equal(500000n); + expect(result.groupPower).to.equal(100); + expect(result.groupActionStatus).to.equal('ActionNeeded'); + }); + + it('should handle null optional fields', () => { + const data = { + ownerId: testIdentifier, + remainingBalance: 100n, + }; + + const result = sdk.TokenBurnResult.fromObject(data); + expect(result.ownerId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.be.undefined(); + expect(result.groupActionStatus).to.be.undefined(); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + ownerId: testIdentifier, + remainingBalance: 500000n, + groupPower: 100, + groupActionStatus: 'ActionNeeded', + }; + + const result = sdk.TokenBurnResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenBurnResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(100); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + ownerId: testIdentifier, + remainingBalance: 500000, + groupPower: 80, + groupActionStatus: 'Completed', + }; + + const result = sdk.TokenBurnResult.fromJSON(data); + expect(result.ownerId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(80); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + ownerId: testIdentifier, + remainingBalance: 500000, + groupPower: 80, + groupActionStatus: 'Completed', + }; + + const result = sdk.TokenBurnResult.fromJSON(data); + const json = result.toJSON(); + + expect(json.ownerId).to.equal(testIdentifier); + expect(json.groupPower).to.equal(80); + + const roundtrip = sdk.TokenBurnResult.fromJSON(json); + expect(roundtrip.ownerId.toBase58()).to.equal(testIdentifier); + expect(roundtrip.groupPower).to.equal(80); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenClaimResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenClaimResult.spec.ts new file mode 100644 index 00000000000..6132e35b243 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenClaimResult.spec.ts @@ -0,0 +1,65 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenClaimResult', () => { + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with groupPower', () => { + const data = { + groupPower: 33, + }; + + const result = sdk.TokenClaimResult.fromObject(data); + expect(result.groupPower).to.equal(33); + expect(result.document).to.be.undefined(); + }); + + it('should handle empty data', () => { + const data = {}; + + const result = sdk.TokenClaimResult.fromObject(data); + expect(result.groupPower).to.be.undefined(); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + groupPower: 33, + }; + + const result = sdk.TokenClaimResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenClaimResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(33); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + groupPower: 42, + }; + + const result = sdk.TokenClaimResult.fromJSON(data); + expect(result.groupPower).to.equal(42); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + groupPower: 42, + }; + + const result = sdk.TokenClaimResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenClaimResult.fromJSON(json); + expect(roundtrip.groupPower).to.equal(42); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenDestroyFrozenResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenDestroyFrozenResult.spec.ts new file mode 100644 index 00000000000..daac9ea13d0 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenDestroyFrozenResult.spec.ts @@ -0,0 +1,65 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenDestroyFrozenResult', () => { + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with groupPower', () => { + const data = { + groupPower: 90, + }; + + const result = sdk.TokenDestroyFrozenResult.fromObject(data); + expect(result.groupPower).to.equal(90); + expect(result.document).to.be.undefined(); + }); + + it('should handle empty data', () => { + const data = {}; + + const result = sdk.TokenDestroyFrozenResult.fromObject(data); + expect(result.groupPower).to.be.undefined(); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + groupPower: 90, + }; + + const result = sdk.TokenDestroyFrozenResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenDestroyFrozenResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(90); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + groupPower: 85, + }; + + const result = sdk.TokenDestroyFrozenResult.fromJSON(data); + expect(result.groupPower).to.equal(85); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + groupPower: 85, + }; + + const result = sdk.TokenDestroyFrozenResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenDestroyFrozenResult.fromJSON(json); + expect(roundtrip.groupPower).to.equal(85); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenDirectPurchaseResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenDirectPurchaseResult.spec.ts new file mode 100644 index 00000000000..e74e9af1cd3 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenDirectPurchaseResult.spec.ts @@ -0,0 +1,85 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenDirectPurchaseResult', () => { + const testIdentifier = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with all fields', () => { + const data = { + buyerId: testIdentifier, + newBalance: 2000000n, + groupPower: 55, + }; + + const result = sdk.TokenDirectPurchaseResult.fromObject(data); + + expect(result.buyerId.toBase58()).to.equal(testIdentifier); + expect(result.newBalance).to.equal(2000000n); + expect(result.groupPower).to.equal(55); + }); + + it('should handle group action without balance', () => { + const data = { + groupPower: 30, + }; + + const result = sdk.TokenDirectPurchaseResult.fromObject(data); + expect(result.buyerId).to.be.undefined(); + expect(result.newBalance).to.be.undefined(); + expect(result.groupPower).to.equal(30); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + buyerId: testIdentifier, + newBalance: 2000000n, + groupPower: 55, + }; + + const result = sdk.TokenDirectPurchaseResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenDirectPurchaseResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(55); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + buyerId: testIdentifier, + newBalance: 2000000, + groupPower: 40, + }; + + const result = sdk.TokenDirectPurchaseResult.fromJSON(data); + + expect(result.buyerId.toBase58()).to.equal(testIdentifier); + expect(result.newBalance).to.equal(2000000n); + expect(result.groupPower).to.equal(40); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + buyerId: testIdentifier, + newBalance: 2000000, + groupPower: 40, + }; + + const result = sdk.TokenDirectPurchaseResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenDirectPurchaseResult.fromJSON(json); + expect(roundtrip.buyerId.toBase58()).to.equal(testIdentifier); + expect(roundtrip.groupPower).to.equal(40); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenEmergencyActionResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenEmergencyActionResult.spec.ts new file mode 100644 index 00000000000..b8a9e3bb094 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenEmergencyActionResult.spec.ts @@ -0,0 +1,65 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenEmergencyActionResult', () => { + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with groupPower', () => { + const data = { + groupPower: 55, + }; + + const result = sdk.TokenEmergencyActionResult.fromObject(data); + expect(result.groupPower).to.equal(55); + expect(result.document).to.be.undefined(); + }); + + it('should handle empty data', () => { + const data = {}; + + const result = sdk.TokenEmergencyActionResult.fromObject(data); + expect(result.groupPower).to.be.undefined(); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + groupPower: 55, + }; + + const result = sdk.TokenEmergencyActionResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenEmergencyActionResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(55); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + groupPower: 45, + }; + + const result = sdk.TokenEmergencyActionResult.fromJSON(data); + expect(result.groupPower).to.equal(45); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + groupPower: 45, + }; + + const result = sdk.TokenEmergencyActionResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenEmergencyActionResult.fromJSON(json); + expect(roundtrip.groupPower).to.equal(45); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenFreezeResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenFreezeResult.spec.ts new file mode 100644 index 00000000000..f55808b1f89 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenFreezeResult.spec.ts @@ -0,0 +1,78 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenFreezeResult', () => { + const testIdentifier = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with all fields', () => { + const data = { + frozenIdentityId: testIdentifier, + groupPower: 80, + }; + + const result = sdk.TokenFreezeResult.fromObject(data); + + expect(result.frozenIdentityId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(80); + }); + + it('should handle group action without identity', () => { + const data = { + groupPower: 45, + }; + + const result = sdk.TokenFreezeResult.fromObject(data); + expect(result.frozenIdentityId).to.be.undefined(); + expect(result.groupPower).to.equal(45); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + frozenIdentityId: testIdentifier, + groupPower: 80, + }; + + const result = sdk.TokenFreezeResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenFreezeResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(80); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + frozenIdentityId: testIdentifier, + groupPower: 60, + }; + + const result = sdk.TokenFreezeResult.fromJSON(data); + + expect(result.frozenIdentityId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(60); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + frozenIdentityId: testIdentifier, + groupPower: 60, + }; + + const result = sdk.TokenFreezeResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenFreezeResult.fromJSON(json); + expect(roundtrip.frozenIdentityId.toBase58()).to.equal(testIdentifier); + expect(roundtrip.groupPower).to.equal(60); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenMintResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenMintResult.spec.ts new file mode 100644 index 00000000000..9c439bb5063 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenMintResult.spec.ts @@ -0,0 +1,100 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenMintResult', () => { + const testIdentifier = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with all fields', () => { + const data = { + recipientId: testIdentifier, + newBalance: 1000000n, + groupPower: 75, + groupActionStatus: 'Completed', + }; + + const result = sdk.TokenMintResult.fromObject(data); + + expect(result.recipientId.toBase58()).to.equal(testIdentifier); + expect(result.newBalance).to.equal(1000000n); + expect(result.groupPower).to.equal(75); + expect(result.groupActionStatus).to.equal('Completed'); + expect(result.document).to.be.undefined(); + }); + + it('should handle optional fields being undefined', () => { + const data = { + groupPower: 25, + }; + + const result = sdk.TokenMintResult.fromObject(data); + expect(result.recipientId).to.be.undefined(); + expect(result.newBalance).to.be.undefined(); + expect(result.groupPower).to.equal(25); + expect(result.groupActionStatus).to.be.undefined(); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + recipientId: testIdentifier, + newBalance: 1000000n, + groupPower: 75, + groupActionStatus: 'Completed', + }; + + const result = sdk.TokenMintResult.fromObject(data); + const obj = result.toObject(); + expect(obj.groupPower).to.equal(75); + expect(obj.groupActionStatus).to.equal('Completed'); + + const roundtrip = sdk.TokenMintResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(75); + expect(roundtrip.groupActionStatus).to.equal('Completed'); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + recipientId: testIdentifier, + newBalance: 1000000, + groupPower: 50, + groupActionStatus: 'Pending', + }; + + const result = sdk.TokenMintResult.fromJSON(data); + expect(result.recipientId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(50); + expect(result.groupActionStatus).to.equal('Pending'); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + recipientId: testIdentifier, + newBalance: 1000000, + groupPower: 50, + groupActionStatus: 'Pending', + }; + + const result = sdk.TokenMintResult.fromJSON(data); + const json = result.toJSON(); + + expect(json.recipientId).to.equal(testIdentifier); + expect(json.groupPower).to.equal(50); + expect(json.groupActionStatus).to.equal('Pending'); + + const roundtrip = sdk.TokenMintResult.fromJSON(json); + expect(roundtrip.recipientId.toBase58()).to.equal(testIdentifier); + expect(roundtrip.groupPower).to.equal(50); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenSetPriceResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenSetPriceResult.spec.ts new file mode 100644 index 00000000000..30df6f38c24 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenSetPriceResult.spec.ts @@ -0,0 +1,89 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenSetPriceResult', () => { + const testIdentifier = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with all fields', () => { + const data = { + ownerId: testIdentifier, + groupPower: 70, + groupActionStatus: 'Approved', + }; + + const result = sdk.TokenSetPriceResult.fromObject(data); + + expect(result.ownerId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(70); + expect(result.groupActionStatus).to.equal('Approved'); + // pricingSchedule is skipped in serde, so it won't be present + expect(result.pricingSchedule).to.be.undefined(); + }); + + it('should handle group action without owner', () => { + const data = { + groupPower: 50, + groupActionStatus: 'Pending', + }; + + const result = sdk.TokenSetPriceResult.fromObject(data); + expect(result.ownerId).to.be.undefined(); + expect(result.groupPower).to.equal(50); + expect(result.groupActionStatus).to.equal('Pending'); + expect(result.pricingSchedule).to.be.undefined(); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + ownerId: testIdentifier, + groupPower: 70, + groupActionStatus: 'Approved', + }; + + const result = sdk.TokenSetPriceResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenSetPriceResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(70); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + ownerId: testIdentifier, + groupPower: 70, + groupActionStatus: 'Approved', + }; + + const result = sdk.TokenSetPriceResult.fromJSON(data); + + expect(result.ownerId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(70); + expect(result.groupActionStatus).to.equal('Approved'); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + ownerId: testIdentifier, + groupPower: 70, + groupActionStatus: 'Approved', + }; + + const result = sdk.TokenSetPriceResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenSetPriceResult.fromJSON(json); + expect(roundtrip.ownerId.toBase58()).to.equal(testIdentifier); + expect(roundtrip.groupPower).to.equal(70); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenTransferResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenTransferResult.spec.ts new file mode 100644 index 00000000000..ae0d3cdc0d0 --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenTransferResult.spec.ts @@ -0,0 +1,82 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenTransferResult', () => { + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with all fields', () => { + const data = { + senderBalance: 900000n, + recipientBalance: 100000n, + groupPower: 25, + }; + + const result = sdk.TokenTransferResult.fromObject(data); + + expect(result.senderBalance).to.equal(900000n); + expect(result.recipientBalance).to.equal(100000n); + expect(result.groupPower).to.equal(25); + }); + + it('should handle group action without balances', () => { + const data = { + groupPower: 50, + }; + + const result = sdk.TokenTransferResult.fromObject(data); + expect(result.senderBalance).to.be.undefined(); + expect(result.recipientBalance).to.be.undefined(); + expect(result.groupPower).to.equal(50); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + senderBalance: 900000n, + recipientBalance: 100000n, + groupPower: 25, + }; + + const result = sdk.TokenTransferResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenTransferResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(25); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + senderBalance: 900000, + recipientBalance: 100000, + groupPower: 25, + }; + + const result = sdk.TokenTransferResult.fromJSON(data); + + expect(result.senderBalance).to.equal(900000n); + expect(result.recipientBalance).to.equal(100000n); + expect(result.groupPower).to.equal(25); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + senderBalance: 900000, + recipientBalance: 100000, + groupPower: 25, + }; + + const result = sdk.TokenTransferResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenTransferResult.fromJSON(json); + expect(roundtrip.groupPower).to.equal(25); + }); + }); +}); diff --git a/packages/wasm-sdk/tests/unit/token-results/TokenUnfreezeResult.spec.ts b/packages/wasm-sdk/tests/unit/token-results/TokenUnfreezeResult.spec.ts new file mode 100644 index 00000000000..3319b6cf69e --- /dev/null +++ b/packages/wasm-sdk/tests/unit/token-results/TokenUnfreezeResult.spec.ts @@ -0,0 +1,78 @@ +import { expect } from '../helpers/chai.ts'; +import init, * as sdk from '../../../dist/sdk.compressed.js'; + +describe('TokenUnfreezeResult', () => { + const testIdentifier = 'H2pb35GtKpjLinncBYeMsXkdDYXCbsFzzVmssce6pSJ1'; + + before(async () => { + await init(); + }); + + describe('fromObject()', () => { + it('should create result from object with all fields', () => { + const data = { + unfrozenIdentityId: testIdentifier, + groupPower: 70, + }; + + const result = sdk.TokenUnfreezeResult.fromObject(data); + + expect(result.unfrozenIdentityId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(70); + }); + + it('should handle group action without identity', () => { + const data = { + groupPower: 35, + }; + + const result = sdk.TokenUnfreezeResult.fromObject(data); + expect(result.unfrozenIdentityId).to.be.undefined(); + expect(result.groupPower).to.equal(35); + expect(result.document).to.be.undefined(); + }); + }); + + describe('toObject()', () => { + it('should round-trip through toObject/fromObject', () => { + const data = { + unfrozenIdentityId: testIdentifier, + groupPower: 70, + }; + + const result = sdk.TokenUnfreezeResult.fromObject(data); + const obj = result.toObject(); + const roundtrip = sdk.TokenUnfreezeResult.fromObject(obj); + expect(roundtrip.groupPower).to.equal(70); + }); + }); + + describe('fromJSON()', () => { + it('should create result from JSON', () => { + const data = { + unfrozenIdentityId: testIdentifier, + groupPower: 60, + }; + + const result = sdk.TokenUnfreezeResult.fromJSON(data); + + expect(result.unfrozenIdentityId.toBase58()).to.equal(testIdentifier); + expect(result.groupPower).to.equal(60); + }); + }); + + describe('toJSON()', () => { + it('should round-trip through toJSON/fromJSON', () => { + const data = { + unfrozenIdentityId: testIdentifier, + groupPower: 60, + }; + + const result = sdk.TokenUnfreezeResult.fromJSON(data); + const json = result.toJSON(); + const roundtrip = sdk.TokenUnfreezeResult.fromJSON(json); + expect(roundtrip.unfrozenIdentityId.toBase58()).to.equal(testIdentifier); + expect(roundtrip.groupPower).to.equal(60); + }); + }); +}); diff --git a/packages/withdrawals-contract/.eslintrc b/packages/withdrawals-contract/.eslintrc deleted file mode 100644 index cb6c7636b60..00000000000 --- a/packages/withdrawals-contract/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "airbnb-base", - "rules": { - "no-plusplus": 0, - "eol-last": [ - "error", - "always" - ], - "class-methods-use-this": "off", - "curly": [ - "error", - "all" - ] - }, - "globals": { - "BigInt": true - } -} diff --git a/packages/withdrawals-contract/eslint.config.mjs b/packages/withdrawals-contract/eslint.config.mjs new file mode 100644 index 00000000000..cdf50e57d0d --- /dev/null +++ b/packages/withdrawals-contract/eslint.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from '../../eslint/base.mjs'; +import mochaTestConfig from '../../eslint/mocha-tests.mjs'; + +export default [ + ...baseConfig, + mochaTestConfig, + { + ignores: ['dist/**', 'node_modules/**'], + }, +]; diff --git a/packages/withdrawals-contract/package.json b/packages/withdrawals-contract/package.json index 01ac9cbaa19..43c3a33f89e 100644 --- a/packages/withdrawals-contract/package.json +++ b/packages/withdrawals-contract/package.json @@ -35,9 +35,7 @@ "@dashevo/wasm-dpp": "workspace:*", "chai": "^4.3.10", "dirty-chai": "^2.0.1", - "eslint": "^8.53.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.29.0", + "eslint": "^9.18.0", "mocha": "^11.1.0", "sinon": "^17.0.1", "sinon-chai": "^3.7.0" diff --git a/packages/withdrawals-contract/test/.eslintrc b/packages/withdrawals-contract/test/.eslintrc deleted file mode 100644 index 720ced73852..00000000000 --- a/packages/withdrawals-contract/test/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "rules": { - "import/no-extraneous-dependencies": "off" - }, - "globals": { - "expect": true - } -} diff --git a/yarn.lock b/yarn.lock index 52e34b2fb5e..0592157998a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -80,7 +80,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.22.13": +"@babel/code-frame@npm:^7.0.0": version: 7.22.13 resolution: "@babel/code-frame@npm:7.22.13" dependencies: @@ -101,6 +101,17 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/code-frame@npm:7.28.6" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.28.5" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10/93e7ed9e039e3cb661bdb97c26feebafacc6ec13d745881dae5c7e2708f579475daebe7a3b5d23b183bb940b30744f52f4a5bcb65b4df03b79d82fcb38495784 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": version: 7.23.3 resolution: "@babel/compat-data@npm:7.23.3" @@ -115,6 +126,36 @@ __metadata: languageName: node linkType: hard +"@babel/compat-data@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/compat-data@npm:7.28.6" + checksum: 10/dc17dfb55711a15f006e34c4610c49b7335fc11b23e192f9e5f625e8ea0f48805e61a57b6b4f5550879332782c93af0b5d6952825fffbb8d4e604b14d698249f + languageName: node + linkType: hard + +"@babel/core@npm:^7.24.4": + version: 7.28.6 + resolution: "@babel/core@npm:7.28.6" + dependencies: + "@babel/code-frame": "npm:^7.28.6" + "@babel/generator": "npm:^7.28.6" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helpers": "npm:^7.28.6" + "@babel/parser": "npm:^7.28.6" + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + "@jridgewell/remapping": "npm:^2.3.5" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10/1a150a69c547daf13c457be1fdaf1a0935d02b94605e777e049537ec2f279b4bb442ffbe1c2d8ff62c688878b1d5530a5784daf72ece950d1917fb78717f51d2 + languageName: node + linkType: hard + "@babel/core@npm:^7.26.10, @babel/core@npm:^7.7.5": version: 7.26.10 resolution: "@babel/core@npm:7.26.10" @@ -138,32 +179,6 @@ __metadata: languageName: node linkType: hard -"@babel/eslint-parser@npm:^7.26.10": - version: 7.26.10 - resolution: "@babel/eslint-parser@npm:7.26.10" - dependencies: - "@nicolo-ribaudo/eslint-scope-5-internals": "npm:5.1.1-v1" - eslint-visitor-keys: "npm:^2.1.0" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - checksum: 10/27eb60d16b8963ea587a54b4bc8bce9b63f7a294455fd00aa6e8f8a45d10ea9b52f89a9d951ff80c226bddbc09c316a3aa63b531fdfa389cf31d1db8d7080796 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/generator@npm:7.23.3" - dependencies: - "@babel/types": "npm:^7.23.3" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" - jsesc: "npm:^2.5.1" - checksum: 10/0f815d275cb3de97ec4724b959b3c7a67b1cde1861eda6612b50c6ba22565f12536d1f004dd48e7bad5e059751950265c6ff546ef48b7a719a11d7b512f1e29d - languageName: node - linkType: hard - "@babel/generator@npm:^7.26.10": version: 7.26.10 resolution: "@babel/generator@npm:7.26.10" @@ -177,6 +192,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/generator@npm:7.28.6" + dependencies: + "@babel/parser": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10/ef2af927e8e0985d02ec4321a242da761a934e927539147c59fdd544034dc7f0e9846f6bf86209aca7a28aee2243ed0fad668adccd48f96d7d6866215173f9af + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" @@ -221,6 +249,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-compilation-targets@npm:7.28.6" + dependencies: + "@babel/compat-data": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10/f512a5aeee4dfc6ea8807f521d085fdca8d66a7d068a6dd5e5b37da10a6081d648c0bbf66791a081e4e8e6556758da44831b331540965dfbf4f5275f3d0a8788 + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.25.9": version: 7.26.9 resolution: "@babel/helper-create-class-features-plugin@npm:7.26.9" @@ -279,29 +320,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-environment-visitor@npm:7.22.20" - checksum: 10/d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-function-name@npm:7.23.0" - dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/types": "npm:^7.23.0" - checksum: 10/7b2ae024cd7a09f19817daf99e0153b3bf2bc4ab344e197e8d13623d5e36117ed0b110914bc248faa64e8ccd3e97971ec7b41cc6fd6163a2b980220c58dcdf6d - languageName: node - linkType: hard - -"@babel/helper-hoist-variables@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-hoist-variables@npm:7.22.5" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc +"@babel/helper-globals@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/helper-globals@npm:7.28.0" + checksum: 10/91445f7edfde9b65dcac47f4f858f68dc1661bf73332060ab67ad7cc7b313421099a2bfc4bda30c3db3842cfa1e86fffbb0d7b2c5205a177d91b22c8d7d9cb47 languageName: node linkType: hard @@ -325,6 +347,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-imports@npm:7.28.6" + dependencies: + "@babel/traverse": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10/64b1380d74425566a3c288074d7ce4dea56d775d2d3325a3d4a6df1dca702916c1d268133b6f385de9ba5b822b3c6e2af5d3b11ac88e5453d5698d77264f0ec0 + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.25.9, @babel/helper-module-transforms@npm:^7.26.0": version: 7.26.0 resolution: "@babel/helper-module-transforms@npm:7.26.0" @@ -338,6 +370,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-transforms@npm:7.28.6" + dependencies: + "@babel/helper-module-imports": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/2e421c7db743249819ee51e83054952709dc2e197c7d5d415b4bdddc718580195704bfcdf38544b3f674efc2eccd4d29a65d38678fc827ed3934a7690984cd8b + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-optimise-call-expression@npm:7.25.9" @@ -397,15 +442,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/helper-split-export-declaration@npm:7.22.6" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 - languageName: node - linkType: hard - "@babel/helper-string-parser@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-string-parser@npm:7.22.5" @@ -420,6 +456,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-string-parser@npm:7.27.1" + checksum: 10/0ae29cc2005084abdae2966afdb86ed14d41c9c37db02c3693d5022fba9f5d59b011d039380b8e537c34daf117c549f52b452398f576e908fb9db3c7abbb3a00 + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.22.20": version: 7.22.20 resolution: "@babel/helper-validator-identifier@npm:7.22.20" @@ -434,6 +477,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-validator-identifier@npm:7.28.5" + checksum: 10/8e5d9b0133702cfacc7f368bf792f0f8ac0483794877c6dca5fcb73810ee138e27527701826fb58a40a004f3a5ec0a2f3c3dd5e326d262530b119918f3132ba7 + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.22.15": version: 7.22.15 resolution: "@babel/helper-validator-option@npm:7.22.15" @@ -448,6 +498,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-option@npm:7.27.1" + checksum: 10/db73e6a308092531c629ee5de7f0d04390835b21a263be2644276cb27da2384b64676cab9f22cd8d8dbd854c92b1d7d56fc8517cf0070c35d1c14a8c828b0903 + languageName: node + linkType: hard + "@babel/helper-wrap-function@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-wrap-function@npm:7.25.9" @@ -469,6 +526,16 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helpers@npm:7.28.6" + dependencies: + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10/213485cdfffc4deb81fc1bf2cefed61bc825049322590ef69690e223faa300a2a4d1e7d806c723bb1f1f538226b9b1b6c356ca94eb47fa7c6d9e9f251ee425e6 + languageName: node + linkType: hard + "@babel/highlight@npm:^7.22.13": version: 7.22.20 resolution: "@babel/highlight@npm:7.22.20" @@ -480,12 +547,14 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.3, @babel/parser@npm:^7.7.0": - version: 7.23.3 - resolution: "@babel/parser@npm:7.23.3" +"@babel/parser@npm:^7.24.4, @babel/parser@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/parser@npm:7.28.6" + dependencies: + "@babel/types": "npm:^7.28.6" bin: parser: ./bin/babel-parser.js - checksum: 10/284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a + checksum: 10/483a6fb5f9876ec9cbbb98816f2c94f39ae4d1158d35f87e1c4bf19a1f56027c96a1a3962ff0c8c46e8322a6d9e1c80d26b7f9668410df13d5b5769d9447b010 languageName: node linkType: hard @@ -1297,17 +1366,6 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/template@npm:7.22.15" - dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/parser": "npm:^7.22.15" - "@babel/types": "npm:^7.22.15" - checksum: 10/21e768e4eed4d1da2ce5d30aa51db0f4d6d8700bc1821fec6292587df7bba2fe1a96451230de8c64b989740731888ebf1141138bfffb14cacccf4d05c66ad93f - languageName: node - linkType: hard - "@babel/template@npm:^7.25.9, @babel/template@npm:^7.26.9": version: 7.26.9 resolution: "@babel/template@npm:7.26.9" @@ -1319,6 +1377,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/template@npm:7.28.6" + dependencies: + "@babel/code-frame": "npm:^7.28.6" + "@babel/parser": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10/0ad6e32bf1e7e31bf6b52c20d15391f541ddd645cbd488a77fe537a15b280ee91acd3a777062c52e03eedbc2e1f41548791f6a3697c02476ec5daf49faa38533 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.10, @babel/traverse@npm:^7.26.5, @babel/traverse@npm:^7.26.8, @babel/traverse@npm:^7.26.9": version: 7.26.10 resolution: "@babel/traverse@npm:7.26.10" @@ -1334,25 +1403,22 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.7.0": - version: 7.23.3 - resolution: "@babel/traverse@npm:7.23.3" - dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 10/522ef8eefe1ed31cd392129efb2f8794ca25bd54b1ad7c3bfa7f46d20c47ef0e392d5c1654ddee3454eed5e546d04c9bfa38b04b82e47144aa545f87ba55572d +"@babel/traverse@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/traverse@npm:7.28.6" + dependencies: + "@babel/code-frame": "npm:^7.28.6" + "@babel/generator": "npm:^7.28.6" + "@babel/helper-globals": "npm:^7.28.0" + "@babel/parser": "npm:^7.28.6" + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + debug: "npm:^4.3.1" + checksum: 10/dd71efe9412433169b805d5c346a6473e539ce30f605752a0d40a0733feba37259bd72bb4ad2ab591e2eaff1ee56633de160c1e98efdc8f373cf33a4a8660275 languageName: node linkType: hard -"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.0, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4": version: 7.23.3 resolution: "@babel/types@npm:7.23.3" dependencies: @@ -1373,6 +1439,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/types@npm:7.28.6" + dependencies: + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.28.5" + checksum: 10/f9c6e52b451065aae5654686ecfc7de2d27dd0fbbc204ee2bd912a71daa359521a32f378981b1cf333ace6c8f86928814452cb9f388a7da59ad468038deb6b5f + languageName: node + linkType: hard + "@balena/dockerignore@npm:^1.0.2": version: 1.0.2 resolution: "@balena/dockerignore@npm:1.0.2" @@ -1415,13 +1491,10 @@ __metadata: "@dashevo/dpns-contract": "workspace:*" "@dashevo/wallet-lib": "workspace:*" "@dashevo/wasm-dpp": "workspace:*" - babel-eslint: "npm:^10.1.0" console-table-printer: "npm:^2.11.0" dash: "workspace:*" dotenv-safe: "npm:^8.2.0" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" lodash: "npm:^4.17.23" mathjs: "npm:^10.4.3" mocha: "npm:^11.1.0" @@ -1459,10 +1532,7 @@ __metadata: core-js: "npm:^3.33.1" crypto-browserify: "npm:^3.12.1" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" - eslint-plugin-jsdoc: "npm:^46.9.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" google-protobuf: "npm:^3.12.2" karma: "npm:^6.4.3" @@ -1505,9 +1575,7 @@ __metadata: chai: "npm:^4.3.10" chai-as-promised: "npm:^7.1.1" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" google-protobuf: "npm:^3.12.2" long: "npm:^5.2.0" mocha: "npm:^11.1.0" @@ -1522,7 +1590,6 @@ __metadata: resolution: "@dashevo/dapi@workspace:packages/dapi" dependencies: "@babel/core": "npm:^7.26.10" - "@babel/eslint-parser": "npm:^7.26.10" "@dashevo/bls": "npm:~1.2.9" "@dashevo/dapi-client": "workspace:*" "@dashevo/dapi-grpc": "workspace:*" @@ -1542,9 +1609,7 @@ __metadata: dotenv: "npm:^8.6.0" dotenv-expand: "npm:^5.1.0" dotenv-safe: "npm:^8.2.0" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" google-protobuf: "npm:^3.12.2" jayson: "npm:^4.1.0" lodash: "npm:^4.17.23" @@ -1577,9 +1642,7 @@ __metadata: "@dashevo/dash-util": "npm:^2.0.3" "@dashevo/dashcore-lib": "npm:~0.22.0" chai: "npm:^4.3.10" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" levelup: "npm:^4.4.0" memdown: "npm:^5.1.0" mocha: "npm:^11.1.0" @@ -1646,9 +1709,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -1684,9 +1745,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -1698,18 +1757,17 @@ __metadata: resolution: "@dashevo/evo-sdk@workspace:packages/js-evo-sdk" dependencies: "@dashevo/wasm-sdk": "workspace:*" - "@typescript-eslint/eslint-plugin": "npm:^5.55.0" - "@typescript-eslint/parser": "npm:^5.55.0" + "@types/chai": "npm:^4.3.11" + "@types/mocha": "npm:^10.0.6" + "@types/node": "npm:^20.10.0" + "@types/sinon": "npm:^9.0.4" + "@types/sinon-chai": "npm:^3.2.4" assert: "npm:^2.0.0" buffer: "npm:^6.0.3" chai: "npm:^4.3.10" chai-as-promised: "npm:^7.1.1" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-config-airbnb-typescript: "npm:^17.0.0" - eslint-plugin-import: "npm:^2.29.0" - eslint-plugin-jsdoc: "npm:^46.9.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" @@ -1726,7 +1784,8 @@ __metadata: string_decoder: "npm:^1.3.0" terser-webpack-plugin: "npm:^5.3.11" ts-loader: "npm:^9.5.0" - typescript: "npm:^3.9.5" + ts-node: "npm:^10.9.2" + typescript: "npm:^5.7.3" url: "npm:^0.11.3" util: "npm:^0.12.4" webpack: "npm:^5.94.0" @@ -1741,9 +1800,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -1761,9 +1818,7 @@ __metadata: chai: "npm:^4.3.10" chai-as-promised: "npm:^7.1.1" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" lodash: "npm:^4.17.23" long: "npm:^5.2.0" mocha: "npm:^11.1.0" @@ -1782,9 +1837,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -1798,9 +1851,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -1831,9 +1882,7 @@ __metadata: dash: "workspace:*" dirty-chai: "npm:^2.0.1" dotenv-safe: "npm:^8.2.0" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" glob: "npm:^10.3.4" https-browserify: "npm:^1.0.0" @@ -1876,13 +1925,19 @@ __metadata: resolution: "@dashevo/platform@workspace:." dependencies: "@iarna/toml": "npm:^2.2.5" + "@typescript-eslint/parser": "npm:^8.0.0" add-stream: "npm:^1.0.0" conventional-changelog: "npm:^3.1.24" conventional-changelog-dash: "github:dashevo/conventional-changelog-dash" dompurify: "npm:^3.2.6" + eslint: "npm:^9.18.0" + eslint-config-airbnb-extended: "npm:^3.0.1" + eslint-plugin-jsdoc: "npm:^50.6.3" + globals: "npm:^15.14.0" node-gyp: "npm:^10.0.1" semver: "npm:^7.5.3" tempfile: "npm:^3.0.0" + typescript: "npm:^5.7.3" ultra-runner: "npm:^3.10.5" languageName: unknown linkType: soft @@ -1918,9 +1973,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -1947,9 +2000,7 @@ __metadata: crypto-js: "npm:^4.2.0" dirty-chai: "npm:^2.0.1" dotenv-safe: "npm:^8.2.0" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" https-browserify: "npm:^1.0.0" karma: "npm:^6.4.3" @@ -1991,9 +2042,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -2004,16 +2053,16 @@ __metadata: version: 0.0.0-use.local resolution: "@dashevo/wasm-dpp2@workspace:packages/wasm-dpp2" dependencies: + "@types/chai": "npm:^4.3.11" + "@types/mocha": "npm:^10.0.6" + "@types/node": "npm:^20.10.0" assert: "npm:^2.0.0" bs58: "npm:^4.0.1" buffer: "npm:^6.0.3" chai: "npm:^4.3.10" chai-as-promised: "npm:^7.1.1" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" - eslint-plugin-jsdoc: "npm:^46.9.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" @@ -2026,6 +2075,9 @@ __metadata: path-browserify: "npm:^1.0.1" process: "npm:^0.11.10" string_decoder: "npm:^1.3.0" + ts-loader: "npm:^9.5.0" + ts-node: "npm:^10.9.2" + typescript: "npm:^5.7.3" url: "npm:^0.11.3" util: "npm:^0.12.4" webpack: "npm:^5.94.0" @@ -2045,7 +2097,7 @@ __metadata: "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/dpns-contract": "workspace:*" "@types/bs58": "npm:^4.0.1" - "@types/node": "npm:^14.6.0" + "@types/node": "npm:^20.10.0" "@yarnpkg/pnpify": "npm:^4.0.0-rc.42" ajv: "npm:^8.6.0" assert: "npm:^2.0.0" @@ -2057,9 +2109,7 @@ __metadata: chai-string: "npm:^1.5.0" crypto-browserify: "npm:^3.12.1" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" fast-json-patch: "npm:^3.1.1" https-browserify: "npm:^1.0.0" @@ -2083,7 +2133,7 @@ __metadata: string_decoder: "npm:^1.3.0" ts-loader: "npm:^9.5.0" tsd: "npm:^0.28.1" - typescript: "npm:^3.9.5" + typescript: "npm:^5.7.3" url: "npm:^0.11.3" util: "npm:^0.12.4" varint: "npm:^6.0.0" @@ -2096,15 +2146,15 @@ __metadata: version: 0.0.0-use.local resolution: "@dashevo/wasm-sdk@workspace:packages/wasm-sdk" dependencies: + "@types/chai": "npm:^4.3.11" + "@types/mocha": "npm:^10.0.6" + "@types/node": "npm:^20.10.0" assert: "npm:^2.0.0" buffer: "npm:^6.0.3" chai: "npm:^4.3.10" chai-as-promised: "npm:^7.1.1" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" - eslint-plugin-jsdoc: "npm:^46.9.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" @@ -2117,6 +2167,9 @@ __metadata: path-browserify: "npm:^1.0.1" process: "npm:^0.11.10" string_decoder: "npm:^1.3.0" + ts-loader: "npm:^9.5.0" + ts-node: "npm:^10.9.2" + typescript: "npm:^5.7.3" url: "npm:^0.11.3" util: "npm:^0.12.4" webpack: "npm:^5.94.0" @@ -2131,9 +2184,7 @@ __metadata: "@dashevo/wasm-dpp": "workspace:*" chai: "npm:^4.3.10" dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" mocha: "npm:^11.1.0" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" @@ -2154,18 +2205,59 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.41.0": - version: 0.41.0 - resolution: "@es-joy/jsdoccomment@npm:0.41.0" +"@emnapi/core@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/core@npm:1.8.1" + dependencies: + "@emnapi/wasi-threads": "npm:1.1.0" + tslib: "npm:^2.4.0" + checksum: 10/904ea60c91fc7d8aeb4a8f2c433b8cfb47c50618f2b6f37429fc5093c857c6381c60628a5cfbc3a7b0d75b0a288f21d4ed2d4533e82f92c043801ef255fd6a5c + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/runtime@npm:1.8.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/26725e202d4baefdc4a6ba770f703dfc80825a27c27a08c22bac1e1ce6f8f75c47b4fe9424d9b63239463c33ef20b650f08d710da18dfa1164a95e5acb865dba + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.1.0": + version: 1.1.0 + resolution: "@emnapi/wasi-threads@npm:1.1.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/0d557e75262d2f4c95cb2a456ba0785ef61f919ce488c1d76e5e3acfd26e00c753ef928cd80068363e0c166ba8cc0141305daf0f81aad5afcd421f38f11e0f4e + languageName: node + linkType: hard + +"@es-joy/jsdoccomment@npm:~0.50.2": + version: 0.50.2 + resolution: "@es-joy/jsdoccomment@npm:0.50.2" dependencies: + "@types/estree": "npm:^1.0.6" + "@typescript-eslint/types": "npm:^8.11.0" comment-parser: "npm:1.4.1" - esquery: "npm:^1.5.0" - jsdoc-type-pratt-parser: "npm:~4.0.0" - checksum: 10/ea581983f32ccc6550f0cb8a1d7178c74c4cbf18add8e18725b2db5ea6021016b49fb93e55e928caf7f2d08007779c0cda71c3fbbfdb92400ebc4f3a07c993f9 + esquery: "npm:^1.6.0" + jsdoc-type-pratt-parser: "npm:~4.1.0" + checksum: 10/a309f01bd1691c6991e5efb78057ec9122ef33208fec2464d7b9e5838964b948fa46c9c944a09218a752b49267f05ac15b557018c8a1897fd8df47b944b4537f + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": + version: 4.9.1 + resolution: "@eslint-community/eslint-utils@npm:4.9.1" + dependencies: + eslint-visitor-keys: "npm:^3.4.3" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 10/863b5467868551c9ae34d03eefe634633d08f623fc7b19d860f8f26eb6f303c1a5934253124163bee96181e45ed22bf27473dccc295937c3078493a4a8c9eddd languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": +"@eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: @@ -2176,34 +2268,80 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: 10/8c36169c815fc5d726078e8c71a5b592957ee60d08c6470f9ce0187c8046af1a00afbda0a065cc40ff18d5d83f82aed9793c6818f7304a74a7488dc9f3ecbd42 +"@eslint-community/regexpp@npm:^4.11.0, @eslint-community/regexpp@npm:^4.12.1, @eslint-community/regexpp@npm:^4.12.2": + version: 4.12.2 + resolution: "@eslint-community/regexpp@npm:4.12.2" + checksum: 10/049b280fddf71dd325514e0a520024969431dc3a8b02fa77476e6820e9122f28ab4c9168c11821f91a27982d2453bcd7a66193356ea84e84fb7c8d793be1ba0c languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.3": - version: 2.1.3 - resolution: "@eslint/eslintrc@npm:2.1.3" +"@eslint/config-array@npm:^0.21.1": + version: 0.21.1 + resolution: "@eslint/config-array@npm:0.21.1" + dependencies: + "@eslint/object-schema": "npm:^2.1.7" + debug: "npm:^4.3.1" + minimatch: "npm:^3.1.2" + checksum: 10/6eaa0435972f735ce52d581f355a0b616e50a9b8a73304a7015398096e252798b9b3b968a67b524eefb0fdeacc57c4d960f0ec6432abe1c1e24be815b88c5d18 + languageName: node + linkType: hard + +"@eslint/config-helpers@npm:^0.4.2": + version: 0.4.2 + resolution: "@eslint/config-helpers@npm:0.4.2" + dependencies: + "@eslint/core": "npm:^0.17.0" + checksum: 10/3f2b4712d8e391c36ec98bc200f7dea423dfe518e42956569666831b89ede83b33120c761dfd3ab6347d8e8894a6d4af47254a18d464a71c6046fd88065f6daf + languageName: node + linkType: hard + +"@eslint/core@npm:^0.17.0": + version: 0.17.0 + resolution: "@eslint/core@npm:0.17.0" + dependencies: + "@types/json-schema": "npm:^7.0.15" + checksum: 10/f9a428cc651ec15fb60d7d60c2a7bacad4666e12508320eafa98258e976fafaa77d7be7be91519e75f801f15f830105420b14a458d4aab121a2b0a59bc43517b + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^3.3.1": + version: 3.3.3 + resolution: "@eslint/eslintrc@npm:3.3.3" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" - espree: "npm:^9.6.0" - globals: "npm:^13.19.0" + espree: "npm:^10.0.1" + globals: "npm:^14.0.0" ignore: "npm:^5.2.0" import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.0" + js-yaml: "npm:^4.1.1" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: 10/77b70a89232fe702c2f765b5b92970f5e4224b55363b923238b996c66fcd991504f40d3663c0543ae17d6c5049ab9b07ab90b65d7601e6f25e8bcd4caf69ac75 + checksum: 10/b586a364ff15ce1b68993aefc051ca330b1fece15fb5baf4a708d00113f9a14895cffd84a5f24c5a97bd4b4321130ab2314f90aa462a250f6b859c2da2cba1f3 + languageName: node + linkType: hard + +"@eslint/js@npm:9.39.2": + version: 9.39.2 + resolution: "@eslint/js@npm:9.39.2" + checksum: 10/6b7f676746f3111b5d1b23715319212ab9297868a0fa9980d483c3da8965d5841673aada2d5653e85a3f7156edee0893a7ae7035211b4efdcb2848154bb947f2 + languageName: node + linkType: hard + +"@eslint/object-schema@npm:^2.1.7": + version: 2.1.7 + resolution: "@eslint/object-schema@npm:2.1.7" + checksum: 10/946ef5d6235b4d1c0907c6c6e6429c8895f535380c562b7705c131f63f2e961b06e8785043c86a293da48e0a60c6286d98ba395b8b32ea55561fe6e4417cb7e4 languageName: node linkType: hard -"@eslint/js@npm:8.53.0": - version: 8.53.0 - resolution: "@eslint/js@npm:8.53.0" - checksum: 10/a372d55aa2bbe0d9399acc8de3c892dcfe507fd914d29fde6826ae54a13452619be626aa7eb70b1ec4d4da5302b6ed8e8ac9bf1f830003f15c0ad56c30b4f520 +"@eslint/plugin-kit@npm:^0.4.1": + version: 0.4.1 + resolution: "@eslint/plugin-kit@npm:0.4.1" + dependencies: + "@eslint/core": "npm:^0.17.0" + levn: "npm:^0.4.1" + checksum: 10/c5947d0ffeddca77d996ac1b886a66060c1a15ed1d5e425d0c7e7d7044a4bd3813fc968892d03950a7831c9b89368a2f7b281e45dd3c74a048962b74bf3a1cb4 languageName: node linkType: hard @@ -2265,14 +2403,20 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13": - version: 0.11.13 - resolution: "@humanwhocodes/config-array@npm:0.11.13" +"@humanfs/core@npm:^0.19.1": + version: 0.19.1 + resolution: "@humanfs/core@npm:0.19.1" + checksum: 10/270d936be483ab5921702623bc74ce394bf12abbf57d9145a69e8a0d1c87eb1c768bd2d93af16c5705041e257e6d9cc7529311f63a1349f3678abc776fc28523 + languageName: node + linkType: hard + +"@humanfs/node@npm:^0.16.6": + version: 0.16.7 + resolution: "@humanfs/node@npm:0.16.7" dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.1" - debug: "npm:^4.1.1" - minimatch: "npm:^3.0.5" - checksum: 10/9f655e1df7efa5a86822cd149ca5cef57240bb8ffd728f0c07cc682cc0a15c6bdce68425fbfd58f9b3e8b16f79b3fd8cb1e96b10c434c9a76f20b2a89f213272 + "@humanfs/core": "npm:^0.19.1" + "@humanwhocodes/retry": "npm:^0.4.0" + checksum: 10/b3633d3dce898592cac515ba5e6693c78e6be92863541d3eaf2c009b10f52b2fa62ff6e6e06f240f2447ddbe7b5f1890bc34e9308470675c876eee207553a08d languageName: node linkType: hard @@ -2283,10 +2427,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.1": - version: 2.0.1 - resolution: "@humanwhocodes/object-schema@npm:2.0.1" - checksum: 10/dbddfd0465aecf92ed845ec30d06dba3f7bb2496d544b33b53dac7abc40370c0e46b8787b268d24a366730d5eeb5336ac88967232072a183905ee4abf7df4dab +"@humanwhocodes/retry@npm:^0.4.0, @humanwhocodes/retry@npm:^0.4.2": + version: 0.4.3 + resolution: "@humanwhocodes/retry@npm:0.4.3" + checksum: 10/0b32cfd362bea7a30fbf80bb38dcaf77fee9c2cae477ee80b460871d03590110ac9c77d654f04ec5beaf71b6f6a89851bdf6c1e34ccdf2f686bd86fcd97d9e61 languageName: node linkType: hard @@ -2315,6 +2459,22 @@ __metadata: languageName: node linkType: hard +"@isaacs/balanced-match@npm:^4.0.1": + version: 4.0.1 + resolution: "@isaacs/balanced-match@npm:4.0.1" + checksum: 10/102fbc6d2c0d5edf8f6dbf2b3feb21695a21bc850f11bc47c4f06aa83bd8884fde3fe9d6d797d619901d96865fdcb4569ac2a54c937992c48885c5e3d9967fe8 + languageName: node + linkType: hard + +"@isaacs/brace-expansion@npm:^5.0.0": + version: 5.0.0 + resolution: "@isaacs/brace-expansion@npm:5.0.0" + dependencies: + "@isaacs/balanced-match": "npm:^4.0.1" + checksum: 10/cf3b7f206aff12128214a1df764ac8cdbc517c110db85249b945282407e3dfc5c6e66286383a7c9391a059fc8e6e6a8ca82262fc9d2590bd615376141fbebd2d + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -2374,7 +2534,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": +"@jridgewell/gen-mapping@npm:^0.3.0": version: 0.3.3 resolution: "@jridgewell/gen-mapping@npm:0.3.3" dependencies: @@ -2385,6 +2545,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/gen-mapping@npm:^0.3.12": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10/902f8261dcf450b4af7b93f9656918e02eec80a2169e155000cb2059f90113dd98f3ccf6efc6072cee1dd84cac48cade51da236972d942babc40e4c23da4d62a + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" @@ -2396,6 +2566,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10/c2bb01856e65b506d439455f28aceacf130d6c023d1d4e3b48705e88def3571753e1a887daa04b078b562316c92d26ce36408a60534bceca3f830aec88a339ad + languageName: node + linkType: hard + "@jridgewell/resolve-uri@npm:3.1.0, @jridgewell/resolve-uri@npm:^3.0.3": version: 3.1.0 resolution: "@jridgewell/resolve-uri@npm:3.1.0" @@ -2448,6 +2628,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10/5d9d207b462c11e322d71911e55e21a4e2772f71ffe8d6f1221b8eb5ae6774458c1d242f897fb0814e8714ca9a6b498abfa74dfe4f434493342902b1a48b33a5 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:0.3.9": version: 0.3.9 resolution: "@jridgewell/trace-mapping@npm:0.3.9" @@ -2458,16 +2645,6 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.18 - resolution: "@jridgewell/trace-mapping@npm:0.3.18" - dependencies: - "@jridgewell/resolve-uri": "npm:3.1.0" - "@jridgewell/sourcemap-codec": "npm:1.4.14" - checksum: 10/f4fabdddf82398a797bcdbb51c574cd69b383db041a6cae1a6a91478681d6aab340c01af655cfd8c6e01cde97f63436a1445f08297cdd33587621cf05ffa0d55 - languageName: node - linkType: hard - "@jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" @@ -2478,6 +2655,26 @@ __metadata: languageName: node linkType: hard +"@jridgewell/trace-mapping@npm:^0.3.28": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10/da0283270e691bdb5543806077548532791608e52386cfbbf3b9e8fb00457859d1bd01d512851161c886eb3a2f3ce6fd9bcf25db8edf3bddedd275bd4a88d606 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.18 + resolution: "@jridgewell/trace-mapping@npm:0.3.18" + dependencies: + "@jridgewell/resolve-uri": "npm:3.1.0" + "@jridgewell/sourcemap-codec": "npm:1.4.14" + checksum: 10/f4fabdddf82398a797bcdbb51c574cd69b383db041a6cae1a6a91478681d6aab340c01af655cfd8c6e01cde97f63436a1445f08297cdd33587621cf05ffa0d55 + languageName: node + linkType: hard + "@js-sdsl/ordered-map@npm:^4.4.2": version: 4.4.2 resolution: "@js-sdsl/ordered-map@npm:4.4.2" @@ -2499,19 +2696,30 @@ __metadata: languageName: node linkType: hard -"@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3": - version: 2.1.8-no-fsevents.3 - resolution: "@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3" - checksum: 10/c6e83af3b5051a3f6562649ff8fe37de9934a4cc02138678ed1badbd13ed3334f7ae5f63f2bbc3432210f6b245f082ac97e9b2afe0c13730c9838b295658c185 +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10/5fd518182427980c28bc724adf06c5f32f9a8915763ef560b5f7d73607d30cd15ac86d0cbd2eb80d4cfab23fc80d0876d89ca36a9daadcb864bc00917c94187c languageName: node linkType: hard -"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": - version: 5.1.1-v1 - resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" +"@next/eslint-plugin-next@npm:^16.1.4": + version: 16.1.5 + resolution: "@next/eslint-plugin-next@npm:16.1.5" dependencies: - eslint-scope: "npm:5.1.1" - checksum: 10/f2e3b2d6a6e2d9f163ca22105910c9f850dc4897af0aea3ef0a5886b63d8e1ba6505b71c99cb78a3bba24a09557d601eb21c8dede3f3213753fcfef364eb0e57 + fast-glob: "npm:3.3.1" + checksum: 10/8846e6a0142b0bfbf4b08617650d0cdaf8944fa2d24a6905d69dab0c2823e5832a4041c4639c191024fb79b16f0f0174b8afb49fd684d3cbcf5bf26153e6b061 + languageName: node + linkType: hard + +"@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3": + version: 2.1.8-no-fsevents.3 + resolution: "@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3" + checksum: 10/c6e83af3b5051a3f6562649ff8fe37de9934a4cc02138678ed1badbd13ed3334f7ae5f63f2bbc3432210f6b245f082ac97e9b2afe0c13730c9838b295658c185 languageName: node linkType: hard @@ -2532,7 +2740,7 @@ __metadata: languageName: node linkType: hard -"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": +"@nodelib/fs.walk@npm:^1.2.3": version: 1.2.8 resolution: "@nodelib/fs.walk@npm:1.2.8" dependencies: @@ -3142,6 +3350,13 @@ __metadata: languageName: node linkType: hard +"@rtsao/scc@npm:^1.1.0": + version: 1.1.0 + resolution: "@rtsao/scc@npm:1.1.0" + checksum: 10/17d04adf404e04c1e61391ed97bca5117d4c2767a76ae3e879390d6dec7b317fcae68afbf9e98badee075d0b64fa60f287729c4942021b4d19cd01db77385c01 + languageName: node + linkType: hard + "@sigstore/bundle@npm:^1.1.0": version: 1.1.0 resolution: "@sigstore/bundle@npm:1.1.0" @@ -3288,6 +3503,22 @@ __metadata: languageName: node linkType: hard +"@stylistic/eslint-plugin@npm:^5.7.0": + version: 5.7.1 + resolution: "@stylistic/eslint-plugin@npm:5.7.1" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/types": "npm:^8.53.1" + eslint-visitor-keys: "npm:^4.2.1" + espree: "npm:^10.4.0" + estraverse: "npm:^5.3.0" + picomatch: "npm:^4.0.3" + peerDependencies: + eslint: ">=9.0.0" + checksum: 10/df50c60e111e79342c2a677c05fff13b02206a0480e3b3fe17e1faf901147e1a2339994b1106a38cc835d20b7b313f1e3e6c9b111b117128ad15cecc9b107c1c + languageName: node + linkType: hard + "@szmarczak/http-timer@npm:^4.0.5": version: 4.0.6 resolution: "@szmarczak/http-timer@npm:4.0.6" @@ -3365,6 +3596,15 @@ __metadata: languageName: node linkType: hard +"@tybys/wasm-util@npm:^0.10.0": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/7fe0d239397aebb002ac4855d30c197c06a05ea8df8511350a3a5b1abeefe26167c60eda8a5508337571161e4c4b53d7c1342296123f9607af8705369de9fa7f + languageName: node + linkType: hard + "@types/bs58@npm:^4.0.1": version: 4.0.4 resolution: "@types/bs58@npm:4.0.4" @@ -3396,13 +3636,20 @@ __metadata: languageName: node linkType: hard -"@types/chai@npm:*, @types/chai@npm:^4.2.12": +"@types/chai@npm:*": version: 4.2.22 resolution: "@types/chai@npm:4.2.22" checksum: 10/948096612d7e21d5922bf3fe280de465f7219d77dbe69ae1a7183e0d0ce116174b9e078d80bf8eefc9df1c93186de98ec3430bb3d992a5ea47b84ce4b4c0ae9e languageName: node linkType: hard +"@types/chai@npm:^4.3.11": + version: 4.3.20 + resolution: "@types/chai@npm:4.3.20" + checksum: 10/94fd87036fb63f62c79caf58ccaec88e23cc109e4d41607d83adc609acd6b24eabc345feb7850095a53f76f99c470888251da9bd1b90849c8b2b5a813296bb19 + languageName: node + linkType: hard + "@types/cli-progress@npm:^3.11.0, @types/cli-progress@npm:^3.11.5": version: 3.11.5 resolution: "@types/cli-progress@npm:3.11.5" @@ -3476,6 +3723,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:^1.0.6": + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 + languageName: node + linkType: hard + "@types/expect@npm:^1.20.4": version: 1.20.4 resolution: "@types/expect@npm:1.20.4" @@ -3490,7 +3744,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 10/1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 @@ -3527,10 +3781,10 @@ __metadata: languageName: node linkType: hard -"@types/mocha@npm:^8.0.3": - version: 8.2.3 - resolution: "@types/mocha@npm:8.2.3" - checksum: 10/c768b67d8fe95f46eadfcda0cfb9c45e5cf3069093327e77f34c1a7be0b2dc519bb8ccce15f986f62e68048adce7004e27cb9fbdcf7e9492f9aa9c90e2156d12 +"@types/mocha@npm:^10.0.6": + version: 10.0.10 + resolution: "@types/mocha@npm:10.0.10" + checksum: 10/4e3b61ed5112add86891a5dd3ebdd087714f5e1784a63d47a96424c0825058fd07074e85e43573462f751636c92808fc18a5f3862fe45e649ea98fdc5a3ee2ea languageName: node linkType: hard @@ -3562,13 +3816,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^14.6.0": - version: 14.17.34 - resolution: "@types/node@npm:14.17.34" - checksum: 10/a7e23fc63ccbf37f07f64580a045866617639c870ec8243de589837b6f8268a809c52eb46da561cdc9df04f6d812b2850acef574707ab03be12b578e4f1485ae - languageName: node - linkType: hard - "@types/node@npm:^15.6.1": version: 15.14.9 resolution: "@types/node@npm:15.14.9" @@ -3576,6 +3823,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.10.0": + version: 20.19.30 + resolution: "@types/node@npm:20.19.30" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10/4a25e5cbcdfc61b9bf45ebbbd199a6ce26efed34bd67c45c3472654a1cf988f7b58ec7c1574ffb5b83c6a772e7eaf1ca9de94fdafc3a36ae6efb852c1f0b6fb0 + languageName: node + linkType: hard + "@types/normalize-package-data@npm:^2.4.0": version: 2.4.1 resolution: "@types/normalize-package-data@npm:2.4.1" @@ -3592,7 +3848,7 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.1.0, @types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": +"@types/semver@npm:^7.1.0, @types/semver@npm:^7.5.0": version: 7.5.5 resolution: "@types/semver@npm:7.5.5" checksum: 10/1b0be2c4d830f5ef002a305308e06e3616fc38a41c9a2c5b4267df82a038d9bd0ba32ec1da82a52db84a720be7e4b69bac7593797d8dc1400a69069af8f19219 @@ -3667,54 +3923,52 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/eslint-plugin@npm:5.55.0" +"@typescript-eslint/eslint-plugin@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.54.0" dependencies: - "@eslint-community/regexpp": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:5.55.0" - "@typescript-eslint/type-utils": "npm:5.55.0" - "@typescript-eslint/utils": "npm:5.55.0" - debug: "npm:^4.3.4" - grapheme-splitter: "npm:^1.0.4" - ignore: "npm:^5.2.0" - natural-compare-lite: "npm:^1.4.0" - semver: "npm:^7.3.7" - tsutils: "npm:^3.21.0" + "@eslint-community/regexpp": "npm:^4.12.2" + "@typescript-eslint/scope-manager": "npm:8.54.0" + "@typescript-eslint/type-utils": "npm:8.54.0" + "@typescript-eslint/utils": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" + ignore: "npm:^7.0.5" + natural-compare: "npm:^1.4.0" + ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/05f921647ab120c4f7fbc36ce7c13dc0bbd160abc77347a816f706d6eb7076076e83aa1676a2e409448a654c8d733e27a8c8f741b270276f13a198330ccc6eb3 + "@typescript-eslint/parser": ^8.54.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/8f1c74ac77d7a84ae3f201bb09cb67271662befed036266af1eaa0653d09b545353441640516c1c86e0a94939887d32f0473c61a642488b14d46533742bfbd1b languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/parser@npm:5.55.0" +"@typescript-eslint/parser@npm:8.54.0, @typescript-eslint/parser@npm:^8.0.0": + version: 8.54.0 + resolution: "@typescript-eslint/parser@npm:8.54.0" dependencies: - "@typescript-eslint/scope-manager": "npm:5.55.0" - "@typescript-eslint/types": "npm:5.55.0" - "@typescript-eslint/typescript-estree": "npm:5.55.0" - debug: "npm:^4.3.4" + "@typescript-eslint/scope-manager": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" + debug: "npm:^4.4.3" peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/a7c48c1d397b896be5b835b12c30cba6b183d4e73b94dece45d17b7c2cc34a3a5a16d53b545c4881656104a02a5e647837ed374460098b6ad4fca99ba5286857 + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/d2e09462c9966ef3deeba71d9e41d1d4876c61eea65888c93a3db6fba48b89a2165459c6519741d40e969da05ed98d3f4c87a7f56c5521ab5699743cc315f6cb languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/scope-manager@npm:5.55.0" +"@typescript-eslint/project-service@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/project-service@npm:8.54.0" dependencies: - "@typescript-eslint/types": "npm:5.55.0" - "@typescript-eslint/visitor-keys": "npm:5.55.0" - checksum: 10/a089b0f45bb83122f9801f42a91519eac1edf73d6fa678ae1471900f3da5ad2966d396fb47348ed948150ad66d471896d5ff8669350586bd9671fe278bcda01a + "@typescript-eslint/tsconfig-utils": "npm:^8.54.0" + "@typescript-eslint/types": "npm:^8.54.0" + debug: "npm:^4.4.3" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10/93f0483f6bbcf7cf776a53a130f7606f597fba67cf111e1897873bf1531efaa96e4851cfd461da0f0cc93afbdb51e47bcce11cf7dd4fb68b7030c7f9f240b92f languageName: node linkType: hard @@ -3728,27 +3982,38 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/type-utils@npm:5.55.0" +"@typescript-eslint/scope-manager@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/scope-manager@npm:8.54.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:5.55.0" - "@typescript-eslint/utils": "npm:5.55.0" - debug: "npm:^4.3.4" - tsutils: "npm:^3.21.0" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" + checksum: 10/3474f3197e8647754393dee62b3145c9de71eaa66c8a68f61c8283aa332141803885db9c96caa6a51f78128ad9ef92f774a90361655e57bd951d5b57eb76f914 + languageName: node + linkType: hard + +"@typescript-eslint/tsconfig-utils@npm:8.54.0, @typescript-eslint/tsconfig-utils@npm:^8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.54.0" peerDependencies: - eslint: "*" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/267a2144fa904522b8ce3425c70e556ae73b8d3a8164adc6af1413da56b607545075806ee40d373b97785ddfdd0ebcf6fcf336a1fcaa5f52c6659a1280c09b87 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/e9d6b29538716f007919bfcee94f09b7f8e7d2b684ad43d1a3c8d43afb9f0539c7707f84a34f42054e31c8c056b0ccf06575d89e860b4d34632ffefaefafe1fc languageName: node linkType: hard -"@typescript-eslint/types@npm:5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/types@npm:5.55.0" - checksum: 10/5ff3b2880e48921e69fdd49fa34d39fa1b004a9018b8effa470b2419b39429fd33a27d8ec0dd91665e4d7b9f6cf5b2958f25f9b8cdcb3eaa21e79427af59b8ef +"@typescript-eslint/type-utils@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/type-utils@npm:8.54.0" + dependencies: + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/utils": "npm:8.54.0" + debug: "npm:^4.4.3" + ts-api-utils: "npm:^2.4.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/60e92fb32274abd70165ce6f4187e4cffa55416374c63731d7de8fdcfb7a558b4dd48909ff1ad38ac39d2ea1248ec54d6ce38dbc065fd34529a217fc2450d5b1 languageName: node linkType: hard @@ -3759,21 +4024,17 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.55.0" - dependencies: - "@typescript-eslint/types": "npm:5.55.0" - "@typescript-eslint/visitor-keys": "npm:5.55.0" - debug: "npm:^4.3.4" - globby: "npm:^11.1.0" - is-glob: "npm:^4.0.3" - semver: "npm:^7.3.7" - tsutils: "npm:^3.21.0" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/e6c51080c0bc4b39d285eb73326731debda903842585ef5e74f61d3d8eb47adeec598b9778734866ac19321b1ba0beb3a4ad1def819bb4b49bc3a61098a5ca65 +"@typescript-eslint/types@npm:8.54.0, @typescript-eslint/types@npm:^8.11.0, @typescript-eslint/types@npm:^8.35.0, @typescript-eslint/types@npm:^8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/types@npm:8.54.0" + checksum: 10/c25cc0bdf90fb150cf6ce498897f43fe3adf9e872562159118f34bd91a9bfab5f720cb1a41f3cdf253b2e840145d7d372089b7cef5156624ef31e98d34f91b31 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/types@npm:8.53.1" + checksum: 10/9a01aa343329af529c645204070dd20be54556c6fd92bfda3a42b6213c0408f5f2f57084064d88d5de1337a7731e57290f0ec11a0fb181bbb3c3b293ef0dcf4a languageName: node linkType: hard @@ -3795,21 +4056,37 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/utils@npm:5.55.0" +"@typescript-eslint/typescript-estree@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.54.0" dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@types/json-schema": "npm:^7.0.9" - "@types/semver": "npm:^7.3.12" - "@typescript-eslint/scope-manager": "npm:5.55.0" - "@typescript-eslint/types": "npm:5.55.0" - "@typescript-eslint/typescript-estree": "npm:5.55.0" - eslint-scope: "npm:^5.1.1" - semver: "npm:^7.3.7" + "@typescript-eslint/project-service": "npm:8.54.0" + "@typescript-eslint/tsconfig-utils": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" + debug: "npm:^4.4.3" + minimatch: "npm:^9.0.5" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.4.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10/3a545037c6f9319251d3ba44cf7a3216b1372422469e27f7ed3415244ebf42553da1ab4644da42d3f0ae2706a8cad12529ffebcb2e75406f74e3b30b812d010d + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/utils@npm:8.54.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10/121c5fc48ccd43c6e83ae574c5670b2babad5231bef84fee181195b74edfd001657f139514f9fda548e1b527e5f9ea03caac735ad9ab9e3281aa3791773c46c5 + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/9f88a2a7ab3e11aa0ff7f99c0e66a0cf2cba10b640def4c64a4f4ef427fecfb22f28dbe5697535915eb01f6507515ac43e45e0ff384bf82856e3420194d9ffdd languageName: node linkType: hard @@ -3830,16 +4107,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.55.0": - version: 5.55.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.55.0" - dependencies: - "@typescript-eslint/types": "npm:5.55.0" - eslint-visitor-keys: "npm:^3.3.0" - checksum: 10/5b6a0e481325f092b2a39abd67d0bce6a42c98178e5494bfb9b0bd4a991ac5f07a54762361c8061f78eae0c194dc3f70eeb4e1b4b862733e9d8a7bf1e42f1f61 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:6.10.0": version: 6.10.0 resolution: "@typescript-eslint/visitor-keys@npm:6.10.0" @@ -3850,10 +4117,148 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.2.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 10/c6fe89a505e513a7592e1438280db1c075764793a2397877ff1351721fe8792a966a5359769e30242b3cd023f2efb9e63ca2ca88019d73b564488cc20e3eab12 +"@typescript-eslint/visitor-keys@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.54.0" + dependencies: + "@typescript-eslint/types": "npm:8.54.0" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10/cca5380ee30250302ee1459e5a0a38de8c16213026dbbff3d167fa7d71d012f31d60ac4483ad45ebd13f2ac963d1ca52dd5f22759a68d4ee57626e421769187a + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -4257,6 +4662,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.15.0": + version: 8.15.0 + resolution: "acorn@npm:8.15.0" + bin: + acorn: bin/acorn + checksum: 10/77f2de5051a631cf1729c090e5759148459cdb76b5f5c70f890503d629cf5052357b0ce783c0f976dd8a93c5150f59f6d18df1def3f502396a20f81282482fa4 + languageName: node + linkType: hard + "acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.9.0": version: 8.11.2 resolution: "acorn@npm:8.11.2" @@ -4547,6 +4961,13 @@ __metadata: languageName: node linkType: hard +"aria-query@npm:^5.3.2": + version: 5.3.2 + resolution: "aria-query@npm:5.3.2" + checksum: 10/b2fe9bc98bd401bc322ccb99717c1ae2aaf53ea0d468d6e7aebdc02fac736e4a99b46971ee05b783b08ade23c675b2d8b60e4a1222a95f6e27bc4d2a0bfdcc03 + languageName: node + linkType: hard + "array-buffer-byte-length@npm:^1.0.0": version: 1.0.0 resolution: "array-buffer-byte-length@npm:1.0.0" @@ -4557,6 +4978,16 @@ __metadata: languageName: node linkType: hard +"array-buffer-byte-length@npm:^1.0.1, array-buffer-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "array-buffer-byte-length@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + is-array-buffer: "npm:^3.0.5" + checksum: 10/0ae3786195c3211b423e5be8dd93357870e6fb66357d81da968c2c39ef43583ef6eece1f9cb1caccdae4806739c65dea832b44b8593414313cd76a89795fca63 + languageName: node + linkType: hard + "array-differ@npm:^3.0.0": version: 3.0.0 resolution: "array-differ@npm:3.0.0" @@ -4571,16 +5002,19 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8, array-includes@npm:^3.1.9": + version: 3.1.9 + resolution: "array-includes@npm:3.1.9" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" - is-string: "npm:^1.0.7" - checksum: 10/856a8be5d118967665936ad33ff3b07adfc50b06753e596e91fb80c3da9b8c022e92e3cc6781156d6ad95db7109b9f603682c7df2d6a529ed01f7f6b39a4a360 + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.24.0" + es-object-atoms: "npm:^1.1.1" + get-intrinsic: "npm:^1.3.0" + is-string: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + checksum: 10/8bfe9a58df74f326b4a76b04ee05c13d871759e888b4ee8f013145297cf5eb3c02cfa216067ebdaac5d74eb9763ac5cad77cdf2773b8ab475833701e032173aa languageName: node linkType: hard @@ -4591,28 +5025,44 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.3 - resolution: "array.prototype.findlastindex@npm:1.2.3" +"array.prototype.findlast@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-shim-unscopables: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.1" - checksum: 10/063cbab8eeac3aa01f3e980eecb9a8c5d87723032b49f7f814ecc6d75c33c03c17e3f43a458127a62e16303cab412f95d6ad9dc7e0ae6d9dc27a9bb76c24df7a + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/7dffcc665aa965718ad6de7e17ac50df0c5e38798c0a5bf9340cf24feb8594df6ec6f3fcbe714c1577728a1b18b5704b15669474b27bceeca91ef06ce2a23c31 languageName: node linkType: hard -"array.prototype.flat@npm:^1.3.2": - version: 1.3.2 - resolution: "array.prototype.flat@npm:1.3.2" +"array.prototype.findlastindex@npm:^1.2.6": + version: 1.2.6 + resolution: "array.prototype.findlastindex@npm:1.2.6" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-shim-unscopables: "npm:^1.0.0" - checksum: 10/d9d2f6f27584de92ec7995bc931103e6de722cd2498bdbfc4cba814fc3e52f056050a93be883018811f7c0a35875f5056584a0e940603a5e5934f0279896aebe + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.9" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + es-shim-unscopables: "npm:^1.1.0" + checksum: 10/5ddb6420e820bef6ddfdcc08ce780d0fd5e627e97457919c27e32359916de5a11ce12f7c55073555e503856618eaaa70845d6ca11dcba724766f38eb1c22f7a2 + languageName: node + linkType: hard + +"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.3": + version: 1.3.3 + resolution: "array.prototype.flat@npm:1.3.3" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/f9b992fa0775d8f7c97abc91eb7f7b2f0ed8430dd9aeb9fdc2967ac4760cdd7fc2ef7ead6528fef40c7261e4d790e117808ce0d3e7e89e91514d4963a531cd01 languageName: node linkType: hard @@ -4628,6 +5078,31 @@ __metadata: languageName: node linkType: hard +"array.prototype.flatmap@npm:^1.3.3": + version: 1.3.3 + resolution: "array.prototype.flatmap@npm:1.3.3" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/473534573aa4b37b1d80705d0ce642f5933cccf5617c9f3e8a56686e9815ba93d469138e86a1f25d2fe8af999c3d24f54d703ec1fc2db2e6778d46d0f4ac951e + languageName: node + linkType: hard + +"array.prototype.tosorted@npm:^1.1.4": + version: 1.1.4 + resolution: "array.prototype.tosorted@npm:1.1.4" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.3" + es-errors: "npm:^1.3.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/874694e5d50e138894ff5b853e639c29b0aa42bbd355acda8e8e9cd337f1c80565f21edc15e8c727fa4c0877fd9d8783c575809e440cc4d2d19acaa048bf967d + languageName: node + linkType: hard + "arraybuffer.prototype.slice@npm:^1.0.2": version: 1.0.2 resolution: "arraybuffer.prototype.slice@npm:1.0.2" @@ -4643,6 +5118,21 @@ __metadata: languageName: node linkType: hard +"arraybuffer.prototype.slice@npm:^1.0.4": + version: 1.0.4 + resolution: "arraybuffer.prototype.slice@npm:1.0.4" + dependencies: + array-buffer-byte-length: "npm:^1.0.1" + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + is-array-buffer: "npm:^3.0.4" + checksum: 10/4821ebdfe7d699f910c7f09bc9fa996f09b96b80bccb4f5dd4b59deae582f6ad6e505ecef6376f8beac1eda06df2dbc89b70e82835d104d6fcabd33c1aed1ae9 + languageName: node + linkType: hard + "arrify@npm:^1.0.1": version: 1.0.1 resolution: "arrify@npm:1.0.1" @@ -4716,6 +5206,13 @@ __metadata: languageName: node linkType: hard +"ast-types-flow@npm:^0.0.8": + version: 0.0.8 + resolution: "ast-types-flow@npm:0.0.8" + checksum: 10/85a1c24af4707871c27cfe456bd2ff7fcbe678f3d1c878ac968c9557735a171a17bdcc8c8f903ceab3fc3c49d5b3da2194e6ab0a6be7fec0e133fa028f21ba1b + languageName: node + linkType: hard + "astral-regex@npm:^2.0.0": version: 2.0.0 resolution: "astral-regex@npm:2.0.0" @@ -4811,6 +5308,20 @@ __metadata: languageName: node linkType: hard +"axe-core@npm:^4.10.0": + version: 4.11.1 + resolution: "axe-core@npm:4.11.1" + checksum: 10/bbc8e8959258a229b92fbaa73437050825579815051cac7b0fdbb6752946fea226e403bfeeef3d60d712477bdd4c01afdc8455f27c3d85e4251df88b032b6250 + languageName: node + linkType: hard + +"axobject-query@npm:^4.1.0": + version: 4.1.0 + resolution: "axobject-query@npm:4.1.0" + checksum: 10/e275dea9b673f71170d914f2d2a18be5d57d8d29717b629e7fedd907dcc2ebdc7a37803ff975874810bd423f222f299c020d28fde40a146f537448bf6bfecb6e + languageName: node + linkType: hard + "b4a@npm:^1.6.4": version: 1.6.7 resolution: "b4a@npm:1.6.7" @@ -4818,22 +5329,6 @@ __metadata: languageName: node linkType: hard -"babel-eslint@npm:^10.1.0": - version: 10.1.0 - resolution: "babel-eslint@npm:10.1.0" - dependencies: - "@babel/code-frame": "npm:^7.0.0" - "@babel/parser": "npm:^7.7.0" - "@babel/traverse": "npm:^7.7.0" - "@babel/types": "npm:^7.7.0" - eslint-visitor-keys: "npm:^1.0.0" - resolve: "npm:^1.12.0" - peerDependencies: - eslint: ">= 4.12.1" - checksum: 10/dc5dd948f8133481bcd66709e6f255212d2fcacb355688db8781883fd89f8bb0bd5229b1736b2f7b376869590261ec43470ec01637b464ff20ef56c5cd6018a3 - languageName: node - linkType: hard - "babel-loader@npm:^9.1.3": version: 9.1.3 resolution: "babel-loader@npm:9.1.3" @@ -5344,13 +5839,6 @@ __metadata: languageName: node linkType: hard -"builtin-modules@npm:^3.3.0": - version: 3.3.0 - resolution: "builtin-modules@npm:3.3.0" - checksum: 10/62e063ab40c0c1efccbfa9ffa31873e4f9d57408cb396a2649981a0ecbce56aabc93c28feaccbc5658c95aab2703ad1d11980e62ec2e5e72637404e1eb60f39e - languageName: node - linkType: hard - "builtin-status-codes@npm:^3.0.0": version: 3.0.0 resolution: "builtin-status-codes@npm:3.0.0" @@ -5478,7 +5966,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.8": +"call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -6161,6 +6649,13 @@ __metadata: languageName: node linkType: hard +"comment-parser@npm:^1.4.1": + version: 1.4.5 + resolution: "comment-parser@npm:1.4.5" + checksum: 10/4b5cacc7ab1ec48e3f51b788bd7cda567f5c83040e029e5c92eacf0785735a9b44ac49fdaf73d9bd4af9464aa4cc8cc7184902090b55b0023605a845f2666ba4 + languageName: node + linkType: hard + "common-ancestor-path@npm:^1.0.1": version: 1.0.1 resolution: "common-ancestor-path@npm:1.0.1" @@ -6199,10 +6694,10 @@ __metadata: languageName: node linkType: hard -"confusing-browser-globals@npm:^1.0.10": - version: 1.0.10 - resolution: "confusing-browser-globals@npm:1.0.10" - checksum: 10/7ccdc44c2ca419cf6576c3e4336106e18d1c5337f547e461342f51aec4a10f96fdfe45414b522be3c7d24ea0b62bf4372cd37768022e4d6161707ffb2c0987e6 +"confusing-browser-globals@npm:^1.0.11": + version: 1.0.11 + resolution: "confusing-browser-globals@npm:1.0.11" + checksum: 10/3afc635abd37e566477f610e7978b15753f0e84025c25d49236f1f14d480117185516bdd40d2a2167e6bed8048641a9854964b9c067e3dcdfa6b5d0ad3c3a5ef languageName: node linkType: hard @@ -6633,6 +7128,13 @@ __metadata: languageName: node linkType: hard +"damerau-levenshtein@npm:^1.0.8": + version: 1.0.8 + resolution: "damerau-levenshtein@npm:1.0.8" + checksum: 10/f4eba1c90170f96be25d95fa3857141b5f81e254f7e4d530da929217b19990ea9a0390fc53d3c1cafac9152fda78e722ea4894f765cf6216be413b5af1fbf821 + languageName: node + linkType: hard + "dargs@npm:^7.0.0": version: 7.0.0 resolution: "dargs@npm:7.0.0" @@ -6655,14 +7157,12 @@ __metadata: "@dashevo/wallet-lib": "workspace:*" "@dashevo/wasm-dpp": "workspace:*" "@dashevo/withdrawals-contract": "workspace:*" - "@types/chai": "npm:^4.2.12" + "@types/chai": "npm:^4.3.11" "@types/dirty-chai": "npm:^2.0.2" - "@types/mocha": "npm:^8.0.3" - "@types/node": "npm:^14.6.0" + "@types/mocha": "npm:^10.0.6" + "@types/node": "npm:^20.10.0" "@types/sinon": "npm:^9.0.4" "@types/sinon-chai": "npm:^3.2.4" - "@typescript-eslint/eslint-plugin": "npm:^5.55.0" - "@typescript-eslint/parser": "npm:^5.55.0" "@yarnpkg/pnpify": "npm:^4.0.0-rc.42" assert: "npm:^2.0.0" browserify-zlib: "npm:^0.2.0" @@ -6674,10 +7174,7 @@ __metadata: crypto-browserify: "npm:^3.12.1" dirty-chai: "npm:^2.0.1" dotenv-safe: "npm:^8.2.0" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-config-airbnb-typescript: "npm:^17.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" events: "npm:^3.3.0" https-browserify: "npm:^1.0.0" karma: "npm:^6.4.3" @@ -6704,9 +7201,9 @@ __metadata: tls: "npm:^0.0.1" ts-loader: "npm:^9.5.0" ts-mock-imports: "npm:^1.3.0" - ts-node: "npm:^10.4.0" + ts-node: "npm:^10.9.2" tsd: "npm:^0.28.1" - typescript: "npm:^3.9.5" + typescript: "npm:^5.7.3" url: "npm:^0.11.3" util: "npm:^0.12.4" webpack: "npm:^5.94.0" @@ -6720,7 +7217,6 @@ __metadata: resolution: "dashmate@workspace:packages/dashmate" dependencies: "@babel/core": "npm:^7.26.10" - "@babel/eslint-parser": "npm:^7.26.10" "@dashevo/bls": "npm:~1.2.9" "@dashevo/dapi-client": "workspace:*" "@dashevo/dashcore-lib": "npm:~0.22.0" @@ -6745,9 +7241,7 @@ __metadata: dot: "npm:^1.1.3" dotenv: "npm:^8.6.0" enquirer: "github:dashpay/enquirer#patch-1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" + eslint: "npm:^9.18.0" glob: "npm:^10.3.4" globby: "npm:^11" hasbin: "npm:^1.2.3" @@ -6772,13 +7266,46 @@ __metadata: sinon-chai: "npm:^3.7.0" systeminformation: "npm:^5.27.14" table: "npm:^6.8.1" - tar: "npm:7.5.4" + tar: "npm:7.5.7" wrap-ansi: "npm:^7.0.0" bin: dashmate: ./bin/run.js languageName: unknown linkType: soft +"data-view-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-buffer@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.2" + checksum: 10/c10b155a4e93999d3a215d08c23eea95f865e1f510b2e7748fcae1882b776df1afe8c99f483ace7fc0e5a3193ab08da138abebc9829d12003746c5a338c4d644 + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-byte-length@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.2" + checksum: 10/2a47055fcf1ab3ec41b00b6f738c6461a841391a643c9ed9befec1117c1765b4d492661d97fb7cc899200c328949dca6ff189d2c6537d96d60e8a02dfe3c95f7 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-offset@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10/fa3bdfa0968bea6711ee50375094b39f561bce3f15f9e558df59de9c25f0bdd4cddc002d9c1d70ac7772ebd36854a7e22d1761e7302a934e6f1c2263bcf44aa2 + languageName: node + linkType: hard + "date-format@npm:^4.0.13": version: 4.0.13 resolution: "date-format@npm:4.0.13" @@ -6842,6 +7369,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.4.1, debug@npm:^4.4.3": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10/9ada3434ea2993800bd9a1e320bd4aa7af69659fb51cca685d390949434bc0a8873c21ed7c9b852af6f2455a55c6d050aa3937d52b3c69f796dab666f762acad + languageName: node + linkType: hard + "debug@npm:~4.3.4": version: 4.3.5 resolution: "debug@npm:4.3.5" @@ -6981,7 +7520,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4, define-properties@npm:^1.2.0": +"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -7186,7 +7725,7 @@ __metadata: languageName: node linkType: hard -"doctrine@npm:3.0.0, doctrine@npm:^3.0.0": +"doctrine@npm:3.0.0": version: 3.0.0 resolution: "doctrine@npm:3.0.0" dependencies: @@ -7279,7 +7818,7 @@ __metadata: languageName: node linkType: hard -"dunder-proto@npm:^1.0.1": +"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1": version: 1.0.1 resolution: "dunder-proto@npm:1.0.1" dependencies: @@ -7508,18 +8047,80 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0, es-abstract@npm:^1.24.1": + version: 1.24.1 + resolution: "es-abstract@npm:1.24.1" dependencies: - array-buffer-byte-length: "npm:^1.0.0" - arraybuffer.prototype.slice: "npm:^1.0.2" - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.5" - es-set-tostringtag: "npm:^2.0.1" - es-to-primitive: "npm:^1.2.1" - function.prototype.name: "npm:^1.1.6" - get-intrinsic: "npm:^1.2.2" + array-buffer-byte-length: "npm:^1.0.2" + arraybuffer.prototype.slice: "npm:^1.0.4" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + data-view-buffer: "npm:^1.0.2" + data-view-byte-length: "npm:^1.0.2" + data-view-byte-offset: "npm:^1.0.1" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + es-set-tostringtag: "npm:^2.1.0" + es-to-primitive: "npm:^1.3.0" + function.prototype.name: "npm:^1.1.8" + get-intrinsic: "npm:^1.3.0" + get-proto: "npm:^1.0.1" + get-symbol-description: "npm:^1.1.0" + globalthis: "npm:^1.0.4" + gopd: "npm:^1.2.0" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + internal-slot: "npm:^1.1.0" + is-array-buffer: "npm:^3.0.5" + is-callable: "npm:^1.2.7" + is-data-view: "npm:^1.0.2" + is-negative-zero: "npm:^2.0.3" + is-regex: "npm:^1.2.1" + is-set: "npm:^2.0.3" + is-shared-array-buffer: "npm:^1.0.4" + is-string: "npm:^1.1.1" + is-typed-array: "npm:^1.1.15" + is-weakref: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + object-inspect: "npm:^1.13.4" + object-keys: "npm:^1.1.1" + object.assign: "npm:^4.1.7" + own-keys: "npm:^1.0.1" + regexp.prototype.flags: "npm:^1.5.4" + safe-array-concat: "npm:^1.1.3" + safe-push-apply: "npm:^1.0.0" + safe-regex-test: "npm:^1.1.0" + set-proto: "npm:^1.0.0" + stop-iteration-iterator: "npm:^1.1.0" + string.prototype.trim: "npm:^1.2.10" + string.prototype.trimend: "npm:^1.0.9" + string.prototype.trimstart: "npm:^1.0.8" + typed-array-buffer: "npm:^1.0.3" + typed-array-byte-length: "npm:^1.0.3" + typed-array-byte-offset: "npm:^1.0.4" + typed-array-length: "npm:^1.0.7" + unbox-primitive: "npm:^1.1.0" + which-typed-array: "npm:^1.1.19" + checksum: 10/c84cb69ebae36781309a3ed70ff40b4767a921d3b3518060fac4e08f14ede04491b68e9f318aedf186e349d4af4a40f5d0e4111e46513800e8368551fd09de8c + languageName: node + linkType: hard + +"es-abstract@npm:^1.22.1": + version: 1.22.3 + resolution: "es-abstract@npm:1.22.3" + dependencies: + array-buffer-byte-length: "npm:^1.0.0" + arraybuffer.prototype.slice: "npm:^1.0.2" + available-typed-arrays: "npm:^1.0.5" + call-bind: "npm:^1.0.5" + es-set-tostringtag: "npm:^2.0.1" + es-to-primitive: "npm:^1.2.1" + function.prototype.name: "npm:^1.1.6" + get-intrinsic: "npm:^1.2.2" get-symbol-description: "npm:^1.0.0" globalthis: "npm:^1.0.3" gopd: "npm:^1.0.1" @@ -7569,6 +8170,30 @@ __metadata: languageName: node linkType: hard +"es-iterator-helpers@npm:^1.2.1": + version: 1.2.2 + resolution: "es-iterator-helpers@npm:1.2.2" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.24.1" + es-errors: "npm:^1.3.0" + es-set-tostringtag: "npm:^2.1.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.3.0" + globalthis: "npm:^1.0.4" + gopd: "npm:^1.2.0" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + internal-slot: "npm:^1.1.0" + iterator.prototype: "npm:^1.1.5" + safe-array-concat: "npm:^1.1.3" + checksum: 10/17b5b2834c4f5719d6ce0e837a4d11c6ba4640bee28290d22ec4daf7106ec3d5fe0ff4f7e5dbaa2b4612e8335934360e964a8f08608d43f2889da106b25481ee + languageName: node + linkType: hard + "es-module-lexer@npm:^1.2.1": version: 1.5.4 resolution: "es-module-lexer@npm:1.5.4" @@ -7596,6 +8221,18 @@ __metadata: languageName: node linkType: hard +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10/86814bf8afbcd8966653f731415888019d4bc4aca6b6c354132a7a75bb87566751e320369654a101d23a91c87a85c79b178bcf40332839bd347aff437c4fb65f + languageName: node + linkType: hard + "es-shim-unscopables@npm:^1.0.0": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" @@ -7605,6 +8242,15 @@ __metadata: languageName: node linkType: hard +"es-shim-unscopables@npm:^1.0.2, es-shim-unscopables@npm:^1.1.0": + version: 1.1.0 + resolution: "es-shim-unscopables@npm:1.1.0" + dependencies: + hasown: "npm:^2.0.2" + checksum: 10/c351f586c30bbabc62355be49564b2435468b52c3532b8a1663672e3d10dc300197e69c247869dd173e56d86423ab95fc0c10b0939cdae597094e0fdca078cba + languageName: node + linkType: hard + "es-to-primitive@npm:^1.2.1": version: 1.2.1 resolution: "es-to-primitive@npm:1.2.1" @@ -7616,6 +8262,17 @@ __metadata: languageName: node linkType: hard +"es-to-primitive@npm:^1.3.0": + version: 1.3.0 + resolution: "es-to-primitive@npm:1.3.0" + dependencies: + is-callable: "npm:^1.2.7" + is-date-object: "npm:^1.0.5" + is-symbol: "npm:^1.0.4" + checksum: 10/17faf35c221aad59a16286cbf58ef6f080bf3c485dff202c490d074d8e74da07884e29b852c245d894eac84f73c58330ec956dfd6d02c0b449d75eb1012a3f9b + languageName: node + linkType: hard + "es6-error@npm:^4.0.1": version: 4.1.1 resolution: "es6-error@npm:4.1.1" @@ -7721,32 +8378,39 @@ __metadata: languageName: node linkType: hard -"eslint-config-airbnb-base@npm:^15.0.0": - version: 15.0.0 - resolution: "eslint-config-airbnb-base@npm:15.0.0" +"eslint-compat-utils@npm:^0.5.1": + version: 0.5.1 + resolution: "eslint-compat-utils@npm:0.5.1" dependencies: - confusing-browser-globals: "npm:^1.0.10" - object.assign: "npm:^4.1.2" - object.entries: "npm:^1.1.5" - semver: "npm:^6.3.0" + semver: "npm:^7.5.4" peerDependencies: - eslint: ^7.32.0 || ^8.2.0 - eslint-plugin-import: ^2.25.2 - checksum: 10/daa68a1dcb7bff338747a952723b5fa9d159980ec3554c395a4b52a7f7d4f00a45e7b465420eb6d4d87a82cef6361e4cfd6dbb38c2f3f52f2140b6cf13654803 + eslint: ">=6.0.0" + checksum: 10/ac65ac1c6107cf19f63f5fc17cea361c9cb1336be7356f23dbb0fac10979974b4622e13e950be43cbf431801f2c07f7dab448573181ccf6edc0b86d5b5304511 languageName: node linkType: hard -"eslint-config-airbnb-typescript@npm:^17.0.0": - version: 17.0.0 - resolution: "eslint-config-airbnb-typescript@npm:17.0.0" - dependencies: - eslint-config-airbnb-base: "npm:^15.0.0" +"eslint-config-airbnb-extended@npm:^3.0.1": + version: 3.0.1 + resolution: "eslint-config-airbnb-extended@npm:3.0.1" + dependencies: + "@next/eslint-plugin-next": "npm:^16.1.4" + "@stylistic/eslint-plugin": "npm:^5.7.0" + confusing-browser-globals: "npm:^1.0.11" + eslint-import-resolver-typescript: "npm:^4.4.4" + eslint-plugin-import: "npm:^2.32.0" + eslint-plugin-import-x: "npm:^4.16.1" + eslint-plugin-jsx-a11y: "npm:^6.10.2" + eslint-plugin-n: "npm:^17.23.2" + eslint-plugin-react: "npm:^7.37.5" + eslint-plugin-react-hooks: "npm:^7.0.1" + globals: "npm:^17.0.0" + typescript-eslint: "npm:^8.53.1" peerDependencies: - "@typescript-eslint/eslint-plugin": ^5.13.0 - "@typescript-eslint/parser": ^5.0.0 - eslint: ^7.32.0 || ^8.2.0 - eslint-plugin-import: ^2.25.3 - checksum: 10/43158416b1575431fe6fbe047bc7640c7f8a9185344e1d1261f1ce239f7ff2a9a55d2cffeb6ffd7b2f74694eb9ca61390daecf122041764fa57dc65b0366ea31 + eslint: ^9.0.0 + peerDependenciesMeta: + eslint: + optional: false + checksum: 10/24e89d991ee3c608266177c0c222ca432168b41ad3d73248e89cc0ef04ae6acb7bab164b263aa959685b5ee63288cecf87e12e782b07f50ab0b7e133e4a1deb3 languageName: node linkType: hard @@ -7766,6 +8430,21 @@ __metadata: languageName: node linkType: hard +"eslint-import-context@npm:^0.1.8, eslint-import-context@npm:^0.1.9": + version: 0.1.9 + resolution: "eslint-import-context@npm:0.1.9" + dependencies: + get-tsconfig: "npm:^4.10.1" + stable-hash-x: "npm:^0.2.0" + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: 10/f0778126bb3aae57c8c68946c71c4418927e9d39f72099b799d9c47a3b5712d6c9166b63ee8be58a020961dcc9216df09c856b825336af375ccbbdeedfc82a99 + languageName: node + linkType: hard + "eslint-import-resolver-node@npm:^0.3.6, eslint-import-resolver-node@npm:^0.3.9": version: 0.3.9 resolution: "eslint-import-resolver-node@npm:0.3.9" @@ -7777,61 +8456,171 @@ __metadata: languageName: node linkType: hard -"eslint-module-utils@npm:^2.8.0": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" +"eslint-import-resolver-typescript@npm:^4.4.4": + version: 4.4.4 + resolution: "eslint-import-resolver-typescript@npm:4.4.4" + dependencies: + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.8" + get-tsconfig: "npm:^4.10.1" + is-bun-module: "npm:^2.0.0" + stable-hash-x: "npm:^0.2.0" + tinyglobby: "npm:^0.2.14" + unrs-resolver: "npm:^1.7.11" + peerDependencies: + eslint: "*" + eslint-plugin-import: "*" + eslint-plugin-import-x: "*" + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + checksum: 10/4f871f6d1a04c55c2087c5ff1030f783a29abb59901b354d7ef58a0fc687d379dcbd08cf377cddeb7e19f26dd380d32d85ee4760e9410a059639d2b3df7d1ff3 + languageName: node + linkType: hard + +"eslint-module-utils@npm:^2.12.1": + version: 2.12.1 + resolution: "eslint-module-utils@npm:2.12.1" dependencies: debug: "npm:^3.2.7" peerDependenciesMeta: eslint: optional: true - checksum: 10/a9a7ed93eb858092e3cdc797357d4ead2b3ea06959b0eada31ab13862d46a59eb064b9cb82302214232e547980ce33618c2992f6821138a4934e65710ed9cc29 + checksum: 10/bd25d6610ec3abaa50e8f1beb0119541562bbb8dd02c035c7e887976fe1e0c5dd8175f4607ca8d86d1146df24d52a071bd3d1dd329f6902bd58df805a8ca16d3 languageName: node linkType: hard -"eslint-plugin-import@npm:^2.29.0": - version: 2.29.0 - resolution: "eslint-plugin-import@npm:2.29.0" +"eslint-plugin-es-x@npm:^7.8.0": + version: 7.8.0 + resolution: "eslint-plugin-es-x@npm:7.8.0" dependencies: - array-includes: "npm:^3.1.7" - array.prototype.findlastindex: "npm:^1.2.3" - array.prototype.flat: "npm:^1.3.2" - array.prototype.flatmap: "npm:^1.3.2" + "@eslint-community/eslint-utils": "npm:^4.1.2" + "@eslint-community/regexpp": "npm:^4.11.0" + eslint-compat-utils: "npm:^0.5.1" + peerDependencies: + eslint: ">=8" + checksum: 10/1df8d52c4fadc06854ce801af05b05f2642aa2deb918fb7d37738596eabd70b7f21a22b150b78ec9104bac6a1b6b4fb796adea2364ede91b01d20964849ce5f7 + languageName: node + linkType: hard + +"eslint-plugin-import-x@npm:^4.16.1": + version: 4.16.1 + resolution: "eslint-plugin-import-x@npm:4.16.1" + dependencies: + "@typescript-eslint/types": "npm:^8.35.0" + comment-parser: "npm:^1.4.1" + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.9" + is-glob: "npm:^4.0.3" + minimatch: "npm:^9.0.3 || ^10.0.1" + semver: "npm:^7.7.2" + stable-hash-x: "npm:^0.2.0" + unrs-resolver: "npm:^1.9.2" + peerDependencies: + "@typescript-eslint/utils": ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 + eslint-import-resolver-node: "*" + peerDependenciesMeta: + "@typescript-eslint/utils": + optional: true + eslint-import-resolver-node: + optional: true + checksum: 10/d1390d49499b613c1334e48fe8b104221584a1473fbec8974584002561aacef5347c4450c559df6fe24c3abe3b0d167eefdc5510e794e96a4ea4f9cb1d501515 + languageName: node + linkType: hard + +"eslint-plugin-import@npm:^2.32.0": + version: 2.32.0 + resolution: "eslint-plugin-import@npm:2.32.0" + dependencies: + "@rtsao/scc": "npm:^1.1.0" + array-includes: "npm:^3.1.9" + array.prototype.findlastindex: "npm:^1.2.6" + array.prototype.flat: "npm:^1.3.3" + array.prototype.flatmap: "npm:^1.3.3" debug: "npm:^3.2.7" doctrine: "npm:^2.1.0" eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.8.0" - hasown: "npm:^2.0.0" - is-core-module: "npm:^2.13.1" + eslint-module-utils: "npm:^2.12.1" + hasown: "npm:^2.0.2" + is-core-module: "npm:^2.16.1" is-glob: "npm:^4.0.3" minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.7" - object.groupby: "npm:^1.0.1" - object.values: "npm:^1.1.7" + object.fromentries: "npm:^2.0.8" + object.groupby: "npm:^1.0.3" + object.values: "npm:^1.2.1" semver: "npm:^6.3.1" - tsconfig-paths: "npm:^3.14.2" + string.prototype.trimend: "npm:^1.0.9" + tsconfig-paths: "npm:^3.15.0" peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 10/d6e8d016f38369892c85b866f762c03dee2b337d4f12031756e30d7490879261d1192a3c2f682fd7c4d2b923465f7a1e3d22cfdad5da1b1391c3bd39ea87af1a + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + checksum: 10/1bacf4967e9ebf99e12176a795f0d6d3a87d1c9a030c2207f27b267e10d96a1220be2647504c7fc13ab543cdf13ffef4b8f5620e0447032dba4ff0d3922f7c9e languageName: node linkType: hard -"eslint-plugin-jsdoc@npm:^46.9.0": - version: 46.9.0 - resolution: "eslint-plugin-jsdoc@npm:46.9.0" +"eslint-plugin-jsdoc@npm:^50.6.3": + version: 50.8.0 + resolution: "eslint-plugin-jsdoc@npm:50.8.0" dependencies: - "@es-joy/jsdoccomment": "npm:~0.41.0" + "@es-joy/jsdoccomment": "npm:~0.50.2" are-docs-informative: "npm:^0.0.2" comment-parser: "npm:1.4.1" - debug: "npm:^4.3.4" + debug: "npm:^4.4.1" escape-string-regexp: "npm:^4.0.0" - esquery: "npm:^1.5.0" - is-builtin-module: "npm:^3.2.1" - semver: "npm:^7.5.4" - spdx-expression-parse: "npm:^3.0.1" + espree: "npm:^10.3.0" + esquery: "npm:^1.6.0" + parse-imports-exports: "npm:^0.2.4" + semver: "npm:^7.7.2" + spdx-expression-parse: "npm:^4.0.0" peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - checksum: 10/0dd20688047c2acf9e816e8b541c56cb4b2660f02fd99e27b4ef6b4505dff0d14596134e40efb351a629f91e4fc2ceab517a071efd650ad2c3d6e4d9c461f650 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: 10/8857bb6583e04af0a1949e602e2b5b2abc5a951583bdc5a3baa0cc24f7c16db367cbc44e008c45b06dc2029685f0eb1ff6a0bb91e90fd82710ce30952d878d5d + languageName: node + linkType: hard + +"eslint-plugin-jsx-a11y@npm:^6.10.2": + version: 6.10.2 + resolution: "eslint-plugin-jsx-a11y@npm:6.10.2" + dependencies: + aria-query: "npm:^5.3.2" + array-includes: "npm:^3.1.8" + array.prototype.flatmap: "npm:^1.3.2" + ast-types-flow: "npm:^0.0.8" + axe-core: "npm:^4.10.0" + axobject-query: "npm:^4.1.0" + damerau-levenshtein: "npm:^1.0.8" + emoji-regex: "npm:^9.2.2" + hasown: "npm:^2.0.2" + jsx-ast-utils: "npm:^3.3.5" + language-tags: "npm:^1.0.9" + minimatch: "npm:^3.1.2" + object.fromentries: "npm:^2.0.8" + safe-regex-test: "npm:^1.0.3" + string.prototype.includes: "npm:^2.0.1" + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + checksum: 10/388550798548d911e2286d530a29153ca00434a06fcfc0e31e0dda46a5e7960005e532fb29ce1ccbf1e394a3af3e5cf70c47ca43778861eacc5e3ed799adb79c + languageName: node + linkType: hard + +"eslint-plugin-n@npm:^17.23.2": + version: 17.23.2 + resolution: "eslint-plugin-n@npm:17.23.2" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.5.0" + enhanced-resolve: "npm:^5.17.1" + eslint-plugin-es-x: "npm:^7.8.0" + get-tsconfig: "npm:^4.8.1" + globals: "npm:^15.11.0" + globrex: "npm:^0.1.2" + ignore: "npm:^5.3.2" + semver: "npm:^7.6.3" + ts-declaration-location: "npm:^1.0.6" + peerDependencies: + eslint: ">=8.23.0" + checksum: 10/67a15908b27fe5f9aee97d280c3e869debef58fc941b285ace6dab0baabe5263086f90d72a059f9e6efe0a427b77d42912892146eb8c882d085733c7cb068ead languageName: node linkType: hard @@ -7861,6 +8650,49 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-react-hooks@npm:^7.0.1": + version: 7.0.1 + resolution: "eslint-plugin-react-hooks@npm:7.0.1" + dependencies: + "@babel/core": "npm:^7.24.4" + "@babel/parser": "npm:^7.24.4" + hermes-parser: "npm:^0.25.1" + zod: "npm:^3.25.0 || ^4.0.0" + zod-validation-error: "npm:^3.5.0 || ^4.0.0" + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + checksum: 10/12e96c68d58c6588305fd17d660524a1ef1e872650ec591d5b138f059431290831c373d4b1c9ae8991fb25f96c43935497d2149678c027e65d0417d3d99ecc85 + languageName: node + linkType: hard + +"eslint-plugin-react@npm:^7.37.5": + version: 7.37.5 + resolution: "eslint-plugin-react@npm:7.37.5" + dependencies: + array-includes: "npm:^3.1.8" + array.prototype.findlast: "npm:^1.2.5" + array.prototype.flatmap: "npm:^1.3.3" + array.prototype.tosorted: "npm:^1.1.4" + doctrine: "npm:^2.1.0" + es-iterator-helpers: "npm:^1.2.1" + estraverse: "npm:^5.3.0" + hasown: "npm:^2.0.2" + jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" + minimatch: "npm:^3.1.2" + object.entries: "npm:^1.1.9" + object.fromentries: "npm:^2.0.8" + object.values: "npm:^1.2.1" + prop-types: "npm:^15.8.1" + resolve: "npm:^2.0.0-next.5" + semver: "npm:^6.3.1" + string.prototype.matchall: "npm:^4.0.12" + string.prototype.repeat: "npm:^1.0.0" + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + checksum: 10/ee1bd4e0ec64f29109d5a625bb703d179c82e0159c86c3f1b52fc1209d2994625a137dae303c333fb308a2e38315e44066d5204998177e31974382f9fda25d5c + languageName: node + linkType: hard + "eslint-rule-docs@npm:^1.1.5": version: 1.1.235 resolution: "eslint-rule-docs@npm:1.1.235" @@ -7868,7 +8700,7 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1": +"eslint-scope@npm:5.1.1": version: 5.1.1 resolution: "eslint-scope@npm:5.1.1" dependencies: @@ -7878,27 +8710,13 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.2": - version: 7.2.2 - resolution: "eslint-scope@npm:7.2.2" +"eslint-scope@npm:^8.4.0": + version: 8.4.0 + resolution: "eslint-scope@npm:8.4.0" dependencies: esrecurse: "npm:^4.3.0" estraverse: "npm:^5.2.0" - checksum: 10/5c660fb905d5883ad018a6fea2b49f3cb5b1cbf2cd4bd08e98646e9864f9bc2c74c0839bed2d292e90a4a328833accc197c8f0baed89cbe8d605d6f918465491 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^1.0.0": - version: 1.3.0 - resolution: "eslint-visitor-keys@npm:1.3.0" - checksum: 10/595ab230e0fcb52f86ba0986a9a473b9fcae120f3729b43f1157f88f27f8addb1e545c4e3d444185f2980e281ca15be5ada6f65b4599eec227cf30e41233b762 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^2.1.0": - version: 2.1.0 - resolution: "eslint-visitor-keys@npm:2.1.0" - checksum: 10/db4547eef5039122d518fa307e938ceb8589da5f6e8f5222efaf14dd62f748ce82e2d2becd3ff9412a50350b726bda95dbea8515a471074547daefa58aee8735 + checksum: 10/e8e611701f65375e034c62123946e628894f0b54aa8cb11abe224816389abe5cd74cf16b62b72baa36504f22d1a958b9b8b0169b82397fe2e7997674c0d09b06 languageName: node linkType: hard @@ -7909,55 +8727,74 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.53.0": - version: 8.53.0 - resolution: "eslint@npm:8.53.0" +"eslint-visitor-keys@npm:^4.2.1": + version: 4.2.1 + resolution: "eslint-visitor-keys@npm:4.2.1" + checksum: 10/3ee00fc6a7002d4b0ffd9dc99e13a6a7882c557329e6c25ab254220d71e5c9c4f89dca4695352949ea678eb1f3ba912a18ef8aac0a7fe094196fd92f441bfce2 + languageName: node + linkType: hard + +"eslint@npm:^9.18.0": + version: 9.39.2 + resolution: "eslint@npm:9.39.2" dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.3" - "@eslint/js": "npm:8.53.0" - "@humanwhocodes/config-array": "npm:^0.11.13" + "@eslint-community/eslint-utils": "npm:^4.8.0" + "@eslint-community/regexpp": "npm:^4.12.1" + "@eslint/config-array": "npm:^0.21.1" + "@eslint/config-helpers": "npm:^0.4.2" + "@eslint/core": "npm:^0.17.0" + "@eslint/eslintrc": "npm:^3.3.1" + "@eslint/js": "npm:9.39.2" + "@eslint/plugin-kit": "npm:^0.4.1" + "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" - "@nodelib/fs.walk": "npm:^1.2.8" - "@ungap/structured-clone": "npm:^1.2.0" + "@humanwhocodes/retry": "npm:^0.4.2" + "@types/estree": "npm:^1.0.6" ajv: "npm:^6.12.4" chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" + cross-spawn: "npm:^7.0.6" debug: "npm:^4.3.2" - doctrine: "npm:^3.0.0" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.2" - eslint-visitor-keys: "npm:^3.4.3" - espree: "npm:^9.6.1" - esquery: "npm:^1.4.2" + eslint-scope: "npm:^8.4.0" + eslint-visitor-keys: "npm:^4.2.1" + espree: "npm:^10.4.0" + esquery: "npm:^1.5.0" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" + file-entry-cache: "npm:^8.0.0" find-up: "npm:^5.0.0" glob-parent: "npm:^6.0.2" - globals: "npm:^13.19.0" - graphemer: "npm:^1.4.0" ignore: "npm:^5.2.0" imurmurhash: "npm:^0.1.4" is-glob: "npm:^4.0.0" - is-path-inside: "npm:^3.0.3" - js-yaml: "npm:^4.1.0" json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" lodash.merge: "npm:^4.6.2" minimatch: "npm:^3.1.2" natural-compare: "npm:^1.4.0" optionator: "npm:^0.9.3" - strip-ansi: "npm:^6.0.1" - text-table: "npm:^0.2.0" + peerDependencies: + jiti: "*" + peerDependenciesMeta: + jiti: + optional: true bin: eslint: bin/eslint.js - checksum: 10/e305a71ce2b9a8631b293266fe53e346c76f28bc8d004af33f10e537cf133db1fb87af3599376e70ed6e0f89a78be10c4f08ddd0c1c9c0c497cd143b4a270420 + checksum: 10/53ff0e9c8264e7e8d40d50fdc0c0df0b701cfc5289beedfb686c214e3e7b199702f894bbd1bb48653727bb1ecbd1147cf5f555a4ae71e1daf35020cdc9072d9f + languageName: node + linkType: hard + +"espree@npm:^10.0.1, espree@npm:^10.3.0, espree@npm:^10.4.0": + version: 10.4.0 + resolution: "espree@npm:10.4.0" + dependencies: + acorn: "npm:^8.15.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10/9b355b32dbd1cc9f57121d5ee3be258fab87ebeb7c83fc6c02e5af1a74fc8c5ba79fe8c663e69ea112c3e84a1b95e6a2067ac4443ee7813bb85ac7581acb8bf9 languageName: node linkType: hard -"espree@npm:^9.1.0, espree@npm:^9.6.0, espree@npm:^9.6.1": +"espree@npm:^9.1.0": version: 9.6.1 resolution: "espree@npm:9.6.1" dependencies: @@ -7978,7 +8815,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2, esquery@npm:^1.5.0": +"esquery@npm:^1.5.0": version: 1.5.0 resolution: "esquery@npm:1.5.0" dependencies: @@ -7987,6 +8824,15 @@ __metadata: languageName: node linkType: hard +"esquery@npm:^1.6.0": + version: 1.7.0 + resolution: "esquery@npm:1.7.0" + dependencies: + estraverse: "npm:^5.1.0" + checksum: 10/4afaf3089367e1f5885caa116ef386dffd8bfd64da21fd3d0e56e938d2667cfb2e5400ab4a825aa70e799bb3741e5b5d63c0b94d86e2d4cf3095c9e64b2f5a15 + languageName: node + linkType: hard + "esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -8126,6 +8972,19 @@ __metadata: languageName: node linkType: hard +"fast-glob@npm:3.3.1": + version: 3.3.1 + resolution: "fast-glob@npm:3.3.1" + dependencies: + "@nodelib/fs.stat": "npm:^2.0.2" + "@nodelib/fs.walk": "npm:^1.2.3" + glob-parent: "npm:^5.1.2" + merge2: "npm:^1.3.0" + micromatch: "npm:^4.0.4" + checksum: 10/51bcd15472879dfe51d4b01c5b70bbc7652724d39cdd082ba11276dbd7d84db0f6b33757e1938af8b2768a4bf485d9be0c89153beae24ee8331d6dcc7550379f + languageName: node + linkType: hard + "fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9": version: 3.2.12 resolution: "fast-glob@npm:3.2.12" @@ -8199,6 +9058,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.5.0": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10/14ca1c9f0a0e8f4f2e9bf4e8551065a164a09545dae548c12a18d238b72e51e5a7b39bd8e5494b56463a0877672d0a6c1ef62c6fa0677db1b0c847773be939b1 + languageName: node + linkType: hard + "fecha@npm:^4.2.0": version: 4.2.1 resolution: "fecha@npm:4.2.1" @@ -8215,12 +9086,12 @@ __metadata: languageName: node linkType: hard -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" dependencies: - flat-cache: "npm:^3.0.4" - checksum: 10/099bb9d4ab332cb93c48b14807a6918a1da87c45dce91d4b61fd40e6505d56d0697da060cb901c729c90487067d93c9243f5da3dc9c41f0358483bfdebca736b + flat-cache: "npm:^4.0.0" + checksum: 10/afe55c4de4e0d226a23c1eae62a7219aafb390859122608a89fa4df6addf55c7fd3f1a2da6f5b41e7cdff496e4cf28bbd215d53eab5c817afa96d2b40c81bfb0 languageName: node linkType: hard @@ -8354,13 +9225,13 @@ __metadata: languageName: node linkType: hard -"flat-cache@npm:^3.0.4": - version: 3.0.4 - resolution: "flat-cache@npm:3.0.4" +"flat-cache@npm:^4.0.0": + version: 4.0.1 + resolution: "flat-cache@npm:4.0.1" dependencies: - flatted: "npm:^3.1.0" - rimraf: "npm:^3.0.2" - checksum: 10/9fe5d0cb97c988e3b25242e71346965fae22757674db3fca14206850af2efa3ca3b04a3ba0eba8d5e20fd8a3be80a2e14b1c2917e70ffe1acb98a8c3327e4c9f + flatted: "npm:^3.2.9" + keyv: "npm:^4.5.4" + checksum: 10/58ce851d9045fffc7871ce2bd718bc485ad7e777bf748c054904b87c351ff1080c2c11da00788d78738bfb51b71e4d5ea12d13b98eb36e3358851ffe495b62dc languageName: node linkType: hard @@ -8373,13 +9244,20 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.1.0, flatted@npm:^3.2.6": +"flatted@npm:^3.2.6": version: 3.2.7 resolution: "flatted@npm:3.2.7" checksum: 10/427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 languageName: node linkType: hard +"flatted@npm:^3.2.9": + version: 3.3.3 + resolution: "flatted@npm:3.3.3" + checksum: 10/8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe + languageName: node + linkType: hard + "fn.name@npm:1.x.x": version: 1.1.0 resolution: "fn.name@npm:1.1.0" @@ -8544,6 +9422,20 @@ __metadata: languageName: node linkType: hard +"function.prototype.name@npm:^1.1.8": + version: 1.1.8 + resolution: "function.prototype.name@npm:1.1.8" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + functions-have-names: "npm:^1.2.3" + hasown: "npm:^2.0.2" + is-callable: "npm:^1.2.7" + checksum: 10/25b9e5bea936732a6f0c0c08db58cc0d609ac1ed458c6a07ead46b32e7b9bf3fe5887796c3f83d35994efbc4fdde81c08ac64135b2c399b8f2113968d44082bc + languageName: node + linkType: hard + "functional-red-black-tree@npm:~1.0.1": version: 1.0.1 resolution: "functional-red-black-tree@npm:1.0.1" @@ -8633,7 +9525,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.5": +"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7": version: 1.3.1 resolution: "get-intrinsic@npm:1.3.1" dependencies: @@ -8675,7 +9567,7 @@ __metadata: languageName: node linkType: hard -"get-proto@npm:^1.0.1": +"get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": version: 1.0.1 resolution: "get-proto@npm:1.0.1" dependencies: @@ -8718,6 +9610,26 @@ __metadata: languageName: node linkType: hard +"get-symbol-description@npm:^1.1.0": + version: 1.1.0 + resolution: "get-symbol-description@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + checksum: 10/a353e3a9595a74720b40fb5bae3ba4a4f826e186e83814d93375182384265676f59e49998b9cdfac4a2225ce95a3d32a68f502a2c5619303987f1c183ab80494 + languageName: node + linkType: hard + +"get-tsconfig@npm:^4.10.1, get-tsconfig@npm:^4.8.1": + version: 4.13.0 + resolution: "get-tsconfig@npm:4.13.0" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10/3603c6da30e312636e4c20461e779114c9126601d1eca70ee4e36e3e3c00e3c21892d2d920027333afa2cc9e20998a436b14abe03a53cde40742581cb0e9ceb2 + languageName: node + linkType: hard + "git-raw-commits@npm:^2.0.8": version: 2.0.10 resolution: "git-raw-commits@npm:2.0.10" @@ -8884,12 +9796,24 @@ __metadata: languageName: node linkType: hard -"globals@npm:^13.19.0": - version: 13.23.0 - resolution: "globals@npm:13.23.0" - dependencies: - type-fest: "npm:^0.20.2" - checksum: 10/bf6a8616f4a64959c0b9a8eb4dc8a02e7dd0082385f7f06bc9694d9fceabe39f83f83789322cfe0470914dc8b273b7a29af5570b9e1a0507d3fb7348a64703a3 +"globals@npm:^14.0.0": + version: 14.0.0 + resolution: "globals@npm:14.0.0" + checksum: 10/03939c8af95c6df5014b137cac83aa909090c3a3985caef06ee9a5a669790877af8698ab38007e4c0186873adc14c0b13764acc754b16a754c216cc56aa5f021 + languageName: node + linkType: hard + +"globals@npm:^15.11.0, globals@npm:^15.14.0": + version: 15.15.0 + resolution: "globals@npm:15.15.0" + checksum: 10/7f561c87b2fd381b27fc2db7df8a4ea7a9bb378667b8a7193e61fd2ca3a876479174e2a303a74345fbea6e1242e16db48915c1fd3bf35adcf4060a795b425e18 + languageName: node + linkType: hard + +"globals@npm:^17.0.0": + version: 17.1.0 + resolution: "globals@npm:17.1.0" + checksum: 10/6e77442a3b80b41b11fb4f986326f0487b9872dee6852cc9373e01696787889f4648d2264a125504315a645be0dde61625200e422b5b8002c106ffbabaaf8fdc languageName: node linkType: hard @@ -8902,6 +9826,16 @@ __metadata: languageName: node linkType: hard +"globalthis@npm:^1.0.4": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" + dependencies: + define-properties: "npm:^1.2.1" + gopd: "npm:^1.0.1" + checksum: 10/1f1fd078fb2f7296306ef9dd51019491044ccf17a59ed49d375b576ca108ff37e47f3d29aead7add40763574a992f16a5367dd1e2173b8634ef18556ab719ac4 + languageName: node + linkType: hard + "globby@npm:^11, globby@npm:^11.0.1, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" @@ -9005,13 +9939,6 @@ __metadata: languageName: node linkType: hard -"graphemer@npm:^1.4.0": - version: 1.4.0 - resolution: "graphemer@npm:1.4.0" - checksum: 10/6dd60dba97007b21e3a829fab3f771803cc1292977fe610e240ea72afd67e5690ac9eeaafc4a99710e78962e5936ab5a460787c2a1180f1cb0ccfac37d29f897 - languageName: node - linkType: hard - "grouped-queue@npm:^2.0.0": version: 2.0.0 resolution: "grouped-queue@npm:2.0.0" @@ -9090,6 +10017,15 @@ __metadata: languageName: node linkType: hard +"has-proto@npm:^1.2.0": + version: 1.2.0 + resolution: "has-proto@npm:1.2.0" + dependencies: + dunder-proto: "npm:^1.0.0" + checksum: 10/7eaed07728eaa28b77fadccabce53f30de467ff186a766872669a833ac2e87d8922b76a22cc58339d7e0277aefe98d6d00762113b27a97cdf65adcf958970935 + languageName: node + linkType: hard + "has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": version: 1.0.3 resolution: "has-symbols@npm:1.0.3" @@ -9244,6 +10180,22 @@ __metadata: languageName: node linkType: hard +"hermes-estree@npm:0.25.1": + version: 0.25.1 + resolution: "hermes-estree@npm:0.25.1" + checksum: 10/7b1eca98b264a25632064cffa5771360d30cf452e77db1e191f9913ee45cf78c292b2dbca707e92fb71b0870abb97e94b506a5ab80abd96ba237fee169b601fe + languageName: node + linkType: hard + +"hermes-parser@npm:^0.25.1": + version: 0.25.1 + resolution: "hermes-parser@npm:0.25.1" + dependencies: + hermes-estree: "npm:0.25.1" + checksum: 10/805efc05691420f236654349872c70731121791fa54de521c7ee51059eae34f84dd19f22ee846741dcb60372f8fb5335719b96b4ecb010d2aed7d872f2eff9cc + languageName: node + linkType: hard + "hmac-drbg@npm:^1.0.1": version: 1.0.1 resolution: "hmac-drbg@npm:1.0.1" @@ -9487,6 +10439,20 @@ __metadata: languageName: node linkType: hard +"ignore@npm:^5.3.2": + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 10/cceb6a457000f8f6a50e1196429750d782afce5680dd878aa4221bd79972d68b3a55b4b1458fc682be978f4d3c6a249046aa0880637367216444ab7b014cfc98 + languageName: node + linkType: hard + +"ignore@npm:^7.0.5": + version: 7.0.5 + resolution: "ignore@npm:7.0.5" + checksum: 10/f134b96a4de0af419196f52c529d5c6120c4456ff8a6b5a14ceaaa399f883e15d58d2ce651c9b69b9388491d4669dda47285d307e827de9304a53a1824801bc6 + languageName: node + linkType: hard + "immediate@npm:^3.2.3": version: 3.3.0 resolution: "immediate@npm:3.3.0" @@ -9622,6 +10588,17 @@ __metadata: languageName: node linkType: hard +"internal-slot@npm:^1.1.0": + version: 1.1.0 + resolution: "internal-slot@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + hasown: "npm:^2.0.2" + side-channel: "npm:^1.1.0" + checksum: 10/1d5219273a3dab61b165eddf358815eefc463207db33c20fcfca54717da02e3f492003757721f972fd0bf21e4b426cab389c5427b99ceea4b8b670dc88ee6d4a + languageName: node + linkType: hard + "interpret@npm:^1.0.0": version: 1.4.0 resolution: "interpret@npm:1.4.0" @@ -9681,6 +10658,17 @@ __metadata: languageName: node linkType: hard +"is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": + version: 3.0.5 + resolution: "is-array-buffer@npm:3.0.5" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.6" + checksum: 10/ef1095c55b963cd0dcf6f88a113e44a0aeca91e30d767c475e7d746d28d1195b10c5076b94491a7a0cd85020ca6a4923070021d74651d093dc909e9932cf689b + languageName: node + linkType: hard + "is-arrayish@npm:^0.2.1": version: 0.2.1 resolution: "is-arrayish@npm:0.2.1" @@ -9695,6 +10683,19 @@ __metadata: languageName: node linkType: hard +"is-async-function@npm:^2.0.0": + version: 2.1.1 + resolution: "is-async-function@npm:2.1.1" + dependencies: + async-function: "npm:^1.0.0" + call-bound: "npm:^1.0.3" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10/7c2ac7efdf671e03265e74a043bcb1c0a32e226bc2a42dfc5ec8644667df668bbe14b91c08e6c1414f392f8cf86cd1d489b3af97756e2c7a49dd1ba63fd40ca6 + languageName: node + linkType: hard + "is-bigint@npm:^1.0.1": version: 1.0.4 resolution: "is-bigint@npm:1.0.4" @@ -9704,6 +10705,15 @@ __metadata: languageName: node linkType: hard +"is-bigint@npm:^1.1.0": + version: 1.1.0 + resolution: "is-bigint@npm:1.1.0" + dependencies: + has-bigints: "npm:^1.0.2" + checksum: 10/10cf327310d712fe227cfaa32d8b11814c214392b6ac18c827f157e1e85363cf9c8e2a22df526689bd5d25e53b58cc110894787afb54e138e7c504174dba15fd + languageName: node + linkType: hard + "is-binary-path@npm:~2.1.0": version: 2.1.0 resolution: "is-binary-path@npm:2.1.0" @@ -9717,18 +10727,28 @@ __metadata: version: 1.1.2 resolution: "is-boolean-object@npm:1.1.2" dependencies: - call-bind: "npm:^1.0.2" - has-tostringtag: "npm:^1.0.0" - checksum: 10/ba794223b56a49a9f185e945eeeb6b7833b8ea52a335cec087d08196cf27b538940001615d3bb976511287cefe94e5907d55f00bb49580533f9ca9b4515fcc2e + call-bind: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.0" + checksum: 10/ba794223b56a49a9f185e945eeeb6b7833b8ea52a335cec087d08196cf27b538940001615d3bb976511287cefe94e5907d55f00bb49580533f9ca9b4515fcc2e + languageName: node + linkType: hard + +"is-boolean-object@npm:^1.2.1": + version: 1.2.2 + resolution: "is-boolean-object@npm:1.2.2" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10/051fa95fdb99d7fbf653165a7e6b2cba5d2eb62f7ffa81e793a790f3fb5366c91c1b7b6af6820aa2937dd86c73aa3ca9d9ca98f500988457b1c59692c52ba911 languageName: node linkType: hard -"is-builtin-module@npm:^3.2.1": - version: 3.2.1 - resolution: "is-builtin-module@npm:3.2.1" +"is-bun-module@npm:^2.0.0": + version: 2.0.0 + resolution: "is-bun-module@npm:2.0.0" dependencies: - builtin-modules: "npm:^3.3.0" - checksum: 10/e8f0ffc19a98240bda9c7ada84d846486365af88d14616e737d280d378695c8c448a621dcafc8332dbf0fcd0a17b0763b845400709963fa9151ddffece90ae88 + semver: "npm:^7.7.1" + checksum: 10/cded5a1a58368b847872d08617975d620ad94426d76a932f3e08d55b4574d199e0a62a4fb024fa2dc444200b71719eb0bffc5d3d1e1cc82e29b293bb8d66a990 languageName: node linkType: hard @@ -9739,7 +10759,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.5.0, is-core-module@npm:^2.8.1": +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.5.0, is-core-module@npm:^2.8.1": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" dependencies: @@ -9748,6 +10768,26 @@ __metadata: languageName: node linkType: hard +"is-core-module@npm:^2.16.1": + version: 2.16.1 + resolution: "is-core-module@npm:2.16.1" + dependencies: + hasown: "npm:^2.0.2" + checksum: 10/452b2c2fb7f889cbbf7e54609ef92cf6c24637c568acc7e63d166812a0fb365ae8a504c333a29add8bdb1686704068caa7f4e4b639b650dde4f00a038b8941fb + languageName: node + linkType: hard + +"is-data-view@npm:^1.0.1, is-data-view@npm:^1.0.2": + version: 1.0.2 + resolution: "is-data-view@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + get-intrinsic: "npm:^1.2.6" + is-typed-array: "npm:^1.1.13" + checksum: 10/357e9a48fa38f369fd6c4c3b632a3ab2b8adca14997db2e4b3fe94c4cd0a709af48e0fb61b02c64a90c0dd542fd489d49c2d03157b05ae6c07f5e4dec9e730a8 + languageName: node + linkType: hard + "is-date-object@npm:^1.0.1": version: 1.0.5 resolution: "is-date-object@npm:1.0.5" @@ -9757,6 +10797,16 @@ __metadata: languageName: node linkType: hard +"is-date-object@npm:^1.0.5, is-date-object@npm:^1.1.0": + version: 1.1.0 + resolution: "is-date-object@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10/3a811b2c3176fb31abee1d23d3dc78b6c65fd9c07d591fcb67553cab9e7f272728c3dd077d2d738b53f9a2103255b0a6e8dfc9568a7805c56a78b2563e8d1dec + languageName: node + linkType: hard + "is-docker@npm:^2.0.0": version: 2.2.1 resolution: "is-docker@npm:2.2.1" @@ -9773,6 +10823,15 @@ __metadata: languageName: node linkType: hard +"is-finalizationregistry@npm:^1.1.0": + version: 1.1.1 + resolution: "is-finalizationregistry@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10/0bfb145e9a1ba852ddde423b0926d2169ae5fe9e37882cde9e8f69031281a986308df4d982283e152396e88b86562ed2256cbaa5e6390fb840a4c25ab54b8a80 + languageName: node + linkType: hard + "is-fullwidth-code-point@npm:^3.0.0": version: 3.0.0 resolution: "is-fullwidth-code-point@npm:3.0.0" @@ -9780,6 +10839,19 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.10": + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" + dependencies: + call-bound: "npm:^1.0.4" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10/cc50fa01034356bdfda26983c5457103240f201f4663c0de1257802714e40d36bcff7aee21091d37bbba4be962fa5c6475ce7ddbc0abfa86d6bef466e41e50a5 + languageName: node + linkType: hard + "is-generator-function@npm:^1.0.7": version: 1.0.10 resolution: "is-generator-function@npm:1.0.10" @@ -9821,6 +10893,13 @@ __metadata: languageName: node linkType: hard +"is-map@npm:^2.0.3": + version: 2.0.3 + resolution: "is-map@npm:2.0.3" + checksum: 10/8de7b41715b08bcb0e5edb0fb9384b80d2d5bcd10e142188f33247d19ff078abaf8e9b6f858e2302d8d05376a26a55cd23a3c9f8ab93292b02fcd2cc9e4e92bb + languageName: node + linkType: hard + "is-nan@npm:^1.2.1": version: 1.3.2 resolution: "is-nan@npm:1.3.2" @@ -9838,6 +10917,13 @@ __metadata: languageName: node linkType: hard +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: 10/8fe5cffd8d4fb2ec7b49d657e1691889778d037494c6f40f4d1a524cadd658b4b53ad7b6b73a59bcb4b143ae9a3d15829af864b2c0f9d65ac1e678c4c80f17e5 + languageName: node + linkType: hard + "is-number-object@npm:^1.0.4": version: 1.0.6 resolution: "is-number-object@npm:1.0.6" @@ -9847,6 +10933,16 @@ __metadata: languageName: node linkType: hard +"is-number-object@npm:^1.1.1": + version: 1.1.1 + resolution: "is-number-object@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10/a5922fb8779ab1ea3b8a9c144522b3d0bea5d9f8f23f7a72470e61e1e4df47714e28e0154ac011998b709cce260c3c9447ad3cd24a96c2f2a0abfdb2cbdc76c8 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -9861,13 +10957,6 @@ __metadata: languageName: node linkType: hard -"is-path-inside@npm:^3.0.3": - version: 3.0.3 - resolution: "is-path-inside@npm:3.0.3" - checksum: 10/abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 - languageName: node - linkType: hard - "is-plain-obj@npm:^1.1.0": version: 1.1.0 resolution: "is-plain-obj@npm:1.1.0" @@ -9908,6 +10997,18 @@ __metadata: languageName: node linkType: hard +"is-regex@npm:^1.2.1": + version: 1.2.1 + resolution: "is-regex@npm:1.2.1" + dependencies: + call-bound: "npm:^1.0.2" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10/c42b7efc5868a5c9a4d8e6d3e9816e8815c611b09535c00fead18a1138455c5cb5e1887f0023a467ad3f9c419d62ba4dc3d9ba8bafe55053914d6d6454a945d2 + languageName: node + linkType: hard + "is-retry-allowed@npm:^1.1.0": version: 1.2.0 resolution: "is-retry-allowed@npm:1.2.0" @@ -9924,6 +11025,13 @@ __metadata: languageName: node linkType: hard +"is-set@npm:^2.0.3": + version: 2.0.3 + resolution: "is-set@npm:2.0.3" + checksum: 10/5685df33f0a4a6098a98c72d94d67cad81b2bc72f1fb2091f3d9283c4a1c582123cd709145b02a9745f0ce6b41e3e43f1c944496d1d74d4ea43358be61308669 + languageName: node + linkType: hard + "is-shared-array-buffer@npm:^1.0.2": version: 1.0.2 resolution: "is-shared-array-buffer@npm:1.0.2" @@ -9933,6 +11041,15 @@ __metadata: languageName: node linkType: hard +"is-shared-array-buffer@npm:^1.0.4": + version: 1.0.4 + resolution: "is-shared-array-buffer@npm:1.0.4" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10/0380d7c60cc692856871526ffcd38a8133818a2ee42d47bb8008248a0cd2121d8c8b5f66b6da3cac24bc5784553cacb6faaf678f66bc88c6615b42af2825230e + languageName: node + linkType: hard + "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -9949,6 +11066,16 @@ __metadata: languageName: node linkType: hard +"is-string@npm:^1.1.1": + version: 1.1.1 + resolution: "is-string@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10/5277cb9e225a7cc8a368a72623b44a99f2cfa139659c6b203553540681ad4276bfc078420767aad0e73eef5f0bd07d4abf39a35d37ec216917879d11cebc1f8b + languageName: node + linkType: hard + "is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": version: 1.0.4 resolution: "is-symbol@npm:1.0.4" @@ -9958,6 +11085,17 @@ __metadata: languageName: node linkType: hard +"is-symbol@npm:^1.0.4, is-symbol@npm:^1.1.1": + version: 1.1.1 + resolution: "is-symbol@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.2" + has-symbols: "npm:^1.1.0" + safe-regex-test: "npm:^1.1.0" + checksum: 10/db495c0d8cd0a7a66b4f4ef7fccee3ab5bd954cb63396e8ac4d32efe0e9b12fdfceb851d6c501216a71f4f21e5ff20fc2ee845a3d52d455e021c466ac5eb2db2 + languageName: node + linkType: hard + "is-text-path@npm:^1.0.1": version: 1.0.1 resolution: "is-text-path@npm:1.0.1" @@ -9976,7 +11114,7 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.14": +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15": version: 1.1.15 resolution: "is-typed-array@npm:1.1.15" dependencies: @@ -10006,6 +11144,13 @@ __metadata: languageName: node linkType: hard +"is-weakmap@npm:^2.0.2": + version: 2.0.2 + resolution: "is-weakmap@npm:2.0.2" + checksum: 10/a7b7e23206c542dcf2fa0abc483142731788771527e90e7e24f658c0833a0d91948a4f7b30d78f7a65255a48512e41a0288b778ba7fc396137515c12e201fd11 + languageName: node + linkType: hard + "is-weakref@npm:^1.0.2": version: 1.0.2 resolution: "is-weakref@npm:1.0.2" @@ -10015,6 +11160,25 @@ __metadata: languageName: node linkType: hard +"is-weakref@npm:^1.1.1": + version: 1.1.1 + resolution: "is-weakref@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10/543506fd8259038b371bb083aac25b16cb4fd8b12fc58053aa3d45ac28dfd001cd5c6dffbba7aeea4213c74732d46b6cb2cfb5b412eed11f2db524f3f97d09a0 + languageName: node + linkType: hard + +"is-weakset@npm:^2.0.3": + version: 2.0.4 + resolution: "is-weakset@npm:2.0.4" + dependencies: + call-bound: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.6" + checksum: 10/1d5e1d0179beeed3661125a6faa2e59bfb48afda06fc70db807f178aa0ebebc3758fb6358d76b3d528090d5ef85148c345dcfbf90839592fe293e3e5e82f2134 + languageName: node + linkType: hard + "is-windows@npm:^1.0.2": version: 1.0.2 resolution: "is-windows@npm:1.0.2" @@ -10170,6 +11334,20 @@ __metadata: languageName: node linkType: hard +"iterator.prototype@npm:^1.1.5": + version: 1.1.5 + resolution: "iterator.prototype@npm:1.1.5" + dependencies: + define-data-property: "npm:^1.1.4" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.6" + get-proto: "npm:^1.0.0" + has-symbols: "npm:^1.1.0" + set-function-name: "npm:^2.0.2" + checksum: 10/352bcf333f42189e65cc8cb2dcb94a5c47cf0a9110ce12aba788d405a980b5f5f3a06c79bf915377e1d480647169babd842ded0d898bed181bf6686e8e6823f6 + languageName: node + linkType: hard + "jackspeak@npm:^3.1.2": version: 3.1.2 resolution: "jackspeak@npm:3.1.2" @@ -10295,7 +11473,7 @@ __metadata: languageName: node linkType: hard -"js-tokens@npm:^4.0.0": +"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" checksum: 10/af37d0d913fb56aec6dc0074c163cc71cd23c0b8aad5c2350747b6721d37ba118af35abdd8b33c47ec2800de07dedb16a527ca9c530ee004093e04958bd0cbf2 @@ -10320,19 +11498,10 @@ __metadata: languageName: node linkType: hard -"jsdoc-type-pratt-parser@npm:~4.0.0": - version: 4.0.0 - resolution: "jsdoc-type-pratt-parser@npm:4.0.0" - checksum: 10/a225ab874e56612730dd6c0466ce9f09e8a0e7d85896e9e5f0fa53cfb2e897128a7ec702fd99ed3854b3fbf5a89ad6dce72ca4f4f6149da69f130c2874f06b75 - languageName: node - linkType: hard - -"jsesc@npm:^2.5.1": - version: 2.5.2 - resolution: "jsesc@npm:2.5.2" - bin: - jsesc: bin/jsesc - checksum: 10/d2096abdcdec56969764b40ffc91d4a23408aa2f351b4d1c13f736f25476643238c43fdbaf38a191c26b1b78fd856d965f5d4d0dde7b89459cd94025190cdf13 +"jsdoc-type-pratt-parser@npm:~4.1.0": + version: 4.1.0 + resolution: "jsdoc-type-pratt-parser@npm:4.1.0" + checksum: 10/30d88f95f6cbb4a1aa6d4b0d0ae46eb1096e606235ecaf9bab7a3ed5da860516b5d1cd967182765002f292c627526db918f3e56d34637bcf810e6ef84d403f3f languageName: node linkType: hard @@ -10486,6 +11655,18 @@ __metadata: languageName: node linkType: hard +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": + version: 3.3.5 + resolution: "jsx-ast-utils@npm:3.3.5" + dependencies: + array-includes: "npm:^3.1.6" + array.prototype.flat: "npm:^1.3.1" + object.assign: "npm:^4.1.4" + object.values: "npm:^1.1.6" + checksum: 10/b61d44613687dfe4cc8ad4b4fbf3711bf26c60b8d5ed1f494d723e0808415c59b24a7c0ed8ab10736a40ff84eef38cbbfb68b395e05d31117b44ffc59d31edfc + languageName: node + linkType: hard + "just-diff-apply@npm:^4.0.1": version: 4.0.1 resolution: "just-diff-apply@npm:4.0.1" @@ -10614,7 +11795,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.0.0, keyv@npm:^4.5.3": +"keyv@npm:^4.0.0, keyv@npm:^4.5.3, keyv@npm:^4.5.4": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -10637,6 +11818,22 @@ __metadata: languageName: node linkType: hard +"language-subtag-registry@npm:^0.3.20": + version: 0.3.23 + resolution: "language-subtag-registry@npm:0.3.23" + checksum: 10/fe13ed74ab9f862db8e5747b98cc9aa08d52a19f85b5cdb4975cd364c8539bd2da3380e4560d2dbbd728ec33dff8a4b4421fcb2e5b1b1bdaa21d16f91a54d0d4 + languageName: node + linkType: hard + +"language-tags@npm:^1.0.9": + version: 1.0.9 + resolution: "language-tags@npm:1.0.9" + dependencies: + language-subtag-registry: "npm:^0.3.20" + checksum: 10/d3a7c14b694e67f519153d6df6cb200681648d38d623c3bfa9d6a66a5ec5493628acb88e9df5aceef3cf1902ab263a205e7d59ee4cf1d6bb67e707b83538bd6d + languageName: node + linkType: hard + "level-concat-iterator@npm:~2.0.0": version: 2.0.1 resolution: "level-concat-iterator@npm:2.0.1" @@ -10994,6 +12191,17 @@ __metadata: languageName: node linkType: hard +"loose-envify@npm:^1.4.0": + version: 1.4.0 + resolution: "loose-envify@npm:1.4.0" + dependencies: + js-tokens: "npm:^3.0.0 || ^4.0.0" + bin: + loose-envify: cli.js + checksum: 10/6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 + languageName: node + linkType: hard + "loupe@npm:^2.3.6": version: 2.3.7 resolution: "loupe@npm:2.3.7" @@ -11452,7 +12660,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -11479,7 +12687,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.0, minimatch@npm:^9.0.3, minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -11488,6 +12696,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.3 || ^10.0.1": + version: 10.1.1 + resolution: "minimatch@npm:10.1.1" + dependencies: + "@isaacs/brace-expansion": "npm:^5.0.0" + checksum: 10/110f38921ea527022e90f7a5f43721838ac740d0a0c26881c03b57c261354fb9a0430e40b2c56dfcea2ef3c773768f27210d1106f1f2be19cde3eea93f26f45e + languageName: node + linkType: hard + "minimist-options@npm:4.1.0": version: 4.1.0 resolution: "minimist-options@npm:4.1.0" @@ -11799,6 +13016,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.3.0": + version: 0.3.4 + resolution: "napi-postinstall@npm:0.3.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10/5541381508f9e1051ff3518701c7130ebac779abb3a1ffe9391fcc3cab4cc0569b0ba0952357db3f6b12909c3bb508359a7a60261ffd795feebbdab967175832 + languageName: node + linkType: hard + "natural-compare-lite@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare-lite@npm:1.4.0" @@ -12316,7 +13542,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": version: 1.13.4 resolution: "object-inspect@npm:1.13.4" checksum: 10/aa13b1190ad3e366f6c83ad8a16ed37a19ed57d267385aa4bfdccda833d7b90465c057ff6c55d035a6b2e52c1a2295582b294217a0a3a1ae7abdd6877ef781fb @@ -12347,7 +13573,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.2, object.assign@npm:^4.1.4": +"object.assign@npm:^4.1.4": version: 4.1.4 resolution: "object.assign@npm:4.1.4" dependencies: @@ -12359,48 +13585,64 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.5": - version: 1.1.6 - resolution: "object.entries@npm:1.1.6" +"object.assign@npm:^4.1.7": + version: 4.1.7 + resolution: "object.assign@npm:4.1.7" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: 10/08a09ff839fd541e8af90a47c67a3dd71721683cdc28e55470e191a8afd8b61188fb9a429fd1d1805808097d8d5950b47c0c2862157dad891226112d8321401b + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + has-symbols: "npm:^1.1.0" + object-keys: "npm:^1.1.1" + checksum: 10/3fe28cdd779f2a728a9a66bd688679ba231a2b16646cd1e46b528fe7c947494387dda4bc189eff3417f3717ef4f0a8f2439347cf9a9aa3cef722fbfd9f615587 languageName: node linkType: hard -"object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" +"object.entries@npm:^1.1.9": + version: 1.1.9 + resolution: "object.entries@npm:1.1.9" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/1bfbe42a51f8d84e417d193fae78e4b8eebb134514cdd44406480f8e8a0e075071e0717635d8e3eccd50fec08c1d555fe505c38804cbac0808397187653edd59 + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.1.1" + checksum: 10/24163ab1e1e013796693fc5f5d349e8b3ac0b6a34a7edb6c17d3dd45c6a8854145780c57d302a82512c1582f63720f4b4779d6c1cfba12cbb1420b978802d8a3 languageName: node linkType: hard -"object.groupby@npm:^1.0.1": - version: 1.0.1 - resolution: "object.groupby@npm:1.0.1" +"object.fromentries@npm:^2.0.8": + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" - checksum: 10/b7123d91403f95d63978513b23a6079c30f503311f64035fafc863c291c787f287b58df3b21ef002ce1d0b820958c9009dd5a8ab696e0eca325639d345e41524 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + checksum: 10/5b2e80f7af1778b885e3d06aeb335dcc86965e39464671adb7167ab06ac3b0f5dd2e637a90d8ebd7426d69c6f135a4753ba3dd7d0fe2a7030cf718dcb910fd92 languageName: node linkType: hard -"object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" +"object.groupby@npm:^1.0.3": + version: 1.0.3 + resolution: "object.groupby@npm:1.0.3" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/20ab42c0bbf984405c80e060114b18cf5d629a40a132c7eac4fb79c5d06deb97496311c19297dcf9c61f45c2539cd4c7f7c5d6230e51db360ff297bbc9910162 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + checksum: 10/44cb86dd2c660434be65f7585c54b62f0425b0c96b5c948d2756be253ef06737da7e68d7106e35506ce4a44d16aa85a413d11c5034eb7ce5579ec28752eb42d0 + languageName: node + linkType: hard + +"object.values@npm:^1.1.6, object.values@npm:^1.2.1": + version: 1.2.1 + resolution: "object.values@npm:1.2.1" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/f5ec9eccdefeaaa834b089c525663436812a65ff13de7964a1c3a9110f32054f2d58aa476a645bb14f75a79f3fe1154fb3e7bfdae7ac1e80affe171b2ef74bce languageName: node linkType: hard @@ -12566,6 +13808,17 @@ __metadata: languageName: node linkType: hard +"own-keys@npm:^1.0.1": + version: 1.0.1 + resolution: "own-keys@npm:1.0.1" + dependencies: + get-intrinsic: "npm:^1.2.6" + object-keys: "npm:^1.1.1" + safe-push-apply: "npm:^1.0.0" + checksum: 10/ab4bb3b8636908554fc19bf899e225444195092864cb61503a0d048fdaf662b04be2605b636a4ffeaf6e8811f6fcfa8cbb210ec964c0eb1a41eb853e1d5d2f41 + languageName: node + linkType: hard + "p-cancelable@npm:^2.0.0": version: 2.1.1 resolution: "p-cancelable@npm:2.1.1" @@ -12853,6 +14106,15 @@ __metadata: languageName: node linkType: hard +"parse-imports-exports@npm:^0.2.4": + version: 0.2.4 + resolution: "parse-imports-exports@npm:0.2.4" + dependencies: + parse-statements: "npm:1.0.11" + checksum: 10/144d459771d1aeaa80eebffe43a2074c34e5b79a86d326c907efea90b62ff41af9555600b8e117e6cab717654d8e20b440e9ab09cdbbc9092f352cb0a9e1f3a3 + languageName: node + linkType: hard + "parse-json@npm:^4.0.0": version: 4.0.0 resolution: "parse-json@npm:4.0.0" @@ -12882,6 +14144,13 @@ __metadata: languageName: node linkType: hard +"parse-statements@npm:1.0.11": + version: 1.0.11 + resolution: "parse-statements@npm:1.0.11" + checksum: 10/287c2739f4cbffa08e28a95ea2d3ff4a8a51ddb367df6212ae2cd80580a1189e09c6edcb8277fc05d0fdbcb93c86ad16b591f317e2fe12ac4189de738863e514 + languageName: node + linkType: hard + "parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -13069,6 +14338,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.2, picomatch@npm:^4.0.3": + version: 4.0.3 + resolution: "picomatch@npm:4.0.3" + checksum: 10/57b99055f40b16798f2802916d9c17e9744e620a0db136554af01d19598b96e45e2f00014c91d1b8b13874b80caa8c295b3d589a3f72373ec4aaf54baa5962d5 + languageName: node + linkType: hard + "pid-cwd@npm:^1.2.0": version: 1.2.0 resolution: "pid-cwd@npm:1.2.0" @@ -13330,6 +14606,17 @@ __metadata: languageName: node linkType: hard +"prop-types@npm:^15.8.1": + version: 15.8.1 + resolution: "prop-types@npm:15.8.1" + dependencies: + loose-envify: "npm:^1.4.0" + object-assign: "npm:^4.1.1" + react-is: "npm:^16.13.1" + checksum: 10/7d959caec002bc964c86cdc461ec93108b27337dabe6192fb97d69e16a0c799a03462713868b40749bfc1caf5f57ef80ac3e4ffad3effa636ee667582a75e2c0 + languageName: node + linkType: hard + "proper-lockfile@npm:^3.2.0": version: 3.2.0 resolution: "proper-lockfile@npm:3.2.0" @@ -13539,6 +14826,13 @@ __metadata: languageName: node linkType: hard +"react-is@npm:^16.13.1": + version: 16.13.1 + resolution: "react-is@npm:16.13.1" + checksum: 10/5aa564a1cde7d391ac980bedee21202fc90bdea3b399952117f54fb71a932af1e5902020144fb354b4690b2414a0c7aafe798eb617b76a3d441d956db7726fdf + languageName: node + linkType: hard + "react-is@npm:^18.0.0": version: 18.2.0 resolution: "react-is@npm:18.2.0" @@ -13745,6 +15039,22 @@ __metadata: languageName: node linkType: hard +"reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.9": + version: 1.0.10 + resolution: "reflect.getprototypeof@npm:1.0.10" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.9" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.7" + get-proto: "npm:^1.0.1" + which-builtin-type: "npm:^1.2.1" + checksum: 10/80a4e2be716f4fe46a89a08ccad0863b47e8ce0f49616cab2d65dab0fbd53c6fdba0f52935fd41d37a2e4e22355c272004f920d63070de849f66eea7aeb4a081 + languageName: node + linkType: hard + "regenerate-unicode-properties@npm:^10.1.0": version: 10.1.1 resolution: "regenerate-unicode-properties@npm:10.1.1" @@ -13797,6 +15107,20 @@ __metadata: languageName: node linkType: hard +"regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": + version: 1.5.4 + resolution: "regexp.prototype.flags@npm:1.5.4" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-errors: "npm:^1.3.0" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + set-function-name: "npm:^2.0.2" + checksum: 10/8ab897ca445968e0b96f6237641510f3243e59c180ee2ee8d83889c52ff735dd1bf3657fcd36db053e35e1d823dd53f2565d0b8021ea282c9fe62401c6c3bd6d + languageName: node + linkType: hard + "regexpu-core@npm:^5.3.1": version: 5.3.2 resolution: "regexpu-core@npm:5.3.2" @@ -13949,7 +15273,14 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.22.4, resolve@npm:^1.9.0": +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10/0763150adf303040c304009231314d1e84c6e5ebfa2d82b7d94e96a6e82bacd1dcc0b58ae257315f3c8adb89a91d8d0f12928241cba2df1680fbe6f60bf99b0e + languageName: node + linkType: hard + +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.22.4, resolve@npm:^1.9.0": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -13962,7 +15293,20 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.9.0#optional!builtin": +"resolve@npm:^2.0.0-next.5": + version: 2.0.0-next.5 + resolution: "resolve@npm:2.0.0-next.5" + dependencies: + is-core-module: "npm:^2.13.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/2d6fd28699f901744368e6f2032b4268b4c7b9185fd8beb64f68c93ac6b22e52ae13560ceefc96241a665b985edf9ffd393ae26d2946a7d3a07b7007b7d51e79 + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.9.0#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -13975,6 +15319,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^2.0.0-next.5#optional!builtin": + version: 2.0.0-next.5 + resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#optional!builtin::version=2.0.0-next.5&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.13.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/05fa778de9d0347c8b889eb7a18f1f06bf0f801b0eb4610b4871a4b2f22e220900cf0ad525e94f990bb8d8921c07754ab2122c0c225ab4cdcea98f36e64fa4c2 + languageName: node + linkType: hard + "responselike@npm:^2.0.0": version: 2.0.1 resolution: "responselike@npm:2.0.1" @@ -14119,6 +15476,19 @@ __metadata: languageName: node linkType: hard +"safe-array-concat@npm:^1.1.3": + version: 1.1.3 + resolution: "safe-array-concat@npm:1.1.3" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.2" + get-intrinsic: "npm:^1.2.6" + has-symbols: "npm:^1.1.0" + isarray: "npm:^2.0.5" + checksum: 10/fac4f40f20a3f7da024b54792fcc61059e814566dcbb04586bfefef4d3b942b2408933f25b7b3dd024affd3f2a6bbc916bef04807855e4f192413941369db864 + languageName: node + linkType: hard + "safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -14133,6 +15503,16 @@ __metadata: languageName: node linkType: hard +"safe-push-apply@npm:^1.0.0": + version: 1.0.0 + resolution: "safe-push-apply@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + isarray: "npm:^2.0.5" + checksum: 10/2bd4e53b6694f7134b9cf93631480e7fafc8637165f0ee91d5a4af5e7f33d37de9562d1af5021178dd4217d0230cde8d6530fa28cfa1ebff9a431bf8fff124b4 + languageName: node + linkType: hard + "safe-regex-test@npm:^1.0.0": version: 1.0.0 resolution: "safe-regex-test@npm:1.0.0" @@ -14144,6 +15524,17 @@ __metadata: languageName: node linkType: hard +"safe-regex-test@npm:^1.0.3, safe-regex-test@npm:^1.1.0": + version: 1.1.0 + resolution: "safe-regex-test@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + is-regex: "npm:^1.2.1" + checksum: 10/ebdb61f305bf4756a5b023ad86067df5a11b26898573afe9e52a548a63c3bd594825d9b0e2dde2eb3c94e57e0e04ac9929d4107c394f7b8e56a4613bed46c69a + languageName: node + linkType: hard + "safe-stable-stringify@npm:^1.1.0": version: 1.1.1 resolution: "safe-stable-stringify@npm:1.1.1" @@ -14330,6 +15721,29 @@ __metadata: languageName: node linkType: hard +"set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + functions-have-names: "npm:^1.2.3" + has-property-descriptors: "npm:^1.0.2" + checksum: 10/c7614154a53ebf8c0428a6c40a3b0b47dac30587c1a19703d1b75f003803f73cdfa6a93474a9ba678fa565ef5fbddc2fae79bca03b7d22ab5fd5163dbe571a74 + languageName: node + linkType: hard + +"set-proto@npm:^1.0.0": + version: 1.0.0 + resolution: "set-proto@npm:1.0.0" + dependencies: + dunder-proto: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + checksum: 10/b87f8187bca595ddc3c0721ece4635015fd9d7cb294e6dd2e394ce5186a71bbfa4dc8a35010958c65e43ad83cde09642660e61a952883c24fd6b45ead15f045c + languageName: node + linkType: hard + "setimmediate@npm:^1.0.5": version: 1.0.5 resolution: "setimmediate@npm:1.0.5" @@ -14847,7 +16261,7 @@ __metadata: languageName: node linkType: hard -"spdx-expression-parse@npm:^3.0.0, spdx-expression-parse@npm:^3.0.1": +"spdx-expression-parse@npm:^3.0.0": version: 3.0.1 resolution: "spdx-expression-parse@npm:3.0.1" dependencies: @@ -14857,6 +16271,16 @@ __metadata: languageName: node linkType: hard +"spdx-expression-parse@npm:^4.0.0": + version: 4.0.0 + resolution: "spdx-expression-parse@npm:4.0.0" + dependencies: + spdx-exceptions: "npm:^2.1.0" + spdx-license-ids: "npm:^3.0.0" + checksum: 10/936be681fbf5edeec3a79c023136479f70d6edb3fd3875089ac86cd324c6c8c81add47399edead296d1d0af17ae5ce88c7f88885eb150b62c2ff6e535841ca6a + languageName: node + linkType: hard + "spdx-license-ids@npm:^3.0.0": version: 3.0.11 resolution: "spdx-license-ids@npm:3.0.11" @@ -14962,6 +16386,13 @@ __metadata: languageName: node linkType: hard +"stable-hash-x@npm:^0.2.0": + version: 0.2.0 + resolution: "stable-hash-x@npm:0.2.0" + checksum: 10/136f05d0e4d441876012b423541476ff5b695c93b56d1959560be858b9e324ea6de6c16ecbd735a040ee8396427dd867bed0bf90b2cdb1fc422566747b91a0e5 + languageName: node + linkType: hard + "stack-trace@npm:0.0.x": version: 0.0.10 resolution: "stack-trace@npm:0.0.10" @@ -14983,6 +16414,16 @@ __metadata: languageName: node linkType: hard +"stop-iteration-iterator@npm:^1.1.0": + version: 1.1.0 + resolution: "stop-iteration-iterator@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + internal-slot: "npm:^1.1.0" + checksum: 10/ff36c4db171ee76c936ccfe9541946b77017f12703d4c446652017356816862d3aa029a64e7d4c4ceb484e00ed4a81789333896390d808458638f3a216aa1f41 + languageName: node + linkType: hard + "stream-browserify@npm:^3.0.0": version: 3.0.0 resolution: "stream-browserify@npm:3.0.0" @@ -15052,6 +16493,63 @@ __metadata: languageName: node linkType: hard +"string.prototype.includes@npm:^2.0.1": + version: 2.0.1 + resolution: "string.prototype.includes@npm:2.0.1" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.3" + checksum: 10/939a5447e4a99a86f29cc97fa24f358e5071f79e34746de4c7eb2cd736ed626ad24870a1e356f33915b3b352bb87f7e4d1cebc15d1e1aaae0923777e21b1b28b + languageName: node + linkType: hard + +"string.prototype.matchall@npm:^4.0.12": + version: 4.0.12 + resolution: "string.prototype.matchall@npm:4.0.12" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.6" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.6" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + internal-slot: "npm:^1.1.0" + regexp.prototype.flags: "npm:^1.5.3" + set-function-name: "npm:^2.0.2" + side-channel: "npm:^1.1.0" + checksum: 10/e4ab34b9e7639211e6c5e9759adb063028c5c5c4fc32ad967838b2bd1e5ce83a66ae8ec755d24a79302849f090b59194571b2c33471e86e7821b21c0f56df316 + languageName: node + linkType: hard + +"string.prototype.repeat@npm:^1.0.0": + version: 1.0.0 + resolution: "string.prototype.repeat@npm:1.0.0" + dependencies: + define-properties: "npm:^1.1.3" + es-abstract: "npm:^1.17.5" + checksum: 10/4b1bd91b75fa8fdf0541625184ebe80e445a465ce4253c19c3bccd633898005dadae0f74b85ae72662a53aafb8035bf48f8f5c0755aec09bc106a7f13959d05e + languageName: node + linkType: hard + +"string.prototype.trim@npm:^1.2.10": + version: 1.2.10 + resolution: "string.prototype.trim@npm:1.2.10" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.2" + define-data-property: "npm:^1.1.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-object-atoms: "npm:^1.0.0" + has-property-descriptors: "npm:^1.0.2" + checksum: 10/47bb63cd2470a64bc5e2da1e570d369c016ccaa85c918c3a8bb4ab5965120f35e66d1f85ea544496fac84b9207a6b722adf007e6c548acd0813e5f8a82f9712a + languageName: node + linkType: hard + "string.prototype.trim@npm:^1.2.8": version: 1.2.8 resolution: "string.prototype.trim@npm:1.2.8" @@ -15074,6 +16572,18 @@ __metadata: languageName: node linkType: hard +"string.prototype.trimend@npm:^1.0.9": + version: 1.0.9 + resolution: "string.prototype.trimend@npm:1.0.9" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.2" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/140c73899b6747de9e499c7c2e7a83d549c47a26fa06045b69492be9cfb9e2a95187499a373983a08a115ecff8bc3bd7b0fb09b8ff72fb2172abe766849272ef + languageName: node + linkType: hard + "string.prototype.trimstart@npm:^1.0.7": version: 1.0.7 resolution: "string.prototype.trimstart@npm:1.0.7" @@ -15085,6 +16595,17 @@ __metadata: languageName: node linkType: hard +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/160167dfbd68e6f7cb9f51a16074eebfce1571656fc31d40c3738ca9e30e35496f2c046fe57b6ad49f65f238a152be8c86fd9a2dd58682b5eba39dad995b3674 + languageName: node + linkType: hard + "string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" @@ -15351,16 +16872,16 @@ __metadata: languageName: node linkType: hard -"tar@npm:^7.5.4": - version: 7.5.6 - resolution: "tar@npm:7.5.6" +"tar@npm:7.5.7": + version: 7.5.7 + resolution: "tar@npm:7.5.7" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/cf4a84d79b9327fcf765f2ea16de4702b9b8dd7dc6b1840b16e0f999628d96b81b2c7efbf83d4eb42b0164856f1db887a5a61ffef97d36cdb77cac742219f9ee + checksum: 10/0d6938dd32fe5c0f17c8098d92bd9889ee0ed9d11f12381b8146b6e8c87bb5aa49feec7abc42463f0597503d8e89e4c4c0b42bff1a5a38444e918b4878b7fd21 languageName: node linkType: hard @@ -15543,6 +17064,16 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15": + version: 0.2.15 + resolution: "tinyglobby@npm:0.2.15" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.3" + checksum: 10/d72bd826a8b0fa5fa3929e7fe5ba48fceb2ae495df3a231b6c5408cd7d8c00b58ab5a9c2a76ba56a62ee9b5e083626f1f33599734bed1ffc4b792406408f0ca2 + languageName: node + linkType: hard + "tinylogic@npm:^2.0.0": version: 2.0.0 resolution: "tinylogic@npm:2.0.0" @@ -15653,6 +17184,26 @@ __metadata: languageName: node linkType: hard +"ts-api-utils@npm:^2.4.0": + version: 2.4.0 + resolution: "ts-api-utils@npm:2.4.0" + peerDependencies: + typescript: ">=4.8.4" + checksum: 10/d6b2b3b6caad8d2f4ddc0c3785d22bb1a6041773335a1c71d73a5d67d11d993763fe8e4faefc4a4d03bb42b26c6126bbcf2e34826baed1def5369d0ebad358fa + languageName: node + linkType: hard + +"ts-declaration-location@npm:^1.0.6": + version: 1.0.7 + resolution: "ts-declaration-location@npm:1.0.7" + dependencies: + picomatch: "npm:^4.0.2" + peerDependencies: + typescript: ">=4.0.0" + checksum: 10/a7932fc75d41f10c16089f8f5a5c1ea49d6afca30f09c91c1df14d0a8510f72bcb9f8a395c04f060b66b855b6bd7ea4df81b335fb9d21bef402969a672a4afa7 + languageName: node + linkType: hard + "ts-loader@npm:^9.5.0": version: 9.5.0 resolution: "ts-loader@npm:9.5.0" @@ -15679,9 +17230,9 @@ __metadata: languageName: node linkType: hard -"ts-node@npm:^10.4.0": - version: 10.9.2 - resolution: "ts-node@npm:10.9.2" +"ts-node@npm:^10.9.1": + version: 10.9.1 + resolution: "ts-node@npm:10.9.1" dependencies: "@cspotcode/source-map-support": "npm:^0.8.0" "@tsconfig/node10": "npm:^1.0.7" @@ -15713,13 +17264,13 @@ __metadata: ts-node-script: dist/bin-script.js ts-node-transpile-only: dist/bin-transpile.js ts-script: dist/bin-script-deprecated.js - checksum: 10/a91a15b3c9f76ac462f006fa88b6bfa528130dcfb849dd7ef7f9d640832ab681e235b8a2bc58ecde42f72851cc1d5d4e22c901b0c11aa51001ea1d395074b794 + checksum: 10/bee56d4dc96ccbafc99dfab7b73fbabc62abab2562af53cdea91c874a301b9d11e42bc33c0a032a6ed6d813dbdc9295ec73dde7b73ea4ebde02b0e22006f7e04 languageName: node linkType: hard -"ts-node@npm:^10.9.1": - version: 10.9.1 - resolution: "ts-node@npm:10.9.1" +"ts-node@npm:^10.9.2": + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" dependencies: "@cspotcode/source-map-support": "npm:^0.8.0" "@tsconfig/node10": "npm:^1.0.7" @@ -15751,7 +17302,7 @@ __metadata: ts-node-script: dist/bin-script.js ts-node-transpile-only: dist/bin-transpile.js ts-script: dist/bin-script-deprecated.js - checksum: 10/bee56d4dc96ccbafc99dfab7b73fbabc62abab2562af53cdea91c874a301b9d11e42bc33c0a032a6ed6d813dbdc9295ec73dde7b73ea4ebde02b0e22006f7e04 + checksum: 10/a91a15b3c9f76ac462f006fa88b6bfa528130dcfb849dd7ef7f9d640832ab681e235b8a2bc58ecde42f72851cc1d5d4e22c901b0c11aa51001ea1d395074b794 languageName: node linkType: hard @@ -15804,7 +17355,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^1.8.1, tslib@npm:^1.9.0": +"tslib@npm:^1.9.0": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: 10/7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb @@ -15818,17 +17369,6 @@ __metadata: languageName: node linkType: hard -"tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" - dependencies: - tslib: "npm:^1.8.1" - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 10/ea036bec1dd024e309939ffd49fda7a351c0e87a1b8eb049570dd119d447250e2c56e0e6c00554e8205760e7417793fdebff752a46e573fbe07d4f375502a5b2 - languageName: node - linkType: hard - "tuf-js@npm:^1.1.7": version: 1.1.7 resolution: "tuf-js@npm:1.1.7" @@ -15902,13 +17442,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 10/8907e16284b2d6cfa4f4817e93520121941baba36b39219ea36acfe64c86b9dbc10c9941af450bd60832c8f43464974d51c0957f9858bc66b952b66b6914cbb9 - languageName: node - linkType: hard - "type-fest@npm:^0.21.2, type-fest@npm:^0.21.3": version: 0.21.3 resolution: "type-fest@npm:0.21.3" @@ -15974,6 +17507,19 @@ __metadata: languageName: node linkType: hard +"typed-array-byte-length@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-byte-length@npm:1.0.3" + dependencies: + call-bind: "npm:^1.0.8" + for-each: "npm:^0.3.3" + gopd: "npm:^1.2.0" + has-proto: "npm:^1.2.0" + is-typed-array: "npm:^1.1.14" + checksum: 10/269dad101dda73e3110117a9b84db86f0b5c07dad3a9418116fd38d580cab7fc628a4fc167e29b6d7c39da2f53374b78e7cb578b3c5ec7a556689d985d193519 + languageName: node + linkType: hard + "typed-array-byte-offset@npm:^1.0.0": version: 1.0.0 resolution: "typed-array-byte-offset@npm:1.0.0" @@ -15987,6 +17533,21 @@ __metadata: languageName: node linkType: hard +"typed-array-byte-offset@npm:^1.0.4": + version: 1.0.4 + resolution: "typed-array-byte-offset@npm:1.0.4" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + for-each: "npm:^0.3.3" + gopd: "npm:^1.2.0" + has-proto: "npm:^1.2.0" + is-typed-array: "npm:^1.1.15" + reflect.getprototypeof: "npm:^1.0.9" + checksum: 10/c2869aa584cdae24ecfd282f20a0f556b13a49a9d5bca1713370bb3c89dff0ccbc5ceb45cb5b784c98f4579e5e3e2a07e438c3a5b8294583e2bd4abbd5104fb5 + languageName: node + linkType: hard + "typed-array-length@npm:^1.0.4": version: 1.0.4 resolution: "typed-array-length@npm:1.0.4" @@ -15998,6 +17559,20 @@ __metadata: languageName: node linkType: hard +"typed-array-length@npm:^1.0.7": + version: 1.0.7 + resolution: "typed-array-length@npm:1.0.7" + dependencies: + call-bind: "npm:^1.0.7" + for-each: "npm:^0.3.3" + gopd: "npm:^1.0.1" + is-typed-array: "npm:^1.1.13" + possible-typed-array-names: "npm:^1.0.0" + reflect.getprototypeof: "npm:^1.0.6" + checksum: 10/d6b2f0e81161682d2726eb92b1dc2b0890890f9930f33f9bcf6fc7272895ce66bc368066d273e6677776de167608adc53fcf81f1be39a146d64b630edbf2081c + languageName: node + linkType: hard + "typed-function@npm:^2.1.0": version: 2.1.0 resolution: "typed-function@npm:2.1.0" @@ -16014,6 +17589,21 @@ __metadata: languageName: node linkType: hard +"typescript-eslint@npm:^8.53.1": + version: 8.54.0 + resolution: "typescript-eslint@npm:8.54.0" + dependencies: + "@typescript-eslint/eslint-plugin": "npm:8.54.0" + "@typescript-eslint/parser": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/utils": "npm:8.54.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/21b1a27fd44716df8d2c7bac4ebd0caef196a04375fff7919dc817066017b6b8700f1e242bd065a26ac7ce0505b7a588626099e04a28142504ed4f0aae8bffb1 + languageName: node + linkType: hard + "typescript@npm:^3.9.5": version: 3.9.10 resolution: "typescript@npm:3.9.10" @@ -16024,6 +17614,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.7.3": + version: 5.9.3 + resolution: "typescript@npm:5.9.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10/c089d9d3da2729fd4ac517f9b0e0485914c4b3c26f80dc0cffcb5de1719a17951e92425d55db59515c1a7ddab65808466debb864d0d56dcf43f27007d0709594 + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A^3.9.5#optional!builtin": version: 3.9.10 resolution: "typescript@patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3" @@ -16034,6 +17634,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10/696e1b017bc2635f4e0c94eb4435357701008e2f272f553d06e35b494b8ddc60aa221145e286c28ace0c89ee32827a28c2040e3a69bdc108b1a5dc8fb40b72e3 + languageName: node + linkType: hard + "ua-parser-js@npm:^1.0.33": version: 1.0.33 resolution: "ua-parser-js@npm:1.0.33" @@ -16090,6 +17700,18 @@ __metadata: languageName: node linkType: hard +"unbox-primitive@npm:^1.1.0": + version: 1.1.0 + resolution: "unbox-primitive@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + has-bigints: "npm:^1.0.2" + has-symbols: "npm:^1.1.0" + which-boxed-primitive: "npm:^1.1.1" + checksum: 10/fadb347020f66b2c8aeacf8b9a79826fa34cc5e5457af4eb0bbc4e79bd87fed0fa795949825df534320f7c13f199259516ad30abc55a6e7b91d8d996ca069e50 + languageName: node + linkType: hard + "undefsafe@npm:^2.0.5": version: 2.0.5 resolution: "undefsafe@npm:2.0.5" @@ -16097,6 +17719,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.21.0": + version: 6.21.0 + resolution: "undici-types@npm:6.21.0" + checksum: 10/ec8f41aa4359d50f9b59fa61fe3efce3477cc681908c8f84354d8567bb3701fafdddf36ef6bff307024d3feb42c837cf6f670314ba37fc8145e219560e473d14 + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -16174,6 +17803,73 @@ __metadata: languageName: node linkType: hard +"unrs-resolver@npm:^1.7.11, unrs-resolver@npm:^1.9.2": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10/4de653508cbaae47883a896bd5cdfef0e5e87b428d62620d16fd35cd534beaebf08ebf0cf2f8b4922aa947b2fe745180facf6cc3f39ba364f7ce0f974cb06a70 + languageName: node + linkType: hard + "untildify@npm:^4.0.0": version: 4.0.0 resolution: "untildify@npm:4.0.0" @@ -16598,6 +18294,52 @@ __metadata: languageName: node linkType: hard +"which-boxed-primitive@npm:^1.1.0, which-boxed-primitive@npm:^1.1.1": + version: 1.1.1 + resolution: "which-boxed-primitive@npm:1.1.1" + dependencies: + is-bigint: "npm:^1.1.0" + is-boolean-object: "npm:^1.2.1" + is-number-object: "npm:^1.1.1" + is-string: "npm:^1.1.1" + is-symbol: "npm:^1.1.1" + checksum: 10/a877c0667bc089518c83ad4d845cf8296b03efe3565c1de1940c646e00a2a1ae9ed8a185bcfa27cbf352de7906f0616d83b9d2f19ca500ee02a551fb5cf40740 + languageName: node + linkType: hard + +"which-builtin-type@npm:^1.2.1": + version: 1.2.1 + resolution: "which-builtin-type@npm:1.2.1" + dependencies: + call-bound: "npm:^1.0.2" + function.prototype.name: "npm:^1.1.6" + has-tostringtag: "npm:^1.0.2" + is-async-function: "npm:^2.0.0" + is-date-object: "npm:^1.1.0" + is-finalizationregistry: "npm:^1.1.0" + is-generator-function: "npm:^1.0.10" + is-regex: "npm:^1.2.1" + is-weakref: "npm:^1.0.2" + isarray: "npm:^2.0.5" + which-boxed-primitive: "npm:^1.1.0" + which-collection: "npm:^1.0.2" + which-typed-array: "npm:^1.1.16" + checksum: 10/22c81c5cb7a896c5171742cd30c90d992ff13fb1ea7693e6cf80af077791613fb3f89aa9b4b7f890bd47b6ce09c6322c409932359580a2a2a54057f7b52d1cbe + languageName: node + linkType: hard + +"which-collection@npm:^1.0.2": + version: 1.0.2 + resolution: "which-collection@npm:1.0.2" + dependencies: + is-map: "npm:^2.0.3" + is-set: "npm:^2.0.3" + is-weakmap: "npm:^2.0.2" + is-weakset: "npm:^2.0.3" + checksum: 10/674bf659b9bcfe4055f08634b48a8588e879161b9fefed57e9ec4ff5601e4d50a05ccd76cf10f698ef5873784e5df3223336d56c7ce88e13bcf52ebe582fc8d7 + languageName: node + linkType: hard + "which-module@npm:^2.0.0": version: 2.0.0 resolution: "which-module@npm:2.0.0" @@ -16643,6 +18385,21 @@ __metadata: languageName: node linkType: hard +"which-typed-array@npm:^1.1.19": + version: 1.1.20 + resolution: "which-typed-array@npm:1.1.20" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + for-each: "npm:^0.3.5" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + checksum: 10/e56da3fc995d330ff012f682476f7883c16b12d36c6717c87c7ca23eb5a5ef957fa89115dacb389b11a9b4e99d5dbe2d12689b4d5d08c050b5aed0eae385b840 + languageName: node + linkType: hard + "which@npm:^1.2.1": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -17113,3 +18870,19 @@ __metadata: checksum: 10/a1f1273ce234300479fb0b8fcd7c4a3ea1be0b63d04f1083bb8df33b10654fb3e1a1162e18c06aa2f22d257be3c60b84f3578c9cbd19134b1973d0578cd90065 languageName: node linkType: hard + +"zod-validation-error@npm:^3.5.0 || ^4.0.0": + version: 4.0.2 + resolution: "zod-validation-error@npm:4.0.2" + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + checksum: 10/5e35ca8ebb4602dcb526e122d7e9fca695c4a479bd97535f3400a732d49160f24f7213a9ed64986fc9dc3a2e8a6c4e1241ec0c4d8a4e3e69ea91a0328ded2192 + languageName: node + linkType: hard + +"zod@npm:^3.25.0 || ^4.0.0": + version: 4.3.6 + resolution: "zod@npm:4.3.6" + checksum: 10/25fc0f62e01b557b4644bf0b393bbaf47542ab30877c37837ea8caf314a8713d220c7d7fe51f68ffa72f0e1018ddfa34d96f1973d23033f5a2a5a9b6b9d9da01 + languageName: node + linkType: hard