Skip to content

PRO-3864 - Wrapped Tokens#456

Merged
vignesha22 merged 3 commits intostagingfrom
PRO-3864-WrappedTokenFilter
Nov 18, 2025
Merged

PRO-3864 - Wrapped Tokens#456
vignesha22 merged 3 commits intostagingfrom
PRO-3864-WrappedTokenFilter

Conversation

@vignesha22
Copy link
Contributor

@vignesha22 vignesha22 commented Nov 18, 2025

Description

  • Filtered out wrapped tokens from pulse search
  • Changed the name and symbol on portfolio tokens for wrapped native tokens

How Has This Been Tested?

  • Tested Locally

Screenshots (if appropriate):

Screenshot 2025-11-18 at 2 20 38 PM
Screenshot 2025-11-18 at 2 20 45 PM
Screenshot 2025-11-18 at 2 20 54 PM

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
    • Wrapped native tokens now show as "Wrapped ..." with correct symbols in search results, asset displays, and portfolio views.
    • Portfolio token filtering now excludes wrapped native tokens alongside other excluded categories.
    • Token name/symbol and contract displays are more consistent for wrapped assets across the app.

@vignesha22 vignesha22 requested review from IAmKio and RanaBug November 18, 2025 08:35
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Walkthrough

Adds wrapped-native token detection utilities and uses them to filter out wrapped native tokens and adjust display name/symbol in parsing and portfolio conversion; one UI comment updated to mention wrapped native tokens.

Changes

Cohort / File(s) Summary
Blockchain utilities
src/utils/blockchain.ts
Added WRAPPED_NATIVE_TOKEN_ADDRESSES, WRAPPED_NATIVE_TOKEN_SYMBOLS, isWrappedNativeToken(tokenAddress, chainId) and getWrappedTokenSymbol(chainId).
Search/asset parsing
src/apps/pulse/utils/parseSearchData.ts
Resolve chainId/contractAddress, call isWrappedNativeToken to exclude wrapped native tokens from results and use wrapped symbol when applicable.
Portfolio service conversion
src/services/pillarXApiWalletPortfolio.ts
Detect wrapped native tokens via isWrappedNativeToken and set conditional display name/symbol using getWrappedTokenSymbol during portfolio -> token conversion.
Portfolio token list (UI)
src/apps/pulse/components/Search/PortfolioTokenList.tsx
Comment updated to mention wrapping native tokens alongside stable currencies (no behavior change).

Sequence Diagram(s)

sequenceDiagram
    participant UI as PortfolioTokenList (UI)
    participant Parse as parseSearchData
    participant Service as pillarXApiWalletPortfolio
    participant Chain as blockchain utils

    Note over Chain: New utilities<br/>(isWrappedNativeToken, getWrappedTokenSymbol)

    UI->>Chain: isWrappedNativeToken(addr, chainId)
    alt wrapped
        Chain-->>UI: true
        UI-->>UI: exclude token from display
    else not wrapped
        Chain-->>UI: false
        UI-->>UI: include token
    end

    Parse->>Chain: isWrappedNativeToken(contract, chainId)
    alt wrapped
        Chain-->>Parse: true
        Parse->>Chain: getWrappedTokenSymbol(chainId)
        Chain-->>Parse: symbol
        Parse-->>App: exclude or label as wrapped
    else not wrapped
        Chain-->>Parse: false
        Parse-->>App: include token entry
    end

    Service->>Chain: isWrappedNativeToken(contract, chainId)
    alt wrapped
        Chain-->>Service: true
        Service->>Chain: getWrappedTokenSymbol(chainId)
        Chain-->>Service: symbol
        Service-->>App: token with "Wrapped <Name>" and wrapped symbol
    else not wrapped
        Chain-->>Service: false
        Service-->>App: token unchanged
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to:
    • Accuracy and coverage of WRAPPED_NATIVE_TOKEN_ADDRESSES mapping for supported chain IDs.
    • Correct resolution and normalization of contractAddress and chainId where used.
    • Consistency in excluding wrapped tokens vs. renaming/displaying them across parse/service/UI paths.

Possibly related PRs

