@0xsequence/catapult 1.3.17 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +276 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +1 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/index.d.ts +1 -0
  6. package/dist/commands/index.d.ts.map +1 -1
  7. package/dist/commands/index.js +1 -0
  8. package/dist/commands/index.js.map +1 -1
  9. package/dist/commands/list.d.ts.map +1 -1
  10. package/dist/commands/list.js +12 -0
  11. package/dist/commands/list.js.map +1 -1
  12. package/dist/commands/provenance.d.ts +3 -0
  13. package/dist/commands/provenance.d.ts.map +1 -0
  14. package/dist/commands/provenance.js +138 -0
  15. package/dist/commands/provenance.js.map +1 -0
  16. package/dist/lib/__tests__/deployer.spec.js +118 -1
  17. package/dist/lib/__tests__/deployer.spec.js.map +1 -1
  18. package/dist/lib/__tests__/network-loader.spec.js.map +1 -1
  19. package/dist/lib/__tests__/provenance.spec.d.ts +2 -0
  20. package/dist/lib/__tests__/provenance.spec.d.ts.map +1 -0
  21. package/dist/lib/__tests__/provenance.spec.js +205 -0
  22. package/dist/lib/__tests__/provenance.spec.js.map +1 -0
  23. package/dist/lib/contracts/__tests__/repository.spec.js +243 -0
  24. package/dist/lib/contracts/__tests__/repository.spec.js.map +1 -1
  25. package/dist/lib/contracts/repository.d.ts +9 -1
  26. package/dist/lib/contracts/repository.d.ts.map +1 -1
  27. package/dist/lib/contracts/repository.js +93 -7
  28. package/dist/lib/contracts/repository.js.map +1 -1
  29. package/dist/lib/core/__tests__/assert-action.spec.d.ts +2 -0
  30. package/dist/lib/core/__tests__/assert-action.spec.d.ts.map +1 -0
  31. package/dist/lib/core/__tests__/assert-action.spec.js +377 -0
  32. package/dist/lib/core/__tests__/assert-action.spec.js.map +1 -0
  33. package/dist/lib/core/__tests__/engine.spec.js +80 -0
  34. package/dist/lib/core/__tests__/engine.spec.js.map +1 -1
  35. package/dist/lib/core/__tests__/loader.spec.js +29 -0
  36. package/dist/lib/core/__tests__/loader.spec.js.map +1 -1
  37. package/dist/lib/core/__tests__/resolver.spec.js +405 -0
  38. package/dist/lib/core/__tests__/resolver.spec.js.map +1 -1
  39. package/dist/lib/core/__tests__/sign-actions.spec.d.ts +2 -0
  40. package/dist/lib/core/__tests__/sign-actions.spec.d.ts.map +1 -0
  41. package/dist/lib/core/__tests__/sign-actions.spec.js +128 -0
  42. package/dist/lib/core/__tests__/sign-actions.spec.js.map +1 -0
  43. package/dist/lib/core/__tests__/signer.spec.d.ts +2 -0
  44. package/dist/lib/core/__tests__/signer.spec.d.ts.map +1 -0
  45. package/dist/lib/core/__tests__/signer.spec.js +40 -0
  46. package/dist/lib/core/__tests__/signer.spec.js.map +1 -0
  47. package/dist/lib/core/context.d.ts +3 -2
  48. package/dist/lib/core/context.d.ts.map +1 -1
  49. package/dist/lib/core/context.js +3 -2
  50. package/dist/lib/core/context.js.map +1 -1
  51. package/dist/lib/core/engine.d.ts +4 -0
  52. package/dist/lib/core/engine.d.ts.map +1 -1
  53. package/dist/lib/core/engine.js +206 -0
  54. package/dist/lib/core/engine.js.map +1 -1
  55. package/dist/lib/core/loader.d.ts +1 -0
  56. package/dist/lib/core/loader.d.ts.map +1 -1
  57. package/dist/lib/core/loader.js +6 -1
  58. package/dist/lib/core/loader.js.map +1 -1
  59. package/dist/lib/core/resolver.d.ts +2 -0
  60. package/dist/lib/core/resolver.d.ts.map +1 -1
  61. package/dist/lib/core/resolver.js +89 -0
  62. package/dist/lib/core/resolver.js.map +1 -1
  63. package/dist/lib/core/signer.d.ts +7 -0
  64. package/dist/lib/core/signer.d.ts.map +1 -0
  65. package/dist/lib/core/signer.js +60 -0
  66. package/dist/lib/core/signer.js.map +1 -0
  67. package/dist/lib/deployer.d.ts.map +1 -1
  68. package/dist/lib/deployer.js +21 -4
  69. package/dist/lib/deployer.js.map +1 -1
  70. package/dist/lib/index.d.ts +1 -0
  71. package/dist/lib/index.d.ts.map +1 -1
  72. package/dist/lib/index.js +1 -0
  73. package/dist/lib/index.js.map +1 -1
  74. package/dist/lib/parsers/__tests__/job.spec.js +77 -0
  75. package/dist/lib/parsers/__tests__/job.spec.js.map +1 -1
  76. package/dist/lib/parsers/__tests__/source.spec.d.ts +2 -0
  77. package/dist/lib/parsers/__tests__/source.spec.d.ts.map +1 -0
  78. package/dist/lib/parsers/__tests__/source.spec.js +158 -0
  79. package/dist/lib/parsers/__tests__/source.spec.js.map +1 -0
  80. package/dist/lib/parsers/index.d.ts +1 -0
  81. package/dist/lib/parsers/index.d.ts.map +1 -1
  82. package/dist/lib/parsers/index.js +1 -0
  83. package/dist/lib/parsers/index.js.map +1 -1
  84. package/dist/lib/parsers/job.d.ts.map +1 -1
  85. package/dist/lib/parsers/job.js +11 -0
  86. package/dist/lib/parsers/job.js.map +1 -1
  87. package/dist/lib/parsers/source.d.ts +4 -0
  88. package/dist/lib/parsers/source.d.ts.map +1 -0
  89. package/dist/lib/parsers/source.js +107 -0
  90. package/dist/lib/parsers/source.js.map +1 -0
  91. package/dist/lib/provenance.d.ts +34 -0
  92. package/dist/lib/provenance.d.ts.map +1 -0
  93. package/dist/lib/provenance.js +694 -0
  94. package/dist/lib/provenance.js.map +1 -0
  95. package/dist/lib/types/actions.d.ts +42 -2
  96. package/dist/lib/types/actions.d.ts.map +1 -1
  97. package/dist/lib/types/actions.js +4 -0
  98. package/dist/lib/types/actions.js.map +1 -1
  99. package/dist/lib/types/contracts.d.ts +3 -0
  100. package/dist/lib/types/contracts.d.ts.map +1 -1
  101. package/dist/lib/types/definitions.d.ts +1 -0
  102. package/dist/lib/types/definitions.d.ts.map +1 -1
  103. package/dist/lib/types/index.d.ts +1 -0
  104. package/dist/lib/types/index.d.ts.map +1 -1
  105. package/dist/lib/types/index.js +1 -0
  106. package/dist/lib/types/index.js.map +1 -1
  107. package/dist/lib/types/source.d.ts +26 -0
  108. package/dist/lib/types/source.d.ts.map +1 -0
  109. package/dist/lib/types/source.js +3 -0
  110. package/dist/lib/types/source.js.map +1 -0
  111. package/dist/lib/types/values.d.ts +33 -1
  112. package/dist/lib/types/values.d.ts.map +1 -1
  113. package/package.json +4 -1
  114. package/.eslintrc.json +0 -29
  115. package/.github/workflows/ci.yml +0 -181
  116. package/CONCEPT.md +0 -24
  117. package/contracts/checked-call.huff +0 -65
  118. package/eslint.config.js +0 -48
  119. package/examples/jobs/guards-v1.yaml +0 -17
  120. package/examples/jobs/sequence-seq-0001-patch.yaml +0 -59
  121. package/examples/jobs/sequence-v1.yaml +0 -59
  122. package/examples/templates/sequence-factory-v1.yaml +0 -56
  123. package/jest.config.js +0 -25
  124. package/src/cli.ts +0 -17
  125. package/src/commands/common.ts +0 -61
  126. package/src/commands/dry.ts +0 -209
  127. package/src/commands/etherscan.ts +0 -360
  128. package/src/commands/index.ts +0 -5
  129. package/src/commands/list.ts +0 -249
  130. package/src/commands/run.ts +0 -146
  131. package/src/commands/utils.ts +0 -215
  132. package/src/index.ts +0 -67
  133. package/src/lib/__tests__/deployer-events.spec.ts +0 -338
  134. package/src/lib/__tests__/deployer.spec.ts +0 -2093
  135. package/src/lib/__tests__/network-loader.spec.ts +0 -150
  136. package/src/lib/__tests__/network-selection.spec.ts +0 -41
  137. package/src/lib/__tests__/network-utils.spec.ts +0 -230
  138. package/src/lib/artifacts/__tests__/fixtures/contract1.json +0 -19
  139. package/src/lib/artifacts/__tests__/fixtures/contract2.json +0 -19
  140. package/src/lib/artifacts/__tests__/fixtures/duplicate-name.json +0 -19
  141. package/src/lib/artifacts/__tests__/fixtures/nested/nested-contract.json +0 -18
  142. package/src/lib/artifacts/__tests__/fixtures/not-an-artifact.json +0 -8
  143. package/src/lib/artifacts/__tests__/fixtures/readme.txt +0 -2
  144. package/src/lib/contracts/__tests__/repository.spec.ts +0 -344
  145. package/src/lib/contracts/repository.ts +0 -313
  146. package/src/lib/core/__tests__/context.spec.ts +0 -37
  147. package/src/lib/core/__tests__/engine.spec.ts +0 -1889
  148. package/src/lib/core/__tests__/graph.spec.ts +0 -125
  149. package/src/lib/core/__tests__/json-integration.spec.ts +0 -425
  150. package/src/lib/core/__tests__/loader.spec.ts +0 -334
  151. package/src/lib/core/__tests__/multi-platform-verification.spec.ts +0 -406
  152. package/src/lib/core/__tests__/resolver.spec.ts +0 -2053
  153. package/src/lib/core/__tests__/static-action.spec.ts +0 -172
  154. package/src/lib/core/context.ts +0 -127
  155. package/src/lib/core/engine.ts +0 -1782
  156. package/src/lib/core/graph.ts +0 -252
  157. package/src/lib/core/loader.ts +0 -247
  158. package/src/lib/core/resolver.ts +0 -757
  159. package/src/lib/deployer.ts +0 -981
  160. package/src/lib/events/__tests__/event-system.spec.ts +0 -392
  161. package/src/lib/events/cli-adapter.ts +0 -369
  162. package/src/lib/events/emitter.ts +0 -62
  163. package/src/lib/events/index.ts +0 -3
  164. package/src/lib/events/types.ts +0 -520
  165. package/src/lib/index.ts +0 -14
  166. package/src/lib/network-loader.ts +0 -90
  167. package/src/lib/network-selection.ts +0 -73
  168. package/src/lib/network-utils.ts +0 -64
  169. package/src/lib/parsers/__tests__/buildinfo.spec.ts +0 -122
  170. package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-bytecode-buildinfo.json +0 -62
  171. package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-json.txt +0 -2
  172. package/src/lib/parsers/__tests__/fixtures/buildinfo/multi-contract-buildinfo.json +0 -89
  173. package/src/lib/parsers/__tests__/fixtures/buildinfo/no-contracts-buildinfo.json +0 -17
  174. package/src/lib/parsers/__tests__/fixtures/buildinfo/simple-buildinfo.json +0 -63
  175. package/src/lib/parsers/__tests__/fixtures/buildinfo/wrong-format.json +0 -4
  176. package/src/lib/parsers/__tests__/job.spec.ts +0 -358
  177. package/src/lib/parsers/__tests__/template.spec.ts +0 -111
  178. package/src/lib/parsers/artifact/__tests__/artifact.spec.ts +0 -117
  179. package/src/lib/parsers/artifact/__tests__/fixtures/empty-bytecode.json +0 -5
  180. package/src/lib/parsers/artifact/__tests__/fixtures/hardhat-artifact.json +0 -67
  181. package/src/lib/parsers/artifact/__tests__/fixtures/invalid-bytecode.json +0 -5
  182. package/src/lib/parsers/artifact/__tests__/fixtures/invalid-json.txt +0 -11
  183. package/src/lib/parsers/artifact/__tests__/fixtures/minimal-artifact.json +0 -5
  184. package/src/lib/parsers/artifact/__tests__/fixtures/missing-abi.json +0 -4
  185. package/src/lib/parsers/artifact/__tests__/fixtures/missing-bytecode.json +0 -11
  186. package/src/lib/parsers/artifact/__tests__/fixtures/missing-contract-name.json +0 -11
  187. package/src/lib/parsers/artifact/__tests__/fixtures/simple-artifact.json +0 -40
  188. package/src/lib/parsers/artifact/__tests__/fixtures/wrong-types.json +0 -7
  189. package/src/lib/parsers/artifact/foundry-1.2.ts +0 -72
  190. package/src/lib/parsers/artifact/index.ts +0 -27
  191. package/src/lib/parsers/artifact/types.ts +0 -9
  192. package/src/lib/parsers/buildinfo.ts +0 -127
  193. package/src/lib/parsers/constants.ts +0 -56
  194. package/src/lib/parsers/index.ts +0 -5
  195. package/src/lib/parsers/job.ts +0 -148
  196. package/src/lib/parsers/template.ts +0 -135
  197. package/src/lib/std/templates/arachnid-deterministic-deployment-proxy.yaml +0 -68
  198. package/src/lib/std/templates/assured-deployment.yaml +0 -46
  199. package/src/lib/std/templates/era-evm-predeploy.yaml +0 -35
  200. package/src/lib/std/templates/erc-2470.yaml +0 -70
  201. package/src/lib/std/templates/min-balance.yaml +0 -35
  202. package/src/lib/std/templates/nano-universal-deployer.yaml +0 -61
  203. package/src/lib/std/templates/raw-erc-2470.yaml +0 -62
  204. package/src/lib/std/templates/raw-nano-universal-deployer.yaml +0 -54
  205. package/src/lib/std/templates/raw-sequence-universal-deployer-2.yaml +0 -52
  206. package/src/lib/std/templates/sequence-universal-deployer-2.yaml +0 -61
  207. package/src/lib/types/__tests__/json-request-action.spec.ts +0 -243
  208. package/src/lib/types/__tests__/read-json-value.spec.ts +0 -278
  209. package/src/lib/types/__tests__/resolve-json-value.spec.ts +0 -769
  210. package/src/lib/types/actions.ts +0 -127
  211. package/src/lib/types/artifacts.ts +0 -21
  212. package/src/lib/types/buildinfo.ts +0 -116
  213. package/src/lib/types/conditions.ts +0 -50
  214. package/src/lib/types/contracts.ts +0 -23
  215. package/src/lib/types/definitions.ts +0 -70
  216. package/src/lib/types/index.ts +0 -8
  217. package/src/lib/types/network.ts +0 -33
  218. package/src/lib/types/project.ts +0 -9
  219. package/src/lib/types/task.ts +0 -9
  220. package/src/lib/types/values.ts +0 -150
  221. package/src/lib/utils/assertion.ts +0 -24
  222. package/src/lib/utils/validation.ts +0 -116
  223. package/src/lib/validation/contract-references.ts +0 -210
  224. package/src/lib/validation/index.ts +0 -1
  225. package/src/lib/verification/__tests__/etherscan.spec.ts +0 -710
  226. package/src/lib/verification/__tests__/sourcify.spec.ts +0 -288
  227. package/src/lib/verification/etherscan.ts +0 -547
  228. package/src/lib/verification/sourcify.ts +0 -248
  229. package/test_validation/artifacts/TestContract.json +0 -9
  230. package/test_validation/jobs/test-missing.yaml +0 -16
  231. package/test_validation/networks.yaml +0 -3
  232. package/tsconfig.json +0 -36
