From dfe8b7e62737a5c298a41f33180b21349a2b11c0 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Thu, 25 Jan 2024 22:37:05 +0700 Subject: [PATCH 1/5] feat: add rank to leaderboard stats --- .../leaderboard/UserLeaderboardPage.tsx | 1 + .../common/ProfileCard.module.sass | 8 +++++ .../leaderboard/common/ProfileCard.tsx | 4 ++- src/components/utils/datahub/leaderboard.ts | 33 ++++++++++++++++--- .../leaderboard/userStatisticsSlice.ts | 2 ++ 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/components/leaderboard/UserLeaderboardPage.tsx b/src/components/leaderboard/UserLeaderboardPage.tsx index 89af27cbc..3866a1074 100644 --- a/src/components/leaderboard/UserLeaderboardPage.tsx +++ b/src/components/leaderboard/UserLeaderboardPage.tsx @@ -156,6 +156,7 @@ export default function UserLeaderboardPage({ address }: UserLeaderboardPageProp {data && (
+ {!!rank && #{rank}} {address ? ( profile?.struct ? ( diff --git a/src/components/utils/datahub/leaderboard.ts b/src/components/utils/datahub/leaderboard.ts index 8a8ea6db7..9775c1727 100644 --- a/src/components/utils/datahub/leaderboard.ts +++ b/src/components/utils/datahub/leaderboard.ts @@ -71,7 +71,17 @@ export async function getTopUsers(): Promise { } const GET_USER_STATS = gql` - query GetUserStats($address: String!) { + query GetUserStats($address: String!, $timestamp: String!) { + staker: activeStakingAddressRankByRewardsForPeriod( + args: { address: $address, period: WEEK, role: STAKER, timestamp: $timestamp } + ) { + rankIndex + } + creator: activeStakingAddressRankByRewardsForPeriod( + args: { address: $address, period: WEEK, role: CREATOR, timestamp: $timestamp } + ) { + rankIndex + } activeStakingAccountActivityMetricsForFixedPeriod( args: { address: $address @@ -103,6 +113,14 @@ const GET_USER_STATS = gql` export async function getUserStatistics({ address }: { address: string }): Promise { const res = await datahubQueryRequest< { + staker: { + reward: string + rankIndex: number + } + creator: { + reward: string + rankIndex: number + } activeStakingAccountActivityMetricsForFixedPeriod: { staker: { likedCreators: number @@ -118,15 +136,22 @@ export async function getUserStatistics({ address }: { address: string }): Promi } } }, - { address: string } + { address: string; timestamp: string } >({ document: GET_USER_STATS, - variables: { address }, + variables: { address, timestamp: getDayAndWeekTimestamp().week.toString() }, }) return { address, - ...res.activeStakingAccountActivityMetricsForFixedPeriod, + creator: { + ...res.activeStakingAccountActivityMetricsForFixedPeriod.creator, + rank: res.creator.rankIndex, + }, + staker: { + ...res.activeStakingAccountActivityMetricsForFixedPeriod.staker, + rank: res.staker.rankIndex, + }, } } diff --git a/src/rtk/features/leaderboard/userStatisticsSlice.ts b/src/rtk/features/leaderboard/userStatisticsSlice.ts index c7b411359..c26c933b5 100644 --- a/src/rtk/features/leaderboard/userStatisticsSlice.ts +++ b/src/rtk/features/leaderboard/userStatisticsSlice.ts @@ -10,12 +10,14 @@ export type UserStatistics = { likedPosts: number earnedByPeriod: string earnedTotal: string + rank: number } creator: { likesCountByPeriod: number stakersWhoLiked: number earnedByPeriod: string earnedTotal: string + rank: number } } From 9b8ddba5dad285df1e5480c8bd58fdd94cb61cbd Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Thu, 25 Jan 2024 22:38:49 +0700 Subject: [PATCH 2/5] fix: make height of loading in leaderrboard row same as content --- src/components/leaderboard/common/LeaderboardTable.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/leaderboard/common/LeaderboardTable.tsx b/src/components/leaderboard/common/LeaderboardTable.tsx index d110f8281..f2e887022 100644 --- a/src/components/leaderboard/common/LeaderboardTable.tsx +++ b/src/components/leaderboard/common/LeaderboardTable.tsx @@ -132,7 +132,7 @@ function UserRow({ )} > {data.rank + 1} -
+
{isLoading ? ( <> @@ -146,10 +146,7 @@ function UserRow({ avatar={profile?.content?.image} size={32} /> -
+
Date: Thu, 25 Jan 2024 22:53:47 +0700 Subject: [PATCH 3/5] feat: add fixed user in bottom of leaderboard table --- src/components/common/balances/Balance.tsx | 44 +++++++++++++------ .../leaderboard/UserLeaderboardPage.tsx | 8 +++- .../leaderboard/common/LeaderboardTable.tsx | 39 ++++++++++++---- 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/components/common/balances/Balance.tsx b/src/components/common/balances/Balance.tsx index b9870e0e0..f40db7faf 100644 --- a/src/components/common/balances/Balance.tsx +++ b/src/components/common/balances/Balance.tsx @@ -19,16 +19,27 @@ const log = newLogger('useCreateBallance') const M_LENGTH = 6 + 1 const K_LENGTH = 3 + 1 -function format( - value: Compact | BN | string, - currency: string, - decimals: number, - withSi?: boolean, - _isShort?: boolean, - precision?: number, +function format({ + value, + currency, + decimals, + withSi, + isShort: _isShort, + fixedDecimalsLength, + precision, withMutedDecimals = true, alwaysShowDecimals = false, -): React.ReactNode { +}: { + value: Compact | BN | string + currency: string + fixedDecimalsLength?: number + decimals: number + withSi?: boolean + isShort?: boolean + precision?: number + withMutedDecimals?: boolean + alwaysShowDecimals?: boolean +}): React.ReactNode { // Remove any excess decimals, because this expects big integers const balanceValue = value.toString().split('.')[0] @@ -56,7 +67,9 @@ function format( <> . - {precision + {fixedDecimalsLength + ? postfix.substring(0, fixedDecimalsLength).padEnd(fixedDecimalsLength, '0') + : precision ? parseFloat(`0.${postfix}`).toPrecision(precision).substring(2) : postfix || '0000'} @@ -75,6 +88,7 @@ type FormatBalanceProps = BareProps & { precision?: number withMutedDecimals?: boolean alwaysShowDecimals?: boolean + fixedDecimalsLength?: number } export const FormatBalance = ({ @@ -84,6 +98,7 @@ export const FormatBalance = ({ isShort, className, precision, + fixedDecimalsLength, withMutedDecimals = true, alwaysShowDecimals, ...bareProps @@ -92,16 +107,17 @@ export const FormatBalance = ({ const { unit: defaultCurrency, decimals: defaultDecimal } = formatBalance.getDefaults() - const balance = format( + const balance = format({ value, - currency || defaultCurrency, - decimals || defaultDecimal, - true, + currency: currency || defaultCurrency, + decimals: decimals || defaultDecimal, + withSi: true, isShort, precision, + fixedDecimalsLength, withMutedDecimals, alwaysShowDecimals, - ) + }) return ( diff --git a/src/components/leaderboard/UserLeaderboardPage.tsx b/src/components/leaderboard/UserLeaderboardPage.tsx index 3866a1074..5e0569f38 100644 --- a/src/components/leaderboard/UserLeaderboardPage.tsx +++ b/src/components/leaderboard/UserLeaderboardPage.tsx @@ -208,7 +208,13 @@ export default function UserLeaderboardPage({ address }: UserLeaderboardPageProp : 'Creators ranked by the amount of SUB earned with Active Staking this week.'}
- +
diff --git a/src/components/leaderboard/common/LeaderboardTable.tsx b/src/components/leaderboard/common/LeaderboardTable.tsx index f2e887022..068ff6456 100644 --- a/src/components/leaderboard/common/LeaderboardTable.tsx +++ b/src/components/leaderboard/common/LeaderboardTable.tsx @@ -29,10 +29,19 @@ import styles from './LeaderboardTable.module.sass' export type LeaderboardTableProps = ComponentProps<'div'> & { role: LeaderboardRole + currentUserRank?: { + rank: number + reward: string + address: string + } } const TABLE_LIMIT = 10 -export default function LeaderboardTable({ role, ...props }: LeaderboardTableProps) { +export default function LeaderboardTable({ + role, + currentUserRank, + ...props +}: LeaderboardTableProps) { const [isOpenModal, setIsOpenModal] = useState(false) const { page, data } = useGetLeaderboardData(role) const dispatch = useAppDispatch() @@ -42,13 +51,25 @@ export default function LeaderboardTable({ role, ...props }: LeaderboardTablePro } }, [dispatch, role]) - const { addresses, slicedData } = useMemo( - () => ({ - addresses: data.slice(0, TABLE_LIMIT).map(row => row.address), - slicedData: data.slice(0, TABLE_LIMIT), - }), - [data], - ) + const { addresses, slicedData } = useMemo<{ + addresses: string[] + slicedData: typeof data + }>(() => { + if (!currentUserRank || currentUserRank.rank < TABLE_LIMIT) { + return { + addresses: data.slice(0, TABLE_LIMIT).map(row => row.address), + slicedData: data.slice(0, TABLE_LIMIT), + } + } + return { + addresses: [ + ...data.slice(0, TABLE_LIMIT - 1).map(row => row.address), + currentUserRank.address, + ], + slicedData: [...data.slice(0, TABLE_LIMIT - 1), currentUserRank], + } + }, [data, currentUserRank]) + const { loading } = useFetchProfileSpaces({ ids: addresses }) return ( @@ -182,7 +203,7 @@ function UserRow({ value={data.reward} currency='SUB' decimals={10} - precision={2} + fixedDecimalsLength={2} /> From 928cb535563d155293be822cfb2716a7e0199fbe Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Thu, 25 Jan 2024 23:11:07 +0700 Subject: [PATCH 4/5] feat: show draft reward details in tooltip --- src/components/common/balances/Balance.tsx | 64 +++++++------- .../posts/view-post/PostRewardStat.tsx | 86 +++++++++++++++---- .../utils/datahub/active-staking.ts | 10 ++- .../features/activeStaking/postRewardSlice.ts | 3 +- 4 files changed, 111 insertions(+), 52 deletions(-) diff --git a/src/components/common/balances/Balance.tsx b/src/components/common/balances/Balance.tsx index f40db7faf..80f6dbc30 100644 --- a/src/components/common/balances/Balance.tsx +++ b/src/components/common/balances/Balance.tsx @@ -43,41 +43,45 @@ function format({ // Remove any excess decimals, because this expects big integers const balanceValue = value.toString().split('.')[0] - const [prefix, postfix] = formatBalance(balanceValue, { - forceUnit: '-', - decimals, - withSi: false, - withZero: true, - }).split('.') - const isShort = _isShort || (withSi && prefix.length >= K_LENGTH && !alwaysShowDecimals) - - if (prefix.length > M_LENGTH && !alwaysShowDecimals) { - const balance = formatBalance(balanceValue, { decimals, withUnit: false }) + try { + const [prefix, postfix] = formatBalance(balanceValue, { + forceUnit: '-', + decimals, + withSi: false, + withZero: true, + }).split('.') + const isShort = _isShort || (withSi && prefix.length >= K_LENGTH && !alwaysShowDecimals) + + if (prefix.length > M_LENGTH && !alwaysShowDecimals) { + const balance = formatBalance(balanceValue, { decimals, withUnit: false }) + return ( + <> + {balance} {currency} + + ) + } + return ( <> - {balance} {currency} + {prefix} + {!isShort && ( + <> + . + + {fixedDecimalsLength + ? postfix.substring(0, fixedDecimalsLength).padEnd(fixedDecimalsLength, '0') + : precision + ? parseFloat(`0.${postfix}`).toPrecision(precision).substring(2) + : postfix || '0000'} + + + )} +  {currency} ) + } catch { + return null } - - return ( - <> - {prefix} - {!isShort && ( - <> - . - - {fixedDecimalsLength - ? postfix.substring(0, fixedDecimalsLength).padEnd(fixedDecimalsLength, '0') - : precision - ? parseFloat(`0.${postfix}`).toPrecision(precision).substring(2) - : postfix || '0000'} - - - )} -  {currency} - - ) } type FormatBalanceProps = BareProps & { diff --git a/src/components/posts/view-post/PostRewardStat.tsx b/src/components/posts/view-post/PostRewardStat.tsx index 40a2fc88c..6470e2a4f 100644 --- a/src/components/posts/view-post/PostRewardStat.tsx +++ b/src/components/posts/view-post/PostRewardStat.tsx @@ -11,25 +11,77 @@ export default function PostRewardStat({ postId, ...props }: PostRewardStatProps const reward = useSelectPostReward(postId) if (!reward?.isNotZero) return null + let finalReward = '0' + try { + finalReward = (BigInt(reward.reward) + BigInt(reward.draftReward)).toString() + } catch {} + return (
- - - - - - earned - +
+
+ {reward.draftReward ? ( + + {BigInt(reward.reward) > 0 && ( + <> + {' '} + earned +{' '} + + )} + {' '} + approx. today + + } + > + +
+ + ) : ( + + )} +
+ + + + + earned + +
) } diff --git a/src/components/utils/datahub/active-staking.ts b/src/components/utils/datahub/active-staking.ts index 9c6151629..e52703b17 100644 --- a/src/components/utils/datahub/active-staking.ts +++ b/src/components/utils/datahub/active-staking.ts @@ -87,15 +87,17 @@ export async function getPostRewards(postIds: string[]): Promise const resultMap = new Map() res.activeStakingRewardsByPosts.forEach(item => { - const reward = BigInt(item.reward) > 0 ? item.reward : item.draftReward resultMap.set(item.persistentPostId, { postId: item.persistentPostId, - amount: reward, - isNotZero: BigInt(reward) > 0, + reward: item.reward, + draftReward: item.draftReward, + isNotZero: BigInt(item.reward) > 0 || BigInt(item.draftReward) > 0, }) }) - return postIds.map(postId => resultMap.get(postId) ?? { postId, amount: '0', isNotZero: false }) + return postIds.map( + postId => resultMap.get(postId) ?? { postId, reward: '0', draftReward: '0', isNotZero: false }, + ) } const GET_ADDRESS_LIKE_COUNT_TO_POSTS = gql` diff --git a/src/rtk/features/activeStaking/postRewardSlice.ts b/src/rtk/features/activeStaking/postRewardSlice.ts index d610cc1d2..1bffa1716 100644 --- a/src/rtk/features/activeStaking/postRewardSlice.ts +++ b/src/rtk/features/activeStaking/postRewardSlice.ts @@ -5,7 +5,8 @@ import { createSimpleManyFetchWrapper } from 'src/rtk/app/wrappers' export type PostRewards = { postId: string - amount: string + reward: string + draftReward: string isNotZero: boolean } From bfc1a3598939650a90b3226edf95e05cc07dc888 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Thu, 25 Jan 2024 23:19:04 +0700 Subject: [PATCH 5/5] fix: issue rank not showing if its first, because rank starts with 0 --- .../leaderboard/common/LeaderboardTable.tsx | 23 ++++++++++++++++--- .../leaderboard/common/ProfileCard.tsx | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/components/leaderboard/common/LeaderboardTable.tsx b/src/components/leaderboard/common/LeaderboardTable.tsx index 068ff6456..fdaa29802 100644 --- a/src/components/leaderboard/common/LeaderboardTable.tsx +++ b/src/components/leaderboard/common/LeaderboardTable.tsx @@ -86,7 +86,13 @@ export default function LeaderboardTable({ {slicedData.length === 0 && Array.from({ length: 3 }).map((_, idx) => )} {slicedData.map(row => ( - + ))}
diff --git a/src/components/leaderboard/common/ProfileCard.tsx b/src/components/leaderboard/common/ProfileCard.tsx index 47543fcf3..fcc626ada 100644 --- a/src/components/leaderboard/common/ProfileCard.tsx +++ b/src/components/leaderboard/common/ProfileCard.tsx @@ -42,7 +42,7 @@ export default function ProfileCard({ address, rank, title, detail, ...props }: size='small' withShadow={false} > - {!!rank && #{rank}} + {typeof rank === 'number' && #{rank + 1}} {address ? ( profile?.struct ? (