@ruvector/edge-net 0.3.0 → 0.4.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.
package/p2p.js CHANGED
@@ -20,6 +20,7 @@ import { SignalingClient } from './signaling.js';
20
20
  import { SyncManager } from './sync.js';
21
21
  import { QDAG } from './qdag.js';
22
22
  import { Ledger } from './ledger.js';
23
+ import { HybridBootstrap, FirebaseLedgerSync } from './firebase-signaling.js';
23
24
 
24
25
  // ============================================
25
26
  // P2P NETWORK CONFIGURATION
@@ -32,7 +33,10 @@ export const P2P_CONFIG = {
32
33
  webrtc: true,
33
34
  dht: true,
34
35
  sync: true,
36
+ firebase: true, // Use Firebase for bootstrap
35
37
  },
38
+ // Bootstrap strategy: 'firebase' | 'local' | 'dht-only'
39
+ bootstrapStrategy: 'firebase',
36
40
  // Connection settings
37
41
  maxPeers: 50,
38
42
  minPeers: 3,
@@ -43,6 +47,18 @@ export const P2P_CONFIG = {
43
47
  dhtAnnounceInterval: 60000,
44
48
  // Sync settings
45
49
  syncInterval: 30000,
50
+ // Firebase settings (optional override)
51
+ firebase: {
52
+ // Default uses public edge-net Firebase
53
+ // Override with your own project for production
54
+ projectId: null,
55
+ apiKey: null,
56
+ },
57
+ // Migration thresholds
58
+ migration: {
59
+ dhtPeerThreshold: 5, // Peers needed before reducing Firebase dependency
60
+ p2pPeerThreshold: 10, // Peers needed for full P2P mode
61
+ },
46
62
  };
47
63
 
48
64
  // ============================================
