quantum-coin-js-sdk 2.0.1 → 2.1.1

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 (233) 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/.gitignore +0 -4
  7. package/.idea/.name +0 -1
  8. package/.idea/modules.xml +0 -8
  9. package/.idea/quantum-coin-js-sdk.iml +0 -12
  10. package/.idea/vcs.xml +0 -6
  11. package/.vs/ProjectSettings.json +0 -3
  12. package/.vs/VSWorkspaceState.json +0 -8
  13. package/.vs/quantum-coin-js-sdk/FileContentIndex/a9d6de82-cfc3-4c22-ac38-06d706ff3673.vsidx +0 -0
  14. package/.vs/quantum-coin-js-sdk/FileContentIndex/fdc816df-1898-4153-99f2-c69ef4c2283b.vsidx +0 -0
  15. package/.vs/quantum-coin-js-sdk/config/applicationhost.config +0 -1011
  16. package/.vs/quantum-coin-js-sdk/v17/.wsuo +0 -0
  17. package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.backup.json +0 -39
  18. package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.json +0 -57
  19. package/.vs/slnx.sqlite +0 -0
  20. package/example/README.md +0 -14
  21. package/example/conversion-example.js +0 -19
  22. package/example/example-create-contract.js +0 -396
  23. package/example/example-encode-decode-rlp.js +0 -225
  24. package/example/example-event-pack-unpack.js +0 -391
  25. package/example/example-misc.js +0 -96
  26. package/example/example-token-pack-unpack.js +0 -960
  27. package/example/example-wallet-version4.js +0 -34
  28. package/example/example-wallet.js +0 -39
  29. package/example/example.js +0 -115
  30. package/example/node_modules/.bin/sdkgen +0 -16
  31. package/example/node_modules/.bin/sdkgen.cmd +0 -17
  32. package/example/node_modules/.bin/sdkgen.ps1 +0 -28
  33. package/example/node_modules/.package-lock.json +0 -51
  34. package/example/node_modules/quantumcoin/.github/workflows/publish-npmjs.yaml +0 -22
  35. package/example/node_modules/quantumcoin/LICENSE +0 -21
  36. package/example/node_modules/quantumcoin/README-SDK.md +0 -828
  37. package/example/node_modules/quantumcoin/README.md +0 -197
  38. package/example/node_modules/quantumcoin/config.d.ts +0 -50
  39. package/example/node_modules/quantumcoin/config.js +0 -123
  40. package/example/node_modules/quantumcoin/examples/AllSolidityTypes.sol +0 -184
  41. package/example/node_modules/quantumcoin/examples/SimpleIERC20.sol +0 -74
  42. package/example/node_modules/quantumcoin/examples/events.js +0 -41
  43. package/example/node_modules/quantumcoin/examples/events.ts +0 -35
  44. package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.js +0 -100
  45. package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.ts +0 -77
  46. package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.js +0 -100
  47. package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.ts +0 -77
  48. package/example/node_modules/quantumcoin/examples/example.js +0 -67
  49. package/example/node_modules/quantumcoin/examples/example.ts +0 -56
  50. package/example/node_modules/quantumcoin/examples/offline-signing.js +0 -77
  51. package/example/node_modules/quantumcoin/examples/offline-signing.ts +0 -65
  52. package/example/node_modules/quantumcoin/examples/package-lock.json +0 -596
  53. package/example/node_modules/quantumcoin/examples/package.json +0 -32
  54. package/example/node_modules/quantumcoin/examples/read-operations.js +0 -32
  55. package/example/node_modules/quantumcoin/examples/read-operations.ts +0 -31
  56. package/example/node_modules/quantumcoin/examples/sdk-generator-erc20.inline.json +0 -251
  57. package/example/node_modules/quantumcoin/examples/solidity-types.ts +0 -43
  58. package/example/node_modules/quantumcoin/examples/wallet-offline.js +0 -36
  59. package/example/node_modules/quantumcoin/examples/wallet-offline.ts +0 -26
  60. package/example/node_modules/quantumcoin/generate-sdk.js +0 -1846
  61. package/example/node_modules/quantumcoin/index.js +0 -12
  62. package/example/node_modules/quantumcoin/package.json +0 -95
  63. package/example/node_modules/quantumcoin/scripts/copy-declarations.js +0 -31
  64. package/example/node_modules/quantumcoin/scripts/run-all-one-by-one.js +0 -151
  65. package/example/node_modules/quantumcoin/src/abi/fragments.d.ts +0 -42
  66. package/example/node_modules/quantumcoin/src/abi/fragments.js +0 -63
  67. package/example/node_modules/quantumcoin/src/abi/index.d.ts +0 -13
  68. package/example/node_modules/quantumcoin/src/abi/index.js +0 -9
  69. package/example/node_modules/quantumcoin/src/abi/interface.d.ts +0 -128
  70. package/example/node_modules/quantumcoin/src/abi/interface.js +0 -605
  71. package/example/node_modules/quantumcoin/src/abi/js-abi-coder.d.ts +0 -8
  72. package/example/node_modules/quantumcoin/src/abi/js-abi-coder.js +0 -538
  73. package/example/node_modules/quantumcoin/src/constants.d.ts +0 -61
  74. package/example/node_modules/quantumcoin/src/constants.js +0 -94
  75. package/example/node_modules/quantumcoin/src/contract/contract-factory.d.ts +0 -28
  76. package/example/node_modules/quantumcoin/src/contract/contract-factory.js +0 -111
  77. package/example/node_modules/quantumcoin/src/contract/contract.d.ts +0 -113
  78. package/example/node_modules/quantumcoin/src/contract/contract.js +0 -408
  79. package/example/node_modules/quantumcoin/src/contract/index.d.ts +0 -9
  80. package/example/node_modules/quantumcoin/src/contract/index.js +0 -9
  81. package/example/node_modules/quantumcoin/src/errors/index.d.ts +0 -92
  82. package/example/node_modules/quantumcoin/src/errors/index.js +0 -200
  83. package/example/node_modules/quantumcoin/src/generator/index.d.ts +0 -81
  84. package/example/node_modules/quantumcoin/src/generator/index.js +0 -1571
  85. package/example/node_modules/quantumcoin/src/index.d.ts +0 -122
  86. package/example/node_modules/quantumcoin/src/index.js +0 -41
  87. package/example/node_modules/quantumcoin/src/internal/hex.d.ts +0 -68
  88. package/example/node_modules/quantumcoin/src/internal/hex.js +0 -180
  89. package/example/node_modules/quantumcoin/src/providers/extra-providers.d.ts +0 -139
  90. package/example/node_modules/quantumcoin/src/providers/extra-providers.js +0 -614
  91. package/example/node_modules/quantumcoin/src/providers/index.d.ts +0 -17
  92. package/example/node_modules/quantumcoin/src/providers/index.js +0 -10
  93. package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.d.ts +0 -12
  94. package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.js +0 -89
  95. package/example/node_modules/quantumcoin/src/providers/provider.d.ts +0 -206
  96. package/example/node_modules/quantumcoin/src/providers/provider.js +0 -524
  97. package/example/node_modules/quantumcoin/src/types/index.d.ts +0 -214
  98. package/example/node_modules/quantumcoin/src/types/index.js +0 -9
  99. package/example/node_modules/quantumcoin/src/utils/address.d.ts +0 -58
  100. package/example/node_modules/quantumcoin/src/utils/address.js +0 -144
  101. package/example/node_modules/quantumcoin/src/utils/encoding.d.ts +0 -120
  102. package/example/node_modules/quantumcoin/src/utils/encoding.js +0 -306
  103. package/example/node_modules/quantumcoin/src/utils/fixednumber.d.ts +0 -57
  104. package/example/node_modules/quantumcoin/src/utils/fixednumber.js +0 -366
  105. package/example/node_modules/quantumcoin/src/utils/hashing.d.ts +0 -76
  106. package/example/node_modules/quantumcoin/src/utils/hashing.js +0 -298
  107. package/example/node_modules/quantumcoin/src/utils/index.d.ts +0 -63
  108. package/example/node_modules/quantumcoin/src/utils/index.js +0 -14
  109. package/example/node_modules/quantumcoin/src/utils/result.d.ts +0 -57
  110. package/example/node_modules/quantumcoin/src/utils/result.js +0 -128
  111. package/example/node_modules/quantumcoin/src/utils/rlp.d.ts +0 -12
  112. package/example/node_modules/quantumcoin/src/utils/rlp.js +0 -215
  113. package/example/node_modules/quantumcoin/src/utils/units.d.ts +0 -29
  114. package/example/node_modules/quantumcoin/src/utils/units.js +0 -107
  115. package/example/node_modules/quantumcoin/src/wallet/index.d.ts +0 -10
  116. package/example/node_modules/quantumcoin/src/wallet/index.js +0 -8
  117. package/example/node_modules/quantumcoin/src/wallet/wallet.d.ts +0 -192
  118. package/example/node_modules/quantumcoin/src/wallet/wallet.js +0 -713
  119. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.js +0 -207
  120. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.ts +0 -191
  121. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.fixtures.js +0 -231
  122. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +0 -387
  123. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +0 -350
  124. package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.js +0 -165
  125. package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.ts +0 -160
  126. package/example/node_modules/quantumcoin/test/e2e/helpers.js +0 -59
  127. package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.js +0 -141
  128. package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.ts +0 -128
  129. package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.js +0 -168
  130. package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +0 -141
  131. package/example/node_modules/quantumcoin/test/e2e/transactional.test.js +0 -245
  132. package/example/node_modules/quantumcoin/test/e2e/transactional.test.ts +0 -208
  133. package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.js +0 -407
  134. package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.ts +0 -337
  135. package/example/node_modules/quantumcoin/test/fixtures/ConstructorParam.sol +0 -23
  136. package/example/node_modules/quantumcoin/test/fixtures/MultiContracts.sol +0 -37
  137. package/example/node_modules/quantumcoin/test/fixtures/SimpleStorage.sol +0 -18
  138. package/example/node_modules/quantumcoin/test/fixtures/StakingContract.abi.json +0 -1
  139. package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.js +0 -49
  140. package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.ts +0 -44
  141. package/example/node_modules/quantumcoin/test/integration/provider.test.js +0 -88
  142. package/example/node_modules/quantumcoin/test/integration/provider.test.ts +0 -85
  143. package/example/node_modules/quantumcoin/test/integration/ws-provider.test.js +0 -41
  144. package/example/node_modules/quantumcoin/test/integration/ws-provider.test.ts +0 -38
  145. package/example/node_modules/quantumcoin/test/security/abi-decoder-bounds.test.js +0 -122
  146. package/example/node_modules/quantumcoin/test/security/contract-overrides.test.js +0 -112
  147. package/example/node_modules/quantumcoin/test/security/generator-injection.test.js +0 -195
  148. package/example/node_modules/quantumcoin/test/security/malformed-input.test.js +0 -330
  149. package/example/node_modules/quantumcoin/test/security/malformed-input.test.ts +0 -35
  150. package/example/node_modules/quantumcoin/test/security/rpc-numeric-bounds.test.js +0 -81
  151. package/example/node_modules/quantumcoin/test/security/rpc-trust.test.js +0 -202
  152. package/example/node_modules/quantumcoin/test/unit/_encrypted-output.txt +0 -6
  153. package/example/node_modules/quantumcoin/test/unit/_log-encrypted-jsons.js +0 -45
  154. package/example/node_modules/quantumcoin/test/unit/_write-keystore-fixture.js +0 -16
  155. package/example/node_modules/quantumcoin/test/unit/abi-interface.test.js +0 -110
  156. package/example/node_modules/quantumcoin/test/unit/abi-interface.test.ts +0 -109
  157. package/example/node_modules/quantumcoin/test/unit/address-wallet.test.js +0 -923
  158. package/example/node_modules/quantumcoin/test/unit/address-wallet.test.ts +0 -877
  159. package/example/node_modules/quantumcoin/test/unit/browser-provider.test.js +0 -85
  160. package/example/node_modules/quantumcoin/test/unit/browser-provider.test.ts +0 -79
  161. package/example/node_modules/quantumcoin/test/unit/contract.test.js +0 -85
  162. package/example/node_modules/quantumcoin/test/unit/contract.test.ts +0 -83
  163. package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.js +0 -127
  164. package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.ts +0 -91
  165. package/example/node_modules/quantumcoin/test/unit/errors.test.js +0 -77
  166. package/example/node_modules/quantumcoin/test/unit/errors.test.ts +0 -76
  167. package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.js +0 -55
  168. package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.ts +0 -54
  169. package/example/node_modules/quantumcoin/test/unit/fixednumber.test.js +0 -656
  170. package/example/node_modules/quantumcoin/test/unit/fixednumber.test.ts +0 -660
  171. package/example/node_modules/quantumcoin/test/unit/fixtures/encrypted-keystores-48-32-36.js +0 -9
  172. package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.js +0 -42
  173. package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.ts +0 -41
  174. package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.js +0 -113
  175. package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.ts +0 -110
  176. package/example/node_modules/quantumcoin/test/unit/generator.test.js +0 -149
  177. package/example/node_modules/quantumcoin/test/unit/generator.test.ts +0 -148
  178. package/example/node_modules/quantumcoin/test/unit/hashing.test.js +0 -64
  179. package/example/node_modules/quantumcoin/test/unit/hashing.test.ts +0 -63
  180. package/example/node_modules/quantumcoin/test/unit/init.test.js +0 -39
  181. package/example/node_modules/quantumcoin/test/unit/init.test.ts +0 -38
  182. package/example/node_modules/quantumcoin/test/unit/interface.test.js +0 -56
  183. package/example/node_modules/quantumcoin/test/unit/interface.test.ts +0 -54
  184. package/example/node_modules/quantumcoin/test/unit/internal-hex.test.js +0 -81
  185. package/example/node_modules/quantumcoin/test/unit/internal-hex.test.ts +0 -80
  186. package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.js +0 -98
  187. package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.ts +0 -64
  188. package/example/node_modules/quantumcoin/test/unit/providers.test.js +0 -252
  189. package/example/node_modules/quantumcoin/test/unit/providers.test.ts +0 -251
  190. package/example/node_modules/quantumcoin/test/unit/result.test.js +0 -80
  191. package/example/node_modules/quantumcoin/test/unit/result.test.ts +0 -79
  192. package/example/node_modules/quantumcoin/test/unit/solidity-types.test.js +0 -49
  193. package/example/node_modules/quantumcoin/test/unit/solidity-types.test.ts +0 -39
  194. package/example/node_modules/quantumcoin/test/unit/utils.test.js +0 -57
  195. package/example/node_modules/quantumcoin/test/unit/utils.test.ts +0 -56
  196. package/example/node_modules/quantumcoin/test/verbose-logger.js +0 -74
  197. package/example/node_modules/quantumcoin/tsconfig.build.json +0 -14
  198. package/example/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +0 -22
  199. package/example/node_modules/seed-words/BUILD.md +0 -7
  200. package/example/node_modules/seed-words/LICENSE +0 -121
  201. package/example/node_modules/seed-words/README.md +0 -67
  202. package/example/node_modules/seed-words/dist/seedwords.d.ts +0 -39
  203. package/example/node_modules/seed-words/package.json +0 -27
  204. package/example/node_modules/seed-words/seedwords.js +0 -315
  205. package/example/node_modules/seed-words/seedwords.txt +0 -65536
  206. package/example/node_modules/seed-words/tsconfig.json +0 -21
  207. package/example/package-lock.json +0 -60
  208. package/example/package.json +0 -15
  209. package/scripts/build-browser-tests.js +0 -29
  210. package/scripts/build-wasm.js +0 -85
  211. package/tests/browser/bundle.js +0 -97643
  212. package/tests/browser/entry.js +0 -57
  213. package/tests/browser/harness.html +0 -20
  214. package/tests/browser/run-browser.js +0 -50
  215. package/tests/encrypted-32.json +0 -1
  216. package/tests/encrypted-36.json +0 -1
  217. package/tests/encrypted-48.json +0 -1
  218. package/tests/generate-verify-vectors.js +0 -88
  219. package/tests/get-gas-price.test.js +0 -59
  220. package/tests/hashing.test.js +0 -34
  221. package/tests/non-transactional.preinit.test.js +0 -33
  222. package/tests/non-transactional.test.js +0 -1318
  223. package/tests/sign-raw-keytype5-context-null.test.js +0 -105
  224. package/tests/sign-raw-transaction.test.js +0 -194
  225. package/tests/sign-verify.test.js +0 -308
  226. package/tests/specs/assert.js +0 -74
  227. package/tests/specs/crypto.spec.js +0 -104
  228. package/tests/specs/hex.js +0 -31
  229. package/tests/specs/preinit.spec.js +0 -19
  230. package/tests/specs/sign.spec.js +0 -90
  231. package/tests/specs/wallet.spec.js +0 -98
  232. package/tests/transactional.rpc.test.js +0 -102
  233. 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
-