quantum-coin-js-sdk 1.0.39 → 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 (226) hide show
  1. package/.gitignore +2 -1
  2. package/README.md +109 -768
  3. package/index.d.ts +76 -545
  4. package/index.js +319 -1194
  5. package/package.json +20 -5
  6. package/wasmBase64.js +7 -16
  7. package/wasm_exec.js +575 -587
  8. package/.idea/.name +0 -1
  9. package/.idea/modules.xml +0 -8
  10. package/.idea/quantum-coin-js-sdk.iml +0 -12
  11. package/.idea/vcs.xml +0 -6
  12. package/.vs/ProjectSettings.json +0 -3
  13. package/.vs/VSWorkspaceState.json +0 -8
  14. package/.vs/quantum-coin-js-sdk/FileContentIndex/a9d6de82-cfc3-4c22-ac38-06d706ff3673.vsidx +0 -0
  15. package/.vs/quantum-coin-js-sdk/FileContentIndex/fdc816df-1898-4153-99f2-c69ef4c2283b.vsidx +0 -0
  16. package/.vs/quantum-coin-js-sdk/config/applicationhost.config +0 -1011
  17. package/.vs/quantum-coin-js-sdk/v17/.wsuo +0 -0
  18. package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.backup.json +0 -39
  19. package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.json +0 -57
  20. package/.vs/slnx.sqlite +0 -0
  21. package/example/README.md +0 -14
  22. package/example/conversion-example.js +0 -19
  23. package/example/example-create-contract.js +0 -396
  24. package/example/example-encode-decode-rlp.js +0 -225
  25. package/example/example-event-pack-unpack.js +0 -391
  26. package/example/example-misc.js +0 -100
  27. package/example/example-rpc-send-signRawTransaction.js +0 -318
  28. package/example/example-rpc-send.js +0 -115
  29. package/example/example-send.js +0 -69
  30. package/example/example-token-pack-unpack.js +0 -960
  31. package/example/example-wallet-version4.js +0 -34
  32. package/example/example-wallet.js +0 -43
  33. package/example/example.js +0 -405
  34. package/example/node_modules/.bin/sdkgen +0 -16
  35. package/example/node_modules/.bin/sdkgen.cmd +0 -17
  36. package/example/node_modules/.bin/sdkgen.ps1 +0 -28
  37. package/example/node_modules/.package-lock.json +0 -47
  38. package/example/node_modules/quantumcoin/.github/workflows/publish-npmjs.yaml +0 -22
  39. package/example/node_modules/quantumcoin/LICENSE +0 -21
  40. package/example/node_modules/quantumcoin/README-SDK.md +0 -828
  41. package/example/node_modules/quantumcoin/README.md +0 -197
  42. package/example/node_modules/quantumcoin/config.d.ts +0 -50
  43. package/example/node_modules/quantumcoin/config.js +0 -123
  44. package/example/node_modules/quantumcoin/examples/AllSolidityTypes.sol +0 -184
  45. package/example/node_modules/quantumcoin/examples/SimpleIERC20.sol +0 -74
  46. package/example/node_modules/quantumcoin/examples/events.js +0 -41
  47. package/example/node_modules/quantumcoin/examples/events.ts +0 -35
  48. package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.js +0 -100
  49. package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.ts +0 -77
  50. package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.js +0 -100
  51. package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.ts +0 -77
  52. package/example/node_modules/quantumcoin/examples/example.js +0 -67
  53. package/example/node_modules/quantumcoin/examples/example.ts +0 -56
  54. package/example/node_modules/quantumcoin/examples/offline-signing.js +0 -77
  55. package/example/node_modules/quantumcoin/examples/offline-signing.ts +0 -65
  56. package/example/node_modules/quantumcoin/examples/package-lock.json +0 -596
  57. package/example/node_modules/quantumcoin/examples/package.json +0 -32
  58. package/example/node_modules/quantumcoin/examples/read-operations.js +0 -32
  59. package/example/node_modules/quantumcoin/examples/read-operations.ts +0 -31
  60. package/example/node_modules/quantumcoin/examples/sdk-generator-erc20.inline.json +0 -251
  61. package/example/node_modules/quantumcoin/examples/solidity-types.ts +0 -43
  62. package/example/node_modules/quantumcoin/examples/wallet-offline.js +0 -36
  63. package/example/node_modules/quantumcoin/examples/wallet-offline.ts +0 -26
  64. package/example/node_modules/quantumcoin/generate-sdk.js +0 -1846
  65. package/example/node_modules/quantumcoin/index.js +0 -12
  66. package/example/node_modules/quantumcoin/package.json +0 -95
  67. package/example/node_modules/quantumcoin/scripts/copy-declarations.js +0 -31
  68. package/example/node_modules/quantumcoin/scripts/run-all-one-by-one.js +0 -151
  69. package/example/node_modules/quantumcoin/src/abi/fragments.d.ts +0 -42
  70. package/example/node_modules/quantumcoin/src/abi/fragments.js +0 -63
  71. package/example/node_modules/quantumcoin/src/abi/index.d.ts +0 -13
  72. package/example/node_modules/quantumcoin/src/abi/index.js +0 -9
  73. package/example/node_modules/quantumcoin/src/abi/interface.d.ts +0 -128
  74. package/example/node_modules/quantumcoin/src/abi/interface.js +0 -605
  75. package/example/node_modules/quantumcoin/src/abi/js-abi-coder.d.ts +0 -8
  76. package/example/node_modules/quantumcoin/src/abi/js-abi-coder.js +0 -538
  77. package/example/node_modules/quantumcoin/src/constants.d.ts +0 -61
  78. package/example/node_modules/quantumcoin/src/constants.js +0 -94
  79. package/example/node_modules/quantumcoin/src/contract/contract-factory.d.ts +0 -28
  80. package/example/node_modules/quantumcoin/src/contract/contract-factory.js +0 -111
  81. package/example/node_modules/quantumcoin/src/contract/contract.d.ts +0 -113
  82. package/example/node_modules/quantumcoin/src/contract/contract.js +0 -408
  83. package/example/node_modules/quantumcoin/src/contract/index.d.ts +0 -9
  84. package/example/node_modules/quantumcoin/src/contract/index.js +0 -9
  85. package/example/node_modules/quantumcoin/src/errors/index.d.ts +0 -92
  86. package/example/node_modules/quantumcoin/src/errors/index.js +0 -200
  87. package/example/node_modules/quantumcoin/src/generator/index.d.ts +0 -81
  88. package/example/node_modules/quantumcoin/src/generator/index.js +0 -1571
  89. package/example/node_modules/quantumcoin/src/index.d.ts +0 -122
  90. package/example/node_modules/quantumcoin/src/index.js +0 -41
  91. package/example/node_modules/quantumcoin/src/internal/hex.d.ts +0 -68
  92. package/example/node_modules/quantumcoin/src/internal/hex.js +0 -180
  93. package/example/node_modules/quantumcoin/src/providers/extra-providers.d.ts +0 -139
  94. package/example/node_modules/quantumcoin/src/providers/extra-providers.js +0 -614
  95. package/example/node_modules/quantumcoin/src/providers/index.d.ts +0 -17
  96. package/example/node_modules/quantumcoin/src/providers/index.js +0 -10
  97. package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.d.ts +0 -12
  98. package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.js +0 -89
  99. package/example/node_modules/quantumcoin/src/providers/provider.d.ts +0 -206
  100. package/example/node_modules/quantumcoin/src/providers/provider.js +0 -524
  101. package/example/node_modules/quantumcoin/src/types/index.d.ts +0 -214
  102. package/example/node_modules/quantumcoin/src/types/index.js +0 -9
  103. package/example/node_modules/quantumcoin/src/utils/address.d.ts +0 -58
  104. package/example/node_modules/quantumcoin/src/utils/address.js +0 -144
  105. package/example/node_modules/quantumcoin/src/utils/encoding.d.ts +0 -120
  106. package/example/node_modules/quantumcoin/src/utils/encoding.js +0 -306
  107. package/example/node_modules/quantumcoin/src/utils/fixednumber.d.ts +0 -57
  108. package/example/node_modules/quantumcoin/src/utils/fixednumber.js +0 -366
  109. package/example/node_modules/quantumcoin/src/utils/hashing.d.ts +0 -76
  110. package/example/node_modules/quantumcoin/src/utils/hashing.js +0 -298
  111. package/example/node_modules/quantumcoin/src/utils/index.d.ts +0 -63
  112. package/example/node_modules/quantumcoin/src/utils/index.js +0 -14
  113. package/example/node_modules/quantumcoin/src/utils/result.d.ts +0 -57
  114. package/example/node_modules/quantumcoin/src/utils/result.js +0 -128
  115. package/example/node_modules/quantumcoin/src/utils/rlp.d.ts +0 -12
  116. package/example/node_modules/quantumcoin/src/utils/rlp.js +0 -215
  117. package/example/node_modules/quantumcoin/src/utils/units.d.ts +0 -29
  118. package/example/node_modules/quantumcoin/src/utils/units.js +0 -107
  119. package/example/node_modules/quantumcoin/src/wallet/index.d.ts +0 -10
  120. package/example/node_modules/quantumcoin/src/wallet/index.js +0 -8
  121. package/example/node_modules/quantumcoin/src/wallet/wallet.d.ts +0 -192
  122. package/example/node_modules/quantumcoin/src/wallet/wallet.js +0 -713
  123. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.js +0 -207
  124. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.ts +0 -191
  125. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.fixtures.js +0 -231
  126. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +0 -387
  127. package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +0 -350
  128. package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.js +0 -165
  129. package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.ts +0 -160
  130. package/example/node_modules/quantumcoin/test/e2e/helpers.js +0 -59
  131. package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.js +0 -141
  132. package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.ts +0 -128
  133. package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.js +0 -168
  134. package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +0 -141
  135. package/example/node_modules/quantumcoin/test/e2e/transactional.test.js +0 -245
  136. package/example/node_modules/quantumcoin/test/e2e/transactional.test.ts +0 -208
  137. package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.js +0 -407
  138. package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.ts +0 -337
  139. package/example/node_modules/quantumcoin/test/fixtures/ConstructorParam.sol +0 -23
  140. package/example/node_modules/quantumcoin/test/fixtures/MultiContracts.sol +0 -37
  141. package/example/node_modules/quantumcoin/test/fixtures/SimpleStorage.sol +0 -18
  142. package/example/node_modules/quantumcoin/test/fixtures/StakingContract.abi.json +0 -1
  143. package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.js +0 -49
  144. package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.ts +0 -44
  145. package/example/node_modules/quantumcoin/test/integration/provider.test.js +0 -88
  146. package/example/node_modules/quantumcoin/test/integration/provider.test.ts +0 -85
  147. package/example/node_modules/quantumcoin/test/integration/ws-provider.test.js +0 -41
  148. package/example/node_modules/quantumcoin/test/integration/ws-provider.test.ts +0 -38
  149. package/example/node_modules/quantumcoin/test/security/abi-decoder-bounds.test.js +0 -122
  150. package/example/node_modules/quantumcoin/test/security/contract-overrides.test.js +0 -112
  151. package/example/node_modules/quantumcoin/test/security/generator-injection.test.js +0 -195
  152. package/example/node_modules/quantumcoin/test/security/malformed-input.test.js +0 -330
  153. package/example/node_modules/quantumcoin/test/security/malformed-input.test.ts +0 -35
  154. package/example/node_modules/quantumcoin/test/security/rpc-numeric-bounds.test.js +0 -81
  155. package/example/node_modules/quantumcoin/test/security/rpc-trust.test.js +0 -202
  156. package/example/node_modules/quantumcoin/test/unit/_encrypted-output.txt +0 -6
  157. package/example/node_modules/quantumcoin/test/unit/_log-encrypted-jsons.js +0 -45
  158. package/example/node_modules/quantumcoin/test/unit/_write-keystore-fixture.js +0 -16
  159. package/example/node_modules/quantumcoin/test/unit/abi-interface.test.js +0 -110
  160. package/example/node_modules/quantumcoin/test/unit/abi-interface.test.ts +0 -109
  161. package/example/node_modules/quantumcoin/test/unit/address-wallet.test.js +0 -923
  162. package/example/node_modules/quantumcoin/test/unit/address-wallet.test.ts +0 -877
  163. package/example/node_modules/quantumcoin/test/unit/browser-provider.test.js +0 -85
  164. package/example/node_modules/quantumcoin/test/unit/browser-provider.test.ts +0 -79
  165. package/example/node_modules/quantumcoin/test/unit/contract.test.js +0 -85
  166. package/example/node_modules/quantumcoin/test/unit/contract.test.ts +0 -83
  167. package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.js +0 -127
  168. package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.ts +0 -91
  169. package/example/node_modules/quantumcoin/test/unit/errors.test.js +0 -77
  170. package/example/node_modules/quantumcoin/test/unit/errors.test.ts +0 -76
  171. package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.js +0 -55
  172. package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.ts +0 -54
  173. package/example/node_modules/quantumcoin/test/unit/fixednumber.test.js +0 -656
  174. package/example/node_modules/quantumcoin/test/unit/fixednumber.test.ts +0 -660
  175. package/example/node_modules/quantumcoin/test/unit/fixtures/encrypted-keystores-48-32-36.js +0 -9
  176. package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.js +0 -42
  177. package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.ts +0 -41
  178. package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.js +0 -113
  179. package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.ts +0 -110
  180. package/example/node_modules/quantumcoin/test/unit/generator.test.js +0 -149
  181. package/example/node_modules/quantumcoin/test/unit/generator.test.ts +0 -148
  182. package/example/node_modules/quantumcoin/test/unit/hashing.test.js +0 -64
  183. package/example/node_modules/quantumcoin/test/unit/hashing.test.ts +0 -63
  184. package/example/node_modules/quantumcoin/test/unit/init.test.js +0 -39
  185. package/example/node_modules/quantumcoin/test/unit/init.test.ts +0 -38
  186. package/example/node_modules/quantumcoin/test/unit/interface.test.js +0 -56
  187. package/example/node_modules/quantumcoin/test/unit/interface.test.ts +0 -54
  188. package/example/node_modules/quantumcoin/test/unit/internal-hex.test.js +0 -81
  189. package/example/node_modules/quantumcoin/test/unit/internal-hex.test.ts +0 -80
  190. package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.js +0 -98
  191. package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.ts +0 -64
  192. package/example/node_modules/quantumcoin/test/unit/providers.test.js +0 -252
  193. package/example/node_modules/quantumcoin/test/unit/providers.test.ts +0 -251
  194. package/example/node_modules/quantumcoin/test/unit/result.test.js +0 -80
  195. package/example/node_modules/quantumcoin/test/unit/result.test.ts +0 -79
  196. package/example/node_modules/quantumcoin/test/unit/solidity-types.test.js +0 -49
  197. package/example/node_modules/quantumcoin/test/unit/solidity-types.test.ts +0 -39
  198. package/example/node_modules/quantumcoin/test/unit/utils.test.js +0 -57
  199. package/example/node_modules/quantumcoin/test/unit/utils.test.ts +0 -56
  200. package/example/node_modules/quantumcoin/test/verbose-logger.js +0 -74
  201. package/example/node_modules/quantumcoin/tsconfig.build.json +0 -14
  202. package/example/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +0 -22
  203. package/example/node_modules/seed-words/BUILD.md +0 -7
  204. package/example/node_modules/seed-words/LICENSE +0 -121
  205. package/example/node_modules/seed-words/README.md +0 -67
  206. package/example/node_modules/seed-words/dist/seedwords.d.ts +0 -39
  207. package/example/node_modules/seed-words/package.json +0 -27
  208. package/example/node_modules/seed-words/seedwords.js +0 -315
  209. package/example/node_modules/seed-words/seedwords.txt +0 -65536
  210. package/example/node_modules/seed-words/tsconfig.json +0 -21
  211. package/example/package-lock.json +0 -56
  212. package/example/package.json +0 -15
  213. package/tests/encrypted-32.json +0 -1
  214. package/tests/encrypted-36.json +0 -1
  215. package/tests/encrypted-48.json +0 -1
  216. package/tests/generate-verify-vectors.js +0 -91
  217. package/tests/get-gas-price.test.js +0 -59
  218. package/tests/non-transactional.preinit.test.js +0 -41
  219. package/tests/non-transactional.test.js +0 -1389
  220. package/tests/scrypt.test.js +0 -128
  221. package/tests/sign-raw-keytype5-context-null.test.js +0 -107
  222. package/tests/sign-raw-transaction.test.js +0 -196
  223. package/tests/sign-verify.test.js +0 -311
  224. package/tests/transactional.relay.test.js +0 -131
  225. package/tests/transactional.rpc.test.js +0 -103
  226. package/tests/verify-vectors.json +0 -95035
