@zofai/zo-sdk 0.2.14 → 0.2.15
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/abstract/BaseDataAPI.cjs +1 -1
- package/dist/abstract/BaseDataAPI.cjs.map +1 -1
- package/dist/abstract/BaseDataAPI.mjs +1 -1
- package/dist/abstract/BaseDataAPI.mjs.map +1 -1
- package/dist/consts/deployments-usdz-mainnet.json +1 -1
- package/dist/consts/deployments-zo-oracle-mainnet.json +329 -0
- package/dist/consts/index.cjs +35 -1
- package/dist/consts/index.cjs.map +1 -1
- package/dist/consts/index.d.cts +45 -0
- package/dist/consts/index.d.cts.map +1 -1
- package/dist/consts/index.d.mts +45 -0
- package/dist/consts/index.d.mts.map +1 -1
- package/dist/consts/index.mjs +31 -0
- package/dist/consts/index.mjs.map +1 -1
- package/dist/data.cjs +1 -1
- package/dist/data.cjs.map +1 -1
- package/dist/data.mjs +1 -1
- package/dist/data.mjs.map +1 -1
- package/dist/implementations/USDZAPI.cjs +426 -78
- package/dist/implementations/USDZAPI.cjs.map +1 -1
- package/dist/implementations/USDZAPI.d.cts +54 -0
- package/dist/implementations/USDZAPI.d.cts.map +1 -1
- package/dist/implementations/USDZAPI.d.mts +54 -0
- package/dist/implementations/USDZAPI.d.mts.map +1 -1
- package/dist/implementations/USDZAPI.mjs +427 -79
- package/dist/implementations/USDZAPI.mjs.map +1 -1
- package/dist/implementations/USDZDataAPI.cjs +38 -0
- package/dist/implementations/USDZDataAPI.cjs.map +1 -1
- package/dist/implementations/USDZDataAPI.d.cts +16 -0
- package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
- package/dist/implementations/USDZDataAPI.d.mts +16 -0
- package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
- package/dist/implementations/USDZDataAPI.mjs +38 -0
- package/dist/implementations/USDZDataAPI.mjs.map +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/dist/interfaces/base.d.cts +19 -1
- package/dist/interfaces/base.d.cts.map +1 -1
- package/dist/interfaces/base.d.mts +19 -1
- package/dist/interfaces/base.d.mts.map +1 -1
- package/dist/interfaces/usdz.d.cts +17 -0
- package/dist/interfaces/usdz.d.cts.map +1 -1
- package/dist/interfaces/usdz.d.mts +17 -0
- package/dist/interfaces/usdz.d.mts.map +1 -1
- package/dist/oracle.cjs +119 -1
- package/dist/oracle.cjs.map +1 -1
- package/dist/oracle.d.cts +57 -1
- package/dist/oracle.d.cts.map +1 -1
- package/dist/oracle.d.mts +57 -1
- package/dist/oracle.d.mts.map +1 -1
- package/dist/oracle.mjs +120 -2
- package/dist/oracle.mjs.map +1 -1
- package/dist/oraclePro.cjs +214 -0
- package/dist/oraclePro.cjs.map +1 -0
- package/dist/oraclePro.d.cts +92 -0
- package/dist/oraclePro.d.cts.map +1 -0
- package/dist/oraclePro.d.mts +92 -0
- package/dist/oraclePro.d.mts.map +1 -0
- package/dist/oraclePro.mjs +196 -0
- package/dist/oraclePro.mjs.map +1 -0
- package/dist/pythProClient.cjs +277 -0
- package/dist/pythProClient.cjs.map +1 -0
- package/dist/pythProClient.d.cts +143 -0
- package/dist/pythProClient.d.cts.map +1 -0
- package/dist/pythProClient.d.mts +143 -0
- package/dist/pythProClient.d.mts.map +1 -0
- package/dist/pythProClient.mjs +269 -0
- package/dist/pythProClient.mjs.map +1 -0
- package/dist/storkClient.cjs +217 -0
- package/dist/storkClient.cjs.map +1 -0
- package/dist/storkClient.d.cts +90 -0
- package/dist/storkClient.d.cts.map +1 -0
- package/dist/storkClient.d.mts +90 -0
- package/dist/storkClient.d.mts.map +1 -0
- package/dist/storkClient.mjs +208 -0
- package/dist/storkClient.mjs.map +1 -0
- package/dist/storkOracle.cjs +61 -0
- package/dist/storkOracle.cjs.map +1 -0
- package/dist/storkOracle.d.cts +21 -0
- package/dist/storkOracle.d.cts.map +1 -0
- package/dist/storkOracle.d.mts +21 -0
- package/dist/storkOracle.d.mts.map +1 -0
- package/dist/storkOracle.mjs +56 -0
- package/dist/storkOracle.mjs.map +1 -0
- package/package.json +1 -1
- package/src/abstract/BaseDataAPI.ts +1 -1
- package/src/consts/deployments-usdz-mainnet.json +1 -1
- package/src/consts/deployments-zo-oracle-mainnet.json +329 -0
- package/src/consts/index.ts +80 -0
- package/src/data.ts +1 -1
- package/src/implementations/USDZAPI.ts +731 -101
- package/src/implementations/USDZDataAPI.ts +42 -0
- package/src/index.ts +3 -0
- package/src/interfaces/base.ts +54 -1
- package/src/interfaces/usdz.ts +125 -0
- package/src/oracle.ts +222 -1
- package/src/oraclePro.ts +312 -0
- package/src/pythProClient.ts +406 -0
- package/src/storkClient.ts +328 -0
- package/src/storkOracle.ts +82 -0
- package/tests/pythProClient.test.ts +155 -0
- package/tests/storkClient.test.ts +316 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/** Kronos Pyth Pro (Pyth Lazer) REST + WebSocket client. */
|
|
2
|
+
export type PythProChannel = 'real_time' | 'fixed_rate@50ms' | 'fixed_rate@200ms' | 'fixed_rate@1000ms';
|
|
3
|
+
export interface PythProPriceFeed {
|
|
4
|
+
priceFeedId: number;
|
|
5
|
+
price: string;
|
|
6
|
+
exponent: number;
|
|
7
|
+
confidence: string;
|
|
8
|
+
feedUpdateTimestamp: string;
|
|
9
|
+
priceUsd: number;
|
|
10
|
+
emaPrice?: string | null;
|
|
11
|
+
emaPriceUsd?: number | null;
|
|
12
|
+
}
|
|
13
|
+
export interface PythProLatestPriceData {
|
|
14
|
+
timestampUs: string;
|
|
15
|
+
priceFeeds: PythProPriceFeed[];
|
|
16
|
+
leEcdsaHex: string | null;
|
|
17
|
+
}
|
|
18
|
+
export interface PythProLatestPriceResponse {
|
|
19
|
+
success: boolean;
|
|
20
|
+
timestamp?: string;
|
|
21
|
+
data?: PythProLatestPriceData;
|
|
22
|
+
message?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface IGetLatestPythProPricesOptions {
|
|
25
|
+
priceFeedIds: number[];
|
|
26
|
+
channel?: PythProChannel;
|
|
27
|
+
includeEmaPrice?: boolean;
|
|
28
|
+
includeUpdateBytes?: boolean;
|
|
29
|
+
/** Override kronos REST base URL (default: `DEFAULT_API_ENDPOINT` or SDK instance apiEndpoint). */
|
|
30
|
+
kronosUrl?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface PythProStreamUpdate {
|
|
33
|
+
subscriptionId: number;
|
|
34
|
+
timestampUs: string;
|
|
35
|
+
priceFeeds: PythProPriceFeed[];
|
|
36
|
+
leEcdsaHex?: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface IPythProStreamSubscription {
|
|
39
|
+
subscriptionId: number;
|
|
40
|
+
priceFeedIds: number[];
|
|
41
|
+
channel?: PythProChannel;
|
|
42
|
+
includeEmaPrice?: boolean;
|
|
43
|
+
includeUpdateBytes?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export type PythProStreamServerMessage = {
|
|
46
|
+
type: 'connected';
|
|
47
|
+
message?: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'subscribed';
|
|
50
|
+
subscriptionId: number;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'unsubscribed';
|
|
53
|
+
subscriptionId: number;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'streamUpdated';
|
|
56
|
+
} & PythProStreamUpdate | {
|
|
57
|
+
type: 'subscriptionError';
|
|
58
|
+
subscriptionId: number;
|
|
59
|
+
message?: string;
|
|
60
|
+
} | {
|
|
61
|
+
type: 'subscribedWithInvalidFeedIdsIgnored';
|
|
62
|
+
subscriptionId: number;
|
|
63
|
+
ignoredFeedIds?: number[];
|
|
64
|
+
} | {
|
|
65
|
+
type: 'error';
|
|
66
|
+
message?: string;
|
|
67
|
+
} | {
|
|
68
|
+
type: 'pong';
|
|
69
|
+
};
|
|
70
|
+
export type PythProStreamClientMessage = {
|
|
71
|
+
type: 'subscribe';
|
|
72
|
+
} & IPythProStreamSubscription | {
|
|
73
|
+
type: 'unsubscribe';
|
|
74
|
+
subscriptionId: number;
|
|
75
|
+
} | {
|
|
76
|
+
type: 'ping';
|
|
77
|
+
};
|
|
78
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
79
|
+
/** Derive ws(s):// stream URL from kronos http(s) base URL. */
|
|
80
|
+
export declare function apiBaseUrlToPythProWsUrl(baseUrl: string): string;
|
|
81
|
+
/**
|
|
82
|
+
* Fetch latest Pyth Pro prices from kronos REST (`GET` or `POST /pyth-pro/latest-price`).
|
|
83
|
+
*/
|
|
84
|
+
export declare function getLatestPythProPrices(baseUrl: string, options: IGetLatestPythProPricesOptions): Promise<PythProLatestPriceData>;
|
|
85
|
+
/**
|
|
86
|
+
* Fetch leEcdsa update bytes via kronos (for on-chain `parse_and_verify_le_ecdsa_update_v2`).
|
|
87
|
+
*/
|
|
88
|
+
export declare function fetchPythProUpdateBytesFromKronos(baseUrl: string, feedIds: number[], options?: Pick<IGetLatestPythProPricesOptions, 'channel' | 'includeEmaPrice'>): Promise<Uint8Array>;
|
|
89
|
+
export interface IPythProStreamClientOptions {
|
|
90
|
+
/** Defaults to apiBaseUrlToPythProWsUrl(baseUrl). */
|
|
91
|
+
wsUrl?: string;
|
|
92
|
+
/** Reconnect after disconnect. Default true. */
|
|
93
|
+
autoReconnect?: boolean;
|
|
94
|
+
/** Initial reconnect delay in ms. Default 1000. */
|
|
95
|
+
reconnectDelayMs?: number;
|
|
96
|
+
/** Ping interval in ms. Default 30000. Set 0 to disable. */
|
|
97
|
+
pingIntervalMs?: number;
|
|
98
|
+
/** Custom WebSocket constructor (Node test mocks, etc.). */
|
|
99
|
+
WebSocketImpl?: typeof WebSocket;
|
|
100
|
+
}
|
|
101
|
+
type StreamUpdateHandler = (update: PythProStreamUpdate) => void;
|
|
102
|
+
type StreamMessageHandler = (message: PythProStreamServerMessage) => void;
|
|
103
|
+
/**
|
|
104
|
+
* WebSocket client for kronos `/pyth-pro/stream`.
|
|
105
|
+
* Multiplexes subscriptions and re-subscribes after reconnect.
|
|
106
|
+
*/
|
|
107
|
+
export declare class PythProStreamClient {
|
|
108
|
+
private readonly wsUrl;
|
|
109
|
+
private readonly autoReconnect;
|
|
110
|
+
private readonly reconnectDelayMs;
|
|
111
|
+
private readonly pingIntervalMs;
|
|
112
|
+
private readonly WebSocketImpl;
|
|
113
|
+
private ws;
|
|
114
|
+
private connectPromise;
|
|
115
|
+
private reconnectTimer;
|
|
116
|
+
private pingTimer;
|
|
117
|
+
private closedByUser;
|
|
118
|
+
private readonly subscriptions;
|
|
119
|
+
private readonly updateHandlers;
|
|
120
|
+
private readonly messageHandlers;
|
|
121
|
+
constructor(baseUrl: string, options?: IPythProStreamClientOptions);
|
|
122
|
+
/** Open the WebSocket and wait for the server `connected` message (or socket open). */
|
|
123
|
+
connect(): Promise<void>;
|
|
124
|
+
disconnect(): void;
|
|
125
|
+
/**
|
|
126
|
+
* Subscribe to live price updates. Returns an unsubscribe function.
|
|
127
|
+
* `onUpdate` is called for each `streamUpdated` matching `subscriptionId`.
|
|
128
|
+
*/
|
|
129
|
+
subscribe(options: IPythProStreamSubscription, onUpdate: StreamUpdateHandler): () => void;
|
|
130
|
+
/** Remove one handler or the whole subscription when `onUpdate` is omitted. */
|
|
131
|
+
unsubscribe(subscriptionId: number, onUpdate?: StreamUpdateHandler): void;
|
|
132
|
+
onMessage(handler: StreamMessageHandler): () => void;
|
|
133
|
+
private send;
|
|
134
|
+
private resubscribeAll;
|
|
135
|
+
private scheduleReconnect;
|
|
136
|
+
private clearReconnect;
|
|
137
|
+
private startPing;
|
|
138
|
+
private stopPing;
|
|
139
|
+
private emitMessage;
|
|
140
|
+
private handleMessage;
|
|
141
|
+
}
|
|
142
|
+
export {};
|
|
143
|
+
//# sourceMappingURL=pythProClient.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pythProClient.d.mts","sourceRoot":"","sources":["../src/pythProClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/** Kronos Pyth Pro (Pyth Lazer) REST + WebSocket client. */
|
|
2
|
+
export function hexToBytes(hex) {
|
|
3
|
+
const normalized = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
4
|
+
const bytes = new Uint8Array(normalized.length / 2);
|
|
5
|
+
for (let i = 0; i < normalized.length; i += 2) {
|
|
6
|
+
bytes[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
|
|
7
|
+
}
|
|
8
|
+
return bytes;
|
|
9
|
+
}
|
|
10
|
+
/** Derive ws(s):// stream URL from kronos http(s) base URL. */
|
|
11
|
+
export function apiBaseUrlToPythProWsUrl(baseUrl) {
|
|
12
|
+
const url = new URL(baseUrl);
|
|
13
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
14
|
+
url.pathname = '/pyth-pro/stream';
|
|
15
|
+
url.search = '';
|
|
16
|
+
url.hash = '';
|
|
17
|
+
return url.toString();
|
|
18
|
+
}
|
|
19
|
+
function normalizeBaseUrl(baseUrl) {
|
|
20
|
+
return baseUrl.replace(/\/+$/, '');
|
|
21
|
+
}
|
|
22
|
+
function parseLatestPriceResponse(json) {
|
|
23
|
+
if (!json.success || !json.data) {
|
|
24
|
+
throw new Error(json.message ?? 'Pyth Pro latest-price request failed');
|
|
25
|
+
}
|
|
26
|
+
return json.data;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Fetch latest Pyth Pro prices from kronos REST (`GET` or `POST /pyth-pro/latest-price`).
|
|
30
|
+
*/
|
|
31
|
+
export async function getLatestPythProPrices(baseUrl, options) {
|
|
32
|
+
const { priceFeedIds, channel, includeEmaPrice, includeUpdateBytes } = options;
|
|
33
|
+
if (priceFeedIds.length === 0) {
|
|
34
|
+
throw new Error('priceFeedIds is required');
|
|
35
|
+
}
|
|
36
|
+
const root = normalizeBaseUrl(baseUrl);
|
|
37
|
+
if (priceFeedIds.length <= 20) {
|
|
38
|
+
const params = new URLSearchParams();
|
|
39
|
+
params.set('priceFeedIds', priceFeedIds.join(','));
|
|
40
|
+
if (channel) {
|
|
41
|
+
params.set('channel', channel);
|
|
42
|
+
}
|
|
43
|
+
if (includeEmaPrice) {
|
|
44
|
+
params.set('includeEmaPrice', 'true');
|
|
45
|
+
}
|
|
46
|
+
if (includeUpdateBytes) {
|
|
47
|
+
params.set('includeUpdateBytes', 'true');
|
|
48
|
+
}
|
|
49
|
+
const res = await fetch(`${root}/pyth-pro/latest-price?${params}`);
|
|
50
|
+
const json = await res.json();
|
|
51
|
+
if (!res.ok && json.message) {
|
|
52
|
+
throw new Error(json.message);
|
|
53
|
+
}
|
|
54
|
+
return parseLatestPriceResponse(json);
|
|
55
|
+
}
|
|
56
|
+
const res = await fetch(`${root}/pyth-pro/latest-price`, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: { 'Content-Type': 'application/json' },
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
priceFeedIds,
|
|
61
|
+
channel,
|
|
62
|
+
includeEmaPrice: includeEmaPrice ?? false,
|
|
63
|
+
includeUpdateBytes: includeUpdateBytes ?? false,
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
const json = await res.json();
|
|
67
|
+
if (!res.ok && json.message) {
|
|
68
|
+
throw new Error(json.message);
|
|
69
|
+
}
|
|
70
|
+
return parseLatestPriceResponse(json);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Fetch leEcdsa update bytes via kronos (for on-chain `parse_and_verify_le_ecdsa_update_v2`).
|
|
74
|
+
*/
|
|
75
|
+
export async function fetchPythProUpdateBytesFromKronos(baseUrl, feedIds, options) {
|
|
76
|
+
const data = await getLatestPythProPrices(baseUrl, {
|
|
77
|
+
priceFeedIds: feedIds,
|
|
78
|
+
channel: options?.channel,
|
|
79
|
+
includeEmaPrice: options?.includeEmaPrice,
|
|
80
|
+
includeUpdateBytes: true,
|
|
81
|
+
});
|
|
82
|
+
if (!data.leEcdsaHex) {
|
|
83
|
+
throw new Error('No leEcdsaHex in kronos Pyth Pro response (set includeUpdateBytes: true)');
|
|
84
|
+
}
|
|
85
|
+
return hexToBytes(data.leEcdsaHex);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* WebSocket client for kronos `/pyth-pro/stream`.
|
|
89
|
+
* Multiplexes subscriptions and re-subscribes after reconnect.
|
|
90
|
+
*/
|
|
91
|
+
export class PythProStreamClient {
|
|
92
|
+
constructor(baseUrl, options) {
|
|
93
|
+
this.ws = null;
|
|
94
|
+
this.connectPromise = null;
|
|
95
|
+
this.reconnectTimer = null;
|
|
96
|
+
this.pingTimer = null;
|
|
97
|
+
this.closedByUser = false;
|
|
98
|
+
this.subscriptions = new Map();
|
|
99
|
+
this.updateHandlers = new Map();
|
|
100
|
+
this.messageHandlers = new Set();
|
|
101
|
+
this.wsUrl = options?.wsUrl ?? apiBaseUrlToPythProWsUrl(baseUrl);
|
|
102
|
+
this.autoReconnect = options?.autoReconnect ?? true;
|
|
103
|
+
this.reconnectDelayMs = options?.reconnectDelayMs ?? 1000;
|
|
104
|
+
this.pingIntervalMs = options?.pingIntervalMs ?? 30000;
|
|
105
|
+
this.WebSocketImpl = options?.WebSocketImpl ?? WebSocket;
|
|
106
|
+
}
|
|
107
|
+
/** Open the WebSocket and wait for the server `connected` message (or socket open). */
|
|
108
|
+
connect() {
|
|
109
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
110
|
+
return Promise.resolve();
|
|
111
|
+
}
|
|
112
|
+
if (this.connectPromise) {
|
|
113
|
+
return this.connectPromise;
|
|
114
|
+
}
|
|
115
|
+
this.closedByUser = false;
|
|
116
|
+
this.connectPromise = new Promise((resolve, reject) => {
|
|
117
|
+
const ws = new this.WebSocketImpl(this.wsUrl);
|
|
118
|
+
this.ws = ws;
|
|
119
|
+
const onOpen = () => {
|
|
120
|
+
this.startPing();
|
|
121
|
+
this.resubscribeAll();
|
|
122
|
+
resolve();
|
|
123
|
+
};
|
|
124
|
+
const onError = (event) => {
|
|
125
|
+
if (ws.readyState !== WebSocket.OPEN) {
|
|
126
|
+
reject(new Error(`Pyth Pro WebSocket connection failed: ${this.wsUrl}`));
|
|
127
|
+
}
|
|
128
|
+
this.emitMessage({ type: 'error', message: String(event) });
|
|
129
|
+
};
|
|
130
|
+
ws.addEventListener('open', onOpen, { once: true });
|
|
131
|
+
ws.addEventListener('error', onError, { once: true });
|
|
132
|
+
ws.addEventListener('message', (event) => {
|
|
133
|
+
this.handleMessage(String(event.data));
|
|
134
|
+
});
|
|
135
|
+
ws.addEventListener('close', () => {
|
|
136
|
+
this.stopPing();
|
|
137
|
+
this.ws = null;
|
|
138
|
+
this.connectPromise = null;
|
|
139
|
+
if (!this.closedByUser && this.autoReconnect) {
|
|
140
|
+
this.scheduleReconnect();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
return this.connectPromise;
|
|
145
|
+
}
|
|
146
|
+
disconnect() {
|
|
147
|
+
this.closedByUser = true;
|
|
148
|
+
this.clearReconnect();
|
|
149
|
+
this.stopPing();
|
|
150
|
+
if (this.ws) {
|
|
151
|
+
this.ws.close();
|
|
152
|
+
this.ws = null;
|
|
153
|
+
}
|
|
154
|
+
this.connectPromise = null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Subscribe to live price updates. Returns an unsubscribe function.
|
|
158
|
+
* `onUpdate` is called for each `streamUpdated` matching `subscriptionId`.
|
|
159
|
+
*/
|
|
160
|
+
subscribe(options, onUpdate) {
|
|
161
|
+
this.subscriptions.set(options.subscriptionId, options);
|
|
162
|
+
let handlers = this.updateHandlers.get(options.subscriptionId);
|
|
163
|
+
if (!handlers) {
|
|
164
|
+
handlers = new Set();
|
|
165
|
+
this.updateHandlers.set(options.subscriptionId, handlers);
|
|
166
|
+
}
|
|
167
|
+
handlers.add(onUpdate);
|
|
168
|
+
void this.connect().then(() => {
|
|
169
|
+
this.send({ type: 'subscribe', ...options });
|
|
170
|
+
});
|
|
171
|
+
return () => {
|
|
172
|
+
this.unsubscribe(options.subscriptionId, onUpdate);
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** Remove one handler or the whole subscription when `onUpdate` is omitted. */
|
|
176
|
+
unsubscribe(subscriptionId, onUpdate) {
|
|
177
|
+
const handlers = this.updateHandlers.get(subscriptionId);
|
|
178
|
+
if (onUpdate && handlers) {
|
|
179
|
+
handlers.delete(onUpdate);
|
|
180
|
+
if (handlers.size > 0) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
this.updateHandlers.delete(subscriptionId);
|
|
185
|
+
this.subscriptions.delete(subscriptionId);
|
|
186
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
187
|
+
this.send({ type: 'unsubscribe', subscriptionId });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
onMessage(handler) {
|
|
191
|
+
this.messageHandlers.add(handler);
|
|
192
|
+
return () => {
|
|
193
|
+
this.messageHandlers.delete(handler);
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
send(message) {
|
|
197
|
+
if (this.ws?.readyState !== WebSocket.OPEN) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
this.ws.send(JSON.stringify(message));
|
|
201
|
+
}
|
|
202
|
+
resubscribeAll() {
|
|
203
|
+
for (const sub of this.subscriptions.values()) {
|
|
204
|
+
this.send({ type: 'subscribe', ...sub });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
scheduleReconnect() {
|
|
208
|
+
if (this.reconnectTimer) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
this.reconnectTimer = setTimeout(() => {
|
|
212
|
+
this.reconnectTimer = null;
|
|
213
|
+
void this.connect().catch(() => {
|
|
214
|
+
this.scheduleReconnect();
|
|
215
|
+
});
|
|
216
|
+
}, this.reconnectDelayMs);
|
|
217
|
+
}
|
|
218
|
+
clearReconnect() {
|
|
219
|
+
if (this.reconnectTimer) {
|
|
220
|
+
clearTimeout(this.reconnectTimer);
|
|
221
|
+
this.reconnectTimer = null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
startPing() {
|
|
225
|
+
if (this.pingIntervalMs <= 0) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
this.stopPing();
|
|
229
|
+
this.pingTimer = setInterval(() => {
|
|
230
|
+
this.send({ type: 'ping' });
|
|
231
|
+
}, this.pingIntervalMs);
|
|
232
|
+
}
|
|
233
|
+
stopPing() {
|
|
234
|
+
if (this.pingTimer) {
|
|
235
|
+
clearInterval(this.pingTimer);
|
|
236
|
+
this.pingTimer = null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
emitMessage(message) {
|
|
240
|
+
for (const handler of this.messageHandlers) {
|
|
241
|
+
handler(message);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
handleMessage(raw) {
|
|
245
|
+
let message;
|
|
246
|
+
try {
|
|
247
|
+
message = JSON.parse(raw);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
this.emitMessage({ type: 'error', message: `Invalid JSON: ${raw}` });
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
this.emitMessage(message);
|
|
254
|
+
if (message.type === 'streamUpdated') {
|
|
255
|
+
const handlers = this.updateHandlers.get(message.subscriptionId);
|
|
256
|
+
if (handlers) {
|
|
257
|
+
for (const handler of handlers) {
|
|
258
|
+
handler({
|
|
259
|
+
subscriptionId: message.subscriptionId,
|
|
260
|
+
timestampUs: message.timestampUs,
|
|
261
|
+
priceFeeds: message.priceFeeds,
|
|
262
|
+
leEcdsaHex: message.leEcdsaHex,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=pythProClient.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pythProClient.mjs","sourceRoot":"","sources":["../src/pythProClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Kronos Stork price REST client + update payload parsing. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.hexToBytes = hexToBytes;
|
|
5
|
+
exports.base64ToBytes = base64ToBytes;
|
|
6
|
+
exports.parseStorkUpdateDataRaw = parseStorkUpdateDataRaw;
|
|
7
|
+
exports.buildStorkUpdateDataFromSignedPrice = buildStorkUpdateDataFromSignedPrice;
|
|
8
|
+
exports.parseStorkUpdateDataList = parseStorkUpdateDataList;
|
|
9
|
+
exports.getLatestStorkPrices = getLatestStorkPrices;
|
|
10
|
+
exports.fetchStorkUpdateDataFromKronos = fetchStorkUpdateDataFromKronos;
|
|
11
|
+
function normalizeBaseUrl(baseUrl) {
|
|
12
|
+
return baseUrl.replace(/\/+$/, '');
|
|
13
|
+
}
|
|
14
|
+
function parseLatestStorkResponse(json) {
|
|
15
|
+
if (!json.success || !json.data) {
|
|
16
|
+
throw new Error(json.message ?? 'Stork latest-price request failed');
|
|
17
|
+
}
|
|
18
|
+
return json.data;
|
|
19
|
+
}
|
|
20
|
+
function hexToBytes(hex) {
|
|
21
|
+
const normalized = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
22
|
+
if (normalized.length % 2 !== 0) {
|
|
23
|
+
throw new Error(`Invalid hex length: ${hex}`);
|
|
24
|
+
}
|
|
25
|
+
const bytes = new Uint8Array(normalized.length / 2);
|
|
26
|
+
for (let i = 0; i < normalized.length; i += 2) {
|
|
27
|
+
bytes[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
|
|
28
|
+
}
|
|
29
|
+
return bytes;
|
|
30
|
+
}
|
|
31
|
+
function base64ToBytes(base64) {
|
|
32
|
+
const normalized = base64.replaceAll('-', '+').replaceAll('_', '/');
|
|
33
|
+
const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);
|
|
34
|
+
const binary = atob(padded);
|
|
35
|
+
const bytes = new Uint8Array(binary.length);
|
|
36
|
+
for (let i = 0; i < binary.length; i++) {
|
|
37
|
+
bytes[i] = binary.charCodeAt(i);
|
|
38
|
+
}
|
|
39
|
+
return bytes;
|
|
40
|
+
}
|
|
41
|
+
function toBytes(value, field) {
|
|
42
|
+
if (value === undefined || value === null) {
|
|
43
|
+
throw new Error(`Missing Stork field: ${field}`);
|
|
44
|
+
}
|
|
45
|
+
if (value instanceof Uint8Array) {
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
return Uint8Array.from(value);
|
|
50
|
+
}
|
|
51
|
+
if (value.startsWith('0x') || /^[0-9a-f]+$/i.test(value)) {
|
|
52
|
+
return hexToBytes(value);
|
|
53
|
+
}
|
|
54
|
+
return base64ToBytes(value);
|
|
55
|
+
}
|
|
56
|
+
function toBigInt(value) {
|
|
57
|
+
if (value === undefined || value === null) {
|
|
58
|
+
return 0n;
|
|
59
|
+
}
|
|
60
|
+
if (typeof value === 'bigint') {
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
if (typeof value === 'string') {
|
|
64
|
+
return BigInt(value);
|
|
65
|
+
}
|
|
66
|
+
// `value` is already a float64 at this point — any u64 > 2^53 has already lost
|
|
67
|
+
// precision before reaching here. String(n) round-trips the truncated float64,
|
|
68
|
+
// not the original integer. Callers should pass string timestamps from the API
|
|
69
|
+
// to avoid this loss.
|
|
70
|
+
return BigInt(String(value));
|
|
71
|
+
}
|
|
72
|
+
function parseV(value) {
|
|
73
|
+
if (typeof value === 'number') {
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
const bytes = toBytes(value, 'v');
|
|
77
|
+
if (bytes.length > 0) {
|
|
78
|
+
return bytes[0];
|
|
79
|
+
}
|
|
80
|
+
if (value.startsWith('0x')) {
|
|
81
|
+
return Number.parseInt(value, 16);
|
|
82
|
+
}
|
|
83
|
+
return Number.parseInt(value, 10);
|
|
84
|
+
}
|
|
85
|
+
function parseStorkUpdateDataRaw(raw) {
|
|
86
|
+
const id = toBytes(raw.id, 'id');
|
|
87
|
+
if (id.length !== 32) {
|
|
88
|
+
throw new Error(`Stork update id must be 32 bytes, got ${id.length}`);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
id,
|
|
92
|
+
temporalNumericValueTimestampNs: toBigInt(raw.temporal_numeric_value_timestamp_ns),
|
|
93
|
+
temporalNumericValueMagnitude: toBigInt(raw.temporal_numeric_value_magnitude),
|
|
94
|
+
temporalNumericValueNegative: raw.temporal_numeric_value_negative ?? false,
|
|
95
|
+
publisherMerkleRoot: toBytes(raw.publisher_merkle_root, 'publisher_merkle_root'),
|
|
96
|
+
valueComputeAlgHash: toBytes(raw.value_compute_alg_hash, 'value_compute_alg_hash'),
|
|
97
|
+
r: toBytes(raw.r, 'r'),
|
|
98
|
+
s: toBytes(raw.s, 's'),
|
|
99
|
+
v: parseV(raw.v ?? 0),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function parseQuantizedPrice(value) {
|
|
103
|
+
let price = BigInt(value);
|
|
104
|
+
const negative = price < 0n;
|
|
105
|
+
if (negative) {
|
|
106
|
+
price = -price;
|
|
107
|
+
}
|
|
108
|
+
return { magnitude: price, negative };
|
|
109
|
+
}
|
|
110
|
+
/** Build on-chain update data from kronos / Stork REST signed price payload. */
|
|
111
|
+
function buildStorkUpdateDataFromSignedPrice(entry,
|
|
112
|
+
/** Fallback 32-byte feeder id when `encoded_asset_id` is absent. */
|
|
113
|
+
feederId) {
|
|
114
|
+
const signed = entry.stork_signed_price;
|
|
115
|
+
if (signed?.timestamped_signature?.signature) {
|
|
116
|
+
const checksum = signed.calculation_alg?.checksum;
|
|
117
|
+
if (!checksum) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const quantizedPrice = signed.quantized_price ?? signed.price ?? entry.price;
|
|
121
|
+
if (!quantizedPrice) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const assetId = signed.encoded_asset_id;
|
|
125
|
+
if (!assetId && !feederId) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const { magnitude, negative } = parseQuantizedPrice(String(quantizedPrice));
|
|
129
|
+
// Nanosecond timestamps for dates in 2026+ (~1.78e18 ns) exceed float64 safe-integer
|
|
130
|
+
// range (2^53 ≈ 9e15). JSON.parse silently truncates them by up to ±127 ns (precision
|
|
131
|
+
// step = 256 at this scale), causing get_stork_message_hash to produce the wrong value
|
|
132
|
+
// and ecrecover to fail → EInvalidSignature (error code 0).
|
|
133
|
+
// Prefer string sources; fall back to update_data.temporal_numeric_value_timestamp_ns
|
|
134
|
+
// (a string in kronos pre-parsed payloads) when stork_signed_price only has a number.
|
|
135
|
+
const rawTimestampNs = signed.timestamped_signature.timestamp_nano
|
|
136
|
+
?? signed.timestamped_signature.timestamp
|
|
137
|
+
?? entry.timestamp;
|
|
138
|
+
const timestampNs = (typeof rawTimestampNs === 'number'
|
|
139
|
+
&& typeof entry.update_data?.temporal_numeric_value_timestamp_ns === 'string')
|
|
140
|
+
? entry.update_data.temporal_numeric_value_timestamp_ns
|
|
141
|
+
: rawTimestampNs;
|
|
142
|
+
const id = assetId
|
|
143
|
+
? toBytes(assetId, 'encoded_asset_id')
|
|
144
|
+
: feederId;
|
|
145
|
+
return {
|
|
146
|
+
id,
|
|
147
|
+
temporalNumericValueTimestampNs: toBigInt(timestampNs),
|
|
148
|
+
temporalNumericValueMagnitude: magnitude,
|
|
149
|
+
temporalNumericValueNegative: negative,
|
|
150
|
+
publisherMerkleRoot: toBytes(signed.publisher_merkle_root, 'publisher_merkle_root'),
|
|
151
|
+
valueComputeAlgHash: toBytes(checksum, 'value_compute_alg_hash'),
|
|
152
|
+
r: toBytes(signed.timestamped_signature.signature.r, 'r'),
|
|
153
|
+
s: toBytes(signed.timestamped_signature.signature.s, 's'),
|
|
154
|
+
v: parseV(signed.timestamped_signature.signature.v),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (entry.update_data) {
|
|
158
|
+
return parseStorkUpdateDataRaw(entry.update_data);
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
function parseStorkUpdateDataList(data,
|
|
163
|
+
/** Stork asset symbol → 32-byte on-chain feeder id from zo-oracle config. */
|
|
164
|
+
assetIdByAsset) {
|
|
165
|
+
const updates = [];
|
|
166
|
+
for (const entry of Object.values(data.prices)) {
|
|
167
|
+
const feederId = assetIdByAsset?.get(entry.asset_id);
|
|
168
|
+
const update = buildStorkUpdateDataFromSignedPrice(entry, feederId);
|
|
169
|
+
if (update) {
|
|
170
|
+
if (update.id.length !== 32) {
|
|
171
|
+
throw new Error(`Stork asset ${entry.asset_id}: id must be 32 bytes (got ${update.id.length}); `
|
|
172
|
+
+ 'pass assetIdByAsset from buildStorkAssetIdMap()');
|
|
173
|
+
}
|
|
174
|
+
updates.push(update);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return updates;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Fetch latest Stork prices from kronos REST (`GET` or `POST /stork/latest-price`).
|
|
181
|
+
*/
|
|
182
|
+
async function getLatestStorkPrices(baseUrl, options) {
|
|
183
|
+
const { assets } = options;
|
|
184
|
+
if (assets.length === 0) {
|
|
185
|
+
throw new Error('assets is required');
|
|
186
|
+
}
|
|
187
|
+
const root = normalizeBaseUrl(baseUrl);
|
|
188
|
+
if (assets.length <= 20) {
|
|
189
|
+
const params = new URLSearchParams();
|
|
190
|
+
params.set('assets', assets.join(','));
|
|
191
|
+
const res = await fetch(`${root}/stork/latest-price?${params}`);
|
|
192
|
+
const json = await res.json();
|
|
193
|
+
if (!res.ok && json.message) {
|
|
194
|
+
throw new Error(json.message);
|
|
195
|
+
}
|
|
196
|
+
return parseLatestStorkResponse(json);
|
|
197
|
+
}
|
|
198
|
+
const res = await fetch(`${root}/stork/latest-price`, {
|
|
199
|
+
method: 'POST',
|
|
200
|
+
headers: { 'Content-Type': 'application/json' },
|
|
201
|
+
body: JSON.stringify({ assets }),
|
|
202
|
+
});
|
|
203
|
+
const json = await res.json();
|
|
204
|
+
if (!res.ok && json.message) {
|
|
205
|
+
throw new Error(json.message);
|
|
206
|
+
}
|
|
207
|
+
return parseLatestStorkResponse(json);
|
|
208
|
+
}
|
|
209
|
+
async function fetchStorkUpdateDataFromKronos(baseUrl, assets, assetIdByAsset) {
|
|
210
|
+
const data = await getLatestStorkPrices(baseUrl, { assets });
|
|
211
|
+
const updates = parseStorkUpdateDataList(data, assetIdByAsset);
|
|
212
|
+
if (updates.length === 0) {
|
|
213
|
+
throw new Error(`No Stork update data returned for assets: ${assets.join(',')}`);
|
|
214
|
+
}
|
|
215
|
+
return updates;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=storkClient.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storkClient.cjs","sourceRoot":"","sources":["../src/storkClient.ts"],"names":[],"mappings":"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"}
|