Skip to content

Comments

PRO-3833-USDC directional changes for Sell sides#446

Merged
vignesha22 merged 11 commits intostagingfrom
feature/PRO-3833-USDC-directional-changes-for-Sell-sides
Nov 4, 2025
Merged

PRO-3833-USDC directional changes for Sell sides#446
vignesha22 merged 11 commits intostagingfrom
feature/PRO-3833-USDC-directional-changes-for-Sell-sides

Conversation

@vignesha22
Copy link
Contributor

@vignesha22 vignesha22 commented Oct 30, 2025

Description

  • Changed the USDC direction on sell side by default it will select where the user has most USDC balance as destination chainId and can be changed by the user
  • Added Settings page for Buy/Sell side on pulse
  • Added custom inputs so that user can change the default settings

How Has This Been Tested?

  • Tested locally

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Summary by CodeRabbit

  • New Features

    • Settings menu to choose default settlement chain and customize buy/sell presets; preferences apply across Buy/Sell flows and previews.
    • Settings button added to main interface; settings panel includes chain picker, buy amount and sell percent presets, refresh and confirm actions.
  • Behavior

    • Buy/Sell quick-amount controls use customizable presets; settlement chain selection influences fee/offer estimation, previews, and execution.
    • UI auto-selects settlement chain based on wallet stable-coin balances and syncs selection into flows.
  • Style

    • Esc control updated from text to an icon.
  • Tests

    • Tests updated for "Settings" label, class-based styling checks, and new props/behaviors in Buy/Sell and preview tests.

@vignesha22 vignesha22 requested review from IAmKio and RanaBug October 30, 2025 09:18
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 30, 2025

Deploying x with  Cloudflare Pages  Cloudflare Pages

Latest commit: 922ae9e
Status: ✅  Deploy successful!
Preview URL: https://36cf0b5d.x-e62.pages.dev
Branch Preview URL: https://feature-pro-3833-usdc-direct.x-e62.pages.dev

View logs

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2025

Walkthrough

HomeScreen now reads wallet portfolio, computes per-chain stable balances to determine maxStableCoinBalance and selectedChainIdForSettlement, exposes a SettingsMenu for custom buy/sell presets and settlement chain, and threads settlement-chain and preset props into Buy, Sell, PreviewSell, relay, and gas-estimation flows.

Changes

