fix: link card deposit Explorer row to the real USDC transfer tx - #2157
Open
MusabShakeel576 wants to merge 349 commits into
Open
fix: link card deposit Explorer row to the real USDC transfer tx#2157MusabShakeel576 wants to merge 349 commits into
MusabShakeel576 wants to merge 349 commits into
Conversation
Mayank/fix/savings analytics
The card purchase activity header used justify-between, which offset the merchant title based on the ChevronLeft width, and the location was pinned with ml-10. Absolutely position the back button so the title truly centers, and drop the spacer. Also center the location text and trim merchant_name/description so stray whitespace from the upstream data doesn't misalign the header.
…us-W0JQd Add escrow status and countdown timer for cashback releases
…splay-xL5yx Improve transaction detail header layout and merchant name handling
…rkflows
Rename useDepositFromEOA -> useDepositFromWallet and add a category prop
('SAVINGS' | 'CARD'). The CARD branch is sponsor-only, uses TransactionType.CARD_DEPOSIT,
and calls createDeposit/bridgeDeposit with category='CARD' so the backend
Connect-Wallet workflows route funds to the Rain Base funding address instead
of the Ethereum vault.
Wire the new hook into CardDepositInternalForm for the production WALLET source
so 'Deposit to card from wallet' works from all 5 supported chains.
https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
…Amount Replace the hardcoded '100' minimum amount passed to useDepositFromWallet in CardDepositInternalForm with EXPO_PUBLIC_MINIMUM_SPONSOR_AMOUNT from lib/config, matching how the Savings flow sources the same threshold. https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
Move the CARD category support off the EOA-pull hook and onto useDepositFromSolidUsdc so card deposits pull from the user's Solid Turnkey Safe AA (the account is the approver and allowance-granter), matching the rest of the new deposit flow. - Revert the useDepositFromEOA rename; restore the original hook as unused dead code and revert DepositToVaultForm to import it again. - useDepositFromSolidUsdc: add category: 'SAVINGS' | 'CARD' prop. When category=CARD: target chain is Base, activity type is CARD_DEPOSIT, and createDeposit / bridgeDeposit are called with category='CARD' so the backend routes funds to the Rain Base funding address. - CardDepositInternalForm: production WALLET path now uses useDepositFromSolidUsdc(USDC, EXPO_PUBLIC_MINIMUM_SPONSOR_AMOUNT, 'CARD'). https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
…Category enum Add DepositCategory enum to lib/types.ts mirroring the backend enum, and use it in place of the string-literal union in: - Deposit / BridgeDeposit request types (lib/types.ts) - useDepositFromSolidUsdc category prop + comparisons + API passes - CardDepositInternalForm's category argument https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
…ins-earUz Add card deposit support to wallet deposit hook
Addresses two issues in the card deposit from Solid wallet flow: 1. When useDepositStore.srcChainId is 0/unset (e.g. after resetDepositFlow persisted an unset value), useDepositFromSolidUsdc silently returned undefined from deposit(), so the form opened the transaction-status screen with no approve UserOp ever submitted and no Turnkey passkey prompt. The hook now throws a clear error when srcChainId is falsy, and CardDepositInternalForm defaults srcChainId to Base (the card funding chain) whenever the stored value is missing or unsupported. 2. Card deposit form now enforces EXPO_PUBLIC_MINIMUM_SPONSOR_AMOUNT via a zod refine on the WALLET source (disables the submit button and surfaces a validation message) and shows a gasless deposit hint row under the destination mirroring DepositToVaultForm's Fuel-icon line. https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
…ins-earUz fix(card-deposit): prevent silent no-op and add minimum-amount UI
Extract the reusable wallet-token picker from SavingsDepositTokenSelector into a shared WalletTokenSelectorScreen component that accepts filter props (supportedChainIds, supportedTokenSymbols, onSelect, empty text) so it can be reused unchanged by the card deposit flow. - New components/WalletTokenSelector/WalletTokenSelectorScreen.tsx hosts the aggregation + filter + render logic previously inlined in the savings selector. - SavingsDepositTokenSelector becomes a thin wrapper that passes the active vault's supportedChains / supportedTokens and navigates back to DEPOSIT_MODAL.OPEN_FORM on select. No behavioural change. - New components/Card/CardDepositTokenSelector.tsx wraps the same screen with a USDC + 5-chains filter and navigates back to CARD_DEPOSIT_MODAL.OPEN_INTERNAL_FORM. - constants/modals.ts adds CARD_DEPOSIT_MODAL.OPEN_TOKEN_SELECTOR. - CardDepositModalProvider renders CardDepositTokenSelector when the new state is active and wires up the Select-token title + back-button routing to the internal form. - CardDepositInternalForm replaces the earlier "default to Base" fallback with a WalletTokenButton that opens the selector. The deposit button is disabled until the user picks a token, and the selected token is shown in the button label (symbol + chain name). https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
…ins-earUz refactor(card-deposit): reuse savings wallet token selector screen
Drop the separate "Token" row and surface the wallet token selector in the same flex-row as the amount input, matching the savings deposit modal layout. AmountInput now accepts an optional rightSlot prop; CardDepositInternalForm passes WalletTokenButton as the slot when the WALLET source is active on production, replacing the static USDC/USDC.e image + label. https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
… WALLET source - CardDepositTokenSelector was calling useDepositStore.setModal (the savings modal store) when a token was selected, which routed the user to the savings-flow's Add Funds screen instead of the card deposit internal form. Switch to useCardDepositStore.setModal so the card modal transitions back to OPEN_INTERNAL_FORM, and set CardDepositSource.WALLET on select so the form re-mounts on the Wallet option. - CardDepositModalProvider's back button from the token selector also now explicitly sets source=WALLET before navigating back, so the internal form's defaultValues.from reads WALLET (not the BORROW default). https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
…ins-earUz fix(card-deposit): render WalletTokenButton inline inside amount input
Adds "External Wallet" as a fourth option in the card deposit dropdown (after Borrow against Savings, Savings, and Wallet). When selected, the card funding address is rendered via the reusable DepositPublicAddress screen from the Add funds modal with a Base chain USDC description that links to the token contract on Basescan. - Extend DepositPublicAddress with optional `address` and `description` props so the "Your Solid address" screen can be reused for arbitrary deposit addresses. - Render the address screen inline in CardDepositInternalForm when the EXTERNAL source is chosen, hiding amount input, destination, error and submit UI for that mode.
…deposit-AtDYW Add external wallet deposit option to card funding
Production "From Wallet" card deposit previously: - Read USDC balance from the Fuse-hardcoded USDC_STARGATE address, so users who picked Ethereum/Polygon/Base/Arbitrum USDC in the token selector always saw 0 balance and the Max button pasted 0. - Displayed "USDC.e" as the symbol on every chain, but the ".e" suffix only applies to Fuse's Stargate-bridged USDC; the other four chains use canonical USDC. Read the balance from the Solid Safe AA on the chain picked in the selector (falling back to the legacy Fuse USDC_STARGATE read when the user hasn't picked a token yet), and show "USDC.e" only when the selected chain is Fuse, otherwise "USDC". Consolidate the duplicate cardDepositSrcChainId/tokenAddress derivations onto the single balance-read source of truth. https://claude.ai/code/session_01TDpHy9uTrVX3PTRp9xS9S5
…ins-earUz fix(card-deposit): balance + symbol track the selected wallet chain
The unconditional <View className="flex-1" /> spacer was rendered as a sibling of the EXTERNAL branch's own flex-1 content wrapper, creating two stacked flex-1 children in the column. The empty sibling overlaid the address card and intercepted pointer events, making the "See token address" link unclickable. Restrict the spacer to non-external modes.
…deposit-AtDYW fix(card-deposit): hide flex spacer when external wallet is selected
Wrap ResponsiveModal's ScrollView in a KeyboardAvoidingView so the keyboard pushes modal content up instead of obscuring the focused input (e.g. the Two-Factor Authentication code entry). https://claude.ai/code/session_01MGVdxsdT6kXH5nPgJJFLJo
Replace the inline chevron-left Pressable in the Settings mobile header with the shared BackButton component, and switch BackButton's icon from ArrowLeft to ChevronLeft so it matches the existing chevron style while gaining the rounded-circle background. https://claude.ai/code/session_015abE3yneWZwkkzqAsvp7su
Settings mobile header still uses BackButton, which now renders its original ArrowLeft icon with the rounded-circle background. https://claude.ai/code/session_015abE3yneWZwkkzqAsvp7su
…omponent-nmVLt Replace custom back button with BackButton component
Restores the single-user fallback in selectSelectedUser that was removed in f8e23ec. Without it, the TurnkeyProvider has no allowCredentials on the welcome page after logout (no user is marked selected), so the authenticator prompt shows every registered passkey instead of just the one matching the button the user pressed. With the fallback, the lone stored user is treated as selected for the purpose of passkey filtering, and its credentialId flows into TurnkeyProviderKit's passkeyConfig.allowCredentials so only that passkey is offered in the system prompt. Regression originally fixed in 5584266 / 63564d5 and reintroduced by f8e23ec. https://claude.ai/code/session_017pCtNrFfjv1ge1t1LiVBSA
…ut-rWhty Wrap modal content with KeyboardAvoidingView for better keyboard handling
…nder review
For a Didit under_review user (e.g. held due to a duplicate device/IP), step 1
of /card/activate now lists the attached warning reasons instead of a generic
"being reviewed" message.
- The under_review step-1 description surfaces the attached warnings
("Your application is under additional review: ...") with a fallback to the
generic "few minutes" copy when there are none. (qa lacked this branch.)
- REJECTED / INCOMPLETE / under_review branches key off the formatted result so
a text-less warning set no longer renders an empty bullet list.
- Add DUPLICATED_DEVICE_FINGERPRINT (+ duplicate IP/device) to the friendly map.
https://claude.ai/code/session_01S2muieprRUo3BGSh8yKBtR
…nings Surface Didit KYC warnings on step 1, including under-review
Web never sent any Amplitude events because initAnalytics is gated behind splashScreenHidden, which is only flipped by onLayoutRootView. That onLayout was attached to SafeAreaProvider, which does not forward an arbitrary onLayout prop to its underlying view on web (it only wires its own inset measurement), so the callback never ran and analytics was never initialized. Native works because the native SafeAreaProvider does forward onLayout. Move onLayout to GestureHandlerRootView, which passes it through to a react-native-web View (fires via ResizeObserver) on web and lays out normally on native. Also gate trackScreen behind a new analyticsReady flag set once initAnalytics resolves, so the first (landing) Page Viewed fires after init instead of being queued before the Amplitude proxy serverUrl is configured and flushed to the wrong endpoint. Enrich the Amplitude Page Viewed event the same way track() does: extract a shared enrichEventParams() helper and use it for screen tracking so UTM/attribution fields land as top-level, queryable properties (utm_source, utm_campaign, ...) and route params are flattened instead of nested under a `params` object. Kept screen tracking on the Amplitude-only path to avoid double-counting in Firebase/GTM. https://claude.ai/code/session_01KR9AG8hkYVigCMsQmDKGS2
Refactor analytics enrichment and fix screen tracking initialization
Removes the "Get X% bonus for deposit" borrow-deposit banner from both the desktop and mobile card details layouts, along with its now-unused imports and styles. The desktop borrow position card now spans the full row width. https://claude.ai/code/session_01V7s9vkb32mh8HHBravEB5G
Remove DepositBonusBanner component from card details
The savings rate chart (savings page) and token price chart (coins/[id] page) tooltips showed a period-over-period percentage change next to the date. Remove that change indicator from both the web (recharts ChartTooltip) and native (AreaChart) tooltips so they only display the value and the date. The selectedPriceChange store update is kept so the coin detail header's price-change indicator continues to work. https://claude.ai/code/session_01KE3gjUzyjkEN8ntFCkDTNC
Remove price change percentage display from chart tooltips
- expo-insights (~55.0.15): zero-config launch/usage analytics for the EAS dashboard; events are sent automatically by the native module. - expo-observe (~0.2.2, the SDK 55-compatible release): startup and performance metrics (time to first render, time to interactive, launch times) dispatched to EAS Observe. Integration details: - lib/observe.ts guards the expo-observe import so OTA updates reaching binaries built before these native modules were added fall back to no-ops instead of crashing at startup (runtimeVersion policy is appVersion). - Root layout is wrapped with AppMetricsRoot (SDK 55 equivalent of ObserveRoot) to record first render, configure() runs at module load with the app environment, and markInteractive() fires once the splash screen is hidden. No Expo SDK upgrade required: both packages support SDK 55, so expo stays at ~55.0.12. https://claude.ai/code/session_01TiJbAYJFJyaHTe9D7A1JmK
- lib/__tests__/observe.test.ts locks in the contract that the EAS Observe wrapper never throws when the native module is unavailable. - Inline eslint disable for the intentional require() in lib/observe.ts, matching the existing convention in lib/assets.ts and lib/utils/cardDetailsReveal.ts. https://claude.ai/code/session_01TiJbAYJFJyaHTe9D7A1JmK
Add EAS Observe integration for startup performance metrics
Replace the gray placeholder box on the unprovisioned agent onboarding state with the agent-wallet product image. Adds the asset to the registry in lib/assets.ts and renders it via expo-image with contentFit="contain". https://claude.ai/code/session_01AZ7i9i1YACRWSgDposkNPF
Surface a Passkey FAQ popup from the onboarding login-help prompt. The prompt now reads "Have trouble logging in? See our Passkey FAQs or Recover your account >", where "Passkey FAQs" opens the popup. - Add constants/passkey-faqs.tsx with the passkey FAQ content - Add PasskeyFaqModal built on the existing ResponsiveModal + FAQ components, reusing the existing vault Lottie asset for the header graphic - Wire the modal into both the mobile and desktop onboarding layouts https://claude.ai/code/session_01C4Jn2RkCUkojpkS83nynmg
Add agent wallet image to agent setup screen
The desktop Manage dropdown rendered its menu as an absolutely-positioned view inside the sticky header. Trapped in the header's stacking context, the menu was painted beneath the card art, hiding the dropdown items. Replace the hand-rolled dropdown with the portal-based DropdownMenu (rendered at the root PortalHost), matching the existing TransactionDropdown pattern. Portal content paints above all page content, so the menu now appears over the card art. This also drops the manual outside-click handler in favor of the primitive's built-in dismiss behavior. https://claude.ai/code/session_01EQ1VUeY2NyNkPANuzfn5Sc
Add Passkey FAQ modal to onboarding flow
Refactor card details dropdown to use DropdownMenu component
Swap in the new gradient agent-wallet.png and render it as a background layer behind the onboarding card instead of an inline image (the exported art had too much empty space above/below when shown inline). - Container is now relative + overflow-hidden so the background respects the rounded corners. - Image is absolutely positioned, top-aligned, full-width at h-[400px] with contentFit="contain" + contentPosition="top" (top-center). - A 300px spacer View reserves the image area; title/description/button render on top. https://claude.ai/code/session_01AZ7i9i1YACRWSgDposkNPF
- Widen modal to 40rem and reduce desktop padding from 2rem to 1rem - Drop the gaps above the title (close->vault, vault->title) since the vault Lottie already includes top/bottom spacing; keep the gap between the title and the FAQ list https://claude.ai/code/session_01C4Jn2RkCUkojpkS83nynmg
Refine passkey FAQ modal layout
Use gradient agent-wallet image as onboarding card background
Add USDT to the Base and BNB Chain bridge token lists so it appears in the Add Funds and Deposit to Savings token selectors (which render from BRIDGE_TOKENS), matching the backend bridge-deposit support: - Base: Tether USD 0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2 (6 dp) - BNB Chain: Binance-Peg BSC-USD 0x55d398326f99059fF775485246999027B3197955 (18 dp) Derive token decimals from the bridge config in the Add Funds wallet-transfer flow (form + useTransferToWallet) instead of hardcoding stablecoins to 6 dp, so the 18-decimal BNB Chain stablecoins (USDC/USDT) transfer and display correctly. https://claude.ai/code/session_012jF7BVuvcndnadBoePaAWG
Support 18-decimal stablecoins on BNB Chain
The activity list re-derives every successful BRIDGE_DEPOSIT's displayed status from a LayerZero delivery check plus a card-transaction lookup that matches crypto_transaction_details.tx_hash. Only the deprecated Bridge card API returns that field — Rain card transactions carry no crypto tx details — so for Rain users the check could never pass and every deposit to card rendered as "Pending" forever (and was then hidden as a stuck transaction after 24h), even when the activity was already SUCCESS in the store and on the activity detail page. Gate the override to the Bridge provider: Rain rows now trust the activity status, which the backend completes from Rain collateral webhooks. Also skips the now-pointless layerzeroscan polling for Rain users.
Addresses four card-deposit activity issues, all Rain-era:
- Instant SUCCESS: useProcessingActivitiesPolling / useTransactionReceiptPolling
marked any PROCESSING activity SUCCESS as soon as its SOURCE-chain receipt
mined. Stargate card deposits (BRIDGE_DEPOSIT, BORROW_AND_DEPOSIT_TO_CARD)
confirm on Fuse in seconds but take minutes to bridge, so they flipped to
SUCCESS before the funds arrived. Exclude cross-chain card-deposit types from
source-receipt promotion (new isSourceReceiptFinalizable); they now finalize
via the Rain collateral webhook (destination confirmation).
- "External wallet transfer" mislabel: BRIDGE_DEPOSIT is dual-use (real bridges
AND "Deposit … to Card"), but the static category map labels it
EXTERNAL_WALLET_TRANSFER. Add getTransactionCategory to relabel the card
variant (title contains "Card") as "Card deposit", used by both the list row
and the detail page.
- Duplicate row: a connect-wallet card deposit creates two card_deposit
activities — the frontend's trackingId and the backend workflow's
`${trackingId}_card`. Collapse them in deduplicateTransactions (keeping the
row with the on-chain hash), mirroring the savings two-step special-case.
- "U" placeholder icon: USDC.e (borrow-and-deposit-to-card symbol) missed the
'USDC' case in getTokenIcon (toUpperCase → 'USDC.E') and fell back to the
DefaultTokenIcon placeholder on the detail page. Map USDC.E to the USDC icon.
A connect-wallet (Wallet source) card deposit shows twice: the frontend card_deposit activity plus a Blockscout/Alchemy-synced "Send USDC" row for the on-chain USDC transfer. They carry different tx hashes (the transfer vs the approve userOp), so hash dedup misses them, and the existing second-pass SEND removal only matched BRIDGE_DEPOSIT / CARD_TRANSACTION — not CARD_DEPOSIT. - Introduce CARD_DEPOSIT_ACTIVITY_TYPES (adds CARD_DEPOSIT and BORROW_AND_DEPOSIT_TO_CARD) and use it in isCardDeposit, the collision priority map, and the second-pass SEND removal, so the redundant Send is dropped for every card-deposit type. - The surviving card_deposit had only a hash (no url), so the detail page's Explorer row (which required url) was hidden. Derive the explorer URL from hash + chainId when url is missing, so the deposit always links on-chain.
The card_deposit row's own hash is the approve userOp for connect-wallet deposits, not the actual transfer, so the detail page's Explorer link pointed at the approve. Add resolveCardDepositTransferTx to find the sibling on-chain USDC transfer (the Blockscout-synced Send, removed from the list but still in cachedActivities) by matching toAddress + chain within 5 minutes, and link the Explorer row to that tx's hash + url instead. Falls back to the activity's own hash (deriving the url from chain) when no sibling transfer exists.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.