@pythnetwork/price-service-client 1.9.1 → 1.10.0
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/PriceServiceConnection.cjs +310 -0
- package/{lib → dist}/PriceServiceConnection.d.ts +23 -23
- package/{lib/ResillientWebSocket.js → dist/ResillientWebSocket.cjs} +45 -52
- package/{lib → dist}/ResillientWebSocket.d.ts +2 -4
- package/dist/index.cjs +32 -0
- package/dist/index.d.ts +2 -0
- package/dist/package.json +1 -0
- package/dist/utils.cjs +27 -0
- package/{lib → dist}/utils.d.ts +2 -3
- package/package.json +34 -11
- package/lib/PriceServiceConnection.d.ts.map +0 -1
- package/lib/PriceServiceConnection.js +0 -314
- package/lib/ResillientWebSocket.d.ts.map +0 -1
- package/lib/examples/PriceServiceClient.d.ts +0 -2
- package/lib/examples/PriceServiceClient.d.ts.map +0 -1
- package/lib/examples/PriceServiceClient.js +0 -53
- package/lib/index.d.ts +0 -3
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -11
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js +0 -25
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable unicorn/no-process-exit */ /* eslint-disable n/no-process-exit */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable @typescript-eslint/no-base-to-string */ /* eslint-disable @typescript-eslint/no-floating-promises */ /* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable no-console */ /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ "use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "PriceServiceConnection", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return PriceServiceConnection;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _priceservicesdk = require("@pythnetwork/price-service-sdk");
|
|
12
|
+
const _axios = /*#__PURE__*/ _interop_require_default(require("axios"));
|
|
13
|
+
const _axiosretry = /*#__PURE__*/ _interop_require_default(require("axios-retry"));
|
|
14
|
+
const _ResillientWebSocket = require("./ResillientWebSocket.cjs");
|
|
15
|
+
const _utils = require("./utils.cjs");
|
|
16
|
+
function _interop_require_default(obj) {
|
|
17
|
+
return obj && obj.__esModule ? obj : {
|
|
18
|
+
default: obj
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
class PriceServiceConnection {
|
|
22
|
+
httpClient;
|
|
23
|
+
priceFeedCallbacks;
|
|
24
|
+
wsClient;
|
|
25
|
+
wsEndpoint;
|
|
26
|
+
logger;
|
|
27
|
+
priceFeedRequestConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Custom handler for web socket errors (connection and message parsing).
|
|
30
|
+
*
|
|
31
|
+
* Default handler only logs the errors.
|
|
32
|
+
*/ onWsError;
|
|
33
|
+
/**
|
|
34
|
+
* Constructs a new Connection.
|
|
35
|
+
*
|
|
36
|
+
* @param endpoint - endpoint URL to the price service. Example: https://website/example/
|
|
37
|
+
* @param config - Optional PriceServiceConnectionConfig for custom configurations.
|
|
38
|
+
*/ constructor(endpoint, config){
|
|
39
|
+
this.httpClient = _axios.default.create({
|
|
40
|
+
baseURL: endpoint,
|
|
41
|
+
timeout: config?.timeout || 5000
|
|
42
|
+
});
|
|
43
|
+
(0, _axiosretry.default)(this.httpClient, {
|
|
44
|
+
retries: config?.httpRetries || 3,
|
|
45
|
+
// eslint-disable-next-line import/no-named-as-default-member
|
|
46
|
+
retryDelay: _axiosretry.default.exponentialDelay.bind(_axiosretry.default)
|
|
47
|
+
});
|
|
48
|
+
this.priceFeedRequestConfig = {
|
|
49
|
+
binary: config?.priceFeedRequestConfig?.binary,
|
|
50
|
+
verbose: config?.priceFeedRequestConfig?.verbose ?? config?.verbose,
|
|
51
|
+
allowOutOfOrder: config?.priceFeedRequestConfig?.allowOutOfOrder
|
|
52
|
+
};
|
|
53
|
+
this.priceFeedCallbacks = new Map();
|
|
54
|
+
// Default logger is console for only warnings and errors.
|
|
55
|
+
this.logger = config?.logger || {
|
|
56
|
+
trace: ()=>{},
|
|
57
|
+
debug: ()=>{},
|
|
58
|
+
info: ()=>{},
|
|
59
|
+
warn: console.warn,
|
|
60
|
+
error: console.error
|
|
61
|
+
};
|
|
62
|
+
this.onWsError = (error)=>{
|
|
63
|
+
this.logger.error(error);
|
|
64
|
+
// Exit the process if it is running in node.
|
|
65
|
+
if (typeof process !== "undefined" && typeof process.exit === "function") {
|
|
66
|
+
this.logger.error("Halting the process due to the websocket error");
|
|
67
|
+
process.exit(1);
|
|
68
|
+
} else {
|
|
69
|
+
this.logger.error("Cannot halt process. Please handle the websocket error.");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
this.wsEndpoint = (0, _utils.makeWebsocketUrl)(endpoint);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Fetch Latest PriceFeeds of given price ids.
|
|
76
|
+
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price ids)
|
|
77
|
+
*
|
|
78
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
79
|
+
* @returns Array of PriceFeeds
|
|
80
|
+
*/ async getLatestPriceFeeds(priceIds) {
|
|
81
|
+
if (priceIds.length === 0) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const response = await this.httpClient.get("/api/latest_price_feeds", {
|
|
85
|
+
params: {
|
|
86
|
+
ids: priceIds,
|
|
87
|
+
verbose: this.priceFeedRequestConfig.verbose,
|
|
88
|
+
binary: this.priceFeedRequestConfig.binary
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const priceFeedsJson = response.data;
|
|
92
|
+
return priceFeedsJson.map((priceFeedJson)=>_priceservicesdk.PriceFeed.fromJson(priceFeedJson));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Fetch latest VAA of given price ids.
|
|
96
|
+
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price ids)
|
|
97
|
+
*
|
|
98
|
+
* This function is coupled to wormhole implemntation.
|
|
99
|
+
*
|
|
100
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
101
|
+
* @returns Array of base64 encoded VAAs.
|
|
102
|
+
*/ async getLatestVaas(priceIds) {
|
|
103
|
+
const response = await this.httpClient.get("/api/latest_vaas", {
|
|
104
|
+
params: {
|
|
105
|
+
ids: priceIds
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return response.data;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Fetch the earliest VAA of the given price id that is published since the given publish time.
|
|
112
|
+
* This will throw an error if the given publish time is in the future, or if the publish time
|
|
113
|
+
* is old and the price service endpoint does not have a db backend for historical requests.
|
|
114
|
+
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price id)
|
|
115
|
+
*
|
|
116
|
+
* This function is coupled to wormhole implemntation.
|
|
117
|
+
*
|
|
118
|
+
* @param priceId - Hex-encoded price id.
|
|
119
|
+
* @param publishTime - Epoch timestamp in seconds.
|
|
120
|
+
* @returns Tuple of VAA and publishTime.
|
|
121
|
+
*/ async getVaa(priceId, publishTime) {
|
|
122
|
+
const response = await this.httpClient.get("/api/get_vaa", {
|
|
123
|
+
params: {
|
|
124
|
+
id: priceId,
|
|
125
|
+
publish_time: publishTime
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return [
|
|
129
|
+
response.data.vaa,
|
|
130
|
+
response.data.publishTime
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Fetch the PriceFeed of the given price id that is published since the given publish time.
|
|
135
|
+
* This will throw an error if the given publish time is in the future, or if the publish time
|
|
136
|
+
* is old and the price service endpoint does not have a db backend for historical requests.
|
|
137
|
+
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price id)
|
|
138
|
+
*
|
|
139
|
+
* @param priceId - Hex-encoded price id.
|
|
140
|
+
* @param publishTime - Epoch timestamp in seconds.
|
|
141
|
+
* @returns PriceFeed
|
|
142
|
+
*/ async getPriceFeed(priceId, publishTime) {
|
|
143
|
+
const response = await this.httpClient.get("/api/get_price_feed", {
|
|
144
|
+
params: {
|
|
145
|
+
id: priceId,
|
|
146
|
+
publish_time: publishTime,
|
|
147
|
+
verbose: this.priceFeedRequestConfig.verbose,
|
|
148
|
+
binary: this.priceFeedRequestConfig.binary
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
return _priceservicesdk.PriceFeed.fromJson(response.data);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Fetch the list of available price feed ids.
|
|
155
|
+
* This will throw an axios error if there is a network problem or the price service returns a non-ok response.
|
|
156
|
+
*
|
|
157
|
+
* @returns Array of hex-encoded price ids.
|
|
158
|
+
*/ async getPriceFeedIds() {
|
|
159
|
+
const response = await this.httpClient.get("/api/price_feed_ids");
|
|
160
|
+
return response.data;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Subscribe to updates for given price ids.
|
|
164
|
+
*
|
|
165
|
+
* It will start a websocket connection if it's not started yet.
|
|
166
|
+
* Also, it won't throw any exception if given price ids are invalid or connection errors. Instead,
|
|
167
|
+
* it calls `connection.onWsError`. If you want to handle the errors you should set the
|
|
168
|
+
* `onWsError` function to your custom error handler.
|
|
169
|
+
*
|
|
170
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
171
|
+
* @param cb - Callback function that is called with a PriceFeed upon updates to given price ids.
|
|
172
|
+
*/ async subscribePriceFeedUpdates(priceIds, cb) {
|
|
173
|
+
if (this.wsClient === undefined) {
|
|
174
|
+
await this.startWebSocket();
|
|
175
|
+
}
|
|
176
|
+
priceIds = priceIds.map((priceId)=>(0, _utils.removeLeading0xIfExists)(priceId));
|
|
177
|
+
const newPriceIds = [];
|
|
178
|
+
for (const id of priceIds){
|
|
179
|
+
if (!this.priceFeedCallbacks.has(id)) {
|
|
180
|
+
this.priceFeedCallbacks.set(id, new Set());
|
|
181
|
+
newPriceIds.push(id);
|
|
182
|
+
}
|
|
183
|
+
this.priceFeedCallbacks.get(id).add(cb);
|
|
184
|
+
}
|
|
185
|
+
const message = {
|
|
186
|
+
ids: newPriceIds,
|
|
187
|
+
type: "subscribe",
|
|
188
|
+
verbose: this.priceFeedRequestConfig.verbose,
|
|
189
|
+
binary: this.priceFeedRequestConfig.binary,
|
|
190
|
+
allow_out_of_order: this.priceFeedRequestConfig.allowOutOfOrder
|
|
191
|
+
};
|
|
192
|
+
await this.wsClient?.send(JSON.stringify(message));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Unsubscribe from updates for given price ids.
|
|
196
|
+
*
|
|
197
|
+
* It will close the websocket connection if it's not subscribed to any price feed updates anymore.
|
|
198
|
+
* Also, it won't throw any exception if given price ids are invalid or connection errors. Instead,
|
|
199
|
+
* it calls `connection.onWsError`. If you want to handle the errors you should set the
|
|
200
|
+
* `onWsError` function to your custom error handler.
|
|
201
|
+
*
|
|
202
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
203
|
+
* @param cb - Optional callback, if set it will only unsubscribe this callback from updates for given price ids.
|
|
204
|
+
*/ async unsubscribePriceFeedUpdates(priceIds, cb) {
|
|
205
|
+
if (this.wsClient === undefined) {
|
|
206
|
+
await this.startWebSocket();
|
|
207
|
+
}
|
|
208
|
+
priceIds = priceIds.map((priceId)=>(0, _utils.removeLeading0xIfExists)(priceId));
|
|
209
|
+
const removedPriceIds = [];
|
|
210
|
+
for (const id of priceIds){
|
|
211
|
+
if (this.priceFeedCallbacks.has(id)) {
|
|
212
|
+
let idRemoved = false;
|
|
213
|
+
if (cb === undefined) {
|
|
214
|
+
this.priceFeedCallbacks.delete(id);
|
|
215
|
+
idRemoved = true;
|
|
216
|
+
} else {
|
|
217
|
+
this.priceFeedCallbacks.get(id).delete(cb);
|
|
218
|
+
if (this.priceFeedCallbacks.get(id).size === 0) {
|
|
219
|
+
this.priceFeedCallbacks.delete(id);
|
|
220
|
+
idRemoved = true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (idRemoved) {
|
|
224
|
+
removedPriceIds.push(id);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const message = {
|
|
229
|
+
ids: removedPriceIds,
|
|
230
|
+
type: "unsubscribe"
|
|
231
|
+
};
|
|
232
|
+
await this.wsClient?.send(JSON.stringify(message));
|
|
233
|
+
if (this.priceFeedCallbacks.size === 0) {
|
|
234
|
+
this.closeWebSocket();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Starts connection websocket.
|
|
239
|
+
*
|
|
240
|
+
* This function is called automatically upon subscribing to price feed updates.
|
|
241
|
+
*/ async startWebSocket() {
|
|
242
|
+
if (this.wsEndpoint === undefined) {
|
|
243
|
+
throw new Error("Websocket endpoint is undefined.");
|
|
244
|
+
}
|
|
245
|
+
this.wsClient = new _ResillientWebSocket.ResilientWebSocket(this.wsEndpoint, this.logger);
|
|
246
|
+
this.wsClient.onError = this.onWsError;
|
|
247
|
+
this.wsClient.onReconnect = ()=>{
|
|
248
|
+
if (this.priceFeedCallbacks.size > 0) {
|
|
249
|
+
const message = {
|
|
250
|
+
ids: [
|
|
251
|
+
...this.priceFeedCallbacks.keys()
|
|
252
|
+
],
|
|
253
|
+
type: "subscribe",
|
|
254
|
+
verbose: this.priceFeedRequestConfig.verbose,
|
|
255
|
+
binary: this.priceFeedRequestConfig.binary,
|
|
256
|
+
allow_out_of_order: this.priceFeedRequestConfig.allowOutOfOrder
|
|
257
|
+
};
|
|
258
|
+
this.logger.info("Resubscribing to existing price feeds.");
|
|
259
|
+
this.wsClient?.send(JSON.stringify(message));
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
this.wsClient.onMessage = (data)=>{
|
|
263
|
+
this.logger.info(`Received message ${data.toString()}`);
|
|
264
|
+
let message;
|
|
265
|
+
try {
|
|
266
|
+
message = JSON.parse(data.toString());
|
|
267
|
+
} catch (error) {
|
|
268
|
+
this.logger.error(`Error parsing message ${data.toString()} as JSON.`);
|
|
269
|
+
this.logger.error(error);
|
|
270
|
+
this.onWsError(error);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (message.type === "response") {
|
|
274
|
+
if (message.status === "error") {
|
|
275
|
+
this.logger.error(`Error response from the websocket server ${message.error}.`);
|
|
276
|
+
this.onWsError(new Error(message.error));
|
|
277
|
+
}
|
|
278
|
+
} else if (message.type === "price_update") {
|
|
279
|
+
let priceFeed;
|
|
280
|
+
try {
|
|
281
|
+
priceFeed = _priceservicesdk.PriceFeed.fromJson(message.price_feed);
|
|
282
|
+
} catch (error) {
|
|
283
|
+
this.logger.error(`Error parsing price feeds from message ${data.toString()}.`);
|
|
284
|
+
this.logger.error(error);
|
|
285
|
+
this.onWsError(error);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (this.priceFeedCallbacks.has(priceFeed.id)) {
|
|
289
|
+
for (const cb of this.priceFeedCallbacks.get(priceFeed.id)){
|
|
290
|
+
cb(priceFeed);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
this.logger.warn(`Ignoring unsupported server response ${data.toString()}.`);
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
await this.wsClient.startWebSocket();
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Closes connection websocket.
|
|
301
|
+
*
|
|
302
|
+
* At termination, the websocket should be closed to finish the
|
|
303
|
+
* process elegantly. It will automatically close when the connection
|
|
304
|
+
* is subscribed to no price feeds.
|
|
305
|
+
*/ closeWebSocket() {
|
|
306
|
+
this.wsClient?.closeWebSocket();
|
|
307
|
+
this.wsClient = undefined;
|
|
308
|
+
this.priceFeedCallbacks.clear();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import { HexString
|
|
2
|
-
import {
|
|
1
|
+
import type { HexString } from "@pythnetwork/price-service-sdk";
|
|
2
|
+
import { PriceFeed } from "@pythnetwork/price-service-sdk";
|
|
3
|
+
import type { Logger } from "ts-log";
|
|
3
4
|
export type DurationInMs = number;
|
|
4
5
|
export type PriceFeedRequestConfig = {
|
|
5
|
-
verbose?: boolean;
|
|
6
|
-
binary?: boolean;
|
|
7
|
-
allowOutOfOrder?: boolean;
|
|
6
|
+
verbose?: boolean | undefined;
|
|
7
|
+
binary?: boolean | undefined;
|
|
8
|
+
allowOutOfOrder?: boolean | undefined;
|
|
8
9
|
};
|
|
9
10
|
export type PriceServiceConnectionConfig = {
|
|
10
|
-
timeout?: DurationInMs;
|
|
11
|
+
timeout?: DurationInMs | undefined;
|
|
11
12
|
/**
|
|
12
13
|
* Number of times a HTTP request will be retried before the API returns a failure. Default: 3.
|
|
13
14
|
*
|
|
14
15
|
* The connection uses exponential back-off for the delay between retries. However,
|
|
15
16
|
* it will timeout regardless of the retries at the configured `timeout` time.
|
|
16
17
|
*/
|
|
17
|
-
httpRetries?: number;
|
|
18
|
-
logger?: Logger;
|
|
19
|
-
verbose?: boolean;
|
|
20
|
-
priceFeedRequestConfig?: PriceFeedRequestConfig;
|
|
18
|
+
httpRetries?: number | undefined;
|
|
19
|
+
logger?: Logger | undefined;
|
|
20
|
+
verbose?: boolean | undefined;
|
|
21
|
+
priceFeedRequestConfig?: PriceFeedRequestConfig | undefined;
|
|
21
22
|
};
|
|
22
23
|
export type PriceFeedUpdateCallback = (priceFeed: PriceFeed) => void;
|
|
23
24
|
export declare class PriceServiceConnection {
|
|
@@ -36,15 +37,15 @@ export declare class PriceServiceConnection {
|
|
|
36
37
|
/**
|
|
37
38
|
* Constructs a new Connection.
|
|
38
39
|
*
|
|
39
|
-
* @param endpoint endpoint URL to the price service. Example: https://website/example/
|
|
40
|
-
* @param config Optional PriceServiceConnectionConfig for custom configurations.
|
|
40
|
+
* @param endpoint - endpoint URL to the price service. Example: https://website/example/
|
|
41
|
+
* @param config - Optional PriceServiceConnectionConfig for custom configurations.
|
|
41
42
|
*/
|
|
42
43
|
constructor(endpoint: string, config?: PriceServiceConnectionConfig);
|
|
43
44
|
/**
|
|
44
45
|
* Fetch Latest PriceFeeds of given price ids.
|
|
45
46
|
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price ids)
|
|
46
47
|
*
|
|
47
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
48
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
48
49
|
* @returns Array of PriceFeeds
|
|
49
50
|
*/
|
|
50
51
|
getLatestPriceFeeds(priceIds: HexString[]): Promise<PriceFeed[] | undefined>;
|
|
@@ -54,7 +55,7 @@ export declare class PriceServiceConnection {
|
|
|
54
55
|
*
|
|
55
56
|
* This function is coupled to wormhole implemntation.
|
|
56
57
|
*
|
|
57
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
58
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
58
59
|
* @returns Array of base64 encoded VAAs.
|
|
59
60
|
*/
|
|
60
61
|
getLatestVaas(priceIds: HexString[]): Promise<string[]>;
|
|
@@ -66,8 +67,8 @@ export declare class PriceServiceConnection {
|
|
|
66
67
|
*
|
|
67
68
|
* This function is coupled to wormhole implemntation.
|
|
68
69
|
*
|
|
69
|
-
* @param priceId Hex-encoded price id.
|
|
70
|
-
* @param publishTime Epoch timestamp in seconds.
|
|
70
|
+
* @param priceId - Hex-encoded price id.
|
|
71
|
+
* @param publishTime - Epoch timestamp in seconds.
|
|
71
72
|
* @returns Tuple of VAA and publishTime.
|
|
72
73
|
*/
|
|
73
74
|
getVaa(priceId: HexString, publishTime: EpochTimeStamp): Promise<[string, EpochTimeStamp]>;
|
|
@@ -77,8 +78,8 @@ export declare class PriceServiceConnection {
|
|
|
77
78
|
* is old and the price service endpoint does not have a db backend for historical requests.
|
|
78
79
|
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price id)
|
|
79
80
|
*
|
|
80
|
-
* @param priceId Hex-encoded price id.
|
|
81
|
-
* @param publishTime Epoch timestamp in seconds.
|
|
81
|
+
* @param priceId - Hex-encoded price id.
|
|
82
|
+
* @param publishTime - Epoch timestamp in seconds.
|
|
82
83
|
* @returns PriceFeed
|
|
83
84
|
*/
|
|
84
85
|
getPriceFeed(priceId: HexString, publishTime: EpochTimeStamp): Promise<PriceFeed>;
|
|
@@ -97,8 +98,8 @@ export declare class PriceServiceConnection {
|
|
|
97
98
|
* it calls `connection.onWsError`. If you want to handle the errors you should set the
|
|
98
99
|
* `onWsError` function to your custom error handler.
|
|
99
100
|
*
|
|
100
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
101
|
-
* @param cb Callback function that is called with a PriceFeed upon updates to given price ids.
|
|
101
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
102
|
+
* @param cb - Callback function that is called with a PriceFeed upon updates to given price ids.
|
|
102
103
|
*/
|
|
103
104
|
subscribePriceFeedUpdates(priceIds: HexString[], cb: PriceFeedUpdateCallback): Promise<void>;
|
|
104
105
|
/**
|
|
@@ -109,8 +110,8 @@ export declare class PriceServiceConnection {
|
|
|
109
110
|
* it calls `connection.onWsError`. If you want to handle the errors you should set the
|
|
110
111
|
* `onWsError` function to your custom error handler.
|
|
111
112
|
*
|
|
112
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
113
|
-
* @param cb Optional callback, if set it will only unsubscribe this callback from updates for given price ids.
|
|
113
|
+
* @param priceIds - Array of hex-encoded price ids.
|
|
114
|
+
* @param cb - Optional callback, if set it will only unsubscribe this callback from updates for given price ids.
|
|
114
115
|
*/
|
|
115
116
|
unsubscribePriceFeedUpdates(priceIds: HexString[], cb?: PriceFeedUpdateCallback): Promise<void>;
|
|
116
117
|
/**
|
|
@@ -128,4 +129,3 @@ export declare class PriceServiceConnection {
|
|
|
128
129
|
*/
|
|
129
130
|
closeWebSocket(): void;
|
|
130
131
|
}
|
|
131
|
-
//# sourceMappingURL=PriceServiceConnection.d.ts.map
|
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*/
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-floating-promises */ /* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable unicorn/prefer-add-event-listener */ /* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-empty-function */ "use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ResilientWebSocket", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ResilientWebSocket;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _isomorphicws = /*#__PURE__*/ _interop_require_default(require("isomorphic-ws"));
|
|
12
|
+
function _interop_require_default(obj) {
|
|
13
|
+
return obj && obj.__esModule ? obj : {
|
|
14
|
+
default: obj
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const PING_TIMEOUT_DURATION = 30_000 + 3000; // It is 30s on the server and 3s is added for delays
|
|
19
18
|
class ResilientWebSocket {
|
|
20
19
|
endpoint;
|
|
21
20
|
wsClient;
|
|
@@ -26,25 +25,24 @@ class ResilientWebSocket {
|
|
|
26
25
|
onError;
|
|
27
26
|
onMessage;
|
|
28
27
|
onReconnect;
|
|
29
|
-
constructor(endpoint, logger)
|
|
28
|
+
constructor(endpoint, logger){
|
|
30
29
|
this.endpoint = endpoint;
|
|
31
30
|
this.logger = logger;
|
|
32
31
|
this.wsFailedAttempts = 0;
|
|
33
|
-
this.onError = (error)
|
|
32
|
+
this.onError = (error)=>{
|
|
34
33
|
this.logger?.error(error);
|
|
35
34
|
};
|
|
36
35
|
this.wsUserClosed = true;
|
|
37
|
-
this.onMessage = ()
|
|
38
|
-
this.onReconnect = ()
|
|
36
|
+
this.onMessage = ()=>{};
|
|
37
|
+
this.onReconnect = ()=>{};
|
|
39
38
|
}
|
|
40
39
|
async send(data) {
|
|
41
40
|
this.logger?.info(`Sending ${data}`);
|
|
42
41
|
await this.waitForMaybeReadyWebSocket();
|
|
43
42
|
if (this.wsClient === undefined) {
|
|
44
43
|
this.logger?.error("Couldn't connect to the websocket server. Error callback is called.");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
this.wsClient?.send(data);
|
|
44
|
+
} else {
|
|
45
|
+
this.wsClient.send(data);
|
|
48
46
|
}
|
|
49
47
|
}
|
|
50
48
|
async startWebSocket() {
|
|
@@ -52,26 +50,28 @@ class ResilientWebSocket {
|
|
|
52
50
|
return;
|
|
53
51
|
}
|
|
54
52
|
this.logger?.info(`Creating Web Socket client`);
|
|
55
|
-
this.wsClient = new
|
|
53
|
+
this.wsClient = new _isomorphicws.default(this.endpoint);
|
|
56
54
|
this.wsUserClosed = false;
|
|
57
|
-
this.wsClient.
|
|
55
|
+
this.wsClient.addEventListener("open", ()=>{
|
|
58
56
|
this.wsFailedAttempts = 0;
|
|
59
57
|
// Ping handler is undefined in browser side so heartbeat is disabled.
|
|
60
58
|
if (this.wsClient.on !== undefined) {
|
|
61
59
|
this.heartbeat();
|
|
62
60
|
}
|
|
63
|
-
};
|
|
64
|
-
this.wsClient.onerror = (event)
|
|
61
|
+
});
|
|
62
|
+
this.wsClient.onerror = (event)=>{
|
|
65
63
|
this.onError(event.error);
|
|
66
64
|
};
|
|
67
|
-
this.wsClient.onmessage = (event)
|
|
65
|
+
this.wsClient.onmessage = (event)=>{
|
|
68
66
|
this.onMessage(event.data);
|
|
69
67
|
};
|
|
70
|
-
this.wsClient.
|
|
68
|
+
this.wsClient.addEventListener("close", async ()=>{
|
|
71
69
|
if (this.pingTimeout !== undefined) {
|
|
72
70
|
clearInterval(this.pingTimeout);
|
|
73
71
|
}
|
|
74
|
-
if (this.wsUserClosed
|
|
72
|
+
if (this.wsUserClosed) {
|
|
73
|
+
this.logger?.info("The connection has been closed successfully.");
|
|
74
|
+
} else {
|
|
75
75
|
this.wsFailedAttempts += 1;
|
|
76
76
|
this.wsClient = undefined;
|
|
77
77
|
const waitTime = expoBackoff(this.wsFailedAttempts);
|
|
@@ -79,29 +79,25 @@ class ResilientWebSocket {
|
|
|
79
79
|
await sleep(waitTime);
|
|
80
80
|
this.restartUnexpectedClosedWebsocket();
|
|
81
81
|
}
|
|
82
|
-
|
|
83
|
-
this.logger?.info("The connection has been closed successfully.");
|
|
84
|
-
}
|
|
85
|
-
};
|
|
82
|
+
});
|
|
86
83
|
if (this.wsClient.on !== undefined) {
|
|
87
84
|
// Ping handler is undefined in browser side
|
|
88
85
|
this.wsClient.on("ping", this.heartbeat.bind(this));
|
|
89
86
|
}
|
|
90
87
|
}
|
|
91
88
|
/**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
heartbeat() {
|
|
89
|
+
* Heartbeat is only enabled in node clients because they support handling
|
|
90
|
+
* ping-pong events.
|
|
91
|
+
*
|
|
92
|
+
* This approach only works when server constantly pings the clients which.
|
|
93
|
+
* Otherwise you might consider sending ping and acting on pong responses
|
|
94
|
+
* yourself.
|
|
95
|
+
*/ heartbeat() {
|
|
100
96
|
this.logger?.info("Heartbeat");
|
|
101
97
|
if (this.pingTimeout !== undefined) {
|
|
102
98
|
clearTimeout(this.pingTimeout);
|
|
103
99
|
}
|
|
104
|
-
this.pingTimeout = setTimeout(()
|
|
100
|
+
this.pingTimeout = setTimeout(()=>{
|
|
105
101
|
this.logger?.warn(`Connection timed out. Reconnecting...`);
|
|
106
102
|
this.wsClient?.terminate();
|
|
107
103
|
this.restartUnexpectedClosedWebsocket();
|
|
@@ -109,20 +105,18 @@ class ResilientWebSocket {
|
|
|
109
105
|
}
|
|
110
106
|
async waitForMaybeReadyWebSocket() {
|
|
111
107
|
let waitedTime = 0;
|
|
112
|
-
while
|
|
113
|
-
this.wsClient.readyState !== this.wsClient.OPEN) {
|
|
108
|
+
while(this.wsClient !== undefined && this.wsClient.readyState !== this.wsClient.OPEN){
|
|
114
109
|
if (waitedTime > 5000) {
|
|
115
110
|
this.wsClient.close();
|
|
116
111
|
return;
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
112
|
+
} else {
|
|
119
113
|
waitedTime += 10;
|
|
120
114
|
await sleep(10);
|
|
121
115
|
}
|
|
122
116
|
}
|
|
123
117
|
}
|
|
124
118
|
async restartUnexpectedClosedWebsocket() {
|
|
125
|
-
if (this.wsUserClosed
|
|
119
|
+
if (this.wsUserClosed) {
|
|
126
120
|
return;
|
|
127
121
|
}
|
|
128
122
|
await this.startWebSocket();
|
|
@@ -142,9 +136,8 @@ class ResilientWebSocket {
|
|
|
142
136
|
this.wsUserClosed = true;
|
|
143
137
|
}
|
|
144
138
|
}
|
|
145
|
-
exports.ResilientWebSocket = ResilientWebSocket;
|
|
146
139
|
async function sleep(ms) {
|
|
147
|
-
return new Promise((resolve)
|
|
140
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
148
141
|
}
|
|
149
142
|
function expoBackoff(attempts) {
|
|
150
143
|
return 2 ** attempts * 100;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/// <reference types="ws" />
|
|
2
1
|
import WebSocket from "isomorphic-ws";
|
|
3
|
-
import { Logger } from "ts-log";
|
|
2
|
+
import type { Logger } from "ts-log";
|
|
4
3
|
/**
|
|
5
4
|
* This class wraps websocket to provide a resilient web socket client.
|
|
6
5
|
*
|
|
@@ -22,7 +21,7 @@ export declare class ResilientWebSocket {
|
|
|
22
21
|
onMessage: (data: WebSocket.Data) => void;
|
|
23
22
|
onReconnect: () => void;
|
|
24
23
|
constructor(endpoint: string, logger?: Logger);
|
|
25
|
-
send(data:
|
|
24
|
+
send(data: unknown): Promise<void>;
|
|
26
25
|
startWebSocket(): Promise<void>;
|
|
27
26
|
/**
|
|
28
27
|
* Heartbeat is only enabled in node clients because they support handling
|
|
@@ -37,4 +36,3 @@ export declare class ResilientWebSocket {
|
|
|
37
36
|
private restartUnexpectedClosedWebsocket;
|
|
38
37
|
closeWebSocket(): void;
|
|
39
38
|
}
|
|
40
|
-
//# sourceMappingURL=ResillientWebSocket.d.ts.map
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get Price () {
|
|
13
|
+
return _priceservicesdk.Price;
|
|
14
|
+
},
|
|
15
|
+
get PriceFeed () {
|
|
16
|
+
return _priceservicesdk.PriceFeed;
|
|
17
|
+
},
|
|
18
|
+
get PriceFeedMetadata () {
|
|
19
|
+
return _priceservicesdk.PriceFeedMetadata;
|
|
20
|
+
},
|
|
21
|
+
get PriceServiceConnection () {
|
|
22
|
+
return _PriceServiceConnection.PriceServiceConnection;
|
|
23
|
+
},
|
|
24
|
+
get isAccumulatorUpdateData () {
|
|
25
|
+
return _priceservicesdk.isAccumulatorUpdateData;
|
|
26
|
+
},
|
|
27
|
+
get parseAccumulatorUpdateData () {
|
|
28
|
+
return _priceservicesdk.parseAccumulatorUpdateData;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const _PriceServiceConnection = require("./PriceServiceConnection.cjs");
|
|
32
|
+
const _priceservicesdk = require("@pythnetwork/price-service-sdk");
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { type DurationInMs, PriceServiceConnection, type PriceServiceConnectionConfig, } from "./PriceServiceConnection.js";
|
|
2
|
+
export { type HexString, PriceFeedMetadata, PriceFeed, Price, type UnixTimestamp, isAccumulatorUpdateData, parseAccumulatorUpdateData, type AccumulatorUpdateData, } from "@pythnetwork/price-service-sdk";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "commonjs" }
|
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get makeWebsocketUrl () {
|
|
13
|
+
return makeWebsocketUrl;
|
|
14
|
+
},
|
|
15
|
+
get removeLeading0xIfExists () {
|
|
16
|
+
return removeLeading0xIfExists;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
function makeWebsocketUrl(endpoint) {
|
|
20
|
+
const url = new URL("ws", endpoint);
|
|
21
|
+
const useHttps = url.protocol === "https:";
|
|
22
|
+
url.protocol = useHttps ? "wss:" : "ws:";
|
|
23
|
+
return url.toString();
|
|
24
|
+
}
|
|
25
|
+
function removeLeading0xIfExists(id) {
|
|
26
|
+
return id.startsWith("0x") ? id.slice(2) : id;
|
|
27
|
+
}
|
package/{lib → dist}/utils.d.ts
RENAMED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { HexString } from "@pythnetwork/price-service-sdk";
|
|
1
|
+
import type { HexString } from "@pythnetwork/price-service-sdk";
|
|
2
2
|
/**
|
|
3
3
|
* Convert http(s) endpoint to ws(s) endpoint.
|
|
4
4
|
*
|
|
5
|
-
* @param endpoint Http(s) protocol endpoint
|
|
5
|
+
* @param endpoint - Http(s) protocol endpoint
|
|
6
6
|
* @returns Ws(s) protocol endpoint of the same address
|
|
7
7
|
*/
|
|
8
8
|
export declare function makeWebsocketUrl(endpoint: string): string;
|
|
9
9
|
export declare function removeLeading0xIfExists(id: HexString): HexString;
|
|
10
|
-
//# sourceMappingURL=utils.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pythnetwork/price-service-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Pyth price service client",
|
|
5
5
|
"deprecated": "This package is deprecated and is no longer maintained. Please use @pythnetwork/hermes-client instead.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Pyth Data Association"
|
|
8
8
|
},
|
|
9
9
|
"homepage": "https://pyth.network",
|
|
10
|
-
"main": "
|
|
11
|
-
"types": "
|
|
10
|
+
"main": "./dist/index.cjs",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
12
|
"files": [
|
|
13
|
-
"
|
|
13
|
+
"dist/**/*"
|
|
14
14
|
],
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
@@ -26,15 +26,13 @@
|
|
|
26
26
|
],
|
|
27
27
|
"license": "Apache-2.0",
|
|
28
28
|
"devDependencies": {
|
|
29
|
+
"@cprussin/eslint-config": "^4.0.2",
|
|
29
30
|
"@types/jest": "^29.4.0",
|
|
30
31
|
"@types/yargs": "^17.0.10",
|
|
31
|
-
"
|
|
32
|
-
"@typescript-eslint/parser": "^5.21.0",
|
|
33
|
-
"eslint": "^8.14.0",
|
|
32
|
+
"eslint": "^9.23.0",
|
|
34
33
|
"jest": "^29.4.0",
|
|
35
34
|
"prettier": "^3.5.3",
|
|
36
35
|
"ts-jest": "^29.0.5",
|
|
37
|
-
"typescript": "^4.6.3",
|
|
38
36
|
"yargs": "^17.4.1"
|
|
39
37
|
},
|
|
40
38
|
"dependencies": {
|
|
@@ -44,17 +42,42 @@
|
|
|
44
42
|
"isomorphic-ws": "^4.0.1",
|
|
45
43
|
"ts-log": "^2.2.4",
|
|
46
44
|
"ws": "^8.6.0",
|
|
47
|
-
"@pythnetwork/price-service-sdk": "1.
|
|
45
|
+
"@pythnetwork/price-service-sdk": "1.9.0"
|
|
48
46
|
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=22.14.0"
|
|
49
|
+
},
|
|
50
|
+
"type": "module",
|
|
51
|
+
"exports": {
|
|
52
|
+
"./PriceServiceConnection": {
|
|
53
|
+
"types": "./dist/PriceServiceConnection.d.ts",
|
|
54
|
+
"default": "./dist/PriceServiceConnection.cjs"
|
|
55
|
+
},
|
|
56
|
+
"./ResillientWebSocket": {
|
|
57
|
+
"types": "./dist/ResillientWebSocket.d.ts",
|
|
58
|
+
"default": "./dist/ResillientWebSocket.cjs"
|
|
59
|
+
},
|
|
60
|
+
".": {
|
|
61
|
+
"types": "./dist/index.d.ts",
|
|
62
|
+
"default": "./dist/index.cjs"
|
|
63
|
+
},
|
|
64
|
+
"./utils": {
|
|
65
|
+
"types": "./dist/utils.d.ts",
|
|
66
|
+
"default": "./dist/utils.cjs"
|
|
67
|
+
},
|
|
68
|
+
"./package.json": "./package.json"
|
|
69
|
+
},
|
|
70
|
+
"module": "./dist/esm/index.js",
|
|
49
71
|
"scripts": {
|
|
50
72
|
"test:e2e": "jest --testPathPattern=.*.e2e.test.ts",
|
|
51
|
-
"build": "
|
|
73
|
+
"build": "ts-duality --noEsm",
|
|
52
74
|
"example": "pnpm run build && node lib/examples/PriceServiceClient.js",
|
|
53
75
|
"fix:format": "prettier --write \"src/**/*.ts\"",
|
|
54
76
|
"fix:lint": "eslint src/ --fix --max-warnings 0",
|
|
55
77
|
"test:format": "prettier --check \"src/**/*.ts\"",
|
|
56
78
|
"test:lint": "eslint src/ --max-warnings 0",
|
|
57
79
|
"preversion": "pnpm run test:lint",
|
|
58
|
-
"version": "pnpm run format && git add -A src"
|
|
80
|
+
"version": "pnpm run format && git add -A src",
|
|
81
|
+
"clean": "rm -rf ./dist"
|
|
59
82
|
}
|
|
60
83
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PriceServiceConnection.d.ts","sourceRoot":"","sources":["../src/PriceServiceConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAItE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC,MAAM,MAAM,sBAAsB,GAAG;IAEnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IAEzC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACjD,CAAC;AAuBF,MAAM,MAAM,uBAAuB,GAAG,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;AAErE,qBAAa,sBAAsB;IACjC,OAAO,CAAC,UAAU,CAAgB;IAElC,OAAO,CAAC,kBAAkB,CAA+C;IACzE,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,UAAU,CAAqB;IAEvC,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,sBAAsB,CAAyB;IAEvD;;;;OAIG;IACH,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAElC;;;;;OAKG;gBACS,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,4BAA4B;IA+CnE;;;;;;OAMG;IACG,mBAAmB,CACvB,QAAQ,EAAE,SAAS,EAAE,GACpB,OAAO,CAAC,SAAS,EAAE,GAAG,SAAS,CAAC;IAkBnC;;;;;;;;OAQG;IACG,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS7D;;;;;;;;;;;OAWG;IACG,MAAM,CACV,OAAO,EAAE,SAAS,EAClB,WAAW,EAAE,cAAc,GAC1B,OAAO,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAUpC;;;;;;;;;OASG;IACG,YAAY,CAChB,OAAO,EAAE,SAAS,EAClB,WAAW,EAAE,cAAc,GAC1B,OAAO,CAAC,SAAS,CAAC;IAarB;;;;;OAKG;IACG,eAAe,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAK7C;;;;;;;;;;OAUG;IACG,yBAAyB,CAC7B,QAAQ,EAAE,SAAS,EAAE,EACrB,EAAE,EAAE,uBAAuB;IA8B7B;;;;;;;;;;OAUG;IACG,2BAA2B,CAC/B,QAAQ,EAAE,SAAS,EAAE,EACrB,EAAE,CAAC,EAAE,uBAAuB;IA4C9B;;;;OAIG;IACG,cAAc;IAyEpB;;;;;;OAMG;IACH,cAAc;CAKf"}
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PriceServiceConnection = void 0;
|
|
7
|
-
const price_service_sdk_1 = require("@pythnetwork/price-service-sdk");
|
|
8
|
-
const axios_1 = __importDefault(require("axios"));
|
|
9
|
-
const axios_retry_1 = __importDefault(require("axios-retry"));
|
|
10
|
-
const ResillientWebSocket_1 = require("./ResillientWebSocket");
|
|
11
|
-
const utils_1 = require("./utils");
|
|
12
|
-
class PriceServiceConnection {
|
|
13
|
-
httpClient;
|
|
14
|
-
priceFeedCallbacks;
|
|
15
|
-
wsClient;
|
|
16
|
-
wsEndpoint;
|
|
17
|
-
logger;
|
|
18
|
-
priceFeedRequestConfig;
|
|
19
|
-
/**
|
|
20
|
-
* Custom handler for web socket errors (connection and message parsing).
|
|
21
|
-
*
|
|
22
|
-
* Default handler only logs the errors.
|
|
23
|
-
*/
|
|
24
|
-
onWsError;
|
|
25
|
-
/**
|
|
26
|
-
* Constructs a new Connection.
|
|
27
|
-
*
|
|
28
|
-
* @param endpoint endpoint URL to the price service. Example: https://website/example/
|
|
29
|
-
* @param config Optional PriceServiceConnectionConfig for custom configurations.
|
|
30
|
-
*/
|
|
31
|
-
constructor(endpoint, config) {
|
|
32
|
-
this.httpClient = axios_1.default.create({
|
|
33
|
-
baseURL: endpoint,
|
|
34
|
-
timeout: config?.timeout || 5000,
|
|
35
|
-
});
|
|
36
|
-
(0, axios_retry_1.default)(this.httpClient, {
|
|
37
|
-
retries: config?.httpRetries || 3,
|
|
38
|
-
retryDelay: axios_retry_1.default.exponentialDelay,
|
|
39
|
-
});
|
|
40
|
-
this.priceFeedRequestConfig = {
|
|
41
|
-
binary: config?.priceFeedRequestConfig?.binary,
|
|
42
|
-
verbose: config?.priceFeedRequestConfig?.verbose ?? config?.verbose,
|
|
43
|
-
allowOutOfOrder: config?.priceFeedRequestConfig?.allowOutOfOrder,
|
|
44
|
-
};
|
|
45
|
-
this.priceFeedCallbacks = new Map();
|
|
46
|
-
// Default logger is console for only warnings and errors.
|
|
47
|
-
this.logger = config?.logger || {
|
|
48
|
-
trace: () => { },
|
|
49
|
-
debug: () => { },
|
|
50
|
-
info: () => { },
|
|
51
|
-
warn: console.warn,
|
|
52
|
-
error: console.error,
|
|
53
|
-
};
|
|
54
|
-
this.onWsError = (error) => {
|
|
55
|
-
this.logger.error(error);
|
|
56
|
-
// Exit the process if it is running in node.
|
|
57
|
-
if (typeof process !== "undefined" &&
|
|
58
|
-
typeof process.exit === "function") {
|
|
59
|
-
this.logger.error("Halting the process due to the websocket error");
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
this.logger.error("Cannot halt process. Please handle the websocket error.");
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
this.wsEndpoint = (0, utils_1.makeWebsocketUrl)(endpoint);
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Fetch Latest PriceFeeds of given price ids.
|
|
70
|
-
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price ids)
|
|
71
|
-
*
|
|
72
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
73
|
-
* @returns Array of PriceFeeds
|
|
74
|
-
*/
|
|
75
|
-
async getLatestPriceFeeds(priceIds) {
|
|
76
|
-
if (priceIds.length === 0) {
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
const response = await this.httpClient.get("/api/latest_price_feeds", {
|
|
80
|
-
params: {
|
|
81
|
-
ids: priceIds,
|
|
82
|
-
verbose: this.priceFeedRequestConfig.verbose,
|
|
83
|
-
binary: this.priceFeedRequestConfig.binary,
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
const priceFeedsJson = response.data;
|
|
87
|
-
return priceFeedsJson.map((priceFeedJson) => price_service_sdk_1.PriceFeed.fromJson(priceFeedJson));
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Fetch latest VAA of given price ids.
|
|
91
|
-
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price ids)
|
|
92
|
-
*
|
|
93
|
-
* This function is coupled to wormhole implemntation.
|
|
94
|
-
*
|
|
95
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
96
|
-
* @returns Array of base64 encoded VAAs.
|
|
97
|
-
*/
|
|
98
|
-
async getLatestVaas(priceIds) {
|
|
99
|
-
const response = await this.httpClient.get("/api/latest_vaas", {
|
|
100
|
-
params: {
|
|
101
|
-
ids: priceIds,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
return response.data;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Fetch the earliest VAA of the given price id that is published since the given publish time.
|
|
108
|
-
* This will throw an error if the given publish time is in the future, or if the publish time
|
|
109
|
-
* is old and the price service endpoint does not have a db backend for historical requests.
|
|
110
|
-
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price id)
|
|
111
|
-
*
|
|
112
|
-
* This function is coupled to wormhole implemntation.
|
|
113
|
-
*
|
|
114
|
-
* @param priceId Hex-encoded price id.
|
|
115
|
-
* @param publishTime Epoch timestamp in seconds.
|
|
116
|
-
* @returns Tuple of VAA and publishTime.
|
|
117
|
-
*/
|
|
118
|
-
async getVaa(priceId, publishTime) {
|
|
119
|
-
const response = await this.httpClient.get("/api/get_vaa", {
|
|
120
|
-
params: {
|
|
121
|
-
id: priceId,
|
|
122
|
-
publish_time: publishTime,
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
return [response.data.vaa, response.data.publishTime];
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Fetch the PriceFeed of the given price id that is published since the given publish time.
|
|
129
|
-
* This will throw an error if the given publish time is in the future, or if the publish time
|
|
130
|
-
* is old and the price service endpoint does not have a db backend for historical requests.
|
|
131
|
-
* This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price id)
|
|
132
|
-
*
|
|
133
|
-
* @param priceId Hex-encoded price id.
|
|
134
|
-
* @param publishTime Epoch timestamp in seconds.
|
|
135
|
-
* @returns PriceFeed
|
|
136
|
-
*/
|
|
137
|
-
async getPriceFeed(priceId, publishTime) {
|
|
138
|
-
const response = await this.httpClient.get("/api/get_price_feed", {
|
|
139
|
-
params: {
|
|
140
|
-
id: priceId,
|
|
141
|
-
publish_time: publishTime,
|
|
142
|
-
verbose: this.priceFeedRequestConfig.verbose,
|
|
143
|
-
binary: this.priceFeedRequestConfig.binary,
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
return price_service_sdk_1.PriceFeed.fromJson(response.data);
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Fetch the list of available price feed ids.
|
|
150
|
-
* This will throw an axios error if there is a network problem or the price service returns a non-ok response.
|
|
151
|
-
*
|
|
152
|
-
* @returns Array of hex-encoded price ids.
|
|
153
|
-
*/
|
|
154
|
-
async getPriceFeedIds() {
|
|
155
|
-
const response = await this.httpClient.get("/api/price_feed_ids");
|
|
156
|
-
return response.data;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Subscribe to updates for given price ids.
|
|
160
|
-
*
|
|
161
|
-
* It will start a websocket connection if it's not started yet.
|
|
162
|
-
* Also, it won't throw any exception if given price ids are invalid or connection errors. Instead,
|
|
163
|
-
* it calls `connection.onWsError`. If you want to handle the errors you should set the
|
|
164
|
-
* `onWsError` function to your custom error handler.
|
|
165
|
-
*
|
|
166
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
167
|
-
* @param cb Callback function that is called with a PriceFeed upon updates to given price ids.
|
|
168
|
-
*/
|
|
169
|
-
async subscribePriceFeedUpdates(priceIds, cb) {
|
|
170
|
-
if (this.wsClient === undefined) {
|
|
171
|
-
await this.startWebSocket();
|
|
172
|
-
}
|
|
173
|
-
priceIds = priceIds.map((priceId) => (0, utils_1.removeLeading0xIfExists)(priceId));
|
|
174
|
-
const newPriceIds = [];
|
|
175
|
-
for (const id of priceIds) {
|
|
176
|
-
if (!this.priceFeedCallbacks.has(id)) {
|
|
177
|
-
this.priceFeedCallbacks.set(id, new Set());
|
|
178
|
-
newPriceIds.push(id);
|
|
179
|
-
}
|
|
180
|
-
this.priceFeedCallbacks.get(id).add(cb);
|
|
181
|
-
}
|
|
182
|
-
const message = {
|
|
183
|
-
ids: newPriceIds,
|
|
184
|
-
type: "subscribe",
|
|
185
|
-
verbose: this.priceFeedRequestConfig.verbose,
|
|
186
|
-
binary: this.priceFeedRequestConfig.binary,
|
|
187
|
-
allow_out_of_order: this.priceFeedRequestConfig.allowOutOfOrder,
|
|
188
|
-
};
|
|
189
|
-
await this.wsClient?.send(JSON.stringify(message));
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Unsubscribe from updates for given price ids.
|
|
193
|
-
*
|
|
194
|
-
* It will close the websocket connection if it's not subscribed to any price feed updates anymore.
|
|
195
|
-
* Also, it won't throw any exception if given price ids are invalid or connection errors. Instead,
|
|
196
|
-
* it calls `connection.onWsError`. If you want to handle the errors you should set the
|
|
197
|
-
* `onWsError` function to your custom error handler.
|
|
198
|
-
*
|
|
199
|
-
* @param priceIds Array of hex-encoded price ids.
|
|
200
|
-
* @param cb Optional callback, if set it will only unsubscribe this callback from updates for given price ids.
|
|
201
|
-
*/
|
|
202
|
-
async unsubscribePriceFeedUpdates(priceIds, cb) {
|
|
203
|
-
if (this.wsClient === undefined) {
|
|
204
|
-
await this.startWebSocket();
|
|
205
|
-
}
|
|
206
|
-
priceIds = priceIds.map((priceId) => (0, utils_1.removeLeading0xIfExists)(priceId));
|
|
207
|
-
const removedPriceIds = [];
|
|
208
|
-
for (const id of priceIds) {
|
|
209
|
-
if (this.priceFeedCallbacks.has(id)) {
|
|
210
|
-
let idRemoved = false;
|
|
211
|
-
if (cb === undefined) {
|
|
212
|
-
this.priceFeedCallbacks.delete(id);
|
|
213
|
-
idRemoved = true;
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
this.priceFeedCallbacks.get(id).delete(cb);
|
|
217
|
-
if (this.priceFeedCallbacks.get(id).size === 0) {
|
|
218
|
-
this.priceFeedCallbacks.delete(id);
|
|
219
|
-
idRemoved = true;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if (idRemoved) {
|
|
223
|
-
removedPriceIds.push(id);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
const message = {
|
|
228
|
-
ids: removedPriceIds,
|
|
229
|
-
type: "unsubscribe",
|
|
230
|
-
};
|
|
231
|
-
await this.wsClient?.send(JSON.stringify(message));
|
|
232
|
-
if (this.priceFeedCallbacks.size === 0) {
|
|
233
|
-
this.closeWebSocket();
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Starts connection websocket.
|
|
238
|
-
*
|
|
239
|
-
* This function is called automatically upon subscribing to price feed updates.
|
|
240
|
-
*/
|
|
241
|
-
async startWebSocket() {
|
|
242
|
-
if (this.wsEndpoint === undefined) {
|
|
243
|
-
throw new Error("Websocket endpoint is undefined.");
|
|
244
|
-
}
|
|
245
|
-
this.wsClient = new ResillientWebSocket_1.ResilientWebSocket(this.wsEndpoint, this.logger);
|
|
246
|
-
this.wsClient.onError = this.onWsError;
|
|
247
|
-
this.wsClient.onReconnect = () => {
|
|
248
|
-
if (this.priceFeedCallbacks.size > 0) {
|
|
249
|
-
const message = {
|
|
250
|
-
ids: Array.from(this.priceFeedCallbacks.keys()),
|
|
251
|
-
type: "subscribe",
|
|
252
|
-
verbose: this.priceFeedRequestConfig.verbose,
|
|
253
|
-
binary: this.priceFeedRequestConfig.binary,
|
|
254
|
-
allow_out_of_order: this.priceFeedRequestConfig.allowOutOfOrder,
|
|
255
|
-
};
|
|
256
|
-
this.logger.info("Resubscribing to existing price feeds.");
|
|
257
|
-
this.wsClient?.send(JSON.stringify(message));
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
this.wsClient.onMessage = (data) => {
|
|
261
|
-
this.logger.info(`Received message ${data.toString()}`);
|
|
262
|
-
let message;
|
|
263
|
-
try {
|
|
264
|
-
message = JSON.parse(data.toString());
|
|
265
|
-
}
|
|
266
|
-
catch (e) {
|
|
267
|
-
this.logger.error(`Error parsing message ${data.toString()} as JSON.`);
|
|
268
|
-
this.logger.error(e);
|
|
269
|
-
this.onWsError(e);
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
if (message.type === "response") {
|
|
273
|
-
if (message.status === "error") {
|
|
274
|
-
this.logger.error(`Error response from the websocket server ${message.error}.`);
|
|
275
|
-
this.onWsError(new Error(message.error));
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
else if (message.type === "price_update") {
|
|
279
|
-
let priceFeed;
|
|
280
|
-
try {
|
|
281
|
-
priceFeed = price_service_sdk_1.PriceFeed.fromJson(message.price_feed);
|
|
282
|
-
}
|
|
283
|
-
catch (e) {
|
|
284
|
-
this.logger.error(`Error parsing price feeds from message ${data.toString()}.`);
|
|
285
|
-
this.logger.error(e);
|
|
286
|
-
this.onWsError(e);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
if (this.priceFeedCallbacks.has(priceFeed.id)) {
|
|
290
|
-
for (const cb of this.priceFeedCallbacks.get(priceFeed.id)) {
|
|
291
|
-
cb(priceFeed);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
this.logger.warn(`Ignoring unsupported server response ${data.toString()}.`);
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
await this.wsClient.startWebSocket();
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Closes connection websocket.
|
|
303
|
-
*
|
|
304
|
-
* At termination, the websocket should be closed to finish the
|
|
305
|
-
* process elegantly. It will automatically close when the connection
|
|
306
|
-
* is subscribed to no price feeds.
|
|
307
|
-
*/
|
|
308
|
-
closeWebSocket() {
|
|
309
|
-
this.wsClient?.closeWebSocket();
|
|
310
|
-
this.wsClient = undefined;
|
|
311
|
-
this.priceFeedCallbacks.clear();
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
exports.PriceServiceConnection = PriceServiceConnection;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ResillientWebSocket.d.ts","sourceRoot":"","sources":["../src/ResillientWebSocket.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC;;;;;;;;;GASG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,MAAM,CAAqB;IAEnC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChC,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC;IAC1C,WAAW,EAAE,MAAM,IAAI,CAAC;gBAEZ,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAavC,IAAI,CAAC,IAAI,EAAE,GAAG;IAcd,cAAc;IAqDpB;;;;;;;OAOG;IACH,OAAO,CAAC,SAAS;YAcH,0BAA0B;YAgB1B,gCAAgC;IAkB9C,cAAc;CAQf"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PriceServiceClient.d.ts","sourceRoot":"","sources":["../../src/examples/PriceServiceClient.ts"],"names":[],"mappings":""}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const yargs_1 = __importDefault(require("yargs"));
|
|
7
|
-
const helpers_1 = require("yargs/helpers");
|
|
8
|
-
const index_1 = require("../index");
|
|
9
|
-
function sleep(ms) {
|
|
10
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
|
-
}
|
|
12
|
-
const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
13
|
-
.option("endpoint", {
|
|
14
|
-
description: "Endpoint URL for the price service. e.g: https://endpoint/example",
|
|
15
|
-
type: "string",
|
|
16
|
-
required: true,
|
|
17
|
-
})
|
|
18
|
-
.option("price-ids", {
|
|
19
|
-
description: "Space separated price feed ids (in hex without leading 0x) to fetch." +
|
|
20
|
-
" e.g: f9c0172ba10dfa4d19088d...",
|
|
21
|
-
type: "array",
|
|
22
|
-
required: true,
|
|
23
|
-
})
|
|
24
|
-
.help()
|
|
25
|
-
.alias("help", "h")
|
|
26
|
-
.parserConfiguration({
|
|
27
|
-
"parse-numbers": false,
|
|
28
|
-
})
|
|
29
|
-
.parseSync();
|
|
30
|
-
async function run() {
|
|
31
|
-
const connection = new index_1.PriceServiceConnection(argv.endpoint, {
|
|
32
|
-
logger: console,
|
|
33
|
-
priceFeedRequestConfig: {
|
|
34
|
-
binary: true,
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
const priceIds = argv.priceIds;
|
|
38
|
-
const priceFeeds = await connection.getLatestPriceFeeds(priceIds);
|
|
39
|
-
console.log(priceFeeds);
|
|
40
|
-
console.log(priceFeeds?.at(0)?.getPriceNoOlderThan(60));
|
|
41
|
-
console.log("Subscribing to price feed updates.");
|
|
42
|
-
await connection.subscribePriceFeedUpdates(priceIds, (priceFeed) => {
|
|
43
|
-
console.log(`Current price for ${priceFeed.id}: ${JSON.stringify(priceFeed.getPriceNoOlderThan(60))}.`);
|
|
44
|
-
console.log(priceFeed.getVAA());
|
|
45
|
-
});
|
|
46
|
-
await sleep(600000);
|
|
47
|
-
// To close the websocket you should either unsubscribe from all
|
|
48
|
-
// price feeds or call `connection.stopWebSocket()` directly.
|
|
49
|
-
console.log("Unsubscribing from price feed updates.");
|
|
50
|
-
await connection.unsubscribePriceFeedUpdates(priceIds);
|
|
51
|
-
// connection.closeWebSocket();
|
|
52
|
-
}
|
|
53
|
-
run();
|
package/lib/index.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export { DurationInMs, PriceServiceConnection, PriceServiceConnectionConfig, } from "./PriceServiceConnection";
|
|
2
|
-
export { HexString, PriceFeedMetadata, PriceFeed, Price, UnixTimestamp, isAccumulatorUpdateData, parseAccumulatorUpdateData, AccumulatorUpdateData, } from "@pythnetwork/price-service-sdk";
|
|
3
|
-
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,KAAK,EACL,aAAa,EACb,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,gCAAgC,CAAC"}
|
package/lib/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseAccumulatorUpdateData = exports.isAccumulatorUpdateData = exports.Price = exports.PriceFeed = exports.PriceFeedMetadata = exports.PriceServiceConnection = void 0;
|
|
4
|
-
var PriceServiceConnection_1 = require("./PriceServiceConnection");
|
|
5
|
-
Object.defineProperty(exports, "PriceServiceConnection", { enumerable: true, get: function () { return PriceServiceConnection_1.PriceServiceConnection; } });
|
|
6
|
-
var price_service_sdk_1 = require("@pythnetwork/price-service-sdk");
|
|
7
|
-
Object.defineProperty(exports, "PriceFeedMetadata", { enumerable: true, get: function () { return price_service_sdk_1.PriceFeedMetadata; } });
|
|
8
|
-
Object.defineProperty(exports, "PriceFeed", { enumerable: true, get: function () { return price_service_sdk_1.PriceFeed; } });
|
|
9
|
-
Object.defineProperty(exports, "Price", { enumerable: true, get: function () { return price_service_sdk_1.Price; } });
|
|
10
|
-
Object.defineProperty(exports, "isAccumulatorUpdateData", { enumerable: true, get: function () { return price_service_sdk_1.isAccumulatorUpdateData; } });
|
|
11
|
-
Object.defineProperty(exports, "parseAccumulatorUpdateData", { enumerable: true, get: function () { return price_service_sdk_1.parseAccumulatorUpdateData; } });
|
package/lib/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,UAOhD;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,SAAS,GAAG,SAAS,CAMhE"}
|
package/lib/utils.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.removeLeading0xIfExists = exports.makeWebsocketUrl = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Convert http(s) endpoint to ws(s) endpoint.
|
|
6
|
-
*
|
|
7
|
-
* @param endpoint Http(s) protocol endpoint
|
|
8
|
-
* @returns Ws(s) protocol endpoint of the same address
|
|
9
|
-
*/
|
|
10
|
-
function makeWebsocketUrl(endpoint) {
|
|
11
|
-
const url = new URL("ws", endpoint);
|
|
12
|
-
const useHttps = url.protocol === "https:";
|
|
13
|
-
url.protocol = useHttps ? "wss:" : "ws:";
|
|
14
|
-
return url.toString();
|
|
15
|
-
}
|
|
16
|
-
exports.makeWebsocketUrl = makeWebsocketUrl;
|
|
17
|
-
function removeLeading0xIfExists(id) {
|
|
18
|
-
if (id.startsWith("0x")) {
|
|
19
|
-
return id.substring(2);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
return id;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
exports.removeLeading0xIfExists = removeLeading0xIfExists;
|