Skip to content

feat(cli)!: migrate to Sequence V3 OMSClient (email-login embedded wallet)#120

Closed
AkshatGada wants to merge 21 commits into
mainfrom
feat/oms-v3-wallet-migration
Closed

feat(cli)!: migrate to Sequence V3 OMSClient (email-login embedded wallet)#120
AkshatGada wants to merge 21 commits into
mainfrom
feat/oms-v3-wallet-migration

Conversation

@AkshatGada

@AkshatGada AkshatGada commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Overview

  • Migrates the CLI wallet onto Sequence's V3 embedded wallet (OMS); OMSClient is now the only path.
  • Login is a single Google browser flow. Email OTP login is removed.
  • After login the CLI checks your balance and routes you automatically: empty wallet goes to a funding page, funded wallet goes to the dashboard.
  • New --remote flag logs in on headless/remote hosts by routing through a self-hosted OIDC relay, so the browser and CLI don't have to be on the same machine.
  • Adds two small Cloudflare Workers: the OIDC relay, and agentconnect-ui (the hosted funding + dashboard page that replaces the retired connector-ui on the same domain).
  • Deletes the old connector-ui and shared packages now that OMS V3 is the only path.

Phase 1 + core Phase 2 of the migration from @0xsequence/dapp-client
(delegated browser-approved sessions) to @0xsequence/typescript-sdk
(OMSClient embedded wallet, email login). Additive and flag-gated —
the legacy path is unchanged and remains the default.

New:
- lib/oms-storage.ts: encrypted file-backed StorageManager + persisted
  EthereumPrivateKeyCredentialSigner key (survives process restarts).
- lib/oms-client.ts: getOmsClient(walletName) singleton.
- lib/oms-tx.ts: runOmsTx — drop-in for runDappClientTx; maps the
  {to,data,value}[] interface onto oms.wallet.sendTransaction with ported
  fee selection (prefer native or USDC, gated on availableRaw).
- lib/tx-dispatch.ts: runTx routes to OMS when POLYGON_AGENT_OMS is set.
- wallet login (email OTP) + wallet logout; list/address handle OMS pointers.

Changed:
- storage.ts: export GCM helpers; add OmsConfig/OmsWalletPointer + helpers
  and bootstrapOmsConfig.
- All 17 runDappClientTx call sites now import runTx via the dispatch shim.
- utils.ts: getReadRpcUrl with public-RPC fallback (OMS has no nodes access key).
- x402-pay receipt poll uses getReadRpcUrl instead of session.projectAccessKey.

Verified end-to-end on Polygon mainnet: email login -> persisted session ->
call with POLYGON_AGENT_OMS=1 -> on-chain USDC transfer
(tx 0xb5e35f2f74fcdb75ccd453e23af4e0d3a88f60e383f00fb2e0e43cbf41613ba1).
… only path

Completes the migration from the dapp-client delegated-session model
(browser approval + relay + on-chain Sapient permission scoping) to the
Sequence V3 OMSClient embedded-wallet model. OMS is now the only path.

Removed:
- packages/connector-ui (browser approval UI) + its deploy workflow
- packages/shared (x25519/xchacha20 relay session crypto)
- src/lib/dapp-client.ts, src/lib/relay-client.ts
- wallet create/import (+ WalletCreateUI), AUTO_WHITELISTED_CONTRACTS,
  spending-limit / --contract scoping flags, relay storage helpers,
  bootstrapAccessKey, SequenceIndexer usage
