feat(perps): default pay token when no balance and Add funds CTA on market details#26281
Conversation
…erps balance Co-authored-by: Cursor <cursoragent@cursor.com>
…on market details Co-authored-by: Cursor <cursoragent@cursor.com>
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
…ndition Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…t unhandled rejection Co-authored-by: Cursor <cursoragent@cursor.com>
…t chain Co-authored-by: Cursor <cursoragent@cursor.com>
…rage Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…nce and perpsStatePreset Co-authored-by: Cursor <cursoragent@cursor.com>
| jest.mock('react-redux', () => ({ | ||
| useSelector: jest.fn(), | ||
| })); | ||
|
|
||
| jest.mock('./index', () => ({ | ||
| usePerpsNetwork: jest.fn(() => 'mainnet'), | ||
| })); | ||
|
|
||
| jest.mock('./usePerpsPaymentTokens', () => ({ | ||
| usePerpsPaymentTokens: jest.fn(() => []), | ||
| })); | ||
|
|
||
| const mockUseSelector = jest.requireMock<typeof import('react-redux')>( | ||
| 'react-redux', | ||
| ).useSelector as jest.MockedFunction< | ||
| (typeof import('react-redux'))['useSelector'] | ||
| >; | ||
| const mockUsePerpsNetwork = jest.requireMock<typeof import('./index')>( | ||
| './index', | ||
| ).usePerpsNetwork as jest.MockedFunction< | ||
| (typeof import('./index'))['usePerpsNetwork'] | ||
| >; | ||
| const mockUsePerpsPaymentTokens = jest.requireMock< | ||
| typeof import('./usePerpsPaymentTokens') | ||
| >('./usePerpsPaymentTokens').usePerpsPaymentTokens as jest.MockedFunction< | ||
| (typeof import('./usePerpsPaymentTokens'))['usePerpsPaymentTokens'] | ||
| >; |
There was a problem hiding this comment.
way too many mocks. Can we use @testing-library/react-hooks? This look like AI verbose. Don't trust this a lot for unit testing.
| const hyperliquidChainId = | ||
| currentNetwork === 'testnet' | ||
| ? HYPERLIQUID_TESTNET_CHAIN_ID | ||
| : HYPERLIQUID_MAINNET_CHAIN_ID; |
There was a problem hiding this comment.
we need to make thinks more generic for other providers integration.
| {hasLongShortButtons && | ||
| !existingPosition && | ||
| !isAtOICap && | ||
| showAddFundsCTA && ( |
There was a problem hiding this comment.
can we have a more descriptive const above?
| {hasLongShortButtons && | ||
| !existingPosition && | ||
| !isAtOICap && | ||
| !showAddFundsCTA && ( |
There was a problem hiding this comment.
same here, reuse the const
aganglada
left a comment
There was a problem hiding this comment.
Don't trust a lot AI to do your unit test, use it to discover edge cases. But mocks will not cover most of the real cases.
…implify market view conditions
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
Tag selection rationale:
The changes are well-scoped to Perps functionality with comprehensive unit tests. Risk is medium because while the changes are isolated to Perps, they affect user-facing payment flows and add a new CTA button. Performance Test Selection: |
The committed fixture schema is out of date. To update, comment: |
|



Description
useDefaultPayWithTokenWhenNoPerpsBalance: returns the allowlist token with highest balance whenavailableBalance <= PERPS_MIN_BALANCE_THRESHOLD, otherwisenull. RespectsperpsPayWithAnyTokenAllowlistAssets.PERPS_MIN_BALANCE_THRESHOLD(0.01) inperpsConfig.tsfor the "no perps balance" threshold and minimum token balance for preselection.setPayToken+setSelectedPaymentToken) or sets selected payment to Perps balance (null).usePerpsLiveAccount, the new hook, anduseConfirmNavigation. WhenshowAddFundsCTA(no position, not at OI cap, balance < 0.01, and hook returnsnull), footer shows "Add funds" only;handleAddFundscallsnavigateToConfirmation({ stack: Routes.PERPS.ROOT })thendepositWithConfirmation(). Otherwise Long/Short buttons are shown as before.Changelog
CHANGELOG entry: When users have no perps balance, the app now preselects the allowlist token with the highest balance for payment when available, and shows an "Add funds" button on the market details screen when no token can be preselected.
Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2569
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Changes the perps funding/payment-token selection and deposit entrypoint from
PerpsMarketDetailsView, which can affect how users land in confirmations and which token is preselected. Logic is gated by balance thresholds/allowlists but still touches trading UX flows and error handling.Overview
Improves the zero/low perps balance onboarding flow by adding
useDefaultPayWithTokenWhenNoPerpsBalance, which selects the allowlisted pay-with-any-token asset with the highest fiat balance (abovePERPS_MIN_BALANCE_THRESHOLD) while excluding the current provider’s native chain.PerpsPayRownow uses this hook to auto-preselect that token when pending trade config has no selected token; otherwise it keeps defaulting to Perps balance (null).PerpsMarketDetailsViewconditionally replaces Long/Short with a single Add funds CTA when balance is below threshold and no default token exists; pressing it navigates to the Perps confirmation stack and triggersdepositWithConfirmation(), logging any deposit errors.Adds supporting config (
PERPS_MIN_BALANCE_THRESHOLD, provider chain-id mapping +getPerpsProviderChainId), expands Perps view state fixtures for component tests, and updates/adds unit tests covering the new behaviors.Written by Cursor Bugbot for commit 13930fc. This will update automatically on new commits. Configure here.