Friktion
Search…
Code to read Oracle Price
Typescript on how to read Pyth oracle prices and calculate TWAp
Here is a snippet of code in typescript on how you can calculate a 30 minute TWAP of the Pyth oracle prices:
1
import { Cluster, clusterApiUrl, Connection, PublicKey } from '@solana/web3.js'
2
import { PythConnection } from './PythConnection'
3
import { getPythProgramKeyForCluster } from './cluster'
4
import { PriceStatus, Product, PriceData, Price} from '.'
5
import { readFileSync } from 'fs';
6
​
7
const SOLANA_CLUSTER_NAME: Cluster = 'mainnet-beta'
8
const connection = new Connection(clusterApiUrl(SOLANA_CLUSTER_NAME))
9
const pythPublicKey = getPythProgramKeyForCluster(SOLANA_CLUSTER_NAME)
10
​
11
const pythConnection = new PythConnection(connection, pythPublicKey)
12
​
13
var END_TIMESTAMP = Date.now();
14
var day = 0;
15
if (new Date(END_TIMESTAMP).getUTCDay() == 4) {
16
day = 4;
17
}
18
else {
19
day = 5;
20
}
21
END_TIMESTAMP = new Date(new Date(END_TIMESTAMP).setDate(new Date(END_TIMESTAMP).getUTCDate() + (((day + 7 - new Date(END_TIMESTAMP).getUTCDay()) % 7) || 7))).setUTCHours(0, 0, 0, 0) + 2 * 60 * 60 * 1000;
22
​
23
console.log(END_TIMESTAMP);
24
const WINDOW_TIME = 60 * 60 * 1000 ;
25
​
26
export type PriceEntry = {
27
timestamp: number;
28
priceData: PriceData;
29
}
30
​
31
export class PythTwap {
32
symbol: string;
33
latestTimestamp: number;
34
windowLength: number;
35
data: PriceEntry[];
36
​
37
constructor(
38
symbol: string,
39
windowLength: number
40
) {
41
this.symbol = symbol;
42
this.windowLength = windowLength;
43
this.latestTimestamp = 0;
44
this.data = [];
45
}
46
​
47
process_data(price: PriceData , latestTimestamp: number) {
48
if (price == null) {
49
return;
50
}
51
if (!this.check_valid(price)) {
52
return;
53
}
54
this.latestTimestamp = latestTimestamp;
55
this.data.push({timestamp: latestTimestamp, priceData: price});
56
}
57
​
58
check_valid(price: PriceData): boolean {
59
if (price == null || price.price == null || price.confidence == null) {
60
return false;
61
}
62
else if (price.price <= 0) {
63
return false;
64
}
65
else if (price.confidence/price.price > 0.25) {
66
return false;
67
}
68
return true;
69
}
70
​
71
calc_twap(): [number, number] {
72
const threshold = this.latestTimestamp - this.windowLength;
73
const prices = this.data.filter((obj) => (obj.timestamp > threshold) && obj.priceData.price !== undefined && obj.priceData.price !== null)
74
const twap = prices.reduce((a: number, b: PriceEntry) => a + b.priceData.price!, 0)/prices.length;
75
return [twap, prices.length];
76
}
77
}
78
​
79
async function checkEnd(Oracles: Map<string, PythTwap>) {
80
const time = Date.now();
81
if (time > END_TIMESTAMP) {
82
pythConnection.stop();
83
console.log("Twap Calcuation Over. Stopping...");
84
Oracles.forEach((oracle, symbol) => console.log(time, symbol, oracle.calc_twap()));
85
return true;
86
}
87
return false;
88
}
89
​
90
async function checkEndTime(Oracles: Map<string, PythTwap>) {
91
const timeout = (time: number) => new Promise(resolve => setTimeout(resolve, time));
92
while (true) {
93
const shouldStop = await timeout(15 * 1000).then(() => checkEnd(Oracles));
94
if (shouldStop) {
95
return process.exit(0);
96
}
97
}
98
}
99
​
100
function main() {
101
const file = readFileSync('./oracle_symbols.txt', 'utf-8');
102
const symbols: string[] = file.split("\n");
103
const Oracles = new Map<string, PythTwap>();
104
symbols.forEach((symbol) => Oracles.set(symbol, new PythTwap(symbol, WINDOW_TIME)));
105
​
106
console.log(symbols);
107
console.log("End Timestamp: ", END_TIMESTAMP);
108
console.log("TWAP Length: ", WINDOW_TIME/1000/1000/60);
109
​
110
pythConnection.onPriceChange((product, price) => {
111
// sample output:
112
// SRM/USD: $8.68725 Β±$0.0131
113
if (price.price && price.confidence) {
114
// tslint:disable-next-line:no-console
115
const parsed_symbol = product.symbol.split(".")[1].split("/")[0];
116
const time = Date.now();
117
Oracles.get(parsed_symbol)?.process_data(price, time);
118
console.log(`${time} ${parsed_symbol} ${price.price} ${price.confidence}`);
119
}
120
});
121
​
122
console.log('Reading from Pyth price feed...')
123
pythConnection.start();
124
checkEndTime(Oracles);
125
}
126
​
127
main()
Copied!
Copy link