- 12 legacy @0xsequence/* + tweetnacl deps (pnpm: +95 -894 packages)

Changed:
- balances + balances Ink UI now read via oms.indexer (publishableKey auth);
  no more projectAccessKey
- withdraw/x402 receipt polling uses getReadRpcUrl (public-RPC fallback)
- all tx commands resolve wallets via loadOmsWalletPointer; chain defaults
  to polygon (OMS wallets are chain-agnostic)
- tx-dispatch.runTx now wraps runOmsTx unconditionally
- CLAUDE.md updated for the OMS-only structure

Verified live on Polygon mainnet with no env flag: wallet login, balances
via oms.indexer, and a USDC transfer via `call`
(tx 0x1c7ff1df746bacab7930dc24ada694fa9061976164871ad3fb6bf3940eec2bdc).
Remove all references to the removed wallet create / browser approval /
--contract scoping / connector-ui flow across SKILL.md files and README.
Document wallet login (email OTP), setup --oms-* credentials, the call
command, and the no-permission-scoping V3 model.
Drop the dead "re-create with wallet create --contract" notes and the
Sapient-era error handling ("No signer supported", session-permission
rejection) from deposit and withdraw — these referred to the removed
dapp-client permission-scoping model and can't occur on the OMS path.
Deposit/withdraw now submit through runOmsTx directly; OMS session
errors are handled in the primitive. Also fix the setup TTY hint to
point at `wallet login` instead of the removed `wallet create`.
return Uint8Array.from(Buffer.from(decrypt(cipher), 'hex'));
}
const keyHex = Buffer.from(randomBytes(32)).toString('hex');
fs.writeFileSync(file, JSON.stringify(encrypt(keyHex)), { mode: 0o600 });
AkshatGada and others added 4 commits July 1, 2026 00:02
Add a `wallet login-browser` subcommand that signs in with Google through the
SDK's OIDC + PKCE redirect flow, using a short-lived localhost callback server.
The resulting session persists identically to email login, so balances, tx and
address resume with no re-login. The funding step is chained after a successful
login (skip with --no-fund).

- oidc-callback-server.ts: loopback server that captures the single callback URL
- oms-client.ts: pass the mandatory redirectAuthStorage; SEQUENCE_OIDC_RELAY_URI override
- oms-storage.ts: FileStorageManager subdir arg, isolating transient OIDC state
- storage.ts: widen loginMethod to email|oidc|google; email now optional
- operations.ts: extract showFunding so `fund` and post-login reuse one path

This is the same-machine flow (browser and CLI co-located). Remote login over a
relay is a follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A small Cloudflare Worker + Durable Object that lets the CLI complete browser
login from any machine, including a remote server where a localhost callback
can't be reached. The browser is redirected to the relay with the OAuth
code+state; the CLI polls for them and finishes the exchange itself. The PKCE
verifier never leaves the CLI, so the relay alone cannot complete a login.
Sessions are keyed by the OIDC state, single-use, with a 10-minute TTL.

Not yet wired into the CLI: the --remote poll path lands once Sequence
allowlists the relay's /api/oidc/cb as a redirect target. Deploy with
`npx wrangler` (kept out of the workspace dep graph to satisfy the repo's
trust policy).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gration

# Conflicts:
#	packages/connector-ui/CHANGELOG.md
#	packages/connector-ui/package.json
#	packages/connector-ui/src/App.css
#	packages/connector-ui/src/index.css
#	packages/shared/CHANGELOG.md
#	packages/shared/package.json
#	pnpm-lock.yaml
@claude

claude Bot commented Jun 30, 2026

Copy link
Copy Markdown

Code review

Found 3 issues. Checked for bugs and CLAUDE.md compliance.

  • Bug: wallet remove always throws "Wallet not found" due to deleteOmsWallet deleting the pointer file before deleteWallet checks for it
  • Team standards: Definite assignment assertions (!) in new file oidc-callback-server.ts
  • Team standards: showFunding uses 4 positional parameters instead of a params object

See inline comments for details.

@claude

claude Bot commented Jun 30, 2026

Copy link
Copy Markdown

Detailed review findings

1. Bug in wallet.ts:284-289wallet remove always throws "Wallet not found"

deleteOmsWallet(name) deletes the wallet pointer file at wallets/<name>.json before deleteWallet(name) checks for it. Since the file is already gone, deleteWallet returns false, and the handler always throws Wallet not found — even when the wallet was successfully removed.

See storage.ts L284-289 and wallet.ts L284-289.

Fix: swap the call order so deleteWallet runs before deleteOmsWallet.


2. Team standards violation in oidc-callback-server.ts:52-53 — definite assignment assertions

Definite assignment assertions (let x!: T) bypass TypeScript's static guarantees. The team standards say: No non-null assertions (!) — narrow the type instead. Fix: initialize with no-op stubs that get overwritten by the Promise executor.


3. Team standards violation in operations.ts:333-338 — positional parameters

showFunding has 4 positional parameters including a defaulted chainId and optional opts. The team standards say: Params objects over positional arguments for functions with 2+ parameters. Refactor to a params object.

@claude

claude Bot commented Jul 6, 2026

Copy link
Copy Markdown

Code review (updated for new commits since last review)

Found 3 issues. Checked for bugs and CLAUDE.md compliance.

1. Bug — setup-ui.tsx:189,196: Hint text says Next: polygon-agent wallet login --email <addr> but --email was removed in this PR. Users following this hint get a yargs error. Fix: change to polygon-agent wallet login.

2. CLAUDE.md violation — App.tsx:351: Non-null assertion (!) on .find() result (AGENTS.find(...)!). Team standards require narrowing the type instead. Fix: add if (!agent) return; guard.

3. CLAUDE.md violation — operations.ts:230: Non-null assertion (!) on singleChainSpec. Team standards require narrowing the type. Fix: const spec = singleChainSpec ?? "polygon";

@JamesLawton JamesLawton closed this Jul 7, 2026
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.

3 participants