@rpckit/websocket 0.9.99

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 ADDED
@@ -0,0 +1,128 @@
1
+ # @rpckit/websocket
2
+
3
+ WebSocket transport for rpckit. Supports subscriptions, keep-alive, reconnection, and request batching.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @rpckit/core @rpckit/websocket
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { webSocket } from '@rpckit/websocket'
15
+
16
+ const transport = webSocket('wss://example.com', {
17
+ timeout: 10000,
18
+ keepAlive: { interval: 30000, method: 'server.ping' },
19
+ reconnect: { delay: 1000, attempts: 5 }
20
+ })
21
+
22
+ await transport.connect()
23
+ const result = await transport.request('my.method', 'param1')
24
+
25
+ // Subscriptions
26
+ const unsub = await transport.subscribe('events.subscribe', (data) => {
27
+ console.log('Event:', data)
28
+ })
29
+
30
+ await transport.close()
31
+ ```
32
+
33
+ ## Electrum Cash Variant
34
+
35
+ For Electrum Cash servers, use the `electrum-cash` subpath which pre-configures handshake, keep-alive method, and unsubscribe conventions:
36
+
37
+ ```typescript
38
+ import { webSocket } from '@rpckit/websocket/electrum-cash'
39
+
40
+ const transport = webSocket('wss://electrum.example.com:50004', {
41
+ keepAlive: 30000 // Automatically uses server.ping
42
+ })
43
+
44
+ // Handshake (server.version) sent automatically on connect
45
+ const tip = await transport.request('blockchain.headers.get_tip')
46
+
47
+ // Unsubscribe automatically calls blockchain.headers.unsubscribe
48
+ const unsub = await transport.subscribe('blockchain.headers.subscribe', (header) => {
49
+ console.log('New block:', header)
50
+ })
51
+ await unsub()
52
+ ```
53
+
54
+ The electrum-cash variant also accepts:
55
+
56
+ - `clientName` - Client name sent in server.version handshake (default: `'rpckit'`)
57
+ - `protocolVersion` - Protocol version (default: `'1.6'`)
58
+
59
+ ## Ethereum Variant
60
+
61
+ For Ethereum JSON-RPC nodes, use the `ethereum` subpath which handles subscription routing:
62
+
63
+ ```typescript
64
+ import { webSocket } from '@rpckit/websocket/ethereum'
65
+
66
+ const transport = webSocket('wss://ethereum-rpc.publicnode.com')
67
+
68
+ // Standard requests
69
+ const blockNumber = await transport.request('eth_blockNumber')
70
+
71
+ // Subscriptions - eth_subscription notifications are routed automatically
72
+ const unsub = await transport.subscribe('eth_subscribe', 'newHeads', (header) => {
73
+ console.log('New block:', header.number)
74
+ })
75
+
76
+ // eth_unsubscribe called automatically
77
+ await unsub()
78
+ ```
79
+
80
+ The ethereum variant automatically:
81
+
82
+ - Routes `eth_subscription` notifications to the correct callback by subscription ID
83
+ - Calls `eth_unsubscribe` on cleanup
84
+ - Suppresses subscription IDs from callbacks (handled internally)
85
+
86
+ ## Subscription Sharing
87
+
88
+ Multiple callers subscribing to the same method+params will share a single server subscription. New subscribers receive the most recent notification data (not stale initial data). The server unsubscribe is only sent when the last listener unsubscribes.
89
+
90
+ ```typescript
91
+ // Both callbacks share one server subscription
92
+ const unsub1 = await transport.subscribe('events', callback1)
93
+ const unsub2 = await transport.subscribe('events', callback2)
94
+
95
+ await unsub1() // callback1 removed, server subscription stays active
96
+ await unsub2() // callback2 removed, NOW server unsubscribe is sent
97
+ ```
98
+
99
+ ## Options
100
+
101
+ - `timeout` - Request timeout in ms
102
+ - `connectTimeout` - Connection timeout in ms
103
+ - `retryCount` - Max retry attempts (default: 3)
104
+ - `retryDelay` - Base delay between retries in ms (default: 150, exponential backoff applied)
105
+ - `keepAlive` - Keep-alive ping interval in ms, or `{ interval, method, params }`
106
+ - `reconnect` - `{ delay: number, attempts: number }` for auto-reconnect after disconnect
107
+ - `headers` - Custom headers for the WebSocket connection
108
+ - `handshake` - `{ method, params }` to send on connect
109
+ - `batch` - `true` (default), `false`, or `{ wait, batchSize }`
110
+ - `onUnsubscribe` - Cleanup callback when the last listener unsubscribes (receives `{ request, method, params, initialResult }`)
111
+ - `notificationFilter` - Filter notifications before delivery; receives `(subscriptionParams, notificationParams)` and returns `boolean`
112
+ - `transformInitialResult` - Transform the initial subscription result before delivery; return `undefined` to suppress
113
+
114
+ ## Socket Access
115
+
116
+ Access the underlying WebSocket for advanced use cases:
117
+
118
+ ```typescript
119
+ // Synchronous - returns null if not yet connected
120
+ const socket = transport.getSocket()
121
+
122
+ // Async - connects first if needed, then returns socket
123
+ const socket = await transport.getSocketAsync()
124
+ ```
125
+
126
+ ## Lazy Initialization
127
+
128
+ Connections are established lazily on first use. Creating a transport is cheap - no resources are allocated until the first `request()`, `subscribe()`, or `connect()` call.
@@ -0,0 +1,3 @@
1
+ export type { ElectrumWebSocketConfig } from './webSocket.js';
2
+ export { webSocket } from './webSocket.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/electrum-cash/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { webSocket } from './webSocket.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/electrum-cash/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,10 @@
1
+ import type { AnySchema, Schema, WebSocketTransport, WebSocketTransportConfig } from '@rpckit/core';
2
+ export interface ElectrumWebSocketConfig extends WebSocketTransportConfig {
3
+ /** Client name sent in server.version handshake (default: 'rpckit') */
4
+ clientName?: string;
5
+ /** Electrum protocol version (default: '1.6') */
6
+ protocolVersion?: string;
7
+ }
8
+ export declare function webSocket<S extends Schema = AnySchema>(url: string, options?: Omit<ElectrumWebSocketConfig, 'url'>): WebSocketTransport<S>;
9
+ export declare function webSocket<S extends Schema = AnySchema>(config: ElectrumWebSocketConfig): WebSocketTransport<S>;
10
+ //# sourceMappingURL=webSocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocket.d.ts","sourceRoot":"","sources":["../../src/electrum-cash/webSocket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EAET,MAAM,EACN,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,uBAAwB,SAAQ,wBAAwB;IACvE,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EACpD,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,GAC7C,kBAAkB,CAAC,CAAC,CAAC,CAAA;AACxB,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EACpD,MAAM,EAAE,uBAAuB,GAC9B,kBAAkB,CAAC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,51 @@
1
+ import { webSocket as baseWebSocket } from '../webSocket.js';
2
+ export function webSocket(configOrUrl, options) {
3
+ const base = typeof configOrUrl === 'string'
4
+ ? { ...options, url: configOrUrl }
5
+ : configOrUrl;
6
+ const { clientName = 'rpckit', protocolVersion = '1.6', ...rest } = base;
7
+ const keepAlive = normalizeKeepAlive(rest.keepAlive);
8
+ return baseWebSocket({
9
+ handshake: {
10
+ method: 'server.version',
11
+ params: [clientName, protocolVersion],
12
+ },
13
+ onUnsubscribe: ({ request, method, params }) => request(method.replace('subscribe', 'unsubscribe'), ...params),
14
+ transformInitialResult: (_method, params, result) => [...params, ...result],
15
+ notificationFilter: electrumParamsMatch,
16
+ ...rest,
17
+ ...(keepAlive !== undefined ? { keepAlive } : {}),
18
+ });
19
+ }
20
+ function normalizeKeepAlive(ka) {
21
+ if (ka === undefined)
22
+ return undefined;
23
+ if (typeof ka === 'number') {
24
+ return { interval: ka, method: 'server.ping' };
25
+ }
26
+ const ping = { ...ka };
27
+ if (!ping.method)
28
+ ping.method = 'server.ping';
29
+ return ping;
30
+ }
31
+ /**
32
+ * Electrum protocol notification filter.
33
+ * Notifications include subscription params as prefix: subscribe([address]) → notification([address, status])
34
+ */
35
+ function electrumParamsMatch(subscriptionParams, notificationParams) {
36
+ return subscriptionParams.every((p, i) => {
37
+ if (i >= notificationParams.length)
38
+ return false;
39
+ const np = notificationParams[i];
40
+ // Simple types can be compared directly
41
+ if (typeof p !== 'object' ||
42
+ p === null ||
43
+ typeof np !== 'object' ||
44
+ np === null) {
45
+ return p === np;
46
+ }
47
+ // Complex types need JSON comparison
48
+ return JSON.stringify(p) === JSON.stringify(np);
49
+ });
50
+ }
51
+ //# sourceMappingURL=webSocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocket.js","sourceRoot":"","sources":["../../src/electrum-cash/webSocket.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAgB5D,MAAM,UAAU,SAAS,CACvB,WAA6C,EAC7C,OAA8C;IAE9C,MAAM,IAAI,GACR,OAAO,WAAW,KAAK,QAAQ;QAC7B,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE;QAClC,CAAC,CAAC,WAAW,CAAA;IAEjB,MAAM,EAAE,UAAU,GAAG,QAAQ,EAAE,eAAe,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;IACxE,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAEpD,OAAO,aAAa,CAAI;QACtB,SAAS,EAAE;YACT,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;SACtC;QACD,aAAa,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAC7C,OAAO,CACL,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,EAC1C,GAAG,MAAM,CACO;QACpB,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC;QAC3E,kBAAkB,EAAE,mBAAmB;QACvC,GAAG,IAAI;QACP,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,EAAyC;IAEzC,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACtC,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;IAChD,CAAC;IACD,MAAM,IAAI,GAAe,EAAE,GAAG,EAAE,EAAE,CAAA;IAClC,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,IAAI,CAAC,MAAM,GAAG,aAAa,CAAA;IAC7C,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CAC1B,kBAA6B,EAC7B,kBAA6B;IAE7B,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvC,IAAI,CAAC,IAAI,kBAAkB,CAAC,MAAM;YAAE,OAAO,KAAK,CAAA;QAChD,MAAM,EAAE,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAA;QAChC,wCAAwC;QACxC,IACE,OAAO,CAAC,KAAK,QAAQ;YACrB,CAAC,KAAK,IAAI;YACV,OAAO,EAAE,KAAK,QAAQ;YACtB,EAAE,KAAK,IAAI,EACX,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,CAAA;QACjB,CAAC;QACD,qCAAqC;QACrC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type { EthereumWebSocketConfig } from './webSocket.js';
2
+ export { webSocket } from './webSocket.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ethereum/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { webSocket } from './webSocket.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ethereum/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,17 @@
1
+ import type { AnySchema, Schema, WebSocketTransport, WebSocketTransportConfig } from '@rpckit/core';
2
+ export interface EthereumWebSocketConfig extends WebSocketTransportConfig {
3
+ }
4
+ /**
5
+ * WebSocket transport configured for Ethereum JSON-RPC.
6
+ *
7
+ * Handles Ethereum's subscription model where:
8
+ * - `eth_subscribe` returns a subscription ID
9
+ * - Notifications arrive via `eth_subscription` method with the subscription ID in params
10
+ * - `eth_unsubscribe` is called with the subscription ID to clean up
11
+ *
12
+ * The subscription ID is captured internally and not delivered to the user callback.
13
+ * Notifications are routed by matching the subscription ID.
14
+ */
15
+ export declare function webSocket<S extends Schema = AnySchema>(url: string, options?: Omit<EthereumWebSocketConfig, 'url'>): WebSocketTransport<S>;
16
+ export declare function webSocket<S extends Schema = AnySchema>(config: EthereumWebSocketConfig): WebSocketTransport<S>;
17
+ //# sourceMappingURL=webSocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocket.d.ts","sourceRoot":"","sources":["../../src/ethereum/webSocket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,MAAM,EACN,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,uBAAwB,SAAQ,wBAAwB;CAAG;AAW5E;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EACpD,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,GAC7C,kBAAkB,CAAC,CAAC,CAAC,CAAA;AACxB,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EACpD,MAAM,EAAE,uBAAuB,GAC9B,kBAAkB,CAAC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,95 @@
1
+ import { webSocket as baseWebSocket } from '../webSocket.js';
2
+ export function webSocket(configOrUrl, options) {
3
+ const config = typeof configOrUrl === 'string'
4
+ ? { ...options, url: configOrUrl }
5
+ : configOrUrl;
6
+ // Track subscription IDs to callback mappings
7
+ const subscriptionCallbacks = new Map();
8
+ // Track notification handlers for cleanup
9
+ const notificationHandlers = new Map();
10
+ const transport = baseWebSocket({
11
+ ...config,
12
+ // Suppress the subscription ID from being delivered to the callback for eth_subscribe
13
+ transformInitialResult: (method, _params, result) => {
14
+ if (method === 'eth_subscribe') {
15
+ return undefined; // Suppress - we handle it in the wrapper
16
+ }
17
+ return result[0];
18
+ },
19
+ // Unsubscribe by calling eth_unsubscribe with the subscription ID
20
+ onUnsubscribe: async ({ request, method, initialResult }) => {
21
+ if (method === 'eth_subscribe' && typeof initialResult === 'string') {
22
+ const handler = notificationHandlers.get(initialResult);
23
+ if (handler) {
24
+ const ws = transport.getSocket();
25
+ if (ws) {
26
+ ws.removeEventListener('message', handler);
27
+ }
28
+ notificationHandlers.delete(initialResult);
29
+ }
30
+ subscriptionCallbacks.delete(initialResult);
31
+ await request('eth_unsubscribe', initialResult);
32
+ }
33
+ },
34
+ });
35
+ // Wrap subscribe to set up Ethereum notification routing
36
+ const originalSubscribe = transport.subscribe.bind(transport);
37
+ transport.subscribe = async (method, ...args) => {
38
+ // For non-eth_subscribe methods, use the original behavior
39
+ if (method !== 'eth_subscribe') {
40
+ return originalSubscribe(method, ...args);
41
+ }
42
+ const callback = args.pop();
43
+ const params = args;
44
+ // Call the original subscribe - it will make the RPC call and get the subscription ID
45
+ // We pass a dummy callback since transformInitialResult will suppress the initial result
46
+ let subscriptionId = null;
47
+ const unsub = await new Promise((resolve, reject) => {
48
+ // We need to intercept the initial result to get the subscription ID
49
+ // Since transformInitialResult suppresses it, we use a request to get it
50
+ transport
51
+ .request('eth_subscribe', ...params)
52
+ .then((id) => {
53
+ subscriptionId = id;
54
+ subscriptionCallbacks.set(subscriptionId, callback);
55
+ // Set up notification handler
56
+ const ws = transport.getSocket();
57
+ if (ws) {
58
+ const notificationHandler = (event) => {
59
+ try {
60
+ const msg = JSON.parse(typeof event.data === 'string' ? event.data : '');
61
+ if (msg.method === 'eth_subscription' &&
62
+ msg.params?.subscription === subscriptionId) {
63
+ callback(msg.params.result);
64
+ }
65
+ }
66
+ catch {
67
+ // Ignore parse errors
68
+ }
69
+ };
70
+ ws.addEventListener('message', notificationHandler);
71
+ notificationHandlers.set(subscriptionId, notificationHandler);
72
+ }
73
+ // Return unsubscribe function
74
+ resolve(async () => {
75
+ if (subscriptionId) {
76
+ const handler = notificationHandlers.get(subscriptionId);
77
+ if (handler) {
78
+ const socket = transport.getSocket();
79
+ if (socket) {
80
+ socket.removeEventListener('message', handler);
81
+ }
82
+ notificationHandlers.delete(subscriptionId);
83
+ }
84
+ subscriptionCallbacks.delete(subscriptionId);
85
+ await transport.request('eth_unsubscribe', subscriptionId);
86
+ }
87
+ });
88
+ })
89
+ .catch(reject);
90
+ });
91
+ return unsub;
92
+ };
93
+ return transport;
94
+ }
95
+ //# sourceMappingURL=webSocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocket.js","sourceRoot":"","sources":["../../src/ethereum/webSocket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { webSocket } from './webSocket.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { webSocket } from './webSocket.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { type AnySchema, type Schema, type WebSocketTransport, type WebSocketTransportConfig } from '@rpckit/core';
2
+ export declare function webSocket<S extends Schema = AnySchema>(url: string, options?: Omit<WebSocketTransportConfig, 'url'>): WebSocketTransport<S>;
3
+ export declare function webSocket<S extends Schema = AnySchema>(config: WebSocketTransportConfig): WebSocketTransport<S>;
4
+ //# sourceMappingURL=webSocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocket.d.ts","sourceRoot":"","sources":["../src/webSocket.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAId,KAAK,MAAM,EAGX,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAE9B,MAAM,cAAc,CAAA;AAucrB,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EACpD,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,KAAK,CAAC,GAC9C,kBAAkB,CAAC,CAAC,CAAC,CAAA;AACxB,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EACpD,MAAM,EAAE,wBAAwB,GAC/B,kBAAkB,CAAC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,429 @@
1
+ import { BatchScheduler, withRetry, } from '@rpckit/core';
2
+ import { WebSocket } from 'isows';
3
+ const socketCache = new Map();
4
+ function getCacheKey(config) {
5
+ return JSON.stringify({
6
+ url: config.url,
7
+ headers: config.headers,
8
+ keepAlive: config.keepAlive,
9
+ reconnect: config.reconnect,
10
+ });
11
+ }
12
+ function getOrCreateSocketClient(config) {
13
+ const cacheKey = getCacheKey(config);
14
+ let client = socketCache.get(cacheKey);
15
+ if (client) {
16
+ client.refCount++;
17
+ return client;
18
+ }
19
+ let ws = null;
20
+ let nextId = 1;
21
+ let closed = false;
22
+ let connectPromise = null;
23
+ let reconnectCount = 0;
24
+ const pending = new Map();
25
+ const subscriptions = new Map();
26
+ // Track pending subscribe requests to prevent race conditions
27
+ const pendingSubscriptions = new Map();
28
+ let keepAliveTimer = null;
29
+ let batchScheduler = null;
30
+ if (config.batch !== false) {
31
+ batchScheduler = new BatchScheduler(typeof config.batch === 'object' ? config.batch : {}, sendBatch);
32
+ }
33
+ function getSubscriptionKey(method, params) {
34
+ return `${method}:${JSON.stringify(params)}`;
35
+ }
36
+ function connect() {
37
+ if (connectPromise)
38
+ return connectPromise;
39
+ connectPromise = new Promise((resolve, reject) => {
40
+ ws = config.headers
41
+ ? // biome-ignore lint/suspicious/noExplicitAny: isows headers typing
42
+ new WebSocket(config.url, { headers: config.headers })
43
+ : new WebSocket(config.url);
44
+ let connectTimer;
45
+ if (config.connectTimeout) {
46
+ connectTimer = setTimeout(() => {
47
+ reject(new Error('Connection timeout'));
48
+ ws?.close();
49
+ void handleDisconnect();
50
+ }, config.connectTimeout);
51
+ }
52
+ ws.onopen = async () => {
53
+ try {
54
+ reconnectCount = 0;
55
+ if (config.handshake) {
56
+ const id = nextId++;
57
+ const req = {
58
+ jsonrpc: '2.0',
59
+ method: config.handshake.method,
60
+ params: config.handshake.params ?? [],
61
+ id,
62
+ };
63
+ await new Promise((res, rej) => {
64
+ pending.set(id, { resolve: () => res(), reject: rej });
65
+ sendRaw(req);
66
+ });
67
+ }
68
+ startKeepAlive();
69
+ // Restore subscriptions after reconnect
70
+ if (subscriptions.size > 0) {
71
+ for (const [_key, entry] of subscriptions) {
72
+ const id = nextId++;
73
+ const req = {
74
+ jsonrpc: '2.0',
75
+ method: entry.method,
76
+ params: entry.params,
77
+ id,
78
+ };
79
+ sendRaw(req);
80
+ // We don't await the response - just re-establish
81
+ }
82
+ }
83
+ if (connectTimer)
84
+ clearTimeout(connectTimer);
85
+ resolve();
86
+ }
87
+ catch (err) {
88
+ reject(err);
89
+ }
90
+ };
91
+ ws.onerror = (event) => {
92
+ if (connectTimer)
93
+ clearTimeout(connectTimer);
94
+ const message = event && typeof event === 'object' && 'message' in event
95
+ ? `WebSocket error: ${event.message}`
96
+ : 'WebSocket error';
97
+ reject(new Error(message));
98
+ void handleDisconnect();
99
+ };
100
+ ws.onclose = () => {
101
+ void handleDisconnect();
102
+ };
103
+ ws.onmessage = (event) => {
104
+ const raw = String(event.data);
105
+ if (!raw.trim())
106
+ return;
107
+ const messages = raw.startsWith('[') ? JSON.parse(raw) : [JSON.parse(raw)];
108
+ for (const msg of messages) {
109
+ if ('id' in msg && msg.id != null) {
110
+ const p = pending.get(msg.id);
111
+ if (p) {
112
+ pending.delete(msg.id);
113
+ if (p.timer)
114
+ clearTimeout(p.timer);
115
+ const resp = msg;
116
+ if (resp.error)
117
+ p.reject(resp.error);
118
+ else
119
+ p.resolve(resp.result);
120
+ }
121
+ }
122
+ else {
123
+ // Subscription notification
124
+ const notif = msg;
125
+ for (const [, entry] of subscriptions) {
126
+ if (entry.method === notif.method) {
127
+ // Apply notification filter if configured
128
+ if (config.notificationFilter) {
129
+ const notifParams = notif.params;
130
+ if (!config.notificationFilter(entry.params, notifParams)) {
131
+ continue;
132
+ }
133
+ }
134
+ entry.lastNotification = notif.params;
135
+ for (const handler of entry.listeners)
136
+ handler(notif.params);
137
+ }
138
+ }
139
+ }
140
+ }
141
+ };
142
+ });
143
+ return connectPromise;
144
+ }
145
+ function startKeepAlive() {
146
+ stopKeepAlive();
147
+ const ka = config.keepAlive;
148
+ if (!ka)
149
+ return;
150
+ const interval = typeof ka === 'number' ? ka : ka.interval;
151
+ const method = typeof ka === 'number' ? undefined : ka.method;
152
+ const params = typeof ka === 'number' ? [] : (ka.params ?? []);
153
+ if (interval > 0 && method) {
154
+ keepAliveTimer = setInterval(() => {
155
+ sendRaw({ jsonrpc: '2.0', method, params, id: nextId++ });
156
+ }, interval);
157
+ }
158
+ }
159
+ function stopKeepAlive() {
160
+ if (keepAliveTimer) {
161
+ clearInterval(keepAliveTimer);
162
+ keepAliveTimer = null;
163
+ }
164
+ }
165
+ async function handleDisconnect() {
166
+ stopKeepAlive();
167
+ connectPromise = null;
168
+ ws = null;
169
+ // Reject all pending requests (but keep subscriptions for restore)
170
+ for (const [, p] of pending) {
171
+ if (p.timer)
172
+ clearTimeout(p.timer);
173
+ p.reject(new Error('WebSocket disconnected'));
174
+ }
175
+ pending.clear();
176
+ if (!closed &&
177
+ config.reconnect &&
178
+ reconnectCount < config.reconnect.attempts) {
179
+ reconnectCount++;
180
+ await new Promise((r) => setTimeout(r, config.reconnect?.delay));
181
+ if (!closed)
182
+ await connect();
183
+ }
184
+ }
185
+ function sendRaw(request) {
186
+ ws?.send(JSON.stringify(request));
187
+ }
188
+ async function sendBatch(requests) {
189
+ await connect();
190
+ return new Promise((resolve, reject) => {
191
+ const ids = new Set(requests.map((r) => r.id));
192
+ const results = [];
193
+ const timer = config.timeout
194
+ ? setTimeout(() => {
195
+ for (const id of ids)
196
+ pending.delete(id);
197
+ reject(new Error('Batch timeout'));
198
+ }, config.timeout)
199
+ : undefined;
200
+ for (const req of requests) {
201
+ pending.set(req.id, {
202
+ resolve: (result) => {
203
+ results.push({ jsonrpc: '2.0', result, id: req.id });
204
+ ids.delete(req.id);
205
+ if (ids.size === 0) {
206
+ if (timer)
207
+ clearTimeout(timer);
208
+ resolve(results);
209
+ }
210
+ },
211
+ reject: (error) => {
212
+ for (const id of ids)
213
+ pending.delete(id);
214
+ if (timer)
215
+ clearTimeout(timer);
216
+ reject(error);
217
+ },
218
+ });
219
+ }
220
+ ws?.send(JSON.stringify(requests));
221
+ });
222
+ }
223
+ async function request(method, params = []) {
224
+ await connect();
225
+ const id = nextId++;
226
+ const req = { jsonrpc: '2.0', method, params, id };
227
+ if (batchScheduler) {
228
+ return batchScheduler.enqueue(req);
229
+ }
230
+ return new Promise((resolve, reject) => {
231
+ const timer = config.timeout
232
+ ? setTimeout(() => {
233
+ pending.delete(id);
234
+ reject(new Error('Request timeout'));
235
+ }, config.timeout)
236
+ : undefined;
237
+ pending.set(id, { resolve, reject, timer });
238
+ sendRaw(req);
239
+ });
240
+ }
241
+ async function subscribe(method, params, onData) {
242
+ await connect();
243
+ const subKey = getSubscriptionKey(method, params);
244
+ // Helper to create unsubscribe function for an entry
245
+ const createUnsubscribe = (e) => () => {
246
+ e.listeners.delete(onData);
247
+ if (e.listeners.size === 0) {
248
+ subscriptions.delete(subKey);
249
+ return true; // was the last listener
250
+ }
251
+ return false; // other listeners remain
252
+ };
253
+ // Check for existing subscription
254
+ let entry = subscriptions.get(subKey);
255
+ if (entry) {
256
+ entry.listeners.add(onData);
257
+ const hasNotification = entry.lastNotification !== undefined;
258
+ return {
259
+ initialResult: hasNotification
260
+ ? entry.lastNotification
261
+ : entry.initialResult,
262
+ unsubscribe: createUnsubscribe(entry),
263
+ fromNotification: hasNotification,
264
+ };
265
+ }
266
+ // Check for pending subscription request (race condition prevention)
267
+ const pendingPromise = pendingSubscriptions.get(subKey);
268
+ if (pendingPromise) {
269
+ // Wait for the in-flight subscription to complete, then tap in
270
+ entry = await pendingPromise;
271
+ entry.listeners.add(onData);
272
+ const hasNotification = entry.lastNotification !== undefined;
273
+ return {
274
+ initialResult: hasNotification
275
+ ? entry.lastNotification
276
+ : entry.initialResult,
277
+ unsubscribe: createUnsubscribe(entry),
278
+ fromNotification: hasNotification,
279
+ };
280
+ }
281
+ // Create new subscription - store promise to prevent race conditions
282
+ const subscriptionPromise = (async () => {
283
+ const id = nextId++;
284
+ const req = { jsonrpc: '2.0', method, params, id };
285
+ const initialResult = await new Promise((resolve, reject) => {
286
+ const timer = config.timeout
287
+ ? setTimeout(() => {
288
+ pending.delete(id);
289
+ reject(new Error('Request timeout'));
290
+ }, config.timeout)
291
+ : undefined;
292
+ pending.set(id, { resolve, reject, timer });
293
+ sendRaw(req);
294
+ });
295
+ const newEntry = {
296
+ method,
297
+ params,
298
+ listeners: new Set([onData]),
299
+ initialResult,
300
+ lastNotification: undefined,
301
+ };
302
+ subscriptions.set(subKey, newEntry);
303
+ return newEntry;
304
+ })();
305
+ pendingSubscriptions.set(subKey, subscriptionPromise);
306
+ try {
307
+ entry = await subscriptionPromise;
308
+ return {
309
+ initialResult: entry.initialResult,
310
+ unsubscribe: createUnsubscribe(entry),
311
+ fromNotification: false,
312
+ };
313
+ }
314
+ finally {
315
+ pendingSubscriptions.delete(subKey);
316
+ }
317
+ }
318
+ async function close() {
319
+ closed = true;
320
+ stopKeepAlive();
321
+ if (batchScheduler)
322
+ await batchScheduler.flush();
323
+ for (const [, p] of pending) {
324
+ if (p.timer)
325
+ clearTimeout(p.timer);
326
+ p.reject(new Error('Transport closed'));
327
+ }
328
+ pending.clear();
329
+ subscriptions.clear();
330
+ ws?.close();
331
+ ws = null;
332
+ connectPromise = null;
333
+ socketCache.delete(cacheKey);
334
+ }
335
+ client = {
336
+ refCount: 1,
337
+ get ws() {
338
+ return ws;
339
+ },
340
+ nextId,
341
+ connectPromise,
342
+ reconnectCount,
343
+ closed,
344
+ pending,
345
+ subscriptions,
346
+ keepAliveTimer,
347
+ batchScheduler,
348
+ connect,
349
+ sendRaw,
350
+ request,
351
+ subscribe,
352
+ close,
353
+ };
354
+ socketCache.set(cacheKey, client);
355
+ return client;
356
+ }
357
+ export function webSocket(configOrUrl, options) {
358
+ const config = typeof configOrUrl === 'string'
359
+ ? { ...options, url: configOrUrl }
360
+ : configOrUrl;
361
+ // Lazy client initialization - only created on first use
362
+ let client = null;
363
+ const getClient = () => {
364
+ if (!client)
365
+ client = getOrCreateSocketClient(config);
366
+ return client;
367
+ };
368
+ const retryOpts = {
369
+ retryCount: config.retryCount,
370
+ retryDelay: config.retryDelay,
371
+ };
372
+ const self = {
373
+ url: config.url,
374
+ connect: () => withRetry(() => getClient().connect(), retryOpts),
375
+ request: (method, ...params) => withRetry(() => getClient().request(method, params), retryOpts),
376
+ async subscribe(method, ...args) {
377
+ const onData = args.pop();
378
+ const params = args;
379
+ const { initialResult, unsubscribe, fromNotification } = await withRetry(() => getClient().subscribe(method, params, onData), retryOpts);
380
+ // Deliver initial result if we got one
381
+ if (initialResult !== undefined) {
382
+ if (fromNotification) {
383
+ // Reused subscription: lastNotification is already in notification format
384
+ onData(initialResult);
385
+ }
386
+ else {
387
+ const transformed = config.transformInitialResult
388
+ ? config.transformInitialResult(method, params, [initialResult])
389
+ : initialResult;
390
+ // Allow transformInitialResult to return undefined to suppress delivery
391
+ if (transformed !== undefined) {
392
+ onData(transformed);
393
+ }
394
+ }
395
+ }
396
+ const unsub = async (cleanup) => {
397
+ const wasLastListener = unsubscribe();
398
+ // Only call onUnsubscribe when the last listener is removed
399
+ if (wasLastListener) {
400
+ const fn = cleanup ?? config.onUnsubscribe;
401
+ if (fn) {
402
+ await fn({ request: self.request, method, params, initialResult });
403
+ }
404
+ }
405
+ };
406
+ return unsub;
407
+ },
408
+ async close() {
409
+ if (!client)
410
+ return;
411
+ client.refCount--;
412
+ if (client.refCount <= 0) {
413
+ await client.close();
414
+ }
415
+ },
416
+ getSocket() {
417
+ return client?.ws ?? null;
418
+ },
419
+ async getSocketAsync() {
420
+ await getClient().connect();
421
+ const c = getClient();
422
+ if (!c.ws)
423
+ throw new Error('WebSocket not connected');
424
+ return c.ws;
425
+ },
426
+ };
427
+ return self;
428
+ }
429
+ //# sourceMappingURL=webSocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocket.js","sourceRoot":"","sources":["../src/webSocket.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@rpckit/websocket",
3
+ "version": "0.9.99",
4
+ "description": "WebSocket transport for rpckit with subscriptions, keep-alive, and reconnection",
5
+ "author": "mainnet_pat",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./electrum-cash": {
17
+ "types": "./dist/electrum-cash/index.d.ts",
18
+ "default": "./dist/electrum-cash/index.js"
19
+ },
20
+ "./ethereum": {
21
+ "types": "./dist/ethereum/index.d.ts",
22
+ "default": "./dist/ethereum/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "keywords": [
29
+ "json-rpc",
30
+ "rpc",
31
+ "websocket",
32
+ "electrum",
33
+ "electrum-cash",
34
+ "ethereum",
35
+ "typescript"
36
+ ],
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/mainnet-pat/rpckit.git",
40
+ "directory": "packages/websocket"
41
+ },
42
+ "homepage": "https://rpckit.dev",
43
+ "bugs": {
44
+ "url": "https://github.com/mainnet-pat/rpckit/issues"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc"
48
+ },
49
+ "dependencies": {
50
+ "@rpckit/core": "*",
51
+ "isows": "^1.0.6"
52
+ },
53
+ "devDependencies": {
54
+ "typescript": "^5.7.0"
55
+ }
56
+ }