Skip to content

feat(widget): scope dashboard yield discovery by category#527

Merged
petar-omni merged 1 commit into
mainfrom
fix/yields-fetching
Jun 9, 2026
Merged

feat(widget): scope dashboard yield discovery by category#527
petar-omni merged 1 commit into
mainfrom
fix/yields-fetching

Conversation

@petar-omni

@petar-omni petar-omni commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Implement category-scoped-yield-discovery for dashboard earn.

Replace the all-yield union load with network-scoped category probes. Add yield summary fetching and category-to-API-type helpers. Keep token switching, yield counts, and max rates scoped to the active category.

Add focused tests for mappings, summary visibility, pagination, and token filtering.

Added

Description of new functionality, feature, or content that has been added in this pull request.

Changed

Description of the modifications made to existing functionality, feature, or content in this pull request. This could include changes to code, CI, documentation, etc.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced yield category-based filtering on the Earn page, allowing users to discover and select yields specific to chosen categories (stake, DeFi, RWA).
    • Improved token selection interface with category-aware yield counts and optimized data loading.
  • Tests

    • Expanded test coverage for yield summaries, token yields, and dashboard category mappings.

Implement category-scoped-yield-discovery for dashboard earn.

Replace the all-yield union load with network-scoped category probes.
Add yield summary fetching and category-to-API-type helpers.
Keep token switching, yield counts, and max rates scoped to the active
category.

Add focused tests for mappings, summary visibility, pagination, and token
filtering.
@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 20b6d4b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a complete dashboard yield category filtering system that enables users to discover and select yield opportunities filtered by category (stake, defi, rwa). It adds API-driven type-to-category mappings, category-probing hooks, token-scoped filtering, updated state management, and UI components that reflect category-aware yield availability.

Changes

Dashboard Yield Category Filtering

Layer / File(s) Summary
Yield summary API helpers and type mapping
packages/widget/src/hooks/api/use-yield-summaries.ts, packages/widget/src/domain/types/yields.ts, packages/widget/tests/domain/yield-summaries.test.ts, packages/widget/tests/domain/dashboard-yield-category-types.test.ts
New use-yield-summaries.ts exports fetchYieldSummariesPage, fetchYieldSummariesByIds, and fetchAllYieldSummaries with pagination and chunking; yields.ts introduces apiYieldTypeToDashboardCategory static mapping and lookup functions; test coverage validates visibility predicate and chunking logic.
Dashboard yield catalog probing hook
packages/widget/src/hooks/api/use-dashboard-yield-catalog.ts
New useDashboardYieldCatalog hook probes available categories using per-category React Query queries, fetches visible summaries sorted by reward rate, and seeds initial token/yield selections from the first visible result per category.
Token list yields with category filtering
packages/widget/src/hooks/api/use-token-list-yields.ts, packages/widget/tests/domain/token-list-yields.test.ts
useTokenListYields now accepts optional dashboardYieldCategory; new fetchTokenListYieldSummaries retrieves summaries via the new helpers; new getDashboardCategoryYieldIdsForToken filters and sorts per-token yields by category and reward; hook returns yieldIdsByToken and yieldCountsByToken.
Yield opportunity multi-fetch refactor
packages/widget/src/hooks/api/use-yield-opportunity/get-yield-opportunity.ts
Updates multi-opportunity fetch path to use fetchYieldSummariesByIds instead of direct controller call, ensuring consistency with new yield summary infrastructure.
Earn page state types and actions
packages/widget/src/pages/details/earn-page/state/types.ts
Extends EarnPageContextType with tokenMaxYieldRatesByToken, tokenYieldCountsByToken, and tokenListYieldsIsLoading; introduces dashboard/token-yield/select action for category-scoped yield selection dispatch.
Earn page context integration and wiring
packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx
Refactors provider to orchestrate useDashboardYieldCatalog and useTokenListYields; introduces selectDashboardTokenYield callback calling getYieldOpportunity; updates token/category selection routes to use category-aware logic; extends context value with yield metadata.
Earn page state reducer
packages/widget/src/pages/details/earn-page/state/earn-page-state-context.tsx
Adds reducer handler for dashboard/token-yield/select that recomputes yield state and reinitializes with selected yield; adjusts initial-yield effect to only apply when stake is unset.
Token selection UI with yield availability gating
packages/widget/src/pages/details/earn-page/components/select-token-section/select-token-list-item.tsx, packages/widget/src/pages/details/earn-page/components/select-token-section/select-token.tsx
SelectTokenListItem accepts availableYieldsCount and canSelectToken to disable unavailable tokens; SelectToken computes per-token counts using context yield maps, filters selectable balances by availability, shows category-selection loading, and passes gating flags to the list renderer.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • jdomingos
  • dnehl
  • Philippoes

