Skip to content

Instantly share code, notes, and snippets.

@denniswon
Created April 6, 2026 15:16
Show Gist options
  • Select an option

  • Save denniswon/d3bd9cebaa01f935c7eb8e8f251394c3 to your computer and use it in GitHub Desktop.

Select an option

Save denniswon/d3bd9cebaa01f935c7eb8e8f251394c3 to your computer and use it in GitHub Desktop.
Proposed newton-warp Structure
★ Insight ─────────────────────────────────────
Separation of concerns: newton-prover-avs is the consensus infrastructure (operators, BLS aggregation, slashing, ZK proofs).
newton-warp is the chain abstraction + compliance layer — the bridge between smart accounts and Newton's policy engine via Rhinestone
Warp. These are fundamentally different domains with different deployment lifecycles, dependencies, and audiences.
Why monorepo: The Rust backend service (intent routing, Rhinestone orchestrator client) and the TypeScript SDK (newton-account-sdk)
must stay in lockstep — API changes in the backend require SDK updates. Colocating them enables atomic PRs, shared CI, and type
consistency.
─────────────────────────────────────────────────
Proposed newton-warp Structure
newton-warp/
├── bin/ # Binary entry points (Rust)
│ ├── newton-warp-gateway/ # Intent routing service (Axum, like newton-prover-avs gateway)
│ │ └── src/main.rs
│ └── deploy/ # Docker configs
│ ├── docker-compose.yml
│ └── docker-compose.rhinestone-mockestrator.yml
├── crates/ # Rust libraries
│ ├── cross-chain-intent/ # Rhinestone orchestrator HTTP client (from PR #485)
│ │ └── src/
│ │ ├── client.rs # CrossChainIntentClient trait
│ │ ├── rhinestone.rs # RhinestoneClient (real HTTP impl)
│ │ ├── service.rs # CrossChainIntentService (retries, backoff)
│ │ ├── mock.rs # MockClient for tests
│ │ ├── types.rs
│ │ └── error.rs
│ ├── warp-gateway/ # Gateway service logic (config, routing, RPC handlers)
│ │ └── src/
│ │ ├── config.rs # WarpGatewayConfig
│ │ ├── handler.rs # RPC handlers (newt_createCrossChainIntent, etc.)
│ │ ├── rpc/ # JSON-RPC API surface
│ │ └── lib.rs
│ └── core/ # Shared types (intent types, chain definitions)
│ └── src/
├── packages/ # TypeScript packages (pnpm workspace)
│ └── account-sdk/ # @magicnewton/newton-account-sdk (from newton-account-sdk repo)
│ ├── src/
│ │ ├── modules/
│ │ │ ├── avs/ # Newton AVS task submission
│ │ │ ├── identity/ # Identity registry interactions
│ │ │ ├── policy/ # Policy contract reads/writes
│ │ │ └── warp/ # NEW: cross-chain intent (route, sign, submit, poll)
│ │ ├── abis/
│ │ ├── types/
│ │ └── utils/
│ ├── package.json
│ ├── tsconfig.json
│ └── vitest.config.ts
├── contracts/ # Solidity (if needed for account modules)
│ ├── src/
│ └── lib/
├── integration-tests/ # E2E tests (Rust)
│ └── tests/
│ └── cross_chain_intent.rs
├── docs/
│ ├── ARCHITECTURE.md
│ ├── RHINESTONE_INTEGRATION.md
│ └── LOCAL_DEVELOPMENT.md
├── Cargo.toml # Rust workspace root
├── package.json # pnpm workspace root
├── pnpm-workspace.yaml
├── Makefile
├── CLAUDE.md
├── .github/
│ └── workflows/
└── .claude/
└── rules/
Key design decisions:
1. bin/newton-warp-gateway/ — standalone Axum service (like newton-prover-avs gateway), not a sidecar. Handles the
newt_createCrossChainIntent RPC endpoint, Rhinestone orchestration, and Newton attestation integration. Communicates with
newton-prover-avs gateway via JSON-RPC for policy evaluation + BLS attestation.
2. crates/cross-chain-intent/ — lifted directly from PR #485. Pure HTTP client with no AVS dependencies. The warp-gateway crate
consumes it.
3. packages/account-sdk/ — migrated from newton-account-sdk repo. Gets a new modules/warp/ for the TypeScript client-side cross-chain
intent flow (route → sign → submit → poll). Continues to use @magicnewton/newton-protocol-sdk (newton-sdk) as a peer dependency for
the core AVS/policy/identity interactions.
4. newton-prover-avs stays clean — PR #485 changes to the gateway (CrossChainIntentConfig, cross_chain_intent field on
GatewayServiceImpl) get reverted. The AVS gateway doesn't need to know about Rhinestone. Instead, newton-warp-gateway calls the AVS
gateway's existing RPC endpoints.
Dependency flow:
newton-warp-gateway
├── crates/cross-chain-intent (Rhinestone HTTP client)
├── crates/core (shared intent types)
└── newton-prover-avs gateway (via JSON-RPC, for attestation)
@magicnewton/newton-account-sdk
├── modules/warp (cross-chain intent TS client)
├── modules/avs (task submission to newton-prover-avs)
└── @magicnewton/newton-protocol-sdk (peer dep, core protocol types)
What happens to PR #485:
- Close PR #485 on newton-prover-avs
- Port the crates/cross-chain-intent/ code and integration tests to newton-warp
- Revert the gateway config/handler changes (the cross_chain_intent field on GatewayServiceImpl)
- The CI/docker compose for mockestrator moves to newton-warp
Open questions for you:
1. Warp gateway ↔ AVS gateway communication: The warp gateway needs Newton attestations for compliance. Should it call the AVS
gateway's newt_createTask / newt_evaluateIntentDirect RPC, or should there be a shared crate for direct attestation generation?
2. Contracts: Do you anticipate any Solidity contracts specific to the chain abstraction layer (e.g., custom ERC-7579 modules, Mandate
validators), or will it purely use the existing NewtonProverTaskManager + Rhinestone's contracts?
3. Should I scaffold the repo now, or do you want to refine the structure first?
@denniswon

