add projected next season tier
This commit is contained in:
parent
3aa65f7f75
commit
1b45a5f677
|
@ -18,7 +18,7 @@ const RewardsPage = () => {
|
||||||
const { showClaim } = useIsAllClaimed(prevSeason, publicKey)
|
const { showClaim } = useIsAllClaimed(prevSeason, publicKey)
|
||||||
|
|
||||||
return !showLeaderboards ? (
|
return !showLeaderboards ? (
|
||||||
showClaim ? (
|
!showClaim ? (
|
||||||
<ClaimPage />
|
<ClaimPage />
|
||||||
) : (
|
) : (
|
||||||
<Season setShowLeaderboards={setShowLeaderboards} />
|
<Season setShowLeaderboards={setShowLeaderboards} />
|
||||||
|
|
|
@ -26,6 +26,38 @@ import MedalIcon from '@components/icons/MedalIcon'
|
||||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||||
import { usePlausible } from 'next-plausible'
|
import { usePlausible } from 'next-plausible'
|
||||||
import { TelemetryEvents } from 'utils/telemetry'
|
import { TelemetryEvents } from 'utils/telemetry'
|
||||||
|
import { useQuery } from '@tanstack/react-query'
|
||||||
|
import { MANGO_DATA_API_URL } from 'utils/constants'
|
||||||
|
import {
|
||||||
|
ActivityFeed,
|
||||||
|
isSpotTradeActivityFeedItem,
|
||||||
|
isSwapActivityFeedItem,
|
||||||
|
} from 'types'
|
||||||
|
import Tooltip from '@components/shared/Tooltip'
|
||||||
|
|
||||||
|
const fetchSeasonTradesData = async (
|
||||||
|
startDate: string,
|
||||||
|
mangoAccountPk: string,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${MANGO_DATA_API_URL}/stats/activity-feed?mango-account=${mangoAccountPk}&start-date=${startDate}`,
|
||||||
|
)
|
||||||
|
const parsedResponse = await response.json()
|
||||||
|
|
||||||
|
if (parsedResponse && parsedResponse?.length) {
|
||||||
|
const swapsAndSpot = parsedResponse.filter(
|
||||||
|
(data: ActivityFeed) =>
|
||||||
|
data.activity_type === 'swap' ||
|
||||||
|
data.activity_type === 'openbook_trade',
|
||||||
|
)
|
||||||
|
return swapsAndSpot
|
||||||
|
} else return []
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to load season trades data', e)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Season = ({
|
const Season = ({
|
||||||
setShowLeaderboards,
|
setShowLeaderboards,
|
||||||
|
@ -48,6 +80,47 @@ const Season = ({
|
||||||
refetch,
|
refetch,
|
||||||
} = useAccountPointsAndRank(mangoAccountAddress, seasonData?.season_id)
|
} = useAccountPointsAndRank(mangoAccountAddress, seasonData?.season_id)
|
||||||
|
|
||||||
|
const { data: seasonTradesData } = useQuery(
|
||||||
|
['season-trades-data', seasonData?.season_start],
|
||||||
|
() => fetchSeasonTradesData(seasonData!.season_start, mangoAccountAddress),
|
||||||
|
{
|
||||||
|
cacheTime: 1000 * 60 * 10,
|
||||||
|
staleTime: 1000 * 60,
|
||||||
|
retry: 3,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
enabled: !!(seasonData?.season_start && mangoAccountAddress),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const averageTradeValue = useMemo(() => {
|
||||||
|
if (!seasonTradesData || !seasonTradesData?.length) return 0
|
||||||
|
const notionalValues = []
|
||||||
|
for (const trade of seasonTradesData) {
|
||||||
|
const { activity_details } = trade
|
||||||
|
if (isSwapActivityFeedItem(trade)) {
|
||||||
|
const value =
|
||||||
|
activity_details.swap_in_amount * activity_details.swap_in_price_usd
|
||||||
|
notionalValues.push(value)
|
||||||
|
}
|
||||||
|
if (isSpotTradeActivityFeedItem(trade)) {
|
||||||
|
const value = activity_details.size * activity_details.price
|
||||||
|
notionalValues.push(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const totalValue = notionalValues.reduce((a, c) => a + c, 0)
|
||||||
|
const averageValue = totalValue / notionalValues.length
|
||||||
|
return averageValue
|
||||||
|
}, [seasonTradesData])
|
||||||
|
|
||||||
|
const projectedTier = useMemo(() => {
|
||||||
|
if (!accountTier?.tier) return ''
|
||||||
|
if (accountTier.tier === 'bot') {
|
||||||
|
return 'bot'
|
||||||
|
} else if (averageTradeValue > 1000) {
|
||||||
|
return 'whale'
|
||||||
|
} else return 'mango'
|
||||||
|
}, [accountTier, averageTradeValue])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!topAccountsTier && !loadingAccountTier) {
|
if (!topAccountsTier && !loadingAccountTier) {
|
||||||
setTopAccountsTier(accountTier?.tier.toLowerCase() || 'mango')
|
setTopAccountsTier(accountTier?.tier.toLowerCase() || 'mango')
|
||||||
|
@ -171,9 +244,7 @@ const Season = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="order-1 col-span-12 lg:order-2 lg:col-span-5">
|
<div className="order-1 col-span-12 lg:order-2 lg:col-span-5">
|
||||||
<div className="mb-4 rounded-2xl border border-th-bkg-3 p-6">
|
<div className="mb-4 rounded-2xl border border-th-bkg-3 p-6">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<h2 className="rewards-h2 mb-4">Your Points</h2>
|
||||||
<h2 className="rewards-h2">Your Points</h2>
|
|
||||||
</div>
|
|
||||||
<div className="mb-4 flex h-14 w-full items-center rounded-xl bg-th-bkg-2 px-3">
|
<div className="mb-4 flex h-14 w-full items-center rounded-xl bg-th-bkg-2 px-3">
|
||||||
{!loadingAccountPointsAndRank ? (
|
{!loadingAccountPointsAndRank ? (
|
||||||
accountPointsAndRank?.total_points ? (
|
accountPointsAndRank?.total_points ? (
|
||||||
|
@ -264,6 +335,35 @@ const Season = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mb-4 rounded-2xl border border-th-bkg-3 p-6">
|
||||||
|
<h2 className="rewards-h2 mb-4">Activity</h2>
|
||||||
|
<div className="border-b border-th-bkg-3">
|
||||||
|
<div className="flex items-center justify-between border-t border-th-bkg-3 px-3 py-2">
|
||||||
|
<p className="rewards-p">Average Trade Value</p>
|
||||||
|
<span className="font-rewards text-lg text-th-active">
|
||||||
|
<FormatNumericValue value={averageTradeValue} isUsd />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between border-t border-th-bkg-3 px-3 py-2">
|
||||||
|
<Tooltip content="Your projected tier for next season. This is based on your average trade value">
|
||||||
|
<p className="rewards-p tooltip-underline">Projected Tier</p>
|
||||||
|
</Tooltip>
|
||||||
|
<span className="font-rewards text-lg text-th-active">
|
||||||
|
{!loadingAccountTier ? (
|
||||||
|
projectedTier ? (
|
||||||
|
<span className="capitalize">{projectedTier}</span>
|
||||||
|
) : (
|
||||||
|
'–'
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<SheenLoader>
|
||||||
|
<div className="h-4 w-12 rounded-sm bg-th-bkg-3" />
|
||||||
|
</SheenLoader>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="rounded-2xl border border-th-bkg-3 p-6">
|
<div className="rounded-2xl border border-th-bkg-3 p-6">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
<h2 className="rewards-h2">Top Accounts</h2>
|
<h2 className="rewards-h2">Top Accounts</h2>
|
||||||
|
|
|
@ -285,6 +285,28 @@ export interface SpotTradeActivity {
|
||||||
symbol: string
|
symbol: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SwapHistoryItem {
|
||||||
|
block_datetime: string
|
||||||
|
mango_account: string
|
||||||
|
signature: string
|
||||||
|
swap_in_amount: number
|
||||||
|
swap_in_loan: number
|
||||||
|
swap_in_loan_origination_fee: number
|
||||||
|
swap_in_price_usd: number
|
||||||
|
swap_in_symbol: string
|
||||||
|
swap_out_amount: number
|
||||||
|
loan: number
|
||||||
|
loan_origination_fee: number
|
||||||
|
swap_out_price_usd: number
|
||||||
|
swap_out_symbol: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SwapActivity {
|
||||||
|
activity_details: SwapHistoryItem
|
||||||
|
block_datetime: string
|
||||||
|
activity_type: string
|
||||||
|
}
|
||||||
|
|
||||||
export function isLiquidationActivityFeedItem(
|
export function isLiquidationActivityFeedItem(
|
||||||
item: ActivityFeed,
|
item: ActivityFeed,
|
||||||
): item is LiquidationActivity {
|
): item is LiquidationActivity {
|
||||||
|
@ -312,6 +334,16 @@ export function isSpotTradeActivityFeedItem(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSwapActivityFeedItem(
|
||||||
|
item: ActivityFeed,
|
||||||
|
): item is SwapActivity {
|
||||||
|
console.log(item)
|
||||||
|
if (item.activity_type === 'swap') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
export function isPerpLiquidation(
|
export function isPerpLiquidation(
|
||||||
activityDetails: SpotOrPerpLiquidationItem,
|
activityDetails: SpotOrPerpLiquidationItem,
|
||||||
): activityDetails is PerpLiquidationFeedItem {
|
): activityDetails is PerpLiquidationFeedItem {
|
||||||
|
@ -321,22 +353,6 @@ export function isPerpLiquidation(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SwapHistoryItem {
|
|
||||||
block_datetime: string
|
|
||||||
mango_account: string
|
|
||||||
signature: string
|
|
||||||
swap_in_amount: number
|
|
||||||
swap_in_loan: number
|
|
||||||
swap_in_loan_origination_fee: number
|
|
||||||
swap_in_price_usd: number
|
|
||||||
swap_in_symbol: string
|
|
||||||
swap_out_amount: number
|
|
||||||
loan: number
|
|
||||||
loan_origination_fee: number
|
|
||||||
swap_out_price_usd: number
|
|
||||||
swap_out_symbol: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NFT {
|
export interface NFT {
|
||||||
address: string
|
address: string
|
||||||
collectionAddress?: string
|
collectionAddress?: string
|
||||||
|
@ -375,7 +391,7 @@ export type GroupedDataItem = PerpStatsItem & Record<string, any>
|
||||||
export type ActivityFeed = {
|
export type ActivityFeed = {
|
||||||
activity_type: string
|
activity_type: string
|
||||||
block_datetime: string
|
block_datetime: string
|
||||||
symbol: string
|
symbol?: string
|
||||||
activity_details:
|
activity_details:
|
||||||
| DepositWithdrawFeedItem
|
| DepositWithdrawFeedItem
|
||||||
| SpotLiquidationFeedItem
|
| SpotLiquidationFeedItem
|
||||||
|
|
Loading…
Reference in New Issue