quantum-coin-js-sdk 2.0.1 → 2.1.0

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 (232) hide show
  1. package/README.md +13 -0
  2. package/index.d.ts +9 -0
  3. package/index.js +37 -4
  4. package/package.json +12 -4
  5. package/wasmBase64.js +3 -2
  6. package/.idea/.name +0 -1
  7. package/.idea/modules.xml +0 -8
  8. package/.idea/quantum-coin-js-sdk.iml +0 -12
  9. package/.idea/vcs.xml +0 -6
  10. package/.vs/ProjectSettings.json +0 -3
  11. package/.vs/VSWorkspaceState.json +0 -8
  12. package/.vs/quantum-coin-js-sdk/FileContentIndex/a9d6de82-cfc3-4c22-ac38-06d706ff3673.vsidx +0 -0
  13. package/.vs/quantum-coin-js-sdk/FileContentIndex/fdc816df-1898-4153-99f2-c69ef4c2283b.vsidx +0 -0
  14. package/.vs/quantum-coin-js-sdk/config/applicationhost.config +0 -1011
  15. package/.vs/quantum-coin-js-sdk/v17/.wsuo +0 -0
  16. package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.backup.json +0 -39
  17. package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.json +0 -57
  18. package/.vs/slnx.sqlite +0 -0
  19. package/example/README.md +0 -14
  20. package/example/conversion-example.js +0 -19
  21. package/example/example-create-contract.js +0 -396
  22. package/example/example-encode-decode-rlp.js +0 -225
  23. package/example/example-event-pack-unpack.js +0 -391
  24. package/example/example-misc.js +0 -96
  25. package/example/example-token-pack-unpack.js +0 -960
  26. package/example/example-wallet-version4.js +0 -34
  27. package/example/example-wallet.js +0 -39
  28. package/example/example.js +0 -115
  29. package/example/node_modules/.bin/sdkgen +0 -16
  30. package/example/node_modules/.bin/sdkgen.cmd +0 -17
  31. package/example/node_modules/.bin/sdkgen.ps1 +0 -28
  32. package/example/node_modules/.package-lock.json +0 -51
  33. package/example/node_modules/quantumcoin/.github/workflows/publish-npmjs.yaml +0 -22
  34. package/example/node_modules/quantumcoin/LICENSE +0 -21
  35. package/example/node_modules/quantumcoin/README-SDK.md +0 -828
  36. package/example/node_modules/quantumcoin/README.md +0 -197
  37. package/example/node_modules/quantumcoin/config.d.ts +0 -50
  38. package/example/node_modules/quantumcoin/config.js +0 -123
  39. package/example/node_modules/quantumcoin/examples/AllSolidityTypes.sol +0 -184
  40. package/example/node_modules/quantumcoin/examples/SimpleIERC20.sol +0 -74
  41. package/example/node_modules/quantumcoin/examples/events.js +0 -41
  42. package/example/node_modules/quantumcoin/examples/events.ts +0 -35
  43. package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.js +0 -100
  44. package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.ts +0 -77
  45. package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.js +0 -100
  46. package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.ts +0 -77
  47. package/example/node_modules/quantumcoin/examples/example.js +0 -67
  48. package/example/node_modules/quantumcoin/examples/example.ts +0 -56
  49. package/example/node_modules/quantumcoin/examples/offline-signing.js +0 -77
  50. package/example/node_modules/quantumcoin/examples/offline-signing.ts +0 -65
  51. package/example/node_modules/quantumcoin/examples/package-lock.json +0 -596
  52. package/example/node_modules/quantumcoin/examples/package.json +0 -32
  53. package/example/node_modules/quantumcoin/examples/read-operations.js +0 -32
  54. package/example/node_modules/quantumcoin/examples/read-operations.ts +0 -31
  55. package/example/node_modules/quantumcoin/examples/sdk-generator-erc20.inline.json +0 -251
  56. package/example/node_modules/quantumcoin/examples/solidity-types.ts +0 -43
  57. package/example/node_modules/quantumcoin/examples/wallet-offline.js +0 -36
  58. package/example/node_modules/quantumcoin/examples/wallet-offline.ts +0 -26
  59. package/example/node_modules/quantumcoin/generate-sdk.js +0 -1846
  60. package/example/node_modules/quantumcoin/index.js +0 -12
  61. package/example/node_modules/quantumcoin/package.json +0 -95
  62. package/example/node_modules/quantumcoin/scripts/copy-declarations.js +0 -31
  63. package/example/node_modules/quantumcoin/scripts/run-all-one-by-one.js +0 -151
  64. package/example/node_modules/quantumcoin/src/abi/fragments.d.ts +0 -42
  65. package/example/node_modules/quantumcoin/src/abi/fragments.js +0 -63
  66. package/example/node_modules/quantumcoin/src/abi/index.d.ts +0 -13
  67. package/example/node_modules/quantumcoin/src/abi/index.js +0 -9
  68. package/example/node_modules/quantumcoin/src/abi/interface.d.ts +0 -128
  69. package/example/node_modules/quantumcoin/src/abi/interface.js +0 -605
  70. package/example/node_modules/quantumcoin/src/abi/js-abi-coder.d.ts +0 -8
  71. package/example/node_modules/quantumcoin/src/abi/js-abi-coder.js +0 -538
  72. package/example/node_modules/quantumcoin/src/constants.d.ts +0 -61
  73. package/example/node_modules/quantumcoin/src/constants.js +0 -94
  74. package/example/node_modules/quantumcoin/src/contract/contract-factory.d.ts +0 -28
  75. package/example/node_modules/quantumcoin/src/contract/contract-factory.js +0 -111
  76. package/example/node_modules/quantumcoin/src/contract/contract.d.ts +0 -113
  77. package/example/node_modules/quantumcoin/src/contract/contract.js +0 -408
  78. package/example/node_modules/quantumcoin/src/contract/index.d.ts +0 -9
  79. package/example/node_modules/quantumcoin/src/contract/index.js +0 -9
  80. package/example/node_modules/quantumcoin/src/errors/index.d.ts +0 -92
  81. package/example/node_modules/quantumcoin/src/errors/index.js +0 -200
  82. package/example/node_modules/quantumcoin/src/generator/index.d.ts +0 -81
  83. package/example/node_modules/quantumcoin/src/generator/index.js +0 -1571
  84. package/example/node_modules/quantumcoin/src/index.d.ts +0 -122
  85. package/example/node_modules/quantumcoin/src/index.js +0 -41
  86. package/example/node_modules/quantumcoin/src/internal/hex.d.ts +0 -68
  87. package/example/node_modules/quantumcoin/src/internal/hex.js +0 -180
  88. package/example/node_modules/quantumcoin/src/providers/extra-providers.d.ts +0 -139
  89. package/example/node_modules/quantumcoin/src/providers/extra-providers.js +0 -614
  90. package/example/node_modules/quantumcoin/src/providers/index.d.ts +0 -17
  91. package/example/node_modules/quantumcoin/src/providers/index.js +0 -10
  92. package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.d.ts +0 -12
  93. package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.js +0 -89
  94. package/example/node_modules/quantumcoin/src/providers/provider.d.ts +0 -206
  95. package/example/node_modules/quantumcoin/src/providers/provider.js +0 -524
  96. package/example/node_modules/quantumcoin/src/types/index.d.ts +0 -214
  97. package/example/node_modules/quantumcoin/src/types/index.js +0 -9
  98. package/example/node_modules/quantumcoin/src/utils/address.d.ts +0 -58
  99. package/example/node_modules/quantumcoin/src/utils/address.js +0 -144
  100. package/example/node_modules/quantumcoin/src/utils/encoding.d.ts +0 -120
  101. package/example/node_modules/quantumcoin/src/utils/encoding.js +0 -306
  102. package/example/node_modules/quantumcoin/src/utils/fixednumber.d.ts +0 -57
  103. package/example/node_modules/quantumcoin/src/utils/fixednumber.js +0 -366
  104. package/example/node_modules/quantumcoin/src/utils/hashing.d.ts +0 -76
  105. package/example/node_modules/quantumcoin/src/utils/hashing.js +0 -298
  106. package/example/node_modules/quantumcoin/src/utils/index.d.ts +0 -63
  107. package/example/node_modules/quantumcoin/src/utils/index.js +0 -14
  108. package/example/node_modules/quantumcoin/src/utils/result.d.ts +0 -57
  109. package/example/node_modules/quantumcoin/src/utils/result.js +0 -128
  110. package/example/node_modules/quantumcoin/src/utils/rlp.d.ts +0 -12
  111. package/example/node_modules/quantumcoin/src/utils/rlp.js +0 -215
  112. package/example/node_modules/quantumcoin/src/utils/units.d.ts +0 -29
  113. package/example/node_modules/quantumcoin/src/utils/units.js +0 -107
  114. package/example/node_modules/quantumcoin/src/wallet/index.d.ts +0 -10
  115. package/example/node_modules/quantumcoin/src/wallet/index.js +0 -8
  116. package/example/node_modules/quantumcoin/src/wallet/wallet.d.ts +0 -192
  117. package/example/node_modules/quantumcoin/src/wallet/wallet.js +0 -713
  118. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.js +0 -207
  119. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.ts +0 -191
  120. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.fixtures.js +0 -231
  121. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +0 -387
  122. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +0 -350
  123. package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.js +0 -165
  124. package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.ts +0 -160
  125. package/example/node_modules/quantumcoin/test/e2e/helpers.js +0 -59
  126. package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.js +0 -141
  127. package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.ts +0 -128
  128. package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.js +0 -168
  129. package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +0 -141
  130. package/example/node_modules/quantumcoin/test/e2e/transactional.test.js +0 -245
  131. package/example/node_modules/quantumcoin/test/e2e/transactional.test.ts +0 -208
  132. package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.js +0 -407
  133. package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.ts +0 -337
  134. package/example/node_modules/quantumcoin/test/fixtures/ConstructorParam.sol +0 -23
  135. package/example/node_modules/quantumcoin/test/fixtures/MultiContracts.sol +0 -37
  136. package/example/node_modules/quantumcoin/test/fixtures/SimpleStorage.sol +0 -18
  137. package/example/node_modules/quantumcoin/test/fixtures/StakingContract.abi.json +0 -1
  138. package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.js +0 -49
  139. package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.ts +0 -44
  140. package/example/node_modules/quantumcoin/test/integration/provider.test.js +0 -88
  141. package/example/node_modules/quantumcoin/test/integration/provider.test.ts +0 -85
  142. package/example/node_modules/quantumcoin/test/integration/ws-provider.test.js +0 -41
  143. package/example/node_modules/quantumcoin/test/integration/ws-provider.test.ts +0 -38
  144. package/example/node_modules/quantumcoin/test/security/abi-decoder-bounds.test.js +0 -122
  145. package/example/node_modules/quantumcoin/test/security/contract-overrides.test.js +0 -112
  146. package/example/node_modules/quantumcoin/test/security/generator-injection.test.js +0 -195
  147. package/example/node_modules/quantumcoin/test/security/malformed-input.test.js +0 -330
  148. package/example/node_modules/quantumcoin/test/security/malformed-input.test.ts +0 -35
  149. package/example/node_modules/quantumcoin/test/security/rpc-numeric-bounds.test.js +0 -81
  150. package/example/node_modules/quantumcoin/test/security/rpc-trust.test.js +0 -202
  151. package/example/node_modules/quantumcoin/test/unit/_encrypted-output.txt +0 -6
  152. package/example/node_modules/quantumcoin/test/unit/_log-encrypted-jsons.js +0 -45
  153. package/example/node_modules/quantumcoin/test/unit/_write-keystore-fixture.js +0 -16
  154. package/example/node_modules/quantumcoin/test/unit/abi-interface.test.js +0 -110
  155. package/example/node_modules/quantumcoin/test/unit/abi-interface.test.ts +0 -109
  156. package/example/node_modules/quantumcoin/test/unit/address-wallet.test.js +0 -923
  157. package/example/node_modules/quantumcoin/test/unit/address-wallet.test.ts +0 -877
  158. package/example/node_modules/quantumcoin/test/unit/browser-provider.test.js +0 -85
  159. package/example/node_modules/quantumcoin/test/unit/browser-provider.test.ts +0 -79
  160. package/example/node_modules/quantumcoin/test/unit/contract.test.js +0 -85
  161. package/example/node_modules/quantumcoin/test/unit/contract.test.ts +0 -83
  162. package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.js +0 -127
  163. package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.ts +0 -91
  164. package/example/node_modules/quantumcoin/test/unit/errors.test.js +0 -77
  165. package/example/node_modules/quantumcoin/test/unit/errors.test.ts +0 -76
  166. package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.js +0 -55
  167. package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.ts +0 -54
  168. package/example/node_modules/quantumcoin/test/unit/fixednumber.test.js +0 -656
  169. package/example/node_modules/quantumcoin/test/unit/fixednumber.test.ts +0 -660
  170. package/example/node_modules/quantumcoin/test/unit/fixtures/encrypted-keystores-48-32-36.js +0 -9
  171. package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.js +0 -42
  172. package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.ts +0 -41
  173. package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.js +0 -113
  174. package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.ts +0 -110
  175. package/example/node_modules/quantumcoin/test/unit/generator.test.js +0 -149
  176. package/example/node_modules/quantumcoin/test/unit/generator.test.ts +0 -148
  177. package/example/node_modules/quantumcoin/test/unit/hashing.test.js +0 -64
  178. package/example/node_modules/quantumcoin/test/unit/hashing.test.ts +0 -63
  179. package/example/node_modules/quantumcoin/test/unit/init.test.js +0 -39
  180. package/example/node_modules/quantumcoin/test/unit/init.test.ts +0 -38
  181. package/example/node_modules/quantumcoin/test/unit/interface.test.js +0 -56
  182. package/example/node_modules/quantumcoin/test/unit/interface.test.ts +0 -54
  183. package/example/node_modules/quantumcoin/test/unit/internal-hex.test.js +0 -81
  184. package/example/node_modules/quantumcoin/test/unit/internal-hex.test.ts +0 -80
  185. package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.js +0 -98
  186. package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.ts +0 -64
  187. package/example/node_modules/quantumcoin/test/unit/providers.test.js +0 -252
  188. package/example/node_modules/quantumcoin/test/unit/providers.test.ts +0 -251
  189. package/example/node_modules/quantumcoin/test/unit/result.test.js +0 -80
  190. package/example/node_modules/quantumcoin/test/unit/result.test.ts +0 -79
  191. package/example/node_modules/quantumcoin/test/unit/solidity-types.test.js +0 -49
  192. package/example/node_modules/quantumcoin/test/unit/solidity-types.test.ts +0 -39
  193. package/example/node_modules/quantumcoin/test/unit/utils.test.js +0 -57
  194. package/example/node_modules/quantumcoin/test/unit/utils.test.ts +0 -56
  195. package/example/node_modules/quantumcoin/test/verbose-logger.js +0 -74
  196. package/example/node_modules/quantumcoin/tsconfig.build.json +0 -14
  197. package/example/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +0 -22
  198. package/example/node_modules/seed-words/BUILD.md +0 -7
  199. package/example/node_modules/seed-words/LICENSE +0 -121
  200. package/example/node_modules/seed-words/README.md +0 -67
  201. package/example/node_modules/seed-words/dist/seedwords.d.ts +0 -39
  202. package/example/node_modules/seed-words/package.json +0 -27
  203. package/example/node_modules/seed-words/seedwords.js +0 -315
  204. package/example/node_modules/seed-words/seedwords.txt +0 -65536
  205. package/example/node_modules/seed-words/tsconfig.json +0 -21
  206. package/example/package-lock.json +0 -60
  207. package/example/package.json +0 -15
  208. package/scripts/build-browser-tests.js +0 -29
  209. package/scripts/build-wasm.js +0 -85
  210. package/tests/browser/bundle.js +0 -97643
  211. package/tests/browser/entry.js +0 -57
  212. package/tests/browser/harness.html +0 -20
  213. package/tests/browser/run-browser.js +0 -50
  214. package/tests/encrypted-32.json +0 -1
  215. package/tests/encrypted-36.json +0 -1
  216. package/tests/encrypted-48.json +0 -1
  217. package/tests/generate-verify-vectors.js +0 -88
  218. package/tests/get-gas-price.test.js +0 -59
  219. package/tests/hashing.test.js +0 -34
  220. package/tests/non-transactional.preinit.test.js +0 -33
  221. package/tests/non-transactional.test.js +0 -1318
  222. package/tests/sign-raw-keytype5-context-null.test.js +0 -105
  223. package/tests/sign-raw-transaction.test.js +0 -194
  224. package/tests/sign-verify.test.js +0 -308
  225. package/tests/specs/assert.js +0 -74
  226. package/tests/specs/crypto.spec.js +0 -104
  227. package/tests/specs/hex.js +0 -31
  228. package/tests/specs/preinit.spec.js +0 -19
  229. package/tests/specs/sign.spec.js +0 -90
  230. package/tests/specs/wallet.spec.js +0 -98
  231. package/tests/transactional.rpc.test.js +0 -102
  232. package/tests/verify-vectors.json +0 -95035
