213 lines
6.0 KiB
TypeScript
213 lines
6.0 KiB
TypeScript
|
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 <span style={{ color: "white", margin: "8px" }}>{value}</span>;
|
||
|
};
|
||
|
|
||
|
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<CumulativeTVLChartData[]>(
|
||
|
(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<TransferChartData[]>((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<TransactionData[]>((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<ChainTVLChartData[]>((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;
|
||
|
};
|