quantumcoin 7.0.12 → 7.0.14

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 (214) hide show
  1. package/README-SDK.md +828 -823
  2. package/README.md +4 -0
  3. package/config.d.ts +50 -50
  4. package/examples/example-generated-sdk-js/README.md +65 -0
  5. package/examples/example-generated-sdk-js/examples/_test-wallet.js +17 -0
  6. package/examples/example-generated-sdk-js/examples/deploy.js +41 -0
  7. package/examples/example-generated-sdk-js/examples/events.js +36 -0
  8. package/examples/example-generated-sdk-js/examples/read-operations.js +46 -0
  9. package/examples/example-generated-sdk-js/examples/write-operations.js +44 -0
  10. package/examples/example-generated-sdk-js/index.d.ts +1 -0
  11. package/examples/example-generated-sdk-js/index.js +15 -0
  12. package/examples/example-generated-sdk-js/package-lock.json +59 -0
  13. package/examples/example-generated-sdk-js/package.json +22 -0
  14. package/examples/example-generated-sdk-js/src/SimpleERC20.d.ts +19 -0
  15. package/examples/example-generated-sdk-js/src/SimpleERC20.js +353 -0
  16. package/examples/example-generated-sdk-js/src/SimpleERC20__factory.d.ts +10 -0
  17. package/examples/example-generated-sdk-js/src/SimpleERC20__factory.js +29 -0
  18. package/examples/example-generated-sdk-js/src/index.d.ts +4 -0
  19. package/examples/example-generated-sdk-js/src/index.js +5 -0
  20. package/examples/example-generated-sdk-js/src/quantumcoin-shims.d.ts +23 -0
  21. package/examples/example-generated-sdk-js/src/types.d.ts +3 -0
  22. package/examples/example-generated-sdk-js/src/types.js +3 -0
  23. package/examples/example-generated-sdk-js/test/e2e/SimpleERC20.e2e.test.js +78 -0
  24. package/examples/example-generated-sdk-ts/README.md +65 -0
  25. package/examples/example-generated-sdk-ts/examples/_test-wallet.js +17 -0
  26. package/examples/example-generated-sdk-ts/examples/deploy.js +41 -0
  27. package/examples/example-generated-sdk-ts/examples/events.js +36 -0
  28. package/examples/example-generated-sdk-ts/examples/read-operations.js +46 -0
  29. package/examples/example-generated-sdk-ts/examples/write-operations.js +44 -0
  30. package/examples/example-generated-sdk-ts/index.d.ts +1 -0
  31. package/examples/example-generated-sdk-ts/index.js +15 -0
  32. package/examples/example-generated-sdk-ts/package-lock.json +59 -0
  33. package/examples/example-generated-sdk-ts/package.json +23 -0
  34. package/examples/example-generated-sdk-ts/src/SimpleERC20.ts +334 -0
  35. package/examples/example-generated-sdk-ts/src/SimpleERC20__factory.ts +28 -0
  36. package/examples/example-generated-sdk-ts/src/index.ts +4 -0
  37. package/examples/example-generated-sdk-ts/src/quantumcoin-shims.d.ts +23 -0
  38. package/examples/example-generated-sdk-ts/src/types.ts +4 -0
  39. package/examples/example-generated-sdk-ts/test/e2e/SimpleERC20.e2e.test.js +78 -0
  40. package/examples/example-generated-sdk-ts/tsconfig.json +14 -0
  41. package/examples/node_modules/.package-lock.json +5 -5
  42. package/examples/node_modules/quantum-coin-js-sdk/README.md +5 -5
  43. package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +1 -1
  44. package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +1031 -1031
  45. package/examples/node_modules/quantum-coin-js-sdk/index.js +15 -15
  46. package/examples/node_modules/quantum-coin-js-sdk/package.json +1 -1
  47. package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +2 -2
  48. package/examples/package-lock.json +6 -6
  49. package/examples/package.json +1 -1
  50. package/examples/sdk-generator-erc20.inline.json +251 -251
  51. package/generate-sdk.js +1845 -1822
  52. package/package.json +2 -2
  53. package/src/abi/fragments.d.ts +42 -42
  54. package/src/abi/index.d.ts +13 -13
  55. package/src/abi/interface.js +11 -2
  56. package/src/abi/js-abi-coder.js +61 -2
  57. package/src/contract/contract.js +53 -5
  58. package/src/contract/index.d.ts +9 -9
  59. package/src/errors/index.d.ts +92 -92
  60. package/src/generator/index.d.ts +11 -4
  61. package/src/generator/index.js +185 -18
  62. package/src/internal/hex.d.ts +68 -61
  63. package/src/internal/hex.js +36 -0
  64. package/src/providers/json-rpc-provider.d.ts +12 -12
  65. package/src/providers/provider.js +141 -8
  66. package/src/utils/address.d.ts +58 -58
  67. package/src/utils/encoding.d.ts +120 -120
  68. package/src/utils/hashing.js +298 -298
  69. package/src/utils/index.d.ts +63 -63
  70. package/src/utils/index.js +14 -14
  71. package/src/utils/result.d.ts +57 -57
  72. package/src/utils/rlp.d.ts +12 -12
  73. package/src/utils/rlp.js +13 -1
  74. package/src/utils/units.d.ts +29 -29
  75. package/src/wallet/index.d.ts +10 -10
  76. package/src/wallet/wallet.d.ts +192 -192
  77. package/src/wallet/wallet.js +713 -630
  78. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/README.md +83 -0
  79. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.abi.json +12544 -0
  80. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.bin +1 -0
  81. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.js +17 -0
  82. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.ts +10 -0
  83. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.js +41 -0
  84. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.ts +41 -0
  85. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.js +36 -0
  86. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.ts +36 -0
  87. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.js +82 -0
  88. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.ts +80 -0
  89. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.js +46 -0
  90. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.ts +44 -0
  91. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.js +44 -0
  92. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.ts +44 -0
  93. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.d.ts +1 -0
  94. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.js +21 -0
  95. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package-lock.json +597 -0
  96. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package.json +25 -0
  97. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.d.ts +1280 -0
  98. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.js +14021 -0
  99. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.d.ts +11 -0
  100. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.js +31 -0
  101. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.d.ts +4 -0
  102. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.js +5 -0
  103. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/quantumcoin-shims.d.ts +25 -0
  104. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.d.ts +3 -0
  105. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.js +3 -0
  106. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
  107. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.extra.test.js +195 -0
  108. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/README.md +83 -0
  109. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.abi.json +12544 -0
  110. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.bin +1 -0
  111. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.js +17 -0
  112. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.ts +10 -0
  113. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.js +41 -0
  114. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.ts +41 -0
  115. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.js +36 -0
  116. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.ts +36 -0
  117. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.js +82 -0
  118. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.ts +80 -0
  119. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.js +46 -0
  120. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.ts +44 -0
  121. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.js +44 -0
  122. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.ts +44 -0
  123. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.d.ts +1 -0
  124. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.js +21 -0
  125. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package-lock.json +597 -0
  126. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package.json +26 -0
  127. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes.ts +13940 -0
  128. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes__factory.ts +31 -0
  129. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/index.ts +4 -0
  130. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/quantumcoin-shims.d.ts +25 -0
  131. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/types.ts +4 -0
  132. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
  133. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.extra.test.js +195 -0
  134. package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/tsconfig.json +18 -0
  135. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/README.md +74 -0
  136. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.abi.json +245 -0
  137. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.bin +1 -0
  138. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.js +17 -0
  139. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.ts +10 -0
  140. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.js +41 -0
  141. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.ts +41 -0
  142. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.js +36 -0
  143. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.ts +36 -0
  144. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.js +82 -0
  145. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.ts +80 -0
  146. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.js +46 -0
  147. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.ts +44 -0
  148. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.js +44 -0
  149. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.ts +44 -0
  150. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.d.ts +1 -0
  151. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.js +16 -0
  152. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package-lock.json +597 -0
  153. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package.json +25 -0
  154. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.d.ts +24 -0
  155. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.js +378 -0
  156. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.d.ts +10 -0
  157. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.js +31 -0
  158. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.d.ts +4 -0
  159. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.js +5 -0
  160. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/quantumcoin-shims.d.ts +25 -0
  161. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.d.ts +3 -0
  162. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.js +3 -0
  163. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/test/e2e/SimpleERC20.e2e.test.js +90 -0
  164. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/README.md +74 -0
  165. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.abi.json +245 -0
  166. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.bin +1 -0
  167. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.js +17 -0
  168. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.ts +10 -0
  169. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.js +41 -0
  170. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.ts +41 -0
  171. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.js +36 -0
  172. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.ts +36 -0
  173. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.js +82 -0
  174. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.ts +80 -0
  175. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.js +46 -0
  176. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.ts +44 -0
  177. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.js +44 -0
  178. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.ts +44 -0
  179. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.d.ts +1 -0
  180. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.js +16 -0
  181. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package-lock.json +597 -0
  182. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package.json +26 -0
  183. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20.ts +361 -0
  184. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20__factory.ts +30 -0
  185. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/index.ts +4 -0
  186. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/quantumcoin-shims.d.ts +25 -0
  187. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/types.ts +4 -0
  188. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/test/e2e/SimpleERC20.e2e.test.js +90 -0
  189. package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/tsconfig.json +18 -0
  190. package/test/e2e/generator-interface.e2e.test.js +165 -0
  191. package/test/e2e/generator-interface.e2e.test.ts +160 -0
  192. package/test/e2e/signing-context-and-fee.e2e.test.js +141 -141
  193. package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -128
  194. package/test/integration/provider.test.js +88 -88
  195. package/test/security/abi-decoder-bounds.test.js +122 -0
  196. package/test/security/contract-overrides.test.js +112 -0
  197. package/test/security/generator-injection.test.js +195 -0
  198. package/test/security/malformed-input.test.js +26 -27
  199. package/test/security/rpc-numeric-bounds.test.js +81 -0
  200. package/test/security/rpc-trust.test.js +202 -0
  201. package/test/unit/abi-interface.test.js +12 -5
  202. package/test/unit/abi-interface.test.ts +8 -1
  203. package/test/unit/address-wallet.test.js +923 -892
  204. package/test/unit/address-wallet.test.ts +877 -877
  205. package/test/unit/encoding-units-rlp.test.js +35 -0
  206. package/test/unit/generator.test.js +48 -1
  207. package/test/unit/generator.test.ts +48 -1
  208. package/test/unit/hashing.test.js +64 -64
  209. package/test/unit/hashing.test.ts +63 -63
  210. package/test/unit/internal-hex.test.js +32 -1
  211. package/test/unit/internal-hex.test.ts +32 -1
  212. package/test/unit/populate-transaction.test.js +33 -0
  213. package/test/unit/providers.test.js +51 -1
  214. package/test/unit/providers.test.ts +53 -0
