@0xsequence/catapult 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. package/.eslintrc.json +29 -0
  2. package/.github/workflows/ci.yml +181 -0
  3. package/CONCEPT.md +24 -0
  4. package/README.md +772 -0
  5. package/contracts/checked-call.huff +65 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +16 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/common.d.ts +11 -0
  11. package/dist/commands/common.d.ts.map +1 -0
  12. package/dist/commands/common.js +73 -0
  13. package/dist/commands/common.js.map +1 -0
  14. package/dist/commands/dry.d.ts +3 -0
  15. package/dist/commands/dry.d.ts.map +1 -0
  16. package/dist/commands/dry.js +171 -0
  17. package/dist/commands/dry.js.map +1 -0
  18. package/dist/commands/etherscan.d.ts +3 -0
  19. package/dist/commands/etherscan.d.ts.map +1 -0
  20. package/dist/commands/etherscan.js +323 -0
  21. package/dist/commands/etherscan.js.map +1 -0
  22. package/dist/commands/index.d.ts +6 -0
  23. package/dist/commands/index.d.ts.map +1 -0
  24. package/dist/commands/index.js +22 -0
  25. package/dist/commands/index.js.map +1 -0
  26. package/dist/commands/list.d.ts +3 -0
  27. package/dist/commands/list.d.ts.map +1 -0
  28. package/dist/commands/list.js +259 -0
  29. package/dist/commands/list.js.map +1 -0
  30. package/dist/commands/run.d.ts +3 -0
  31. package/dist/commands/run.d.ts.map +1 -0
  32. package/dist/commands/run.js +96 -0
  33. package/dist/commands/run.js.map +1 -0
  34. package/dist/commands/utils.d.ts +3 -0
  35. package/dist/commands/utils.d.ts.map +1 -0
  36. package/dist/commands/utils.js +46 -0
  37. package/dist/commands/utils.js.map +1 -0
  38. package/dist/index.d.ts +4 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +58 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/lib/__tests__/deployer-events.spec.d.ts +2 -0
  43. package/dist/lib/__tests__/deployer-events.spec.d.ts.map +1 -0
  44. package/dist/lib/__tests__/deployer-events.spec.js +260 -0
  45. package/dist/lib/__tests__/deployer-events.spec.js.map +1 -0
  46. package/dist/lib/__tests__/deployer.spec.d.ts +2 -0
  47. package/dist/lib/__tests__/deployer.spec.d.ts.map +1 -0
  48. package/dist/lib/__tests__/deployer.spec.js +884 -0
  49. package/dist/lib/__tests__/deployer.spec.js.map +1 -0
  50. package/dist/lib/__tests__/network-utils.spec.d.ts +2 -0
  51. package/dist/lib/__tests__/network-utils.spec.d.ts.map +1 -0
  52. package/dist/lib/__tests__/network-utils.spec.js +140 -0
  53. package/dist/lib/__tests__/network-utils.spec.js.map +1 -0
  54. package/dist/lib/contracts/__tests__/repository.spec.d.ts +2 -0
  55. package/dist/lib/contracts/__tests__/repository.spec.d.ts.map +1 -0
  56. package/dist/lib/contracts/__tests__/repository.spec.js +321 -0
  57. package/dist/lib/contracts/__tests__/repository.spec.js.map +1 -0
  58. package/dist/lib/contracts/repository.d.ts +27 -0
  59. package/dist/lib/contracts/repository.d.ts.map +1 -0
  60. package/dist/lib/contracts/repository.js +241 -0
  61. package/dist/lib/contracts/repository.js.map +1 -0
  62. package/dist/lib/core/__tests__/engine.spec.d.ts +2 -0
  63. package/dist/lib/core/__tests__/engine.spec.d.ts.map +1 -0
  64. package/dist/lib/core/__tests__/engine.spec.js +1212 -0
  65. package/dist/lib/core/__tests__/engine.spec.js.map +1 -0
  66. package/dist/lib/core/__tests__/graph.spec.d.ts +2 -0
  67. package/dist/lib/core/__tests__/graph.spec.d.ts.map +1 -0
  68. package/dist/lib/core/__tests__/graph.spec.js +116 -0
  69. package/dist/lib/core/__tests__/graph.spec.js.map +1 -0
  70. package/dist/lib/core/__tests__/json-integration.spec.d.ts +2 -0
  71. package/dist/lib/core/__tests__/json-integration.spec.d.ts.map +1 -0
  72. package/dist/lib/core/__tests__/json-integration.spec.js +300 -0
  73. package/dist/lib/core/__tests__/json-integration.spec.js.map +1 -0
  74. package/dist/lib/core/__tests__/loader.spec.d.ts +2 -0
  75. package/dist/lib/core/__tests__/loader.spec.d.ts.map +1 -0
  76. package/dist/lib/core/__tests__/loader.spec.js +288 -0
  77. package/dist/lib/core/__tests__/loader.spec.js.map +1 -0
  78. package/dist/lib/core/__tests__/multi-platform-verification.spec.d.ts +2 -0
  79. package/dist/lib/core/__tests__/multi-platform-verification.spec.d.ts.map +1 -0
  80. package/dist/lib/core/__tests__/multi-platform-verification.spec.js +342 -0
  81. package/dist/lib/core/__tests__/multi-platform-verification.spec.js.map +1 -0
  82. package/dist/lib/core/__tests__/resolver.spec.d.ts +2 -0
  83. package/dist/lib/core/__tests__/resolver.spec.d.ts.map +1 -0
  84. package/dist/lib/core/__tests__/resolver.spec.js +1367 -0
  85. package/dist/lib/core/__tests__/resolver.spec.js.map +1 -0
  86. package/dist/lib/core/__tests__/static-action.spec.d.ts +2 -0
  87. package/dist/lib/core/__tests__/static-action.spec.d.ts.map +1 -0
  88. package/dist/lib/core/__tests__/static-action.spec.js +136 -0
  89. package/dist/lib/core/__tests__/static-action.spec.js.map +1 -0
  90. package/dist/lib/core/context.d.ts +29 -0
  91. package/dist/lib/core/context.d.ts.map +1 -0
  92. package/dist/lib/core/context.js +88 -0
  93. package/dist/lib/core/context.js.map +1 -0
  94. package/dist/lib/core/engine.d.ts +25 -0
  95. package/dist/lib/core/engine.d.ts.map +1 -0
  96. package/dist/lib/core/engine.js +1191 -0
  97. package/dist/lib/core/engine.js.map +1 -0
  98. package/dist/lib/core/graph.d.ts +18 -0
  99. package/dist/lib/core/graph.d.ts.map +1 -0
  100. package/dist/lib/core/graph.js +158 -0
  101. package/dist/lib/core/graph.js.map +1 -0
  102. package/dist/lib/core/loader.d.ts +25 -0
  103. package/dist/lib/core/loader.d.ts.map +1 -0
  104. package/dist/lib/core/loader.js +248 -0
  105. package/dist/lib/core/loader.js.map +1 -0
  106. package/dist/lib/core/resolver.d.ts +20 -0
  107. package/dist/lib/core/resolver.d.ts.map +1 -0
  108. package/dist/lib/core/resolver.js +307 -0
  109. package/dist/lib/core/resolver.js.map +1 -0
  110. package/dist/lib/deployer.d.ts +39 -0
  111. package/dist/lib/deployer.d.ts.map +1 -0
  112. package/dist/lib/deployer.js +533 -0
  113. package/dist/lib/deployer.js.map +1 -0
  114. package/dist/lib/events/__tests__/event-system.spec.d.ts +2 -0
  115. package/dist/lib/events/__tests__/event-system.spec.d.ts.map +1 -0
  116. package/dist/lib/events/__tests__/event-system.spec.js +256 -0
  117. package/dist/lib/events/__tests__/event-system.spec.js.map +1 -0
  118. package/dist/lib/events/cli-adapter.d.ts +13 -0
  119. package/dist/lib/events/cli-adapter.d.ts.map +1 -0
  120. package/dist/lib/events/cli-adapter.js +244 -0
  121. package/dist/lib/events/cli-adapter.js.map +1 -0
  122. package/dist/lib/events/emitter.d.ts +11 -0
  123. package/dist/lib/events/emitter.d.ts.map +1 -0
  124. package/dist/lib/events/emitter.js +29 -0
  125. package/dist/lib/events/emitter.js.map +1 -0
  126. package/dist/lib/events/index.d.ts +4 -0
  127. package/dist/lib/events/index.d.ts.map +1 -0
  128. package/dist/lib/events/index.js +20 -0
  129. package/dist/lib/events/index.js.map +1 -0
  130. package/dist/lib/events/types.d.ts +368 -0
  131. package/dist/lib/events/types.d.ts.map +1 -0
  132. package/dist/lib/events/types.js +3 -0
  133. package/dist/lib/events/types.js.map +1 -0
  134. package/dist/lib/index.d.ts +5 -0
  135. package/dist/lib/index.d.ts.map +1 -0
  136. package/dist/lib/index.js +44 -0
  137. package/dist/lib/index.js.map +1 -0
  138. package/dist/lib/network-loader.d.ts +3 -0
  139. package/dist/lib/network-loader.d.ts.map +1 -0
  140. package/dist/lib/network-loader.js +80 -0
  141. package/dist/lib/network-loader.js.map +1 -0
  142. package/dist/lib/network-match.d.ts +3 -0
  143. package/dist/lib/network-match.d.ts.map +1 -0
  144. package/dist/lib/network-match.js +62 -0
  145. package/dist/lib/network-match.js.map +1 -0
  146. package/dist/lib/network-utils.d.ts +4 -0
  147. package/dist/lib/network-utils.d.ts.map +1 -0
  148. package/dist/lib/network-utils.js +39 -0
  149. package/dist/lib/network-utils.js.map +1 -0
  150. package/dist/lib/parsers/__tests__/buildinfo.spec.d.ts +2 -0
  151. package/dist/lib/parsers/__tests__/buildinfo.spec.d.ts.map +1 -0
  152. package/dist/lib/parsers/__tests__/buildinfo.spec.js +132 -0
  153. package/dist/lib/parsers/__tests__/buildinfo.spec.js.map +1 -0
  154. package/dist/lib/parsers/__tests__/job.spec.d.ts +2 -0
  155. package/dist/lib/parsers/__tests__/job.spec.d.ts.map +1 -0
  156. package/dist/lib/parsers/__tests__/job.spec.js +318 -0
  157. package/dist/lib/parsers/__tests__/job.spec.js.map +1 -0
  158. package/dist/lib/parsers/__tests__/template.spec.d.ts +2 -0
  159. package/dist/lib/parsers/__tests__/template.spec.d.ts.map +1 -0
  160. package/dist/lib/parsers/__tests__/template.spec.js +126 -0
  161. package/dist/lib/parsers/__tests__/template.spec.js.map +1 -0
  162. package/dist/lib/parsers/artifact/__tests__/artifact.spec.d.ts +2 -0
  163. package/dist/lib/parsers/artifact/__tests__/artifact.spec.d.ts.map +1 -0
  164. package/dist/lib/parsers/artifact/__tests__/artifact.spec.js +128 -0
  165. package/dist/lib/parsers/artifact/__tests__/artifact.spec.js.map +1 -0
  166. package/dist/lib/parsers/artifact/foundry-1.2.d.ts +3 -0
  167. package/dist/lib/parsers/artifact/foundry-1.2.d.ts.map +1 -0
  168. package/dist/lib/parsers/artifact/foundry-1.2.js +82 -0
  169. package/dist/lib/parsers/artifact/foundry-1.2.js.map +1 -0
  170. package/dist/lib/parsers/artifact/index.d.ts +3 -0
  171. package/dist/lib/parsers/artifact/index.d.ts.map +1 -0
  172. package/dist/lib/parsers/artifact/index.js +17 -0
  173. package/dist/lib/parsers/artifact/index.js.map +1 -0
  174. package/dist/lib/parsers/artifact/types.d.ts +3 -0
  175. package/dist/lib/parsers/artifact/types.d.ts.map +1 -0
  176. package/dist/lib/parsers/artifact/types.js +3 -0
  177. package/dist/lib/parsers/artifact/types.js.map +1 -0
  178. package/dist/lib/parsers/buildinfo.d.ts +5 -0
  179. package/dist/lib/parsers/buildinfo.d.ts.map +1 -0
  180. package/dist/lib/parsers/buildinfo.js +85 -0
  181. package/dist/lib/parsers/buildinfo.js.map +1 -0
  182. package/dist/lib/parsers/constants.d.ts +4 -0
  183. package/dist/lib/parsers/constants.d.ts.map +1 -0
  184. package/dist/lib/parsers/constants.js +45 -0
  185. package/dist/lib/parsers/constants.js.map +1 -0
  186. package/dist/lib/parsers/index.d.ts +5 -0
  187. package/dist/lib/parsers/index.d.ts.map +1 -0
  188. package/dist/lib/parsers/index.js +21 -0
  189. package/dist/lib/parsers/index.js.map +1 -0
  190. package/dist/lib/parsers/job.d.ts +3 -0
  191. package/dist/lib/parsers/job.d.ts.map +1 -0
  192. package/dist/lib/parsers/job.js +74 -0
  193. package/dist/lib/parsers/job.js.map +1 -0
  194. package/dist/lib/parsers/template.d.ts +3 -0
  195. package/dist/lib/parsers/template.d.ts.map +1 -0
  196. package/dist/lib/parsers/template.js +91 -0
  197. package/dist/lib/parsers/template.js.map +1 -0
  198. package/dist/lib/std/templates/assured-deployment.yaml +45 -0
  199. package/dist/lib/std/templates/erc-2470.yaml +67 -0
  200. package/dist/lib/std/templates/min-balance.yaml +32 -0
  201. package/dist/lib/std/templates/nano-universal-deployer.yaml +59 -0
  202. package/dist/lib/std/templates/raw-erc-2470.yaml +59 -0
  203. package/dist/lib/std/templates/raw-nano-universal-deployer.yaml +51 -0
  204. package/dist/lib/std/templates/raw-sequence-universal-deployer-2.yaml +48 -0
  205. package/dist/lib/std/templates/sequence-universal-deployer-2.yaml +57 -0
  206. package/dist/lib/types/__tests__/json-request-action.spec.d.ts +2 -0
  207. package/dist/lib/types/__tests__/json-request-action.spec.d.ts.map +1 -0
  208. package/dist/lib/types/__tests__/json-request-action.spec.js +219 -0
  209. package/dist/lib/types/__tests__/json-request-action.spec.js.map +1 -0
  210. package/dist/lib/types/__tests__/read-json-value.spec.d.ts +2 -0
  211. package/dist/lib/types/__tests__/read-json-value.spec.d.ts.map +1 -0
  212. package/dist/lib/types/__tests__/read-json-value.spec.js +233 -0
  213. package/dist/lib/types/__tests__/read-json-value.spec.js.map +1 -0
  214. package/dist/lib/types/actions.d.ts +74 -0
  215. package/dist/lib/types/actions.d.ts.map +1 -0
  216. package/dist/lib/types/actions.js +18 -0
  217. package/dist/lib/types/actions.js.map +1 -0
  218. package/dist/lib/types/artifacts.d.ts +15 -0
  219. package/dist/lib/types/artifacts.d.ts.map +1 -0
  220. package/dist/lib/types/artifacts.js +3 -0
  221. package/dist/lib/types/artifacts.js.map +1 -0
  222. package/dist/lib/types/buildinfo.d.ts +112 -0
  223. package/dist/lib/types/buildinfo.d.ts.map +1 -0
  224. package/dist/lib/types/buildinfo.js +3 -0
  225. package/dist/lib/types/buildinfo.js.map +1 -0
  226. package/dist/lib/types/conditions.d.ts +17 -0
  227. package/dist/lib/types/conditions.d.ts.map +1 -0
  228. package/dist/lib/types/conditions.js +21 -0
  229. package/dist/lib/types/conditions.js.map +1 -0
  230. package/dist/lib/types/contracts.d.ts +14 -0
  231. package/dist/lib/types/contracts.d.ts.map +1 -0
  232. package/dist/lib/types/contracts.js +3 -0
  233. package/dist/lib/types/contracts.js.map +1 -0
  234. package/dist/lib/types/definitions.d.ts +51 -0
  235. package/dist/lib/types/definitions.d.ts.map +1 -0
  236. package/dist/lib/types/definitions.js +3 -0
  237. package/dist/lib/types/definitions.js.map +1 -0
  238. package/dist/lib/types/index.d.ts +9 -0
  239. package/dist/lib/types/index.d.ts.map +1 -0
  240. package/dist/lib/types/index.js +25 -0
  241. package/dist/lib/types/index.js.map +1 -0
  242. package/dist/lib/types/network.d.ts +9 -0
  243. package/dist/lib/types/network.d.ts.map +1 -0
  244. package/dist/lib/types/network.js +3 -0
  245. package/dist/lib/types/network.js.map +1 -0
  246. package/dist/lib/types/project.d.ts +5 -0
  247. package/dist/lib/types/project.d.ts.map +1 -0
  248. package/dist/lib/types/project.js +3 -0
  249. package/dist/lib/types/project.js.map +1 -0
  250. package/dist/lib/types/task.d.ts +9 -0
  251. package/dist/lib/types/task.d.ts.map +1 -0
  252. package/dist/lib/types/task.js +3 -0
  253. package/dist/lib/types/task.js.map +1 -0
  254. package/dist/lib/types/values.d.ts +78 -0
  255. package/dist/lib/types/values.d.ts.map +1 -0
  256. package/dist/lib/types/values.js +3 -0
  257. package/dist/lib/types/values.js.map +1 -0
  258. package/dist/lib/utils/validation.d.ts +5 -0
  259. package/dist/lib/utils/validation.d.ts.map +1 -0
  260. package/dist/lib/utils/validation.js +77 -0
  261. package/dist/lib/utils/validation.js.map +1 -0
  262. package/dist/lib/validation/contract-references.d.ts +12 -0
  263. package/dist/lib/validation/contract-references.d.ts.map +1 -0
  264. package/dist/lib/validation/contract-references.js +112 -0
  265. package/dist/lib/validation/contract-references.js.map +1 -0
  266. package/dist/lib/validation/index.d.ts +1 -0
  267. package/dist/lib/validation/index.d.ts.map +1 -0
  268. package/dist/lib/validation/index.js +2 -0
  269. package/dist/lib/validation/index.js.map +1 -0
  270. package/dist/lib/verification/__tests__/etherscan.spec.d.ts +2 -0
  271. package/dist/lib/verification/__tests__/etherscan.spec.d.ts.map +1 -0
  272. package/dist/lib/verification/__tests__/etherscan.spec.js +565 -0
  273. package/dist/lib/verification/__tests__/etherscan.spec.js.map +1 -0
  274. package/dist/lib/verification/__tests__/sourcify.spec.d.ts +2 -0
  275. package/dist/lib/verification/__tests__/sourcify.spec.d.ts.map +1 -0
  276. package/dist/lib/verification/__tests__/sourcify.spec.js +212 -0
  277. package/dist/lib/verification/__tests__/sourcify.spec.js.map +1 -0
  278. package/dist/lib/verification/etherscan.d.ts +56 -0
  279. package/dist/lib/verification/etherscan.d.ts.map +1 -0
  280. package/dist/lib/verification/etherscan.js +340 -0
  281. package/dist/lib/verification/etherscan.js.map +1 -0
  282. package/dist/lib/verification/sourcify.d.ts +12 -0
  283. package/dist/lib/verification/sourcify.d.ts.map +1 -0
  284. package/dist/lib/verification/sourcify.js +227 -0
  285. package/dist/lib/verification/sourcify.js.map +1 -0
  286. package/eslint.config.js +48 -0
  287. package/examples/jobs/guards-v1.yaml +17 -0
  288. package/examples/jobs/sequence-seq-0001-patch.yaml +59 -0
  289. package/examples/jobs/sequence-v1.yaml +59 -0
  290. package/examples/templates/sequence-factory-v1.yaml +56 -0
  291. package/jest.config.js +25 -0
  292. package/package.json +68 -0
  293. package/src/cli.ts +17 -0
  294. package/src/commands/common.ts +61 -0
  295. package/src/commands/dry.ts +208 -0
  296. package/src/commands/etherscan.ts +360 -0
  297. package/src/commands/index.ts +5 -0
  298. package/src/commands/list.ts +249 -0
  299. package/src/commands/run.ts +136 -0
  300. package/src/commands/utils.ts +52 -0
  301. package/src/index.ts +67 -0
  302. package/src/lib/__tests__/deployer-events.spec.ts +338 -0
  303. package/src/lib/__tests__/deployer.spec.ts +1204 -0
  304. package/src/lib/__tests__/network-utils.spec.ts +181 -0
  305. package/src/lib/artifacts/__tests__/fixtures/contract1.json +19 -0
  306. package/src/lib/artifacts/__tests__/fixtures/contract2.json +19 -0
  307. package/src/lib/artifacts/__tests__/fixtures/duplicate-name.json +19 -0
  308. package/src/lib/artifacts/__tests__/fixtures/nested/nested-contract.json +18 -0
  309. package/src/lib/artifacts/__tests__/fixtures/not-an-artifact.json +8 -0
  310. package/src/lib/artifacts/__tests__/fixtures/readme.txt +2 -0
  311. package/src/lib/contracts/__tests__/repository.spec.ts +344 -0
  312. package/src/lib/contracts/repository.ts +313 -0
  313. package/src/lib/core/__tests__/engine.spec.ts +1514 -0
  314. package/src/lib/core/__tests__/graph.spec.ts +125 -0
  315. package/src/lib/core/__tests__/json-integration.spec.ts +360 -0
  316. package/src/lib/core/__tests__/loader.spec.ts +334 -0
  317. package/src/lib/core/__tests__/multi-platform-verification.spec.ts +406 -0
  318. package/src/lib/core/__tests__/resolver.spec.ts +1693 -0
  319. package/src/lib/core/__tests__/static-action.spec.ts +172 -0
  320. package/src/lib/core/context.ts +127 -0
  321. package/src/lib/core/engine.ts +1531 -0
  322. package/src/lib/core/graph.ts +252 -0
  323. package/src/lib/core/loader.ts +263 -0
  324. package/src/lib/core/resolver.ts +498 -0
  325. package/src/lib/deployer.ts +768 -0
  326. package/src/lib/events/__tests__/event-system.spec.ts +343 -0
  327. package/src/lib/events/cli-adapter.ts +325 -0
  328. package/src/lib/events/emitter.ts +62 -0
  329. package/src/lib/events/index.ts +3 -0
  330. package/src/lib/events/types.ts +469 -0
  331. package/src/lib/index.ts +14 -0
  332. package/src/lib/network-loader.ts +59 -0
  333. package/src/lib/network-utils.ts +64 -0
  334. package/src/lib/parsers/__tests__/buildinfo.spec.ts +122 -0
  335. package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-bytecode-buildinfo.json +62 -0
  336. package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-json.txt +2 -0
  337. package/src/lib/parsers/__tests__/fixtures/buildinfo/multi-contract-buildinfo.json +89 -0
  338. package/src/lib/parsers/__tests__/fixtures/buildinfo/no-contracts-buildinfo.json +17 -0
  339. package/src/lib/parsers/__tests__/fixtures/buildinfo/simple-buildinfo.json +63 -0
  340. package/src/lib/parsers/__tests__/fixtures/buildinfo/wrong-format.json +4 -0
  341. package/src/lib/parsers/__tests__/job.spec.ts +335 -0
  342. package/src/lib/parsers/__tests__/template.spec.ts +111 -0
  343. package/src/lib/parsers/artifact/__tests__/artifact.spec.ts +117 -0
  344. package/src/lib/parsers/artifact/__tests__/fixtures/empty-bytecode.json +5 -0
  345. package/src/lib/parsers/artifact/__tests__/fixtures/hardhat-artifact.json +67 -0
  346. package/src/lib/parsers/artifact/__tests__/fixtures/invalid-bytecode.json +5 -0
  347. package/src/lib/parsers/artifact/__tests__/fixtures/invalid-json.txt +11 -0
  348. package/src/lib/parsers/artifact/__tests__/fixtures/minimal-artifact.json +5 -0
  349. package/src/lib/parsers/artifact/__tests__/fixtures/missing-abi.json +4 -0
  350. package/src/lib/parsers/artifact/__tests__/fixtures/missing-bytecode.json +11 -0
  351. package/src/lib/parsers/artifact/__tests__/fixtures/missing-contract-name.json +11 -0
  352. package/src/lib/parsers/artifact/__tests__/fixtures/simple-artifact.json +40 -0
  353. package/src/lib/parsers/artifact/__tests__/fixtures/wrong-types.json +7 -0
  354. package/src/lib/parsers/artifact/foundry-1.2.ts +72 -0
  355. package/src/lib/parsers/artifact/index.ts +27 -0
  356. package/src/lib/parsers/artifact/types.ts +9 -0
  357. package/src/lib/parsers/buildinfo.ts +127 -0
  358. package/src/lib/parsers/constants.ts +56 -0
  359. package/src/lib/parsers/index.ts +5 -0
  360. package/src/lib/parsers/job.ts +101 -0
  361. package/src/lib/parsers/template.ts +131 -0
  362. package/src/lib/std/templates/assured-deployment.yaml +45 -0
  363. package/src/lib/std/templates/erc-2470.yaml +67 -0
  364. package/src/lib/std/templates/min-balance.yaml +32 -0
  365. package/src/lib/std/templates/nano-universal-deployer.yaml +59 -0
  366. package/src/lib/std/templates/raw-erc-2470.yaml +59 -0
  367. package/src/lib/std/templates/raw-nano-universal-deployer.yaml +51 -0
  368. package/src/lib/std/templates/raw-sequence-universal-deployer-2.yaml +48 -0
  369. package/src/lib/std/templates/sequence-universal-deployer-2.yaml +57 -0
  370. package/src/lib/types/__tests__/json-request-action.spec.ts +243 -0
  371. package/src/lib/types/__tests__/read-json-value.spec.ts +264 -0
  372. package/src/lib/types/actions.ts +127 -0
  373. package/src/lib/types/artifacts.ts +21 -0
  374. package/src/lib/types/buildinfo.ts +116 -0
  375. package/src/lib/types/conditions.ts +50 -0
  376. package/src/lib/types/contracts.ts +23 -0
  377. package/src/lib/types/definitions.ts +68 -0
  378. package/src/lib/types/index.ts +8 -0
  379. package/src/lib/types/network.ts +22 -0
  380. package/src/lib/types/project.ts +9 -0
  381. package/src/lib/types/task.ts +9 -0
  382. package/src/lib/types/values.ts +116 -0
  383. package/src/lib/utils/validation.ts +116 -0
  384. package/src/lib/validation/contract-references.ts +210 -0
  385. package/src/lib/validation/index.ts +1 -0
  386. package/src/lib/verification/__tests__/etherscan.spec.ts +710 -0
  387. package/src/lib/verification/__tests__/sourcify.spec.ts +288 -0
  388. package/src/lib/verification/etherscan.ts +546 -0
  389. package/src/lib/verification/sourcify.ts +248 -0
  390. package/test_validation/artifacts/TestContract.json +9 -0
  391. package/test_validation/jobs/test-missing.yaml +16 -0
  392. package/test_validation/networks.yaml +3 -0
  393. package/tsconfig.json +36 -0
