@meshwhisper/sdk 0.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 (163) hide show
  1. package/README.md +138 -0
  2. package/dist/browser/index.d.ts +4 -0
  3. package/dist/browser/index.d.ts.map +1 -0
  4. package/dist/browser/index.js +19 -0
  5. package/dist/browser/index.js.map +1 -0
  6. package/dist/chaff/index.d.ts +91 -0
  7. package/dist/chaff/index.d.ts.map +1 -0
  8. package/dist/chaff/index.js +268 -0
  9. package/dist/chaff/index.js.map +1 -0
  10. package/dist/cluster/index.d.ts +159 -0
  11. package/dist/cluster/index.d.ts.map +1 -0
  12. package/dist/cluster/index.js +393 -0
  13. package/dist/cluster/index.js.map +1 -0
  14. package/dist/compliance/index.d.ts +129 -0
  15. package/dist/compliance/index.d.ts.map +1 -0
  16. package/dist/compliance/index.js +315 -0
  17. package/dist/compliance/index.js.map +1 -0
  18. package/dist/crypto/index.d.ts +65 -0
  19. package/dist/crypto/index.d.ts.map +1 -0
  20. package/dist/crypto/index.js +146 -0
  21. package/dist/crypto/index.js.map +1 -0
  22. package/dist/group/index.d.ts +155 -0
  23. package/dist/group/index.d.ts.map +1 -0
  24. package/dist/group/index.js +560 -0
  25. package/dist/group/index.js.map +1 -0
  26. package/dist/index.d.ts +7 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +11 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/namespace/index.d.ts +155 -0
  31. package/dist/namespace/index.d.ts.map +1 -0
  32. package/dist/namespace/index.js +278 -0
  33. package/dist/namespace/index.js.map +1 -0
  34. package/dist/node/index.d.ts +4 -0
  35. package/dist/node/index.d.ts.map +1 -0
  36. package/dist/node/index.js +19 -0
  37. package/dist/node/index.js.map +1 -0
  38. package/dist/packet/index.d.ts +63 -0
  39. package/dist/packet/index.d.ts.map +1 -0
  40. package/dist/packet/index.js +244 -0
  41. package/dist/packet/index.js.map +1 -0
  42. package/dist/permissions/index.d.ts +107 -0
  43. package/dist/permissions/index.d.ts.map +1 -0
  44. package/dist/permissions/index.js +282 -0
  45. package/dist/permissions/index.js.map +1 -0
  46. package/dist/persistence/idb-storage.d.ts +27 -0
  47. package/dist/persistence/idb-storage.d.ts.map +1 -0
  48. package/dist/persistence/idb-storage.js +75 -0
  49. package/dist/persistence/idb-storage.js.map +1 -0
  50. package/dist/persistence/index.d.ts +4 -0
  51. package/dist/persistence/index.d.ts.map +1 -0
  52. package/dist/persistence/index.js +3 -0
  53. package/dist/persistence/index.js.map +1 -0
  54. package/dist/persistence/node-storage.d.ts +33 -0
  55. package/dist/persistence/node-storage.d.ts.map +1 -0
  56. package/dist/persistence/node-storage.js +90 -0
  57. package/dist/persistence/node-storage.js.map +1 -0
  58. package/dist/persistence/serialization.d.ts +4 -0
  59. package/dist/persistence/serialization.d.ts.map +1 -0
  60. package/dist/persistence/serialization.js +49 -0
  61. package/dist/persistence/serialization.js.map +1 -0
  62. package/dist/persistence/types.d.ts +29 -0
  63. package/dist/persistence/types.d.ts.map +1 -0
  64. package/dist/persistence/types.js +5 -0
  65. package/dist/persistence/types.js.map +1 -0
  66. package/dist/ratchet/index.d.ts +80 -0
  67. package/dist/ratchet/index.d.ts.map +1 -0
  68. package/dist/ratchet/index.js +259 -0
  69. package/dist/ratchet/index.js.map +1 -0
  70. package/dist/reciprocity/index.d.ts +109 -0
  71. package/dist/reciprocity/index.d.ts.map +1 -0
  72. package/dist/reciprocity/index.js +311 -0
  73. package/dist/reciprocity/index.js.map +1 -0
  74. package/dist/relay/index.d.ts +87 -0
  75. package/dist/relay/index.d.ts.map +1 -0
  76. package/dist/relay/index.js +286 -0
  77. package/dist/relay/index.js.map +1 -0
  78. package/dist/routing/index.d.ts +136 -0
  79. package/dist/routing/index.d.ts.map +1 -0
  80. package/dist/routing/index.js +478 -0
  81. package/dist/routing/index.js.map +1 -0
  82. package/dist/sdk/index.d.ts +322 -0
  83. package/dist/sdk/index.d.ts.map +1 -0
  84. package/dist/sdk/index.js +1530 -0
  85. package/dist/sdk/index.js.map +1 -0
  86. package/dist/sybil/index.d.ts +123 -0
  87. package/dist/sybil/index.d.ts.map +1 -0
  88. package/dist/sybil/index.js +491 -0
  89. package/dist/sybil/index.js.map +1 -0
  90. package/dist/transport/browser/index.d.ts +34 -0
  91. package/dist/transport/browser/index.d.ts.map +1 -0
  92. package/dist/transport/browser/index.js +176 -0
  93. package/dist/transport/browser/index.js.map +1 -0
  94. package/dist/transport/local/index.d.ts +57 -0
  95. package/dist/transport/local/index.d.ts.map +1 -0
  96. package/dist/transport/local/index.js +442 -0
  97. package/dist/transport/local/index.js.map +1 -0
  98. package/dist/transport/negotiator/index.d.ts +79 -0
  99. package/dist/transport/negotiator/index.d.ts.map +1 -0
  100. package/dist/transport/negotiator/index.js +289 -0
  101. package/dist/transport/negotiator/index.js.map +1 -0
  102. package/dist/transport/node/index.d.ts +56 -0
  103. package/dist/transport/node/index.d.ts.map +1 -0
  104. package/dist/transport/node/index.js +209 -0
  105. package/dist/transport/node/index.js.map +1 -0
  106. package/dist/transport/noop/index.d.ts +11 -0
  107. package/dist/transport/noop/index.d.ts.map +1 -0
  108. package/dist/transport/noop/index.js +20 -0
  109. package/dist/transport/noop/index.js.map +1 -0
  110. package/dist/transport/p2p/index.d.ts +109 -0
  111. package/dist/transport/p2p/index.d.ts.map +1 -0
  112. package/dist/transport/p2p/index.js +237 -0
  113. package/dist/transport/p2p/index.js.map +1 -0
  114. package/dist/transport/websocket/index.d.ts +89 -0
  115. package/dist/transport/websocket/index.d.ts.map +1 -0
  116. package/dist/transport/websocket/index.js +498 -0
  117. package/dist/transport/websocket/index.js.map +1 -0
  118. package/dist/transport/websocket/serialize.d.ts +5 -0
  119. package/dist/transport/websocket/serialize.d.ts.map +1 -0
  120. package/dist/transport/websocket/serialize.js +55 -0
  121. package/dist/transport/websocket/serialize.js.map +1 -0
  122. package/dist/types.d.ts +215 -0
  123. package/dist/types.d.ts.map +1 -0
  124. package/dist/types.js +15 -0
  125. package/dist/types.js.map +1 -0
  126. package/dist/x3dh/index.d.ts +120 -0
  127. package/dist/x3dh/index.d.ts.map +1 -0
  128. package/dist/x3dh/index.js +290 -0
  129. package/dist/x3dh/index.js.map +1 -0
  130. package/package.json +59 -0
  131. package/src/browser/index.ts +19 -0
  132. package/src/chaff/index.ts +340 -0
  133. package/src/cluster/index.ts +482 -0
  134. package/src/compliance/index.ts +407 -0
  135. package/src/crypto/index.ts +193 -0
  136. package/src/group/index.ts +719 -0
  137. package/src/index.ts +87 -0
  138. package/src/lz4js.d.ts +58 -0
  139. package/src/namespace/index.ts +336 -0
  140. package/src/node/index.ts +19 -0
  141. package/src/packet/index.ts +326 -0
  142. package/src/permissions/index.ts +405 -0
  143. package/src/persistence/idb-storage.ts +83 -0
  144. package/src/persistence/index.ts +3 -0
  145. package/src/persistence/node-storage.ts +96 -0
  146. package/src/persistence/serialization.ts +75 -0
  147. package/src/persistence/types.ts +33 -0
  148. package/src/ratchet/index.ts +363 -0
  149. package/src/reciprocity/index.ts +371 -0
  150. package/src/relay/index.ts +382 -0
  151. package/src/routing/index.ts +577 -0
  152. package/src/sdk/index.ts +1994 -0
  153. package/src/sybil/index.ts +661 -0
  154. package/src/transport/browser/index.ts +201 -0
  155. package/src/transport/local/index.ts +540 -0
  156. package/src/transport/negotiator/index.ts +397 -0
  157. package/src/transport/node/index.ts +234 -0
  158. package/src/transport/noop/index.ts +22 -0
  159. package/src/transport/p2p/index.ts +345 -0
  160. package/src/transport/websocket/index.ts +660 -0
  161. package/src/transport/websocket/serialize.ts +68 -0
  162. package/src/types.ts +275 -0
  163. package/src/x3dh/index.ts +388 -0
