@k256/sdk 0.1.7 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/ws/decoder.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import { base58Encode } from '../utils/base58';
11
+ import type { BlockMiniStats, TrendDirection } from '../types';
11
12
  import { MessageType, type DecodedMessage, type PoolUpdateMessage, type FeeMarketMessage } from './types';
12
13
 
13
14
  /**
@@ -116,11 +117,33 @@ export function decodeMessage(data: ArrayBuffer): DecodedMessage | null {
116
117
  offset += 92;
117
118
  }
118
119
 
120
+ // Decode recent_blocks (Vec<BlockMiniStats>) — v3
121
+ // Guard: need at least 8 bytes for count + 1 byte for trend after
122
+ const recentBlocksCount = offset + 8 <= payload.byteLength
123
+ ? Number(payloadView.getBigUint64(offset, true))
124
+ : 0;
125
+ offset += 8;
126
+ const recentBlocks: BlockMiniStats[] = [];
127
+ for (let i = 0; i < recentBlocksCount && offset + 32 <= payload.byteLength; i++) {
128
+ const rbSlot = Number(payloadView.getBigUint64(offset, true)); offset += 8;
129
+ const rbCuConsumed = Number(payloadView.getBigUint64(offset, true)); offset += 8;
130
+ const rbTxCount = payloadView.getUint32(offset, true); offset += 4;
131
+ const rbUtilizationPct = payloadView.getFloat32(offset, true); offset += 4;
132
+ const rbAvgCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
133
+ recentBlocks.push({ slot: rbSlot, cuConsumed: rbCuConsumed, txCount: rbTxCount, utilizationPct: rbUtilizationPct, avgCuPrice: rbAvgCuPrice });
134
+ }
135
+
136
+ // Decode trend (u8) — v3
137
+ const trendByte = offset < payload.byteLength ? payloadView.getUint8(offset) : 2;
138
+ offset += 1;
139
+ const trend: TrendDirection = trendByte === 0 ? 'rising' : trendByte === 1 ? 'falling' : 'stable';
140
+
119
141
  return {
120
142
  type: 'fee_market',
121
143
  data: {
122
144
  slot, timestampMs, recommended, state, isStale,
123
145
  blockUtilizationPct, blocksInWindow, accounts,
146
+ recentBlocks, trend,
124
147
  },
125
148
  } as FeeMarketMessage;
126
149
  }
@@ -180,6 +203,35 @@ export function decodeMessage(data: ArrayBuffer): DecodedMessage | null {
180
203
  };
181
204
  }
182
205
 
206
+ case MessageType.BlockStats: {
207
+ // BlockStats (0x0F) — v3
208
+ // Layout: slot(u64) + cu_consumed(u64) + execution_cu(u64) + cu_limit(u64) + cu_remaining(u64)
209
+ // + utilization_pct(f32) + tx_count(u32) + avg_cu_per_tx(u32) + avg_cu_price(u64)
210
+ // + min_cu_price(u64) + max_cu_price(u64) + timestamp_ms(u64)
211
+ let offset = 0; // payload already has type byte stripped
212
+ const slot = Number(payloadView.getBigUint64(offset, true)); offset += 8;
213
+ const cuConsumed = Number(payloadView.getBigUint64(offset, true)); offset += 8;
214
+ const executionCu = Number(payloadView.getBigUint64(offset, true)); offset += 8;
215
+ const cuLimit = Number(payloadView.getBigUint64(offset, true)); offset += 8;
216
+ const cuRemaining = Number(payloadView.getBigUint64(offset, true)); offset += 8;
217
+ const utilizationPct = payloadView.getFloat32(offset, true); offset += 4;
218
+ const txCount = payloadView.getUint32(offset, true); offset += 4;
219
+ const avgCuPerTx = payloadView.getUint32(offset, true); offset += 4;
220
+ const avgCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
221
+ const minCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
222
+ const maxCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
223
+ const timestampMs = Number(payloadView.getBigUint64(offset, true)); offset += 8;
224
+
225
+ return {
226
+ type: 'block_stats',
227
+ data: {
228
+ slot, cuConsumed, executionCu, cuLimit, cuRemaining, utilizationPct,
229
+ txCount, avgCuPerTx, avgCuPrice, minCuPrice, maxCuPrice, timestampMs,
230
+ },
231
+ receivedAt: Date.now(),
232
+ };
233
+ }
234
+
183
235
  default:
184
236
  return null;
185
237
  }
package/src/ws/index.ts CHANGED
@@ -45,6 +45,7 @@ export type {
45
45
  DecodedMessage,
46
46
  PoolUpdateMessage,
47
47
  FeeMarketMessage,
48
+ BlockStatsMessage,
48
49
  BlockhashMessage,
49
50
  QuoteMessage,
50
51
  HeartbeatMessage,
package/src/ws/types.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  * See: https://github.com/k256-xyz for protocol documentation
6
6
  */
7
7
 
8
+ import type { BlockMiniStats, TrendDirection, BlockStats } from '../types';
9
+
8
10
  /**
9
11
  * WebSocket message type constants
10
12
  *
@@ -40,6 +42,8 @@ export const MessageType = {
40
42
  Heartbeat: 0x0d,
41
43
  /** Batched pool updates for high throughput */
42
44
  PoolUpdateBatch: 0x0e,
45
+ /** Block-level statistics (v3) */
46
+ BlockStats: 0x0f,
43
47
  /** Error message (UTF-8 string) */
44
48
  Error: 0xff,
45
49
  } as const;
@@ -105,9 +109,22 @@ export interface FeeMarketMessage {
105
109
  /** Minimum non-zero fee observed */
106
110
  minNonzeroPrice: number;
107
111
  }[];
112
+ /** Recent block mini-stats (v3) */
113
+ recentBlocks: BlockMiniStats[];
114
+ /** Fee trend direction (v3) */
115
+ trend: TrendDirection;
108
116
  };
109
117
  }
110
118
 
119
+ /**
120
+ * Decoded block stats from binary message (v3)
121
+ */
122
+ export interface BlockStatsMessage {
123
+ type: 'block_stats';
124
+ data: BlockStats;
125
+ receivedAt: number;
126
+ }
127
+
111
128
  /**
112
129
  * Decoded blockhash from binary message
113
130
  */
@@ -223,6 +240,7 @@ export interface PongMessage {
223
240
  export type DecodedMessage =
224
241
  | PoolUpdateMessage
225
242
  | FeeMarketMessage
243
+ | BlockStatsMessage
226
244
  | BlockhashMessage
227
245
  | QuoteMessage
228
246
  | HeartbeatMessage