Skip to content

Commit b846fc3

Browse files
authored
add new latest_price_info endpoint (#264)
* add new latest_price_info endpoint * add verbose query param to latest_price_feeds * add back logging statement for VAA * trigger CI
1 parent aa7be4d commit b846fc3

File tree

3 files changed

+38
-24
lines changed

3 files changed

+38
-24
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ function dummyPriceInfoPair(
4343
attestationTime: 0,
4444
seqNum,
4545
vaaBytes: Buffer.from(vaa, "hex").toString("binary"),
46+
emitterChainId: 0,
4647
},
4748
];
4849
}

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

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
11
import {
22
ChainId,
33
hexToUint8Array,
4-
uint8ArrayToHex,
4+
uint8ArrayToHex
55
} from "@certusone/wormhole-sdk";
66

77
import {
88
createSpyRPCServiceClient,
9-
subscribeSignedVAA,
9+
subscribeSignedVAA
1010
} from "@certusone/wormhole-spydk";
1111

1212
import { importCoreWasm } from "@certusone/wormhole-sdk/lib/cjs/solana/wasm";
1313

14-
import { envOrErr, sleep, TimestampInSec } from "./helpers";
15-
import { PromClient } from "./promClient";
1614
import {
1715
getBatchSummary,
1816
parseBatchPriceAttestation,
19-
priceAttestationToPriceFeed,
17+
priceAttestationToPriceFeed
2018
} from "@certusone/p2w-sdk";
21-
import { ClientReadableStream } from "@grpc/grpc-js";
2219
import {
2320
FilterEntry,
24-
SubscribeSignedVAAResponse,
21+
SubscribeSignedVAAResponse
2522
} from "@certusone/wormhole-spydk/lib/cjs/proto/spy/v1/spy";
26-
import { logger } from "./logging";
23+
import { ClientReadableStream } from "@grpc/grpc-js";
2724
import { HexString, PriceFeed } from "@pythnetwork/pyth-sdk-js";
25+
import { sleep, TimestampInSec } from "./helpers";
26+
import { logger } from "./logging";
27+
import { PromClient } from "./promClient";
2828

2929
export type PriceInfo = {
3030
vaaBytes: string;
3131
seqNum: number;
3232
attestationTime: TimestampInSec;
3333
priceFeed: PriceFeed;
34+
emitterChainId: number;
3435
};
3536

3637
export interface PriceStore {
@@ -196,6 +197,7 @@ export class Listener implements PriceStore {
196197
vaaBytes: vaaBytes,
197198
attestationTime: priceAttestation.attestationTime,
198199
priceFeed,
200+
emitterChainId: parsedVAA.emitter_chain,
199201
});
200202

201203
for (let callback of this.updateCallbacks) {

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

+27-16
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import express, { Express } from "express";
21
import cors from "cors";
2+
import express, { NextFunction, Request, Response } from "express";
3+
import { Joi, schema, validate, ValidationError } from "express-validation";
4+
import { Server } from "http";
5+
import { StatusCodes } from "http-status-codes";
36
import morgan from "morgan";
47
import responseTime from "response-time";
5-
import { Request, Response, NextFunction } from "express";
8+
import { DurationInMs, DurationInSec } from "./helpers";
69
import { PriceStore } from "./listen";
710
import { logger } from "./logging";
811
import { PromClient } from "./promClient";
9-
import { DurationInMs, DurationInSec } from "./helpers";
10-
import { StatusCodes } from "http-status-codes";
11-
import { validate, ValidationError, Joi, schema } from "express-validation";
12-
import { Server } from "http";
1312

1413
const MORGAN_LOG_FORMAT =
1514
':remote-addr - :remote-user ":method :url HTTP/:http-version"' +
@@ -135,13 +134,16 @@ export class RestAPI {
135134
ids: Joi.array()
136135
.items(Joi.string().regex(/^(0x)?[a-f0-9]{64}$/))
137136
.required(),
137+
verbose: Joi.boolean(),
138138
}).required(),
139139
};
140140
app.get(
141141
"/api/latest_price_feeds",
142142
validate(latestPriceFeedsInputSchema),
143143
(req: Request, res: Response) => {
144144
let priceIds = req.query.ids as string[];
145+
// verbose is optional, default to false
146+
let verbose = req.query.verbose === "true";
145147

146148
let responseJson = [];
147149

@@ -167,7 +169,18 @@ export class RestAPI {
167169
freshness
168170
);
169171

170-
responseJson.push(latestPriceInfo.priceFeed.toJson());
172+
if (verbose) {
173+
responseJson.push({
174+
...latestPriceInfo.priceFeed.toJson(),
175+
metadata: {
176+
emitter_chain: latestPriceInfo.emitterChainId,
177+
attestation_time: latestPriceInfo.attestationTime,
178+
sequence_number: latestPriceInfo.seqNum,
179+
},
180+
});
181+
} else {
182+
responseJson.push(latestPriceInfo.priceFeed.toJson());
183+
}
171184
}
172185

173186
if (notFoundIds.length > 0) {
@@ -180,18 +193,16 @@ export class RestAPI {
180193
endpoints.push(
181194
"api/latest_price_feeds?ids[]=<price_feed_id>&ids[]=<price_feed_id_2>&.."
182195
);
183-
184-
app.get(
185-
"/api/price_feed_ids",
186-
(req: Request, res: Response) => {
187-
const availableIds = this.priceFeedVaaInfo.getPriceIds();
188-
res.json([...availableIds]);
189-
}
190-
);
191196
endpoints.push(
192-
"api/price_feed_ids"
197+
"api/latest_price_feeds?ids[]=<price_feed_id>&ids[]=<price_feed_id_2>&..&verbose=true"
193198
);
194199

200+
app.get("/api/price_feed_ids", (req: Request, res: Response) => {
201+
const availableIds = this.priceFeedVaaInfo.getPriceIds();
202+
res.json([...availableIds]);
203+
});
204+
endpoints.push("api/price_feed_ids");
205+
195206
app.get("/ready", (_, res: Response) => {
196207
if (this.isReady!()) {
197208
res.sendStatus(StatusCodes.OK);

0 commit comments

Comments
 (0)