@@ -0,0 +1,478 @@
1
+ // ============================================================
2
+ // MeshWhisper SDK — Social Graph Routing
3
+ // Uses social proximity (not geographic or DHT) as routing
4
+ // topology. Implements Bubble-Rap-inspired discovery with
5
+ // small-world properties (~6 hop average path length).
6
+ // See PRD section 7.1.
7
+ // ============================================================
8
+ // ---------------------------------------------------------------------------
9
+ // Constants
10
+ // ---------------------------------------------------------------------------
11
+ /** Default TTL for proximity table entries (1 hour). */
12
+ const DEFAULT_PEER_TTL_MS = 60 * 60 * 1000;
13
+ /** Default TTL for cached routes (5 minutes). */
14
+ const DEFAULT_ROUTE_TTL_MS = 5 * 60 * 1000;
15
+ /** Default timeout for pending route requests (5 seconds). */
16
+ const DEFAULT_REQUEST_TIMEOUT_MS = 5 * 1000;
17
+ /** Maximum number of recent packet hashes kept for deduplication. */
18
+ const SEEN_PACKET_CAPACITY = 10_000;
19
+ /** Number of socially-closest peers to gossip route requests to. */
20
+ const GOSSIP_FANOUT = 5;
21
+ // ---------------------------------------------------------------------------
22
+ // Helpers
23
+ // ---------------------------------------------------------------------------
24
+ /** Convert a Uint8Array to a hex string for use as a Map key. */
25
+ function hashToHex(hash) {
26
+ let out = '';
27
+ for (let i = 0; i < hash.length; i++) {
28
+ out += hash[i].toString(16).padStart(2, '0');
29
+ }
30
+ return out;
31
+ }
32
+ /** Constant-time-ish byte array equality. */
33
+ function bytesEqual(a, b) {
34
+ if (a.length !== b.length)
35
+ return false;
36
+ let diff = 0;
37
+ for (let i = 0; i < a.length; i++) {
38
+ diff |= a[i] ^ b[i];
39
+ }
40
+ return diff === 0;
41
+ }
42
+ /**
43
+ * XOR distance between two destination hashes.
44
+ * Returns a number usable for comparison (lower = closer).
45
+ * Works on up to 8-byte hashes.
46
+ */
47
+ function xorDistance(a, b) {
48
+ const len = Math.min(a.length, b.length);
49
+ let distance = 0;
50
+ for (let i = 0; i < len; i++) {
51
+ distance = distance * 256 + (a[i] ^ b[i]);
52
+ }
53
+ return distance;
54
+ }
55
+ /**
56
+ * Compute a simple hash of a packet for deduplication.
57
+ * Uses destHash + senderEphemeralId + first 8 bytes of payload.
58
+ */
59
+ function packetFingerprint(packet) {
60
+ const parts = [];
61
+ for (let i = 0; i < packet.destHash.length; i++) {
62
+ parts.push(packet.destHash[i]);
63
+ }
64
+ for (let i = 0; i < packet.senderEphemeralId.length; i++) {
65
+ parts.push(packet.senderEphemeralId[i]);
66
+ }
67
+ const payloadSample = Math.min(8, packet.encryptedPayload.length);
68
+ for (let i = 0; i < payloadSample; i++) {
69
+ parts.push(packet.encryptedPayload[i]);
70
+ }
71
+ return parts.map(b => b.toString(16).padStart(2, '0')).join('');
72
+ }
73
+ // ---------------------------------------------------------------------------
74
+ // PeerProximityTable
75
+ // ---------------------------------------------------------------------------
76
+ /**
77
+ * Maintains a table of known peers indexed by social proximity.
78
+ * Entries are keyed by peerId and can also be looked up by destHash.
79
+ */
80
+ export class PeerProximityTable {
81
+ entries = new Map();
82
+ destHashIndex = new Map(); // hex(destHash) -> peerId
83
+ ttlMs;
84
+ constructor(ttlMs = DEFAULT_PEER_TTL_MS) {
85
+ this.ttlMs = ttlMs;
86
+ }
87
+ /** Add or replace a peer entry. */
88
+ addPeer(entry) {
89
+ this.entries.set(entry.peerId, entry);
90
+ this.destHashIndex.set(hashToHex(entry.destHash), entry.peerId);
91
+ }
92
+ /** Remove a peer by ID. */
93
+ removePeer(peerId) {
94
+ const existing = this.entries.get(peerId);
95
+ if (existing) {
96
+ this.destHashIndex.delete(hashToHex(existing.destHash));
97
+ this.entries.delete(peerId);
98
+ }
99
+ }
100
+ /** Partially update an existing peer entry. */
101
+ updatePeer(peerId, updates) {
102
+ const existing = this.entries.get(peerId);
103
+ if (!existing)
104
+ return;
105
+ // If destHash changes, update the index.
106
+ if (updates.destHash && !bytesEqual(updates.destHash, existing.destHash)) {
107
+ this.destHashIndex.delete(hashToHex(existing.destHash));
108
+ this.destHashIndex.set(hashToHex(updates.destHash), peerId);
109
+ }
110
+ const updated = { ...existing, ...updates };
111
+ this.entries.set(peerId, updated);
112
+ }
113
+ /** Find a peer that owns the given destination hash. */
114
+ findPeer(destHash) {
115
+ const hex = hashToHex(destHash);
116
+ const peerId = this.destHashIndex.get(hex);
117
+ if (peerId === undefined)
118
+ return null;
119
+ const entry = this.entries.get(peerId);
120
+ if (!entry) {
121
+ // Stale index entry — clean up.
122
+ this.destHashIndex.delete(hex);
123
+ return null;
124
+ }
125
+ return entry;
126
+ }
127
+ /**
128
+ * Return the N peers whose known destHash is closest (by XOR distance) to
129
+ * the target destination hash. Results are sorted closest-first.
130
+ */
131
+ getClosestPeers(destHash, count) {
132
+ const scored = [];
133
+ for (const entry of this.entries.values()) {
134
+ scored.push({
135
+ entry,
136
+ distance: xorDistance(entry.destHash, destHash),
137
+ });
138
+ }
139
+ scored.sort((a, b) => a.distance - b.distance);
140
+ return scored.slice(0, count).map(s => s.entry);
141
+ }
142
+ /** Remove entries whose lastSeen is older than maxAgeMs. */
143
+ pruneStale(maxAgeMs = this.ttlMs) {
144
+ const cutoff = Date.now() - maxAgeMs;
145
+ for (const [peerId, entry] of this.entries) {
146
+ if (entry.lastSeen < cutoff) {
147
+ this.removePeer(peerId);
148
+ }
149
+ }
150
+ }
151
+ /** Number of entries currently in the table. */
152
+ get size() {
153
+ return this.entries.size;
154
+ }
155
+ /** Iterate all entries (snapshot). */
156
+ allEntries() {
157
+ return Array.from(this.entries.values());
158
+ }
159
+ }
160
+ // ---------------------------------------------------------------------------
161
+ // Seen-packet LRU set (bounded ring buffer)
162
+ // ---------------------------------------------------------------------------
163
+ class SeenPacketSet {
164
+ capacity;
165
+ set = new Set();
166
+ ring;
167
+ cursor = 0;
168
+ constructor(capacity = SEEN_PACKET_CAPACITY) {
169
+ this.capacity = capacity;
170
+ this.ring = new Array(capacity).fill('');
171
+ }
172
+ /** Returns true if the fingerprint was already in the set. */
173
+ testAndAdd(fingerprint) {
174
+ if (this.set.has(fingerprint))
175
+ return true;
176
+ // Evict oldest if at capacity.
177
+ if (this.set.size >= this.capacity) {
178
+ const evict = this.ring[this.cursor];
179
+ if (evict)
180
+ this.set.delete(evict);
181
+ }
182
+ this.ring[this.cursor] = fingerprint;
183
+ this.set.add(fingerprint);
184
+ this.cursor = (this.cursor + 1) % this.capacity;
185
+ return false;
186
+ }
187
+ has(fingerprint) {
188
+ return this.set.has(fingerprint);
189
+ }
190
+ }
191
+ // ---------------------------------------------------------------------------
192
+ // Route cache
193
+ // ---------------------------------------------------------------------------
194
+ class RouteCache {
195
+ routes = new Map();
196
+ getCachedRoute(destHash) {
197
+ const key = hashToHex(destHash);
198
+ const route = this.routes.get(key);
199
+ if (!route)
200
+ return null;
201
+ if (Date.now() > route.expiresAt) {
202
+ this.routes.delete(key);
203
+ return null;
204
+ }
205
+ return route;
206
+ }
207
+ cacheRoute(route) {
208
+ this.routes.set(hashToHex(route.destHash), route);
209
+ }
210
+ invalidateRoute(destHash) {
211
+ this.routes.delete(hashToHex(destHash));
212
+ }
213
+ }
214
+ // ---------------------------------------------------------------------------
215
+ // SocialGraphRouter
216
+ // ---------------------------------------------------------------------------
217
+ /**
218
+ * Core social graph router.
219
+ *
220
+ * Uses the peer proximity table as the routing topology.
221
+ * Route discovery gossips route requests to socially proximate peers
222
+ * and selects the shortest/fastest offered route.
223
+ */
224
+ export class SocialGraphRouter {
225
+ localPeerId;
226
+ proximityTable;
227
+ routeCache = new RouteCache();
228
+ seenPackets = new SeenPacketSet();
229
+ pendingRequests = new Map();
230
+ routeTtlMs;
231
+ requestTimeoutMs;
232
+ constructor(localPeerId, proximityTable, options) {
233
+ this.localPeerId = localPeerId;
234
+ this.proximityTable = proximityTable;
235
+ this.routeTtlMs = options?.routeTtlMs ?? DEFAULT_ROUTE_TTL_MS;
236
+ this.requestTimeoutMs = options?.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
237
+ }
238
+ // -----------------------------------------------------------------------
239
+ // Route cache public API
240
+ // -----------------------------------------------------------------------
241
+ /** Retrieve a cached route if it exists and has not expired. */
242
+ getCachedRoute(destHash) {
243
+ return this.routeCache.getCachedRoute(destHash);
244
+ }
245
+ /** Store a route in the cache. */
246
+ cacheRoute(route) {
247
+ this.routeCache.cacheRoute(route);
248
+ }
249
+ /** Remove a cached route. */
250
+ invalidateRoute(destHash) {
251
+ this.routeCache.invalidateRoute(destHash);
252
+ }
253
+ // -----------------------------------------------------------------------
254
+ // Route discovery (PRD section 7.1)
255
+ // -----------------------------------------------------------------------
256
+ /**
257
+ * Discover a route to the given destination hash.
258
+ *
259
+ * Algorithm:
260
+ * 1. Check the route cache for a non-expired entry.
261
+ * 2. Check if any connected peer in the proximity table has a recent
262
+ * relay path to the destination.
263
+ * 3. If not, create a RouteRequest (containing only dest_hash, not
264
+ * sender identity) and gossip it to socially proximate peers.
265
+ * 4. Collect RouteOffer responses within the request timeout.
266
+ * 5. Select the shortest/fastest offered route.
267
+ *
268
+ * Returns the route, or null if no route could be discovered within the
269
+ * timeout window.
270
+ */
271
+ findRoute(destHash) {
272
+ // 1. Check cache.
273
+ const cached = this.routeCache.getCachedRoute(destHash);
274
+ if (cached)
275
+ return Promise.resolve(cached);
276
+ // 2. Check proximity table for a direct or relay path.
277
+ const directPeer = this.proximityTable.findPeer(destHash);
278
+ if (directPeer && this.isRecent(directPeer.lastSeen)) {
279
+ const route = this.peerToRoute(directPeer, destHash);
280
+ this.routeCache.cacheRoute(route);
281
+ return Promise.resolve(route);
282
+ }
283
+ // 3. Create a RouteRequest and gossip to close peers.
284
+ const requestId = this.generateRequestId();
285
+ const request = {
286
+ destHash,
287
+ requestId,
288
+ ttl: 6, // small-world average path length
289
+ timestamp: Date.now(),
290
+ };
291
+ return new Promise((resolve) => {
292
+ const pending = {
293
+ request,
294
+ createdAt: Date.now(),
295
+ timeoutMs: this.requestTimeoutMs,
296
+ offers: [],
297
+ resolve,
298
+ };
299
+ const key = hashToHex(requestId);
300
+ this.pendingRequests.set(key, pending);
301
+ // 4-5. Timeout: after the window closes, pick the best offer.
302
+ setTimeout(() => {
303
+ this.resolvePendingRequest(key);
304
+ }, this.requestTimeoutMs);
305
+ });
306
+ }
307
+ /**
308
+ * Handle an incoming route request from a neighbouring peer.
309
+ *
310
+ * If this node knows the destination (via its proximity table), it
311
+ * returns a RouteOffer. Otherwise returns null (the caller should
312
+ * decide whether to forward the request further).
313
+ */
314
+ handleRouteRequest(request, fromPeer) {
315
+ const peer = this.proximityTable.findPeer(request.destHash);
316
+ if (!peer)
317
+ return null;
318
+ if (!this.isRecent(peer.lastSeen))
319
+ return null;
320
+ return {
321
+ requestId: request.requestId,
322
+ hopCount: peer.hopCount + 1, // +1 for this node in the path
323
+ estimatedLatency: peer.latency,
324
+ offeredBy: this.localPeerId,
325
+ };
326
+ }
327
+ /**
328
+ * Register a received route offer against the matching pending request.
329
+ * If no pending request exists for the offer's requestId, the offer is
330
+ * silently dropped.
331
+ */
332
+ handleRouteOffer(offer) {
333
+ const key = hashToHex(offer.requestId);
334
+ const pending = this.pendingRequests.get(key);
335
+ if (!pending)
336
+ return;
337
+ pending.offers.push(offer);
338
+ }
339
+ /**
340
+ * Return a list of the RouteRequests that are still awaiting responses.
341
+ * Expired requests are pruned as a side-effect.
342
+ */
343
+ getPendingRequests() {
344
+ this.pruneExpiredRequests();
345
+ const result = [];
346
+ for (const pending of this.pendingRequests.values()) {
347
+ result.push(pending.request);
348
+ }
349
+ return result;
350
+ }
351
+ /**
352
+ * Return the list of socially proximate peers that a route request
353
+ * should be gossiped to. Useful for the transport layer to know where
354
+ * to send route requests produced by findRoute.
355
+ */
356
+ getGossipTargets(destHash) {
357
+ return this.proximityTable.getClosestPeers(destHash, GOSSIP_FANOUT);
358
+ }
359
+ // -----------------------------------------------------------------------
360
+ // Message forwarding
361
+ // -----------------------------------------------------------------------
362
+ /**
363
+ * Determine the next-hop peer to forward a message to for the given
364
+ * destination hash.
365
+ *
366
+ * Returns null if no route is known.
367
+ */
368
+ getNextHop(destHash) {
369
+ // Try cache first.
370
+ const cached = this.routeCache.getCachedRoute(destHash);
371
+ if (cached)
372
+ return cached.nextHop;
373
+ // Try direct peer from proximity table.
374
+ const peer = this.proximityTable.findPeer(destHash);
375
+ if (peer && this.isRecent(peer.lastSeen)) {
376
+ return peer.relayPath.length > 0 ? peer.relayPath[0] : peer.peerId;
377
+ }
378
+ // Try closest peer as a heuristic relay.
379
+ const closest = this.proximityTable.getClosestPeers(destHash, 1);
380
+ if (closest.length > 0 && this.isRecent(closest[0].lastSeen)) {
381
+ return closest[0].peerId;
382
+ }
383
+ return null;
384
+ }
385
+ /**
386
+ * Determine whether this device should relay a given packet.
387
+ *
388
+ * A packet is relayed when:
389
+ * - Its TTL is greater than 0
390
+ * - It has not been seen before (deduplication)
391
+ */
392
+ shouldRelay(packet) {
393
+ if (packet.ttl <= 0)
394
+ return false;
395
+ const fp = packetFingerprint(packet);
396
+ const alreadySeen = this.seenPackets.testAndAdd(fp);
397
+ return !alreadySeen;
398
+ }
399
+ /**
400
+ * Return a copy of the packet with TTL decremented by 1.
401
+ * Callers must ensure TTL > 0 before calling (see shouldRelay).
402
+ */
403
+ decrementTTL(packet) {
404
+ if (packet.ttl <= 0) {
405
+ throw new RangeError('Cannot decrement TTL below 0');
406
+ }
407
+ return {
408
+ ...packet,
409
+ ttl: packet.ttl - 1,
410
+ };
411
+ }
412
+ // -----------------------------------------------------------------------
413
+ // Internal helpers
414
+ // -----------------------------------------------------------------------
415
+ /** Check if a timestamp is recent enough to trust. */
416
+ isRecent(timestamp) {
417
+ return (Date.now() - timestamp) < DEFAULT_PEER_TTL_MS;
418
+ }
419
+ /** Convert a proximity entry to a Route. */
420
+ peerToRoute(peer, destHash) {
421
+ const now = Date.now();
422
+ return {
423
+ destHash,
424
+ nextHop: peer.relayPath.length > 0 ? peer.relayPath[0] : peer.peerId,
425
+ hopCount: peer.hopCount,
426
+ estimatedLatency: peer.latency,
427
+ discoveredAt: now,
428
+ expiresAt: now + this.routeTtlMs,
429
+ };
430
+ }
431
+ /** Resolve a pending request by selecting the best offer. */
432
+ resolvePendingRequest(key) {
433
+ const pending = this.pendingRequests.get(key);
434
+ if (!pending)
435
+ return;
436
+ this.pendingRequests.delete(key);
437
+ if (pending.offers.length === 0) {
438
+ pending.resolve(null);
439
+ return;
440
+ }
441
+ // Select best offer: prefer fewest hops, then lowest latency.
442
+ pending.offers.sort((a, b) => {
443
+ if (a.hopCount !== b.hopCount)
444
+ return a.hopCount - b.hopCount;
445
+ return a.estimatedLatency - b.estimatedLatency;
446
+ });
447
+ const best = pending.offers[0];
448
+ const now = Date.now();
449
+ const route = {
450
+ destHash: pending.request.destHash,
451
+ nextHop: best.offeredBy,
452
+ hopCount: best.hopCount,
453
+ estimatedLatency: best.estimatedLatency,
454
+ discoveredAt: now,
455
+ expiresAt: now + this.routeTtlMs,
456
+ };
457
+ this.routeCache.cacheRoute(route);
458
+ pending.resolve(route);
459
+ }
460
+ /** Remove pending requests that have exceeded their timeout. */
461
+ pruneExpiredRequests() {
462
+ const now = Date.now();
463
+ for (const [key, pending] of this.pendingRequests) {
464
+ if (now - pending.createdAt > pending.timeoutMs) {
465
+ this.pendingRequests.delete(key);
466
+ pending.resolve(null);
467
+ }
468
+ }
469
+ }
470
+ /** Generate a random 16-byte request ID. */
471
+ generateRequestId() {
472
+ const id = new Uint8Array(16);
473
+ // globalThis.crypto is available in Node.js 19+ and all modern browsers.
474
+ globalThis.crypto.getRandomValues(id);
475
+ return id;
476
+ }
477
+ }
478
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,yCAAyC;AACzC,2DAA2D;AAC3D,2DAA2D;AAC3D,uDAAuD;AACvD,uBAAuB;AACvB,+DAA+D;AAI/D,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,wDAAwD;AACxD,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE3C,iDAAiD;AACjD,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE3C,8DAA8D;AAC9D,MAAM,0BAA0B,GAAG,CAAC,GAAG,IAAI,CAAC;AAE5C,qEAAqE;AACrE,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAEpC,oEAAoE;AACpE,MAAM,aAAa,GAAG,CAAC,CAAC;AAexB,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,iEAAiE;AACjE,SAAS,SAAS,CAAC,IAAgB;IACjC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6CAA6C;AAC7C,SAAS,UAAU,CAAC,CAAa,EAAE,CAAa;IAC9C,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,CAAa,EAAE,CAAa;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,QAAQ,GAAG,QAAQ,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,MAAc;IACvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACZ,OAAO,GAAoC,IAAI,GAAG,EAAE,CAAC;IACrD,aAAa,GAAwB,IAAI,GAAG,EAAE,CAAC,CAAC,0BAA0B;IAC1E,KAAK,CAAS;IAE/B,YAAY,QAAgB,mBAAmB;QAC7C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,mCAAmC;IACnC,OAAO,CAAC,KAAyB;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAClE,CAAC;IAED,2BAA2B;IAC3B,UAAU,CAAC,MAAc;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,UAAU,CAAC,MAAc,EAAE,OAAoC;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,yCAAyC;QACzC,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,OAAO,GAAuB,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;QAChE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,wDAAwD;IACxD,QAAQ,CAAC,QAAoB;QAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAEtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,gCAAgC;YAChC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,QAAoB,EAAE,KAAa;QACjD,MAAM,MAAM,GAA2D,EAAE,CAAC;QAE1E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK;gBACL,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC;aAChD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,4DAA4D;IAC5D,UAAU,CAAC,WAAmB,IAAI,CAAC,KAAK;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;QACrC,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,IAAI,KAAK,CAAC,QAAQ,GAAG,MAAM,EAAE,CAAC;gBAC5B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,sCAAsC;IACtC,UAAU;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;CACF;AAED,8EAA8E;AAC9E,4CAA4C;AAC5C,8EAA8E;AAE9E,MAAM,aAAa;IACA,QAAQ,CAAS;IACjB,GAAG,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC7B,IAAI,CAAW;IACxB,MAAM,GAAG,CAAC,CAAC;IAEnB,YAAY,WAAmB,oBAAoB;QACjD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,8DAA8D;IAC9D,UAAU,CAAC,WAAmB;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,+BAA+B;QAC/B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,KAAK;gBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;CACF;AAcD,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E,MAAM,UAAU;IACG,MAAM,GAAuB,IAAI,GAAG,EAAE,CAAC;IAExD,cAAc,CAAC,QAAoB;QACjC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU,CAAC,KAAY;QACrB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC;IAED,eAAe,CAAC,QAAoB;QAClC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1C,CAAC;CACF;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,OAAO,iBAAiB;IACnB,WAAW,CAAS;IACpB,cAAc,CAAqB;IAE3B,UAAU,GAAe,IAAI,UAAU,EAAE,CAAC;IAC1C,WAAW,GAAkB,IAAI,aAAa,EAAE,CAAC;IACjD,eAAe,GAAgC,IAAI,GAAG,EAAE,CAAC;IACzD,UAAU,CAAS;IACnB,gBAAgB,CAAS;IAE1C,YACE,WAAmB,EACnB,cAAkC,EAClC,OAGC;QAED,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,oBAAoB,CAAC;QAC9D,IAAI,CAAC,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,IAAI,0BAA0B,CAAC;IAClF,CAAC;IAED,0EAA0E;IAC1E,yBAAyB;IACzB,0EAA0E;IAE1E,gEAAgE;IAChE,cAAc,CAAC,QAAoB;QACjC,OAAO,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED,kCAAkC;IAClC,UAAU,CAAC,KAAY;QACrB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,6BAA6B;IAC7B,eAAe,CAAC,QAAoB;QAClC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,0EAA0E;IAC1E,oCAAoC;IACpC,0EAA0E;IAE1E;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,QAAoB;QAC5B,kBAAkB;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACxD,IAAI,MAAM;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE3C,uDAAuD;QACvD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC1D,IAAI,UAAU,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACrD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAClC,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,sDAAsD;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAiB;YAC5B,QAAQ;YACR,SAAS;YACT,GAAG,EAAE,CAAC,EAAE,kCAAkC;YAC1C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QAEF,OAAO,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,EAAE;YAC3C,MAAM,OAAO,GAAmB;gBAC9B,OAAO;gBACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,SAAS,EAAE,IAAI,CAAC,gBAAgB;gBAChC,MAAM,EAAE,EAAE;gBACV,OAAO;aACR,CAAC;YAEF,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;YACjC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAEvC,8DAA8D;YAC9D,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;YAClC,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,kBAAkB,CAAC,OAAqB,EAAE,QAAgB;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAE/C,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,+BAA+B;YAC5D,gBAAgB,EAAE,IAAI,CAAC,OAAO;YAC9B,SAAS,EAAE,IAAI,CAAC,WAAW;SAC5B,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,gBAAgB,CAAC,KAAiB;QAChC,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,kBAAkB;QAChB,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC;YACpD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,gBAAgB,CAAC,QAAoB;QACnC,OAAO,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACtE,CAAC;IAED,0EAA0E;IAC1E,qBAAqB;IACrB,0EAA0E;IAE1E;;;;;OAKG;IACH,UAAU,CAAC,QAAoB;QAC7B,mBAAmB;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACxD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC,OAAO,CAAC;QAElC,wCAAwC;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACrE,CAAC;QAED,yCAAyC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACjE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7D,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3B,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,WAAW,CAAC,MAAc;QACxB,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAElC,MAAM,EAAE,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,MAAc;QACzB,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,UAAU,CAAC,8BAA8B,CAAC,CAAC;QACvD,CAAC;QACD,OAAO;YACL,GAAG,MAAM;YACT,GAAG,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC;SACpB,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,mBAAmB;IACnB,0EAA0E;IAE1E,sDAAsD;IAC9C,QAAQ,CAAC,SAAiB;QAChC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,mBAAmB,CAAC;IACxD,CAAC;IAED,4CAA4C;IACpC,WAAW,CAAC,IAAwB,EAAE,QAAoB;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO;YACL,QAAQ;YACR,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;YACpE,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,gBAAgB,EAAE,IAAI,CAAC,OAAO;YAC9B,YAAY,EAAE,GAAG;YACjB,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,UAAU;SACjC,CAAC;IACJ,CAAC;IAED,6DAA6D;IACrD,qBAAqB,CAAC,GAAW;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEjC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,8DAA8D;QAC9D,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC3B,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;gBAAE,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;YAC9D,OAAO,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,gBAAgB,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAU;YACnB,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ;YAClC,OAAO,EAAE,IAAI,CAAC,SAAS;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,YAAY,EAAE,GAAG;YACjB,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,UAAU;SACjC,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAClC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,gEAAgE;IACxD,oBAAoB;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAClD,IAAI,GAAG,GAAG,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;gBAChD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,4CAA4C;IACpC,iBAAiB;QACvB,MAAM,EAAE,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9B,yEAAyE;QACzE,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;CACF"}