mango-v4-ui/hooks/useBirdeye24hrPrices.ts

89 lines
2.8 KiB
TypeScript

import { Group, Serum3Market } from '@blockworks-foundation/mango-v4'
import mangoStore from '@store/mangoStore'
import { useQuery } from '@tanstack/react-query'
import { makeApiRequest } from 'apis/birdeye/helpers'
import useMangoGroup from './useMangoGroup'
import { DAILY_SECONDS } from 'utils/constants'
const fetchBirdeye24hrPrices = async (
group: Group | undefined,
spotMarkets: Serum3Market[],
) => {
if (!group) return []
try {
const queryEnd = Math.floor(Date.now() / 1000)
const queryStart = queryEnd - DAILY_SECONDS
// collect unique quote tokens
const uniqueQuoteTokens = Array.from(
new Set(
spotMarkets.map((market) => {
const quoteBank = group.getFirstBankByTokenIndex(
market.quoteTokenIndex,
)
return quoteBank?.mint
}),
),
).filter(Boolean) // remove any undefined values
// fetch responses for unique quote tokens
const quoteResponses = await Promise.all(
uniqueQuoteTokens.map(async (quoteToken) => {
const quoteQuery = `defi/history_price?address=${quoteToken}&address_type=token&type=1H&time_from=${queryStart}&time_to=${queryEnd}`
const quoteResponse = await makeApiRequest(quoteQuery)
return {
quoteToken,
items: quoteResponse?.data?.items?.length
? quoteResponse.data.items
: [],
}
}),
)
// create a map for quick access to quote items based on quoteToken
const quoteItemsMap = new Map(
quoteResponses.map((response) => [response.quoteToken, response.items]),
)
// fetch base responses and match them with quote items
const promises = spotMarkets.map(async (market) => {
const baseBank = group.getFirstBankByTokenIndex(market.baseTokenIndex)
const quoteBank = group.getFirstBankByTokenIndex(market.quoteTokenIndex)
const baseQuery = `defi/history_price?address=${baseBank?.mint}&address_type=token&type=1H&time_from=${queryStart}&time_to=${queryEnd}`
const baseResponse = await makeApiRequest(baseQuery)
return {
base: baseResponse?.data?.items?.length ? baseResponse.data.items : [],
quote: quoteItemsMap.get(quoteBank?.mint) || [],
marketIndex: market.marketIndex,
}
})
const responses = await Promise.all(promises)
return responses
} catch (e) {
console.error('error fetching 24-hour price data from birdeye', e)
return []
}
}
export const useBirdeye24hrPrices = () => {
const spotMarkets = mangoStore((s) => s.serumMarkets)
const { group } = useMangoGroup()
return useQuery(
['birdeye-daily-prices'],
() => fetchBirdeye24hrPrices(group, spotMarkets),
{
cacheTime: 1000 * 60 * 15,
staleTime: 1000 * 60 * 10,
retry: 3,
enabled: !!(group && spotMarkets?.length),
refetchOnWindowFocus: false,
},
)
}