🐰 A rabbit hops through dashboards bright,
Yields sorted neatly, oh what a sight!
By category, by rate, filtered just right,
Stakes, DeFi, and RWA—opportunity takes flight! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description explains the core change and approach, but the template sections 'Added' and 'Changed' lack substantive details beyond the introductory summary. Expand the 'Added' and 'Changed' sections with specific details about new functions, hooks, API changes, and modifications to existing behavior to fully complete the template.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: scoping dashboard yield discovery by category rather than loading all yields.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/yields-fetching

Comment @coderabbitai help to get the list of available commands and usage tips.

@aws-amplify-eu-central-1

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-527.df4xyoi0xyeak.amplifyapp.com

@aws-amplify-eu-central-1

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-527.d2ribjy8evqo6h.amplifyapp.com

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx (1)

538-544: 💤 Low value

Consider adding user feedback when yield lookup fails.

When yieldId is undefined (line 542), the function returns silently. If tokenListYields is still loading or the token unexpectedly has no yields for the active category, the user clicks a token and nothing happens.

This may be intentional UX (tokens without yields should be visually disabled per the stack context), but if that gating ever fails, a defensive log or brief toast would help diagnose issues.

🤖 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 `@packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx`
around lines 538 - 544, Add a defensive user feedback path when yield lookup
fails: in the block that computes yieldId from tokenListYields.yieldIdsByToken
using tokenString(tokenBalance.token), detect when yieldId is undefined and
instead of returning silently, call a UI feedback function (e.g., showToast or
processLogger.warn) explaining "No yields found for selected token" or "Yields
still loading" and include contextual data (tokenString(tokenBalance.token));
then return early. Update the code around tokenListYields, yieldId, tokenString,
tokenBalance, and selectDashboardTokenYield so successful lookups still call
selectDashboardTokenYield({ token: tokenBalance.token, yieldId }) and failed
lookups produce the toast/log for diagnostics.
🤖 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 `@packages/widget/src/hooks/api/use-dashboard-yield-catalog.ts`:
- Around line 43-57: The probe currently fetches only a single page in the
dashboard category queries (see queries mapping in
use-dashboard-yield-catalog.ts using fetchYieldSummariesPage with
DEFAULT_YIELD_SUMMARIES_PAGE_LIMIT and getYieldSummariesQueryKey) which can
falsely mark a category as unavailable if visible yields are on later pages;
change the probe logic to page through results (or request an unbounded/large
limit if supported) until either a visible yield is found or no more pages
remain, and then base the visibility check and initial selection seeding on that
aggregated result instead of the single first page; ensure the same fix is
applied to both probe usages (the query mapping and the second probe at lines
~68-74) and preserve abort signal handling when iterating pages.

In `@packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx`:
- Around line 503-527: selectDashboardTokenYield currently calls
getYieldOpportunity(...).map(...).run() and ignores the Left path, causing
silent failures; modify the EitherAsync chain in selectDashboardTokenYield to
handle errors explicitly (use .ifLeft(), .bimap(), or .caseOf() before .run())
and dispatch a failure/clear-loading action (or log/show error) so the reducer
sees the error and UI state is cleared; ensure the same dispatch target
("dashboard/token-yield/select") success path remains unchanged and add a new
dispatch/action for the error case (or reuse an existing error/clear action) so
network/invalid-yield errors are surfaced.

---

Nitpick comments:
In `@packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx`:
- Around line 538-544: Add a defensive user feedback path when yield lookup
fails: in the block that computes yieldId from tokenListYields.yieldIdsByToken
using tokenString(tokenBalance.token), detect when yieldId is undefined and
instead of returning silently, call a UI feedback function (e.g., showToast or
processLogger.warn) explaining "No yields found for selected token" or "Yields
still loading" and include contextual data (tokenString(tokenBalance.token));
then return early. Update the code around tokenListYields, yieldId, tokenString,
tokenBalance, and selectDashboardTokenYield so successful lookups still call
selectDashboardTokenYield({ token: tokenBalance.token, yieldId }) and failed
lookups produce the toast/log for diagnostics.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e84fb7d2-df92-49f3-a48e-a3d89a1ea1eb

📥 Commits

Reviewing files that changed from the base of the PR and between 5b0c396 and 20b6d4b.

📒 Files selected for processing (13)
  • packages/widget/src/domain/types/yields.ts
  • packages/widget/src/hooks/api/use-dashboard-yield-catalog.ts
  • packages/widget/src/hooks/api/use-token-list-yields.ts
  • packages/widget/src/hooks/api/use-yield-opportunity/get-yield-opportunity.ts
  • packages/widget/src/hooks/api/use-yield-summaries.ts
  • packages/widget/src/pages/details/earn-page/components/select-token-section/select-token-list-item.tsx
  • packages/widget/src/pages/details/earn-page/components/select-token-section/select-token.tsx
  • packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx
  • packages/widget/src/pages/details/earn-page/state/earn-page-state-context.tsx
  • packages/widget/src/pages/details/earn-page/state/types.ts
  • packages/widget/tests/domain/dashboard-yield-category-types.test.ts
  • packages/widget/tests/domain/token-list-yields.test.ts
  • packages/widget/tests/domain/yield-summaries.test.ts

