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