Suggested reviewers

  • IAmKio
  • RanaBug

Poem

🐇 I hop through lines both short and long,
Wrapped tokens sorted, tidy and strong.
Names that sparkle, symbols aligned,
Lists trimmed neat — a rabbit-approved find. 🎩✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
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.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title "PRO-3864 - Wrapped Tokens" directly relates to the main changes in the PR, which involve handling wrapped tokens across search and portfolio components.
Description check ✅ Passed The PR description covers the main changes and includes testing details and screenshots, but lacks specific technical details about implementation.
✨ 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 PRO-3864-WrappedTokenFilter

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.

@vignesha22 vignesha22 self-assigned this Nov 18, 2025
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 18, 2025

Deploying x with  Cloudflare Pages  Cloudflare Pages

Latest commit: 2177c74
Status: ✅  Deploy successful!
Preview URL: https://6769696f.x-e62.pages.dev
Branch Preview URL: https://pro-3864-wrappedtokenfilter.x-e62.pages.dev

View logs

@github-actions github-actions bot temporarily deployed to Preview (PRO-3864-WrappedTokenFilter) November 18, 2025 08: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: 0

🧹 Nitpick comments (2)
src/utils/blockchain.ts (1)

523-525: Consider a more defensive fallback for unsupported chainIds.

The function returns an empty string when a chainId is not found in the mapping. While this is unlikely to cause issues in practice (since isWrappedNativeToken would also return false for unsupported chainIds), it could lead to display issues if the mappings get out of sync.

Consider one of these alternatives:

 export const getWrappedTokenSymbol = (chainId: number): string => {
-  return WRAPPED_NATIVE_TOKEN_SYMBOLS[chainId] || '';
+  const symbol = WRAPPED_NATIVE_TOKEN_SYMBOLS[chainId];
+  if (!symbol) {
+    console.warn(`No wrapped token symbol found for chainId: ${chainId}`);
+    return '';
+  }
+  return symbol;
 };

Or return undefined to make the absence explicit:

export const getWrappedTokenSymbol = (chainId: number): string | undefined => {
  return WRAPPED_NATIVE_TOKEN_SYMBOLS[chainId];
};
src/apps/pulse/utils/parseSearchData.ts (1)

79-100: Consider extracting the wrapped token logic into a shared utility.

The wrapped token detection and display name/symbol computation is duplicated across parseAssetData, parseTokenData, and parseFreshAndTrendingTokens. While the current implementation is correct, consider extracting this into a reusable utility function to reduce duplication and improve maintainability.

Example refactor:

function getTokenDisplayInfo(
  address: string,
  chainId: number,
  name: string,
  symbol: string
) {
  const isWrapped = isWrappedNativeToken(address, chainId);
  return {
    displayName: isWrapped ? `Wrapped ${name}` : name,
    displaySymbol: isWrapped ? getWrappedTokenSymbol(chainId) : symbol,
  };
}

Then use it in the parsing functions:

const { displayName, displaySymbol } = getTokenDisplayInfo(
  contractAddress,
  chainId,
  asset.name,
  asset.symbol
);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d62f231 and 6f73a7a.

📒 Files selected for processing (4)
  • src/apps/pulse/components/Search/PortfolioTokenList.tsx (2 hunks)
  • src/apps/pulse/utils/parseSearchData.ts (4 hunks)
  • src/services/pillarXApiWalletPortfolio.ts (2 hunks)
  • src/utils/blockchain.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 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/utils/blockchain.ts
  • src/services/pillarXApiWalletPortfolio.ts
📚 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/Search/PortfolioTokenList.tsx
📚 Learning: 2025-04-23T15:04:20.826Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 290
File: src/apps/pillarx-app/components/TileTitle/TitleTitle.tsx:6-10
Timestamp: 2025-04-23T15:04:20.826Z
Learning: In this repository, TileTitleProps and TileTitle are different types that serve different purposes. TileTitleProps is used for the TileTitle component and has optional fields (title?, leftDecorator?, rightDecorator?), while TileTitle in api.ts has a required text field. The TileTitleProps interface aligns with the TokensMarketData.title type in api.ts which also has optional fields.

