Skip to content

Conversation

@fairlighteth
Copy link
Contributor

@fairlighteth fairlighteth commented Nov 18, 2025

Summary

Related to #6531 and #6429

Guard bridge token aggregation against malformed provider entries so they no longer crash the selector (apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts:45-79) and add a sanity check inside TokenWithLogo.fromToken to surface misuse early (libs/common-const/src/types.ts:7-22). The bridge UI now reports routes as unavailable whenever every upstream token is discarded, preventing the blank-screen regression observed when switching chains in bridge mode.

To Test

  1. Open production-like build (Base → Arbitrum bridge flow)

    • Connect wallet on Base, reproduce the crash scenario (permit on Limit Orders → swap flow → open buy selector → switch to Arbitrum) and verify the selector stays responsive
    • When the provider returns malformed tokens, expect a console warning [bridgeTokens] Ignoring malformed token instead of an error boundary
    • Selector should either list valid tokens or show the “route unavailable” message, never a blank screen
  2. Smoke test other token selectors

    • Regular swap/limit order selectors still render tokens correctly
    • No unexpected runtime errors involving TokenWithLogo.fromToken

Background

The bridge provider occasionally returns null tokens even when isRouteAvailable is true, which previously caused token.chainId dereferences to explode. These changes sanitize external data and keep the selector functional despite upstream glitches.

Summary by CodeRabbit

  • Bug Fixes

    • Malformed bridge tokens (missing key data) are now ignored with warnings, and bridge availability reports false when no valid tokens remain.
  • Improvements

    • Stronger runtime validation for token data to prevent bad entries from reaching the UI.
    • Improved handling of token logo information so token displays are more consistent.

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

@fairlighteth fairlighteth self-assigned this Nov 18, 2025
@vercel
Copy link

vercel bot commented Nov 18, 2025

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

Project Deployment Preview Updated (UTC)
cowfi Ready Ready Preview Nov 24, 2025 1:23pm
explorer-dev Ready Ready Preview Nov 24, 2025 1:23pm
swap-dev Ready Ready Preview Nov 24, 2025 1:23pm
widget-configurator Ready Ready Preview Nov 24, 2025 1:23pm
2 Skipped Deployments
Project Deployment Preview Updated (UTC)
cosmos Ignored Ignored Nov 24, 2025 1:23pm
sdk-tools Ignored Ignored Preview Nov 24, 2025 1:23pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Walkthrough

Replaces direct token mapping in the bridge-supported-tokens hook with a filtering reduce that skips malformed tokens (missing chainId/address) and wraps valid entries via TokenWithLogo.fromToken; TokenWithLogo now requires/exports logoURI and enforces presence of chainId and address at runtime.

Changes

Cohort / File(s) Summary
Bridge Token Hook Validation
apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
Replaces mapping with a reduce that filters out tokens missing chainId or address, logs warnings for skipped tokens, constructs tokens via TokenWithLogo.fromToken, and sets isRouteAvailable to false when no valid tokens exist.
TokenWithLogo Class Enhancement
libs/common-const/src/types.ts
Adds required runtime validation in TokenWithLogo.fromToken (throws if chainId/address missing) and changes constructor to accept logoURI as the first public parameter (making logoURI a public property).

Sequence Diagram(s)

sequenceDiagram
    participant Hook as BridgeHook
    participant API as BridgeAPI
    participant TokenClass as TokenWithLogo

    Note over Hook,API: fetch supported tokens
    Hook->>API: request supported tokens
    API-->>Hook: result { tokens: [...], isRouteAvailable }
    Note over Hook: reduce over result.tokens
    Hook->>Hook: for each token\n- if missing chainId/address -> log warning, skip
    Hook->>TokenClass: TokenWithLogo.fromToken(validToken, logoURI)
    TokenClass-->>Hook: TokenWithLogo instance
    Note over Hook: derive tokens array\nset isRouteAvailable = (tokens.length>0 ? result.isRouteAvailable : false)
    Hook-->>Consumer: { tokens: [...TokenWithLogo], isRouteAvailable }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Attention areas:
    • Update impact of TokenWithLogo constructor signature across codebase (instantiations, subclassing).
    • Correctness of token filtering and isRouteAvailable derivation in edge cases.
    • Console warnings—verify logging level/format for production.

