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:
parent
cdf99f4c60
commit
378e99b345
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@pythnetwork/pyth-price-service",
|
"name": "@pythnetwork/pyth-price-service",
|
||||||
"version": "2.2.3",
|
"version": "2.2.4",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@pythnetwork/pyth-price-service",
|
"name": "@pythnetwork/pyth-price-service",
|
||||||
"version": "2.2.3",
|
"version": "2.2.4",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certusone/wormhole-sdk": "^0.1.4",
|
"@certusone/wormhole-sdk": "^0.1.4",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@pythnetwork/pyth-price-service",
|
"name": "@pythnetwork/pyth-price-service",
|
||||||
"version": "2.2.3",
|
"version": "2.2.4",
|
||||||
"description": "Pyth Price Service",
|
"description": "Pyth Price Service",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { HexString, PriceFeed, Price } from "@pythnetwork/pyth-sdk-js";
|
import { HexString, Price, PriceFeed } from "@pythnetwork/pyth-sdk-js";
|
||||||
import { PriceStore, PriceInfo } from "../listen";
|
|
||||||
import { RestAPI } from "../rest";
|
|
||||||
import { Express } from "express";
|
import { Express } from "express";
|
||||||
import request from "supertest";
|
|
||||||
import { StatusCodes } from "http-status-codes";
|
import { StatusCodes } from "http-status-codes";
|
||||||
|
import request from "supertest";
|
||||||
|
import { PriceInfo, PriceStore } from "../listen";
|
||||||
|
import { RestAPI } from "../rest";
|
||||||
|
|
||||||
let app: Express;
|
let app: Express;
|
||||||
let priceInfoMap: Map<string, PriceInfo>;
|
let priceInfoMap: Map<string, PriceInfo>;
|
||||||
|
@ -82,6 +82,23 @@ describe("Latest Price Feed Endpoint", () => {
|
||||||
expect(resp.body).toContainEqual(dummyPriceFeed(ids[1]).toJson());
|
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 () => {
|
test("When called with some non-existent ids within ids, returns error mentioning non-existent ids", async () => {
|
||||||
const ids = [
|
const ids = [
|
||||||
expandTo64Len("ab01"),
|
expandTo64Len("ab01"),
|
||||||
|
|
|
@ -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 { Server } from "http";
|
||||||
import { WebSocket, WebSocketServer } from "ws";
|
import { WebSocket, WebSocketServer } from "ws";
|
||||||
import { sleep } from "../helpers";
|
import { sleep } from "../helpers";
|
||||||
|
@ -49,20 +49,20 @@ function dummyPriceInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
function dummyPriceFeed(id: string): PriceFeed {
|
function dummyPriceFeed(id: string): PriceFeed {
|
||||||
return PriceFeed.fromJson({
|
return new PriceFeed({
|
||||||
ema_price: {
|
emaPrice: new Price({
|
||||||
conf: "1",
|
conf: "1",
|
||||||
expo: 2,
|
expo: 2,
|
||||||
price: "3",
|
price: "3",
|
||||||
publish_time: 4,
|
publishTime: 4,
|
||||||
},
|
}),
|
||||||
id,
|
id,
|
||||||
price: {
|
price: new Price({
|
||||||
conf: "5",
|
conf: "5",
|
||||||
expo: 6,
|
expo: 6,
|
||||||
price: "7",
|
price: "7",
|
||||||
publish_time: 8,
|
publishTime: 8,
|
||||||
},
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +273,10 @@ describe("Client receives data", () => {
|
||||||
|
|
||||||
expect(serverMessages[1]).toEqual({
|
expect(serverMessages[1]).toEqual({
|
||||||
type: "price_update",
|
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]);
|
api.dispatchPriceFeedUpdate(priceInfos[1]);
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
|
import { HexString } from "@pythnetwork/pyth-sdk-js";
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import express, { NextFunction, Request, Response } from "express";
|
import express, { NextFunction, Request, Response } from "express";
|
||||||
import { Joi, schema, validate, ValidationError } from "express-validation";
|
import { Joi, schema, validate, ValidationError } from "express-validation";
|
||||||
import { Server } from "http";
|
import { Server } from "http";
|
||||||
import { StatusCodes } from "http-status-codes";
|
import { StatusCodes } from "http-status-codes";
|
||||||
import morgan from "morgan";
|
import morgan from "morgan";
|
||||||
import responseTime from "response-time";
|
import { TimestampInSec } from "./helpers";
|
||||||
import { DurationInMs, DurationInSec, TimestampInSec } from "./helpers";
|
|
||||||
import { PriceStore } from "./listen";
|
import { PriceStore } from "./listen";
|
||||||
import { logger } from "./logging";
|
import { logger } from "./logging";
|
||||||
import { PromClient } from "./promClient";
|
import { PromClient } from "./promClient";
|
||||||
import { HexString } from "@pythnetwork/pyth-sdk-js";
|
|
||||||
|
|
||||||
const MORGAN_LOG_FORMAT =
|
const MORGAN_LOG_FORMAT =
|
||||||
':remote-addr - :remote-user ":method :url HTTP/:http-version"' +
|
':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}$/))
|
.items(Joi.string().regex(/^(0x)?[a-f0-9]{64}$/))
|
||||||
.required(),
|
.required(),
|
||||||
verbose: Joi.boolean(),
|
verbose: Joi.boolean(),
|
||||||
|
binary: Joi.boolean(),
|
||||||
}).required(),
|
}).required(),
|
||||||
};
|
};
|
||||||
app.get(
|
app.get(
|
||||||
|
@ -129,6 +129,8 @@ export class RestAPI {
|
||||||
const priceIds = req.query.ids as string[];
|
const priceIds = req.query.ids as string[];
|
||||||
// verbose is optional, default to false
|
// verbose is optional, default to false
|
||||||
const verbose = req.query.verbose === "true";
|
const verbose = req.query.verbose === "true";
|
||||||
|
// binary is optional, default to false
|
||||||
|
const binary = req.query.binary === "true";
|
||||||
|
|
||||||
const responseJson = [];
|
const responseJson = [];
|
||||||
|
|
||||||
|
@ -146,9 +148,9 @@ export class RestAPI {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
responseJson.push({
|
||||||
responseJson.push({
|
...latestPriceInfo.priceFeed.toJson(),
|
||||||
...latestPriceInfo.priceFeed.toJson(),
|
...(verbose && {
|
||||||
metadata: {
|
metadata: {
|
||||||
emitter_chain: latestPriceInfo.emitterChainId,
|
emitter_chain: latestPriceInfo.emitterChainId,
|
||||||
attestation_time: latestPriceInfo.attestationTime,
|
attestation_time: latestPriceInfo.attestationTime,
|
||||||
|
@ -156,10 +158,11 @@ export class RestAPI {
|
||||||
price_service_receive_time:
|
price_service_receive_time:
|
||||||
latestPriceInfo.priceServiceReceiveTime,
|
latestPriceInfo.priceServiceReceiveTime,
|
||||||
},
|
},
|
||||||
});
|
}),
|
||||||
} else {
|
...(binary && {
|
||||||
responseJson.push(latestPriceInfo.priceFeed.toJson());
|
vaa: latestPriceInfo.vaa.toString("base64"),
|
||||||
}
|
}),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notFoundIds.length > 0) {
|
if (notFoundIds.length > 0) {
|
||||||
|
@ -175,6 +178,9 @@ export class RestAPI {
|
||||||
endpoints.push(
|
endpoints.push(
|
||||||
"api/latest_price_feeds?ids[]=<price_feed_id>&ids[]=<price_feed_id_2>&..&verbose=true"
|
"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) => {
|
app.get("/api/price_feed_ids", (req: Request, res: Response) => {
|
||||||
const availableIds = this.priceFeedVaaInfo.getPriceIds();
|
const availableIds = this.priceFeedVaaInfo.getPriceIds();
|
||||||
|
|
Loading…
Reference in New Issue