@jack-kernel/sdk 1.0.0 → 1.1.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.
Files changed (49) hide show
  1. package/dist/cjs/index.js +43 -2
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/yellow/channel-state-manager.js +167 -0
  4. package/dist/cjs/yellow/channel-state-manager.js.map +1 -0
  5. package/dist/cjs/yellow/clear-node-connection.js +390 -0
  6. package/dist/cjs/yellow/clear-node-connection.js.map +1 -0
  7. package/dist/cjs/yellow/event-mapper.js +254 -0
  8. package/dist/cjs/yellow/event-mapper.js.map +1 -0
  9. package/dist/cjs/yellow/serialization.js +130 -0
  10. package/dist/cjs/yellow/serialization.js.map +1 -0
  11. package/dist/cjs/yellow/session-key-manager.js +308 -0
  12. package/dist/cjs/yellow/session-key-manager.js.map +1 -0
  13. package/dist/cjs/yellow/types.js +12 -0
  14. package/dist/cjs/yellow/types.js.map +1 -0
  15. package/dist/cjs/yellow/yellow-provider.js +1545 -0
  16. package/dist/cjs/yellow/yellow-provider.js.map +1 -0
  17. package/dist/esm/index.js +34 -1
  18. package/dist/esm/index.js.map +1 -1
  19. package/dist/esm/yellow/channel-state-manager.js +163 -0
  20. package/dist/esm/yellow/channel-state-manager.js.map +1 -0
  21. package/dist/esm/yellow/clear-node-connection.js +385 -0
  22. package/dist/esm/yellow/clear-node-connection.js.map +1 -0
  23. package/dist/esm/yellow/event-mapper.js +248 -0
  24. package/dist/esm/yellow/event-mapper.js.map +1 -0
  25. package/dist/esm/yellow/serialization.js +125 -0
  26. package/dist/esm/yellow/serialization.js.map +1 -0
  27. package/dist/esm/yellow/session-key-manager.js +302 -0
  28. package/dist/esm/yellow/session-key-manager.js.map +1 -0
  29. package/dist/esm/yellow/types.js +11 -0
  30. package/dist/esm/yellow/types.js.map +1 -0
  31. package/dist/esm/yellow/yellow-provider.js +1538 -0
  32. package/dist/esm/yellow/yellow-provider.js.map +1 -0
  33. package/dist/types/index.d.ts +47 -2
  34. package/dist/types/index.d.ts.map +1 -1
  35. package/dist/types/yellow/channel-state-manager.d.ts +106 -0
  36. package/dist/types/yellow/channel-state-manager.d.ts.map +1 -0
  37. package/dist/types/yellow/clear-node-connection.d.ts +202 -0
  38. package/dist/types/yellow/clear-node-connection.d.ts.map +1 -0
  39. package/dist/types/yellow/event-mapper.d.ts +74 -0
  40. package/dist/types/yellow/event-mapper.d.ts.map +1 -0
  41. package/dist/types/yellow/serialization.d.ts +52 -0
  42. package/dist/types/yellow/serialization.d.ts.map +1 -0
  43. package/dist/types/yellow/session-key-manager.d.ts +179 -0
  44. package/dist/types/yellow/session-key-manager.d.ts.map +1 -0
  45. package/dist/types/yellow/types.d.ts +177 -0
  46. package/dist/types/yellow/types.d.ts.map +1 -0
  47. package/dist/types/yellow/yellow-provider.d.ts +303 -0
  48. package/dist/types/yellow/yellow-provider.d.ts.map +1 -0
  49. package/package.json +1 -1
