@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 +2 -2
- package/dist/index.cjs +131 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +131 -75
- package/dist/index.js.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +79 -10
- package/dist/types/index.d.ts +79 -10
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.cjs +20 -4
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js +20 -4
- package/dist/utils/index.js.map +1 -1
- package/dist/ws/index.cjs +111 -71
- package/dist/ws/index.cjs.map +1 -1
- package/dist/ws/index.d.cts +53 -24
- package/dist/ws/index.d.ts +53 -24
- package/dist/ws/index.js +111 -71
- package/dist/ws/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/types/index.ts +84 -11
- package/src/utils/base58.ts +35 -7
- package/src/ws/client.ts +11 -6
- package/src/ws/decoder.ts +94 -100
- package/src/ws/index.ts +2 -1
- package/src/ws/types.ts +49 -25
package/src/ws/decoder.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { base58Encode } from '../utils/base58';
|
|
11
|
-
import {
|
|
11
|
+
import type { BlockMiniStats, TrendDirection } from '../types';
|
|
12
|
+
import { MessageType, type DecodedMessage, type PoolUpdateMessage, type FeeMarketMessage } from './types';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Decode a binary WebSocket message from K2
|
|
@@ -69,84 +70,78 @@ export function decodeMessage(data: ArrayBuffer): DecodedMessage | null {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
case MessageType.PriorityFees: {
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
// Offset 94: top_10_fee: u64
|
|
88
|
-
// Offset 102: top_25_fee: u64
|
|
89
|
-
// Offset 110: spike_detected: bool
|
|
90
|
-
// Offset 111: spike_fee: u64
|
|
91
|
-
// Total: 119 bytes
|
|
92
|
-
if (payload.byteLength < 24) return null;
|
|
73
|
+
// FeeMarketWire bincode layout (per-writable-account model):
|
|
74
|
+
// Header (42 bytes):
|
|
75
|
+
// Offset 0: slot: u64 (8 bytes)
|
|
76
|
+
// Offset 8: timestamp_ms: u64 (8 bytes)
|
|
77
|
+
// Offset 16: recommended: u64 (8 bytes)
|
|
78
|
+
// Offset 24: state: u8 (1 byte)
|
|
79
|
+
// Offset 25: is_stale: bool (1 byte)
|
|
80
|
+
// Offset 26: block_utilization_pct: f32 (4 bytes)
|
|
81
|
+
// Offset 30: blocks_in_window: u32 (4 bytes)
|
|
82
|
+
// Offset 34: account_count: u64 (8 bytes) [bincode Vec length]
|
|
83
|
+
// Per account (92 bytes each):
|
|
84
|
+
// pubkey: [u8; 32], total_txs: u32, active_slots: u32,
|
|
85
|
+
// cu_consumed: u64, utilization_pct: f32,
|
|
86
|
+
// p25: u64, p50: u64, p75: u64, p90: u64, min_nonzero_price: u64
|
|
87
|
+
if (payload.byteLength < 42) return null;
|
|
93
88
|
|
|
94
89
|
const slot = Number(payloadView.getBigUint64(0, true));
|
|
95
90
|
const timestampMs = Number(payloadView.getBigUint64(8, true));
|
|
96
91
|
const recommended = Number(payloadView.getBigUint64(16, true));
|
|
97
|
-
const state =
|
|
98
|
-
const isStale =
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
92
|
+
const state = payloadView.getUint8(24);
|
|
93
|
+
const isStale = payloadView.getUint8(25) !== 0;
|
|
94
|
+
const blockUtilizationPct = payloadView.getFloat32(26, true);
|
|
95
|
+
const blocksInWindow = payloadView.getUint32(30, true);
|
|
96
|
+
const accountCount = Number(payloadView.getBigUint64(34, true));
|
|
97
|
+
|
|
98
|
+
const accounts: FeeMarketMessage['data']['accounts'] = [];
|
|
99
|
+
let offset = 42;
|
|
100
|
+
for (let i = 0; i < accountCount && offset + 92 <= payload.byteLength; i++) {
|
|
101
|
+
const pubkeyBytes = new Uint8Array(payload, offset, 32);
|
|
102
|
+
const pubkey = base58Encode(pubkeyBytes);
|
|
103
|
+
const totalTxs = payloadView.getUint32(offset + 32, true);
|
|
104
|
+
const activeSlots = payloadView.getUint32(offset + 36, true);
|
|
105
|
+
const cuConsumed = Number(payloadView.getBigUint64(offset + 40, true));
|
|
106
|
+
const utilizationPct = payloadView.getFloat32(offset + 48, true);
|
|
107
|
+
const p25 = Number(payloadView.getBigUint64(offset + 52, true));
|
|
108
|
+
const p50 = Number(payloadView.getBigUint64(offset + 60, true));
|
|
109
|
+
const p75 = Number(payloadView.getBigUint64(offset + 68, true));
|
|
110
|
+
const p90 = Number(payloadView.getBigUint64(offset + 76, true));
|
|
111
|
+
const minNonzeroPrice = Number(payloadView.getBigUint64(offset + 84, true));
|
|
112
|
+
|
|
113
|
+
accounts.push({
|
|
114
|
+
pubkey, totalTxs, activeSlots, cuConsumed, utilizationPct,
|
|
115
|
+
p25, p50, p75, p90, minNonzeroPrice,
|
|
116
|
+
});
|
|
117
|
+
offset += 92;
|
|
107
118
|
}
|
|
108
119
|
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
let
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
landingP99Fee = Number(payloadView.getBigUint64(86, true));
|
|
121
|
-
top10Fee = Number(payloadView.getBigUint64(94, true));
|
|
122
|
-
top25Fee = Number(payloadView.getBigUint64(102, true));
|
|
123
|
-
spikeDetected = payloadView.getUint8(110) !== 0;
|
|
124
|
-
spikeFee = Number(payloadView.getBigUint64(111, true));
|
|
120
|
+
// Decode recent_blocks (Vec<BlockMiniStats>) — v3
|
|
121
|
+
const recentBlocksCount = Number(payloadView.getBigUint64(offset, true));
|
|
122
|
+
offset += 8;
|
|
123
|
+
const recentBlocks: BlockMiniStats[] = [];
|
|
124
|
+
for (let i = 0; i < recentBlocksCount; i++) {
|
|
125
|
+
const rbSlot = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
126
|
+
const rbCuConsumed = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
127
|
+
const rbTxCount = payloadView.getUint32(offset, true); offset += 4;
|
|
128
|
+
const rbUtilizationPct = payloadView.getFloat32(offset, true); offset += 4;
|
|
129
|
+
const rbAvgCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
130
|
+
recentBlocks.push({ slot: rbSlot, cuConsumed: rbCuConsumed, txCount: rbTxCount, utilizationPct: rbUtilizationPct, avgCuPrice: rbAvgCuPrice });
|
|
125
131
|
}
|
|
126
132
|
|
|
133
|
+
// Decode trend (u8) — v3
|
|
134
|
+
const trendByte = payloadView.getUint8(offset); offset += 1;
|
|
135
|
+
const trend: TrendDirection = trendByte === 0 ? 'rising' : trendByte === 1 ? 'falling' : 'stable';
|
|
136
|
+
|
|
127
137
|
return {
|
|
128
|
-
type: '
|
|
138
|
+
type: 'fee_market',
|
|
129
139
|
data: {
|
|
130
|
-
slot,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
state,
|
|
134
|
-
isStale,
|
|
135
|
-
swapP50,
|
|
136
|
-
swapP75,
|
|
137
|
-
swapP90,
|
|
138
|
-
swapP99,
|
|
139
|
-
swapSamples,
|
|
140
|
-
landingP50Fee,
|
|
141
|
-
landingP75Fee,
|
|
142
|
-
landingP90Fee,
|
|
143
|
-
landingP99Fee,
|
|
144
|
-
top10Fee,
|
|
145
|
-
top25Fee,
|
|
146
|
-
spikeDetected,
|
|
147
|
-
spikeFee,
|
|
140
|
+
slot, timestampMs, recommended, state, isStale,
|
|
141
|
+
blockUtilizationPct, blocksInWindow, accounts,
|
|
142
|
+
recentBlocks, trend,
|
|
148
143
|
},
|
|
149
|
-
};
|
|
144
|
+
} as FeeMarketMessage;
|
|
150
145
|
}
|
|
151
146
|
|
|
152
147
|
case MessageType.Blockhash: {
|
|
@@ -204,6 +199,35 @@ export function decodeMessage(data: ArrayBuffer): DecodedMessage | null {
|
|
|
204
199
|
};
|
|
205
200
|
}
|
|
206
201
|
|
|
202
|
+
case MessageType.BlockStats: {
|
|
203
|
+
// BlockStats (0x0F) — v3
|
|
204
|
+
// Layout: slot(u64) + cu_consumed(u64) + execution_cu(u64) + cu_limit(u64) + cu_remaining(u64)
|
|
205
|
+
// + utilization_pct(f32) + tx_count(u32) + avg_cu_per_tx(u32) + avg_cu_price(u64)
|
|
206
|
+
// + min_cu_price(u64) + max_cu_price(u64) + timestamp_ms(u64)
|
|
207
|
+
let offset = 0; // payload already has type byte stripped
|
|
208
|
+
const slot = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
209
|
+
const cuConsumed = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
210
|
+
const executionCu = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
211
|
+
const cuLimit = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
212
|
+
const cuRemaining = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
213
|
+
const utilizationPct = payloadView.getFloat32(offset, true); offset += 4;
|
|
214
|
+
const txCount = payloadView.getUint32(offset, true); offset += 4;
|
|
215
|
+
const avgCuPerTx = payloadView.getUint32(offset, true); offset += 4;
|
|
216
|
+
const avgCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
217
|
+
const minCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
218
|
+
const maxCuPrice = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
219
|
+
const timestampMs = Number(payloadView.getBigUint64(offset, true)); offset += 8;
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
type: 'block_stats',
|
|
223
|
+
data: {
|
|
224
|
+
slot, cuConsumed, executionCu, cuLimit, cuRemaining, utilizationPct,
|
|
225
|
+
txCount, avgCuPerTx, avgCuPrice, minCuPrice, maxCuPrice, timestampMs,
|
|
226
|
+
},
|
|
227
|
+
receivedAt: Date.now(),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
207
231
|
default:
|
|
208
232
|
return null;
|
|
209
233
|
}
|
|
@@ -341,19 +365,7 @@ function decodePoolUpdate(payload: ArrayBuffer, payloadView: DataView): PoolUpda
|
|
|
341
365
|
},
|
|
342
366
|
};
|
|
343
367
|
} catch {
|
|
344
|
-
return
|
|
345
|
-
type: 'pool_update',
|
|
346
|
-
data: {
|
|
347
|
-
sequence: 0,
|
|
348
|
-
slot: 0,
|
|
349
|
-
writeVersion: 0,
|
|
350
|
-
protocol: 'unknown',
|
|
351
|
-
poolAddress: '',
|
|
352
|
-
tokenMints: [],
|
|
353
|
-
tokenBalances: [],
|
|
354
|
-
tokenDecimals: [],
|
|
355
|
-
},
|
|
356
|
-
};
|
|
368
|
+
return null;
|
|
357
369
|
}
|
|
358
370
|
}
|
|
359
371
|
|
|
@@ -461,24 +473,6 @@ function decodeQuote(payload: ArrayBuffer, payloadView: DataView): DecodedMessag
|
|
|
461
473
|
},
|
|
462
474
|
};
|
|
463
475
|
} catch {
|
|
464
|
-
return
|
|
465
|
-
type: 'quote',
|
|
466
|
-
data: {
|
|
467
|
-
topicId: '',
|
|
468
|
-
timestampMs: 0,
|
|
469
|
-
sequence: 0,
|
|
470
|
-
inputMint: '',
|
|
471
|
-
outputMint: '',
|
|
472
|
-
inAmount: '0',
|
|
473
|
-
outAmount: '0',
|
|
474
|
-
priceImpactBps: 0,
|
|
475
|
-
contextSlot: 0,
|
|
476
|
-
algorithm: '',
|
|
477
|
-
isImprovement: false,
|
|
478
|
-
isCached: false,
|
|
479
|
-
isStale: false,
|
|
480
|
-
routePlan: null,
|
|
481
|
-
},
|
|
482
|
-
};
|
|
476
|
+
return null;
|
|
483
477
|
}
|
|
484
478
|
}
|
package/src/ws/index.ts
CHANGED
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;
|
|
@@ -66,42 +70,61 @@ export interface PoolUpdateMessage {
|
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
/**
|
|
69
|
-
* Decoded
|
|
70
|
-
*
|
|
71
|
-
* All fields from K2
|
|
73
|
+
* Decoded fee market from binary message (per-writable-account model)
|
|
74
|
+
*
|
|
75
|
+
* All fields from K2 FeeMarketWire
|
|
72
76
|
*/
|
|
73
|
-
export interface
|
|
74
|
-
type: '
|
|
77
|
+
export interface FeeMarketMessage {
|
|
78
|
+
type: 'fee_market';
|
|
75
79
|
data: {
|
|
76
80
|
slot: number;
|
|
77
81
|
timestampMs: number;
|
|
78
|
-
/** Recommended priority fee in
|
|
82
|
+
/** Recommended priority fee in microlamports/CU (max p75 across hottest accounts) */
|
|
79
83
|
recommended: number;
|
|
80
84
|
/** Fee state: 0=low, 1=normal, 2=high, 3=extreme */
|
|
81
85
|
state: number;
|
|
82
86
|
/** True if data is stale (no recent samples) */
|
|
83
87
|
isStale: boolean;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
88
|
+
/** Block utilization percentage (0-100) */
|
|
89
|
+
blockUtilizationPct: number;
|
|
90
|
+
/** Number of blocks in the observation window */
|
|
91
|
+
blocksInWindow: number;
|
|
92
|
+
/** Per-writable-account fee data */
|
|
93
|
+
accounts: {
|
|
94
|
+
/** Account public key (Base58) */
|
|
95
|
+
pubkey: string;
|
|
96
|
+
/** Total transactions touching this account */
|
|
97
|
+
totalTxs: number;
|
|
98
|
+
/** Active slots for this account */
|
|
99
|
+
activeSlots: number;
|
|
100
|
+
/** Total CU consumed */
|
|
101
|
+
cuConsumed: number;
|
|
102
|
+
/** Utilization percentage (0-100) of 12M CU limit */
|
|
103
|
+
utilizationPct: number;
|
|
104
|
+
/** Fee percentiles in microlamports/CU */
|
|
105
|
+
p25: number;
|
|
106
|
+
p50: number;
|
|
107
|
+
p75: number;
|
|
108
|
+
p90: number;
|
|
109
|
+
/** Minimum non-zero fee observed */
|
|
110
|
+
minNonzeroPrice: number;
|
|
111
|
+
}[];
|
|
112
|
+
/** Recent block mini-stats (v3) */
|
|
113
|
+
recentBlocks: BlockMiniStats[];
|
|
114
|
+
/** Fee trend direction (v3) */
|
|
115
|
+
trend: TrendDirection;
|
|
102
116
|
};
|
|
103
117
|
}
|
|
104
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
|
+
|
|
105
128
|
/**
|
|
106
129
|
* Decoded blockhash from binary message
|
|
107
130
|
*/
|
|
@@ -216,7 +239,8 @@ export interface PongMessage {
|
|
|
216
239
|
*/
|
|
217
240
|
export type DecodedMessage =
|
|
218
241
|
| PoolUpdateMessage
|
|
219
|
-
|
|
|
242
|
+
| FeeMarketMessage
|
|
243
|
+
| BlockStatsMessage
|
|
220
244
|
| BlockhashMessage
|
|
221
245
|
| QuoteMessage
|
|
222
246
|
| HeartbeatMessage
|