Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 53 additions & 21 deletions apps/insights/src/components/PriceFeed/Chart/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,17 @@ const useChartElem = (symbol: string, feedId: string) => {
return;
}
isBackfilling.current = true;
const url = new URL("/historical-prices", globalThis.location.origin);

const url = new URL(
"https://benchmarks.pyth.network/v1/shims/tradingview/history",
);
url.searchParams.set("symbol", symbol);
url.searchParams.set("from", from.toString());
url.searchParams.set("to", to.toString());
url.searchParams.set("resolution", resolution);
url.searchParams.set("cluster", "pythnet");
url.searchParams.set(
"resolution",
mapResolutionToBenchmarksApi(resolution),
);

abortControllerRef.current = new AbortController();
abortControllerRef.current.signal.addEventListener("abort", () => {
Expand All @@ -177,7 +182,15 @@ const useChartElem = (symbol: string, feedId: string) => {
return;
}

const data = historicalDataSchema.parse(jsonData);
const benchmarkData = benchmarksApiResponseSchema.parse(jsonData);

// Transform OHLC data to our format using close prices
const data = benchmarkData.t.map((timestamp, i) => ({
time: timestamp as UTCTimestamp,
price: benchmarkData.c[i], // Use close price
Copy link
Collaborator

@cprussin cprussin Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this -- I think we will need to put more thought in here. If we aren't showing OHLC candles, I think the chart will be misleading. Plus, we should have full resolution (individual points) when zoomed all the way in, so OHLC doesn't really make sense at that resolution. Let's grab some time to chat through this

confidence: 0, // No confidence data from benchmarks API
status: PriceStatus.Trading,
}));
Comment on lines +188 to +193
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd do this using a zod transform


// Get the current historical price data
// Note that .data() returns (WhitespaceData | LineData)[], hence the type cast.
Expand All @@ -194,16 +207,17 @@ const useChartElem = (symbol: string, feedId: string) => {
value: d.price,
}),
}));
// we have no confidence data, set confidence bands to match the price
const newHistoricalConfidenceHighData = data.map((d) => ({
time: d.time,
...(d.status === PriceStatus.Trading && {
value: d.price + d.confidence,
value: d.price,
}),
}));
const newHistoricalConfidenceLowData = data.map((d) => ({
time: d.time,
...(d.status === PriceStatus.Trading && {
value: d.price - d.confidence,
value: d.price,
}),
}));

Expand Down Expand Up @@ -381,21 +395,15 @@ type ChartRefContents = {
price: ISeriesApi<"Line">;
};

const historicalDataSchema = z.array(
z
.strictObject({
timestamp: z.number(),
price: z.number(),
confidence: z.number(),
status: z.nativeEnum(PriceStatus),
})
.transform((d) => ({
time: Number(d.timestamp) as UTCTimestamp,
price: d.price,
confidence: d.confidence,
status: d.status,
})),
);
const benchmarksApiResponseSchema = z.object({
s: z.string(), // status
t: z.array(z.number()), // timestamp
o: z.array(z.number()), // open
h: z.array(z.number()), // high
l: z.array(z.number()), // low
c: z.array(z.number()), // close
v: z.array(z.number()), // volume
});
const priceFormat = {
type: "price",
precision: 5,
Expand All @@ -408,6 +416,30 @@ const confidenceConfig = {
lineWidth: 1,
} as const;

/**
* Map our internal resolution format to the benchmarks API resolution format
*/
function mapResolutionToBenchmarksApi(resolution: string): string {
switch (resolution) {
case "1s":
case "1m": {
return "1";
}
case "5m": {
return "5";
}
case "1H": {
return "60";
}
case "1D": {
return "1D";
}
default: {
throw new Error(`Unknown resolution: ${resolution}`);
}
}
}

const useChartResize = (
chartContainerRef: RefObject<HTMLDivElement | null>,
chartRef: RefObject<ChartRefContents | undefined>,
Expand Down
Loading