Skip to content

Comments

Fixes/Relay_Buy#460

Merged
vignesha22 merged 3 commits intostagingfrom
OP_Mobula_Search
Nov 24, 2025
Merged

Fixes/Relay_Buy#460
vignesha22 merged 3 commits intostagingfrom
OP_Mobula_Search

Conversation

@vignesha22
Copy link
Contributor

@vignesha22 vignesha22 commented Nov 20, 2025

Description

  • Enable Trading check should only show when the relayBuy is false
  • Native Token Fix on OP only for pulse Search alone.
  • Changed the token input to use token price on buy
  • Fixed decimals on previewBuy

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

    • Relay Buy is enabled by default and the buy flows now use propagated USDC price for more accurate quotes.
  • Improvements

    • Token/address normalization improved for cross-chain and Optimism native tokens.
    • Portfolio balances now include optional per-chain price data for clearer value display.
    • Buy flow validation tightened to prevent invalid USD amounts and align button behavior with selected buy path.

✏️ Tip: You can customize this high-level summary in your review settings.

@vignesha22 vignesha22 requested review from IAmKio and RanaBug November 20, 2025 13:55
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 20, 2025

Walkthrough

Derives and exposes USDC price from portfolio data on HomeScreen, threads usdcPrice through PreviewBuy → Buy → useRelayBuy, normalizes certain native token addresses to zero address, changes per-chain stable-balance return shape to include price, and flips the default Relay Buy flag to true.

Changes

Cohort / File(s) Change Summary
USDC Price Propagation
src/apps/pulse/components/App/HomeScreen.tsx, src/apps/pulse/components/Buy/Buy.tsx, src/apps/pulse/components/Buy/PreviewBuy.tsx
Adds optional usdcPrice state/prop, derives USDC price from chain with max stable balance in HomeScreen, and passes usdcPrice into PreviewBuy and Buy so Relay Buy flows receive the price.
Buy Button & Flow Selection
src/apps/pulse/components/Buy/BuyButton.tsx
Adds useRelayBuy boolean prop, expands expressIntentResponse union to include BuyOffer, updates button text and disabled logic to distinguish Relay Buy vs Intent SDK flows and to conditionally show "Enable Trading".
Relay Buy Hook & Quote Logic
src/apps/pulse/hooks/useRelayBuy.ts
Adds usdcPrice?: number to BuyParams, getBestOffer (default 1.0) and executeBuy; normalizes native-token addresses to zero address for quote requests; converts USD→USDC using explicit usdcPrice with 6-decimal handling and tighter input validation.
Stable Balance Return Shape
src/apps/pulse/utils/utils.tsx
Changes getStableCurrencyBalanceOnEachChain return type from { [chainId:number]: number } to { [chainId:number]: { balance: number; price?: number } } and updates internal population accordingly.
Address Normalization in Parsers
src/apps/pulse/utils/parseSearchData.ts
Adds normalizeContractAddress helper to map Optimism Mobula native ETH placeholder to zero address and applies normalization across parseAssetData, parseTokenData, and parseFreshAndTrendingTokens.
Remote Config Default Flip
src/hooks/useRemoteConfig.ts, src/services/firebase.ts
Changes initial/default value and error fallback for useRelayBuy from false to true (remote-config default and Firebase fallback updated).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant HomeScreen
    participant Portfolio
    participant Buy
    participant PreviewBuy
    participant useRelayBuy
    participant QuoteService

    User->>HomeScreen: open app
    HomeScreen->>Portfolio: fetch wallet balances
    Portfolio-->>HomeScreen: balances + per-chain price info
    HomeScreen->>HomeScreen: determine max stable balance & usdcPrice
    HomeScreen->>Buy: render with usdcPrice

    User->>Buy: start buy flow
    Buy->>PreviewBuy: open preview (passes usdcPrice)
    PreviewBuy->>useRelayBuy: getBestOffer(usdAmount, usdcPrice)
    Note over useRelayBuy: normalize native token -> 0x0\nconvert USD to USDC using usdcPrice
    useRelayBuy->>QuoteService: request quote (normalized addresses, usdc amount)
    QuoteService-->>useRelayBuy: return offer
    useRelayBuy-->>PreviewBuy: offer
    PreviewBuy-->>Buy: display quote
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to BuyButton.tsx (union type extension and conditional rendering between Relay Buy and Intent SDK).
  • Verify useRelayBuy.ts decimal math, native-address normalization, parameter defaults, and error handling for invalid USD amounts.
  • Ensure all call sites handle the new { balance, price? } shape from getStableCurrencyBalanceOnEachChain.
  • Check parseSearchData.ts normalization is applied consistently where token/asset contract fields are used.

