quantumcoin 7.0.11 → 7.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-SDK.md +828 -807
- package/README.md +17 -0
- package/config.d.ts +50 -50
- package/examples/example-generated-sdk-js/README.md +65 -0
- package/examples/example-generated-sdk-js/examples/_test-wallet.js +17 -0
- package/examples/example-generated-sdk-js/examples/deploy.js +41 -0
- package/examples/example-generated-sdk-js/examples/events.js +36 -0
- package/examples/example-generated-sdk-js/examples/read-operations.js +46 -0
- package/examples/example-generated-sdk-js/examples/write-operations.js +44 -0
- package/examples/example-generated-sdk-js/index.d.ts +1 -0
- package/examples/example-generated-sdk-js/index.js +15 -0
- package/examples/example-generated-sdk-js/package-lock.json +59 -0
- package/examples/example-generated-sdk-js/package.json +22 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20.d.ts +19 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20.js +353 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20__factory.d.ts +10 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20__factory.js +29 -0
- package/examples/example-generated-sdk-js/src/index.d.ts +4 -0
- package/examples/example-generated-sdk-js/src/index.js +5 -0
- package/examples/example-generated-sdk-js/src/quantumcoin-shims.d.ts +23 -0
- package/examples/example-generated-sdk-js/src/types.d.ts +3 -0
- package/examples/example-generated-sdk-js/src/types.js +3 -0
- package/examples/example-generated-sdk-js/test/e2e/SimpleERC20.e2e.test.js +78 -0
- package/examples/example-generated-sdk-ts/README.md +65 -0
- package/examples/example-generated-sdk-ts/examples/_test-wallet.js +17 -0
- package/examples/example-generated-sdk-ts/examples/deploy.js +41 -0
- package/examples/example-generated-sdk-ts/examples/events.js +36 -0
- package/examples/example-generated-sdk-ts/examples/read-operations.js +46 -0
- package/examples/example-generated-sdk-ts/examples/write-operations.js +44 -0
- package/examples/example-generated-sdk-ts/index.d.ts +1 -0
- package/examples/example-generated-sdk-ts/index.js +15 -0
- package/examples/example-generated-sdk-ts/package-lock.json +59 -0
- package/examples/example-generated-sdk-ts/package.json +23 -0
- package/examples/example-generated-sdk-ts/src/SimpleERC20.ts +334 -0
- package/examples/example-generated-sdk-ts/src/SimpleERC20__factory.ts +28 -0
- package/examples/example-generated-sdk-ts/src/index.ts +4 -0
- package/examples/example-generated-sdk-ts/src/quantumcoin-shims.d.ts +23 -0
- package/examples/example-generated-sdk-ts/src/types.ts +4 -0
- package/examples/example-generated-sdk-ts/test/e2e/SimpleERC20.e2e.test.js +78 -0
- package/examples/example-generated-sdk-ts/tsconfig.json +14 -0
- package/examples/package-lock.json +1 -1
- package/examples/sdk-generator-erc20.inline.json +251 -251
- package/generate-sdk.js +1825 -1823
- package/package.json +1 -1
- package/src/abi/fragments.d.ts +42 -42
- package/src/abi/index.d.ts +13 -13
- package/src/contract/index.d.ts +9 -9
- package/src/errors/index.d.ts +92 -92
- package/src/generator/index.d.ts +11 -4
- package/src/generator/index.js +33 -5
- package/src/internal/hex.d.ts +68 -61
- package/src/internal/hex.js +36 -0
- package/src/providers/json-rpc-provider.d.ts +12 -12
- package/src/providers/provider.js +3 -3
- package/src/utils/address.d.ts +58 -58
- package/src/utils/encoding.d.ts +120 -120
- package/src/utils/hashing.js +298 -298
- package/src/utils/index.d.ts +63 -63
- package/src/utils/index.js +14 -14
- package/src/utils/result.d.ts +57 -57
- package/src/utils/rlp.d.ts +12 -12
- package/src/utils/units.d.ts +29 -29
- package/src/wallet/index.d.ts +10 -10
- package/src/wallet/wallet.d.ts +192 -187
- package/src/wallet/wallet.js +630 -610
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/README.md +83 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.abi.json +12544 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.bin +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.js +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.d.ts +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.js +21 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package-lock.json +597 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package.json +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.d.ts +1280 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.js +14021 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.d.ts +11 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.js +29 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.d.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.js +5 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.d.ts +3 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.js +3 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.extra.test.js +195 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/README.md +83 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.abi.json +12544 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.bin +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.js +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.d.ts +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.js +21 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package-lock.json +597 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package.json +26 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes.ts +13940 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes__factory.ts +29 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/index.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/types.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.extra.test.js +195 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/tsconfig.json +18 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/README.md +74 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.abi.json +245 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.bin +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.js +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.d.ts +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.js +16 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package-lock.json +597 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package.json +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.d.ts +24 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.js +372 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.d.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.js +29 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.d.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.js +5 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.d.ts +3 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.js +3 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/test/e2e/SimpleERC20.e2e.test.js +90 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/README.md +74 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.abi.json +245 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.bin +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.js +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.d.ts +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.js +16 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package-lock.json +597 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package.json +26 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20.ts +355 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20__factory.ts +28 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/index.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/types.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/test/e2e/SimpleERC20.e2e.test.js +90 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/tsconfig.json +18 -0
- package/test/e2e/generator-interface.e2e.test.js +163 -0
- package/test/e2e/generator-interface.e2e.test.ts +158 -0
- package/test/e2e/signing-context-and-fee.e2e.test.js +141 -141
- package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -128
- package/test/integration/provider.test.js +88 -88
- package/test/unit/address-wallet.test.js +892 -751
- package/test/unit/address-wallet.test.ts +877 -736
- package/test/unit/generator.test.js +48 -1
- package/test/unit/generator.test.ts +48 -1
- package/test/unit/hashing.test.js +64 -64
- package/test/unit/hashing.test.ts +63 -63
- package/test/unit/internal-hex.test.js +32 -1
- package/test/unit/internal-hex.test.ts +32 -1
- package/test/unit/providers.test.js +51 -1
- package/test/unit/providers.test.ts +53 -0
- package/SPEC.md +0 -3784
- package/examples/node_modules/.bin/esbuild +0 -16
- package/examples/node_modules/.bin/esbuild.cmd +0 -17
- package/examples/node_modules/.bin/esbuild.ps1 +0 -28
- package/examples/node_modules/.bin/sdkgen +0 -16
- package/examples/node_modules/.bin/sdkgen.cmd +0 -17
- package/examples/node_modules/.bin/sdkgen.ps1 +0 -28
- package/examples/node_modules/.bin/tsx +0 -16
- package/examples/node_modules/.bin/tsx.cmd +0 -17
- package/examples/node_modules/.bin/tsx.ps1 +0 -28
- package/examples/node_modules/.package-lock.json +0 -235
- package/examples/node_modules/@esbuild/win32-x64/README.md +0 -3
- package/examples/node_modules/@esbuild/win32-x64/esbuild.exe +0 -0
- package/examples/node_modules/@esbuild/win32-x64/package.json +0 -20
- package/examples/node_modules/esbuild/LICENSE.md +0 -21
- package/examples/node_modules/esbuild/README.md +0 -3
- package/examples/node_modules/esbuild/bin/esbuild +0 -223
- package/examples/node_modules/esbuild/install.js +0 -289
- package/examples/node_modules/esbuild/lib/main.d.ts +0 -716
- package/examples/node_modules/esbuild/lib/main.js +0 -2532
- package/examples/node_modules/esbuild/package.json +0 -49
- package/examples/node_modules/get-tsconfig/LICENSE +0 -21
- package/examples/node_modules/get-tsconfig/README.md +0 -235
- package/examples/node_modules/get-tsconfig/dist/index.cjs +0 -7
- package/examples/node_modules/get-tsconfig/dist/index.d.cts +0 -2088
- package/examples/node_modules/get-tsconfig/dist/index.d.mts +0 -2088
- package/examples/node_modules/get-tsconfig/dist/index.mjs +0 -7
- package/examples/node_modules/get-tsconfig/package.json +0 -46
- package/examples/node_modules/quantum-coin-js-sdk/.github/workflows/publish-npmjs.yaml +0 -22
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE +0 -21
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE-wasm_exec.js.txt +0 -30
- package/examples/node_modules/quantum-coin-js-sdk/README.md +0 -1665
- package/examples/node_modules/quantum-coin-js-sdk/example/README.md +0 -14
- package/examples/node_modules/quantum-coin-js-sdk/example/conversion-example.js +0 -19
- package/examples/node_modules/quantum-coin-js-sdk/example/example-create-contract.js +0 -396
- package/examples/node_modules/quantum-coin-js-sdk/example/example-encode-decode-rlp.js +0 -225
- package/examples/node_modules/quantum-coin-js-sdk/example/example-event-pack-unpack.js +0 -391
- package/examples/node_modules/quantum-coin-js-sdk/example/example-misc.js +0 -101
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send-signRawTransaction.js +0 -318
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send.js +0 -116
- package/examples/node_modules/quantum-coin-js-sdk/example/example-send.js +0 -70
- package/examples/node_modules/quantum-coin-js-sdk/example/example-token-pack-unpack.js +0 -961
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet-version4.js +0 -35
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet.js +0 -43
- package/examples/node_modules/quantum-coin-js-sdk/example/example.js +0 -405
- package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +0 -134
- package/examples/node_modules/quantum-coin-js-sdk/example/package.json +0 -15
- package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +0 -1024
- package/examples/node_modules/quantum-coin-js-sdk/index.js +0 -3062
- package/examples/node_modules/quantum-coin-js-sdk/package.json +0 -34
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-32.json +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-36.json +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-48.json +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/tests/generate-verify-vectors.js +0 -91
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.preinit.test.js +0 -41
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.test.js +0 -686
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-keytype5-context-null.test.js +0 -107
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-transaction.test.js +0 -196
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-verify.test.js +0 -311
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.relay.test.js +0 -131
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.rpc.test.js +0 -103
- package/examples/node_modules/quantum-coin-js-sdk/tests/verify-vectors.json +0 -95035
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.d.ts +0 -9
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +0 -16
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.d.ts +0 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.js +0 -587
- package/examples/node_modules/resolve-pkg-maps/LICENSE +0 -21
- package/examples/node_modules/resolve-pkg-maps/README.md +0 -216
- package/examples/node_modules/resolve-pkg-maps/dist/index.cjs +0 -1
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.cts +0 -11
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.mts +0 -11
- package/examples/node_modules/resolve-pkg-maps/dist/index.mjs +0 -1
- package/examples/node_modules/resolve-pkg-maps/package.json +0 -42
- package/examples/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +0 -22
- package/examples/node_modules/seed-words/BUILD.md +0 -7
- package/examples/node_modules/seed-words/LICENSE +0 -121
- package/examples/node_modules/seed-words/README.md +0 -67
- package/examples/node_modules/seed-words/dist/seedwords.d.ts +0 -39
- package/examples/node_modules/seed-words/package.json +0 -27
- package/examples/node_modules/seed-words/seedwords.js +0 -315
- package/examples/node_modules/seed-words/seedwords.txt +0 -65536
- package/examples/node_modules/seed-words/tsconfig.json +0 -21
- package/examples/node_modules/tsx/LICENSE +0 -21
- package/examples/node_modules/tsx/README.md +0 -32
- package/examples/node_modules/tsx/dist/cjs/api/index.cjs +0 -1
- package/examples/node_modules/tsx/dist/cjs/api/index.d.cts +0 -35
- package/examples/node_modules/tsx/dist/cjs/api/index.d.mts +0 -35
- package/examples/node_modules/tsx/dist/cjs/api/index.mjs +0 -1
- package/examples/node_modules/tsx/dist/cjs/index.cjs +0 -1
- package/examples/node_modules/tsx/dist/cjs/index.mjs +0 -1
- package/examples/node_modules/tsx/dist/cli.cjs +0 -54
- package/examples/node_modules/tsx/dist/cli.mjs +0 -55
- package/examples/node_modules/tsx/dist/client-BQVF1NaW.mjs +0 -1
- package/examples/node_modules/tsx/dist/client-D6NvIMSC.cjs +0 -1
- package/examples/node_modules/tsx/dist/esm/api/index.cjs +0 -1
- package/examples/node_modules/tsx/dist/esm/api/index.d.cts +0 -35
- package/examples/node_modules/tsx/dist/esm/api/index.d.mts +0 -35
- package/examples/node_modules/tsx/dist/esm/api/index.mjs +0 -1
- package/examples/node_modules/tsx/dist/esm/index.cjs +0 -2
- package/examples/node_modules/tsx/dist/esm/index.mjs +0 -2
- package/examples/node_modules/tsx/dist/get-pipe-path-BHW2eJdv.mjs +0 -1
- package/examples/node_modules/tsx/dist/get-pipe-path-BoR10qr8.cjs +0 -1
- package/examples/node_modules/tsx/dist/index-7AaEi15b.mjs +0 -14
- package/examples/node_modules/tsx/dist/index-BWFBUo6r.cjs +0 -1
- package/examples/node_modules/tsx/dist/index-gbaejti9.mjs +0 -1
- package/examples/node_modules/tsx/dist/index-gckBtVBf.cjs +0 -14
- package/examples/node_modules/tsx/dist/lexer-DQCqS3nf.mjs +0 -3
- package/examples/node_modules/tsx/dist/lexer-DgIbo0BU.cjs +0 -3
- package/examples/node_modules/tsx/dist/loader.cjs +0 -1
- package/examples/node_modules/tsx/dist/loader.mjs +0 -1
- package/examples/node_modules/tsx/dist/node-features-_8ZFwP_x.mjs +0 -1
- package/examples/node_modules/tsx/dist/node-features-roYmp9jK.cjs +0 -1
- package/examples/node_modules/tsx/dist/package-CeBgXWuR.mjs +0 -1
- package/examples/node_modules/tsx/dist/package-Dxt5kIHw.cjs +0 -1
- package/examples/node_modules/tsx/dist/patch-repl.cjs +0 -1
- package/examples/node_modules/tsx/dist/patch-repl.mjs +0 -1
- package/examples/node_modules/tsx/dist/preflight.cjs +0 -1
- package/examples/node_modules/tsx/dist/preflight.mjs +0 -1
- package/examples/node_modules/tsx/dist/register-2sWVXuRQ.cjs +0 -1
- package/examples/node_modules/tsx/dist/register-B7jrtLTO.mjs +0 -1
- package/examples/node_modules/tsx/dist/register-CFH5oNdT.mjs +0 -4
- package/examples/node_modules/tsx/dist/register-D46fvsV_.cjs +0 -4
- package/examples/node_modules/tsx/dist/repl.cjs +0 -3
- package/examples/node_modules/tsx/dist/repl.mjs +0 -3
- package/examples/node_modules/tsx/dist/require-D4F1Lv60.cjs +0 -1
- package/examples/node_modules/tsx/dist/require-DQxpCAr4.mjs +0 -1
- package/examples/node_modules/tsx/dist/suppress-warnings.cjs +0 -1
- package/examples/node_modules/tsx/dist/suppress-warnings.mjs +0 -1
- package/examples/node_modules/tsx/dist/temporary-directory-B83uKxJF.cjs +0 -1
- package/examples/node_modules/tsx/dist/temporary-directory-CwHp0_NW.mjs +0 -1
- package/examples/node_modules/tsx/dist/types-Cxp8y2TL.d.ts +0 -5
- package/examples/node_modules/tsx/package.json +0 -68
|
@@ -1,751 +1,892 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @testCategory unit
|
|
3
|
-
* @blockchainRequired false
|
|
4
|
-
* @transactional false
|
|
5
|
-
* @description Wallet functionality: constructors, static factories, encryption, signing, nonce management (offline)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { describe, it } = require("node:test");
|
|
9
|
-
const assert = require("node:assert/strict");
|
|
10
|
-
|
|
11
|
-
const { Initialize } = require("../../config");
|
|
12
|
-
const qc = require("../../index");
|
|
13
|
-
const { logSuite, logTest, logAddress } = require("../verbose-logger");
|
|
14
|
-
const {
|
|
15
|
-
TEST_ENCRYPTED_JSON_48,
|
|
16
|
-
TEST_ENCRYPTED_JSON_32,
|
|
17
|
-
TEST_ENCRYPTED_JSON_36,
|
|
18
|
-
} = require("./fixtures/encrypted-keystores-48-32-36");
|
|
19
|
-
|
|
20
|
-
describe("Address + Wallet (offline)", () => {
|
|
21
|
-
logSuite("Address + Wallet (offline)");
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
// Hardcoded test wallet (from upstream quantum-coin-js-sdk examples)
|
|
24
|
-
// WARNING: test-only wallet; never use for real funds.
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
const TEST_WALLET_ENCRYPTED_JSON =
|
|
27
|
-
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
28
|
-
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
29
|
-
const TEST_WALLET_ADDRESS = "0x1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6";
|
|
30
|
-
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
// Hardcoded seed words (generated once via quantum-coin-js-sdk.newWalletSeedWords()).
|
|
33
|
-
// WARNING: test-only seed words; never use for real funds.
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
const TEST_SEED_WORDS = [
|
|
36
|
-
"cylamidal","suculate","sealmate","radiploid","equifaxis","and","antipoise","stitchesy","perelade","lite","gourtarel","thursat",
|
|
37
|
-
"overdrome","cogulate","nonviva","stewnut","floribund","enduivist","decatary","elvenwort","indoucate","ravelent","vocalus","wetshirt",
|
|
38
|
-
"rutatory","percect","breaktout","corpation","myricorus","veofreat","junkard","supercarp","sukerus","tautang","facetype","shishkin",
|
|
39
|
-
"insulal","hobstone","stumbed","tecutonic","jumplike","hegwirth","idea","bhagatpur","pavastava","kukuluan","mageiline","extranite"
|
|
40
|
-
];
|
|
41
|
-
const TEST_SEED_ADDRESS = "0x3Ce22c0e2714196734E42B0D4D5AD11284260502A560e46c2Cd857391564142F".toLowerCase();
|
|
42
|
-
|
|
43
|
-
// First 32 and 36 words from TEST_SEED_WORDS (addresses from Wallet.fromPhrase run)
|
|
44
|
-
const TEST_SEED_WORDS_32 = TEST_SEED_WORDS.slice(0, 32);
|
|
45
|
-
const TEST_SEED_WORDS_36 = TEST_SEED_WORDS.slice(0, 36);
|
|
46
|
-
const TEST_SEED_ADDRESS_32 = "0x38b12df2d4762a04a183f936c47747a1f13d0b0ba72066b43b4b6d7f776e9e25";
|
|
47
|
-
const TEST_SEED_ADDRESS_36 = "0x030e264c853bd859c53fae3ad6ef0e011dc799685e2b05d5efa7ac50f10ca075";
|
|
48
|
-
const PASSPHRASE_PHRASE = "mySecurePassword123";
|
|
49
|
-
|
|
50
|
-
it("validates and normalizes 32-byte addresses", async () => {
|
|
51
|
-
logTest("validates and normalizes 32-byte addresses", {});
|
|
52
|
-
await Initialize(null);
|
|
53
|
-
const wallet = qc.Wallet.createRandom();
|
|
54
|
-
logAddress("wallet", wallet.address);
|
|
55
|
-
assert.equal(qc.isAddress(wallet.address), true);
|
|
56
|
-
assert.equal(qc.getAddress(wallet.address), wallet.address.toLowerCase());
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("fromEncryptedJsonSync opens a known wallet (hardcoded)", async () => {
|
|
60
|
-
logTest("fromEncryptedJsonSync opens a known wallet (hardcoded)", {});
|
|
61
|
-
await Initialize(null);
|
|
62
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
63
|
-
logAddress("wallet", wallet.address);
|
|
64
|
-
assert.equal(wallet.address, TEST_WALLET_ADDRESS);
|
|
65
|
-
assert.equal(qc.isAddress(wallet.address), true);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("fromEncryptedJsonSync opens 48-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
69
|
-
await Initialize(null);
|
|
70
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_48, PASSPHRASE_PHRASE);
|
|
71
|
-
assert.equal(wallet.address, TEST_SEED_ADDRESS);
|
|
72
|
-
assert.equal(qc.isAddress(wallet.address), true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("fromEncryptedJsonSync opens 32-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
76
|
-
await Initialize(null);
|
|
77
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_32, PASSPHRASE_PHRASE);
|
|
78
|
-
assert.equal(wallet.address, TEST_SEED_ADDRESS_32);
|
|
79
|
-
assert.equal(qc.isAddress(wallet.address), true);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("fromEncryptedJsonSync opens 36-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
83
|
-
await Initialize(null);
|
|
84
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_36, PASSPHRASE_PHRASE);
|
|
85
|
-
assert.equal(wallet.address, TEST_SEED_ADDRESS_36);
|
|
86
|
-
assert.equal(qc.isAddress(wallet.address), true);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("encryptSync + fromEncryptedJsonSync roundtrip (deterministic address)", async () => {
|
|
90
|
-
await Initialize(null);
|
|
91
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
92
|
-
const json = wallet.encryptSync("mySecurePassword123");
|
|
93
|
-
assert.equal(typeof json, "string");
|
|
94
|
-
assert.ok(json.includes("address"));
|
|
95
|
-
const wallet2 = qc.Wallet.fromEncryptedJsonSync(json, "mySecurePassword123");
|
|
96
|
-
assert.equal(wallet2.address, wallet.address);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it("encryptSync accepts Uint8Array password", async () => {
|
|
100
|
-
await Initialize(null);
|
|
101
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
102
|
-
const pw = qc.toUtf8Bytes("mySecurePassword123");
|
|
103
|
-
const json = wallet.encryptSync(pw);
|
|
104
|
-
assert.equal(typeof json, "string");
|
|
105
|
-
assert.ok(json.includes("address"));
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("Wallet constructor accepts privateKey hex string (roundtrip address)", async () => {
|
|
109
|
-
await Initialize(null);
|
|
110
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
111
|
-
const wallet2 = new qc.Wallet(wallet.privateKey);
|
|
112
|
-
assert.equal(wallet2.address, wallet.address);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it("fromPhrase supports string[] and string inputs (48 words)", async () => {
|
|
116
|
-
await Initialize(null);
|
|
117
|
-
assert.equal(TEST_SEED_WORDS.length, 48);
|
|
118
|
-
|
|
119
|
-
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
120
|
-
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS.join(" "));
|
|
121
|
-
const w3 = qc.Wallet.fromPhrase(TEST_SEED_WORDS.join(","));
|
|
122
|
-
|
|
123
|
-
assert.equal(w1.address, TEST_SEED_ADDRESS);
|
|
124
|
-
assert.equal(w2.address, TEST_SEED_ADDRESS);
|
|
125
|
-
assert.equal(w3.address, TEST_SEED_ADDRESS);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("fromPhrase supports 32-word seed phrase", async () => {
|
|
129
|
-
await Initialize(null);
|
|
130
|
-
assert.equal(TEST_SEED_WORDS_32.length, 32);
|
|
131
|
-
|
|
132
|
-
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
133
|
-
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32.join(" "));
|
|
134
|
-
|
|
135
|
-
assert.equal(w1.address, TEST_SEED_ADDRESS_32);
|
|
136
|
-
assert.equal(w2.address, TEST_SEED_ADDRESS_32);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it("fromPhrase supports 36-word seed phrase", async () => {
|
|
140
|
-
await Initialize(null);
|
|
141
|
-
assert.equal(TEST_SEED_WORDS_36.length, 36);
|
|
142
|
-
|
|
143
|
-
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
144
|
-
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36.join(" "));
|
|
145
|
-
|
|
146
|
-
assert.equal(w1.address, TEST_SEED_ADDRESS_36);
|
|
147
|
-
assert.equal(w2.address, TEST_SEED_ADDRESS_36);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("fromPhrase rejects invalid phrase lengths (must be 32, 36, or 48 words)", async () => {
|
|
151
|
-
await Initialize(null);
|
|
152
|
-
assert.throws(() => qc.Wallet.fromPhrase("one two three"), /32, 36, or 48 words/i);
|
|
153
|
-
assert.throws(() => qc.Wallet.fromPhrase(new Array(47).fill("word")), /32, 36, or 48 words/i);
|
|
154
|
-
assert.throws(() => qc.Wallet.fromPhrase(new Array(12).fill("word")), /32, 36, or 48 words/i);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("fromKeys creates wallet from privateKey + publicKey bytes (roundtrip address)", async () => {
|
|
158
|
-
await Initialize(null);
|
|
159
|
-
const original = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
160
|
-
const privBytes = original.signingKey.privateKeyBytes;
|
|
161
|
-
const pubBytes = original.signingKey.publicKeyBytes;
|
|
162
|
-
|
|
163
|
-
const fromBytes = qc.Wallet.fromKeys(privBytes, pubBytes);
|
|
164
|
-
assert.equal(fromBytes.address, original.address);
|
|
165
|
-
assert.equal(qc.isAddress(fromBytes.address), true);
|
|
166
|
-
|
|
167
|
-
const fromHex = qc.Wallet.fromKeys(original.privateKey, qc.hexlify(pubBytes));
|
|
168
|
-
assert.equal(fromHex.address, original.address);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it("fromKeys rejects empty keys", async () => {
|
|
172
|
-
await Initialize(null);
|
|
173
|
-
assert.throws(() => qc.Wallet.fromKeys(new Uint8Array(0), new Uint8Array(1)), /privateKey must not be empty/);
|
|
174
|
-
assert.throws(() => qc.Wallet.fromKeys(new Uint8Array(1), new Uint8Array(0)), /publicKey must not be empty/);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it("signTransaction works offline and returns raw tx hex", async () => {
|
|
178
|
-
await Initialize(null);
|
|
179
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
180
|
-
const to = qc.Wallet.createRandom().address;
|
|
181
|
-
const raw = await wallet.signTransaction({
|
|
182
|
-
to,
|
|
183
|
-
value: 0n,
|
|
184
|
-
gasLimit: 21000,
|
|
185
|
-
nonce: 0,
|
|
186
|
-
chainId: 123123,
|
|
187
|
-
remarks: null,
|
|
188
|
-
});
|
|
189
|
-
assert.equal(typeof raw, "string");
|
|
190
|
-
assert.ok(raw.startsWith("0x"));
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it("signTransaction resolves nonce when omitted (and treats remarks omitted vs null the same)", async () => {
|
|
194
|
-
await Initialize(null);
|
|
195
|
-
const calls = { count: 0, tags: [] };
|
|
196
|
-
const fakeProvider = {
|
|
197
|
-
chainId: 123123,
|
|
198
|
-
getTransactionCount: async (_addr, tag) => {
|
|
199
|
-
calls.count++;
|
|
200
|
-
calls.tags.push(tag);
|
|
201
|
-
return 5;
|
|
202
|
-
},
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
206
|
-
const to = qc.Wallet.createRandom().address;
|
|
207
|
-
|
|
208
|
-
const raw1 = await wallet.signTransaction({ to }); // nonce omitted, remarks omitted, gasLimit/value/data omitted
|
|
209
|
-
const raw2 = await wallet.signTransaction({ to, remarks: null }); // same behavior for remarks
|
|
210
|
-
|
|
211
|
-
assert.ok(typeof raw1 === "string" && raw1.startsWith("0x"));
|
|
212
|
-
// PQC signing may be non-deterministic, so do not assert raw equality.
|
|
213
|
-
assert.ok(typeof raw2 === "string" && raw2.startsWith("0x"));
|
|
214
|
-
assert.equal(calls.count >= 1, true);
|
|
215
|
-
// wallet prefers "pending" first
|
|
216
|
-
assert.equal(calls.tags[0], "pending");
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it("signTransaction supports contract creation (to: null) with explicit nonce", async () => {
|
|
220
|
-
await Initialize(null);
|
|
221
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
222
|
-
const raw = await wallet.signTransaction({
|
|
223
|
-
to: null,
|
|
224
|
-
data: "0x",
|
|
225
|
-
nonce: 0,
|
|
226
|
-
gasLimit: 500000,
|
|
227
|
-
chainId: 123123,
|
|
228
|
-
});
|
|
229
|
-
assert.ok(typeof raw === "string" && raw.startsWith("0x"));
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("signTransaction rejects remarks > 32 bytes", async () => {
|
|
233
|
-
await Initialize(null);
|
|
234
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
235
|
-
const to = qc.Wallet.createRandom().address;
|
|
236
|
-
const tooLong = "0x" + "11".repeat(33);
|
|
237
|
-
await assert.rejects(
|
|
238
|
-
() =>
|
|
239
|
-
wallet.signTransaction({
|
|
240
|
-
to,
|
|
241
|
-
value: 0n,
|
|
242
|
-
gasLimit: 21000,
|
|
243
|
-
nonce: 0,
|
|
244
|
-
chainId: 123123,
|
|
245
|
-
remarks: tooLong,
|
|
246
|
-
}),
|
|
247
|
-
);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it("connect(provider) returns a new wallet with provider attached", async () => {
|
|
251
|
-
await Initialize(null);
|
|
252
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
253
|
-
const fakeProvider = {
|
|
254
|
-
chainId: 123123,
|
|
255
|
-
getBalance: async () => 123n,
|
|
256
|
-
getTransactionCount: async () => 7,
|
|
257
|
-
sendTransaction: async () => ({ hash: "0x" + "11".repeat(32), wait: async () => ({ blockNumber: 1 }) }),
|
|
258
|
-
};
|
|
259
|
-
const connected = wallet.connect(fakeProvider);
|
|
260
|
-
assert.equal(connected.address, wallet.address);
|
|
261
|
-
assert.equal(connected.provider, fakeProvider);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("sendTransaction uses provider.sendTransaction with signed raw tx (no broadcast in test)", async () => {
|
|
265
|
-
await Initialize(null);
|
|
266
|
-
const calls = { send: 0, raw: null };
|
|
267
|
-
const fakeProvider = {
|
|
268
|
-
chainId: 123123,
|
|
269
|
-
getTransactionCount: async () => 0,
|
|
270
|
-
sendTransaction: async (raw) => {
|
|
271
|
-
calls.send++;
|
|
272
|
-
calls.raw = raw;
|
|
273
|
-
return { hash: "0x" + "22".repeat(32), wait: async () => ({ blockNumber: 1 }) };
|
|
274
|
-
},
|
|
275
|
-
};
|
|
276
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
277
|
-
const to = qc.Wallet.createRandom().address;
|
|
278
|
-
const resp = await wallet.sendTransaction({ to, value: 0n, gasLimit: 21000, nonce: 0 });
|
|
279
|
-
assert.equal(calls.send, 1);
|
|
280
|
-
assert.equal(typeof calls.raw, "string");
|
|
281
|
-
assert.ok(calls.raw.startsWith("0x"));
|
|
282
|
-
assert.ok(resp && resp.hash);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it("NonceManager caches nonce and increments between sends (offline)", async () => {
|
|
286
|
-
await Initialize(null);
|
|
287
|
-
const calls = { getNonce: 0, nonces: [] };
|
|
288
|
-
const fakeProvider = {
|
|
289
|
-
chainId: 123123,
|
|
290
|
-
getTransactionCount: async () => {
|
|
291
|
-
calls.getNonce++;
|
|
292
|
-
return 10;
|
|
293
|
-
},
|
|
294
|
-
sendTransaction: async () => ({ hash: "0x" + "33".repeat(32), wait: async () => ({ blockNumber: 1 }) }),
|
|
295
|
-
};
|
|
296
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
297
|
-
const nm = new qc.NonceManager(wallet);
|
|
298
|
-
|
|
299
|
-
// Intercept wallet.sendTransaction to capture nonce used (still signs tx).
|
|
300
|
-
const originalSend = wallet.sendTransaction.bind(wallet);
|
|
301
|
-
wallet.sendTransaction = async (tx) => {
|
|
302
|
-
calls.nonces.push(tx.nonce);
|
|
303
|
-
return originalSend(tx);
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const to = qc.Wallet.createRandom().address;
|
|
307
|
-
await nm.sendTransaction({ to, value: 0n, gasLimit: 21000 });
|
|
308
|
-
await nm.sendTransaction({ to, value: 0n, gasLimit: 21000 });
|
|
309
|
-
|
|
310
|
-
assert.equal(calls.getNonce, 1);
|
|
311
|
-
assert.deepEqual(calls.nonces, [10, 11]);
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
it("VoidSigner exposes getAddress()", async () => {
|
|
315
|
-
await Initialize(null);
|
|
316
|
-
const addr = qc.Wallet.createRandom().address;
|
|
317
|
-
const vs = new qc.VoidSigner(addr, null);
|
|
318
|
-
assert.equal(await vs.getAddress(), addr.toLowerCase());
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
it("resolveAddress supports string, Addressable, and Promise inputs", async () => {
|
|
322
|
-
await Initialize(null);
|
|
323
|
-
const wallet = qc.Wallet.createRandom();
|
|
324
|
-
assert.equal(qc.resolveAddress(wallet.address), wallet.address.toLowerCase());
|
|
325
|
-
assert.equal(await qc.resolveAddress(wallet), wallet.address.toLowerCase());
|
|
326
|
-
assert.equal(await qc.resolveAddress(Promise.resolve(wallet.address)), wallet.address.toLowerCase());
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
// ---------------------------------------------------------------------------
|
|
330
|
-
// createRandom with keyType
|
|
331
|
-
// ---------------------------------------------------------------------------
|
|
332
|
-
|
|
333
|
-
it("createRandom(null, null) creates wallet with explicit null keyType", async () => {
|
|
334
|
-
await Initialize(null);
|
|
335
|
-
const w = qc.Wallet.createRandom(null, null);
|
|
336
|
-
assert.equal(qc.isAddress(w.address), true);
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
it("createRandom(null, 3) creates wallet with keyType 3", async () => {
|
|
340
|
-
await Initialize(null);
|
|
341
|
-
const w = qc.Wallet.createRandom(null, 3);
|
|
342
|
-
assert.equal(qc.isAddress(w.address), true);
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
it("createRandom(null, 5) creates wallet with keyType 5", async () => {
|
|
346
|
-
await Initialize(null);
|
|
347
|
-
const w = qc.Wallet.createRandom(null, 5);
|
|
348
|
-
assert.equal(qc.isAddress(w.address), true);
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
it("createRandom(null, 3) signTransaction works offline", async () => {
|
|
352
|
-
await Initialize(null);
|
|
353
|
-
const w = qc.Wallet.createRandom(null, 3);
|
|
354
|
-
const to = qc.Wallet.createRandom().address;
|
|
355
|
-
const raw = await w.signTransaction({ to, value: 0n, gasLimit: 21000, nonce: 0, chainId: 123123 });
|
|
356
|
-
assert.ok(typeof raw === "string" && raw.startsWith("0x"));
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it("createRandom(null, 5) signTransaction works offline", async () => {
|
|
360
|
-
await Initialize(null);
|
|
361
|
-
const w = qc.Wallet.createRandom(null, 5);
|
|
362
|
-
const to = qc.Wallet.createRandom().address;
|
|
363
|
-
const raw = await w.signTransaction({ to, value: 0n, gasLimit: 21000, nonce: 0, chainId: 123123 });
|
|
364
|
-
assert.ok(typeof raw === "string" && raw.startsWith("0x"));
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
it("createRandom(null, 3) encryptSync + fromEncryptedJsonSync roundtrip", async () => {
|
|
368
|
-
await Initialize(null);
|
|
369
|
-
const w = qc.Wallet.createRandom(null, 3);
|
|
370
|
-
const json = w.encryptSync("testPassword123!");
|
|
371
|
-
const w2 = qc.Wallet.fromEncryptedJsonSync(json, "testPassword123!");
|
|
372
|
-
assert.equal(w2.address, w.address);
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
it("createRandom(null, 5) encryptSync + fromEncryptedJsonSync roundtrip", async () => {
|
|
376
|
-
await Initialize(null);
|
|
377
|
-
const w = qc.Wallet.createRandom(null, 5);
|
|
378
|
-
const json = w.encryptSync("testPassword123!");
|
|
379
|
-
const w2 = qc.Wallet.fromEncryptedJsonSync(json, "testPassword123!");
|
|
380
|
-
assert.equal(w2.address, w.address);
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
it("createRandom rejects invalid keyType values", async () => {
|
|
384
|
-
await Initialize(null);
|
|
385
|
-
assert.throws(() => qc.Wallet.createRandom(null, 1), /keyType must be null, 3, or 5/);
|
|
386
|
-
assert.throws(() => qc.Wallet.createRandom(null, 2), /keyType must be null, 3, or 5/);
|
|
387
|
-
assert.throws(() => qc.Wallet.createRandom(null, 4), /keyType must be null, 3, or 5/);
|
|
388
|
-
assert.throws(() => qc.Wallet.createRandom(null, "3"), /keyType must be null, 3, or 5/);
|
|
389
|
-
assert.throws(() => qc.Wallet.createRandom(null, true), /keyType must be null, 3, or 5/);
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// ---------------------------------------------------------------------------
|
|
393
|
-
// fromSeed
|
|
394
|
-
// ---------------------------------------------------------------------------
|
|
395
|
-
|
|
396
|
-
it("fromSeed roundtrip: createRandom(keyType 3) seed -> fromSeed produces same address", async () => {
|
|
397
|
-
await Initialize(null);
|
|
398
|
-
const w = qc.Wallet.createRandom(null, 3);
|
|
399
|
-
assert.notEqual(w.seed, null);
|
|
400
|
-
const { hexToBytes } = require("../../src/internal/hex");
|
|
401
|
-
const seedBytes = Array.from(hexToBytes(w.seed));
|
|
402
|
-
assert.equal(seedBytes.length, 64);
|
|
403
|
-
const wFromSeed = qc.Wallet.fromSeed(seedBytes);
|
|
404
|
-
assert.equal(wFromSeed.address, w.address);
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
it("fromSeed roundtrip: createRandom(keyType 5) seed -> fromSeed produces same address", async () => {
|
|
408
|
-
await Initialize(null);
|
|
409
|
-
const w = qc.Wallet.createRandom(null, 5);
|
|
410
|
-
assert.notEqual(w.seed, null);
|
|
411
|
-
const { hexToBytes } = require("../../src/internal/hex");
|
|
412
|
-
const seedBytes = Array.from(hexToBytes(w.seed));
|
|
413
|
-
assert.equal(seedBytes.length, 72);
|
|
414
|
-
const wFromSeed = qc.Wallet.fromSeed(seedBytes);
|
|
415
|
-
assert.equal(wFromSeed.address, w.address);
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
it("fromSeed rejects non-array input", async () => {
|
|
419
|
-
await Initialize(null);
|
|
420
|
-
assert.throws(() => qc.Wallet.fromSeed("not an array"), /seed must be an array/);
|
|
421
|
-
assert.throws(() => qc.Wallet.fromSeed(12345), /seed must be an array/);
|
|
422
|
-
assert.throws(() => qc.Wallet.fromSeed(null), /seed must be an array/);
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
it("fromSeed rejects wrong-length arrays", async () => {
|
|
426
|
-
await Initialize(null);
|
|
427
|
-
assert.throws(() => qc.Wallet.fromSeed(new Array(32).fill(0)), /seed must be 64, 72, or 96 bytes/);
|
|
428
|
-
assert.throws(() => qc.Wallet.fromSeed(new Array(48).fill(0)), /seed must be 64, 72, or 96 bytes/);
|
|
429
|
-
assert.throws(() => qc.Wallet.fromSeed(new Array(100).fill(0)), /seed must be 64, 72, or 96 bytes/);
|
|
430
|
-
assert.throws(() => qc.Wallet.fromSeed([]), /seed must be 64, 72, or 96 bytes/);
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
// ---------------------------------------------------------------------------
|
|
434
|
-
// Hardcoded fromSeed test vectors
|
|
435
|
-
// ---------------------------------------------------------------------------
|
|
436
|
-
|
|
437
|
-
it("fromSeed with hardcoded 64-byte seed (keyType 3) produces expected address", async () => {
|
|
438
|
-
await Initialize(null);
|
|
439
|
-
const seed3 = [51,214,149,165,206,96,227,5,173,247,83,219,210,2,221,2,4,48,117,55,88,109,241,204,31,62,23,128,47,21,168,247,28,118,30,185,229,255,17,27,34,107,225,138,254,156,55,9,253,255,142,148,234,189,232,43,173,84,159,108,8,35,58,77];
|
|
440
|
-
const addr3 = "0x2ceeaE376719215f1597d144Ee1549AB64f1Eb8D49f1f84D9F3a526400d1a4F6".toLowerCase();
|
|
441
|
-
const w = qc.Wallet.fromSeed(seed3);
|
|
442
|
-
assert.equal(w.address, addr3);
|
|
443
|
-
assert.equal(qc.isAddress(w.address), true);
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
it("fromSeed with hardcoded 72-byte seed (keyType 5) produces expected address", async () => {
|
|
447
|
-
await Initialize(null);
|
|
448
|
-
const seed5 = [58,255,242,97,43,252,180,220,51,164,15,238,50,215,248,10,29,19,152,124,211,29,41,81,233,103,152,244,59,239,145,216,189,77,244,198,230,165,109,191,18,12,199,252,232,42,197,9,237,237,237,93,254,89,177,192,7,178,95,70,174,88,126,130,89,205,140,175,7,142,191,84];
|
|
449
|
-
const addr5 = "0xeB12DF9517F867749056fE02EbCba67c9D84a97A6f4eDc6DA6555Ff4A30b9538".toLowerCase();
|
|
450
|
-
const w = qc.Wallet.fromSeed(seed5);
|
|
451
|
-
assert.equal(w.address, addr5);
|
|
452
|
-
assert.equal(qc.isAddress(w.address), true);
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
// ---------------------------------------------------------------------------
|
|
456
|
-
// encryptSeedSync
|
|
457
|
-
// ---------------------------------------------------------------------------
|
|
458
|
-
|
|
459
|
-
it("encryptSeedSync: 32-word seed (64 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
|
|
460
|
-
await Initialize(null);
|
|
461
|
-
const seedwords = require("seed-words");
|
|
462
|
-
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
463
|
-
assert.equal(seedArr.length, 64);
|
|
464
|
-
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
465
|
-
|
|
466
|
-
const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
|
|
467
|
-
assert.equal(typeof json, "string");
|
|
468
|
-
assert.ok(json.includes("address"));
|
|
469
|
-
|
|
470
|
-
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
471
|
-
assert.equal(restored.address, ref.address);
|
|
472
|
-
assert.equal(restored.address, TEST_SEED_ADDRESS_32);
|
|
473
|
-
assert.equal(restored.privateKey, ref.privateKey);
|
|
474
|
-
assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
it("encryptSeedSync: 36-word seed (72 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
|
|
478
|
-
await Initialize(null);
|
|
479
|
-
const seedwords = require("seed-words");
|
|
480
|
-
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_36);
|
|
481
|
-
assert.equal(seedArr.length, 72);
|
|
482
|
-
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
483
|
-
|
|
484
|
-
const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
|
|
485
|
-
assert.equal(typeof json, "string");
|
|
486
|
-
assert.ok(json.includes("address"));
|
|
487
|
-
|
|
488
|
-
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
489
|
-
assert.equal(restored.address, ref.address);
|
|
490
|
-
assert.equal(restored.address, TEST_SEED_ADDRESS_36);
|
|
491
|
-
assert.equal(restored.privateKey, ref.privateKey);
|
|
492
|
-
assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
it("encryptSeedSync: 48-word seed (96 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
|
|
496
|
-
await Initialize(null);
|
|
497
|
-
const seedwords = require("seed-words");
|
|
498
|
-
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS);
|
|
499
|
-
assert.equal(seedArr.length, 96);
|
|
500
|
-
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
501
|
-
|
|
502
|
-
const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
|
|
503
|
-
assert.equal(typeof json, "string");
|
|
504
|
-
assert.ok(json.includes("address"));
|
|
505
|
-
|
|
506
|
-
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
507
|
-
assert.equal(restored.address, ref.address);
|
|
508
|
-
assert.equal(restored.address, TEST_SEED_ADDRESS);
|
|
509
|
-
assert.equal(restored.privateKey, ref.privateKey);
|
|
510
|
-
assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
it("encryptSeedSync accepts Uint8Array seed", async () => {
|
|
514
|
-
await Initialize(null);
|
|
515
|
-
const seedwords = require("seed-words");
|
|
516
|
-
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
517
|
-
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
518
|
-
|
|
519
|
-
const json = qc.Wallet.encryptSeedSync(new Uint8Array(seedArr), PASSPHRASE_PHRASE);
|
|
520
|
-
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
521
|
-
assert.equal(restored.address, ref.address);
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
it("encryptSeedSync rejects non-array seed input", async () => {
|
|
525
|
-
await Initialize(null);
|
|
526
|
-
assert.throws(() => qc.Wallet.encryptSeedSync("not an array", PASSPHRASE_PHRASE), /seed must be an array/);
|
|
527
|
-
assert.throws(() => qc.Wallet.encryptSeedSync(12345, PASSPHRASE_PHRASE), /seed must be an array/);
|
|
528
|
-
assert.throws(() => qc.Wallet.encryptSeedSync(null, PASSPHRASE_PHRASE), /seed must be an array/);
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
it("encryptSeedSync rejects wrong-length seed arrays", async () => {
|
|
532
|
-
await Initialize(null);
|
|
533
|
-
assert.throws(() => qc.Wallet.encryptSeedSync(new Array(32).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
534
|
-
assert.throws(() => qc.Wallet.encryptSeedSync(new Array(48).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
535
|
-
assert.throws(() => qc.Wallet.encryptSeedSync(new Array(100).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
536
|
-
assert.throws(() => qc.Wallet.encryptSeedSync([], PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
it("encryptSeedSync rejects password shorter than 12 characters", async () => {
|
|
540
|
-
await Initialize(null);
|
|
541
|
-
const seed = new Array(64).fill(1);
|
|
542
|
-
assert.throws(() => qc.Wallet.encryptSeedSync(seed, "short"), /password must be at least 12 characters/);
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
// ---------------------------------------------------------------------------
|
|
546
|
-
// publicKey getter
|
|
547
|
-
// ---------------------------------------------------------------------------
|
|
548
|
-
|
|
549
|
-
it("publicKey getter returns hex matching signingKey.publicKeyBytes", async () => {
|
|
550
|
-
await Initialize(null);
|
|
551
|
-
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
552
|
-
const expected = "0x" + Buffer.from(w.signingKey.publicKeyBytes).toString("hex");
|
|
553
|
-
assert.equal(w.publicKey, expected);
|
|
554
|
-
assert.equal((w.publicKey.length - 2) / 2, 1408);
|
|
555
|
-
});
|
|
556
|
-
|
|
557
|
-
it("publicKey getter works for keyType 5 (2688-byte public key)", async () => {
|
|
558
|
-
await Initialize(null);
|
|
559
|
-
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
560
|
-
const expected = "0x" + Buffer.from(w.signingKey.publicKeyBytes).toString("hex");
|
|
561
|
-
assert.equal(w.publicKey, expected);
|
|
562
|
-
assert.equal((w.publicKey.length - 2) / 2, 2688);
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
it("publicKey getter works for createRandom wallet", async () => {
|
|
566
|
-
await Initialize(null);
|
|
567
|
-
const w = qc.Wallet.createRandom();
|
|
568
|
-
assert.equal(typeof w.publicKey, "string");
|
|
569
|
-
assert.ok(w.publicKey.startsWith("0x"));
|
|
570
|
-
assert.equal(w.publicKey, "0x" + Buffer.from(w.signingKey.publicKeyBytes).toString("hex"));
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
// ---------------------------------------------------------------------------
|
|
574
|
-
// seed getter
|
|
575
|
-
// ---------------------------------------------------------------------------
|
|
576
|
-
|
|
577
|
-
it("seed is non-null hex for fromPhrase(32-word)", async () => {
|
|
578
|
-
await Initialize(null);
|
|
579
|
-
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
580
|
-
assert.equal(typeof w.seed, "string");
|
|
581
|
-
assert.ok(w.seed.startsWith("0x"));
|
|
582
|
-
assert.equal((w.seed.length - 2) / 2, 64);
|
|
583
|
-
assert.equal(w.seed, "0x319fda8ec642b6b649d805770647d82aa4377ced5c51e4e39c0026bd983ad7b150fc475633d246216ac8b81af68bf929bf68a3fd151a2b6c925ef3cc70ecdb8b");
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
it("seed is non-null hex for fromPhrase(36-word)", async () => {
|
|
587
|
-
await Initialize(null);
|
|
588
|
-
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
589
|
-
assert.equal(typeof w.seed, "string");
|
|
590
|
-
assert.equal((w.seed.length - 2) / 2, 72);
|
|
591
|
-
assert.equal(w.seed, "0x319fda8ec642b6b649d805770647d82aa4377ced5c51e4e39c0026bd983ad7b150fc475633d246216ac8b81af68bf929bf68a3fd151a2b6c925ef3cc70ecdb8bdaf9e0ff4c96cb07");
|
|
592
|
-
});
|
|
593
|
-
|
|
594
|
-
it("seed is non-null hex for fromPhrase(48-word)", async () => {
|
|
595
|
-
await Initialize(null);
|
|
596
|
-
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
597
|
-
assert.equal(typeof w.seed, "string");
|
|
598
|
-
assert.equal((w.seed.length - 2) / 2, 96);
|
|
599
|
-
assert.equal(w.seed, "0x319fda8ec642b6b649d805770647d82aa4377ced5c51e4e39c0026bd983ad7b150fc475633d246216ac8b81af68bf929bf68a3fd151a2b6c925ef3cc70ecdb8bdaf9e0ff4c96cb076c776546d970e1be70a962a868df0eeba1c076a780cb4c3b");
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
it("seed is non-null for fromSeed() and matches fromPhrase() with same words", async () => {
|
|
603
|
-
await Initialize(null);
|
|
604
|
-
const seedwords = require("seed-words");
|
|
605
|
-
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
606
|
-
const wSeed = qc.Wallet.fromSeed(Array.from(seedArr));
|
|
607
|
-
const wPhrase = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
608
|
-
assert.equal(wSeed.seed, wPhrase.seed);
|
|
609
|
-
assert.equal(wSeed.address, wPhrase.address);
|
|
610
|
-
});
|
|
611
|
-
|
|
612
|
-
it("seed is non-null for createRandom() (seed-derived)", async () => {
|
|
613
|
-
await Initialize(null);
|
|
614
|
-
const w = qc.Wallet.createRandom();
|
|
615
|
-
assert.notEqual(w.seed, null);
|
|
616
|
-
assert.equal(typeof w.seed, "string");
|
|
617
|
-
assert.ok(w.seed.startsWith("0x"));
|
|
618
|
-
assert.equal((w.seed.length - 2) / 2, 64);
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
it("seed is non-null for createRandom(null, 5) (seed-derived, keyType 5)", async () => {
|
|
622
|
-
await Initialize(null);
|
|
623
|
-
const w = qc.Wallet.createRandom(null, 5);
|
|
624
|
-
assert.notEqual(w.seed, null);
|
|
625
|
-
assert.equal((w.seed.length - 2) / 2, 72);
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
it("seed is null for fromKeys()", async () => {
|
|
629
|
-
await Initialize(null);
|
|
630
|
-
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
631
|
-
const wk = qc.Wallet.fromKeys(w.signingKey.privateKeyBytes, w.signingKey.publicKeyBytes);
|
|
632
|
-
assert.equal(wk.seed, null);
|
|
633
|
-
assert.equal(wk.address, w.address);
|
|
634
|
-
});
|
|
635
|
-
|
|
636
|
-
it("seed is null for fromEncryptedJsonSync() with v3 JSON", async () => {
|
|
637
|
-
await Initialize(null);
|
|
638
|
-
const w = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
639
|
-
assert.equal(w.seed, null);
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
it("seed is null for fromEncryptedJsonSync() with v4 JSON", async () => {
|
|
643
|
-
await Initialize(null);
|
|
644
|
-
const w32 = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_32, PASSPHRASE_PHRASE);
|
|
645
|
-
assert.equal(w32.seed, null);
|
|
646
|
-
const w36 = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_36, PASSPHRASE_PHRASE);
|
|
647
|
-
assert.equal(w36.seed, null);
|
|
648
|
-
const w48 = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_48, PASSPHRASE_PHRASE);
|
|
649
|
-
assert.equal(w48.seed, null);
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
// ---------------------------------------------------------------------------
|
|
653
|
-
//
|
|
654
|
-
// ---------------------------------------------------------------------------
|
|
655
|
-
|
|
656
|
-
it("
|
|
657
|
-
await Initialize(null);
|
|
658
|
-
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
659
|
-
const
|
|
660
|
-
assert.
|
|
661
|
-
|
|
662
|
-
assert.
|
|
663
|
-
|
|
664
|
-
assert.equal(
|
|
665
|
-
assert.equal(
|
|
666
|
-
});
|
|
667
|
-
|
|
668
|
-
it("
|
|
669
|
-
await Initialize(null);
|
|
670
|
-
const w = qc.Wallet.
|
|
671
|
-
const
|
|
672
|
-
assert.
|
|
673
|
-
|
|
674
|
-
assert.
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
const
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
assert.equal(
|
|
686
|
-
assert.
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
const
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
const
|
|
707
|
-
const
|
|
708
|
-
assert.
|
|
709
|
-
const
|
|
710
|
-
assert.equal(
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
assert.
|
|
722
|
-
assert.
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
const
|
|
729
|
-
assert.
|
|
730
|
-
|
|
731
|
-
assert.
|
|
732
|
-
assert.
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
assert.
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory unit
|
|
3
|
+
* @blockchainRequired false
|
|
4
|
+
* @transactional false
|
|
5
|
+
* @description Wallet functionality: constructors, static factories, encryption, signing, nonce management (offline)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { describe, it } = require("node:test");
|
|
9
|
+
const assert = require("node:assert/strict");
|
|
10
|
+
|
|
11
|
+
const { Initialize } = require("../../config");
|
|
12
|
+
const qc = require("../../index");
|
|
13
|
+
const { logSuite, logTest, logAddress } = require("../verbose-logger");
|
|
14
|
+
const {
|
|
15
|
+
TEST_ENCRYPTED_JSON_48,
|
|
16
|
+
TEST_ENCRYPTED_JSON_32,
|
|
17
|
+
TEST_ENCRYPTED_JSON_36,
|
|
18
|
+
} = require("./fixtures/encrypted-keystores-48-32-36");
|
|
19
|
+
|
|
20
|
+
describe("Address + Wallet (offline)", () => {
|
|
21
|
+
logSuite("Address + Wallet (offline)");
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Hardcoded test wallet (from upstream quantum-coin-js-sdk examples)
|
|
24
|
+
// WARNING: test-only wallet; never use for real funds.
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const TEST_WALLET_ENCRYPTED_JSON =
|
|
27
|
+
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
28
|
+
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
29
|
+
const TEST_WALLET_ADDRESS = "0x1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6";
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Hardcoded seed words (generated once via quantum-coin-js-sdk.newWalletSeedWords()).
|
|
33
|
+
// WARNING: test-only seed words; never use for real funds.
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
const TEST_SEED_WORDS = [
|
|
36
|
+
"cylamidal","suculate","sealmate","radiploid","equifaxis","and","antipoise","stitchesy","perelade","lite","gourtarel","thursat",
|
|
37
|
+
"overdrome","cogulate","nonviva","stewnut","floribund","enduivist","decatary","elvenwort","indoucate","ravelent","vocalus","wetshirt",
|
|
38
|
+
"rutatory","percect","breaktout","corpation","myricorus","veofreat","junkard","supercarp","sukerus","tautang","facetype","shishkin",
|
|
39
|
+
"insulal","hobstone","stumbed","tecutonic","jumplike","hegwirth","idea","bhagatpur","pavastava","kukuluan","mageiline","extranite"
|
|
40
|
+
];
|
|
41
|
+
const TEST_SEED_ADDRESS = "0x3Ce22c0e2714196734E42B0D4D5AD11284260502A560e46c2Cd857391564142F".toLowerCase();
|
|
42
|
+
|
|
43
|
+
// First 32 and 36 words from TEST_SEED_WORDS (addresses from Wallet.fromPhrase run)
|
|
44
|
+
const TEST_SEED_WORDS_32 = TEST_SEED_WORDS.slice(0, 32);
|
|
45
|
+
const TEST_SEED_WORDS_36 = TEST_SEED_WORDS.slice(0, 36);
|
|
46
|
+
const TEST_SEED_ADDRESS_32 = "0x38b12df2d4762a04a183f936c47747a1f13d0b0ba72066b43b4b6d7f776e9e25";
|
|
47
|
+
const TEST_SEED_ADDRESS_36 = "0x030e264c853bd859c53fae3ad6ef0e011dc799685e2b05d5efa7ac50f10ca075";
|
|
48
|
+
const PASSPHRASE_PHRASE = "mySecurePassword123";
|
|
49
|
+
|
|
50
|
+
it("validates and normalizes 32-byte addresses", async () => {
|
|
51
|
+
logTest("validates and normalizes 32-byte addresses", {});
|
|
52
|
+
await Initialize(null);
|
|
53
|
+
const wallet = qc.Wallet.createRandom();
|
|
54
|
+
logAddress("wallet", wallet.address);
|
|
55
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
56
|
+
assert.equal(qc.getAddress(wallet.address), wallet.address.toLowerCase());
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("fromEncryptedJsonSync opens a known wallet (hardcoded)", async () => {
|
|
60
|
+
logTest("fromEncryptedJsonSync opens a known wallet (hardcoded)", {});
|
|
61
|
+
await Initialize(null);
|
|
62
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
63
|
+
logAddress("wallet", wallet.address);
|
|
64
|
+
assert.equal(wallet.address, TEST_WALLET_ADDRESS);
|
|
65
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("fromEncryptedJsonSync opens 48-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
69
|
+
await Initialize(null);
|
|
70
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_48, PASSPHRASE_PHRASE);
|
|
71
|
+
assert.equal(wallet.address, TEST_SEED_ADDRESS);
|
|
72
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("fromEncryptedJsonSync opens 32-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
76
|
+
await Initialize(null);
|
|
77
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_32, PASSPHRASE_PHRASE);
|
|
78
|
+
assert.equal(wallet.address, TEST_SEED_ADDRESS_32);
|
|
79
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("fromEncryptedJsonSync opens 36-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
83
|
+
await Initialize(null);
|
|
84
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_36, PASSPHRASE_PHRASE);
|
|
85
|
+
assert.equal(wallet.address, TEST_SEED_ADDRESS_36);
|
|
86
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("encryptSync + fromEncryptedJsonSync roundtrip (deterministic address)", async () => {
|
|
90
|
+
await Initialize(null);
|
|
91
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
92
|
+
const json = wallet.encryptSync("mySecurePassword123");
|
|
93
|
+
assert.equal(typeof json, "string");
|
|
94
|
+
assert.ok(json.includes("address"));
|
|
95
|
+
const wallet2 = qc.Wallet.fromEncryptedJsonSync(json, "mySecurePassword123");
|
|
96
|
+
assert.equal(wallet2.address, wallet.address);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("encryptSync accepts Uint8Array password", async () => {
|
|
100
|
+
await Initialize(null);
|
|
101
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
102
|
+
const pw = qc.toUtf8Bytes("mySecurePassword123");
|
|
103
|
+
const json = wallet.encryptSync(pw);
|
|
104
|
+
assert.equal(typeof json, "string");
|
|
105
|
+
assert.ok(json.includes("address"));
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("Wallet constructor accepts privateKey hex string (roundtrip address)", async () => {
|
|
109
|
+
await Initialize(null);
|
|
110
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
111
|
+
const wallet2 = new qc.Wallet(wallet.privateKey);
|
|
112
|
+
assert.equal(wallet2.address, wallet.address);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("fromPhrase supports string[] and string inputs (48 words)", async () => {
|
|
116
|
+
await Initialize(null);
|
|
117
|
+
assert.equal(TEST_SEED_WORDS.length, 48);
|
|
118
|
+
|
|
119
|
+
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
120
|
+
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS.join(" "));
|
|
121
|
+
const w3 = qc.Wallet.fromPhrase(TEST_SEED_WORDS.join(","));
|
|
122
|
+
|
|
123
|
+
assert.equal(w1.address, TEST_SEED_ADDRESS);
|
|
124
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS);
|
|
125
|
+
assert.equal(w3.address, TEST_SEED_ADDRESS);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("fromPhrase supports 32-word seed phrase", async () => {
|
|
129
|
+
await Initialize(null);
|
|
130
|
+
assert.equal(TEST_SEED_WORDS_32.length, 32);
|
|
131
|
+
|
|
132
|
+
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
133
|
+
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32.join(" "));
|
|
134
|
+
|
|
135
|
+
assert.equal(w1.address, TEST_SEED_ADDRESS_32);
|
|
136
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_32);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("fromPhrase supports 36-word seed phrase", async () => {
|
|
140
|
+
await Initialize(null);
|
|
141
|
+
assert.equal(TEST_SEED_WORDS_36.length, 36);
|
|
142
|
+
|
|
143
|
+
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
144
|
+
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36.join(" "));
|
|
145
|
+
|
|
146
|
+
assert.equal(w1.address, TEST_SEED_ADDRESS_36);
|
|
147
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_36);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("fromPhrase rejects invalid phrase lengths (must be 32, 36, or 48 words)", async () => {
|
|
151
|
+
await Initialize(null);
|
|
152
|
+
assert.throws(() => qc.Wallet.fromPhrase("one two three"), /32, 36, or 48 words/i);
|
|
153
|
+
assert.throws(() => qc.Wallet.fromPhrase(new Array(47).fill("word")), /32, 36, or 48 words/i);
|
|
154
|
+
assert.throws(() => qc.Wallet.fromPhrase(new Array(12).fill("word")), /32, 36, or 48 words/i);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("fromKeys creates wallet from privateKey + publicKey bytes (roundtrip address)", async () => {
|
|
158
|
+
await Initialize(null);
|
|
159
|
+
const original = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
160
|
+
const privBytes = original.signingKey.privateKeyBytes;
|
|
161
|
+
const pubBytes = original.signingKey.publicKeyBytes;
|
|
162
|
+
|
|
163
|
+
const fromBytes = qc.Wallet.fromKeys(privBytes, pubBytes);
|
|
164
|
+
assert.equal(fromBytes.address, original.address);
|
|
165
|
+
assert.equal(qc.isAddress(fromBytes.address), true);
|
|
166
|
+
|
|
167
|
+
const fromHex = qc.Wallet.fromKeys(original.privateKey, qc.hexlify(pubBytes));
|
|
168
|
+
assert.equal(fromHex.address, original.address);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("fromKeys rejects empty keys", async () => {
|
|
172
|
+
await Initialize(null);
|
|
173
|
+
assert.throws(() => qc.Wallet.fromKeys(new Uint8Array(0), new Uint8Array(1)), /privateKey must not be empty/);
|
|
174
|
+
assert.throws(() => qc.Wallet.fromKeys(new Uint8Array(1), new Uint8Array(0)), /publicKey must not be empty/);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("signTransaction works offline and returns raw tx hex", async () => {
|
|
178
|
+
await Initialize(null);
|
|
179
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
180
|
+
const to = qc.Wallet.createRandom().address;
|
|
181
|
+
const raw = await wallet.signTransaction({
|
|
182
|
+
to,
|
|
183
|
+
value: 0n,
|
|
184
|
+
gasLimit: 21000,
|
|
185
|
+
nonce: 0,
|
|
186
|
+
chainId: 123123,
|
|
187
|
+
remarks: null,
|
|
188
|
+
});
|
|
189
|
+
assert.equal(typeof raw, "string");
|
|
190
|
+
assert.ok(raw.startsWith("0x"));
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("signTransaction resolves nonce when omitted (and treats remarks omitted vs null the same)", async () => {
|
|
194
|
+
await Initialize(null);
|
|
195
|
+
const calls = { count: 0, tags: [] };
|
|
196
|
+
const fakeProvider = {
|
|
197
|
+
chainId: 123123,
|
|
198
|
+
getTransactionCount: async (_addr, tag) => {
|
|
199
|
+
calls.count++;
|
|
200
|
+
calls.tags.push(tag);
|
|
201
|
+
return 5;
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
206
|
+
const to = qc.Wallet.createRandom().address;
|
|
207
|
+
|
|
208
|
+
const raw1 = await wallet.signTransaction({ to }); // nonce omitted, remarks omitted, gasLimit/value/data omitted
|
|
209
|
+
const raw2 = await wallet.signTransaction({ to, remarks: null }); // same behavior for remarks
|
|
210
|
+
|
|
211
|
+
assert.ok(typeof raw1 === "string" && raw1.startsWith("0x"));
|
|
212
|
+
// PQC signing may be non-deterministic, so do not assert raw equality.
|
|
213
|
+
assert.ok(typeof raw2 === "string" && raw2.startsWith("0x"));
|
|
214
|
+
assert.equal(calls.count >= 1, true);
|
|
215
|
+
// wallet prefers "pending" first
|
|
216
|
+
assert.equal(calls.tags[0], "pending");
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("signTransaction supports contract creation (to: null) with explicit nonce", async () => {
|
|
220
|
+
await Initialize(null);
|
|
221
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
222
|
+
const raw = await wallet.signTransaction({
|
|
223
|
+
to: null,
|
|
224
|
+
data: "0x",
|
|
225
|
+
nonce: 0,
|
|
226
|
+
gasLimit: 500000,
|
|
227
|
+
chainId: 123123,
|
|
228
|
+
});
|
|
229
|
+
assert.ok(typeof raw === "string" && raw.startsWith("0x"));
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("signTransaction rejects remarks > 32 bytes", async () => {
|
|
233
|
+
await Initialize(null);
|
|
234
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
235
|
+
const to = qc.Wallet.createRandom().address;
|
|
236
|
+
const tooLong = "0x" + "11".repeat(33);
|
|
237
|
+
await assert.rejects(
|
|
238
|
+
() =>
|
|
239
|
+
wallet.signTransaction({
|
|
240
|
+
to,
|
|
241
|
+
value: 0n,
|
|
242
|
+
gasLimit: 21000,
|
|
243
|
+
nonce: 0,
|
|
244
|
+
chainId: 123123,
|
|
245
|
+
remarks: tooLong,
|
|
246
|
+
}),
|
|
247
|
+
);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it("connect(provider) returns a new wallet with provider attached", async () => {
|
|
251
|
+
await Initialize(null);
|
|
252
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
253
|
+
const fakeProvider = {
|
|
254
|
+
chainId: 123123,
|
|
255
|
+
getBalance: async () => 123n,
|
|
256
|
+
getTransactionCount: async () => 7,
|
|
257
|
+
sendTransaction: async () => ({ hash: "0x" + "11".repeat(32), wait: async () => ({ blockNumber: 1 }) }),
|
|
258
|
+
};
|
|
259
|
+
const connected = wallet.connect(fakeProvider);
|
|
260
|
+
assert.equal(connected.address, wallet.address);
|
|
261
|
+
assert.equal(connected.provider, fakeProvider);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it("sendTransaction uses provider.sendTransaction with signed raw tx (no broadcast in test)", async () => {
|
|
265
|
+
await Initialize(null);
|
|
266
|
+
const calls = { send: 0, raw: null };
|
|
267
|
+
const fakeProvider = {
|
|
268
|
+
chainId: 123123,
|
|
269
|
+
getTransactionCount: async () => 0,
|
|
270
|
+
sendTransaction: async (raw) => {
|
|
271
|
+
calls.send++;
|
|
272
|
+
calls.raw = raw;
|
|
273
|
+
return { hash: "0x" + "22".repeat(32), wait: async () => ({ blockNumber: 1 }) };
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
277
|
+
const to = qc.Wallet.createRandom().address;
|
|
278
|
+
const resp = await wallet.sendTransaction({ to, value: 0n, gasLimit: 21000, nonce: 0 });
|
|
279
|
+
assert.equal(calls.send, 1);
|
|
280
|
+
assert.equal(typeof calls.raw, "string");
|
|
281
|
+
assert.ok(calls.raw.startsWith("0x"));
|
|
282
|
+
assert.ok(resp && resp.hash);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("NonceManager caches nonce and increments between sends (offline)", async () => {
|
|
286
|
+
await Initialize(null);
|
|
287
|
+
const calls = { getNonce: 0, nonces: [] };
|
|
288
|
+
const fakeProvider = {
|
|
289
|
+
chainId: 123123,
|
|
290
|
+
getTransactionCount: async () => {
|
|
291
|
+
calls.getNonce++;
|
|
292
|
+
return 10;
|
|
293
|
+
},
|
|
294
|
+
sendTransaction: async () => ({ hash: "0x" + "33".repeat(32), wait: async () => ({ blockNumber: 1 }) }),
|
|
295
|
+
};
|
|
296
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
297
|
+
const nm = new qc.NonceManager(wallet);
|
|
298
|
+
|
|
299
|
+
// Intercept wallet.sendTransaction to capture nonce used (still signs tx).
|
|
300
|
+
const originalSend = wallet.sendTransaction.bind(wallet);
|
|
301
|
+
wallet.sendTransaction = async (tx) => {
|
|
302
|
+
calls.nonces.push(tx.nonce);
|
|
303
|
+
return originalSend(tx);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const to = qc.Wallet.createRandom().address;
|
|
307
|
+
await nm.sendTransaction({ to, value: 0n, gasLimit: 21000 });
|
|
308
|
+
await nm.sendTransaction({ to, value: 0n, gasLimit: 21000 });
|
|
309
|
+
|
|
310
|
+
assert.equal(calls.getNonce, 1);
|
|
311
|
+
assert.deepEqual(calls.nonces, [10, 11]);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("VoidSigner exposes getAddress()", async () => {
|
|
315
|
+
await Initialize(null);
|
|
316
|
+
const addr = qc.Wallet.createRandom().address;
|
|
317
|
+
const vs = new qc.VoidSigner(addr, null);
|
|
318
|
+
assert.equal(await vs.getAddress(), addr.toLowerCase());
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("resolveAddress supports string, Addressable, and Promise inputs", async () => {
|
|
322
|
+
await Initialize(null);
|
|
323
|
+
const wallet = qc.Wallet.createRandom();
|
|
324
|
+
assert.equal(qc.resolveAddress(wallet.address), wallet.address.toLowerCase());
|
|
325
|
+
assert.equal(await qc.resolveAddress(wallet), wallet.address.toLowerCase());
|
|
326
|
+
assert.equal(await qc.resolveAddress(Promise.resolve(wallet.address)), wallet.address.toLowerCase());
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// ---------------------------------------------------------------------------
|
|
330
|
+
// createRandom with keyType
|
|
331
|
+
// ---------------------------------------------------------------------------
|
|
332
|
+
|
|
333
|
+
it("createRandom(null, null) creates wallet with explicit null keyType", async () => {
|
|
334
|
+
await Initialize(null);
|
|
335
|
+
const w = qc.Wallet.createRandom(null, null);
|
|
336
|
+
assert.equal(qc.isAddress(w.address), true);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it("createRandom(null, 3) creates wallet with keyType 3", async () => {
|
|
340
|
+
await Initialize(null);
|
|
341
|
+
const w = qc.Wallet.createRandom(null, 3);
|
|
342
|
+
assert.equal(qc.isAddress(w.address), true);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("createRandom(null, 5) creates wallet with keyType 5", async () => {
|
|
346
|
+
await Initialize(null);
|
|
347
|
+
const w = qc.Wallet.createRandom(null, 5);
|
|
348
|
+
assert.equal(qc.isAddress(w.address), true);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it("createRandom(null, 3) signTransaction works offline", async () => {
|
|
352
|
+
await Initialize(null);
|
|
353
|
+
const w = qc.Wallet.createRandom(null, 3);
|
|
354
|
+
const to = qc.Wallet.createRandom().address;
|
|
355
|
+
const raw = await w.signTransaction({ to, value: 0n, gasLimit: 21000, nonce: 0, chainId: 123123 });
|
|
356
|
+
assert.ok(typeof raw === "string" && raw.startsWith("0x"));
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it("createRandom(null, 5) signTransaction works offline", async () => {
|
|
360
|
+
await Initialize(null);
|
|
361
|
+
const w = qc.Wallet.createRandom(null, 5);
|
|
362
|
+
const to = qc.Wallet.createRandom().address;
|
|
363
|
+
const raw = await w.signTransaction({ to, value: 0n, gasLimit: 21000, nonce: 0, chainId: 123123 });
|
|
364
|
+
assert.ok(typeof raw === "string" && raw.startsWith("0x"));
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it("createRandom(null, 3) encryptSync + fromEncryptedJsonSync roundtrip", async () => {
|
|
368
|
+
await Initialize(null);
|
|
369
|
+
const w = qc.Wallet.createRandom(null, 3);
|
|
370
|
+
const json = w.encryptSync("testPassword123!");
|
|
371
|
+
const w2 = qc.Wallet.fromEncryptedJsonSync(json, "testPassword123!");
|
|
372
|
+
assert.equal(w2.address, w.address);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it("createRandom(null, 5) encryptSync + fromEncryptedJsonSync roundtrip", async () => {
|
|
376
|
+
await Initialize(null);
|
|
377
|
+
const w = qc.Wallet.createRandom(null, 5);
|
|
378
|
+
const json = w.encryptSync("testPassword123!");
|
|
379
|
+
const w2 = qc.Wallet.fromEncryptedJsonSync(json, "testPassword123!");
|
|
380
|
+
assert.equal(w2.address, w.address);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it("createRandom rejects invalid keyType values", async () => {
|
|
384
|
+
await Initialize(null);
|
|
385
|
+
assert.throws(() => qc.Wallet.createRandom(null, 1), /keyType must be null, 3, or 5/);
|
|
386
|
+
assert.throws(() => qc.Wallet.createRandom(null, 2), /keyType must be null, 3, or 5/);
|
|
387
|
+
assert.throws(() => qc.Wallet.createRandom(null, 4), /keyType must be null, 3, or 5/);
|
|
388
|
+
assert.throws(() => qc.Wallet.createRandom(null, "3"), /keyType must be null, 3, or 5/);
|
|
389
|
+
assert.throws(() => qc.Wallet.createRandom(null, true), /keyType must be null, 3, or 5/);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// ---------------------------------------------------------------------------
|
|
393
|
+
// fromSeed
|
|
394
|
+
// ---------------------------------------------------------------------------
|
|
395
|
+
|
|
396
|
+
it("fromSeed roundtrip: createRandom(keyType 3) seed -> fromSeed produces same address", async () => {
|
|
397
|
+
await Initialize(null);
|
|
398
|
+
const w = qc.Wallet.createRandom(null, 3);
|
|
399
|
+
assert.notEqual(w.seed, null);
|
|
400
|
+
const { hexToBytes } = require("../../src/internal/hex");
|
|
401
|
+
const seedBytes = Array.from(hexToBytes(w.seed));
|
|
402
|
+
assert.equal(seedBytes.length, 64);
|
|
403
|
+
const wFromSeed = qc.Wallet.fromSeed(seedBytes);
|
|
404
|
+
assert.equal(wFromSeed.address, w.address);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it("fromSeed roundtrip: createRandom(keyType 5) seed -> fromSeed produces same address", async () => {
|
|
408
|
+
await Initialize(null);
|
|
409
|
+
const w = qc.Wallet.createRandom(null, 5);
|
|
410
|
+
assert.notEqual(w.seed, null);
|
|
411
|
+
const { hexToBytes } = require("../../src/internal/hex");
|
|
412
|
+
const seedBytes = Array.from(hexToBytes(w.seed));
|
|
413
|
+
assert.equal(seedBytes.length, 72);
|
|
414
|
+
const wFromSeed = qc.Wallet.fromSeed(seedBytes);
|
|
415
|
+
assert.equal(wFromSeed.address, w.address);
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it("fromSeed rejects non-array input", async () => {
|
|
419
|
+
await Initialize(null);
|
|
420
|
+
assert.throws(() => qc.Wallet.fromSeed("not an array"), /seed must be an array/);
|
|
421
|
+
assert.throws(() => qc.Wallet.fromSeed(12345), /seed must be an array/);
|
|
422
|
+
assert.throws(() => qc.Wallet.fromSeed(null), /seed must be an array/);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
it("fromSeed rejects wrong-length arrays", async () => {
|
|
426
|
+
await Initialize(null);
|
|
427
|
+
assert.throws(() => qc.Wallet.fromSeed(new Array(32).fill(0)), /seed must be 64, 72, or 96 bytes/);
|
|
428
|
+
assert.throws(() => qc.Wallet.fromSeed(new Array(48).fill(0)), /seed must be 64, 72, or 96 bytes/);
|
|
429
|
+
assert.throws(() => qc.Wallet.fromSeed(new Array(100).fill(0)), /seed must be 64, 72, or 96 bytes/);
|
|
430
|
+
assert.throws(() => qc.Wallet.fromSeed([]), /seed must be 64, 72, or 96 bytes/);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// ---------------------------------------------------------------------------
|
|
434
|
+
// Hardcoded fromSeed test vectors
|
|
435
|
+
// ---------------------------------------------------------------------------
|
|
436
|
+
|
|
437
|
+
it("fromSeed with hardcoded 64-byte seed (keyType 3) produces expected address", async () => {
|
|
438
|
+
await Initialize(null);
|
|
439
|
+
const seed3 = [51,214,149,165,206,96,227,5,173,247,83,219,210,2,221,2,4,48,117,55,88,109,241,204,31,62,23,128,47,21,168,247,28,118,30,185,229,255,17,27,34,107,225,138,254,156,55,9,253,255,142,148,234,189,232,43,173,84,159,108,8,35,58,77];
|
|
440
|
+
const addr3 = "0x2ceeaE376719215f1597d144Ee1549AB64f1Eb8D49f1f84D9F3a526400d1a4F6".toLowerCase();
|
|
441
|
+
const w = qc.Wallet.fromSeed(seed3);
|
|
442
|
+
assert.equal(w.address, addr3);
|
|
443
|
+
assert.equal(qc.isAddress(w.address), true);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it("fromSeed with hardcoded 72-byte seed (keyType 5) produces expected address", async () => {
|
|
447
|
+
await Initialize(null);
|
|
448
|
+
const seed5 = [58,255,242,97,43,252,180,220,51,164,15,238,50,215,248,10,29,19,152,124,211,29,41,81,233,103,152,244,59,239,145,216,189,77,244,198,230,165,109,191,18,12,199,252,232,42,197,9,237,237,237,93,254,89,177,192,7,178,95,70,174,88,126,130,89,205,140,175,7,142,191,84];
|
|
449
|
+
const addr5 = "0xeB12DF9517F867749056fE02EbCba67c9D84a97A6f4eDc6DA6555Ff4A30b9538".toLowerCase();
|
|
450
|
+
const w = qc.Wallet.fromSeed(seed5);
|
|
451
|
+
assert.equal(w.address, addr5);
|
|
452
|
+
assert.equal(qc.isAddress(w.address), true);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// ---------------------------------------------------------------------------
|
|
456
|
+
// encryptSeedSync
|
|
457
|
+
// ---------------------------------------------------------------------------
|
|
458
|
+
|
|
459
|
+
it("encryptSeedSync: 32-word seed (64 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
|
|
460
|
+
await Initialize(null);
|
|
461
|
+
const seedwords = require("seed-words");
|
|
462
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
463
|
+
assert.equal(seedArr.length, 64);
|
|
464
|
+
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
465
|
+
|
|
466
|
+
const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
|
|
467
|
+
assert.equal(typeof json, "string");
|
|
468
|
+
assert.ok(json.includes("address"));
|
|
469
|
+
|
|
470
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
471
|
+
assert.equal(restored.address, ref.address);
|
|
472
|
+
assert.equal(restored.address, TEST_SEED_ADDRESS_32);
|
|
473
|
+
assert.equal(restored.privateKey, ref.privateKey);
|
|
474
|
+
assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it("encryptSeedSync: 36-word seed (72 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
|
|
478
|
+
await Initialize(null);
|
|
479
|
+
const seedwords = require("seed-words");
|
|
480
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_36);
|
|
481
|
+
assert.equal(seedArr.length, 72);
|
|
482
|
+
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
483
|
+
|
|
484
|
+
const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
|
|
485
|
+
assert.equal(typeof json, "string");
|
|
486
|
+
assert.ok(json.includes("address"));
|
|
487
|
+
|
|
488
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
489
|
+
assert.equal(restored.address, ref.address);
|
|
490
|
+
assert.equal(restored.address, TEST_SEED_ADDRESS_36);
|
|
491
|
+
assert.equal(restored.privateKey, ref.privateKey);
|
|
492
|
+
assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it("encryptSeedSync: 48-word seed (96 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
|
|
496
|
+
await Initialize(null);
|
|
497
|
+
const seedwords = require("seed-words");
|
|
498
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS);
|
|
499
|
+
assert.equal(seedArr.length, 96);
|
|
500
|
+
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
501
|
+
|
|
502
|
+
const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
|
|
503
|
+
assert.equal(typeof json, "string");
|
|
504
|
+
assert.ok(json.includes("address"));
|
|
505
|
+
|
|
506
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
507
|
+
assert.equal(restored.address, ref.address);
|
|
508
|
+
assert.equal(restored.address, TEST_SEED_ADDRESS);
|
|
509
|
+
assert.equal(restored.privateKey, ref.privateKey);
|
|
510
|
+
assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it("encryptSeedSync accepts Uint8Array seed", async () => {
|
|
514
|
+
await Initialize(null);
|
|
515
|
+
const seedwords = require("seed-words");
|
|
516
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
517
|
+
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
518
|
+
|
|
519
|
+
const json = qc.Wallet.encryptSeedSync(new Uint8Array(seedArr), PASSPHRASE_PHRASE);
|
|
520
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
521
|
+
assert.equal(restored.address, ref.address);
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it("encryptSeedSync rejects non-array seed input", async () => {
|
|
525
|
+
await Initialize(null);
|
|
526
|
+
assert.throws(() => qc.Wallet.encryptSeedSync("not an array", PASSPHRASE_PHRASE), /seed must be an array/);
|
|
527
|
+
assert.throws(() => qc.Wallet.encryptSeedSync(12345, PASSPHRASE_PHRASE), /seed must be an array/);
|
|
528
|
+
assert.throws(() => qc.Wallet.encryptSeedSync(null, PASSPHRASE_PHRASE), /seed must be an array/);
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it("encryptSeedSync rejects wrong-length seed arrays", async () => {
|
|
532
|
+
await Initialize(null);
|
|
533
|
+
assert.throws(() => qc.Wallet.encryptSeedSync(new Array(32).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
534
|
+
assert.throws(() => qc.Wallet.encryptSeedSync(new Array(48).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
535
|
+
assert.throws(() => qc.Wallet.encryptSeedSync(new Array(100).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
536
|
+
assert.throws(() => qc.Wallet.encryptSeedSync([], PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
it("encryptSeedSync rejects password shorter than 12 characters", async () => {
|
|
540
|
+
await Initialize(null);
|
|
541
|
+
const seed = new Array(64).fill(1);
|
|
542
|
+
assert.throws(() => qc.Wallet.encryptSeedSync(seed, "short"), /password must be at least 12 characters/);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// ---------------------------------------------------------------------------
|
|
546
|
+
// publicKey getter
|
|
547
|
+
// ---------------------------------------------------------------------------
|
|
548
|
+
|
|
549
|
+
it("publicKey getter returns hex matching signingKey.publicKeyBytes", async () => {
|
|
550
|
+
await Initialize(null);
|
|
551
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
552
|
+
const expected = "0x" + Buffer.from(w.signingKey.publicKeyBytes).toString("hex");
|
|
553
|
+
assert.equal(w.publicKey, expected);
|
|
554
|
+
assert.equal((w.publicKey.length - 2) / 2, 1408);
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
it("publicKey getter works for keyType 5 (2688-byte public key)", async () => {
|
|
558
|
+
await Initialize(null);
|
|
559
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
560
|
+
const expected = "0x" + Buffer.from(w.signingKey.publicKeyBytes).toString("hex");
|
|
561
|
+
assert.equal(w.publicKey, expected);
|
|
562
|
+
assert.equal((w.publicKey.length - 2) / 2, 2688);
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
it("publicKey getter works for createRandom wallet", async () => {
|
|
566
|
+
await Initialize(null);
|
|
567
|
+
const w = qc.Wallet.createRandom();
|
|
568
|
+
assert.equal(typeof w.publicKey, "string");
|
|
569
|
+
assert.ok(w.publicKey.startsWith("0x"));
|
|
570
|
+
assert.equal(w.publicKey, "0x" + Buffer.from(w.signingKey.publicKeyBytes).toString("hex"));
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// ---------------------------------------------------------------------------
|
|
574
|
+
// seed getter
|
|
575
|
+
// ---------------------------------------------------------------------------
|
|
576
|
+
|
|
577
|
+
it("seed is non-null hex for fromPhrase(32-word)", async () => {
|
|
578
|
+
await Initialize(null);
|
|
579
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
580
|
+
assert.equal(typeof w.seed, "string");
|
|
581
|
+
assert.ok(w.seed.startsWith("0x"));
|
|
582
|
+
assert.equal((w.seed.length - 2) / 2, 64);
|
|
583
|
+
assert.equal(w.seed, "0x319fda8ec642b6b649d805770647d82aa4377ced5c51e4e39c0026bd983ad7b150fc475633d246216ac8b81af68bf929bf68a3fd151a2b6c925ef3cc70ecdb8b");
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
it("seed is non-null hex for fromPhrase(36-word)", async () => {
|
|
587
|
+
await Initialize(null);
|
|
588
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
589
|
+
assert.equal(typeof w.seed, "string");
|
|
590
|
+
assert.equal((w.seed.length - 2) / 2, 72);
|
|
591
|
+
assert.equal(w.seed, "0x319fda8ec642b6b649d805770647d82aa4377ced5c51e4e39c0026bd983ad7b150fc475633d246216ac8b81af68bf929bf68a3fd151a2b6c925ef3cc70ecdb8bdaf9e0ff4c96cb07");
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
it("seed is non-null hex for fromPhrase(48-word)", async () => {
|
|
595
|
+
await Initialize(null);
|
|
596
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
597
|
+
assert.equal(typeof w.seed, "string");
|
|
598
|
+
assert.equal((w.seed.length - 2) / 2, 96);
|
|
599
|
+
assert.equal(w.seed, "0x319fda8ec642b6b649d805770647d82aa4377ced5c51e4e39c0026bd983ad7b150fc475633d246216ac8b81af68bf929bf68a3fd151a2b6c925ef3cc70ecdb8bdaf9e0ff4c96cb076c776546d970e1be70a962a868df0eeba1c076a780cb4c3b");
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
it("seed is non-null for fromSeed() and matches fromPhrase() with same words", async () => {
|
|
603
|
+
await Initialize(null);
|
|
604
|
+
const seedwords = require("seed-words");
|
|
605
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
606
|
+
const wSeed = qc.Wallet.fromSeed(Array.from(seedArr));
|
|
607
|
+
const wPhrase = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
608
|
+
assert.equal(wSeed.seed, wPhrase.seed);
|
|
609
|
+
assert.equal(wSeed.address, wPhrase.address);
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
it("seed is non-null for createRandom() (seed-derived)", async () => {
|
|
613
|
+
await Initialize(null);
|
|
614
|
+
const w = qc.Wallet.createRandom();
|
|
615
|
+
assert.notEqual(w.seed, null);
|
|
616
|
+
assert.equal(typeof w.seed, "string");
|
|
617
|
+
assert.ok(w.seed.startsWith("0x"));
|
|
618
|
+
assert.equal((w.seed.length - 2) / 2, 64);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it("seed is non-null for createRandom(null, 5) (seed-derived, keyType 5)", async () => {
|
|
622
|
+
await Initialize(null);
|
|
623
|
+
const w = qc.Wallet.createRandom(null, 5);
|
|
624
|
+
assert.notEqual(w.seed, null);
|
|
625
|
+
assert.equal((w.seed.length - 2) / 2, 72);
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
it("seed is null for fromKeys()", async () => {
|
|
629
|
+
await Initialize(null);
|
|
630
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
631
|
+
const wk = qc.Wallet.fromKeys(w.signingKey.privateKeyBytes, w.signingKey.publicKeyBytes);
|
|
632
|
+
assert.equal(wk.seed, null);
|
|
633
|
+
assert.equal(wk.address, w.address);
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
it("seed is null for fromEncryptedJsonSync() with v3 JSON", async () => {
|
|
637
|
+
await Initialize(null);
|
|
638
|
+
const w = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
639
|
+
assert.equal(w.seed, null);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
it("seed is null for fromEncryptedJsonSync() with v4 JSON", async () => {
|
|
643
|
+
await Initialize(null);
|
|
644
|
+
const w32 = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_32, PASSPHRASE_PHRASE);
|
|
645
|
+
assert.equal(w32.seed, null);
|
|
646
|
+
const w36 = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_36, PASSPHRASE_PHRASE);
|
|
647
|
+
assert.equal(w36.seed, null);
|
|
648
|
+
const w48 = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_48, PASSPHRASE_PHRASE);
|
|
649
|
+
assert.equal(w48.seed, null);
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
// ---------------------------------------------------------------------------
|
|
653
|
+
// getPhrase()
|
|
654
|
+
// ---------------------------------------------------------------------------
|
|
655
|
+
|
|
656
|
+
it("getPhrase returns 32 words and roundtrips through fromPhrase (same address)", async () => {
|
|
657
|
+
await Initialize(null);
|
|
658
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
659
|
+
const phrase = w.getPhrase();
|
|
660
|
+
assert.ok(Array.isArray(phrase));
|
|
661
|
+
assert.equal(phrase.length, 32);
|
|
662
|
+
assert.deepEqual(phrase, TEST_SEED_WORDS_32);
|
|
663
|
+
const w2 = qc.Wallet.fromPhrase(phrase);
|
|
664
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_32);
|
|
665
|
+
assert.equal(w2.address, w.address);
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
it("getPhrase returns 36 words and roundtrips through fromPhrase (same address)", async () => {
|
|
669
|
+
await Initialize(null);
|
|
670
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
671
|
+
const phrase = w.getPhrase();
|
|
672
|
+
assert.ok(Array.isArray(phrase));
|
|
673
|
+
assert.equal(phrase.length, 36);
|
|
674
|
+
assert.deepEqual(phrase, TEST_SEED_WORDS_36);
|
|
675
|
+
const w2 = qc.Wallet.fromPhrase(phrase);
|
|
676
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_36);
|
|
677
|
+
assert.equal(w2.address, w.address);
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it("getPhrase returns 48 words and roundtrips through fromPhrase (same address)", async () => {
|
|
681
|
+
await Initialize(null);
|
|
682
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
683
|
+
const phrase = w.getPhrase();
|
|
684
|
+
assert.ok(Array.isArray(phrase));
|
|
685
|
+
assert.equal(phrase.length, 48);
|
|
686
|
+
assert.deepEqual(phrase, TEST_SEED_WORDS);
|
|
687
|
+
const w2 = qc.Wallet.fromPhrase(phrase);
|
|
688
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS);
|
|
689
|
+
assert.equal(w2.address, w.address);
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
it("getPhrase on fromSeed(32-word seed) returns the matching 32 words", async () => {
|
|
693
|
+
await Initialize(null);
|
|
694
|
+
const seedwords = require("seed-words");
|
|
695
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
696
|
+
const w = qc.Wallet.fromSeed(Array.from(seedArr));
|
|
697
|
+
assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS_32);
|
|
698
|
+
const w2 = qc.Wallet.fromPhrase(w.getPhrase());
|
|
699
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_32);
|
|
700
|
+
assert.equal(w2.address, w.address);
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
it("getPhrase on fromSeed(36-word seed) returns the matching 36 words", async () => {
|
|
704
|
+
await Initialize(null);
|
|
705
|
+
const seedwords = require("seed-words");
|
|
706
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_36);
|
|
707
|
+
const w = qc.Wallet.fromSeed(Array.from(seedArr));
|
|
708
|
+
assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS_36);
|
|
709
|
+
const w2 = qc.Wallet.fromPhrase(w.getPhrase());
|
|
710
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_36);
|
|
711
|
+
assert.equal(w2.address, w.address);
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
it("getPhrase on fromSeed(48-word seed) returns the matching 48 words", async () => {
|
|
715
|
+
await Initialize(null);
|
|
716
|
+
const seedwords = require("seed-words");
|
|
717
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS);
|
|
718
|
+
const w = qc.Wallet.fromSeed(Array.from(seedArr));
|
|
719
|
+
assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS);
|
|
720
|
+
const w2 = qc.Wallet.fromPhrase(w.getPhrase());
|
|
721
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS);
|
|
722
|
+
assert.equal(w2.address, w.address);
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (32-word)", async () => {
|
|
726
|
+
await Initialize(null);
|
|
727
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
728
|
+
const json = w.encryptSync(PASSPHRASE_PHRASE);
|
|
729
|
+
assert.equal(JSON.parse(json).version, 5);
|
|
730
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
731
|
+
assert.equal(restored.seed, w.seed);
|
|
732
|
+
assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS_32);
|
|
733
|
+
assert.equal(restored.address, TEST_SEED_ADDRESS_32);
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (36-word)", async () => {
|
|
737
|
+
await Initialize(null);
|
|
738
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
739
|
+
const json = w.encryptSync(PASSPHRASE_PHRASE);
|
|
740
|
+
assert.equal(JSON.parse(json).version, 5);
|
|
741
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
742
|
+
assert.equal(restored.seed, w.seed);
|
|
743
|
+
assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS_36);
|
|
744
|
+
assert.equal(restored.address, TEST_SEED_ADDRESS_36);
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (48-word)", async () => {
|
|
748
|
+
await Initialize(null);
|
|
749
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
750
|
+
const json = w.encryptSync(PASSPHRASE_PHRASE);
|
|
751
|
+
assert.equal(JSON.parse(json).version, 5);
|
|
752
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
753
|
+
assert.equal(restored.seed, w.seed);
|
|
754
|
+
assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS);
|
|
755
|
+
assert.equal(restored.address, TEST_SEED_ADDRESS);
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
it("getPhrase on createRandom returns 32 words that recreate the same wallet", async () => {
|
|
759
|
+
await Initialize(null);
|
|
760
|
+
const w = qc.Wallet.createRandom();
|
|
761
|
+
const phrase = w.getPhrase();
|
|
762
|
+
assert.ok(Array.isArray(phrase));
|
|
763
|
+
assert.equal(phrase.length, 32);
|
|
764
|
+
const w2 = qc.Wallet.fromPhrase(phrase);
|
|
765
|
+
assert.equal(w2.address, w.address);
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
it("getPhrase on createRandom(null, 5) returns 36 words that recreate the same wallet", async () => {
|
|
769
|
+
await Initialize(null);
|
|
770
|
+
const w = qc.Wallet.createRandom(null, 5);
|
|
771
|
+
const phrase = w.getPhrase();
|
|
772
|
+
assert.ok(Array.isArray(phrase));
|
|
773
|
+
assert.equal(phrase.length, 36);
|
|
774
|
+
const w2 = qc.Wallet.fromPhrase(phrase);
|
|
775
|
+
assert.equal(w2.address, w.address);
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
it("getPhrase returns null when seed is null (fromKeys wallet)", async () => {
|
|
779
|
+
await Initialize(null);
|
|
780
|
+
const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
781
|
+
const w = qc.Wallet.fromKeys(ref.signingKey.privateKeyBytes, ref.signingKey.publicKeyBytes);
|
|
782
|
+
assert.equal(w.seed, null);
|
|
783
|
+
assert.equal(w.getPhrase(), null);
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
it("getPhrase returns null for v3 encrypted-JSON wallet (no preExpansionSeed)", async () => {
|
|
787
|
+
await Initialize(null);
|
|
788
|
+
const w = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
789
|
+
assert.equal(w.seed, null);
|
|
790
|
+
assert.equal(w.getPhrase(), null);
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
// ---------------------------------------------------------------------------
|
|
794
|
+
// seed roundtrip through encryptSync / fromEncryptedJsonSync
|
|
795
|
+
// ---------------------------------------------------------------------------
|
|
796
|
+
|
|
797
|
+
it("seed roundtrips through encryptSync + fromEncryptedJsonSync for fromPhrase wallet", async () => {
|
|
798
|
+
await Initialize(null);
|
|
799
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
800
|
+
const json = w.encryptSync(PASSPHRASE_PHRASE);
|
|
801
|
+
assert.equal(JSON.parse(json).version, 5);
|
|
802
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
803
|
+
assert.equal(restored.seed, w.seed);
|
|
804
|
+
assert.equal(restored.address, w.address);
|
|
805
|
+
assert.equal(restored.privateKey, w.privateKey);
|
|
806
|
+
assert.equal(restored.publicKey, w.publicKey);
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
it("seed roundtrips through encryptSync + fromEncryptedJsonSync for createRandom wallet", async () => {
|
|
810
|
+
await Initialize(null);
|
|
811
|
+
const w = qc.Wallet.createRandom();
|
|
812
|
+
const json = w.encryptSync(PASSPHRASE_PHRASE);
|
|
813
|
+
assert.equal(JSON.parse(json).version, 5);
|
|
814
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
815
|
+
assert.equal(restored.seed, w.seed);
|
|
816
|
+
assert.equal(restored.address, w.address);
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
it("seed roundtrips through encryptSeedSync + fromEncryptedJsonSync", async () => {
|
|
820
|
+
await Initialize(null);
|
|
821
|
+
const seedwords = require("seed-words");
|
|
822
|
+
const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
|
|
823
|
+
const seedHex = "0x" + Buffer.from(new Uint8Array(seedArr)).toString("hex");
|
|
824
|
+
const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
|
|
825
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
826
|
+
assert.equal(restored.seed, seedHex);
|
|
827
|
+
assert.equal(restored.address, TEST_SEED_ADDRESS_32);
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
// ---------------------------------------------------------------------------
|
|
831
|
+
// encryptSync version behavior
|
|
832
|
+
// ---------------------------------------------------------------------------
|
|
833
|
+
|
|
834
|
+
it("encryptSync on seed-bearing wallet produces version 5 JSON", async () => {
|
|
835
|
+
await Initialize(null);
|
|
836
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
837
|
+
assert.notEqual(w.seed, null);
|
|
838
|
+
const json = w.encryptSync(PASSPHRASE_PHRASE);
|
|
839
|
+
assert.equal(JSON.parse(json).version, 5);
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
it("encryptSync on non-seed wallet (fromKeys) uses fallback path", async () => {
|
|
843
|
+
await Initialize(null);
|
|
844
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
845
|
+
const wk = qc.Wallet.fromKeys(w.signingKey.privateKeyBytes, w.signingKey.publicKeyBytes);
|
|
846
|
+
assert.equal(wk.seed, null);
|
|
847
|
+
const json = wk.encryptSync(PASSPHRASE_PHRASE);
|
|
848
|
+
const parsed = JSON.parse(json);
|
|
849
|
+
assert.ok(parsed.version === 3 || parsed.version === 4);
|
|
850
|
+
const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
|
|
851
|
+
assert.equal(restored.address, wk.address);
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
// ---------------------------------------------------------------------------
|
|
855
|
+
// getSigningContext
|
|
856
|
+
// ---------------------------------------------------------------------------
|
|
857
|
+
|
|
858
|
+
it("getSigningContext: 32-word wallet (pubKey 1408) returns 0 by default, 2 with fullSign", async () => {
|
|
859
|
+
await Initialize(null);
|
|
860
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
861
|
+
assert.strictEqual(w.getSigningContext(), 0);
|
|
862
|
+
assert.strictEqual(w.getSigningContext(null), 0);
|
|
863
|
+
assert.strictEqual(w.getSigningContext(false), 0);
|
|
864
|
+
assert.strictEqual(w.getSigningContext(true), 2);
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
it("getSigningContext: 48-word wallet (pubKey 1408) returns 0 by default, 2 with fullSign", async () => {
|
|
868
|
+
await Initialize(null);
|
|
869
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
870
|
+
assert.strictEqual(w.getSigningContext(), 0);
|
|
871
|
+
assert.strictEqual(w.getSigningContext(null), 0);
|
|
872
|
+
assert.strictEqual(w.getSigningContext(false), 0);
|
|
873
|
+
assert.strictEqual(w.getSigningContext(true), 2);
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
it("getSigningContext: 36-word wallet (pubKey 2688) returns 1 for all fullSign values", async () => {
|
|
877
|
+
await Initialize(null);
|
|
878
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
879
|
+
assert.strictEqual(w.getSigningContext(), 1);
|
|
880
|
+
assert.strictEqual(w.getSigningContext(null), 1);
|
|
881
|
+
assert.strictEqual(w.getSigningContext(false), 1);
|
|
882
|
+
assert.strictEqual(w.getSigningContext(true), 1);
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
it("getSigningContext: throws for unsupported public key size", async () => {
|
|
886
|
+
await Initialize(null);
|
|
887
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
888
|
+
w.signingKey.publicKeyBytes = new Uint8Array(100);
|
|
889
|
+
assert.throws(() => w.getSigningContext(), /unsupported public key size/);
|
|
890
|
+
});
|
|
891
|
+
});
|
|
892
|
+
|