@@ -1,360 +0,0 @@
1
- import { Command } from 'commander'
2
- import chalk from 'chalk'
3
- import { loadNetworks } from '../lib/network-loader'
4
- import { resolveSingleChainId } from '../lib/network-selection'
5
- import { projectOption, verbosityOption } from './common'
6
- import { setVerbosity } from '../index'
7
- import * as solc from 'solc'
8
- import { createHash } from 'crypto'
9
-
10
- type ApiAction = 'getsourcecode' | 'getabi'
11
-
12
- interface EtherscanCmdBase {
13
- project: string
14
- verbose: number
15
- etherscanApiKey?: string
16
- network?: string
17
- address: string
18
- raw?: boolean
19
- }
20
-
21
- function getEtherscanApiUrl(chainId: number): string {
22
- return `https://api.etherscan.io/v2/api?chainid=${chainId}`
23
- }
24
-
25
- type EtherscanSourceEnvelope = {
26
- rawResult: Record<string, unknown>
27
- parsedSource: unknown // standard-json object or flattened string
28
- }
29
-
30
- async function fetchFromEtherscan(
31
- chainId: number,
32
- apiKey: string,
33
- address: string,
34
- action: ApiAction
35
- ): Promise<unknown | EtherscanSourceEnvelope> {
36
- const apiUrl = getEtherscanApiUrl(chainId)
37
- const params = new URLSearchParams({
38
- module: 'contract',
39
- action,
40
- apikey: apiKey,
41
- address
42
- })
43
- const resp = await fetch(`${apiUrl}&${params.toString()}`, {
44
- method: 'GET',
45
- signal: AbortSignal.timeout(20000)
46
- })
47
- if (!resp.ok) {
48
- throw new Error(`HTTP ${resp.status}: ${resp.statusText}`)
49
- }
50
- const data = await resp.json() as {
51
- status: string
52
- message?: string
53
- result:
54
- | string
55
- | Array<{
56
- SourceCode?: string
57
- ABI?: string
58
- [key: string]: unknown
59
- }>
60
- }
61
-
62
- if (data.status !== '1') {
63
- // Etherscan v2 returns status "0" with message in result
64
- const msg = typeof data.result === 'string' ? data.result : JSON.stringify(data.result)
65
- throw new Error(msg || 'Unknown Etherscan error')
66
- }
67
-
68
- if (action === 'getabi') {
69
- // data.result is a JSON-encoded string for ABI, parse and return as object
70
- if (typeof data.result !== 'string') {
71
- throw new Error('Unexpected ABI result format from Etherscan')
72
- }
73
- try {
74
- return JSON.parse(data.result as string)
75
- } catch (_e) {
76
- throw new Error('Failed to parse ABI JSON returned by Etherscan')
77
- }
78
- }
79
-
80
- if (action === 'getsourcecode') {
81
- // data.result[0].SourceCode is a string; when standard-json it is wrapped with a leading and trailing character
82
- if (!Array.isArray(data.result) || data.result.length === 0) {
83
- throw new Error('Empty result from Etherscan')
84
- }
85
- const first = (data.result as Array<{ SourceCode?: string }>)[0] as Record<string, unknown>
86
- const sourceCodeRaw = first?.SourceCode as string
87
- if (typeof sourceCodeRaw !== 'string' || sourceCodeRaw.length === 0) {
88
- throw new Error('No SourceCode found on Etherscan')
89
- }
90
-
91
- // The SourceCode may be:
92
- // 1) a raw source (flattened) string
93
- // 2) a JSON string that may be double-wrapped like: "{...}" or "{{...}}"
94
- // Try to normalize to a parsed JSON object when possible, otherwise return the raw string.
95
- const trimmed = sourceCodeRaw.trim()
96
- // Heuristic: if it starts with '{{' and ends with '}}', strip one layer
97
- const cleaned = trimmed.startsWith('{{') && trimmed.endsWith('}}')
98
- ? trimmed.slice(1, -1)
99
- : trimmed
100
-
101
- // Try to parse JSON; if it fails, return string
102
- try {
103
- const parsed = JSON.parse(cleaned)
104
- return { rawResult: first, parsedSource: parsed }
105
- } catch {
106
- // Not JSON, return as-is string
107
- return { rawResult: first, parsedSource: sourceCodeRaw }
108
- }
109
- }
110
-
111
- return data.result
112
- }
113
-
114
- export function makeEtherscanCommand(): Command {
115
- const etherscan = new Command('etherscan')
116
- .description('Etherscan helper commands (ABI/source fetch)')
117
-
118
- // Common options builder
119
- const withCommon = (cmd: Command) => {
120
- projectOption(cmd)
121
- verbosityOption(cmd)
122
- cmd
123
- .option('--etherscan-api-key <key>', 'Etherscan API key. Can also be set via ETHERSCAN_API_KEY env var.')
124
- .option('-n, --network <selector>', 'Target network (chain ID or name). When a name matches multiple networks, the first match is used.')
125
- .option('-a, --address <address>', 'Contract address to query', '')
126
- .option('--raw', 'Print raw response (no pretty JSON). Useful for piping.', false)
127
- return cmd
128
- }
129
-
130
- // etherscan abi
131
- const abi = new Command('abi')
132
- .description('Fetch contract ABI from Etherscan and print to stdout')
133
- withCommon(abi)
134
- abi.action(async (options: EtherscanCmdBase) => {
135
- try {
136
- setVerbosity(options.verbose as 0 | 1 | 2 | 3)
137
-
138
- const apiKey = options.etherscanApiKey || process.env.ETHERSCAN_API_KEY
139
- if (!apiKey) {
140
- console.error(chalk.red('Etherscan API key is required. Use --etherscan-api-key or set ETHERSCAN_API_KEY.'))
141
- process.exit(1)
142
- }
143
-
144
- if (!options.address) {
145
- console.error(chalk.red('Missing required --address option'))
146
- process.exit(1)
147
- }
148
-
149
- // Determine chainId
150
- let chainId: number | undefined
151
- const networks = await loadNetworks(options.project)
152
- if (options.network) {
153
- chainId = resolveSingleChainId(options.network, networks)
154
- } else if (networks.length === 1) {
155
- chainId = networks[0].chainId
156
- }
157
- if (!chainId) {
158
- console.error(chalk.red('Please provide --network <selector>. When multiple networks are configured, selection is required.'))
159
- process.exit(1)
160
- }
161
-
162
- const result = await fetchFromEtherscan(chainId!, apiKey, options.address, 'getabi')
163
-
164
- if (options.raw) {
165
- // raw: output minified JSON
166
- process.stdout.write(JSON.stringify(result))
167
- } else {
168
- // pretty
169
- console.log(JSON.stringify(result, null, 2))
170
- }
171
- } catch (error) {
172
- console.error(chalk.red('Error fetching ABI from Etherscan:'), error instanceof Error ? error.message : String(error))
173
- process.exit(1)
174
- }
175
- })
176
-
177
- // etherscan source
178
- const source = new Command('source')
179
- .description('Fetch contract source and emit a self-contained build-info JSON suitable for verification')
180
- withCommon(source)
181
- source.action(async (options: EtherscanCmdBase) => {
182
- try {
183
- setVerbosity(options.verbose as 0 | 1 | 2 | 3)
184
-
185
- const apiKey = options.etherscanApiKey || process.env.ETHERSCAN_API_KEY
186
- if (!apiKey) {
187
- console.error(chalk.red('Etherscan API key is required. Use --etherscan-api-key or set ETHERSCAN_API_KEY.'))
188
- process.exit(1)
189
- }
190
-
191
- if (!options.address) {
192
- console.error(chalk.red('Missing required --address option'))
193
- process.exit(1)
194
- }
195
-
196
- // Determine chainId
197
- let chainId: number | undefined
198
- const networks2 = await loadNetworks(options.project)
199
- if (options.network) {
200
- chainId = resolveSingleChainId(options.network, networks2)
201
- } else if (networks2.length === 1) {
202
- chainId = networks2[0].chainId
203
- }
204
- if (!chainId) {
205
- console.error(chalk.red('Please provide --network <selector>. When multiple networks are configured, selection is required.'))
206
- process.exit(1)
207
- }
208
-
209
- const result = await fetchFromEtherscan(chainId!, apiKey, options.address, 'getsourcecode') as EtherscanSourceEnvelope
210
-
211
- const raw = result.rawResult
212
- const parsed = result.parsedSource
213
-
214
- // Extract compiler version with commit from metadata when available
215
- const compilerVersion = (raw?.CompilerVersion as string | undefined) || ''
216
- const optimizationUsed = (raw?.OptimizationUsed as string | undefined) || ''
217
- const runsStr = (raw?.Runs as string | undefined) || ''
218
- const evmVersionRaw = (raw?.EVMVersion as string | undefined) || ''
219
- const isStandardJson = !!(parsed && typeof parsed === 'object' && 'language' in parsed && 'sources' in parsed)
220
-
221
- // If we have a standard JSON input, use it; otherwise build one from flattened source
222
- type SolcInput = {
223
- language: string
224
- sources: Record<string, { content?: string }>
225
- settings?: {
226
- optimizer?: { enabled?: boolean; runs?: number }
227
- evmVersion?: string
228
- outputSelection?: Record<string, Record<string, string[]>>
229
- viaIR?: boolean
230
- libraries?: Record<string, Record<string, string>>
231
- }
232
- }
233
- let input: SolcInput
234
- if (isStandardJson) {
235
- input = parsed as SolcInput
236
- // Ensure outputSelection includes required entries to get creation bytecode and metadata
237
- const currentSel = (input.settings?.outputSelection ?? {}) as Record<string, Record<string, string[]>>
238
- const mergedSel: Record<string, Record<string, string[]>> = {
239
- '*': {
240
- '*': Array.from(new Set<string>([
241
- ...((currentSel?.['*']?.['*']) || []),
242
- 'abi',
243
- 'evm.bytecode',
244
- 'evm.deployedBytecode',
245
- 'metadata',
246
- 'userdoc',
247
- 'devdoc',
248
- 'evm.methodIdentifiers'
249
- ]))
250
- }
251
- }
252
- input.settings = {
253
- ...(input.settings || {}),
254
- outputSelection: mergedSel
255
- }
256
- } else {
257
- // Build a minimal standard JSON input from flattened source
258
- const flattened = String(parsed || '')
259
- input = {
260
- language: 'Solidity',
261
- sources: {
262
- 'Flattened.sol': { content: flattened }
263
- },
264
- settings: {
265
- optimizer: {
266
- enabled: optimizationUsed === '1',
267
- runs: Number.isFinite(Number(runsStr)) ? Number(runsStr) : 200
268
- },
269
- evmVersion: evmVersionRaw && evmVersionRaw !== 'default' ? evmVersionRaw : undefined,
270
- outputSelection: {
271
- '*': {
272
- '*': [
273
- 'abi',
274
- 'evm.bytecode.object',
275
- 'evm.bytecode.sourceMap',
276
- 'evm.bytecode.linkReferences',
277
- 'evm.deployedBytecode.object',
278
- 'evm.deployedBytecode.sourceMap',
279
- 'evm.deployedBytecode.linkReferences',
280
- 'evm.deployedBytecode.immutableReferences',
281
- 'evm.methodIdentifiers',
282
- 'metadata'
283
- ]
284
- }
285
- }
286
- }
287
- }
288
- }
289
-
290
- // Compile with exact solc version when possible
291
- const solcInput = JSON.stringify(input)
292
- const versionTag = compilerVersion && compilerVersion.startsWith('v') ? compilerVersion : (compilerVersion ? `v${compilerVersion}` : '')
293
- let outputRaw: string
294
- if (versionTag) {
295
- outputRaw = await new Promise<string>((resolve, reject) => {
296
- // @ts-ignore - loadRemoteVersion exists in solc js
297
- solc.loadRemoteVersion(versionTag, (err: unknown, specificSolc: { compile: (input: string) => string } | undefined) => {
298
- if (err || !specificSolc) return reject((err as Error) || new Error('Failed to load solc version'))
299
- try {
300
- resolve(specificSolc.compile(solcInput))
301
- } catch (e) {
302
- reject(e)
303
- }
304
- })
305
- })
306
- } else {
307
- outputRaw = solc.compile(solcInput)
308
- }
309
- const output = JSON.parse(outputRaw)
310
-
311
- // Build build-info id as hex of sha1 of input
312
- const id = createHash('sha1').update(solcInput).digest('hex')
313
-
314
- // Determine solc versions
315
- const solcLongVersion = (output?.compiler?.version as string | undefined) || (compilerVersion ? compilerVersion.replace(/^v/, '') : undefined)
316
- const solcMaybe = solc as unknown as { version?: () => string }
317
- const solcVersion = (solcLongVersion || '').split('+')[0] || (typeof solcMaybe.version === 'function' ? solcMaybe.version() : 'unknown')
318
-
319
- // Augment settings with defaults similar to reference format
320
- const basePath = process.cwd()
321
- const includePaths = [basePath]
322
- const allowPaths = includePaths
323
-
324
- const buildInfo = {
325
- id,
326
- source_id_to_path: Object.fromEntries(Object.keys(input.sources).map((p, i) => [String(i), p])),
327
- language: input.language,
328
- _format: 'ethers-rs-sol-build-info-1',
329
- input: {
330
- version: solcVersion,
331
- language: input.language,
332
- sources: input.sources,
333
- settings: input.settings,
334
- evmVersion: input.settings?.evmVersion || 'cancun',
335
- viaIR: input.settings?.viaIR || false,
336
- libraries: input.settings?.libraries || {}
337
- },
338
- allowPaths,
339
- basePath,
340
- includePaths,
341
- output: {
342
- contracts: output.contracts || {},
343
- sources: output.sources || {}
344
- },
345
- solcLongVersion: solcLongVersion || solcVersion,
346
- solcVersion: solcVersion
347
- }
348
-
349
- // Print build-info JSON
350
- console.log(options.raw ? JSON.stringify(buildInfo) : JSON.stringify(buildInfo, null, 2))
351
- } catch (error) {
352
- console.error(chalk.red('Error fetching source from Etherscan:'), error instanceof Error ? error.message : String(error))
353
- process.exit(1)
354
- }
355
- })
356
-
357
- etherscan.addCommand(abi)
358
- etherscan.addCommand(source)
359
- return etherscan
360
- }
@@ -1,5 +0,0 @@
1
- export * from './run'
2
- export * from './dry'
3
- export * from './list'
4
- export * from './utils'
5
- export * from './etherscan'
@@ -1,249 +0,0 @@
1
- import { Command } from 'commander'
2
- import chalk from 'chalk'
3
- import * as path from 'path'
4
- import { loadProject, projectOption, noStdOption, verbosityOption } from './common'
5
- import { loadNetworks } from '../lib/network-loader'
6
- import { setVerbosity } from '../index'
7
-
8
- interface ListOptions {
9
- project: string
10
- std: boolean
11
- verbose: number
12
- }
13
-
14
- interface NetworksListOptions {
15
- project: string
16
- verbose: number
17
- onlyTestnets?: boolean
18
- onlyNonTestnets?: boolean
19
- }
20
-
21
- export function makeListCommand(): Command {
22
- const list = new Command('list')
23
- .description('List project resources like jobs, contracts, and networks')
24
-
25
- const listJobs = new Command('jobs')
26
- .description('List all available jobs in the project')
27
- projectOption(listJobs)
28
- noStdOption(listJobs)
29
- verbosityOption(listJobs)
30
- listJobs.action(async (options: ListOptions) => {
31
- try {
32
- // Set verbosity level for logging
33
- setVerbosity(options.verbose as 0 | 1 | 2 | 3)
34
- const loader = await loadProject(options.project, {
35
- loadStdTemplates: options.std !== false
36
- })
37
- console.log(chalk.bold.underline('Available Jobs:'))
38
- if (loader.jobs.size === 0) {
39
- console.log(chalk.yellow('No jobs found in this project.'))
40
- return
41
- }
42
- for (const job of loader.jobs.values()) {
43
- const deprecatedMark = (job as { deprecated?: boolean }).deprecated ? ` ${chalk.yellow('(deprecated)')}` : ''
44
- console.log(`- ${chalk.cyan(job.name)} (v${job.version})${deprecatedMark}`)
45
- if (job.description) {
46
- console.log(` ${chalk.gray(job.description)}`)
47
- }
48
- }
49
- } catch (error) {
50
- console.error(chalk.red('Error listing jobs:'), error instanceof Error ? error.message : String(error))
51
- process.exit(1)
52
- }
53
- })
54
-
55
- const listContracts = new Command('contracts')
56
- .description('List all contracts found in the project')
57
- projectOption(listContracts)
58
- noStdOption(listContracts)
59
- verbosityOption(listContracts)
60
- listContracts.action(async (options: ListOptions) => {
61
- try {
62
- // Set verbosity level for logging
63
- setVerbosity(options.verbose as 0 | 1 | 2 | 3)
64
- const loader = await loadProject(options.project, {
65
- loadStdTemplates: options.std !== false
66
- })
67
- const contracts = loader.contractRepository.getAll()
68
- const ambiguousRefs = loader.contractRepository.getAmbiguousReferences()
69
-
70
- // Display contracts
71
- console.log(chalk.bold.underline('Available Contracts:'))
72
- if (contracts.length === 0) {
73
- console.log(chalk.yellow('No contracts found in this project.'))
74
- } else {
75
- for (const contract of contracts) {
76
- const name = contract.contractName || 'Unknown'
77
- const source = contract.sourceName || 'Unknown'
78
- console.log(`- ${chalk.cyan(name)} (${source})`)
79
- console.log(` ${chalk.gray('Unique Hash:')} ${contract.uniqueHash}`)
80
- if (contract.buildInfoId) {
81
- console.log(` ${chalk.gray('Build Info ID:')} ${contract.buildInfoId}`)
82
- }
83
- console.log(` ${chalk.gray('Sources:')} ${Array.from(contract._sources).map(p => path.relative(options.project, p)).join(', ')}`)
84
- }
85
- }
86
-
87
- // Display ambiguous references if any
88
- if (ambiguousRefs.length > 0) {
89
- console.log('\n' + chalk.bold.underline(chalk.yellow('Ambiguous References:')))
90
- console.log(chalk.yellow('The following references point to multiple contracts:'))
91
- for (const ref of ambiguousRefs) {
92
- console.log(`- ${chalk.red(ref)}`)
93
- }
94
- console.log(chalk.yellow('Use the unique hash or a more specific path to reference these contracts.'))
95
- }
96
-
97
- if (contracts.length === 0) {
98
- console.log('\n' + chalk.yellow('No contracts found in this project. Make sure you have artifact files or build-info files in your project.'))
99
- }
100
- } catch (error) {
101
- console.error(chalk.red('Error listing contracts:'), error instanceof Error ? error.message : String(error))
102
- process.exit(1)
103
- }
104
- })
105
-
106
- const listTemplates = new Command('templates')
107
- .description('List all available templates')
108
- projectOption(listTemplates)
109
- noStdOption(listTemplates)
110
- verbosityOption(listTemplates)
111
- listTemplates.action(async (options: ListOptions) => {
112
- try {
113
- // Set verbosity level for logging
114
- setVerbosity(options.verbose as 0 | 1 | 2 | 3)
115
- const loader = await loadProject(options.project, {
116
- loadStdTemplates: options.std !== false
117
- })
118
- console.log(chalk.bold.underline('Available Templates:'))
119
- if (loader.templates.size === 0) {
120
- console.log(chalk.yellow('No templates found.'))
121
- return
122
- }
123
- for (const template of loader.templates.values()) {
124
- console.log(`- ${chalk.cyan(template.name)}`)
125
- if (template.description) {
126
- console.log(` ${chalk.gray(template.description)}`)
127
- }
128
- }
129
- } catch (error) {
130
- console.error(chalk.red('Error listing templates:'), error instanceof Error ? error.message : String(error))
131
- process.exit(1)
132
- }
133
- })
134
-
135
- const listNetworks = new Command('networks')
136
- .description('List all configured networks')
137
- projectOption(listNetworks)
138
- verbosityOption(listNetworks)
139
- listNetworks.option('--only-testnets', 'Show only test networks')
140
- listNetworks.option('--only-non-testnets', 'Show only non-test networks')
141
- listNetworks.option('--simple', 'Output only network names, one per line')
142
- listNetworks.option('--simple-chain-ids', 'Output only chain IDs, one per line')
143
- listNetworks.action(async (options: NetworksListOptions & { simple?: boolean; simpleChainIds?: boolean }) => {
144
- try {
145
- // Set verbosity level for logging
146
- setVerbosity(options.verbose as 0 | 1 | 2 | 3)
147
- const networks = await loadNetworks(options.project)
148
-
149
- // Apply filtering if specified
150
- let filteredNetworks = networks
151
- if (options.onlyTestnets) {
152
- filteredNetworks = networks.filter(network => network.testnet === true)
153
- } else if (options.onlyNonTestnets) {
154
- filteredNetworks = networks.filter(network => network.testnet !== true)
155
- }
156
-
157
- // Handle simple output formats
158
- if (options.simple) {
159
- if (filteredNetworks.length === 0) {
160
- console.log('')
161
- return
162
- }
163
- console.log(filteredNetworks.map(network => network.name).join('\n'))
164
- return
165
- }
166
-
167
- if (options.simpleChainIds) {
168
- if (filteredNetworks.length === 0) {
169
- console.log('')
170
- return
171
- }
172
- console.log(filteredNetworks.map(network => network.chainId.toString()).join('\n'))
173
- return
174
- }
175
-
176
- // Default formatted output
177
- console.log(chalk.bold.underline('Available Networks:'))
178
- if (filteredNetworks.length === 0) {
179
- if (options.onlyTestnets) {
180
- console.log(chalk.yellow('No test networks configured.'))
181
- } else if (options.onlyNonTestnets) {
182
- console.log(chalk.yellow('No non-test networks configured.'))
183
- } else {
184
- console.log(chalk.yellow('No networks configured. Create a networks.yaml file in your project root.'))
185
- }
186
- return
187
- }
188
-
189
- for (const network of filteredNetworks) {
190
- const testnetIndicator = network.testnet ? chalk.green('(testnet)') : ''
191
- console.log(`- ${chalk.cyan(network.name)} (Chain ID: ${network.chainId}) ${testnetIndicator}`)
192
- console.log(` ${chalk.gray(`RPC: ${network.rpcUrl}`)}`)
193
- }
194
- } catch (error) {
195
- console.error(chalk.red('Error listing networks:'), error instanceof Error ? error.message : String(error))
196
- process.exit(1)
197
- }
198
- })
199
-
200
- // New: list constants
201
- const listConstants = new Command('constants')
202
- .description('List constants defined at top-level and per job')
203
- projectOption(listConstants)
204
- noStdOption(listConstants)
205
- verbosityOption(listConstants)
206
- listConstants.action(async (options: ListOptions) => {
207
- try {
208
- setVerbosity(options.verbose as 0 | 1 | 2 | 3)
209
- const loader = await loadProject(options.project, {
210
- loadStdTemplates: options.std !== false
211
- })
212
- console.log(chalk.bold.underline('Top-level Constants:'))
213
- if (loader.constants.size === 0) {
214
- console.log(chalk.yellow('No top-level constants found.'))
215
- } else {
216
- for (const [key, value] of loader.constants.entries()) {
217
- // Only display keys to avoid dumping large values
218
- console.log(`- ${chalk.cyan(key)}${options.verbose ? ` = ${JSON.stringify(value)}` : ''}`)
219
- }
220
- }
221
- console.log(chalk.bold.underline('\nJob-level Constants:'))
222
- let anyJobConstants = false
223
- for (const job of loader.jobs.values()) {
224
- const constants = job.constants
225
- if (constants && Object.keys(constants).length > 0) {
226
- anyJobConstants = true
227
- console.log(`- ${chalk.cyan(job.name)}:`)
228
- for (const key of Object.keys(constants)) {
229
- console.log(` • ${key}${options.verbose ? ` = ${JSON.stringify(constants[key])}` : ''}`)
230
- }
231
- }
232
- }
233
- if (!anyJobConstants) {
234
- console.log(chalk.yellow('No job-level constants found.'))
235
- }
236
- } catch (error) {
237
- console.error(chalk.red('Error listing constants:'), error instanceof Error ? error.message : String(error))
238
- process.exit(1)
239
- }
240
- })
241
-
242
- list.addCommand(listJobs)
243
- list.addCommand(listContracts)
244
- list.addCommand(listTemplates)
245
- list.addCommand(listNetworks)
246
- list.addCommand(listConstants)
247
-
248
- return list
249
- }