Comment on lines +43 to +57
queries: dashboardYieldCategories.map((category) => {
const params: YieldSummariesParams = {
network: network ?? undefined,
types: getApiYieldTypesForDashboardCategory(category),
sort: "rewardRateDesc",
limit: DEFAULT_YIELD_SUMMARIES_PAGE_LIMIT,
};

return {
enabled: probeEnabled,
staleTime,
queryKey: getYieldSummariesQueryKey(params),
queryFn: ({ signal }: { signal: AbortSignal }) =>
fetchYieldSummariesPage({ apiClient, params, signal }),
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Single-page probing can falsely mark categories as unavailable.

Line 55 fetches only one page (Line 48 limit), and Line 69 searches visibility only within that page. If visible yields start after the first page, the category is incorrectly hidden and no initial selection is seeded.

💡 Suggested fix
 import {
   DEFAULT_YIELD_SUMMARIES_PAGE_LIMIT,
+  fetchAllYieldSummaries,
   fetchYieldSummariesPage,
   getYieldSummariesQueryKey,
   isVisibleYieldSummary,
   type YieldSummariesParams,
 } from "./use-yield-summaries";
@@
       return {
         enabled: probeEnabled,
         staleTime,
-        queryKey: getYieldSummariesQueryKey(params),
+        queryKey: getYieldSummariesQueryKey({ ...params, allPages: true }),
         queryFn: ({ signal }: { signal: AbortSignal }) =>
-          fetchYieldSummariesPage({ apiClient, params, signal }),
+          fetchAllYieldSummaries({ apiClient, params, signal }),
       };
     }),
   });

Also applies to: 68-74

🤖 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 `@packages/widget/src/hooks/api/use-dashboard-yield-catalog.ts` around lines 43
- 57, The probe currently fetches only a single page in the dashboard category
queries (see queries mapping in use-dashboard-yield-catalog.ts using
fetchYieldSummariesPage with DEFAULT_YIELD_SUMMARIES_PAGE_LIMIT and
getYieldSummariesQueryKey) which can falsely mark a category as unavailable if
visible yields are on later pages; change the probe logic to page through
results (or request an unbounded/large limit if supported) until either a
visible yield is found or no more pages remain, and then base the visibility
check and initial selection seeding on that aggregated result instead of the
single first page; ensure the same fix is applied to both probe usages (the
query mapping and the second probe at lines ~68-74) and preserve abort signal
handling when iterating pages.

Comment on lines +503 to +527
const selectDashboardTokenYield = useCallback(
({
token,
yieldId,
}: {
token: TokenBalanceScanResponseDto["token"];
yieldId: Yield["id"];
}) => {
getYieldOpportunity({
yieldId,
isLedgerLive,
apiClient,
queryClient,
})
.map((yieldDto) => {
dispatch({
type: "dashboard/token-yield/select",
data: { token, yieldDto },
});
return yieldDto;
})
.run();
},
[apiClient, dispatch, isLedgerLive, queryClient]
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Silent failure when getYieldOpportunity rejects.

The EitherAsync chain calls .run() but only handles the success path via .map(). If getYieldOpportunity fails (network error, invalid yield), the promise resolves to a Left that is ignored—no dispatch occurs, no loading state clears, and the user sees no feedback.

Consider handling the error branch explicitly, e.g., via .ifLeft() before .run(), or using .caseOf() / .bimap() to surface failures to the user or at least reset any pending state.

🤖 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 `@packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx`
around lines 503 - 527, selectDashboardTokenYield currently calls
getYieldOpportunity(...).map(...).run() and ignores the Left path, causing
silent failures; modify the EitherAsync chain in selectDashboardTokenYield to
handle errors explicitly (use .ifLeft(), .bimap(), or .caseOf() before .run())
and dispatch a failure/clear-loading action (or log/show error) so the reducer
sees the error and UI state is cleared; ensure the same dispatch target
("dashboard/token-yield/select") success path remains unchanged and add a new
dispatch/action for the error case (or reuse an existing error/clear action) so
network/invalid-yield errors are surfaced.

@xhakti xhakti left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM

@dnehl dnehl left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

lgtm - just a nit

tokenYieldCountsByToken,
}: {
item: TokenBalanceScanResponseDto;
selectedDashboardYieldCategory: unknown;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

unknown could be DashboardYieldCategory | null right?

@petar-omni petar-omni merged commit 229da83 into main Jun 9, 2026
8 checks passed
@petar-omni petar-omni deleted the fix/yields-fetching branch June 9, 2026 08:43
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.

3 participants