Possibly related PRs

Suggested labels

Bridge

Suggested reviewers

  • elena-zh
  • shoom3301

Poem

🐰 A little rabbit checks each token's face,
Skips the gaps with a gentle, cautious pace,
Logo first, then chain and address in line,
I wrap them neat so routes can safely shine. ✨

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 correctly summarizes the main change: adding validation to token structure in useBridgeSupportedTokens and TokenWithLogo to prevent crashes.
Description check ✅ Passed The description includes all required template sections: Summary with issue references, clear high-level description, comprehensive To Test steps with checkboxes, and detailed Background context.
✨ 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 fix/white-screen-of-death

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15e10da and 43ed61c.

📒 Files selected for processing (1)
  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-09-25T08:49:32.256Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
📚 Learning: 2025-08-05T14:27:05.023Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5992
File: libs/wallet/src/web3-react/utils/switchChain.ts:36-38
Timestamp: 2025-08-05T14:27:05.023Z
Learning: In libs/wallet/src/web3-react/utils/switchChain.ts, the team prefers using Record<SupportedChainId, string | null> over Partial<Record<SupportedChainId, string>> for WALLET_RPC_SUGGESTION to enforce that all supported chain IDs have explicit values set, even if some might be null. This ensures compile-time completeness checking.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
📚 Learning: 2025-08-08T13:55:17.528Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/state/tokens/allTokensAtom.ts:78-78
Timestamp: 2025-08-08T13:55:17.528Z
Learning: In libs/tokens/src/state/tokens/allTokensAtom.ts (TypeScript/Jotai), the team prefers to wait for token lists to initialize (listsStatesListAtom non-empty) before returning tokens. No fallback to favorites/user-added/native tokens should be used when listsStatesList is empty.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
📚 Learning: 2025-08-12T06:33:19.348Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6137
File: libs/tokens/src/state/tokens/allTokensAtom.ts:34-65
Timestamp: 2025-08-12T06:33:19.348Z
Learning: In libs/tokens/src/utils/parseTokenInfo.ts, the parseTokenInfo() function returns a new instance of TokenInfo using object spread syntax ({ ...token, ... }), making it safe to mutate properties like lpTokenProvider on the returned object without side effects.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
🧬 Code graph analysis (1)
apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts (1)
libs/common-const/src/types.ts (1)
  • TokenWithLogo (6-36)
⏰ 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: Setup
  • GitHub Check: Cypress
🔇 Additional comments (3)
apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts (3)

27-45: Excellent defensive filtering to prevent crashes from malformed provider data.

The pre-validation approach correctly:

  • Catches malformed tokens before they reach TokenWithLogo.fromToken (which would throw)
  • Logs a clear warning for debugging rather than crashing the UI
  • Provides sensible empty-string fallbacks for missing name/symbol
  • Accumulates only valid tokens for the selector

This defensive duplication of validation (also present in TokenWithLogo.fromToken) is appropriate when consuming external bridge provider data.


46-46: Correct logic to prevent blank-screen regression.

Setting isRouteAvailable to false when all tokens are filtered out prevents the blank-screen scenario described in the PR objectives. This ensures the UI shows "route unavailable" rather than an empty selector.


27-27: Add null/undefined check before accessing result.tokens.

The code at line 27 assumes result.tokens is always defined, but evidence from useBridgeProviderBuyTokens.ts (which calls the same SDK method) uses optional chaining: tokens?.reduce(...). This pattern inconsistency indicates the SDK contract allows tokens to be undefined. Add result.tokens?.reduce(...) or an explicit guard to prevent potential runtime errors.

⛔ Skipped due to learnings
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.

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

@elena-zh elena-zh left a comment

Choose a reason for hiding this comment

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

Hey @fairlighteth , thank you! I have not been able to face a crash during my tests.

@fairlighteth fairlighteth marked this pull request as ready for review November 19, 2025 15:50
@fairlighteth fairlighteth requested a review from a team November 19, 2025 15:50
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)
libs/common-const/src/types.ts (1)

