@k256/sdk 0.4.0 → 0.5.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/src/ws/decoder.ts CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { base58Encode } from '../utils/base58';
11
11
  import type { BlockMiniStats, TrendDirection } from '../types';
12
- import { MessageType, type DecodedMessage, type PoolUpdateMessage, type FeeMarketMessage } from './types';
12
+ import { MessageType, type DecodedMessage, type PoolUpdateMessage, type FeeMarketMessage, type PriceEntry, type PriceBatchMessage, type PriceSnapshotMessage } from './types';
13
13
 
14
14
  /**
15
15
  * Decode a binary WebSocket message from K2
@@ -232,11 +232,66 @@ export function decodeMessage(data: ArrayBuffer): DecodedMessage | null {
232
232
  };
233
233
  }
234
234
 
235
+ case MessageType.PriceUpdate: {
236
+ // Single price entry (56 bytes, no count prefix):
237
+ // [mint:32B][usd_price:u64 LE][slot:u64 LE][timestamp_ms:u64 LE]
238
+ // K2 currently doesn't send 0x11, but handle for forward compat.
239
+ if (payload.byteLength < 56) return null;
240
+ const mintBytes = new Uint8Array(payload, 0, 32);
241
+ return {
242
+ type: 'price_update',
243
+ data: {
244
+ mint: base58Encode(mintBytes),
245
+ usdPrice: Number(payloadView.getBigUint64(32, true)) / 1e12,
246
+ slot: Number(payloadView.getBigUint64(40, true)),
247
+ timestampMs: Number(payloadView.getBigUint64(48, true)),
248
+ },
249
+ };
250
+ }
251
+
252
+ case MessageType.PriceBatch:
253
+ case MessageType.PriceSnapshot: {
254
+ // Both use identical binary format from serialize_price_message():
255
+ // [count:u16 LE][entry₁:56B]...[entryₙ:56B]
256
+ // Each entry: [mint:32B][usd_price:u64 LE][slot:u64 LE][timestamp_ms:u64 LE]
257
+ if (payload.byteLength < 2) return null;
258
+ const entries = decodePriceEntries(payload);
259
+ const priceType = msgType === MessageType.PriceSnapshot ? 'price_snapshot' : 'price_batch';
260
+ return { type: priceType, data: entries } as PriceBatchMessage | PriceSnapshotMessage;
261
+ }
262
+
235
263
  default:
236
264
  return null;
237
265
  }
238
266
  }
239
267
 
268
+ /**
269
+ * Decode price entries from a PriceBatch or PriceSnapshot payload.
270
+ *
271
+ * Wire format: [count:u16 LE][entry₁:56B]...[entryₙ:56B]
272
+ */
273
+ export function decodePriceEntries(payload: ArrayBuffer): PriceEntry[] {
274
+ const view = new DataView(payload);
275
+ if (payload.byteLength < 2) return [];
276
+
277
+ const count = view.getUint16(0, true);
278
+ const entries: PriceEntry[] = [];
279
+ let offset = 2;
280
+
281
+ for (let i = 0; i < count && offset + 56 <= payload.byteLength; i++) {
282
+ const mintBytes = new Uint8Array(payload, offset, 32);
283
+ entries.push({
284
+ mint: base58Encode(mintBytes),
285
+ usdPrice: Number(view.getBigUint64(offset + 32, true)) / 1e12,
286
+ slot: Number(view.getBigUint64(offset + 40, true)),
287
+ timestampMs: Number(view.getBigUint64(offset + 48, true)),
288
+ });
289
+ offset += 56;
290
+ }
291
+
292
+ return entries;
293
+ }
294
+
240
295
  /**
241
296
  * Decode a batch of pool updates
242
297
  *
package/src/ws/index.ts CHANGED
@@ -33,10 +33,11 @@ export type {
33
33
  ConnectionState,
34
34
  SubscribeOptions,
35
35
  SubscribeQuoteOptions,
36
+ SubscribePriceOptions,
36
37
  } from './client';
37
38
 
38
39
  // Decoder (for advanced usage)
39
- export { decodeMessage, decodePoolUpdateBatch } from './decoder';
40
+ export { decodeMessage, decodePoolUpdateBatch, decodePriceEntries } from './decoder';
40
41
 
41
42
  // Types
42
43
  export { MessageType } from './types';
@@ -48,6 +49,10 @@ export type {
48
49
  BlockStatsMessage,
49
50
  BlockhashMessage,
50
51
  QuoteMessage,
52
+ PriceEntry,
53
+ PriceUpdateMessage,
54
+ PriceBatchMessage,
55
+ PriceSnapshotMessage,
51
56
  HeartbeatMessage,
52
57
  ErrorMessage,
53
58
  SubscribedMessage,
package/src/ws/types.ts CHANGED
@@ -44,6 +44,16 @@ export const MessageType = {
44
44
  PoolUpdateBatch: 0x0e,
45
45
  /** Block-level statistics (v3) */
46
46
  BlockStats: 0x0f,
47
+ /** Subscribe to price updates (JSON) - Client → Server */
48
+ SubscribePrice: 0x10,
49
+ /** Single price update (bincode 56B) - Server → Client */
50
+ PriceUpdate: 0x11,
51
+ /** Batched price updates (bincode [u16 count][entries...]) - Server → Client */
52
+ PriceBatch: 0x12,
53
+ /** Initial price snapshot (same binary format as PriceBatch) - Server → Client */
54
+ PriceSnapshot: 0x13,
55
+ /** Unsubscribe from prices (no payload) - Client → Server */
56
+ UnsubscribePrice: 0x14,
47
57
  /** Error message (UTF-8 string) */
48
58
  Error: 0xff,
49
59
  } as const;
@@ -214,6 +224,42 @@ export interface QuoteSubscribedMessage {
214
224
  };
215
225
  }
216
226
 
227
+ /**
228
+ * Single decoded price entry (shared by PriceUpdate, PriceBatch, PriceSnapshot)
229
+ */
230
+ export interface PriceEntry {
231
+ mint: string;
232
+ usdPrice: number;
233
+ slot: number;
234
+ timestampMs: number;
235
+ }
236
+
237
+ /**
238
+ * Single price update from binary message (0x11)
239
+ * Note: K2 currently sends all updates via PriceBatch (0x12)
240
+ */
241
+ export interface PriceUpdateMessage {
242
+ type: 'price_update';
243
+ data: PriceEntry;
244
+ }
245
+
246
+ /**
247
+ * Batched price updates from binary message (0x12)
248
+ */
249
+ export interface PriceBatchMessage {
250
+ type: 'price_batch';
251
+ data: PriceEntry[];
252
+ }
253
+
254
+ /**
255
+ * Initial price snapshot from binary message (0x13)
256
+ * Same binary format as PriceBatch — sent once after subscribe_price
257
+ */
258
+ export interface PriceSnapshotMessage {
259
+ type: 'price_snapshot';
260
+ data: PriceEntry[];
261
+ }
262
+
217
263
  /**
218
264
  * Error message from server
219
265
  */
@@ -243,6 +289,9 @@ export type DecodedMessage =
243
289
  | BlockStatsMessage
244
290
  | BlockhashMessage
245
291
  | QuoteMessage
292
+ | PriceUpdateMessage
293
+ | PriceBatchMessage
294
+ | PriceSnapshotMessage
246
295
  | HeartbeatMessage
247
296
  | SubscribedMessage
248
297
  | QuoteSubscribedMessage