@gethashd/bytecave-browser 1.0.57 → 1.0.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/client.ts CHANGED
@@ -7,7 +7,6 @@
7
7
  import { createLibp2p, Libp2p } from 'libp2p';
8
8
  import { webRTC } from '@libp2p/webrtc';
9
9
  import { webSockets } from '@libp2p/websockets';
10
- import { webTransport } from '@libp2p/webtransport';
11
10
  import { noise } from '@chainsafe/libp2p-noise';
12
11
  import { yamux } from '@chainsafe/libp2p-yamux';
13
12
  import { floodsub } from '@libp2p/floodsub';
@@ -22,7 +21,6 @@ import { ethers } from 'ethers';
22
21
  import { ContractDiscovery, RelayDiscovery } from './discovery.js';
23
22
  import { p2pProtocolClient } from './p2p-protocols.js';
24
23
  import { StorageWebSocketClient } from './storage-websocket.js';
25
- import { StorageWebTransportClient } from './storage-webtransport.js';
26
24
  import { CONTENT_REGISTRY_ABI } from './contracts/ContentRegistry.js';
27
25
  import type {
28
26
  ByteCaveConfig,
@@ -45,7 +43,6 @@ export class ByteCaveClient {
45
43
  private knownPeers: Map<string, PeerInfo> = new Map();
46
44
  private connectionState: ConnectionState = 'disconnected';
47
45
  private eventListeners: Map<string, Set<Function>> = new Map();
48
- private readonly PEERS_CACHE_KEY = 'bytecave_known_peers';
49
46
 
50
47
  constructor(config: ByteCaveConfig) {
51
48
  this.config = {
@@ -64,9 +61,6 @@ export class ByteCaveClient {
64
61
  if (config.vaultNodeRegistryAddress && config.rpcUrl) {
65
62
  this.contractDiscovery = new ContractDiscovery(config.vaultNodeRegistryAddress, config.rpcUrl);
66
63
  }
67
-
68
- // Load cached peers from localStorage
69
- this.loadCachedPeers();
70
64
  }
71
65
 
72
66
  /**
@@ -102,12 +96,11 @@ export class ByteCaveClient {
102
96
 
103
97
  console.log('[ByteCave] Bootstrap peers:', bootstrapPeers);
104
98
 
105
- // Create libp2p node with WebRTC and WebTransport transports
99
+ // Create libp2p node with WebRTC transport
106
100
  this.node = await createLibp2p({
107
101
  transports: [
108
102
  webRTC() as any,
109
103
  webSockets() as any,
110
- webTransport() as any,
111
104
  circuitRelayTransport() as any
112
105
  ],
113
106
  connectionEncrypters: [noise()],
@@ -283,19 +276,14 @@ export class ByteCaveClient {
283
276
  // Fetch health data
284
277
  const health = await p2pProtocolClient.getHealthFromPeer(peer.peerId);
285
278
  if (health) {
286
- const peerInfo = {
279
+ this.knownPeers.set(peer.peerId, {
287
280
  peerId: peer.peerId,
288
281
  publicKey: health.publicKey || '',
289
282
  contentTypes: health.contentTypes || 'all',
290
- httpEndpoint: (health as any).httpEndpoint || '',
291
- multiaddrs: peer.multiaddrs || [],
292
- relayAddrs: (peer as any).relayAddrs || [],
293
283
  connected: true,
294
- isRegistered: (peer as any).isRegistered || false,
295
- onChainNodeId: (peer as any).onChainNodeId || ''
296
- };
297
- this.knownPeers.set(peer.peerId, peerInfo);
298
- this.saveCachedPeers();
284
+ nodeId: health.nodeId
285
+ });
286
+ console.log('[ByteCave] ✓ Discovered peer:', health.nodeId || peer.peerId.slice(0, 12));
299
287
  }
300
288
  } catch (err: any) {
301
289
  console.warn('[ByteCave] Failed to process peer from directory:', peer.peerId.slice(0, 12), err.message);
@@ -336,11 +324,6 @@ export class ByteCaveClient {
336
324
  discoveredPeers: this.knownPeers.size
337
325
  });
338
326
 
339
- // Dial cached peers after startup (important when relay is down)
340
- setTimeout(() => {
341
- this.dialCachedPeers();
342
- }, 2000); // Wait 2s for node to fully initialize
343
-
344
327
  } catch (error) {
345
328
  this.setConnectionState('error');
346
329
  console.error('Failed to start ByteCave client:', error);
@@ -407,19 +390,14 @@ export class ByteCaveClient {
407
390
  try {
408
391
  const health = await p2pProtocolClient.getHealthFromPeer(peer.peerId);
409
392
  if (health) {
410
- const peerInfo = {
393
+ this.knownPeers.set(peer.peerId, {
411
394
  peerId: peer.peerId,
412
395
  publicKey: health.publicKey || '',
413
396
  contentTypes: health.contentTypes || 'all',
414
- httpEndpoint: (health as any).httpEndpoint || '',
415
- multiaddrs: (peer as any).multiaddrs || [],
416
- relayAddrs: (peer as any).relayAddrs || [],
417
397
  connected: true,
418
- isRegistered: (peer as any).isRegistered || false,
419
- onChainNodeId: (peer as any).onChainNodeId || ''
420
- };
421
- this.knownPeers.set(peer.peerId, peerInfo);
422
- this.saveCachedPeers();
398
+ nodeId: health.nodeId
399
+ });
400
+ console.log('[ByteCave] Refresh: ✓ Updated peer info:', health.nodeId || peer.peerId.slice(0, 12));
423
401
  }
424
402
  } catch (err: any) {
425
403
  console.warn('[ByteCave] Refresh: Failed to get health from peer:', peer.peerId.slice(0, 12), err.message);
@@ -498,103 +476,19 @@ Nonce: ${nonce}`;
498
476
  }
499
477
  }
500
478
 
501
- // Storage fallback strategy:
502
- // 1. Try WebSocket relay (most reliable)
503
- // 2. If relay fails, try WebTransport direct to node
504
-
505
- // Try WebSocket relay first
506
- if (this.config.relayWsUrl) {
507
- console.log('[ByteCave] Attempting storage via WebSocket relay');
508
-
509
- try {
510
- if (!this.storageWsClient) {
511
- this.storageWsClient = new StorageWebSocketClient(this.config.relayWsUrl);
512
- }
513
-
514
- const wsAuth = authorization ? {
515
- signature: authorization.signature,
516
- address: authorization.sender,
517
- timestamp: authorization.timestamp,
518
- nonce: authorization.nonce,
519
- appId: authorization.appId,
520
- contentHash: authorization.contentHash
521
- } : undefined;
522
-
523
- const result = await this.storageWsClient.store({
524
- data: dataArray,
525
- contentType: mimeType || 'application/octet-stream',
526
- hashIdToken,
527
- authorization: wsAuth,
528
- timeout: 30000
529
- });
530
-
531
- if (result.success && result.cid) {
532
- console.log('[ByteCave] ✓ WebSocket storage successful:', result.cid);
533
- return {
534
- success: true,
535
- cid: result.cid,
536
- peerId: 'relay-ws'
537
- };
538
- }
539
-
540
- console.warn('[ByteCave] WebSocket storage failed, trying WebTransport:', result.error);
541
- } catch (err: any) {
542
- console.warn('[ByteCave] WebSocket storage exception, trying WebTransport:', err.message);
543
- }
544
- } else {
545
- console.log('[ByteCave] WebSocket relay not configured, trying WebTransport');
479
+ // Use WebSocket relay for storage (simpler connection management than direct P2P)
480
+ if (!this.config.relayWsUrl) {
481
+ return { success: false, error: 'WebSocket relay URL not configured' };
546
482
  }
547
483
 
548
- // Fallback to WebTransport direct to node
549
- console.log('[ByteCave] Attempting storage via WebTransport direct');
484
+ console.log('[ByteCave] Storing via WebSocket relay');
550
485
 
551
486
  try {
552
- // Try cached peers first, then discovery services
553
- let nodes: any[] = Array.from(this.knownPeers.values());
554
-
555
- if (nodes.length === 0) {
556
- console.log('[ByteCave] No cached peers, trying discovery services');
557
- if (this.relayDiscovery) {
558
- nodes = await this.relayDiscovery.getConnectedPeers();
559
- } else if (this.contractDiscovery) {
560
- nodes = await this.contractDiscovery.getActiveNodes();
561
- }
562
- } else {
563
- console.log('[ByteCave] Using', nodes.length, 'cached peers for WebTransport');
564
- }
565
-
566
- if (nodes.length === 0) {
567
- return {
568
- success: false,
569
- error: 'No nodes available for WebTransport storage'
570
- };
571
- }
572
-
573
- const nodeWithWebTransport = nodes.find((node: any) =>
574
- node.multiaddrs?.some((addr: string) => addr.includes('/webtransport'))
575
- );
576
-
577
- if (!nodeWithWebTransport || !nodeWithWebTransport.multiaddrs) {
578
- return {
579
- success: false,
580
- error: 'No nodes with WebTransport support found'
581
- };
582
- }
583
-
584
- const wtMultiaddr = nodeWithWebTransport.multiaddrs.find((addr: string) =>
585
- addr.includes('/webtransport')
586
- );
587
-
588
- if (!wtMultiaddr) {
589
- return {
590
- success: false,
591
- error: 'No WebTransport multiaddr found'
592
- };
487
+ if (!this.storageWsClient) {
488
+ this.storageWsClient = new StorageWebSocketClient(this.config.relayWsUrl);
593
489
  }
594
490
 
595
- const wtClient = new StorageWebTransportClient(wtMultiaddr);
596
-
597
- const wtAuth = authorization ? {
491
+ const wsAuth = authorization ? {
598
492
  signature: authorization.signature,
599
493
  address: authorization.sender,
600
494
  timestamp: authorization.timestamp,
@@ -603,27 +497,28 @@ Nonce: ${nonce}`;
603
497
  contentHash: authorization.contentHash
604
498
  } : undefined;
605
499
 
606
- const result = await wtClient.store({
500
+ const result = await this.storageWsClient.store({
607
501
  data: dataArray,
608
502
  contentType: mimeType || 'application/octet-stream',
609
503
  hashIdToken,
610
- authorization: wtAuth
504
+ authorization: wsAuth,
505
+ timeout: 30000
611
506
  });
612
507
 
613
508
  if (result.success && result.cid) {
614
- console.log('[ByteCave] ✓ WebTransport storage successful:', result.cid);
509
+ console.log('[ByteCave] ✓ WebSocket storage successful:', result.cid);
615
510
  return {
616
511
  success: true,
617
512
  cid: result.cid,
618
- peerId: nodeWithWebTransport.peerId
513
+ peerId: 'relay-ws'
619
514
  };
620
515
  }
621
516
 
622
- console.error('[ByteCave] WebTransport storage failed:', result.error);
623
- return { success: false, error: result.error || 'All storage methods failed' };
517
+ console.warn('[ByteCave] WebSocket storage failed:', result.error);
518
+ return { success: false, error: result.error || 'WebSocket storage failed' };
624
519
  } catch (err: any) {
625
- console.error('[ByteCave] WebTransport storage exception:', err.message);
626
- return { success: false, error: `All storage methods failed: ${err.message}` };
520
+ console.error('[ByteCave] WebSocket storage exception:', err.message);
521
+ return { success: false, error: err.message };
627
522
  }
628
523
  }
629
524
 
@@ -818,59 +713,19 @@ Nonce: ${nonce}`;
818
713
  uptime: number;
819
714
  } | null> {
820
715
  try {
821
- // Check if we have addresses for this peer
716
+ // Check if we have relay addresses for this peer
822
717
  const peerInfo = this.knownPeers.get(peerId);
823
718
  const relayAddrs = (peerInfo as any)?.relayAddrs;
824
- const multiaddrs = peerInfo?.multiaddrs;
825
719
 
826
- // Try to dial the peer if not already connected
827
- if (this.node) {
828
- const connections = this.node.getConnections().filter(c => c.remotePeer.toString() === peerId);
829
-
830
- if (connections.length === 0) {
831
- console.log('[ByteCave] No existing connection to peer, attempting to dial');
832
-
833
- // Try relay addresses first (if available)
834
- if (relayAddrs && relayAddrs.length > 0) {
835
- console.log('[ByteCave] Trying relay address:', relayAddrs[0].slice(0, 60));
836
- try {
837
- const ma = multiaddr(relayAddrs[0]);
838
- await this.node.dial(ma as any);
839
- console.log('[ByteCave] ✓ Connected via relay');
840
- } catch (dialError: any) {
841
- console.warn('[ByteCave] Relay dial failed:', dialError.message);
842
-
843
- // Fallback to WebTransport if relay fails
844
- if (multiaddrs && multiaddrs.length > 0) {
845
- const wtAddr = multiaddrs.find((addr: string) => addr.includes('/webtransport'));
846
- if (wtAddr) {
847
- console.log('[ByteCave] Trying WebTransport address:', wtAddr.slice(0, 60));
848
- try {
849
- const ma = multiaddr(wtAddr);
850
- await this.node.dial(ma as any);
851
- console.log('[ByteCave] ✓ Connected via WebTransport');
852
- } catch (wtError: any) {
853
- console.warn('[ByteCave] WebTransport dial failed:', wtError.message);
854
- }
855
- }
856
- }
857
- }
858
- } else if (multiaddrs && multiaddrs.length > 0) {
859
- // No relay addresses, try WebTransport directly
860
- const wtAddr = multiaddrs.find((addr: string) => addr.includes('/webtransport'));
861
- if (wtAddr) {
862
- console.log('[ByteCave] Trying WebTransport address (no relay):', wtAddr.slice(0, 60));
863
- try {
864
- const ma = multiaddr(wtAddr);
865
- await this.node.dial(ma as any);
866
- console.log('[ByteCave] ✓ Connected via WebTransport');
867
- } catch (wtError: any) {
868
- console.warn('[ByteCave] WebTransport dial failed:', wtError.message);
869
- }
870
- }
871
- }
872
- } else {
873
- console.log('[ByteCave] Already connected to peer via', connections[0].remoteAddr.toString().slice(0, 60));
720
+ // If we have relay addresses, dial through relay first
721
+ if (relayAddrs && relayAddrs.length > 0 && this.node) {
722
+ console.log('[ByteCave] Dialing peer through relay:', peerId.slice(0, 12), relayAddrs[0]);
723
+ try {
724
+ const ma = multiaddr(relayAddrs[0]);
725
+ await this.node.dial(ma as any);
726
+ console.log('[ByteCave] Successfully dialed peer through relay');
727
+ } catch (dialError) {
728
+ console.warn('[ByteCave] Failed to dial through relay:', dialError);
874
729
  }
875
730
  }
876
731
 
@@ -1000,132 +855,11 @@ Nonce: ${nonce}`;
1000
855
  };
1001
856
 
1002
857
  this.knownPeers.set(announcement.peerId, peerInfo);
1003
- this.saveCachedPeers();
1004
-
1005
- // Attempt to dial the peer if not already connected
1006
- if (this.node && !peerInfo.connected) {
1007
- this.dialPeer(announcement.peerId, peerInfo.relayAddrs, peerInfo.multiaddrs).catch(err => {
1008
- console.warn('[ByteCave] Failed to dial announced peer:', err.message);
1009
- });
1010
- }
1011
858
 
1012
859
  this.emit('peerAnnounce', peerInfo);
1013
860
  }
1014
-
1015
- /**
1016
- * Attempt to dial a peer using relay or WebTransport addresses
1017
- */
1018
- private async dialPeer(peerId: string, relayAddrs?: string[], multiaddrs?: string[]): Promise<void> {
1019
- if (!this.node) return;
1020
-
1021
- // Check if already connected
1022
- const connections = this.node.getConnections().filter(c => c.remotePeer.toString() === peerId);
1023
- if (connections.length > 0) {
1024
- console.log('[ByteCave] Already connected to peer:', peerId.slice(0, 12));
1025
- return;
1026
- }
1027
-
1028
- console.log('[ByteCave] Attempting to dial peer:', peerId.slice(0, 12));
1029
-
1030
- // Try relay first
1031
- if (relayAddrs && relayAddrs.length > 0) {
1032
- console.log('[ByteCave] Trying relay address:', relayAddrs[0].slice(0, 60));
1033
- try {
1034
- const ma = multiaddr(relayAddrs[0]);
1035
- await this.node.dial(ma as any);
1036
- console.log('[ByteCave] ✓ Connected via relay');
1037
-
1038
- // Update connected status
1039
- const peer = this.knownPeers.get(peerId);
1040
- if (peer) {
1041
- peer.connected = true;
1042
- }
1043
- return;
1044
- } catch (error: any) {
1045
- console.warn('[ByteCave] Relay dial failed:', error.message);
1046
- }
1047
- }
1048
-
1049
- // Fallback to WebTransport
1050
- if (multiaddrs && multiaddrs.length > 0) {
1051
- const wtAddr = multiaddrs.find((addr: string) => addr.includes('/webtransport'));
1052
- if (wtAddr) {
1053
- console.log('[ByteCave] Trying WebTransport address:', wtAddr.slice(0, 60));
1054
- try {
1055
- const ma = multiaddr(wtAddr);
1056
- await this.node.dial(ma as any);
1057
- console.log('[ByteCave] ✓ Connected via WebTransport');
1058
-
1059
- // Update connected status
1060
- const peer = this.knownPeers.get(peerId);
1061
- if (peer) {
1062
- peer.connected = true;
1063
- }
1064
- } catch (error: any) {
1065
- console.warn('[ByteCave] WebTransport dial failed:', error.message);
1066
- }
1067
- }
1068
- }
1069
- }
1070
861
 
1071
862
 
1072
- /**
1073
- * Load cached peers from localStorage
1074
- */
1075
- private loadCachedPeers(): void {
1076
- try {
1077
- const cached = localStorage.getItem(this.PEERS_CACHE_KEY);
1078
- if (cached) {
1079
- const peers = JSON.parse(cached);
1080
- console.log('[ByteCave] Loaded', peers.length, 'cached peers from localStorage');
1081
- for (const peer of peers) {
1082
- this.knownPeers.set(peer.peerId, { ...peer, connected: false });
1083
- }
1084
- }
1085
- } catch (error) {
1086
- console.warn('[ByteCave] Failed to load cached peers:', error);
1087
- }
1088
- }
1089
-
1090
- /**
1091
- * Dial all cached peers (used on startup when relay might be down)
1092
- */
1093
- private async dialCachedPeers(): Promise<void> {
1094
- console.log('[ByteCave] Dialing', this.knownPeers.size, 'cached peers...');
1095
-
1096
- for (const [peerId, peerInfo] of this.knownPeers) {
1097
- // Skip if already connected
1098
- if (peerInfo.connected) {
1099
- continue;
1100
- }
1101
-
1102
- const relayAddrs = (peerInfo as any).relayAddrs;
1103
- const multiaddrs = peerInfo.multiaddrs;
1104
-
1105
- if (relayAddrs || multiaddrs) {
1106
- this.dialPeer(peerId, relayAddrs, multiaddrs).catch(err => {
1107
- console.warn('[ByteCave] Failed to dial cached peer:', peerId.slice(0, 12), err.message);
1108
- });
1109
-
1110
- // Stagger dials to avoid overwhelming the network
1111
- await new Promise(resolve => setTimeout(resolve, 500));
1112
- }
1113
- }
1114
- }
1115
-
1116
- /**
1117
- * Save known peers to localStorage
1118
- */
1119
- private saveCachedPeers(): void {
1120
- try {
1121
- const peers = Array.from(this.knownPeers.values());
1122
- localStorage.setItem(this.PEERS_CACHE_KEY, JSON.stringify(peers));
1123
- console.log('[ByteCave] Saved', peers.length, 'peers to localStorage');
1124
- } catch (error) {
1125
- console.warn('[ByteCave] Failed to save cached peers:', error);
1126
- }
1127
- }
1128
-
1129
863
  /**
1130
864
  * Check if a nodeId is registered in the on-chain registry
1131
865
  */
package/src/types.ts CHANGED
@@ -25,10 +25,6 @@ export interface PeerInfo {
25
25
  nodeUrl?: string;
26
26
  isRegistered?: boolean;
27
27
  owner?: string;
28
- multiaddrs?: string[];
29
- httpEndpoint?: string;
30
- relayAddrs?: string[];
31
- onChainNodeId?: string;
32
28
  }
33
29
 
34
30
  export interface StoreResult {
@@ -1,47 +0,0 @@
1
- /**
2
- * WebTransport Storage Client
3
- *
4
- * Provides direct browser-to-node storage over WebTransport (HTTP/3)
5
- * Used as fallback when WebSocket relay is unavailable
6
- */
7
- export interface WebTransportStorageRequest {
8
- data: Uint8Array;
9
- contentType: string;
10
- hashIdToken?: number;
11
- authorization?: {
12
- signature: string;
13
- address: string;
14
- timestamp: number;
15
- nonce: string;
16
- appId: string;
17
- contentHash: string;
18
- };
19
- }
20
- export interface WebTransportStorageResponse {
21
- success: boolean;
22
- cid?: string;
23
- error?: string;
24
- }
25
- export declare class StorageWebTransportClient {
26
- private nodeMultiaddr;
27
- constructor(nodeMultiaddr: string);
28
- /**
29
- * Store data via WebTransport direct to node
30
- */
31
- store(request: WebTransportStorageRequest): Promise<WebTransportStorageResponse>;
32
- /**
33
- * Convert libp2p multiaddr to WebTransport URL
34
- */
35
- private multiaddrToWebTransportUrl;
36
- /**
37
- * Extract certificate hash from multiaddr
38
- * Format: /ip4/127.0.0.1/udp/4001/quic-v1/webtransport/certhash/uEi...
39
- */
40
- private extractCertHash;
41
- /**
42
- * Convert libp2p multihash cert hash to SHA-256 ArrayBuffer for WebTransport
43
- * The certhash in multiaddr format is: uEi<hex-hash>
44
- * where 'u' = base32 multibase, 'Ei' = multihash prefix for SHA-256
45
- */
46
- private certHashToSHA256;
47
- }