Cohort / File(s) Summary
HomeScreen & tests
src/apps/pulse/components/App/HomeScreen.tsx, src/apps/pulse/components/App/tests/HomeScreen.test.tsx
Queries wallet portfolio, computes per-chain stable balances → maxStableCoinBalance, manages selectedChainIdForSettlement, customBuyAmounts, customSellAmounts, toggles displaySettingsMenu, renders SettingsMenu. Tests updated to expect "Settings" label and class-based styling checks.
Buy component & tests
src/apps/pulse/components/Buy/Buy.tsx, src/apps/pulse/components/Buy/tests/Buy.test.tsx
BuyProps now accept maxStableCoinBalance and customBuyAmounts; removed internal per-chain balance calculation; quick-amount presets come from customBuyAmounts; hooks/messages use provided chainId/balance; tests updated to pass new props.
Sell, PreviewSell & tests
src/apps/pulse/components/Sell/Sell.tsx, src/apps/pulse/components/Sell/PreviewSell.tsx, src/apps/pulse/components/Sell/tests/*
Added customSellAmounts and selectedChainIdForSettlement props; sell flow, USDC resolution, gas estimation, offer fetch and execute now use settlement chain (toChainId/selectedChainIdForSettlement); quick-amounts driven by customSellAmounts; tests adapted accordingly.
SettingsMenu (new)
src/apps/pulse/components/Settings/SettingsMenu.tsx
New component: settlement chain selector, four custom buy amount inputs, four custom sell percentage inputs, refresh/close controls, validation, keyboard/click-outside handling, and commit via setters to parent.
Misc UI small changes
src/apps/pulse/components/Misc/Esc.tsx, src/apps/pulse/components/Misc/Settings.tsx
Esc button now uses an SVG icon; Settings component signature changed to accept { onClick }, wired to button, data-testid added and aria label updated to "Settings".
Relay / gas hooks & tests
src/apps/pulse/hooks/useRelaySell.ts, src/apps/pulse/hooks/useGasEstimation.ts, src/apps/pulse/hooks/tests/useRelaySell.test.tsx
Added toChainId wiring across SellParams, getBestSellOffer, buildSellTransactions, executeSell and into useGasEstimation; destination chain threaded into quote/tx building and gas estimation; tests updated to include toChainId.
Utils helper
src/apps/pulse/utils/utils.tsx
New helper getStableCurrencyBalanceOnEachChain aggregates stable-currency balances per chain from wallet portfolio assets.

Sequence Diagram(s)

sequenceDiagram
    participant HS as HomeScreen
    participant WP as WalletPortfolioQuery
    participant SM as SettingsMenu
    participant Buy as Buy
    participant Sell as Sell
    participant Relay as Relay (useRelaySell / useGasEstimation)

    HS->>WP: fetch walletPortfolioData
    WP-->>HS: walletPortfolioData
    HS->>HS: compute per-chain stable balances → maxStableCoinBalance
    HS->>HS: set selectedChainIdForSettlement

    alt Open Settings
        HS->>SM: render (customBuyAmounts, customSellAmounts, selectedChainId)
        SM-->>HS: commit updated presets & selectedChainId
    end

    HS->>Buy: pass maxStableCoinBalance + customBuyAmounts
    HS->>Sell: pass customSellAmounts + selectedChainIdForSettlement

    Sell->>Relay: request offer / build txs (toChainId = selectedChainIdForSettlement)
    Relay-->>Sell: sell offer / txs (targeting toChainId)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • HomeScreen: portfolio fetch, per-chain balance computation and syncing selectedChainIdForSettlement.
    • useRelaySell / useGasEstimation: propagation of toChainId into quote/tx/fee flows.
    • SettingsMenu: input validation, keyboard/click-outside handling, commit semantics.
    • Cross-component prop/signature changes (Buy/Sell/PreviewSell) and corresponding tests.

Possibly related PRs

Suggested reviewers

  • IAmKio
  • RanaBug

Poem

🐇 I hopped through ledgers, counted coins on each chain,
I set a default settlement, saved presets in a pane.
I clicked my little menu, set buy and sell with care,
Now props flow tidy everywhere — I nibble code with flair. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly reflects the main change: updating USDC directional logic on the sell side to default to the chain with the highest balance.
Description check ✅ Passed The description covers the key changes (USDC direction, Settings page, custom inputs) and includes testing details and types of changes, though testing could be more thorough.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/PRO-3833-USDC-directional-changes-for-Sell-sides

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/apps/pulse/hooks/useGasEstimation.ts (1)

158-169: Missing toChainId in useEffect dependency array.

The useEffect triggers gas estimation when dependencies change, but it's missing toChainId in its dependency array. Since estimateGasFees (called via estimateGasFeesRef.current()) depends on toChainId (line 151), gas estimation won't re-run when the user changes the settlement chain.

Apply this diff:

   useEffect(() => {
     if (
       sellOffer &&
       sellToken &&
       kit &&
       tokenAmount &&
       estimateGasFeesRef.current &&
       !isPaused
     ) {
       estimateGasFeesRef.current();
     }
-  }, [sellOffer, sellToken, kit, tokenAmount, isPaused]);
+  }, [sellOffer, sellToken, kit, tokenAmount, isPaused, toChainId]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebaf571 and 5c901e8.

⛔ Files ignored due to path filters (5)
  • src/apps/pulse/components/App/tests/__snapshots__/AppWrapper.test.tsx.snap is excluded by !**/*.snap
  • src/apps/pulse/components/App/tests/__snapshots__/HomeScreen.test.tsx.snap is excluded by !**/*.snap
  • src/apps/pulse/components/Buy/tests/__snapshots__/PreviewBuy.test.tsx.snap is excluded by !**/*.snap
  • src/apps/pulse/components/Sell/tests/__snapshots__/PreviewSell.test.tsx.snap is excluded by !**/*.snap
  • src/apps/pulse/components/Sell/tests/__snapshots__/Sell.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (14)
  • src/apps/pulse/components/App/HomeScreen.tsx (8 hunks)
  • src/apps/pulse/components/App/tests/HomeScreen.test.tsx (1 hunks)
  • src/apps/pulse/components/Buy/Buy.tsx (6 hunks)
  • src/apps/pulse/components/Buy/tests/Buy.test.tsx (3 hunks)
  • src/apps/pulse/components/Misc/Esc.tsx (2 hunks)
  • src/apps/pulse/components/Misc/Settings.tsx (1 hunks)
  • src/apps/pulse/components/Sell/PreviewSell.tsx (8 hunks)
  • src/apps/pulse/components/Sell/Sell.tsx (4 hunks)
  • src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx (2 hunks)
  • src/apps/pulse/components/Sell/tests/Sell.test.tsx (2 hunks)
  • src/apps/pulse/components/Settings/SettingsMenu.tsx (1 hunks)
  • src/apps/pulse/hooks/tests/useRelaySell.test.tsx (4 hunks)
  • src/apps/pulse/hooks/useGasEstimation.ts (3 hunks)
  • src/apps/pulse/hooks/useRelaySell.ts (9 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: RanaBug
PR: pillarwallet/x#391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.
📚 Learning: 2025-09-09T12:40:15.629Z
Learnt from: RanaBug
PR: pillarwallet/x#391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.

Applied to files:

  • src/apps/pulse/components/Sell/tests/Sell.test.tsx
  • src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx
  • src/apps/pulse/components/Sell/Sell.tsx
  • src/apps/pulse/components/Sell/PreviewSell.tsx
  • src/apps/pulse/components/Buy/Buy.tsx
  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-08-20T09:14:16.888Z
Learnt from: RanaBug
PR: pillarwallet/x#374
File: src/apps/pillarx-app/index.tsx:12-12
Timestamp: 2025-08-20T09:14:16.888Z
Learning: In this codebase, Transaction Kit providers are set up at the container level (src/containers/Authorized.tsx), not at individual app component levels. App components like src/apps/pillarx-app/index.tsx are children that consume the context through the provider tree.

Applied to files:

  • src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx
  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-08-12T07:42:24.656Z
Learnt from: IAmKio
PR: pillarwallet/x#351
File: src/apps/pulse/utils/intent.ts:44-53
Timestamp: 2025-08-12T07:42:24.656Z
Learning: In the Pulse app's intent utilities (src/apps/pulse/utils/intent.ts), the team has chosen to use floating-point arithmetic for token amount calculations despite potential precision issues, accepting JavaScript's decimal place limitations as a valid trade-off for their use case.

Applied to files:

  • src/apps/pulse/components/Buy/Buy.tsx
📚 Learning: 2025-03-28T09:22:22.712Z
Learnt from: RanaBug
PR: pillarwallet/x#275
File: src/apps/the-exchange/components/DropdownTokensList/DropdownTokenList.tsx:180-195
Timestamp: 2025-03-28T09:22:22.712Z
Learning: In the Exchange app, `swapTokenList` and `receiveTokenList` are derived from `searchTokenResult` when search is active, so including `searchToken` in the useEffect dependency array that uses these lists would be redundant as the lists will update when search results change.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
🧬 Code graph analysis (4)
src/apps/pulse/components/Settings/SettingsMenu.tsx (2)
src/utils/blockchain.ts (2)
  • CompatibleChains (321-323)
  • getLogoForChainId (165-199)
src/apps/pulse/components/Misc/Refresh.tsx (1)
  • Refresh (10-35)
src/apps/pulse/components/Sell/PreviewSell.tsx (1)
src/utils/blockchain.ts (1)
  • getLogoForChainId (165-199)
src/apps/pulse/components/Buy/Buy.tsx (1)
src/apps/pulse/utils/blockchain.ts (1)
  • isNativeToken (17-18)
src/apps/pulse/components/App/HomeScreen.tsx (5)
src/apps/pulse/constants/tokens.ts (1)
  • STABLE_CURRENCIES (13-15)
src/apps/pulse/components/Settings/SettingsMenu.tsx (1)
  • SettingsMenu (22-379)
src/apps/pulse/components/Misc/Refresh.tsx (1)
  • Refresh (10-35)
src/apps/pulse/components/Misc/Settings.tsx (1)
  • Settings (7-21)
src/apps/pulse/components/Buy/Buy.tsx (1)
  • Buy (69-663)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: unit-tests
  • GitHub Check: lint
🔇 Additional comments (32)
src/apps/pulse/components/Misc/Esc.tsx (1)

2-2: LGTM! Clean icon migration.

The replacement of text with an SVG icon improves UI consistency while maintaining accessibility and functionality.

Also applies to: 28-32

src/apps/pulse/hooks/tests/useRelaySell.test.tsx (1)

385-385: LGTM! Test coverage properly updated.

The addition of toChainId to test calls correctly exercises the new settlement chain functionality, including edge cases with unsupported chains.

Also applies to: 442-442, 512-512, 584-584

src/apps/pulse/components/App/tests/HomeScreen.test.tsx (1)

106-106: LGTM! Test updated for Settings button.

The test assertion correctly reflects the UI change from "Save" to "Settings" button.

src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx (1)

133-133: LGTM! Test properly updated for settlement chain.

The test correctly includes the new selectedChainIdForSettlement prop and passes it to executeSell, aligning with the production code changes.

Also applies to: 247-247

src/apps/pulse/components/Misc/Settings.tsx (1)

3-5: LGTM! Settings component properly enhanced.

The addition of the onClick handler, corrected aria-label, and test ID properly enables the Settings functionality while maintaining accessibility and testability.

Also applies to: 7-14

src/apps/pulse/components/Buy/tests/Buy.test.tsx (3)

198-202: LGTM! Test props properly extended.

The addition of maxStableCoinBalance and customBuyAmounts to mockProps correctly supports the new Buy component functionality.


402-405: LGTM! Proper handling of missing data.

Providing an empty portfolioTokens array when wallet portfolio data is undefined ensures consistent test behavior.


581-584: LGTM! Low balance scenario properly tested.

The test correctly exercises the insufficient balance warning by setting maxStableCoinBalance below the minimum required amount.

src/apps/pulse/components/Sell/Sell.tsx (4)

49-50: LGTM! Props properly defined.

The addition of customSellAmounts and selectedChainIdForSettlement props enables dynamic configuration of sell presets and settlement chain handling.


63-64: LGTM! Props properly destructured.

The new props are correctly extracted from the props object for use in the component.


94-94: LGTM! Settlement chain properly propagated.

Passing selectedChainIdForSettlement as toChainId to getBestSellOffer ensures sell quotes are calculated for the correct destination chain.


450-450: LGTM! Dynamic sell amounts enabled.

Replacing hardcoded values with customSellAmounts enables flexible configuration of quick-select amounts from parent components.

src/apps/pulse/components/Sell/PreviewSell.tsx (6)

39-39: LGTM! Settlement chain prop added.

The selectedChainIdForSettlement prop is properly defined and destructured for use throughout the component.

Also applies to: 51-51


84-84: LGTM! Gas estimation uses settlement chain.

Passing selectedChainIdForSettlement as toChainId to useGasEstimation ensures gas fees are estimated for the correct destination chain.


216-216: LGTM! USDC address resolved on settlement chain.

Using selectedChainIdForSettlement to get the USDC address correctly targets the destination chain where funds will be received.


252-252: LGTM! Quote refresh uses settlement chain.

The refresh logic correctly passes selectedChainIdForSettlement to ensure updated quotes are for the correct destination chain.


369-374: LGTM! Settlement chain passed to executeSell.

The execution call correctly includes selectedChainIdForSettlement as the third argument, enabling proper cross-chain settlement routing.


595-595: LGTM! UI reflects settlement chain.

The USDC display correctly uses selectedChainIdForSettlement for the chain logo and test ID, properly indicating where funds will be received.

Also applies to: 604-604

src/apps/pulse/components/Sell/tests/Sell.test.tsx (2)

71-85: LGTM!

Test props correctly updated to include portfolioTokens, maxStableCoinBalance, customSellAmounts, and selectedChainIdForSettlement, aligning with the component's new signature.


176-187: Good adjustment for conditional MAX button rendering.

The test correctly includes 'MAX' in customSellAmounts to ensure the MAX button is rendered, reflecting the dynamic button generation based on the preset array.

src/apps/pulse/hooks/useRelaySell.ts (4)

45-52: LGTM!

The addition of toChainId to SellParams enables cross-chain settlement. This parameter is properly propagated throughout the sell flow.


132-189: Correct usage of toChainId for destination chain settlement.

The USDC address resolution (line 146) and quote request (line 183) correctly use toChainId for the destination chain, enabling users to sell tokens and receive USDC on a different chain.


296-368: Proper chain-aware transaction building.

USDC address resolution (line 337) correctly uses toChainId for destination chain targeting, and the fee calculation logic properly computes the 1% platform fee on the settlement chain.


755-788: USDC fee transfer correctly targets settlement chain.

The fee transfer transaction (line 768) properly uses toChainId as the chainId, ensuring the 1% USDC fee is transferred on the settlement chain where the USDC will be received.

src/apps/pulse/components/Settings/SettingsMenu.tsx (4)

63-71: Verify the refresh handler implementation.

The refresh handler currently only simulates a 1-second delay without performing any actual refresh logic. Is this intentional as a placeholder, or should it trigger a data refresh (e.g., re-fetching portfolio balances or USDC amounts)?

If a real refresh is needed, consider adding the refresh logic here or documenting that this is intentionally a placeholder for future implementation.


280-314: LGTM! Buy amount input validation is sound.

The validation correctly:

  • Allows numeric input with optional decimals (line 299)
  • Prevents non-numeric characters
  • Applies sensible defaults on blur if the field is empty (line 306)

324-362: LGTM! Sell percentage validation properly constrains input.

The validation correctly:

  • Allows numeric input with optional decimals (line 343)
  • Enforces a maximum of 100% (line 345)
  • Applies sensible defaults on blur if the field is empty (line 353)

96-132: Proper keyboard and click-outside handling.

ESC key handling (lines 97-112) correctly closes the dropdown first before closing the menu, and click-outside handling (lines 115-132) properly closes the dropdown when clicking elsewhere. Both handlers clean up event listeners appropriately.

src/apps/pulse/components/Buy/Buy.tsx (4)

44-86: LGTM! Props correctly refactored for external balance/chain state.

The addition of maxStableCoinBalance and customBuyAmounts props successfully lifts state management to the parent component, enabling centralized control over balance, chain selection, and buy amount presets.


138-170: LGTM! Balance and chain logic correctly uses external prop.

The component now derives sumOfStableBalance from maxStableCoinBalance.balance (line 144) and uses maxStableCoinBalance.chainId for native token lookup (line 154). The dependency array (line 170) correctly includes maxStableCoinBalance.


192-239: Consider adding maxStableCoinBalance to the dependency array.

The useEffect includes sumOfStableBalance in its dependencies (line 233), but sumOfStableBalance is derived from maxStableCoinBalance.balance (line 144). To ensure the effect re-runs when the parent updates maxStableCoinBalance, consider including it directly in the dependency array.

Current approach may work if sumOfStableBalance always updates when maxStableCoinBalance changes, but explicit inclusion would make the dependency clearer and more robust:

   }, [
     sumOfStableBalance,
     usdAmount,
     setPayingTokens,
     walletPortfolioData?.result.data,
     dispensableAssets.length,
+    maxStableCoinBalance,
   ]);

600-637: LGTM! Button rendering correctly uses customizable presets.

The buttons are now dynamically rendered from customBuyAmounts (line 602), enabling users to customize their buy amount presets via the SettingsMenu.

Comment on lines +261 to +263
useEffect(() => {
setSelectedChainIdForSettlement(maxStableCoinBalance.chainId);
}, [maxStableCoinBalance.chainId]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Preserve user-selected settlement chain

Every time wallet balances refresh (manual refresh or the built-in 15 s timer), maxStableCoinBalance recalculates and this effect force-resets selectedChainIdForSettlement back to the highest-balance chain. That wipes out any manual choice the user made in Settings, so the new “user can change this selection” requirement can’t be satisfied for more than a few seconds. Please gate this auto-sync so it only runs until the user picks a chain themselves.

-  useEffect(() => {
-    setSelectedChainIdForSettlement(maxStableCoinBalance.chainId);
-  }, [maxStableCoinBalance.chainId]);
+  const [hasManualSettlementSelection, setHasManualSettlementSelection] =
+    useState(false);
+
+  const handleManualSettlementSelection = useCallback((chainId: number) => {
+    setSelectedChainIdForSettlement(chainId);
+    setHasManualSettlementSelection(true);
+  }, []);
+
+  useEffect(() => {
+    if (!hasManualSettlementSelection) {
+      setSelectedChainIdForSettlement(maxStableCoinBalance.chainId);
+    }
+  }, [maxStableCoinBalance.chainId, hasManualSettlementSelection]);

Then pass handleManualSettlementSelection down to SettingsMenu instead of the raw setSelectedChainIdForSettlement, and flip the manual-selection flag back to false if the user explicitly selects the computed default again.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/apps/pulse/components/App/HomeScreen.tsx around lines 261-263, the effect
currently forces selectedChainIdForSettlement to maxStableCoinBalance.chainId on
every balance refresh, which overwrites a user’s manual choice; change this to
only auto-sync while the user has not made a manual selection by introducing a
local boolean (e.g., hasManuallySelectedSettlement) default false, update the
effect to set selectedChainIdForSettlement from maxStableCoinBalance.chainId
only when hasManuallySelectedSettlement is false, add a
handleManualSettlementSelection function that sets selectedChainIdForSettlement
and sets hasManuallySelectedSettlement to true (and if the user picks the
computed default again, set hasManuallySelectedSettlement back to false), and
pass handleManualSettlementSelection into SettingsMenu instead of directly
passing setSelectedChainIdForSettlement.

@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) October 30, 2025 10:38 Inactive
/>
) : (
<>
<p className="flex text-base font-normal text-white/[.5] w-full text-center mb-6">
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is it Settings OR displaying the fact that this is a beta version. Teh beta version display should always show no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is it Settings OR displaying the fact that this is a beta version. Teh beta version display should always show no?

I made the whole home page inside the OR choice not only the para and Aldin asked me to remove that on settings page

Copy link
Collaborator

Choose a reason for hiding this comment

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

But so where is the beta version showing now?

setSumOfStableBalance(sum);
if (maxStableBalance < 2) {

setSumOfStableBalance(maxStableCoinBalance.balance);
Copy link
Collaborator

Choose a reason for hiding this comment

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

from my understanding the maxStableCoinBalance is on a specific chainId right? Should it not be the total of stable balances here?

onClick={onClose}
type="button"
aria-label="Close"
className="flex items-center justify-center"
Copy link
Collaborator

Choose a reason for hiding this comment

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

the component Esc is being used in several components, please make sure this styling is not specific to one component and does not affect other components

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's doing the same thing and I made it separate just because it shouldn't affect other components and have specifically for settings page

Copy link
Collaborator

Choose a reason for hiding this comment

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

Was this a design change or something? Just trying to understand why the ESC component changed here as it's a shared component

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No I wanted every button to follow the same design like settings and refresh

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok

}, [closeSettingsMenu, showChainDropdown]);

// Handle click outside to close dropdown and tooltip
useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

there is an existing hook for this handle click outside: useClickOutside

closeSettingsMenu();
};

// Handle ESC key to close settings
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is an existing hook for this handle ESC key: useKeyboardNavigation

}

const usdcAddress = getUSDCAddress(fromChainId);
const usdcAddress = getUSDCAddress(toChainId);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why has this changed from fromChainId to toChainId?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's what was the ticket description

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok fine...

chainId: fromChainId,
currency: normalizedFromTokenAddress,
toChainId: fromChainId,
toChainId,
Copy link
Collaborator

Choose a reason for hiding this comment

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

same question here

Copy link
Collaborator

@IAmKio IAmKio left a comment

Choose a reason for hiding this comment

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

Some minor changes

onClick={onClose}
type="button"
aria-label="Close"
className="flex items-center justify-center"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Was this a design change or something? Just trying to understand why the ESC component changed here as it's a shared component

Comment on lines 1002 to 1010
<div
className="flex flex-col w-full"
style={{
border: '2px solid #1E1D24',
minHeight: 264,
backgroundColor: '#1E1D24',
borderRadius: 16,
marginTop: 40,
}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we change the inline stiles here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was kept as it is that's why will change it to tailwind

Comment on lines 981 to 996
<span style={{ marginLeft: 14, marginRight: 10 }}>
<img
src={SearchIcon}
alt="search-icon"
width={12}
height={12}
/>
</span>
<div
className="flex-1"
style={{
marginLeft: 12,
backgroundColor: 'black',
borderRadius: 10,
width: 40,
height: 40,
justifyContent: 'center',
alignItems: 'center',
display: 'flex',
padding: '2px 2px 4px 2px',
color: 'grey',
textAlign: 'left',
opacity: 0.5,
height: 20,
fontSize: 13,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Change this inline styles please to tailwind

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was kept as it is that's why will change it to tailwind

@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) October 31, 2025 13:38 Inactive
@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) October 31, 2025 13:40 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/apps/pulse/components/Settings/SettingsMenu.tsx (1)

67-74: Convert comment to TODO docblock.

The inline comment at line 69 should be formatted as a proper TODO docblock rather than a plain comment.

Apply this diff:

-  const handleRefresh = async () => {
-    setIsRefreshing(true);
-    // Simulate a refresh action - you can add actual refresh logic here
-    await new Promise((resolve) => {
-      setTimeout(resolve, 1000);
-    });
-    setIsRefreshing(false);
-  };
+  /**
+   * TODO: Implement actual refresh logic
+   * Currently simulates a refresh action with a 1-second delay
+   */
+  const handleRefresh = async () => {
+    setIsRefreshing(true);
+    await new Promise((resolve) => {
+      setTimeout(resolve, 1000);
+    });
+    setIsRefreshing(false);
+  };
🧹 Nitpick comments (1)
src/apps/pulse/components/Settings/SettingsMenu.tsx (1)

