Skip to content

Commit

Permalink
feat: update subgraph api to use zod with retries
Browse files Browse the repository at this point in the history
  • Loading branch information
frontier159 committed Oct 31, 2024
1 parent 32af62d commit 8e8a785
Show file tree
Hide file tree
Showing 11 changed files with 808 additions and 363 deletions.
3 changes: 2 additions & 1 deletion apps/dapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
"tippy.js": "^6.3.7",
"use-debounce": "^9.0.2",
"use-interval": "^1.4.0",
"util": "^0.12.4"
"util": "^0.12.4",
"zod": "^3.19.1"
},
"devDependencies": {
"@babel/core": "^7.16.0",
Expand Down
21 changes: 11 additions & 10 deletions apps/dapp/src/components/Pages/Core/DappPages/Borrow/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
formatNumberFixedDecimals,
} from 'utils/formatter';
import { formatDailyDataPoints } from 'utils/charts';
import { fetchGenericSubgraph } from 'utils/subgraph';
import { queryTlcDailySnapshots, subgraphQuery } from 'utils/subgraph';
import IntervalToggler from 'components/Charts/IntervalToggler';
import env from 'constants/env';

Expand Down Expand Up @@ -50,17 +50,18 @@ export const TlcChart = () => {

useEffect(() => {
const fetchMetrics = async () => {
const { data } = await fetchGenericSubgraph<any>(
const response = await subgraphQuery(
env.subgraph.templeV2,
`{
tlcDailySnapshots(orderBy: timestamp, orderDirection: desc) {
timestamp
utilRatio
interestYield
}
}`
queryTlcDailySnapshots()
);

setMetrics(
response.tlcDailySnapshots.map((r) => ({
timestamp: parseFloat(r.timestamp),
utilRatio: parseFloat(r.utilRatio),
interestYield: parseFloat(r.interestYield),
}))
);
setMetrics(data.tlcDailySnapshots);
};
fetchMetrics();
}, []);
Expand Down
39 changes: 17 additions & 22 deletions apps/dapp/src/components/Pages/Core/DappPages/Borrow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {
TreasuryReservesVault__factory,
} from 'types/typechain';
import { ITlcDataTypes } from 'types/typechain/contracts/interfaces/v2/templeLineOfCredit/ITempleLineOfCredit';
import { fetchGenericSubgraph } from 'utils/subgraph';
import {
queryTlcMinBorrowAmount,
queryTlcPrices,
subgraphQuery,
} from 'utils/subgraph';
import { BigNumber, ethers } from 'ethers';
import daiImg from 'assets/images/newui-images/tokens/dai.png';
import templeImg from 'assets/images/newui-images/tokens/temple.png';
Expand Down Expand Up @@ -86,23 +90,18 @@ export const BorrowPage = () => {
const [metricsLoading, setMetricsLoading] = useState(false);

const getPrices = useCallback(async () => {
const { data } = await fetchGenericSubgraph<any>(
const response = await subgraphQuery(
env.subgraph.templeV2,
`{
tokens {
price
symbol
}
treasuryReservesVaults {
treasuryPriceIndex
}
}`
queryTlcPrices()
);
setPrices({
templePrice: data.tokens.filter((t: any) => t.symbol == 'TEMPLE')[0]
.price,
daiPrice: data.tokens.filter((t: any) => t.symbol == 'DAI')[0].price,
tpi: data.treasuryReservesVaults[0].treasuryPriceIndex,
templePrice: parseFloat(
response.tokens.filter((t: any) => t.symbol == 'TEMPLE')[0].price
),
daiPrice: parseFloat(
response.tokens.filter((t: any) => t.symbol == 'DAI')[0].price
),
tpi: parseFloat(response.treasuryReservesVaults[0].treasuryPriceIndex),
});
}, []);

Expand Down Expand Up @@ -210,13 +209,9 @@ export const BorrowPage = () => {
};
getAccountPosition();
try {
const { data } = await fetchGenericSubgraph<any>(
const response = await subgraphQuery(
env.subgraph.templeV2,
`{
tlcDailySnapshots(orderBy: timestamp, orderDirection: desc, first: 1) {
minBorrowAmount
}
}`
queryTlcMinBorrowAmount()
);

const tlcInfoFromContracts = await getTlcInfoFromContracts();
Expand All @@ -230,7 +225,7 @@ export const BorrowPage = () => {
}

setTlcInfo({
minBorrow: data.tlcDailySnapshots[0].minBorrowAmount,
minBorrow: parseFloat(response.tlcDailySnapshots[0].minBorrowAmount),
borrowRate: tlcInfoFromContracts?.borrowRate || 0,
liquidationLtv: tlcInfoFromContracts?.liquidationLtv || 0,
strategyBalance: tlcInfoFromContracts?.strategyBalance || 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import { formatTimestampedChartData } from 'utils/charts';
import useV2StrategySnapshotData, {
StrategyTokenField,
V2SnapshotMetric,
V2StrategySnapshot,
} from '../hooks/use-dashboardv2-daily-snapshots';
import {
ALL_STRATEGIES,
DashboardData,
isTRVDashboard,
StrategyKey,
} from '../DashboardConfig';
import { V2StrategySnapshot } from 'utils/subgraph';

type XAxisTickFormatter = (timestamp: number) => string;

Expand Down Expand Up @@ -181,12 +182,16 @@ const V2StrategyMetricsChart: React.FC<{

const filteredDaily =
dailyMetrics
?.filter((m) => chartStrategyNames.includes(m.strategy.name))
?.filter((m) =>
chartStrategyNames.includes(m.strategy.name as StrategyKey)
)
.sort((a, b) => parseInt(a.timestamp) - parseInt(b.timestamp)) ?? [];

const filteredHourly =
hourlyMetrics
?.filter((m) => chartStrategyNames.includes(m.strategy.name))
?.filter((m) =>
chartStrategyNames.includes(m.strategy.name as StrategyKey)
)
.sort((a, b) => parseInt(a.timestamp) - parseInt(b.timestamp)) ?? [];

// if we are rendering chart for only one strategy we can use data as is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import { queryMinTablet } from 'styles/breakpoints';
import env from 'constants/env';
import linkSvg from 'assets/icons/link.svg?react';
import { formatNumberWithCommas } from 'utils/formatter';
import { DashboardData, Dashboards, isTRVDashboard } from '../DashboardConfig';
import {
DashboardData,
Dashboards,
isTRVDashboard,
StrategyKey,
} from '../DashboardConfig';

type Props = {
dashboardData: DashboardData;
Expand Down Expand Up @@ -271,8 +276,8 @@ const TxnHistoryTable = (props: Props) => {
const timeOnly = format(new Date(Number(tx.timestamp) * 1000), 'H:mm:ss');
return {
date: isBiggerThanTablet ? datetime : dateOnly,
type: tx.name,
strategy: tx.strategy.name,
type: tx.name as TxType,
strategy: tx.strategy.name as StrategyKey,
token: tx.token.symbol,
amount: amountFmt,
txHash: tx.hash,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { useQuery } from '@tanstack/react-query';
import env from 'constants/env';
import { getQueryKey } from 'utils/react-query-helpers';
import { SubGraphResponse } from 'hooks/core/types';
import { fetchGenericSubgraph } from 'utils/subgraph';
import { StrategyKey } from '../DashboardConfig';
import {
queryStrategyDailySnapshots,
queryStrategyHourlySnapshots,
subgraphQuery,
V2StrategySnapshot,
} from 'utils/subgraph';

const V2SnapshotMetrics = [
'totalMarketValueUSD',
Expand All @@ -30,38 +33,12 @@ const STRATEGY_TOKEN_FIELDS = [

export type StrategyTokenField = (typeof STRATEGY_TOKEN_FIELDS)[number];

const QUERIED_FIELDS = `
strategy{
name
}
timeframe
timestamp
${V2SnapshotMetrics.join('\n')}
strategyTokens{
${STRATEGY_TOKEN_FIELDS.join('\n')}
}
`;

export type V2StrategySnapshot = {
timestamp: string;
timeframe: string;
strategy: { name: StrategyKey };
strategyTokens: { [key in (typeof STRATEGY_TOKEN_FIELDS)[number]]: string }[];
} & { [key in V2SnapshotMetric]: string };

export function isV2SnapshotMetric(
key?: string | null
): key is V2SnapshotMetric {
return V2SnapshotMetrics.some((m) => m === key);
}

type FetchV2StrategyDailySnapshotResponse = SubGraphResponse<{
strategyDailySnapshots: V2StrategySnapshot[];
}>;
type FetchV2StrategyHourlySnapshotResponse = SubGraphResponse<{
strategyHourlySnapshots: V2StrategySnapshot[];
}>;

const ONE_DAY_ONE_HOUR_MS = 25 * 60 * 60 * 1000;
const ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1000;

Expand All @@ -73,22 +50,17 @@ async function fetchStrategyHourlySnapshots() {
).toString();
// if # of strategies * 24 > 1000 we would be missing data
// but we shouldnt be getting anywhere close to that
const query = `
query {
strategyHourlySnapshots(first: ${itemsPerPage},
orderBy: timestamp,
orderDirection: asc,
where: {timestamp_gt: ${since}}
) {
${QUERIED_FIELDS}
}
}`;
const resp =
await fetchGenericSubgraph<FetchV2StrategyHourlySnapshotResponse>(
env.subgraph.templeV2Balances,
query
);
return resp?.data?.strategyHourlySnapshots ?? [];
const resp = await subgraphQuery(
env.subgraph.templeV2Balances,
queryStrategyHourlySnapshots(
V2SnapshotMetrics,
STRATEGY_TOKEN_FIELDS,
itemsPerPage,
since
)
);

return resp.strategyHourlySnapshots;
}

async function fetchStrategyDailySnapshots() {
Expand All @@ -99,26 +71,19 @@ async function fetchStrategyDailySnapshots() {
const MAX_PAGE_SIZE = 1000; // current max page size
let skip = 0;
while (true) {
const query = `
query {
strategyDailySnapshots(first: ${MAX_PAGE_SIZE},
orderBy: timestamp,
orderDirection: asc,
where: {timestamp_gt: ${since}}
skip: ${skip}) {
${QUERIED_FIELDS}
}
}`;
const page =
await fetchGenericSubgraph<FetchV2StrategyDailySnapshotResponse>(
env.subgraph.templeV2Balances,
query
);
const itemsOnPage = page.data?.strategyDailySnapshots.length ?? 0;
if (page.data) {
result.push(...page.data.strategyDailySnapshots);
skip += itemsOnPage;
}
const page = await subgraphQuery(
env.subgraph.templeV2Balances,
queryStrategyDailySnapshots(
V2SnapshotMetrics,
STRATEGY_TOKEN_FIELDS,
MAX_PAGE_SIZE,
since,
skip
)
);
const itemsOnPage = page.strategyDailySnapshots.length ?? 0;
result.push(...page.strategyDailySnapshots);
skip += itemsOnPage;
if (itemsOnPage < MAX_PAGE_SIZE) {
break;
}
Expand Down
Loading

0 comments on commit 8e8a785

Please sign in to comment.