8-10: Good defensive validation; consider also checking for null chainId.

The validation correctly guards against malformed tokens and provides a clear error message. The check prevents the white-screen crash described in the PR objectives.

Consider using loose equality to also catch null chainId:

-    if (!token || token.chainId === undefined || !token.address) {
+    if (!token || token.chainId == null || !token.address) {
      throw new Error('TokenWithLogo.fromToken requires a token with chainId and address')
    }

This would catch both undefined and null values, making the validation more robust against various malformed provider responses.

apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts (1)

46-49: Effective validation that prevents crashes while maintaining observability.

The validation correctly filters malformed tokens during aggregation and logs warnings for visibility. This aligns with the PR objective of preventing the white-screen crash when bridge providers return invalid data.

For consistency with the suggestion in types.ts, consider also catching null chainId:

-                if (!token || !token.address || token.chainId === undefined) {
+                if (!token || !token.address || token.chainId == null) {
                  console.warn('[bridgeTokens] Ignoring malformed token', token)
                  return
                }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71df046 and 15e10da.

📒 Files selected for processing (2)
  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts (2 hunks)
  • libs/common-const/src/types.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-08-05T14:27:05.023Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5992
File: libs/wallet/src/web3-react/utils/switchChain.ts:36-38
Timestamp: 2025-08-05T14:27:05.023Z
Learning: In libs/wallet/src/web3-react/utils/switchChain.ts, the team prefers using Record<SupportedChainId, string | null> over Partial<Record<SupportedChainId, string>> for WALLET_RPC_SUGGESTION to enforce that all supported chain IDs have explicit values set, even if some might be null. This ensures compile-time completeness checking.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
📚 Learning: 2025-09-25T08:49:32.256Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
📚 Learning: 2025-08-08T13:55:17.528Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/state/tokens/allTokensAtom.ts:78-78
Timestamp: 2025-08-08T13:55:17.528Z
Learning: In libs/tokens/src/state/tokens/allTokensAtom.ts (TypeScript/Jotai), the team prefers to wait for token lists to initialize (listsStatesListAtom non-empty) before returning tokens. No fallback to favorites/user-added/native tokens should be used when listsStatesList is empty.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
📚 Learning: 2025-09-25T08:48:53.495Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.

Applied to files:

  • apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts
📚 Learning: 2025-08-12T06:33:19.348Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6137
File: libs/tokens/src/state/tokens/allTokensAtom.ts:34-65
Timestamp: 2025-08-12T06:33:19.348Z
Learning: In libs/tokens/src/utils/parseTokenInfo.ts, the parseTokenInfo() function returns a new instance of TokenInfo using object spread syntax ({ ...token, ... }), making it safe to mutate properties like lpTokenProvider on the returned object without side effects.

Applied to files:

  • libs/common-const/src/types.ts
📚 Learning: 2025-08-12T06:33:19.348Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6137
File: libs/tokens/src/state/tokens/allTokensAtom.ts:34-65
Timestamp: 2025-08-12T06:33:19.348Z
Learning: In libs/tokens/src/state/tokens/allTokensAtom.ts, the parseTokenInfo() function returns a new instance of TokenInfo each time, making it safe to mutate properties like lpTokenProvider on the returned object without side effects.

Applied to files:

  • libs/common-const/src/types.ts
🔇 Additional comments (2)
apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedTokens.ts (2)

73-74: Correct logic that addresses the core issue.

The derivation ensures isRouteAvailable is false when no valid tokens remain after filtering, preventing the blank-screen regression described in the PR objectives. The approach correctly handles the scenario where providers report isRouteAvailable: true but return only malformed tokens.


77-78: LGTM!

The return statement correctly uses the derived values, ensuring consumers receive consistent and validated state where isRouteAvailable accurately reflects token availability.

@alfetopito alfetopito merged commit d3d14b2 into develop Nov 25, 2025
15 checks passed
@alfetopito alfetopito deleted the fix/white-screen-of-death branch November 25, 2025 10:47
@github-actions github-actions bot locked and limited conversation to collaborators Nov 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants