feat(appkit-wagmi): Omen deposit-flow demo in WebView#571
Conversation
Adds an "Omen" mock funded-account screen that opens the WalletConnect Pay deposit flow (buyer-experience /deposit) in an in-app WebView — no context switch, no redirect. Reuses the #570 WebView scaffolding (wc: deeplink hand-off, returnUrl + preferUniversalLinks) with a deposit-specific onMessage that credits a mock balance from DEPOSIT_COMPLETE/DEPOSIT_CANCELLED. - OmenStore (valtio): mock balance + activity + credit() - Omen screen: balance, "Deposit crypto", activity list - OmenDepositWebView: WebView + deeplink interception + DEPOSIT_* bridge - Entry button on the Connections screen + navigation wiring Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @tomiir's task in 2m 39s —— View job Found 5 issue(s)Issue 1: Hardcoded branch-preview Worker URL will silently break when the branch is deletedID: depositurl-hardcoded-preview-url-a3f1 Context:
Recommendation: Gate behind an env var or at minimum an explicit const BX_DEPOSIT_URL = process.env.OMEN_DEPOSIT_URL
?? 'https://tomiir-bx-deposit-flow-poc-wc-pay-buyer-experience-dev.walletconnect-v1-bridge.workers.dev/deposit';Issue 2:
|
| * posts DEPOSIT_COMPLETE / DEPOSIT_CANCELLED back over the RN WebView bridge — never a redirect. | ||
| */ | ||
| const BX_DEPOSIT_URL = | ||
| 'https://tomiir-bx-deposit-flow-poc-wc-pay-buyer-experience-dev.walletconnect-v1-bridge.workers.dev/deposit'; |
There was a problem hiding this comment.
🤖 Auto Review Issue: Hardcoded branch-preview Worker URL will silently break when the branch is deleted
Severity: HIGH
Category: code_quality
Tool: Claude Auto Review
Context:
- Pattern:
BX_DEPOSIT_URLis set to a Cloudflare branch-preview Worker URL (tomiir-bx-deposit-flow-poc-…workers.dev) - Risk: Branch-preview Workers are ephemeral — the URL disappears when the branch/deployment is cleaned up; the WebView will silently fail to load and users see
onLoadError - Impact: The entire deposit flow becomes unreachable in any build that ships before the URL is swapped
- Trigger: The branch-preview deployment is deleted or expired (common in preview environments)
Recommendation: Gate behind an env var or at minimum an explicit __DEV__ guard:
const BX_DEPOSIT_URL = process.env.OMEN_DEPOSIT_URL
?? 'https://tomiir-bx-deposit-flow-poc-wc-pay-buyer-experience-dev.walletconnect-v1-bridge.workers.dev/deposit';|
|
||
| // In-frame navigations to a wallet deeplink are handed to the OS (opens the wallet); everything | ||
| // else loads in the WebView. | ||
| const onShouldStartLoadWithRequest = useCallback( |
There was a problem hiding this comment.
🤖 Auto Review Issue: onShouldStartLoadWithRequest allows arbitrary custom URL schemes through the WebView
Severity: HIGH
Category: security
Tool: Claude Auto Review
Context:
- Pattern:
onShouldStartLoadWithRequestonly intercepts WC deeplinks (isWalletDeeplink); all other URLs (includingtel:,sms:,market:,intent:) returntrue(allow).new URL('tel:+1234')throws, so the catch block returnsfalse, meaningisWalletDeeplinkreturnsfalseand the scheme is allowed to load. - Risk: A malicious injection into the hosted BX page could navigate the WebView to a custom native scheme (
tel:,sms:), triggering OS-level app launches or dialogs without user consent - Impact: Unexpected native app invocations, social engineering vectors (e.g. pre-filled phone calls or SMS)
- Trigger: Any XSS or page-level injection in the hosted BX deposit page
Recommendation: Explicitly allow only http/https and known WC deeplinks:
const onShouldStartLoadWithRequest = useCallback((request: ShouldStartLoadRequest): boolean => {
if (isWalletDeeplink(request.url)) {
openWallet(request.url);
return false;
}
// Block non-http(s) schemes — don't let the page drive native scheme handlers
if (!/^https?:\/\//i.test(request.url)) {
return false;
}
return true;
}, [openWallet]);| * posts DEPOSIT_COMPLETE / DEPOSIT_CANCELLED back over the RN WebView bridge — never a redirect. | ||
| */ | ||
| const BX_DEPOSIT_URL = | ||
| 'https://tomiir-bx-deposit-flow-poc-wc-pay-buyer-experience-dev.walletconnect-v1-bridge.workers.dev/deposit'; |
There was a problem hiding this comment.
🤖 Auto Review Issue: External domain URL — branch-preview workers.dev
Severity: MEDIUM
Category: security
Tool: Claude Auto Review
| </Text> | ||
| {tx.txHash ? ( | ||
| <TouchableOpacity | ||
| onPress={() => Linking.openURL(`https://basescan.org/tx/${tx.txHash}`)}> |
There was a problem hiding this comment.
🤖 Auto Review Issue: External domain URL — basescan.org hardcoded explorer link
Severity: LOW
Category: security
Tool: Claude Auto Review
|
|
||
| import {buildOmenDepositUrl} from './depositUrl'; | ||
|
|
||
| function formatUsd(n: number): string { |
There was a problem hiding this comment.
🤖 Auto Review Issue: formatUsd duplicated across two files
Severity: LOW
Category: code_quality
Tool: Claude Auto Review
Context:
- Pattern:
formatUsdis defined in bothOmen/index.tsx(lines 14-19, handles negatives) andOmenDepositWebView.tsx(lines 35-37, positive-only). The two implementations are subtly different, creating a divergence risk. - Risk: Future edits fix a formatting bug in one but not the other
- Impact: Inconsistent display (e.g. a negative credited amount in one view vs the other)
- Trigger: Any formatting edge case (very large amounts, negative credits, rounding)
Recommendation: Extract to src/utils/formatUsd.ts with a single implementation handling both positive and negative values, then import in both screens.
There was a problem hiding this comment.
Pull request overview
Adds an Omen deposit-flow demo to the dapps/appkit-wagmi sample app, showcasing completing the WalletConnect Pay /deposit flow inside an in-app WebView and crediting a local mock “funded account” via the RN WebView bridge (no redirect/context switch).
Changes:
- Introduces a Valtio-backed
OmenStorefor mock balance/activity and deposit crediting. - Adds new Omen screens: a funded-account UI and a dedicated deposit WebView that handles
DEPOSIT_COMPLETE/DEPOSIT_CANCELLEDmessages. - Wires the demo entrypoint into Connections and navigation (new routes + button).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| dapps/appkit-wagmi/src/utils/TypesUtil.ts | Adds new stack route types for Omen and OmenDepositWebView. |
| dapps/appkit-wagmi/src/stores/OmenStore.ts | New Valtio store for mock balance/activity + credit() helper. |
| dapps/appkit-wagmi/src/screens/Omen/OmenDepositWebView.tsx | New WebView screen for deposit flow + RN bridge handling + deeplink interception. |
| dapps/appkit-wagmi/src/screens/Omen/index.tsx | New funded-account screen: balance, deposit CTA, activity list with explorer link. |
| dapps/appkit-wagmi/src/screens/Omen/depositUrl.ts | Builds the BX /deposit URL with destination + returnUrl + preferUniversalLinks. |
| dapps/appkit-wagmi/src/screens/Connections/index.tsx | Adds OmenDemoButton to the Connections screen. |
| dapps/appkit-wagmi/src/screens/Connections/components/OmenDemoButton.tsx | New button to open the Omen demo screen. |
| dapps/appkit-wagmi/src/navigators/RootStackNavigator.tsx | Registers the new Omen routes in the root stack navigator. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| function formatUsd(n: number): string { | ||
| return `$${n.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/, ',')}`; | ||
| } |
| function formatUsd(n: number): string { | ||
| const sign = n < 0 ? '-' : ''; | ||
| return `${sign}$${Math.abs(n) | ||
| .toFixed(2) | ||
| .replace(/\B(?=(\d{3})+(?!\d))/, ',')}`; | ||
| } |
| function isWalletDeeplink(url: string): boolean { | ||
| try { | ||
| const wcUri = new URL(url).searchParams.get('uri'); | ||
| return !!wcUri && wcUri.startsWith('wc:'); | ||
| } catch { | ||
| return false; | ||
| } | ||
| } |
| {tx.txHash ? ( | ||
| <TouchableOpacity | ||
| onPress={() => Linking.openURL(`https://basescan.org/tx/${tx.txHash}`)}> | ||
| <Text variant="small-400" style={{color: Theme['accent-100']}}> | ||
| View on explorer | ||
| </Text> | ||
| </TouchableOpacity> |
Restyle the native Omen screen to match the web host (apps/deposit-demo): dark zinc surfaces, violet accent, code-drawn logo + wordmark header with Sign out, purple welcome-offer banner, styled balance/deposit pill/activity. Hide the stack header for Omen so the in-content header is the only one. No image assets added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
We have no JS console on-device, so tapping a wallet failing silently was un-diagnosable. Add a floating debug overlay that captures every navigation request + isWalletDeeplink verdict, window.open targets, the Linking canOpenURL/openURL handoff result, load/HTTP errors, and BX's own console/window-error/unhandledrejection lines (forwarded via injected JS over the RN bridge, marked __omenDebug so the DEPOSIT_* contract is untouched). Copy/Clear + capped ring buffer. Gated behind a DEBUG const. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Open BX with ?theme=dark, paint the WebView + a dark loading cover in the Omen bg until onLoadEnd (kills the white flash on open), wrap in a dark SafeAreaView, and hide the redundant native header so BX's own "Add money" chrome is the only one — the deposit reads as part of the app. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deposit to 0x13302Eb0aD9Af2F847119dC4Ac632fFe196d0B0f, and after a successful deposit show the confirmation briefly then close the webview and return to the Omen home (now showing the credited balance + new activity row). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Intercept the gooddeposit:// handoff from the BX deposit page in OmenDepositWebView and open a full-screen "GoodWallet" modal (its own light skin + brand, slid up so it reads as a separate wallet). The screen lists mock token holdings, lets you pick a token + amount, shows the requesting app + destination, and on Confirm mock-sends, credits OmenStore, and returns to Omen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Handle the DEPOSIT_OPEN_WALLET postMessage in onMessage → navigate to the GoodDepositConfirm modal. Drop the gooddeposit:// scheme interception: iOS WKWebView never surfaced the custom-scheme navigation, so the deeplink path was dead. The postMessage bridge is the reliable channel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Carry network + token through the DEPOSIT_OPEN_WALLET bridge message into the GoodWallet screen: preselect the matching token (still changeable) and show the chosen network on the request card — the "ideal wallet: preselected but changeable" behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Redesign the screen: app-avatar request card, horizontal network chips (with logos), a token list showing balances + USD value, a cleaner amount card and a "Deposit $X" CTA. - Add an in-wallet network + token selector (mirrors the BX concept); the BX pre-selection still preselects both, and they stay changeable. - Model mock holdings per network with realistic prices for non-stables (ETH 3550, POL 0.52; stables ~1) and show per-token USD value. - Fix the close control not being tappable on iOS: drop the modal SafeAreaView for useSafeAreaInsets + a padded Pressable close button below the status bar. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
What
POC demo of the WalletConnect Pay deposit flow inside an in-app WebView — the "mobile app + WebView, no context switch" experience. Adds an Omen mock funded-account screen to the
appkit-wagmidApp that opens the buyer-experience/depositpage in a WebView and credits a mock balance from the result posted back over the RN bridge. No redirect.Built on the WebView scaffolding from #570 (merged): reuses the
wc:deeplink hand-off (onShouldStartLoadWithRequest/onOpenWindow→Linking.openURL) and thereturnUrl+preferUniversalLinksURL params.Changes
stores/OmenStore.ts— valtio store: mock balance + activity,credit({amount, source, txHash})(falls back to a nominal amount when the wallet doesn't report one).screens/Omen/index.tsx— funded-account screen: balance, + Deposit crypto, activity list with explorer links.screens/Omen/depositUrl.ts— builds the BX/depositURL withto/app=Omen/returnUrl(getMetadata().redirect.native) /preferUniversalLinks=1.screens/Omen/OmenDepositWebView.tsx— the WebView. Reuses feat(appkit-wagmi): pay-flow WebView PoC — paste URL & open in WebView #570's deeplink interception but with a deposit-specificonMessageforDEPOSIT_COMPLETE/DEPOSIT_CANCELLED→ creditsOmenStore, then shows the reusedPaySuccessView.screens/Connections/components/OmenDemoButton.tsx+ wiring inConnections/index.tsx,navigators/RootStackNavigator.tsx,utils/TypesUtil.ts.The deposit page currently points at a BX branch preview Worker (
tomiir-bx-deposit-flow-poc-…workers.dev); swap the base URL indepositUrl.tswhen the route ships to a stable env.Test
cd dapps/appkit-wagmi && yarn install && yarn prebuildtsc --noEmitandeslintclean on the new/edited files. Not yet run on a device/simulator.Open item
returnUrlon the Wallet tab: the BX/depositwallet path drives AppKit directly (bypasses the payment-machine returnUrl wiring from buyer-experience#967), so the wallet round-trip back to the app needs a device test and likely a small BX-side change. The Address/QR and Exchange paths don't depend on it.🤖 Generated with Claude Code