Skip to content

feat(agent): bring Agent Wallet to master (hidden in production)#2111

Open
MusabShakeel576 wants to merge 24 commits into
masterfrom
claude/brave-fermi-R0BgM
Open

feat(agent): bring Agent Wallet to master (hidden in production)#2111
MusabShakeel576 wants to merge 24 commits into
masterfrom
claude/brave-fermi-R0BgM

Conversation

@MusabShakeel576
Copy link
Copy Markdown
Contributor

@MusabShakeel576 MusabShakeel576 commented Jun 1, 2026

What

Cherry-picks the Agent Wallet feature from qa onto a branch off master, and hides the Agent tab in production until the feature is released.

Task 1 — Cherry-pick Agent Wallet from qa

Cherry-picked all 23 agent commits (the feat/fix/style/refactor(agent) series from claude/agent-yield-payments-b4DMj) in order, since the feature landed on qa incrementally rather than as a single merge. master previously had no agent code.

  • New files (match qa byte-for-byte): app/(protected)/agent/index.tsx, components/Agent/*, hooks/useAgent.ts, hooks/useBorrowAndDepositToAgent.ts, constants/agentPromptTemplate.ts, lib/utils/borrowAndBridge.ts.
  • Shared files resolved as additive unions, keeping both master content and the agent additions: constants/path.ts, constants/transaction.ts, lib/types.ts, app/(protected)/_layout.tsx, lib/api.ts, hooks/useBorrowAndDepositToCard.ts.
  • Verified the card-deposit refactor (useBorrowAndDepositToCard.ts, lib/api.ts) matches qa exactly so the existing card flow is unaffected. All local imports resolve on master (borrow/deposit infra, ABIs, hooks already present).

Task 2 — Hide Agent tab in production

hooks/useNav.ts now omits the Agent entry from the nav menu when isProduction, reusing the existing isProduction flag from @/lib/config. The agent route still exists; only the tab is hidden in prod.

Notes

  • Backend Agent Wallet endpoints are promoted separately: Solid-Money/solid-backend#1496.
  • node_modules isn't available in this environment, so lint/typecheck were not run locally — please let CI validate.

https://claude.ai/code/session_01Hzy5zskEvLozGA6ih1Bhty

claude added 24 commits June 1, 2026 11:45
…ration UX

Wire the new /v1/agents/* backend endpoints into the UI: useAgentQuery,
useProvisionAgent, useUpdateAgent, useAgentApiKeys, useGenerateAgentApiKey,
useRevokeAgentApiKey. Add an Agent route accessible from the desktop nav
that lets users provision an agent wallet, view the agent EOA / daily cap
/ allowlist, generate sk_solid_live_ API keys (one-time reveal), revoke
keys, and copy a curl example + a Markdown system-prompt template
designed to drop into Claude Desktop or ChatGPT custom GPTs. Surface
agent activity types in the transaction-details map. Deposit flow is
stubbed with a 'coming soon' toast — backend supports any path; client
borrow-and-bridge wiring lands in a follow-up.

(cherry picked from commit 99639c8)
…-chain balance

- Move AgentSummary, AgentApiKeySummary, GenerateAgentApiKeyResponse from
  lib/api.ts to lib/types.ts. AgentSummary now only carries agentEoaAddress
  to match the simplified backend response.
- Drop User.hasDepositedToAgentWallet — derived on the fly from the
  activity feed via useAgentDeposited (long-cached, one-way transition).
- Drop useUpdateAgent (cap/allowlist removed from backend).
- Add useAgentBalance: viem readContract on Base USDC for the agent EOA,
  refreshing every 60s.
- Update Agent page copy from 'Idle USD principal stays in your soUSD
  vault and keeps earning' to 'Start earning yield on idle USDC in your
  agent wallet'.
- Replace the cap/spent/allowlist counters card with a single 'USDC
  balance on Base' panel sourced from chain.

(cherry picked from commit 32aed6b)
Use ' in copy that was tripping CI lint:
- 'We'll create a new EOA…' (Agent setup CTA)
- 'This is the only time you'll see the full key…' (reveal modal description)
- 'I've saved it' (reveal modal confirmation button)

(cherry picked from commit 16a1e8e)
- Reuse Base USDC address via getStargateToken(base.id) from
  lib/utils/stargate.ts instead of duplicating the literal in
  hooks/useAgent.ts. Keeps the canonical mapping single-sourced.
- Match useBalances resilience options on useAgentBalance: gcTime,
  retry: 3 with exponential retryDelay, refetchOnWindowFocus,
  refetchOnReconnect.
- Drop unused User.agentEoaAddress field from lib/types.ts — the
  agent address is sourced via useAgentQuery, not user hydration.
- Remove dead { confirmed ? null : null } branch and the unused
  confirmed state from ApiKeyRevealModal.tsx.
- Switch IntegrationSnippet's clipboard call from a dynamic
  import('expo-clipboard') inside the handler to a static import,
  matching the canonical pattern in components/CopyToClipboard.tsx.
- Re-route AgentApiKeySummary import in ApiKeyList.tsx from @/lib/api
  (where it no longer lives) to @/lib/types.

(cherry picked from commit 0f17a9b)
- Register agent/index in the protected Stack with headerShown: false
  so the default 'agent/index' header strip stops rendering above the
  page (matches every other route in (protected)).
- Restyle the 'Set up your agent' empty state to mirror the
  /card/pending box (rounded-2xl, border-white/5, bg-[#1C1C1C], padded
  px-6 pb-8 pt-10, centered title + description). Skipping the image
  per the screenshot direction; full-width primary CTA at the bottom.

(cherry picked from commit 73f4f31)
- Drop the Agent Wallet heading + description from the empty state so
  the setup card stands alone (only render them once provisioned).
- Narrow the empty state container to max-w-lg / pt-8 to mirror
  /card/pending; keep max-w-3xl + py-6/md:py-10 once provisioned.
- Reserve a 268px-tall placeholder block above the title — same
  height as /card/pending's card-fade illustration, so the layout
  doesn't jump when we swap in the real artwork later.
- Rename CTA + box title from 'Set up Agent' / 'Set up your agent' to
  'Set up your Agent Wallet'. Provisioning creates the EOA itself,
  the Turnkey user, and the policy in one step — there's no separate
  'agent' without a wallet, so the longer name is more accurate.

(cherry picked from commit c417daf)
Hit /agent?status=loading | not_provisioned | provisioned | deposited
to force the page into a specific branch without going through real
provisioning + activity flow. Useful for visual QA on the empty state,
provisioned state, and the Switch's deposited variant.

- Override is parsed via useLocalSearchParams and gated on !isProduction
  — the param is silently ignored on prod builds.
- Live useAgent* hooks keep firing under the override so toggling the
  param off cleanly reverts to real data without a remount.
- 'provisioned' / 'deposited' supply a stub agent EOA, a fake 2.34
  USDC balance, and (for 'deposited') flip the Human/Agent Switch to
  the right side.

(cherry picked from commit fb2f4e5)
UI restyle informed by the screenshot direction:

- Move Generate API Key + Deposit out of inline cards into the page
  header. flex-row justify-between with title block on the left and
  buttons on the right (desktop), matching /card/details:352. On mobile
  the header collapses to title above + circular action buttons (a
  green Deposit + dark Generate Key) in a row, mirroring the mobile
  hero pattern.
- Drop the Human/Agent toggle entirely. The deposited bool is no
  longer surfaced in the UI.
- Wallet + API key boxes now sit side-by-side on desktop (flex-row,
  flex-1 each) and stack on mobile (flex-col). 'How to use' lives
  below as a single full-width box.
- All three boxes use the same rounded-2xl bg-[#1C1C1C] base as the
  setup card. Inner content stays left-aligned per the direction;
  copy + balance live inside the wallet card.
- Strip every border-* class. Sub-elements (api key rows, snippet
  block, reveal modal key block) now use rounded-xl bg-[#262626]
  instead of bordered backgrounds.
- All ActivityIndicators on the agent surface explicitly color='white'
  to drop the platform-default tinted spinner.
- Bump the provisioned-state max-width from max-w-3xl to max-w-5xl
  so the side-by-side cards have room to breathe.
- Deposit button still no-ops to a clarifying toast — the actual
  flow is the borrow-against-savings clone (per the original plan
  U3) and is being tracked as a follow-up.

(cherry picked from commit 94bb265)
…lance gradient

Borrow flow:
- Extract the heavy lifting of useBorrowAndDepositToCard into a shared
  inner async helper at lib/utils/borrowAndBridge.ts. The function takes
  destinationAddress + destinationChainId/Key + destinationToken so the
  same on-chain transaction batch (approve soUSD → Aave supply →
  borrow USDC.e → approve CardDepositManager → BridgePaymaster
  callWithValue) handles any Stargate destination.
- useBorrowAndDepositToCard becomes a thin wrapper that resolves the
  card-funding address and forwards to the helper. Existing tracking
  events + Sentry breadcrumbs preserved.
- New useBorrowAndDepositToAgent wraps the same helper with the agent
  EOA + base.id + Stargate Base USDC, and emits AGENT_WALLET_DEPOSIT
  activities.
- The CardDepositManager forwards regardless of receiver because
  isWhitelistEnabled is off in prod (verified: no caller of
  authorizeCards or setWhitelistEnabled in this repo or boring-vault),
  so we reuse the existing manager + sponsorship path on
  BridgePaymaster — no new contract, no new sponsor tx.

Modal:
- New AgentDepositModal: amount input, live borrow position
  (useAaveBorrowPosition), Max button capped at totalSupplied * LTV -
  totalBorrowed, brand-variant Borrow CTA. On submit invokes the new
  hook; toast on success/failure; modal closes on success.
- Bound to the Agent page Deposit button (replaces the 'coming soon'
  toast). Mobile circular Deposit button opens the same modal.

Page header:
- Copy prompt button moved out of IntegrationSnippet and into the
  page-header button group, alongside Generate API key + Deposit. Uses
  the same secondary 'h-12 rounded-xl bg-[#303030] px-6' styling as
  Generate API key, with a FileText icon. Mobile gets a third dark
  CircleAction labelled 'Prompt'.
- IntegrationSnippet now only renders the curl example + copy
  affordance and points users at the header for the prompt template.

Balance card:
- Replace the bg-[#1C1C1C] balance box with a /card/details-style
  SpendingBalanceCard: rounded-[20px], green LinearGradient overlay
  (rgba(104,216,82,…)), 50px USDC balance up top, 'Earning yield on
  idle USDC' caption underneath. Address moves into the API keys
  card so the balance card stays a hero panel.

(cherry picked from commit 838d335)
…lance card

Modal:
- Rebuild AgentDepositModal on top of ResponsiveModal with the same
  containerClassName='min-h-[42rem] overflow-y-auto flex-1' that the
  card deposit uses, so size + animation + header back-button behavior
  match. Inner content adopts CardDepositInternalForm primitives:
  bg-accent rounded-2xl px-5 py-{3,4} blocks, 'Amount to borrow' label
  + USDC token icon + 2xl input, 'Available to borrow / Max' row, and
  a small position breakdown (Currently borrowed, Supplied as
  collateral). Brand-variant Borrow CTA at the bottom.

Provisioned page:
- Bump max-width from max-w-5xl to max-w-7xl to match /card/details:150.
- Center the desktop header (title block + button row stacked, both
  items-center) instead of the previous flex-row justify-between.
- Bump page-level gap from gap-6 to gap-10 (gap-12 on md) so the
  header breathes above the boxes.
- Add max-w-xl to IntegrationSnippet's description so the line length
  isn't card-wide on desktop.

Balance card:
- Switch the LinearGradient palette from green
  rgba(104,216,82,…) to blue rgba(74,144,226,1) → rgba(120,192,250,0.55)
  so the agent page reads distinctly from the green card surface,
  purple savings, and yellow rewards.
- Rename label from 'USDC balance on Base' to 'Spendable balance' to
  match /card/details copy.
- Add gap-12 between the balance and 'Earning' rows so the two blocks
  are visually separated, with min-h-[260px] floor to match the card
  card's minimum hero height.

(cherry picked from commit 69e69a4)
Revert the items-center stack to the original layout (title left,
buttons right) with mx-auto on the row so the whole header still
sits centered within the max-w-7xl page wrapper.

(cherry picked from commit fb607ef)
…posit

Replace the bespoke amount-input + position-summary modal content with
a direct clone of the card form's BORROW path:
- BorrowSlider from components/Card/BorrowSlider for the amount input
  (slider + decimal input fused; min 0, max = totalSupplied * 0.69 -
  totalBorrowed, matching the card flow's CardDepositInternalForm:706).
- TokenDetails block with Borrow rate (from useAaveBorrowPosition.borrowAPY)
  and Collateral Required (live computed from slider value), plus the
  same 'Use your soUSD as collateral … Learn more.' helper paragraph
  used on /card/details.
- Bottom CTA reduced to a single brand-variant 'Deposit' button matching
  CardDepositInternalForm:548 — same h-12 rounded-2xl, ActivityIndicator
  swap when submitting.

Page header:
- Drop the wrapper's mx-auto (the page-level mx-auto on the max-w-7xl
  container already centers it). Switch items-end to items-center so
  the buttons align with the title text baseline rather than its
  descender.

Balance gradient:
- First stop now rgba(4, 96, 203, 1) per the latest spec; second stop
  unchanged.

(cherry picked from commit 2fbc21d)
Replaces the single POST /v1/agents/provision call with the four-step
init → walletAccount → user → policy chain. We mint (or refresh) a
Turnkey read-write session up front with one passkey gesture, then each
step silently API-key-stamps the unsigned activity body the backend
hands us and posts the signed envelope back. Backend relays the signed
bytes to Turnkey verbatim, so the stamp still validates.

This fixes the ORGANIZATION_MISMATCH error users hit on Set up Agent —
the parent-org admin can't sign writes against existing sub-orgs.

(cherry picked from commit 97a4901)
SignedTurnkeyRequest, ProvisioningActivity, ProvisioningInitResponse,
and ProvisioningStepInput were declared inline next to the fetch
helpers; move them to lib/types.ts to match the convention used by the
rest of the file. useAgent.ts imports SignedTurnkeyRequest from there
directly now instead of re-exporting via api.ts.

(cherry picked from commit 7111e38)
Two staging failures fixed:

- loginWithPasskey now passes organizationId: subOrganizationId so the
  session API key is minted on the user's sub-org. Without this Turnkey
  rejects sub-org activities with PUBLIC_KEY_NOT_FOUND.

- If init returns an agentEoaAddress, the user already had a derived
  wallet account from a prior failed attempt. We skip the
  createWalletAccounts stamp and use init's `activity` (createUsers
  body) directly.

Also: ensureSession now invalidates a cached session if its
organizationId doesn't match the user's sub-org, since switching scopes
requires a fresh login.

(cherry picked from commit 952e0f4)
Match the rest of the agent flow: ResponsiveModal wrapper for
mobile/web parity, brand-variant button at h-14 rounded-2xl like the
email-OTP and swap modals.

(cherry picked from commit 467be61)
Prompt template:
- Endpoint URL is built from EXPO_PUBLIC_FLASH_API_BASE_URL with the
  required `/accounts/v1/...` path so AI tools call the live route
  instead of the legacy `/v1/...` (the latter 404s on accounts-qa).
- Drop MVP-out-of-scope language: no per-tx caps, no daily caps, no
  recipient allowlist (none of these are enforced server-side anymore).
- Explicit safety paragraph: pasting the live key into Claude Desktop /
  ChatGPT is fine — the key only authorizes USDC payments out of this
  one agent wallet, gated by a Turnkey policy.
- First-turn behavior: the model should respond in 3-4 sentences,
  confirm setup, and suggest exactly 3 x402 stores/APIs relevant to
  the user as a "what to try first" prompt. No technical detail.

Deposit modal:
- Source picker (web only — thirdweb's connector flow is web-only),
  branching into the existing borrow-against-savings flow or a new
  external-wallet flow.
- New AgentDepositExternalForm: connect via thirdweb, switch chain to
  Base, transfer USDC directly from the connected wallet to the agent
  EOA. Logs an AGENT_WALLET_DEPOSIT activity. No Stargate, no yield —
  the copy makes that explicit.

Also: IntegrationSnippet now uses the same dynamic base URL.
(cherry picked from commit 9c3c60d)
…or-key first

External deposit:
- Drop the thirdweb connect-wallet flow. The new screen reuses
  DepositPublicAddress to render the agent EOA as a copyable string +
  QR code, scoped to Base USDC. Works on both web and native.
- Removes the ~200-line transfer/activity-creation code and the
  thirdweb dependency for this surface.

Borrow form:
- Yellow warning banner above the slider when isProduction is false:
  the soUSD/Aave market isn't deployed in QA so the borrow flow can't
  actually execute. Points users at the external-wallet option for
  testing.

Prompt template:
- New first-turn step zero: if the AI doesn't have SOLID_API_KEY yet,
  it must ask the user to paste one (and tell them where to generate
  it — the Agent tab) before doing anything else.

(cherry picked from commit 500ee5e)
…reen

Mirror the card deposit modal's source selector. The agent deposit
modal is now a single screen with a 'From' dropdown at the top
(Borrow against Savings / External Wallet) and the matching form
rendered inline below. Removes the prior options-step indirection,
the back-button bookkeeping, and the per-option descriptions.

- Web: real DropdownMenu (radix) — same -mt-4 rounded-b-2xl pattern.
- Native: inline expanding section (Pressable + isOpen) — same as the
  card flow's SourceSelectorNative.
- AgentDepositBorrowForm extracted into its own file for symmetry with
  AgentDepositExternalForm.

(cherry picked from commit 106e1ca)
Single-network surface (Base USDC only); the link sent users to a
generic supported-networks doc that doesn't apply here. The Base
chain badge + 'Send only USDC on Base' warning carry the right scope.

(cherry picked from commit a4dcd98)
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
solid-app Ignored Ignored Jun 1, 2026 11:50am
solid-app-staging Ignored Ignored Jun 1, 2026 11:50am

Request Review

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.

2 participants