Skip to content

Commit bfb3b7b

Browse files
jayantkJayant Krishnamurthyali-bahjati
authored
Move staleness check to new endpoint (#278)
* move staleness to new endpoint * actually send the response * Add schema * Fix freshness metric to use publish time instead of attestation Time * Rename endpoint to /api/ + small fix * Bump version Co-authored-by: Jayant Krishnamurthy <[email protected]> Co-authored-by: Ali Behjati <[email protected]>
1 parent f3e17ad commit bfb3b7b

File tree

8 files changed

+39
-24
lines changed

8 files changed

+39
-24
lines changed

devnet/pyth-price-service.yaml

-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,5 @@ spec:
7070
value: '5'
7171
- name: READINESS_NUM_LOADED_SYMBOLS
7272
value: '6'
73-
- name: READINESS_FRESHNESS_TIME_SECONDS
74-
value: '10'
7573
- name: LOG_LEVEL
7674
value: debug

third_party/pyth/price-service/.env.sample

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ SPY_SERVICE_FILTERS=[{"chain_id":1,"emitter_address":"71f8dcb863d176e2c420ad6610
1515
# Number of seconds to sync with spy to be sure to have latest messages
1616
READINESS_SPY_SYNC_TIME_SECONDS=60
1717
READINESS_NUM_LOADED_SYMBOLS=5
18-
READINESS_FRESHNESS_TIME_SECONDS=10
1918

2019
WS_PORT=6200
2120
REST_PORT=4200

third_party/pyth/price-service/docker-compose.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ services:
2424
- PROM_PORT=8081
2525
- READINESS_SPY_SYNC_TIME_SECONDS=60
2626
- READINESS_NUM_LOADED_SYMBOLS=8
27-
- READINESS_FRESHNESS_TIME_SECONDS=10
2827
- LOG_LEVEL=debug
2928
healthcheck:
3029
test:

third_party/pyth/price-service/package-lock.json

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

third_party/pyth/price-service/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pythnetwork/pyth-price-service",
3-
"version": "1.0.0",
3+
"version": "1.4.1",
44
"description": "Pyth Price Service",
55
"main": "index.js",
66
"scripts": {

third_party/pyth/price-service/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ async function run() {
3535
envOrErr("READINESS_SPY_SYNC_TIME_SECONDS")
3636
),
3737
numLoadedSymbols: parseInt(envOrErr("READINESS_NUM_LOADED_SYMBOLS")),
38-
freshnessTimeSeconds: parseInt(envOrErr("READINESS_FRESHNESS_TIME_SECONDS")),
3938
},
4039
},
4140
promClient

third_party/pyth/price-service/src/listen.ts

+1-11
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export interface PriceStore {
4343
type ListenerReadinessConfig = {
4444
spySyncTimeSeconds: number;
4545
numLoadedSymbols: number;
46-
freshnessTimeSeconds: number;
4746
};
4847

4948
type ListenerConfig = {
@@ -246,16 +245,7 @@ export class Listener implements PriceStore {
246245
if (this.priceFeedVaaMap.size < this.readinessConfig.numLoadedSymbols) {
247246
return false;
248247
}
249-
let priceIds = [...this.getPriceIds()];
250-
let arePricesFresh = priceIds.every(
251-
(priceId) =>
252-
currentTime -
253-
this.priceFeedVaaMap.get(priceId)!.priceFeed.publishTime <=
254-
this.readinessConfig.freshnessTimeSeconds
255-
);
256-
if (!arePricesFresh) {
257-
return false;
258-
}
248+
259249
return true;
260250
}
261251
}

third_party/pyth/price-service/src/rest.ts

+33-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { Server } from "http";
55
import { StatusCodes } from "http-status-codes";
66
import morgan from "morgan";
77
import responseTime from "response-time";
8-
import { DurationInMs, DurationInSec } from "./helpers";
8+
import { DurationInMs, DurationInSec, TimestampInSec } from "./helpers";
99
import { PriceStore } from "./listen";
1010
import { logger } from "./logging";
1111
import { PromClient } from "./promClient";
12+
import { HexString } from "@pythnetwork/pyth-sdk-js";
1213

1314
const MORGAN_LOG_FORMAT =
1415
':remote-addr - :remote-user ":method :url HTTP/:http-version"' +
@@ -104,7 +105,7 @@ export class RestAPI {
104105
}
105106

106107
const freshness: DurationInSec =
107-
new Date().getTime() / 1000 - latestPriceInfo.attestationTime;
108+
new Date().getTime() / 1000 - latestPriceInfo.priceFeed.publishTime;
108109
this.promClient?.addApiRequestsPriceFreshness(
109110
req.path,
110111
id,
@@ -162,7 +163,7 @@ export class RestAPI {
162163
}
163164

164165
const freshness: DurationInSec =
165-
new Date().getTime() / 1000 - latestPriceInfo.attestationTime;
166+
new Date().getTime() / 1000 - latestPriceInfo.priceFeed.publishTime;
166167
this.promClient?.addApiRequestsPriceFreshness(
167168
req.path,
168169
id,
@@ -203,6 +204,35 @@ export class RestAPI {
203204
});
204205
endpoints.push("api/price_feed_ids");
205206

207+
const staleFeedsInputSchema: schema = {
208+
query: Joi.object({
209+
threshold: Joi.number().required(),
210+
}).required(),
211+
};
212+
app.get("/api/stale_feeds",
213+
validate(staleFeedsInputSchema),
214+
(req: Request, res: Response) => {
215+
let stalenessThresholdSeconds = Number(req.query.threshold as string);
216+
217+
let currentTime: TimestampInSec = Math.floor(Date.now() / 1000);
218+
219+
let priceIds = [...this.priceFeedVaaInfo.getPriceIds()];
220+
let stalePrices: Record<HexString, number> = {}
221+
222+
for (let priceId of priceIds) {
223+
const latency = currentTime - this.priceFeedVaaInfo.getLatestPriceInfo(priceId)!.priceFeed.publishTime
224+
if (latency > stalenessThresholdSeconds) {
225+
stalePrices[priceId] = latency
226+
}
227+
}
228+
229+
res.json(stalePrices);
230+
}
231+
);
232+
endpoints.push(
233+
"/api/stale_feeds?threshold=<staleness_threshold_seconds>"
234+
);
235+
206236
app.get("/ready", (_, res: Response) => {
207237
if (this.isReady!()) {
208238
res.sendStatus(StatusCodes.OK);

0 commit comments

Comments
 (0)