Skip to content

Commit

Permalink
update graph chart
Browse files Browse the repository at this point in the history
  • Loading branch information
foxier25 committed Nov 19, 2024
1 parent 444f3c9 commit deeaf7d
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 18 deletions.
64 changes: 60 additions & 4 deletions src/components/Tokens/TokenDetails/ChartSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,72 @@ import { startTransition, Suspense, useMemo } from 'react'

import { PriceChart } from './PriceChart'
import TimePeriodSelector from './TimeSelector'
import { ti } from 'make-plural'

function usePriceHistory(tokenPriceData: TokenPriceQuery): PricePoint[] | undefined {
function fillMissingTimestamps(priceHistory: any, interval: number, totalTime: number) {
if (!Array.isArray(priceHistory) || priceHistory.length === 0) {
return priceHistory; // Return the original array if invalid or empty
}

// Sort the array by timestamp to ensure proper filling
priceHistory.sort((a, b) => a.timestamp - b.timestamp);
const currentTimestamp = Date.now() / 1000
const filledHistory = [];

for (let i = 0; i < priceHistory.length - 1; i++) {
const current = priceHistory[i];
const next = priceHistory[i + 1];

// Add the current object to the filled array
if(next.timestamp + totalTime >= currentTimestamp) {
if(current.timestamp + totalTime >= currentTimestamp) filledHistory.push(current);

// Fill missing timestamps
let timestamp = current.timestamp + interval;
while (timestamp < next.timestamp) {
if(timestamp + totalTime >= currentTimestamp)
filledHistory.push({
...current, // Copy previous values
timestamp, // Update timestamp
});
timestamp += interval;
}
}
}

// Add the last object to the filled array
filledHistory.push(priceHistory[priceHistory.length - 1]);
return filledHistory;
}

function getTimeInterval(timePeriod:any) {
switch(timePeriod) {
case 0:
return [300, 3600];
case 1:
return [600, 86400];
case 2:
return [3600, 604800];
case 3:
return [3600, 2592000];
case 4:
return [86400, 31536000];
}
return [86400, 0];
}

function usePriceHistory(tokenPriceData: TokenPriceQuery, timePeriod: any): PricePoint[] | undefined {

const [timeInterval, totalTime] = getTimeInterval(timePeriod);
// Appends the current price to the end of the priceHistory array
const priceHistory = useMemo(() => {
const market = tokenPriceData.token?.market
const priceHistory = market?.priceHistory?.filter(isPricePoint)
// const priceHistory = market?.priceHistory?.filter(isPricePoint)
const currentPrice = market?.price?.value
if (Array.isArray(priceHistory) && currentPrice !== undefined) {
const timestamp = Date.now() / 1000
return [...priceHistory, { timestamp, value: currentPrice }]
return fillMissingTimestamps([...priceHistory, { timestamp, value: currentPrice }], timeInterval, totalTime)
}
return priceHistory
}, [tokenPriceData])
Expand Down Expand Up @@ -55,7 +111,7 @@ function Chart({
}) {
// Initializes time period to global & maintain separate time period for subsequent changes
const timePeriod = useAtomValue(pageTimePeriodAtom)
const prices = usePriceHistory(tokenPriceQuery)
const prices = usePriceHistory(tokenPriceQuery, timePeriod)

return (
<ChartContainer data-testid="chart-container">
Expand All @@ -70,4 +126,4 @@ function Chart({
/>
</ChartContainer>
)
}
}
56 changes: 42 additions & 14 deletions src/pages/TokenDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Chain, TokenQuery, Currency, TokenQueryData } from 'graphql/data/Token'
import { TokenPriceQuery } from 'graphql/data/TokenPrice'

const GetTokenInfo = gql`
query GetTokenInfo($tokenAddress: String!) {
query GetTokenInfo($tokenAddress: String!, $days: Int, $hours: Int) {
bundles(first: 10) {
ethPriceUSD
}
Expand All @@ -29,14 +29,22 @@ query GetTokenInfo($tokenAddress: String!) {
derivedETH
# Get daily data for more detailed metrics
tokenDayData(first: 365, orderBy: date, orderDirection: asc) {
tokenDayData(first: $days, orderBy: date, orderDirection: desc) {
id
date
priceUSD # The price of the token in USD for the day
totalValueLockedUSD
volumeUSD
}
tokenHourData(first: $hours, orderBy: periodStartUnix, orderDirection: desc) {
id
periodStartUnix
priceUSD # The price of the token in USD for the day
totalValueLockedUSD
volumeUSD
}
# Get all pools involving this token for liquidity details
whitelistPools {
id
Expand All @@ -57,11 +65,29 @@ query GetTokenInfo($tokenAddress: String!) {

export const pageTimePeriodAtom = atomWithStorage<TimePeriod>('tokenDetailsTimePeriod', TimePeriod.DAY)

function getQueryParams(timePeriod:any) {
switch(timePeriod) {
case 0:
return [2, 2];
case 1:
return [2, 24];
case 2:
return [2, 168];
case 3:
return [30, 2];
case 4:
return [365, 2];
}
return [2, 2];
}


export default function TokenDetailsPage() {
const { tokenAddress, chainName } = useParams<{ tokenAddress: string; chainName?: string }>()
const chain = validateUrlChainParam(chainName)
const isNative = tokenAddress === NATIVE_CHAIN_ID
const [timePeriod, setTimePeriod] = useAtom(pageTimePeriodAtom)
const [totalDays, totalHours] = getQueryParams(timePeriod);
const [address, duration] = useMemo(
/* tokenAddress will always be defined in the path for for this page to render, but useParams will always
return optional arguments; nullish coalescing operator is present here to appease typechecker */
Expand All @@ -82,11 +108,12 @@ export default function TokenDetailsPage() {
duration,
},
})

const { data: luxData, loading: luxLoading } = useQuery(GetTokenInfo, {
client: luxClient,
variables: {
tokenAddress: address,
days: totalDays,
hours: totalHours,
},
})
if (luxLoading) {
Expand Down Expand Up @@ -152,28 +179,29 @@ const transformedTokenDetail: TokenQuery = tokenPriceQuery??{
};
const ethPriceUSD = luxData?.bundles[0]?.ethPriceUSD;
const ethPrice = luxData?.token?.derivedETH;
const tokenDayData = luxData?.token?.tokenDayData.filter((data: any) => parseFloat(data.priceUSD) !== 0).map((data: any) => ({
id: `VGltZXN0YW1wZWRBbW91bnQ6MV8x${data.date}_VVNE`, // Encoded version of the timestamped amount
timestamp: data.date,
value: parseFloat(data.priceUSD),
}))
const tokenHourData = luxData?.token?.tokenHourData.filter((data: any) => parseFloat(data.priceUSD) !== 0).map((data: any) => ({
id: `VGltZXN0YW1wZWRBbW91bnQ6MV8x${data.periodStartUnix}_VVNE`, // Encoded version of the timestamped amount
timestamp: data.periodStartUnix,
value: parseFloat(data.priceUSD),
}))

const transformedTokenPriceHistory:TokenPriceQuery = {
token: {
__typename: "Token",
id: "VG9rZW46RVRIRVJFVU1fMHhhMGI4Njk5MWM2MjE4YjM2YzFkMTlkNGEyZTllYjBjZTM2MDZlYjQ4", // Encoded version of the token ID
address: luxData?.token?.id,
chain: Chain.Lux,
market: {
__typename: "TokenMarket",
id: "VG9rZW5NYXJrZXQ6RVRIRVJFVU1fMHhhMGI4Njk5MWM2MjE4YjM2YzFkMTlkNGEyZTllYjBjZTM2MDZlYjQ4X1VTRA==", // Encoded ID for the market
price: {
__typename: "Amount",
id: "QW1vdW50OjFfVVNE", // Encoded amount ID
value: parseFloat(ethPriceUSD) * parseFloat(ethPrice),
},
priceHistory: luxData?.token?.tokenDayData.filter((data: any) => parseFloat(data.priceUSD) !== 0)
.map((data: any) => ({
__typename: "TimestampedAmount",
id: `VGltZXN0YW1wZWRBbW91bnQ6MV8x${data.date}_VVNE`, // Encoded version of the timestamped amount
timestamp: data.date,
value: parseFloat(data.priceUSD),
})),
priceHistory: timePeriod < 3 ? tokenHourData : tokenDayData,
},
},
};
Expand All @@ -200,4 +228,4 @@ const renderTokenDetail = (tokenAddress: any, chain: any, tokenQuery: any) => (
}
if (!tokenQuery) return <TokenDetailsPageSkeleton />
return renderTokenDetail(tokenAddress, chain, tokenQuery)
}
}

0 comments on commit deeaf7d

Please sign in to comment.