Applied to files:

  • src/apps/pulse/components/Search/PortfolioTokenList.tsx
📚 Learning: 2025-04-23T15:04:20.826Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 290
File: src/apps/pillarx-app/components/TileTitle/TitleTitle.tsx:6-10
Timestamp: 2025-04-23T15:04:20.826Z
Learning: In this repository, TileTitleProps and TileTitle are different types that serve different purposes. TileTitleProps is used for the TileTitle component and has optional fields (title?, leftDecorator?, rightDecorator?), while TileTitle in api.ts has a required title field. The TileTitleProps structure aligns with how it's used in the TokensMarketData type in api.ts.

Applied to files:

  • src/apps/pulse/components/Search/PortfolioTokenList.tsx
📚 Learning: 2025-11-04T14:34:00.373Z
Learnt from: RanaBug
Repo: pillarwallet/x PR: 445
File: src/containers/Authorized.tsx:63-77
Timestamp: 2025-11-04T14:34:00.373Z
Learning: In src/containers/Authorized.tsx, the tempKit useEffect intentionally excludes chainId from its dependency array because the kit is used by useWalletModeVerification to check wallet mode across all supported chains, regardless of the currently selected chainId. The chainId parameter is only used for initial kit configuration and does not affect the multi-chain verification results.

Applied to files:

  • src/apps/pulse/components/Search/PortfolioTokenList.tsx
  • src/services/pillarXApiWalletPortfolio.ts
🧬 Code graph analysis (4)
src/utils/blockchain.ts (1)
src/apps/the-exchange/utils/wrappedTokens.ts (1)
  • WRAPPED_NATIVE_TOKEN_ADDRESSES (8-21)
src/apps/pulse/components/Search/PortfolioTokenList.tsx (3)
src/services/pillarXApiWalletPortfolio.ts (1)
  • convertPortfolioAPIResponseToToken (27-61)
src/utils/blockchain.ts (1)
  • isWrappedNativeToken (514-521)
src/services/tokensData.ts (1)
  • chainNameToChainIdTokensData (234-255)
src/services/pillarXApiWalletPortfolio.ts (2)
src/utils/blockchain.ts (2)
  • isWrappedNativeToken (514-521)
  • getWrappedTokenSymbol (523-525)
src/services/tokensData.ts (1)
  • chainIdToChainNameTokensData (210-231)
src/apps/pulse/utils/parseSearchData.ts (3)
src/services/tokensData.ts (1)
  • chainNameToChainIdTokensData (234-255)
src/utils/blockchain.ts (3)
  • isWrappedNativeToken (514-521)
  • getWrappedTokenSymbol (523-525)
  • getChainName (269-288)
src/types/api.ts (1)
  • TokensMarketData (170-177)
⏰ 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 (9)
src/apps/pulse/components/Search/PortfolioTokenList.tsx (2)

12-15: LGTM on the import addition.

The import of isWrappedNativeToken is correctly placed and necessary for the filtering logic below.


58-65: Wrapped token filtering logic looks correct.

The filter correctly excludes both stable currencies and wrapped native tokens. The usage of chainNameToChainIdTokensData to convert the blockchain name to a chainId for the isWrappedNativeToken check is consistent with the pattern used elsewhere in this PR.

src/services/pillarXApiWalletPortfolio.ts (2)

17-22: LGTM on the import additions.

The imports of isWrappedNativeToken and getWrappedTokenSymbol are correctly placed and necessary for the wrapped token handling logic below.


35-59: Wrapped token handling logic looks correct.

The implementation properly:

  • Extracts the chainId from the contract's chainId string
  • Detects wrapped native tokens
  • Adjusts the display name to "Wrapped " format
  • Uses the correct wrapped token symbol from getWrappedTokenSymbol

The logic is consistent with the approach used in parseSearchData.ts.

src/utils/blockchain.ts (2)

514-521: LGTM on the wrapped token detection logic.

The function correctly handles:

  • Unsupported chainIds by returning false
  • Case-insensitive address comparison (appropriate for Ethereum addresses)