@@ -80,8 +80,9 @@ function _collectTupleRegistry(contractName, abi) {
80
80
  const key = _tupleKey(param);
81
81
  if (byKey.has(key)) return byKey.get(key);
82
82
 
83
- const suggested =
84
- _tupleBaseNameFromInternalType(contractName, param && param.internalType) || `${contractName}Tuple${++counter}`;
83
+ const suggested = _safeTypeIdent(
84
+ _tupleBaseNameFromInternalType(contractName, param && param.internalType) || `${contractName}Tuple${++counter}`,
85
+ );
85
86
  let baseName = suggested;
86
87
  if (usedNames.has(baseName) && usedNames.get(baseName) !== key) {
87
88
  let n = 1;
@@ -376,11 +377,115 @@ function _safeIdent(name) {
376
377
  return (name || "arg").replace(/[^a-zA-Z0-9_]/g, "_");
377
378
  }
378
379
 
380
+ // NatSpec/doc text is attacker-controllable (it comes from arbitrary Solidity
381
+ // source). It is emitted into generated `/** ... */` JSDoc blocks, so a `*/` in the
382
+ // text would close the comment early and turn whatever follows into executable code
383
+ // in the generated .js/.ts files. Neutralize the comment delimiters (and strip
384
+ // CR/LF so a line cannot be split) before interpolation.
385
+ function _escapeComment(text) {
386
+ return String(text == null ? "" : text)
387
+ .replace(/\*\//g, "* /")
388
+ .replace(/\/\*/g, "/ *")
389
+ .replace(/[\r\n]+/g, " ");
390
+ }
391
+
392
+ // Reserved words / dangerous property names that must never be emitted as a raw
393
+ // identifier (class name, function name, import/require specifier, etc.).
394
+ const _RESERVED_IDENTIFIERS = new Set([
395
+ "break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do",
396
+ "else", "export", "extends", "finally", "for", "function", "if", "import", "in", "instanceof",
397
+ "new", "return", "super", "switch", "this", "throw", "try", "typeof", "var", "void", "while",
398
+ "with", "yield", "enum", "await", "implements", "interface", "let", "package", "private",
399
+ "protected", "public", "static", "null", "true", "false",
400
+ "__proto__", "constructor", "prototype",
401
+ ]);
402
+
403
+ /**
404
+ * Assert that `name` is safe to interpolate verbatim into generated source code
405
+ * (class names, function names, type names, require/import specifiers, file names).
406
+ *
407
+ * This is the primary defense against code-injection and path-traversal
408
+ * via attacker-controlled ABI / artifact `name` fields: only strict JS/TS
409
+ * identifiers are allowed, which by construction cannot contain quotes, newlines,
410
+ * path separators, `..`, or other breakout characters.
411
+ *
412
+ * @param {any} name
413
+ * @param {string=} kind Human-readable description for error messages.
414
+ * @returns {string} the validated name
415
+ */
416
+ function _assertSafeIdentifier(name, kind) {
417
+ const label = kind || "identifier";
418
+ if (typeof name !== "string" || !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) {
419
+ throw new Error(`Unsafe ${label} for code generation: ${JSON.stringify(name)}`);
420
+ }
421
+ if (_RESERVED_IDENTIFIERS.has(name)) {
422
+ throw new Error(`${label} must not be a reserved word: ${JSON.stringify(name)}`);
423
+ }
424
+ return name;
425
+ }
426
+
427
+ /**
428
+ * Coerce an arbitrary string (e.g. a struct name derived from an attacker-controlled
429
+ * `internalType`) into a safe type identifier. Unlike `_assertSafeIdentifier` this
430
+ * never throws; it sanitizes so auto-generated type names always remain valid.
431
+ * @param {any} s
432
+ * @returns {string}
433
+ */
434
+ function _safeTypeIdent(s) {
435
+ let v = String(s == null ? "" : s).replace(/[^A-Za-z0-9_$]/g, "_");
436
+ if (!/^[A-Za-z_$]/.test(v)) v = "_" + v;
437
+ return v || "_Tuple";
438
+ }
439
+
440
+ /**
441
+ * Validate every rendered function name in an ABI. Only `function` entries are
442
+ * emitted as method identifiers, so those are the names that must be safe.
443
+ * @param {any[]} abi
444
+ */
445
+ function _assertSafeAbiNames(abi) {
446
+ for (const f of abi || []) {
447
+ if (f && f.type === "function" && f.name != null) {
448
+ _assertSafeIdentifier(f.name, "ABI function name");
449
+ }
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Assert that `filePath` resolves to a location inside `outDir` (defense-in-depth).
455
+ * @param {string} outDir
456
+ * @param {string} filePath
457
+ */
458
+ function _assertWithinDir(outDir, filePath) {
459
+ const root = path.resolve(outDir);
460
+ const resolved = path.resolve(filePath);
461
+ const rel = path.relative(root, resolved);
462
+ if (rel.startsWith("..") || path.isAbsolute(rel)) {
463
+ throw new Error(`Refusing to write outside output directory: ${resolved}`);
464
+ }
465
+ }
466
+
379
467
  function _findConstructor(abi) {
380
468
  const ctor = abi.find((f) => f && f.type === "constructor");
381
469
  return ctor || { type: "constructor", inputs: [] };
382
470
  }
383
471
 
472
+ /**
473
+ * Return true if the given bytecode artifact represents an interface
474
+ * (or otherwise non-deployable contract with no runtime code).
475
+ *
476
+ * `solc` writes an empty `.bin` for `interface` declarations and fully
477
+ * abstract `contract` declarations. We treat `null`, `undefined`, empty
478
+ * string, and the bare `"0x"` / `"0X"` prefix as interface bytecode.
479
+ *
480
+ * @param {string|null|undefined} bytecode
481
+ * @returns {boolean}
482
+ */
483
+ function _isInterfaceBytecode(bytecode) {
484
+ if (bytecode == null) return true;
485
+ const s = String(bytecode).trim().toLowerCase();
486
+ return s === "" || s === "0x";
487
+ }
488
+
384
489
  function _solTypeToTestValueExpr(param) {
385
490
  const type = typeof param === "string" ? param : String(param && param.type ? param.type : "");
386
491
  const internalType = typeof param === "object" && param ? String(param.internalType || "") : "";
@@ -491,7 +596,7 @@ function _renderContractTs({ contractName, abi, bytecode, docs }) {
491
596
  for (const line of docs.contract.split(/\r?\n/g)) {
492
597
  const t = line.trim();
493
598
  if (!t) continue;
494
- contractTsLines.push(` * ${t}`);
599
+ contractTsLines.push(` * ${_escapeComment(t)}`);
495
600
  }
496
601
  }
497
602
  contractTsLines.push(` */`);
@@ -522,7 +627,12 @@ function _renderContractTs({ contractName, abi, bytecode, docs }) {
522
627
  ` ${name}: async (${argsSig}${argsSig ? ", " : ""}overrides?: any): Promise<import("quantumcoin").TransactionRequest> => {`,
523
628
  );
524
629
  contractTsLines.push(` const data = this.interface.encodeFunctionData(${JSON.stringify(name)}, [${argsNames}]);`);
525
- contractTsLines.push(` return { to: this.address, data, ...(overrides || {}) };`);
630
+ // Drop attacker-controllable to/data/from; protected fields win.
631
+ contractTsLines.push(` const safeOverrides: any = {};`);
632
+ contractTsLines.push(
633
+ ` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "chainId", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
634
+ );
635
+ contractTsLines.push(` return { ...safeOverrides, to: this.address, data };`);
526
636
  contractTsLines.push(` },`);
527
637
  }
528
638
  contractTsLines.push(` } as any;`);
@@ -559,7 +669,7 @@ function _renderContractTs({ contractName, abi, bytecode, docs }) {
559
669
  for (const line of fnDoc.split(/\r?\n/g)) {
560
670
  const t = line.trim();
561
671
  if (!t) continue;
562
- contractTsLines.push(` * ${t}`);
672
+ contractTsLines.push(` * ${_escapeComment(t)}`);
563
673
  }
564
674
  }
565
675
  contractTsLines.push(` */`);
@@ -611,7 +721,7 @@ function _renderContractJs({ contractName, abi, bytecode, docs }) {
611
721
  for (const line of docs.contract.split(/\r?\n/g)) {
612
722
  const t = line.trim();
613
723
  if (!t) continue;
614
- lines.push(` * ${t}`);
724
+ lines.push(` * ${_escapeComment(t)}`);
615
725
  }
616
726
  }
617
727
  lines.push(" */");
@@ -637,7 +747,12 @@ function _renderContractJs({ contractName, abi, bytecode, docs }) {
637
747
  const argsSig = inputs.map((p, i) => _safeIdent(p.name || `arg${i}`)).join(", ");
638
748
  lines.push(` ${name}: async (${argsSig}${argsSig ? ", " : ""}overrides) => {`);
639
749
  lines.push(` const data = this.interface.encodeFunctionData(${JSON.stringify(name)}, [${argsNames}]);`);
640
- lines.push(` return { to: this.address, data, ...(overrides || {}) };`);
750
+ // Drop attacker-controllable to/data/from; protected fields win.
751
+ lines.push(` const safeOverrides = {};`);
752
+ lines.push(
753
+ ` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "chainId", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
754
+ );
755
+ lines.push(` return { ...safeOverrides, to: this.address, data };`);
641
756
  lines.push(" },");
642
757
  }
643
758
  lines.push(" };");
@@ -662,7 +777,7 @@ function _renderContractJs({ contractName, abi, bytecode, docs }) {
662
777
  for (const line of fnDoc.split(/\r?\n/g)) {
663
778
  const t = line.trim();
664
779
  if (!t) continue;
665
- lines.push(` * ${t}`);
780
+ lines.push(` * ${_escapeComment(t)}`);
666
781
  }
667
782
  }
668
783
  for (const p of inputs) {
@@ -826,7 +941,13 @@ function _renderFactoryTs({ contractName, abi }) {
826
941
  factoryTsLines.push(` try { nonce = await provider.getTransactionCount(from, "pending"); } catch { nonce = await provider.getTransactionCount(from, "latest"); }`);
827
942
  factoryTsLines.push(` const address = getCreateAddress({ from, nonce });`);
828
943
  factoryTsLines.push(` const txReq: any = this.getDeployTransaction(${deployArgsNames});`);
829
- factoryTsLines.push(` const tx = await signer.sendTransaction({ ...txReq, ...(overrides || {}), nonce });`);
944
+ // Only allow-listed override fields may reach the signer; protected fields
945
+ // (to/data from txReq, and the computed nonce) always win.
946
+ factoryTsLines.push(` const safeOverrides: any = {};`);
947
+ factoryTsLines.push(
948
+ ` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
949
+ );
950
+ factoryTsLines.push(` const tx = await signer.sendTransaction({ ...txReq, ...safeOverrides, nonce });`);
830
951
  factoryTsLines.push(` return new ${contractName}(address, signer as any, tx as any);`);
831
952
  factoryTsLines.push(` }`);
832
953
  factoryTsLines.push(``);
@@ -865,7 +986,13 @@ function _renderFactoryJs({ contractName, abi }) {
865
986
  lines.push(` try { nonce = await provider.getTransactionCount(from, "pending"); } catch { nonce = await provider.getTransactionCount(from, "latest"); }`);
866
987
  lines.push(` const address = getCreateAddress({ from, nonce });`);
867
988
  lines.push(` const txReq = this.getDeployTransaction(${deployArgsNames});`);
868
- lines.push(` const tx = await signer.sendTransaction({ ...txReq, ...(overrides || {}), nonce });`);
989
+ // Only allow-listed override fields may reach the signer; protected fields
990
+ // (to/data from txReq, and the computed nonce) always win.
991
+ lines.push(` const safeOverrides = {};`);
992
+ lines.push(
993
+ ` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
994
+ );
995
+ lines.push(` const tx = await signer.sendTransaction({ ...txReq, ...safeOverrides, nonce });`);
869
996
  lines.push(` return new ${contractName}(address, signer, tx);`);
870
997
  lines.push(` }`);
871
998
  lines.push("");
@@ -957,11 +1084,21 @@ function _renderIndexDts(contractNames) {
957
1084
  * Generate a transactional e2e test file (JavaScript) for the typed contract package.
958
1085
  * The test deploys the contract with constructor args (if any) and invokes one write method.
959
1086
  *
960
- * @param {{ contractName: string, abi: any[] }} opts
1087
+ * When `bytecode` is omitted, empty, or `"0x"` the contract is treated as an interface:
1088
+ * the generated test still attempts the deploy (the receipt-status assertion still validates
1089
+ * SDK wrapper wiring) but the post-deploy `provider.getCode(...)` bytecode assertion is
1090
+ * skipped, since interfaces deploy with no runtime code by design.
1091
+ *
1092
+ * @param {{ contractName: string, abi: any[], bytecode?: string }} opts
961
1093
  * @returns {string}
962
1094
  */
963
1095
  function generateTransactionalTestJs(opts) {
964
- const { contractName, abi } = opts;
1096
+ const { contractName, abi, bytecode } = opts;
1097
+ // This renders `${contractName}`, `${contractName}__factory` and method
1098
+ // names directly into JS source and a require() specifier.
1099
+ _assertSafeIdentifier(contractName, "contract name");
1100
+ _assertSafeAbiNames(abi);
1101
+ const isInterface = _isInterfaceBytecode(bytecode);
965
1102
  const factoryName = `${contractName}__factory`;
966
1103
  const ctor = _findConstructor(abi);
967
1104
  const ctorInputs = ctor.inputs || [];
@@ -1083,7 +1220,7 @@ const { getProvider, Wallet } = require("quantumcoin");
1083
1220
  // Require the package root so it works for both TS (dist) and JS (src) packages.
1084
1221
  const { ${contractName}, ${factoryName} } = require("../..");
1085
1222
 
1086
- // Hardcoded test wallet (test-only; never use for real funds)
1223
+ // SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
1087
1224
  const TEST_WALLET_ENCRYPTED_JSON =
1088
1225
  ${JSON.stringify(
1089
1226
  "{\"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}",
@@ -1127,8 +1264,10 @@ describe("${contractName} transactional", () => {
1127
1264
  assert.ok(deployReceipt);
1128
1265
  assert.ok(deployReceipt.blockNumber != null);
1129
1266
 
1130
- const code = await provider.getCode(contract.target, "latest");
1131
- assert.ok(code && code !== "0x");
1267
+ ${isInterface
1268
+ ? `// Skipping bytecode check: ${contractName} is an interface (no bytecode).`
1269
+ : `const code = await provider.getCode(contract.target, "latest");
1270
+ assert.ok(code && code !== "0x");`}
1132
1271
 
1133
1272
  ${erc20Assertions ? erc20Assertions : `// (no ERC-20 surface detected for extra assertions)`}
1134
1273
 
@@ -1191,7 +1330,10 @@ function _getContractTestMeta(opts) {
1191
1330
  * Generate a single transactional e2e test that deploys and invokes methods on ALL contracts.
1192
1331
  * Used when the package has multiple contracts so one test exercises every contract.
1193
1332
  *
1194
- * @param {{ artifacts: Array<{ contractName: string, abi: any[] }> }} opts
1333
+ * Accepts `bytecode` per artifact for forward-compatibility, although the multi-contract
1334
+ * template currently emits no `getCode` assertion (so the value is not yet consumed).
1335
+ *
1336
+ * @param {{ artifacts: Array<{ contractName: string, abi: any[], bytecode?: string }> }} opts
1195
1337
  * @returns {string}
1196
1338
  */
1197
1339
  function generateAllContractsTransactionalTestJs(opts) {
@@ -1200,6 +1342,12 @@ function generateAllContractsTransactionalTestJs(opts) {
1200
1342
  throw new Error("generateAllContractsTransactionalTestJs requires at least 2 artifacts");
1201
1343
  }
1202
1344
 
1345
+ // Contract names and method names are interpolated into source + require().
1346
+ for (const a of artifacts) {
1347
+ _assertSafeIdentifier(a && a.contractName, "contract name");
1348
+ _assertSafeAbiNames(a && a.abi);
1349
+ }
1350
+
1203
1351
  const requireNames = [];
1204
1352
  for (const a of artifacts) {
1205
1353
  requireNames.push(a.contractName, `${a.contractName}__factory`);
@@ -1262,7 +1410,7 @@ const { getProvider, Wallet } = require("quantumcoin");
1262
1410
 
1263
1411
  ${requireLine}
1264
1412
 
1265
- // Hardcoded test wallet (test-only; never use for real funds)
1413
+ // SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
1266
1414
  const TEST_WALLET_ENCRYPTED_JSON =
1267
1415
  ${JSON.stringify(
1268
1416
  "{\"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}",
@@ -1321,6 +1469,13 @@ function generateFromArtifacts(opts) {
1321
1469
  throw new Error(`Unsupported generator lang: ${lang}`);
1322
1470
  }
1323
1471
 
1472
+ // Reject attacker-controlled names before they are interpolated into
1473
+ // generated source or used to build output file paths.
1474
+ for (const a of opts.artifacts || []) {
1475
+ _assertSafeIdentifier(a && a.contractName, "contract name");
1476
+ _assertSafeAbiNames(a && a.abi);
1477
+ }
1478
+
1324
1479
  const contractNames = opts.artifacts.map((a) => a.contractName);
1325
1480
 
1326
1481
  const typesFile = path.join(opts.outDir, lang === "ts" ? `types.ts` : `types.js`);
@@ -1342,6 +1497,12 @@ function generateFromArtifacts(opts) {
1342
1497
  const contractDtsFile = lang === "js" ? path.join(opts.outDir, `${a.contractName}.d.ts`) : null;
1343
1498
  const factoryDtsFile = lang === "js" ? path.join(opts.outDir, `${a.contractName}__factory.d.ts`) : null;
1344
1499
 
1500
+ // Defense-in-depth — even though contractName is a validated identifier,
1501
+ // ensure no output path escapes the target directory.
1502
+ for (const f of [contractFile, factoryFile, contractDtsFile, factoryDtsFile]) {
1503
+ if (f) _assertWithinDir(opts.outDir, f);
1504
+ }
1505
+
1345
1506
  if (lang === "ts") {
1346
1507
  fs.writeFileSync(
1347
1508
  contractFile,
@@ -1400,5 +1561,11 @@ function generate(opts) {
1400
1561
  return { contractFile, factoryFile, typesFile: res.typesFile, indexFile: res.indexFile };
1401
1562
  }
1402
1563
 
1403
- module.exports = { generate, generateFromArtifacts, generateTransactionalTestJs, generateAllContractsTransactionalTestJs };
1564
+ module.exports = {
1565
+ generate,
1566
+ generateFromArtifacts,
1567
+ generateTransactionalTestJs,
1568
+ generateAllContractsTransactionalTestJs,
1569
+ assertSafeIdentifier: _assertSafeIdentifier,
1570
+ };
1404
1571
 
@@ -1,61 +1,68 @@
1
- /**
2
- * Return true if `value` is a Uint8Array.
3
- * @param {any} value
4
- * @returns {value is Uint8Array}
5
- */
6
- export function isUint8Array(value: any): value is Uint8Array;
7
- /**
8
- * Normalize a hex string.
9
- * @param {string} hex
10
- * @returns {string}
11
- */
12
- export function normalizeHex(hex: string): string;
13
- /**
14
- * Returns true if value is a hex string.
15
- * @param {any} value
16
- * @param {number=} lengthBytes Optional exact byte length.
17
- * @returns {boolean}
18
- */
19
- export function isHexString(value: any, lengthBytes?: number | undefined): boolean;
20
- /**
21
- * Strip 0x prefix.
22
- * @param {string} hex
23
- * @returns {string}
24
- */
25
- export function strip0x(hex: string): string;
26
- /**
27
- * Ensure a 0x prefix.
28
- * @param {string} hex
29
- * @returns {string}
30
- */
31
- export function add0x(hex: string): string;
32
- /**
33
- * Convert a hex string to bytes.
34
- * @param {string} hex
35
- * @returns {Uint8Array}
36
- */
37
- export function hexToBytes(hex: string): Uint8Array;
38
- /**
39
- * Convert bytes to hex string.
40
- * @param {Uint8Array} bytes
41
- * @returns {string}
42
- */
43
- export function bytesToHex(bytes: Uint8Array): string;
44
- /**
45
- * UTF-8 encode a string to bytes.
46
- * @param {string} str
47
- * @returns {Uint8Array}
48
- */
49
- export function utf8ToBytes(str: string): Uint8Array;
50
- /**
51
- * UTF-8 decode bytes to a string.
52
- * @param {Uint8Array} bytes
53
- * @returns {string}
54
- */
55
- export function bytesToUtf8(bytes: Uint8Array): string;
56
- /**
57
- * Convert BytesLike to Uint8Array.
58
- * @param {string | Uint8Array} data
59
- * @returns {Uint8Array}
60
- */
61
- export function arrayify(data: string | Uint8Array): Uint8Array;
1
+ /**
2
+ * Return true if `value` is a Uint8Array.
3
+ * @param {any} value
4
+ * @returns {value is Uint8Array}
5
+ */
6
+ export function isUint8Array(value: any): value is Uint8Array;
7
+ /**
8
+ * Normalize a hex string.
9
+ * @param {string} hex
10
+ * @returns {string}
11
+ */
12
+ export function normalizeHex(hex: string): string;
13
+ /**
14
+ * Format a number/bigint as a JSON-RPC QUANTITY hex string (no leading zeros).
15
+ * @param value
16
+ */
17
+ export function toQuantityHex(value: number | bigint): string;
18
+ /** Alias of `toQuantityHex` matching ethers.js v6 naming. */
19
+ export const toQuantity: typeof toQuantityHex;
20
+ /**
21
+ * Returns true if value is a hex string.
22
+ * @param {any} value
23
+ * @param {number=} lengthBytes Optional exact byte length.
24
+ * @returns {boolean}
25
+ */
26
+ export function isHexString(value: any, lengthBytes?: number | undefined): boolean;
27
+ /**
28
+ * Strip 0x prefix.
29
+ * @param {string} hex
30
+ * @returns {string}
31
+ */
32
+ export function strip0x(hex: string): string;
33
+ /**
34
+ * Ensure a 0x prefix.
35
+ * @param {string} hex
36
+ * @returns {string}
37
+ */
38
+ export function add0x(hex: string): string;
39
+ /**
40
+ * Convert a hex string to bytes.
41
+ * @param {string} hex
42
+ * @returns {Uint8Array}
43
+ */
44
+ export function hexToBytes(hex: string): Uint8Array;
45
+ /**
46
+ * Convert bytes to hex string.
47
+ * @param {Uint8Array} bytes
48
+ * @returns {string}
49
+ */
50
+ export function bytesToHex(bytes: Uint8Array): string;
51
+ /**
52
+ * UTF-8 encode a string to bytes.
53
+ * @param {string} str
54
+ * @returns {Uint8Array}
55
+ */
56
+ export function utf8ToBytes(str: string): Uint8Array;
57
+ /**
58
+ * UTF-8 decode bytes to a string.
59
+ * @param {Uint8Array} bytes
60
+ * @returns {string}
61
+ */
62
+ export function bytesToUtf8(bytes: Uint8Array): string;
63
+ /**
64
+ * Convert BytesLike to Uint8Array.
65
+ * @param {string | Uint8Array} data
66
+ * @returns {Uint8Array}
67
+ */
68
+ export function arrayify(data: string | Uint8Array): Uint8Array;
@@ -35,6 +35,40 @@ function normalizeHex(hex) {
35
35
  return h;
36
36
  }
37
37
 
38
+ /**
39
+ * Format a number/bigint as a JSON-RPC QUANTITY hex string.
40
+ *
41
+ * Per the Ethereum JSON-RPC spec, quantities use the most compact
42
+ * representation with no leading zeros, with the single exception that
43
+ * zero is encoded as "0x0".
44
+ *
45
+ * Use this for block numbers, gas amounts, nonces, balances, and other
46
+ * numeric RPC parameters. Do NOT use it for DATA hex (addresses,
47
+ * bytecode, byte-arrays) — use `normalizeHex` for those.
48
+ *
49
+ * @param {number|bigint} value
50
+ * @returns {string}
51
+ */
52
+ function toQuantityHex(value) {
53
+ let n;
54
+ if (typeof value === "bigint") {
55
+ n = value;
56
+ } else if (typeof value === "number") {
57
+ if (!Number.isInteger(value)) {
58
+ throw new TypeError("toQuantityHex: value must be an integer or bigint");
59
+ }
60
+ n = BigInt(value);
61
+ } else {
62
+ throw new TypeError("toQuantityHex: value must be a number or bigint");
63
+ }
64
+ if (n < 0n) throw new RangeError("toQuantityHex: value must be non-negative");
65
+ if (n === 0n) return "0x0";
66
+ return "0x" + n.toString(16);
67
+ }
68
+
69
+ /** Alias of `toQuantityHex` matching ethers.js v6 naming. */
70
+ const toQuantity = toQuantityHex;
71
+
38
72
  /**
39
73
  * Returns true if value is a hex string.
40
74
  * @param {any} value
@@ -132,6 +166,8 @@ function arrayify(data) {
132
166
  module.exports = {
133
167
  isUint8Array,
134
168
  normalizeHex,
169
+ toQuantityHex,
170
+ toQuantity,
135
171
  isHexString,
136
172
  strip0x,
137
173
  add0x,
@@ -1,12 +1,12 @@
1
- export class JsonRpcProvider extends AbstractProvider {
2
- /**
3
- * @param {string=} url RPC endpoint (defaults to Config.rpcEndpoint or https://public.rpc.quantumcoinapi.com)
4
- * @param {number=} chainId Chain ID (defaults to 123123)
5
- */
6
- constructor(url?: string | undefined, chainId?: number | undefined);
7
- url: string;
8
- chainId: number;
9
- }
10
- export class JsonRpcApiProvider extends JsonRpcProvider {
11
- }
12
- import { AbstractProvider } from "./provider";
1
+ export class JsonRpcProvider extends AbstractProvider {
2
+ /**
3
+ * @param {string=} url RPC endpoint (defaults to Config.rpcEndpoint or https://public.rpc.quantumcoinapi.com)
4
+ * @param {number=} chainId Chain ID (defaults to 123123)
5
+ */
6
+ constructor(url?: string | undefined, chainId?: number | undefined);
7
+ url: string;
8
+ chainId: number;
9
+ }
10
+ export class JsonRpcApiProvider extends JsonRpcProvider {
11
+ }
12
+ import { AbstractProvider } from "./provider";