Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
||
| // Visible tabs - these are the main navigation tabs | ||
| const VISIBLE_TAB_NAMES = ['index', 'savings', 'card', 'activity']; | ||
| const VISIBLE_TAB_NAMES = ['index', 'savings', Platform.OS === 'ios' ? null : 'card', 'activity']; |
There was a problem hiding this comment.
Array contains null value on iOS
Low Severity
The VISIBLE_TAB_NAMES array includes null when Platform.OS === 'ios', creating an array like ['index', 'savings', null, 'activity']. While this doesn't cause runtime errors (since route.name won't match null), it's semantically incorrect and adds unnecessary overhead. The array should either be constructed conditionally or filtered with .filter(Boolean) to remove falsy values.
| > | ||
| <Text className="text-base font-bold text-black">Done</Text> | ||
| </Button> | ||
| )} |
There was a problem hiding this comment.
Minimum withdrawal threshold traps user funds
High Severity
The withdraw button now only appears when parseFloat(availableBalance) >= 1, replacing the previous behavior where the button was always visible but disabled when balance was zero or less. Users with balances between $0 and $1 (e.g., $0.50) cannot withdraw their funds because the withdraw button is hidden and replaced with a "Done" button that only closes the modal, effectively trapping their money.
…loader-oX5Fh-qa fix(savings): keep page mounted on vault switch, show inline skeletons
…ysical card shipping with Rain's actual displayName rule Rain's only character restriction is on configuration.displayName for physical cards (alphanumeric, spaces, periods, hyphens), and is ignored for virtual cards entirely. The Rain KYC form was rejecting valid applicants with non-Latin names (Cyrillic, Arabic, CJK) for both virtual and physical cards. - RainKyc schema: removed Latin-only regex on firstName/lastName. - OrderPhysicalCardModal: relaxed the shipping name regex to match Rain's documented rule (also allow digits and periods) since these names are embossed as the physical card's displayName.
…tion-rain-AeJe0 Refactor name validation for Rain KYC and physical card forms
Fetch and display the safe's native ETH balance on Arbitrum alongside Ethereum, Fuse, and Base. Users who sent ETH to their Arbitrum safe address can now see and transfer those funds from the Send flow.
Add Arbitrum network support to balance fetching
@didit-protocol/sdk-react-native's Expo plugin injects the Podfile entry pointing at .../sdk-ios/main/DiditSDK.podspec. On 2026-05-25 main was bumped to 4.0.0, which no longer satisfies the SdkReactNative.podspec constraint of `DiditSDK ~> 3.2`, so pod install fails on every iOS EAS build with a CocoaPods version conflict. Patch the plugin to use the 3.2.13 tagged podspec — the latest 3.2.x release that still ships the flat DiditSDK.xcframework + OpenSSL.xcframework the react-native-quick-crypto patch relies on for OpenSSL.
…ments #2093 pinned the DiditSDK pod to 3.2.13, which gets pod install past the version constraint but introduces a new fault: VerificationError gained a .retryBlocked case starting in 3.2.10, and @didit-protocol/sdk-react-native@3.2.8's DiditSdkBridge.swift mapErrorType() switch only handles .sessionExpired / .networkError / .cameraAccessDenied / .unknown. Xcode errors out with "switch must be exhaustive" during the Fastlane step. 3.2.9 is the latest DiditSDK iOS release before the enum was extended, so the wrapper's 4-case switch is still exhaustive against it. Verified by diffing the swiftinterface across 3.2.8 / 3.2.9 / 3.2.10 / 3.2.13 — the .retryBlocked case lands in 3.2.10. The wrapper's other switches (VerificationStatus, VerificationResult) are unchanged across 3.2.x.
fix(ios): pin DiditSDK pod to 3.2.13 instead of tracking main
The send form pulled balance from wagmi's useBalance, which has a 5-minute default staleTime in the app's QueryClient and isn't invalidated by the safe-account send flow (useSend doesn't go through useTransactionAwait). After a previous send, the token picker — fed by useWalletTokens (5s polling + SSE-invalidated) — showed the fresh balance, but selecting a token brought the user back to a SendForm displaying wagmi's stale cache. Drop wagmi's useBalance and source the balance from useWalletTokens instead, looking up the live token by contractAddress + chainId. The picker and the send screen now read from the same query. Max button also lost precision: it did `balanceAmount.toString()` where balanceAmount was Number(formatUnits(wei, decimals)). For balances whose low-order wei round up when squeezed into a float64, parseUnits later produced a BigInt above the actual on-chain balance and the transfer reverted — while Send stayed enabled because the Zod check was a JS-Number compare. Build the max string from the wei BigInt via formatUnits so it round-trips through parseUnits exactly, and validate amount <= balance in wei so the button can't enable for amounts that exceed the balance after rounding.
…vZYP Replace wagmi useBalance with useWalletTokens for fresher balance data
The form uses react-hook-form's onChange mode, which only re-runs the
Zod schema when the Controller's TextInput fires onChange. handleMaxPress
just calls setValue('amount', maxAmount), which writes the value but
doesn't run validation, so isValid stays at its prior value (false if
the user hadn't typed first) and the Review button remains disabled.
Call trigger('amount') after setValue — matches the pattern already
used in CardRepayForm and RegularWithdrawForm for the same problem.
…DOC-qa fix(send): trigger validation on Max so Review enables immediately
…or fallback useRewardsUserData/useTierBenefits/useRewardsConfig used enabled: !!getJWTToken(), but getJWTToken returns null on web, so the queries never ran and the rewards page hung in <PageLayout isLoading /> forever. Web auth rides on cookies via credentials: 'include'; mobile is already inside (protected). Also surface a retry UI when the data fetch errors instead of silently spinning. https://claude.ai/code/session_01SREGQCDTiC5CNZRJkjVFj3
Add error state handling and retry functionality to rewards page
Adds a /rescue-token screen that lets users move USDC accidentally sent to their Turnkey signer address (user.walletAddress) into their Safe (user.safeAddress) on Ethereum, signed via the existing passkey flow. Displays the stuck balance, destination Safe address, and the ETH gas required with an info tooltip explaining users can reach out to the Solid team if they can't cover gas. https://claude.ai/code/session_01U9boKN8kBrUytLY72BfSbB
Adds a RESCUE_TOKEN transaction type (incoming wallet transfer) and wires useRescueToken through createActivity/updateActivity so the recovery shows up in the activity feed: PENDING when the user signs, PROCESSING once the tx hash is broadcast (with Etherscan link), then SUCCESS or FAILED based on the receipt. https://claude.ai/code/session_01U9boKN8kBrUytLY72BfSbB
Call POST /accounts/v1/users/platforms once per authenticated session with Platform.OS, so the backend can verify "downloaded the app" Layer3 quests via /v1/layer3-quests/check-native-app.
Track user platform (iOS/Android/Web) for quest verification
feat(rescue-token): add /rescue-token page to recover stuck USDC (qa)
Fetch BSC balances (ERC-20 via Alchemy + native BNB via viem) the same way Arbitrum, Base, and Ethereum are handled. Wire BSC through wagmi chains/transports and add BNB to native token + CoinGecko price lookups. The Send token list now includes BSC tokens and falls back to the viem chain name when a chain isn't in BRIDGE_TOKENS, so BSC entries don't crash the row label. BSC is Alchemy-only — Blockscout has no BSC instance and the existing fallback returns [] gracefully on Alchemy failure. Unblocks users who accidentally sent BEP-20 USDC (or any other token) to their Solid safe address on BSC.
feat(balances): enable BSC chain to surface stuck funds
Route notification taps by the `type` the backend sets in the payload. Card transaction notifications now open the card screen instead of always landing on home, completing the existing deep-link TODO in the tap handler. https://claude.ai/code/session_01Wxoh4LSUztzSkDBgb66n67
Add deep linking support for push notifications
…r-side These five events are now emitted server-side via the backend Amplitude Node SDK. Add a per-call `amplitude` option to track() and set it to false at the matching client call sites so Amplitude no longer double-counts them. Firebase + GTM still fire, so web conversion / ad attribution is preserved. - Account Created: SIGNUP_COMPLETED (signup/creating). - Savings Deposit: DEPOSIT_COMPLETED in the 5 backend-routed deposit hooks (EOA USDC/Fuse/ETH, Solid USDC/ETH). Client-only deposits (useDeposit, useDepositFromSolidFuse) and the add-funds-to-wallet step (useTransferToWallet) keep firing Amplitude — the backend does not track those paths. - Card Deposit: CARD_DEPOSIT_COMPLETED (useCardDepositPoller fallback). - Card Borrow: BRIDGE_TO_ARBITRUM_COMPLETED in useBorrowAndDepositToCard only (the generic bridge/swap-to-card hooks are not borrows and keep firing Amplitude). trackIdentity calls are kept (they set the Amplitude user id/properties). https://claude.ai/code/session_011g7dN8ScZ3Yr4U6fhYEsq5
Suppress client Amplitude for server-side emitted events
…denials When Didit (KycStatus.REJECTED) or Rain (RainApplicationStatus.DENIED) KYC reaches a final denied decision, the first activation step no longer renders an action button. These outcomes cannot be manually overridden or resubmitted, so the previous "Contact support" (Rain) and "Retry KYC" (Didit) buttons were misleading dead ends. - getKYCButtonText: Rain DENIED returns no button (LOCKED/CANCELED keep "Contact support" since support can still assist with those). - isRainKYCButtonDisabled: DENIED has no actionable onPress. - getStepButtonText / isStepButtonDisabled: Didit REJECTED returns no button and no onPress. Bridge endorsement REVOKED still allows "Retry KYC". - getStepDescription: Didit REJECTED fallback no longer promises a retry. - handleRainKYCPress: drop the now-unreachable DENIED -> Intercom branch. https://claude.ai/code/session_01S2muieprRUo3BGSh8yKBtR
Treat KYC DENIED status as final decision with no action button
Add Binance-Peg USD Coin (USDC, 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d)
on BNB Chain as a new bridge deposit source in the Add Funds ("send from
your crypto wallet" + "share your deposit address") and Deposit-to-Savings
(USDC vault) flows, alongside Polygon/Arbitrum.
- constants/bridge.ts: BSC entry (USDC, 18 decimals, isPermit false) + gold
circular BNB icon; add optional decimals to BridgeToken type
- lib/thirdweb.ts: register bsc chain so switchChain works in the
connected-wallet deposit flow
- hooks/useDepositFromEOA.ts: derive source-token decimals from the bridge
config instead of hardcoding 6 (BSC USDC is 18 decimals)
- constants/alchemy.ts: enable BSC token-balance fetching via Alchemy
- components/Coin/BalanceBreakdown.tsx: map the BSC chain icon + name in the
coin detail network breakdown
- assets/images/bsc.png + lib/assets.ts: circular gold BNB Chain icon
https://claude.ai/code/session_013JRn2tvDbZssJGAx4b6gJX
Add BNB Chain support to bridge and balance breakdown


Note
High Risk
Updates KYC and card funding/management flows across web and native (including new third-party SDKs and iOS extension targets), which are user-verification and payments-adjacent paths with higher regression risk.
Overview
Adds multi-provider card support (Bridge vs Rain) across the app, including provider-aware formatting, deposit address selection (contracts vs
funding_instructions), card status routing, and gating of actions like deposit/withdraw/freeze/PIN management based on provider and customer/KYC state.Reworks KYC: replaces the existing Persona-based
kycflow with Didit (newkyc.native.tsxfor mobile and updated web embedding), and adds a separatebridge-kycPersona page for Bridge-only KYC; card KYC entry now redirects to the correct provider flow.Introduces MeaWallet MPP integration and iOS Wallet Extensions (new extension entrypoints + docs), adds registry/config plumbing (
.npmrc,meawallet/mea_configignore, Expo plugins + EAS extension provisioning), and removes Fingerprint.com usage/envs and signup fingerprint collection. Also adds a hiddensavings-oldroute for side-by-side savings calculation comparison and minor home/coin chart UX/data-fetch adjustments (spin-and-win card, CoinGecko native token charting, savings summary backend hook).Written by Cursor Bugbot for commit 1f5b304. This will update automatically on new commits. Configure here.