Skip to content

refactor(offchain): adapt clients to permissionless settle()#11

Open
grimnote wants to merge 6 commits into
redesign/drop-operator-stakingfrom
redesign/offchain-permissionless-settle
Open

refactor(offchain): adapt clients to permissionless settle()#11
grimnote wants to merge 6 commits into
redesign/drop-operator-stakingfrom
redesign/offchain-permissionless-settle

Conversation

@grimnote

Copy link
Copy Markdown
Contributor

What

PR 2 of the lightweight redesign: adapt the off-chain clients to the permissionless on-chain settlement from #10. Everywhere a client did OperatorRegistry.claimTask()TaskExecutor.executeTask(), it now calls CCTPV2EscrowReceiver.settle(message, attestation) directly. No claim, no registry, no executor, no fees, no staking.

Stacked on redesign/drop-operator-staking (#10). Retarget to main once that merges.

Changes by package

  • operator (NestJS) — replace the claim+execute path with a MessageRelayPort.settle() call; delete EthersTaskExecutorAdapter + TaskExecutorPort; remove the operator-status startup check; collapse inbound/outbound through the relay port. The job claiming state is left unused (kept to preserve the passing entity/repository specs).
  • operator-cli — delete register/stake/unbond/withdraw/status commands and their ABIs; rewire relay to settle() with the real CCTPV2EscrowReceiver ABI; reframe as a dev/debug/deploy tool (adds a reineira bin alias).
  • offchain-shared — drop OperatorInfo/TaskClaim/OperatorStatus types and the registry/executor/fee/handler addresses; keep ESCROW_RECEIVER + CCTP constants.
  • sdk — clean break (major bump): remove OPERATOR_REGISTRY_ABI/TASK_EXECUTOR_ABI, the four dead NetworkAddresses fields, and CCTP_RELAY_TASK_TYPE; fix test stubs. coordinatorUrl/relayTaskId retained (coordinator kept).
  • coordinator — no code change: its round-robin SSE inbox has no deleted-contract deps and is the lightweight, scalable dedup seam (per the agreed "thin burn-inbox" decision).
  • docs — offchain/operator/cli READMEs rewritten off staking/claim and onto permissionless settle().

Decisions applied

  • Coordinator → thin burn-inbox (kept; round-robin retained as the scale seam).
  • SDK → clean break (dead public surface removed; major version).
  • CLI → dev/debug/deploy tool (relay kept and rewired; staking commands gone).

Verification

  • tsc/tsup build: shared, operator, operator-cli, coordinator, sdk all green.
  • operator jest — 138 passed (incl. rewired service spec). sdk vitest — 78 passed.
  • Prettier-clean on touched docs.
  • Not verified here (no live infra): a real CCTP settle() end-to-end against Circle Iris + funded testnet wallets. Unit-verified, not E2E-verified.

🤖 Generated with Claude Code

grimnote and others added 3 commits June 27, 2026 15:11
…utor

Replace the OperatorRegistry claim + TaskExecutor.executeTask path with a direct
MessageRelayPort.settle(message, attestation) call to CCTPV2EscrowReceiver. Delete
the EthersTaskExecutorAdapter and TaskExecutorPort; add settle() + getOperatorAddress()
to the message-relay port/adapter; remove the operator-status startup check. The
job-entity 'claiming' state becomes unused (kept to preserve passing entity/repository
specs). Inbound and outbound both flow through the message-relay port.

operator: tsc clean; jest 138 passed (9 suites).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- operator-cli: delete register/stake/unbond/withdraw/status commands and their
  ABIs; rewire `relay` to call CCTPV2EscrowReceiver.settle(message, attestation);
  add real receiver ABI; reframe CLI as dev/debug/deploy tool.
- offchain-shared: drop OperatorInfo/TaskClaim/OperatorStatus types and the
  registry/executor/fee/handler addresses; keep ESCROW_RECEIVER + CCTP consts.
- sdk: clean break — remove OPERATOR_REGISTRY_ABI/TASK_EXECUTOR_ABI, the four dead
  NetworkAddresses fields, and CCTP_RELAY_TASK_TYPE; fix test stubs. coordinatorUrl
  and relayTaskId retained (coordinator kept as thin inbox).
- coordinator: no code change — round-robin SSE inbox has no deleted-contract deps
  and is the scalable dedup seam.

Builds: shared/cli/coordinator tsc clean; sdk tsup + 78 vitest passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update offchain README, operator README, operator-cli README: replace
operator-economics/staking/claim content with the permissionless settle() flow;
swap deployed-contract tables to the escrow receiver; fix mermaids and env vars.
Add `reineira` bin alias and reframe the CLI as a dev/debug/deploy tool.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
grimnote and others added 3 commits June 27, 2026 16:59
Real bugs:
- Refresh operator + operator-cli .env.example: drop deleted OperatorRegistry/
  TaskExecutor/FeeManager/CCTPHandler/staking vars; add ESCROW_RECEIVER_ADDRESS
  and ESCROW_CHAIN_ID (a copied template now boots a working relayer).
- sse-coordinator-client: derive the subscription address from PRIVATE_KEY instead
  of requiring the now-undocumented OPERATOR_ADDRESS (kept as optional override).

Cleanup (remove vestigial 'claiming' state):
- Drop 'claiming' from RelayJobStatus, the DTO, getJobStatus(), and delete
  startClaiming()/startExecuting(); retries go pending_retry -> executing via
  startRetry(). Remove the dead 'insufficient stake' non-retryable error.
  Rewrite the entity + repository specs accordingly.

Hardening:
- Fail loud at startup when PRIVATE_KEY / ESCROW_RECEIVER_ADDRESS are unset.
- getOperatorAddress() no longer throws on a malformed key (warns, returns '').
- Validate ESCROW_CHAIN_ID is numeric (NaN -> default).
- Null-guard tx.wait() in relayMessage()/settle() (fall back to tx.hash).
- Fix relay.ts EscrowSettled event comment to match ABI param names.

operator: tsc clean; jest 133 passed. cli build clean. prettier clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From the PR #10 review (cross-checked against this branch):
- offchain/README: remove the dead @reineira-os/orchestration related-repo link
  (the receiver lives in @reineira-os/escrow now).
- sdk: remove the stale governanceToken field/address (the GOV staking token of
  the deleted OperatorRegistry); unused by any SDK module.

sdk: tsup build + 78 vitest passed. prettier clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From the combined review of both PRs:
- ethers-message-relay: the RPC_URL fallback in getChainConfig leaked into
  outbound relayMessage(), silently routing a relay to an unconfigured chain
  onto the escrow RPC. Seed RPC_URL as the escrow chain's entry instead and drop
  the blanket fallback, so outbound relays to unknown chains fail loudly. Cache
  escrowChainId / receiver / transmitter / operatorAddress in the constructor
  (was re-reading config per settle()).
- operator.service.executeJob: retries now route by taskType — outbound jobs
  relay to the destination, others settle — instead of always calling settle().
- Extract addressFromPrivateKey into a shared wallet.util used by both the
  relay and SSE adapters (was duplicated).
- shared: drop unused TaskResult type and the dead AUTOMATION/AGENT_CALL task hashes.
- coordinator README: replace the deleted OperatorRegistry.selectOperator() future-
  work item with relayer dedup.

operator: tsc clean; jest 133 passed. shared/cli build clean. prettier clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant