Skip to content

Qa#1505

Open
LiorAgnin wants to merge 316 commits into
masterfrom
qa
Open

Qa#1505
LiorAgnin wants to merge 316 commits into
masterfrom
qa

Conversation

@LiorAgnin
Copy link
Copy Markdown
Contributor

@LiorAgnin LiorAgnin commented Feb 15, 2026

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 kyc flow with Didit (new kyc.native.tsx for mobile and updated web embedding), and adds a separate bridge-kyc Persona 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_config ignore, Expo plugins + EAS extension provisioning), and removes Fingerprint.com usage/envs and signup fingerprint collection. Also adds a hidden savings-old route 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.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 15, 2026

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

Project Deployment Actions Updated (UTC)
solid-app-staging Ready Ready Preview, Comment Jun 3, 2026 1:18pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
solid-app Ignored Ignored Preview Jun 3, 2026 1:18pm

Request Review

Comment thread store/useActivityStore.ts
Comment thread components/Transaction/index.tsx
Comment thread app/(protected)/(tabs)/activity/[clientTxId].tsx
Comment thread hooks/useCardWithdrawals.ts
Comment thread hooks/useGeoCompliance.ts
Comment thread lib/api.ts
Comment thread components/Markdown.tsx Outdated
Comment thread components/Card/WithdrawCardFundsModal.tsx
Comment thread components/CustomTabBar.tsx Outdated

// 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'];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

>
<Text className="text-base font-bold text-black">Done</Text>
</Button>
)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

MusabShakeel576 and others added 30 commits May 20, 2026 17:30
…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
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.

4 participants