@@ -75,6 +91,10 @@ export class P2PNetwork extends EventEmitter {
75
91
  this.qdag = null;
76
92
  this.ledger = null;
77
93
 
94
+ // Firebase bootstrap (Google Cloud)
95
+ this.hybridBootstrap = null;
96
+ this.firebaseLedgerSync = null;
97
+
78
98
  // State
79
99
  this.state = 'stopped';
80
100
  this.peers = new Map();
@@ -107,8 +127,12 @@ export class P2PNetwork extends EventEmitter {
107
127
  this.ledger = new Ledger({ nodeId: this.nodeId });
108
128
  console.log(' ✅ Ledger initialized');
109
129
 
110
- // Try signaling server first
111
- if (this.options.autoStart.signaling) {
130
+ // Start Firebase bootstrap (Google Cloud) - Primary path
131
+ if (this.options.autoStart.firebase && this.options.bootstrapStrategy === 'firebase') {
132
+ await this.startFirebaseBootstrap();
133
+ }
134
+ // Fallback: Try local signaling server
135
+ else if (this.options.autoStart.signaling) {
112
136
  await this.startSignaling();
113
137
  }
114
138
 
@@ -127,6 +151,14 @@ export class P2PNetwork extends EventEmitter {
127
151
  await this.startSync();
128
152
  }
129
153
 
154
+ // Start Firebase hybrid bootstrap after WebRTC/DHT are ready
155
+ if (this.hybridBootstrap && this.webrtc) {
156
+ await this.hybridBootstrap.start(this.webrtc, this.dht);
157
+
158
+ // Also start Firebase ledger sync
159
+ await this.startFirebaseLedgerSync();
160
+ }
161
+
130
162
  // Wire up event handlers
131
163
  this.setupEventHandlers();
132
164
 
@@ -159,6 +191,11 @@ export class P2PNetwork extends EventEmitter {
159
191
 
160
192
  this.state = 'stopping';
161
193
 
194
+ // Stop Firebase components
195
+ if (this.hybridBootstrap) await this.hybridBootstrap.stop();
196
+ if (this.firebaseLedgerSync) this.firebaseLedgerSync.stop();
197
+
198
+ // Stop P2P components
162
199
  if (this.syncManager) this.syncManager.stop();
163
200
  if (this.dht) this.dht.stop();
164
201
  if (this.webrtc) this.webrtc.close();
@@ -171,7 +208,69 @@ export class P2PNetwork extends EventEmitter {
171
208
  }
172
209
 
173
210
  /**
174
- * Start signaling client
211
+ * Start Firebase hybrid bootstrap (Google Cloud)
212
+ * Primary bootstrap path - uses Firebase for discovery, migrates to P2P
213
+ */
214
+ async startFirebaseBootstrap() {
215
+ try {
216
+ this.hybridBootstrap = new HybridBootstrap({
217
+ peerId: this.nodeId,
218
+ firebaseConfig: this.options.firebase?.projectId ? {
219
+ apiKey: this.options.firebase.apiKey,
220
+ projectId: this.options.firebase.projectId,
221
+ authDomain: `${this.options.firebase.projectId}.firebaseapp.com`,
222
+ databaseURL: `https://${this.options.firebase.projectId}-default-rtdb.firebaseio.com`,
223
+ } : undefined,
224
+ dhtPeerThreshold: this.options.migration?.dhtPeerThreshold,
225
+ p2pPeerThreshold: this.options.migration?.p2pPeerThreshold,
226
+ });
227
+
228
+ // Wire up bootstrap events
229
+ this.hybridBootstrap.on('peer-discovered', ({ peerId, source }) => {
230
+ console.log(` 🔍 Discovered peer via ${source}: ${peerId.slice(0, 8)}...`);
231
+ });
232
+
233
+ this.hybridBootstrap.on('mode-changed', ({ from, to }) => {
234
+ console.log(` 🔄 Bootstrap mode: ${from} → ${to}`);
235
+ this.emit('bootstrap-mode-changed', { from, to });
236
+ });
237
+
238
+ // Start will be called after WebRTC/DHT init
239
+ console.log(' ✅ Firebase bootstrap initialized');
240
+
241
+ } catch (err) {
242
+ console.log(' ⚠️ Firebase bootstrap failed:', err.message);
243
+ // Fall back to local signaling
244
+ await this.startSignaling();
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Start Firebase ledger sync
250
+ */
251
+ async startFirebaseLedgerSync() {
252
+ if (!this.ledger) return;
253
+
254
+ try {
255
+ this.firebaseLedgerSync = new FirebaseLedgerSync(this.ledger, {
256
+ peerId: this.nodeId,
257
+ firebaseConfig: this.options.firebase?.projectId ? {
258
+ apiKey: this.options.firebase.apiKey,
259
+ projectId: this.options.firebase.projectId,
260
+ } : undefined,
261
+ syncInterval: this.options.syncInterval,
262
+ });
263
+
264
+ await this.firebaseLedgerSync.start();
265
+ console.log(' ✅ Firebase ledger sync started');
266
+
267
+ } catch (err) {
268
+ console.log(' ⚠️ Firebase ledger sync failed:', err.message);
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Start signaling client (fallback for local development)
175
274
  */
176
275
  async startSignaling() {
177
276
  try {
@@ -182,7 +281,7 @@ export class P2PNetwork extends EventEmitter {
182
281
 
183
282
  const connected = await this.signaling.connect();
184
283
  if (connected) {
185
- console.log(' ✅ Signaling connected');
284
+ console.log(' ✅ Signaling connected (local)');
186
285
  } else {
187
286
  console.log(' ⚠️ Signaling unavailable (will use DHT)');
188
287
  }
@@ -520,8 +619,18 @@ export class P2PNetwork extends EventEmitter {
520
619
 
521
620
  /**
522
621
  * Get connection mode
622
+ * Returns the current bootstrap/connectivity mode
523
623
  */
524
624
  getMode() {
625
+ // Check Firebase hybrid bootstrap mode first
626
+ if (this.hybridBootstrap) {
627
+ const bootstrapMode = this.hybridBootstrap.mode;
628
+ if (bootstrapMode === 'p2p') return 'full-p2p';
629
+ if (bootstrapMode === 'hybrid') return 'firebase-hybrid';
630
+ if (bootstrapMode === 'firebase') return 'firebase-bootstrap';
631
+ }
632
+
633
+ // Legacy mode detection
525
634
  if (this.webrtc?.mode === 'webrtc' && this.signaling?.isConnected) {
526
635
  return 'full-p2p';
527
636
  }
@@ -534,16 +643,32 @@ export class P2PNetwork extends EventEmitter {
534
643
  return 'local';
535
644
  }
536
645
 
646
+ /**
647
+ * Get bootstrap mode (firebase/hybrid/p2p)
648
+ */
649
+ getBootstrapMode() {
650
+ return this.hybridBootstrap?.mode || 'none';
651
+ }
652
+
537
653
  /**
538
654
  * Get network statistics
539
655
  */
540
656
  getStats() {
657
+ const bootstrapStats = this.hybridBootstrap?.getStats() || {};
658
+
541
659
  return {
542
660
  ...this.stats,
543
661
  nodeId: this.nodeId,
544
662
  state: this.state,
545
663
  mode: this.getMode(),
664
+ bootstrapMode: this.getBootstrapMode(),
546
665
  peers: this.peers.size,
666
+ // Firebase stats
667
+ firebaseConnected: bootstrapStats.firebaseConnected || false,
668
+ firebasePeers: bootstrapStats.firebasePeers || 0,
669
+ firebaseSignals: bootstrapStats.firebaseSignals || 0,
670
+ p2pSignals: bootstrapStats.p2pSignals || 0,
671
+ // Legacy signaling
547
672
  signalingConnected: this.signaling?.isConnected || false,
548
673
  webrtcMode: this.webrtc?.mode || 'none',
549
674
  dhtPeers: this.dht?.getPeers().length || 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruvector/edge-net",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Distributed compute intelligence network with AI agents and workers - contribute browser compute, spawn distributed AI agents, earn credits. Features Time Crystal coordination, Neural DAG attention, P2P swarm intelligence, ONNX inference, WebRTC signaling, CRDT ledger, and multi-agent workflows.",
6
6
  "main": "ruvector_edge_net.js",
@@ -10,7 +10,8 @@
10
10
  "edge-net": "./cli.js",
11
11
  "ruvector-edge": "./cli.js",
12
12
  "edge-net-join": "./join.js",
13
- "edge-net-genesis": "./genesis.js"
13
+ "edge-net-genesis": "./genesis.js",
14
+ "edge-net-firebase-setup": "./firebase-setup.js"
14
15
  },
15
16
  "keywords": [
16
17
  "wasm",
@@ -49,7 +50,12 @@
49
50
  "kademlia",
50
51
  "genesis-node",
51
52
  "turn-server",
52
- "nat-traversal"
53
+ "nat-traversal",
54
+ "google-cloud",
55
+ "firebase",
56
+ "gcloud",
57
+ "firestore",
58
+ "realtime-database"
53
59
  ],
54
60
  "author": "RuVector Team <team@ruvector.dev>",
55
61
  "license": "MIT",
@@ -88,6 +94,8 @@
88
94
  "dht.js",
89
95
  "genesis.js",
90
96
  "p2p.js",
97
+ "firebase-signaling.js",
98
+ "firebase-setup.js",
91
99
  "README.md",
92
100
  "LICENSE"
93
101
  ],
@@ -146,6 +154,12 @@
146
154
  },
147
155
  "./p2p": {
148
156
  "import": "./p2p.js"
157
+ },
158
+ "./firebase-signaling": {
159
+ "import": "./firebase-signaling.js"
160
+ },
161
+ "./firebase-setup": {
162
+ "import": "./firebase-setup.js"
149
163
  }
150
164
  },
151
165
  "sideEffects": [
@@ -168,11 +182,21 @@
168
182
  "genesis": "node genesis.js",
169
183
  "genesis:start": "node genesis.js --port 8787",
170
184
  "p2p": "node -e \"import('./p2p.js').then(m => m.createP2PNetwork({ nodeId: 'test' }))\"",
171
- "monitor": "node -e \"import('./monitor.js').then(m => { const mon = new m.Monitor(); mon.start(); setInterval(() => console.log(JSON.stringify(mon.generateReport(), null, 2)), 5000); })\""
185
+ "monitor": "node -e \"import('./monitor.js').then(m => { const mon = new m.Monitor(); mon.start(); setInterval(() => console.log(JSON.stringify(mon.generateReport(), null, 2)), 5000); })\"",
186
+ "firebase:setup": "node firebase-setup.js",
187
+ "firebase:check": "node firebase-setup.js --check"
172
188
  },
173
189
  "dependencies": {
174
190
  "@ruvector/ruvllm": "^0.2.3",
175
191
  "@xenova/transformers": "^2.17.2",
176
192
  "ws": "^8.18.3"
193
+ },
194
+ "peerDependencies": {
195
+ "firebase": "^10.0.0"
196
+ },
197
+ "peerDependenciesMeta": {
198
+ "firebase": {
199
+ "optional": true
200
+ }
177
201
  }
178
202
  }