add binary query string to /latest_price_feeds (#445)

* add binary query string to /latest_price_feeds

* fix precommit

* fix both rest and ws tests

* bump package version

* fix tests to use the latest schema
This commit is contained in:
Daniel Chew 2023-01-02 17:38:52 +09:00 committed by GitHub
parent cdf99f4c60
commit 378e99b345
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 26 deletions

View File

@ -1,12 +1,12 @@
{
"name": "@pythnetwork/pyth-price-service",
"version": "2.2.3",
"version": "2.2.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@pythnetwork/pyth-price-service",
"version": "2.2.3",
"version": "2.2.4",
"license": "Apache-2.0",
"dependencies": {
"@certusone/wormhole-sdk": "^0.1.4",

View File

@ -1,6 +1,6 @@
{
"name": "@pythnetwork/pyth-price-service",
"version": "2.2.3",
"version": "2.2.4",
"description": "Pyth Price Service",
"main": "index.js",
"scripts": {

View File

@ -1,9 +1,9 @@
import { HexString, PriceFeed, Price } from "@pythnetwork/pyth-sdk-js";
import { PriceStore, PriceInfo } from "../listen";
import { RestAPI } from "../rest";
import { HexString, Price, PriceFeed } from "@pythnetwork/pyth-sdk-js";
import { Express } from "express";
import request from "supertest";
import { StatusCodes } from "http-status-codes";
import request from "supertest";
import { PriceInfo, PriceStore } from "../listen";
import { RestAPI } from "../rest";
let app: Express;
let priceInfoMap: Map<string, PriceInfo>;
@ -82,6 +82,23 @@ describe("Latest Price Feed Endpoint", () => {
expect(resp.body).toContainEqual(dummyPriceFeed(ids[1]).toJson());
});
test("When called with valid ids and binary flag set to true, returns correct price feed with binary vaa", async () => {
const ids = [expandTo64Len("abcd"), expandTo64Len("3456")];
const resp = await request(app)
.get("/api/latest_price_feeds")
.query({ ids, binary: true });
expect(resp.status).toBe(StatusCodes.OK);
expect(resp.body.length).toBe(2);
expect(resp.body).toContainEqual({
...priceInfoMap.get(ids[0])!.priceFeed.toJson(),
vaa: priceInfoMap.get(ids[0])!.vaa.toString("base64"),
});
expect(resp.body).toContainEqual({
...priceInfoMap.get(ids[1])!.priceFeed.toJson(),
vaa: priceInfoMap.get(ids[1])!.vaa.toString("base64"),
});
});
test("When called with some non-existent ids within ids, returns error mentioning non-existent ids", async () => {
const ids = [
expandTo64Len("ab01"),

View File

@ -1,4 +1,4 @@
import { HexString, PriceFeed } from "@pythnetwork/pyth-sdk-js";
import { HexString, Price, PriceFeed } from "@pythnetwork/pyth-sdk-js";
import { Server } from "http";
import { WebSocket, WebSocketServer } from "ws";
import { sleep } from "../helpers";
@ -49,20 +49,20 @@ function dummyPriceInfo(
}
function dummyPriceFeed(id: string): PriceFeed {
return PriceFeed.fromJson({
ema_price: {
return new PriceFeed({
emaPrice: new Price({
conf: "1",
expo: 2,
price: "3",
publish_time: 4,
},
publishTime: 4,
}),
id,
price: {
price: new Price({
conf: "5",
expo: 6,
price: "7",
publish_time: 8,
},
publishTime: 8,
}),
});
}
@ -273,7 +273,10 @@ describe("Client receives data", () => {
expect(serverMessages[1]).toEqual({
type: "price_update",
price_feed: priceInfos[0].priceFeed.toJson(),
price_feed: {
...priceInfos[0].priceFeed.toJson(),
vaa: priceInfos[0].vaa.toString("base64"),
},
});
api.dispatchPriceFeedUpdate(priceInfos[1]);

View File

@ -1,15 +1,14 @@
import { HexString } from "@pythnetwork/pyth-sdk-js";
import cors from "cors";
import express, { NextFunction, Request, Response } from "express";
import { Joi, schema, validate, ValidationError } from "express-validation";
import { Server } from "http";
import { StatusCodes } from "http-status-codes";
import morgan from "morgan";
import responseTime from "response-time";
import { DurationInMs, DurationInSec, TimestampInSec } from "./helpers";
import { TimestampInSec } from "./helpers";
import { PriceStore } from "./listen";
import { logger } from "./logging";
import { PromClient } from "./promClient";
import { HexString } from "@pythnetwork/pyth-sdk-js";
const MORGAN_LOG_FORMAT =
':remote-addr - :remote-user ":method :url HTTP/:http-version"' +
@ -120,6 +119,7 @@ export class RestAPI {
.items(Joi.string().regex(/^(0x)?[a-f0-9]{64}$/))
.required(),
verbose: Joi.boolean(),
binary: Joi.boolean(),
}).required(),
};
app.get(
@ -129,6 +129,8 @@ export class RestAPI {
const priceIds = req.query.ids as string[];
// verbose is optional, default to false
const verbose = req.query.verbose === "true";
// binary is optional, default to false
const binary = req.query.binary === "true";
const responseJson = [];
@ -146,9 +148,9 @@ export class RestAPI {
continue;
}
if (verbose) {
responseJson.push({
...latestPriceInfo.priceFeed.toJson(),
responseJson.push({
...latestPriceInfo.priceFeed.toJson(),
...(verbose && {
metadata: {
emitter_chain: latestPriceInfo.emitterChainId,
attestation_time: latestPriceInfo.attestationTime,
@ -156,10 +158,11 @@ export class RestAPI {
price_service_receive_time:
latestPriceInfo.priceServiceReceiveTime,
},
});
} else {
responseJson.push(latestPriceInfo.priceFeed.toJson());
}
}),
...(binary && {
vaa: latestPriceInfo.vaa.toString("base64"),
}),
});
}
if (notFoundIds.length > 0) {
@ -175,6 +178,9 @@ export class RestAPI {
endpoints.push(
"api/latest_price_feeds?ids[]=<price_feed_id>&ids[]=<price_feed_id_2>&..&verbose=true"
);
endpoints.push(
"api/latest_price_feeds?ids[]=<price_feed_id>&ids[]=<price_feed_id_2>&..&verbose=true&binary=true"
);
app.get("/api/price_feed_ids", (req: Request, res: Response) => {
const availableIds = this.priceFeedVaaInfo.getPriceIds();