47-64: Extract default values to constants for maintainability.

The default buy amounts and sell percentages are repeated in multiple locations (initialization, onBlur handlers at lines 289 and 336, and validation at lines 80-91). Extracting these to constants would improve maintainability.

Add constants before the component:

+const DEFAULT_BUY_AMOUNTS = ['10', '20', '50', '100'];
+const DEFAULT_SELL_PERCENTAGES = ['10', '25', '50', '75'];
+
 export default function SettingsMenu(props: SettingsMenuProps) {

Then update state initialization:

-  const [buyAmount1, setBuyAmount1] = useState(customBuyAmounts[0] || '10');
-  const [buyAmount2, setBuyAmount2] = useState(customBuyAmounts[1] || '20');
-  const [buyAmount3, setBuyAmount3] = useState(customBuyAmounts[2] || '50');
-  const [buyAmount4, setBuyAmount4] = useState(customBuyAmounts[3] || '100');
+  const [buyAmount1, setBuyAmount1] = useState(customBuyAmounts[0] || DEFAULT_BUY_AMOUNTS[0]);
+  const [buyAmount2, setBuyAmount2] = useState(customBuyAmounts[1] || DEFAULT_BUY_AMOUNTS[1]);
+  const [buyAmount3, setBuyAmount3] = useState(customBuyAmounts[2] || DEFAULT_BUY_AMOUNTS[2]);
+  const [buyAmount4, setBuyAmount4] = useState(customBuyAmounts[3] || DEFAULT_BUY_AMOUNTS[3]);

Apply similar changes to sell percentages and reference these constants in onBlur handlers and handleConfirm.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 255f937 and ea659b9.

📒 Files selected for processing (1)
  • src/apps/pulse/components/Settings/SettingsMenu.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.
🧬 Code graph analysis (1)
src/apps/pulse/components/Settings/SettingsMenu.tsx (4)
src/utils/blockchain.ts (2)
  • CompatibleChains (321-323)
  • getLogoForChainId (165-199)
src/apps/pulse/hooks/useKeyboardNavigation.ts (1)
  • useKeyboardNavigation (7-35)
src/apps/pulse/hooks/useClickOutside.ts (1)
  • useClickOutside (7-29)
src/apps/pulse/components/Misc/Refresh.tsx (1)
  • Refresh (10-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: lint
  • GitHub Check: unit-tests
  • GitHub Check: build

Comment on lines +275 to +294
<input
type="text"
inputMode="numeric"
value={item.value}
onChange={(e) => {
const { value } = e.target;
// Only allow empty string or valid numbers (including decimals)
if (value === '' || /^\d*\.?\d*$/.test(value)) {
item.setter(value);
}
}}
onBlur={(e) => {
// If empty on blur, set to default
if (e.target.value === '') {
item.setter(['10', '20', '50', '100'][index]);
}
}}
className="flex-1 bg-transparent text-white !text-[13px] font-medium outline-none w-full"
data-testid={`pulse-settings-buy-amount-${index + 1}`}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add accessibility labels and consider improving decimal validation.

Two concerns:

  1. Accessibility: The input fields lack aria-label attributes, which would improve screen reader support.

  2. Validation edge case: The regex /^\d*\.?\d*$/ allows incomplete decimals like "." or "5.". While the onBlur handler addresses empty strings, it doesn't normalize trailing decimals. For example, if a user types "5." and blurs, the value remains "5." rather than being normalized to "5".

Apply this diff to add aria-labels:

 <input
   type="text"
   inputMode="numeric"
+  aria-label={`Buy amount preset ${index + 1}`}
   value={item.value}

Optionally, enhance the onBlur handler to normalize trailing decimals:

   onBlur={(e) => {
-    // If empty on blur, set to default
-    if (e.target.value === '') {
+    const val = e.target.value;
+    if (val === '' || val === '.') {
       item.setter(['10', '20', '50', '100'][index]);
+    } else if (val.endsWith('.')) {
+      // Remove trailing decimal point
+      item.setter(val.slice(0, -1));
     }
   }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<input
type="text"
inputMode="numeric"
value={item.value}
onChange={(e) => {
const { value } = e.target;
// Only allow empty string or valid numbers (including decimals)
if (value === '' || /^\d*\.?\d*$/.test(value)) {
item.setter(value);
}
}}
onBlur={(e) => {
// If empty on blur, set to default
if (e.target.value === '') {
item.setter(['10', '20', '50', '100'][index]);
}
}}
className="flex-1 bg-transparent text-white !text-[13px] font-medium outline-none w-full"
data-testid={`pulse-settings-buy-amount-${index + 1}`}
/>
<input
type="text"
inputMode="numeric"
aria-label={`Buy amount preset ${index + 1}`}
value={item.value}
onChange={(e) => {
const { value } = e.target;
// Only allow empty string or valid numbers (including decimals)
if (value === '' || /^\d*\.?\d*$/.test(value)) {
item.setter(value);
}
}}
onBlur={(e) => {
const val = e.target.value;
if (val === '' || val === '.') {
item.setter(['10', '20', '50', '100'][index]);
} else if (val.endsWith('.')) {
// Remove trailing decimal point
item.setter(val.slice(0, -1));
}
}}
className="flex-1 bg-transparent text-white !text-[13px] font-medium outline-none w-full"
data-testid={`pulse-settings-buy-amount-${index + 1}`}
/>
🤖 Prompt for AI Agents
In src/apps/pulse/components/Settings/SettingsMenu.tsx around lines 275 to 294,
add an accessible aria-label to the input (e.g. aria-label={`Buy amount ${index
+ 1}`} or a descriptive label string) to improve screen reader support, and
update the onBlur handler to normalize incomplete decimals: if the value ends
with a trailing dot (e.g. "5.") remove the dot to make "5", and if the value is
just "." replace it with a sensible fallback (either "0" or the component's
default for that index), while keeping the existing behavior that replaces an
empty string with the default.

Comment on lines +318 to +342
<input
type="text"
inputMode="numeric"
value={item.value}
onChange={(e) => {
const { value } = e.target;
// Only allow empty string or valid numbers (including decimals)
// Also check that the value doesn't exceed 100
if (value === '' || /^\d*\.?\d*$/.test(value)) {
const numValue = parseFloat(value);
if (value === '' || numValue <= 100) {
item.setter(value);
}
}
}}
onBlur={(e) => {
// If empty on blur, set to default
if (e.target.value === '') {
item.setter(['10', '25', '50', '75'][index]);
}
}}
className="flex-1 bg-transparent text-white !text-[13px] font-medium outline-none w-full"
data-testid={`pulse-settings-sell-percent-${index + 1}`}
/>
<span className="text-white/50 text-sm ml-1">%</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add accessibility labels and consider validation feedback.

Two concerns:

  1. Accessibility: The input fields lack aria-label attributes for screen reader support.

  2. UX for >100 validation: When a user attempts to type a value greater than 100, the input silently rejects the keystroke with no visual feedback. Consider either:

    • Allowing the input and displaying an error message
    • Capping the value at 100 on blur
    • Providing visual feedback (e.g., red border) when the constraint is violated

Apply this diff to add aria-labels:

 <input
   type="text"
   inputMode="numeric"
+  aria-label={`Sell percentage preset ${index + 1}`}
   value={item.value}

Optionally, improve validation feedback by capping on blur instead:

   onChange={(e) => {
     const { value } = e.target;
-    // Only allow empty string or valid numbers (including decimals)
-    // Also check that the value doesn't exceed 100
-    if (value === '' || /^\d*\.?\d*$/.test(value)) {
-      const numValue = parseFloat(value);
-      if (value === '' || numValue <= 100) {
-        item.setter(value);
-      }
+    if (value === '' || /^\d*\.?\d*$/.test(value)) {
+      item.setter(value);
     }
   }}
   onBlur={(e) => {
-    // If empty on blur, set to default
-    if (e.target.value === '') {
+    const val = e.target.value;
+    const numValue = parseFloat(val);
+    if (val === '' || val === '.' || isNaN(numValue)) {
       item.setter(['10', '25', '50', '75'][index]);
+    } else if (numValue > 100) {
+      item.setter('100');
+    } else if (val.endsWith('.')) {
+      item.setter(val.slice(0, -1));
     }
   }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<input
type="text"
inputMode="numeric"
value={item.value}
onChange={(e) => {
const { value } = e.target;
// Only allow empty string or valid numbers (including decimals)
// Also check that the value doesn't exceed 100
if (value === '' || /^\d*\.?\d*$/.test(value)) {
const numValue = parseFloat(value);
if (value === '' || numValue <= 100) {
item.setter(value);
}
}
}}
onBlur={(e) => {
// If empty on blur, set to default
if (e.target.value === '') {
item.setter(['10', '25', '50', '75'][index]);
}
}}
className="flex-1 bg-transparent text-white !text-[13px] font-medium outline-none w-full"
data-testid={`pulse-settings-sell-percent-${index + 1}`}
/>
<span className="text-white/50 text-sm ml-1">%</span>
<input
type="text"
inputMode="numeric"
aria-label={`Sell percentage preset ${index + 1}`}
value={item.value}
onChange={(e) => {
const { value } = e.target;
if (value === '' || /^\d*\.?\d*$/.test(value)) {
item.setter(value);
}
}}
onBlur={(e) => {
const val = e.target.value;
const numValue = parseFloat(val);
if (val === '' || val === '.' || isNaN(numValue)) {
item.setter(['10', '25', '50', '75'][index]);
} else if (numValue > 100) {
item.setter('100');
} else if (val.endsWith('.')) {
item.setter(val.slice(0, -1));
}
}}
className="flex-1 bg-transparent text-white !text-[13px] font-medium outline-none w-full"
data-testid={`pulse-settings-sell-percent-${index + 1}`}
/>
<span className="text-white/50 text-sm ml-1">%</span>

@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) October 31, 2025 13:47 Inactive
@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) October 31, 2025 13:53 Inactive
@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) October 31, 2025 15:41 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/apps/pulse/components/App/tests/HomeScreen.test.tsx (2)

121-130: Consider extracting the hardcoded color value for better maintainability.

The arbitrary Tailwind color class 'bg-[#1E1D24]' is hardcoded in the assertions. If this color value changes in the future, the test will need updates. Consider extracting it to a test constant or using a semantic CSS class name if available.

Additionally, lines 125-130 use separate assertions to check two classes on the same element, which could be simplified.

Example refactor:

+const ACTIVE_BG_CLASS = 'bg-[#1E1D24]';
+const INACTIVE_BG_CLASS = 'bg-black';
+const INACTIVE_TEXT_CLASS = 'text-grey';
+
 it('toggles between Buy and Sell components correctly', () => {
   // ...
   
-  // Check button classes for Buy state
-  expect(screen.getByTestId('pulse-buy-toggle-button')).toHaveClass(
-    'bg-[#1E1D24]'
-  );
-  expect(screen.getByTestId('pulse-sell-toggle-button')).toHaveClass(
-    'bg-black'
-  );
-  expect(screen.getByTestId('pulse-sell-toggle-button')).toHaveClass(
-    'text-grey'
-  );
+  // Check active Buy button styling
+  expect(screen.getByTestId('pulse-buy-toggle-button')).toHaveClass(ACTIVE_BG_CLASS);
+  // Check inactive Sell button styling
+  const sellButton = screen.getByTestId('pulse-sell-toggle-button');
+  expect(sellButton).toHaveClass(INACTIVE_BG_CLASS, INACTIVE_TEXT_CLASS);

147-156: Styling assertions are correct; same refactor suggestion applies.

The class-based assertions correctly verify the Sell state button styling. The same optional refactor suggestion from lines 121-130 applies here for consistency (extracting the hardcoded color constant and simplifying the multiple assertions).

src/apps/pulse/components/Settings/SettingsMenu.tsx (1)

55-72: Consider using nullish coalescing for edge case correctness.

The || operator treats '0' as falsy, which means if customBuyAmounts[0] or customSellAmounts[0] is '0', it would default to the fallback value instead. While '0' is not a practical preset, using ?? would be more technically correct:

-  const [buyAmount1, setBuyAmount1] = useState(customBuyAmounts[0] || '10');
+  const [buyAmount1, setBuyAmount1] = useState(customBuyAmounts[0] ?? '10');

Apply similar changes to all other state initializations (lines 56-72).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c796ff0 and b3aad49.

📒 Files selected for processing (2)
  • src/apps/pulse/components/App/tests/HomeScreen.test.tsx (3 hunks)
  • src/apps/pulse/components/Settings/SettingsMenu.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.
📚 Learning: 2025-08-12T07:42:24.656Z
Learnt from: IAmKio
Repo: pillarwallet/x PR: 351
File: src/apps/pulse/utils/intent.ts:44-53
Timestamp: 2025-08-12T07:42:24.656Z
Learning: In the Pulse app's intent utilities (src/apps/pulse/utils/intent.ts), the team has chosen to use floating-point arithmetic for token amount calculations despite potential precision issues, accepting JavaScript's decimal place limitations as a valid trade-off for their use case.

Applied to files:

  • src/apps/pulse/components/Settings/SettingsMenu.tsx
📚 Learning: 2025-09-09T12:40:15.629Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.

Applied to files:

  • src/apps/pulse/components/Settings/SettingsMenu.tsx
🧬 Code graph analysis (1)
src/apps/pulse/components/Settings/SettingsMenu.tsx (4)
src/utils/blockchain.ts (2)
  • CompatibleChains (321-323)
  • getLogoForChainId (165-199)
src/apps/pulse/hooks/useKeyboardNavigation.ts (1)
  • useKeyboardNavigation (7-35)
src/apps/pulse/hooks/useClickOutside.ts (1)
  • useClickOutside (7-29)
src/apps/pulse/components/Misc/Refresh.tsx (1)
  • Refresh (10-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: lint
  • GitHub Check: unit-tests
  • GitHub Check: build
🔇 Additional comments (3)
src/apps/pulse/components/App/tests/HomeScreen.test.tsx (1)

106-106: LGTM! Label correctly updated to Settings.

The test assertion properly reflects the UI change from "Save" to "Settings" as described in the PR objectives.

src/apps/pulse/components/Settings/SettingsMenu.tsx (2)

85-105: Validation pattern is sound, with same edge case as state initialization.

The validation logic correctly provides fallbacks for empty strings. Note that this function uses the same || operator pattern as the state initialization (lines 55-72), so the '0' edge case applies here as well.

Also, values from the input fields (e.g., buyAmount1) are passed directly, so any incomplete decimals like "5." that make it through the input validation would be propagated to the parent state. This relates to the decimal normalization concerns in past review comments.


107-370: Well-structured component with correct hook usage.

The implementation demonstrates several strengths:

  • Proper hook integration: useKeyboardNavigation and useClickOutside are correctly used, addressing previous review feedback.
  • Clear component structure: Settings sections are well-organized with consistent styling and layout.
  • State management: The chain dropdown and input field states are properly managed with appropriate close/reset behaviors.
  • ESC key handling: Correctly prioritizes closing the dropdown first (line 110-111), then the menu itself (line 113), providing good UX.
  • Test coverage: Comprehensive data-testid attributes for testing.

Note: Previous review comments on lines 283-302 and 326-350 regarding accessibility (missing aria-label attributes) and decimal normalization remain valid points for improvement.

@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) October 31, 2025 15:57 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/apps/pulse/components/App/HomeScreen.tsx (1)

226-228: User-selected settlement chain is overwritten on every balance refresh.

This issue was already flagged in a previous review: every time wallet balances refresh (manual refresh or the 15s timer), this effect force-resets selectedChainIdForSettlement back to maxStableCoinBalance.chainId, wiping out any manual choice the user made in Settings. This directly violates the PR requirement that "the user can override this selection."

Please implement the gating logic suggested in the previous review to preserve user selections:

+  const [hasManualSettlementSelection, setHasManualSettlementSelection] =
+    useState(false);
+
+  const handleManualSettlementSelection = useCallback((chainId: number) => {
+    setSelectedChainIdForSettlement(chainId);
+    setHasManualSettlementSelection(true);
+  }, []);
+
   useEffect(() => {
-    setSelectedChainIdForSettlement(maxStableCoinBalance.chainId);
-  }, [maxStableCoinBalance.chainId]);
+    if (!hasManualSettlementSelection) {
+      setSelectedChainIdForSettlement(maxStableCoinBalance.chainId);
+    }
+  }, [maxStableCoinBalance.chainId, hasManualSettlementSelection]);

Then pass handleManualSettlementSelection to SettingsMenu (line 924) instead of setSelectedChainIdForSettlement, and reset hasManualSettlementSelection to false if the user explicitly picks the computed default again.

🧹 Nitpick comments (2)
src/apps/pulse/utils/utils.tsx (1)

213-253: Refactor to eliminate duplicate filtering and improve performance.

The function filters assets twice with identical logic (lines 229-236 and 239-244), then iterates over the results with nested loops. This is inefficient for large portfolios.

Consider this refactor:

 export const getStableCurrencyBalanceOnEachChain = (
   walletPortfolioData: WalletPortfolioMobulaResponse
 ): { [chainId: number]: number } => {
-  // get the list of chainIds from STABLE_CURRENCIES
   const chainIds = Array.from(
     new Set(STABLE_CURRENCIES.map((currency) => currency.chainId))
   );
 
-  // create a map to hold the balance for each chainId
   const balanceMap: { [chainId: number]: number } = {};
   chainIds.forEach((chainId) => {
     balanceMap[chainId] = 0;
   });
-  // calculate the balance for each chainId
+
+  // Build a lookup map for faster stable currency checks
+  const stableLookup = new Map<string, number>();
+  STABLE_CURRENCIES.forEach((stable) => {
+    const key = `${stable.chainId}:${stable.address.toLowerCase()}`;
+    stableLookup.set(key, stable.chainId);
+  });
+
   walletPortfolioData?.result.data.assets
-    ?.filter((asset) =>
-      asset.contracts_balances.some((contract) =>
-        STABLE_CURRENCIES.some(
-          (stable) =>
-            stable.address.toLowerCase() === contract.address.toLowerCase() &&
-            stable.chainId === Number(contract.chainId.split(':').at(-1))
-        )
-      )
-    )
     .forEach((asset) => {
-      const stableContracts = asset.contracts_balances.filter((contract) =>
-        STABLE_CURRENCIES.some(
-          (stable) =>
-            stable.address.toLowerCase() === contract.address.toLowerCase() &&
-            stable.chainId === Number(contract.chainId.split(':').at(-1))
-        )
-      );
-      stableContracts.forEach((contract) => {
+      asset.contracts_balances.forEach((contract) => {
         const chainId = Number(contract.chainId.split(':').at(-1));
-        balanceMap[chainId] += asset.price * contract.balance;
+        const key = `${chainId}:${contract.address.toLowerCase()}`;
+        if (stableLookup.has(key)) {
+          const price = asset.price ?? 0;
+          const balance = contract.balance ?? 0;
+          balanceMap[chainId] += price * balance;
+        }
       });
     });
 
   return balanceMap;
 };

This eliminates the duplicate filter and reduces the O(n×m×k) complexity to O(n×m) by using a Map lookup.

src/apps/pulse/components/App/HomeScreen.tsx (1)

107-110: Clarify the default balance of 2.

The comment "Default to 2 to allow trading initially" is helpful, but the magic number 2 might confuse future maintainers. Is this a minimum threshold documented elsewhere?

Consider extracting this as a named constant:

+const DEFAULT_MIN_STABLE_BALANCE_FOR_TRADING = 2;
+
 export default function HomeScreen(props: HomeScreenProps) {
   // ...
   const [maxStableCoinBalance, setMaxStableCoinBalance] = useState<{
     chainId: number;
     balance: number;
-  }>({ chainId: 1, balance: 2 }); // Default to 2 to allow trading initially
+  }>({ chainId: 1, balance: DEFAULT_MIN_STABLE_BALANCE_FOR_TRADING });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3aad49 and c292fbf.

📒 Files selected for processing (2)
  • src/apps/pulse/components/App/HomeScreen.tsx (8 hunks)
  • src/apps/pulse/utils/utils.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.
📚 Learning: 2025-08-12T07:42:24.656Z
Learnt from: IAmKio
Repo: pillarwallet/x PR: 351
File: src/apps/pulse/utils/intent.ts:44-53
Timestamp: 2025-08-12T07:42:24.656Z
Learning: In the Pulse app's intent utilities (src/apps/pulse/utils/intent.ts), the team has chosen to use floating-point arithmetic for token amount calculations despite potential precision issues, accepting JavaScript's decimal place limitations as a valid trade-off for their use case.

Applied to files:

  • src/apps/pulse/utils/utils.tsx
📚 Learning: 2025-09-09T12:40:15.629Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-08-20T09:14:16.888Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 374
File: src/apps/pillarx-app/index.tsx:12-12
Timestamp: 2025-08-20T09:14:16.888Z
Learning: In this codebase, Transaction Kit providers are set up at the container level (src/containers/Authorized.tsx), not at individual app component levels. App components like src/apps/pillarx-app/index.tsx are children that consume the context through the provider tree.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-03-28T09:22:22.712Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 275
File: src/apps/the-exchange/components/DropdownTokensList/DropdownTokenList.tsx:180-195
Timestamp: 2025-03-28T09:22:22.712Z
Learning: In the Exchange app, `swapTokenList` and `receiveTokenList` are derived from `searchTokenResult` when search is active, so including `searchToken` in the useEffect dependency array that uses these lists would be redundant as the lists will update when search results change.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
🧬 Code graph analysis (2)
src/apps/pulse/utils/utils.tsx (2)
src/types/api.ts (1)
  • WalletPortfolioMobulaResponse (750-752)
src/apps/pulse/constants/tokens.ts (1)
  • STABLE_CURRENCIES (13-15)
src/apps/pulse/components/App/HomeScreen.tsx (5)
src/apps/pulse/utils/utils.tsx (1)
  • getStableCurrencyBalanceOnEachChain (214-253)
src/apps/pulse/components/Settings/SettingsMenu.tsx (1)
  • SettingsMenu (32-370)
src/apps/pulse/components/Misc/Refresh.tsx (1)
  • Refresh (10-35)
src/apps/pulse/components/Misc/Settings.tsx (1)
  • Settings (7-21)
src/apps/pulse/components/Buy/Buy.tsx (1)
  • Buy (69-663)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: unit-tests
  • GitHub Check: build
🔇 Additional comments (1)
src/apps/pulse/components/App/HomeScreen.tsx (1)

916-1032: LGTM: Settings menu integration is clean.

The conditional rendering of SettingsMenu vs. the main Buy/Sell UI is clear, and the props passed to Buy, Sell, PreviewSell, and SettingsMenu correctly wire up the new settlement chain and custom amounts features. The UI restructure aligns with the PR objectives.

Comment on lines +212 to +217
const maxStableBalance = Math.max(...Object.values(stableBalance));
const chainIdOfMaxStableBalance = Number(
Object.keys(stableBalance).find(
(key) => stableBalance[Number(key)] === maxStableBalance
) || '1'
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle edge case when stable balance map is empty.

If getStableCurrencyBalanceOnEachChain returns an empty object (no stable currencies found), Math.max(...Object.values(stableBalance)) returns -Infinity, and .find(...) returns undefined. The fallback || '1' prevents a crash, but you'll set balance to -Infinity.

Apply this diff to default to a safe state:

     const stableBalance =
       getStableCurrencyBalanceOnEachChain(walletPortfolioData);
+    if (Object.keys(stableBalance).length === 0) {
+      setMaxStableCoinBalance({ chainId: 1, balance: 0 });
+      return;
+    }
     const maxStableBalance = Math.max(...Object.values(stableBalance));
     const chainIdOfMaxStableBalance = Number(
       Object.keys(stableBalance).find(
         (key) => stableBalance[Number(key)] === maxStableBalance
       ) || '1'
     );

Committable suggestion skipped: line range outside the PR's diff.

@vignesha22 vignesha22 requested review from IAmKio and RanaBug November 3, 2025 09:53
Copy link
Collaborator

@IAmKio IAmKio left a comment

Choose a reason for hiding this comment

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

LGTM - please wait for @RanaBug to check her comments also

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) November 4, 2025 09:26 Inactive
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@github-actions github-actions bot temporarily deployed to Preview (feature/PRO-3833-USDC-directional-changes-for-Sell-sides) November 4, 2025 09:28 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/apps/pulse/components/App/HomeScreen.tsx (1)

220-222: Preserve user-selected settlement chain.

This effect overwrites user-selected settlement chains on every balance refresh (15s timer). The issue and solution are already documented in previous review comments.

🧹 Nitpick comments (1)
src/apps/pulse/components/App/HomeScreen.tsx (1)

201-217: Consider removing portfolioTokens dependency.

The effect only uses walletPortfolioData to compute stable balances (line 206), but the early return also checks portfolioTokens which is derived separately (lines 790-798). This dependency might cause unnecessary delays if portfolioTokens hasn't populated yet when walletPortfolioData arrives.

Consider this refactor:

   useEffect(() => {
-    if (!walletPortfolioData || !portfolioTokens || portfolioTokens.length === 0) {
+    if (!walletPortfolioData) {
       return;
     }
     const stableBalance =
       getStableCurrencyBalanceOnEachChain(walletPortfolioData);
+    if (Object.keys(stableBalance).length === 0) {
+      setMaxStableCoinBalance({ chainId: 1, balance: 0 });
+      return;
+    }
     const maxStableBalance = Math.max(...Object.values(stableBalance));
     const chainIdOfMaxStableBalance = Number(
       Object.keys(stableBalance).find(
         (key) => stableBalance[Number(key)] === maxStableBalance
       ) || '1'
     );
     setMaxStableCoinBalance({
       chainId: chainIdOfMaxStableBalance,
       balance: maxStableBalance,
     });
-  }, [portfolioTokens, walletPortfolioData]);
+  }, [walletPortfolioData]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c292fbf and e8879d6.

📒 Files selected for processing (2)
  • src/apps/pulse/components/App/HomeScreen.tsx (8 hunks)
  • src/apps/pulse/utils/utils.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/apps/pulse/utils/utils.tsx
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.
📚 Learning: 2025-09-09T12:40:15.629Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-03-28T09:22:22.712Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 275
File: src/apps/the-exchange/components/DropdownTokensList/DropdownTokenList.tsx:180-195
Timestamp: 2025-03-28T09:22:22.712Z
Learning: In the Exchange app, `swapTokenList` and `receiveTokenList` are derived from `searchTokenResult` when search is active, so including `searchToken` in the useEffect dependency array that uses these lists would be redundant as the lists will update when search results change.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-08-20T09:14:16.888Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 374
File: src/apps/pillarx-app/index.tsx:12-12
Timestamp: 2025-08-20T09:14:16.888Z
Learning: In this codebase, Transaction Kit providers are set up at the container level (src/containers/Authorized.tsx), not at individual app component levels. App components like src/apps/pillarx-app/index.tsx are children that consume the context through the provider tree.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
🧬 Code graph analysis (1)
src/apps/pulse/components/App/HomeScreen.tsx (5)
src/apps/pulse/utils/utils.tsx (1)
  • getStableCurrencyBalanceOnEachChain (214-255)
src/apps/pulse/components/Settings/SettingsMenu.tsx (1)
  • SettingsMenu (32-370)
src/apps/pulse/components/Misc/Refresh.tsx (1)
  • Refresh (10-35)
src/apps/pulse/components/Misc/Settings.tsx (1)
  • Settings (7-21)
src/apps/pulse/components/Buy/Buy.tsx (1)
  • Buy (69-663)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: unit-tests
  • GitHub Check: lint
  • GitHub Check: build
🔇 Additional comments (4)
src/apps/pulse/components/App/HomeScreen.tsx (4)

35-35: LGTM! Clean integration of new settings and balance tracking.

The imports and state declarations correctly introduce SettingsMenu, balance computation utilities, and configurable buy/sell presets. The default stable balance of 2 allows trading initially while waiting for actual portfolio data.

Also applies to: 43-43, 107-135


193-199: LGTM! Wallet portfolio query configured correctly.

The hook correctly skips queries when no account is connected and disables refetch-on-focus to prevent unnecessary polling.


268-268: LGTM! Settlement chain correctly propagated through sell flow.

The selectedChainIdForSettlement is properly used in sell offer fetching (line 268), included in effect dependencies (line 298), and passed to PreviewSell (line 864).

Also applies to: 298-298, 864-864


909-1027: LGTM! Clean UI restructure with settings integration.

The conditional rendering between SettingsMenu and main trading UI is well-structured. Props are correctly threaded to child components: Buy receives maxStableCoinBalance and customBuyAmounts, Sell receives customSellAmounts and selectedChainIdForSettlement. The refresh button is appropriately disabled when no token is selected.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/apps/pulse/components/App/HomeScreen.tsx (2)

211-216: Handle edge case when stable balance map is empty.

If getStableCurrencyBalanceOnEachChain returns an empty object (no stable currencies found), Math.max(...Object.values(stableBalance)) returns -Infinity, and the fallback || '1' prevents a crash but sets balance to -Infinity. This was flagged in a previous review and remains unaddressed.

Apply this diff to default to a safe state:

     const stableBalance =
       getStableCurrencyBalanceOnEachChain(walletPortfolioData);
+    if (Object.keys(stableBalance).length === 0) {
+      setMaxStableCoinBalance({ chainId: 1, balance: 0 });
+      return;
+    }
     const maxStableBalance = Math.max(...Object.values(stableBalance));
     const chainIdOfMaxStableBalance = Number(
       Object.keys(stableBalance).find(
         (key) => stableBalance[Number(key)] === maxStableBalance
       ) || '1'
     );

224-226: Preserve user-selected settlement chain.

Every time wallet balances refresh (manual refresh or the built-in 15s timer), maxStableCoinBalance recalculates and this effect force-resets selectedChainIdForSettlement back to the highest-balance chain. That wipes out any manual choice the user made in Settings, so the new "user can change this selection" requirement cannot be satisfied for more than a few seconds.

Please gate this auto-sync so it only runs until the user picks a chain themselves:

-  useEffect(() => {
-    setSelectedChainIdForSettlement(maxStableCoinBalance.chainId);
-  }, [maxStableCoinBalance.chainId]);
+  const [hasManualSettlementSelection, setHasManualSettlementSelection] =
+    useState(false);
+
+  const handleManualSettlementSelection = useCallback((chainId: number) => {
+    setSelectedChainIdForSettlement(chainId);
+    setHasManualSettlementSelection(true);
+  }, []);
+
+  useEffect(() => {
+    if (!hasManualSettlementSelection) {
+      setSelectedChainIdForSettlement(maxStableCoinBalance.chainId);
+    }
+  }, [maxStableCoinBalance.chainId, hasManualSettlementSelection]);

Then pass handleManualSettlementSelection down to SettingsMenu (line 922) instead of the raw setSelectedChainIdForSettlement, and reset the manual-selection flag back to false if the user explicitly selects the computed default again.

🧹 Nitpick comments (1)
src/apps/pulse/components/App/HomeScreen.tsx (1)

107-110: Consider clarifying the default balance value.

The default balance of 2 with the comment "Default to 2 to allow trading initially" may be misleading. This default will be immediately replaced by the computed value from the effect at lines 201-221 once walletPortfolioData loads. If the intent is to allow trading before portfolio data loads, consider documenting this more clearly or using a more meaningful initial value (e.g., 0 with a loading state).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8879d6 and 922ae9e.

⛔ Files ignored due to path filters (2)
  • src/apps/pillarx-app/components/TokenMarketDataRow/tests/__snapshots__/LeftColumnTokenMarketDataRow.test.tsx.snap is excluded by !**/*.snap
  • src/apps/pillarx-app/components/TokensWithMarketDataTile/test/__snapshots__/TokensWithMarketDataTile.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (1)
  • src/apps/pulse/components/App/HomeScreen.tsx (8 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.
📚 Learning: 2025-09-09T12:40:15.629Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 391
File: src/apps/pulse/components/Sell/Sell.tsx:113-130
Timestamp: 2025-09-09T12:40:15.629Z
Learning: In the Pulse app Sell component, when a user changes/switches tokens, the input amount automatically resets to 0, which means liquidity validation state doesn't become stale when tokens change.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-03-28T09:22:22.712Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 275
File: src/apps/the-exchange/components/DropdownTokensList/DropdownTokenList.tsx:180-195
Timestamp: 2025-03-28T09:22:22.712Z
Learning: In the Exchange app, `swapTokenList` and `receiveTokenList` are derived from `searchTokenResult` when search is active, so including `searchToken` in the useEffect dependency array that uses these lists would be redundant as the lists will update when search results change.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
📚 Learning: 2025-08-20T09:14:16.888Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 374
File: src/apps/pillarx-app/index.tsx:12-12
Timestamp: 2025-08-20T09:14:16.888Z
Learning: In this codebase, Transaction Kit providers are set up at the container level (src/containers/Authorized.tsx), not at individual app component levels. App components like src/apps/pillarx-app/index.tsx are children that consume the context through the provider tree.

Applied to files:

  • src/apps/pulse/components/App/HomeScreen.tsx
🧬 Code graph analysis (1)
src/apps/pulse/components/App/HomeScreen.tsx (5)
src/apps/pulse/utils/utils.tsx (1)
  • getStableCurrencyBalanceOnEachChain (214-255)
src/apps/pulse/components/Settings/SettingsMenu.tsx (1)
  • SettingsMenu (32-370)
src/apps/pulse/components/Misc/Refresh.tsx (1)
  • Refresh (10-35)
src/apps/pulse/components/Misc/Settings.tsx (1)
  • Settings (7-21)
src/apps/pulse/components/Buy/Buy.tsx (1)
  • Buy (69-663)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: unit-tests
  • GitHub Check: lint
  • GitHub Check: build
🔇 Additional comments (3)
src/apps/pulse/components/App/HomeScreen.tsx (3)

193-199: LGTM!

The wallet portfolio query setup is correct, with appropriate skip conditions and refetch configuration.


272-272: LGTM!

The selectedChainIdForSettlement is correctly passed to both the sell offer retrieval and PreviewSell component, properly threading the settlement chain preference through the sell flow.

Also applies to: 868-868


913-1031: LGTM!

The UI restructure integrating SettingsMenu is well-implemented. The conditional rendering between Settings and the main trading UI is clear, props are correctly threaded through to Buy/Sell components, and the spread syntax adding 'MAX' to custom amounts works correctly.

Note: The SettingsMenu integration at line 922 directly passes setSelectedChainIdForSettlement, which connects to the critical issue flagged above regarding auto-reset of user's manual selection.

@vignesha22 vignesha22 requested a review from IAmKio November 4, 2025 11:19
@vignesha22 vignesha22 merged commit 9c85d97 into staging Nov 4, 2025
6 of 7 checks passed
@vignesha22 vignesha22 deleted the feature/PRO-3833-USDC-directional-changes-for-Sell-sides branch November 4, 2025 11:29
@coderabbitai coderabbitai bot mentioned this pull request Nov 5, 2025
3 tasks
@coderabbitai coderabbitai bot mentioned this pull request Nov 28, 2025
3 tasks
@coderabbitai coderabbitai bot mentioned this pull request Dec 23, 2025
3 tasks
@coderabbitai coderabbitai bot mentioned this pull request Jan 6, 2026
3 tasks
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.

3 participants