@@ -0,0 +1,335 @@
1
+ import * as fs from 'fs'
2
+ import * as path from 'path'
3
+ import { parseJob } from '../job'
4
+ import { Job } from '../../types'
5
+
6
+ describe('parseJob', () => {
7
+ // --- Happy Path Tests ---
8
+
9
+ it('should correctly parse a valid, complex job with multiple actions and dependencies (sequence-v1)', () => {
10
+ const yamlPath = path.resolve(__dirname, '../../../../examples/jobs/sequence-v1.yaml')
11
+ const yamlContent = fs.readFileSync(yamlPath, 'utf-8')
12
+
13
+ const job: Job = parseJob(yamlContent)
14
+
15
+ expect(job.name).toBe('sequence-v1')
16
+ expect(job.version).toBe('1.0.0')
17
+ expect(job.description).toBe('The Sequence v1 contracts')
18
+ expect(job.depends_on).toBeUndefined()
19
+ expect(job.actions).toHaveLength(6)
20
+
21
+ // Spot-check a simple action
22
+ const factoryAction = job.actions.find((a) => a.name === 'factory')
23
+ expect(factoryAction).toBeDefined()
24
+ expect(factoryAction?.template).toBe('sequence-universal-deployer-2')
25
+ expect(factoryAction?.arguments).toEqual({
26
+ creationCode: '{{Contract(sequence/v1/factory).creationCode}}',
27
+ salt: '0',
28
+ })
29
+ expect(factoryAction?.depends_on).toBeUndefined()
30
+
31
+ // Spot-check an action with dependencies and complex arguments
32
+ const mainModuleAction = job.actions.find((a) => a.name === 'main-module')
33
+ expect(mainModuleAction).toBeDefined()
34
+ expect(mainModuleAction?.template).toBe('sequence-universal-deployer-2')
35
+ expect(mainModuleAction?.depends_on).toEqual(['factory'])
36
+ expect(mainModuleAction?.arguments).toEqual({
37
+ salt: '0',
38
+ creationCode: {
39
+ type: 'constructor-encode',
40
+ arguments: {
41
+ creationCode: '{{Contract(sequence/v1/main-module).creationCode}}',
42
+ types: ['address'],
43
+ values: ['{{factory.address}}'],
44
+ },
45
+ },
46
+ })
47
+ })
48
+
49
+ it('should correctly parse a job with job-level depends_on (guards-v1)', () => {
50
+ const yamlPath = path.resolve(__dirname, '../../../../examples/jobs/guards-v1.yaml')
51
+ const yamlContent = fs.readFileSync(yamlPath, 'utf-8')
52
+
53
+ const job: Job = parseJob(yamlContent)
54
+
55
+ expect(job.name).toBe('guards-v1')
56
+ expect(job.version).toBe('1')
57
+ expect(job.description).toBe('Deploy both prod and dev guards for Sequence v1')
58
+ expect(job.depends_on).toEqual(['sequence-v1'])
59
+ expect(job.actions).toHaveLength(2)
60
+ })
61
+
62
+ it('should handle numeric versions and convert them to strings', () => {
63
+ const yamlContent = `
64
+ name: test-job
65
+ version: 1
66
+ description: A test job
67
+ actions:
68
+ - name: action1
69
+ template: tpl1
70
+ arguments: {}
71
+ `
72
+ const job = parseJob(yamlContent)
73
+ expect(job.version).toBe('1')
74
+ expect(typeof job.version).toBe('string')
75
+ })
76
+
77
+ // --- Error Handling and Validation Tests ---
78
+
79
+ it('should throw an error for malformed YAML', () => {
80
+ const invalidYaml = 'name: bad-yaml\n actions: - item1'
81
+ expect(() => parseJob(invalidYaml)).toThrow(/Failed to parse job YAML:.*at line 1/)
82
+ })
83
+
84
+ it('should throw an error if YAML content does not resolve to an object', () => {
85
+ const invalidYaml = 'just-a-string'
86
+ expect(() => parseJob(invalidYaml)).toThrow('Invalid job: YAML content must resolve to an object.')
87
+ })
88
+
89
+ it('should throw an error if the "name" field is missing', () => {
90
+ const yamlContent = `
91
+ version: "1.0"
92
+ actions: []
93
+ `
94
+ expect(() => parseJob(yamlContent)).toThrow('Invalid job: "name" field is required and must be a string.')
95
+ })
96
+
97
+ it('should throw an error if the "name" field is not a string', () => {
98
+ const yamlContent = `
99
+ name: 12345
100
+ version: "1.0"
101
+ actions: []
102
+ `
103
+ expect(() => parseJob(yamlContent)).toThrow('Invalid job: "name" field is required and must be a string.')
104
+ })
105
+
106
+ it('should throw an error if the "version" field is missing', () => {
107
+ const yamlContent = `
108
+ name: "my-job"
109
+ actions: []
110
+ `
111
+ expect(() => parseJob(yamlContent)).toThrow('Invalid job "my-job": "version" field is required.')
112
+ })
113
+
114
+ it('should throw an error if the "actions" field is missing', () => {
115
+ const yamlContent = `
116
+ name: "my-job"
117
+ version: "1"
118
+ `
119
+ expect(() => parseJob(yamlContent)).toThrow('Invalid job "my-job": "actions" field is required and must be an array.')
120
+ })
121
+
122
+ it('should throw an error if the "actions" field is not an array', () => {
123
+ const yamlContent = `
124
+ name: "my-job"
125
+ version: "1"
126
+ actions: "not-an-array"
127
+ `
128
+ expect(() => parseJob(yamlContent)).toThrow('Invalid job "my-job": "actions" field is required and must be an array.')
129
+ })
130
+
131
+ it('should throw an error if an item in the "actions" array is not an object', () => {
132
+ const yamlContent = `
133
+ name: "my-job"
134
+ version: "1"
135
+ actions:
136
+ - "i-am-a-string-not-an-object"
137
+ `
138
+ expect(() => parseJob(yamlContent)).toThrow(
139
+ 'Invalid job "my-job": contains a non-object item in "actions" array.',
140
+ )
141
+ })
142
+
143
+ it('should throw an error if an action is missing its "name" field', () => {
144
+ const yamlContent = `
145
+ name: "my-job"
146
+ version: "1"
147
+ actions:
148
+ - template: "my-template"
149
+ arguments: {}
150
+ `
151
+ expect(() => parseJob(yamlContent)).toThrow('Invalid job "my-job": an action is missing the required "name" field.')
152
+ })
153
+
154
+ it('should throw an error if an action is missing its "template" field', () => {
155
+ const yamlContent = `
156
+ name: "my-job"
157
+ version: "1"
158
+ actions:
159
+ - name: "my-action"
160
+ arguments: {}
161
+ `
162
+ expect(() => parseJob(yamlContent)).toThrow(
163
+ 'Invalid job "my-job": action "my-action" must have either a "template" field (for template actions) or a "type" field (for primitive actions).',
164
+ )
165
+ })
166
+
167
+ it('should throw an error if an action is missing its "arguments" field', () => {
168
+ const yamlContent = `
169
+ name: "my-job"
170
+ version: "1"
171
+ actions:
172
+ - name: "my-action"
173
+ template: "my-template"
174
+ `
175
+ expect(() => parseJob(yamlContent)).toThrow(
176
+ 'Invalid job "my-job": action "my-action" is missing the required "arguments" field or it is not an object.',
177
+ )
178
+ })
179
+
180
+ it('should throw an error if an action has "arguments" that are not an object', () => {
181
+ const yamlContent = `
182
+ name: "my-job"
183
+ version: "1"
184
+ actions:
185
+ - name: "my-action"
186
+ template: "my-template"
187
+ arguments: ["not", "an", "object"]
188
+ `
189
+ expect(() => parseJob(yamlContent)).toThrow(
190
+ 'Invalid job "my-job": action "my-action" is missing the required "arguments" field or it is not an object.',
191
+ )
192
+ })
193
+
194
+ // --- Output Field Tests ---
195
+
196
+ it('should correctly parse actions with output: true', () => {
197
+ const yamlContent = `
198
+ name: "my-job"
199
+ version: "1"
200
+ actions:
201
+ - name: "action-with-output"
202
+ template: "my-template"
203
+ arguments: {}
204
+ output: true
205
+ `
206
+ const job = parseJob(yamlContent)
207
+ expect(job.actions[0].output).toBe(true)
208
+ })
209
+
210
+ it('should correctly parse actions with output: false', () => {
211
+ const yamlContent = `
212
+ name: "my-job"
213
+ version: "1"
214
+ actions:
215
+ - name: "action-without-output"
216
+ template: "my-template"
217
+ arguments: {}
218
+ output: false
219
+ `
220
+ const job = parseJob(yamlContent)
221
+ expect(job.actions[0].output).toBe(false)
222
+ })
223
+
224
+ it('should correctly parse actions with no output field (undefined)', () => {
225
+ const yamlContent = `
226
+ name: "my-job"
227
+ version: "1"
228
+ actions:
229
+ - name: "action-no-output"
230
+ template: "my-template"
231
+ arguments: {}
232
+ `
233
+ const job = parseJob(yamlContent)
234
+ expect(job.actions[0].output).toBeUndefined()
235
+ })
236
+
237
+ it('should correctly parse actions with output: object (custom map)', () => {
238
+ const yamlContent = `
239
+ name: "my-job"
240
+ version: "1"
241
+ actions:
242
+ - name: "action-custom"
243
+ template: "my-template"
244
+ arguments: {}
245
+ output:
246
+ address: "{{someAddress}}"
247
+ txHash: "{{action-custom.hash}}"
248
+ `
249
+ const job = parseJob(yamlContent)
250
+ expect(typeof job.actions[0].output).toBe('object')
251
+ expect(job.actions[0].output).toEqual({
252
+ address: '{{someAddress}}',
253
+ txHash: '{{action-custom.hash}}'
254
+ } as any)
255
+ })
256
+
257
+ it('should throw an error if output field is not a boolean or object', () => {
258
+ const yamlContent = `
259
+ name: "my-job"
260
+ version: "1"
261
+ actions:
262
+ - name: "my-action"
263
+ template: "my-template"
264
+ arguments: {}
265
+ output: "not-a-boolean"
266
+ `
267
+ expect(() => parseJob(yamlContent)).toThrow(
268
+ 'Invalid job "my-job": action "my-action" has an invalid "output" field. It must be either a boolean (true/false) or an object mapping custom outputs.',
269
+ )
270
+ })
271
+
272
+ it('should throw an error if output field is a number', () => {
273
+ const yamlContent = `
274
+ name: "my-job"
275
+ version: "1"
276
+ actions:
277
+ - name: "my-action"
278
+ template: "my-template"
279
+ arguments: {}
280
+ output: 1
281
+ `
282
+ expect(() => parseJob(yamlContent)).toThrow(
283
+ 'Invalid job "my-job": action "my-action" has an invalid "output" field. It must be either a boolean (true/false) or an object mapping custom outputs.',
284
+ )
285
+ })
286
+
287
+ it('should correctly parse mixed actions with and without output fields', () => {
288
+ const yamlContent = `
289
+ name: "my-job"
290
+ version: "1"
291
+ actions:
292
+ - name: "action1"
293
+ template: "template1"
294
+ arguments: {}
295
+ output: true
296
+ - name: "action2"
297
+ template: "template2"
298
+ arguments: {}
299
+ - name: "action3"
300
+ template: "template3"
301
+ arguments: {}
302
+ output: false
303
+ - name: "action4"
304
+ template: "template4"
305
+ arguments: {}
306
+ output:
307
+ important: "{{action4.hash}}"
308
+ `
309
+ const job = parseJob(yamlContent)
310
+ expect(job.actions[0].output).toBe(true)
311
+ expect(job.actions[1].output).toBeUndefined()
312
+ expect(job.actions[2].output).toBe(false)
313
+ expect(job.actions[3].output).toEqual({ important: '{{action4.hash}}' } as any)
314
+ })
315
+
316
+ // --- New: Job-level constants field parsing ---
317
+
318
+ it('should allow an optional job-level constants block as an object', () => {
319
+ const yamlContent = `
320
+ name: "job-with-constants"
321
+ version: "1"
322
+ constants:
323
+ FEE: "1000"
324
+ ADMIN: "0x0000000000000000000000000000000000000001"
325
+ actions:
326
+ - name: "a1"
327
+ template: "t1"
328
+ arguments:
329
+ x: "{{FEE}}"
330
+ `
331
+ const job = parseJob(yamlContent) as any
332
+ // parseJob doesn't attach constants; loader attaches it. This test ensures YAML is acceptable and does not throw.
333
+ expect(job.name).toBe('job-with-constants')
334
+ })
335
+ })
@@ -0,0 +1,111 @@
1
+ import * as fs from 'fs'
2
+ import * as path from 'path'
3
+ import { parseTemplate } from '../template'
4
+ import { isContractExistsCondition, isJobCompletedCondition, Template } from '../../types'
5
+
6
+ describe('parseTemplate', () => {
7
+ // --- Happy Path Tests ---
8
+
9
+ it('should correctly parse a valid template with a complex structure (sequence-factory-v1)', () => {
10
+ const yamlPath = path.resolve(__dirname, '../../../../examples/templates/sequence-factory-v1.yaml')
11
+ const yamlContent = fs.readFileSync(yamlPath, 'utf-8')
12
+
13
+ const template = parseTemplate(yamlContent)
14
+
15
+ expect(template.name).toBe('sequence-factory-v1')
16
+ expect(template.arguments).toBeDefined()
17
+ expect(template.returns).toBeDefined()
18
+ expect(template.actions).toHaveLength(1)
19
+ expect(template.outputs).toBeDefined()
20
+ expect(template.outputs?.address).toBeDefined()
21
+
22
+ // Test the specific 'setup' block parsing where it's an array of conditions
23
+ expect(template.setup).toBeDefined()
24
+ expect(template.setup?.actions).toBeUndefined() // No actions in this setup
25
+ expect(template.setup?.skip_condition).toHaveLength(1)
26
+ expect(isJobCompletedCondition(template.setup?.skip_condition?.[0])).toBe(true)
27
+ })
28
+
29
+ it('should correctly parse a template with an object-based setup block (nano-universal-deployer)', () => {
30
+ const yamlPath = path.resolve(__dirname, '../../std/templates/nano-universal-deployer.yaml')
31
+ const yamlContent = fs.readFileSync(yamlPath, 'utf-8')
32
+
33
+ const template = parseTemplate(yamlContent)
34
+
35
+ expect(template.name).toBe('nano-universal-deployer')
36
+
37
+ // Test the specific 'setup' block parsing where it's a structured object
38
+ expect(template.setup).toBeDefined()
39
+ expect(template.setup?.actions).toHaveLength(3)
40
+ expect(template.setup?.skip_condition).toHaveLength(1)
41
+ expect(template.setup?.actions?.[0].type).toBe('test-nicks-method')
42
+ expect(isContractExistsCondition(template.setup?.skip_condition?.[0])).toBe(true)
43
+ })
44
+
45
+ it('should parse a template with no optional fields like setup, description, arguments, or outputs', () => {
46
+ const minimalYaml = `
47
+ name: minimal-template
48
+ actions:
49
+ - type: send-transaction
50
+ arguments:
51
+ to: '0x123'
52
+ data: '0xabc'
53
+ `
54
+ const template = parseTemplate(minimalYaml)
55
+ expect(template.name).toBe('minimal-template')
56
+ expect(template.description).toBeUndefined()
57
+ expect(template.arguments).toBeUndefined()
58
+ expect(template.setup).toBeUndefined()
59
+ expect(template.actions).toHaveLength(1)
60
+ expect(template.outputs).toBeUndefined()
61
+ })
62
+
63
+ // --- Error Handling and Validation Tests ---
64
+
65
+ it('should throw an error for malformed YAML', () => {
66
+ const invalidYaml = `
67
+ name: bad-yaml
68
+ actions: - item1
69
+ `
70
+ expect(() => parseTemplate(invalidYaml)).toThrow(/Failed to parse template YAML:.* at line 2/)
71
+ })
72
+
73
+ it('should throw an error if the "name" field is missing', () => {
74
+ const yamlContent = `
75
+ version: "1.0"
76
+ actions: []
77
+ `
78
+ expect(() => parseTemplate(yamlContent)).toThrow('Invalid template: "name" field is required and must be a string.')
79
+ })
80
+
81
+ it('should throw an error if the "actions" field is missing or not an array', () => {
82
+ const missingActions = `
83
+ name: "my-template"
84
+ `
85
+ expect(() => parseTemplate(missingActions)).toThrow('Invalid template "my-template": "actions" field is required and must be an array.')
86
+
87
+ const wrongTypeActions = `
88
+ name: "my-template"
89
+ actions: "not-an-array"
90
+ `
91
+ expect(() => parseTemplate(wrongTypeActions)).toThrow('Invalid template "my-template": "actions" field is required and must be an array.')
92
+ })
93
+
94
+ it('should throw an error if the "outputs" field is not an object when provided', () => {
95
+ const wrongTypeOutputs = `
96
+ name: "my-template"
97
+ actions: []
98
+ outputs: ["not-an-object"]
99
+ `
100
+ expect(() => parseTemplate(wrongTypeOutputs)).toThrow('Invalid template "my-template": "outputs" field must be an object if provided.')
101
+ })
102
+
103
+ it('should throw an error if the "setup" field is not an array or object', () => {
104
+ const invalidSetup = `
105
+ name: "my-template"
106
+ actions: []
107
+ setup: "i-am-a-string"
108
+ `
109
+ expect(() => parseTemplate(invalidSetup)).toThrow('Invalid template "my-template": "setup" field must be an array or an object if provided.')
110
+ })
111
+ })
@@ -0,0 +1,117 @@
1
+ import * as fs from 'fs'
2
+ import * as path from 'path'
3
+ import { parseArtifact } from '../index'
4
+
5
+ describe('Artifact Parsing', () => {
6
+ const fixturesDir = path.join(__dirname, 'fixtures')
7
+
8
+ // Helper function to read fixture files
9
+ const readFixture = (filename: string): string => {
10
+ return fs.readFileSync(path.join(fixturesDir, filename), 'utf-8')
11
+ }
12
+
13
+ describe('parseArtifact function', () => {
14
+ it('should parse a simple artifact with string bytecode', () => {
15
+ const content = readFixture('simple-artifact.json')
16
+ const result = parseArtifact(content, '/test/simple-artifact.json')
17
+
18
+ expect(result).not.toBeNull()
19
+ expect(result!.contractName).toBe('SimpleToken')
20
+ expect(result!.abi).toBeInstanceOf(Array)
21
+ expect(result!.abi.length).toBe(2)
22
+ expect(result!.bytecode).toMatch(/^0x[0-9a-fA-F]+$/)
23
+ expect(result!.deployedBytecode).toMatch(/^0x[0-9a-fA-F]+$/)
24
+ })
25
+
26
+ it('should parse a Hardhat-style artifact with bytecode object', () => {
27
+ const content = readFixture('hardhat-artifact.json')
28
+ const result = parseArtifact(content, '/test/hardhat-artifact.json')
29
+
30
+ expect(result).not.toBeNull()
31
+ expect(result!.contractName).toBe('ERC20Token')
32
+ expect(result!.sourceName).toBe('contracts/ERC20Token.sol')
33
+ expect(result!.abi).toBeInstanceOf(Array)
34
+ expect(result!.abi.length).toBe(3)
35
+ expect(result!.bytecode).toMatch(/^0x[0-9a-fA-F]+$/)
36
+ expect(result!.deployedBytecode).toMatch(/^0x[0-9a-fA-F]+$/)
37
+ expect(result!.compiler).toBeDefined()
38
+ expect(result!.compiler!.version).toBe('0.8.19+commit.7dd6d404')
39
+ expect(result!.source).toContain('contract ERC20Token')
40
+ })
41
+
42
+ it('should parse a minimal artifact with only required fields', () => {
43
+ const content = readFixture('minimal-artifact.json')
44
+ const result = parseArtifact(content, '/test/minimal-artifact.json')
45
+
46
+ expect(result).not.toBeNull()
47
+ expect(result!.contractName).toBe('Minimal')
48
+ expect(result!.abi).toBeInstanceOf(Array)
49
+ expect(result!.abi.length).toBe(0)
50
+ expect(result!.bytecode).toBe('0x608060405234801561001057600080fd5b50')
51
+ expect(result!.deployedBytecode).toBeUndefined()
52
+ expect(result!.sourceName).toBeUndefined()
53
+ expect(result!.source).toBeUndefined()
54
+ expect(result!.compiler).toBeUndefined()
55
+ })
56
+
57
+ it('should return null for invalid JSON', () => {
58
+ const content = readFixture('invalid-json.txt')
59
+ const result = parseArtifact(content, '/test/invalid-json.txt')
60
+
61
+ expect(result).toBeNull()
62
+ })
63
+
64
+ it('should derive contractName from filename when missing', () => {
65
+ const content = readFixture('missing-contract-name.json')
66
+ const result = parseArtifact(content, '/test/missing-contract-name.json')
67
+
68
+ expect(result).not.toBeNull()
69
+ expect(result!.contractName).toBe('missing-contract-name')
70
+ })
71
+
72
+ it('should return null when abi is missing', () => {
73
+ const content = readFixture('missing-abi.json')
74
+ const result = parseArtifact(content, '/test/missing-abi.json')
75
+
76
+ expect(result).toBeNull()
77
+ })
78
+
79
+ it('should return null when bytecode is missing', () => {
80
+ const content = readFixture('missing-bytecode.json')
81
+ const result = parseArtifact(content, '/test/missing-bytecode.json')
82
+
83
+ expect(result).toBeNull()
84
+ })
85
+
86
+ it('should return null when bytecode does not start with 0x', () => {
87
+ const content = readFixture('invalid-bytecode.json')
88
+ const result = parseArtifact(content, '/test/invalid-bytecode.json')
89
+
90
+ expect(result).toBeNull()
91
+ })
92
+
93
+ it('should return null when bytecode is empty', () => {
94
+ const content = readFixture('empty-bytecode.json')
95
+ const result = parseArtifact(content, '/test/empty-bytecode.json')
96
+
97
+ expect(result).toBeNull()
98
+ })
99
+
100
+ it('should return null when fields have wrong types', () => {
101
+ const content = readFixture('wrong-types.json')
102
+ const result = parseArtifact(content, '/test/wrong-types.json')
103
+
104
+ expect(result).toBeNull()
105
+ })
106
+
107
+ it('should handle null input gracefully', () => {
108
+ const result = parseArtifact('null', '/test/null.json')
109
+ expect(result).toBeNull()
110
+ })
111
+
112
+ it('should handle empty string input gracefully', () => {
113
+ const result = parseArtifact('', '/test/empty.json')
114
+ expect(result).toBeNull()
115
+ })
116
+ })
117
+ })
@@ -0,0 +1,5 @@
1
+ {
2
+ "contractName": "EmptyBytecode",
3
+ "abi": [],
4
+ "bytecode": ""
5
+ }
@@ -0,0 +1,67 @@
1
+ {
2
+ "contractName": "ERC20Token",
3
+ "sourceName": "contracts/ERC20Token.sol",
4
+ "abi": [
5
+ {
6
+ "type": "constructor",
7
+ "inputs": [
8
+ {
9
+ "name": "initialSupply",
10
+ "type": "uint256"
11
+ }
12
+ ]
13
+ },
14
+ {
15
+ "type": "function",
16
+ "name": "balanceOf",
17
+ "inputs": [
18
+ {
19
+ "name": "account",
20
+ "type": "address"
21
+ }
22
+ ],
23
+ "outputs": [
24
+ {
25
+ "name": "",
26
+ "type": "uint256"
27
+ }
28
+ ],
29
+ "stateMutability": "view"
30
+ },
31
+ {
32
+ "type": "event",
33
+ "name": "Transfer",
34
+ "inputs": [
35
+ {
36
+ "name": "from",
37
+ "type": "address",
38
+ "indexed": true
39
+ },
40
+ {
41
+ "name": "to",
42
+ "type": "address",
43
+ "indexed": true
44
+ },
45
+ {
46
+ "name": "value",
47
+ "type": "uint256",
48
+ "indexed": false
49
+ }
50
+ ]
51
+ }
52
+ ],
53
+ "bytecode": {
54
+ "object": "0x608060405234801561001057600080fd5b50604051610abc380380610abc8339818101604052810190610032919061007a565b806000819055505061009e565b600080fd5b6000819050919050565b61005681610043565b811461006157600080fd5b50565b6000815190506100738161004d565b92915050565b60006020828403121561008f5761008e61003e565b5b600061009d84828501610064565b91505092915050565b610a0f806100ad6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806318160ddd1461005c57806370a0823114610078578063a9059cbb146100a8578063dd62ed3e146100c4575b600080fd5b6100646100f4565b60405161006f919061018a565b60405180910390f35b610092600480360381019061008d91906101d6565b6100fa565b60405161009f919061018a565b60405180910390f35b6100c260048036038101906100bd919061024f565b610142565b005b6100de60048036038101906100d9919061028f565b61015c565b6040516100eb919061018a565b60405180910390f35b60005481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600061014f338484610181565b905092915050565b5050565b600060016000858573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a2646970667358221220",
55
+ "sourceMap": "123:456:0:-:0;;;789:100;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::o;8:123:-1;5:3;2:1;21:10;18:1;14:2;11:3;8:2;123:456:0;;;;;;;",
56
+ "linkReferences": {}
57
+ },
58
+ "deployedBytecode": {
59
+ "object": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806318160ddd1461005c57806370a0823114610078578063a9059cbb146100a8578063dd62ed3e146100c4575b600080fd5b6100646100f4565b60405161006f919061018a565b60405180910390f35b610092600480360381019061008d91906101d6565b6100fa565b60405161009f919061018a565b60405180910390f35b6100c260048036038101906100bd919061024f565b610142565b005b6100de60048036038101906100d9919061028f565b61015c565b6040516100eb919061018a565b60405180910390f35b60005481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600061014f338484610181565b905092915050565b5050565b600060016000858573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a2646970667358221220",
60
+ "sourceMap": "123:456:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::o;",
61
+ "linkReferences": {}
62
+ },
63
+ "compiler": {
64
+ "version": "0.8.19+commit.7dd6d404"
65
+ },
66
+ "source": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ncontract ERC20Token {\n mapping(address => uint256) private _balances;\n mapping(address => mapping(address => uint256)) private _allowances;\n uint256 private _totalSupply;\n \n constructor(uint256 initialSupply) {\n _totalSupply = initialSupply;\n _balances[msg.sender] = initialSupply;\n }\n \n function balanceOf(address account) public view returns (uint256) {\n return _balances[account];\n }\n}\n"
67
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "contractName": "InvalidBytecode",
3
+ "abi": [],
4
+ "bytecode": "608060405234801561001057600080fd5b50"
5
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "contractName": "InvalidJson",
3
+ "abi": [
4
+ {
5
+ "type": "function"
6
+ // Missing comma here makes it invalid JSON
7
+ "name": "test"
8
+ }
9
+ ]
10
+ "bytecode": "0x123"
11
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "contractName": "Minimal",
3
+ "abi": [],
4
+ "bytecode": "0x608060405234801561001057600080fd5b50"
5
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "contractName": "MissingAbi",
3
+ "bytecode": "0x608060405234801561001057600080fd5b50"
4
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "contractName": "MissingBytecode",
3
+ "abi": [
4
+ {
5
+ "type": "function",
6
+ "name": "test",
7
+ "inputs": [],
8
+ "outputs": []
9
+ }
10
+ ]
11
+ }