@@ -0,0 +1,385 @@
1
+ /**
2
+ * ClearNode WebSocket Connection Manager
3
+ *
4
+ * Manages the WebSocket connection to Yellow Network's ClearNode relay server
5
+ * with reconnection logic, request-response correlation, and event emission.
6
+ *
7
+ * Key features:
8
+ * - Exponential backoff reconnection: delay = initialDelay * 2^(attempt-1)
9
+ * - Request-response correlation using method name matching
10
+ * - EventEmitter pattern for connected/disconnected events
11
+ * - Cleanup of all pending handlers on disconnect
12
+ *
13
+ * Requirements: 10.1, 10.2, 10.3, 10.4, 10.5
14
+ */
15
+ import { EventEmitter } from 'events';
16
+ /** WebSocket readyState constants */
17
+ const WS_OPEN = 1;
18
+ const WS_CONNECTING = 0;
19
+ /**
20
+ * Calculate the exponential backoff delay for a given reconnection attempt.
21
+ *
22
+ * Formula: delay = initialDelay * 2^(attempt - 1)
23
+ *
24
+ * This is exported as a pure function so it can be independently tested
25
+ * (including via property-based tests).
26
+ *
27
+ * @param initialDelay - The base delay in milliseconds
28
+ * @param attempt - The attempt number (1-based)
29
+ * @returns The delay in milliseconds before the given attempt
30
+ */
31
+ export function calculateBackoffDelay(initialDelay, attempt) {
32
+ if (attempt < 1) {
33
+ return initialDelay;
34
+ }
35
+ return initialDelay * Math.pow(2, attempt - 1);
36
+ }
37
+ /**
38
+ * Manages a WebSocket connection to Yellow Network's ClearNode.
39
+ *
40
+ * Provides:
41
+ * - connect/disconnect lifecycle management
42
+ * - send (fire-and-forget) and sendAndWait (request-response correlation)
43
+ * - Automatic reconnection with exponential backoff
44
+ * - Event emission for 'connected' and 'disconnected' events
45
+ * - Cleanup of pending handlers on disconnect
46
+ *
47
+ * Requirements: 10.1, 10.2, 10.3, 10.4, 10.5
48
+ */
49
+ export class ClearNodeConnection {
50
+ url;
51
+ maxReconnectAttempts;
52
+ reconnectDelay;
53
+ messageTimeout;
54
+ wsFactory;
55
+ ws = null;
56
+ emitter = new EventEmitter();
57
+ pendingRequests = [];
58
+ messageHandlers = [];
59
+ _isConnected = false;
60
+ _isDisposed = false;
61
+ reconnectAttempt = 0;
62
+ reconnectTimer = null;
63
+ /**
64
+ * @param url - The ClearNode WebSocket URL
65
+ * @param options - Connection configuration options
66
+ * @param wsFactory - Optional WebSocket factory for testing. Defaults to global WebSocket.
67
+ */
68
+ constructor(url, options, wsFactory) {
69
+ this.url = url;
70
+ this.maxReconnectAttempts = options?.maxReconnectAttempts ?? 5;
71
+ this.reconnectDelay = options?.reconnectDelay ?? 1000;
72
+ this.messageTimeout = options?.messageTimeout ?? 30000;
73
+ this.wsFactory = wsFactory ?? ((wsUrl) => new WebSocket(wsUrl));
74
+ }
75
+ /**
76
+ * Establish a WebSocket connection to ClearNode.
77
+ *
78
+ * Resolves when the connection is open and ready.
79
+ * Rejects if the connection fails to establish.
80
+ *
81
+ * Requirement 10.1: Emit a connected event on successful connection.
82
+ */
83
+ async connect() {
84
+ if (this._isDisposed) {
85
+ throw new Error('ClearNodeConnection has been disposed');
86
+ }
87
+ if (this._isConnected && this.ws) {
88
+ return;
89
+ }
90
+ return new Promise((resolve, reject) => {
91
+ let settled = false;
92
+ try {
93
+ this.ws = this.wsFactory(this.url);
94
+ }
95
+ catch (err) {
96
+ reject(new Error(`Failed to create WebSocket: ${err instanceof Error ? err.message : String(err)}`));
97
+ return;
98
+ }
99
+ this.ws.onopen = () => {
100
+ if (settled)
101
+ return;
102
+ settled = true;
103
+ this._isConnected = true;
104
+ this.reconnectAttempt = 0;
105
+ this.emitter.emit('connected');
106
+ resolve();
107
+ };
108
+ this.ws.onerror = (event) => {
109
+ if (settled)
110
+ return;
111
+ settled = true;
112
+ const errorMessage = event && typeof event === 'object' && 'message' in event
113
+ ? String(event.message)
114
+ : 'WebSocket connection failed';
115
+ reject(new Error(errorMessage));
116
+ };
117
+ this.ws.onclose = () => {
118
+ if (!settled) {
119
+ settled = true;
120
+ reject(new Error('WebSocket closed before connection was established'));
121
+ return;
122
+ }
123
+ this.handleDisconnect();
124
+ };
125
+ this.ws.onmessage = (event) => {
126
+ this.handleMessage(event.data);
127
+ };
128
+ });
129
+ }
130
+ /**
131
+ * Close the WebSocket connection and clean up all resources.
132
+ *
133
+ * Requirement 10.4: Clean up all pending message handlers on disconnect.
134
+ */
135
+ async disconnect() {
136
+ this._isDisposed = true;
137
+ this.cancelReconnect();
138
+ this.cleanupPendingRequests(new Error('Connection closed by client'));
139
+ this.messageHandlers = [];
140
+ if (this.ws) {
141
+ const ws = this.ws;
142
+ this.ws = null;
143
+ this._isConnected = false;
144
+ // Remove handlers to prevent reconnection attempts
145
+ ws.onopen = null;
146
+ ws.onclose = null;
147
+ ws.onerror = null;
148
+ ws.onmessage = null;
149
+ // Only close if not already closed/closing
150
+ if (ws.readyState === WS_OPEN || ws.readyState === WS_CONNECTING) {
151
+ ws.close();
152
+ }
153
+ this.emitter.emit('disconnected');
154
+ }
155
+ this._isConnected = false;
156
+ }
157
+ /**
158
+ * Send a message and wait for a correlated response.
159
+ *
160
+ * The response is matched by method name: when a message is received
161
+ * that contains a matching method field, the promise resolves with that response.
162
+ *
163
+ * Requirement 10.5: Request-response correlation using method name matching.
164
+ *
165
+ * @param message - The message string to send
166
+ * @param method - The method name to correlate the response with
167
+ * @param timeout - Optional timeout in ms (defaults to messageTimeout)
168
+ * @returns The parsed response data
169
+ * @throws Error if the connection is not open, the request times out, or the connection drops
170
+ */
171
+ async sendAndWait(message, method, timeout) {
172
+ if (!this._isConnected || !this.ws || this.ws.readyState !== WS_OPEN) {
173
+ throw new Error('WebSocket is not connected');
174
+ }
175
+ const effectiveTimeout = timeout ?? this.messageTimeout;
176
+ return new Promise((resolve, reject) => {
177
+ const timer = setTimeout(() => {
178
+ this.removePendingRequest(pending);
179
+ reject(new Error(`Request timed out waiting for response to method: ${method}`));
180
+ }, effectiveTimeout);
181
+ const pending = {
182
+ method,
183
+ resolve: resolve,
184
+ reject,
185
+ timer,
186
+ };
187
+ this.pendingRequests.push(pending);
188
+ this.ws.send(message);
189
+ });
190
+ }
191
+ /**
192
+ * Send a message without waiting for a response (fire-and-forget).
193
+ *
194
+ * @param message - The message string to send
195
+ * @throws Error if the connection is not open
196
+ */
197
+ send(message) {
198
+ if (!this._isConnected || !this.ws || this.ws.readyState !== WS_OPEN) {
199
+ throw new Error('WebSocket is not connected');
200
+ }
201
+ this.ws.send(message);
202
+ }
203
+ /**
204
+ * Register a handler for incoming messages.
205
+ *
206
+ * Handlers receive the parsed message data for all incoming messages
207
+ * (including those that match pending requests).
208
+ *
209
+ * @param handler - Callback invoked with the parsed message data
210
+ */
211
+ onMessage(handler) {
212
+ this.messageHandlers.push(handler);
213
+ }
214
+ /**
215
+ * Whether the WebSocket connection is currently open and ready.
216
+ */
217
+ get isConnected() {
218
+ return this._isConnected;
219
+ }
220
+ /**
221
+ * Register an event listener for connection lifecycle events.
222
+ *
223
+ * Supported events: 'connected', 'disconnected'
224
+ */
225
+ on(event, handler) {
226
+ this.emitter.on(event, handler);
227
+ }
228
+ /**
229
+ * Remove an event listener.
230
+ */
231
+ off(event, handler) {
232
+ this.emitter.off(event, handler);
233
+ }
234
+ // ============================================================================
235
+ // Private Methods
236
+ // ============================================================================
237
+ /**
238
+ * Handle an incoming WebSocket message.
239
+ *
240
+ * Parses the message as JSON and checks for method-based correlation
241
+ * with pending requests. Also dispatches to all registered message handlers.
242
+ */
243
+ handleMessage(rawData) {
244
+ let data;
245
+ try {
246
+ const text = typeof rawData === 'string' ? rawData : String(rawData);
247
+ data = JSON.parse(text);
248
+ }
249
+ catch {
250
+ // If the message is not valid JSON, pass the raw data
251
+ data = rawData;
252
+ }
253
+ // Dispatch to all registered message handlers
254
+ for (const handler of this.messageHandlers) {
255
+ try {
256
+ handler(data);
257
+ }
258
+ catch {
259
+ // Swallow handler errors to prevent one handler from breaking others
260
+ }
261
+ }
262
+ // Check for method-based correlation with pending requests
263
+ if (data && typeof data === 'object') {
264
+ const messageObj = data;
265
+ const responseMethod = this.extractMethod(messageObj);
266
+ if (responseMethod) {
267
+ const matchIndex = this.pendingRequests.findIndex((req) => req.method === responseMethod);
268
+ if (matchIndex !== -1) {
269
+ const pending = this.pendingRequests[matchIndex];
270
+ this.pendingRequests.splice(matchIndex, 1);
271
+ clearTimeout(pending.timer);
272
+ pending.resolve(data);
273
+ }
274
+ }
275
+ }
276
+ }
277
+ /**
278
+ * Extract the method name from a parsed message object.
279
+ *
280
+ * Supports common message formats:
281
+ * - { method: "..." }
282
+ * - { type: "..." }
283
+ * - Nested: { response: { method: "..." } }
284
+ */
285
+ extractMethod(obj) {
286
+ // Direct method field
287
+ if (typeof obj.method === 'string') {
288
+ return obj.method;
289
+ }
290
+ // Type field as fallback
291
+ if (typeof obj.type === 'string') {
292
+ return obj.type;
293
+ }
294
+ // Nested response object
295
+ if (obj.response && typeof obj.response === 'object') {
296
+ const response = obj.response;
297
+ if (typeof response.method === 'string') {
298
+ return response.method;
299
+ }
300
+ }
301
+ return undefined;
302
+ }
303
+ /**
304
+ * Handle an unexpected WebSocket disconnection.
305
+ *
306
+ * Cleans up state and initiates reconnection with exponential backoff.
307
+ *
308
+ * Requirement 10.2: Exponential backoff reconnection.
309
+ * Requirement 10.3: Emit disconnected and mark unavailable when retries exhausted.
310
+ */
311
+ handleDisconnect() {
312
+ const wasConnected = this._isConnected;
313
+ this._isConnected = false;
314
+ this.ws = null;
315
+ // If disposed, don't attempt reconnection
316
+ if (this._isDisposed) {
317
+ return;
318
+ }
319
+ // Attempt reconnection
320
+ if (wasConnected) {
321
+ this.attemptReconnect();
322
+ }
323
+ }
324
+ /**
325
+ * Attempt to reconnect with exponential backoff.
326
+ *
327
+ * Requirement 10.2: delay = initialDelay * 2^(attempt-1)
328
+ * Requirement 10.3: Mark provider unavailable when all retries exhausted.
329
+ */
330
+ attemptReconnect() {
331
+ this.reconnectAttempt++;
332
+ if (this.reconnectAttempt > this.maxReconnectAttempts) {
333
+ // All retries exhausted
334
+ this.cleanupPendingRequests(new Error('All reconnection attempts exhausted'));
335
+ this.emitter.emit('disconnected');
336
+ return;
337
+ }
338
+ const delay = calculateBackoffDelay(this.reconnectDelay, this.reconnectAttempt);
339
+ this.reconnectTimer = setTimeout(async () => {
340
+ this.reconnectTimer = null;
341
+ if (this._isDisposed) {
342
+ return;
343
+ }
344
+ try {
345
+ await this.connect();
346
+ }
347
+ catch {
348
+ // Connection failed, try again
349
+ this.attemptReconnect();
350
+ }
351
+ }, delay);
352
+ }
353
+ /**
354
+ * Cancel any pending reconnection timer.
355
+ */
356
+ cancelReconnect() {
357
+ if (this.reconnectTimer !== null) {
358
+ clearTimeout(this.reconnectTimer);
359
+ this.reconnectTimer = null;
360
+ }
361
+ }
362
+ /**
363
+ * Reject all pending requests with the given error and clean up timers.
364
+ *
365
+ * Requirement 10.4: Clean up all pending message handlers on disconnect.
366
+ */
367
+ cleanupPendingRequests(error) {
368
+ const pending = [...this.pendingRequests];
369
+ this.pendingRequests = [];
370
+ for (const req of pending) {
371
+ clearTimeout(req.timer);
372
+ req.reject(error);
373
+ }
374
+ }
375
+ /**
376
+ * Remove a specific pending request from the list.
377
+ */
378
+ removePendingRequest(request) {
379
+ const index = this.pendingRequests.indexOf(request);
380
+ if (index !== -1) {
381
+ this.pendingRequests.splice(index, 1);
382
+ }
383
+ }
384
+ }
385
+ //# 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":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA8BtC,qCAAqC;AACrC,MAAM,OAAO,GAAG,CAAC,CAAC;AAClB,MAAM,aAAa,GAAG,CAAC,CAAC;AAmBxB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAAoB,EAAE,OAAe;IACzE,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,mBAAmB;IACb,GAAG,CAAS;IACZ,oBAAoB,CAAS;IAC7B,cAAc,CAAS;IACvB,cAAc,CAAS;IACvB,SAAS,CAAmB;IAErC,EAAE,GAAsB,IAAI,CAAC;IAC7B,OAAO,GAAiB,IAAI,YAAY,EAAE,CAAC;IAC3C,eAAe,GAAqB,EAAE,CAAC;IACvC,eAAe,GAAmC,EAAE,CAAC;IACrD,YAAY,GAAY,KAAK,CAAC;IAC9B,WAAW,GAAY,KAAK,CAAC;IAC7B,gBAAgB,GAAW,CAAC,CAAC;IAC7B,cAAc,GAAyC,IAAI,CAAC;IAEpE;;;;OAIG;IACH,YAAY,GAAW,EAAE,OAA2B,EAAE,SAA4B;QAChF,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,oBAAoB,GAAG,OAAO,EAAE,oBAAoB,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,IAAI,CAAC;QACtD,IAAI,CAAC,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,KAAK,CAAC;QACvD,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,KAAK,CAA0B,CAAC,CAAC;IACnG,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QAED,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,IAAI,OAAO,GAAG,KAAK,CAAC;YAEpB,IAAI,CAAC;gBACH,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBACrG,OAAO;YACT,CAAC;YAED,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE;gBACpB,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;gBAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC/B,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,KAAc,EAAE,EAAE;gBACnC,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,YAAY,GAChB,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK;oBACtD,CAAC,CAAC,MAAM,CAAE,KAA8B,CAAC,OAAO,CAAC;oBACjD,CAAC,CAAC,6BAA6B,CAAC;gBACpC,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YAClC,CAAC,CAAC;YAEF,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE;gBACrB,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM,CAAC,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC,CAAC;oBACxE,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,CAAC,CAAC;YAEF,IAAI,CAAC,EAAE,CAAC,SAAS,GAAG,CAAC,KAAwB,EAAE,EAAE;gBAC/C,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,sBAAsB,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAE1B,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAE1B,mDAAmD;YACnD,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC;YACjB,EAAE,CAAC,OAAO,GAAG,IAAI,CAAC;YAClB,EAAE,CAAC,OAAO,GAAG,IAAI,CAAC;YAClB,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC;YAEpB,2CAA2C;YAC3C,IAAI,EAAE,CAAC,UAAU,KAAK,OAAO,IAAI,EAAE,CAAC,UAAU,KAAK,aAAa,EAAE,CAAC;gBACjE,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,WAAW,CAAI,OAAe,EAAE,MAAc,EAAE,OAAgB;QACpE,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,gBAAgB,GAAG,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC;QAExD,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;gBACnC,MAAM,CAAC,IAAI,KAAK,CAAC,qDAAqD,MAAM,EAAE,CAAC,CAAC,CAAC;YACnF,CAAC,EAAE,gBAAgB,CAAC,CAAC;YAErB,MAAM,OAAO,GAAmB;gBAC9B,MAAM;gBACN,OAAO,EAAE,OAAmC;gBAC5C,MAAM;gBACN,KAAK;aACN,CAAC;YAEF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,CAAC,EAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,OAAe;QAClB,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;IAED;;;;;;;OAOG;IACH,SAAS,CAAC,OAAgC;QACxC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,EAAE,CAAC,KAAa,EAAE,OAAqC;QACrD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,KAAa,EAAE,OAAqC;QACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,+EAA+E;IAC/E,kBAAkB;IAClB,+EAA+E;IAE/E;;;;;OAKG;IACK,aAAa,CAAC,OAAgB;QACpC,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,sDAAsD;YACtD,IAAI,GAAG,OAAO,CAAC;QACjB,CAAC;QAED,8CAA8C;QAC9C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAC3C,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,qEAAqE;YACvE,CAAC;QACH,CAAC;QAED,2DAA2D;QAC3D,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,IAA+B,CAAC;YACnD,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YAEtD,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAC/C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,cAAc,CACvC,CAAC;gBAEF,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;oBACtB,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;oBACjD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;oBAC3C,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBAC5B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACK,aAAa,CAAC,GAA4B;QAChD,sBAAsB;QACtB,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO,GAAG,CAAC,MAAM,CAAC;QACpB,CAAC;QAED,yBAAyB;QACzB,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,GAAG,CAAC,IAAI,CAAC;QAClB,CAAC;QAED,yBAAyB;QACzB,IAAI,GAAG,CAAC,QAAQ,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAmC,CAAC;YACzD,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxC,OAAO,QAAQ,CAAC,MAAM,CAAC;YACzB,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;OAOG;IACK,gBAAgB;QACtB,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACvC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QAEf,0CAA0C;QAC1C,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,uBAAuB;QACvB,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,gBAAgB;QACtB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAExB,IAAI,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACtD,wBAAwB;YACxB,IAAI,CAAC,sBAAsB,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC;YAC9E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAEhF,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;YAC1C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAE3B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;gBAC/B,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACjC,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,sBAAsB,CAAC,KAAY;QACzC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1C,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAE1B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACxB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,OAAuB;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACpD,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Yellow Network Event-to-Status Mapper
3
+ *
4
+ * Maps Yellow Network events, channel statuses, and state intents to JACK
5
+ * ExecutionStatus values. These are pure functions with no side effects,
6
+ * extracted from the dashboard's route.ts mapping tables into SDK-level
7
+ * reusable functions.
8
+ *
9
+ * Requirements: 9.1, 9.2, 9.3, 9.4, 9.5, 9.6
10
+ */
11
+ import { ExecutionStatus } from '../types.js';
12
+ // ============================================================================
13
+ // Terminal statuses — only SETTLED, ABORTED, and EXPIRED are terminal
14
+ // ============================================================================
15
+ const TERMINAL_STATUSES = new Set([
16
+ ExecutionStatus.SETTLED,
17
+ ExecutionStatus.ABORTED,
18
+ ExecutionStatus.EXPIRED,
19
+ ]);
20
+ // ============================================================================
21
+ // Yellow Event Mapping Table
22
+ // ============================================================================
23
+ const EVENT_STATUS_MAP = {
24
+ quote_accepted: {
25
+ executionStatus: ExecutionStatus.QUOTED,
26
+ stepLabel: 'Solver Quote Accepted (Yellow Network)',
27
+ stepStatus: 'COMPLETED',
28
+ isTerminal: false,
29
+ },
30
+ solver_quoted: {
31
+ executionStatus: ExecutionStatus.QUOTED,
32
+ stepLabel: 'Solver Quote Received (Yellow Network)',
33
+ stepStatus: 'COMPLETED',
34
+ isTerminal: false,
35
+ },
36
+ execution_started: {
37
+ executionStatus: ExecutionStatus.EXECUTING,
38
+ stepLabel: 'Execution Started (Yellow Network)',
39
+ stepStatus: 'IN_PROGRESS',
40
+ isTerminal: false,
41
+ },
42
+ routing_started: {
43
+ executionStatus: ExecutionStatus.EXECUTING,
44
+ stepLabel: 'Cross-Chain Routing Started (Yellow Network)',
45
+ stepStatus: 'IN_PROGRESS',
46
+ isTerminal: false,
47
+ },
48
+ settlement_submitted: {
49
+ executionStatus: ExecutionStatus.SETTLING,
50
+ stepLabel: 'Settlement Submitted (Yellow Network)',
51
+ stepStatus: 'IN_PROGRESS',
52
+ isTerminal: false,
53
+ },
54
+ settled: {
55
+ executionStatus: ExecutionStatus.SETTLED,
56
+ stepLabel: 'Settlement Finalized (Yellow Network)',
57
+ stepStatus: 'COMPLETED',
58
+ isTerminal: true,
59
+ },
60
+ settlement_finalized: {
61
+ executionStatus: ExecutionStatus.SETTLED,
62
+ stepLabel: 'Settlement Finalized (Yellow Network)',
63
+ stepStatus: 'COMPLETED',
64
+ isTerminal: true,
65
+ },
66
+ failed: {
67
+ executionStatus: ExecutionStatus.ABORTED,
68
+ stepLabel: 'Execution Failed (Yellow Network)',
69
+ stepStatus: 'FAILED',
70
+ isTerminal: true,
71
+ },
72
+ execution_failed: {
73
+ executionStatus: ExecutionStatus.ABORTED,
74
+ stepLabel: 'Execution Failed (Yellow Network)',
75
+ stepStatus: 'FAILED',
76
+ isTerminal: true,
77
+ },
78
+ settlement_failed: {
79
+ executionStatus: ExecutionStatus.ABORTED,
80
+ stepLabel: 'Settlement Failed (Yellow Network)',
81
+ stepStatus: 'FAILED',
82
+ isTerminal: true,
83
+ },
84
+ expired: {
85
+ executionStatus: ExecutionStatus.EXPIRED,
86
+ stepLabel: 'Intent Expired (Yellow Network)',
87
+ stepStatus: 'FAILED',
88
+ isTerminal: true,
89
+ },
90
+ canceled: {
91
+ executionStatus: ExecutionStatus.ABORTED,
92
+ stepLabel: 'Intent Canceled (Yellow Network)',
93
+ stepStatus: 'FAILED',
94
+ isTerminal: true,
95
+ },
96
+ };
97
+ // ============================================================================
98
+ // Channel Status Mapping Table
99
+ // ============================================================================
100
+ const CHANNEL_STATUS_MAP = {
101
+ void: {
102
+ executionStatus: ExecutionStatus.CREATED,
103
+ stepLabel: 'Channel Status: VOID (ERC-7824)',
104
+ stepStatus: 'COMPLETED',
105
+ isTerminal: false,
106
+ },
107
+ initial: {
108
+ executionStatus: ExecutionStatus.QUOTED,
109
+ stepLabel: 'Channel Status: INITIAL (ERC-7824)',
110
+ stepStatus: 'IN_PROGRESS',
111
+ isTerminal: false,
112
+ },
113
+ active: {
114
+ executionStatus: ExecutionStatus.EXECUTING,
115
+ stepLabel: 'Channel Status: ACTIVE (ERC-7824)',
116
+ stepStatus: 'IN_PROGRESS',
117
+ isTerminal: false,
118
+ },
119
+ dispute: {
120
+ executionStatus: ExecutionStatus.EXECUTING,
121
+ stepLabel: 'Channel Status: DISPUTE (ERC-7824)',
122
+ stepStatus: 'IN_PROGRESS',
123
+ isTerminal: false,
124
+ },
125
+ final: {
126
+ executionStatus: ExecutionStatus.SETTLED,
127
+ stepLabel: 'Channel Status: FINAL (ERC-7824)',
128
+ stepStatus: 'COMPLETED',
129
+ isTerminal: true,
130
+ },
131
+ };
132
+ // ============================================================================
133
+ // State Intent Mapping Table
134
+ // ============================================================================
135
+ const STATE_INTENT_MAP = {
136
+ initialize: {
137
+ executionStatus: ExecutionStatus.QUOTED,
138
+ stepLabel: 'State Intent: INITIALIZE (ERC-7824)',
139
+ stepStatus: 'IN_PROGRESS',
140
+ isTerminal: false,
141
+ },
142
+ operate: {
143
+ executionStatus: ExecutionStatus.EXECUTING,
144
+ stepLabel: 'State Intent: OPERATE (ERC-7824)',
145
+ stepStatus: 'IN_PROGRESS',
146
+ isTerminal: false,
147
+ },
148
+ resize: {
149
+ executionStatus: ExecutionStatus.EXECUTING,
150
+ stepLabel: 'State Intent: RESIZE (ERC-7824)',
151
+ stepStatus: 'COMPLETED',
152
+ isTerminal: false,
153
+ },
154
+ finalize: {
155
+ executionStatus: ExecutionStatus.SETTLED,
156
+ stepLabel: 'State Intent: FINALIZE (ERC-7824)',
157
+ stepStatus: 'COMPLETED',
158
+ isTerminal: true,
159
+ },
160
+ };
161
+ // ============================================================================
162
+ // Normalization Helper
163
+ // ============================================================================
164
+ /**
165
+ * Normalizes an event/status/intent string to lowercase with underscores.
166
+ * Trims whitespace and replaces spaces and hyphens with underscores.
167
+ */
168
+ function normalizeKey(value) {
169
+ return value.trim().toLowerCase().replace(/[\s-]+/g, '_');
170
+ }
171
+ // ============================================================================
172
+ // Public Mapping Functions
173
+ // ============================================================================
174
+ /**
175
+ * Map a Yellow Network event name to a JACK MappedEvent.
176
+ *
177
+ * Accepts event names in any casing; normalizes to lowercase with underscores.
178
+ * Returns undefined for unknown events.
179
+ *
180
+ * @param event - The Yellow Network event name (e.g., "quote_accepted", "settled")
181
+ * @returns The corresponding MappedEvent, or undefined if the event is unknown
182
+ *
183
+ * Requirements: 9.1, 9.2, 9.3, 9.4, 9.5
184
+ */
185
+ export function mapYellowEvent(event) {
186
+ const key = normalizeKey(event);
187
+ return Object.hasOwn(EVENT_STATUS_MAP, key) ? EVENT_STATUS_MAP[key] : undefined;
188
+ }
189
+ /**
190
+ * Map a channel status to a JACK MappedEvent.
191
+ *
192
+ * Accepts channel statuses in any casing (e.g., "ACTIVE", "active", "Active").
193
+ * Returns undefined for unknown statuses.
194
+ *
195
+ * @param status - The ERC-7824 channel status (e.g., "VOID", "ACTIVE", "FINAL")
196
+ * @returns The corresponding MappedEvent, or undefined if the status is unknown
197
+ *
198
+ * Requirement: 9.6
199
+ */
200
+ export function mapChannelStatus(status) {
201
+ const key = normalizeKey(status);
202
+ return Object.hasOwn(CHANNEL_STATUS_MAP, key) ? CHANNEL_STATUS_MAP[key] : undefined;
203
+ }
204
+ /**
205
+ * Map a state intent to a JACK MappedEvent.
206
+ *
207
+ * Accepts state intents in any casing (e.g., "FINALIZE", "finalize", "Finalize").
208
+ * Returns undefined for unknown intents.
209
+ *
210
+ * @param intent - The ERC-7824 state intent (e.g., "INITIALIZE", "OPERATE", "FINALIZE")
211
+ * @returns The corresponding MappedEvent, or undefined if the intent is unknown
212
+ *
213
+ * Requirement: 9.6
214
+ */
215
+ export function mapStateIntent(intent) {
216
+ const key = normalizeKey(intent);
217
+ return Object.hasOwn(STATE_INTENT_MAP, key) ? STATE_INTENT_MAP[key] : undefined;
218
+ }
219
+ /**
220
+ * Infer the best mapping from a notification payload.
221
+ *
222
+ * Checks fields in priority order: event → channelStatus → stateIntent.
223
+ * Returns the first successful mapping, or undefined if no field matches.
224
+ *
225
+ * @param notification - An object with optional event, channelStatus, and stateIntent fields
226
+ * @returns The best matching MappedEvent, or undefined if no mapping is found
227
+ *
228
+ * Requirements: 9.1, 9.2, 9.3, 9.4, 9.5, 9.6
229
+ */
230
+ export function inferMapping(notification) {
231
+ if (notification.event) {
232
+ const mapped = mapYellowEvent(notification.event);
233
+ if (mapped)
234
+ return mapped;
235
+ }
236
+ if (notification.channelStatus) {
237
+ const mapped = mapChannelStatus(notification.channelStatus);
238
+ if (mapped)
239
+ return mapped;
240
+ }
241
+ if (notification.stateIntent) {
242
+ const mapped = mapStateIntent(notification.stateIntent);
243
+ if (mapped)
244
+ return mapped;
245
+ }
246
+ return undefined;
247
+ }
248
+ //# sourceMappingURL=event-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-mapper.js","sourceRoot":"","sources":["../../../src/yellow/event-mapper.ts"],"names":[],"mappings":"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"}