@k256/sdk 0.1.6 → 0.2.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/README.md CHANGED
@@ -25,7 +25,7 @@ const client = new K256WebSocketClient({
25
25
 
26
26
  // Message callbacks
27
27
  onPoolUpdate: (update) => console.log('Pool:', update.data.poolAddress),
28
- onPriorityFees: (fees) => console.log('Fees:', fees.data.recommended),
28
+ onFeeMarket: (fees) => console.log('Fees:', fees.data.recommended),
29
29
  onBlockhash: (bh) => console.log('Blockhash:', bh.data.blockhash),
30
30
 
31
31
  // Connection callbacks
@@ -67,7 +67,7 @@ client.disconnect();
67
67
  | Type | Description |
68
68
  |------|-------------|
69
69
  | `pool_update` | DEX pool state change |
70
- | `priority_fees` | Fee estimates (~400ms updates) |
70
+ | `fee_market` | Per-writable-account fee market (~400ms updates) |
71
71
  | `blockhash` | Latest blockhash (~400ms updates) |
72
72
  | `quote` | Streaming quote update |
73
73
  | `subscribed` | Subscription confirmed |
package/dist/index.cjs CHANGED
@@ -23,8 +23,15 @@ function base58Encode(bytes) {
23
23
  return leadingZeros + digits.reverse().map((d) => BASE58_ALPHABET[d]).join("");
24
24
  }
25
25
  function base58Decode(str) {
26
+ if (str.length === 0) {
27
+ return new Uint8Array(0);
28
+ }
29
+ let leadingZeros = 0;
30
+ for (let i = 0; i < str.length && str[i] === "1"; i++) {
31
+ leadingZeros++;
32
+ }
26
33
  const bytes = [0];
27
- for (let i = 0; i < str.length; i++) {
34
+ for (let i = leadingZeros; i < str.length; i++) {
28
35
  const char = str[i];
29
36
  const value = BASE58_ALPHABET.indexOf(char);
30
37
  if (value === -1) {
@@ -41,10 +48,19 @@ function base58Decode(str) {
41
48
  carry >>= 8;
42
49
  }
43
50
  }
44
- for (let i = 0; i < str.length && str[i] === "1"; i++) {
45
- bytes.push(0);
51
+ bytes.reverse();
52
+ if (leadingZeros > 0 && bytes.length === 1 && bytes[0] === 0) {
53
+ return new Uint8Array(leadingZeros);
54
+ }
55
+ const startIdx = bytes.length > 1 && bytes[0] === 0 ? 1 : 0;
56
+ const result = new Uint8Array(leadingZeros + bytes.length - startIdx);
57
+ for (let i = 0; i < leadingZeros; i++) {
58
+ result[i] = 0;
46
59
  }
47
- return new Uint8Array(bytes.reverse());
60
+ for (let i = startIdx; i < bytes.length; i++) {
61
+ result[leadingZeros + i - startIdx] = bytes[i];
62
+ }
63
+ return result;
48
64
  }
49
65
  function isValidPubkey(address) {
50
66
  if (address.length < 32 || address.length > 44) {
@@ -93,6 +109,8 @@ var MessageType = {
93
109
  Heartbeat: 13,
94
110
  /** Batched pool updates for high throughput */
95
111
  PoolUpdateBatch: 14,
112
+ /** Block-level statistics (v3) */
113
+ BlockStats: 15,
96
114
  /** Error message (UTF-8 string) */
97
115
  Error: 255
98
116
  };
@@ -133,55 +151,75 @@ function decodeMessage(data) {
133
151
  return { type: "error", data: { message: text } };
134
152
  }
135
153
  case MessageType.PriorityFees: {
136
- if (payload.byteLength < 24) return null;
154
+ if (payload.byteLength < 42) return null;
137
155
  const slot = Number(payloadView.getBigUint64(0, true));
138
156
  const timestampMs = Number(payloadView.getBigUint64(8, true));
139
157
  const recommended = Number(payloadView.getBigUint64(16, true));
140
- const state = payload.byteLength > 24 ? payloadView.getUint8(24) : 1;
141
- const isStale = payload.byteLength > 25 ? payloadView.getUint8(25) !== 0 : false;
142
- let swapP50 = 0, swapP75 = 0, swapP90 = 0, swapP99 = 0;
143
- if (payload.byteLength >= 58) {
144
- swapP50 = Number(payloadView.getBigUint64(26, true));
145
- swapP75 = Number(payloadView.getBigUint64(34, true));
146
- swapP90 = Number(payloadView.getBigUint64(42, true));
147
- swapP99 = Number(payloadView.getBigUint64(50, true));
158
+ const state = payloadView.getUint8(24);
159
+ const isStale = payloadView.getUint8(25) !== 0;
160
+ const blockUtilizationPct = payloadView.getFloat32(26, true);
161
+ const blocksInWindow = payloadView.getUint32(30, true);
162
+ const accountCount = Number(payloadView.getBigUint64(34, true));
163
+ const accounts = [];
164
+ let offset = 42;
165
+ for (let i = 0; i < accountCount && offset + 92 <= payload.byteLength; i++) {
166
+ const pubkeyBytes = new Uint8Array(payload, offset, 32);
167
+ const pubkey = base58Encode(pubkeyBytes);
168
+ const totalTxs = payloadView.getUint32(offset + 32, true);
169
+ const activeSlots = payloadView.getUint32(offset + 36, true);
170
+ const cuConsumed = Number(payloadView.getBigUint64(offset + 40, true));
171
+ const utilizationPct = payloadView.getFloat32(offset + 48, true);
172
+ const p25 = Number(payloadView.getBigUint64(offset + 52, true));
173
+ const p50 = Number(payloadView.getBigUint64(offset + 60, true));
174
+ const p75 = Number(payloadView.getBigUint64(offset + 68, true));
175
+ const p90 = Number(payloadView.getBigUint64(offset + 76, true));
176
+ const minNonzeroPrice = Number(payloadView.getBigUint64(offset + 84, true));
177
+ accounts.push({
178
+ pubkey,
179
+ totalTxs,
180
+ activeSlots,
181
+ cuConsumed,
182
+ utilizationPct,
183
+ p25,
184
+ p50,
185
+ p75,
186
+ p90,
187
+ minNonzeroPrice
188
+ });
189
+ offset += 92;
148
190
  }
149
- let swapSamples = 0;
150
- let landingP50Fee = 0, landingP75Fee = 0, landingP90Fee = 0, landingP99Fee = 0;
151
- let top10Fee = 0, top25Fee = 0;
152
- let spikeDetected = false, spikeFee = 0;
153
- if (payload.byteLength >= 119) {
154
- swapSamples = payloadView.getUint32(58, true);
155
- landingP50Fee = Number(payloadView.getBigUint64(62, true));
156
- landingP75Fee = Number(payloadView.getBigUint64(70, true));
157
- landingP90Fee = Number(payloadView.getBigUint64(78, true));
158
- landingP99Fee = Number(payloadView.getBigUint64(86, true));
159
- top10Fee = Number(payloadView.getBigUint64(94, true));
160
- top25Fee = Number(payloadView.getBigUint64(102, true));
161
- spikeDetected = payloadView.getUint8(110) !== 0;
162
- spikeFee = Number(payloadView.getBigUint64(111, true));
191
+ const recentBlocksCount = Number(payloadView.getBigUint64(offset, true));
192
+ offset += 8;
193
+ const recentBlocks = [];
194
+ for (let i = 0; i < recentBlocksCount; i++) {
195
+ const rbSlot = Number(payloadView.getBigUint64(offset, true));
196
+ offset += 8;
197
+ const rbCuConsumed = Number(payloadView.getBigUint64(offset, true));
198
+ offset += 8;
199
+ const rbTxCount = payloadView.getUint32(offset, true);
200
+ offset += 4;
201
+ const rbUtilizationPct = payloadView.getFloat32(offset, true);
202
+ offset += 4;
203
+ const rbAvgCuPrice = Number(payloadView.getBigUint64(offset, true));
204
+ offset += 8;
205
+ recentBlocks.push({ slot: rbSlot, cuConsumed: rbCuConsumed, txCount: rbTxCount, utilizationPct: rbUtilizationPct, avgCuPrice: rbAvgCuPrice });
163
206
  }
207
+ const trendByte = payloadView.getUint8(offset);
208
+ offset += 1;
209
+ const trend = trendByte === 0 ? "rising" : trendByte === 1 ? "falling" : "stable";
164
210
  return {
165
- type: "priority_fees",
211
+ type: "fee_market",
166
212
  data: {
167
213
  slot,
168
214
  timestampMs,
169
215
  recommended,
170
216
  state,
171
217
  isStale,
172
- swapP50,
173
- swapP75,
174
- swapP90,
175
- swapP99,
176
- swapSamples,
177
- landingP50Fee,
178
- landingP75Fee,
179
- landingP90Fee,
180
- landingP99Fee,
181
- top10Fee,
182
- top25Fee,
183
- spikeDetected,
184
- spikeFee
218
+ blockUtilizationPct,
219
+ blocksInWindow,
220
+ accounts,
221
+ recentBlocks,
222
+ trend
185
223
  }
186
224
  };
187
225
  }
@@ -226,6 +264,51 @@ function decodeMessage(data) {
226
264
  }
227
265
  };
228
266
  }
267
+ case MessageType.BlockStats: {
268
+ let offset = 0;
269
+ const slot = Number(payloadView.getBigUint64(offset, true));
270
+ offset += 8;
271
+ const cuConsumed = Number(payloadView.getBigUint64(offset, true));
272
+ offset += 8;
273
+ const executionCu = Number(payloadView.getBigUint64(offset, true));
274
+ offset += 8;
275
+ const cuLimit = Number(payloadView.getBigUint64(offset, true));
276
+ offset += 8;
277
+ const cuRemaining = Number(payloadView.getBigUint64(offset, true));
278
+ offset += 8;
279
+ const utilizationPct = payloadView.getFloat32(offset, true);
280
+ offset += 4;
281
+ const txCount = payloadView.getUint32(offset, true);
282
+ offset += 4;
283
+ const avgCuPerTx = payloadView.getUint32(offset, true);
284
+ offset += 4;
285
+ const avgCuPrice = Number(payloadView.getBigUint64(offset, true));
286
+ offset += 8;
287
+ const minCuPrice = Number(payloadView.getBigUint64(offset, true));
288
+ offset += 8;
289
+ const maxCuPrice = Number(payloadView.getBigUint64(offset, true));
290
+ offset += 8;
291
+ const timestampMs = Number(payloadView.getBigUint64(offset, true));
292
+ offset += 8;
293
+ return {
294
+ type: "block_stats",
295
+ data: {
296
+ slot,
297
+ cuConsumed,
298
+ executionCu,
299
+ cuLimit,
300
+ cuRemaining,
301
+ utilizationPct,
302
+ txCount,
303
+ avgCuPerTx,
304
+ avgCuPrice,
305
+ minCuPrice,
306
+ maxCuPrice,
307
+ timestampMs
308
+ },
309
+ receivedAt: Date.now()
310
+ };
311
+ }
229
312
  default:
230
313
  return null;
231
314
  }
@@ -307,19 +390,7 @@ function decodePoolUpdate(payload, payloadView) {
307
390
  }
308
391
  };
309
392
  } catch {
310
- return {
311
- type: "pool_update",
312
- data: {
313
- sequence: 0,
314
- slot: 0,
315
- writeVersion: 0,
316
- protocol: "unknown",
317
- poolAddress: "",
318
- tokenMints: [],
319
- tokenBalances: [],
320
- tokenDecimals: []
321
- }
322
- };
393
+ return null;
323
394
  }
324
395
  }
325
396
  function decodeQuote(payload, payloadView) {
@@ -390,25 +461,7 @@ function decodeQuote(payload, payloadView) {
390
461
  }
391
462
  };
392
463
  } catch {
393
- return {
394
- type: "quote",
395
- data: {
396
- topicId: "",
397
- timestampMs: 0,
398
- sequence: 0,
399
- inputMint: "",
400
- outputMint: "",
401
- inAmount: "0",
402
- outAmount: "0",
403
- priceImpactBps: 0,
404
- contextSlot: 0,
405
- algorithm: "",
406
- isImprovement: false,
407
- isCached: false,
408
- isStale: false,
409
- routePlan: null
410
- }
411
- };
464
+ return null;
412
465
  }
413
466
  }
414
467
 
@@ -710,8 +763,11 @@ var K256WebSocketClient = class {
710
763
  case "pool_update":
711
764
  this.config.onPoolUpdate?.(decoded);
712
765
  break;
713
- case "priority_fees":
714
- this.config.onPriorityFees?.(decoded);
766
+ case "fee_market":
767
+ this.config.onFeeMarket?.(decoded);
768
+ break;
769
+ case "block_stats":
770
+ this.config.onBlockStats?.(decoded);
715
771
  break;
716
772
  case "blockhash":
717
773
  this.config.onBlockhash?.(decoded);