Skip to content
This repository was archived by the owner on Mar 14, 2024. It is now read-only.

Commit de9d497

Browse files
committed
add new optional metadata property to PriceFeed and test
1 parent 7fd8ae7 commit de9d497

File tree

4 files changed

+161
-12
lines changed

4 files changed

+161
-12
lines changed

src/__tests__/PriceFeed.test.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Price, PriceFeed, PriceStatus } from "../index";
1+
import { Price, PriceFeed, PriceFeedMetadata, PriceStatus } from "../index";
22

33
beforeAll(() => {
44
jest.useFakeTimers();
@@ -42,8 +42,7 @@ test("Parsing Price Feed works as expected", () => {
4242
new Price("1", 4, "10")
4343
);
4444
expect(priceFeed.getLatestAvailablePriceWithinDuration(5)).toBeUndefined();
45-
46-
expect(priceFeed.toJson()).toStrictEqual(data);
45+
expect(priceFeed.toJson()).toEqual(data);
4746
});
4847

4948
test("getCurrentPrice returns undefined if status is not Trading", () => {
@@ -99,3 +98,37 @@ test("getLatestAvailablePrice returns prevPrice when status is not Trading", ()
9998
);
10099
expect(priceFeed.getLatestAvailablePriceWithinDuration(10)).toBeUndefined();
101100
});
101+
102+
test("getMetadata returns PriceFeedMetadata as expected", () => {
103+
const data = {
104+
conf: "1",
105+
ema_conf: "2",
106+
ema_price: "3",
107+
expo: 4,
108+
id: "abcdef0123456789",
109+
max_num_publishers: 6,
110+
metadata: new PriceFeedMetadata({
111+
attestation_time: 7,
112+
emitter_chain: 8,
113+
sequence_number: 9,
114+
}),
115+
num_publishers: 10,
116+
prev_conf: "11",
117+
prev_price: "12",
118+
prev_publish_time: 13,
119+
price: "14",
120+
product_id: "0123456789abcdef",
121+
publish_time: 16,
122+
status: PriceStatus.Unknown,
123+
};
124+
125+
const priceFeed = PriceFeed.fromJson(data);
126+
127+
expect(priceFeed.getMetadata()).toStrictEqual(
128+
new PriceFeedMetadata({
129+
attestation_time: 7,
130+
emitter_chain: 8,
131+
sequence_number: 9,
132+
})
133+
);
134+
});

src/index.ts

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,36 @@ export enum PriceStatus {
5353
Unknown = "Unknown",
5454
}
5555

56+
/**
57+
* Metadata about the price
58+
*
59+
* Represents metadata of a price feed.
60+
*/
61+
export class PriceFeedMetadata {
62+
/**
63+
* Attestation time of the price
64+
*/
65+
attestation_time: number;
66+
/**
67+
* Chain of the emitter
68+
*/
69+
emitter_chain: number;
70+
/**
71+
* Sequence number of the price
72+
*/
73+
sequence_number: number;
74+
75+
constructor(metadata: {
76+
attestation_time: number;
77+
emitter_chain: number;
78+
sequence_number: number;
79+
}) {
80+
this.attestation_time = metadata.attestation_time;
81+
this.emitter_chain = metadata.emitter_chain;
82+
this.sequence_number = metadata.sequence_number;
83+
}
84+
}
85+
5686
/**
5787
* Pyth Price Feed
5888
*
@@ -84,6 +114,10 @@ export class PriceFeed {
84114
* Maximum number of allowed publishers that can contribute to a price.
85115
*/
86116
maxNumPublishers: number;
117+
/**
118+
* Metadata about the price
119+
*/
120+
metadata?: PriceFeedMetadata;
87121
/**
88122
* Number of publishers that made up current aggregate.
89123
*/
@@ -124,6 +158,7 @@ export class PriceFeed {
124158
expo: number;
125159
id: HexString;
126160
maxNumPublishers: number;
161+
metadata?: PriceFeedMetadata;
127162
numPublishers: number;
128163
prevConf: string;
129164
prevPrice: string;
@@ -139,6 +174,7 @@ export class PriceFeed {
139174
this.expo = rawValues.expo;
140175
this.id = rawValues.id;
141176
this.maxNumPublishers = rawValues.maxNumPublishers;
177+
this.metadata = rawValues.metadata;
142178
this.numPublishers = rawValues.numPublishers;
143179
this.prevConf = rawValues.prevConf;
144180
this.prevPrice = rawValues.prevPrice;
@@ -158,6 +194,7 @@ export class PriceFeed {
158194
expo: jsonFeed.expo,
159195
id: jsonFeed.id,
160196
maxNumPublishers: jsonFeed.max_num_publishers,
197+
metadata: jsonFeed.metadata,
161198
numPublishers: jsonFeed.num_publishers,
162199
prevConf: jsonFeed.prev_conf,
163200
prevPrice: jsonFeed.prev_price,
@@ -177,6 +214,7 @@ export class PriceFeed {
177214
expo: this.expo,
178215
id: this.id,
179216
max_num_publishers: this.maxNumPublishers,
217+
metadata: this.metadata,
180218
num_publishers: this.numPublishers,
181219
prev_conf: this.prevConf,
182220
prev_price: this.prevPrice,
@@ -186,6 +224,7 @@ export class PriceFeed {
186224
publish_time: this.publishTime,
187225
status: this.status,
188226
};
227+
// this is done to avoid sending undefined values to the server
189228
return Convert.priceFeedToJson(jsonFeed);
190229
}
191230

@@ -259,18 +298,33 @@ export class PriceFeed {
259298
* @returns a struct containing the latest available price, confidence interval and the exponent for
260299
* both numbers, or `undefined` if no price update occurred within `duration` seconds of the current time.
261300
*/
262-
getLatestAvailablePriceWithinDuration(duration: DurationInSeconds): Price | undefined {
301+
getLatestAvailablePriceWithinDuration(
302+
duration: DurationInSeconds
303+
): Price | undefined {
263304
const [price, timestamp] = this.getLatestAvailablePriceUnchecked();
264305

265306
const currentTime: UnixTimestamp = Math.floor(Date.now() / 1000);
266-
307+
267308
// This checks the absolute difference as a sanity check
268309
// for the cases that the system time is behind or price
269-
// feed timestamp happen to be in the future (a bug).
310+
// feed timestamp happen to be in the future (a bug).
270311
if (Math.abs(currentTime - timestamp) > duration) {
271312
return undefined;
272313
}
273314

274315
return price;
275316
}
317+
318+
/**
319+
* Get the price feed metadata.
320+
*
321+
* @returns a struct containing the attestation time, emitter chain, and the sequence number.
322+
* Returns `undefined` if metadata is currently unavailable.
323+
*/
324+
getMetadata(): PriceFeedMetadata | undefined {
325+
if (this.metadata === undefined) {
326+
return undefined;
327+
}
328+
return new PriceFeedMetadata(this.metadata);
329+
}
276330
}

src/schemas/PriceFeed.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ export interface PriceFeed {
3535
* Maximum number of allowed publishers that can contribute to a price.
3636
*/
3737
max_num_publishers: number;
38+
/**
39+
* Metadata about the price
40+
*/
41+
metadata?: PriceFeedMetadata;
3842
/**
3943
* Number of publishers that made up current aggregate.
4044
*/
@@ -69,6 +73,26 @@ export interface PriceFeed {
6973
status: PriceStatus;
7074
}
7175

76+
/**
77+
* Metadata about the price
78+
*
79+
* Represents metadata of a price feed.
80+
*/
81+
export interface PriceFeedMetadata {
82+
/**
83+
* Attestation time of the price
84+
*/
85+
attestation_time: number;
86+
/**
87+
* Chain of the emitter
88+
*/
89+
emitter_chain: number;
90+
/**
91+
* Sequence number of the price
92+
*/
93+
sequence_number: number;
94+
}
95+
7296
/**
7397
* Status of price (Trading is valid).
7498
*
@@ -249,6 +273,11 @@ const typeMap: any = {
249273
{ json: "expo", js: "expo", typ: 0 },
250274
{ json: "id", js: "id", typ: "" },
251275
{ json: "max_num_publishers", js: "max_num_publishers", typ: 0 },
276+
{
277+
json: "metadata",
278+
js: "metadata",
279+
typ: u(undefined, r("PriceFeedMetadata")),
280+
},
252281
{ json: "num_publishers", js: "num_publishers", typ: 0 },
253282
{ json: "prev_conf", js: "prev_conf", typ: "" },
254283
{ json: "prev_price", js: "prev_price", typ: "" },
@@ -260,5 +289,13 @@ const typeMap: any = {
260289
],
261290
"any"
262291
),
292+
PriceFeedMetadata: o(
293+
[
294+
{ json: "attestation_time", js: "attestation_time", typ: 0 },
295+
{ json: "emitter_chain", js: "emitter_chain", typ: 0 },
296+
{ json: "sequence_number", js: "sequence_number", typ: 0 },
297+
],
298+
"any"
299+
),
263300
PriceStatus: ["Auction", "Halted", "Trading", "Unknown"],
264301
};

src/schemas/price_feed.json

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@
9494
"$ref": "#/definitions/PriceStatus"
9595
}
9696
]
97+
},
98+
"metadata": {
99+
"description": "Metadata about the price",
100+
"allOf": [
101+
{
102+
"$ref": "#/definitions/PriceFeedMetadata"
103+
}
104+
]
97105
}
98106
},
99107
"definitions": {
@@ -103,12 +111,29 @@
103111
"PriceStatus": {
104112
"description": "Represents availability status of a price feed.",
105113
"type": "string",
106-
"enum": [
107-
"Unknown",
108-
"Trading",
109-
"Halted",
110-
"Auction"
111-
]
114+
"enum": ["Unknown", "Trading", "Halted", "Auction"]
115+
},
116+
"PriceFeedMetadata": {
117+
"description": "Represents metadata of a price feed.",
118+
"type": "object",
119+
"required": ["attestation_time", "emitter_chain", "sequence_number"],
120+
"properties": {
121+
"attestation_time": {
122+
"description": "Attestation time of the price",
123+
"type": "integer",
124+
"format": "int64"
125+
},
126+
"emitter_chain": {
127+
"description": "Chain of the emitter",
128+
"type": "integer",
129+
"format": "int16"
130+
},
131+
"sequence_number": {
132+
"description": "Sequence number of the price",
133+
"type": "integer",
134+
"format": "int64"
135+
}
136+
}
112137
}
113138
}
114139
}

0 commit comments

Comments
 (0)