496-503: No issues found—mappings are consistent and correct.

Verification confirms that WRAPPED_NATIVE_TOKEN_ADDRESSES in blockchain.ts matches the exchange app exactly. Both include the same 6 chains (Ethereum, Polygon, Optimism, Arbitrum, Base, BNB) with identical addresses. XDAI (chainId 100) is intentionally excluded in both locations, as documented in the exchange app with the comment "// Not including XDAI below," and confirmed by the explicit XDAI filtering in blockchain.ts.

src/apps/pulse/utils/parseSearchData.ts (3)

14-18: LGTM on the import additions.

The imports are correctly placed and necessary for the wrapped token handling logic in the parsing functions below.


46-67: Wrapped token handling in parseAssetData looks correct.

The implementation properly detects wrapped native tokens and adjusts the display name and symbol accordingly. The pattern is consistent with the approach used in pillarXApiWalletPortfolio.ts.


128-159: Wrapped token handling in parseFreshAndTrendingTokens looks correct.

The implementation properly handles wrapped native tokens by:

  • Extracting the chainId from the projection id
  • Detecting wrapped tokens
  • Computing appropriate display names and symbols

The logic is consistent with the other parsing functions in this file.

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 (2)
src/utils/blockchain.ts (2)

496-503: Consider consolidating duplicate wrapped token mappings.

This mapping duplicates WRAPPED_NATIVE_TOKEN_ADDRESSES from src/apps/the-exchange/utils/wrappedTokens.ts (identical addresses for all chains). Additionally, the Polygon address on line 498 duplicates the existing WRAPPED_POL_TOKEN_ADDRESS constant defined at lines 59-60 in this same file.

Consider consolidating these into a single shared utility to reduce maintenance burden when addresses need updates.

If there's a deliberate architectural reason to keep exchange app utilities separate from general utilities, consider at least reusing WRAPPED_POL_TOKEN_ADDRESS for the Polygon entry:

 export const WRAPPED_NATIVE_TOKEN_ADDRESSES: Record<number, string> = {
-  137: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', // Polygon - WPOL
+  137: WRAPPED_POL_TOKEN_ADDRESS, // Polygon - WPOL
 };

514-521: Implementation looks good with optional input validation.

The case-insensitive address comparison is correct for Ethereum addresses, and the function properly handles unsupported chains.

Optionally, consider adding basic input validation to catch invalid inputs early:

 export const isWrappedNativeToken = (
   tokenAddress: string,
   chainId: number
 ): boolean => {
+  if (!tokenAddress || !chainId) return false;
   const wrappedAddress = WRAPPED_NATIVE_TOKEN_ADDRESSES[chainId];
   if (!wrappedAddress) return false;
   return tokenAddress.toLowerCase() === wrappedAddress.toLowerCase();
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f73a7a and e944e52.

📒 Files selected for processing (2)
  • src/apps/pulse/utils/parseSearchData.ts (4 hunks)
  • src/utils/blockchain.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/apps/pulse/utils/parseSearchData.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
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.
📚 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/utils/blockchain.ts
🧬 Code graph analysis (1)
src/utils/blockchain.ts (1)
src/apps/the-exchange/utils/wrappedTokens.ts (1)
  • WRAPPED_NATIVE_TOKEN_ADDRESSES (8-21)
⏰ 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 (2)
src/utils/blockchain.ts (2)

505-512: LGTM!

The wrapped native token symbols mapping is correctly defined for all supported chains.


523-525: No action required—the code is safe.

The mappings are perfectly aligned: both WRAPPED_NATIVE_TOKEN_ADDRESSES and WRAPPED_NATIVE_TOKEN_SYMBOLS contain identical chain IDs (1, 137, 10, 42161, 8453, 56). Since getWrappedTokenSymbol is only called when isWrappedNativeToken returns true, and that function checks WRAPPED_NATIVE_TOKEN_ADDRESSES[chainId] exists before returning true, the chainId is guaranteed to exist in both mappings. The empty string fallback is defensive programming and unreachable in practice.

@vignesha22 vignesha22 merged commit 6f02fe1 into staging Nov 18, 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