Adds a headless end-to-end round-trip that spawns the ganache CLI as a child process, deploys NotaryRegistry.sol via in-process solc-js compilation, and exercises services/notaryChain.ts (anchorPlan + finalizeAnchor) against the real chain via ethers v6.
Closes gap-analysis v3 §7.9 / §8.5 — PR Q’s existing E2E covered Postgres only; this one covers the chain adapter boundary the orchestrator actually depends on.
Changes
contracts/NotaryRegistry.sol — add OZ v5 constructor(address initialOwner) Ownable(initialOwner) {} (required by OpenZeppelin v5; contract was written for v4 and would not compile otherwise).
orchestrator/src/services/notaryChain.ts:
Bug fix: Step tuple ABI shape was (uint8, address, uint256, bytes) — but IComboHandler.Step is (uint8, bytes, address, uint256). Different tuple order → different canonical signature → different function selector → every on-chain call silently reverted with no revert data. Corrected to match.
Disable JsonRpcProvider response cache (cacheTimeout: -1) so back-to-back anchor+finalize on fast chains no longer read a stale getTransactionCount and collide on nonce.
orchestrator/tests/e2e/helpers/compileNotaryRegistry.ts — in-process solc-js compilation with recursive import resolver (handles ./interfaces/*.sol + @openzeppelin/contracts/...), returns { abi, bytecode } ready for ContractFactory. Avoids any hardhat dependency.
orchestrator/tests/e2e/notaryChainRoundtrip.e2e.test.ts — gated on RUN_E2E=1; 3 tests:
anchorPlan writes a PlanRegistered record on-chain (verified via plans(bytes32) read).
finalizeAnchor writes a PlanFinalized record, emits the matching receipt hash.
anchorPlan falls back to mode: mock cleanly when envs are unset.
orchestrator/package.json — adds ganache@7.9.2, solc@0.8.20 to devDependencies.
Verification
npx tsc --noEmit clean.
npx jest unit suite: 10 suites / 128 tests — unchanged, all passing.
RUN_E2E=1 npx jest --config=jest.e2e.config.js tests/e2e/notaryChainRoundtrip.e2e.test.ts: 3 / 3 passing.
Notes
No UI changes. Entirely backend / test infrastructure.
Mock-fallback path for anchorPlan is preserved — production deployments without chain envs degrade gracefully.
Does not yet encode full plan steps into registerPlan — PR E’s SWIFT step IDs will land that separately.
## Summary
Adds a headless end-to-end round-trip that spawns the ganache CLI as a child process, deploys `NotaryRegistry.sol` via in-process `solc-js` compilation, and exercises `services/notaryChain.ts` (`anchorPlan` + `finalizeAnchor`) against the real chain via ethers v6.
Closes gap-analysis v3 §7.9 / §8.5 — PR Q’s existing E2E covered Postgres only; this one covers the chain adapter boundary the orchestrator actually depends on.
## Changes
- `contracts/NotaryRegistry.sol` — add OZ v5 `constructor(address initialOwner) Ownable(initialOwner) {}` (required by OpenZeppelin v5; contract was written for v4 and would not compile otherwise).
- `orchestrator/src/services/notaryChain.ts`:
- **Bug fix**: Step tuple ABI shape was `(uint8, address, uint256, bytes)` — but `IComboHandler.Step` is `(uint8, bytes, address, uint256)`. Different tuple order → different canonical signature → different function selector → every on-chain call silently reverted with no revert data. Corrected to match.
- Disable JsonRpcProvider response cache (`cacheTimeout: -1`) so back-to-back anchor+finalize on fast chains no longer read a stale `getTransactionCount` and collide on nonce.
- `orchestrator/tests/e2e/helpers/compileNotaryRegistry.ts` — in-process `solc-js` compilation with recursive import resolver (handles `./interfaces/*.sol` + `@openzeppelin/contracts/...`), returns `{ abi, bytecode }` ready for `ContractFactory`. Avoids any hardhat dependency.
- `orchestrator/tests/e2e/notaryChainRoundtrip.e2e.test.ts` — gated on `RUN_E2E=1`; 3 tests:
1. `anchorPlan` writes a `PlanRegistered` record on-chain (verified via `plans(bytes32)` read).
2. `finalizeAnchor` writes a `PlanFinalized` record, emits the matching receipt hash.
3. `anchorPlan` falls back to `mode: mock` cleanly when envs are unset.
- `orchestrator/package.json` — adds `ganache@7.9.2`, `solc@0.8.20` to devDependencies.
## Verification
- `npx tsc --noEmit` clean.
- `npx jest` unit suite: **10 suites / 128 tests** — unchanged, all passing.
- `RUN_E2E=1 npx jest --config=jest.e2e.config.js tests/e2e/notaryChainRoundtrip.e2e.test.ts`: **3 / 3 passing**.
## Notes
- No UI changes. Entirely backend / test infrastructure.
- Mock-fallback path for `anchorPlan` is preserved — production deployments without chain envs degrade gracefully.
- Does not yet encode full plan steps into `registerPlan` — PR E’s SWIFT step IDs will land that separately.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Adds a headless end-to-end round-trip that spawns the ganache CLI as a child process, deploys
NotaryRegistry.solvia in-processsolc-jscompilation, and exercisesservices/notaryChain.ts(anchorPlan+finalizeAnchor) against the real chain via ethers v6.Closes gap-analysis v3 §7.9 / §8.5 — PR Q’s existing E2E covered Postgres only; this one covers the chain adapter boundary the orchestrator actually depends on.
Changes
contracts/NotaryRegistry.sol— add OZ v5constructor(address initialOwner) Ownable(initialOwner) {}(required by OpenZeppelin v5; contract was written for v4 and would not compile otherwise).orchestrator/src/services/notaryChain.ts:(uint8, address, uint256, bytes)— butIComboHandler.Stepis(uint8, bytes, address, uint256). Different tuple order → different canonical signature → different function selector → every on-chain call silently reverted with no revert data. Corrected to match.cacheTimeout: -1) so back-to-back anchor+finalize on fast chains no longer read a stalegetTransactionCountand collide on nonce.orchestrator/tests/e2e/helpers/compileNotaryRegistry.ts— in-processsolc-jscompilation with recursive import resolver (handles./interfaces/*.sol+@openzeppelin/contracts/...), returns{ abi, bytecode }ready forContractFactory. Avoids any hardhat dependency.orchestrator/tests/e2e/notaryChainRoundtrip.e2e.test.ts— gated onRUN_E2E=1; 3 tests:anchorPlanwrites aPlanRegisteredrecord on-chain (verified viaplans(bytes32)read).finalizeAnchorwrites aPlanFinalizedrecord, emits the matching receipt hash.anchorPlanfalls back tomode: mockcleanly when envs are unset.orchestrator/package.json— addsganache@7.9.2,solc@0.8.20to devDependencies.Verification
npx tsc --noEmitclean.npx jestunit suite: 10 suites / 128 tests — unchanged, all passing.RUN_E2E=1 npx jest --config=jest.e2e.config.js tests/e2e/notaryChainRoundtrip.e2e.test.ts: 3 / 3 passing.Notes
anchorPlanis preserved — production deployments without chain envs degrade gracefully.registerPlan— PR E’s SWIFT step IDs will land that separately.