Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Killed gauges display problem ; reduce the ttl for cache by lru #11196

Merged
merged 21 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions apps/web/src/pages/api/gauges/getAllGauges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import qs from 'qs'
import { getViemClients } from 'utils/viem.server'
import { stringify } from 'viem'

const MAX_CACHE_SECONDS = 60 * 5
const MAX_CACHE_SECONDS = 10

const handler: NextApiHandler = async (req, res) => {
const queryString = qs.stringify(req.query)
Expand All @@ -31,12 +31,7 @@ const handler: NextApiHandler = async (req, res) => {
},
)

if (blockNumber) {
// cache for long time if blockNumber is provided
res.setHeader('Cache-Control', `max-age=10800, s-maxage=31536000`)
} else {
res.setHeader('Cache-Control', `max-age=10, s-maxage=${MAX_CACHE_SECONDS}, stale-while-revalidate`)
}
res.setHeader('Cache-Control', `max-age=${MAX_CACHE_SECONDS}, s-maxage=${MAX_CACHE_SECONDS}`)
return res.status(200).json({
data: JSON.parse(stringify(gauges)),
lastUpdated: Number(Date.now()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ type ListItemProps = {
export function GaugeIdentifierDetails({ data }: ListItemProps) {
const hasManager = data.type === GaugeType.ALM
const { managerName } = usePositionManagerName(data)
const { t } = useTranslation()

return (
<Flex justifyContent="space-between" flex="1">
Expand All @@ -157,6 +158,15 @@ export function GaugeIdentifierDetails({ data }: ListItemProps) {
</Text>
</Flex>
) : null}
{data.killed && (
<span
style={{
color: '#FFB237',
}}
>
{t('Deleted')}
</span>
)}
</Flex>
</FlexGap>
<FlexGap gap="0.25em" justifyContent="flex-end" flexWrap="wrap" style={{ flex: 1 }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ export const TableRow: React.FC<RowProps> = ({ data, submitted, vote = { ...DEFA
</Text>
</Flex>
) : null}
{data.killed && (
<span
style={{
color: '#FFB237',
}}
>
{t('Deleted')}
</span>
)}
</Flex>
</FlexGap>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const useSelectRowsWithQuery = (gauges: Gauge[] | undefined) => {
}

export const useGaugeRows = () => {
const { data: gauges, isLoading: gaugeIsLoading } = useGauges()
const { data: gauges, isLoading: gaugeIsLoading } = useGauges(true)
const { selectRowsHash, onRowSelect, refetch, isLoading: voteIsLoading } = useSelectRowsWithQuery(gauges)
const rows = useMemo(() => {
const gaugesMap = new Map(gauges?.map((gauge) => [gauge.hash, gauge]))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
useMatchBreakpoints,
} from '@pancakeswap/uikit'
import ConnectWalletButton from 'components/ConnectWalletButton'
import useAccountActiveChain from 'hooks/useAccountActiveChain'
import keyBy from 'lodash/keyBy'
import NextLink from 'next/link'
import { PropsWithChildren, useCallback, useEffect, useMemo, useState } from 'react'
import styled from 'styled-components'
Expand All @@ -24,7 +26,6 @@ import { useEpochVotePower } from 'views/GaugesVoting/hooks/useEpochVotePower'
import { useGauges } from 'views/GaugesVoting/hooks/useGauges'
import { useUserVoteSlopes } from 'views/GaugesVoting/hooks/useUserVoteGauges'
import { useWriteGaugesVoteCallback } from 'views/GaugesVoting/hooks/useWriteGaugesVoteCallback'
import { useAccount } from 'wagmi'
import { RemainingVotePower } from '../../RemainingVotePower'
import { AddGaugeModal } from '../AddGauge/AddGaugeModal'
import { EmptyTable } from './EmptyTable'
Expand All @@ -47,7 +48,7 @@ const Scrollable = styled.div.withConfig({ shouldForwardProp: (prop) => !['expan
`

export const VoteTable = () => {
const { address: account } = useAccount()
const { account } = useAccountActiveChain()
const { t } = useTranslation()
const [submitted, setSubmitted] = useState(false)
const { cakeLockedAmount } = useCakeLockStatus()
Expand Down Expand Up @@ -134,37 +135,42 @@ export const VoteTable = () => {
}, [gaugesCount, rows])

const sortedSubmitVotes = useMemo(() => {
const voteGauges = slopes
.map((slope) => {
const vote = votes[slope.hash]
// update vote power
if (vote && !vote?.locked) {
const row = gauges?.find((r) => r.hash === slope.hash)
if (!row) return undefined
const currentPower = Number(vote.power) ? BigInt((Number(vote.power) * 100).toFixed(0)) : 0n
const { nativePower = 0, proxyPower = 0, nativeEnd, proxyEnd } = slope || {}
// ignore vote if current power is 0 and never voted
if (currentPower === 0n && nativePower === 0 && proxyPower === 0 && !nativeEnd && !proxyEnd) return undefined
return {
...row,
delta: currentPower - (BigInt(nativePower) + BigInt(proxyPower)),
weight: currentPower,
}
}
// vote deleted
if (!vote && (slope.proxyPower > 0 || slope.nativePower > 0)) {
const row = gauges?.find((r) => r.hash === slope.hash)
if (!row) return undefined
return {
...row,
delta: 0n - (BigInt(slope.nativePower) + BigInt(slope.proxyPower)),
weight: 0n,
}
const slopesByHash = keyBy(slopes, 'hash')
const voteGaugesAdded = Object.keys(votes).map((hash) => {
const vote = votes[hash]
const slope = slopesByHash[hash]
const row = gauges?.find((r) => r.hash === hash)
if (!row || !slope) return undefined
const currentPower = Number(vote.power) ? BigInt((Number(vote.power) * 100).toFixed(0)) : 0n
const { nativePower = 0, proxyPower = 0, nativeEnd, proxyEnd } = slope || {}
// ignore vote if current power is 0 and never voted
if (currentPower === 0n && nativePower === 0 && proxyPower === 0 && !nativeEnd && !proxyEnd) return undefined
return {
...row,
delta: currentPower - (BigInt(nativePower) + BigInt(proxyPower)),
weight: currentPower,
}
})
const voteGaugesRemoved = slopes.map((slope) => {
const vote = votes[slope.hash]

// vote deleted
if (!vote && (slope.proxyPower > 0 || slope.nativePower > 0)) {
const row = gauges?.find((r) => r.hash === slope.hash)
if (!row) return undefined
return {
...row,
delta: 0n - (BigInt(slope.nativePower) + BigInt(slope.proxyPower)),
weight: 0n,
}
return undefined
})
}
return undefined
})

const voteGauges = [...voteGaugesAdded, ...voteGaugesRemoved]
.filter((gauge: GaugeWithDelta | undefined): gauge is GaugeWithDelta => Boolean(gauge))
.sort((a, b) => (b.delta < a.delta ? 1 : -1))

return voteGauges
}, [slopes, votes, gauges])

Expand Down
8 changes: 5 additions & 3 deletions apps/web/src/views/GaugesVoting/hooks/useGauges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ import { ChainId } from '@pancakeswap/chains'
import { Gauge } from '@pancakeswap/gauges'
import { useQuery } from '@tanstack/react-query'
import { useActiveChainId } from 'hooks/useActiveChainId'
import { stringify } from 'qs'

type Response = {
data: Gauge[]
lastUpdated: number
}

export const useGauges = () => {
export const useGauges = (showKilled: boolean = false) => {
const { chainId } = useActiveChainId()

const { data, isPending } = useQuery({
queryKey: ['gaugesVoting', chainId],
queryKey: ['gaugesVoting', chainId, showKilled],

queryFn: async (): Promise<Gauge[]> => {
const response = await fetch(`/api/gauges/getAllGauges${chainId === ChainId.BSC_TESTNET ? '?testnet=1' : ''}`)
const query = stringify({ testnet: chainId === ChainId.BSC_TESTNET ? 1 : undefined, killed: showKilled })
const response = await fetch(`/api/gauges/getAllGauges?${query}`)
if (response.ok) {
const result = (await response.json()) as Response

Expand Down
21 changes: 16 additions & 5 deletions apps/web/src/views/GaugesVoting/hooks/useUserVote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import dayjs from 'dayjs'
import useAccountActiveChain from 'hooks/useAccountActiveChain'
import { useGaugesVotingContract } from 'hooks/useContract'
import { useEffect, useMemo } from 'react'
import { publicClient as getPublicClient } from 'utils/viem'
import { isAddressEqual } from 'utils'
import { publicClient as getPublicClient } from 'utils/viem'
import { Address, Hex, zeroAddress } from 'viem'
import { useCurrentBlockTimestamp } from 'views/CakeStaking/hooks/useCurrentBlockTimestamp'
import { useVeCakeUserInfo } from 'views/CakeStaking/hooks/useVeCakeUserInfo'
Expand Down Expand Up @@ -100,11 +100,17 @@ export const useUserVote = (gauge: Gauge | undefined, submitted?: boolean, usePr
.unix(Number(proxyLastVoteTime))
.add(10, 'day')
.isAfter(dayjs.unix(currentTimestamp))
const nativeVoteLocked = dayjs
let nativeVoteLocked = dayjs
.unix(Number(nativeLastVoteTime))
.add(10, 'day')
.isAfter(dayjs.unix(currentTimestamp))
let [nativeSlope, nativePower, proxySlope, proxyPower] = [_nativeSlope, _nativePower, _proxySlope, _proxyPower]

if (gauge?.killed) {
nativeVoteLocked = true
nativePower = 0n
}

if (!proxyEnd) {
return {
hash: gauge?.hash as Hex,
Expand Down Expand Up @@ -197,18 +203,23 @@ export const useUserVote = (gauge: Gauge | undefined, submitted?: boolean, usePr
})
: []
const [[nativeSlope, nativePower, nativeEnd], lastVoteTime] = response
const voteLocked = dayjs.unix(Number(lastVoteTime)).add(10, 'day').isAfter(dayjs.unix(currentTimestamp))
let voteLocked = dayjs.unix(Number(lastVoteTime)).add(10, 'day').isAfter(dayjs.unix(currentTimestamp))
let votedPower = nativePower
if (gauge?.killed) {
voteLocked = true
votedPower = 0n
}

return {
hash: gauge?.hash as Hex,
nativeSlope,
nativePower,
nativePower: votedPower,
nativeEnd,
nativeLastVoteTime: lastVoteTime,
nativeVoteLocked: voteLocked,

slope: nativeSlope,
power: nativePower,
power: votedPower,
end: nativeEnd,
lastVoteTime,
voteLocked,
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/views/GaugesVoting/hooks/useVotedPower.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useQuery } from '@tanstack/react-query'
import useAccountActiveChain from 'hooks/useAccountActiveChain'
import { useGaugesVotingContract } from 'hooks/useContract'
import { useAccount } from 'wagmi'

export const useVotedPower = () => {
const { address: account } = useAccount()
const { account } = useAccountActiveChain()
const contract = useGaugesVotingContract()
const { data } = useQuery({
queryKey: ['/vecake/vote-power', contract.address, account],
Expand Down
5 changes: 4 additions & 1 deletion packages/gauges/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@
},
"./package.json": "./package.json"
},
"peerDependencies": {
"@pancakeswap/utils": "workspace:*"
},
"devDependencies": {
"@pancakeswap/sdk": "workspace:^",
"@pancakeswap/position-managers": "workspace:^",
"@pancakeswap/sdk": "workspace:^",
"@types/lodash": "^4.14.202",
"lodash": "^4.17.21",
"tsup": "^6.7.0"
Expand Down
56 changes: 23 additions & 33 deletions packages/gauges/src/constants/config/getGauges.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,31 @@
import { cacheByLRU } from '@pancakeswap/utils/cacheByLRU'
import { GaugeConfig } from '../../types'
import { GAUGES_API } from './endpoint'

function createGaugeConfigFetcher() {
let gauges: GaugeConfig[] | undefined
let fetchRequest: Promise<GaugeConfig[]> | undefined

return async function getGaugeConfig() {
if (fetchRequest) return fetchRequest
const fetchGaugeConfig = async () => {
if (gauges) {
return gauges
}
try {
const response = await fetch(GAUGES_API, {
signal: AbortSignal.timeout(3000),
})
if (response.ok) {
gauges = await response.json()
if (!gauges) {
throw new Error(`Unexpected empty gauges fetched from remote ${gauges}`)
}
return gauges
}
throw new Error(`Fetch failed with status: ${response.status}`)
} catch (e) {
if (e instanceof Error) {
throw new Error(`Fetch failed: ${e.message}`)
} else {
throw new Error(`Fetch failed: ${e}`)
}
} finally {
fetchRequest = undefined
const fetchGaugeConfig = async () => {
try {
const response = await fetch(GAUGES_API, {
signal: AbortSignal.timeout(3000),
})
if (response.ok) {
const gauges: GaugeConfig[] = await response.json()
if (!gauges) {
throw new Error(`Unexpected empty gauges fetched from remote`)
}
return gauges
}
throw new Error(`Fetch failed with status: ${response.status}`)
} catch (e) {
if (e instanceof Error) {
throw new Error(`Fetch failed: ${e.message}`)
} else {
throw new Error(`Fetch failed: ${e}`)
}
fetchRequest = fetchGaugeConfig()
return fetchRequest
}
}

export const getGauges = createGaugeConfigFetcher()
export const getGauges = cacheByLRU(fetchGaugeConfig, {
name: 'getGaugesConfig',
ttl: 10000,
key: () => [],
})
12 changes: 11 additions & 1 deletion packages/gauges/src/fetchAllGauges.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { cacheByLRU } from '@pancakeswap/utils/cacheByLRU'
import { AbiStateMutability, ContractFunctionReturnType, PublicClient } from 'viem'
import { gaugesVotingABI } from './abis/gaugesVoting'
import { getContract } from './contract'
import { fetchGaugesCount } from './fetchGaugesCount'
import { getGaugeHash } from './getGaugeHash'
import { GaugeInfo } from './types'

export const fetchAllGauges = async (
const _fetchAllGauges = async (
client: PublicClient,
options?: {
blockNumber?: bigint
Expand Down Expand Up @@ -44,3 +45,12 @@ export const fetchAllGauges = async (
} as GaugeInfo
})
}

export const fetchAllGauges = cacheByLRU(_fetchAllGauges, {
name: 'fetchAllGauges',
ttl: 10000,
key: (params) => {
const [, options] = params
return [options?.blockNumber]
},
})
Loading
Loading