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,1846 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * sdkgen
4
- *
5
- * NOTE: This script is the SDK generator CLI entrypoint.
6
- *
7
- * SPEC.md section 15: Typed Contract Generator
8
- *
9
- * Usage:
10
- * - Non-interactive:
11
- * `node generate-sdk.js --abi path/to/abi.json --bin path/to/bytecode.bin --out ./out --name MyContract`
12
- *
13
- * - Interactive:
14
- * `node generate-sdk.js --abi path/to/abi.json --bin path/to/bytecode.bin`
15
- */
16
-
17
- const fs = require("node:fs");
18
- const path = require("node:path");
19
- const readline = require("node:readline/promises");
20
- const { stdin, stdout } = require("node:process");
21
- const { execFileSync, spawnSync } = require("node:child_process");
22
-
23
- const {
24
- generate,
25
- generateFromArtifacts,
26
- generateTransactionalTestJs,
27
- generateAllContractsTransactionalTestJs,
28
- assertSafeIdentifier,
29
- } = require("./src/generator");
30
-
31
- function _helpText() {
32
- return `
33
- sdkgen (generate-sdk.js)
34
-
35
- Generates TypeScript or JavaScript contract wrappers (plus optional package scaffold, examples and transactional tests).
36
-
37
- If you run this script with no parameters, it prints this help.
38
-
39
- USAGE
40
- node generate-sdk.js [options]
41
-
42
- INPUT MODES
43
- 1) ABI + BIN (bytecode)
44
- --abi <path/to/Contract.abi.json>
45
- --bin <path/to/Contract.bin>
46
- --name <ContractName> (optional; defaults from ABI filename)
47
-
48
- 2) Solidity (.sol) sources
49
- --sol "<A.sol,B.sol,...>" (comma-separated list; can be 1+ files)
50
- --name <ContractName> (optional; if omitted, generates ALL deployable contracts found)
51
- --solc <path/to/solc.exe> (optional; defaults from env; see ENV below)
52
- --solc-args "<args>" (optional; extra args passed to solc, e.g. "--via-ir --evm-version london")
53
-
54
- 3) Artifacts JSON (array of ABI+BIN pairs)
55
- --artifacts-json <path/to/artifacts.json>
56
- The JSON file should be an array. Each entry supports:
57
- - { abi: "<path|abiJsonString|abiArray>", bin: "<path|0x...>", name?: "<ContractName>" }
58
- If "name" is omitted and abi is a path, the contract name defaults from the ABI filename.
59
-
60
- Example artifacts.json (ABI+BIN pairs):
61
- [
62
- {
63
- "abi": "./artifacts/Alpha.abi.json",
64
- "bin": "./artifacts/Alpha.bin",
65
- "name": "Alpha"
66
- },
67
- {
68
- "abi": [
69
- {
70
- "type": "function",
71
- "name": "set",
72
- "stateMutability": "nonpayable",
73
- "inputs": [{ "name": "value", "type": "uint256" }],
74
- "outputs": []
75
- }
76
- ],
77
- "bin": "0x6000600055...",
78
- "name": "Beta"
79
- }
80
- ]
81
-
82
- PACKAGE OUTPUT (optional)
83
- --create-package
84
- --package-dir <folder>
85
- --package-name <name>
86
- --package-description <text>
87
- --package-author <text>
88
- --package-license <spdx> (default: MIT)
89
- --package-version <semver> (default: 0.0.1)
90
-
91
- Notes:
92
- - When --create-package is used, the generator creates a complete npm package scaffold with:
93
- - src/*.(ts|js) (contracts + factories; depends on --lang)
94
- - test/e2e/*.e2e.test.js (transactional tests)
95
- - examples/ (deploy, read-operations, write-operations, offline-signing, events in .js and .ts)
96
- - artifacts/ (only when using --sol)
97
- - index.js + index.d.ts (package entry shims; TS mode uses dist/)
98
- - For --lang ts, the generator will run:
99
- npm install
100
- npm run build:ts
101
- as the final step.
102
- - For --lang js, the generator will run:
103
- npm install
104
- and no build step is required.
105
-
106
- GENERAL OPTIONS
107
- --out <folder> Output folder (default: ./generated-contract)
108
- --lang <ts|js> Output language for generated contract sources (default: ts)
109
- --non-interactive | --yes Disable prompts (required for CI)
110
- -h | --help Show this help
111
-
112
- ENVIRONMENT
113
- QC_SOLC_PATH / SOLC / SOLC_PATH
114
- Path to solc executable used when compiling Solidity.
115
- Default: c:\\solc\\solc.exe
116
-
117
- QC_RPC_URL / QC_CHAIN_ID
118
- Used by the auto-generated transactional tests in the generated package.
119
-
120
- EXAMPLES
121
- Generate typed files from ABI+BIN into ./out:
122
- node generate-sdk.js --abi .\\artifacts\\MyContract.abi.json --bin .\\artifacts\\MyContract.bin --out .\\out --name MyContract --non-interactive
123
-
124
- Generate a new typed package from ABI+BIN:
125
- node generate-sdk.js --abi .\\My.abi.json --bin .\\My.bin --name MyContract --create-package --package-dir .\\tmp --package-name my-typed-contract --package-description "My typed contract" --package-author "me" --non-interactive
126
-
127
- Generate a new typed package from Solidity (single file):
128
- set QC_SOLC_PATH=c:\\solc\\solc.exe
129
- node generate-sdk.js --sol ".\\contracts\\MyContract.sol" --create-package --package-dir .\\tmp --package-name my-typed-contract --package-description "My typed contract" --package-author "me" --non-interactive
130
-
131
- Generate a new typed package from Solidity (multiple files):
132
- node generate-sdk.js --sol ".\\contracts\\A.sol,.\\contracts\\B.sol,.\\contracts\\lib\\C.sol" --create-package --package-dir .\\tmp --package-name my-typed-contract --package-description "My typed contract" --package-author "me" --non-interactive
133
-
134
- `.trimStart();
135
- }
136
-
137
- function _argValue(argv, name) {
138
- const idx = argv.indexOf(name);
139
- if (idx === -1) return null;
140
- return argv[idx + 1] || null;
141
- }
142
-
143
- function _hasFlag(argv, name) {
144
- return argv.includes(name);
145
- }
146
-
147
- function _normalizeLang(v) {
148
- const t = (v == null ? "ts" : String(v)).trim().toLowerCase();
149
- if (!t) return "ts";
150
- if (t === "ts" || t === "typescript") return "ts";
151
- if (t === "js" || t === "javascript") return "js";
152
- throw new Error(`Invalid --lang: ${v} (expected "ts" or "js")`);
153
- }
154
-
155
- function _basenameNoExt(p) {
156
- const b = path.basename(p);
157
- const i = b.lastIndexOf(".");
158
- return i === -1 ? b : b.slice(0, i);
159
- }
160
-
161
- function _defaultContractNameFromAbiPath(abiPath) {
162
- const b = path.basename(abiPath);
163
- if (/\.abi\.json$/i.test(b)) return b.replace(/\.abi\.json$/i, "");
164
- return _basenameNoExt(abiPath);
165
- }
166
-
167
- function _ensureDir(p) {
168
- fs.mkdirSync(p, { recursive: true });
169
- }
170
-
171
- function _readRootDependencies() {
172
- const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"));
173
- return pkg.dependencies || {};
174
- }
175
-
176
- function _readRootPackageJson() {
177
- return JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"));
178
- }
179
-
180
- function _readJson(filePath) {
181
- return JSON.parse(fs.readFileSync(filePath, "utf8"));
182
- }
183
-
184
- function _looksLikeHex(s) {
185
- if (typeof s !== "string") return false;
186
- const t = s.trim();
187
- if (!t) return false;
188
- if (t.startsWith("0x")) return /^0x[0-9a-fA-F]*$/.test(t);
189
- return /^[0-9a-fA-F]*$/.test(t);
190
- }
191
-
192
- function _readArtifactsJson(fileAbs) {
193
- const baseDir = path.dirname(fileAbs);
194
- const parsed = _readJson(fileAbs);
195
- if (!Array.isArray(parsed)) throw new Error(`Artifacts JSON must be an array: ${fileAbs}`);
196
-
197
- /** @type {Array<{ contractName: string, abi: any[], bytecode: string, docs?: any }>} */
198
- const artifacts = [];
199
-
200
- for (let i = 0; i < parsed.length; i++) {
201
- const entry = parsed[i];
202
- if (!entry || typeof entry !== "object") throw new Error(`Invalid artifacts entry at index ${i} (expected object)`);
203
-
204
- const abiField = entry.abi ?? entry.abiPath;
205
- const binField = entry.bin ?? entry.bytecode ?? entry.binPath ?? entry.bytecodePath;
206
- const nameField = entry.name ?? entry.contractName;
207
-
208
- let abi;
209
- let abiPath = null;
210
- if (typeof abiField === "string") {
211
- // Support either:
212
- // - file path to an ABI JSON file
213
- // - inline ABI JSON string (encoded ABI array)
214
- const maybePath = path.resolve(baseDir, abiField);
215
- if (fs.existsSync(maybePath) && fs.statSync(maybePath).isFile()) {
216
- abiPath = maybePath;
217
- abi = _readJson(abiPath);
218
- } else {
219
- try {
220
- abi = JSON.parse(abiField);
221
- } catch (e) {
222
- throw new Error(
223
- `Invalid "abi" for artifacts entry ${i} (expected ABI file path or ABI JSON string). Not found: ${maybePath}`,
224
- );
225
- }
226
- }
227
- } else if (Array.isArray(abiField)) {
228
- abi = abiField;
229
- } else {
230
- throw new Error(`Invalid "abi" for artifacts entry ${i} (expected path, ABI JSON string, or ABI array)`);
231
- }
232
- if (!Array.isArray(abi)) throw new Error(`ABI must be an array (entry ${i})`);
233
-
234
- let bytecodeRaw;
235
- if (typeof binField === "string") {
236
- const maybePath = path.resolve(baseDir, binField);
237
- if (fs.existsSync(maybePath) && fs.statSync(maybePath).isFile()) {
238
- bytecodeRaw = fs.readFileSync(maybePath, "utf8").trim();
239
- } else if (_looksLikeHex(binField)) {
240
- bytecodeRaw = binField.trim();
241
- } else {
242
- throw new Error(`BIN/bytecode file not found (entry ${i}): ${maybePath}`);
243
- }
244
- } else {
245
- throw new Error(`Invalid "bin" for artifacts entry ${i} (expected path or hex string)`);
246
- }
247
-
248
- const bytecode = bytecodeRaw.startsWith("0x") ? bytecodeRaw : `0x${bytecodeRaw}`;
249
-
250
- let contractName = null;
251
- if (typeof nameField === "string" && nameField.trim()) {
252
- contractName = _cap(nameField.trim());
253
- } else if (abiPath) {
254
- contractName = _cap(_defaultContractNameFromAbiPath(abiPath));
255
- } else {
256
- throw new Error(`Missing contract name for artifacts entry ${i}. Provide "name" or use abi as a path.`);
257
- }
258
-
259
- // Reject attacker-controlled contract names before they are used to
260
- // build output file paths or interpolated into generated source.
261
- assertSafeIdentifier(contractName, "contract name");
262
- artifacts.push({ contractName, abi, bytecode, docs: null });
263
- }
264
-
265
- // Ensure stable ordering and unique names
266
- artifacts.sort((a, b) => a.contractName.localeCompare(b.contractName));
267
- const seen = new Set();
268
- for (const a of artifacts) {
269
- if (seen.has(a.contractName)) throw new Error(`Duplicate contractName in artifacts JSON: ${a.contractName}`);
270
- seen.add(a.contractName);
271
- }
272
-
273
- if (artifacts.length === 0) throw new Error("Artifacts JSON contained no entries.");
274
- return artifacts;
275
- }
276
-
277
- function _rewriteFileDepsToAbsolute(deps, rootDir) {
278
- const out = { ...deps };
279
- for (const [name, ver] of Object.entries(out)) {
280
- if (typeof ver === "string" && ver.startsWith("file:")) {
281
- const rel = ver.slice("file:".length);
282
- const abs = path.resolve(rootDir, rel);
283
- out[name] = `file:${abs.replace(/\\\\/g, "/")}`;
284
- }
285
- }
286
- return out;
287
- }
288
-
289
- function _writeJson(filePath, obj) {
290
- fs.writeFileSync(filePath, JSON.stringify(obj, null, 2) + "\n", "utf8");
291
- }
292
-
293
- function _writeText(filePath, content) {
294
- fs.writeFileSync(filePath, content, "utf8");
295
- }
296
-
297
- function _findConstructor(abi) {
298
- const ctor = (abi || []).find((f) => f && f.type === "constructor");
299
- return ctor || { type: "constructor", inputs: [] };
300
- }
301
-
302
- function _solTypeToExampleValueExpr(param) {
303
- const type = typeof param === "string" ? param : String(param && param.type ? param.type : "");
304
- const internalType = typeof param === "object" && param ? String(param.internalType || "") : "";
305
- if (!type) return "undefined";
306
-
307
- // Arrays (dynamic or fixed)
308
- if (type.endsWith("]")) {
309
- const inner = type.slice(0, type.lastIndexOf("["));
310
- const bracket = type.slice(type.lastIndexOf("[") + 1, type.length - 1);
311
- const isFixed = bracket.length > 0;
312
- const fixedLen = isFixed ? Number(bracket) : 0;
313
- const elemParam = { ...(param || {}), type: inner };
314
- const elemExpr = _solTypeToExampleValueExpr(elemParam);
315
- if (isFixed && Number.isFinite(fixedLen) && fixedLen > 0) {
316
- // Fixed arrays MUST match the exact declared length.
317
- return `Array(${fixedLen}).fill(${elemExpr})`;
318
- }
319
- return `[${elemExpr}]`;
320
- }
321
-
322
- if (type === "address") return "wallet.address";
323
- if (type === "bool") return "true";
324
- if (type === "string") return JSON.stringify("hello");
325
- if (type === "bytes") return JSON.stringify("0x1234");
326
-
327
- const mBytesN = type.match(/^bytes(\d+)$/);
328
- if (mBytesN) {
329
- const n = Number(mBytesN[1]);
330
- if (Number.isFinite(n) && n >= 1 && n <= 32) return JSON.stringify(`0x${"11".repeat(n)}`);
331
- }
332
-
333
- // Use plain numbers/strings for ints/uints.
334
- if (type.startsWith("uint") && /\benum\b/.test(internalType)) return "1";
335
- if (type.startsWith("uint")) return "123";
336
- if (type.startsWith("int")) return "-123";
337
-
338
- if (type === "tuple") {
339
- const comps = Array.isArray(param && param.components) ? param.components : [];
340
- if (comps.length === 0) return "{}";
341
- const fields = comps.map((c, idx) => {
342
- const name = c && typeof c.name === "string" && c.name ? c.name : `field${idx}`;
343
- return `${JSON.stringify(name)}: ${_solTypeToExampleValueExpr(c)}`;
344
- });
345
- return `{ ${fields.join(", ")} }`;
346
- }
347
-
348
- return "undefined";
349
- }
350
-
351
- function _parseCommaSeparatedFiles(v) {
352
- if (!v) return [];
353
- return v
354
- .split(",")
355
- .map((s) => s.trim())
356
- .filter(Boolean);
357
- }
358
-
359
- function _parseSolcExtraArgs(raw) {
360
- if (!raw) return [];
361
- const t = String(raw).trim();
362
- if (!t) return [];
363
-
364
- // Allow a JSON array string: ["--via-ir","--evm-version","london"]
365
- if (t.startsWith("[")) {
366
- const arr = JSON.parse(t);
367
- if (!Array.isArray(arr) || !arr.every((x) => typeof x === "string")) {
368
- throw new Error(`--solc-args JSON must be a string[] (got: ${t.slice(0, 80)}${t.length > 80 ? "..." : ""})`);
369
- }
370
- return arr.filter((s) => s.trim()).map((s) => s.trim());
371
- }
372
-
373
- // Otherwise treat as a single string of space-separated args (basic quoting support).
374
- /** @type {string[]} */
375
- const out = [];
376
- let cur = "";
377
- let inQuote = null; // "'" | "\""
378
- let escaping = false;
379
-
380
- for (let i = 0; i < t.length; i++) {
381
- const ch = t[i];
382
-
383
- if (escaping) {
384
- cur += ch;
385
- escaping = false;
386
- continue;
387
- }
388
-
389
- if (ch === "\\") {
390
- // allow escaping inside quotes (and harmless outside)
391
- escaping = true;
392
- continue;
393
- }
394
-
395
- if (inQuote) {
396
- if (ch === inQuote) {
397
- inQuote = null;
398
- } else {
399
- cur += ch;
400
- }
401
- continue;
402
- }
403
-
404
- if (ch === '"' || ch === "'") {
405
- inQuote = ch;
406
- continue;
407
- }
408
-
409
- if (/\s/.test(ch)) {
410
- if (cur) out.push(cur);
411
- cur = "";
412
- continue;
413
- }
414
-
415
- cur += ch;
416
- }
417
-
418
- if (cur) out.push(cur);
419
- return out;
420
- }
421
-
422
- function _resolveSolcPath(argv) {
423
- const solcArg = _argValue(argv, "--solc") || _argValue(argv, "--solc-path") || _argValue(argv, "--solcPath");
424
- const env =
425
- solcArg ||
426
- process.env.QC_SOLC_PATH ||
427
- process.env.SOLC ||
428
- process.env.SOLC_PATH ||
429
- process.env.solc ||
430
- null;
431
- return env || "c:\\solc\\solc.exe";
432
- }
433
-
434
- function _assertSolcExists(solcPath) {
435
- if (!fs.existsSync(solcPath)) {
436
- throw new Error(
437
- `solc not found at ${solcPath}. Set env QC_SOLC_PATH or SOLC (e.g. c:\\\\solc\\\\solc.exe) or pass --solc <path>.`,
438
- );
439
- }
440
- }
441
-
442
- function _compileSolidityToArtifacts({ solcPath, solFilesAbs, contractNameFilter, solcExtraArgs }) {
443
- _assertSolcExists(solcPath);
444
- const extra = Array.isArray(solcExtraArgs) ? solcExtraArgs : [];
445
- const base = extra.includes("--optimize") ? [] : ["--optimize"];
446
- const out = execFileSync(solcPath, [...base, ...extra, "--combined-json", "abi,bin", ...solFilesAbs], { encoding: "utf8" });
447
- const parsed = JSON.parse(out);
448
-
449
- const artifacts = [];
450
- for (const key of Object.keys(parsed.contracts || {})) {
451
- const entry = parsed.contracts[key];
452
- const name = key.includes(":") ? key.split(":").pop() : key;
453
- if (!name) continue;
454
- if (contractNameFilter && name !== contractNameFilter) continue;
455
- const abi = entry && entry.abi ? JSON.parse(entry.abi) : null;
456
- const bin = entry && typeof entry.bin === "string" ? entry.bin : "";
457
- if (!abi || !Array.isArray(abi)) continue;
458
- if (!bin) continue; // skip abstract/interfaces
459
- // Validate before _writeSolcArtifacts uses the name to build paths.
460
- assertSafeIdentifier(name, "contract name");
461
- artifacts.push({ contractName: name, abi, bytecode: bin.startsWith("0x") ? bin : `0x${bin}` });
462
- }
463
-
464
- if (contractNameFilter && artifacts.length === 0) {
465
- throw new Error(`No compiled contract matched --name ${contractNameFilter}`);
466
- }
467
- if (artifacts.length === 0) {
468
- throw new Error("No deployable contracts found in solc output (empty bytecode).");
469
- }
470
-
471
- // Stable ordering
472
- artifacts.sort((a, b) => a.contractName.localeCompare(b.contractName));
473
- return artifacts;
474
- }
475
-
476
- function _writeSolcArtifacts(outRoot, artifacts) {
477
- const artifactsDir = path.join(outRoot, "artifacts");
478
- _ensureDir(artifactsDir);
479
- for (const a of artifacts) {
480
- _writeText(path.join(artifactsDir, `${a.contractName}.abi.json`), JSON.stringify(a.abi, null, 2) + "\n");
481
- _writeText(path.join(artifactsDir, `${a.contractName}.bin`), a.bytecode + "\n");
482
- }
483
- }
484
-
485
- function _normalizeSolDoc(text) {
486
- if (!text) return "";
487
- return text
488
- .split(/\r?\n/g)
489
- .map((l) => l.trim())
490
- .filter(Boolean)
491
- .map((l) => {
492
- // Normalize common NatSpec tags into plain text (but keep @param/@return as-is)
493
- if (l.startsWith("@title ")) return l.slice("@title ".length).trim();
494
- if (l.startsWith("@notice ")) return l.slice("@notice ".length).trim();
495
- if (l.startsWith("@dev ")) return l.slice("@dev ".length).trim();
496
- return l;
497
- })
498
- .filter(Boolean)
499
- // Defense-in-depth: doc text is later embedded inside generated `/** ... */`
500
- // JSDoc blocks. Neutralize comment delimiters here too so a `*/` in NatSpec can
501
- // never close the generated comment early and inject executable code.
502
- .map((l) => l.replace(/\*\//g, "* /").replace(/\/\*/g, "/ *"))
503
- .join("\n")
504
- .trim();
505
- }
506
-
507
- function _extractSolDocs(solFilesAbs) {
508
- /** @type {Record<string, { contract?: string, functions: Record<string,string> }>} */
509
- const out = {};
510
-
511
- for (const file of solFilesAbs) {
512
- const src = fs.readFileSync(file, "utf8");
513
- const lines = src.split(/\r?\n/g);
514
-
515
- let pending = [];
516
- let inBlock = false;
517
- let currentContract = null;
518
-
519
- const flushPending = () => {
520
- const s = _normalizeSolDoc(pending.join("\n"));
521
- pending = [];
522
- return s;
523
- };
524
-
525
- for (let i = 0; i < lines.length; i++) {
526
- const raw = lines[i];
527
- const t = raw.trim();
528
-
529
- if (inBlock) {
530
- // Capture block comment content lines, stripping leading '*' and the closing '*/'
531
- const endIdx = raw.indexOf("*/");
532
- const content = endIdx !== -1 ? raw.slice(0, endIdx) : raw;
533
- const cleaned = content.replace(/^\s*\*\s?/, "").trim();
534
- if (cleaned) pending.push(cleaned);
535
- if (endIdx !== -1) inBlock = false;
536
- continue;
537
- }
538
-
539
- // Solidity NatSpec / doc comments
540
- if (t.startsWith("/**")) {
541
- inBlock = true;
542
- // Capture anything after '/**' on the same line and handle one-line comments.
543
- const startIdx = raw.indexOf("/**") + 3;
544
- const rest = raw.slice(startIdx);
545
- const endIdx = rest.indexOf("*/");
546
- const content = endIdx !== -1 ? rest.slice(0, endIdx) : rest;
547
- const cleaned = content.replace(/^\s*\*\s?/, "").trim();
548
- if (cleaned) pending.push(cleaned);
549
- if (endIdx !== -1) inBlock = false;
550
- continue;
551
- }
552
- if (t.startsWith("///")) {
553
- pending.push(t.slice(3).trim());
554
- continue;
555
- }
556
-
557
- // Skip empty lines without breaking pending docs
558
- if (!t) continue;
559
-
560
- // Contract/interface/library declaration
561
- const cMatch = t.match(/^(contract|interface|library)\s+([A-Za-z_][A-Za-z0-9_]*)\b/);
562
- if (cMatch) {
563
- const name = cMatch[2];
564
- const doc = flushPending();
565
- currentContract = name;
566
- if (!out[name]) out[name] = { contract: "", functions: {} };
567
- if (doc) out[name].contract = doc;
568
- continue;
569
- }
570
-
571
- // Function declaration
572
- const fMatch = t.match(/^function\s+([A-Za-z_][A-Za-z0-9_]*)\b/);
573
- if (fMatch && currentContract) {
574
- const fn = fMatch[1];
575
- const doc = flushPending();
576
- if (!out[currentContract]) out[currentContract] = { contract: "", functions: {} };
577
- if (doc) out[currentContract].functions[fn] = doc;
578
- continue;
579
- }
580
-
581
- // If we hit a real code line that's not a declaration, discard any pending doc
582
- pending = [];
583
- }
584
- }
585
-
586
- // Normalize all docs
587
- for (const k of Object.keys(out)) {
588
- out[k].contract = _normalizeSolDoc(out[k].contract || "");
589
- for (const fn of Object.keys(out[k].functions || {})) {
590
- out[k].functions[fn] = _normalizeSolDoc(out[k].functions[fn]);
591
- }
592
- }
593
-
594
- return out;
595
- }
596
-
597
- function _renderPackageIndexJs({ artifacts, entryDir }) {
598
- const dir = entryDir || "dist";
599
- const lines = [];
600
- lines.push("/**");
601
- lines.push(" * Auto-generated typed contract package.");
602
- lines.push(" *");
603
- lines.push(` * This file re-exports the package entry bundle in \`${dir}/\`.`);
604
- lines.push(" */");
605
- lines.push("");
606
- lines.push(`const entry = require("./${dir}");`);
607
- lines.push("Object.assign(exports, entry);");
608
- lines.push("");
609
-
610
- for (const a of artifacts) {
611
- const doc = a.docs && typeof a.docs.contract === "string" ? a.docs.contract : "";
612
- if (doc && doc.trim()) {
613
- lines.push("/**");
614
- for (const l of doc.split(/\r?\n/g)) {
615
- const t = l.trim();
616
- if (!t) continue;
617
- lines.push(` * ${t}`);
618
- }
619
- lines.push(" */");
620
- } else {
621
- lines.push("/**");
622
- lines.push(` * ${a.contractName}`);
623
- lines.push(" */");
624
- }
625
- lines.push(`exports.${a.contractName} = entry.${a.contractName};`);
626
- lines.push(`exports.${a.contractName}__factory = entry.${a.contractName}__factory;`);
627
- lines.push("");
628
- }
629
-
630
- return lines.join("\n") + "\n";
631
- }
632
-
633
- function _quoteIfNeeded(s) {
634
- if (typeof s !== "string") return s;
635
- return /[ \t"]/g.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s;
636
- }
637
-
638
- function _npmCmd() {
639
- return process.platform === "win32" ? "npm.cmd" : "npm";
640
- }
641
-
642
- function _runNpm(args, cwd) {
643
- if (process.platform === "win32") {
644
- const cmd = `${_npmCmd()} ${args.map(_quoteIfNeeded).join(" ")}`;
645
- const res = spawnSync("cmd.exe", ["/d", "/s", "/c", cmd], { cwd, encoding: "utf8", stdio: "inherit" });
646
- if (res.error) throw res.error;
647
- if (res.status !== 0) throw new Error(`npm command failed: ${cmd}`);
648
- return;
649
- }
650
-
651
- const res = spawnSync(_npmCmd(), args, { cwd, encoding: "utf8", stdio: "inherit" });
652
- if (res.error) throw res.error;
653
- if (res.status !== 0) throw new Error(`npm command failed: ${_npmCmd()} ${args.join(" ")}`);
654
- }
655
-
656
- async function main() {
657
- const argv = process.argv.slice(2);
658
-
659
- if (argv.length === 0 || _hasFlag(argv, "--help") || _hasFlag(argv, "-h")) {
660
- process.stdout.write(_helpText());
661
- process.exitCode = 0;
662
- return;
663
- }
664
-
665
- const abiPathArg = _argValue(argv, "--abi");
666
- const binPathArg = _argValue(argv, "--bin");
667
- const solArg = _argValue(argv, "--sol") || _argValue(argv, "--sol-files") || _argValue(argv, "--solFiles");
668
- const solcArgsRaw = _argValue(argv, "--solc-args") || _argValue(argv, "--solcArgs");
669
- const artifactsJsonArg =
670
- _argValue(argv, "--artifacts-json") || _argValue(argv, "--artifactsJson") || _argValue(argv, "--artifacts");
671
- const outArg = _argValue(argv, "--out");
672
- const nameArg = _argValue(argv, "--name");
673
- const nonInteractive = _hasFlag(argv, "--non-interactive") || _hasFlag(argv, "--yes");
674
- const createPackageFlag = _hasFlag(argv, "--create-package");
675
- const pkgDirArg = _argValue(argv, "--package-dir");
676
- const pkgNameArg = _argValue(argv, "--package-name");
677
- const pkgDescArg = _argValue(argv, "--package-description") || "";
678
- const pkgAuthorArg = _argValue(argv, "--package-author") || "";
679
- const pkgLicenseArg = _argValue(argv, "--package-license") || "MIT";
680
- const pkgVersionArg = _argValue(argv, "--package-version") || "0.0.1";
681
- const lang = _normalizeLang(_argValue(argv, "--lang") || _argValue(argv, "--language") || _argValue(argv, "--type"));
682
-
683
- // Decide input type.
684
- let inputType = null; // "abibin" | "sol" | "artifactsjson"
685
- if (solArg) inputType = "sol";
686
- if (artifactsJsonArg) inputType = inputType || "artifactsjson";
687
- if (abiPathArg || binPathArg) inputType = inputType || "abibin";
688
- if ((solArg ? 1 : 0) + (artifactsJsonArg ? 1 : 0) + (abiPathArg || binPathArg ? 1 : 0) > 1) {
689
- throw new Error("Select only one input mode: --abi/--bin OR --sol OR --artifacts-json.");
690
- }
691
-
692
- let createPackage = false;
693
- let outDir = outArg ? path.resolve(outArg) : null;
694
- let contractName = nameArg || null;
695
-
696
- // Interactive prompt: ask input type first.
697
- let absAbi = null;
698
- let absBin = null;
699
- let solFilesAbs = [];
700
- let artifactsJsonAbs = null;
701
- const solcExtraArgs = solcArgsRaw ? _parseSolcExtraArgs(solcArgsRaw) : [];
702
-
703
- if (!nonInteractive) {
704
- const rl0 = readline.createInterface({ input: stdin, output: stdout });
705
- try {
706
- if (!inputType) {
707
- const ans = (await rl0.question("Input type? (1) ABI+BIN (2) SOL (3) ARTIFACTS JSON ")).trim();
708
- inputType = ans === "2" ? "sol" : ans === "3" ? "artifactsjson" : "abibin";
709
- }
710
- if (inputType === "abibin") {
711
- const abiP = abiPathArg || (await rl0.question("Enter ABI path (.json): ")).trim();
712
- const binP = binPathArg || (await rl0.question("Enter bytecode path (.bin): ")).trim();
713
- if (!abiP || !binP) throw new Error("Missing ABI/BIN paths.");
714
- absAbi = path.resolve(abiP);
715
- absBin = path.resolve(binP);
716
- if (!fs.existsSync(absAbi)) throw new Error(`ABI file not found: ${absAbi}`);
717
- if (!fs.existsSync(absBin)) throw new Error(`Bytecode file not found: ${absBin}`);
718
- contractName = contractName || _cap(_defaultContractNameFromAbiPath(absAbi));
719
- } else if (inputType === "sol") {
720
- const solP = solArg || (await rl0.question("Enter Solidity file(s) (comma-separated): ")).trim();
721
- const files = _parseCommaSeparatedFiles(solP);
722
- if (files.length === 0) throw new Error("Missing Solidity file(s).");
723
- solFilesAbs = files.map((p) => path.resolve(p));
724
- for (const f of solFilesAbs) {
725
- if (!fs.existsSync(f)) throw new Error(`Solidity file not found: ${f}`);
726
- }
727
- if (!contractName) {
728
- const maybe = (await rl0.question("Contract name (optional; empty = generate all): ")).trim();
729
- if (maybe) contractName = maybe;
730
- }
731
- } else {
732
- const p = artifactsJsonArg || (await rl0.question("Enter artifacts JSON path (.json): ")).trim();
733
- if (!p) throw new Error("Missing artifacts JSON path.");
734
- artifactsJsonAbs = path.resolve(p);
735
- if (!fs.existsSync(artifactsJsonAbs)) throw new Error(`Artifacts JSON file not found: ${artifactsJsonAbs}`);
736
- }
737
- } finally {
738
- rl0.close();
739
- }
740
- }
741
-
742
- // Non-interactive input validation
743
- if (nonInteractive) {
744
- if (!inputType) {
745
- throw new Error("Select an input type: pass --abi/--bin OR pass --sol <file1.sol,file2.sol> OR pass --artifacts-json <file.json>.");
746
- }
747
- if (inputType === "abibin") {
748
- if (!abiPathArg || !binPathArg) {
749
- throw new Error("Missing required arguments: --abi <path> --bin <path>");
750
- }
751
- absAbi = path.resolve(abiPathArg);
752
- absBin = path.resolve(binPathArg);
753
- if (!fs.existsSync(absAbi)) throw new Error(`ABI file not found: ${absAbi}`);
754
- if (!fs.existsSync(absBin)) throw new Error(`Bytecode file not found: ${absBin}`);
755
- contractName = contractName || _cap(_defaultContractNameFromAbiPath(absAbi));
756
- } else if (inputType === "sol") {
757
- const files = _parseCommaSeparatedFiles(solArg);
758
- if (files.length === 0) throw new Error("Missing required argument: --sol <file1.sol,file2.sol>");
759
- solFilesAbs = files.map((p) => path.resolve(p));
760
- for (const f of solFilesAbs) {
761
- if (!fs.existsSync(f)) throw new Error(`Solidity file not found: ${f}`);
762
- }
763
- // contractName can be null => generate all
764
- } else {
765
- if (!artifactsJsonArg) throw new Error("Missing required argument: --artifacts-json <path/to/artifacts.json>");
766
- artifactsJsonAbs = path.resolve(artifactsJsonArg);
767
- if (!fs.existsSync(artifactsJsonAbs)) throw new Error(`Artifacts JSON file not found: ${artifactsJsonAbs}`);
768
- }
769
- }
770
-
771
- if (createPackageFlag) {
772
- createPackage = true;
773
- }
774
-
775
- if (!nonInteractive && !createPackageFlag) {
776
- const rl = readline.createInterface({ input: stdin, output: stdout });
777
- try {
778
- const ans = (await rl.question("Do you want to create a new package? (Y/N) ")).trim().toLowerCase();
779
- createPackage = ans === "y" || ans === "yes";
780
-
781
- if (createPackage) {
782
- const pkgFolder = (await rl.question("Enter the folder path where the package should be created: ")).trim();
783
- const pkgName = (await rl.question("Enter package name: ")).trim();
784
- const pkgDesc = (await rl.question("Enter package description: ")).trim();
785
- const pkgAuthor = (await rl.question("Enter author name: ")).trim();
786
- const pkgLicense = (await rl.question("Enter license (default: MIT): ")).trim() || "MIT";
787
- const pkgVersion = (await rl.question("Enter version (default: 0.0.1): ")).trim() || "0.0.1";
788
-
789
- outDir = path.resolve(pkgFolder, pkgName);
790
- _ensureDir(outDir);
791
-
792
- _createPackageScaffold({
793
- outDir,
794
- pkgName,
795
- pkgDesc,
796
- pkgAuthor,
797
- pkgLicense,
798
- pkgVersion,
799
- lang,
800
- });
801
- } else {
802
- const target = (await rl.question("Enter the location in your existing package (relative to package root): ")).trim();
803
- outDir = path.resolve(process.cwd(), target || "src/contracts");
804
- }
805
- } finally {
806
- rl.close();
807
- }
808
- }
809
-
810
- if (createPackage && nonInteractive) {
811
- const pkgFolder = pkgDirArg ? path.resolve(pkgDirArg) : null;
812
- const pkgName = pkgNameArg || null;
813
- if (!pkgFolder || !pkgName) {
814
- throw new Error("When using --create-package in non-interactive mode, pass --package-dir <dir> and --package-name <name>.");
815
- }
816
- outDir = path.resolve(pkgFolder, pkgName);
817
- _ensureDir(outDir);
818
- _createPackageScaffold({
819
- outDir,
820
- pkgName,
821
- pkgDesc: pkgDescArg,
822
- pkgAuthor: pkgAuthorArg,
823
- pkgLicense: pkgLicenseArg,
824
- pkgVersion: pkgVersionArg,
825
- lang,
826
- });
827
- }
828
-
829
- if (!outDir) outDir = path.resolve(process.cwd(), "generated-contract");
830
-
831
- const targetSrcDir = createPackage ? path.join(outDir, "src") : outDir;
832
- _ensureDir(targetSrcDir);
833
-
834
- // Resolve compilation / artifacts
835
- /** @type {Array<{ contractName: string, abi: any[], bytecode: string }>} */
836
- let artifacts = [];
837
- if (inputType === "abibin") {
838
- const abi = _readJson(absAbi);
839
- const bytecodeRaw = fs.readFileSync(absBin, "utf8").trim();
840
- const bytecode = bytecodeRaw.startsWith("0x") ? bytecodeRaw : `0x${bytecodeRaw}`;
841
- artifacts = [{ contractName, abi, bytecode, docs: null }];
842
- } else if (inputType === "sol") {
843
- const solcPath = _resolveSolcPath(argv);
844
- artifacts = _compileSolidityToArtifacts({ solcPath, solFilesAbs, contractNameFilter: contractName, solcExtraArgs });
845
-
846
- // Attach Solidity doc comments (NatSpec) to artifacts
847
- const docsByContract = _extractSolDocs(solFilesAbs);
848
- for (const a of artifacts) {
849
- a.docs = docsByContract[a.contractName] || null;
850
- }
851
-
852
- // As requested: emit ABI/BIN artifacts to disk
853
- _writeSolcArtifacts(createPackage ? outDir : targetSrcDir, artifacts);
854
- } else {
855
- // Artifacts JSON
856
- artifacts = _readArtifactsJson(artifactsJsonAbs || path.resolve(artifactsJsonArg));
857
- }
858
-
859
- // Final guard — every contract name used for code generation and for
860
- // building output/example/test file paths must be a safe identifier.
861
- for (const a of artifacts) {
862
- assertSafeIdentifier(a && a.contractName, "contract name");
863
- }
864
-
865
- if (artifacts.length === 1) {
866
- // Keep the old API/behavior for single-contract generation.
867
- const a = artifacts[0];
868
- generateFromArtifacts({ outDir: targetSrcDir, artifacts: [a], lang });
869
- } else {
870
- generateFromArtifacts({ outDir: targetSrcDir, artifacts, lang });
871
- }
872
-
873
- if (createPackage) {
874
- _writeText(
875
- path.join(outDir, "README.md"),
876
- _packageReadme({
877
- pkgName: pkgNameArg || path.basename(outDir),
878
- pkgDesc: pkgDescArg,
879
- artifacts,
880
- createdFromSolidity: inputType === "sol",
881
- lang,
882
- }),
883
- );
884
-
885
- // Transactional tests (always per-contract)
886
- _ensureDir(path.join(outDir, "test", "e2e"));
887
- _ensureDir(path.join(outDir, "examples"));
888
-
889
- // Shared helper for examples (keeps examples runnable via plain `node`).
890
- // WARNING: test-only wallet; never use for real funds.
891
- _writeText(
892
- path.join(outDir, "examples", "_test-wallet.js"),
893
- `const { Wallet } = require("quantumcoin");\n\n// 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.)\nconst TEST_WALLET_ENCRYPTED_JSON =\n ${JSON.stringify(
894
- "{\"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}",
895
- )};\nconst TEST_WALLET_PASSPHRASE = \"QuantumCoinExample123!\";\n\nfunction createTestWallet(provider) {\n // Caller must have called Initialize() first.\n return Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);\n}\n\nmodule.exports = {\n TEST_WALLET_ENCRYPTED_JSON,\n TEST_WALLET_PASSPHRASE,\n createTestWallet,\n};\n`,
896
- );
897
-
898
- // TypeScript _test-wallet (for TS examples)
899
- _writeText(
900
- path.join(outDir, "examples", "_test-wallet.ts"),
901
- `import { Wallet } from "quantumcoin";
902
-
903
- // 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.)
904
- export const TEST_WALLET_ENCRYPTED_JSON =
905
- ${JSON.stringify(
906
- "{\"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}",
907
- )};
908
- export const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
909
-
910
- export function createTestWallet(provider: unknown) {
911
- return Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
912
- }
913
- `,
914
- );
915
-
916
- for (const a of artifacts) {
917
- _writeText(
918
- path.join(outDir, "test", "e2e", `${a.contractName}.e2e.test.js`),
919
- generateTransactionalTestJs({ contractName: a.contractName, abi: a.abi, bytecode: a.bytecode }),
920
- );
921
- }
922
-
923
- if (artifacts.length > 1) {
924
- _writeText(
925
- path.join(outDir, "test", "e2e", "all-contracts.e2e.test.js"),
926
- generateAllContractsTransactionalTestJs({
927
- artifacts: artifacts.map((a) => ({ contractName: a.contractName, abi: a.abi, bytecode: a.bytecode })),
928
- }),
929
- );
930
- }
931
-
932
- if (artifacts.length === 1) {
933
- // Back-compat: keep original example filenames for a single-contract package.
934
- const a = artifacts[0];
935
- const ctor = _findConstructor(a.abi);
936
- const ctorArgsExpr = (ctor.inputs || []).map((i) => _solTypeToExampleValueExpr(i)).join(", ");
937
-
938
- _writeText(
939
- path.join(outDir, "examples", "deploy.js"),
940
- `/**
941
- * Deploy example (generated).
942
- *
943
- * Requires:
944
- * - QC_RPC_URL env var
945
- *
946
- * WARNING: uses a hardcoded test wallet (funded) for convenience.
947
- */
948
- const { Initialize } = require("quantumcoin/config");
949
- const { getProvider, Wallet } = require("quantumcoin");
950
- const { ${a.contractName}__factory } = require("..");
951
-
952
- // 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.)
953
- const TEST_WALLET_ENCRYPTED_JSON =
954
- ${JSON.stringify(
955
- "{\"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}",
956
- )};
957
- const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
958
-
959
- async function main() {
960
- const rpcUrl = process.env.QC_RPC_URL;
961
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
962
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
963
- await Initialize(null);
964
-
965
- const provider = getProvider(rpcUrl, chainId);
966
- const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
967
-
968
- const factory = new ${a.contractName}__factory(wallet);
969
- const contract = await factory.deploy(${ctorArgsExpr}${ctorArgsExpr ? ", " : ""}{ gasLimit: 600000 });
970
- const tx = contract.deployTransaction();
971
- if (tx) await tx.wait(1, 600_000);
972
-
973
- console.log("Deployed at:", contract.target);
974
- console.log("Next:");
975
- console.log(' $env:CONTRACT_ADDRESS="' + contract.target + '"');
976
- console.log(" node examples/read-operations.js");
977
- }
978
-
979
- main().catch((e) => {
980
- console.error(e);
981
- process.exitCode = 1;
982
- });
983
- `,
984
- );
985
-
986
- _writeText(
987
- path.join(outDir, "examples", "deploy.ts"),
988
- `/**
989
- * Deploy example (generated) - TypeScript.
990
- *
991
- * Requires:
992
- * - QC_RPC_URL env var
993
- *
994
- * WARNING: uses a hardcoded test wallet (funded) for convenience.
995
- */
996
- import { Initialize } from "quantumcoin/config";
997
- import { getProvider, Wallet } from "quantumcoin";
998
- import { ${a.contractName}__factory } from "..";
999
-
1000
- // 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.)
1001
- const TEST_WALLET_ENCRYPTED_JSON =
1002
- ${JSON.stringify(
1003
- "{\"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}",
1004
- )};
1005
- const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
1006
-
1007
- async function main(): Promise<void> {
1008
- const rpcUrl = process.env.QC_RPC_URL;
1009
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1010
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1011
- await Initialize(null);
1012
-
1013
- const provider = getProvider(rpcUrl, chainId);
1014
- const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
1015
-
1016
- const factory = new ${a.contractName}__factory(wallet);
1017
- const contract = await factory.deploy(${ctorArgsExpr}${ctorArgsExpr ? ", " : ""}{ gasLimit: 600000 });
1018
- const tx = contract.deployTransaction();
1019
- if (tx) await tx.wait(1, 600_000);
1020
-
1021
- console.log("Deployed at:", contract.target);
1022
- console.log("Next:");
1023
- console.log(' $env:CONTRACT_ADDRESS="' + contract.target + '"');
1024
- console.log(" npx tsx examples/read-operations.ts");
1025
- }
1026
-
1027
- main().catch((e) => {
1028
- console.error(e);
1029
- process.exitCode = 1;
1030
- });
1031
- `,
1032
- );
1033
-
1034
- _writeText(
1035
- path.join(outDir, "examples", "read-operations.js"),
1036
- `/**
1037
- * Read operations example (generated).
1038
- *
1039
- * Requires:
1040
- * - QC_RPC_URL env var
1041
- * - CONTRACT_ADDRESS env var
1042
- */
1043
- const { Initialize } = require("quantumcoin/config");
1044
- const { getProvider } = require("quantumcoin");
1045
- const { ${a.contractName} } = require("..");
1046
-
1047
- async function main() {
1048
- const rpcUrl = process.env.QC_RPC_URL;
1049
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1050
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1051
- const address = process.env.CONTRACT_ADDRESS;
1052
- if (!address) throw new Error("CONTRACT_ADDRESS is required");
1053
- await Initialize(null);
1054
-
1055
- const provider = getProvider(rpcUrl, chainId);
1056
- const contract = ${a.contractName}.connect(address, provider);
1057
-
1058
- console.log("Contract:", contract.target);
1059
-
1060
- if (typeof contract.name === "function") {
1061
- console.log("name():", await contract.name());
1062
- }
1063
- if (typeof contract.symbol === "function") {
1064
- console.log("symbol():", await contract.symbol());
1065
- }
1066
- if (typeof contract.totalSupply === "function") {
1067
- // Generated wrappers already unwrap single-return values to a hard type.
1068
- const v = await contract.totalSupply();
1069
- console.log("totalSupply():", v.toString());
1070
- }
1071
- if (typeof contract.balanceOf === "function" && process.env.WALLET_ADDRESS) {
1072
- // Generated wrappers already unwrap single-return values to a hard type.
1073
- const v = await contract.balanceOf(process.env.WALLET_ADDRESS);
1074
- console.log("balanceOf(WALLET_ADDRESS):", v.toString());
1075
- }
1076
- }
1077
-
1078
- main().catch((e) => {
1079
- console.error(e);
1080
- process.exitCode = 1;
1081
- });
1082
- `,
1083
- );
1084
-
1085
- _writeText(
1086
- path.join(outDir, "examples", "read-operations.ts"),
1087
- `/**
1088
- * Read operations example (generated) - TypeScript.
1089
- *
1090
- * Requires:
1091
- * - QC_RPC_URL env var
1092
- * - CONTRACT_ADDRESS env var
1093
- */
1094
- import { Initialize } from "quantumcoin/config";
1095
- import { getProvider } from "quantumcoin";
1096
- import { ${a.contractName} } from "..";
1097
-
1098
- async function main(): Promise<void> {
1099
- const rpcUrl = process.env.QC_RPC_URL;
1100
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1101
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1102
- const address = process.env.CONTRACT_ADDRESS;
1103
- if (!address) throw new Error("CONTRACT_ADDRESS is required");
1104
- await Initialize(null);
1105
-
1106
- const provider = getProvider(rpcUrl, chainId);
1107
- const contract = ${a.contractName}.connect(address, provider);
1108
-
1109
- console.log("Contract:", contract.target);
1110
-
1111
- if (typeof contract.name === "function") {
1112
- console.log("name():", await contract.name());
1113
- }
1114
- if (typeof contract.symbol === "function") {
1115
- console.log("symbol():", await contract.symbol());
1116
- }
1117
- if (typeof contract.totalSupply === "function") {
1118
- const v = await contract.totalSupply();
1119
- console.log("totalSupply():", v.toString());
1120
- }
1121
- if (typeof contract.balanceOf === "function" && process.env.WALLET_ADDRESS) {
1122
- const v = await contract.balanceOf(process.env.WALLET_ADDRESS);
1123
- console.log("balanceOf(WALLET_ADDRESS):", v.toString());
1124
- }
1125
- }
1126
-
1127
- main().catch((e) => {
1128
- console.error(e);
1129
- process.exitCode = 1;
1130
- });
1131
- `,
1132
- );
1133
-
1134
- _writeText(
1135
- path.join(outDir, "examples", "write-operations.js"),
1136
- `/**
1137
- * Write operations example (generated).
1138
- *
1139
- * Requires:
1140
- * - QC_RPC_URL env var
1141
- * - CONTRACT_ADDRESS env var
1142
- *
1143
- * WARNING: uses a hardcoded test wallet (funded) for convenience.
1144
- */
1145
- const { Initialize } = require("quantumcoin/config");
1146
- const { getProvider, Wallet } = require("quantumcoin");
1147
- const { ${a.contractName} } = require("..");
1148
-
1149
- // 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.)
1150
- const TEST_WALLET_ENCRYPTED_JSON =
1151
- ${JSON.stringify(
1152
- "{\"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}",
1153
- )};
1154
- const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
1155
-
1156
- async function main() {
1157
- const rpcUrl = process.env.QC_RPC_URL;
1158
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1159
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1160
- const address = process.env.CONTRACT_ADDRESS;
1161
- if (!address) throw new Error("CONTRACT_ADDRESS is required");
1162
- await Initialize(null);
1163
-
1164
- const provider = getProvider(rpcUrl, chainId);
1165
- const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
1166
- const contract = ${a.contractName}.connect(address, wallet);
1167
-
1168
- if (typeof contract.approve === "function") {
1169
- const tx = await contract.approve(wallet.address, 123, { gasLimit: 200000 });
1170
- await tx.wait(1, 600_000);
1171
- console.log("approve(wallet.address, 123) succeeded");
1172
- return;
1173
- }
1174
-
1175
- console.log("No known write method template for this ABI.");
1176
- }
1177
-
1178
- main().catch((e) => {
1179
- console.error(e);
1180
- process.exitCode = 1;
1181
- });
1182
- `,
1183
- );
1184
-
1185
- _writeText(
1186
- path.join(outDir, "examples", "write-operations.ts"),
1187
- `/**
1188
- * Write operations example (generated) - TypeScript.
1189
- *
1190
- * Requires:
1191
- * - QC_RPC_URL env var
1192
- * - CONTRACT_ADDRESS env var
1193
- *
1194
- * WARNING: uses a hardcoded test wallet (funded) for convenience.
1195
- */
1196
- import { Initialize } from "quantumcoin/config";
1197
- import { getProvider, Wallet } from "quantumcoin";
1198
- import { ${a.contractName} } from "..";
1199
-
1200
- // 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.)
1201
- const TEST_WALLET_ENCRYPTED_JSON =
1202
- ${JSON.stringify(
1203
- "{\"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}",
1204
- )};
1205
- const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
1206
-
1207
- async function main(): Promise<void> {
1208
- const rpcUrl = process.env.QC_RPC_URL;
1209
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1210
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1211
- const address = process.env.CONTRACT_ADDRESS;
1212
- if (!address) throw new Error("CONTRACT_ADDRESS is required");
1213
- await Initialize(null);
1214
-
1215
- const provider = getProvider(rpcUrl, chainId);
1216
- const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
1217
- const contract = ${a.contractName}.connect(address, wallet);
1218
-
1219
- if (typeof contract.approve === "function") {
1220
- const tx = await contract.approve(wallet.address, 123, { gasLimit: 200000 });
1221
- await tx.wait(1, 600_000);
1222
- console.log("approve(wallet.address, 123) succeeded");
1223
- return;
1224
- }
1225
-
1226
- console.log("No known write method template for this ABI.");
1227
- }
1228
-
1229
- main().catch((e) => {
1230
- console.error(e);
1231
- process.exitCode = 1;
1232
- });
1233
- `,
1234
- );
1235
-
1236
- _writeText(
1237
- path.join(outDir, "examples", "offline-signing.js"),
1238
- `/**
1239
- * Offline signing example (generated).
1240
- *
1241
- * Demonstrates:
1242
- * - ${a.contractName}__factory.getDeployTransaction(...)
1243
- * - contract.populateTransaction.<method>(...)
1244
- * - wallet.signTransaction(txReq) (offline) + provider.sendRawTransaction(rawTx)
1245
- *
1246
- * Requires:
1247
- * - QC_RPC_URL env var
1248
- *
1249
- * WARNING: uses a hardcoded test wallet (funded) for convenience.
1250
- */
1251
- const { Initialize } = require("quantumcoin/config");
1252
- const { getProvider, Wallet, getCreateAddress } = require("quantumcoin");
1253
- const { ${a.contractName}, ${a.contractName}__factory } = require("..");
1254
-
1255
- // 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.)
1256
- const TEST_WALLET_ENCRYPTED_JSON =
1257
- ${JSON.stringify(
1258
- "{\"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}",
1259
- )};
1260
- const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
1261
-
1262
- async function main() {
1263
- const rpcUrl = process.env.QC_RPC_URL;
1264
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1265
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1266
-
1267
- await Initialize(null);
1268
- const provider = getProvider(rpcUrl, chainId);
1269
-
1270
- // Offline wallet (no provider attached). We'll resolve nonce from provider manually.
1271
- const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
1272
- const from = wallet.address;
1273
-
1274
- const factory = new ${a.contractName}__factory(wallet);
1275
- const deployTxReq = factory.getDeployTransaction(${ctorArgsExpr});
1276
-
1277
- let gasLimit = 600000;
1278
- try {
1279
- const est = await provider.estimateGas({ from, data: deployTxReq.data });
1280
- gasLimit = Number(est + 200_000n);
1281
- } catch {
1282
- gasLimit = 6_000_000;
1283
- }
1284
- const bytecodeSize = (${a.contractName}.bytecode || "").length;
1285
- if (bytecodeSize > 20000 && gasLimit < 6_000_000) gasLimit = 6_000_000;
1286
-
1287
- const nonce0 = await provider.getTransactionCount(from, "pending");
1288
- const predicted = getCreateAddress({ from, nonce: nonce0 });
1289
-
1290
- const rawDeploy = await wallet.signTransaction({
1291
- ...deployTxReq,
1292
- nonce: nonce0,
1293
- chainId,
1294
- gasLimit,
1295
- });
1296
-
1297
- const sentDeploy = await provider.sendRawTransaction(rawDeploy);
1298
- console.log("deploy tx hash:", sentDeploy.hash);
1299
- await sentDeploy.wait(1, 600_000);
1300
-
1301
- const contract = ${a.contractName}.connect(predicted, provider);
1302
- console.log("deployed at:", contract.target);
1303
-
1304
- // Optional: offline-sign a write method if present (ERC20-like approve)
1305
- if (contract.populateTransaction && typeof contract.populateTransaction.approve === "function") {
1306
- const txReq = await contract.populateTransaction.approve(from, 123, { gasLimit: 200000 });
1307
- const nonce1 = await provider.getTransactionCount(from, "pending");
1308
- const raw = await wallet.signTransaction({ ...txReq, nonce: nonce1, chainId });
1309
- const sent = await provider.sendRawTransaction(raw);
1310
- console.log("approve tx hash:", sent.hash);
1311
- await sent.wait(1, 600_000);
1312
- console.log("approve succeeded");
1313
- } else {
1314
- console.log("No known write method for offline-signing demo (skipping write tx).");
1315
- }
1316
- }
1317
-
1318
- main().catch((e) => {
1319
- console.error(e);
1320
- process.exitCode = 1;
1321
- });
1322
- `,
1323
- );
1324
-
1325
- _writeText(
1326
- path.join(outDir, "examples", "offline-signing.ts"),
1327
- `/**
1328
- * Offline signing example (generated) - TypeScript.
1329
- *
1330
- * Demonstrates:
1331
- * - ${a.contractName}__factory.getDeployTransaction(...)
1332
- * - contract.populateTransaction.<method>(...)
1333
- * - wallet.signTransaction(txReq) (offline) + provider.sendRawTransaction(rawTx)
1334
- *
1335
- * Requires:
1336
- * - QC_RPC_URL env var
1337
- *
1338
- * WARNING: uses a hardcoded test wallet (funded) for convenience.
1339
- */
1340
- import { Initialize } from "quantumcoin/config";
1341
- import { getProvider, Wallet, getCreateAddress } from "quantumcoin";
1342
- import { ${a.contractName}, ${a.contractName}__factory } from "..";
1343
-
1344
- // 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.)
1345
- const TEST_WALLET_ENCRYPTED_JSON =
1346
- ${JSON.stringify(
1347
- "{\"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}",
1348
- )};
1349
- const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
1350
-
1351
- async function main(): Promise<void> {
1352
- const rpcUrl = process.env.QC_RPC_URL;
1353
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1354
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1355
-
1356
- await Initialize(null);
1357
- const provider = getProvider(rpcUrl, chainId);
1358
-
1359
- const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
1360
- const from = wallet.address;
1361
-
1362
- const factory = new ${a.contractName}__factory(wallet);
1363
- const deployTxReq = factory.getDeployTransaction(${ctorArgsExpr});
1364
-
1365
- let gasLimit = 600000;
1366
- try {
1367
- const est = await provider.estimateGas({ from, data: deployTxReq.data });
1368
- gasLimit = Number(est + 200_000n);
1369
- } catch {
1370
- gasLimit = 6_000_000;
1371
- }
1372
- const bytecodeSize = (${a.contractName}.bytecode || "").length;
1373
- if (bytecodeSize > 20000 && gasLimit < 6_000_000) gasLimit = 6_000_000;
1374
-
1375
- const nonce0 = await provider.getTransactionCount(from, "pending");
1376
- const predicted = getCreateAddress({ from, nonce: nonce0 });
1377
-
1378
- const rawDeploy = await wallet.signTransaction({
1379
- ...deployTxReq,
1380
- nonce: nonce0,
1381
- chainId,
1382
- gasLimit,
1383
- });
1384
-
1385
- const sentDeploy = await provider.sendRawTransaction(rawDeploy);
1386
- console.log("deploy tx hash:", sentDeploy.hash);
1387
- await sentDeploy.wait(1, 600_000);
1388
-
1389
- const contract = ${a.contractName}.connect(predicted, provider);
1390
- console.log("deployed at:", contract.target);
1391
-
1392
- if (contract.populateTransaction && typeof contract.populateTransaction.approve === "function") {
1393
- const txReq = await contract.populateTransaction.approve(from, 123, { gasLimit: 200000 });
1394
- const nonce1 = await provider.getTransactionCount(from, "pending");
1395
- const raw = await wallet.signTransaction({ ...txReq, nonce: nonce1, chainId });
1396
- const sent = await provider.sendRawTransaction(raw);
1397
- console.log("approve tx hash:", sent.hash);
1398
- await sent.wait(1, 600_000);
1399
- console.log("approve succeeded");
1400
- } else {
1401
- console.log("No known write method for offline-signing demo (skipping write tx).");
1402
- }
1403
- }
1404
-
1405
- main().catch((e) => {
1406
- console.error(e);
1407
- process.exitCode = 1;
1408
- });
1409
- `,
1410
- );
1411
-
1412
- _writeText(
1413
- path.join(outDir, "examples", "events.js"),
1414
- `/**
1415
- * Events/logs example (generated).
1416
- *
1417
- * Requires:
1418
- * - QC_RPC_URL env var
1419
- * - CONTRACT_ADDRESS env var
1420
- */
1421
- const { Initialize } = require("quantumcoin/config");
1422
- const { getProvider } = require("quantumcoin");
1423
- const { ${a.contractName} } = require("..");
1424
-
1425
- async function main() {
1426
- const rpcUrl = process.env.QC_RPC_URL;
1427
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1428
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1429
- const address = process.env.CONTRACT_ADDRESS;
1430
- if (!address) throw new Error("CONTRACT_ADDRESS is required");
1431
- await Initialize(null);
1432
-
1433
- const provider = getProvider(rpcUrl, chainId);
1434
- const contract = ${a.contractName}.connect(address, provider);
1435
-
1436
- const fromBlock = process.env.FROM_BLOCK ? Number(process.env.FROM_BLOCK) : "latest";
1437
- const toBlock = process.env.TO_BLOCK ? Number(process.env.TO_BLOCK) : "latest";
1438
-
1439
- const logs = await contract.queryFilter("Transfer", fromBlock, toBlock);
1440
- console.log("Logs:", logs.length);
1441
- for (const l of logs.slice(0, 10)) {
1442
- console.log(l);
1443
- }
1444
- }
1445
-
1446
- main().catch((e) => {
1447
- console.error(e);
1448
- process.exitCode = 1;
1449
- });
1450
- `,
1451
- );
1452
-
1453
- _writeText(
1454
- path.join(outDir, "examples", "events.ts"),
1455
- `/**
1456
- * Events/logs example (generated) - TypeScript.
1457
- *
1458
- * Requires:
1459
- * - QC_RPC_URL env var
1460
- * - CONTRACT_ADDRESS env var
1461
- */
1462
- import { Initialize } from "quantumcoin/config";
1463
- import { getProvider } from "quantumcoin";
1464
- import { ${a.contractName} } from "..";
1465
-
1466
- async function main(): Promise<void> {
1467
- const rpcUrl = process.env.QC_RPC_URL;
1468
- if (!rpcUrl) throw new Error("QC_RPC_URL is required");
1469
- const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;
1470
- const address = process.env.CONTRACT_ADDRESS;
1471
- if (!address) throw new Error("CONTRACT_ADDRESS is required");
1472
- await Initialize(null);
1473
-
1474
- const provider = getProvider(rpcUrl, chainId);
1475
- const contract = ${a.contractName}.connect(address, provider);
1476
-
1477
- const fromBlock = process.env.FROM_BLOCK ? Number(process.env.FROM_BLOCK) : "latest";
1478
- const toBlock = process.env.TO_BLOCK ? Number(process.env.TO_BLOCK) : "latest";
1479
-
1480
- const logs = await contract.queryFilter("Transfer", fromBlock, toBlock);
1481
- console.log("Logs:", logs.length);
1482
- for (const l of logs.slice(0, 10)) {
1483
- console.log(l);
1484
- }
1485
- }
1486
-
1487
- main().catch((e) => {
1488
- console.error(e);
1489
- process.exitCode = 1;
1490
- });
1491
- `,
1492
- );
1493
- } else {
1494
- // Multi-contract: avoid filename collisions.
1495
- for (const a of artifacts) {
1496
- const ctor = _findConstructor(a.abi);
1497
- const ctorArgsExpr = (ctor.inputs || []).map((i) => _solTypeToExampleValueExpr(i)).join(", ");
1498
-
1499
- _writeText(
1500
- path.join(outDir, "examples", `deploy-${a.contractName}.js`),
1501
- `const { Initialize } = require("quantumcoin/config");\nconst { getProvider } = require("quantumcoin");\nconst { createTestWallet } = require("./_test-wallet");\nconst { ${a.contractName}__factory } = require("..");\n\nasync function main() {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const wallet = createTestWallet(provider);\n\n const factory = new ${a.contractName}__factory(wallet);\n const contract = await factory.deploy(${ctorArgsExpr}${ctorArgsExpr ? ", " : ""}{ gasLimit: 600000 });\n const tx = contract.deployTransaction();\n if (tx) await tx.wait(1, 600_000);\n\n console.log("Deployed ${a.contractName} at:", contract.target);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1502
- );
1503
-
1504
- _writeText(
1505
- path.join(outDir, "examples", `read-operations-${a.contractName}.js`),
1506
- `const { Initialize } = require("quantumcoin/config");\nconst { getProvider } = require("quantumcoin");\nconst { ${a.contractName} } = require("..");\n\nasync function main() {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n const address = process.env.CONTRACT_ADDRESS;\n if (!address) throw new Error("CONTRACT_ADDRESS is required");\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const contract = ${a.contractName}.connect(address, provider);\n\n console.log("${a.contractName}:", contract.target);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1507
- );
1508
-
1509
- _writeText(
1510
- path.join(outDir, "examples", `write-operations-${a.contractName}.js`),
1511
- `const { Initialize } = require("quantumcoin/config");\nconst { getProvider } = require("quantumcoin");\nconst { createTestWallet } = require("./_test-wallet");\nconst { ${a.contractName} } = require("..");\n\nasync function main() {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n const address = process.env.CONTRACT_ADDRESS;\n if (!address) throw new Error("CONTRACT_ADDRESS is required");\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const wallet = createTestWallet(provider);\n const contract = ${a.contractName}.connect(address, wallet);\n\n console.log("Connected:", contract.target);\n console.log("Done");\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1512
- );
1513
-
1514
- _writeText(
1515
- path.join(outDir, "examples", `offline-signing-${a.contractName}.js`),
1516
- `const { Initialize } = require("quantumcoin/config");\nconst { getProvider, Wallet, getCreateAddress } = require("quantumcoin");\nconst { TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE } = require("./_test-wallet");\nconst { ${a.contractName}__factory, ${a.contractName} } = require("..");\n\nasync function main() {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);\n const from = wallet.address;\n\n const factory = new ${a.contractName}__factory(wallet);\n const deployTxReq = factory.getDeployTransaction();\n const nonce0 = await provider.getTransactionCount(from, \"pending\");\n const predicted = getCreateAddress({ from, nonce: nonce0 });\n\n const rawDeploy = await wallet.signTransaction({ ...deployTxReq, nonce: nonce0, chainId, gasLimit: 6_000_000 });\n const sentDeploy = await provider.sendRawTransaction(rawDeploy);\n await sentDeploy.wait(1, 600_000);\n\n const contract = ${a.contractName}.connect(predicted, provider);\n console.log(\"deployed at:\", contract.target);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1517
- );
1518
-
1519
- _writeText(
1520
- path.join(outDir, "examples", `events-${a.contractName}.js`),
1521
- `const { Initialize } = require("quantumcoin/config");\nconst { getProvider } = require("quantumcoin");\nconst { ${a.contractName} } = require("..");\n\nasync function main() {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n const address = process.env.CONTRACT_ADDRESS;\n if (!address) throw new Error("CONTRACT_ADDRESS is required");\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const contract = ${a.contractName}.connect(address, provider);\n\n const logs = await contract.queryFilter("Transfer", "latest", "latest");\n console.log("Logs:", logs.length);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1522
- );
1523
-
1524
- _writeText(
1525
- path.join(outDir, "examples", `deploy-${a.contractName}.ts`),
1526
- `import { Initialize } from "quantumcoin/config";\nimport { getProvider } from "quantumcoin";\nimport { createTestWallet } from "./_test-wallet";\nimport { ${a.contractName}__factory } from "..";\n\nasync function main(): Promise<void> {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const wallet = createTestWallet(provider);\n\n const factory = new ${a.contractName}__factory(wallet);\n const contract = await factory.deploy(${ctorArgsExpr}${ctorArgsExpr ? ", " : ""}{ gasLimit: 600000 });\n const tx = contract.deployTransaction();\n if (tx) await tx.wait(1, 600_000);\n\n console.log("Deployed ${a.contractName} at:", contract.target);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1527
- );
1528
- _writeText(
1529
- path.join(outDir, "examples", `read-operations-${a.contractName}.ts`),
1530
- `import { Initialize } from "quantumcoin/config";\nimport { getProvider } from "quantumcoin";\nimport { ${a.contractName} } from "..";\n\nasync function main(): Promise<void> {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n const address = process.env.CONTRACT_ADDRESS;\n if (!address) throw new Error("CONTRACT_ADDRESS is required");\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const contract = ${a.contractName}.connect(address, provider);\n\n console.log("${a.contractName}:", contract.target);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1531
- );
1532
- _writeText(
1533
- path.join(outDir, "examples", `write-operations-${a.contractName}.ts`),
1534
- `import { Initialize } from "quantumcoin/config";\nimport { getProvider } from "quantumcoin";\nimport { createTestWallet } from "./_test-wallet";\nimport { ${a.contractName} } from "..";\n\nasync function main(): Promise<void> {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n const address = process.env.CONTRACT_ADDRESS;\n if (!address) throw new Error("CONTRACT_ADDRESS is required");\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const wallet = createTestWallet(provider);\n const contract = ${a.contractName}.connect(address, wallet);\n\n console.log("Connected:", contract.target);\n console.log("Done");\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1535
- );
1536
- _writeText(
1537
- path.join(outDir, "examples", `offline-signing-${a.contractName}.ts`),
1538
- `import { Initialize } from "quantumcoin/config";\nimport { getProvider, Wallet, getCreateAddress } from "quantumcoin";\nimport { TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE } from "./_test-wallet";\nimport { ${a.contractName}__factory, ${a.contractName} } from "..";\n\nasync function main(): Promise<void> {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const wallet = Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);\n const from = wallet.address;\n\n const factory = new ${a.contractName}__factory(wallet);\n const deployTxReq = factory.getDeployTransaction();\n const nonce0 = await provider.getTransactionCount(from, "pending");\n const predicted = getCreateAddress({ from, nonce: nonce0 });\n\n const rawDeploy = await wallet.signTransaction({ ...deployTxReq, nonce: nonce0, chainId, gasLimit: 6_000_000 });\n const sentDeploy = await provider.sendRawTransaction(rawDeploy);\n await sentDeploy.wait(1, 600_000);\n\n const contract = ${a.contractName}.connect(predicted, provider);\n console.log("deployed at:", contract.target);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1539
- );
1540
- _writeText(
1541
- path.join(outDir, "examples", `events-${a.contractName}.ts`),
1542
- `import { Initialize } from "quantumcoin/config";\nimport { getProvider } from "quantumcoin";\nimport { ${a.contractName} } from "..";\n\nasync function main(): Promise<void> {\n const rpcUrl = process.env.QC_RPC_URL;\n if (!rpcUrl) throw new Error("QC_RPC_URL is required");\n const chainId = process.env.QC_CHAIN_ID ? Number(process.env.QC_CHAIN_ID) : 123123;\n const address = process.env.CONTRACT_ADDRESS;\n if (!address) throw new Error("CONTRACT_ADDRESS is required");\n await Initialize(null);\n\n const provider = getProvider(rpcUrl, chainId);\n const contract = ${a.contractName}.connect(address, provider);\n\n const logs = await contract.queryFilter("Transfer", "latest", "latest");\n console.log("Logs:", logs.length);\n}\n\nmain().catch((e) => { console.error(e); process.exitCode = 1; });\n`,
1543
- );
1544
- }
1545
- }
1546
-
1547
- // Add examples scripts and tsx devDependency so TS examples can run
1548
- const pkgPath = path.join(outDir, "package.json");
1549
- const pkg = _readJson(pkgPath);
1550
- pkg.scripts = pkg.scripts || {};
1551
- if (artifacts.length === 1) {
1552
- pkg.scripts.examples = "node examples/deploy.js && node examples/read-operations.js && node examples/write-operations.js && node examples/offline-signing.js && node examples/events.js";
1553
- pkg.scripts["examples:ts"] = "npx tsx examples/deploy.ts && npx tsx examples/read-operations.ts && npx tsx examples/write-operations.ts && npx tsx examples/offline-signing.ts && npx tsx examples/events.ts";
1554
- } else {
1555
- const tsParts = [];
1556
- for (const a of artifacts) {
1557
- tsParts.push(`npx tsx examples/deploy-${a.contractName}.ts`, `npx tsx examples/read-operations-${a.contractName}.ts`, `npx tsx examples/write-operations-${a.contractName}.ts`, `npx tsx examples/offline-signing-${a.contractName}.ts`, `npx tsx examples/events-${a.contractName}.ts`);
1558
- }
1559
- pkg.scripts["examples:ts"] = tsParts.join(" && ");
1560
- }
1561
- pkg.devDependencies = pkg.devDependencies || {};
1562
- pkg.devDependencies.tsx = "^4.7.0";
1563
- _writeJson(pkgPath, pkg);
1564
-
1565
- // Write an index.js re-export shim, then install and run build scripts.
1566
- _writeText(path.join(outDir, "index.js"), _renderPackageIndexJs({ artifacts, entryDir: lang === "ts" ? "dist" : "src" }));
1567
- }
1568
-
1569
- // Final step: after package creation, emit types.
1570
- if (createPackage) {
1571
- _runNpm(["install", "--no-fund", "--no-audit"], outDir);
1572
- if (lang === "ts") {
1573
- _runNpm(["run", "build:ts"], outDir);
1574
- }
1575
- }
1576
-
1577
- console.warn("This is an experimental SDK. Use at your own risk.");
1578
- console.log(`Generated contract files in: ${targetSrcDir}`);
1579
- }
1580
-
1581
- function _cap(s) {
1582
- return s ? s[0].toUpperCase() + s.slice(1) : s;
1583
- }
1584
-
1585
- function _abiParamSig(p, { includeName = true } = {}) {
1586
- if (!p || typeof p !== "object") return "";
1587
- const t = typeof p.type === "string" ? p.type : "";
1588
- const n = includeName && typeof p.name === "string" && p.name ? ` ${p.name}` : "";
1589
- const indexed = p.indexed ? " indexed" : "";
1590
- return `${t}${indexed}${n}`.trim();
1591
- }
1592
-
1593
- function _abiFnSig(f) {
1594
- const inputs = (f.inputs || []).map((p) => _abiParamSig(p)).filter(Boolean).join(", ");
1595
- const outputs = (f.outputs || []).map((p) => _abiParamSig(p, { includeName: false })).filter(Boolean).join(", ");
1596
- const mut = f.stateMutability && f.stateMutability !== "nonpayable" ? ` ${f.stateMutability}` : "";
1597
- const returns = outputs ? ` returns (${outputs})` : "";
1598
- return `${f.name}(${inputs})${mut}${returns}`.trim();
1599
- }
1600
-
1601
- function _abiEventSig(e) {
1602
- const inputs = (e.inputs || []).map((p) => _abiParamSig(p)).filter(Boolean).join(", ");
1603
- return `${e.name}(${inputs})`.trim();
1604
- }
1605
-
1606
- function _abiErrorSig(er) {
1607
- const inputs = (er.inputs || []).map((p) => _abiParamSig(p)).filter(Boolean).join(", ");
1608
- return `${er.name}(${inputs})`.trim();
1609
- }
1610
-
1611
- function _firstLine(s) {
1612
- if (!s) return "";
1613
- const t = String(s).trim();
1614
- if (!t) return "";
1615
- return t.split(/\r?\n/g)[0].trim();
1616
- }
1617
-
1618
- function _packageReadme({ pkgName, pkgDesc, artifacts, createdFromSolidity, lang = "ts" }) {
1619
- const outLang = _normalizeLang(lang);
1620
- const srcExt = outLang === "js" ? "js" : "ts";
1621
- const list = (artifacts || []).map((a) => a.contractName).filter(Boolean);
1622
- const hasMultiple = list.length > 1;
1623
-
1624
- const contractLinks = list.length
1625
- ? list.map((n) => `- [\`${n}\`](#${n.toLowerCase()})`).join("\n")
1626
- : "- (none)";
1627
-
1628
- const envBlock = `- \`QC_RPC_URL\` (required for transactional tests)\n- \`QC_CHAIN_ID\` (optional; defaults are used if omitted)\n`;
1629
-
1630
- const commonExamples = hasMultiple
1631
- ? `Examples are generated per contract (e.g. \`examples/deploy-<Contract>.js\`).`
1632
- : `- [deploy](./examples/deploy.js)\n- [read operations](./examples/read-operations.js)\n- [write operations](./examples/write-operations.js)\n- [events](./examples/events.js)\n`;
1633
-
1634
- const contractsMd = (artifacts || [])
1635
- .map((a) => {
1636
- const name = a.contractName;
1637
- const desc = a.docs && typeof a.docs.contract === "string" && a.docs.contract.trim() ? a.docs.contract.trim() : "";
1638
-
1639
- const fnDocs = (a.docs && a.docs.functions) || {};
1640
- const abi = Array.isArray(a.abi) ? a.abi : [];
1641
- const functions = abi.filter((x) => x && x.type === "function").sort((x, y) => String(x.name).localeCompare(String(y.name)));
1642
- const events = abi.filter((x) => x && x.type === "event").sort((x, y) => String(x.name).localeCompare(String(y.name)));
1643
- const errors = abi.filter((x) => x && x.type === "error").sort((x, y) => String(x.name).localeCompare(String(y.name)));
1644
- const ctor = abi.find((x) => x && x.type === "constructor");
1645
-
1646
- const examples = hasMultiple
1647
- ? `- [deploy](./examples/deploy-${name}.js)\n- [read operations](./examples/read-operations-${name}.js)\n- [write operations](./examples/write-operations-${name}.js)\n- [events](./examples/events-${name}.js)\n`
1648
- : `- [deploy](./examples/deploy.js)\n- [read operations](./examples/read-operations.js)\n- [write operations](./examples/write-operations.js)\n- [events](./examples/events.js)\n`;
1649
-
1650
- const testLink = `- [transactional test](./test/e2e/${name}.e2e.test.js)\n`;
1651
-
1652
- const fileLinks = [
1653
- `- [\`src/${name}.${srcExt}\`](./src/${name}.${srcExt})`,
1654
- `- [\`src/${name}__factory.${srcExt}\`](./src/${name}__factory.${srcExt})`,
1655
- createdFromSolidity ? `- [\`artifacts/${name}.abi.json\`](./artifacts/${name}.abi.json)` : null,
1656
- createdFromSolidity ? `- [\`artifacts/${name}.bin\`](./artifacts/${name}.bin)` : null,
1657
- ]
1658
- .filter(Boolean)
1659
- .join("\n");
1660
-
1661
- const ctorSig = ctor
1662
- ? `\`constructor(${(ctor.inputs || []).map((p) => _abiParamSig(p)).filter(Boolean).join(", ")})\``
1663
- : "`constructor()`";
1664
-
1665
- const fnList = functions.length
1666
- ? functions
1667
- .map((f) => {
1668
- const doc = fnDocs && typeof fnDocs[f.name] === "string" ? _firstLine(fnDocs[f.name]) : "";
1669
- return `- \`${_abiFnSig(f)}\`${doc ? ` — ${doc}` : ""}`;
1670
- })
1671
- .join("\n")
1672
- : "- (none)";
1673
-
1674
- const eventList = events.length ? events.map((e) => `- \`${_abiEventSig(e)}\``).join("\n") : "- (none)";
1675
- const errorList = errors.length ? errors.map((er) => `- \`${_abiErrorSig(er)}\``).join("\n") : "- (none)";
1676
-
1677
- return [
1678
- `## ${name}`,
1679
- desc ? `\n${desc}\n` : "",
1680
- `- **Exports**: \`${name}\`, \`${name}__factory\``,
1681
- `- **Constructor**: ${ctorSig}`,
1682
- "",
1683
- "### Files",
1684
- fileLinks,
1685
- "",
1686
- "### Examples",
1687
- examples.trimEnd(),
1688
- "",
1689
- "### Tests",
1690
- testLink.trimEnd(),
1691
- "",
1692
- "### Functions",
1693
- fnList,
1694
- "",
1695
- "### Events",
1696
- eventList,
1697
- "",
1698
- "### Errors",
1699
- errorList,
1700
- "",
1701
- ]
1702
- .filter(Boolean)
1703
- .join("\n");
1704
- })
1705
- .join("\n");
1706
-
1707
- return (
1708
- `# ${pkgName}\n\n` +
1709
- `${pkgDesc || ""}\n\n` +
1710
- "> **Note:** This is an experimental SDK. Use at your own risk.\n\n" +
1711
- "## What’s in this package\n\n" +
1712
- (outLang === "ts"
1713
- ? "- Typed contract wrappers and factories in `src/` (compiled output in `dist/`)\n"
1714
- : "- JavaScript contract wrappers and factories in `src/` (TypeScript types via `.d.ts`)\n") +
1715
- "- Transactional tests in `test/e2e/`\n" +
1716
- `- Example scripts in \`examples/\`\n` +
1717
- (createdFromSolidity ? "- ABI/BIN artifacts in `artifacts/`\n" : "") +
1718
- "\n" +
1719
- "## Install\n\n" +
1720
- "- `npm install`\n\n" +
1721
- "## Build\n\n" +
1722
- (outLang === "ts" ? "- `npm run build:ts`\n\n" : "- (no build step required)\n\n") +
1723
- "## Run tests\n\n" +
1724
- "- `npm test`\n\n" +
1725
- "Transactional tests require:\n" +
1726
- envBlock +
1727
- "\n" +
1728
- "## Examples\n\n" +
1729
- (hasMultiple ? `${commonExamples}\n\n` : `${commonExamples}\n`) +
1730
- "## Contracts\n\n" +
1731
- contractLinks +
1732
- "\n\n" +
1733
- (contractsMd ? contractsMd : "") +
1734
- "\n"
1735
- );
1736
- }
1737
-
1738
- function _createPackageScaffold({ outDir, pkgName, pkgDesc, pkgAuthor, pkgLicense, pkgVersion, lang = "ts" }) {
1739
- _ensureDir(outDir);
1740
- _ensureDir(path.join(outDir, "src"));
1741
- _ensureDir(path.join(outDir, "test", "e2e"));
1742
- _ensureDir(path.join(outDir, "examples"));
1743
-
1744
- const outLang = _normalizeLang(lang);
1745
- const isTs = outLang === "ts";
1746
-
1747
- const rootPkg = _readRootPackageJson();
1748
- const rootDeps = _rewriteFileDepsToAbsolute(rootPkg.dependencies || {}, __dirname);
1749
-
1750
- // Ensure the generated package depends on this repo's quantumcoin via absolute file path.
1751
- rootDeps.quantumcoin = `file:${__dirname.replace(/\\\\/g, "/")}`;
1752
-
1753
- const pkgJson = {
1754
- name: pkgName,
1755
- version: pkgVersion,
1756
- description: pkgDesc,
1757
- author: pkgAuthor,
1758
- license: pkgLicense,
1759
- main: isTs ? "dist/index.js" : "src/index.js",
1760
- types: isTs ? "dist/index.d.ts" : "src/index.d.ts",
1761
- scripts: {
1762
- ...(isTs
1763
- ? {
1764
- "build:ts": "npx -p typescript tsc -p tsconfig.json",
1765
- build: "npm run build:ts",
1766
- "build-powershell": "npm run build:ts",
1767
- test: "npm run build:ts && node --test --test-concurrency=1 \"test/**/*.test.js\"",
1768
- "test:e2e": "npm run build:ts && node --test --test-concurrency=1 \"test/e2e/**/*.test.js\"",
1769
- }
1770
- : {
1771
- build: "node -e \"console.log('JS package: no build step required')\"",
1772
- "build-powershell": "node -e \"console.log('JS package: no build step required')\"",
1773
- test: "node --test --test-concurrency=1 \"test/**/*.test.js\"",
1774
- "test:e2e": "node --test --test-concurrency=1 \"test/e2e/**/*.test.js\"",
1775
- }),
1776
- },
1777
- dependencies: rootDeps,
1778
- devDependencies: {},
1779
- };
1780
-
1781
- _writeJson(path.join(outDir, "package.json"), pkgJson);
1782
- if (isTs) {
1783
- _writeJson(path.join(outDir, "tsconfig.json"), {
1784
- compilerOptions: {
1785
- target: "ES2022",
1786
- lib: ["ES2022"],
1787
- module: "CommonJS",
1788
- declaration: true,
1789
- rootDir: "src",
1790
- outDir: "dist",
1791
- strict: true,
1792
- esModuleInterop: true,
1793
- skipLibCheck: true,
1794
- },
1795
- include: ["src/**/*.ts"],
1796
- });
1797
- }
1798
-
1799
- _writeText(
1800
- path.join(outDir, "README.md"),
1801
- _packageReadme({ pkgName, pkgDesc, artifacts: [], createdFromSolidity: false, lang: outLang }),
1802
- );
1803
-
1804
- _writeText(path.join(outDir, ".gitignore"), `node_modules\n/dist\n*.log\n`);
1805
-
1806
- // Provide a root index.d.ts without needing a separate build step.
1807
- // This is mainly for convenience and for tooling that expects a top-level .d.ts.
1808
- _writeText(path.join(outDir, "index.d.ts"), `export * from "./${isTs ? "dist" : "src"}";\n`);
1809
-
1810
- // Minimal shims so the generated TypeScript can compile even though `quantumcoin`
1811
- // is a JavaScript package (no bundled .d.ts in this repo).
1812
- _writeText(
1813
- path.join(outDir, "src", "quantumcoin-shims.d.ts"),
1814
- `declare module "quantumcoin" {\n` +
1815
- ` export type ContractRunner = any;\n` +
1816
- ` export type TransactionResponse = any;\n` +
1817
- ` export type ContractTransactionResponse = any;\n` +
1818
- ` export type TransactionRequest = any;\n` +
1819
- `\n` +
1820
- ` export class Contract {\n` +
1821
- ` constructor(address: string, abi: any, runner?: any, bytecode?: any);\n` +
1822
- ` target: string;\n` +
1823
- ` address: string;\n` +
1824
- ` interface: any;\n` +
1825
- ` populateTransaction: any;\n` +
1826
- ` call(methodName: string, args: any[], overrides?: TransactionRequest): Promise<any>;\n` +
1827
- ` send(methodName: string, args: any[], overrides?: TransactionRequest): Promise<ContractTransactionResponse>;\n` +
1828
- ` deployTransaction(): TransactionResponse | null;\n` +
1829
- ` }\n` +
1830
- `\n` +
1831
- ` export class ContractFactory {\n` +
1832
- ` signer: any;\n` +
1833
- ` constructor(abi: any, bytecode: string, signer: any);\n` +
1834
- ` getDeployTransaction(...args: any[]): TransactionRequest;\n` +
1835
- ` }\n` +
1836
- `\n` +
1837
- ` export function getCreateAddress(opts: { from: string; nonce: number }): string;\n` +
1838
- `}\n`,
1839
- );
1840
- }
1841
-
1842
- main().catch((e) => {
1843
- console.error(e);
1844
- process.exitCode = 1;
1845
- });
1846
-