Copy link
Copy Markdown
Author

⏺ Everything compiles and passes formatting. Let me also update the Justfile to add a forge install step for setup.

Read 1 file (ctrl+o to expand)

⏺ Update(~/projects/newton-warp/Justfile)
⎿  Added 7 lines
4 set dotenv-load
5 set shell := ["bash", "-euo", "pipefail", "-c"]
6
7 +# ─── Setup ────────────────────────────────────────────
8 +
9 +# Install all dependencies (Foundry submodules + Node packages)
10 +install:
11 + cd contracts && forge install
12 + cd packages/sdk && pnpm install
13 +
14 # ─── Build ────────────────────────────────────────────
15
16 # Build everything (Rust workspace + TypeScript SDK)

⏺ ★ Insight ─────────────────────────────────────

  • Foundry contracts scaffold: Two contracts matching the architecture doc — EIP1271AttestationSigValidator (the EIP-1271 co-signer for
    2-of-2 ownable validator) and ClientPermissionRouter (per-client policy routing). Both are TODO stubs for the implementation PRs.
  • Git submodules, not --no-git: Using git submodule add instead of forge install --no-git ensures the submodule references are tracked
    in .gitmodules and survive git clone --recursive. The nested eigenlayer-middleware pulls in OpenZeppelin, eigenlayer-contracts, and
    their own forge-std — all transitively available via the remappings in foundry.toml.
  • forge build compiles 23 files: Even with two stub contracts, the build pulls in forge-std's Test.sol and its dependency chain. The
    sparse_mode = true setting in foundry.toml ensures only referenced files are compiled in CI.
    ─────────────────────────────────────────────────

Here's what was set up for contracts/:

┌───────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────┐
│ File │ Purpose │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ foundry.toml │ Foundry config — Solc 0.8.27, via-ir, optimizer, remappings for eigenlayer + │
│ │ openzeppelin + forge-std │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ .gitignore │ Ignores cache/, out/, broadcast/, local anvil deployment files │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ src/EIP1271AttestationSigValidator.sol │ Scaffold for the EIP-1271 co-signer (validates BLS attestations via TaskManager) │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ src/ClientPermissionRouter.sol │ Scaffold for per-client policy routing │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ test/EIP1271AttestationSigValidator.t.sol │ Test scaffold │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ test/ClientPermissionRouter.t.sol │ Test scaffold │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ script/.gitkeep │ Placeholder for deployment scripts │
├───────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
│ .gitmodules │ forge-std + eigenlayer-middleware (with transitive OpenZeppelin + │
│ │ eigenlayer-contracts) │
└───────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────┘

