@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,757 +0,0 @@
1
- import { ethers } from 'ethers'
2
- import {
3
- Value,
4
- ValueResolver as ValueResolverObject,
5
- AbiEncodeValue,
6
- AbiPackValue,
7
- ConstructorEncodeValue,
8
- ComputeCreateValue,
9
- ComputeCreate2Value,
10
- ReadBalanceValue,
11
- BasicArithmeticValue,
12
- CallValue,
13
- ContractExistsValue,
14
- JobCompletedValue,
15
- ReadJsonValue,
16
- ValueEmptyValue,
17
- SliceBytesValue,
18
- } from '../types'
19
- import { ExecutionContext } from './context'
20
- import { isAddress, isBigNumberish, isBytesLike } from '../utils/assertion'
21
-
22
- /**
23
- * A scope for resolving local variables, such as template arguments.
24
- * This allows a template to use placeholders like `{{my_arg}}` which are
25
- * filled in by the job calling the template.
26
- */
27
- export type ResolutionScope = Map<string, any>
28
-
29
- /**
30
- * The ValueResolver is responsible for turning declarative `Value` types from
31
- * the YAML files into concrete, usable data at runtime. It handles placeholders,
32
- * on-chain data fetching, and dynamic computations like encoding and address calculation.
33
- */
34
- export class ValueResolver {
35
- /**
36
- * Resolves a `Value<any>` into its final, concrete form.
37
- * This is the main entry point for the resolver.
38
- *
39
- * @param value The value to resolve. It can be a literal, a `{{...}}` reference string,
40
- * or a `ValueResolver` object (e.g., `{ type: 'abi-encode', ... }`).
41
- * @param context The execution context, providing access to the provider, signer, and outputs.
42
- * @param scope The local resolution scope, used for template arguments.
43
- * @returns A promise that resolves to the final concrete value.
44
- */
45
- public async resolve<T>(value: Value<any>, context: ExecutionContext, scope: ResolutionScope = new Map()): Promise<T> {
46
- // 1. Handle literals (non-string, non-object) and null
47
- if (typeof value !== 'string' && (typeof value !== 'object' || value === null)) {
48
- return value as T
49
- }
50
-
51
- // 2. Handle string values
52
- if (typeof value === 'string') {
53
- const refMatch = value.match(/^{{(.*)}}$/)
54
- if (refMatch) {
55
- // It's a reference like `{{...}}`, resolve the expression inside
56
- const expression = refMatch[1].trim()
57
- return this.resolveExpression(expression, context, scope)
58
- }
59
- // It's a string literal
60
- return value as T
61
- }
62
-
63
- // 3. Handle arrays
64
- if (Array.isArray(value)) {
65
- return Promise.all(value.map(item => this.resolve(item, context, scope))) as Promise<T>
66
- }
67
-
68
- // 4. Handle ValueResolver objects
69
- if (typeof value === 'object' && 'type' in value) {
70
- return this.resolveValueResolverObject(value as ValueResolverObject, context, scope)
71
- }
72
-
73
- // 5. Handle plain objects as literals (for JSON data)
74
- if (typeof value === 'object') {
75
- return value as T
76
- }
77
-
78
- // 6. If we get here, something unexpected happened
79
- throw new Error(`Cannot resolve value: unexpected value type: ${typeof value}`)
80
- }
81
-
82
- /**
83
- * Resolves an expression from inside a `{{...}}` placeholder.
84
- * @private
85
- */
86
- private async resolveExpression(expression: string, context: ExecutionContext, scope: ResolutionScope): Promise<any> {
87
- // Check for Contract(...) syntax with optional property access
88
- const contractMatch = expression.match(/^Contract\((.*?)\)(\.\w+)?$/)
89
- if (contractMatch) {
90
- const [, reference, property] = contractMatch
91
- const contractRef = reference.trim()
92
-
93
- // Look up the contract with context path for relative artifact resolution
94
- const contract = context.contractRepository.lookup(contractRef, context.getContextPath())
95
- if (!contract) {
96
- // Provide extra diagnostics to help users understand where lookup occurred
97
- const ctx = context.getContextPath()
98
- throw new Error(
99
- `Artifact not found for reference: "${contractRef}" (resolved relative to: ${ctx ?? 'N/A'}). ` +
100
- `Ensure the path and contract name are correct and that the build-info/artifact is discoverable.`
101
- )
102
- }
103
-
104
- // If no property requested, return the entire Contract object
105
- if (!property) {
106
- return contract
107
- }
108
-
109
- // Extract the property name (remove the leading dot)
110
- const propName = property.substring(1)
111
-
112
- // Access the requested property
113
- const value = (contract as any)[propName]
114
- if (value === undefined) {
115
- throw new Error(`Property "${propName}" does not exist on contract found for reference "${contractRef}"`)
116
- }
117
-
118
- return value
119
- }
120
-
121
- // Check for Network() property access (single segment or dotted path)
122
- const networkMatch = expression.match(/^Network\(\)\.(.+)$/)
123
- if (networkMatch) {
124
- const path = networkMatch[1]
125
- const segments = path.split('.')
126
- const network = context.getNetwork()
127
-
128
- if (segments.length === 1) {
129
- const property = segments[0]
130
- if (property === 'testnet') {
131
- // Default to false if not set.
132
- return !!network.testnet
133
- }
134
- const value = (network as unknown as Record<string, unknown>)[property]
135
- if (value === undefined) {
136
- throw new Error(`Property "${property}" does not exist on network`)
137
- }
138
- return value
139
- }
140
-
141
- // Dotted paths (e.g. params.myParam): missing keys default to false.
142
- let current: unknown = network
143
- for (const segment of segments) {
144
- if (current === null || current === undefined || typeof current !== 'object') {
145
- return false
146
- }
147
- current = (current as Record<string, unknown>)[segment]
148
- if (current === undefined) {
149
- return false
150
- }
151
- }
152
- return current
153
- }
154
-
155
- // Check scope for local variables (template arguments) first
156
- if (scope.has(expression)) {
157
- return scope.get(expression)
158
- }
159
-
160
- // Check constants (job-level then top-level)
161
- const constantValue = (context as any).getConstant?.(expression)
162
- if (constantValue !== undefined) {
163
- return constantValue
164
- }
165
-
166
- // Check context for global outputs from other jobs/actions
167
- try {
168
- return context.getOutput(expression)
169
- } catch (e) {
170
- // Provide a more helpful error if an unresolved reference is found
171
- throw new Error(`Failed to resolve expression "{{${expression}}}". It is not a valid Contract(...) or Network() reference, local scope variable, constant, or a known output.`)
172
- }
173
- }
174
-
175
- /**
176
- * Dispatches a `ValueResolver` object to its specific handler.
177
- * @private
178
- */
179
- private async resolveValueResolverObject(
180
- obj: ValueResolverObject,
181
- context: ExecutionContext,
182
- scope: ResolutionScope,
183
- ): Promise<any> {
184
- // Recursively resolve all arguments before processing the object itself
185
- const resolvedArgs = await this.resolveArguments(obj.arguments, context, scope)
186
-
187
- switch (obj.type) {
188
- case 'abi-encode':
189
- return this.resolveAbiEncode(resolvedArgs as AbiEncodeValue['arguments'])
190
- case 'abi-pack':
191
- return this.resolveAbiPack(resolvedArgs as AbiPackValue['arguments'])
192
- case 'constructor-encode':
193
- return this.resolveConstructorEncode(resolvedArgs as ConstructorEncodeValue['arguments'])
194
- case 'compute-create':
195
- return this.resolveComputeCreate(resolvedArgs as ComputeCreateValue['arguments'])
196
- case 'compute-create2':
197
- return this.resolveComputeCreate2(resolvedArgs as ComputeCreate2Value['arguments'])
198
- case 'read-balance':
199
- return this.resolveReadBalance(resolvedArgs as ReadBalanceValue['arguments'], context)
200
- case 'basic-arithmetic':
201
- return this.resolveBasicArithmetic(resolvedArgs as BasicArithmeticValue['arguments'])
202
- case 'call':
203
- return this.resolveCall(resolvedArgs as CallValue['arguments'], context)
204
- case 'contract-exists':
205
- return this.resolveContractExists(resolvedArgs as ContractExistsValue['arguments'], context)
206
- case 'job-completed':
207
- return this.resolveJobCompleted(resolvedArgs as JobCompletedValue['arguments'], context)
208
- case 'read-json':
209
- return this.resolveReadJson(resolvedArgs as ReadJsonValue['arguments'])
210
- case 'resolve-json':
211
- return this.resolveJsonValue(resolvedArgs, context)
212
- case 'value-empty':
213
- return this.resolveValueEmpty(resolvedArgs as ValueEmptyValue['arguments'])
214
- case 'slice-bytes':
215
- return this.resolveSliceBytes(resolvedArgs as SliceBytesValue['arguments'])
216
- default:
217
- throw new Error(`Unknown value resolver type: ${(obj as any).type}`)
218
- }
219
- }
220
-
221
- // --- Specific Resolver Implementations ---
222
-
223
- private resolveAbiEncode(args: AbiEncodeValue['arguments']): string {
224
- const { signature, values } = args
225
-
226
- // Validate that signature is provided
227
- if (!signature) {
228
- throw new Error('abi-encode: signature is required')
229
- }
230
-
231
- // Validate that values array is provided
232
- if (!values) {
233
- throw new Error('abi-encode: values array is required')
234
- }
235
-
236
- // At this point, signature should be resolved to a string
237
- const signatureStr = signature as string
238
- if (typeof signatureStr !== 'string') {
239
- throw new Error('abi-encode: signature must be a string')
240
- }
241
-
242
- try {
243
- // Create a temporary interface with just this function to encode the data
244
- const iface = new ethers.Interface([`function ${signatureStr}`])
245
-
246
- // Get the function name from the signature (everything before the first '(')
247
- const functionName = signatureStr.split('(')[0]
248
-
249
- // Encode the function call data
250
- return iface.encodeFunctionData(functionName, values)
251
- } catch (error) {
252
- throw new Error(`abi-encode: Failed to encode function data: ${error instanceof Error ? error.message : String(error)}`)
253
- }
254
- }
255
-
256
- private resolveAbiPack(args: AbiPackValue['arguments']): string {
257
- const { types, values } = args
258
-
259
- // Validate that types array is provided
260
- if (!types) {
261
- throw new Error('abi-pack: types array is required')
262
- }
263
-
264
- // Validate that values array is provided
265
- if (!values) {
266
- throw new Error('abi-pack: values array is required')
267
- }
268
-
269
- // Validate that types and values arrays have the same length
270
- if (types.length !== values.length) {
271
- throw new Error(`abi-pack: types array length (${types.length}) must match values array length (${values.length})`)
272
- }
273
-
274
- // At this point, types should be resolved to strings
275
- const typesArray = types as string[]
276
- if (!typesArray.every(type => typeof type === 'string')) {
277
- throw new Error('abi-pack: all types must be strings')
278
- }
279
-
280
- try {
281
- // Use ethers.js solidityPacked for packed encoding (no padding)
282
- return ethers.solidityPacked(typesArray, values)
283
- } catch (error) {
284
- throw new Error(`abi-pack: Failed to pack values: ${error instanceof Error ? error.message : String(error)}`)
285
- }
286
- }
287
-
288
- private resolveConstructorEncode(args: ConstructorEncodeValue['arguments']): string {
289
- const { creationCode, types, values } = args
290
-
291
- // Validate that types and values arrays have the same length
292
- if (types && values && types.length !== values.length) {
293
- throw new Error(`constructor-encode: types array length (${types.length}) must match values array length (${values.length})`)
294
- }
295
-
296
- // If no creationCode is provided, just do ABI encoding of constructor arguments
297
- if (!creationCode) {
298
- // If no constructor arguments either, return empty string
299
- if (!types || !values || types.length === 0 || values.length === 0) {
300
- return '0x'
301
- }
302
-
303
- // ABI encode the constructor arguments using the explicit types
304
- return ethers.AbiCoder.defaultAbiCoder().encode(types as string[], values)
305
- }
306
-
307
- // Validate that creation code is valid bytecode
308
- if (!isBytesLike(creationCode)) {
309
- throw new Error(`Invalid creation code: ${creationCode}`)
310
- }
311
-
312
- // If no constructor arguments, return the creation code as-is
313
- if (!types || !values || types.length === 0 || values.length === 0) {
314
- return creationCode
315
- }
316
-
317
- // ABI encode the constructor arguments using the explicit types
318
- const encodedArgs = ethers.AbiCoder.defaultAbiCoder().encode(types as string[], values)
319
-
320
- // Concatenate creation code with encoded constructor arguments
321
- // Remove '0x' prefix from encoded args if present
322
- const cleanEncodedArgs = encodedArgs.startsWith('0x') ? encodedArgs.slice(2) : encodedArgs
323
- const cleanCreationCode = creationCode.startsWith('0x') ? creationCode.slice(2) : creationCode
324
-
325
- return '0x' + cleanCreationCode + cleanEncodedArgs
326
- }
327
-
328
- private resolveComputeCreate(args: ComputeCreateValue['arguments']): string {
329
- const { deployerAddress, nonce } = args
330
- // Check if the deployer address is a valid address
331
- if (!isAddress(deployerAddress)) {
332
- throw new Error(`Invalid deployer address: ${deployerAddress}`)
333
- }
334
- // Check if the nonce is a valid value
335
- if (!isBigNumberish(nonce)) {
336
- throw new Error(`Invalid nonce: ${nonce}`)
337
- }
338
- const bnNonce = ethers.toBigInt(nonce)
339
- // Create the create address
340
- return ethers.getCreateAddress({
341
- from: deployerAddress,
342
- nonce: bnNonce,
343
- })
344
- }
345
-
346
- private resolveComputeCreate2(args: ComputeCreate2Value['arguments']): string {
347
- const { deployerAddress, salt, initCode } = args
348
- // Check if the deployer address is a valid address
349
- if (!isAddress(deployerAddress)) {
350
- throw new Error(`Invalid deployer address: ${deployerAddress}`)
351
- }
352
- // Check if the salt is a valid bytes value
353
- if (!isBytesLike(salt)) {
354
- throw new Error(`Invalid salt: ${salt}`)
355
- }
356
- // Check if the init code is a valid bytes value
357
- if (!isBytesLike(initCode)) {
358
- throw new Error(`Invalid init code: ${initCode}`)
359
- }
360
- // Hash the init code using Keccak256
361
- const initCodeHash = ethers.keccak256(initCode)
362
- // Create the create2 address
363
- return ethers.getCreate2Address(deployerAddress, salt, initCodeHash)
364
- }
365
-
366
- private async resolveReadBalance(args: ReadBalanceValue['arguments'], context: ExecutionContext): Promise<string> {
367
- // Check if the address is a valid address
368
- const addressValue = args.address as any
369
-
370
- if (!isAddress(addressValue)) {
371
- throw new Error(`Invalid address: ${addressValue}`)
372
- }
373
-
374
- const balance = await context.provider.getBalance(addressValue)
375
- return balance.toString()
376
- }
377
-
378
- private resolveBasicArithmetic(args: BasicArithmeticValue['arguments']): string | boolean {
379
- if (!args.values || args.values.length < 2) {
380
- throw new Error(`basic-arithmetic requires at least 2 values, got ${args.values?.length ?? 0}`)
381
- }
382
-
383
- switch (args.operation) {
384
- // Equality (return boolean, tolerate nullish / non-numeric values)
385
- case 'eq': {
386
- const [a, b] = args.values
387
- return this.valuesEqual(a, b)
388
- }
389
- case 'neq': {
390
- const [a, b] = args.values
391
- return !this.valuesEqual(a, b)
392
- }
393
-
394
- // Arithmetic (return string)
395
- case 'add':
396
- case 'sub':
397
- case 'mul':
398
- case 'div':
399
- case 'gt':
400
- case 'lt':
401
- case 'gte':
402
- case 'lte':
403
- break
404
-
405
- default:
406
- throw new Error(`Unsupported basic-arithmetic operation: ${args.operation}`)
407
- }
408
-
409
- const numbers = args.values.map(v => ethers.toBigInt(v))
410
- const [a, b] = numbers
411
-
412
- switch (args.operation) {
413
- case 'add': return numbers.reduce((sum, current) => sum + current).toString()
414
- case 'sub': return (a - b).toString()
415
- case 'mul': return (a * b).toString()
416
- case 'div': return (a / b).toString()
417
-
418
- // Comparison (return boolean)
419
- case 'gt': return a > b
420
- case 'lt': return a < b
421
- case 'gte': return a >= b
422
- case 'lte': return a <= b
423
-
424
- default:
425
- throw new Error(`Unsupported basic-arithmetic operation: ${args.operation}`)
426
- }
427
- }
428
-
429
- private valuesEqual(a: any, b: any): boolean {
430
- if (a == null || b == null) {
431
- return a == null && b == null
432
- }
433
-
434
- if (isBigNumberish(a) && isBigNumberish(b)) {
435
- return ethers.toBigInt(a) === ethers.toBigInt(b)
436
- }
437
-
438
- if (typeof a === 'string' && typeof b === 'string') {
439
- return a === b
440
- }
441
-
442
- if (typeof a === 'boolean' && typeof b === 'boolean') {
443
- return a === b
444
- }
445
-
446
- if ((typeof a === 'object' && a !== null) || (typeof b === 'object' && b !== null)) {
447
- return JSON.stringify(a) === JSON.stringify(b)
448
- }
449
-
450
- return a === b
451
- }
452
-
453
- private async resolveCall(args: CallValue['arguments'], context: ExecutionContext): Promise<any> {
454
- const { to, signature, values } = args
455
-
456
- // Validate that we have a target address
457
- if (!to) {
458
- throw new Error('call: target address (to) is required')
459
- }
460
-
461
- // Validate that the target address is a valid Ethereum address
462
- if (!isAddress(to)) {
463
- throw new Error(`call: invalid target address: ${to}`)
464
- }
465
-
466
- // Validate that signature is provided
467
- if (!signature) {
468
- throw new Error('call: function signature is required')
469
- }
470
-
471
- // Validate that values array is provided
472
- if (!values) {
473
- throw new Error('call: values array is required')
474
- }
475
-
476
- const signatureStr = signature as string
477
- if (typeof signatureStr !== 'string') {
478
- throw new Error('call: signature must be a string')
479
- }
480
-
481
- try {
482
- // Create a temporary interface with just this function to encode the call data
483
- const iface = new ethers.Interface([`function ${signatureStr}`])
484
-
485
- // Get the function name from the signature (everything before the first '(')
486
- const functionName = signatureStr.split('(')[0]
487
-
488
- // Encode the function call data
489
- const callData = iface.encodeFunctionData(functionName, values)
490
-
491
- // Make the call using the provider
492
- const result = await context.provider.call({
493
- to: to,
494
- data: callData
495
- })
496
-
497
- // If the result is '0x', it means the function doesn't return anything
498
- if (result === '0x') {
499
- return null
500
- }
501
-
502
- // Decode the result using the function's return type
503
- const decodedResult = iface.decodeFunctionResult(functionName, result)
504
-
505
- // If there's only one return value, return it directly
506
- // Otherwise, return the array of values
507
- if (decodedResult.length === 1) {
508
- return decodedResult[0]
509
- }
510
-
511
- return decodedResult
512
- } catch (error) {
513
- throw new Error(`call: Failed to execute contract call: ${error instanceof Error ? error.message : String(error)}`)
514
- }
515
- }
516
-
517
- private async resolveContractExists(args: ContractExistsValue['arguments'], context: ExecutionContext): Promise<boolean> {
518
- const { address } = args
519
-
520
- if (!isAddress(address)) {
521
- throw new Error(`contract-exists: invalid address: ${address}`)
522
- }
523
-
524
- try {
525
- const code = await context.provider.getCode(address)
526
- // getCode returns '0x' if no contract exists at the address
527
- return code !== '0x'
528
- } catch (error) {
529
- throw new Error(`contract-exists: Failed to check contract existence: ${error instanceof Error ? error.message : String(error)}`)
530
- }
531
- }
532
-
533
- private async resolveJobCompleted(args: JobCompletedValue['arguments'], context: ExecutionContext): Promise<boolean> {
534
- const { job: jobName } = args
535
-
536
- // For now, we'll assume that if the job is being referenced, it has been completed.
537
- // This is a simplification - in a more complete implementation, we might check
538
- // the job's completion status from the deployer's results.
539
- //
540
- // Since the dependency graph already ensures jobs run in the correct order,
541
- // and this condition is used in setup blocks to wait for dependencies,
542
- // we can simply return true here.
543
- return true
544
- }
545
-
546
- private resolveReadJson(args: ReadJsonValue['arguments']): any {
547
- const { json, path } = args
548
-
549
- if (json === undefined || json === null) {
550
- throw new Error('read-json: json argument is required')
551
- }
552
-
553
- if (typeof path !== 'string' && typeof path !== 'number') {
554
- throw new Error('read-json: path must be a string or number')
555
- }
556
-
557
- const normalizedPath = String(path)
558
-
559
- // If path is empty, return the entire JSON object
560
- if (normalizedPath === '') {
561
- return json
562
- }
563
-
564
- try {
565
- // Split the path by dots to handle nested access
566
- const pathParts = normalizedPath.split('.')
567
- let current = json
568
-
569
- for (const part of pathParts) {
570
- if (current === null || current === undefined) {
571
- throw new Error(`Cannot access property "${part}" of ${current}`)
572
- }
573
-
574
- // Check if the part is a number (array index)
575
- const index = parseInt(part, 10)
576
- if (!isNaN(index) && Array.isArray(current)) {
577
- current = current[index]
578
- } else if (typeof current === 'object') {
579
- current = current[part]
580
- } else {
581
- throw new Error(`Cannot access property "${part}" of non-object value`)
582
- }
583
- }
584
-
585
- return current
586
- } catch (error) {
587
- throw new Error(`read-json: Failed to access path "${normalizedPath}": ${error instanceof Error ? error.message : String(error)}`)
588
- }
589
- }
590
-
591
- private async resolveJsonValue(args: any, context: ExecutionContext): Promise<any> {
592
- if (Array.isArray(args)) {
593
- return Promise.all(args.map(v => this.resolveJsonValue(v, context)))
594
- } else if (typeof args === 'object' && args !== null) {
595
- const resolved: Record<string, any> = {}
596
- for (const [k, v] of Object.entries(args)) {
597
- resolved[k] = await this.resolveJsonValue(v, context)
598
- }
599
- return resolved
600
- } else {
601
- // For primitive values, resolve them using the main resolve method
602
- return this.resolve(args, context)
603
- }
604
- }
605
-
606
- private resolveValueEmpty(args: ValueEmptyValue['arguments']): boolean {
607
- const { value } = args
608
-
609
- if (value === undefined || value === null) {
610
- return true
611
- }
612
-
613
- if (typeof value === 'string') {
614
- return value === '' || value === '0x'
615
- }
616
-
617
- if (Array.isArray(value)) {
618
- return value.length === 0
619
- }
620
-
621
- if (typeof value === 'object') {
622
- return Object.keys(value).length === 0
623
- }
624
-
625
- return false
626
- }
627
-
628
- private resolveSliceBytes(args: SliceBytesValue['arguments']): string {
629
- const { value, start, end, range } = args
630
-
631
- if (!isBytesLike(value)) {
632
- throw new Error('slice-bytes: value must be bytes-like (hex string, Uint8Array, etc.)')
633
- }
634
-
635
- if (range !== undefined && (start !== undefined || end !== undefined)) {
636
- throw new Error('slice-bytes: provide either range or start/end, not both')
637
- }
638
-
639
- if (range !== undefined && typeof range !== 'string') {
640
- throw new Error('slice-bytes: range must be a string in "start:end" format')
641
- }
642
-
643
- const normalizedHex = ethers.hexlify(value as ethers.BytesLike)
644
- const hexBody = normalizedHex.slice(2)
645
-
646
- if (hexBody.length % 2 !== 0) {
647
- throw new Error('slice-bytes: value must have an even-length hex string')
648
- }
649
-
650
- const totalBytes = hexBody.length / 2
651
- const { startIndex, endIndex } = this.computeSliceBounds(totalBytes, { start, end, range })
652
-
653
- if (startIndex >= endIndex) {
654
- return '0x'
655
- }
656
-
657
- const sliced = hexBody.slice(startIndex * 2, endIndex * 2)
658
- return sliced.length === 0 ? '0x' : `0x${sliced}`
659
- }
660
-
661
- private computeSliceBounds(
662
- totalBytes: number,
663
- params: { start?: any; end?: any; range?: any },
664
- ): { startIndex: number; endIndex: number } {
665
- let startValue: number | undefined
666
- let endValue: number | undefined
667
-
668
- if (params.range !== undefined) {
669
- const trimmedRange = (params.range as string).trim()
670
- const rangeMatch = trimmedRange.match(/^\[?\s*(-?\d+)?\s*:\s*(-?\d+)?\s*\]?$/)
671
-
672
- if (!rangeMatch) {
673
- throw new Error('slice-bytes: range must follow the "start:end" format (e.g., "0:4" or ":-1")')
674
- }
675
-
676
- const [, rawStart, rawEnd] = rangeMatch
677
- if (rawStart !== undefined) {
678
- startValue = this.parseSliceIndex(rawStart, 'range start')
679
- }
680
- if (rawEnd !== undefined) {
681
- endValue = this.parseSliceIndex(rawEnd, 'range end')
682
- }
683
- } else {
684
- if (params.start !== undefined) {
685
- startValue = this.parseSliceIndex(params.start, 'start')
686
- }
687
- if (params.end !== undefined) {
688
- endValue = this.parseSliceIndex(params.end, 'end')
689
- }
690
- }
691
-
692
- const startIndex = this.normalizeSliceIndex(startValue ?? 0, totalBytes)
693
- const endIndex = this.normalizeSliceIndex(endValue ?? totalBytes, totalBytes)
694
-
695
- return { startIndex, endIndex }
696
- }
697
-
698
- private parseSliceIndex(value: any, label: string): number {
699
- if (value === undefined || value === null) {
700
- throw new Error(`slice-bytes: ${label} cannot be null or undefined`)
701
- }
702
-
703
- const normalizedValue = typeof value === 'string' ? value.trim() : value
704
-
705
- try {
706
- const bigIntValue = ethers.toBigInt(normalizedValue)
707
- const maxSafe = BigInt(Number.MAX_SAFE_INTEGER)
708
- if (bigIntValue > maxSafe || bigIntValue < -maxSafe) {
709
- throw new Error(`${label} is outside the supported numeric range`)
710
- }
711
- return Number(bigIntValue)
712
- } catch (_error) {
713
- throw new Error(`slice-bytes: ${label} must be an integer or integer-like string`)
714
- }
715
- }
716
-
717
- private normalizeSliceIndex(index: number, totalBytes: number): number {
718
- if (!Number.isFinite(index) || !Number.isInteger(index)) {
719
- throw new Error('slice-bytes: slice positions must be finite integers')
720
- }
721
-
722
- let normalized = index
723
- if (normalized < 0) {
724
- normalized = totalBytes + normalized
725
- }
726
-
727
- if (normalized < 0) {
728
- normalized = 0
729
- }
730
-
731
- if (normalized > totalBytes) {
732
- normalized = totalBytes
733
- }
734
-
735
- return normalized
736
- }
737
-
738
- /**
739
- * Helper to recursively resolve the `arguments` field of any `ValueResolver` object.
740
- * @private
741
- */
742
- private async resolveArguments(args: any, context: ExecutionContext, scope: ResolutionScope): Promise<any> {
743
- if (Array.isArray(args)) {
744
- return Promise.all(args.map(arg => this.resolve(arg, context, scope)))
745
- }
746
- if (typeof args === 'object' && args !== null) {
747
- const resolvedObject: { [key: string]: any } = {}
748
- for (const key in args) {
749
- if (Object.prototype.hasOwnProperty.call(args, key)) {
750
- resolvedObject[key] = await this.resolve(args[key], context, scope)
751
- }
752
- }
753
- return resolvedObject
754
- }
755
- return this.resolve(args, context, scope)
756
- }
757
- }