@jack-kernel/sdk 1.0.0 → 1.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.
Files changed (91) hide show
  1. package/dist/cjs/index.js +125 -2
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/lifi/chain-map.js +39 -0
  4. package/dist/cjs/lifi/chain-map.js.map +1 -0
  5. package/dist/cjs/lifi/fallback.js +135 -0
  6. package/dist/cjs/lifi/fallback.js.map +1 -0
  7. package/dist/cjs/lifi/index.js +34 -0
  8. package/dist/cjs/lifi/index.js.map +1 -0
  9. package/dist/cjs/lifi/lifi-provider.js +496 -0
  10. package/dist/cjs/lifi/lifi-provider.js.map +1 -0
  11. package/dist/cjs/lifi/token-map.js +75 -0
  12. package/dist/cjs/lifi/token-map.js.map +1 -0
  13. package/dist/cjs/lifi/types.js +3 -0
  14. package/dist/cjs/lifi/types.js.map +1 -0
  15. package/dist/cjs/lifi/utils.js +45 -0
  16. package/dist/cjs/lifi/utils.js.map +1 -0
  17. package/dist/cjs/yellow/channel-state-manager.js +167 -0
  18. package/dist/cjs/yellow/channel-state-manager.js.map +1 -0
  19. package/dist/cjs/yellow/clear-node-connection.js +390 -0
  20. package/dist/cjs/yellow/clear-node-connection.js.map +1 -0
  21. package/dist/cjs/yellow/event-mapper.js +254 -0
  22. package/dist/cjs/yellow/event-mapper.js.map +1 -0
  23. package/dist/cjs/yellow/serialization.js +130 -0
  24. package/dist/cjs/yellow/serialization.js.map +1 -0
  25. package/dist/cjs/yellow/session-key-manager.js +308 -0
  26. package/dist/cjs/yellow/session-key-manager.js.map +1 -0
  27. package/dist/cjs/yellow/types.js +12 -0
  28. package/dist/cjs/yellow/types.js.map +1 -0
  29. package/dist/cjs/yellow/yellow-provider.js +1545 -0
  30. package/dist/cjs/yellow/yellow-provider.js.map +1 -0
  31. package/dist/esm/index.js +102 -1
  32. package/dist/esm/index.js.map +1 -1
  33. package/dist/esm/lifi/chain-map.js +35 -0
  34. package/dist/esm/lifi/chain-map.js.map +1 -0
  35. package/dist/esm/lifi/fallback.js +128 -0
  36. package/dist/esm/lifi/fallback.js.map +1 -0
  37. package/dist/esm/lifi/index.js +19 -0
  38. package/dist/esm/lifi/index.js.map +1 -0
  39. package/dist/esm/lifi/lifi-provider.js +492 -0
  40. package/dist/esm/lifi/lifi-provider.js.map +1 -0
  41. package/dist/esm/lifi/token-map.js +71 -0
  42. package/dist/esm/lifi/token-map.js.map +1 -0
  43. package/dist/esm/lifi/types.js +2 -0
  44. package/dist/esm/lifi/types.js.map +1 -0
  45. package/dist/esm/lifi/utils.js +41 -0
  46. package/dist/esm/lifi/utils.js.map +1 -0
  47. package/dist/esm/yellow/channel-state-manager.js +163 -0
  48. package/dist/esm/yellow/channel-state-manager.js.map +1 -0
  49. package/dist/esm/yellow/clear-node-connection.js +385 -0
  50. package/dist/esm/yellow/clear-node-connection.js.map +1 -0
  51. package/dist/esm/yellow/event-mapper.js +248 -0
  52. package/dist/esm/yellow/event-mapper.js.map +1 -0
  53. package/dist/esm/yellow/serialization.js +125 -0
  54. package/dist/esm/yellow/serialization.js.map +1 -0
  55. package/dist/esm/yellow/session-key-manager.js +302 -0
  56. package/dist/esm/yellow/session-key-manager.js.map +1 -0
  57. package/dist/esm/yellow/types.js +11 -0
  58. package/dist/esm/yellow/types.js.map +1 -0
  59. package/dist/esm/yellow/yellow-provider.js +1538 -0
  60. package/dist/esm/yellow/yellow-provider.js.map +1 -0
  61. package/dist/types/index.d.ts +104 -2
  62. package/dist/types/index.d.ts.map +1 -1
  63. package/dist/types/lifi/chain-map.d.ts +27 -0
  64. package/dist/types/lifi/chain-map.d.ts.map +1 -0
  65. package/dist/types/lifi/fallback.d.ts +58 -0
  66. package/dist/types/lifi/fallback.d.ts.map +1 -0
  67. package/dist/types/lifi/index.d.ts +18 -0
  68. package/dist/types/lifi/index.d.ts.map +1 -0
  69. package/dist/types/lifi/lifi-provider.d.ts +133 -0
  70. package/dist/types/lifi/lifi-provider.d.ts.map +1 -0
  71. package/dist/types/lifi/token-map.d.ts +34 -0
  72. package/dist/types/lifi/token-map.d.ts.map +1 -0
  73. package/dist/types/lifi/types.d.ts +52 -0
  74. package/dist/types/lifi/types.d.ts.map +1 -0
  75. package/dist/types/lifi/utils.d.ts +29 -0
  76. package/dist/types/lifi/utils.d.ts.map +1 -0
  77. package/dist/types/yellow/channel-state-manager.d.ts +106 -0
  78. package/dist/types/yellow/channel-state-manager.d.ts.map +1 -0
  79. package/dist/types/yellow/clear-node-connection.d.ts +202 -0
  80. package/dist/types/yellow/clear-node-connection.d.ts.map +1 -0
  81. package/dist/types/yellow/event-mapper.d.ts +74 -0
  82. package/dist/types/yellow/event-mapper.d.ts.map +1 -0
  83. package/dist/types/yellow/serialization.d.ts +52 -0
  84. package/dist/types/yellow/serialization.d.ts.map +1 -0
  85. package/dist/types/yellow/session-key-manager.d.ts +179 -0
  86. package/dist/types/yellow/session-key-manager.d.ts.map +1 -0
  87. package/dist/types/yellow/types.d.ts +177 -0
  88. package/dist/types/yellow/types.d.ts.map +1 -0
  89. package/dist/types/yellow/yellow-provider.d.ts +303 -0
  90. package/dist/types/yellow/yellow-provider.d.ts.map +1 -0
  91. package/package.json +4 -1
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ /**
3
+ * Channel State Manager for Yellow Network Integration
4
+ *
5
+ * Tracks local channel state and provides on-chain query capabilities.
6
+ * Maintains a local cache of channel states from ClearNode messages and
7
+ * falls back to on-chain queries via viem PublicClient when the WebSocket
8
+ * is disconnected.
9
+ *
10
+ * Requirements: 7.1, 7.2, 7.3, 7.4
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ChannelStateManager = void 0;
14
+ // ============================================================================
15
+ // Custody Contract ABI (minimal)
16
+ // ============================================================================
17
+ /**
18
+ * Minimal ABI for the custody contract's balance query function.
19
+ *
20
+ * The custody contract exposes a `getChannelBalances` function that returns
21
+ * the token balances held in a specific channel for the given token addresses.
22
+ *
23
+ * Function signature: getChannelBalances(bytes32 channelId, address[] tokens) → uint256[]
24
+ */
25
+ const CUSTODY_BALANCE_ABI = [
26
+ {
27
+ name: 'getChannelBalances',
28
+ type: 'function',
29
+ stateMutability: 'view',
30
+ inputs: [
31
+ { name: 'channelId', type: 'bytes32' },
32
+ { name: 'tokens', type: 'address[]' },
33
+ ],
34
+ outputs: [{ name: 'balances', type: 'uint256[]' }],
35
+ },
36
+ ];
37
+ // ============================================================================
38
+ // ChannelStateManager
39
+ // ============================================================================
40
+ /**
41
+ * Manages local channel state cache and provides on-chain query capabilities.
42
+ *
43
+ * The ChannelStateManager serves two purposes:
44
+ * 1. Maintains a local cache of channel states received from ClearNode messages,
45
+ * enabling fast lookups without network calls.
46
+ * 2. Provides on-chain balance queries via viem PublicClient for when the
47
+ * WebSocket connection is unavailable (Requirement 7.4) or when authoritative
48
+ * on-chain data is needed (Requirement 7.2).
49
+ *
50
+ * Requirements: 7.1, 7.2, 7.3, 7.4
51
+ */
52
+ class ChannelStateManager {
53
+ publicClient;
54
+ custodyAddress;
55
+ channels;
56
+ /**
57
+ * @param publicClient - viem PublicClient for on-chain balance queries
58
+ * @param custodyAddress - Address of the custody contract holding channel collateral
59
+ */
60
+ constructor(publicClient, custodyAddress) {
61
+ this.publicClient = publicClient;
62
+ this.custodyAddress = custodyAddress;
63
+ this.channels = new Map();
64
+ }
65
+ /**
66
+ * Update the local cache with a channel state from a ClearNode response.
67
+ *
68
+ * This is called when the YellowProvider receives channel state updates
69
+ * from ClearNode messages (create, resize, close, or get_ledger_balances).
70
+ *
71
+ * Requirement 7.1: Maintain local channel state from ClearNode responses.
72
+ *
73
+ * @param channelId - The channel identifier
74
+ * @param state - The channel state to cache
75
+ */
76
+ updateChannel(channelId, state) {
77
+ this.channels.set(channelId, state);
78
+ }
79
+ /**
80
+ * Get a locally cached channel state by channel ID.
81
+ *
82
+ * Returns undefined if the channel is not in the local cache.
83
+ * For authoritative on-chain data, use queryOnChainBalances instead.
84
+ *
85
+ * Requirement 7.2: Query specific channel status by channel ID.
86
+ *
87
+ * @param channelId - The channel identifier
88
+ * @returns The cached channel state, or undefined if not found
89
+ */
90
+ getChannel(channelId) {
91
+ return this.channels.get(channelId);
92
+ }
93
+ /**
94
+ * Get all locally cached channel states.
95
+ *
96
+ * Returns a snapshot array of all channels currently in the cache.
97
+ * The returned array is a copy; modifications do not affect the cache.
98
+ *
99
+ * Requirement 7.1: Return list of channels with their statuses and allocations.
100
+ *
101
+ * @returns Array of all cached channel states
102
+ */
103
+ getAllChannels() {
104
+ return Array.from(this.channels.values());
105
+ }
106
+ /**
107
+ * Query on-chain channel balances from the custody contract.
108
+ *
109
+ * Uses viem PublicClient.readContract to call the custody contract's
110
+ * getChannelBalances function. This provides authoritative on-chain data
111
+ * and is used as a fallback when the ClearNode WebSocket is disconnected.
112
+ *
113
+ * Requirement 7.2: Query on-chain custody contract for channel balances.
114
+ * Requirement 7.4: Fall back to on-chain queries when WebSocket is disconnected.
115
+ *
116
+ * @param channelId - The channel identifier (bytes32 hex string)
117
+ * @param tokens - Array of token addresses to query balances for
118
+ * @returns Array of token balances as bigint values, one per token
119
+ * @throws Error if the on-chain query fails
120
+ */
121
+ async queryOnChainBalances(channelId, tokens) {
122
+ try {
123
+ const balances = await this.publicClient.readContract({
124
+ address: this.custodyAddress,
125
+ abi: CUSTODY_BALANCE_ABI,
126
+ functionName: 'getChannelBalances',
127
+ args: [channelId, tokens],
128
+ });
129
+ return [...balances];
130
+ }
131
+ catch (error) {
132
+ const message = error instanceof Error ? error.message : String(error);
133
+ throw new Error(`Failed to query on-chain balances for channel ${channelId}: ${message}`);
134
+ }
135
+ }
136
+ /**
137
+ * Find an open (ACTIVE) channel for a given token address.
138
+ *
139
+ * Searches the local cache for a channel with status 'ACTIVE' that
140
+ * matches the specified token address. Returns the first match found.
141
+ *
142
+ * This is used by the YellowProvider to reuse existing channels
143
+ * when executing intents, avoiding unnecessary channel creation.
144
+ *
145
+ * @param token - The token address to find an open channel for
146
+ * @returns The first matching ACTIVE channel, or undefined if none found
147
+ */
148
+ findOpenChannel(token) {
149
+ for (const channel of this.channels.values()) {
150
+ if (channel.status === 'ACTIVE' && channel.token === token) {
151
+ return channel;
152
+ }
153
+ }
154
+ return undefined;
155
+ }
156
+ /**
157
+ * Clear all cached channel states.
158
+ *
159
+ * This is typically called when the provider disconnects or when
160
+ * a full state refresh is needed.
161
+ */
162
+ clear() {
163
+ this.channels.clear();
164
+ }
165
+ }
166
+ exports.ChannelStateManager = ChannelStateManager;
167
+ //# sourceMappingURL=channel-state-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-state-manager.js","sourceRoot":"","sources":["../../../src/yellow/channel-state-manager.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAKH,+EAA+E;AAC/E,iCAAiC;AACjC,+EAA+E;AAE/E;;;;;;;GAOG;AACH,MAAM,mBAAmB,GAAG;IAC1B;QACE,IAAI,EAAE,oBAAoB;QAC1B,IAAI,EAAE,UAAU;QAChB,eAAe,EAAE,MAAM;QACvB,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE;YACtC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE;SACtC;QACD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;KACnD;CACO,CAAC;AAEX,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E;;;;;;;;;;;GAWG;AACH,MAAa,mBAAmB;IACb,YAAY,CAAe;IAC3B,cAAc,CAAgB;IAC9B,QAAQ,CAA4B;IAErD;;;OAGG;IACH,YAAY,YAA0B,EAAE,cAA6B;QACnE,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAClD,CAAC;IAED;;;;;;;;;;OAUG;IACH,aAAa,CAAC,SAAiB,EAAE,KAAmB;QAClD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED;;;;;;;;;;OAUG;IACH,UAAU,CAAC,SAAiB;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED;;;;;;;;;OASG;IACH,cAAc;QACZ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,oBAAoB,CAAC,SAAiB,EAAE,MAAgB;QAC5D,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;gBACpD,OAAO,EAAE,IAAI,CAAC,cAAc;gBAC5B,GAAG,EAAE,mBAAmB;gBACxB,YAAY,EAAE,oBAAoB;gBAClC,IAAI,EAAE,CAAC,SAA0B,EAAE,MAAyB,CAAC;aAC9D,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,iDAAiD,SAAS,KAAK,OAAO,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,KAAa;QAC3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;gBAC3D,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;OAKG;IACH,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF;AAxHD,kDAwHC"}
@@ -0,0 +1,390 @@
1
+ "use strict";
2
+ /**
3
+ * ClearNode WebSocket Connection Manager
4
+ *
5
+ * Manages the WebSocket connection to Yellow Network's ClearNode relay server
6
+ * with reconnection logic, request-response correlation, and event emission.
7
+ *
8
+ * Key features:
9
+ * - Exponential backoff reconnection: delay = initialDelay * 2^(attempt-1)
10
+ * - Request-response correlation using method name matching
11
+ * - EventEmitter pattern for connected/disconnected events
12
+ * - Cleanup of all pending handlers on disconnect
13
+ *
14
+ * Requirements: 10.1, 10.2, 10.3, 10.4, 10.5
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.ClearNodeConnection = void 0;
18
+ exports.calculateBackoffDelay = calculateBackoffDelay;
19
+ const events_1 = require("events");
20
+ /** WebSocket readyState constants */
21
+ const WS_OPEN = 1;
22
+ const WS_CONNECTING = 0;
23
+ /**
24
+ * Calculate the exponential backoff delay for a given reconnection attempt.
25
+ *
26
+ * Formula: delay = initialDelay * 2^(attempt - 1)
27
+ *
28
+ * This is exported as a pure function so it can be independently tested
29
+ * (including via property-based tests).
30
+ *
31
+ * @param initialDelay - The base delay in milliseconds
32
+ * @param attempt - The attempt number (1-based)
33
+ * @returns The delay in milliseconds before the given attempt
34
+ */
35
+ function calculateBackoffDelay(initialDelay, attempt) {
36
+ if (attempt < 1) {
37
+ return initialDelay;
38
+ }
39
+ return initialDelay * Math.pow(2, attempt - 1);
40
+ }
41
+ /**
42
+ * Manages a WebSocket connection to Yellow Network's ClearNode.
43
+ *
44
+ * Provides:
45
+ * - connect/disconnect lifecycle management
46
+ * - send (fire-and-forget) and sendAndWait (request-response correlation)
47
+ * - Automatic reconnection with exponential backoff
48
+ * - Event emission for 'connected' and 'disconnected' events
49
+ * - Cleanup of pending handlers on disconnect
50
+ *
51
+ * Requirements: 10.1, 10.2, 10.3, 10.4, 10.5
52
+ */
53
+ class ClearNodeConnection {
54
+ url;
55
+ maxReconnectAttempts;
56
+ reconnectDelay;
57
+ messageTimeout;
58
+ wsFactory;
59
+ ws = null;
60
+ emitter = new events_1.EventEmitter();
61
+ pendingRequests = [];
62
+ messageHandlers = [];
63
+ _isConnected = false;
64
+ _isDisposed = false;
65
+ reconnectAttempt = 0;
66
+ reconnectTimer = null;
67
+ /**
68
+ * @param url - The ClearNode WebSocket URL
69
+ * @param options - Connection configuration options
70
+ * @param wsFactory - Optional WebSocket factory for testing. Defaults to global WebSocket.
71
+ */
72
+ constructor(url, options, wsFactory) {
73
+ this.url = url;
74
+ this.maxReconnectAttempts = options?.maxReconnectAttempts ?? 5;
75
+ this.reconnectDelay = options?.reconnectDelay ?? 1000;
76
+ this.messageTimeout = options?.messageTimeout ?? 30000;
77
+ this.wsFactory = wsFactory ?? ((wsUrl) => new WebSocket(wsUrl));
78
+ }
79
+ /**
80
+ * Establish a WebSocket connection to ClearNode.
81
+ *
82
+ * Resolves when the connection is open and ready.
83
+ * Rejects if the connection fails to establish.
84
+ *
85
+ * Requirement 10.1: Emit a connected event on successful connection.
86
+ */
87
+ async connect() {
88
+ if (this._isDisposed) {
89
+ throw new Error('ClearNodeConnection has been disposed');
90
+ }
91
+ if (this._isConnected && this.ws) {
92
+ return;
93
+ }
94
+ return new Promise((resolve, reject) => {
95
+ let settled = false;
96
+ try {
97
+ this.ws = this.wsFactory(this.url);
98
+ }
99
+ catch (err) {
100
+ reject(new Error(`Failed to create WebSocket: ${err instanceof Error ? err.message : String(err)}`));
101
+ return;
102
+ }
103
+ this.ws.onopen = () => {
104
+ if (settled)
105
+ return;
106
+ settled = true;
107
+ this._isConnected = true;
108
+ this.reconnectAttempt = 0;
109
+ this.emitter.emit('connected');
110
+ resolve();
111
+ };
112
+ this.ws.onerror = (event) => {
113
+ if (settled)
114
+ return;
115
+ settled = true;
116
+ const errorMessage = event && typeof event === 'object' && 'message' in event
117
+ ? String(event.message)
118
+ : 'WebSocket connection failed';
119
+ reject(new Error(errorMessage));
120
+ };
121
+ this.ws.onclose = () => {
122
+ if (!settled) {
123
+ settled = true;
124
+ reject(new Error('WebSocket closed before connection was established'));
125
+ return;
126
+ }
127
+ this.handleDisconnect();
128
+ };
129
+ this.ws.onmessage = (event) => {
130
+ this.handleMessage(event.data);
131
+ };
132
+ });
133
+ }
134
+ /**
135
+ * Close the WebSocket connection and clean up all resources.
136
+ *
137
+ * Requirement 10.4: Clean up all pending message handlers on disconnect.
138
+ */
139
+ async disconnect() {
140
+ this._isDisposed = true;
141
+ this.cancelReconnect();
142
+ this.cleanupPendingRequests(new Error('Connection closed by client'));
143
+ this.messageHandlers = [];
144
+ if (this.ws) {
145
+ const ws = this.ws;
146
+ this.ws = null;
147
+ this._isConnected = false;
148
+ // Remove handlers to prevent reconnection attempts
149
+ ws.onopen = null;
150
+ ws.onclose = null;
151
+ ws.onerror = null;
152
+ ws.onmessage = null;
153
+ // Only close if not already closed/closing
154
+ if (ws.readyState === WS_OPEN || ws.readyState === WS_CONNECTING) {
155
+ ws.close();
156
+ }
157
+ this.emitter.emit('disconnected');
158
+ }
159
+ this._isConnected = false;
160
+ }
161
+ /**
162
+ * Send a message and wait for a correlated response.
163
+ *
164
+ * The response is matched by method name: when a message is received
165
+ * that contains a matching method field, the promise resolves with that response.
166
+ *
167
+ * Requirement 10.5: Request-response correlation using method name matching.
168
+ *
169
+ * @param message - The message string to send
170
+ * @param method - The method name to correlate the response with
171
+ * @param timeout - Optional timeout in ms (defaults to messageTimeout)
172
+ * @returns The parsed response data
173
+ * @throws Error if the connection is not open, the request times out, or the connection drops
174
+ */
175
+ async sendAndWait(message, method, timeout) {
176
+ if (!this._isConnected || !this.ws || this.ws.readyState !== WS_OPEN) {
177
+ throw new Error('WebSocket is not connected');
178
+ }
179
+ const effectiveTimeout = timeout ?? this.messageTimeout;
180
+ return new Promise((resolve, reject) => {
181
+ const timer = setTimeout(() => {
182
+ this.removePendingRequest(pending);
183
+ reject(new Error(`Request timed out waiting for response to method: ${method}`));
184
+ }, effectiveTimeout);
185
+ const pending = {
186
+ method,
187
+ resolve: resolve,
188
+ reject,
189
+ timer,
190
+ };
191
+ this.pendingRequests.push(pending);
192
+ this.ws.send(message);
193
+ });
194
+ }
195
+ /**
196
+ * Send a message without waiting for a response (fire-and-forget).
197
+ *
198
+ * @param message - The message string to send
199
+ * @throws Error if the connection is not open
200
+ */
201
+ send(message) {
202
+ if (!this._isConnected || !this.ws || this.ws.readyState !== WS_OPEN) {
203
+ throw new Error('WebSocket is not connected');
204
+ }
205
+ this.ws.send(message);
206
+ }
207
+ /**
208
+ * Register a handler for incoming messages.
209
+ *
210
+ * Handlers receive the parsed message data for all incoming messages
211
+ * (including those that match pending requests).
212
+ *
213
+ * @param handler - Callback invoked with the parsed message data
214
+ */
215
+ onMessage(handler) {
216
+ this.messageHandlers.push(handler);
217
+ }
218
+ /**
219
+ * Whether the WebSocket connection is currently open and ready.
220
+ */
221
+ get isConnected() {
222
+ return this._isConnected;
223
+ }
224
+ /**
225
+ * Register an event listener for connection lifecycle events.
226
+ *
227
+ * Supported events: 'connected', 'disconnected'
228
+ */
229
+ on(event, handler) {
230
+ this.emitter.on(event, handler);
231
+ }
232
+ /**
233
+ * Remove an event listener.
234
+ */
235
+ off(event, handler) {
236
+ this.emitter.off(event, handler);
237
+ }
238
+ // ============================================================================
239
+ // Private Methods
240
+ // ============================================================================
241
+ /**
242
+ * Handle an incoming WebSocket message.
243
+ *
244
+ * Parses the message as JSON and checks for method-based correlation
245
+ * with pending requests. Also dispatches to all registered message handlers.
246
+ */
247
+ handleMessage(rawData) {
248
+ let data;
249
+ try {
250
+ const text = typeof rawData === 'string' ? rawData : String(rawData);
251
+ data = JSON.parse(text);
252
+ }
253
+ catch {
254
+ // If the message is not valid JSON, pass the raw data
255
+ data = rawData;
256
+ }
257
+ // Dispatch to all registered message handlers
258
+ for (const handler of this.messageHandlers) {
259
+ try {
260
+ handler(data);
261
+ }
262
+ catch {
263
+ // Swallow handler errors to prevent one handler from breaking others
264
+ }
265
+ }
266
+ // Check for method-based correlation with pending requests
267
+ if (data && typeof data === 'object') {
268
+ const messageObj = data;
269
+ const responseMethod = this.extractMethod(messageObj);
270
+ if (responseMethod) {
271
+ const matchIndex = this.pendingRequests.findIndex((req) => req.method === responseMethod);
272
+ if (matchIndex !== -1) {
273
+ const pending = this.pendingRequests[matchIndex];
274
+ this.pendingRequests.splice(matchIndex, 1);
275
+ clearTimeout(pending.timer);
276
+ pending.resolve(data);
277
+ }
278
+ }
279
+ }
280
+ }
281
+ /**
282
+ * Extract the method name from a parsed message object.
283
+ *
284
+ * Supports common message formats:
285
+ * - { method: "..." }
286
+ * - { type: "..." }
287
+ * - Nested: { response: { method: "..." } }
288
+ */
289
+ extractMethod(obj) {
290
+ // Direct method field
291
+ if (typeof obj.method === 'string') {
292
+ return obj.method;
293
+ }
294
+ // Type field as fallback
295
+ if (typeof obj.type === 'string') {
296
+ return obj.type;
297
+ }
298
+ // Nested response object
299
+ if (obj.response && typeof obj.response === 'object') {
300
+ const response = obj.response;
301
+ if (typeof response.method === 'string') {
302
+ return response.method;
303
+ }
304
+ }
305
+ return undefined;
306
+ }
307
+ /**
308
+ * Handle an unexpected WebSocket disconnection.
309
+ *
310
+ * Cleans up state and initiates reconnection with exponential backoff.
311
+ *
312
+ * Requirement 10.2: Exponential backoff reconnection.
313
+ * Requirement 10.3: Emit disconnected and mark unavailable when retries exhausted.
314
+ */
315
+ handleDisconnect() {
316
+ const wasConnected = this._isConnected;
317
+ this._isConnected = false;
318
+ this.ws = null;
319
+ // If disposed, don't attempt reconnection
320
+ if (this._isDisposed) {
321
+ return;
322
+ }
323
+ // Attempt reconnection
324
+ if (wasConnected) {
325
+ this.attemptReconnect();
326
+ }
327
+ }
328
+ /**
329
+ * Attempt to reconnect with exponential backoff.
330
+ *
331
+ * Requirement 10.2: delay = initialDelay * 2^(attempt-1)
332
+ * Requirement 10.3: Mark provider unavailable when all retries exhausted.
333
+ */
334
+ attemptReconnect() {
335
+ this.reconnectAttempt++;
336
+ if (this.reconnectAttempt > this.maxReconnectAttempts) {
337
+ // All retries exhausted
338
+ this.cleanupPendingRequests(new Error('All reconnection attempts exhausted'));
339
+ this.emitter.emit('disconnected');
340
+ return;
341
+ }
342
+ const delay = calculateBackoffDelay(this.reconnectDelay, this.reconnectAttempt);
343
+ this.reconnectTimer = setTimeout(async () => {
344
+ this.reconnectTimer = null;
345
+ if (this._isDisposed) {
346
+ return;
347
+ }
348
+ try {
349
+ await this.connect();
350
+ }
351
+ catch {
352
+ // Connection failed, try again
353
+ this.attemptReconnect();
354
+ }
355
+ }, delay);
356
+ }
357
+ /**
358
+ * Cancel any pending reconnection timer.
359
+ */
360
+ cancelReconnect() {
361
+ if (this.reconnectTimer !== null) {
362
+ clearTimeout(this.reconnectTimer);
363
+ this.reconnectTimer = null;
364
+ }
365
+ }
366
+ /**
367
+ * Reject all pending requests with the given error and clean up timers.
368
+ *
369
+ * Requirement 10.4: Clean up all pending message handlers on disconnect.
370
+ */
371
+ cleanupPendingRequests(error) {
372
+ const pending = [...this.pendingRequests];
373
+ this.pendingRequests = [];
374
+ for (const req of pending) {
375
+ clearTimeout(req.timer);
376
+ req.reject(error);
377
+ }
378
+ }
379
+ /**
380
+ * Remove a specific pending request from the list.
381
+ */
382
+ removePendingRequest(request) {
383
+ const index = this.pendingRequests.indexOf(request);
384
+ if (index !== -1) {
385
+ this.pendingRequests.splice(index, 1);
386
+ }
387
+ }
388
+ }
389
+ exports.ClearNodeConnection = ClearNodeConnection;
390
+ //# sourceMappingURL=clear-node-connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clear-node-connection.js","sourceRoot":"","sources":["../../../src/yellow/clear-node-connection.ts"],"names":[],"mappings":"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"}