Possibly related PRs

Suggested reviewers

  • nikhilkumar1612
  • RanaBug
  • IAmKio

Poem

🐰 A tiny hop, a quiet cheer,
USDC trickles, prices clear,
Native addresses washed to zero,
Relay Buy hums — the pipeline's hero,
Hop on, trade — the rabbit's near! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Fixes/Relay_Buy' is vague and does not clearly convey the specific changes made in the changeset. Use a more descriptive title that summarizes the main change, such as 'Fix Relay Buy flow with USDC price handling and native token normalization' or 'Update Relay Buy to use USDC pricing and fix OP native token handling'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description addresses the template structure and includes testing information, but lacks sufficient detail about the technical implementation and scope of changes.
✨ 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 OP_Mobula_Search

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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/utils/utils.tsx (1)

218-263: Stable balance per chain is overwritten instead of accumulated

In getStableCurrencyBalanceOnEachChain, each matching stable contract does:

balanceMap[chainId] = {
  balance: price * balance,
  price: asset.price ? asset.price : undefined,
};

This overwrites any previous value for that chainId. If a user has:

  • Multiple stable contracts for the same token on a chain, or
  • Multiple stable tokens counted in STABLE_CURRENCIES for the same chain,

you’ll only retain the last one processed, so balance under-reports total stable value and can cause the wrong maxStableCoinBalance chain to be selected.

I’d suggest accumulating instead:

-        const price = asset.price ?? 0;
-        const balance = contract.balance ?? 0;
-        balanceMap[chainId] = {
-          balance: price * balance,
-          price: asset.price ? asset.price : undefined,
-        };
+        const price = asset.price ?? 0;
+        const balance = contract.balance ?? 0;
+        const prev = balanceMap[chainId] || { balance: 0, price: undefined };
+        const usdValue = price * balance;
+        balanceMap[chainId] = {
+          balance: prev.balance + usdValue,
+          // Prefer a non‑zero price if available, otherwise keep previous
+          price: price || prev.price,
+        };

That keeps your “USD balance per chain” semantics while avoiding silent under-counting.

🧹 Nitpick comments (6)
src/apps/pulse/utils/parseSearchData.ts (4)

17-40: OP native ETH normalization helper looks good; consider minor robustness tweaks

The normalization logic is clear and correctly scoped to Optimism native ETH. To make it a bit more defensive against API quirks, you could safely loosen the symbol check to be case-insensitive:

