@typus/typus-sdk 1.9.4 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/utils/api/price.d.ts +7 -2
- package/dist/src/utils/api/price.js +92 -56
- package/dist/src/utils/pyth/constant.d.ts +3 -24
- package/dist/src/utils/pyth/constant.js +77 -191
- package/dist/src/utils/pyth/pythClient.d.ts +77 -19
- package/dist/src/utils/pyth/pythClient.js +263 -74
- package/package.json +4 -3
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
export declare function getPairPrices(pair: string, startTs: string, endTs: string): Promise<any>;
|
|
2
2
|
export declare function getLatestPrice(pair: string): Promise<string>;
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Fetch latest display prices for every mapped token.
|
|
5
|
+
* @param accessToken Optional Lazer JWT / API key; falls back to PYTH_LAZER_TOKEN env.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getPythLatestPrice(accessToken?: string): Promise<Map<string, number>>;
|
|
4
8
|
/**
|
|
5
9
|
* Fetch latest Pyth prices for the specified symbols.
|
|
6
10
|
* @param symbols Array of token symbols (e.g., ["BTC", "ETH"]) to fetch prices for.
|
|
11
|
+
* @param accessToken Optional Lazer JWT / API key; falls back to PYTH_LAZER_TOKEN env.
|
|
7
12
|
* @returns Map where keys are token symbols and values are their latest prices.
|
|
8
13
|
*/
|
|
9
|
-
export declare function getPythLatestPriceBySymbols(symbols: string[]): Promise<Map<string, number>>;
|
|
14
|
+
export declare function getPythLatestPriceBySymbols(symbols: string[], accessToken?: string): Promise<Map<string, number>>;
|
|
10
15
|
export declare function getLatestPriceUSD(): Promise<Map<string, number>>;
|
|
@@ -51,6 +51,15 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
51
51
|
}
|
|
52
52
|
return ar;
|
|
53
53
|
};
|
|
54
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
55
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
56
|
+
if (ar || !(i in from)) {
|
|
57
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
58
|
+
ar[i] = from[i];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
62
|
+
};
|
|
54
63
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
64
|
exports.getPairPrices = getPairPrices;
|
|
56
65
|
exports.getLatestPrice = getLatestPrice;
|
|
@@ -113,85 +122,112 @@ function getLatestPrice(pair) {
|
|
|
113
122
|
});
|
|
114
123
|
});
|
|
115
124
|
}
|
|
116
|
-
|
|
125
|
+
// Pyth Lazer (Pro) numeric feed ids for the display-price helpers below.
|
|
126
|
+
// hermes.pyth.network requires an API key from 2026-08-18 and no key form is
|
|
127
|
+
// browser-safe there, so these helpers fetch from the Lazer `/price` endpoint
|
|
128
|
+
// instead — it accepts the short-lived JWTs a browser can hold.
|
|
129
|
+
// - XAU is priced off XAUT/USD (feed 172): the metal-spot feed 346 is not
|
|
130
|
+
// entitled on our key, and one unentitled id 403s the whole batch.
|
|
131
|
+
// - USOIL / XAG / USDJPY are unentitled with no crypto proxy — dropped.
|
|
132
|
+
// - Several Sui-ecosystem feeds are inactive upstream as of 2026-07-20
|
|
133
|
+
// (TURBOS, SCA, AFSUI, NAVX, BUCK, VSUI, HASUI) and return no row until
|
|
134
|
+
// Pyth reactivates them.
|
|
135
|
+
var lazerDisplayIds = {
|
|
136
|
+
SUI: 11,
|
|
137
|
+
CETUS: 401,
|
|
138
|
+
USDC: 7,
|
|
139
|
+
BTC: 1,
|
|
140
|
+
ETH: 2,
|
|
141
|
+
SOL: 6,
|
|
142
|
+
TURBOS: 599,
|
|
143
|
+
APT: 28,
|
|
144
|
+
USDT: 8,
|
|
145
|
+
DOGE: 13,
|
|
146
|
+
INJ: 46,
|
|
147
|
+
SEI: 51,
|
|
148
|
+
JUP: 92,
|
|
149
|
+
SCA: 545,
|
|
150
|
+
AFSUI: 353,
|
|
151
|
+
NAVX: 509,
|
|
152
|
+
USDY: 276,
|
|
153
|
+
BUCK: 390,
|
|
154
|
+
VSUI: 622,
|
|
155
|
+
HASUI: 443,
|
|
156
|
+
AUSD: 367,
|
|
157
|
+
DEEP: 173,
|
|
158
|
+
BLUE: 381,
|
|
159
|
+
XAU: 172,
|
|
160
|
+
WAL: 624,
|
|
161
|
+
HYPE: 110,
|
|
162
|
+
XRP: 14,
|
|
163
|
+
HAEDAL: 648,
|
|
164
|
+
};
|
|
165
|
+
var LAZER_PRICE_URL = "https://pyth.dourolabs.app/v1/fixed_rate@1000ms/price";
|
|
166
|
+
function fetchLazerDisplayPrices(names, accessToken) {
|
|
117
167
|
return __awaiter(this, void 0, void 0, function () {
|
|
118
|
-
var
|
|
168
|
+
var entries, ids, timestamp, query, token, map, response, rows, priceById;
|
|
119
169
|
return __generator(this, function (_a) {
|
|
120
170
|
switch (_a.label) {
|
|
121
171
|
case 0:
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
172
|
+
entries = names.map(function (name) { return [name, lazerDisplayIds[name]]; }).filter(function (_a) {
|
|
173
|
+
var _b = __read(_a, 2), id = _b[1];
|
|
174
|
+
return id != null;
|
|
175
|
+
});
|
|
176
|
+
ids = __spreadArray([], __read(new Set(entries.map(function (_a) {
|
|
177
|
+
var _b = __read(_a, 2), id = _b[1];
|
|
178
|
+
return id;
|
|
179
|
+
}))), false);
|
|
180
|
+
timestamp = Math.floor((Date.now() - 2000) / 1000) * 1000000;
|
|
181
|
+
query = ids.map(function (id) { return "ids=".concat(id); }).join("&");
|
|
182
|
+
token = accessToken !== null && accessToken !== void 0 ? accessToken : process.env.PYTH_LAZER_TOKEN;
|
|
183
|
+
map = new Map();
|
|
184
|
+
return [4 /*yield*/, fetch("".concat(LAZER_PRICE_URL, "?").concat(query, "×tamp=").concat(timestamp), {
|
|
127
185
|
method: "GET",
|
|
128
|
-
headers: {
|
|
186
|
+
headers: token ? { Authorization: "Bearer ".concat(token) } : {},
|
|
129
187
|
})];
|
|
130
188
|
case 1:
|
|
131
189
|
response = _a.sent();
|
|
132
|
-
|
|
133
|
-
|
|
190
|
+
if (!response.ok) {
|
|
191
|
+
console.error("Failed to fetch Pyth prices: ".concat(response.status));
|
|
192
|
+
return [2 /*return*/, map];
|
|
193
|
+
}
|
|
134
194
|
return [4 /*yield*/, response.json()];
|
|
135
195
|
case 2:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
var
|
|
140
|
-
|
|
196
|
+
rows = _a.sent();
|
|
197
|
+
priceById = new Map(rows.map(function (r) { return [r.price_feed_id, r.price * Math.pow(10, r.exponent)]; }));
|
|
198
|
+
entries.forEach(function (_a) {
|
|
199
|
+
var _b = __read(_a, 2), name = _b[0], id = _b[1];
|
|
200
|
+
var price = priceById.get(id);
|
|
201
|
+
if (price != null) {
|
|
202
|
+
map.set(name, price);
|
|
203
|
+
}
|
|
141
204
|
});
|
|
142
205
|
return [2 /*return*/, map];
|
|
143
|
-
case 3: return [2 /*return*/];
|
|
144
206
|
}
|
|
145
207
|
});
|
|
146
208
|
});
|
|
147
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Fetch latest display prices for every mapped token.
|
|
212
|
+
* @param accessToken Optional Lazer JWT / API key; falls back to PYTH_LAZER_TOKEN env.
|
|
213
|
+
*/
|
|
214
|
+
function getPythLatestPrice(accessToken) {
|
|
215
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
216
|
+
return __generator(this, function (_a) {
|
|
217
|
+
return [2 /*return*/, fetchLazerDisplayPrices(Object.keys(lazerDisplayIds), accessToken)];
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
}
|
|
148
221
|
/**
|
|
149
222
|
* Fetch latest Pyth prices for the specified symbols.
|
|
150
223
|
* @param symbols Array of token symbols (e.g., ["BTC", "ETH"]) to fetch prices for.
|
|
224
|
+
* @param accessToken Optional Lazer JWT / API key; falls back to PYTH_LAZER_TOKEN env.
|
|
151
225
|
* @returns Map where keys are token symbols and values are their latest prices.
|
|
152
226
|
*/
|
|
153
|
-
function getPythLatestPriceBySymbols(symbols) {
|
|
227
|
+
function getPythLatestPriceBySymbols(symbols, accessToken) {
|
|
154
228
|
return __awaiter(this, void 0, void 0, function () {
|
|
155
|
-
var idsParam, apiUrlWithParams, response, map, data;
|
|
156
229
|
return __generator(this, function (_a) {
|
|
157
|
-
|
|
158
|
-
case 0:
|
|
159
|
-
idsParam = Object.entries(pythId)
|
|
160
|
-
.filter(function (_a) {
|
|
161
|
-
var _b = __read(_a, 2), id = _b[0], token = _b[1];
|
|
162
|
-
return symbols.includes(token);
|
|
163
|
-
})
|
|
164
|
-
.map(function (_a) {
|
|
165
|
-
var _b = __read(_a, 1), id = _b[0];
|
|
166
|
-
return "ids[]=".concat(id);
|
|
167
|
-
})
|
|
168
|
-
.join("&");
|
|
169
|
-
apiUrlWithParams = "https://hermes.pyth.network/api/latest_price_feeds?".concat(idsParam);
|
|
170
|
-
return [4 /*yield*/, fetch(apiUrlWithParams, {
|
|
171
|
-
method: "GET",
|
|
172
|
-
headers: { "Content-Type": "application/json" },
|
|
173
|
-
})];
|
|
174
|
-
case 1:
|
|
175
|
-
response = _a.sent();
|
|
176
|
-
map = new Map();
|
|
177
|
-
if (!response.ok) return [3 /*break*/, 3];
|
|
178
|
-
return [4 /*yield*/, response.json()];
|
|
179
|
-
case 2:
|
|
180
|
-
data = _a.sent();
|
|
181
|
-
data.forEach(function (p) {
|
|
182
|
-
var token = pythId[p.id];
|
|
183
|
-
// Convert price using exponent provided
|
|
184
|
-
var price = p.price.price / Math.pow(10, -p.price.expo);
|
|
185
|
-
if (symbols.includes(token)) {
|
|
186
|
-
map.set(token, price);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
return [3 /*break*/, 4];
|
|
190
|
-
case 3:
|
|
191
|
-
console.error("Failed to fetch Pyth prices: ".concat(response.status));
|
|
192
|
-
_a.label = 4;
|
|
193
|
-
case 4: return [2 /*return*/, map];
|
|
194
|
-
}
|
|
230
|
+
return [2 /*return*/, fetchLazerDisplayPrices(symbols, accessToken)];
|
|
195
231
|
});
|
|
196
232
|
});
|
|
197
233
|
}
|
|
@@ -1,29 +1,8 @@
|
|
|
1
1
|
import { TOKEN } from "../../../src/constants";
|
|
2
|
-
export declare const
|
|
3
|
-
|
|
4
|
-
[key in TOKEN]?: string;
|
|
5
|
-
};
|
|
6
|
-
TESTNET: {
|
|
7
|
-
[key in TOKEN]?: string;
|
|
8
|
-
};
|
|
2
|
+
export declare const feedIds: {
|
|
3
|
+
[key in TOKEN]: number;
|
|
9
4
|
};
|
|
10
|
-
export declare const
|
|
11
|
-
MAINNET: {
|
|
12
|
-
[key in TOKEN]?: string;
|
|
13
|
-
};
|
|
14
|
-
TESTNET: {
|
|
15
|
-
[key in TOKEN]?: string;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
export declare const wormholeStateId: {
|
|
19
|
-
MAINNET: string;
|
|
20
|
-
TESTNET: string;
|
|
21
|
-
};
|
|
22
|
-
export declare const pythStateId: {
|
|
23
|
-
MAINNET: string;
|
|
24
|
-
TESTNET: string;
|
|
25
|
-
};
|
|
26
|
-
export declare const endpoint: {
|
|
5
|
+
export declare const lazerStateId: {
|
|
27
6
|
MAINNET: string;
|
|
28
7
|
TESTNET: string;
|
|
29
8
|
};
|
|
@@ -1,195 +1,81 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
wUSDT: "0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588",
|
|
76
|
-
// DOGE: "0x31775e1d6897129e8a84eeba975778fb50015b88039e9bc140bbd839694ac0ae",
|
|
77
|
-
INJ: "0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3",
|
|
78
|
-
SEI: "0x95f1aef92c74670d40f1f37ee6fb158ffd6a0f8913b07b9e61087f9b7273b11c",
|
|
79
|
-
JUP: "0xe92860f24d56f9ba9894658202633062744556e98fb3e924b4a2694d82f05737",
|
|
80
|
-
SCA: "0xeacabc6304d11fc10a757f63286ef44415d8e91b7a1a525ae94a7ec9398b73f3",
|
|
81
|
-
AFSUI: "0xd213e2929116af56c3ce71a1acee874f1dd03f42567b552085fa9d8ce8ce7134",
|
|
82
|
-
NAVX: "0x946292ad3f481f36f5e558726cf4974e2a7a34598bf15d2abe3619e7b6a8db91",
|
|
83
|
-
USDY: "0xc222a1d2b89218c034b515e738b19ee268c105d8ede44d95b279f1c8bfbb68af",
|
|
84
|
-
BUCK: "0xed0899e3a021f1e59031ad365bb3014d78f9ba5556e263692d3508b9272daabf",
|
|
85
|
-
VSUI: "0xabb2661c87ecac9f93eade3dd089dbb6e9eb4083eba3b35371ee6f8fa1133752",
|
|
86
|
-
HASUI: "0xb675212df51f05b159e31e3047895778df9df1c870587102a06fc96100853361",
|
|
87
|
-
AUSD: "0xf1882d28af56a63960f0c313e6c76eab8f802f15e801ebfca223412b55375fe3",
|
|
88
|
-
FUD: "0x15f63843dcccf30510f48ff6e363f9ead3b0b05d7f7dde6e3890a7e9e4d83e4a",
|
|
89
|
-
DEEP: "0xe18bf5fa857d5ca8af1f6a458b26e853ecdc78fc2f3dc17f4821374ad94d8327",
|
|
90
|
-
BLUE: "0x64559fcff99ed360543d7f4778f4712d2dc5c303ec1ac98f084c88c647ff7689",
|
|
91
|
-
BLUB: "0xc171055a63e9b4c09e29cc018129379e0a8581512f6726f5bfe5429985773312",
|
|
92
|
-
HIPPO: "0x082736b80698caf1379f0ad10a637668ccd531a96133d1f5053df97bffd2933b",
|
|
93
|
-
STSUI: "0xda703fbee4d7ee09aba630ef809efd79d162202bdf976ae8258875207ebd5557",
|
|
94
|
-
NS: "0x65aca56071505735c09091deb8733fdeba265bd9723dd4fb326b5ffd6843b3a3",
|
|
95
|
-
WAL: "0xa6ba0195b5364be116059e401fb71484ed3400d4d9bfbdf46bd11eab4f9b7cea",
|
|
96
|
-
LBTC: "0x29448db25efe8c72afe3a3c0c0631337408bd3cbc5f09d3dab0754460a965dae",
|
|
97
|
-
JPY: "0x20a938f54b68f1f2ef18ea0328f6dd0747f8ea11486d22b021e83a900be89776",
|
|
98
|
-
XAU: "0x30a19158f5a54c0adf8fb7560627343f22a1bc852b89d56be1accdc5dbf96d0e",
|
|
99
|
-
XAG: "0x321ba4d608fa75ba76d6d73daa715abcbdeb9dba02257f05a1b59178b49f599b",
|
|
100
|
-
USOIL: "0x24d84a7ab973231e4394015ece17a2155174123be2f8e38c751e17fbd2fcedad",
|
|
101
|
-
TBTC: "0xed1b51d4fb17e8c8b54a0c5bdbd59b38a0304d032287eb38d907374f16b5f535",
|
|
102
|
-
BNB: "0xecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a",
|
|
103
|
-
xBTC: "0xfd5464ac394d347958864c8a93dc71f2be56a5943fefc459a0074dc314b415d8",
|
|
104
|
-
},
|
|
3
|
+
exports.lazerStateId = exports.feedIds = void 0;
|
|
4
|
+
// Pyth Lazer numeric feed IDs (u32). Source: https://docs.pyth.network/lazer/price-feed-ids
|
|
5
|
+
// Same-asset wrappers (wETH, sbETH, wSOL, wAPT, wUSDT, wUSDC, sbBTC) map to their
|
|
6
|
+
// underlying base/USD feed; LSTs and BTC derivatives (AFSUI, VSUI, HASUI, STSUI,
|
|
7
|
+
// LBTC, xBTC, TBTC, WBTC) use their own dedicated feeds, matching typus-rust.
|
|
8
|
+
// XAU is priced off Crypto.XAUT/USD 172 (24/7; spot 346 is market-hours gated).
|
|
9
|
+
exports.feedIds = {
|
|
10
|
+
// placeholder feed ID for Typus Index; not live on Pyth Lazer
|
|
11
|
+
TYPUS: 0,
|
|
12
|
+
FUD: 0,
|
|
13
|
+
BLUB: 0,
|
|
14
|
+
LIQ: 0,
|
|
15
|
+
MFUD: 0,
|
|
16
|
+
MBLUB: 0,
|
|
17
|
+
MLIQ: 0,
|
|
18
|
+
SPSUI: 0,
|
|
19
|
+
sSCA: 0,
|
|
20
|
+
TEXP: 0,
|
|
21
|
+
USD: 0,
|
|
22
|
+
sbBTC: 1,
|
|
23
|
+
WBTC: 103,
|
|
24
|
+
xBTC: 1598,
|
|
25
|
+
TBTC: 588,
|
|
26
|
+
LBTC: 468,
|
|
27
|
+
wETH: 2,
|
|
28
|
+
sbETH: 2,
|
|
29
|
+
wSOL: 6,
|
|
30
|
+
USDC: 7,
|
|
31
|
+
wUSDC: 7,
|
|
32
|
+
sbUSDT: 8,
|
|
33
|
+
wUSDT: 8,
|
|
34
|
+
SUI: 11,
|
|
35
|
+
AFSUI: 353,
|
|
36
|
+
VSUI: 622,
|
|
37
|
+
HASUI: 443,
|
|
38
|
+
STSUI: 736,
|
|
39
|
+
DOGE: 13,
|
|
40
|
+
XRP: 14,
|
|
41
|
+
BNB: 15,
|
|
42
|
+
wAPT: 28,
|
|
43
|
+
INJ: 46,
|
|
44
|
+
SEI: 51,
|
|
45
|
+
JUP: 92,
|
|
46
|
+
HYPE: 110,
|
|
47
|
+
DEEP: 173,
|
|
48
|
+
USDY: 276,
|
|
49
|
+
JPY: 340,
|
|
50
|
+
USOIL: 657,
|
|
51
|
+
XAG: 345,
|
|
52
|
+
XAU: 172,
|
|
53
|
+
AUSD: 367,
|
|
54
|
+
BLUE: 381,
|
|
55
|
+
BUCK: 390,
|
|
56
|
+
CETUS: 401,
|
|
57
|
+
HIPPO: 448,
|
|
58
|
+
NAVX: 509,
|
|
59
|
+
NS: 514,
|
|
60
|
+
SCA: 545,
|
|
61
|
+
TURBOS: 599,
|
|
62
|
+
WAL: 624,
|
|
63
|
+
HAEDAL: 648,
|
|
64
|
+
AAPLX: 1792,
|
|
65
|
+
COINX: 1796,
|
|
66
|
+
CRCLX: 1798,
|
|
67
|
+
GOOGLX: 1808,
|
|
68
|
+
HOODX: 1815,
|
|
69
|
+
METAX: 1824,
|
|
70
|
+
MSTRX: 1827,
|
|
71
|
+
NVDAX: 1833,
|
|
72
|
+
QQQX: 1837,
|
|
73
|
+
SPYX: 1843,
|
|
74
|
+
TSLAX: 1847,
|
|
105
75
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
WBTC: "0x9a62b4863bdeaabdc9500fce769cf7e72d5585eeb28a6d26e4cafadc13f76ab2",
|
|
112
|
-
wETH: "0x9193fd47f9a0ab99b6e365a464c8a9ae30e6150fc37ed2a89c1586631f6fc4ab",
|
|
113
|
-
sbETH: "0x9193fd47f9a0ab99b6e365a464c8a9ae30e6150fc37ed2a89c1586631f6fc4ab",
|
|
114
|
-
wSOL: "0x9d0d275efbd37d8a8855f6f2c761fa5983293dd8ce202ee5196626de8fcd4469",
|
|
115
|
-
wAPT: "0x7c5b7837c44a69b469325463ac0673ac1aa8435ff44ddb4191c9ae380463647f",
|
|
116
|
-
CETUS: "0x24c0247fb22457a719efac7f670cdc79be321b521460bd6bd2ccfa9f80713b14",
|
|
117
|
-
TURBOS: "0x442e52f04392b0dcb48c6aaf7940568acd510281021be9f9b3a449c559c79613",
|
|
118
|
-
SCA: "0xf6de1d3279a269a597d813cbaca59aa906543ab9a8c64e84a4722f1a20863985",
|
|
119
|
-
SEI: "0xde2dd2684b3ff808cebdfb23afbf8b6ac3822832029dae744f81d9eb44b5c9b8",
|
|
120
|
-
INJ: "0x353a36a5b3d6809b4cc349dca627e2775e1d19b6b9c86f0eabe138fd3d772023",
|
|
121
|
-
AFSUI: "0xd779885c5246357e24cbde7348f2d81f756d9650975c02d81346b15d8b557ebf",
|
|
122
|
-
NAVX: "0x5b117a6a2de70796bffe36495bad576b788a34c33ca0648bd57852ead3f41e32",
|
|
123
|
-
HASUI: "0x4c1d831576b60fec657e0c310943eff8c1f28197c552e57d1fefdc55edddb263",
|
|
124
|
-
VSUI: "0xf3bc79117acc3636d57778d9d0f83a871df1b7a53eb61fe893ff108d9664ec8b",
|
|
125
|
-
DEEP: "0x8c7f3a322b94cc69db2a2ac575cbd94bf5766113324c3a3eceac91e3e88a51ed",
|
|
126
|
-
BLUE: "0x5515a34fc610bba6b601575ed1d2535b2f9df1f339fd0d435fef487c1ee3df9c",
|
|
127
|
-
NS: "0xc6352e1ea55d7b5acc3ed690cc3cdf8007978071d7bfd6a189445018cfb366e0",
|
|
128
|
-
JUP: "0xb804ada6f77feb30a73fbed7fc53dc66ff25133dee0815109d4267e43b2e6bdd",
|
|
129
|
-
WAL: "0xeb7e669f74d976c0b99b6ef9801e3a77716a95f1a15754e0f1399ce3fb60973d",
|
|
130
|
-
LBTC: "0xeba15840ddf425dacb5ff0990334fc03d034487f4ad416280859b96bf2af89f8",
|
|
131
|
-
XAU: "0x5b36eb3c0935908082926c0c767a55b87a2a4eb3a45908785b41f9d5a11e4f7b",
|
|
132
|
-
XAG: "0xd5c5afce92e988bf0a0940d618443c36c31dd7f239a545982db3166e963c9aa4",
|
|
133
|
-
USOIL: "0x71e40a6e2af5a194e149a761ae11d43e987b9ecbee1834d65d61103721c72e02",
|
|
134
|
-
DOGE: "0xd59a5f5173424ba725a7d033d86f2eadf2745f87a908bd27e1d27339eff598ce",
|
|
135
|
-
HYPE: "0x1c047be615eaa5a87afa0e111b20a512dd6c0f4a1f0f691693cf852c1768f35d",
|
|
136
|
-
XRP: "0x93bfda25cb6b1653a9c769e8216014bd2c06997f3edb479566761fbf2abf6ac2",
|
|
137
|
-
xBTC: "0xa4b9db1866ee6e2a156e8c36fc66be0f68f232388ebb578c949c2c6beb50128b",
|
|
138
|
-
JPY: "0xde0e6088e7292f50738ecbdebd4502415d4f8de4cfe001918e29b3f4faf15baa",
|
|
139
|
-
BNB: "0x9c6e77f0ecfc46aac395e21c52ccb96518f85acacae743c5b47f4ca5e29826c3",
|
|
140
|
-
SPYX: "0x6a2d53a802faee96b26f5fa86d9ccf05d58008e4f32c95985d12edb60f5e23ea",
|
|
141
|
-
QQQX: "0xcce836357b028bd85e866320f194980125b58e6117a2e86a24ed5c154df1e799",
|
|
142
|
-
NVDAX: "0x1ccc57727035cc40a122cecd95f15240de4fb3f2acd5542c8f2109ebc47871a1",
|
|
143
|
-
TSLAX: "0x678fee0f8d449160f7df3a14db41d7318e917c3afae98eed434a87073cb80c6b",
|
|
144
|
-
AAPLX: "0x80c9fa9060e2682528a9b02e0facfd6c4816e1bb363bdc3c9a6e94224618e03d",
|
|
145
|
-
GOOGLX: "0xff0bda4e0c212f409b89c6c5714c1957f6a867eced1bcfde863bd074d2a0d54c",
|
|
146
|
-
METAX: "0x0cd398ea0262b504a946b3d4acde457a21bee9d41a27083ebf6ec19f99272155",
|
|
147
|
-
COINX: "0xf19da6da74181c159f3619cc50fdd4dcc62d15538c707175464968a14cbb0464",
|
|
148
|
-
CRCLX: "0x299b647faef2456b93155b5609ac5edc9ba18bb4f5f6a27383920a528b2ff052",
|
|
149
|
-
HOODX: "0x1f0a01610d47dfe0506bb4cfd903335bf2d148adc86459c06385b97309e51d2a",
|
|
150
|
-
MSTRX: "0xab35f27f1118959cbf82e5ab907808df40b25c16c5745c21a1af721a2e0a926e",
|
|
151
|
-
},
|
|
152
|
-
TESTNET: {
|
|
153
|
-
SUI: "0x1ebb295c789cc42b3b2a1606482cd1c7124076a0f5676718501fda8c7fd075a0",
|
|
154
|
-
CETUS: "0xb0ba78106259b7ceefd288edc5f65b65f8b7bca0816e61dae5136616aac7d3da",
|
|
155
|
-
USDC: "0x9c4dd4008297ffa5e480684b8100ec21cc934405ed9a25d4e4d7b6259aad9c81",
|
|
156
|
-
wUSDC: "0x9c4dd4008297ffa5e480684b8100ec21cc934405ed9a25d4e4d7b6259aad9c81",
|
|
157
|
-
WBTC: "0x72431a238277695d3f31e4425225a4462674ee6cceeea9d66447b210755fffba",
|
|
158
|
-
wETH: "0x4fde30cb8a5dc3cfee1c1c358fc66dc308408827efb217247c7ba54d76ccbee9",
|
|
159
|
-
sbETH: "0x4fde30cb8a5dc3cfee1c1c358fc66dc308408827efb217247c7ba54d76ccbee9",
|
|
160
|
-
wSOL: "0x33fbce1cad5ca155f2f5051430b23a694bc6e5de6df43e0f8aefe29f4a84336d",
|
|
161
|
-
TURBOS: "0xfe38289883c3afed692e5856f4896b3e094d4793e2ccf0a2715b890a718fa5c0",
|
|
162
|
-
wAPT: "0x9eeb8cb349d8e89fa9e6c94a97d6d30096f5b3c16bd50d9de96608f67a278c18",
|
|
163
|
-
wUSDT: "0x956fdcbf83a26c962319f7742f5728a0a7ce59c7f0cbe13c112b259e7ee953cd",
|
|
164
|
-
// DOGE: "0x17b358d730663caa888c8b621b9994a60af422cd83f32237c6b2a8b3230d71b9",
|
|
165
|
-
INJ: "0x459e2e0dd757715449fc1d36925f384446bf192c9f86a4ca02d587c82de51802",
|
|
166
|
-
SEI: "0xb3e7f40e8268fb2539a03b29c1b38366e061c3c8222f7ad4c8db998eb0a02f8d",
|
|
167
|
-
JUP: "0x23817c9edbbfbdef6add3800cd52751eff5bb0f7abd32e54a8f2225d6a6523d3",
|
|
168
|
-
SCA: "0xf96e3c4b7d74efbde9df5b669188421196e6164adf6fbaaa92903c42569807c8",
|
|
169
|
-
AFSUI: "0x6785a8c69da40c9435d41a2585cf92643d2ed2c5cd12938ecff28eaf54efadcd",
|
|
170
|
-
NAVX: "0x94905bdcaa656b0908aa8a3a42cf72b0e8e2e849f7d0a7e0e39bb9e1dc3c9cf6",
|
|
171
|
-
USDY: "0x1fec4ed70f870911948d93eb2abe6fa4a3a4b1e4633cf36c7e91adfb4af1733f",
|
|
172
|
-
BLUE: "0xcc9016bcfaf1839f1dd63b0929a0d62dfb93e84442fd5b4598552605e365b3ec",
|
|
173
|
-
BLUB: "0xdcd4cc5f06fac1ca72e8551ab1a2e847298afa6f19e370ad9891199a59d2c22e",
|
|
174
|
-
JPY: "0xd14cadaf54a926f701db021eceaa89b3d09363e1bce51bfcb2291a32a693f928",
|
|
175
|
-
XAU: "0x742d48ff1d7a45c91aee4ad4f0059396c28988f99074d4a191951ac086b90a5a",
|
|
176
|
-
XAG: "",
|
|
177
|
-
USOIL: "",
|
|
178
|
-
xBTC: "0xb6c3b17fdda1eaa847e62c8d36a8dada35b010bb340fdb5a16d556f0fa37e59b",
|
|
179
|
-
},
|
|
180
|
-
};
|
|
181
|
-
// Get the state IDs of the Pyth and Wormhole contracts from
|
|
182
|
-
// https://docs.pyth.network/price-feeds/contract-addresses/sui
|
|
183
|
-
exports.wormholeStateId = {
|
|
184
|
-
MAINNET: "0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c",
|
|
185
|
-
TESTNET: "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790",
|
|
186
|
-
};
|
|
187
|
-
exports.pythStateId = {
|
|
188
|
-
MAINNET: "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8",
|
|
189
|
-
TESTNET: "0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c",
|
|
190
|
-
};
|
|
191
|
-
// Get the Stable Hermes service URL from https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes
|
|
192
|
-
exports.endpoint = {
|
|
193
|
-
MAINNET: "https://hermes.pyth.network",
|
|
194
|
-
TESTNET: "https://hermes-beta.pyth.network",
|
|
76
|
+
// Pyth Lazer State object IDs on Sui.
|
|
77
|
+
// Source: https://docs.pyth.network/price-feeds/pro/contract-addresses
|
|
78
|
+
exports.lazerStateId = {
|
|
79
|
+
MAINNET: "0xd0db9c1e9212a98120384bf78d8b8c985d87b9ee6921dffcf9d1394062911573",
|
|
80
|
+
TESTNET: "0x7b570126bfdcc7f7b2b4028445d4ac1d35c41da498606a2b097c3973425698d3",
|
|
195
81
|
};
|
|
@@ -1,22 +1,80 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { PythLazerClient, Channel } from "@pythnetwork/pyth-lazer-sdk";
|
|
2
|
+
import { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
|
|
3
|
+
import { Transaction, type TransactionResult } from "@mysten/sui/transactions";
|
|
3
4
|
import { TOKEN } from "../../../src/constants";
|
|
4
|
-
|
|
5
|
-
export
|
|
5
|
+
export type MoveApiVersion = "v1" | "v2";
|
|
6
|
+
export interface PythLazerSuiClientOpts {
|
|
7
|
+
/**
|
|
8
|
+
* Long-lived-key source (WebSocket). Node-side crankers and scripts pass
|
|
9
|
+
* this. Do NOT use it in a browser — the key would ship in the bundle.
|
|
10
|
+
*/
|
|
11
|
+
lazer?: PythLazerClient;
|
|
12
|
+
/**
|
|
13
|
+
* Client-safe alternative: returns a short-lived Pyth JWT per call, and
|
|
14
|
+
* price fetches go over REST instead of the WS. The JWT is accepted on
|
|
15
|
+
* `POST /v1/latest_price` and `/v1/price` (verified against mainnet), and
|
|
16
|
+
* that host sends `access-control-allow-origin: *`, so the browser can call
|
|
17
|
+
* it directly. Takes precedence over `lazer` when both are supplied.
|
|
18
|
+
*/
|
|
19
|
+
getAccessToken?: () => string | Promise<string>;
|
|
20
|
+
restEndpoint?: string;
|
|
21
|
+
channel?: Channel;
|
|
22
|
+
/** Which Lazer Move API to call. See DEFAULT_MOVE_API. */
|
|
23
|
+
moveApiVersion?: MoveApiVersion;
|
|
24
|
+
sui: SuiJsonRpcClient;
|
|
6
25
|
network: "MAINNET" | "TESTNET";
|
|
7
|
-
|
|
8
|
-
|
|
26
|
+
lazerPackage: string;
|
|
27
|
+
oraclePackage: string;
|
|
28
|
+
oracleV2Id: string;
|
|
29
|
+
stateObjectId?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare class PythLazerSuiClient {
|
|
32
|
+
readonly lazer?: PythLazerClient;
|
|
33
|
+
readonly getAccessToken?: () => string | Promise<string>;
|
|
34
|
+
readonly restEndpoint: string;
|
|
35
|
+
readonly channel: Channel;
|
|
36
|
+
readonly moveApiVersion: MoveApiVersion;
|
|
37
|
+
readonly sui: SuiJsonRpcClient;
|
|
38
|
+
readonly network: "MAINNET" | "TESTNET";
|
|
39
|
+
readonly stateObjectId: string;
|
|
40
|
+
readonly lazerPackage: string;
|
|
41
|
+
readonly oraclePackage: string;
|
|
42
|
+
readonly oracleV2Id: string;
|
|
43
|
+
constructor(opts: PythLazerSuiClientOpts);
|
|
44
|
+
/** `_v2` suffix on the Lazer/oracle entries when on the v2 Move API. */
|
|
45
|
+
private get v();
|
|
46
|
+
/**
|
|
47
|
+
* Fetches a signed `leEcdsa` update over REST using a short-lived token.
|
|
48
|
+
* Mirrors typus-rust `lazer_ingestion::rest_client`.
|
|
49
|
+
*/
|
|
50
|
+
private fetchUpdateOverRest;
|
|
51
|
+
private resolveFeedIds;
|
|
52
|
+
private resolveTypeArgument;
|
|
53
|
+
/**
|
|
54
|
+
* Fetches a Pyth Lazer `leEcdsa` update covering every requested token, adds
|
|
55
|
+
* `pyth_lazer::parse_and_verify_le_ecdsa_update` to the PTB, and returns the
|
|
56
|
+
* verified `Update` argument for use in subsequent move calls.
|
|
57
|
+
*/
|
|
58
|
+
updatePythLazer(tx: Transaction, tokens: TOKEN[], timestamp?: number): Promise<TransactionResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Calls `oracle_v2::update_latest_price(oracle_v2, update, clock)`. A single
|
|
61
|
+
* call updates every feed in the verified update.
|
|
62
|
+
*/
|
|
63
|
+
updateOracleV2WithPythLazer(tx: Transaction, tokens: TOKEN[]): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Calls `oracle_v2::update_settle_price(oracle_v2, update, timestamp, clock)`.
|
|
66
|
+
* Authority-gated on-chain. `timestamp` is in seconds.
|
|
67
|
+
*/
|
|
68
|
+
updateOracleV2SettlePriceWithPythLazer(tx: Transaction, tokens: TOKEN[], timestamp: number): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Calls `oracle_v2::add_latest_price_new_token<TOKEN>(oracle_v2, feed_id, update, clock)`.
|
|
71
|
+
* One-shot initializer for a brand-new token in the oracle's `feed_id_map`.
|
|
72
|
+
*/
|
|
73
|
+
addLatestPriceNewToken(tx: Transaction, token: TOKEN, tokenTypeArgument?: string): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Calls `oracle_v2::add_settle_price_new_token<TOKEN>(oracle_v2, feed_id, update, timestamp, clock)`.
|
|
76
|
+
* `timestamp` (seconds) is forwarded to the Lazer fetch when supplied and
|
|
77
|
+
* passed on-chain; defaults to now, matching the freshness window.
|
|
78
|
+
*/
|
|
79
|
+
addSettlePriceNewToken(tx: Transaction, token: TOKEN, timestamp?: number, tokenTypeArgument?: string): Promise<void>;
|
|
9
80
|
}
|
|
10
|
-
export declare function createPythClient(provider: any, network: "MAINNET" | "TESTNET"): PythClient;
|
|
11
|
-
/**
|
|
12
|
-
* @returns priceInfoObjectIds
|
|
13
|
-
*/
|
|
14
|
-
export declare function updatePyth(pythClient: PythClient, tx: Transaction, tokens: TOKEN[], suiCoin?: Argument): Promise<ObjectId[]>;
|
|
15
|
-
export declare function updateOracleWithPythUsd(pythClient: PythClient, tx: Transaction, oraclePackage: string, baseToken: TOKEN): void;
|
|
16
|
-
/**
|
|
17
|
-
* Adds the necessary commands for updating the pyth price feeds to the transaction block.
|
|
18
|
-
* @param tx transaction block to add commands to
|
|
19
|
-
* @param updates array of price feed updates received from the price service
|
|
20
|
-
* @param feedIds array of feed ids to update (in hex format)
|
|
21
|
-
*/
|
|
22
|
-
export declare function updatePriceFeeds(pythClient: PythClient, tx: Transaction, updates: Buffer[], feedIds: HexString[], suiCoin?: Argument): Promise<ObjectId[]>;
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
2
13
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
14
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
15
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -36,81 +47,259 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
36
47
|
}
|
|
37
48
|
};
|
|
38
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
40
|
-
exports.updatePyth = updatePyth;
|
|
41
|
-
exports.updateOracleWithPythUsd = updateOracleWithPythUsd;
|
|
42
|
-
exports.updatePriceFeeds = updatePriceFeeds;
|
|
43
|
-
var pyth_sui_js_1 = require("@pythnetwork/pyth-sui-js");
|
|
44
|
-
var constant_1 = require("./constant");
|
|
50
|
+
exports.PythLazerSuiClient = void 0;
|
|
45
51
|
var constants_1 = require("../../../src/constants");
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
52
|
+
var constant_1 = require("./constant");
|
|
53
|
+
var DEFAULT_PROPERTIES = ["price", "emaPrice", "exponent", "feedUpdateTimestamp"];
|
|
54
|
+
// The mainnet oracle reads `fixed_rate@1000ms`, and that channel is only served
|
|
55
|
+
// by the Lazer *v2* Move API (`..._v2` entries) — the v1 entries are pinned to
|
|
56
|
+
// the 200ms channel. Changing one without the other aborts on-chain.
|
|
57
|
+
var DEFAULT_CHANNEL = "fixed_rate@1000ms";
|
|
58
|
+
var DEFAULT_MOVE_API = "v2";
|
|
59
|
+
// Signed (`leEcdsa`) payloads come from the legacy Lazer host, not the Pro `/v1`
|
|
60
|
+
// API — the Pro OpenAPI exposes no signed-payload route at all.
|
|
61
|
+
var DEFAULT_REST_ENDPOINT = "https://pyth-lazer-0.dourolabs.app";
|
|
62
|
+
/** Browser-safe: hex -> bytes without Node's Buffer. */
|
|
63
|
+
var hexToBytes = function (hex) {
|
|
64
|
+
var clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
65
|
+
if (clean.length % 2 !== 0) {
|
|
66
|
+
throw new Error("Pyth Lazer leEcdsa payload is not valid hex (odd length)");
|
|
67
|
+
}
|
|
68
|
+
var out = new Uint8Array(clean.length / 2);
|
|
69
|
+
for (var i = 0; i < out.length; i++) {
|
|
70
|
+
out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
};
|
|
74
|
+
var PythLazerSuiClient = /** @class */ (function () {
|
|
75
|
+
function PythLazerSuiClient(opts) {
|
|
76
|
+
var _a, _b, _c, _d;
|
|
77
|
+
this.lazer = opts.lazer;
|
|
78
|
+
this.getAccessToken = opts.getAccessToken;
|
|
79
|
+
// A missing price source is only fatal when a price is actually fetched
|
|
80
|
+
// — plenty of callers construct a client purely for read-only views.
|
|
81
|
+
this.restEndpoint = ((_a = opts.restEndpoint) !== null && _a !== void 0 ? _a : DEFAULT_REST_ENDPOINT).replace(/\/+$/, "");
|
|
82
|
+
this.channel = (_b = opts.channel) !== null && _b !== void 0 ? _b : DEFAULT_CHANNEL;
|
|
83
|
+
this.moveApiVersion = (_c = opts.moveApiVersion) !== null && _c !== void 0 ? _c : DEFAULT_MOVE_API;
|
|
84
|
+
this.sui = opts.sui;
|
|
85
|
+
this.network = opts.network;
|
|
86
|
+
this.lazerPackage = opts.lazerPackage;
|
|
87
|
+
this.oraclePackage = opts.oraclePackage;
|
|
88
|
+
this.oracleV2Id = opts.oracleV2Id;
|
|
89
|
+
this.stateObjectId = (_d = opts.stateObjectId) !== null && _d !== void 0 ? _d : constant_1.lazerStateId[opts.network];
|
|
90
|
+
if (!this.stateObjectId) {
|
|
91
|
+
throw new Error("No Pyth Lazer state object id mapped for ".concat(opts.network));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
Object.defineProperty(PythLazerSuiClient.prototype, "v", {
|
|
95
|
+
/** `_v2` suffix on the Lazer/oracle entries when on the v2 Move API. */
|
|
96
|
+
get: function () {
|
|
97
|
+
return this.moveApiVersion === "v2" ? "_v2" : "";
|
|
98
|
+
},
|
|
99
|
+
enumerable: false,
|
|
100
|
+
configurable: true
|
|
85
101
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return [4 /*yield*/,
|
|
112
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Fetches a signed `leEcdsa` update over REST using a short-lived token.
|
|
104
|
+
* Mirrors typus-rust `lazer_ingestion::rest_client`.
|
|
105
|
+
*/
|
|
106
|
+
PythLazerSuiClient.prototype.fetchUpdateOverRest = function (priceFeedIds, timestamp) {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
108
|
+
var token, path, res, _a, _b, _c;
|
|
109
|
+
return __generator(this, function (_d) {
|
|
110
|
+
switch (_d.label) {
|
|
111
|
+
case 0: return [4 /*yield*/, this.getAccessToken()];
|
|
112
|
+
case 1:
|
|
113
|
+
token = _d.sent();
|
|
114
|
+
path = timestamp ? "v1/price" : "v1/latest_price";
|
|
115
|
+
return [4 /*yield*/, fetch("".concat(this.restEndpoint, "/").concat(path), {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers: { Authorization: "Bearer ".concat(token), "Content-Type": "application/json" },
|
|
118
|
+
body: JSON.stringify(__assign({ priceFeedIds: priceFeedIds, properties: DEFAULT_PROPERTIES, formats: ["leEcdsa"], jsonBinaryEncoding: "hex", channel: this.channel }, (timestamp ? { timestamp: timestamp * 1000000 } : {}))),
|
|
119
|
+
})];
|
|
120
|
+
case 2:
|
|
121
|
+
res = _d.sent();
|
|
122
|
+
if (!!res.ok) return [3 /*break*/, 4];
|
|
123
|
+
_a = Error.bind;
|
|
124
|
+
_c = (_b = "Pyth Lazer ".concat(path, " ").concat(res.status, ": ")).concat;
|
|
125
|
+
return [4 /*yield*/, res.text()];
|
|
126
|
+
case 3: throw new (_a.apply(Error, [void 0, _c.apply(_b, [_d.sent()])]))();
|
|
127
|
+
case 4: return [4 /*yield*/, res.json()];
|
|
128
|
+
case 5: return [2 /*return*/, (_d.sent())];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
PythLazerSuiClient.prototype.resolveFeedIds = function (tokens) {
|
|
134
|
+
return tokens.map(function (token) {
|
|
135
|
+
var id = constant_1.feedIds[token];
|
|
136
|
+
if (id == null) {
|
|
137
|
+
throw new Error("No Pyth Lazer feed id mapped for token ".concat(token));
|
|
113
138
|
}
|
|
139
|
+
return id;
|
|
114
140
|
});
|
|
115
|
-
}
|
|
116
|
-
|
|
141
|
+
};
|
|
142
|
+
PythLazerSuiClient.prototype.resolveTypeArgument = function (token, override) {
|
|
143
|
+
var typeArg = override !== null && override !== void 0 ? override : constants_1.tokenType[this.network][token];
|
|
144
|
+
if (!typeArg) {
|
|
145
|
+
throw new Error("No coin type mapped for ".concat(token, " on ").concat(this.network));
|
|
146
|
+
}
|
|
147
|
+
return typeArg;
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Fetches a Pyth Lazer `leEcdsa` update covering every requested token, adds
|
|
151
|
+
* `pyth_lazer::parse_and_verify_le_ecdsa_update` to the PTB, and returns the
|
|
152
|
+
* verified `Update` argument for use in subsequent move calls.
|
|
153
|
+
*/
|
|
154
|
+
PythLazerSuiClient.prototype.updatePythLazer = function (tx, tokens, timestamp) {
|
|
155
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
156
|
+
var priceFeedIds, update, hex, u8array;
|
|
157
|
+
var _a;
|
|
158
|
+
return __generator(this, function (_b) {
|
|
159
|
+
switch (_b.label) {
|
|
160
|
+
case 0:
|
|
161
|
+
priceFeedIds = this.resolveFeedIds(tokens);
|
|
162
|
+
if (!this.lazer && !this.getAccessToken) {
|
|
163
|
+
throw new Error("PythLazerSuiClient needs either `lazer` (WS) or `getAccessToken` (REST) to fetch prices");
|
|
164
|
+
}
|
|
165
|
+
if (!this.getAccessToken) return [3 /*break*/, 2];
|
|
166
|
+
return [4 /*yield*/, this.fetchUpdateOverRest(priceFeedIds, timestamp)];
|
|
167
|
+
case 1:
|
|
168
|
+
update = _b.sent();
|
|
169
|
+
return [3 /*break*/, 6];
|
|
170
|
+
case 2:
|
|
171
|
+
if (!timestamp) return [3 /*break*/, 4];
|
|
172
|
+
return [4 /*yield*/, this.lazer.getPrice({
|
|
173
|
+
priceFeedIds: priceFeedIds,
|
|
174
|
+
properties: DEFAULT_PROPERTIES,
|
|
175
|
+
formats: ["leEcdsa"],
|
|
176
|
+
jsonBinaryEncoding: "hex",
|
|
177
|
+
channel: this.channel,
|
|
178
|
+
timestamp: timestamp * 1000000, // seconds -> nanoseconds
|
|
179
|
+
})];
|
|
180
|
+
case 3:
|
|
181
|
+
update = _b.sent();
|
|
182
|
+
return [3 /*break*/, 6];
|
|
183
|
+
case 4: return [4 /*yield*/, this.lazer.getLatestPrice({
|
|
184
|
+
priceFeedIds: priceFeedIds,
|
|
185
|
+
properties: DEFAULT_PROPERTIES,
|
|
186
|
+
formats: ["leEcdsa"],
|
|
187
|
+
jsonBinaryEncoding: "hex",
|
|
188
|
+
channel: this.channel,
|
|
189
|
+
})];
|
|
190
|
+
case 5:
|
|
191
|
+
update = _b.sent();
|
|
192
|
+
_b.label = 6;
|
|
193
|
+
case 6:
|
|
194
|
+
hex = (_a = update.leEcdsa) === null || _a === void 0 ? void 0 : _a.data;
|
|
195
|
+
if (!hex) {
|
|
196
|
+
throw new Error("Pyth Lazer getLatestPrice returned no leEcdsa payload");
|
|
197
|
+
}
|
|
198
|
+
u8array = hexToBytes(hex);
|
|
199
|
+
return [2 /*return*/, tx.moveCall({
|
|
200
|
+
target: "".concat(this.lazerPackage, "::pyth_lazer::parse_and_verify_le_ecdsa_update").concat(this.v),
|
|
201
|
+
arguments: [tx.object(this.stateObjectId), tx.object.clock(), tx.pure.vector("u8", u8array)],
|
|
202
|
+
})];
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Calls `oracle_v2::update_latest_price(oracle_v2, update, clock)`. A single
|
|
209
|
+
* call updates every feed in the verified update.
|
|
210
|
+
*/
|
|
211
|
+
PythLazerSuiClient.prototype.updateOracleV2WithPythLazer = function (tx, tokens) {
|
|
212
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
213
|
+
var verifiedUpdate;
|
|
214
|
+
return __generator(this, function (_a) {
|
|
215
|
+
switch (_a.label) {
|
|
216
|
+
case 0: return [4 /*yield*/, this.updatePythLazer(tx, tokens)];
|
|
217
|
+
case 1:
|
|
218
|
+
verifiedUpdate = _a.sent();
|
|
219
|
+
tx.moveCall({
|
|
220
|
+
target: "".concat(this.oraclePackage, "::oracle_v2::update_latest_price").concat(this.v),
|
|
221
|
+
typeArguments: [],
|
|
222
|
+
arguments: [tx.object(this.oracleV2Id), verifiedUpdate, tx.object("0x6")],
|
|
223
|
+
});
|
|
224
|
+
return [2 /*return*/];
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* Calls `oracle_v2::update_settle_price(oracle_v2, update, timestamp, clock)`.
|
|
231
|
+
* Authority-gated on-chain. `timestamp` is in seconds.
|
|
232
|
+
*/
|
|
233
|
+
PythLazerSuiClient.prototype.updateOracleV2SettlePriceWithPythLazer = function (tx, tokens, timestamp) {
|
|
234
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
235
|
+
var verifiedUpdate;
|
|
236
|
+
return __generator(this, function (_a) {
|
|
237
|
+
switch (_a.label) {
|
|
238
|
+
case 0: return [4 /*yield*/, this.updatePythLazer(tx, tokens, timestamp)];
|
|
239
|
+
case 1:
|
|
240
|
+
verifiedUpdate = _a.sent();
|
|
241
|
+
tx.moveCall({
|
|
242
|
+
target: "".concat(this.oraclePackage, "::oracle_v2::update_settle_price").concat(this.v),
|
|
243
|
+
typeArguments: [],
|
|
244
|
+
arguments: [tx.object(this.oracleV2Id), verifiedUpdate, tx.pure.u64(timestamp), tx.object("0x6")],
|
|
245
|
+
});
|
|
246
|
+
return [2 /*return*/];
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Calls `oracle_v2::add_latest_price_new_token<TOKEN>(oracle_v2, feed_id, update, clock)`.
|
|
253
|
+
* One-shot initializer for a brand-new token in the oracle's `feed_id_map`.
|
|
254
|
+
*/
|
|
255
|
+
PythLazerSuiClient.prototype.addLatestPriceNewToken = function (tx, token, tokenTypeArgument) {
|
|
256
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
257
|
+
var feedId, typeArg, verifiedUpdate;
|
|
258
|
+
return __generator(this, function (_a) {
|
|
259
|
+
switch (_a.label) {
|
|
260
|
+
case 0:
|
|
261
|
+
feedId = this.resolveFeedIds([token])[0];
|
|
262
|
+
typeArg = this.resolveTypeArgument(token, tokenTypeArgument);
|
|
263
|
+
return [4 /*yield*/, this.updatePythLazer(tx, [token])];
|
|
264
|
+
case 1:
|
|
265
|
+
verifiedUpdate = _a.sent();
|
|
266
|
+
tx.moveCall({
|
|
267
|
+
target: "".concat(this.oraclePackage, "::oracle_v2::add_latest_price_new_token").concat(this.v),
|
|
268
|
+
typeArguments: [typeArg],
|
|
269
|
+
arguments: [tx.object(this.oracleV2Id), tx.pure.u32(feedId), verifiedUpdate, tx.object("0x6")],
|
|
270
|
+
});
|
|
271
|
+
return [2 /*return*/];
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
};
|
|
276
|
+
/**
|
|
277
|
+
* Calls `oracle_v2::add_settle_price_new_token<TOKEN>(oracle_v2, feed_id, update, timestamp, clock)`.
|
|
278
|
+
* `timestamp` (seconds) is forwarded to the Lazer fetch when supplied and
|
|
279
|
+
* passed on-chain; defaults to now, matching the freshness window.
|
|
280
|
+
*/
|
|
281
|
+
PythLazerSuiClient.prototype.addSettlePriceNewToken = function (tx, token, timestamp, tokenTypeArgument) {
|
|
282
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
283
|
+
var feedId, typeArg, ts, verifiedUpdate;
|
|
284
|
+
return __generator(this, function (_a) {
|
|
285
|
+
switch (_a.label) {
|
|
286
|
+
case 0:
|
|
287
|
+
feedId = this.resolveFeedIds([token])[0];
|
|
288
|
+
typeArg = this.resolveTypeArgument(token, tokenTypeArgument);
|
|
289
|
+
ts = timestamp !== null && timestamp !== void 0 ? timestamp : Math.floor(Date.now() / 1000);
|
|
290
|
+
return [4 /*yield*/, this.updatePythLazer(tx, [token], timestamp)];
|
|
291
|
+
case 1:
|
|
292
|
+
verifiedUpdate = _a.sent();
|
|
293
|
+
tx.moveCall({
|
|
294
|
+
target: "".concat(this.oraclePackage, "::oracle_v2::add_settle_price_new_token").concat(this.v),
|
|
295
|
+
typeArguments: [typeArg],
|
|
296
|
+
arguments: [tx.object(this.oracleV2Id), tx.pure.u32(feedId), verifiedUpdate, tx.pure.u64(ts), tx.object("0x6")],
|
|
297
|
+
});
|
|
298
|
+
return [2 /*return*/];
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
return PythLazerSuiClient;
|
|
304
|
+
}());
|
|
305
|
+
exports.PythLazerSuiClient = PythLazerSuiClient;
|
package/package.json
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
"name": "@typus/typus-sdk",
|
|
3
3
|
"author": "Typus",
|
|
4
4
|
"description": "typus sdk",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.10.1",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@mysten/bcs": "2.0.3",
|
|
8
8
|
"@mysten/kiosk": "1.2.0",
|
|
9
9
|
"@mysten/sui": "2.13.2",
|
|
10
|
-
"@pythnetwork/pyth-
|
|
10
|
+
"@pythnetwork/pyth-lazer-sdk": "6.2.2",
|
|
11
|
+
"@pythnetwork/pyth-lazer-sui-js": "0.3.0",
|
|
11
12
|
"@shinami/clients": "0.10.0",
|
|
12
13
|
"bignumber.js": "^9.1.2",
|
|
13
14
|
"camelcase-keys-deep": "^0.1.0",
|
|
@@ -51,4 +52,4 @@
|
|
|
51
52
|
"url": "https://github.com/Typus-Lab/typus-sdk/issues"
|
|
52
53
|
},
|
|
53
54
|
"homepage": "https://github.com/Typus-Lab/typus-sdk#readme"
|
|
54
|
-
}
|
|
55
|
+
}
|