Build verified: forge build compiles cleanly, forge fmt --check passes.

Is there anything else you want scaffolded before the initial commit?

✻ Cooked for 41s

⏺ Background command "Initialize nested submodules" completed (exit code 0)

⏺ Good — the nested submodule init also completed successfully. Everything is in place.

Waiting on you — anything else to scaffold before the initial commit?

❯ how should we solve newton-warp/contracts dependencies newton-prover-avs/contracts? (contract addresses for stagef vs prod for
different chain ids, abis, source etc.) gitsubmodules? or manual cross-repo sync step (newton-warp pulling from newton-prover-avs)? how
can we achieve this when newton-prover-avs is a private repo (but within the same newt-foundation github org)

⏺ Good question. There are three things Warp needs from newton-prover-avs:

┌──────────────────────┬───────────────────────────────────────────────────────────────────────────────┬────────────────────────┐
│ Need │ Examples │ Frequency of Change │
├──────────────────────┼───────────────────────────────────────────────────────────────────────────────┼────────────────────────┤
│ Solidity interfaces │ INewtonPolicyClient, INewtonProverTaskManager (for validateAttestationDirect) │ Rare (API stable) │
├──────────────────────┼───────────────────────────────────────────────────────────────────────────────┼────────────────────────┤
│ Deployment addresses │ TaskManager, PolicyClientRegistry per chain/env │ Every AVS deploy │
├──────────────────────┼───────────────────────────────────────────────────────────────────────────────┼────────────────────────┤
│ ABIs │ For the TypeScript SDK to call Newton contracts │ When interfaces change │
└──────────────────────┴───────────────────────────────────────────────────────────────────────────────┴────────────────────────┘

Here are the realistic options:

Option A: Git submodule (newton-prover-avs)

contracts/lib/newton-prover-avs/ # full repo as submodule

Forge remapping: @newton-avs/=lib/newton-prover-avs/contracts/src/

Pros: Zero sync machinery, forge resolves imports natively, version-pinned to a commit, works within same GitHub org via SSH deploy
keys in CI.

Cons: The AVS repo is large (ZK circuits, Rust crates, docs). You'd pull ~100MB+ of unrelated code just for a handful of interfaces.
CI clone time increases. Every git clone --recursive is slower.

Private repo access: Add a deploy key (read-only) for newton-prover-avs in the newton-warp CI secrets. SSH URLs in .gitmodules:
url = git@github.com:newt-foundation/newton-prover-avs.git

Option B: Interfaces-only package (new repo)

Extract INewtonPolicyClient, INewtonProverTaskManager, INewtonPolicyData, and shared structs into
newt-foundation/newton-protocol-interfaces — a lightweight repo (~20 files) that can even be public.

contracts/lib/newton-protocol-interfaces/ # tiny submodule

Pros: Clean boundary, fast CI, can be made public (interfaces aren't secret), usable by any future Newton integration (not just Warp).

Cons: Another repo to maintain. When an AVS interface changes, you need to update the interfaces repo first, then bump the submodule
in Warp. Extra step in the release workflow.

Option C: Copy interfaces + maintain deployment config locally

Copy the ~5-10 interface files into contracts/src/interfaces/ directly. No submodule.

Pros: Simplest. No cross-repo machinery. No CI auth issues. Works immediately.

Cons: Manual sync when interfaces change. Risk of staleness. But interfaces are stable — they change rarely.

Deployment Addresses (orthogonal to all three)

Regardless of which option handles Solidity interfaces, deployment addresses should not come from a submodule (they'd be stale the
moment the submodule is pinned). Instead:

Warp maintains its own config files with Newton AVS addresses per chain/env:

contracts/config/newton-avs.stagef.json # { "11155111": { "taskManager": "0x...", ... } }
contracts/config/newton-avs.prod.json

Updated manually after AVS deploys, or automated via a CI step in the AVS deploy pipeline that opens a PR on newton-warp with updated
addresses.

My recommendation

Option B long-term, Option C for now.

For scaffolding, copy the interfaces directly — it's 5-10 .sol files. No submodule auth to configure, no new repo to create, no CI
complexity. Once the contract interfaces stabilize and more consumers exist (e.g., third-party integrators), extract into
newton-protocol-interfaces.

For deployment addresses, start with local config files in contracts/config/. Add a CI sync step later when the deploy cadence
warrants it.

What's your preference?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment