Skip to content

feat: support reward table & rank table#5637

Open
cuzz-venus wants to merge 1 commit into
mainfrom
feat/prime-leaderboard-table
Open

feat: support reward table & rank table#5637
cuzz-venus wants to merge 1 commit into
mainfrom
feat/prime-leaderboard-table

Conversation

@cuzz-venus

@cuzz-venus cuzz-venus commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Jira ticket(s)

VPD-1335
VPD-1336

Changes

  • support reward table
  • support rank table
image

@changeset-bot

changeset-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 7b2c2d9

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.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

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

@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
dapp-preview Ready Ready Preview Jun 16, 2026 10:03am
dapp-testnet Ready Ready Preview Jun 16, 2026 10:03am
venus.io Ready Ready Preview Jun 16, 2026 10:03am

Request Review

@greptile-apps

greptile-apps Bot commented Jun 16, 2026

Copy link
Copy Markdown

Greptile Summary

Implements the Prime Leaderboard RankTable and RewardTable components (both currently driven by placeholder data), and extends Pagination / useUrlPagination with an optional paramKey so multiple tables on the same page can paginate independently without clobbering each other's URL state.

  • useUrlPagination and usePagination are refactored to accept a custom paramKey, defaulting to the existing PAGE_PARAM_KEY; both now use functional setSearchParams updates to preserve unrelated query params.
  • RankTable and RewardTable each define a dedicated page param key (ranksPage / rewardsPage), column definitions with client-side sort functions, and a sliced data view driven by the current URL page.
  • Seven translation files receive new rankTable and rewardTable keys; RankBadge sub-component maps rank 1–3 to distinct SVG badge assets.

Confidence Score: 4/5

The pagination changes are safe to merge; all new components use placeholder data with explicit TODO markers before real API wiring lands.

The main concern is that both useUrlPagination and Pagination's internal usePagination independently write to the same URL param on each navigation — the first write holds a 0-indexed value before the second overwrites it with the correct 1-indexed value. React 18 batching keeps the final rendered state correct today, but the design is fragile under edge conditions. The pre-existing === undefined guard in usePagination is also worth fixing since this PR is the first to touch that block.

RewardTable/index.tsx and RankTable/index.tsx for the dual pagination management pattern; usePagination.ts for the null-check fix.

Important Files Changed

Filename Overview
apps/evm/src/components/Pagination/usePagination.ts Refactored to accept a custom paramKey, preserving existing params via functional setSearchParams. The auto-init guard uses === undefined instead of === null, so the internal initialisation never fires (pre-existing, surfaced by this change).
apps/evm/src/components/Pagination/index.tsx Minimal change: threads new optional paramKey prop through to usePagination. No logic concerns.
apps/evm/src/hooks/useUrlPagination/index.ts Clean refactor: accepts optional paramKey (defaulting to PAGE_PARAM_KEY), preserves all other search params, adds paramKey to the useCallback dependency array. Initialisation guard correctly uses !pageIndex.
apps/evm/src/pages/PrimeLeaderboard/RankTable/index.tsx New rank table using placeholder data. Both useUrlPagination and <Pagination> manage the same URL param, causing a redundant double write on each page change. The final rendered page is correct due to React 18 batching.
apps/evm/src/pages/PrimeLeaderboard/RewardTable/index.tsx New reward table using placeholder data. Hardcodes USDT and 'U' market columns (will need to be dynamic), uses raw hex gradient values for the wallet badge border, and has the same dual URL-write concern as RankTable.
apps/evm/src/pages/PrimeLeaderboard/RankTable/RankBadge/index.tsx Clean component mapping ranks 1–3 to badge SVG assets; returns null for any other rank.

