Skip to content

feat(explorer): show network costs and protocol fee breakdown on order details - #7588

Open
jmg-duarte wants to merge 38 commits into
developfrom
jmgd/ucp
Open

feat(explorer): show network costs and protocol fee breakdown on order details#7588
jmg-duarte wants to merge 38 commits into
developfrom
jmgd/ucp

Conversation

@jmg-duarte

@jmg-duarte jmg-duarte commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Replace the single combined "fee" figure on the order details page with a costs & fees breakdown:

  • Network costs from the orderbook's gasCost (read off RawOrder until the SDK ships it).
  • Protocol & partner fees aggregated from all of the order's trades' executedProtocolFees, per token + fee type — position 0 is the protocol fee, later ones are numbered partner fees.
  • Totals are kept per token — wrapped-native fees are deliberately not folded into the native total, so the headline matches the rows beneath it. Orders with no recorded gasCost fall back to the old combined-fee display.

Based on #5024

image

To Test

  1. Open the explorer and search an order settled against a backend that records gasCost
  2. Expand Costs & Fees and check the Network costs row + per-fee rows
  3. For an order with no gas cost, confirm the legacy combined-fee display

Summary by CodeRabbit

  • New Features

    • Added an optional costs and fees breakdown for orders, including network costs and protocol fees by token and fee type.
    • Added expandable “Show more” details for lengthy fee breakdowns.
    • Added explanatory tooltip content for fee and network-cost details.
    • Fee data now appears when enabled and falls back to the existing display when unavailable.
  • Bug Fixes

    • Improved fee aggregation across multiple trades while excluding invalid or zero-value fees.
    • Standardized the shared “Show more” control across the Explorer.

@vercel

vercel Bot commented May 28, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cowfi Ready Ready Preview Aug 14, 2026 10:56am
explorer-dev Ready Ready Preview Aug 14, 2026 10:56am
storybook Ready Ready Preview Aug 14, 2026 10:56am
swap-dev Ready Ready Preview Aug 14, 2026 10:56am
widget-configurator Ready Ready Preview Aug 14, 2026 10:56am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
cosmos Ignored Ignored Aug 14, 2026 10:56am
sdk-tools Ignored Ignored Preview Aug 14, 2026 10:56am

Request Review

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)

Walkthrough

The Explorer now models protocol fees, aggregates them from executed trades, fetches them across paginated order trades, and displays network and protocol-fee breakdowns behind a feature flag. Legacy fee rendering remains as a fallback.

Changes

Protocol fee extraction and display