@@ -1,1318 +0,0 @@
1
- const { describe, test, before } = require('node:test');
2
- const assert = require('node:assert/strict');
3
- const path = require('path');
4
- const fs = require('fs');
5
-
6
- // Tests are required to live under `tests/` per project convention.
7
- // These are the "non-transactional" tests: offline operations + read-only relay/RPC calls.
8
-
9
- const qcsdk = require('..');
10
-
11
- const MAINNET_CHAIN_ID = 123123;
12
- const PUBLIC_RPC_URL = 'https://public.rpc.quantumcoinapi.com';
13
-
14
- const VALID_ADDRESS_EXAMPLE =
15
- '0x6f605c4142f1cb037f967101a5b28ccd00b27cce4516190356baaf284d20e667';
16
- const VALID_ADDRESS_EXAMPLE_UPPER =
17
- '0X6F605C4142F1CB037F967101A5B28CCD00B27CCE4516190356BAAF284D20E667';
18
- const TO_ADDRESS_EXAMPLE =
19
- '0x8293cd9b6ac502d2fe077b0c157dad39f36a5e546525b053151dced633634612';
20
-
21
- // Example seed words (48) from `example/example.js`
22
- const SEED_WORD_LIST =
23
- 'servetize,redmation,suaveton,dreadtolk,rondial,pondicle,miscoil,teaguery,dylodecid,portnel,mantical,slapware,sluthike,tactise,crierial,tajluvki,pranicum,sockcup,stacksong,duerling,genogram,peasate,pulubly,skimpop,feldtail,saprostal,crabrock,radiment,dolocsin,strigemen,juryeuk,fextial,merunized,tangienti,stylocyte,plumvieve,bobstike,nosecrown,acudemy,gripstick,lacreous,marculade,sporculum,outslope,bioburden,trompong,sidelay,finchage'
24
- .split(',');
25
-
26
- // Example wallet created with external wallet (from examples)
27
- const EXAMPLE_WALLET_ENCRYPTED_JSON =
28
- '{"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}';
29
- const EXAMPLE_WALLET_PASSPHRASE = 'QuantumCoinExample123!';
30
-
31
- // Fixture for "wallet test" (same as example wallet)
32
- const TEST_WALLET_ENCRYPTED_JSON = EXAMPLE_WALLET_ENCRYPTED_JSON;
33
- const TEST_WALLET_PASSPHRASE = EXAMPLE_WALLET_PASSPHRASE;
34
-
35
- // Fixture for seed-words address test
36
- const TEST_SEED_WORDS = [
37
- 'cylamidal', 'suculate', 'sealmate', 'radiploid', 'equifaxis', 'and', 'antipoise', 'stitchesy', 'perelade', 'lite',
38
- 'gourtarel', 'thursat', 'overdrome', 'cogulate', 'nonviva', 'stewnut', 'floribund', 'enduivist', 'decatary', 'elvenwort',
39
- 'indoucate', 'ravelent', 'vocalus', 'wetshirt', 'rutatory', 'percect', 'breaktout', 'corpation', 'myricorus', 'veofreat',
40
- 'junkard', 'supercarp', 'sukerus', 'tautang', 'facetype', 'shishkin', 'insulal', 'hobstone', 'stumbed', 'tecutonic',
41
- 'jumplike', 'hegwirth', 'idea', 'bhagatpur', 'pavastava', 'kukuluan', 'mageiline', 'extranite',
42
- ];
43
- const TEST_SEED_ADDRESS = '0x3Ce22c0e2714196734E42B0D4D5AD11284260502A560e46c2Cd857391564142F'.toLowerCase();
44
-
45
- // First 32 and 36 words from TEST_SEED_WORDS (for deterministic address tests)
46
- const TEST_SEED_WORDS_32 = TEST_SEED_WORDS.slice(0, 32);
47
- const TEST_SEED_WORDS_36 = TEST_SEED_WORDS.slice(0, 36);
48
- // Expected addresses for first 32/36 words (deterministic from test run)
49
- const TEST_SEED_ADDRESS_32 = '0x38b12df2d4762a04a183f936c47747a1f13d0b0ba72066b43b4b6d7f776e9e25';
50
- const TEST_SEED_ADDRESS_36 = '0x030e264c853bd859c53fae3ad6ef0e011dc799685e2b05d5efa7ac50f10ca075';
51
-
52
- // Default test password for encrypt/decrypt in seed-wallet roundtrip tests
53
- const SEED_WALLET_TEST_PASSPHRASE = TEST_WALLET_PASSPHRASE;
54
-
55
- async function rpc(method, params) {
56
- const response = await fetch(PUBLIC_RPC_URL, {
57
- method: 'POST',
58
- headers: { 'Content-Type': 'application/json' },
59
- body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
60
- });
61
- assert.ok(response.ok, `RPC HTTP ${response.status}`);
62
- return response.json();
63
- }
64
-
65
- function isHex0x(str) {
66
- return typeof str === 'string' && /^0x[0-9a-fA-F]*$/.test(str);
67
- }
68
-
69
- function isHex(str) {
70
- return typeof str === 'string' && /^[0-9a-fA-F]+$/.test(str);
71
- }
72
-
73
- /** True if CIRCL WASM is loaded, newWallet() returns a wallet, and verifyWallet passes. */
74
- function isCirclAvailable() {
75
- const w = qcsdk.newWallet();
76
- return (
77
- typeof w === 'object' &&
78
- w != null &&
79
- w.privateKey != null &&
80
- w.address != null &&
81
- qcsdk.verifyWallet(w) === true
82
- );
83
- }
84
-
85
- function hexToBytes(hex) {
86
- assert.ok(typeof hex === 'string');
87
- const h = hex.startsWith('0x') ? hex.slice(2) : hex;
88
- assert.equal(h.length % 2, 0);
89
- const out = [];
90
- for (let i = 0; i < h.length; i += 2) out.push(parseInt(h.slice(i, i + 2), 16));
91
- return out;
92
- }
93
-
94
- describe('non-transactional', () => {
95
- test('exports: all classes are constructible (and not callable without new)', () => {
96
- const classExports = [
97
- 'Config',
98
- 'EventLogEncodeResult',
99
- 'PackUnpackResult',
100
- 'TransactionSigningRequest',
101
- 'Wallet',
102
- ];
103
-
104
- for (const name of classExports) {
105
- assert.equal(typeof qcsdk[name], 'function', `${name} export missing`);
106
- assert.throws(() => qcsdk[name](), TypeError, `${name} should require new`);
107
- // Basic "positive" constructability check
108
- assert.ok(new qcsdk[name](), `${name} should be new-able`);
109
- }
110
- });
111
-
112
- before(async () => {
113
- const cfg = new qcsdk.Config(MAINNET_CHAIN_ID);
114
- const initResult = await qcsdk.initialize(cfg);
115
- assert.equal(initResult, true, 'SDK initialize should succeed');
116
- });
117
-
118
- test('initialize: calling initialize twice returns false', async () => {
119
- const cfg = new qcsdk.Config(MAINNET_CHAIN_ID);
120
- const init2 = await qcsdk.initialize(cfg);
121
- assert.equal(init2, false);
122
- });
123
-
124
- test('isAddressValid: accepts valid 0x/0X and rejects invalid', () => {
125
- assert.equal(qcsdk.isAddressValid(VALID_ADDRESS_EXAMPLE), true);
126
- assert.equal(qcsdk.isAddressValid(VALID_ADDRESS_EXAMPLE_UPPER), true);
127
- assert.equal(qcsdk.isAddressValid('asfasdfasdfs'), false);
128
- assert.equal(qcsdk.isAddressValid(null), false);
129
- });
130
-
131
- test('wallet: newWallet/verifyWallet/serializeWallet/deserializeWallet roundtrip', () => {
132
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
133
- const w1 = qcsdk.newWallet();
134
- assert.ok(w1);
135
- assert.equal(typeof w1.address, 'string');
136
- assert.ok(w1.privateKey && (w1.privateKey.byteLength !== undefined || typeof w1.privateKey.length === 'number'));
137
- assert.ok(w1.publicKey && (w1.publicKey.byteLength !== undefined || typeof w1.publicKey.length === 'number'));
138
- assert.ok(w1.privateKey.length > 0);
139
- assert.ok(w1.publicKey.length > 0);
140
- assert.equal(qcsdk.verifyWallet(w1), true);
141
- assert.equal(qcsdk.isAddressValid(w1.address), true);
142
-
143
- const serialized = qcsdk.serializeWallet(w1);
144
- assert.ok(serialized && typeof serialized === 'string');
145
- const w2 = qcsdk.deserializeWallet(serialized);
146
- assert.ok(w2);
147
- assert.equal(w2.address.toLowerCase(), w1.address.toLowerCase());
148
- assert.equal(qcsdk.verifyWallet(w2), true);
149
- });
150
-
151
- test('wallet encrypted: serializeEncryptedWallet/deserializeEncryptedWallet', () => {
152
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
153
- const passphrase = 'QuantumCoinExample123!';
154
- const w1 = qcsdk.newWallet();
155
- const enc = qcsdk.serializeEncryptedWallet(w1, passphrase);
156
- assert.ok(enc && typeof enc === 'string');
157
-
158
- const w2 = qcsdk.deserializeEncryptedWallet(enc, passphrase);
159
- assert.ok(w2);
160
- assert.equal(w2.address.toLowerCase(), w1.address.toLowerCase());
161
- assert.equal(qcsdk.verifyWallet(w2), true);
162
-
163
- // Negative: wrong passphrase
164
- const wBad = qcsdk.deserializeEncryptedWallet(enc, passphrase + 'wrong');
165
- assert.equal(wBad, null);
166
- });
167
-
168
- test('wallet test', () => {
169
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
170
- const wallet = qcsdk.deserializeEncryptedWallet(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
171
- assert.ok(wallet, 'deserializeEncryptedWallet should return a wallet');
172
- assert.equal(typeof wallet.address, 'string');
173
- assert.equal(wallet.address.toLowerCase(), '0x1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6');
174
- assert.equal(qcsdk.verifyWallet(wallet), true);
175
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
176
- });
177
-
178
- test('seed words: newWalletSeedWords/openWalletFromSeedWords (static fixture)', () => {
179
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
180
- const seedWords = qcsdk.newWalletSeedWords();
181
- assert.ok(seedWords);
182
- assert.ok(Array.isArray(seedWords) || typeof seedWords === 'string');
183
-
184
- // Positive: open deterministic wallet from seed words fixture (48-word legacy / hybrideds)
185
- const seedWallet = qcsdk.openWalletFromSeedWords(SEED_WORD_LIST);
186
- assert.ok(seedWallet);
187
- assert.equal(qcsdk.verifyWallet(seedWallet), true);
188
- assert.equal(qcsdk.isAddressValid(seedWallet.address), true);
189
-
190
- // Negative: invalid seed input
191
- assert.equal(qcsdk.openWalletFromSeedWords(['not', 'enough']), null);
192
- });
193
-
194
- test('seed words: openWalletFromSeedWords TEST_SEED_WORDS yields TEST_SEED_ADDRESS', () => {
195
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
196
- const wallet = qcsdk.openWalletFromSeedWords(TEST_SEED_WORDS);
197
- assert.ok(wallet, 'openWalletFromSeedWords should return a wallet');
198
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS);
199
- assert.equal(qcsdk.verifyWallet(wallet), true);
200
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
201
- });
202
-
203
- test('seed words: first 32 words from TEST_SEED_WORDS — verifyWallet and isAddressValid (deterministic)', () => {
204
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
205
- const wallet = qcsdk.openWalletFromSeedWords(TEST_SEED_WORDS_32);
206
- assert.ok(wallet, 'openWalletFromSeedWords(first 32) should return a wallet');
207
- assert.equal(qcsdk.verifyWallet(wallet), true);
208
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
209
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS_32);
210
- });
211
-
212
- test('seed words: first 36 words from TEST_SEED_WORDS — verifyWallet and isAddressValid (deterministic)', () => {
213
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
214
- const wallet = qcsdk.openWalletFromSeedWords(TEST_SEED_WORDS_36);
215
- assert.ok(wallet, 'openWalletFromSeedWords(first 36) should return a wallet');
216
- assert.equal(qcsdk.verifyWallet(wallet), true);
217
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
218
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS_36);
219
- });
220
-
221
- // --- openWalletFromSeed tests (raw seed byte arrays) ---
222
-
223
- // Hardcoded seed byte arrays derived from TEST_SEED_WORDS via seed-words.getSeedArrayFromWordList
224
- const TEST_SEED_ARRAY_48 = [49,159,218,142,198,66,182,182,73,216,5,119,6,71,216,42,164,55,124,237,92,81,228,227,156,0,38,189,152,58,215,177,80,252,71,86,51,210,70,33,106,200,184,26,246,139,249,41,191,104,163,253,21,26,43,108,146,94,243,204,112,236,219,139,218,249,224,255,76,150,203,7,108,119,101,70,217,112,225,190,112,169,98,168,104,223,14,235,161,192,118,167,128,203,76,59];
225
- const TEST_SEED_ARRAY_32 = [49,159,218,142,198,66,182,182,73,216,5,119,6,71,216,42,164,55,124,237,92,81,228,227,156,0,38,189,152,58,215,177,80,252,71,86,51,210,70,33,106,200,184,26,246,139,249,41,191,104,163,253,21,26,43,108,146,94,243,204,112,236,219,139];
226
- const TEST_SEED_ARRAY_36 = [49,159,218,142,198,66,182,182,73,216,5,119,6,71,216,42,164,55,124,237,92,81,228,227,156,0,38,189,152,58,215,177,80,252,71,86,51,210,70,33,106,200,184,26,246,139,249,41,191,104,163,253,21,26,43,108,146,94,243,204,112,236,219,139,218,249,224,255,76,150,203,7];
227
-
228
- test('openWalletFromSeed: 96-byte seed produces expected address (hybrideds)', () => {
229
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
230
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_48);
231
- assert.ok(wallet, 'openWalletFromSeed should return a wallet for 96-byte seed');
232
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS);
233
- assert.equal(qcsdk.verifyWallet(wallet), true);
234
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
235
- });
236
-
237
- test('openWalletFromSeed: 64-byte seed produces expected address (hybrid)', () => {
238
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
239
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
240
- assert.ok(wallet, 'openWalletFromSeed should return a wallet for 64-byte seed');
241
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS_32);
242
- assert.equal(qcsdk.verifyWallet(wallet), true);
243
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
244
- });
245
-
246
- test('openWalletFromSeed: 72-byte seed produces expected address (hybrid5)', () => {
247
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
248
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_36);
249
- assert.ok(wallet, 'openWalletFromSeed should return a wallet for 72-byte seed');
250
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS_36);
251
- assert.equal(qcsdk.verifyWallet(wallet), true);
252
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
253
- });
254
-
255
- test('openWalletFromSeed: matches openWalletFromSeedWords for all three schemes', () => {
256
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
257
- for (const [seedArray, seedWords] of [
258
- [TEST_SEED_ARRAY_48, TEST_SEED_WORDS],
259
- [TEST_SEED_ARRAY_32, TEST_SEED_WORDS_32],
260
- [TEST_SEED_ARRAY_36, TEST_SEED_WORDS_36],
261
- ]) {
262
- const fromSeed = qcsdk.openWalletFromSeed(seedArray);
263
- const fromWords = qcsdk.openWalletFromSeedWords(seedWords);
264
- assert.ok(fromSeed, 'openWalletFromSeed should return a wallet');
265
- assert.ok(fromWords, 'openWalletFromSeedWords should return a wallet');
266
- assert.equal(fromSeed.address.toLowerCase(), fromWords.address.toLowerCase());
267
- }
268
- });
269
-
270
- test('openWalletFromSeed: accepts Uint8Array input', () => {
271
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
272
- const wallet = qcsdk.openWalletFromSeed(new Uint8Array(TEST_SEED_ARRAY_48));
273
- assert.ok(wallet, 'openWalletFromSeed should accept Uint8Array');
274
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS);
275
- });
276
-
277
- test('openWalletFromSeed: null input returns null', () => {
278
- assert.equal(qcsdk.openWalletFromSeed(null), null);
279
- });
280
-
281
- test('openWalletFromSeed: undefined input returns null', () => {
282
- assert.equal(qcsdk.openWalletFromSeed(undefined), null);
283
- });
284
-
285
- test('openWalletFromSeed: empty array returns null', () => {
286
- assert.equal(qcsdk.openWalletFromSeed([]), null);
287
- });
288
-
289
- test('openWalletFromSeed: wrong length array returns null', () => {
290
- assert.equal(qcsdk.openWalletFromSeed([1, 2, 3, 4, 5]), null);
291
- assert.equal(qcsdk.openWalletFromSeed(new Array(63).fill(0)), null);
292
- assert.equal(qcsdk.openWalletFromSeed(new Array(65).fill(0)), null);
293
- assert.equal(qcsdk.openWalletFromSeed(new Array(71).fill(0)), null);
294
- assert.equal(qcsdk.openWalletFromSeed(new Array(73).fill(0)), null);
295
- assert.equal(qcsdk.openWalletFromSeed(new Array(95).fill(0)), null);
296
- assert.equal(qcsdk.openWalletFromSeed(new Array(97).fill(0)), null);
297
- });
298
-
299
- test('openWalletFromSeed: non-array input returns null', () => {
300
- assert.equal(qcsdk.openWalletFromSeed('not an array'), null);
301
- assert.equal(qcsdk.openWalletFromSeed(12345), null);
302
- assert.equal(qcsdk.openWalletFromSeed({}), null);
303
- });
304
-
305
- // --- serializeSeedAsEncryptedWallet tests ---
306
-
307
- test('serializeSeedAsEncryptedWallet: 96-byte seed roundtrip — address and keys match', () => {
308
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
309
- const json = qcsdk.serializeSeedAsEncryptedWallet(TEST_SEED_ARRAY_48, SEED_WALLET_TEST_PASSPHRASE);
310
- assert.ok(json && typeof json === 'string', 'should return a JSON string');
311
- const wallet = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
312
- assert.ok(wallet, 'deserializeEncryptedWallet should return a wallet');
313
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS);
314
- assert.equal(qcsdk.verifyWallet(wallet), true);
315
- const ref = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_48);
316
- assert.ok(ref);
317
- assert.equal(wallet.publicKey.length, ref.publicKey.length);
318
- for (let i = 0; i < wallet.publicKey.length; i++) assert.equal(wallet.publicKey[i], ref.publicKey[i]);
319
- assert.equal(wallet.privateKey.length, ref.privateKey.length);
320
- for (let i = 0; i < wallet.privateKey.length; i++) assert.equal(wallet.privateKey[i], ref.privateKey[i]);
321
- });
322
-
323
- test('serializeSeedAsEncryptedWallet: 64-byte seed roundtrip — address and keys match', () => {
324
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
325
- const json = qcsdk.serializeSeedAsEncryptedWallet(TEST_SEED_ARRAY_32, SEED_WALLET_TEST_PASSPHRASE);
326
- assert.ok(json && typeof json === 'string', 'should return a JSON string');
327
- const wallet = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
328
- assert.ok(wallet, 'deserializeEncryptedWallet should return a wallet');
329
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS_32);
330
- assert.equal(qcsdk.verifyWallet(wallet), true);
331
- const ref = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
332
- assert.ok(ref);
333
- assert.equal(wallet.publicKey.length, ref.publicKey.length);
334
- for (let i = 0; i < wallet.publicKey.length; i++) assert.equal(wallet.publicKey[i], ref.publicKey[i]);
335
- assert.equal(wallet.privateKey.length, ref.privateKey.length);
336
- for (let i = 0; i < wallet.privateKey.length; i++) assert.equal(wallet.privateKey[i], ref.privateKey[i]);
337
- });
338
-
339
- test('serializeSeedAsEncryptedWallet: 72-byte seed roundtrip — address and keys match', () => {
340
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
341
- const json = qcsdk.serializeSeedAsEncryptedWallet(TEST_SEED_ARRAY_36, SEED_WALLET_TEST_PASSPHRASE);
342
- assert.ok(json && typeof json === 'string', 'should return a JSON string');
343
- const wallet = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
344
- assert.ok(wallet, 'deserializeEncryptedWallet should return a wallet');
345
- assert.equal(wallet.address.toLowerCase(), TEST_SEED_ADDRESS_36);
346
- assert.equal(qcsdk.verifyWallet(wallet), true);
347
- const ref = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_36);
348
- assert.ok(ref);
349
- assert.equal(wallet.publicKey.length, ref.publicKey.length);
350
- for (let i = 0; i < wallet.publicKey.length; i++) assert.equal(wallet.publicKey[i], ref.publicKey[i]);
351
- assert.equal(wallet.privateKey.length, ref.privateKey.length);
352
- for (let i = 0; i < wallet.privateKey.length; i++) assert.equal(wallet.privateKey[i], ref.privateKey[i]);
353
- });
354
-
355
- test('serializeSeedAsEncryptedWallet: null seed returns null', () => {
356
- assert.equal(qcsdk.serializeSeedAsEncryptedWallet(null, SEED_WALLET_TEST_PASSPHRASE), null);
357
- });
358
-
359
- test('serializeSeedAsEncryptedWallet: wrong-length seed returns null', () => {
360
- assert.equal(qcsdk.serializeSeedAsEncryptedWallet(new Array(5).fill(0), SEED_WALLET_TEST_PASSPHRASE), null);
361
- assert.equal(qcsdk.serializeSeedAsEncryptedWallet(new Array(63).fill(0), SEED_WALLET_TEST_PASSPHRASE), null);
362
- assert.equal(qcsdk.serializeSeedAsEncryptedWallet(new Array(97).fill(0), SEED_WALLET_TEST_PASSPHRASE), null);
363
- });
364
-
365
- test('serializeSeedAsEncryptedWallet: null passphrase returns null', () => {
366
- assert.equal(qcsdk.serializeSeedAsEncryptedWallet(TEST_SEED_ARRAY_32, null), null);
367
- });
368
-
369
- test('serializeSeedAsEncryptedWallet: short passphrase returns null', () => {
370
- assert.equal(qcsdk.serializeSeedAsEncryptedWallet(TEST_SEED_ARRAY_32, 'short'), null);
371
- });
372
-
373
- test('serializeSeedAsEncryptedWallet: non-string passphrase returns null', () => {
374
- assert.equal(qcsdk.serializeSeedAsEncryptedWallet(TEST_SEED_ARRAY_32, 12345), null);
375
- });
376
-
377
- // --- preExpansionSeed field tests ---
378
-
379
- test('Wallet class: constructor without preExpansionSeed defaults to null', () => {
380
- const w = new qcsdk.Wallet('0xabc', [1, 2], [3, 4]);
381
- assert.equal(w.preExpansionSeed, null);
382
- });
383
-
384
- test('Wallet class: constructor with preExpansionSeed stores it', () => {
385
- const seed = new Uint8Array([10, 20, 30]);
386
- const w = new qcsdk.Wallet('0xabc', [1, 2], [3, 4], seed);
387
- assert.ok(w.preExpansionSeed != null);
388
- assert.equal(w.preExpansionSeed.length, 3);
389
- assert.equal(w.preExpansionSeed[0], 10);
390
- });
391
-
392
- test('newWallet: wallet has preExpansionSeed === null', () => {
393
- const w = qcsdk.newWallet();
394
- assert.ok(w && typeof w === 'object');
395
- assert.equal(w.preExpansionSeed, null);
396
- });
397
-
398
- test('openWalletFromSeed: 64-byte seed — preExpansionSeed is byte-equal to input', () => {
399
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
400
- assert.ok(wallet && wallet.preExpansionSeed != null);
401
- assert.equal(wallet.preExpansionSeed.length, 64);
402
- const inputU8 = new Uint8Array(TEST_SEED_ARRAY_32);
403
- for (let i = 0; i < 64; i++) assert.equal(wallet.preExpansionSeed[i], inputU8[i]);
404
- });
405
-
406
- test('openWalletFromSeed: 72-byte seed — preExpansionSeed is byte-equal to input', () => {
407
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_36);
408
- assert.ok(wallet && wallet.preExpansionSeed != null);
409
- assert.equal(wallet.preExpansionSeed.length, 72);
410
- const inputU8 = new Uint8Array(TEST_SEED_ARRAY_36);
411
- for (let i = 0; i < 72; i++) assert.equal(wallet.preExpansionSeed[i], inputU8[i]);
412
- });
413
-
414
- test('openWalletFromSeed: 96-byte seed — preExpansionSeed is byte-equal to input', () => {
415
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_48);
416
- assert.ok(wallet && wallet.preExpansionSeed != null);
417
- assert.equal(wallet.preExpansionSeed.length, 96);
418
- const inputU8 = new Uint8Array(TEST_SEED_ARRAY_48);
419
- for (let i = 0; i < 96; i++) assert.equal(wallet.preExpansionSeed[i], inputU8[i]);
420
- });
421
-
422
- test('openWalletFromSeedWords: wallet has non-null preExpansionSeed', () => {
423
- const wallet = qcsdk.openWalletFromSeedWords(TEST_SEED_WORDS);
424
- assert.ok(wallet && wallet.preExpansionSeed != null);
425
- assert.equal(wallet.preExpansionSeed.length, 96);
426
- });
427
-
428
- test('serializeEncryptedWallet roundtrip: seed wallet (64-byte) preserves preExpansionSeed and produces V5', () => {
429
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
430
- assert.ok(wallet && wallet.preExpansionSeed != null);
431
- const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
432
- assert.ok(json && typeof json === 'string');
433
- const parsed = JSON.parse(json);
434
- assert.equal(parsed.version, 5, 'seed wallet should produce V5 encrypted JSON');
435
- const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
436
- assert.ok(restored);
437
- assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
438
- assert.ok(restored.preExpansionSeed != null);
439
- assert.equal(restored.preExpansionSeed.length, 64);
440
- const origSeed = new Uint8Array(TEST_SEED_ARRAY_32);
441
- for (let i = 0; i < 64; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
442
- });
443
-
444
- test('serializeEncryptedWallet roundtrip: seed wallet (72-byte) preserves preExpansionSeed and produces V5', () => {
445
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_36);
446
- assert.ok(wallet && wallet.preExpansionSeed != null);
447
- const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
448
- assert.ok(json && typeof json === 'string');
449
- const parsed = JSON.parse(json);
450
- assert.equal(parsed.version, 5, 'seed wallet should produce V5 encrypted JSON');
451
- const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
452
- assert.ok(restored);
453
- assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
454
- assert.ok(restored.preExpansionSeed != null);
455
- assert.equal(restored.preExpansionSeed.length, 72);
456
- const origSeed = new Uint8Array(TEST_SEED_ARRAY_36);
457
- for (let i = 0; i < 72; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
458
- });
459
-
460
- test('serializeEncryptedWallet roundtrip: seed wallet (96-byte) preserves preExpansionSeed and produces V5', () => {
461
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_48);
462
- assert.ok(wallet && wallet.preExpansionSeed != null);
463
- const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
464
- assert.ok(json && typeof json === 'string');
465
- const parsed = JSON.parse(json);
466
- assert.equal(parsed.version, 5, 'seed wallet should produce V5 encrypted JSON');
467
- const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
468
- assert.ok(restored);
469
- assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
470
- assert.ok(restored.preExpansionSeed != null);
471
- assert.equal(restored.preExpansionSeed.length, 96);
472
- const origSeed = new Uint8Array(TEST_SEED_ARRAY_48);
473
- for (let i = 0; i < 96; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
474
- });
475
-
476
- test('serializeEncryptedWallet roundtrip: non-seed wallet has null preExpansionSeed and produces V4', () => {
477
- const wallet = qcsdk.newWallet();
478
- assert.ok(wallet);
479
- assert.equal(wallet.preExpansionSeed, null);
480
- const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
481
- assert.ok(json && typeof json === 'string');
482
- const parsed = JSON.parse(json);
483
- assert.equal(parsed.version, 4, 'non-seed wallet should produce V4 encrypted JSON');
484
- const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
485
- assert.ok(restored);
486
- assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
487
- assert.equal(restored.preExpansionSeed, null);
488
- });
489
-
490
- test('serializeWallet/deserializeWallet roundtrip: seed wallet preserves preExpansionSeed', () => {
491
- const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
492
- assert.ok(wallet && wallet.preExpansionSeed != null);
493
- const json = qcsdk.serializeWallet(wallet);
494
- assert.ok(json && typeof json === 'string');
495
- const parsed = JSON.parse(json);
496
- assert.ok(parsed.preExpansionSeed, 'serialized JSON should contain preExpansionSeed field');
497
- const restored = qcsdk.deserializeWallet(json);
498
- assert.ok(restored);
499
- assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
500
- assert.ok(restored.preExpansionSeed != null);
501
- assert.equal(restored.preExpansionSeed.length, 64);
502
- const origSeed = new Uint8Array(TEST_SEED_ARRAY_32);
503
- for (let i = 0; i < 64; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
504
- });
505
-
506
- test('serializeWallet/deserializeWallet roundtrip: non-seed wallet has null preExpansionSeed and no field in JSON', () => {
507
- const wallet = qcsdk.newWallet();
508
- assert.ok(wallet);
509
- assert.equal(wallet.preExpansionSeed, null);
510
- const json = qcsdk.serializeWallet(wallet);
511
- assert.ok(json && typeof json === 'string');
512
- const parsed = JSON.parse(json);
513
- assert.equal(parsed.preExpansionSeed, undefined, 'non-seed wallet JSON should not contain preExpansionSeed');
514
- const restored = qcsdk.deserializeWallet(json);
515
- assert.ok(restored);
516
- assert.equal(restored.preExpansionSeed, null);
517
- });
518
-
519
- test('backward compat: deserializeEncryptedWallet on V4 JSON (no seed) returns wallet with null preExpansionSeed', () => {
520
- const wallet = qcsdk.deserializeEncryptedWallet(EXAMPLE_WALLET_ENCRYPTED_JSON, EXAMPLE_WALLET_PASSPHRASE);
521
- assert.ok(wallet);
522
- assert.equal(wallet.preExpansionSeed, null);
523
- assert.equal(qcsdk.verifyWallet(wallet), true);
524
- });
525
-
526
- test('backward compat: deserializeWallet on JSON without preExpansionSeed field returns null seed', () => {
527
- const wallet = qcsdk.newWallet();
528
- const jsonWithoutSeed = JSON.stringify({
529
- address: wallet.address,
530
- privateKey: Array.from(wallet.privateKey).map(b => String.fromCodePoint(b)).join(''),
531
- publicKey: Array.from(wallet.publicKey).map(b => String.fromCodePoint(b)).join(''),
532
- });
533
- const w = qcsdk.newWallet();
534
- const json = qcsdk.serializeWallet(w);
535
- const parsed = JSON.parse(json);
536
- delete parsed.preExpansionSeed;
537
- const cleanJson = JSON.stringify(parsed);
538
- const restored = qcsdk.deserializeWallet(cleanJson);
539
- assert.ok(restored);
540
- assert.equal(restored.preExpansionSeed, null);
541
- });
542
-
543
- // Hardcoded encrypted wallet JSON (from openWalletFromSeedWords + serializeEncryptedWallet with SEED_WALLET_TEST_PASSPHRASE).
544
- // Deserialize and verify addresses match. Uses fixtures in tests/ (encrypted-48.json, encrypted-32.json, encrypted-36.json).
545
- test('seed words: deserializeEncryptedWallet from serialized 48/32/36 seed wallets — addresses match', () => {
546
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
547
- const testsDir = __dirname;
548
- const enc48 = fs.readFileSync(path.join(testsDir, 'encrypted-48.json'), 'utf8').trim();
549
- const enc32 = fs.readFileSync(path.join(testsDir, 'encrypted-32.json'), 'utf8').trim();
550
- const enc36 = fs.readFileSync(path.join(testsDir, 'encrypted-36.json'), 'utf8').trim();
551
- for (const [enc, expectedAddress] of [
552
- [enc48, TEST_SEED_ADDRESS],
553
- [enc32, TEST_SEED_ADDRESS_32],
554
- [enc36, TEST_SEED_ADDRESS_36],
555
- ]) {
556
- const wallet = qcsdk.deserializeEncryptedWallet(enc, SEED_WALLET_TEST_PASSPHRASE);
557
- assert.ok(wallet, 'deserializeEncryptedWallet should return a wallet');
558
- assert.equal(wallet.address.toLowerCase(), expectedAddress);
559
- assert.equal(qcsdk.verifyWallet(wallet), true);
560
- assert.equal(qcsdk.isAddressValid(wallet.address), true);
561
- }
562
- });
563
-
564
- test('publicKeyFromPrivateKey/addressFromPublicKey and signature helpers', () => {
565
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
566
- const wallet = qcsdk.newWallet();
567
- assert.ok(wallet);
568
- assert.equal(qcsdk.verifyWallet(wallet), true);
569
-
570
- const pubHex = qcsdk.publicKeyFromPrivateKey(wallet.privateKey);
571
- assert.ok(pubHex && typeof pubHex === 'string');
572
- assert.ok(isHex(pubHex), 'publicKeyFromPrivateKey returns hex (no 0x prefix)');
573
-
574
- // Compare derived public key bytes to wallet publicKey bytes
575
- const pubBytes = hexToBytes(pubHex);
576
- assert.equal(pubBytes.length, wallet.publicKey.length);
577
- for (let i = 0; i < pubBytes.length; i++) assert.equal(pubBytes[i], wallet.publicKey[i]);
578
-
579
- // addressFromPublicKey should match wallet address
580
- const addr = qcsdk.addressFromPublicKey(wallet.publicKey);
581
- assert.equal(addr.toLowerCase(), wallet.address.toLowerCase());
582
-
583
- // combinePublicKeySignature + publicKeyFromSignature roundtrip (use CIRCL hybrideds when available)
584
- const digest = new TextEncoder().encode('verifyverifyverifyverifyverifyok'); // 32 bytes
585
- assert.equal(digest.length, 32);
586
- const g = typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : {};
587
- const circl = g.circl;
588
- let sig;
589
- if (circl && circl.hybrideds) {
590
- const privU8 = wallet.privateKey instanceof Uint8Array ? wallet.privateKey : new Uint8Array(wallet.privateKey);
591
- const sigRes = circl.hybrideds.signCompact(privU8, digest);
592
- if (sigRes && sigRes.error) throw new Error('CIRCL sign failed: ' + sigRes.error);
593
- sig = sigRes.result instanceof Uint8Array ? Array.from(sigRes.result) : sigRes.result;
594
- } else {
595
- // Skip roundtrip if CIRCL not loaded (e.g. WASM not yet CIRCL build)
596
- return;
597
- }
598
- const combinedHex = qcsdk.combinePublicKeySignature(wallet.publicKey, sig);
599
- assert.ok(combinedHex && typeof combinedHex === 'string' && isHex(combinedHex));
600
-
601
- const combinedBytes = hexToBytes(combinedHex);
602
- const recoveredPubHex = qcsdk.publicKeyFromSignature(digest, combinedBytes);
603
- assert.ok(recoveredPubHex && typeof recoveredPubHex === 'string' && isHex(recoveredPubHex));
604
- assert.equal(recoveredPubHex.toLowerCase(), pubHex.toLowerCase());
605
-
606
- // Negative: wrong digest size
607
- assert.equal(qcsdk.publicKeyFromSignature([1, 2, 3], combinedBytes), null);
608
- });
609
-
610
- test('RLP: encodeRlp/decodeRlp roundtrip and negative decode', () => {
611
- // Note: current WASM DecodeRlp returns a JSON string where decoded bytes appear as boolean arrays.
612
- // We validate that encode->decode is structurally consistent rather than matching the original JS value.
613
- const enc = qcsdk.encodeRlp(['hello', 123, true]);
614
- assert.equal(enc.error, '');
615
- assert.ok(isHex0x(enc.result));
616
-
617
- const dec = qcsdk.decodeRlp(enc.result);
618
- assert.equal(dec.error, '');
619
- const decoded = JSON.parse(dec.result);
620
- assert.ok(Array.isArray(decoded));
621
- assert.equal(decoded.length, 3);
622
- assert.ok(Array.isArray(decoded[0]) && decoded[0].length === 5); // "hello" bytes -> 5 trues
623
- assert.ok(Array.isArray(decoded[1]) && decoded[1].length >= 1);
624
- assert.ok(Array.isArray(decoded[2]) && decoded[2].length >= 1);
625
- assert.ok(decoded.flat(2).every((b) => typeof b === 'boolean'));
626
-
627
- const bad = qcsdk.decodeRlp('not-hex');
628
- assert.notEqual(bad.error, '');
629
- });
630
-
631
- test('ABI pack/unpack: packMethodData/unpackMethodData via RPC eth_call', async () => {
632
- // Minimal ERC20-like ABI used in examples
633
- const erc20ABI = JSON.stringify([
634
- {
635
- name: 'balanceOf',
636
- type: 'function',
637
- inputs: [{ name: 'account', type: 'address' }],
638
- outputs: [{ name: '', type: 'uint256' }],
639
- stateMutability: 'view',
640
- },
641
- {
642
- name: 'name',
643
- type: 'function',
644
- inputs: [],
645
- outputs: [{ name: '', type: 'string' }],
646
- stateMutability: 'view',
647
- },
648
- ]);
649
-
650
- const tokenAddress =
651
- '0x1Bd75060B22686a9f32Af80BC02348c1BAeDBba06f47ad723885c92a6566B65d';
652
- const holderAddress =
653
- '0xd51773b5dde3f8e4d29ae42b5046510e2a11fd0c8e4175853d6227896eb445c6';
654
-
655
- const pack = qcsdk.packMethodData(erc20ABI, 'balanceOf', holderAddress);
656
- assert.equal(pack.error, '');
657
- assert.ok(isHex0x(pack.result));
658
-
659
- const call = await rpc('eth_call', [{ to: tokenAddress, data: pack.result }, 'latest']);
660
- assert.ok(call && (call.result || call.error));
661
- assert.ok(call.result && isHex0x(call.result), 'eth_call should return hex');
662
-
663
- const unpack = qcsdk.unpackMethodData(erc20ABI, 'balanceOf', call.result);
664
- assert.equal(unpack.error, '');
665
- const parsed = JSON.parse(unpack.result);
666
- assert.ok(Array.isArray(parsed));
667
- assert.equal(typeof parsed[0], 'string');
668
-
669
- // Negative: invalid ABI JSON
670
- const badPack = qcsdk.packMethodData('not-json', 'balanceOf', holderAddress);
671
- assert.notEqual(badPack.error, '');
672
- });
673
-
674
- test('Event logs: encodeEventLog/decodeEventLog (Transfer)', () => {
675
- const transferABI = JSON.stringify([
676
- {
677
- name: 'Transfer',
678
- type: 'event',
679
- anonymous: false,
680
- inputs: [
681
- { name: 'from', type: 'address', indexed: true },
682
- { name: 'to', type: 'address', indexed: true },
683
- { name: 'value', type: 'uint256', indexed: false },
684
- ],
685
- },
686
- ]);
687
-
688
- const fromAddress =
689
- '0xd51773b5dde3f8e4d29ae42b5046510e2a11fd0c8e4175853d6227896eb445c6';
690
- const toAddress =
691
- '0x1Bd75060B22686a9f32Af80BC02348c1BAeDBba06f47ad723885c92a6566B65d';
692
- const value = '1000000000000000000';
693
-
694
- const enc = qcsdk.encodeEventLog(transferABI, 'Transfer', fromAddress, toAddress, value);
695
- assert.equal(enc.error, '');
696
- assert.ok(enc.result);
697
- assert.equal(Array.isArray(enc.result.topics), true);
698
- assert.equal(enc.result.topics.length, 3);
699
- assert.ok(isHex0x(enc.result.data));
700
-
701
- const dec = qcsdk.decodeEventLog(transferABI, 'Transfer', enc.result.topics, enc.result.data);
702
- assert.equal(dec.error, '');
703
- const decoded = JSON.parse(dec.result);
704
- assert.equal(decoded.from.toLowerCase(), fromAddress.toLowerCase());
705
- assert.equal(decoded.to.toLowerCase(), toAddress.toLowerCase());
706
- assert.equal(decoded.value, value);
707
-
708
- // Negative: invalid ABI
709
- const bad = qcsdk.decodeEventLog('not-json', 'Transfer', enc.result.topics, enc.result.data);
710
- assert.notEqual(bad.error, '');
711
- });
712
-
713
- // --- packCreateContractData tests (ported from Go main_test.go) ---
714
-
715
- test('packCreateContractData: parameterless constructor', () => {
716
- const abi = JSON.stringify([{
717
- type: 'constructor',
718
- inputs: [],
719
- stateMutability: 'nonpayable',
720
- }]);
721
- const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
722
- const result = qcsdk.packCreateContractData(abi, bytecode);
723
- assert.equal(result.error, '');
724
- assert.ok(isHex0x(result.result));
725
- assert.ok(result.result.toLowerCase().startsWith(bytecode.toLowerCase()));
726
- });
727
-
728
- test('packCreateContractData: constructor with uint256 params', () => {
729
- const abi = JSON.stringify([{
730
- type: 'constructor',
731
- inputs: [
732
- { name: 'a', type: 'uint256' },
733
- { name: 'b', type: 'uint256' },
734
- ],
735
- stateMutability: 'nonpayable',
736
- }]);
737
- const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
738
- const result = qcsdk.packCreateContractData(abi, bytecode, '1', '2');
739
- assert.equal(result.error, '');
740
- assert.ok(isHex0x(result.result));
741
- assert.ok(result.result.length > bytecode.length, 'result should be longer than bytecode alone');
742
- assert.ok(result.result.toLowerCase().startsWith(bytecode.toLowerCase()));
743
- });
744
-
745
- test('packCreateContractData: constructor with address param', () => {
746
- const abi = JSON.stringify([{
747
- type: 'constructor',
748
- inputs: [{ name: 'owner', type: 'address' }],
749
- stateMutability: 'nonpayable',
750
- }]);
751
- const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
752
- const ownerAddr = '0x0000000000000000000000000000000000000000000000000000000000000001';
753
- const result = qcsdk.packCreateContractData(abi, bytecode, ownerAddr);
754
- assert.equal(result.error, '');
755
- assert.ok(isHex0x(result.result));
756
- assert.ok(result.result.length > bytecode.length);
757
- });
758
-
759
- test('packCreateContractData: constructor with uint256[] array param', () => {
760
- const abi = JSON.stringify([{
761
- type: 'constructor',
762
- inputs: [{ name: 'values', type: 'uint256[]' }],
763
- stateMutability: 'nonpayable',
764
- }]);
765
- const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
766
- const result = qcsdk.packCreateContractData(abi, bytecode, ['100', '200', '300']);
767
- assert.equal(result.error, '');
768
- assert.ok(isHex0x(result.result));
769
- assert.ok(result.result.length > bytecode.length);
770
- });
771
-
772
- test('packCreateContractData: empty ABI JSON returns error', () => {
773
- const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
774
- const r1 = qcsdk.packCreateContractData('', bytecode);
775
- assert.notEqual(r1.error, '');
776
- const r2 = qcsdk.packCreateContractData(' ', bytecode);
777
- assert.notEqual(r2.error, '');
778
- });
779
-
780
- test('packCreateContractData: empty bytecode returns error', () => {
781
- const abi = JSON.stringify([{ type: 'constructor', inputs: [], stateMutability: 'nonpayable' }]);
782
- const r1 = qcsdk.packCreateContractData(abi, '');
783
- assert.notEqual(r1.error, '');
784
- const r2 = qcsdk.packCreateContractData(abi, ' ');
785
- assert.notEqual(r2.error, '');
786
- });
787
-
788
- test('packCreateContractData: invalid bytecode returns error', () => {
789
- const abi = JSON.stringify([{ type: 'constructor', inputs: [], stateMutability: 'nonpayable' }]);
790
- const result = qcsdk.packCreateContractData(abi, '0xinvalid');
791
- assert.notEqual(result.error, '');
792
- });
793
-
794
- test('packCreateContractData: argument count mismatch returns error', () => {
795
- const abi = JSON.stringify([{
796
- type: 'constructor',
797
- inputs: [
798
- { name: 'a', type: 'uint256' },
799
- { name: 'b', type: 'uint256' },
800
- ],
801
- stateMutability: 'nonpayable',
802
- }]);
803
- const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
804
- const tooFew = qcsdk.packCreateContractData(abi, bytecode, '1');
805
- assert.notEqual(tooFew.error, '');
806
- const tooMany = qcsdk.packCreateContractData(abi, bytecode, '1', '2', '3');
807
- assert.notEqual(tooMany.error, '');
808
- });
809
-
810
- // --- packMethodData / unpackMethodData extended tests (ported from Go) ---
811
-
812
- test('packMethodData: zero-argument method (name())', () => {
813
- const abi = JSON.stringify([{
814
- name: 'name',
815
- type: 'function',
816
- inputs: [],
817
- outputs: [{ name: '', type: 'string' }],
818
- stateMutability: 'view',
819
- }]);
820
- const result = qcsdk.packMethodData(abi, 'name');
821
- assert.equal(result.error, '');
822
- assert.ok(isHex0x(result.result));
823
- assert.equal(result.result.length, 10, 'zero-arg method should produce 4-byte selector (0x + 8 hex chars)');
824
- });
825
-
826
- test('packMethodData: address[] argument', () => {
827
- const abi = JSON.stringify([{
828
- name: 'getAmountsIn',
829
- type: 'function',
830
- inputs: [
831
- { name: 'amountOut', type: 'uint256' },
832
- { name: 'path', type: 'address[]' },
833
- ],
834
- outputs: [{ name: 'amounts', type: 'uint256[]' }],
835
- stateMutability: 'view',
836
- }]);
837
- const addr1 = '0x0000000000000000000000000000000000000000000000000000000000000001';
838
- const addr2 = '0x0000000000000000000000000000000000000000000000000000000000000002';
839
- const result = qcsdk.packMethodData(abi, 'getAmountsIn', '1000', [addr1, addr2]);
840
- assert.equal(result.error, '');
841
- assert.ok(isHex0x(result.result));
842
- assert.ok(result.result.length > 10);
843
- });
844
-
845
- test('packMethodData: uint256[] argument', () => {
846
- const abi = JSON.stringify([{
847
- name: 'batchTransfer',
848
- type: 'function',
849
- inputs: [{ name: 'amounts', type: 'uint256[]' }],
850
- outputs: [],
851
- stateMutability: 'nonpayable',
852
- }]);
853
- const result = qcsdk.packMethodData(abi, 'batchTransfer', ['100', '200', '300']);
854
- assert.equal(result.error, '');
855
- assert.ok(isHex0x(result.result));
856
- });
857
-
858
- test('packMethodData: mixed arguments (address, uint256, bool)', () => {
859
- const abi = JSON.stringify([{
860
- name: 'doSomething',
861
- type: 'function',
862
- inputs: [
863
- { name: 'to', type: 'address' },
864
- { name: 'amount', type: 'uint256' },
865
- { name: 'flag', type: 'bool' },
866
- ],
867
- outputs: [],
868
- stateMutability: 'nonpayable',
869
- }]);
870
- const addr = '0x0000000000000000000000000000000000000000000000000000000000000001';
871
- const result = qcsdk.packMethodData(abi, 'doSomething', addr, '500', true);
872
- assert.equal(result.error, '');
873
- assert.ok(isHex0x(result.result));
874
- assert.ok(result.result.length > 10);
875
- });
876
-
877
- test('packMethodData: empty method name returns error', () => {
878
- const abi = JSON.stringify([{
879
- name: 'getValue',
880
- type: 'function',
881
- inputs: [],
882
- outputs: [{ name: '', type: 'uint256' }],
883
- }]);
884
- const r1 = qcsdk.packMethodData(abi, '');
885
- assert.notEqual(r1.error, '');
886
- const r2 = qcsdk.packMethodData(abi, ' ');
887
- assert.notEqual(r2.error, '');
888
- });
889
-
890
- test('unpackMethodData: empty method name returns error', () => {
891
- const abi = JSON.stringify([{
892
- name: 'getValue',
893
- type: 'function',
894
- inputs: [],
895
- outputs: [{ name: '', type: 'uint256' }],
896
- }]);
897
- const r1 = qcsdk.unpackMethodData(abi, '', '0x00');
898
- assert.notEqual(r1.error, '');
899
- const r2 = qcsdk.unpackMethodData(abi, ' ', '0x00');
900
- assert.notEqual(r2.error, '');
901
- });
902
-
903
- test('unpackMethodData: non-existent method returns error', () => {
904
- const abi = JSON.stringify([{
905
- name: 'getValue',
906
- type: 'function',
907
- inputs: [],
908
- outputs: [{ name: '', type: 'uint256' }],
909
- }]);
910
- const result = qcsdk.unpackMethodData(abi, 'nonExistentMethod', '0x00');
911
- assert.notEqual(result.error, '');
912
- });
913
-
914
- test('unpackMethodData: invalid hex data returns error', () => {
915
- const abi = JSON.stringify([{
916
- name: 'getValue',
917
- type: 'function',
918
- inputs: [],
919
- outputs: [{ name: '', type: 'uint256' }],
920
- }]);
921
- const result = qcsdk.unpackMethodData(abi, 'getValue', 'invalid hex');
922
- assert.notEqual(result.error, '');
923
- });
924
-
925
- test('packMethodData/unpackMethodData: offline roundtrip with balanceOf', () => {
926
- const abi = JSON.stringify([{
927
- name: 'balanceOf',
928
- type: 'function',
929
- inputs: [{ name: 'account', type: 'address' }],
930
- outputs: [{ name: '', type: 'uint256' }],
931
- stateMutability: 'view',
932
- }]);
933
- const addr = '0x0000000000000000000000000000000000000000000000000000000000000001';
934
- const pack = qcsdk.packMethodData(abi, 'balanceOf', addr);
935
- assert.equal(pack.error, '');
936
- assert.ok(isHex0x(pack.result));
937
- const returnData = '0x' + '00'.repeat(31) + '0a';
938
- const unpack = qcsdk.unpackMethodData(abi, 'balanceOf', returnData);
939
- assert.equal(unpack.error, '');
940
- const parsed = JSON.parse(unpack.result);
941
- assert.ok(Array.isArray(parsed));
942
- assert.equal(parsed[0], '10');
943
- });
944
-
945
- // --- Event log encode/decode extended tests (ported from Go) ---
946
-
947
- test('encodeEventLog: all-indexed event (Approval)', () => {
948
- const abi = JSON.stringify([{
949
- name: 'Approval',
950
- type: 'event',
951
- anonymous: false,
952
- inputs: [
953
- { name: 'owner', type: 'address', indexed: true },
954
- { name: 'spender', type: 'address', indexed: true },
955
- { name: 'value', type: 'uint256', indexed: true },
956
- ],
957
- }]);
958
- const owner = '0x0000000000000000000000000000000000000000000000000000000000000001';
959
- const spender = '0x0000000000000000000000000000000000000000000000000000000000000002';
960
- const value = '1000000000000000000';
961
- const enc = qcsdk.encodeEventLog(abi, 'Approval', owner, spender, value);
962
- assert.equal(enc.error, '');
963
- assert.equal(enc.result.topics.length, 4);
964
- assert.equal(enc.result.data, '0x');
965
- });
966
-
967
- test('encodeEventLog: all-non-indexed event (Received)', () => {
968
- const abi = JSON.stringify([{
969
- name: 'Received',
970
- type: 'event',
971
- anonymous: false,
972
- inputs: [
973
- { name: 'sender', type: 'address', indexed: false },
974
- { name: 'amount', type: 'uint256', indexed: false },
975
- ],
976
- }]);
977
- const sender = '0x0000000000000000000000000000000000000000000000000000000000000001';
978
- const amount = '1000000000000000000';
979
- const enc = qcsdk.encodeEventLog(abi, 'Received', sender, amount);
980
- assert.equal(enc.error, '');
981
- assert.equal(enc.result.topics.length, 1);
982
- assert.ok(enc.result.data !== '' && enc.result.data !== '0x');
983
- });
984
-
985
- test('encodeEventLog: anonymous event has no signature topic', () => {
986
- const abi = JSON.stringify([{
987
- name: 'AnonEvent',
988
- type: 'event',
989
- anonymous: true,
990
- inputs: [
991
- { name: 'value', type: 'uint256', indexed: true },
992
- ],
993
- }]);
994
- const enc = qcsdk.encodeEventLog(abi, 'AnonEvent', '42');
995
- assert.equal(enc.error, '');
996
- assert.equal(enc.result.topics.length, 1, 'anonymous event should have only indexed param topics, no signature');
997
- });
998
-
999
- test('encodeEventLog: invalid event name returns error', () => {
1000
- const abi = JSON.stringify([{
1001
- name: 'Transfer',
1002
- type: 'event',
1003
- anonymous: false,
1004
- inputs: [],
1005
- }]);
1006
- const enc = qcsdk.encodeEventLog(abi, 'NonExistentEvent');
1007
- assert.notEqual(enc.error, '');
1008
- });
1009
-
1010
- test('encodeEventLog: argument count mismatch returns error', () => {
1011
- const abi = JSON.stringify([{
1012
- name: 'Transfer',
1013
- type: 'event',
1014
- anonymous: false,
1015
- inputs: [
1016
- { name: 'from', type: 'address', indexed: true },
1017
- { name: 'to', type: 'address', indexed: true },
1018
- ],
1019
- }]);
1020
- const enc = qcsdk.encodeEventLog(abi, 'Transfer', '0x0000000000000000000000000000000000000000000000000000000000000001');
1021
- assert.notEqual(enc.error, '');
1022
- });
1023
-
1024
- test('decodeEventLog: invalid event name returns error', () => {
1025
- const abi = JSON.stringify([{
1026
- name: 'Transfer',
1027
- type: 'event',
1028
- anonymous: false,
1029
- inputs: [],
1030
- }]);
1031
- const dec = qcsdk.decodeEventLog(abi, 'NonExistentEvent', ['0x00'], '0x');
1032
- assert.notEqual(dec.error, '');
1033
- });
1034
-
1035
- test('decodeEventLog: invalid topic signature returns error', () => {
1036
- const abi = JSON.stringify([{
1037
- name: 'Transfer',
1038
- type: 'event',
1039
- anonymous: false,
1040
- inputs: [
1041
- { name: 'from', type: 'address', indexed: true },
1042
- ],
1043
- }]);
1044
- const wrongTopics = [
1045
- '0x0000000000000000000000000000000000000000000000000000000000000000',
1046
- '0x0000000000000000000000000000000000000000000000000000000000000001',
1047
- ];
1048
- const dec = qcsdk.decodeEventLog(abi, 'Transfer', wrongTopics, '0x');
1049
- assert.notEqual(dec.error, '');
1050
- });
1051
-
1052
- test('encodeEventLog/decodeEventLog: complex roundtrip (2 indexed + 3 non-indexed)', () => {
1053
- const abi = JSON.stringify([{
1054
- name: 'ComplexEvent',
1055
- type: 'event',
1056
- anonymous: false,
1057
- inputs: [
1058
- { name: 'indexedAddr', type: 'address', indexed: true },
1059
- { name: 'indexedValue', type: 'uint256', indexed: true },
1060
- { name: 'nonIndexedAddr', type: 'address', indexed: false },
1061
- { name: 'nonIndexedValue', type: 'uint256', indexed: false },
1062
- { name: 'flag', type: 'bool', indexed: false },
1063
- ],
1064
- }]);
1065
- const indexedAddr = '0x0000000000000000000000000000000000000000000000000000000000000001';
1066
- const indexedValue = '1000000000000000000';
1067
- const nonIndexedAddr = '0x0000000000000000000000000000000000000000000000000000000000000002';
1068
- const nonIndexedValue = '2000000000000000000';
1069
- const flag = true;
1070
-
1071
- const enc = qcsdk.encodeEventLog(abi, 'ComplexEvent', indexedAddr, indexedValue, nonIndexedAddr, nonIndexedValue, flag);
1072
- assert.equal(enc.error, '');
1073
- assert.equal(enc.result.topics.length, 3);
1074
- assert.ok(enc.result.data !== '0x');
1075
-
1076
- const dec = qcsdk.decodeEventLog(abi, 'ComplexEvent', enc.result.topics, enc.result.data);
1077
- assert.equal(dec.error, '');
1078
- const decoded = JSON.parse(dec.result);
1079
- assert.equal(decoded.indexedAddr.toLowerCase(), indexedAddr.toLowerCase());
1080
- assert.equal(decoded.indexedValue, indexedValue);
1081
- assert.equal(decoded.nonIndexedAddr.toLowerCase(), nonIndexedAddr.toLowerCase());
1082
- assert.equal(decoded.nonIndexedValue, nonIndexedValue);
1083
- assert.equal(decoded.flag, true);
1084
- });
1085
-
1086
- // --- RLP encode/decode extended tests (ported from Go) ---
1087
-
1088
- test('encodeRlp/decodeRlp: string roundtrip', () => {
1089
- const enc = qcsdk.encodeRlp('hello');
1090
- assert.equal(enc.error, '');
1091
- assert.ok(isHex0x(enc.result));
1092
- const dec = qcsdk.decodeRlp(enc.result);
1093
- assert.equal(dec.error, '');
1094
- });
1095
-
1096
- test('encodeRlp/decodeRlp: number roundtrip', () => {
1097
- const enc = qcsdk.encodeRlp(42);
1098
- assert.equal(enc.error, '');
1099
- assert.ok(isHex0x(enc.result));
1100
- const dec = qcsdk.decodeRlp(enc.result);
1101
- assert.equal(dec.error, '');
1102
- });
1103
-
1104
- test('encodeRlp/decodeRlp: boolean roundtrip', () => {
1105
- const encTrue = qcsdk.encodeRlp(true);
1106
- assert.equal(encTrue.error, '');
1107
- assert.ok(isHex0x(encTrue.result));
1108
- const decTrue = qcsdk.decodeRlp(encTrue.result);
1109
- assert.equal(decTrue.error, '');
1110
-
1111
- const encFalse = qcsdk.encodeRlp(false);
1112
- assert.equal(encFalse.error, '');
1113
- assert.ok(isHex0x(encFalse.result));
1114
- const decFalse = qcsdk.decodeRlp(encFalse.result);
1115
- assert.equal(decFalse.error, '');
1116
- });
1117
-
1118
- test('encodeRlp/decodeRlp: hex string (0x48656c6c6f = "Hello")', () => {
1119
- const enc = qcsdk.encodeRlp('0x48656c6c6f');
1120
- assert.equal(enc.error, '');
1121
- assert.ok(isHex0x(enc.result));
1122
- const dec = qcsdk.decodeRlp(enc.result);
1123
- assert.equal(dec.error, '');
1124
- });
1125
-
1126
- test('encodeRlp/decodeRlp: empty array', () => {
1127
- const enc = qcsdk.encodeRlp([]);
1128
- assert.equal(enc.error, '');
1129
- assert.ok(isHex0x(enc.result));
1130
- const dec = qcsdk.decodeRlp(enc.result);
1131
- assert.equal(dec.error, '');
1132
- const decoded = JSON.parse(dec.result);
1133
- assert.ok(Array.isArray(decoded));
1134
- assert.equal(decoded.length, 0);
1135
- });
1136
-
1137
- test('encodeRlp/decodeRlp: nested array', () => {
1138
- const enc = qcsdk.encodeRlp([['inner', 1], 'outer']);
1139
- assert.equal(enc.error, '');
1140
- assert.ok(isHex0x(enc.result));
1141
- const dec = qcsdk.decodeRlp(enc.result);
1142
- assert.equal(dec.error, '');
1143
- const decoded = JSON.parse(dec.result);
1144
- assert.ok(Array.isArray(decoded));
1145
- assert.equal(decoded.length, 2);
1146
- assert.ok(Array.isArray(decoded[0]));
1147
- });
1148
-
1149
- test('decodeRlp: empty string input returns error', () => {
1150
- const dec = qcsdk.decodeRlp('');
1151
- assert.notEqual(dec.error, '');
1152
- });
1153
-
1154
- // --- createAddress / createAddress2 extended tests (ported from Go) ---
1155
-
1156
- test('createAddress: different nonces produce different addresses', () => {
1157
- const w = qcsdk.newWallet();
1158
- const addresses = new Set();
1159
- for (let nonce = 0; nonce < 5; nonce++) {
1160
- const addr = qcsdk.createAddress(w.address, nonce);
1161
- assert.ok(addr && isHex0x(addr));
1162
- addresses.add(addr.toLowerCase());
1163
- }
1164
- assert.equal(addresses.size, 5, 'nonces 0-4 should produce 5 distinct addresses');
1165
- });
1166
-
1167
- test('createAddress: different deployer addresses produce different contract addresses', () => {
1168
- const w1 = qcsdk.newWallet();
1169
- const w2 = qcsdk.newWallet();
1170
- const a1 = qcsdk.createAddress(w1.address, 0);
1171
- const a2 = qcsdk.createAddress(w2.address, 0);
1172
- assert.ok(a1 && a2);
1173
- assert.notEqual(a1.toLowerCase(), a2.toLowerCase());
1174
- });
1175
-
1176
- test('createAddress2: different salts produce different addresses', () => {
1177
- const w = qcsdk.newWallet();
1178
- const initHash = '0x' + '11'.repeat(32);
1179
- const salt1 = '0x' + '01'.repeat(32);
1180
- const salt2 = '0x' + '02'.repeat(32);
1181
- const a1 = qcsdk.createAddress2(w.address, salt1, initHash);
1182
- const a2 = qcsdk.createAddress2(w.address, salt2, initHash);
1183
- assert.ok(a1 && a2);
1184
- assert.notEqual(a1.toLowerCase(), a2.toLowerCase());
1185
- });
1186
-
1187
- test('createAddress2: different initHashes produce different addresses', () => {
1188
- const w = qcsdk.newWallet();
1189
- const salt = '0x' + '22'.repeat(32);
1190
- const initHash1 = '0x' + '11'.repeat(32);
1191
- const initHash2 = '0x' + '33'.repeat(32);
1192
- const a1 = qcsdk.createAddress2(w.address, salt, initHash1);
1193
- const a2 = qcsdk.createAddress2(w.address, salt, initHash2);
1194
- assert.ok(a1 && a2);
1195
- assert.notEqual(a1.toLowerCase(), a2.toLowerCase());
1196
- });
1197
-
1198
- test('contract address calculation: createAddress + createAddress2 basic validity and determinism', () => {
1199
- const w = qcsdk.newWallet();
1200
- const a0 = qcsdk.createAddress(w.address, 0);
1201
- const a0b = qcsdk.createAddress(w.address, 0);
1202
- const a1 = qcsdk.createAddress(w.address, 1);
1203
- assert.ok(a0 && typeof a0 === 'string');
1204
- assert.ok(isHex0x(a0));
1205
- assert.equal(a0, a0b);
1206
- assert.notEqual(a0, a1);
1207
-
1208
- // CREATE2
1209
- const salt = '0x' + '22'.repeat(32);
1210
- const initHash = '0x' + '11'.repeat(32);
1211
- const c2a = qcsdk.createAddress2(w.address, salt, initHash);
1212
- const c2b = qcsdk.createAddress2(w.address, salt, initHash);
1213
- assert.ok(c2a && isHex0x(c2a));
1214
- assert.equal(c2a, c2b);
1215
-
1216
- // Negative: invalid nonce type / invalid params
1217
- assert.equal(qcsdk.createAddress(w.address, '0'), null);
1218
- assert.equal(qcsdk.createAddress2(null, salt, initHash), null);
1219
- });
1220
-
1221
- test('signing: signSendCoinTransaction and signRawTransaction validate inputs and produce tx data', async () => {
1222
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
1223
- const wallet = qcsdk.newWallet();
1224
- assert.ok(wallet);
1225
-
1226
- const signSend = await qcsdk.signSendCoinTransaction(wallet, TO_ADDRESS_EXAMPLE, '0', 0);
1227
- assert.equal(signSend.resultCode, 0);
1228
- assert.ok(isHex0x(signSend.txnHash));
1229
- assert.ok(isHex0x(signSend.txnData));
1230
-
1231
- const txReq = new qcsdk.TransactionSigningRequest(
1232
- wallet,
1233
- TO_ADDRESS_EXAMPLE,
1234
- '0x0',
1235
- 0,
1236
- null,
1237
- 21000,
1238
- null,
1239
- MAINNET_CHAIN_ID,
1240
- );
1241
- const signRaw = qcsdk.signRawTransaction(txReq);
1242
- assert.equal(signRaw.resultCode, 0);
1243
- assert.ok(isHex0x(signRaw.txnHash));
1244
- assert.ok(isHex0x(signRaw.txnData));
1245
-
1246
- // Negative: invalid to address and invalid remarks length
1247
- const signSendBad = await qcsdk.signSendCoinTransaction(wallet, 'bad', '1', 0);
1248
- assert.notEqual(signSendBad.resultCode, 0);
1249
-
1250
- const longRemarks = '0x' + 'aa'.repeat(33); // > 32 bytes
1251
- const txReqBad = new qcsdk.TransactionSigningRequest(
1252
- wallet,
1253
- TO_ADDRESS_EXAMPLE,
1254
- '0x0',
1255
- 0,
1256
- null,
1257
- 21000,
1258
- longRemarks,
1259
- MAINNET_CHAIN_ID,
1260
- );
1261
- const signRawBad = qcsdk.signRawTransaction(txReqBad);
1262
- assert.notEqual(signRawBad.resultCode, 0);
1263
- });
1264
-
1265
- // ---------------------------------------------------------------------------
1266
- // Security-fix negative coverage
1267
- // ---------------------------------------------------------------------------
1268
-
1269
- test('security: deserializeWallet returns null on malformed JSON (no thrown exception)', () => {
1270
- const garbage = [
1271
- '{bad json',
1272
- '',
1273
- 'null',
1274
- '42',
1275
- '{"address":"abc"',
1276
- undefined,
1277
- ];
1278
- for (const input of garbage) {
1279
- const result = qcsdk.deserializeWallet(input);
1280
- assert.ok(
1281
- result === null || result === -1000,
1282
- `deserializeWallet(${JSON.stringify(input)}) should return null or -1000, got ${result}`,
1283
- );
1284
- }
1285
- });
1286
-
1287
- test('security: signRawTransaction rejects invalid hex in valueInWei', () => {
1288
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
1289
- const wallet = qcsdk.newWallet();
1290
- const txReq = new qcsdk.TransactionSigningRequest(
1291
- wallet, TO_ADDRESS_EXAMPLE, '0xZZZZ', 0, null, 21000, null, MAINNET_CHAIN_ID,
1292
- );
1293
- const res = qcsdk.signRawTransaction(txReq);
1294
- assert.equal(res.resultCode, -903, 'invalid hex valueInWei must return -903');
1295
- });
1296
-
1297
- test('security: signRawTransaction rejects invalid hex in data', () => {
1298
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
1299
- const wallet = qcsdk.newWallet();
1300
- const txReq = new qcsdk.TransactionSigningRequest(
1301
- wallet, TO_ADDRESS_EXAMPLE, '0x0', 0, '0xGGGG', 21000, null, MAINNET_CHAIN_ID,
1302
- );
1303
- const res = qcsdk.signRawTransaction(txReq);
1304
- assert.equal(res.resultCode, -906, 'invalid hex data must return -906');
1305
- });
1306
-
1307
- test('security: signRawTransaction rejects invalid hex in remarks', () => {
1308
- assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
1309
- const wallet = qcsdk.newWallet();
1310
- const txReq = new qcsdk.TransactionSigningRequest(
1311
- wallet, TO_ADDRESS_EXAMPLE, '0x0', 0, null, 21000, '0xZZZZ', MAINNET_CHAIN_ID,
1312
- );
1313
- const res = qcsdk.signRawTransaction(txReq);
1314
- assert.equal(res.resultCode, -909, 'invalid hex remarks must return -909');
1315
- });
1316
-
1317
- });
1318
-