@@ -1,330 +0,0 @@
1
- /**
2
- * @testCategory security
3
- * @blockchainRequired false
4
- * @transactional false
5
- * @description Security tests for malformed input, edge cases, and invalid values.
6
- * Run with VERBOSE=1 for test names.
7
- */
8
-
9
- const { describe, it } = require("node:test");
10
- const assert = require("node:assert/strict");
11
-
12
- const { Initialize } = require("../../config");
13
- const qc = require("../../index");
14
- const { logSuite, logTest } = require("../verbose-logger");
15
-
16
- describe("Security: Malformed Input", () => {
17
- logSuite("Security: Malformed Input");
18
- it("rejects invalid address length and characters", async () => {
19
- logTest("rejects invalid address length and characters", {});
20
- await Initialize(null);
21
- assert.equal(qc.isAddress("0x1234"), false);
22
- assert.equal(qc.isAddress("not-an-address"), false);
23
- assert.throws(() => qc.getAddress("0x1234"), /invalid address/i);
24
- });
25
-
26
- it("rejects too-long bytes32 strings", () => {
27
- logTest("rejects too-long bytes32 strings", {});
28
- assert.throws(() => qc.encodeBytes32String("x".repeat(33)), /max 32/i);
29
- });
30
-
31
- it("rejects invalid parseUnits inputs", () => {
32
- logTest("rejects invalid parseUnits inputs", {});
33
- assert.throws(() => qc.parseUnits("", 18), /invalid/i);
34
- assert.throws(() => qc.parseUnits("1.234", 2), /exceeds decimals/i);
35
- });
36
- });
37
-
38
- describe("Security: Private key enumeration protection", () => {
39
- logSuite("Security: Private key enumeration protection");
40
-
41
- it("JSON.stringify(wallet) must NOT contain privateKey or seed", async () => {
42
- logTest("JSON.stringify(wallet) must NOT contain privateKey or seed", {});
43
- await Initialize(null);
44
- const w = qc.Wallet.createRandom();
45
- const json = JSON.stringify(w);
46
- const parsed = JSON.parse(json);
47
-
48
- assert.ok(!("privateKey" in parsed), "privateKey must not appear in JSON");
49
- assert.ok(!("seed" in parsed), "seed must not appear in JSON");
50
- assert.ok(!("signingKey" in parsed), "signingKey must not appear in JSON");
51
- assert.ok(!("_qcWallet" in parsed), "_qcWallet must not appear in JSON");
52
- assert.ok(!("_seed" in parsed), "_seed must not appear in JSON");
53
- assert.ok(!("privateKeyBytes" in parsed), "privateKeyBytes must not appear in JSON");
54
-
55
- assert.ok("address" in parsed, "address should be in JSON");
56
- });
57
-
58
- it("Object.keys(wallet) must not include secret properties", async () => {
59
- logTest("Object.keys(wallet) must not include secret properties", {});
60
- await Initialize(null);
61
- const w = qc.Wallet.createRandom();
62
- const keys = Object.keys(w);
63
-
64
- assert.ok(!keys.includes("privateKey"), "privateKey must not be enumerable");
65
- assert.ok(!keys.includes("seed"), "seed must not be enumerable");
66
- assert.ok(!keys.includes("signingKey"), "signingKey must not be enumerable");
67
- assert.ok(!keys.includes("_qcWallet"), "_qcWallet must not be enumerable");
68
- assert.ok(!keys.includes("_seed"), "_seed must not be enumerable");
69
- });
70
-
71
- it("privateKey and seed are still accessible directly", async () => {
72
- logTest("privateKey and seed are still accessible directly", {});
73
- await Initialize(null);
74
- const w = qc.Wallet.createRandom();
75
- assert.equal(typeof w.privateKey, "string");
76
- assert.ok(w.privateKey.startsWith("0x"));
77
- assert.equal(typeof w.seed, "string");
78
- });
79
- });
80
-
81
- describe("Security: Wallet.connect() preserves state", () => {
82
- logSuite("Security: Wallet.connect() preserves state");
83
-
84
- it("connect() preserves seed", async () => {
85
- logTest("connect() preserves seed", {});
86
- await Initialize(null);
87
- const w = qc.Wallet.createRandom();
88
- const seedBefore = w.seed;
89
-
90
- const provider = new qc.JsonRpcProvider("http://127.0.0.1:9999", 123123);
91
- const connected = w.connect(provider);
92
-
93
- assert.equal(connected.seed, seedBefore, "seed must survive connect()");
94
- assert.equal(connected.address, w.address, "address must survive connect()");
95
- });
96
- });
97
-
98
- describe("Security: KDF string password handling", () => {
99
- logSuite("Security: KDF string password handling");
100
-
101
- it("pbkdf2 with plain string password does not crash", async () => {
102
- logTest("pbkdf2 with plain string password does not crash", {});
103
- const result = qc.pbkdf2("password123", "salt123", 1000, 32, "sha256");
104
- assert.equal(typeof result, "string");
105
- assert.ok(result.startsWith("0x"));
106
- });
107
-
108
- it("computeHmac with plain string key/data does not crash", async () => {
109
- logTest("computeHmac with plain string key/data does not crash", {});
110
- const result = qc.computeHmac("sha256", "mykey", "mydata");
111
- assert.equal(typeof result, "string");
112
- assert.ok(result.startsWith("0x"));
113
- });
114
-
115
- it("scryptSync with plain string password does not crash", async () => {
116
- logTest("scryptSync with plain string password does not crash", {});
117
- const result = qc.scryptSync("password123", "salt123", 1024, 8, 1, 32);
118
- assert.equal(typeof result, "string");
119
- assert.ok(result.startsWith("0x"));
120
- });
121
- });
122
-
123
- describe("Security: Numeric precision in signTransaction", () => {
124
- logSuite("Security: Numeric precision in signTransaction");
125
-
126
- it("rejects number value above MAX_SAFE_INTEGER", async () => {
127
- logTest("rejects number value above MAX_SAFE_INTEGER", {});
128
- await Initialize(null);
129
- const w = qc.Wallet.createRandom();
130
- await assert.rejects(
131
- () => w.signTransaction({ to: w.address, value: Number.MAX_SAFE_INTEGER + 1, nonce: 0, chainId: 123123 }),
132
- /overflow/i,
133
- );
134
- });
135
-
136
- it("accepts bigint value for large amounts", async () => {
137
- logTest("accepts bigint value for large amounts", {});
138
- await Initialize(null);
139
- const w = qc.Wallet.createRandom();
140
- const raw = await w.signTransaction({
141
- to: w.address,
142
- value: 999999999999999999999n,
143
- nonce: 0,
144
- chainId: 123123,
145
- });
146
- assert.equal(typeof raw, "string");
147
- assert.ok(raw.startsWith("0x"));
148
- });
149
-
150
- it("accepts string value '0x' as zero", async () => {
151
- logTest("accepts string value '0x' as zero", {});
152
- await Initialize(null);
153
- const w = qc.Wallet.createRandom();
154
- const raw = await w.signTransaction({ to: w.address, value: "0x", nonce: 0, chainId: 123123 });
155
- assert.equal(typeof raw, "string");
156
- });
157
- });
158
-
159
- describe("Security: Password strength enforcement", () => {
160
- logSuite("Security: Password strength enforcement");
161
-
162
- it("encryptSync rejects password shorter than 12 characters", async () => {
163
- logTest("encryptSync rejects password shorter than 12 characters", {});
164
- await Initialize(null);
165
- const w = qc.Wallet.createRandom();
166
- assert.throws(() => w.encryptSync("short"), /password must be at least 12 characters/);
167
- });
168
-
169
- it("encryptSync accepts password of 12+ characters", async () => {
170
- logTest("encryptSync accepts password of 12+ characters", {});
171
- await Initialize(null);
172
- const w = qc.Wallet.createRandom();
173
- const json = w.encryptSync("abcdefghijkl");
174
- assert.equal(typeof json, "string");
175
- assert.ok(json.length > 0);
176
- });
177
- });
178
-
179
- describe("Security: Message signing removed", () => {
180
- logSuite("Security: Message signing removed");
181
-
182
- it("hashMessage is not exported", () => {
183
- logTest("hashMessage is not exported", {});
184
- assert.equal(qc.hashMessage, undefined, "hashMessage should not be exported");
185
- });
186
-
187
- it("verifyMessage is not exported", () => {
188
- logTest("verifyMessage is not exported", {});
189
- assert.equal(qc.verifyMessage, undefined, "verifyMessage should not be exported");
190
- });
191
-
192
- it("recoverAddress is not exported", () => {
193
- logTest("recoverAddress is not exported", {});
194
- assert.equal(qc.recoverAddress, undefined, "recoverAddress should not be exported");
195
- });
196
-
197
- it("MessagePrefix is not exported", () => {
198
- logTest("MessagePrefix is not exported", {});
199
- assert.equal(qc.MessagePrefix, undefined, "MessagePrefix should not be exported");
200
- });
201
- });
202
-
203
- describe("Security: Error messages do not leak secrets", () => {
204
- logSuite("Security: Error messages do not leak secrets");
205
-
206
- it("fromKeys error does not contain actual key bytes", async () => {
207
- logTest("fromKeys error does not contain actual key bytes", {});
208
- await Initialize(null);
209
- const fakeKey = "0xdeadbeef";
210
- try {
211
- qc.Wallet.fromKeys(fakeKey, fakeKey);
212
- assert.fail("should have thrown");
213
- } catch (e) {
214
- assert.ok(!e.message.includes("deadbeef"), "error must not contain key material");
215
- assert.ok(e.message.includes("[REDACTED]") || !e.message.includes("0x"), "value should be redacted");
216
- }
217
- });
218
- });
219
-
220
- describe("Security: _hexToBigInt handles '0x'", () => {
221
- logSuite("Security: _hexToBigInt handles '0x'");
222
-
223
- it("getBalance does not crash on '0x' response", async () => {
224
- logTest("getBalance does not crash on '0x' response", {});
225
- assert.equal(typeof qc.JsonRpcProvider, "function");
226
- });
227
- });
228
-
229
- describe("Security: RLP depth limit", () => {
230
- logSuite("Security: RLP depth limit");
231
-
232
- it("rejects deeply nested RLP (depth > 64)", () => {
233
- logTest("rejects deeply nested RLP (depth > 64)", {});
234
- let inner = [];
235
- for (let i = 0; i < 70; i++) {
236
- inner = [inner];
237
- }
238
- const encoded = qc.encodeRlp(inner);
239
- assert.throws(() => qc.decodeRlp(encoded), /maximum nesting depth exceeded/);
240
- });
241
-
242
- it("accepts RLP within depth limit", () => {
243
- logTest("accepts RLP within depth limit", {});
244
- const encoded = qc.encodeRlp([["hello", "world"], "test"]);
245
- const decoded = qc.decodeRlp(encoded);
246
- assert.ok(Array.isArray(decoded));
247
- });
248
- });
249
-
250
- describe("Security: Seed phrase with invalid words", () => {
251
- logSuite("Security: Seed phrase with invalid words");
252
-
253
- it("rejects gibberish words of correct count", async () => {
254
- logTest("rejects gibberish words of correct count", {});
255
- await Initialize(null);
256
- const gibberish = new Array(32).fill("xyzzyplugh");
257
- assert.throws(
258
- () => qc.Wallet.fromPhrase(gibberish),
259
- { message: /failed/i },
260
- );
261
- });
262
-
263
- it("rejects empty string words of correct count", async () => {
264
- logTest("rejects empty string words of correct count", {});
265
- await Initialize(null);
266
- const empty = new Array(32).fill("");
267
- assert.throws(() => qc.Wallet.fromPhrase(empty));
268
- });
269
- });
270
-
271
- describe("Security: Keccak-256 test vectors", () => {
272
- logSuite("Security: Keccak-256 test vectors");
273
-
274
- it("keccak256 of empty bytes matches known digest", async () => {
275
- logTest("keccak256 of empty bytes matches known digest", {});
276
- const result = qc.keccak256(new Uint8Array(0));
277
- assert.equal(result, "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
278
- });
279
-
280
- it("keccak256 of 'hello' matches known digest", async () => {
281
- logTest("keccak256 of 'hello' matches known digest", {});
282
- const bytes = new TextEncoder().encode("hello");
283
- const result = qc.keccak256(bytes);
284
- assert.equal(result, "0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8");
285
- });
286
-
287
- it("sha256 produces correct length output", () => {
288
- logTest("sha256 produces correct length output", {});
289
- const result = qc.sha256(new Uint8Array([1, 2, 3]));
290
- assert.equal(typeof result, "string");
291
- assert.equal(result.length, 66);
292
- });
293
- });
294
-
295
- describe("Security: BigInt in provider params", () => {
296
- logSuite("Security: BigInt in provider params");
297
-
298
- it("JsonRpcProvider serializes BigInt params without crashing", async (t) => {
299
- logTest("JsonRpcProvider serializes BigInt params without crashing", {});
300
- if (typeof fetch !== "function") {
301
- t.skip("global fetch not available");
302
- return;
303
- }
304
- const originalFetch = fetch;
305
- global.fetch = async (_url, init) => {
306
- const body = JSON.parse(init.body);
307
- assert.equal(body.params[0].value, "0x3e8");
308
- const responseBody = JSON.stringify({ jsonrpc: "2.0", id: body.id, result: "0x1" });
309
- return { ok: true, text: async () => responseBody, json: async () => JSON.parse(responseBody) };
310
- };
311
- try {
312
- const p = new qc.JsonRpcProvider("http://example.invalid", 123123);
313
- await p._perform("eth_call", [{ to: "0x" + "00".repeat(32), value: 1000n }]);
314
- } finally {
315
- global.fetch = originalFetch;
316
- }
317
- });
318
- });
319
-
320
- describe("Security: Per-instance RPC IDs", () => {
321
- logSuite("Security: Per-instance RPC IDs");
322
-
323
- it("different provider instances have independent ID counters", () => {
324
- logTest("different provider instances have independent ID counters", {});
325
- const p1 = new qc.JsonRpcProvider("http://a.invalid", 1);
326
- const p2 = new qc.JsonRpcProvider("http://b.invalid", 1);
327
- assert.equal(p1._rpcId, 1);
328
- assert.equal(p2._rpcId, 1);
329
- });
330
- });
@@ -1,35 +0,0 @@
1
- /**
2
- * @testCategory security
3
- * @blockchainRequired false
4
- * @transactional false
5
- * @description Security tests for malformed input, edge cases, and invalid values
6
- */
7
-
8
- import { describe, it } from "node:test";
9
- import assert from "node:assert/strict";
10
-
11
- import { Initialize } from "../../config";
12
- import qc from "../../index";
13
- import { logSuite, logTest } from "../verbose-logger";
14
-
15
- describe("Security: Malformed Input", () => {
16
- logSuite("Security: Malformed Input");
17
- it("rejects invalid address length and characters", async () => {
18
- logTest("rejects invalid address length and characters", {});
19
- await Initialize(null);
20
- assert.equal(qc.isAddress("0x1234"), false);
21
- assert.equal(qc.isAddress("not-an-address"), false);
22
- assert.throws(() => qc.getAddress("0x1234"), /invalid address/i);
23
- });
24
-
25
- it("rejects too-long bytes32 strings", () => {
26
- logTest("rejects too-long bytes32 strings", {});
27
- assert.throws(() => qc.encodeBytes32String("x".repeat(33)), /max 32/i);
28
- });
29
-
30
- it("rejects invalid parseUnits inputs", () => {
31
- logTest("rejects invalid parseUnits inputs", {});
32
- assert.throws(() => qc.parseUnits("", 18), /invalid/i);
33
- assert.throws(() => qc.parseUnits("1.234", 2), /exceeds decimals/i);
34
- });
35
- });
@@ -1,81 +0,0 @@
1
- /**
2
- * @testCategory security
3
- * @blockchainRequired false
4
- * @transactional false
5
- * @description RPC quantities are untrusted. A value above
6
- * Number.MAX_SAFE_INTEGER must fail loudly instead of being silently
7
- * truncated by Number(BigInt(...)). The decoder keeps returning a
8
- * `number` (no signature change); only out-of-range values throw.
9
- */
10
-
11
- const { describe, it } = require("node:test");
12
- const assert = require("node:assert/strict");
13
-
14
- const { Initialize } = require("../../config");
15
- const qc = require("../../index");
16
- const { logSuite, logTest } = require("../verbose-logger");
17
-
18
- // 2^53 = 9007199254740992 = one past Number.MAX_SAFE_INTEGER.
19
- const UNSAFE_HEX = "0x20000000000000";
20
- const TX_HASH = "0x" + "aa".repeat(32);
21
-
22
- class NumProvider extends qc.AbstractProvider {
23
- constructor(map) {
24
- super();
25
- this._map = map;
26
- }
27
- async _perform(method) {
28
- return Object.prototype.hasOwnProperty.call(this._map, method) ? this._map[method] : null;
29
- }
30
- }
31
-
32
- describe("Security: untrusted RPC quantity bounds", () => {
33
- logSuite("Security: untrusted RPC quantity bounds");
34
-
35
- it("getBlockNumber throws for a value above MAX_SAFE_INTEGER (negative)", async () => {
36
- logTest("getBlockNumber rejects an out-of-range quantity", {});
37
- await Initialize(null);
38
- const p = new NumProvider({ eth_blockNumber: UNSAFE_HEX });
39
- await assert.rejects(() => p.getBlockNumber(), /safe integer range/i);
40
- });
41
-
42
- it("getBlock throws when block.number exceeds MAX_SAFE_INTEGER (negative)", async () => {
43
- logTest("getBlock rejects an out-of-range block number", {});
44
- await Initialize(null);
45
- const p = new NumProvider({
46
- eth_getBlockByNumber: { hash: "0x" + "11".repeat(32), number: UNSAFE_HEX, timestamp: "0x1", transactions: [] },
47
- });
48
- await assert.rejects(() => p.getBlock("latest"), /safe integer range/i);
49
- });
50
-
51
- it("getTransactionReceipt throws when a quantity exceeds MAX_SAFE_INTEGER (negative)", async () => {
52
- logTest("getTransactionReceipt rejects an out-of-range quantity", {});
53
- await Initialize(null);
54
- const p = new NumProvider({
55
- eth_getTransactionReceipt: { transactionHash: TX_HASH, blockNumber: UNSAFE_HEX, status: "0x1" },
56
- });
57
- await assert.rejects(() => p.getTransactionReceipt(TX_HASH), /safe integer range/i);
58
- });
59
-
60
- it("decodes normal in-range quantities to the correct number (positive)", async () => {
61
- logTest("decodes in-range quantities correctly", {});
62
- await Initialize(null);
63
- const p = new NumProvider({
64
- eth_blockNumber: "0x10",
65
- eth_getTransactionReceipt: {
66
- transactionHash: TX_HASH,
67
- blockNumber: "0x5",
68
- transactionIndex: "0x0",
69
- status: "0x1",
70
- },
71
- });
72
- const bn = await p.getBlockNumber();
73
- assert.equal(bn, 16);
74
- assert.equal(typeof bn, "number");
75
-
76
- const receipt = await p.getTransactionReceipt(TX_HASH);
77
- assert.equal(receipt.blockNumber, 5);
78
- assert.equal(typeof receipt.blockNumber, "number");
79
- assert.equal(receipt.status, 1);
80
- });
81
- });
@@ -1,202 +0,0 @@
1
- /**
2
- * @testCategory security
3
- * @blockchainRequired false
4
- * @transactional false
5
- * @description Do not trust the RPC node. A broadcast must be rejected if
6
- * the node returns a transaction hash different from the one we
7
- * signed, and event logs from foreign contract addresses must be
8
- * dropped from getLogs results.
9
- */
10
-
11
- const { describe, it } = require("node:test");
12
- const assert = require("node:assert/strict");
13
-
14
- const { Initialize } = require("../../config");
15
- const qc = require("../../index");
16
- const { logSuite, logTest } = require("../verbose-logger");
17
-
18
- const SIGNED_HASH = "0x" + "aa".repeat(32);
19
-
20
- class SendProvider extends qc.AbstractProvider {
21
- constructor(returnedHash) {
22
- super();
23
- this._returnedHash = returnedHash;
24
- }
25
- async _perform(method) {
26
- if (method === "eth_sendRawTransaction") return this._returnedHash;
27
- if (method === "eth_getTransactionByHash") return { hash: this._returnedHash };
28
- return null;
29
- }
30
- }
31
-
32
- describe("Security: RPC broadcast hash verification", () => {
33
- logSuite("Security: RPC broadcast hash verification");
34
-
35
- it("throws when the node returns a different hash than the signed tx (negative)", async () => {
36
- logTest("throws when the node returns a different hash than the signed tx", {});
37
- await Initialize(null);
38
- const p = new SendProvider("0x" + "bb".repeat(32));
39
- await assert.rejects(
40
- () => p.sendTransaction("0xrawsigned", { expectedHash: SIGNED_HASH }),
41
- /does not match the signed transaction/i,
42
- );
43
- });
44
-
45
- it("returns the response when the node hash matches (positive, case-insensitive)", async () => {
46
- logTest("returns the response when the node hash matches", {});
47
- await Initialize(null);
48
- const p = new SendProvider(SIGNED_HASH);
49
- const resp = await p.sendTransaction("0xrawsigned", { expectedHash: SIGNED_HASH.toUpperCase() });
50
- assert.ok(resp && typeof resp.hash === "string");
51
- assert.equal(resp.hash.toLowerCase(), SIGNED_HASH);
52
- });
53
-
54
- it("without expectedHash, sendTransaction stays backward compatible", async () => {
55
- logTest("without expectedHash, sendTransaction stays backward compatible", {});
56
- await Initialize(null);
57
- const p = new SendProvider(SIGNED_HASH);
58
- const resp = await p.sendTransaction("0xrawsigned");
59
- assert.equal(resp.hash, SIGNED_HASH);
60
- });
61
- });
62
-
63
- class LogProvider extends qc.AbstractProvider {
64
- constructor(logs) {
65
- super();
66
- this._logs = logs;
67
- }
68
- async _perform(method) {
69
- if (method === "eth_getLogs") return this._logs;
70
- return null;
71
- }
72
- }
73
-
74
- describe("Security: event-log provenance", () => {
75
- logSuite("Security: event-log provenance");
76
-
77
- it("drops logs whose address does not match the filter (negative) and keeps matching ones (positive)", async () => {
78
- logTest("drops foreign-address logs and keeps matching ones", {});
79
- await Initialize(null);
80
- const target = "0x" + "11".repeat(32);
81
- const foreign = "0x" + "99".repeat(32);
82
- const p = new LogProvider([
83
- { address: target, topics: [], data: "0x", blockNumber: "0x1" },
84
- { address: foreign, topics: [], data: "0x", blockNumber: "0x1" },
85
- { address: target.toUpperCase(), topics: [], data: "0x", blockNumber: "0x1" },
86
- ]);
87
-
88
- const logs = await p.getLogs({ address: target });
89
- assert.equal(logs.length, 2, "only logs from the requested address survive");
90
- for (const l of logs) {
91
- assert.equal(l.address.toLowerCase(), target.toLowerCase());
92
- }
93
- });
94
-
95
- it("returns all logs when no address filter is given (positive)", async () => {
96
- logTest("returns all logs when no address filter is given", {});
97
- await Initialize(null);
98
- const p = new LogProvider([
99
- { address: "0x" + "11".repeat(32), topics: [], data: "0x" },
100
- { address: "0x" + "99".repeat(32), topics: [], data: "0x" },
101
- ]);
102
- const logs = await p.getLogs({ fromBlock: 0 });
103
- assert.equal(logs.length, 2);
104
- });
105
- });
106
-
107
- const AA = "0x" + "aa".repeat(32);
108
- const BB = "0x" + "bb".repeat(32);
109
-
110
- class HashProvider extends qc.AbstractProvider {
111
- constructor(obj) {
112
- super();
113
- this._obj = obj;
114
- }
115
- async _perform(method) {
116
- if (method === "eth_getTransactionByHash") return this._obj;
117
- if (method === "eth_getTransactionReceipt") return this._obj;
118
- return null;
119
- }
120
- }
121
-
122
- describe("Security: read-back / confirmation hash verification", () => {
123
- logSuite("Security: read-back / confirmation hash verification");
124
-
125
- it("getTransaction throws when the returned hash differs from the requested hash (negative)", async () => {
126
- logTest("getTransaction rejects a mismatched returned hash", {});
127
- await Initialize(null);
128
- const p = new HashProvider({ hash: BB });
129
- await assert.rejects(() => p.getTransaction(AA), /does not match the requested hash/i);
130
- });
131
-
132
- it("getTransaction returns the response when the hash matches (positive)", async () => {
133
- logTest("getTransaction accepts a matching hash", {});
134
- await Initialize(null);
135
- const p = new HashProvider({ hash: AA });
136
- const tx = await p.getTransaction(AA);
137
- assert.equal(tx.hash, AA);
138
- });
139
-
140
- it("getTransactionReceipt throws when transactionHash differs (negative)", async () => {
141
- logTest("getTransactionReceipt rejects a mismatched receipt", {});
142
- await Initialize(null);
143
- const p = new HashProvider({ transactionHash: BB, blockNumber: "0x1" });
144
- await assert.rejects(() => p.getTransactionReceipt(AA), /does not match the requested hash/i);
145
- });
146
-
147
- it("wait() rejects when the node returns a receipt for a different tx (negative)", async () => {
148
- logTest("wait() rejects a mismatched receipt", {});
149
- await Initialize(null);
150
- const p = new HashProvider({ transactionHash: BB, blockNumber: "0x1" });
151
- const resp = new qc.TransactionResponse({ hash: AA }, p);
152
- await assert.rejects(() => resp.wait(1, 5000), /does not match the requested hash/i);
153
- });
154
- });
155
-
156
- describe("Security: event-log topic binding", () => {
157
- logSuite("Security: event-log topic binding");
158
-
159
- const eventAbi = [
160
- {
161
- type: "event",
162
- name: "Transfer",
163
- anonymous: false,
164
- inputs: [
165
- { name: "from", type: "address", indexed: true },
166
- { name: "to", type: "address", indexed: true },
167
- { name: "value", type: "uint256", indexed: false },
168
- ],
169
- },
170
- ];
171
-
172
- it("getLogs drops logs whose topic0 does not match the requested topic (negative+positive)", async () => {
173
- logTest("getLogs filters by topic0", {});
174
- await Initialize(null);
175
- const addr = "0x" + "11".repeat(32);
176
- const wanted = "0x" + "cc".repeat(32);
177
- const other = "0x" + "dd".repeat(32);
178
- const p = new LogProvider([
179
- { address: addr, topics: [wanted], data: "0x", blockNumber: "0x1" },
180
- { address: addr, topics: [other], data: "0x", blockNumber: "0x1" },
181
- ]);
182
- const logs = await p.getLogs({ address: addr, topics: [wanted] });
183
- assert.equal(logs.length, 1);
184
- assert.equal(logs[0].topics[0], wanted);
185
- });
186
-
187
- it("queryFilter only returns logs matching the event's topic0 (negative+positive)", async () => {
188
- logTest("queryFilter binds results to the event topic", {});
189
- await Initialize(null);
190
- const addr = "0x" + "11".repeat(32);
191
- const topic0 = new qc.Interface(eventAbi).getEventTopic("Transfer");
192
- const wrong = "0x" + "ee".repeat(32);
193
- const p = new LogProvider([
194
- { address: addr, topics: [topic0], data: "0x", blockNumber: "0x1" },
195
- { address: addr, topics: [wrong], data: "0x", blockNumber: "0x1" },
196
- ]);
197
- const contract = new qc.Contract(addr, eventAbi, p);
198
- const events = await contract.queryFilter("Transfer", 0, "latest");
199
- assert.equal(events.length, 1, "only the matching-topic log survives");
200
- assert.equal(events[0].topics[0], topic0);
201
- });
202
- });