Layer / File(s) Summary
Fee contracts and aggregation
apps/explorer/src/api/operator/types.ts, apps/explorer/src/utils/operator.ts, apps/explorer/src/test/utils/operator/protocolFees.test.ts
Adds protocol-fee models and categories. Aggregates valid executed fees by position, policy type, and token. Converts gasCost to BigNumber.
Order fee fetching and enrichment
apps/explorer/src/hooks/useOperatorTrades.ts, apps/explorer/src/explorer/components/OrderWidget/index.tsx, apps/explorer/src/components/orders/OrderDetails/index.tsx, apps/explorer/src/test/hooks/useOperatorTrades.test.tsx
Fetches and deduplicates paginated trades. Exposes protocol-fee loading and error state. Passes fees into enriched order details.
Feature-flagged fee breakdown UI
apps/explorer/src/hooks/useFeeDisplayFeatureFlag.ts, apps/explorer/src/components/orders/GasFeeDisplay/index.tsx, apps/explorer/src/components/orders/NumbersBreakdown/index.tsx, apps/explorer/src/components/orders/DetailsTable/items/CostAndFeesItem.tsx, apps/explorer/src/components/orders/DetailsTable/detailsTableTooltips.tsx, apps/explorer/src/components/common/ShowMoreButton.tsx, apps/explorer/src/components/AppDataRowContent/AppDataRowContent.tsx, apps/explorer/src/components/orders/OrderSurplusDisplay/index.tsx, apps/explorer/src/test/components/*, apps/explorer/src/test/data/operator.ts
Adds feature-flagged network and protocol-fee rendering, token metadata formatting, expandable details, fallback behavior, tooltip text, shared button styling, and related tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • cowprotocol/cowswap#7961: Adds CoW API trade fixtures containing protocol-fee records used by related fee-breakdown paths.

Suggested reviewers: fairlighteth, limitofzero

Poem

A rabbit counts fees by the light of the moon,
With network costs joining the tune.
Trades hop through pages, duplicates depart,
Tokens line up in a neat little chart.
“Show more,” says the rabbit, “then show less!”
The Explorer displays each fee with finesse.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description explains the costs and fees breakdown, includes a screenshot, and provides clear manual testing steps; optional background and self-check sections are absent.
Title check ✅ Passed The title clearly and concisely describes the main Explorer change: displaying network costs and protocol fee details on order details.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jmgd/ucp

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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 28, 2026

Copy link
Copy Markdown

Deploying explorer-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: f051cfc
Status: ✅  Deploy successful!
Preview URL: https://e6f10d01.explorer-dev-dxz.pages.dev
Branch Preview URL: https://jmgd-ucp.explorer-dev-dxz.pages.dev

View logs

@vercel
vercel Bot temporarily deployed to Preview – cowfi May 28, 2026 16:55 Inactive
@vercel
vercel Bot temporarily deployed to Preview – swap-dev May 28, 2026 16:55 Inactive
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 28, 2026

Copy link
Copy Markdown

Deploying swap-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: f051cfc
Status: ✅  Deploy successful!
Preview URL: https://e778039a.swap-dev-5u6.pages.dev
Branch Preview URL: https://jmgd-ucp.swap-dev-5u6.pages.dev

View logs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
apps/explorer/src/test/utils/operator/orderFees.test.ts (1)

81-89: ⚡ Quick win

Add a mixed-checksum aggregation regression test.

Current coverage checks case-insensitive comparison, but not aggregation across multiple trades where the same token appears in different casing. Add one test with two trades (FEE_TOKEN and FEE_TOKEN.toLowerCase()) and assert single-token aggregation without warning.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/explorer/src/test/utils/operator/orderFees.test.ts` around lines 81 -
89, Add a regression test in orderFees.test.ts that verifies aggregation across
mixed-checksum token strings: create two trades using makeTrade — one with token
FEE_TOKEN and one with FEE_TOKEN.toLowerCase() — pass them to getFees alongside
an order from makeOrder with executedFeeToken set to a different-cased FEE_TOKEN
and totalFee large enough to split protocol/network fees, then assert the
returned protocolFees equals the sum of both trade amounts (as a single token
aggregation) and networkCosts equals the expected remainder; also assert no
warning was emitted (e.g., result.warnings is empty or console.warn was not
called) to ensure the same-token branch aggregates case-insensitively across
multiple trades.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/explorer/src/api/operator/types.ts`:
- Around line 104-108: Change the protocolFeeTokenAddress property in the
OperatorTrade type from string to AddressKey (replace protocolFeeTokenAddress?:
string with protocolFeeTokenAddress?: AddressKey) and update all callers; then
replace any address comparisons that use toLowerCase() in the sameDenomination
logic with the address helpers — in apps/explorer/src/utils/operator.ts and
apps/explorer/src/components/orders/GasFeeDisplay/index.tsx use
areAddressesEqual(a,b) or normalize using getAddressKey(addr) before comparing
instead of addr.toLowerCase(), ensuring you import AddressKey, areAddressesEqual
and getAddressKey from the existing address utility module.

In `@apps/explorer/src/components/orders/GasFeeDisplay/index.tsx`:
- Around line 67-69: Replace direct .toLowerCase() comparisons with the cow-sdk
address helper: update the sameDenomination computation in GasFeeDisplay to call
areAddressesEqual(executedFeeToken, protocolFeeTokenAddress) instead of
comparing lowered strings; change formatFee and resolveToken signatures to
accept an AddressKey parameter type and inside each use
areAddressesEqual(tokenAddress, addressKey) (or similar) to determine equality
rather than calling toLowerCase() on addresses, and update any internal logic
that relied on string lowercasing to use the areAddressesEqual helper for all
address comparisons.

In `@apps/explorer/src/utils/operator.ts`:
- Around line 461-468: The fees grouping currently keys feesByToken by raw token
strings causing checksum-casing splits; change feesByToken to Map<AddressKey,
BigNumber> and when iterating executedProtocolFees use getAddressKey(token) as
the key (while still validating token exists) so amounts aggregate under a
normalized AddressKey (refer to feesByToken and the trades.forEach block). Also
replace the string lower-case comparison in sameDenomination with a call to
areAddressesEqual(tokenA, tokenB) per the address-comparison guideline to ensure
correct equality checks across checksum variants.

---

Nitpick comments:
In `@apps/explorer/src/test/utils/operator/orderFees.test.ts`:
- Around line 81-89: Add a regression test in orderFees.test.ts that verifies
aggregation across mixed-checksum token strings: create two trades using
makeTrade — one with token FEE_TOKEN and one with FEE_TOKEN.toLowerCase() — pass
them to getFees alongside an order from makeOrder with executedFeeToken set to a
different-cased FEE_TOKEN and totalFee large enough to split protocol/network
fees, then assert the returned protocolFees equals the sum of both trade amounts
(as a single token aggregation) and networkCosts equals the expected remainder;
also assert no warning was emitted (e.g., result.warnings is empty or
console.warn was not called) to ensure the same-token branch aggregates
case-insensitively across multiple trades.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 834ec6c8-a987-4d6c-a53b-f60aacd95af2

📥 Commits

Reviewing files that changed from the base of the PR and between b6459f0 and 90b75e9.

📒 Files selected for processing (9)
  • apps/explorer/src/api/operator/types.ts
  • apps/explorer/src/components/AppDataRowContent/AppDataRowContent.tsx
  • apps/explorer/src/components/common/ShowMoreButton.tsx
  • apps/explorer/src/components/orders/GasFeeDisplay/GasFeeDisplay.stories.tsx
  • apps/explorer/src/components/orders/GasFeeDisplay/index.tsx
  • apps/explorer/src/components/orders/NumbersBreakdown/index.tsx
  • apps/explorer/src/components/orders/OrderDetails/index.tsx
  • apps/explorer/src/test/utils/operator/orderFees.test.ts
  • apps/explorer/src/utils/operator.ts

Comment thread apps/explorer/src/api/operator/types.ts Outdated
Comment thread apps/explorer/src/components/orders/GasFeeDisplay/index.tsx Outdated
Comment thread apps/explorer/src/utils/operator.ts Outdated
@vercel
vercel Bot temporarily deployed to Preview – storybook May 29, 2026 10:24 Inactive
@vercel
vercel Bot temporarily deployed to Preview – widget-configurator May 29, 2026 10:24 Inactive
@vercel
vercel Bot temporarily deployed to Preview – explorer-dev May 29, 2026 10:24 Inactive
@vercel
vercel Bot temporarily deployed to Preview – cowfi May 29, 2026 10:25 Inactive
@vercel
vercel Bot temporarily deployed to Preview – swap-dev May 29, 2026 10:26 Inactive
@alfetopito

Copy link
Copy Markdown
Contributor

@alfetopito

Copy link
Copy Markdown
Contributor

Additionally, something is weird. Checking a random order, I see this:

image

The network costs token is not being decoded for some reason.
When the token details cannot be fetched, it defaults to showing the full integer amount and the token address.

In this case, the token is WETH.

However, it's also an edge case as it's an ethflow order, so the sell token should actually be displayed as ETH.

@fhenneke

Copy link
Copy Markdown

I was expecting a change towards only displaying protocol fees. We will not be able to reconstruct network fees. (I am assuming that order.totalFee is essentially what we call executedFee in other places. We want to remove that number.)

@vercel
vercel Bot temporarily deployed to Preview – storybook June 2, 2026 07:52 Inactive
@vercel
vercel Bot temporarily deployed to Preview – widget-configurator June 2, 2026 07:52 Inactive
@vercel
vercel Bot temporarily deployed to Preview – explorer-dev June 2, 2026 07:52 Inactive
@vercel
vercel Bot temporarily deployed to Preview – cowfi June 2, 2026 07:53 Inactive
@vercel
vercel Bot temporarily deployed to Preview – swap-dev June 2, 2026 07:54 Inactive
@fairlighteth
fairlighteth self-requested a review June 2, 2026 08:00

@fairlighteth fairlighteth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ AI Review (Codex GPT-5, worked 4m): fee breakdown uses only the current fills page

Finding: Aggregate fee breakdown from all order trades, not the paginated fills table page

  • Location: apps/explorer/src/components/orders/OrderDetails/index.tsx:160
  • enrichOrderFromTrades calls getFees(order, trades), but trades comes from useOrderTrades(order, tableState.pageOffset, tableState.pageSize), which fetches limit + 1 records and then slices back to the current page.
  • For a partially fillable order with more than 10 fills, the overview breakdown only sums the visible page. Page 1 omits later fills; after paging in the Fills tab, returning to Overview can show different fee/network-cost values for the same order.
  • Impact: order-level costs become undercounted and page-dependent.

Suggested fix

  • Use a complete trade set or dedicated aggregate for the order-level fee breakdown, or only render the breakdown when all trades needed for the aggregate have been loaded.
  • Add coverage for an order with more fills than RESULTS_PER_PAGE so protocolFees includes all fills and does not change with pageOffset.
Review scope and related context

This is separate from the existing review comments, which already cover:

  • Address typing/comparison: resolved with AddressKey, getAddressKey, and areAddressesEqual.
  • EthFlow WETH/ETH fee-token formatting: already reported by @alfetopito.
  • Whether network fees should be displayed at all: already raised by @fhenneke.
  • Mixed-checksum aggregation coverage: already suggested by CodeRabbit.
🤖 Prompt for AI agents
Verify this finding against current code. Fix only if still valid, keep the change minimal, and validate with targeted tests.

Context:
- apps/explorer/src/components/orders/OrderDetails/index.tsx:160 calls getFees(order, trades).
- apps/explorer/src/explorer/components/OrderWidget/index.tsx:36 passes useOrderTrades(order, tableState.pageOffset, tableState.pageSize).
- apps/explorer/src/hooks/useOperatorTrades.ts:69 fetches limit + 1 and lines 119-122 slice back to the current page.
- Fee breakdown should be order-level, not dependent on the currently selected fills page.

@vercel
vercel Bot temporarily deployed to Preview – storybook June 2, 2026 11:00 Inactive
@vercel
vercel Bot temporarily deployed to Preview – widget-configurator June 2, 2026 11:00 Inactive
@vercel
vercel Bot temporarily deployed to Preview – swap-dev June 2, 2026 11:00 Inactive
@vercel
vercel Bot temporarily deployed to Preview – explorer-dev June 2, 2026 11:00 Inactive
@vercel
vercel Bot temporarily deployed to Preview – cowfi June 2, 2026 11:01 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/explorer/src/components/orders/GasFeeDisplay/index.tsx (1)

105-123: 💤 Low value

Minor: Redundant getAddressKey call on already-normalized address.

Line 122 calls getAddressKey(address) but address is already an AddressKey (from fee.tokenAddress, which was normalized via getAddressKey(token) in operator.ts line 482). Since feeTokensByKey is also keyed by getAddressKey(...) results, you can use feeTokensByKey.get(address) directly.

♻️ Simplify lookup
-  return feeTokensByKey.get(getAddressKey(address)) || undefined
+  return feeTokensByKey.get(address) || undefined
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/explorer/src/components/orders/GasFeeDisplay/index.tsx` around lines 105
- 123, In resolveToken, avoid the redundant normalization by using the
already-normalized AddressKey directly when looking up feeTokensByKey: replace
the final lookup that uses feeTokensByKey.get(getAddressKey(address)) with
feeTokensByKey.get(address). This touches the resolveToken function and the
feeTokensByKey map usage; no other behavior changes needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/explorer/src/components/orders/GasFeeDisplay/index.tsx`:
- Around line 105-123: In resolveToken, avoid the redundant normalization by
using the already-normalized AddressKey directly when looking up feeTokensByKey:
replace the final lookup that uses feeTokensByKey.get(getAddressKey(address))
with feeTokensByKey.get(address). This touches the resolveToken function and the
feeTokensByKey map usage; no other behavior changes needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0cdd163f-1d15-40e1-b367-37dab2ea2e25

📥 Commits

Reviewing files that changed from the base of the PR and between 352c1de and 285c309.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (28)
  • apps/cowswap-frontend/package.json
  • apps/explorer/package.json
  • apps/explorer/src/api/operator/types.ts
  • apps/explorer/src/components/orders/DetailsTable/detailsTableTooltips.tsx
  • apps/explorer/src/components/orders/GasFeeDisplay/GasFeeDisplay.stories.tsx
  • apps/explorer/src/components/orders/GasFeeDisplay/index.tsx
  • apps/explorer/src/components/orders/OrderDetails/index.tsx
  • apps/explorer/src/test/data/operator.ts
  • apps/explorer/src/test/utils/operator/orderFees.test.ts
  • apps/explorer/src/utils/operator.ts
  • apps/sdk-tools/package.json
  • apps/widget-configurator/package.json
  • libs/analytics/package.json
  • libs/balances-and-allowances/package.json
  • libs/common-const/package.json
  • libs/common-hooks/package.json
  • libs/common-utils/package.json
  • libs/core/package.json
  • libs/currency/package.json
  • libs/ens/package.json
  • libs/events/package.json
  • libs/multicall/package.json
  • libs/permit-utils/package.json
  • libs/tokens/package.json
  • libs/types/package.json
  • libs/ui/package.json
  • libs/wallet/package.json
  • libs/widget-lib/package.json
✅ Files skipped from review due to trivial changes (18)
  • libs/analytics/package.json
  • libs/ui/package.json
  • libs/widget-lib/package.json
  • libs/wallet/package.json
  • libs/balances-and-allowances/package.json
  • libs/permit-utils/package.json
  • libs/common-utils/package.json
  • libs/multicall/package.json
  • libs/currency/package.json
  • libs/common-const/package.json
  • libs/core/package.json
  • libs/common-hooks/package.json
  • apps/widget-configurator/package.json
  • libs/events/package.json
  • libs/types/package.json
  • apps/sdk-tools/package.json
  • libs/ens/package.json
  • apps/explorer/package.json

@vercel
vercel Bot temporarily deployed to Preview – storybook June 2, 2026 13:09 Inactive
@vercel
vercel Bot temporarily deployed to Preview – widget-configurator June 2, 2026 13:09 Inactive
cowswap-release-sync Bot and others added 9 commits August 3, 2026 09:40
The breakdown is still being built out, so ship it disabled and enable it per
environment through `isExplorerFeeDisplayEnabled`. With the flag off the order
details page behaves as it did before the feature: the legacy combined
executed fee, its original label, tooltip and inline layout, and none of the
extra requests.

The flag is read once, in a named hook over the shared `useFeatureFlags`, and
gates two seams: `CostAndFeesItem` for what renders, and `OrderWidget` for
whether the all-trades fetch runs at all. `GasFeeDisplay` stays flag-agnostic
and takes `showBreakdown`, so Storybook and tests can drive both states.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cut the commentary down to what the code cannot say for itself, and drop what
would go stale on the next edit: an arithmetic aside tied to two constants, a
hardcoded route path, references to a test file by path and to another test by
name, and a restatement of the fee aggregation key that gave that invariant a
second home to drift from.

Two were not merely verbose but wrong. `OrderWidget` claimed the fee error was
suppressed because it shared a root cause with the trades error, which the
distinct error messages contradict; the real reason is to avoid a second
banner. And `ProtocolFee.tokenAddress` was documented as the surplus-side
token, an unverified claim in a place where it would be taken on trust.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jmg-duarte

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
apps/explorer/src/test/components/costsAndFeesFeatureFlag.test.tsx (1)

1-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Import ReactNode directly.

Replace React.ReactNode with ReactNode imported from react in apps/explorer/src/test/components/costsAndFeesFeatureFlag.test.tsx.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/explorer/src/test/components/costsAndFeesFeatureFlag.test.tsx` around
lines 1 - 33, Import ReactNode directly from react in the test file and replace
the React.ReactNode type references in the mocked DetailRow definition with
ReactNode, preserving the existing component behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/explorer/src/components/orders/DetailsTable/items/CostAndFeesItem.tsx`:
- Around line 15-24: Update showBreakdown in CostAndFeesItem to require both the
fee display feature flag and a positive order.gasCost value. Use this gated
value for the label, tooltipText, stack, and GasFeeDisplay props so missing or
zero gas costs retain the legacy presentation.

In `@apps/explorer/src/components/orders/GasFeeDisplay/index.tsx`:
- Line 157: Update the raw-address fallback in the token display logic to call
shortenAddress(tokenAddress) instead of abbreviateString(tokenAddress, 6, 4).
Ensure shortenAddress is imported from `@cowprotocol/common-utils` and remove the
obsolete abbreviation usage for this fallback.
- Around line 100-107: Update the totals useMemo in GasFeeDisplay to aggregate
wrapped-native fee amounts under the native token key while preserving original
token addresses for detail rows. In
apps/explorer/src/components/orders/GasFeeDisplay/index.tsx lines 100-107, apply
the wrapped-native-to-native key mapping during aggregation. In
apps/explorer/src/test/components/costsAndFeesBreakdown.test.tsx lines 85-89,
assert a single native headline total and retain WETH in the expanded fee rows.

In `@apps/explorer/src/hooks/useOperatorTrades.ts`:
- Line 154: Update the onError callback in useOperatorTrades to type its
parameter as unknown, call normalizeError once to create an error value, and
pass that normalized value to console.error alongside the existing context and
message.

In `@apps/explorer/src/test/hooks/useOperatorTrades.test.tsx`:
- Around line 112-113: Replace React.ReactNode annotations with the directly
imported ReactNode type at
apps/explorer/src/test/hooks/useOperatorTrades.test.tsx:112-113,
apps/explorer/src/components/orders/GasFeeDisplay/index.tsx:40, 51-59, 148-156,
and 162-163, and
apps/explorer/src/test/components/costsAndFeesBreakdown.test.tsx:55; add or
reuse the named ReactNode imports in each file without changing runtime imports
or behavior.

---

Nitpick comments:
In `@apps/explorer/src/test/components/costsAndFeesFeatureFlag.test.tsx`:
- Around line 1-33: Import ReactNode directly from react in the test file and
replace the React.ReactNode type references in the mocked DetailRow definition
with ReactNode, preserving the existing component behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5ec8c2d-3e27-408b-bfbd-2d8b2543b04a

📥 Commits

Reviewing files that changed from the base of the PR and between 1df6397 and 7602ad3.

📒 Files selected for processing (19)
  • apps/explorer/src/api/operator/types.ts
  • apps/explorer/src/components/AppDataRowContent/AppDataRowContent.tsx
  • apps/explorer/src/components/common/ShowMoreButton.tsx
  • apps/explorer/src/components/orders/DetailsTable/detailsTableTooltips.tsx
  • apps/explorer/src/components/orders/DetailsTable/items/CostAndFeesItem.tsx
  • apps/explorer/src/components/orders/GasFeeDisplay/GasFeeDisplay.stories.tsx
  • apps/explorer/src/components/orders/GasFeeDisplay/index.tsx
  • apps/explorer/src/components/orders/NumbersBreakdown/index.tsx
  • apps/explorer/src/components/orders/OrderDetails/index.tsx
  • apps/explorer/src/components/orders/OrderSurplusDisplay/index.tsx
  • apps/explorer/src/explorer/components/OrderWidget/index.tsx
  • apps/explorer/src/hooks/useFeeDisplayFeatureFlag.ts
  • apps/explorer/src/hooks/useOperatorTrades.ts
  • apps/explorer/src/test/components/costsAndFeesBreakdown.test.tsx
  • apps/explorer/src/test/components/costsAndFeesFeatureFlag.test.tsx
  • apps/explorer/src/test/data/operator.ts
  • apps/explorer/src/test/hooks/useOperatorTrades.test.tsx
  • apps/explorer/src/test/utils/operator/protocolFees.test.ts
  • apps/explorer/src/utils/operator.ts
💤 Files with no reviewable changes (1)
  • apps/explorer/src/components/orders/GasFeeDisplay/GasFeeDisplay.stories.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/explorer/src/components/AppDataRowContent/AppDataRowContent.tsx
  • apps/explorer/src/test/data/operator.ts

Comment thread apps/explorer/src/components/orders/DetailsTable/items/CostAndFeesItem.tsx Outdated
Comment thread apps/explorer/src/components/orders/GasFeeDisplay/index.tsx Outdated
Comment thread apps/explorer/src/components/orders/GasFeeDisplay/index.tsx Outdated
Comment thread apps/explorer/src/hooks/useOperatorTrades.ts Outdated
Comment thread apps/explorer/src/test/hooks/useOperatorTrades.test.tsx Outdated
- Gate the Costs and fees row presentation (label, tooltip, stacked
  layout) on the same conditions GasFeeDisplay uses, so orders without
  a usable gas cost or fee list keep the legacy row end to end.
- Use shortenAddress for the raw-address fallback instead of slicing.
- Normalize the SWR onError rejection value before logging it.
- Import React type names directly instead of the React.* prefix form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@elena-zh elena-zh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey @jmg-duarte , could you please check why I don't see any breakdown for my costs and fees for this order?

It is not affected by the feature-flag, and the order was placed using the widget with a partner fee inside:

Image

@jmg-duarte

jmg-duarte commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

@elena-zh the order was found in prod, which is already tracking but not returning the gas values yet
As such, it didn't return the field, didn't show, it's working as expected 😅

Screenshot 2026-08-11 at 16 58 13

For example, this one was placed against staging, so it's found and returned by barn: https://explorer-dev-git-jmgd-ucp-cowswap-dev.vercel.app/sepolia/orders/0x84ed78f0be57edfd8a791acb8a773c7c0cec8a9800345e31575f8baa632c9e9309fbad1ea29c36dfe4f8f7baa87c5edf85e0d9f36a7afb73

@elena-zh

Copy link
Copy Markdown
Contributor

@jmg-duarte , sorry! Indeed, my develop was pointing to Prod.

I managed to place another order, I see a breakdown now, But could you please clarify why all fees are 'volume' fees now?
image

As far as I remember, we agreed to have:

  • protocol fee (our volume fee)
  • partner fee (if partner fee is set)

Other than that, changes LGTM, since CoW Swap UI related changes will be implemented later.

@jmg-duarte

Copy link
Copy Markdown
Contributor Author

They show as volume because they're applied as volume fees, I didn't recall what we had decided and at this point we're running multiple conversations, sorry about that. Let me fix it and I'll re-request a review

Comment thread apps/explorer/src/components/orders/GasFeeDisplay/index.tsx Outdated
Comment thread apps/explorer/src/hooks/useOperatorTrades.ts
jmg-duarte and others added 6 commits August 13, 2026 10:10
Move the row building, per-token totals and token lookup out of the
GasFeeDisplay hooks into pure functions, and unit test them directly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Fills table and the fee breakdown each paged the trades themselves.
Both now read one shared SWR entry: the table slices its page from that
list, and the breakdown reduces over it.

Paging the table client-side is also more correct, since getTrades merges
PROD and BARN but offsets each environment separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jmg-duarte
jmg-duarte requested a review from azebuado August 14, 2026 13:12
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.

6 participants