@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.
- package/.eslintrc.json +29 -0
- package/.github/workflows/ci.yml +181 -0
- package/CONCEPT.md +24 -0
- package/README.md +772 -0
- package/contracts/checked-call.huff +65 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/common.d.ts +11 -0
- package/dist/commands/common.d.ts.map +1 -0
- package/dist/commands/common.js +73 -0
- package/dist/commands/common.js.map +1 -0
- package/dist/commands/dry.d.ts +3 -0
- package/dist/commands/dry.d.ts.map +1 -0
- package/dist/commands/dry.js +171 -0
- package/dist/commands/dry.js.map +1 -0
- package/dist/commands/etherscan.d.ts +3 -0
- package/dist/commands/etherscan.d.ts.map +1 -0
- package/dist/commands/etherscan.js +323 -0
- package/dist/commands/etherscan.js.map +1 -0
- package/dist/commands/index.d.ts +6 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +22 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +259 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/run.d.ts +3 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +96 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/utils.d.ts +3 -0
- package/dist/commands/utils.d.ts.map +1 -0
- package/dist/commands/utils.js +46 -0
- package/dist/commands/utils.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/__tests__/deployer-events.spec.d.ts +2 -0
- package/dist/lib/__tests__/deployer-events.spec.d.ts.map +1 -0
- package/dist/lib/__tests__/deployer-events.spec.js +260 -0
- package/dist/lib/__tests__/deployer-events.spec.js.map +1 -0
- package/dist/lib/__tests__/deployer.spec.d.ts +2 -0
- package/dist/lib/__tests__/deployer.spec.d.ts.map +1 -0
- package/dist/lib/__tests__/deployer.spec.js +884 -0
- package/dist/lib/__tests__/deployer.spec.js.map +1 -0
- package/dist/lib/__tests__/network-utils.spec.d.ts +2 -0
- package/dist/lib/__tests__/network-utils.spec.d.ts.map +1 -0
- package/dist/lib/__tests__/network-utils.spec.js +140 -0
- package/dist/lib/__tests__/network-utils.spec.js.map +1 -0
- package/dist/lib/contracts/__tests__/repository.spec.d.ts +2 -0
- package/dist/lib/contracts/__tests__/repository.spec.d.ts.map +1 -0
- package/dist/lib/contracts/__tests__/repository.spec.js +321 -0
- package/dist/lib/contracts/__tests__/repository.spec.js.map +1 -0
- package/dist/lib/contracts/repository.d.ts +27 -0
- package/dist/lib/contracts/repository.d.ts.map +1 -0
- package/dist/lib/contracts/repository.js +241 -0
- package/dist/lib/contracts/repository.js.map +1 -0
- package/dist/lib/core/__tests__/engine.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/engine.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/engine.spec.js +1212 -0
- package/dist/lib/core/__tests__/engine.spec.js.map +1 -0
- package/dist/lib/core/__tests__/graph.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/graph.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/graph.spec.js +116 -0
- package/dist/lib/core/__tests__/graph.spec.js.map +1 -0
- package/dist/lib/core/__tests__/json-integration.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/json-integration.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/json-integration.spec.js +300 -0
- package/dist/lib/core/__tests__/json-integration.spec.js.map +1 -0
- package/dist/lib/core/__tests__/loader.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/loader.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/loader.spec.js +288 -0
- package/dist/lib/core/__tests__/loader.spec.js.map +1 -0
- package/dist/lib/core/__tests__/multi-platform-verification.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/multi-platform-verification.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/multi-platform-verification.spec.js +342 -0
- package/dist/lib/core/__tests__/multi-platform-verification.spec.js.map +1 -0
- package/dist/lib/core/__tests__/resolver.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/resolver.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/resolver.spec.js +1367 -0
- package/dist/lib/core/__tests__/resolver.spec.js.map +1 -0
- package/dist/lib/core/__tests__/static-action.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/static-action.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/static-action.spec.js +136 -0
- package/dist/lib/core/__tests__/static-action.spec.js.map +1 -0
- package/dist/lib/core/context.d.ts +29 -0
- package/dist/lib/core/context.d.ts.map +1 -0
- package/dist/lib/core/context.js +88 -0
- package/dist/lib/core/context.js.map +1 -0
- package/dist/lib/core/engine.d.ts +25 -0
- package/dist/lib/core/engine.d.ts.map +1 -0
- package/dist/lib/core/engine.js +1191 -0
- package/dist/lib/core/engine.js.map +1 -0
- package/dist/lib/core/graph.d.ts +18 -0
- package/dist/lib/core/graph.d.ts.map +1 -0
- package/dist/lib/core/graph.js +158 -0
- package/dist/lib/core/graph.js.map +1 -0
- package/dist/lib/core/loader.d.ts +25 -0
- package/dist/lib/core/loader.d.ts.map +1 -0
- package/dist/lib/core/loader.js +248 -0
- package/dist/lib/core/loader.js.map +1 -0
- package/dist/lib/core/resolver.d.ts +20 -0
- package/dist/lib/core/resolver.d.ts.map +1 -0
- package/dist/lib/core/resolver.js +307 -0
- package/dist/lib/core/resolver.js.map +1 -0
- package/dist/lib/deployer.d.ts +39 -0
- package/dist/lib/deployer.d.ts.map +1 -0
- package/dist/lib/deployer.js +533 -0
- package/dist/lib/deployer.js.map +1 -0
- package/dist/lib/events/__tests__/event-system.spec.d.ts +2 -0
- package/dist/lib/events/__tests__/event-system.spec.d.ts.map +1 -0
- package/dist/lib/events/__tests__/event-system.spec.js +256 -0
- package/dist/lib/events/__tests__/event-system.spec.js.map +1 -0
- package/dist/lib/events/cli-adapter.d.ts +13 -0
- package/dist/lib/events/cli-adapter.d.ts.map +1 -0
- package/dist/lib/events/cli-adapter.js +244 -0
- package/dist/lib/events/cli-adapter.js.map +1 -0
- package/dist/lib/events/emitter.d.ts +11 -0
- package/dist/lib/events/emitter.d.ts.map +1 -0
- package/dist/lib/events/emitter.js +29 -0
- package/dist/lib/events/emitter.js.map +1 -0
- package/dist/lib/events/index.d.ts +4 -0
- package/dist/lib/events/index.d.ts.map +1 -0
- package/dist/lib/events/index.js +20 -0
- package/dist/lib/events/index.js.map +1 -0
- package/dist/lib/events/types.d.ts +368 -0
- package/dist/lib/events/types.d.ts.map +1 -0
- package/dist/lib/events/types.js +3 -0
- package/dist/lib/events/types.js.map +1 -0
- package/dist/lib/index.d.ts +5 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +44 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/network-loader.d.ts +3 -0
- package/dist/lib/network-loader.d.ts.map +1 -0
- package/dist/lib/network-loader.js +80 -0
- package/dist/lib/network-loader.js.map +1 -0
- package/dist/lib/network-match.d.ts +3 -0
- package/dist/lib/network-match.d.ts.map +1 -0
- package/dist/lib/network-match.js +62 -0
- package/dist/lib/network-match.js.map +1 -0
- package/dist/lib/network-utils.d.ts +4 -0
- package/dist/lib/network-utils.d.ts.map +1 -0
- package/dist/lib/network-utils.js +39 -0
- package/dist/lib/network-utils.js.map +1 -0
- package/dist/lib/parsers/__tests__/buildinfo.spec.d.ts +2 -0
- package/dist/lib/parsers/__tests__/buildinfo.spec.d.ts.map +1 -0
- package/dist/lib/parsers/__tests__/buildinfo.spec.js +132 -0
- package/dist/lib/parsers/__tests__/buildinfo.spec.js.map +1 -0
- package/dist/lib/parsers/__tests__/job.spec.d.ts +2 -0
- package/dist/lib/parsers/__tests__/job.spec.d.ts.map +1 -0
- package/dist/lib/parsers/__tests__/job.spec.js +318 -0
- package/dist/lib/parsers/__tests__/job.spec.js.map +1 -0
- package/dist/lib/parsers/__tests__/template.spec.d.ts +2 -0
- package/dist/lib/parsers/__tests__/template.spec.d.ts.map +1 -0
- package/dist/lib/parsers/__tests__/template.spec.js +126 -0
- package/dist/lib/parsers/__tests__/template.spec.js.map +1 -0
- package/dist/lib/parsers/artifact/__tests__/artifact.spec.d.ts +2 -0
- package/dist/lib/parsers/artifact/__tests__/artifact.spec.d.ts.map +1 -0
- package/dist/lib/parsers/artifact/__tests__/artifact.spec.js +128 -0
- package/dist/lib/parsers/artifact/__tests__/artifact.spec.js.map +1 -0
- package/dist/lib/parsers/artifact/foundry-1.2.d.ts +3 -0
- package/dist/lib/parsers/artifact/foundry-1.2.d.ts.map +1 -0
- package/dist/lib/parsers/artifact/foundry-1.2.js +82 -0
- package/dist/lib/parsers/artifact/foundry-1.2.js.map +1 -0
- package/dist/lib/parsers/artifact/index.d.ts +3 -0
- package/dist/lib/parsers/artifact/index.d.ts.map +1 -0
- package/dist/lib/parsers/artifact/index.js +17 -0
- package/dist/lib/parsers/artifact/index.js.map +1 -0
- package/dist/lib/parsers/artifact/types.d.ts +3 -0
- package/dist/lib/parsers/artifact/types.d.ts.map +1 -0
- package/dist/lib/parsers/artifact/types.js +3 -0
- package/dist/lib/parsers/artifact/types.js.map +1 -0
- package/dist/lib/parsers/buildinfo.d.ts +5 -0
- package/dist/lib/parsers/buildinfo.d.ts.map +1 -0
- package/dist/lib/parsers/buildinfo.js +85 -0
- package/dist/lib/parsers/buildinfo.js.map +1 -0
- package/dist/lib/parsers/constants.d.ts +4 -0
- package/dist/lib/parsers/constants.d.ts.map +1 -0
- package/dist/lib/parsers/constants.js +45 -0
- package/dist/lib/parsers/constants.js.map +1 -0
- package/dist/lib/parsers/index.d.ts +5 -0
- package/dist/lib/parsers/index.d.ts.map +1 -0
- package/dist/lib/parsers/index.js +21 -0
- package/dist/lib/parsers/index.js.map +1 -0
- package/dist/lib/parsers/job.d.ts +3 -0
- package/dist/lib/parsers/job.d.ts.map +1 -0
- package/dist/lib/parsers/job.js +74 -0
- package/dist/lib/parsers/job.js.map +1 -0
- package/dist/lib/parsers/template.d.ts +3 -0
- package/dist/lib/parsers/template.d.ts.map +1 -0
- package/dist/lib/parsers/template.js +91 -0
- package/dist/lib/parsers/template.js.map +1 -0
- package/dist/lib/std/templates/assured-deployment.yaml +45 -0
- package/dist/lib/std/templates/erc-2470.yaml +67 -0
- package/dist/lib/std/templates/min-balance.yaml +32 -0
- package/dist/lib/std/templates/nano-universal-deployer.yaml +59 -0
- package/dist/lib/std/templates/raw-erc-2470.yaml +59 -0
- package/dist/lib/std/templates/raw-nano-universal-deployer.yaml +51 -0
- package/dist/lib/std/templates/raw-sequence-universal-deployer-2.yaml +48 -0
- package/dist/lib/std/templates/sequence-universal-deployer-2.yaml +57 -0
- package/dist/lib/types/__tests__/json-request-action.spec.d.ts +2 -0
- package/dist/lib/types/__tests__/json-request-action.spec.d.ts.map +1 -0
- package/dist/lib/types/__tests__/json-request-action.spec.js +219 -0
- package/dist/lib/types/__tests__/json-request-action.spec.js.map +1 -0
- package/dist/lib/types/__tests__/read-json-value.spec.d.ts +2 -0
- package/dist/lib/types/__tests__/read-json-value.spec.d.ts.map +1 -0
- package/dist/lib/types/__tests__/read-json-value.spec.js +233 -0
- package/dist/lib/types/__tests__/read-json-value.spec.js.map +1 -0
- package/dist/lib/types/actions.d.ts +74 -0
- package/dist/lib/types/actions.d.ts.map +1 -0
- package/dist/lib/types/actions.js +18 -0
- package/dist/lib/types/actions.js.map +1 -0
- package/dist/lib/types/artifacts.d.ts +15 -0
- package/dist/lib/types/artifacts.d.ts.map +1 -0
- package/dist/lib/types/artifacts.js +3 -0
- package/dist/lib/types/artifacts.js.map +1 -0
- package/dist/lib/types/buildinfo.d.ts +112 -0
- package/dist/lib/types/buildinfo.d.ts.map +1 -0
- package/dist/lib/types/buildinfo.js +3 -0
- package/dist/lib/types/buildinfo.js.map +1 -0
- package/dist/lib/types/conditions.d.ts +17 -0
- package/dist/lib/types/conditions.d.ts.map +1 -0
- package/dist/lib/types/conditions.js +21 -0
- package/dist/lib/types/conditions.js.map +1 -0
- package/dist/lib/types/contracts.d.ts +14 -0
- package/dist/lib/types/contracts.d.ts.map +1 -0
- package/dist/lib/types/contracts.js +3 -0
- package/dist/lib/types/contracts.js.map +1 -0
- package/dist/lib/types/definitions.d.ts +51 -0
- package/dist/lib/types/definitions.d.ts.map +1 -0
- package/dist/lib/types/definitions.js +3 -0
- package/dist/lib/types/definitions.js.map +1 -0
- package/dist/lib/types/index.d.ts +9 -0
- package/dist/lib/types/index.d.ts.map +1 -0
- package/dist/lib/types/index.js +25 -0
- package/dist/lib/types/index.js.map +1 -0
- package/dist/lib/types/network.d.ts +9 -0
- package/dist/lib/types/network.d.ts.map +1 -0
- package/dist/lib/types/network.js +3 -0
- package/dist/lib/types/network.js.map +1 -0
- package/dist/lib/types/project.d.ts +5 -0
- package/dist/lib/types/project.d.ts.map +1 -0
- package/dist/lib/types/project.js +3 -0
- package/dist/lib/types/project.js.map +1 -0
- package/dist/lib/types/task.d.ts +9 -0
- package/dist/lib/types/task.d.ts.map +1 -0
- package/dist/lib/types/task.js +3 -0
- package/dist/lib/types/task.js.map +1 -0
- package/dist/lib/types/values.d.ts +78 -0
- package/dist/lib/types/values.d.ts.map +1 -0
- package/dist/lib/types/values.js +3 -0
- package/dist/lib/types/values.js.map +1 -0
- package/dist/lib/utils/validation.d.ts +5 -0
- package/dist/lib/utils/validation.d.ts.map +1 -0
- package/dist/lib/utils/validation.js +77 -0
- package/dist/lib/utils/validation.js.map +1 -0
- package/dist/lib/validation/contract-references.d.ts +12 -0
- package/dist/lib/validation/contract-references.d.ts.map +1 -0
- package/dist/lib/validation/contract-references.js +112 -0
- package/dist/lib/validation/contract-references.js.map +1 -0
- package/dist/lib/validation/index.d.ts +1 -0
- package/dist/lib/validation/index.d.ts.map +1 -0
- package/dist/lib/validation/index.js +2 -0
- package/dist/lib/validation/index.js.map +1 -0
- package/dist/lib/verification/__tests__/etherscan.spec.d.ts +2 -0
- package/dist/lib/verification/__tests__/etherscan.spec.d.ts.map +1 -0
- package/dist/lib/verification/__tests__/etherscan.spec.js +565 -0
- package/dist/lib/verification/__tests__/etherscan.spec.js.map +1 -0
- package/dist/lib/verification/__tests__/sourcify.spec.d.ts +2 -0
- package/dist/lib/verification/__tests__/sourcify.spec.d.ts.map +1 -0
- package/dist/lib/verification/__tests__/sourcify.spec.js +212 -0
- package/dist/lib/verification/__tests__/sourcify.spec.js.map +1 -0
- package/dist/lib/verification/etherscan.d.ts +56 -0
- package/dist/lib/verification/etherscan.d.ts.map +1 -0
- package/dist/lib/verification/etherscan.js +340 -0
- package/dist/lib/verification/etherscan.js.map +1 -0
- package/dist/lib/verification/sourcify.d.ts +12 -0
- package/dist/lib/verification/sourcify.d.ts.map +1 -0
- package/dist/lib/verification/sourcify.js +227 -0
- package/dist/lib/verification/sourcify.js.map +1 -0
- package/eslint.config.js +48 -0
- package/examples/jobs/guards-v1.yaml +17 -0
- package/examples/jobs/sequence-seq-0001-patch.yaml +59 -0
- package/examples/jobs/sequence-v1.yaml +59 -0
- package/examples/templates/sequence-factory-v1.yaml +56 -0
- package/jest.config.js +25 -0
- package/package.json +68 -0
- package/src/cli.ts +17 -0
- package/src/commands/common.ts +61 -0
- package/src/commands/dry.ts +208 -0
- package/src/commands/etherscan.ts +360 -0
- package/src/commands/index.ts +5 -0
- package/src/commands/list.ts +249 -0
- package/src/commands/run.ts +136 -0
- package/src/commands/utils.ts +52 -0
- package/src/index.ts +67 -0
- package/src/lib/__tests__/deployer-events.spec.ts +338 -0
- package/src/lib/__tests__/deployer.spec.ts +1204 -0
- package/src/lib/__tests__/network-utils.spec.ts +181 -0
- package/src/lib/artifacts/__tests__/fixtures/contract1.json +19 -0
- package/src/lib/artifacts/__tests__/fixtures/contract2.json +19 -0
- package/src/lib/artifacts/__tests__/fixtures/duplicate-name.json +19 -0
- package/src/lib/artifacts/__tests__/fixtures/nested/nested-contract.json +18 -0
- package/src/lib/artifacts/__tests__/fixtures/not-an-artifact.json +8 -0
- package/src/lib/artifacts/__tests__/fixtures/readme.txt +2 -0
- package/src/lib/contracts/__tests__/repository.spec.ts +344 -0
- package/src/lib/contracts/repository.ts +313 -0
- package/src/lib/core/__tests__/engine.spec.ts +1514 -0
- package/src/lib/core/__tests__/graph.spec.ts +125 -0
- package/src/lib/core/__tests__/json-integration.spec.ts +360 -0
- package/src/lib/core/__tests__/loader.spec.ts +334 -0
- package/src/lib/core/__tests__/multi-platform-verification.spec.ts +406 -0
- package/src/lib/core/__tests__/resolver.spec.ts +1693 -0
- package/src/lib/core/__tests__/static-action.spec.ts +172 -0
- package/src/lib/core/context.ts +127 -0
- package/src/lib/core/engine.ts +1531 -0
- package/src/lib/core/graph.ts +252 -0
- package/src/lib/core/loader.ts +263 -0
- package/src/lib/core/resolver.ts +498 -0
- package/src/lib/deployer.ts +768 -0
- package/src/lib/events/__tests__/event-system.spec.ts +343 -0
- package/src/lib/events/cli-adapter.ts +325 -0
- package/src/lib/events/emitter.ts +62 -0
- package/src/lib/events/index.ts +3 -0
- package/src/lib/events/types.ts +469 -0
- package/src/lib/index.ts +14 -0
- package/src/lib/network-loader.ts +59 -0
- package/src/lib/network-utils.ts +64 -0
- package/src/lib/parsers/__tests__/buildinfo.spec.ts +122 -0
- package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-bytecode-buildinfo.json +62 -0
- package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-json.txt +2 -0
- package/src/lib/parsers/__tests__/fixtures/buildinfo/multi-contract-buildinfo.json +89 -0
- package/src/lib/parsers/__tests__/fixtures/buildinfo/no-contracts-buildinfo.json +17 -0
- package/src/lib/parsers/__tests__/fixtures/buildinfo/simple-buildinfo.json +63 -0
- package/src/lib/parsers/__tests__/fixtures/buildinfo/wrong-format.json +4 -0
- package/src/lib/parsers/__tests__/job.spec.ts +335 -0
- package/src/lib/parsers/__tests__/template.spec.ts +111 -0
- package/src/lib/parsers/artifact/__tests__/artifact.spec.ts +117 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/empty-bytecode.json +5 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/hardhat-artifact.json +67 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/invalid-bytecode.json +5 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/invalid-json.txt +11 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/minimal-artifact.json +5 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/missing-abi.json +4 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/missing-bytecode.json +11 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/missing-contract-name.json +11 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/simple-artifact.json +40 -0
- package/src/lib/parsers/artifact/__tests__/fixtures/wrong-types.json +7 -0
- package/src/lib/parsers/artifact/foundry-1.2.ts +72 -0
- package/src/lib/parsers/artifact/index.ts +27 -0
- package/src/lib/parsers/artifact/types.ts +9 -0
- package/src/lib/parsers/buildinfo.ts +127 -0
- package/src/lib/parsers/constants.ts +56 -0
- package/src/lib/parsers/index.ts +5 -0
- package/src/lib/parsers/job.ts +101 -0
- package/src/lib/parsers/template.ts +131 -0
- package/src/lib/std/templates/assured-deployment.yaml +45 -0
- package/src/lib/std/templates/erc-2470.yaml +67 -0
- package/src/lib/std/templates/min-balance.yaml +32 -0
- package/src/lib/std/templates/nano-universal-deployer.yaml +59 -0
- package/src/lib/std/templates/raw-erc-2470.yaml +59 -0
- package/src/lib/std/templates/raw-nano-universal-deployer.yaml +51 -0
- package/src/lib/std/templates/raw-sequence-universal-deployer-2.yaml +48 -0
- package/src/lib/std/templates/sequence-universal-deployer-2.yaml +57 -0
- package/src/lib/types/__tests__/json-request-action.spec.ts +243 -0
- package/src/lib/types/__tests__/read-json-value.spec.ts +264 -0
- package/src/lib/types/actions.ts +127 -0
- package/src/lib/types/artifacts.ts +21 -0
- package/src/lib/types/buildinfo.ts +116 -0
- package/src/lib/types/conditions.ts +50 -0
- package/src/lib/types/contracts.ts +23 -0
- package/src/lib/types/definitions.ts +68 -0
- package/src/lib/types/index.ts +8 -0
- package/src/lib/types/network.ts +22 -0
- package/src/lib/types/project.ts +9 -0
- package/src/lib/types/task.ts +9 -0
- package/src/lib/types/values.ts +116 -0
- package/src/lib/utils/validation.ts +116 -0
- package/src/lib/validation/contract-references.ts +210 -0
- package/src/lib/validation/index.ts +1 -0
- package/src/lib/verification/__tests__/etherscan.spec.ts +710 -0
- package/src/lib/verification/__tests__/sourcify.spec.ts +288 -0
- package/src/lib/verification/etherscan.ts +546 -0
- package/src/lib/verification/sourcify.ts +248 -0
- package/test_validation/artifacts/TestContract.json +9 -0
- package/test_validation/jobs/test-missing.yaml +16 -0
- package/test_validation/networks.yaml +3 -0
- package/tsconfig.json +36 -0
|
@@ -0,0 +1,1191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ExecutionEngine = void 0;
|
|
37
|
+
const types_1 = require("../types");
|
|
38
|
+
const resolver_1 = require("./resolver");
|
|
39
|
+
const validation_1 = require("../utils/validation");
|
|
40
|
+
const events_1 = require("../events");
|
|
41
|
+
const etherscan_1 = require("../verification/etherscan");
|
|
42
|
+
const ethers_1 = require("ethers");
|
|
43
|
+
class ExecutionEngine {
|
|
44
|
+
constructor(templates, eventEmitter, verificationRegistry, noPostCheckConditions) {
|
|
45
|
+
this.resolver = new resolver_1.ValueResolver();
|
|
46
|
+
this.templates = templates;
|
|
47
|
+
this.events = eventEmitter || events_1.deploymentEvents;
|
|
48
|
+
this.verificationRegistry = verificationRegistry || (0, etherscan_1.createDefaultVerificationRegistry)();
|
|
49
|
+
this.noPostCheckConditions = noPostCheckConditions ?? false;
|
|
50
|
+
}
|
|
51
|
+
getPostCheckRetryConfig(context) {
|
|
52
|
+
const network = context.getNetwork();
|
|
53
|
+
const isLocal = network.chainId === 31337 ||
|
|
54
|
+
network.chainId === 1337 ||
|
|
55
|
+
/localhost|127\.0\.0\.1/i.test(network.rpcUrl);
|
|
56
|
+
if (isLocal) {
|
|
57
|
+
return { retries: 100, delayMs: 50 };
|
|
58
|
+
}
|
|
59
|
+
return { retries: 15, delayMs: 2000 };
|
|
60
|
+
}
|
|
61
|
+
async executeJob(job, context) {
|
|
62
|
+
this.events.emitEvent({
|
|
63
|
+
type: 'job_started',
|
|
64
|
+
level: 'info',
|
|
65
|
+
data: {
|
|
66
|
+
jobName: job.name,
|
|
67
|
+
jobVersion: job.version,
|
|
68
|
+
networkName: context.getNetwork().name,
|
|
69
|
+
chainId: context.getNetwork().chainId
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const previousContextPath = context.getContextPath();
|
|
73
|
+
context.setContextPath(job._path);
|
|
74
|
+
try {
|
|
75
|
+
const executionOrder = this.topologicalSortActions(job);
|
|
76
|
+
for (const actionName of executionOrder) {
|
|
77
|
+
const action = job.actions.find(a => a.name === actionName);
|
|
78
|
+
if (!action) {
|
|
79
|
+
throw new Error(`Internal error: Action "${actionName}" not found in job "${job.name}".`);
|
|
80
|
+
}
|
|
81
|
+
await this.executeAction(action, context, new Map());
|
|
82
|
+
}
|
|
83
|
+
if (!this.noPostCheckConditions && job.skip_condition) {
|
|
84
|
+
const { retries, delayMs } = this.getPostCheckRetryConfig(context);
|
|
85
|
+
const shouldSkip = await this.retryBooleanCheck(async () => this.evaluateSkipConditions(job.skip_condition, context, new Map()), retries, delayMs);
|
|
86
|
+
if (!shouldSkip) {
|
|
87
|
+
throw new Error(`Job "${job.name}" failed post-execution check: skip conditions did not evaluate to true`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
context.setContextPath(previousContextPath);
|
|
93
|
+
}
|
|
94
|
+
this.events.emitEvent({
|
|
95
|
+
type: 'job_completed',
|
|
96
|
+
level: 'info',
|
|
97
|
+
data: {
|
|
98
|
+
jobName: job.name,
|
|
99
|
+
networkName: context.getNetwork().name,
|
|
100
|
+
chainId: context.getNetwork().chainId
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async executeAction(action, context, scope) {
|
|
105
|
+
const actionName = 'name' in action ? action.name : action.type;
|
|
106
|
+
const templateName = 'template' in action
|
|
107
|
+
? (action.template || action.type)
|
|
108
|
+
: action.type;
|
|
109
|
+
if (!templateName) {
|
|
110
|
+
throw new Error(`Action "${actionName}": missing both template and type fields`);
|
|
111
|
+
}
|
|
112
|
+
const printableName = (typeof actionName === 'string' && actionName.trim().length > 0)
|
|
113
|
+
? actionName
|
|
114
|
+
: ((0, types_1.isPrimitiveActionType)(templateName) ? templateName : `template:${templateName}`);
|
|
115
|
+
this.events.emitEvent({
|
|
116
|
+
type: 'action_started',
|
|
117
|
+
level: 'info',
|
|
118
|
+
data: {
|
|
119
|
+
actionName: printableName,
|
|
120
|
+
jobName: 'unknown'
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const shouldSkip = await this.evaluateSkipConditions(action.skip_condition, context, scope);
|
|
124
|
+
if (shouldSkip) {
|
|
125
|
+
this.events.emitEvent({
|
|
126
|
+
type: 'action_skipped',
|
|
127
|
+
level: 'info',
|
|
128
|
+
data: {
|
|
129
|
+
actionName: actionName,
|
|
130
|
+
reason: 'condition met'
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
const hasCustomOutput = 'name' in action && action.name &&
|
|
134
|
+
action.output &&
|
|
135
|
+
typeof action.output === 'object' &&
|
|
136
|
+
!Array.isArray(action.output);
|
|
137
|
+
if (hasCustomOutput) {
|
|
138
|
+
const customOutput = action.output;
|
|
139
|
+
for (const [key, value] of Object.entries(customOutput)) {
|
|
140
|
+
const resolvedOutput = await this.resolver.resolve(value, context, scope);
|
|
141
|
+
const outputKey = `${action.name}.${key}`;
|
|
142
|
+
context.setOutput(outputKey, resolvedOutput);
|
|
143
|
+
this.events.emitEvent({
|
|
144
|
+
type: 'output_stored',
|
|
145
|
+
level: 'debug',
|
|
146
|
+
data: {
|
|
147
|
+
outputKey,
|
|
148
|
+
value: resolvedOutput
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if ((0, types_1.isPrimitiveActionType)(templateName)) {
|
|
156
|
+
const hasCustomOutput = 'name' in action && action.name &&
|
|
157
|
+
action.output &&
|
|
158
|
+
typeof action.output === 'object' &&
|
|
159
|
+
!Array.isArray(action.output);
|
|
160
|
+
const primitiveAction = 'template' in action
|
|
161
|
+
? {
|
|
162
|
+
type: (action.type || action.template),
|
|
163
|
+
name: action.name,
|
|
164
|
+
arguments: action.arguments,
|
|
165
|
+
skip_condition: action.skip_condition,
|
|
166
|
+
depends_on: action.depends_on
|
|
167
|
+
}
|
|
168
|
+
: action;
|
|
169
|
+
await this.executePrimitive(primitiveAction, context, scope, hasCustomOutput);
|
|
170
|
+
if (hasCustomOutput) {
|
|
171
|
+
const customOutput = action.output;
|
|
172
|
+
for (const [key, value] of Object.entries(customOutput)) {
|
|
173
|
+
const resolvedOutput = await this.resolver.resolve(value, context, scope);
|
|
174
|
+
const outputKey = `${action.name}.${key}`;
|
|
175
|
+
context.setOutput(outputKey, resolvedOutput);
|
|
176
|
+
this.events.emitEvent({
|
|
177
|
+
type: 'output_stored',
|
|
178
|
+
level: 'debug',
|
|
179
|
+
data: {
|
|
180
|
+
outputKey,
|
|
181
|
+
value: resolvedOutput
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
await this.executeTemplate(action, templateName, context, scope);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async executeTemplate(callingAction, templateName, context, parentScope = new Map()) {
|
|
192
|
+
const template = this.templates.get(templateName);
|
|
193
|
+
if (!template) {
|
|
194
|
+
const actionName = 'name' in callingAction ? callingAction.name : callingAction.type;
|
|
195
|
+
throw new Error(`Template "${templateName}" not found for action "${actionName}".`);
|
|
196
|
+
}
|
|
197
|
+
this.events.emitEvent({
|
|
198
|
+
type: 'template_entered',
|
|
199
|
+
level: 'debug',
|
|
200
|
+
data: {
|
|
201
|
+
templateName: template.name
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
const templateScope = new Map();
|
|
205
|
+
if ('arguments' in callingAction) {
|
|
206
|
+
for (const [key, value] of Object.entries(callingAction.arguments)) {
|
|
207
|
+
const resolvedValue = await this.resolver.resolve(value, context, parentScope);
|
|
208
|
+
templateScope.set(key, resolvedValue);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const previousContextPath = context.getContextPath();
|
|
212
|
+
context.setContextPath(template._path);
|
|
213
|
+
try {
|
|
214
|
+
if (template.setup) {
|
|
215
|
+
if (template.setup.skip_condition && await this.evaluateSkipConditions(template.setup.skip_condition, context, templateScope)) {
|
|
216
|
+
this.events.emitEvent({
|
|
217
|
+
type: 'template_setup_skipped',
|
|
218
|
+
level: 'info',
|
|
219
|
+
data: {
|
|
220
|
+
templateName: template.name,
|
|
221
|
+
reason: 'setup skip condition met'
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
else if (template.setup.actions) {
|
|
226
|
+
this.events.emitEvent({
|
|
227
|
+
type: 'template_setup_started',
|
|
228
|
+
level: 'debug',
|
|
229
|
+
data: {
|
|
230
|
+
templateName: template.name
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
for (const setupAction of template.setup.actions) {
|
|
234
|
+
await this.executeAction(setupAction, context, templateScope);
|
|
235
|
+
}
|
|
236
|
+
this.events.emitEvent({
|
|
237
|
+
type: 'template_setup_completed',
|
|
238
|
+
level: 'debug',
|
|
239
|
+
data: {
|
|
240
|
+
templateName: template.name
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const templateSkipConditions = template.skip_condition;
|
|
246
|
+
const templateShouldSkip = await this.evaluateSkipConditions(templateSkipConditions, context, templateScope);
|
|
247
|
+
if (templateShouldSkip) {
|
|
248
|
+
this.events.emitEvent({
|
|
249
|
+
type: 'template_skipped',
|
|
250
|
+
level: 'info',
|
|
251
|
+
data: {
|
|
252
|
+
templateName: template.name,
|
|
253
|
+
reason: 'condition met'
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
for (const templateAction of template.actions) {
|
|
259
|
+
await this.executeAction(templateAction, context, templateScope);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (!this.noPostCheckConditions && template.skip_condition) {
|
|
263
|
+
const { retries, delayMs } = this.getPostCheckRetryConfig(context);
|
|
264
|
+
const shouldSkip = await this.retryBooleanCheck(async () => this.evaluateSkipConditions(template.skip_condition, context, templateScope), retries, delayMs);
|
|
265
|
+
if (!shouldSkip) {
|
|
266
|
+
throw new Error(`Template "${template.name}" failed post-execution check: skip conditions did not evaluate to true`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if ('name' in callingAction) {
|
|
270
|
+
const actionName = callingAction.name;
|
|
271
|
+
const customOutput = callingAction.output;
|
|
272
|
+
if (customOutput && typeof customOutput === 'object' && !Array.isArray(customOutput)) {
|
|
273
|
+
for (const [key, value] of Object.entries(customOutput)) {
|
|
274
|
+
const resolvedOutput = await this.resolver.resolve(value, context, templateScope);
|
|
275
|
+
const outputKey = `${actionName}.${key}`;
|
|
276
|
+
context.setOutput(outputKey, resolvedOutput);
|
|
277
|
+
this.events.emitEvent({
|
|
278
|
+
type: 'output_stored',
|
|
279
|
+
level: 'debug',
|
|
280
|
+
data: {
|
|
281
|
+
outputKey,
|
|
282
|
+
value: resolvedOutput
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else if (template.outputs) {
|
|
288
|
+
for (const [key, value] of Object.entries(template.outputs)) {
|
|
289
|
+
const resolvedOutput = await this.resolver.resolve(value, context, templateScope);
|
|
290
|
+
const outputKey = `${actionName}.${key}`;
|
|
291
|
+
context.setOutput(outputKey, resolvedOutput);
|
|
292
|
+
this.events.emitEvent({
|
|
293
|
+
type: 'output_stored',
|
|
294
|
+
level: 'debug',
|
|
295
|
+
data: {
|
|
296
|
+
outputKey,
|
|
297
|
+
value: resolvedOutput
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
this.events.emitEvent({
|
|
304
|
+
type: 'template_exited',
|
|
305
|
+
level: 'debug',
|
|
306
|
+
data: {
|
|
307
|
+
templateName: template.name
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
finally {
|
|
312
|
+
context.setContextPath(previousContextPath);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
async executePrimitive(action, context, scope, hasCustomOutput = false) {
|
|
316
|
+
const actionName = action.name || action.type;
|
|
317
|
+
this.events.emitEvent({
|
|
318
|
+
type: 'primitive_action',
|
|
319
|
+
level: 'debug',
|
|
320
|
+
data: {
|
|
321
|
+
actionType: action.type
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
switch (action.type) {
|
|
325
|
+
case 'send-transaction': {
|
|
326
|
+
const resolvedTo = await this.resolver.resolve(action.arguments.to, context, scope);
|
|
327
|
+
const resolvedData = action.arguments.data ? await this.resolver.resolve(action.arguments.data, context, scope) : '0x';
|
|
328
|
+
const resolvedValue = action.arguments.value ? await this.resolver.resolve(action.arguments.value, context, scope) : 0;
|
|
329
|
+
const resolvedGasMultiplier = action.arguments.gasMultiplier !== undefined ? await this.resolver.resolve(action.arguments.gasMultiplier, context, scope) : undefined;
|
|
330
|
+
const to = (0, validation_1.validateAddress)(resolvedTo, actionName);
|
|
331
|
+
const data = (0, validation_1.validateHexData)(resolvedData, actionName, 'data');
|
|
332
|
+
const value = (0, validation_1.validateBigNumberish)(resolvedValue, actionName, 'value');
|
|
333
|
+
let gasMultiplier;
|
|
334
|
+
if (resolvedGasMultiplier !== undefined) {
|
|
335
|
+
if (typeof resolvedGasMultiplier !== 'number' || resolvedGasMultiplier <= 0) {
|
|
336
|
+
throw new Error(`Action "${actionName}": gasMultiplier must be a positive number, got: ${resolvedGasMultiplier}`);
|
|
337
|
+
}
|
|
338
|
+
gasMultiplier = resolvedGasMultiplier;
|
|
339
|
+
}
|
|
340
|
+
const txParams = { to, data, value };
|
|
341
|
+
const network = context.getNetwork();
|
|
342
|
+
if (network.gasLimit) {
|
|
343
|
+
const baseGasLimit = network.gasLimit;
|
|
344
|
+
txParams.gasLimit = gasMultiplier ? Math.floor(baseGasLimit * gasMultiplier) : baseGasLimit;
|
|
345
|
+
}
|
|
346
|
+
else if (gasMultiplier) {
|
|
347
|
+
const signer = await context.getResolvedSigner();
|
|
348
|
+
const estimatedGas = await signer.estimateGas({ to, data, value });
|
|
349
|
+
txParams.gasLimit = Math.floor(Number(estimatedGas) * gasMultiplier);
|
|
350
|
+
}
|
|
351
|
+
const signer = await context.getResolvedSigner();
|
|
352
|
+
const tx = await signer.sendTransaction(txParams);
|
|
353
|
+
this.events.emitEvent({
|
|
354
|
+
type: 'transaction_sent',
|
|
355
|
+
level: 'info',
|
|
356
|
+
data: {
|
|
357
|
+
to,
|
|
358
|
+
value: value.toString(),
|
|
359
|
+
dataPreview: String(data).substring(0, 42),
|
|
360
|
+
txHash: tx.hash
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
const receipt = await tx.wait();
|
|
364
|
+
if (!receipt || receipt.status !== 1) {
|
|
365
|
+
throw new Error(`Transaction for action "${actionName}" failed (reverted). Hash: ${tx.hash}`);
|
|
366
|
+
}
|
|
367
|
+
this.events.emitEvent({
|
|
368
|
+
type: 'transaction_confirmed',
|
|
369
|
+
level: 'info',
|
|
370
|
+
data: {
|
|
371
|
+
txHash: tx.hash,
|
|
372
|
+
blockNumber: receipt.blockNumber
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
if (action.name && !hasCustomOutput) {
|
|
376
|
+
context.setOutput(`${action.name}.hash`, tx.hash);
|
|
377
|
+
context.setOutput(`${action.name}.receipt`, receipt);
|
|
378
|
+
}
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
case 'send-signed-transaction': {
|
|
382
|
+
const resolvedRawTx = await this.resolver.resolve(action.arguments.transaction, context, scope);
|
|
383
|
+
const rawTx = (0, validation_1.validateRawTransaction)(resolvedRawTx, actionName);
|
|
384
|
+
const tx = await context.provider.broadcastTransaction(rawTx);
|
|
385
|
+
this.events.emitEvent({
|
|
386
|
+
type: 'transaction_sent',
|
|
387
|
+
level: 'info',
|
|
388
|
+
data: {
|
|
389
|
+
to: '',
|
|
390
|
+
value: '0',
|
|
391
|
+
dataPreview: 'signed transaction',
|
|
392
|
+
txHash: tx.hash
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
const receipt = await tx.wait();
|
|
396
|
+
if (!receipt || receipt.status !== 1) {
|
|
397
|
+
throw new Error(`Signed transaction for action "${actionName}" failed (reverted). Hash: ${tx.hash}`);
|
|
398
|
+
}
|
|
399
|
+
this.events.emitEvent({
|
|
400
|
+
type: 'transaction_confirmed',
|
|
401
|
+
level: 'info',
|
|
402
|
+
data: {
|
|
403
|
+
txHash: tx.hash,
|
|
404
|
+
blockNumber: receipt.blockNumber
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
if (action.name && !hasCustomOutput) {
|
|
408
|
+
context.setOutput(`${action.name}.hash`, tx.hash);
|
|
409
|
+
context.setOutput(`${action.name}.receipt`, receipt);
|
|
410
|
+
}
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
case 'verify-contract': {
|
|
414
|
+
const actionName = action.name || action.type;
|
|
415
|
+
const resolvedAddress = await this.resolver.resolve(action.arguments.address, context, scope);
|
|
416
|
+
const resolvedContract = await this.resolver.resolve(action.arguments.contract, context, scope);
|
|
417
|
+
const resolvedConstructorArgs = action.arguments.constructorArguments
|
|
418
|
+
? await this.resolver.resolve(action.arguments.constructorArguments, context, scope)
|
|
419
|
+
: undefined;
|
|
420
|
+
const resolvedPlatform = action.arguments.platform
|
|
421
|
+
? await this.resolver.resolve(action.arguments.platform, context, scope)
|
|
422
|
+
: 'all';
|
|
423
|
+
const address = (0, validation_1.validateAddress)(resolvedAddress, actionName);
|
|
424
|
+
if (!resolvedContract || typeof resolvedContract !== 'object') {
|
|
425
|
+
throw new Error(`Action "${actionName}": contract must be a Contract object`);
|
|
426
|
+
}
|
|
427
|
+
const contract = resolvedContract;
|
|
428
|
+
let platformsToTry;
|
|
429
|
+
if (resolvedPlatform === 'all') {
|
|
430
|
+
platformsToTry = ['all'];
|
|
431
|
+
}
|
|
432
|
+
else if (typeof resolvedPlatform === 'string') {
|
|
433
|
+
platformsToTry = [resolvedPlatform];
|
|
434
|
+
}
|
|
435
|
+
else if (Array.isArray(resolvedPlatform)) {
|
|
436
|
+
if (!resolvedPlatform.every(p => typeof p === 'string')) {
|
|
437
|
+
throw new Error(`Action "${actionName}": platform array must contain only strings`);
|
|
438
|
+
}
|
|
439
|
+
platformsToTry = resolvedPlatform;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
throw new Error(`Action "${actionName}": platform must be a string, array of strings, or 'all'`);
|
|
443
|
+
}
|
|
444
|
+
if (!contract.sourceName) {
|
|
445
|
+
throw new Error(`Action "${actionName}": Contract is missing sourceName required for verification`);
|
|
446
|
+
}
|
|
447
|
+
if (!contract.contractName) {
|
|
448
|
+
throw new Error(`Action "${actionName}": Contract is missing contractName required for verification`);
|
|
449
|
+
}
|
|
450
|
+
if (!contract.compiler) {
|
|
451
|
+
throw new Error(`Action "${actionName}": Contract is missing compiler information required for verification`);
|
|
452
|
+
}
|
|
453
|
+
if (!contract.buildInfoId) {
|
|
454
|
+
throw new Error(`Action "${actionName}": Contract is missing buildInfoId required for verification`);
|
|
455
|
+
}
|
|
456
|
+
let constructorArguments;
|
|
457
|
+
if (resolvedConstructorArgs !== undefined) {
|
|
458
|
+
constructorArguments = (0, validation_1.validateHexData)(resolvedConstructorArgs, actionName, 'constructorArguments');
|
|
459
|
+
}
|
|
460
|
+
const network = context.getNetwork();
|
|
461
|
+
const contractName = `${contract.sourceName}:${contract.contractName}`;
|
|
462
|
+
if (platformsToTry.includes('all')) {
|
|
463
|
+
const configuredPlatforms = this.verificationRegistry.getConfiguredPlatforms(network);
|
|
464
|
+
if (configuredPlatforms.length === 0) {
|
|
465
|
+
this.events.emitEvent({
|
|
466
|
+
type: 'action_skipped',
|
|
467
|
+
level: 'warn',
|
|
468
|
+
data: {
|
|
469
|
+
actionName: actionName,
|
|
470
|
+
reason: `No configured verification platforms available for network ${network.name}`
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
let anySuccess = false;
|
|
476
|
+
for (const platform of configuredPlatforms) {
|
|
477
|
+
try {
|
|
478
|
+
await this.verifyOnSinglePlatform(platform, contract, address, constructorArguments, network, actionName, contractName, action, context, hasCustomOutput);
|
|
479
|
+
anySuccess = true;
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
this.events.emitEvent({
|
|
483
|
+
type: 'verification_failed',
|
|
484
|
+
level: 'warn',
|
|
485
|
+
data: {
|
|
486
|
+
actionName: actionName,
|
|
487
|
+
address,
|
|
488
|
+
contractName,
|
|
489
|
+
platform: platform.name,
|
|
490
|
+
error: error instanceof Error ? error.message : String(error)
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
if (!anySuccess) {
|
|
496
|
+
throw new Error(`Verification failed on all configured platforms for network ${network.name}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
let anySuccess = false;
|
|
501
|
+
for (const platformName of platformsToTry) {
|
|
502
|
+
const platform = this.verificationRegistry.get(platformName);
|
|
503
|
+
if (!platform) {
|
|
504
|
+
throw new Error(`Action "${actionName}": Unsupported verification platform "${platformName}"`);
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
await this.verifyOnSinglePlatform(platform, contract, address, constructorArguments, network, actionName, contractName, action, context, hasCustomOutput);
|
|
508
|
+
anySuccess = true;
|
|
509
|
+
}
|
|
510
|
+
catch (error) {
|
|
511
|
+
this.events.emitEvent({
|
|
512
|
+
type: 'verification_failed',
|
|
513
|
+
level: platformsToTry.length > 1 ? 'warn' : 'error',
|
|
514
|
+
data: {
|
|
515
|
+
actionName: actionName,
|
|
516
|
+
address,
|
|
517
|
+
contractName,
|
|
518
|
+
platform: platform.name,
|
|
519
|
+
error: error instanceof Error ? error.message : String(error)
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
if (platformsToTry.length === 1) {
|
|
523
|
+
throw error;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (!anySuccess && platformsToTry.length > 1) {
|
|
528
|
+
throw new Error(`Verification failed on all specified platforms: ${platformsToTry.join(', ')}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
case 'static': {
|
|
534
|
+
const resolvedValue = await this.resolver.resolve(action.arguments.value, context, scope);
|
|
535
|
+
if (action.name && !hasCustomOutput) {
|
|
536
|
+
context.setOutput(`${action.name}.value`, resolvedValue);
|
|
537
|
+
}
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
case 'create-contract': {
|
|
541
|
+
const resolvedData = await this.resolver.resolve(action.arguments.data, context, scope);
|
|
542
|
+
const resolvedValue = action.arguments.value ? await this.resolver.resolve(action.arguments.value, context, scope) : 0;
|
|
543
|
+
const resolvedGasMultiplier = action.arguments.gasMultiplier !== undefined ? await this.resolver.resolve(action.arguments.gasMultiplier, context, scope) : undefined;
|
|
544
|
+
const data = (0, validation_1.validateHexData)(resolvedData, actionName, 'data');
|
|
545
|
+
const value = (0, validation_1.validateBigNumberish)(resolvedValue, actionName, 'value');
|
|
546
|
+
let gasMultiplier;
|
|
547
|
+
if (resolvedGasMultiplier !== undefined) {
|
|
548
|
+
if (typeof resolvedGasMultiplier !== 'number' || resolvedGasMultiplier <= 0) {
|
|
549
|
+
throw new Error(`Action "${actionName}": gasMultiplier must be a positive number, got: ${resolvedGasMultiplier}`);
|
|
550
|
+
}
|
|
551
|
+
gasMultiplier = resolvedGasMultiplier;
|
|
552
|
+
}
|
|
553
|
+
const txParams = { to: null, data, value };
|
|
554
|
+
const network = context.getNetwork();
|
|
555
|
+
if (network.gasLimit) {
|
|
556
|
+
const baseGasLimit = network.gasLimit;
|
|
557
|
+
txParams.gasLimit = gasMultiplier ? Math.floor(baseGasLimit * gasMultiplier) : baseGasLimit;
|
|
558
|
+
}
|
|
559
|
+
else if (gasMultiplier) {
|
|
560
|
+
const signer = await context.getResolvedSigner();
|
|
561
|
+
const estimatedGas = await signer.estimateGas({ to: null, data, value });
|
|
562
|
+
txParams.gasLimit = Math.floor(Number(estimatedGas) * gasMultiplier);
|
|
563
|
+
}
|
|
564
|
+
const signer = await context.getResolvedSigner();
|
|
565
|
+
const tx = await signer.sendTransaction(txParams);
|
|
566
|
+
this.events.emitEvent({
|
|
567
|
+
type: 'transaction_sent',
|
|
568
|
+
level: 'info',
|
|
569
|
+
data: {
|
|
570
|
+
to: 'contract creation',
|
|
571
|
+
value: value.toString(),
|
|
572
|
+
dataPreview: String(data).substring(0, 42),
|
|
573
|
+
txHash: tx.hash
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
const receipt = await tx.wait();
|
|
577
|
+
if (!receipt || receipt.status !== 1) {
|
|
578
|
+
throw new Error(`Contract creation for action "${actionName}" failed (reverted). Hash: ${tx.hash}`);
|
|
579
|
+
}
|
|
580
|
+
if (!receipt.contractAddress) {
|
|
581
|
+
throw new Error(`Contract creation for action "${actionName}" did not return a contract address. Hash: ${tx.hash}`);
|
|
582
|
+
}
|
|
583
|
+
this.events.emitEvent({
|
|
584
|
+
type: 'transaction_confirmed',
|
|
585
|
+
level: 'info',
|
|
586
|
+
data: {
|
|
587
|
+
txHash: tx.hash,
|
|
588
|
+
blockNumber: receipt.blockNumber
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
this.events.emitEvent({
|
|
592
|
+
type: 'contract_created',
|
|
593
|
+
level: 'info',
|
|
594
|
+
data: {
|
|
595
|
+
contractAddress: receipt.contractAddress,
|
|
596
|
+
txHash: tx.hash,
|
|
597
|
+
blockNumber: receipt.blockNumber
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
if (action.name && !hasCustomOutput) {
|
|
601
|
+
context.setOutput(`${action.name}.hash`, tx.hash);
|
|
602
|
+
context.setOutput(`${action.name}.receipt`, receipt);
|
|
603
|
+
context.setOutput(`${action.name}.address`, receipt.contractAddress);
|
|
604
|
+
}
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
case 'test-nicks-method': {
|
|
608
|
+
const defaultBytecode = '0x608060405234801561001057600080fd5b5061013d806100206000396000f3fe60806040526004361061001e5760003560e01c80639c4ae2d014610023575b600080fd5b6100cb6004803603604081101561003957600080fd5b81019060208101813564010000000081111561005457600080fd5b82018360208201111561006657600080fd5b8035906020019184600183028401116401000000008311171561008857600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955050913592506100cd915050565b005b60008183516020850134f56040805173ffffffffffffffffffffffffffffffffffffffff83168152905191925081900360200190a050505056fea264697066735822122033609f614f03931b92d88c309d698449bb77efcd517328d341fa4f923c5d8c7964736f6c63430007060033';
|
|
609
|
+
const args = action.arguments || {};
|
|
610
|
+
const resolvedBytecode = args.bytecode ? await this.resolver.resolve(args.bytecode, context, scope) : defaultBytecode;
|
|
611
|
+
const resolvedGasPrice = args.gasPrice ? await this.resolver.resolve(args.gasPrice, context, scope) : undefined;
|
|
612
|
+
const resolvedGasLimit = args.gasLimit ? await this.resolver.resolve(args.gasLimit, context, scope) : undefined;
|
|
613
|
+
const resolvedFundingAmount = args.fundingAmount ? await this.resolver.resolve(args.fundingAmount, context, scope) : undefined;
|
|
614
|
+
const bytecode = (0, validation_1.validateHexData)(resolvedBytecode, actionName, 'bytecode');
|
|
615
|
+
const gasPrice = resolvedGasPrice ? (0, validation_1.validateBigNumberish)(resolvedGasPrice, actionName, 'gasPrice') : undefined;
|
|
616
|
+
const gasLimit = resolvedGasLimit ? (0, validation_1.validateBigNumberish)(resolvedGasLimit, actionName, 'gasLimit') : undefined;
|
|
617
|
+
const fundingAmount = resolvedFundingAmount ? (0, validation_1.validateBigNumberish)(resolvedFundingAmount, actionName, 'fundingAmount') : undefined;
|
|
618
|
+
const success = await this.testNicksMethod(bytecode, context, gasPrice, gasLimit, fundingAmount);
|
|
619
|
+
if (!success) {
|
|
620
|
+
throw new Error(`Nick's method test failed for action "${actionName}"`);
|
|
621
|
+
}
|
|
622
|
+
this.events.emitEvent({
|
|
623
|
+
type: 'action_completed',
|
|
624
|
+
level: 'info',
|
|
625
|
+
data: {
|
|
626
|
+
actionName: actionName,
|
|
627
|
+
result: 'Nick\'s method test passed'
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
if (action.name && !hasCustomOutput) {
|
|
631
|
+
context.setOutput(`${action.name}.success`, true);
|
|
632
|
+
}
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
case 'json-request': {
|
|
636
|
+
const resolvedUrl = await this.resolver.resolve(action.arguments.url, context, scope);
|
|
637
|
+
const resolvedMethod = action.arguments.method ? await this.resolver.resolve(action.arguments.method, context, scope) : 'GET';
|
|
638
|
+
const resolvedHeaders = action.arguments.headers ? await this.resolver.resolve(action.arguments.headers, context, scope) : {};
|
|
639
|
+
const resolvedBody = action.arguments.body ? await this.resolver.resolve(action.arguments.body, context, scope) : undefined;
|
|
640
|
+
if (typeof resolvedUrl !== 'string') {
|
|
641
|
+
throw new Error(`Action "${actionName}": url must be a string, got: ${typeof resolvedUrl}`);
|
|
642
|
+
}
|
|
643
|
+
if (typeof resolvedMethod !== 'string') {
|
|
644
|
+
throw new Error(`Action "${actionName}": method must be a string, got: ${typeof resolvedMethod}`);
|
|
645
|
+
}
|
|
646
|
+
if (resolvedHeaders && typeof resolvedHeaders !== 'object') {
|
|
647
|
+
throw new Error(`Action "${actionName}": headers must be an object, got: ${typeof resolvedHeaders}`);
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
const fetchOptions = {
|
|
651
|
+
method: resolvedMethod.toUpperCase(),
|
|
652
|
+
headers: {
|
|
653
|
+
'Content-Type': 'application/json',
|
|
654
|
+
...resolvedHeaders
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
if (resolvedBody !== undefined && resolvedMethod.toUpperCase() !== 'GET') {
|
|
658
|
+
fetchOptions.body = JSON.stringify(resolvedBody);
|
|
659
|
+
}
|
|
660
|
+
this.events.emitEvent({
|
|
661
|
+
type: 'action_started',
|
|
662
|
+
level: 'info',
|
|
663
|
+
data: {
|
|
664
|
+
actionName: actionName,
|
|
665
|
+
message: `Making ${resolvedMethod.toUpperCase()} request to ${resolvedUrl}`
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
const response = await fetch(resolvedUrl, fetchOptions);
|
|
669
|
+
if (!response.ok) {
|
|
670
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
671
|
+
}
|
|
672
|
+
const responseData = await response.json();
|
|
673
|
+
this.events.emitEvent({
|
|
674
|
+
type: 'action_completed',
|
|
675
|
+
level: 'info',
|
|
676
|
+
data: {
|
|
677
|
+
actionName: actionName,
|
|
678
|
+
message: `Request completed successfully (${response.status})`
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
if (action.name && !hasCustomOutput) {
|
|
682
|
+
context.setOutput(`${action.name}.response`, responseData);
|
|
683
|
+
context.setOutput(`${action.name}.status`, response.status);
|
|
684
|
+
context.setOutput(`${action.name}.statusText`, response.statusText);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
catch (error) {
|
|
688
|
+
this.events.emitEvent({
|
|
689
|
+
type: 'action_failed',
|
|
690
|
+
level: 'error',
|
|
691
|
+
data: {
|
|
692
|
+
actionName: actionName,
|
|
693
|
+
error: error instanceof Error ? error.message : String(error)
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
throw new Error(`Action "${actionName}" failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
697
|
+
}
|
|
698
|
+
break;
|
|
699
|
+
}
|
|
700
|
+
default:
|
|
701
|
+
throw new Error(`Unknown or unimplemented primitive action type: ${action.type}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
async verifyOnSinglePlatform(platform, contract, address, constructorArguments, network, actionName, contractName, action, context, hasCustomOutput = false) {
|
|
705
|
+
const supportsNetwork = platform.supportsNetwork(network);
|
|
706
|
+
if (!supportsNetwork) {
|
|
707
|
+
this.events.emitEvent({
|
|
708
|
+
type: 'action_skipped',
|
|
709
|
+
level: 'info',
|
|
710
|
+
data: {
|
|
711
|
+
actionName: actionName,
|
|
712
|
+
reason: `Network ${network.name} does not support ${platform.name} verification`
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const isConfigured = platform.isConfigured();
|
|
718
|
+
if (!isConfigured) {
|
|
719
|
+
this.events.emitEvent({
|
|
720
|
+
type: 'action_skipped',
|
|
721
|
+
level: 'warn',
|
|
722
|
+
data: {
|
|
723
|
+
actionName: actionName,
|
|
724
|
+
reason: `Verification skipped: ${platform.getConfigurationRequirements()}`
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
let buildInfoPath;
|
|
730
|
+
for (const sourcePath of contract._sources) {
|
|
731
|
+
if (sourcePath.includes('/build-info/') && sourcePath.endsWith('.json')) {
|
|
732
|
+
buildInfoPath = sourcePath;
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (!buildInfoPath) {
|
|
737
|
+
throw new Error(`Action "${actionName}": No build-info file found in contract sources`);
|
|
738
|
+
}
|
|
739
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
740
|
+
let buildInfoContent;
|
|
741
|
+
try {
|
|
742
|
+
buildInfoContent = await fs.readFile(buildInfoPath, 'utf-8');
|
|
743
|
+
}
|
|
744
|
+
catch (error) {
|
|
745
|
+
throw new Error(`Action "${actionName}": Failed to read build info file at ${buildInfoPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
746
|
+
}
|
|
747
|
+
let buildInfo;
|
|
748
|
+
try {
|
|
749
|
+
buildInfo = JSON.parse(buildInfoContent);
|
|
750
|
+
}
|
|
751
|
+
catch (error) {
|
|
752
|
+
throw new Error(`Action "${actionName}": Failed to parse build info JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
753
|
+
}
|
|
754
|
+
this.events.emitEvent({
|
|
755
|
+
type: 'verification_started',
|
|
756
|
+
level: 'info',
|
|
757
|
+
data: {
|
|
758
|
+
actionName: actionName,
|
|
759
|
+
address,
|
|
760
|
+
contractName,
|
|
761
|
+
platform: platform.name,
|
|
762
|
+
networkName: network.name
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
try {
|
|
766
|
+
const verificationResult = await platform.verifyContract({
|
|
767
|
+
contract,
|
|
768
|
+
buildInfo,
|
|
769
|
+
address,
|
|
770
|
+
constructorArguments,
|
|
771
|
+
network
|
|
772
|
+
});
|
|
773
|
+
if (!verificationResult.success) {
|
|
774
|
+
throw new Error(`Verification failed: ${verificationResult.message}`);
|
|
775
|
+
}
|
|
776
|
+
if (verificationResult.isAlreadyVerified) {
|
|
777
|
+
this.events.emitEvent({
|
|
778
|
+
type: 'verification_completed',
|
|
779
|
+
level: 'info',
|
|
780
|
+
data: {
|
|
781
|
+
actionName: actionName,
|
|
782
|
+
address,
|
|
783
|
+
contractName,
|
|
784
|
+
platform: platform.name,
|
|
785
|
+
message: verificationResult.message
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
this.events.emitEvent({
|
|
791
|
+
type: 'verification_submitted',
|
|
792
|
+
level: 'info',
|
|
793
|
+
data: {
|
|
794
|
+
actionName: actionName,
|
|
795
|
+
platform: platform.name,
|
|
796
|
+
guid: verificationResult.guid || 'N/A',
|
|
797
|
+
message: verificationResult.message
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
this.events.emitEvent({
|
|
801
|
+
type: 'verification_completed',
|
|
802
|
+
level: 'info',
|
|
803
|
+
data: {
|
|
804
|
+
actionName: actionName,
|
|
805
|
+
address,
|
|
806
|
+
contractName,
|
|
807
|
+
platform: platform.name,
|
|
808
|
+
message: 'Contract verified successfully'
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
if (action.name && !hasCustomOutput) {
|
|
813
|
+
context.setOutput(`${action.name}.verified`, true);
|
|
814
|
+
if (verificationResult.guid) {
|
|
815
|
+
context.setOutput(`${action.name}.guid`, verificationResult.guid);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
catch (error) {
|
|
820
|
+
this.events.emitEvent({
|
|
821
|
+
type: 'verification_failed',
|
|
822
|
+
level: 'error',
|
|
823
|
+
data: {
|
|
824
|
+
actionName: actionName,
|
|
825
|
+
address,
|
|
826
|
+
contractName,
|
|
827
|
+
platform: platform.name,
|
|
828
|
+
error: error instanceof Error ? error.message : String(error)
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
throw error;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
async testNicksMethod(bytecode, context, gasPrice, gasLimit, fundingAmount) {
|
|
835
|
+
let testResult = false;
|
|
836
|
+
let eoaAddress;
|
|
837
|
+
let wallet;
|
|
838
|
+
try {
|
|
839
|
+
const defaultGasPrice = gasPrice || ethers_1.ethers.parseUnits('100', 'gwei');
|
|
840
|
+
const defaultGasLimit = gasLimit || 250000n;
|
|
841
|
+
const calculatedCost = BigInt(defaultGasPrice.toString()) * BigInt(defaultGasLimit.toString());
|
|
842
|
+
const defaultFundingAmount = fundingAmount || calculatedCost;
|
|
843
|
+
const signer = await context.getResolvedSigner();
|
|
844
|
+
const signerAddress = await signer.getAddress();
|
|
845
|
+
const signerBalance = await context.provider.getBalance(signerAddress);
|
|
846
|
+
if (signerBalance < BigInt(defaultFundingAmount.toString())) {
|
|
847
|
+
this.events.emitEvent({
|
|
848
|
+
type: 'action_failed',
|
|
849
|
+
level: 'error',
|
|
850
|
+
data: {
|
|
851
|
+
message: `Insufficient funds: signer has ${ethers_1.ethers.formatEther(signerBalance)} ETH but needs ${ethers_1.ethers.formatEther(defaultFundingAmount)} ETH`
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
const result = await this.generateNicksMethodTransaction(bytecode, defaultGasPrice, defaultGasLimit);
|
|
857
|
+
const rawTx = result.rawTx;
|
|
858
|
+
eoaAddress = result.eoaAddress;
|
|
859
|
+
wallet = result.wallet;
|
|
860
|
+
this.events.emitEvent({
|
|
861
|
+
type: 'debug_info',
|
|
862
|
+
level: 'debug',
|
|
863
|
+
data: {
|
|
864
|
+
message: `Testing Nick's method with EOA: ${eoaAddress}`
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
const currentBalance = await context.provider.getBalance(eoaAddress);
|
|
868
|
+
const neededFunding = BigInt(defaultFundingAmount.toString()) - currentBalance;
|
|
869
|
+
if (neededFunding > 0) {
|
|
870
|
+
this.events.emitEvent({
|
|
871
|
+
type: 'transaction_sent',
|
|
872
|
+
level: 'debug',
|
|
873
|
+
data: {
|
|
874
|
+
to: eoaAddress,
|
|
875
|
+
value: neededFunding.toString(),
|
|
876
|
+
dataPreview: 'funding EOA for Nick\'s method test',
|
|
877
|
+
txHash: 'pending'
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
this.events.emitEvent({
|
|
881
|
+
type: 'debug_info',
|
|
882
|
+
level: 'debug',
|
|
883
|
+
data: {
|
|
884
|
+
message: `[NICK'S METHOD DEBUG] Sending funding transaction: ${ethers_1.ethers.formatEther(neededFunding)} ETH to ${eoaAddress}`
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
const signer = await context.getResolvedSigner();
|
|
888
|
+
const fundingTx = await signer.sendTransaction({
|
|
889
|
+
to: eoaAddress,
|
|
890
|
+
value: neededFunding
|
|
891
|
+
});
|
|
892
|
+
this.events.emitEvent({
|
|
893
|
+
type: 'debug_info',
|
|
894
|
+
level: 'debug',
|
|
895
|
+
data: {
|
|
896
|
+
message: `[NICK'S METHOD DEBUG] Funding transaction sent: ${fundingTx.hash}, waiting for confirmation...`
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
const fundingReceipt = await fundingTx.wait();
|
|
900
|
+
this.events.emitEvent({
|
|
901
|
+
type: 'transaction_confirmed',
|
|
902
|
+
level: 'debug',
|
|
903
|
+
data: {
|
|
904
|
+
txHash: fundingTx.hash,
|
|
905
|
+
blockNumber: fundingReceipt?.blockNumber || 0
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
this.events.emitEvent({
|
|
909
|
+
type: 'debug_info',
|
|
910
|
+
level: 'debug',
|
|
911
|
+
data: {
|
|
912
|
+
message: `[NICK'S METHOD DEBUG] Funded EOA ${eoaAddress} with ${ethers_1.ethers.formatEther(neededFunding)} ETH, receipt status: ${fundingReceipt?.status}`
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
if (!fundingReceipt || fundingReceipt.status !== 1) {
|
|
916
|
+
this.events.emitEvent({
|
|
917
|
+
type: 'action_failed',
|
|
918
|
+
level: 'error',
|
|
919
|
+
data: {
|
|
920
|
+
message: `[NICK'S METHOD DEBUG] Funding transaction failed! Hash: ${fundingTx.hash}, Status: ${fundingReceipt?.status}`
|
|
921
|
+
}
|
|
922
|
+
});
|
|
923
|
+
return false;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
else {
|
|
927
|
+
this.events.emitEvent({
|
|
928
|
+
type: 'debug_info',
|
|
929
|
+
level: 'debug',
|
|
930
|
+
data: {
|
|
931
|
+
message: `[NICK'S METHOD DEBUG] EOA already has sufficient balance, skipping funding`
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
this.events.emitEvent({
|
|
936
|
+
type: 'debug_info',
|
|
937
|
+
level: 'debug',
|
|
938
|
+
data: {
|
|
939
|
+
message: `[NICK'S METHOD DEBUG] Broadcasting Nick's method transaction. RawTx: ${rawTx.substring(0, 100)}...`
|
|
940
|
+
}
|
|
941
|
+
});
|
|
942
|
+
const deployTx = await context.provider.broadcastTransaction(rawTx);
|
|
943
|
+
this.events.emitEvent({
|
|
944
|
+
type: 'debug_info',
|
|
945
|
+
level: 'debug',
|
|
946
|
+
data: {
|
|
947
|
+
message: `[NICK'S METHOD DEBUG] Transaction broadcasted successfully. Hash: ${deployTx.hash}, waiting for confirmation...`
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
const receipt = await deployTx.wait();
|
|
951
|
+
this.events.emitEvent({
|
|
952
|
+
type: 'debug_info',
|
|
953
|
+
level: 'debug',
|
|
954
|
+
data: {
|
|
955
|
+
message: `[NICK'S METHOD DEBUG] Transaction receipt received. Status: ${receipt?.status}, ContractAddress: ${receipt?.contractAddress}, BlockNumber: ${receipt?.blockNumber}`
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
if (receipt && receipt.status === 1) {
|
|
959
|
+
this.events.emitEvent({
|
|
960
|
+
type: 'transaction_confirmed',
|
|
961
|
+
level: 'info',
|
|
962
|
+
data: {
|
|
963
|
+
txHash: deployTx.hash,
|
|
964
|
+
blockNumber: receipt.blockNumber || 0
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
this.events.emitEvent({
|
|
968
|
+
type: 'debug_info',
|
|
969
|
+
level: 'debug',
|
|
970
|
+
data: {
|
|
971
|
+
message: `[NICK'S METHOD DEBUG] Nick's method test successful - contract deployed at ${receipt.contractAddress}`
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
testResult = true;
|
|
975
|
+
}
|
|
976
|
+
else {
|
|
977
|
+
this.events.emitEvent({
|
|
978
|
+
type: 'action_failed',
|
|
979
|
+
level: 'error',
|
|
980
|
+
data: {
|
|
981
|
+
message: `[NICK'S METHOD DEBUG] Nick's method test failed - transaction reverted or failed. Hash: ${deployTx.hash}, Status: ${receipt?.status}`
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
testResult = false;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
catch (error) {
|
|
988
|
+
this.events.emitEvent({
|
|
989
|
+
type: 'action_failed',
|
|
990
|
+
level: 'error',
|
|
991
|
+
data: {
|
|
992
|
+
message: `[NICK'S METHOD DEBUG] Nick's method test failed with error: ${error instanceof Error ? error.message : String(error)}`
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
if (error instanceof Error && error.stack) {
|
|
996
|
+
this.events.emitEvent({
|
|
997
|
+
type: 'action_failed',
|
|
998
|
+
level: 'debug',
|
|
999
|
+
data: {
|
|
1000
|
+
message: `[NICK'S METHOD DEBUG] Error stack trace: ${error.stack}`
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
testResult = false;
|
|
1005
|
+
}
|
|
1006
|
+
finally {
|
|
1007
|
+
if (eoaAddress && wallet) {
|
|
1008
|
+
try {
|
|
1009
|
+
await this.returnRemainingFunds(eoaAddress, wallet, context);
|
|
1010
|
+
}
|
|
1011
|
+
catch (error) {
|
|
1012
|
+
this.events.emitEvent({
|
|
1013
|
+
type: 'action_failed',
|
|
1014
|
+
level: 'warn',
|
|
1015
|
+
data: {
|
|
1016
|
+
message: `Failed to return remaining funds from EOA ${eoaAddress}: ${error instanceof Error ? error.message : String(error)}`
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
return testResult;
|
|
1023
|
+
}
|
|
1024
|
+
async generateNicksMethodTransaction(bytecode, gasPrice, gasLimit) {
|
|
1025
|
+
const wallet = ethers_1.ethers.Wallet.createRandom();
|
|
1026
|
+
const unsignedTx = {
|
|
1027
|
+
type: 0,
|
|
1028
|
+
chainId: 0,
|
|
1029
|
+
nonce: 0,
|
|
1030
|
+
gasPrice: gasPrice,
|
|
1031
|
+
gasLimit: gasLimit,
|
|
1032
|
+
to: null,
|
|
1033
|
+
value: 0,
|
|
1034
|
+
data: bytecode
|
|
1035
|
+
};
|
|
1036
|
+
const signedTx = await wallet.signTransaction(unsignedTx);
|
|
1037
|
+
const parsedTx = ethers_1.ethers.Transaction.from(signedTx);
|
|
1038
|
+
const eoaAddress = parsedTx.from;
|
|
1039
|
+
return {
|
|
1040
|
+
rawTx: signedTx,
|
|
1041
|
+
eoaAddress: eoaAddress,
|
|
1042
|
+
wallet: wallet
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
async returnRemainingFunds(eoaAddress, wallet, context) {
|
|
1046
|
+
const remainingBalance = await context.provider.getBalance(eoaAddress);
|
|
1047
|
+
if (remainingBalance <= 0n) {
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
const connectedWallet = wallet.connect(context.provider);
|
|
1051
|
+
const gasPrice = await context.provider.getFeeData().then(data => data.gasPrice || ethers_1.ethers.parseUnits('20', 'gwei'));
|
|
1052
|
+
const gasLimit = 21000n;
|
|
1053
|
+
const gasCost = BigInt(gasPrice.toString()) * gasLimit;
|
|
1054
|
+
if (remainingBalance <= gasCost) {
|
|
1055
|
+
this.events.emitEvent({
|
|
1056
|
+
type: 'action_info',
|
|
1057
|
+
level: 'debug',
|
|
1058
|
+
data: {
|
|
1059
|
+
message: `Remaining balance ${ethers_1.ethers.formatEther(remainingBalance)} ETH is insufficient to cover gas costs for fund return`
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
const amountToSend = remainingBalance - gasCost;
|
|
1065
|
+
this.events.emitEvent({
|
|
1066
|
+
type: 'transaction_sent',
|
|
1067
|
+
level: 'debug',
|
|
1068
|
+
data: {
|
|
1069
|
+
to: await (await context.getResolvedSigner()).getAddress(),
|
|
1070
|
+
value: amountToSend.toString(),
|
|
1071
|
+
dataPreview: 'returning remaining funds from Nick\'s method test',
|
|
1072
|
+
txHash: 'pending'
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
const returnTx = await connectedWallet.sendTransaction({
|
|
1076
|
+
to: await (await context.getResolvedSigner()).getAddress(),
|
|
1077
|
+
value: amountToSend,
|
|
1078
|
+
gasPrice: gasPrice,
|
|
1079
|
+
gasLimit: gasLimit
|
|
1080
|
+
});
|
|
1081
|
+
await returnTx.wait();
|
|
1082
|
+
this.events.emitEvent({
|
|
1083
|
+
type: 'transaction_confirmed',
|
|
1084
|
+
level: 'debug',
|
|
1085
|
+
data: {
|
|
1086
|
+
txHash: returnTx.hash,
|
|
1087
|
+
blockNumber: (await returnTx.wait())?.blockNumber || 0
|
|
1088
|
+
}
|
|
1089
|
+
});
|
|
1090
|
+
this.events.emitEvent({
|
|
1091
|
+
type: 'debug_info',
|
|
1092
|
+
level: 'debug',
|
|
1093
|
+
data: {
|
|
1094
|
+
message: `Returned ${ethers_1.ethers.formatEther(amountToSend)} ETH from test EOA ${eoaAddress} to original wallet`
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
async retryBooleanCheck(checkFn, retries = 3, delayMs = 2000) {
|
|
1099
|
+
const milestones = new Set();
|
|
1100
|
+
const total = retries + 1;
|
|
1101
|
+
milestones.add(1);
|
|
1102
|
+
milestones.add(Math.max(1, Math.floor(total * 0.25)));
|
|
1103
|
+
milestones.add(Math.max(1, Math.floor(total * 0.5)));
|
|
1104
|
+
milestones.add(Math.max(1, Math.floor(total * 0.75)));
|
|
1105
|
+
milestones.add(total);
|
|
1106
|
+
for (let attempt = 0; attempt < total; attempt++) {
|
|
1107
|
+
try {
|
|
1108
|
+
const result = await checkFn();
|
|
1109
|
+
if (result) {
|
|
1110
|
+
return true;
|
|
1111
|
+
}
|
|
1112
|
+
if (milestones.has(attempt + 1)) {
|
|
1113
|
+
this.events.emitEvent({
|
|
1114
|
+
type: 'debug_info',
|
|
1115
|
+
level: 'debug',
|
|
1116
|
+
data: {
|
|
1117
|
+
message: `Post-execution check returned false (attempt ${attempt + 1}/${total}).`
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
catch (err) {
|
|
1123
|
+
if (milestones.has(attempt + 1)) {
|
|
1124
|
+
this.events.emitEvent({
|
|
1125
|
+
type: 'debug_info',
|
|
1126
|
+
level: 'debug',
|
|
1127
|
+
data: {
|
|
1128
|
+
message: `Post-execution check threw error (attempt ${attempt + 1}/${total}): ${err instanceof Error ? err.message : String(err)}`
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
if (attempt < retries) {
|
|
1134
|
+
await new Promise(res => setTimeout(res, delayMs));
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
return false;
|
|
1138
|
+
}
|
|
1139
|
+
async evaluateSkipConditions(conditions, context, scope) {
|
|
1140
|
+
if (!conditions || conditions.length === 0) {
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1143
|
+
for (const condition of conditions) {
|
|
1144
|
+
const shouldSkip = await this.resolver.resolve(condition, context, scope);
|
|
1145
|
+
if (shouldSkip) {
|
|
1146
|
+
return true;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
return false;
|
|
1150
|
+
}
|
|
1151
|
+
topologicalSortActions(job) {
|
|
1152
|
+
const sorted = [];
|
|
1153
|
+
const graph = new Map();
|
|
1154
|
+
const inDegree = new Map();
|
|
1155
|
+
const actionMap = new Map(job.actions.map(a => [a.name, a]));
|
|
1156
|
+
for (const action of job.actions) {
|
|
1157
|
+
graph.set(action.name, new Set(action.depends_on || []));
|
|
1158
|
+
inDegree.set(action.name, 0);
|
|
1159
|
+
}
|
|
1160
|
+
for (const [actionName, dependencies] of graph.entries()) {
|
|
1161
|
+
for (const depName of dependencies) {
|
|
1162
|
+
if (!actionMap.has(depName)) {
|
|
1163
|
+
throw new Error(`Action "${actionName}" in job "${job.name}" has an invalid dependency on "${depName}", which does not exist.`);
|
|
1164
|
+
}
|
|
1165
|
+
inDegree.set(actionName, (inDegree.get(actionName) ?? 0) + 1);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
const queue = Array.from(inDegree.entries())
|
|
1169
|
+
.filter(([, degree]) => degree === 0)
|
|
1170
|
+
.map(([name]) => name);
|
|
1171
|
+
while (queue.length > 0) {
|
|
1172
|
+
const currentName = queue.shift();
|
|
1173
|
+
sorted.push(currentName);
|
|
1174
|
+
for (const [actionName, dependencies] of graph.entries()) {
|
|
1175
|
+
if (dependencies.has(currentName)) {
|
|
1176
|
+
const newDegree = (inDegree.get(actionName) ?? 1) - 1;
|
|
1177
|
+
inDegree.set(actionName, newDegree);
|
|
1178
|
+
if (newDegree === 0) {
|
|
1179
|
+
queue.push(actionName);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
if (sorted.length !== job.actions.length) {
|
|
1185
|
+
throw new Error(`Circular dependency detected among actions in job "${job.name}".`);
|
|
1186
|
+
}
|
|
1187
|
+
return sorted;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
exports.ExecutionEngine = ExecutionEngine;
|
|
1191
|
+
//# sourceMappingURL=engine.js.map
|