PR C: wire real NotaryRegistry on Chain 138 (arch step 4) #7
Reference in New Issue
Block a user
Delete Branch "devin/1776875569-notary-chain-wiring"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements step 4 from the architecture gap-analysis — the ledger-anchor layer (arch §4.5 + §5.7) stops being a mock and starts writing to the deployed
NotaryRegistryon Chain 138. Independent of PRs A/B; can land in any order.What lands
services/notaryChain.ts(new)ethers-v6 adapter. Minimal ABI (two functions, two events, one view) lifted from
contracts/interfaces/INotaryRegistry.sol:registerPlan(bytes32 planId, Step[] steps, address creator)finalizePlan(bytes32 planId, bool success)getPlan(bytes32)GET /api/plans/:id/proof(wired later)Public surface:
anchorPlan(plan)→{ mode: 'chain'|'mock', txHash?, planHash, blockNumber?, contractAddress? }finalizeAnchor(planId, success)→{ mode, txHash?, receiptHash?, blockNumber? }computePlanHash(plan)andplanIdToBytes32(planId)— deterministic helpers so the mock and chain paths publish identical hashes for identical inputs.A singleton contract/wallet is cached after first use, keyed on
contractAddress, and can be reset via__resetForTests().Graceful mock fallback
If any of
CHAIN_138_RPC_URL,NOTARY_REGISTRY_ADDRESS,ORCHESTRATOR_PRIVATE_KEYis unset, both functions returnmode: 'mock'and log the reason. Unit tests, CI, and local dev require no extra wiring.services/notary.ts(refactored)Still the single entry point for
ExecutionCoordinator; now delegates tonotaryChainand surfaces the extra on-chain fields (mode,txHash,blockNumber,contractAddress,receiptHash) to callers. If the chain call throws, we log + fall back to mock so a momentary RPC outage cannot take the workflow down.config/env.tsAll four regex-validated. Missing envs do not fail startup.
Tests
tests/unit/notaryChain.test.ts— 6 cases:planIdToBytes32determinism + collision-resistance,computePlanHashdeterminism, and the three mock-fallback paths (empty config, partial config, finalizeAnchor).Verification
Not in this PR
registerPlanis called with an emptyStep[]for now. PR E (SWIFT gateway) introduces stable step IDs, after which we can serialise the real steps.getNotaryProofstill returns a deterministic mock — the on-chain read will be wired in PR D alongside the events table (so a single query reconstructs{ onChainProof, eventTrail }).Series order
A → B → C → D → E → F → G → H.
- services/notaryChain.ts: new ethers-v6 adapter speaking to the deployed NotaryRegistry.sol via CHAIN_138_RPC_URL + NOTARY_REGISTRY_ADDRESS + ORCHESTRATOR_PRIVATE_KEY. Exposes anchorPlan(plan) -> { mode, txHash, planHash, blockNumber } and finalizeAnchor(planId, success) -> { mode, txHash, receiptHash } with deterministic mock fallback when envs are absent. - services/notary.ts: refactored to delegate to notaryChain; preserves the prior signature and returns extra on-chain fields (mode, txHash, blockNumber, contractAddress) when the anchor lands. - config/env.ts: add CHAIN_138_RPC_URL, CHAIN_138_CHAIN_ID, NOTARY_REGISTRY_ADDRESS, ORCHESTRATOR_PRIVATE_KEY (all optional, validated via regex where applicable). - package.json: add ethers@^6.11.0 dependency. - tests/unit/notaryChain.test.ts: 6 tests covering deterministic hashing helpers and the mock fallback path. tsc clean. 51 tests pass (45 pre-existing + 6 new).