import { NotionalTVLCumulative } from "../../../hooks/useCumulativeTVL"; import { NotionalTransferredFrom } from "../../../hooks/useNotionalTransferred"; import { TimeFrame } from "./TimeFrame"; import { DateTime } from "luxon"; import { Totals } from "../../../hooks/useTransactionTotals"; import { ChainInfo, CHAINS_BY_ID, VAA_EMITTER_ADDRESSES, } from "../../../utils/consts"; import { NotionalTVL } from "../../../hooks/useTVL"; import { ChainId } from "@certusone/wormhole-sdk"; export const formatTVL = (tvl: number) => { const [divisor, unit, fractionDigits] = tvl < 1e3 ? [1, "", 0] : tvl < 1e6 ? [1e3, "K", 0] : tvl < 1e9 ? [1e6, "M", 0] : [1e9, "B", 2]; return `$${(tvl / divisor).toFixed(fractionDigits)} ${unit}`; }; export const formatDate = (date: Date) => { return date.toLocaleString("en-US", { day: "numeric", month: "long", year: "numeric", timeZone: "UTC", }); }; export const formatTickDay = (date: Date) => { return date.toLocaleString("en-US", { day: "numeric", month: "short", year: "numeric", timeZone: "UTC", }); }; export const formatTickMonth = (date: Date) => { return date.toLocaleString("en-US", { month: "short", year: "numeric", timeZone: "UTC", }); }; export const formatTransactionCount = (transactionCount: number) => { return transactionCount.toLocaleString("en-US"); }; export const renderLegendText = (value: any) => { return {value}; }; export const getStartDate = (timeFrame: TimeFrame) => { return timeFrame.duration ? DateTime.now().toUTC().minus(timeFrame.duration).toJSDate() : undefined; }; export interface CumulativeTVLChartData { date: Date; totalTVL: number; tvlByChain: { [chainId: string]: number; }; } export const createCumulativeTVLChartData = ( cumulativeTVL: NotionalTVLCumulative, timeFrame: TimeFrame ) => { const startDate = getStartDate(timeFrame); return Object.entries(cumulativeTVL.DailyLocked) .reduce( (chartData, [dateString, chainsAssets]) => { const date = new Date(dateString); if (!startDate || date >= startDate) { const data: CumulativeTVLChartData = { date: date, totalTVL: 0, tvlByChain: {}, }; Object.entries(chainsAssets).forEach(([chainId, lockedAssets]) => { const notional = lockedAssets["*"].Notional; if (chainId === "*") { data.totalTVL = notional; } else { data.tvlByChain[chainId] = notional; } }); chartData.push(data); } return chartData; }, [] ) .sort((a, z) => a.date.getTime() - z.date.getTime()); }; export interface TransferChartData { date: Date; totalTransferred: number; transferredByChain: { [chainId: string]: number; }; } export const createCumulativeTransferChartData = ( notionalTransferredFrom: NotionalTransferredFrom, timeFrame: TimeFrame ) => { const startDate = getStartDate(timeFrame); return Object.keys(notionalTransferredFrom.Daily) .sort() .reduce((chartData, dateString) => { const transferFromData = notionalTransferredFrom.Daily[dateString]; const data: TransferChartData = { date: new Date(dateString), totalTransferred: 0, transferredByChain: {}, }; Object.entries(transferFromData).forEach(([chainId, amount]) => { if (chainId === "*") { data.totalTransferred = (chartData[chartData.length - 1]?.totalTransferred || 0) + amount; } else { data.transferredByChain[chainId] = (chartData[chartData.length - 1]?.transferredByChain[chainId] || 0) + amount; } }); chartData.push(data); return chartData; }, []) .filter((value) => !startDate || startDate <= value.date); }; export interface TransactionData { date: Date; totalTransactions: number; transactionsByChain: { [chainId: string]: number; }; } export const createCumulativeTransactionData = ( totals: Totals, timeFrame: TimeFrame ) => { const startDate = getStartDate(timeFrame); return Object.keys(totals.DailyTotals) .sort() .reduce((chartData, dateString) => { const groupByKeys = totals.DailyTotals[dateString]; const prevData = chartData[chartData.length - 1]; const data: TransactionData = { date: new Date(dateString), totalTransactions: prevData?.totalTransactions || 0, transactionsByChain: {}, }; VAA_EMITTER_ADDRESSES.forEach((address) => { const count = groupByKeys[address] || 0; data.totalTransactions += count; const chainId = address.slice(0, address.indexOf(":")); if (data.transactionsByChain[chainId] === undefined) { data.transactionsByChain[chainId] = prevData?.transactionsByChain[chainId] || 0; } data.transactionsByChain[chainId] += count; }); chartData.push(data); return chartData; }, []) .filter((value) => !startDate || startDate <= value.date); }; export interface ChainTVLChartData { chainInfo: ChainInfo; tvl: number; tvlRatio: number; } export const createChainTVLChartData = (tvl: NotionalTVL) => { let maxTVL = 0; const chainTVLs = Object.entries(tvl.AllTime) .reduce((chartData, [chainId, assets]) => { const chainInfo = CHAINS_BY_ID[+chainId as ChainId]; if (chainInfo !== undefined) { const tvl = assets["*"].Notional; chartData.push({ chainInfo: chainInfo, tvl: tvl, tvlRatio: 0, }); maxTVL = Math.max(maxTVL, tvl); } return chartData; }, []) .sort((a, z) => z.tvl - a.tvl); if (maxTVL > 0) { chainTVLs.forEach((chainTVL) => { chainTVL.tvlRatio = (chainTVL.tvl / maxTVL) * 100; }); } return chainTVLs; };