-
-
Save denniswon/fffb80a5fb4647abcfbdf1ecbe3dd7ad to your computer and use it in GitHub Desktop.
| Now I have the full picture. Here's the deep analysis: | |
| The Architecture Problem | |
| The commenter is pointing at a fundamental tension in the PRD's design. Let me map it out: | |
| Current PRD Architecture (per-account policy storage) | |
| Developer deploys PolicyClient contract (once) | |
| └── Per user account: | |
| ├── Install ownable validator (2-of-2) | |
| ├── Install Policy Client fallback module | |
| └── Call setPolicy() on the account's fallback module ← N×M transactions | |
| The NewtonPolicyClient mixin (line 44-48) stores policy state per-contract in ERC-7201 namespaced storage: | |
| struct NewtonPolicyClientStorage { | |
| INewtonProverTaskManager policyTaskManager; | |
| address policy; // pointer to NewtonPolicy contract | |
| bytes32 policyId; // which policy config within that contract | |
| address policyClientOwner; | |
| } | |
| If the fallback module is per-account, each account has its own copy of this storage. Changing policyId or policy address = one transaction per account per chain. | |
| What Newton Already Has (singleton pattern) | |
| Newton's existing architecture already solves this for the current AVS use case: | |
| 1. NewtonPolicy contract — Singleton deployed by the developer via NewtonPolicyFactory. Stores policy configs keyed by policyId. One contract, many configs. | |
| 2. NewtonPolicyClient mixin — Each developer deploys ONE policy client contract. It stores a pointer to the NewtonPolicy contract and a policyId. When the developer calls setPolicy(policyConfig), it updates the config on the NewtonPolicy | |
| contract and gets back a new policyId — one transaction, affects all tasks that reference this policy client. | |
| 3. PolicyClientRegistry — Directory of active policy clients, keyed by address. Used by IdentityRegistry to validate linkages. | |
| 4. TaskManager validation — _getPolicyState() reads the policy from the policy client address at validation time, not from per-account storage. The policy client is passed as task.policyClient in the Task struct. | |
| The Key Insight | |
| The commenter's concern is valid only if the ERC-7579 fallback module duplicates policy storage per-account. But it doesn't have to. | |
| There are three architectures worth considering: | |
| --- | |
| Option A: Shared Policy Client Contract (simplest, Newton-native) | |
| The developer deploys one NewtonPolicyClient contract (already the existing pattern). The ERC-7579 fallback module on each account just stores a pointer to this shared contract — not the policy config itself. | |
| Developer's PolicyClient (singleton, on-chain) | |
| ├── policy: 0xNewtonPolicy | |
| ├── policyId: bytes32 | |
| └── policyClientOwner: developer | |
| User Account A ──→ fallback module stores: policyClient = 0xDevPolicyClient | |
| User Account B ──→ fallback module stores: policyClient = 0xDevPolicyClient | |
| User Account C ──→ (not yet created, will inherit on first use) | |
| Policy change: Developer calls setPolicy() on their single PolicyClient contract. One transaction. All accounts immediately reflect the new policy because the ownable validator calls isValidSignature() on the PolicyClient, which reads the | |
| current policy at validation time. | |
| Accounts not yet created: No problem — the policyClient address is a constructor/init parameter of the SDK. When the account is eventually created, it points to the already-configured PolicyClient. | |
| Cross-chain: The developer deploys one PolicyClient per chain (or uses a deterministic deploy like CREATE2 for the same address). Policy changes = M transactions (one per chain), not N×M. | |
| Option B: Registry Lookup (no per-account module state) | |
| The fallback module doesn't store policyClient at all. Instead, it resolves the policy client from PolicyClientRegistry at validation time, keyed by the developer's address (the account creator). | |
| PolicyClientRegistry (singleton) | |
| └── developer address → PolicyClient address | |
| User Account A ──→ fallback module stores: developer = 0xDev (or nothing, inferred from account creator) | |
| Pro: Zero per-account configuration. | |
| Con: Extra indirection at validation time (one more SLOAD). Also requires a reliable mapping from "account" to "developer" — which might not exist on-chain unless the SDK stores it. | |
| Option C: Hybrid (per-account override + default) | |
| Each account defaults to the developer's shared PolicyClient but can optionally override with a per-account policy. This supports tiered accounts (premium users get different policies). | |
| User Account A ──→ fallback module: policyClientOverride = address(0) → uses developer default | |
| User Account B ──→ fallback module: policyClientOverride = 0xCustomPolicy → custom | |
| --- | |
| My Recommendation | |
| Option A is the right answer for the PRD. It's the existing Newton pattern — the commenter's concern dissolves when you realize the fallback module only stores a pointer, not the policy config. The PRD should clarify: | |
| 1. The fallback module stores policyClientAddress (the developer's shared contract), not inline policy config | |
| 2. setPolicy() is called on the developer's PolicyClient contract, not on each user account | |
| 3. Policy changes are 1 transaction (same chain) or M transactions (M chains) — never N×M | |
| 4. The SDK's NewtonAccount.init({ policyClientAddress }) already reflects this — it's a per-developer init, not per-user | |
| The PRD's setPolicy section was confusing because it described the fallback module as "exposes setPolicy() and policy configuration storage" — implying per-account config storage. It should say "exposes INewtonPolicyClient interface, | |
| delegating to the developer's shared PolicyClient contract." | |
| --- | |
| Want me to reply to the comment with this analysis and update both the PRD doc and Notion page accordingly? |
Now I have comprehensive understanding of the Rhinestone SDK. Let me synthesize the findings against our PRD.
★ Insight ─────────────────────────────────────
The Rhinestone SDK is much more sophisticated than what our PRD's Newton Account SDK suggests. Key architectural differences:
- Rhinestone separates prepare/sign/submit — our PRD merges them into single calls like transfer(). Rhinestone's prepareTransaction → signTransaction → submitTransaction three-step flow is deliberate: it enables the client-side signing step
that EIP-712/Permit2 requires. - Rhinestone has SignatureMode constants — including SIG_MODE_ERC1271 — which is exactly how Newton's Policy Client co-signer would integrate. The infrastructure already exists.
- Account types are first-class — Safe, Nexus, Kernel, Startale, Passport, EOA — each with version configs. Our PRD treats this as an implementation detail.
─────────────────────────────────────────────────
PRD Gap Analysis: Newton Account SDK vs Rhinestone Reality
Critical Gaps
- Missing the Prepare/Sign/Submit Pipeline
The Rhinestone SDK uses a three-step pattern: prepareTransaction() → signTransaction() → submitTransaction(). Our PRD's account.transfer() merges all three, which won't work because:
- The user must sign EIP-712 typed data on the client side (Turnkey or wallet)
- The Newton attestation (step 2 of 2-of-2) requires a completed BLS evaluation, which is server-side
- These two signatures must be combined before submission
Our SDK needs either:
- A similar three-step flow, or
- An opinionated sendTransaction() that handles the orchestration internally (Rhinestone has this too — their sendTransaction wraps prepare+sign+submit)
- Account Type Configuration is Missing
Rhinestone supports 6 account types with version configs:
type AccountType = 'safe' | 'nexus' | 'kernel' | 'startale' | 'passport' | 'eoa'
Our PRD has createAccount() with no account type selection. The user needs to choose which ERC-7579 account implementation to use. Different account types have different module installation mechanics, signature formats, and EIP-7702
compatibility.
- Module Installation Flow Not Addressed
Rhinestone's SDK has explicit setup() and deploy() methods per chain that handle module installation. Our PRD's createAccount() implicitly installs the ownable validator + intent executor + policy client fallback module, but doesn't expose:
- isDeployed(chain) — check if account exists on a chain
- setup(chain) — install missing modules on existing accounts
- getValidators(chain) / getExecutors(chain) — introspect installed modules
- Intent Executor Module Must Be Installed
The Rhinestone docs state: "The Intent Executor module must be installed on ERC-7579 accounts before using Warp." This is the on-chain permission layer enabling the relayer to execute on the user's behalf. Our PRD mentions it in the
architecture diagram but doesn't address the installation UX — do we install it automatically during createAccount()? What if the user already has a smart account without it?
- Permit2 Flow is Completely Missing
Rhinestone intents require Permit2 approvals on the origin chain before signing. The SDK has dedicated helpers:
signPermit2Batch()
signPermit2Sequential()
checkERC20AllowanceDirect()
getPermit2Address()
Our PRD's convert() and transfer() don't mention Permit2 at all. Without it, cross-chain intents can't access the user's tokens for the solver to settle.
- Token Requirements / Approval Step Missing
Rhinestone's /intents/route response includes tokenRequirements — a per-chain map of approvals and wraps needed before the intent can be signed. Types:
- ApprovalRequired — ERC-20 approve to Permit2 contract
- WrapRequired — ETH → WETH conversion
Our PRD skips this entirely. The SDK needs to handle or surface these requirements.
- SignatureMode for EIP-1271 Co-Signing
Rhinestone has explicit signature modes including SIG_MODE_ERC1271 (value 1). This is how the ownable validator knows that the second signer is a contract (EIP-1271) rather than an EOA. Our PRD doesn't mention signature mode configuration at
all. Newton's Policy Client as EIP-1271 co-signer requires signatureMode: SIG_MODE_ERC1271 when configuring the intent.
- setupOps for Smart Account Initialization
The Rhinestone Account type includes setupOps — operations to execute during account creation (module installations). Our PRD needs to define what setupOps Newton generates (ownable validator init, policy client module install, intent executor
install).
Medium Gaps
- Portfolio Endpoint Mismatch
Rhinestone's portfolio is per-account via GET /accounts/{address}/portfolio with chain/token filters. Our PRD's account.balance() doesn't show chain filtering or locked/unlocked breakdown (Rhinestone tracks locked balances in resource locks).
- Gas Sponsorship Not Mapped to Newton
Rhinestone supports sponsorSettings: { gasSponsored, bridgeFeesSponsored, swapFeesSponsored }. Our PRD mentions "Gas abstraction: Users should not need native gas tokens" but doesn't map this to the Rhinestone sponsor settings or paymaster
configuration.
- EIP-7702 Delegation Flow
Rhinestone has signEip7702InitData() which returns the signed authorization tuple. Our PRD's upgradeEOA() needs to use this — it's not a simple API call, it requires the user to sign the authorization.
- Missing waitForExecution()
Rhinestone has waitForExecution(result, acceptsPreconfirmations) that polls for on-chain finality. Our PRD returns { status: 'completed' } synchronously from transfer(), which isn't realistic for cross-chain intents that take 2-5 seconds.
- destinationExecutions for Arbitrary Calldata
Rhinestone's intent model supports destinationExecutions: Execution[] where each execution has { to, value, data }. This is how contract interactions on the destination chain work. Our PRD added data: '0x' to transfer() but doesn't model
multi-execution intents (e.g., swap + deposit into vault in one intent).
Architecture Corrections
- The PRD's Ownable Validator 2-of-2 Needs Refinement
Looking at Rhinestone's getOwnableValidator():
function getOwnableValidator(threshold: number, owners: Address[]): Module {
return {
address: OWNABLE_VALIDATOR_ADDRESS, // 0x000000000013fdb5234e4e3162a810f54d9f7e98
initData: encodeAbiParameters(
[{ name: 'threshold', type: 'uint256' }, { name: 'owners', type: 'address[]' }],
[BigInt(threshold), owners.sort()],
),
...
}
}
The owners array takes addresses (both EOA and contract). For Newton's 2-of-2, it would be:
owners: [userEOAAddress, newtonPolicyClientAddress].sort()
threshold: 2
The ownable validator at 0x000000000013fdb5234e4e3162a810f54d9f7e98 already supports EIP-1271 for contract owners. No custom module is needed — this confirms the PRD's approach. But the PRD should reference this exact contract address and the
SDK's getOwnableValidator() helper.
- Same-Chain vs Cross-Chain Are Different Rhinestone Paths
Looking at the Rhinestone SDK structure:
- execution/utils.ts — cross-chain via orchestrator
- execution/singleChainOps.ts — same-chain execution (UserOps via bundler)
Our PRD mentions "Same-chain transfers skip Rhinestone entirely" in lessons.md, but the SDK interface doesn't distinguish between these paths. Rhinestone's SDK handles this internally based on routing — our SDK should too.
Summary: What Needs to Change in the PRD
┌──────────┬────────────────────────────────────────────┬───────────────────────────────────────────────────────────────┐
│ Priority │ Gap │ Action │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P0 │ Prepare/sign/submit pipeline missing │ Add three-step flow or document that sendTransaction wraps it │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P0 │ Permit2 approval flow not addressed │ Add token requirements step before intent submission │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P0 │ Account type selection missing │ Add account provider config (safe/nexus/kernel/eoa) │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P0 │ SignatureMode.ERC1271 not configured │ Document signature mode for Newton co-signer │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P1 │ Module installation UX missing │ Add setup(), isDeployed(), getValidators() │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P1 │ Intent Executor installation not addressed │ Document auto-install during account creation │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P1 │ waitForExecution() missing │ Add polling/callback for async intent completion │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P1 │ EIP-7702 needs user signature │ Fix upgradeEOA() to include signer param │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P2 │ Portfolio locked/unlocked breakdown │ Align with Rhinestone's portfolio model │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P2 │ Gas sponsorship config missing │ Map to Rhinestone sponsor settings │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P2 │ Multi-execution intents not modeled │ Support destinationExecutions[] │
├──────────┼────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
│ P2 │ setupOps for account init not defined │ Define Newton's module installation operations │
└──────────┴────────────────────────────────────────────┴───────────────────────────────────────────────────────────────┘
Want me to draft an updated SDK interface that addresses all P0 and P1 gaps?
✻ Baked for 4m 1s
⏺ Agent "Research Rhinestone contracts repos" completed
⏺ Agent "Research Rhinestone SDK repo" completed
⏺ Agent "Research Rhinestone intent docs" completed
⏺ All three research agents completed. The findings confirm and strengthen my analysis. Let me add the critical new insights from the agent results that I missed earlier.
Additional Critical Findings from Deep Research
From the Contracts Agent (On-Chain Architecture)
Newton's EIP-1271 co-signer approach is confirmed viable, but with an important nuance:
The OwnableValidator's CheckSignatures.recoverNSignatures uses Solady's SignatureCheckerLib, which automatically falls back to ERC-1271 for contract addresses. This means:
- For a 2-of-2 setup with [userEOA, newtonPolicyClient], the validator concatenates 2 signatures
- For the user's ECDSA signature: standard ecrecover
- For Newton's contract signature: calls isValidSignature(hash, signature) on the Policy Client contract
- The 130-byte concatenated format matters — Newton's "signature" portion must be ABI-encoded (Task, TaskResponse, SignatureData) that the Policy Client's isValidSignature can decode
The Intent Executor has permanent execution privileges — once installed, it can call executeFromExecutor on the smart account indefinitely. There's no time-bound or per-operation approval. All authorization happens at the signature level. This
is fine for Newton's use case but worth noting in the PRD's security section.
The atomic fill signer is centralized — $atomicFillSigner is a single Rhinestone-controlled ECDSA key. Newton cannot influence which fills are authorized unless integrated into Rhinestone's orchestrator pipeline. This confirms our Model C
approach (Newton wraps Rhinestone) is correct — we control policy evaluation before Rhinestone even sees the intent.
From the SDK Agent (Full API Surface)
Three signing flows exist, not one:
┌──────────────────────┬──────────────────────────────┬────────────────────────────────────────────────────────────────┐
│ Flow │ Use Case │ Method │
├──────────────────────┼──────────────────────────────┼────────────────────────────────────────────────────────────────┤
│ Intent (cross-chain) │ Cross-chain via orchestrator │ prepareTransaction → signTransaction → submitTransaction │
├──────────────────────┼──────────────────────────────┼────────────────────────────────────────────────────────────────┤
│ UserOp (same-chain) │ Same-chain via 4337 bundler │ prepareUserOperation → signUserOperation → submitUserOperation │
├──────────────────────┼──────────────────────────────┼────────────────────────────────────────────────────────────────┤
│ All-in-one │ Convenience wrapper │ sendTransaction / sendUserOperation │
└──────────────────────┴──────────────────────────────┴────────────────────────────────────────────────────────────────┘
Our PRD only has the all-in-one pattern. For a developer SDK, exposing the three-step flow is important for applications that need custom UI (e.g., showing the user what they're signing before they sign).
Session keys (Smart Sessions) have an intent-execution policy type at address 0xa09b47de6e510cbdc18b97e9239bedcb44fb4901. This is specifically designed for authorizing intent execution via session keys — relevant for our use case where
Turnkey-managed keys sign on behalf of users.
sendTransaction has a sponsored field that maps to Rhinestone's sponsor settings:
type Sponsorship = boolean | { gas: boolean, bridging: boolean, swaps: boolean }
From the Docs Agent (API Reference)
Never modify intentOp after receiving it from /intents/route — it contains an HMAC (serverSignature). Only append signatures. This is a critical integration constraint our PRD doesn't mention. The Newton gateway wrapping Rhinestone must pass
the intentOp through unmodified.
The quote must be refreshed immediately before signing — stale quotes cause expiry errors. Our SDK flow needs to handle this (no caching of quotes).
EOAs must handle Permit2 approvals manually; smart accounts get them via preClaimOps. Since our ERC-7579 accounts are smart accounts, Permit2 approvals are handled automatically — but we need to document this.
Updated Gap Summary (incorporating all three agents)
┌─────┬────────────────────────────────────────────────────────────────────────────────────────────┬──────────┬─────────────────┐
│ # │ Gap │ Severity │ Source │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 1 │ Prepare/sign/submit pipeline — SDK needs 3-step flow, not just sendTransaction │ P0 │ SDK agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 2 │ UserOp path for same-chain — separate from intent path │ P0 │ SDK agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 3 │ Account type selection (safe/nexus/kernel/eoa) with version configs │ P0 │ SDK agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 4 │ SignatureMode.ERC1271 must be configured for Newton co-signer │ P0 │ Contracts agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 5 │ Signature format: Newton's portion must be valid for SignatureCheckerLib ERC-1271 fallback │ P0 │ Contracts agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 6 │ intentOp must not be modified after quote (HMAC) — gateway must pass through │ P0 │ Docs agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 7 │ Quote refresh before signing — no caching │ P1 │ Docs agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 8 │ waitForExecution() with preconfirmation support │ P1 │ SDK agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 9 │ Token requirements (Permit2 approvals, ETH wraps) surfaced to developer │ P1 │ Docs agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 10 │ Module installation: setup(), isDeployed(), getValidators() │ P1 │ SDK agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 11 │ Intent Executor auto-installation during account creation │ P1 │ Contracts agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 12 │ Session key support with intent-execution policy for Turnkey keys │ P2 │ SDK agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 13 │ Gas sponsorship mapped to Rhinestone's sponsorSettings │ P2 │ Docs agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 14 │ Intent Executor has permanent privileges — note in security section │ P2 │ Contracts agent │
├─────┼────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ 15 │ Atomic fill signer is centralized Rhinestone key — note in risk section │ P2 │ Contracts agent │
└─────┴────────────────────────────────────────────────────────────────────────────────────────────┴──────────┴─────────────────┘
Want me to draft the updated SDK interface that addresses all P0 and P1 gaps?
Here's the full SDK interface review. I'll evaluate each method against Newton's actual on-chain architecture and the Rhinestone integration model.
SDK Interface Review
Purpose: Developer-level SDK initialization (one-time).
Issues:
uses, it belongs on the PolicyClient config, not the SDK init.
SDK should resolve it from PolicyClientRegistry by developer address.
Verdict: Needs gatewayUrl and apiKey. Consider making chains optional (auto-discover from gateway). policyClientAddress should support per-chain mapping.
Purpose: Deploy a new ERC-7579 smart account with Newton modules installed.
Issues:
Verdict: Needs gas payment strategy, clearer owner type, and return type definition.
Purpose: ERC-7702 delegation for existing EOA wallets.
Issues:
signer/wallet parameter.
Verdict: Needs a signer parameter. Should be clearly gated behind a phase flag or separate import.
Purpose: Cross-chain asset movement (bridge + optional swap).
Issues:
internally.
Verdict: Needs toChain (or explicit "unified balance" semantics), amount denomination docs, and slippage/deadline params.
Purpose: Unified balance across chains.
Issues:
accuracy.
Verdict: Needs data source clarity, token filter, and staleness metadata.
Purpose: Policy-gated transfer (potentially cross-chain).
Issues:
suggestion of executeIntent makes more sense as the underlying method, with transfer as sugar for the data: '0x' case.
Verdict: Consider exposing executeIntent as the general method with transfer as sugar. Clarify auto-routing, memo storage, ETH support, and attestation return type.
Purpose: Submit encrypted verifiable credential for KYC.
Issues:
newt_getPrivacyPublicKey).
Verdict: Needs explicit encryption handling, chain_id, dual-signature auth, and type alignment with Newton's identity domains.
Purpose: Check account's compliance status.
Issues:
Verdict: Needs data source, timestamp, and per-chain granularity.
Purpose: Audit trail and compliance reporting.
Issues:
that.
Verdict: PDF export should be deferred. Transaction queries need ISO date ranges and pagination.
Missing Methods
┌─────────────────────────────────────┬───────────────────────────────────────────────────────────────────┐
│ Method │ Why It's Needed │
├─────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ account.address / account.addresses │ Get the account address(es) per chain │
├─────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ account.isDeployed(chain?) │ Check if account is deployed on a given chain │
├─────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ newton.getPolicy() │ Read current policy config from the shared PolicyClient │
├─────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ newton.setPolicy(config) │ Update policy on the shared PolicyClient (developer admin action) │
├─────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ account.attestations({ taskId? }) │ Query attestation proofs for compliance evidence │
├─────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ account.revokeEOA() │ Revoke ERC-7702 delegation (set delegate to 0x0) │
└─────────────────────────────────────┴───────────────────────────────────────────────────────────────────┘
Summary
┌──────────────────────────┬─────────────────────────────────────────────────────────────────┬──────────┐
│ Method │ Issues │ Severity │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ init() │ Missing gatewayUrl, apiKey; policyClientAddress needs per-chain │ High │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ createAccount() │ Gas payment unclear, owner type ambiguous, no return type │ Medium │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ upgradeEOA() │ Missing signer param for authorization signing │ High │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ convert() │ Missing toChain, slippage, amount denomination │ Medium │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ balance() │ Missing data source, token filter, staleness │ Low │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ transfer() │ Conflates transfer + execution, unclear auto-routing │ Medium │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ submitCredential() │ Missing encryption, chain_id, dual-sig │ High │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ complianceStatus() │ Missing data source, timestamp │ Low │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ transactions() │ Needs ISO dates, pagination │ Low │
├──────────────────────────┼─────────────────────────────────────────────────────────────────┼──────────┤
│ exportComplianceReport() │ PDF generation is Phase 2+ │ Low │
└──────────────────────────┴─────────────────────────────────────────────────────────────────┴──────────┘
The highest-priority fixes are init() (missing gateway connection params), upgradeEOA() (missing signer), and submitCredential() (missing encryption flow that aligns with Newton's existing privacy API).
Want me to draft an updated SDK interface that addresses these issues?