-  if (
-    contract.toLowerCase() === OP_NATIVE_MOBULA.toLowerCase() &&
-    symbol === 'ETH' &&
-    chainId === OPTIMISM_CHAIN_ID
-  ) {
+  if (
+    contract.toLowerCase() === OP_NATIVE_MOBULA.toLowerCase() &&
+    symbol.toUpperCase() === 'ETH' &&
+    chainId === OPTIMISM_CHAIN_ID
+  ) {

This avoids breakage if Mobula ever returns eth / Eth instead of strictly ETH.


67-88: Use normalizedContract when checking isWrappedNativeToken for consistency

You correctly normalize the contract before storing it in the Asset object, but the wrapped-native filter still uses the original contractAddress. Using the normalized value would make the semantics consistent across all uses:

-      const contractAddress = contracts[i];
-      const normalizedContract = normalizeContractAddress(
-        contractAddress,
-        asset.symbol,
-        chainId
-      );
+      const contractAddress = contracts[i];
+      const normalizedContract = normalizeContractAddress(
+        contractAddress,
+        asset.symbol,
+        chainId
+      );

       // Filter out wrapped native tokens (WETH, WBNB, WPOL, etc.) from search results
-      if (!isWrappedNativeToken(contractAddress, chainId)) {
+      if (!isWrappedNativeToken(normalizedContract, chainId)) {

Same pattern can be applied in parseTokenData and parseFreshAndTrendingTokens below.


100-125: Mirror normalization usage in parseTokenData

As above, consider using normalizedContract for the wrapped-native filter to keep behavior aligned with the Asset.contract value:

-    if (MOBULA_CHAIN_NAMES.includes(blockchains[i])) {
-      const chainId = chainNameToChainIdTokensData(blockchains[i]);
-      const contractAddress = contracts[i];
-      const normalizedContract = normalizeContractAddress(
-        contractAddress,
-        asset.symbol,
-        chainId
-      );
-
-      // Filter out wrapped native tokens (WETH, WBNB, WPOL, etc.) from search results
-      if (!isWrappedNativeToken(contractAddress, chainId)) {
+    if (MOBULA_CHAIN_NAMES.includes(blockchains[i])) {
+      const chainId = chainNameToChainIdTokensData(blockchains[i]);
+      const contractAddress = contracts[i];
+      const normalizedContract = normalizeContractAddress(
+        contractAddress,
+        asset.symbol,
+        chainId
+      );
+
+      // Filter out wrapped native tokens (WETH, WBNB, WPOL, etc.) from search results
+      if (!isWrappedNativeToken(normalizedContract, chainId)) {
         result.push({
           ...
           contract: normalizedContract,

Functionally this should be equivalent today, but it future-proofs behavior if the wrapped-native detection ever starts treating the zero address specially.


152-184: parseFreshAndTrendingTokens normalization fits well; align wrapped-native check as well

The extraction of symbol and use of normalizeContractAddress before constructing the Asset looks good. For consistency with the other helpers, you could also use normalizedContract for the wrapped-native filter:

-        const contractAddress = j.leftColumn?.line1?.copyLink || '';
-        const symbol = j.leftColumn?.line1?.text2 || '';
-        const normalizedContract = normalizeContractAddress(
-          contractAddress,
-          symbol,
-          +chainId
-        );
+        const contractAddress = j.leftColumn?.line1?.copyLink || '';
+        const symbol = j.leftColumn?.line1?.text2 || '';
+        const normalizedContract = normalizeContractAddress(
+          contractAddress,
+          symbol,
+          +chainId
+        );

         // Filter out wrapped native tokens (WETH, WBNB, WPOL, etc.) from search results
-        if (!isWrappedNativeToken(contractAddress, +chainId)) {
+        if (!isWrappedNativeToken(normalizedContract, +chainId)) {
           res.push({
             chain: getChainName(+chainId),
             contract: normalizedContract,
             ...
             symbol,

Nice reuse of the helper and keeping the Optimism-native handling localized to this utility.

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

110-115: USDC price derivation and propagation look consistent, minor cleanups possible

The usdcPrice wiring from portfolio → getStableCurrencyBalanceOnEachChainHomeScreenPreviewBuy/Buy is coherent:

  • You pick the chain with the maximum stable “balance” and read price from that same entry.
  • That usdcPrice is then the one used for both the initial quote (Buy) and preview/refresh (PreviewBuy).

Two small follow‑ups you might consider:

  1. maxStableCoinBalance’s price?: number field is never set or read; either populate it when calling setMaxStableCoinBalance or drop it from the type to keep state shape minimal.
  2. if (usdcPriceForMaxChain) setUsdcPrice(usdcPriceForMaxChain); will ignore legitimate 0 values and leave a stale prior price; if you ever expect 0/very-low prices from the API, using an explicit != null check would avoid that subtlety.

Functionally this looks fine; these are mostly cleanliness and edge‑case considerations.

Also applies to: 159-160, 212-242, 960-979, 1124-1143

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

58-82: usdcPrice propagation into Relay Buy quotes and button state looks correct

  • Adding usdcPrice to BuyProps, threading it into getBestOffer, and including it in fetchBuyOffer’s dependencies ensures Relay quotes are computed using the portfolio‑derived USDC price.
  • Passing useRelayBuy={USE_RELAY_BUY} into BuyButton cleanly gates the “Enable Trading” behavior to the Intent SDK path only.

Behavior-wise this matches the PR goals; the dependency/refresh behavior around usdcPrice is acceptable given you already have an explicit/auto refresh mechanism.

Also applies to: 100-103, 280-337, 781-805

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between caf8364 and 9cacabb.

📒 Files selected for processing (9)
  • src/apps/pulse/components/App/HomeScreen.tsx (5 hunks)
  • src/apps/pulse/components/Buy/Buy.tsx (5 hunks)
  • src/apps/pulse/components/Buy/BuyButton.tsx (7 hunks)
  • src/apps/pulse/components/Buy/PreviewBuy.tsx (4 hunks)
  • src/apps/pulse/hooks/useRelayBuy.ts (4 hunks)
  • src/apps/pulse/utils/parseSearchData.ts (7 hunks)
  • src/apps/pulse/utils/utils.tsx (2 hunks)
  • src/hooks/useRemoteConfig.ts (1 hunks)
  • src/services/firebase.ts (2 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/Buy/PreviewBuy.tsx
  • src/apps/pulse/hooks/useRelayBuy.ts
  • src/apps/pulse/components/App/HomeScreen.tsx
  • src/apps/pulse/components/Buy/BuyButton.tsx
  • 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/Buy/PreviewBuy.tsx
  • src/apps/pulse/hooks/useRelayBuy.ts
  • src/apps/pulse/components/App/HomeScreen.tsx
🧬 Code graph analysis (4)
src/hooks/useRemoteConfig.ts (1)
src/apps/pulse/hooks/useRelayBuy.ts (1)
  • useRelayBuy (47-799)
src/apps/pulse/utils/parseSearchData.ts (2)
src/utils/blockchain.ts (2)
  • isWrappedNativeToken (514-521)
  • getChainName (269-288)
src/apps/pulse/utils/constants.ts (1)
  • getChainName (51-70)
src/apps/pulse/components/Buy/BuyButton.tsx (2)
src/apps/pulse/hooks/useRelayBuy.ts (2)
  • useRelayBuy (47-799)
  • BuyOffer (30-36)
src/apps/pulse/types/tokens.ts (1)
  • PayingToken (12-21)
src/apps/pulse/utils/utils.tsx (1)
src/apps/pulse/constants/tokens.ts (1)
  • STABLE_CURRENCIES (13-15)
⏰ 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: lint
  • GitHub Check: unit-tests
🔇 Additional comments (4)
src/services/firebase.ts (1)

34-36: Relay Buy now defaults to enabled in both config and error fallback paths

Setting remoteConfig.defaultConfig.USE_RELAY_BUY to true and returning true from getUseRelayBuyFlag on errors means Relay Buy will be enabled whenever remote config is unreachable or unset. This is a behavioral flip from the previous default-off posture; please confirm this is intended for all environments (including staging/production) and aligned with your rollout plan.

Also applies to: 55-63

src/hooks/useRemoteConfig.ts (1)

35-37: Initial Relay Buy state now optimistic true before Remote Config resolves

useRelayBuy now starts as true, and is only overridden once Remote Config (or URL override) loads. Together with the Firebase default and error fallback, Relay Buy will be effectively “on by default” even during startup or transient config errors. Please verify that this optimistic behavior is desired for all environments and won’t surprise users who previously saw Intent SDK first.

src/apps/pulse/components/Buy/PreviewBuy.tsx (1)

55-71: Preview refresh correctly uses usdcPrice; execution still depends on useRelayBuy’s default

Within PreviewBuy:

  • The new usdcPrice prop is cleanly added and passed into getBestOffer inside refreshPreviewBuyData, and included in that callback’s dependency list.
  • Auto‑refresh will thus recompute Relay offers using the latest portfolio‑derived USDC price.

However, note that the confirm path calls executeBuyDirectly(), which delegates to executeBuy in useRelayBuy without forwarding usdcPrice. As a result, the execution quote may use the default price configured inside useRelayBuy rather than the value you used for the preview. See the separate comment on useRelayBuy.executeBuy for a concrete suggestion.

Also applies to: 73-89, 497-553, 613-631

src/apps/pulse/components/Buy/BuyButton.tsx (1)

1-17: Buy button behavior cleanly separates Relay Buy from Intent SDK

This refactor looks solid:

  • The new useRelayBuy prop is correctly threaded into both getButtonText and isDisabled.
  • “Enable Trading on …” is now only shown when !useRelayBuy and modules aren’t installed, so Relay Buy never displays the Intent‑SDK‑specific enablement path.
  • For Relay Buy, getButtonText sensibly prefers expressIntentResponse.tokenAmountToReceive (from BuyOffer) when available, and falls back to the price‑based estimate otherwise.
  • The widened expressIntentResponse union (ExpressIntentResponse | BuyOffer | null | { error: string }) is guarded by property checks ('tokenAmountToReceive' in …, .bids?.length, .error) so each flow reads only the fields it owns.

Overall this achieves the “Enable Trading only when relayBuy is false” objective without introducing obvious regressions in the disabled state logic.

Also applies to: 24-41, 59-107, 109-126, 128-142, 144-163, 178-189

import { isWrappedNativeToken } from '../../../utils/blockchain';

// Optimism uses this special address for native ETH in Mobula API
const OP_NATIVE_MOBULA = '0xdeaddeaddeaddeaddeaddeaddeaddeaddead0000';
Copy link
Collaborator

Choose a reason for hiding this comment

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

And for other natives they use 0xeeee 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.

Yes this fix is only for op

toChainId
);
const normalizedToTokenAddress = isNativeToken(toTokenAddress)
? '0x0000000000000000000000000000000000000000'
Copy link
Collaborator

Choose a reason for hiding this comment

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

So why are we not wrapping anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So for wrapped token it has to convert the input to wrapped but on wallets balance that won't be possible to have that many wrapped token as the native. On sell it can be wrapped token since it's the destination token but for buy you can't enforce this

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok

@cloudflare-workers-and-pages
Copy link

Deploying x with  Cloudflare Pages  Cloudflare Pages

Latest commit: fbd155f
Status: ✅  Deploy successful!
Preview URL: https://b76cebc2.x-e62.pages.dev
Branch Preview URL: https://op-mobula-search.x-e62.pages.dev

View logs

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 (1)
src/apps/pulse/hooks/useRelayBuy.ts (1)

149-176: USD→USDC conversion logic is correct; consider guarding usdcPrice ≤ 0 explicitly

The native token normalization and USD→USDC conversion (usdAmount / usdcPrice then parseUnits(..., 6)) look correct for Relay’s EXact‑input USDC model. The only edge case is if usdcPrice is 0 or non‑finite, where toFixed will throw and surface as “Invalid amount.” If you want clearer diagnostics and a safer failure mode, you could add an explicit guard:

-          const usdAmount = parseFloat(fromAmount);
-          if (Number.isNaN(usdAmount) || usdAmount <= 0) {
-            throw new Error('Invalid amount');
-          }
-
-          // Convert USD to USDC amount using actual USDC price
-          const usdcAmount = usdAmount / usdcPrice;
+          const usdAmount = parseFloat(fromAmount);
+          if (Number.isNaN(usdAmount) || usdAmount <= 0) {
+            throw new Error('Invalid amount');
+          }
+          if (!Number.isFinite(usdcPrice) || usdcPrice <= 0) {
+            throw new Error('Invalid USDC price');
+          }
+
+          // Convert USD to USDC amount using actual USDC price
+          const usdcAmount = usdAmount / usdcPrice;

This is defensive rather than strictly required, since usdcPrice should already be > 0.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9cacabb and fbd155f.

📒 Files selected for processing (2)
  • src/apps/pulse/components/Buy/PreviewBuy.tsx (5 hunks)
  • src/apps/pulse/hooks/useRelayBuy.ts (6 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 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/Buy/PreviewBuy.tsx
  • src/apps/pulse/hooks/useRelayBuy.ts
📚 Learning: 2025-11-21T13:10:33.401Z
Learnt from: aldin4u
Repo: pillarwallet/x PR: 461
File: src/apps/pulse/components/Search/MarketList.tsx:10-15
Timestamp: 2025-11-21T13:10:33.401Z
Learning: In the Pulse app's MarketList component (src/apps/pulse/components/Search/MarketList.tsx), markets should display liquidity (not price) in the right-hand column. This is per the design specification.

Applied to files:

  • src/apps/pulse/components/Buy/PreviewBuy.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/Buy/PreviewBuy.tsx
  • src/apps/pulse/hooks/useRelayBuy.ts
📚 Learning: 2025-05-23T14:44:33.911Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 315
File: src/apps/the-exchange/utils/wrappedTokens.ts:6-20
Timestamp: 2025-05-23T14:44:33.911Z
Learning: XDAI (Gnosis Chain) is intentionally excluded from the WRAPPED_NATIVE_TOKEN_ADDRESSES mapping in the exchange app's wrappedTokens utility.

Applied to files:

  • src/apps/pulse/hooks/useRelayBuy.ts
🧬 Code graph analysis (1)
src/apps/pulse/hooks/useRelayBuy.ts (1)
src/services/tokensData.ts (1)
  • Token (19-29)
⏰ 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 (5)
src/apps/pulse/components/Buy/PreviewBuy.tsx (3)

55-71: Propagating usdcPrice into PreviewBuy props looks consistent

usdcPrice is optional, correctly threaded from PreviewBuyProps into the component, and only used in Relay Buy paths, so existing non‑Relay flows remain unaffected.

Also applies to: 73-88


388-395: executeBuy now receives portfolio and usdcPrice, aligning execution with preview

Passing both userPortfolio and usdcPrice into executeBuy ensures the executed Relay Buy uses the same USDC pricing context and balance validation as the preview, resolving the earlier quote mismatch between preview and execution.


535-542: Including usdcPrice in quote refresh and dependencies avoids stale pricing

Forwarding usdcPrice into getBestOffer and adding it to refreshPreviewBuyData’s deps means preview quotes will re‑compute when USDC price changes, and the 15s auto‑refresh will track the latest price rather than a captured value.

Also applies to: 614-632

src/apps/pulse/hooks/useRelayBuy.ts (2)

24-45: usdcPrice threading into BuyParams and hook state is clean and backwards‑compatible

Adding usdcPrice?: number to BuyParams and keeping it optional (with a default of 1.0 in getBestOffer) lets newer flows be price‑aware without breaking existing callers that don’t pass a value.


608-614: executeBuy now forwards usdcPrice into getBestOffer, keeping execution aligned with preview

Extending executeBuy’s signature and passing usdcPrice through to getBestOffer ensures the execution quote uses the same USDC price as the one used for preview/refresh, avoiding subtle discrepancies while keeping older call sites functional via the usdcPrice default.

Also applies to: 631-638

@vignesha22 vignesha22 merged commit 78de4b6 into staging Nov 24, 2025
6 checks passed
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.

2 participants