@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,4 +0,0 @@
1
- {
2
- "contractName": "MissingAbi",
3
- "bytecode": "0x608060405234801561001057600080fd5b50"
4
- }
@@ -1,11 +0,0 @@
1
- {
2
- "contractName": "MissingBytecode",
3
- "abi": [
4
- {
5
- "type": "function",
6
- "name": "test",
7
- "inputs": [],
8
- "outputs": []
9
- }
10
- ]
11
- }
@@ -1,11 +0,0 @@
1
- {
2
- "abi": [
3
- {
4
- "type": "function",
5
- "name": "test",
6
- "inputs": [],
7
- "outputs": []
8
- }
9
- ],
10
- "bytecode": "0x608060405234801561001057600080fd5b50"
11
- }
@@ -1,40 +0,0 @@
1
- {
2
- "contractName": "SimpleToken",
3
- "abi": [
4
- {
5
- "type": "constructor",
6
- "inputs": [
7
- {
8
- "name": "name",
9
- "type": "string"
10
- },
11
- {
12
- "name": "symbol",
13
- "type": "string"
14
- }
15
- ]
16
- },
17
- {
18
- "type": "function",
19
- "name": "transfer",
20
- "inputs": [
21
- {
22
- "name": "to",
23
- "type": "address"
24
- },
25
- {
26
- "name": "amount",
27
- "type": "uint256"
28
- }
29
- ],
30
- "outputs": [
31
- {
32
- "name": "",
33
- "type": "bool"
34
- }
35
- ]
36
- }
37
- ],
38
- "bytecode": "0x608060405234801561001057600080fd5b506040516103e93803806103e98339818101604052810190610032919061007a565b80600090805190602001906100489291906100ad565b50506100fb565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100a982610060565b810181811067ffffffffffffffff821117156100c8576100c7610071565b5b80604052505050565b60006100db6100a0565b90506100e782826100a0565b919050565b6000819050919050565b6100ff816100ec565b811461010a57600080fd5b50565b60008151905061011c816100f6565b92915050565b6000602082840312156101385761013761005b565b5b60006101468482850161010d565b91505092915050565b6102df8061015f6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a9059cbb1461003b578063dd62ed3e14610057575b600080fd5b61005560048036038101906100509190610123565b610087565b005b610071600480360381019061006c9190610163565b6100a1565b60405161007e91906101b2565b60405180910390f35b6000610094338484610121565b50505050565b50565b600082600082815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a26469706673582212206a",
39
- "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a9059cbb1461003b578063dd62ed3e14610057575b600080fd5b61005560048036038101906100509190610123565b610087565b005b610071600480360381019061006c9190610163565b6100a1565b60405161007e91906101b2565b60405180910390f35b6000610094338484610121565b50505050565b50565b600082600082815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a26469706673582212206a"
40
- }
@@ -1,7 +0,0 @@
1
- {
2
- "contractName": 123,
3
- "abi": "not-an-array",
4
- "bytecode": {
5
- "object": "0x608060405234801561001057600080fd5b50"
6
- }
7
- }
@@ -1,72 +0,0 @@
1
- import { ArtifactParser } from './types'
2
- import { Artifact } from '../../types'
3
- import * as path from 'path'
4
-
5
- /**
6
- * A parser for Foundry 1.2+ artifact format.
7
- * Can handle artifacts with or without explicit "contractName" field.
8
- * If no contractName is present, it attempts to extract it from:
9
- * 1. metadata.settings.compilationTarget
10
- * 2. The filename as a fallback
11
- */
12
- export const foundry12Parser: ArtifactParser = (content: string, filePath: string): Omit<Artifact, '_path' | '_hash'> | null => {
13
- try {
14
- const json = JSON.parse(content)
15
-
16
- // Basic validation to see if it matches our expected structure
17
- if (
18
- typeof json === 'object' &&
19
- json !== null &&
20
- Array.isArray(json.abi) &&
21
- (typeof json.bytecode === 'string' || (typeof json.bytecode === 'object' && typeof json.bytecode.object === 'string'))
22
- ) {
23
- // Handle Hardhat-style bytecode object vs. simple string
24
- const bytecode = typeof json.bytecode === 'object' ? json.bytecode.object : json.bytecode
25
- if (!bytecode || !bytecode.startsWith('0x')) {
26
- return null // Bytecode must be a hex string
27
- }
28
-
29
- const deployedBytecode = typeof json.deployedBytecode === 'object' ? json.deployedBytecode?.object : json.deployedBytecode
30
-
31
- // Extract contract name from various sources
32
- let contractName = json.contractName
33
-
34
- // If no explicit contractName, prefer filename over metadata to match file-based lookups
35
- if (!contractName && filePath) {
36
- const basename = path.basename(filePath, '.json')
37
- contractName = basename
38
- }
39
-
40
- // If still no contract name, try to extract from metadata as fallback
41
- if (!contractName && json.metadata?.settings?.compilationTarget) {
42
- const compilationTarget = json.metadata.settings.compilationTarget
43
- // compilationTarget is like {"src/Counter.sol": "Counter"}
44
- const contractNames = Object.values(compilationTarget)
45
- if (contractNames.length > 0) {
46
- contractName = contractNames[0]
47
- }
48
- }
49
-
50
- // Must have a contract name to proceed
51
- if (!contractName) {
52
- return null
53
- }
54
-
55
- // We have a likely match
56
- return {
57
- contractName: contractName,
58
- sourceName: json.sourceName,
59
- abi: json.abi,
60
- bytecode: bytecode,
61
- deployedBytecode: deployedBytecode,
62
- compiler: json.compiler,
63
- source: json.source,
64
- }
65
- }
66
-
67
- return null
68
- } catch (error) {
69
- // Not valid JSON, so it's not for this parser
70
- return null
71
- }
72
- }
@@ -1,27 +0,0 @@
1
- import { ArtifactParser } from './types'
2
- import { foundry12Parser } from './foundry-1.2'
3
- import { Artifact } from '../../types'
4
-
5
- // Array of all available artifact parsers.
6
- // To add a new format, create a new parser and add it to this list.
7
- const parsers: ArtifactParser[] = [
8
- foundry12Parser,
9
- // Future parsers (e.g., truffleParser) would go here.
10
- ]
11
-
12
- /**
13
- * Attempts to parse a file's content using a series of registered parsers.
14
- * Returns the first successfully parsed Artifact.
15
- * @param content The raw string content of the file.
16
- * @param filePath The path to the file being parsed.
17
- * @returns A parsed Artifact object or null if no parser succeeds.
18
- */
19
- export function parseArtifact(content: string, filePath: string): Omit<Artifact, '_path' | '_hash'> | null {
20
- for (const parser of parsers) {
21
- const result = parser(content, filePath)
22
- if (result) {
23
- return result
24
- }
25
- }
26
- return null
27
- }
@@ -1,9 +0,0 @@
1
- import { Artifact } from '../../types'
2
-
3
- /**
4
- * A function that attempts to parse a file's content into a standard Artifact object.
5
- * @param content The raw string content of the file.
6
- * @param filePath The path to the file being parsed.
7
- * @returns An object conforming to the Artifact interface (without internal properties), or null if parsing fails.
8
- */
9
- export type ArtifactParser = (content: string, filePath: string) => Omit<Artifact, '_path' | '_hash'> | null
@@ -1,127 +0,0 @@
1
- import { createHash } from 'crypto'
2
- import { keccak256, toUtf8Bytes } from 'ethers'
3
- import { BuildInfo, ExtractedContract } from '../types'
4
-
5
- /**
6
- * Validates if a parsed object is a valid build-info file
7
- * Supports standard build-info formats and factory-style formats
8
- */
9
- function isValidBuildInfo(data: any): data is BuildInfo {
10
- return (
11
- data &&
12
- typeof data === 'object' &&
13
- // _format field is optional (for factory-style formats)
14
- (data._format === undefined || data._format === 'hh-sol-build-info-1' || data._format === 'ethers-rs-sol-build-info-1') &&
15
- typeof data.id === 'string' &&
16
- typeof data.solcVersion === 'string' &&
17
- // solcLongVersion is optional (for factory-style formats)
18
- (data.solcLongVersion === undefined || typeof data.solcLongVersion === 'string') &&
19
- data.input &&
20
- typeof data.input === 'object' &&
21
- data.output &&
22
- typeof data.output === 'object' &&
23
- data.output.contracts &&
24
- typeof data.output.contracts === 'object'
25
- )
26
- }
27
-
28
- /**
29
- * Parses a build-info file and extracts individual contracts
30
- * @param content The raw string content of the build-info file
31
- * @param filePath The path to the build-info file
32
- * @returns Array of extracted contracts or null if parsing fails
33
- */
34
- export function parseBuildInfo(content: string, filePath: string): ExtractedContract[] | null {
35
- try {
36
- const data = JSON.parse(content)
37
-
38
- if (!isValidBuildInfo(data)) {
39
- return null
40
- }
41
-
42
- const extractedContracts: ExtractedContract[] = []
43
-
44
- // Extract contracts from output.contracts
45
- for (const [sourceName, sourceContracts] of Object.entries(data.output.contracts)) {
46
- for (const [contractName, contractData] of Object.entries(sourceContracts)) {
47
- // Validate contract data
48
- if (!contractData.abi || !Array.isArray(contractData.abi)) {
49
- continue
50
- }
51
-
52
- // Handle both Hardhat format (with 0x prefix) and ethers-rs format (without 0x prefix)
53
- if (!contractData.evm?.bytecode?.object ||
54
- (!contractData.evm.bytecode.object.startsWith('0x') && !/^[0-9a-fA-F]+$/.test(contractData.evm.bytecode.object))) {
55
- continue
56
- }
57
-
58
- // Get source content if available
59
- const sourceContent = data.input.sources[sourceName]?.content
60
-
61
- // Normalize bytecode to ensure it has 0x prefix (required by the rest of the system)
62
- const bytecode = contractData.evm.bytecode.object.startsWith('0x')
63
- ? contractData.evm.bytecode.object
64
- : '0x' + contractData.evm.bytecode.object
65
-
66
- const deployedBytecode = contractData.evm.deployedBytecode?.object
67
- ? (contractData.evm.deployedBytecode.object.startsWith('0x')
68
- ? contractData.evm.deployedBytecode.object
69
- : '0x' + contractData.evm.deployedBytecode.object)
70
- : undefined
71
-
72
- // Create the extracted contract
73
- const extractedContract: ExtractedContract = {
74
- contractName,
75
- sourceName,
76
- fullyQualifiedName: `${sourceName}:${contractName}`,
77
- abi: contractData.abi,
78
- bytecode,
79
- deployedBytecode,
80
- source: sourceContent,
81
- compiler: {
82
- // Use solcLongVersion if available, otherwise fallback to solcVersion
83
- version: data.solcLongVersion || data.solcVersion
84
- },
85
- buildInfoId: data.id,
86
- buildInfoPath: filePath
87
- }
88
-
89
- extractedContracts.push(extractedContract)
90
- }
91
- }
92
-
93
- return extractedContracts.length > 0 ? extractedContracts : null
94
-
95
- } catch (error) {
96
- // Not valid JSON or other parsing error
97
- return null
98
- }
99
- }
100
-
101
- /**
102
- * Checks if a file path looks like a build-info file
103
- * Follows the conventions: artifacts/build-info/*.json or out/build-info/*.json
104
- */
105
- export function isBuildInfoFile(filePath: string): boolean {
106
- // Standard build-info file patterns
107
- if (filePath.includes('/build-info/') && filePath.endsWith('.json')) {
108
- return true
109
- }
110
-
111
- return false
112
- }
113
-
114
- /**
115
- * Converts an ExtractedContract to an Artifact-compatible format
116
- */
117
- export function extractedContractToArtifact(extracted: ExtractedContract): Omit<import('../types').Artifact, '_path' | '_hash'> {
118
- return {
119
- contractName: extracted.contractName,
120
- abi: extracted.abi,
121
- bytecode: extracted.bytecode,
122
- deployedBytecode: extracted.deployedBytecode,
123
- sourceName: extracted.sourceName,
124
- source: extracted.source,
125
- compiler: extracted.compiler
126
- }
127
- }
@@ -1,56 +0,0 @@
1
- import { parse as parseYaml, YAMLParseError } from 'yaml'
2
- import { ConstantsDocument } from '../types'
3
-
4
- /**
5
- * Parses a YAML string defining a constants document into a structured ConstantsDocument.
6
- * Accepts files with `type: "constants"`, optional `name`, and required `constants` object.
7
- * Returns null if the YAML is not a constants document.
8
- */
9
- export function parseConstants(yamlContent: string): ConstantsDocument | null {
10
- let rawObject: any
11
- try {
12
- rawObject = parseYaml(yamlContent)
13
- } catch (e) {
14
- if (e instanceof YAMLParseError) {
15
- const line = (e as any).linePos?.[0]?.line ? ` at line ${(e as any).linePos[0].line}` : ''
16
- throw new Error(`Failed to parse constants YAML: ${e.message}${line}.`)
17
- }
18
- throw e
19
- }
20
-
21
- if (!rawObject || typeof rawObject !== 'object') {
22
- return null
23
- }
24
-
25
- if (rawObject.type !== 'constants') {
26
- return null
27
- }
28
-
29
- if (rawObject.name !== undefined && typeof rawObject.name !== 'string') {
30
- throw new Error('Invalid constants: "name" must be a string if provided.')
31
- }
32
-
33
- if (!rawObject.constants || typeof rawObject.constants !== 'object' || Array.isArray(rawObject.constants)) {
34
- throw new Error('Invalid constants: "constants" field is required and must be an object.')
35
- }
36
-
37
- const doc: ConstantsDocument = {
38
- type: 'constants',
39
- name: rawObject.name,
40
- constants: rawObject.constants
41
- }
42
-
43
- return doc
44
- }
45
-
46
- /**
47
- * Validates and extracts optional job-level constants from a parsed job raw object.
48
- * Throws if present but not an object.
49
- */
50
- export function extractJobConstants(rawJob: any, jobNameForErrors: string): Record<string, any> | undefined {
51
- if (rawJob.constants === undefined) return undefined
52
- if (typeof rawJob.constants !== 'object' || Array.isArray(rawJob.constants)) {
53
- throw new Error(`Invalid job "${jobNameForErrors}": "constants" field must be an object if provided.`)
54
- }
55
- return rawJob.constants as Record<string, any>
56
- }
@@ -1,5 +0,0 @@
1
- // Export all parsers
2
- export * from './template'
3
- export * from './job'
4
- export * from './buildinfo'
5
- export * from './constants'
@@ -1,148 +0,0 @@
1
- import { parse as parseYaml, YAMLParseError } from 'yaml'
2
- import { Condition, Job, JobAction } from '../types'
3
-
4
- /**
5
- * Determines whether a raw YAML item is a valid Condition.
6
- * Mirrors the validation logic used for templates so job-level
7
- * skip conditions behave consistently.
8
- */
9
- function isCondition(item: any): item is Condition {
10
- if (!item || typeof item !== 'object' || typeof item.type !== 'string') {
11
- return false
12
- }
13
-
14
- if (['contract-exists', 'job-completed'].includes(item.type)) {
15
- return true
16
- }
17
-
18
- if (item.type === 'basic-arithmetic') {
19
- const op = item.arguments?.operation
20
- return typeof op === 'string' && ['eq', 'neq', 'gt', 'lt', 'gte', 'lte'].includes(op)
21
- }
22
-
23
- return false
24
- }
25
-
26
- /**
27
- * Parses a YAML string defining a job into a structured `Job` object.
28
- * This function validates the presence and basic types of required fields
29
- * for both the job and its nested actions.
30
- *
31
- * @param yamlContent The raw YAML content of the job file as a string.
32
- * @returns The parsed and validated `Job` object.
33
- * @throws {Error} If the YAML is malformed or if the job is missing required fields.
34
- */
35
- export function parseJob(yamlContent: string): Job {
36
- let rawObject: any
37
- try {
38
- rawObject = parseYaml(yamlContent)
39
- } catch (e) {
40
- if (e instanceof YAMLParseError) {
41
- const line = e.linePos?.[0].line ? ` at line ${e.linePos[0].line}` : ''
42
- throw new Error(`Failed to parse job YAML: ${e.message}${line}.`)
43
- }
44
- throw e
45
- }
46
-
47
- if (!rawObject || typeof rawObject !== 'object') {
48
- throw new Error('Invalid job: YAML content must resolve to an object.')
49
- }
50
-
51
- // If a top-level discriminator exists and is not a job, bail out early with a helpful error
52
- if (rawObject.type && rawObject.type !== 'job') {
53
- throw new Error('Invalid job: unexpected type discriminator. Did you mean a template file with type: "template"?')
54
- }
55
-
56
- // --- Validate required top-level fields ---
57
- if (!rawObject.name || typeof rawObject.name !== 'string') {
58
- throw new Error('Invalid job: "name" field is required and must be a string.')
59
- }
60
- // The YAML parser may interpret a version like "1.0" as a number, so we ensure it's a string.
61
- if (!rawObject.version) {
62
- throw new Error(`Invalid job "${rawObject.name}": "version" field is required.`)
63
- }
64
- rawObject.version = String(rawObject.version)
65
-
66
- if (!rawObject.actions || !Array.isArray(rawObject.actions)) {
67
- throw new Error(`Invalid job "${rawObject.name}": "actions" field is required and must be an array.`)
68
- }
69
-
70
- // --- Validate each action within the job ---
71
- for (const action of rawObject.actions) {
72
- if (!action || typeof action !== 'object') {
73
- throw new Error(`Invalid job "${rawObject.name}": contains a non-object item in "actions" array.`)
74
- }
75
- if (!action.name || typeof action.name !== 'string') {
76
- throw new Error(`Invalid job "${rawObject.name}": an action is missing the required "name" field.`)
77
- }
78
-
79
- // Validate that the action has either a template or type field, but not both
80
- const hasTemplate = action.template && typeof action.template === 'string'
81
- const hasType = action.type && typeof action.type === 'string'
82
-
83
- if (!hasTemplate && !hasType) {
84
- throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" must have either a "template" field (for template actions) or a "type" field (for primitive actions).`)
85
- }
86
- if (hasTemplate && hasType) {
87
- throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" cannot have both "template" and "type" fields. Use only one.`)
88
- }
89
-
90
- if (!action.arguments || typeof action.arguments !== 'object' || Array.isArray(action.arguments)) {
91
- throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" is missing the required "arguments" field or it is not an object.`)
92
- }
93
-
94
- // Validate the optional output field
95
- if (action.output !== undefined) {
96
- const t = typeof action.output
97
- const isObject = t === 'object' && action.output !== null && !Array.isArray(action.output)
98
- if (t !== 'boolean' && !isObject) {
99
- throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" has an invalid "output" field. It must be either a boolean (true/false) or an object mapping custom outputs.`)
100
- }
101
- }
102
- }
103
-
104
- // --- Optional: validate deprecated flag if present ---
105
- if (rawObject.deprecated !== undefined && typeof rawObject.deprecated !== 'boolean') {
106
- throw new Error(`Invalid job "${rawObject.name}": "deprecated" must be a boolean if provided.`)
107
- }
108
- // --- Optional: validate min_evm_version if present ---
109
- if (rawObject.min_evm_version !== undefined && typeof rawObject.min_evm_version !== 'string') {
110
- throw new Error(`Invalid job "${rawObject.name}": "min_evm_version" must be a string if provided.`)
111
- }
112
-
113
- // --- Optional: validate job-level skip_condition and constants ---
114
- if (rawObject.skip_condition !== undefined) {
115
- if (!Array.isArray(rawObject.skip_condition)) {
116
- throw new Error(`Invalid job "${rawObject.name}": "skip_condition" must be an array if provided.`)
117
- }
118
- for (const condition of rawObject.skip_condition) {
119
- if (!isCondition(condition)) {
120
- throw new Error(`Invalid job "${rawObject.name}": "skip_condition" contains an invalid condition entry.`)
121
- }
122
- }
123
- }
124
-
125
- if (rawObject.constants !== undefined) {
126
- if (typeof rawObject.constants !== 'object' || rawObject.constants === null || Array.isArray(rawObject.constants)) {
127
- throw new Error(`Invalid job "${rawObject.name}": "constants" field must be an object if provided.`)
128
- }
129
- }
130
-
131
- // --- Construct and return the strongly-typed Job object ---
132
- const job: Job = {
133
- name: rawObject.name,
134
- version: rawObject.version,
135
- description: rawObject.description,
136
- depends_on: rawObject.depends_on,
137
- // We've validated the necessary parts, so a cast is reasonable here.
138
- actions: rawObject.actions as JobAction[],
139
- only_networks: rawObject.only_networks,
140
- skip_networks: rawObject.skip_networks,
141
- min_evm_version: rawObject.min_evm_version,
142
- deprecated: rawObject.deprecated === true,
143
- skip_condition: rawObject.skip_condition as Condition[] | undefined,
144
- constants: rawObject.constants,
145
- }
146
-
147
- return job
148
- }
@@ -1,135 +0,0 @@
1
- import { parse as parseYaml, YAMLParseError } from 'yaml'
2
- import { Template, Action, Condition, Value } from '../types'
3
-
4
- /**
5
- * Helper to check if a parsed YAML object represents a Condition.
6
- * Conditions are specific checks that resolve to a boolean, used in `skip_condition` blocks.
7
- * @param item The parsed object from YAML.
8
- * @returns True if the item is a Condition, false otherwise.
9
- */
10
- function isCondition(item: any): item is Condition {
11
- // A 'Condition' must be an object with a 'type' property.
12
- if (!item || typeof item !== 'object' || typeof item.type !== 'string') {
13
- return false
14
- }
15
-
16
- // Check against known, specific condition types from `src/lib/types/conditions.ts`.
17
- if (['contract-exists', 'job-completed'].includes(item.type)) {
18
- return true
19
- }
20
-
21
- if (item.type === 'value-empty') {
22
- return !!(item.arguments && typeof item.arguments === 'object' && 'value' in item.arguments)
23
- }
24
-
25
- // The 'basic-arithmetic' ValueResolver can also act as a Condition
26
- // if it performs a boolean comparison operation.
27
- if (item.type === 'basic-arithmetic') {
28
- if (item.arguments && typeof item.arguments.operation === 'string') {
29
- const booleanOperations = ['eq', 'neq', 'gt', 'lt', 'gte', 'lte']
30
- return booleanOperations.includes(item.arguments.operation)
31
- }
32
- }
33
-
34
- return false
35
- }
36
-
37
- /**
38
- * Parses a YAML string defining an action template into a structured `Template` object.
39
- * This function handles validation and normalization of the template structure, including
40
- * the flexible `setup` block which can be an array of mixed actions/conditions or
41
- * a structured object.
42
- *
43
- * @param yamlContent The raw YAML content of the template file as a string.
44
- * @returns The parsed and validated `Template` object.
45
- * @throws {Error} If the YAML is malformed, or if the template is missing required fields
46
- * like `name`, `actions`, or `outputs`.
47
- */
48
- export function parseTemplate(yamlContent: string): Template {
49
- let rawObject: any
50
- try {
51
- rawObject = parseYaml(yamlContent)
52
- } catch (e) {
53
- if (e instanceof YAMLParseError) {
54
- // Provide a more user-friendly error message including the line number
55
- const line = e.linePos?.[0].line ? ` at line ${e.linePos[0].line}` : ''
56
- throw new Error(`Failed to parse template YAML: ${e.message}${line}.`)
57
- }
58
- throw e
59
- }
60
-
61
- if (!rawObject || typeof rawObject !== 'object') {
62
- throw new Error('Invalid template: YAML content must resolve to an object.')
63
- }
64
-
65
- // If a discriminator is provided, ensure it matches
66
- if (rawObject.type !== undefined && rawObject.type !== 'template') {
67
- throw new Error('Invalid template: expected type to be "template" if provided.')
68
- }
69
-
70
- // --- Validate required fields ---
71
- if (!rawObject.name || typeof rawObject.name !== 'string') {
72
- throw new Error('Invalid template: "name" field is required and must be a string.')
73
- }
74
- if (!rawObject.actions || !Array.isArray(rawObject.actions)) {
75
- throw new Error(`Invalid template "${rawObject.name}": "actions" field is required and must be an array.`)
76
- }
77
-
78
- // Allow 'outputs' to be optional. If it exists, it must be an object.
79
- if (rawObject.outputs && (typeof rawObject.outputs !== 'object' || Array.isArray(rawObject.outputs))) {
80
- throw new Error(`Invalid template "${rawObject.name}": "outputs" field must be an object if provided.`)
81
- }
82
-
83
- // --- Construct the base template object ---
84
- const template: Template = {
85
- type: 'template',
86
- name: rawObject.name,
87
- description: rawObject.description,
88
- arguments: rawObject.arguments,
89
- returns: rawObject.returns,
90
- actions: rawObject.actions as Action[],
91
- skip_condition: rawObject.skip_condition as Condition[],
92
- }
93
-
94
- // Only include outputs if it was provided in the YAML
95
- if (rawObject.outputs) {
96
- template.outputs = rawObject.outputs as Record<string, Value<any>>
97
- }
98
-
99
- // --- Handle the 'setup' block which can have multiple formats ---
100
- if (rawObject.setup) {
101
- if (Array.isArray(rawObject.setup)) {
102
- // Format 1: An array of mixed actions and conditions (e.g., sequence-factory-v1.yaml).
103
- // We need to iterate and categorize each item.
104
- const setupActions: Action[] = []
105
- const setupConditions: Condition[] = []
106
-
107
- for (const item of rawObject.setup) {
108
- if (isCondition(item)) {
109
- setupConditions.push(item)
110
- } else {
111
- // If it's not an explicit condition, we assume it's an action.
112
- setupActions.push(item as Action)
113
- }
114
- }
115
-
116
- template.setup = {}
117
- if (setupActions.length > 0) {
118
- template.setup.actions = setupActions
119
- }
120
- if (setupConditions.length > 0) {
121
- template.setup.skip_condition = setupConditions
122
- }
123
- } else if (typeof rawObject.setup === 'object') {
124
- // Format 2: A structured object (e.g., nano-universal-deployer.yaml), which maps directly to our type.
125
- template.setup = {
126
- actions: (rawObject.setup.actions || []) as Action[],
127
- skip_condition: (rawObject.setup.skip_condition || []) as Condition[],
128
- }
129
- } else {
130
- throw new Error(`Invalid template "${rawObject.name}": "setup" field must be an array or an object if provided.`)
131
- }
132
- }
133
-
134
- return template
135
- }