Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 WalkthroughAdds quote metadata (quoteId, quoteVerified, quoteExpiration) through bridge context and exposes UI: Quote ID display with copy, verification badge/icon, tooltip with refresh/expiration, helpers/tests, barrel exports, and locale entries; also minor import/barrel reorganizations. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (8)
apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/TradeRateDetails/index.tsx (1)
33-35: Consider reusingQuoteIdInput/QuoteExpirationInputtype aliases instead of inline types.The types
string | number | nullandstring | nullduplicate the domain aliases already defined inquoteId.ts.♻️ Proposed type reuse
+import { type QuoteExpirationInput, type QuoteIdInput } from '../RowQuoteId/quoteId' interface TradeRateDetailsProps { ... - quoteId?: string | number | null - quoteVerified?: boolean | null - quoteExpiration?: string | null + quoteId?: QuoteIdInput + quoteVerified?: boolean | null + quoteExpiration?: QuoteExpirationInput ... }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/TradeRateDetails/index.tsx` around lines 33 - 35, Replace the inline union types for quoteId and quoteExpiration with the existing aliases: import and use QuoteIdInput for quoteId (instead of string | number | null) and QuoteExpirationInput for quoteExpiration (instead of string | null) in the TradeRateDetails component; update the props/type declaration referencing quoteId?: QuoteIdInput and quoteExpiration?: QuoteExpirationInput and ensure the import of these types from the module that defines them (e.g., quoteId.ts) is added at the top of the file.apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/QuoteVerificationIndicator.tsx (1)
15-59:CompactIconWrapperduplicates styles already applied byCompactIconTooltip > div.Both
CompactIconTooltip > div(lines 16–21) andCompactIconWrapper(lines 53–59) applydisplay: inline-flex,align-items: center,justify-content: center, andline-height: 0. Onlyvertical-align: middleis unique toCompactIconWrapper. Consider keeping only the wrapper and removing the redundant targeting on> div, or eliminating the wrapper and movingvertical-align: middleinto the> divselector.♻️ Consolidate styles into a single layer
const CompactIconTooltip = styled(HoverTooltip)` > div { - display: inline-flex; - align-items: center; - justify-content: center; - line-height: 0; + vertical-align: middle; } `Then update
CompactIconWrapperto keep the full flex layout (or vice-versa).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/QuoteVerificationIndicator.tsx` around lines 15 - 59, The styles for centering are duplicated: remove the redundant rules from CompactIconTooltip's "> div" selector and keep them on CompactIconWrapper; specifically delete display:inline-flex, align-items:center, justify-content:center and line-height:0 from CompactIconTooltip > div, and ensure CompactIconWrapper (the styled span) retains display:inline-flex, align-items:center, justify-content:center, line-height:0 and vertical-align:middle so all icon instances use CompactIconWrapper for layout.apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.test.ts (1)
35-39:getQuoteExpiresInLabeltest suite is missing coverage for the hours and exact-minutes branches.The following reachable code paths in
quoteId.tshave no tests:
hours > 0→"{h}h {m}m"(e.g.,"1h 5m")seconds === 0→"{m}m"(exact minutes, e.g.,"3m")- Already-expired quote →
"0s"✅ Proposed additional test cases
+ it('formats remaining hours', () => { + const now = Date.parse('2026-02-18T12:00:00.000Z') + expect(getQuoteExpiresInLabel('2026-02-18T13:05:00.000Z', now)).toBe('1h 5m') + }) + + it('formats exact minutes with no seconds', () => { + const now = Date.parse('2026-02-18T12:00:00.000Z') + expect(getQuoteExpiresInLabel('2026-02-18T12:03:00.000Z', now)).toBe('3m') + }) + + it('returns 0s for an already-expired quote', () => { + const now = Date.parse('2026-02-18T12:01:00.000Z') + expect(getQuoteExpiresInLabel('2026-02-18T12:00:00.000Z', now)).toBe('0s') + })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.test.ts` around lines 35 - 39, Add new unit tests to apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.test.ts that call getQuoteExpiresInLabel with inputs exercising the missing branches: (1) an expiry >1 hour to assert the "Hh Mm" format (e.g., expect "1h 5m" for a timestamp 1h5m in the future), (2) an expiry with seconds===0 to assert exact minute formatting (e.g., expect "3m" for exactly 3 minutes), and (3) an already-expired timestamp (expiry <= now) to assert it returns "0s"; use the existing pattern of passing a fixed now value like the other tests to keep them deterministic.apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/quoteId.ts (1)
33-33: Hours branch silently drops seconds — document the intentional truncation.
"1h 5m 30s"is displayed as"1h 5m"once hours are present. This is a reasonable design simplification for long countdowns, but it is undocumented and untested (see test file note below).♻️ Add a brief comment
- if (hours > 0) return `${hours}h ${minutes}m` + // Seconds precision is intentionally omitted for hour-scale countdowns + if (hours > 0) return `${hours}h ${minutes}m`🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/quoteId.ts` at line 33, Add a brief inline comment above the hours branch that states seconds are intentionally omitted when hours > 0 (i.e., the line "if (hours > 0) return `${hours}h ${minutes}m`") so the truncation is documented and clear to reviewers and tests; keep the implementation unchanged, just document the design choice mentioning "seconds intentionally dropped for long countdowns" and link it to the hours/minutes branch.apps/cowswap-frontend/src/modules/swap/containers/SwapRateDetails/index.tsx (1)
41-44: Duplicates quote-metadata derivation already handled bynormalizeQuoteMeta.Lines 41–44 manually re-implement the same
quoteError → quoteResponse → id/verified/expirationderivation thatnormalizeQuoteMetainuseQuoteSwapContext.tsalready encapsulates. Extracting a shareduseQuoteMetadata()hook would remove this duplication and keep normalization (includingString(id)) in one place.♻️ Sketch of a shared hook
// modules/tradeQuote/hooks/useQuoteMetadata.ts export function useQuoteMetadata() { const { quote, error: quoteError } = useTradeQuote() const quoteResponse = quoteError ? undefined : quote?.quoteResults.quoteResponse return { quoteId: quoteResponse?.id != null ? String(quoteResponse.id) : undefined, quoteVerified: !!quoteResponse?.verified, quoteExpiration: quoteResponse?.expiration ?? null, showVerificationIcon: !!quoteResponse, } }Both
SwapRateDetailsanduseQuoteSwapContextcan then calluseQuoteMetadata().🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/swap/containers/SwapRateDetails/index.tsx` around lines 41 - 44, SwapRateDetails duplicates the quote metadata derivation already handled by normalizeQuoteMeta in useQuoteSwapContext; extract a shared hook (e.g., useQuoteMetadata) that centralizes quote, quoteError → quoteResponse mapping and normalization (ensure id is cast via String(id) when present, quoteVerified boolean, quoteExpiration defaulting to null, and a showVerificationIcon flag), then replace the manual derivation in SwapRateDetails and call useQuoteMetadata from useQuoteSwapContext so both consume the single source of truth (refer to SwapRateDetails, useQuoteSwapContext, and normalizeQuoteMeta when implementing).apps/cowswap-frontend/src/modules/bridge/hooks/useQuoteSwapContext.ts (1)
44-48: Prefer primitive memo deps over the fullquoteobject.
quoteMetaonly reads three leaf primitives (id,verified,expiration) fromquote?.quoteResults.quoteResponse. Using the wholequoteobject as a dep means every poll cycle (whentradeQuotesatom updates thequotereference) recreatesquoteMetaeven when those three fields haven't changed, cascading unnecessarily into the outeruseMemo.♻️ Proposed refactor
+ const quoteResponse = quoteError ? undefined : quote?.quoteResults.quoteResponse const quoteMeta = useMemo(() => { - const quoteResponse = quoteError ? undefined : quote?.quoteResults.quoteResponse - return normalizeQuoteMeta(quoteResponse?.id, quoteResponse?.verified, quoteResponse?.expiration) - }, [quote, quoteError]) + return normalizeQuoteMeta(quoteResponse?.id, quoteResponse?.verified, quoteResponse?.expiration) + }, [quoteResponse?.id, quoteResponse?.verified, quoteResponse?.expiration])As per coding guidelines: "Derive primitive memo deps (e.g., balance strings, amount hashes) instead of spreading whole objects/arrays into dependency lists."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/bridge/hooks/useQuoteSwapContext.ts` around lines 44 - 48, The memo is depending on the whole `quote` object causing needless recomputations; change the dependency list of the `useMemo` that computes `quoteMeta` to use the three primitive fields it actually reads instead of `quote`—capture `const id = quote?.quoteResults.quoteResponse?.id`, `const verified = quote?.quoteResults.quoteResponse?.verified`, and `const expiration = quote?.quoteResults.quoteResponse?.expiration` (or derive them inline) and then call `normalizeQuoteMeta(id, verified, expiration)` with dependencies `[id, verified, expiration, quoteError]`; keep the `useMemo` and `normalizeQuoteMeta` usage unchanged.apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.tsx (2)
55-84: Extract1500as a named constant.The clipboard timeout
1500is a magic number. Hoisting it makes intent clear and centralises any future tweak.♻️ Proposed refactor
+const COPY_FEEDBACK_DURATION_MS = 1500 + export function QuoteIdValue({ quoteId }: QuoteIdValueProps): ReactNode { const { t } = useLingui() - const [isCopied, setCopied] = useCopyClipboard(1500) + const [isCopied, setCopied] = useCopyClipboard(COPY_FEEDBACK_DURATION_MS)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.tsx` around lines 55 - 84, Extract the magic number 1500 used in useCopyClipboard inside QuoteIdValue into a clearly named constant (e.g., COPY_FEEDBACK_DURATION_MS) at the top of the module, then replace the literal in the useCopyClipboard call with that constant; update any related references in QuoteIdValue (and ensure handleCopy / setCopied behavior remains unchanged) so the timeout value is centralized and self-documenting.
86-91:expiration?is redundant —QuoteExpirationInputalready includesundefined.
QuoteExpirationInputis typed asstring | null | undefined, so the?modifier adds no new information and creates a subtle inconsistency with the explicit union.♻️ Proposed refactor
interface RowQuoteIdProps { quoteId: QuoteIdInput isVerified?: boolean | null - expiration?: QuoteExpirationInput + expiration: QuoteExpirationInput styleProps?: RowStyleProps }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.tsx` around lines 86 - 91, The expiration property on the RowQuoteIdProps interface is declared as optional (expiration?) but QuoteExpirationInput is already string | null | undefined, so remove the optional modifier and declare it as expiration: QuoteExpirationInput to avoid redundancy and keep typings consistent; update the RowQuoteIdProps interface (and any places constructing RowQuoteIdProps if needed) to use expiration: QuoteExpirationInput instead of expiration?: QuoteExpirationInput.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/cowswap-frontend/src/locales/es-ES.po`:
- Around line 162-165: Several msgstr entries in the ES PO file are empty (e.g.,
the msgid "You don't have any orders at the moment." referenced from
OrdersTableNoOrdersContent.utils.tsx); update each empty msgstr to the correct
Spanish translation (or copy the English text deliberately if intended) for that
msgid and likewise fill the other empty msgstr entries listed (lines: 483-485,
794-796, 1252-1254, 1518-1521, 1782-1785, 1876-1879, 2307-2310, 2717-2721,
2994-2997, 3154-3156, 3335-3338, 3564-3567, 3768-3771, 3923-3926, 4295-4298,
4442-4445, 4662-4665, 4873-4876, 4965-4968, 5137-5141, 6658-6661) ensuring each
msgid’s Spanish translation matches the UI context (use the same
phrasing/terminology as the rest of the locale); save the file and run any
lint/po validation to confirm no empty msgstr remain.
In `@apps/cowswap-frontend/src/locales/ru-RU.po`:
- Around line 162-165: The ru-RU .po contains empty msgstr values for new
empty-state strings (e.g. msgid "You don't have any orders at the moment."
referenced from OrdersTableNoOrdersContent.utils.tsx) causing fallback to
English; update the corresponding msgstr for that msgid with the proper Russian
translation (or copy the English text as a temporary placeholder) and likewise
fill in the other empty msgstr entries noted in the review (the ranges listed)
so all new empty-state msgid strings in
apps/cowswap-frontend/src/locales/ru-RU.po have non-empty Russian translations.
- Around line 5376-5379: The msgstr for the msgid "Confirm Swap and Bridge" in
apps/cowswap-frontend/src/locales/ru-RU.po is still English; update the msgstr
value for that msgid to the Russian translation (e.g., "Подтвердить обмен и
перевод через мост") so the locale file returns a proper ru-RU string for
useGetConfirmButtonLabel.
In `@apps/cowswap-frontend/src/modules/swap/containers/SwapRateDetails/index.tsx`:
- Line 45: The expression for showQuoteVerificationIcon is redundant because
quoteResponse is undefined whenever quoteError is truthy; replace the current
compound guard with a single existence check by using only quoteResponse (i.e.,
set showQuoteVerificationIcon based on !!quoteResponse) so the unnecessary &&
!quoteError term is removed; update the declaration of showQuoteVerificationIcon
and run tests to confirm no behavioral changes.
---
Nitpick comments:
In `@apps/cowswap-frontend/src/modules/bridge/hooks/useQuoteSwapContext.ts`:
- Around line 44-48: The memo is depending on the whole `quote` object causing
needless recomputations; change the dependency list of the `useMemo` that
computes `quoteMeta` to use the three primitive fields it actually reads instead
of `quote`—capture `const id = quote?.quoteResults.quoteResponse?.id`, `const
verified = quote?.quoteResults.quoteResponse?.verified`, and `const expiration =
quote?.quoteResults.quoteResponse?.expiration` (or derive them inline) and then
call `normalizeQuoteMeta(id, verified, expiration)` with dependencies `[id,
verified, expiration, quoteError]`; keep the `useMemo` and `normalizeQuoteMeta`
usage unchanged.
In `@apps/cowswap-frontend/src/modules/swap/containers/SwapRateDetails/index.tsx`:
- Around line 41-44: SwapRateDetails duplicates the quote metadata derivation
already handled by normalizeQuoteMeta in useQuoteSwapContext; extract a shared
hook (e.g., useQuoteMetadata) that centralizes quote, quoteError → quoteResponse
mapping and normalization (ensure id is cast via String(id) when present,
quoteVerified boolean, quoteExpiration defaulting to null, and a
showVerificationIcon flag), then replace the manual derivation in
SwapRateDetails and call useQuoteMetadata from useQuoteSwapContext so both
consume the single source of truth (refer to SwapRateDetails,
useQuoteSwapContext, and normalizeQuoteMeta when implementing).
In
`@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.test.ts`:
- Around line 35-39: Add new unit tests to
apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.test.ts
that call getQuoteExpiresInLabel with inputs exercising the missing branches:
(1) an expiry >1 hour to assert the "Hh Mm" format (e.g., expect "1h 5m" for a
timestamp 1h5m in the future), (2) an expiry with seconds===0 to assert exact
minute formatting (e.g., expect "3m" for exactly 3 minutes), and (3) an
already-expired timestamp (expiry <= now) to assert it returns "0s"; use the
existing pattern of passing a fixed now value like the other tests to keep them
deterministic.
In
`@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/index.tsx`:
- Around line 55-84: Extract the magic number 1500 used in useCopyClipboard
inside QuoteIdValue into a clearly named constant (e.g.,
COPY_FEEDBACK_DURATION_MS) at the top of the module, then replace the literal in
the useCopyClipboard call with that constant; update any related references in
QuoteIdValue (and ensure handleCopy / setCopied behavior remains unchanged) so
the timeout value is centralized and self-documenting.
- Around line 86-91: The expiration property on the RowQuoteIdProps interface is
declared as optional (expiration?) but QuoteExpirationInput is already string |
null | undefined, so remove the optional modifier and declare it as expiration:
QuoteExpirationInput to avoid redundancy and keep typings consistent; update the
RowQuoteIdProps interface (and any places constructing RowQuoteIdProps if
needed) to use expiration: QuoteExpirationInput instead of expiration?:
QuoteExpirationInput.
In
`@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/quoteId.ts`:
- Line 33: Add a brief inline comment above the hours branch that states seconds
are intentionally omitted when hours > 0 (i.e., the line "if (hours > 0) return
`${hours}h ${minutes}m`") so the truncation is documented and clear to reviewers
and tests; keep the implementation unchanged, just document the design choice
mentioning "seconds intentionally dropped for long countdowns" and link it to
the hours/minutes branch.
In
`@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/QuoteVerificationIndicator.tsx`:
- Around line 15-59: The styles for centering are duplicated: remove the
redundant rules from CompactIconTooltip's "> div" selector and keep them on
CompactIconWrapper; specifically delete display:inline-flex, align-items:center,
justify-content:center and line-height:0 from CompactIconTooltip > div, and
ensure CompactIconWrapper (the styled span) retains display:inline-flex,
align-items:center, justify-content:center, line-height:0 and
vertical-align:middle so all icon instances use CompactIconWrapper for layout.
In
`@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/TradeRateDetails/index.tsx`:
- Around line 33-35: Replace the inline union types for quoteId and
quoteExpiration with the existing aliases: import and use QuoteIdInput for
quoteId (instead of string | number | null) and QuoteExpirationInput for
quoteExpiration (instead of string | null) in the TradeRateDetails component;
update the props/type declaration referencing quoteId?: QuoteIdInput and
quoteExpiration?: QuoteExpirationInput and ensure the import of these types from
the module that defines them (e.g., quoteId.ts) is added at the top of the file.
| #: apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Content/NoOrders/OrdersTableNoOrdersContent.utils.tsx | ||
| msgid "You don't have any orders at the moment." | ||
| msgstr "" | ||
|
|
There was a problem hiding this comment.
Fill missing Spanish translations for new order/quote strings.
Several newly added entries still have empty msgstr values, so they’ll render in English/blank in the ES locale. Please translate these or explicitly copy the English text if that’s intended.
Also applies to: 483-485, 794-796, 1252-1254, 1518-1521, 1782-1785, 1876-1879, 2307-2310, 2717-2721, 2994-2997, 3154-3156, 3335-3338, 3564-3567, 3768-3771, 3923-3926, 4295-4298, 4442-4445, 4662-4665, 4873-4876, 4965-4968, 5137-5141, 6658-6661
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/cowswap-frontend/src/locales/es-ES.po` around lines 162 - 165, Several
msgstr entries in the ES PO file are empty (e.g., the msgid "You don't have any
orders at the moment." referenced from OrdersTableNoOrdersContent.utils.tsx);
update each empty msgstr to the correct Spanish translation (or copy the English
text deliberately if intended) for that msgid and likewise fill the other empty
msgstr entries listed (lines: 483-485, 794-796, 1252-1254, 1518-1521, 1782-1785,
1876-1879, 2307-2310, 2717-2721, 2994-2997, 3154-3156, 3335-3338, 3564-3567,
3768-3771, 3923-3926, 4295-4298, 4442-4445, 4662-4665, 4873-4876, 4965-4968,
5137-5141, 6658-6661) ensuring each msgid’s Spanish translation matches the UI
context (use the same phrasing/terminology as the rest of the locale); save the
file and run any lint/po validation to confirm no empty msgstr remain.
| #: apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Content/NoOrders/OrdersTableNoOrdersContent.utils.tsx | ||
| msgid "You don't have any orders at the moment." | ||
| msgstr "" | ||
|
|
There was a problem hiding this comment.
Missing Russian translations for new empty‑state strings.
These msgstr entries are empty, so ru-RU will fall back to English/blank. Please provide translations (or copy the English msgid if you want a temporary fallback).
Also applies to: 483-485, 794-796, 1252-1254, 1518-1520, 1782-1784, 1876-1878, 2307-2310, 3155-3156, 3335-3338, 3564-3567, 3768-3771, 3923-3925, 3963-3965, 4151-4153, 4295-4297, 4442-4444, 4662-4665, 4873-4876, 4905-4907, 4965-4967, 6658-6661
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/cowswap-frontend/src/locales/ru-RU.po` around lines 162 - 165, The ru-RU
.po contains empty msgstr values for new empty-state strings (e.g. msgid "You
don't have any orders at the moment." referenced from
OrdersTableNoOrdersContent.utils.tsx) causing fallback to English; update the
corresponding msgstr for that msgid with the proper Russian translation (or copy
the English text as a temporary placeholder) and likewise fill in the other
empty msgstr entries noted in the review (the ranges listed) so all new
empty-state msgid strings in apps/cowswap-frontend/src/locales/ru-RU.po have
non-empty Russian translations.
| #: apps/cowswap-frontend/src/modules/trade/hooks/useGetConfirmButtonLabel.ts | ||
| msgid "Confirm Swap and Bridge" | ||
| msgstr "Confirm Swap and Bridge" | ||
|
|
There was a problem hiding this comment.
Localize “Confirm Swap and Bridge”.
msgstr is still English; please translate it for ru-RU consistency.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/cowswap-frontend/src/locales/ru-RU.po` around lines 5376 - 5379, The
msgstr for the msgid "Confirm Swap and Bridge" in
apps/cowswap-frontend/src/locales/ru-RU.po is still English; update the msgstr
value for that msgid to the Russian translation (e.g., "Подтвердить обмен и
перевод через мост") so the locale file returns a proper ru-RU string for
useGetConfirmButtonLabel.
apps/cowswap-frontend/src/modules/swap/containers/SwapRateDetails/index.tsx
Outdated
Show resolved
Hide resolved
Out of curiosity, what does Matcha show when the quote is not verified? The thing with the check is that, specially for new users that haven't seen/noticed there's 2 versions, it looks as good as the green one. In any case, the specific icons are just suggestions. There's also an empty shield icon which might be less alarming. |
…d and unverified components
Did some experimentation and now use an outlined shield when it's verified: pushed in 55b0c9e |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/QuoteIdTooltipContent.tsx (1)
38-40:expirationprop is used only as a boolean gate — consider narrowing the API.The component ignores the actual expiration string; only its truthiness (
expiration && isQuoteUpdatePossible) is tested. PassingQuoteExpirationInput(a full string union) when only presence matters is slightly over-specified. UsinghasExpiration?: booleanwould make the intent explicit and reduce coupling to the upstream quote type.♻️ Optional simplification
interface QuoteIdTooltipContentProps { - expiration?: QuoteExpirationInput + hasExpiration?: boolean } -export function QuoteIdTooltipContent({ expiration }: QuoteIdTooltipContentProps): ReactNode { +export function QuoteIdTooltipContent({ hasExpiration }: QuoteIdTooltipContentProps): ReactNode { ... - {expiration && isQuoteUpdatePossible ? ( + {hasExpiration && isQuoteUpdatePossible ? (Callsites would pass
hasExpiration={!!expiration}.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/QuoteIdTooltipContent.tsx` around lines 38 - 40, The prop expiration on QuoteIdTooltipContentProps is only used as a boolean gate (checked via expiration && isQuoteUpdatePossible), so change the prop to hasExpiration?: boolean to make the intent explicit: update the QuoteIdTooltipContentProps interface, rename usages of the prop inside the QuoteIdTooltipContent component to hasExpiration, and update callsites to pass hasExpiration={!!expiration}; ensure logic that used "expiration && isQuoteUpdatePossible" now uses "hasExpiration && isQuoteUpdatePossible".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/cowswap-frontend/src/modules/swap/containers/SwapRateDetails/index.tsx`:
- Around line 22-32: The child selector in FeeSummaryWithVerification currently
targets any direct div child and may unintentionally style feeElement if its
root is a div; update the JSX to wrap QuoteVerificationIcon in a dedicated
wrapper element (e.g., a span/div with a specific className or data attribute)
and change the styled-component rule to target that wrapper (e.g.,
.quoteVerificationWrapper) instead of the generic `> div`, ensuring feeElement
is not affected while keeping the icon layout consistent.
---
Nitpick comments:
In
`@apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/QuoteIdTooltipContent.tsx`:
- Around line 38-40: The prop expiration on QuoteIdTooltipContentProps is only
used as a boolean gate (checked via expiration && isQuoteUpdatePossible), so
change the prop to hasExpiration?: boolean to make the intent explicit: update
the QuoteIdTooltipContentProps interface, rename usages of the prop inside the
QuoteIdTooltipContent component to hasExpiration, and update callsites to pass
hasExpiration={!!expiration}; ensure logic that used "expiration &&
isQuoteUpdatePossible" now uses "hasExpiration && isQuoteUpdatePossible".
apps/cowswap-frontend/src/modules/swap/containers/SwapRateDetails/index.tsx
Show resolved
Hide resolved
|
Hey @fairlighteth , nice! Some discrepancies:
Thanks! |
|
@elena-zh thank you for reviewing
|







Summary
This PR surfaces quote metadata already returned by the backend in the Swap widget UI, so users/support can inspect quote identity and verification state without DevTools.
It adds a new Quote ID row in expanded details and a compact verification signal in collapsed details, with correct swap-only behavior and error/no-quote guards.
Key changes:
UI refinements from review feedback:
Screenshots:
Screen.Recording.2026-02-18.at.12.57.30.mov
Screen.Recording.2026-02-18.at.12.56.13.mov
To Test
containers/RowQuoteId/index.tsx apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/RowQuoteId/QuoteVerificationIndicator.tsx apps/cowswap-
frontend/src/modules/bridge/hooks/useQuoteSwapContext.ts apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts apps/
cowswap-frontend/src/modules/account/containers/CowShedInfo/index.tsx apps/cowswap-frontend/src/modules/accountProxy/index.ts
--watchman=false
Background
This is frontend-only. No backend/API changes were required.
The backend has long returned quote metadata on each quote response; we now surface it in UI:
Data path:
This implementation intentionally treats missing verification as unverified and hides metadata when quote state is unavailable/error to avoid stale or misleading UI signals.
Summary by CodeRabbit