feat(deposit-app): WalletConnect Pay deposit demo dapp (Expo)#542
feat(deposit-app): WalletConnect Pay deposit demo dapp (Expo)#542ganchoradkov wants to merge 6 commits into
Conversation
A responsive Expo (web + native) demo showing WalletConnect Pay as a deposit rail for a custodial trading app. Built to match the provided prototype's design (Inter / JetBrains Mono / Instrument Serif). - Home: real on-chain portfolio value via the AppKit balance RPC, with a deposit-only activity feed; responsive desktop (sidebar + modal) and mobile (bottom nav + sheet) layouts from a single viewport-detecting screen. - Deposit flow (amount → checkout → complete): confirming an amount creates a real payment via the Pay API (same contract as pos-app); the BX checkout opens in a new tab on web (it forbids iframing) and a WebView on native, with status polling driving completion. Closing the in-app modal cancels the pending payment. - Local caching: portfolio cached and refreshed at most once/hour; completed deposits persisted so the feed + balance survive reloads. - Settings: "Clear demo data" wipes cached balance + persisted deposits. Credentials are read from env (gitignored .env); no secrets are hardcoded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @ganchoradkov's task in 3m 11s —— View job Review complete
🚨 PR Too Large Files: 41 Lines: 21,861 Severity: HIGH Category: maintainability Found 8 issue(s)Issue 1:
|
Replace the 50/100/500/1000 quick-pick chips with 0.01, 0.10, 1, 2, 5, and let the row wrap so five chips fit on narrow screens. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new Expo (web + native) demo dApp under dapps/deposit-app to showcase WalletConnect Pay as a deposit rail, including a responsive desktop/mobile layout and an end-to-end deposit flow with checkout + polling.
Changes:
- Introduces a deposit flow state machine (
amount → checkout → complete) with Pay API integration, status polling, and cancellation on modal dismissal. - Adds UI for desktop (sidebar + modal) and mobile (bottom nav + sheet), plus settings to clear cached demo data.
- Implements small utilities for typed AsyncStorage JSON, manual USD formatting, and viewport-based device detection.
Reviewed changes
Copilot reviewed 30 out of 41 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| dapps/deposit-app/wcpay-deposit-demo-v2.jsx | Reference prototype JSX used as the visual source-of-truth for the RN implementation. |
| dapps/deposit-app/utils/storage.ts | Typed JSON wrapper over AsyncStorage for caching portfolio + deposits. |
| dapps/deposit-app/utils/format.ts | Manual USD formatting + relative time helpers. |
| dapps/deposit-app/tsconfig.json | Strict TS config + @/* path alias. |
| dapps/deposit-app/stores/use-deposit-store.tsx | Deposit flow store: payment creation, polling, persistence, cancellation, balance layering. |
| dapps/deposit-app/services/pay.ts | WalletConnect Pay client (create/status/cancel) + polling interval normalization. |
| dapps/deposit-app/services/balance.ts | Portfolio fetch via WalletConnect RPC balance endpoint. |
| dapps/deposit-app/scripts/reset-project.js | Expo “reset project” helper script (scaffolding utility). |
| dapps/deposit-app/package.json | App dependencies, scripts, and security overrides. |
| dapps/deposit-app/hooks/use-device.ts | Device detection hook (desktop vs mobile) based on web viewport width. |
| dapps/deposit-app/eslint.config.js | Expo flat ESLint config. |
| dapps/deposit-app/deposit-app.md | Product/spec documentation for the demo and user journey. |
| dapps/deposit-app/data/activity.ts | Activity feed types and initial mocked state (now empty by default). |
| dapps/deposit-app/constants/theme.ts | Design tokens (colors/fonts/radius) ported from the prototype. |
| dapps/deposit-app/components/ui/icons.ts | Lucide icon alias layer to match prototype naming. |
| dapps/deposit-app/components/SettingsModal.tsx | Settings modal with “Clear demo data” action. |
| dapps/deposit-app/components/home/Sidebar.tsx | Desktop sidebar UI with settings entrypoint. |
| dapps/deposit-app/components/home/MobileHome.tsx | Mobile home screen: balance, CTAs, activity feed/empty state. |
| dapps/deposit-app/components/home/DesktopHome.tsx | Desktop home screen: balance hero, CTAs, activity feed/empty state. |
| dapps/deposit-app/components/home/BottomNav.tsx | Mobile bottom nav with settings entrypoint. |
| dapps/deposit-app/components/deposit/DepositOverlay.tsx | Responsive modal/sheet wrapper rendering the flow steps. |
| dapps/deposit-app/components/deposit/DepositAmountStep.tsx | Step 1 UI: method tabs, amount input, presets, continue CTA + errors. |
| dapps/deposit-app/components/deposit/CompleteStep.tsx | Success step UI with animated amount count-up and Done CTA. |
| dapps/deposit-app/components/deposit/CheckoutSurface.web.tsx | Web checkout surface: tab-based checkout + “waiting” state + reopen. |
| dapps/deposit-app/components/deposit/CheckoutSurface.tsx | Native checkout surface: embedded WebView + deep-link handling. |
| dapps/deposit-app/babel.config.js | Expo Babel preset configuration. |
| dapps/deposit-app/app/index.tsx | Home screen layout switch (desktop vs mobile) + overlay wiring. |
| dapps/deposit-app/app/_layout.tsx | App root: font loading, splash handling, DepositProvider setup. |
| dapps/deposit-app/app.json | Expo app configuration (router, splash, web output, plugins). |
| dapps/deposit-app/.gitignore | Deposit-app specific ignores (node_modules, Expo artifacts, env locals). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
`npm run web:build` runs `expo export --platform web` to produce the static web bundle in dist/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document the required env vars (project id, Pay API url/key, deposit merchant id, demo account) with empty placeholders for onboarding. The real .env stays gitignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- gitignore: ignore .env and .env.* (keep !.env.example) so plain .env files can't be committed - balance: add 30s fetch timeout + demo-only note that real apps must not put user addresses in URLs - pay: enforce HTTPS on the API URL (Api-Key is sent every request); throw on invalid/<=0 amounts instead of sending NaN - store: cap status-poll retries on persistent errors; detach popup opener to prevent reverse-tabnabbing; reset retry counter per payment - complete: show the real (truncated) paymentId instead of a fake tx hash - checkout (web): use a real apostrophe instead of ' (rendered literally) - deps: pin @expo-google-fonts/*, lucide-react-native, babel-preset-expo to exact versions - remove the prototype artifact wcpay-deposit-demo-v2.jsx (no longer needed) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review feedback addressed —
|
| Finding | Status | Change |
|---|---|---|
.env not fully gitignored (HIGH) |
✅ | .gitignore now ignores .env + .env.*, with !.env.example |
| Wallet address in URL path (HIGH) | ✅ | Added demo-only caveat comment in balance.ts (fixed demo account; real apps must not put user addresses in URLs) |
No timeout on fetchPortfolio (MED) |
✅ | 30s AbortController, matching pay.ts |
| Unbounded poll retries (MED) | ✅ | Cap at 20 consecutive errors → surfaces "status unavailable"; counter resets per payment |
| No HTTPS enforcement on Pay API URL (MED) | ✅ | pay.ts headers() throws if API_URL isn't https:// |
amountToCents NaN (Copilot) |
✅ | Throws on invalid/≤0 amount instead of sending a bad value |
| Popup opened without opener protection (Copilot) | ✅ | Detach opener on the checkout popup (prevents reverse-tabnabbing) while keeping the synchronous handle |
' rendered literally (LOW) |
✅ | Replaced with a real apostrophe in CheckoutSurface.web.tsx |
| Fake tx hash shown as "Confirmed" (LOW) | ✅ | Now shows the real (truncated) paymentId |
| Caret/tilde dep ranges (Copilot) | ✅ | Pinned @expo-google-fonts/*, lucide-react-native, babel-preset-expo to exact versions |
Prototype artifact wcpay-deposit-demo-v2.jsx (MED) |
✅ | Deleted (−907 lines) |
| "PR too large" (HIGH/maintainability) | ℹ️ | Acknowledged — net-new demo app, kept as a single PR per the reviewer's own "more recommendation than blocker" note |
tsc --noEmit and expo lint are clean. Net +60 / −928.
Note (unchanged, by design):
EXPO_PUBLIC_*vars are inlined into the client bundle, so the Paywcp_key ships to clients in this demo. Before any public/production deploy the Pay calls should move behind a backend/proxy (aspos-appdoes on web), leaving only the project id + read-only balance RPC client-side.
What
A responsive Expo (web + native) demo showing WalletConnect Pay as a deposit rail for a custodial trading app. Built to the provided prototype's design (Inter / JetBrains Mono / Instrument Serif), with a single viewport-detecting screen rendering a desktop layout (sidebar + centered modal) or mobile layout (bottom nav + bottom sheet).
Deposit flow
flowchart LR A[Home<br/>portfolio value] -->|Deposit| B[Amount entry] B -->|Continue| C{Create payment<br/>Pay API} C -->|gatewayUrl| D[Checkout] D -->|web| E[New tab + poll] D -->|native| F[WebView + poll] E --> G{status} F --> G G -->|succeeded| H[Complete<br/>credit balance + record deposit] G -->|modal closed| I[cancel payment] H --> AHighlights
pos-app). The BX checkout forbids iframing (X-Frame-Options: DENY), so it opens in a new tab on web and a WebView on native, with status polling driving completion. Closing the in-app modal cancels the pending payment.Security
.env.EXPO_PUBLIC_*vars (incl. the Paywcp_key) are inlined into the client bundle. Fine for a demo; before any public deploy the Pay calls should move behind a backend/proxy (aspos-appdoes on web).Verification
tsc --noEmitandexpo lintclean; web bundle compiles and renders (desktop + mobile home verified via screenshots).🤖 Generated with Claude Code