Comments Outside Diff (1)

  1. apps/evm/src/pages/PrimeLeaderboard/RankTable/index.tsx, line 511-574 (link)

    P2 Redundant dual URL writes on every page navigation

    Both useUrlPagination (line 511) and the <Pagination> component (which internally calls usePagination) are independently writing to RANKS_PAGE_PARAM_KEY on each page change. When the user navigates, usePagination.handlePageChange writes index (0-indexed) to the URL first, then onChange={setCurrentPage} immediately writes index + 1 (1-indexed). React 18's automatic batching means only the final value is committed, so the displayed data is correct — but the first write is the wrong value for the URL convention used by usePagination itself (pageParam - 1). If batching ever fails (e.g., inside a startTransition or async update path), the intermediate state would briefly show the wrong page.

    The cleaner pattern is to let Pagination be the sole URL writer and rely on useUrlPagination purely as a reader. Since Pagination already keeps paramKey in sync, the onChange callback can be used only to trigger non-URL side-effects (e.g., a data refetch once real API calls replace the placeholder slice). The same pattern applies to RewardTable.

Reviews (1): Last reviewed commit: "feat: support reward table & rank table" | Re-trigger Greptile

Comment on lines 45 to +50
// Automatically set default page param if none was set
useEffect(() => {
if (urlPageParam === undefined) {
setSearchParams({
[PAGE_PARAM_KEY]: '1',
});
setPageParam('1');
}
}, [urlPageParam, setSearchParams]);
}, [urlPageParam, setPageParam]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The auto-initialisation effect checks for undefined but searchParams.get() returns null for a missing key, so this condition is always false. Switching to === null makes the intent explicit and ensures the guard works without relying on the paired useUrlPagination hook.

Suggested change
// Automatically set default page param if none was set
useEffect(() => {
if (urlPageParam === undefined) {
setSearchParams({
[PAGE_PARAM_KEY]: '1',
});
setPageParam('1');
}
}, [urlPageParam, setSearchParams]);
}, [urlPageParam, setPageParam]);
// Automatically set default page param if none was set
useEffect(() => {
if (urlPageParam === null) {
setPageParam('1');
}
}, [urlPageParam, setPageParam]);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same pattern as ProposalList/VoterLeaderboard. Page init is handled by useUrlPagination, so this is harmless. Reworking the shared hook is out of scope.

Comment on lines +87 to +100
{
key: 'uRewards',
label: t('primeLeaderboard.rewardTable.columns.marketRewards', { symbol: 'U' }),
selectOptionLabel: t('primeLeaderboard.rewardTable.columns.marketRewards', { symbol: 'U' }),
align: 'right',
sortRows: (rowA, rowB, direction) =>
direction === 'asc'
? rowA.uRewardsCents - rowB.uRewardsCents
: rowB.uRewardsCents - rowA.uRewardsCents,
renderCell: ({ uRewardsCents }) => (
<span className="text-b1r text-white">
{formatCentsToReadableValue({ value: uRewardsCents })}
</span>
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Placeholder token symbol 'U' is ambiguous

The market column is rendered with symbol: 'U', which is not a recognisable token symbol. When the API integration lands, the columns will need to be generated dynamically from the list of markets that distribute Prime rewards; hardcoding even placeholder symbols like 'U' makes it easy to ship this into production without replacing the placeholder. Consider using 'XVS' or another real Prime-eligible token symbol so the placeholder is visually representative, and add a note that the column list must come from the API.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

placeholder

@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for ./apps/evm

Status Category Percentage Covered / Total
🔵 Lines 81.58% 47751 / 58531
🔵 Statements 81.58% 47751 / 58531
🔵 Functions 62.65% 666 / 1063
🔵 Branches 73% 5441 / 7453
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/evm/src/components/Pagination/index.tsx 92.85% 80% 20% 92.85% 54-55, 83-86
apps/evm/src/components/Pagination/usePagination.ts 85.91% 71.42% 0% 85.91% 1, 32-34, 49, 87-93
apps/evm/src/hooks/useUrlPagination/index.ts 97.05% 90% 100% 97.05% 1
apps/evm/src/pages/PrimeLeaderboard/RankTable/index.tsx 100% 80% 100% 100%
apps/evm/src/pages/PrimeLeaderboard/RankTable/RankBadge/index.tsx 100% 0% 100% 100%
apps/evm/src/pages/PrimeLeaderboard/RewardTable/index.tsx 94.17% 81.81% 75% 94.17% 78-80, 93-95
Generated in workflow #13636 for commit 7b2c2d9 by the Vitest Coverage Report Action

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.

1 participant