@leofcoin/peernet 1.0.10 → 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.
@@ -0,0 +1,35 @@
1
+ # breaking changes
2
+ ## 1.0.10
3
+ ### start
4
+ #### before
5
+ ```js
6
+ const node = await new Node()
7
+ ```
8
+
9
+ #### now
10
+ ```js
11
+ const node = await new Node()
12
+ // gives time to setup things...
13
+ await node.start()
14
+ ```
15
+
16
+ ## 1.1.0
17
+ ### autoStart
18
+ #### before
19
+ ```js
20
+ const node = await new Node()
21
+ // gives time to setup things...
22
+ await node.start()
23
+ ```
24
+
25
+ #### now
26
+ ```js
27
+ const node = await new Node()
28
+ ```
29
+ or
30
+
31
+ ```js
32
+ const node = await new Node({autoStart: false}) // defaults to true
33
+ // gives time to setup things...
34
+ await node.start()
35
+ ```
package/README.md CHANGED
@@ -11,7 +11,9 @@ const config = {
11
11
  stars: ['wss://peach.leofcoin.org']
12
12
  }
13
13
 
14
- await new Peernet(config)
14
+ const node = await new Peernet(config)
15
+ // ... setup some things
16
+ await node.start()
15
17
 
16
18
  console.log(globalThis.peernet)
17
19
  ```
@@ -1,4 +1,4 @@
1
- import { L as LittlePubSub } from './peernet-7ba6837f.js';
1
+ import { L as LittlePubSub } from './peernet-4aaa825c.js';
2
2
  import './value-157ab062.js';
3
3
 
4
4
  var clientApi = _pubsub => {
@@ -235,6 +235,9 @@ class Peer {
235
235
  #chunkSize = 16 * 1024; // 16384
236
236
  #queRunning = false;
237
237
  #MAX_BUFFERED_AMOUNT = 16 * 1024 * 1024;
238
+ initiator = false;
239
+ state;
240
+ #makingOffer = false;
238
241
  get connection() {
239
242
  return this.#connection;
240
243
  }
@@ -247,7 +250,7 @@ class Peer {
247
250
  /**
248
251
  * @params {Object} options
249
252
  * @params {string} options.channelName - this peerid : otherpeer id
250
- */
253
+ */
251
254
  constructor(options = {}) {
252
255
  this._in = this._in.bind(this);
253
256
  this.offerOptions = options.offerOptions;
@@ -375,6 +378,69 @@ class Peer {
375
378
  credential: "openrelayproject",
376
379
  }];
377
380
  this.#connection = new wrtc.RTCPeerConnection({ iceServers });
381
+ this.#connection.onnegotiationneeded = async () => {
382
+ try {
383
+ this.#makingOffer = true;
384
+ await this.#connection.setLocalDescription();
385
+ this._sendMessage({ description: this.#connection.localDescription });
386
+ this.#makingOffer = false;
387
+ }
388
+ catch (err) {
389
+ console.error(err);
390
+ }
391
+ };
392
+ this.#connection.oniceconnectionstatechange = () => {
393
+ if (this.#connection.iceConnectionState === "failed") {
394
+ this.#connection.restartIce();
395
+ }
396
+ };
397
+ this.#connection.onconnectionstatechange = () => {
398
+ switch (this.#connection.connectionState) {
399
+ case "new":
400
+ case "checking":
401
+ this.state = "connecting";
402
+ break;
403
+ case "connected":
404
+ this.state = 'connected';
405
+ break;
406
+ case "closed":
407
+ case "disconnected":
408
+ this.state = "disconnected";
409
+ break;
410
+ case "failed":
411
+ this.state = 'failed';
412
+ break;
413
+ default:
414
+ this.state = this.#connection.connectionState;
415
+ break;
416
+ }
417
+ if (this.state === 'connected') {
418
+ this.#connection.ondatachannel = (message) => {
419
+ message.channel.onopen = () => {
420
+ this.#connected = true;
421
+ // debug(`peer:connected ${this}`)
422
+ pubsub.publish('peer:connected', this);
423
+ };
424
+ message.channel.onclose = () => this.close.bind(this);
425
+ message.channel.onmessage = (message) => {
426
+ this._handleMessage(this.id, message);
427
+ };
428
+ this.#channel = message.channel;
429
+ };
430
+ if (this.initiator) {
431
+ this.#channel = this.#connection.createDataChannel('messageChannel');
432
+ this.#channel.onopen = () => {
433
+ this.#connected = true;
434
+ pubsub.publish('peer:connected', this);
435
+ // this.#channel.send('hi')
436
+ };
437
+ this.#channel.onclose = () => this.close.bind(this);
438
+ this.#channel.onmessage = (message) => {
439
+ this._handleMessage(this.peerId, message);
440
+ };
441
+ }
442
+ }
443
+ };
378
444
  this.#connection.onicecandidate = ({ candidate }) => {
379
445
  if (candidate) {
380
446
  this.address = candidate.address;
@@ -386,33 +452,6 @@ class Peer {
386
452
  };
387
453
  // if (this.initiator) this.#connection.onnegotiationneeded = () => {
388
454
  // console.log('create offer');
389
- this.#connection.ondatachannel = (message) => {
390
- message.channel.onopen = () => {
391
- this.#connected = true;
392
- // debug(`peer:connected ${this}`)
393
- pubsub.publish('peer:connected', this);
394
- };
395
- message.channel.onclose = () => this.close.bind(this);
396
- message.channel.onmessage = (message) => {
397
- this._handleMessage(this.id, message);
398
- };
399
- this.#channel = message.channel;
400
- };
401
- if (this.initiator) {
402
- this.#channel = this.#connection.createDataChannel('messageChannel');
403
- this.#channel.onopen = () => {
404
- this.#connected = true;
405
- pubsub.publish('peer:connected', this);
406
- // this.#channel.send('hi')
407
- };
408
- this.#channel.onclose = () => this.close.bind(this);
409
- this.#channel.onmessage = (message) => {
410
- this._handleMessage(this.peerId, message);
411
- };
412
- const offer = await this.#connection.createOffer();
413
- await this.#connection.setLocalDescription(offer);
414
- this._sendMessage({ 'sdp': this.#connection.localDescription });
415
- }
416
455
  }
417
456
  catch (e) {
418
457
  console.log(e);
@@ -449,39 +488,36 @@ class Peer {
449
488
  } });
450
489
  }
451
490
  async _in(message, data) {
452
- // message = JSON.parse(message);
453
- if (!this.#connection || message.to !== this.id || message.from !== this.#peerId)
454
- return;
455
- // if (data.videocall) return this._startStream(true, false); // start video and audio stream
456
- // if (data.call) return this._startStream(true, true); // start audio stream
457
- if (this.#connection?.signalingState === 'stable' && this.#connection?.remoteDescription !== null && this.#connection?.localDescription !== null)
458
- return;
459
- if (message.candidate) {
460
- // debug(`incoming candidate ${this.#channelName}`)
461
- // debug(message.candidate.candidate)
462
- this.remoteAddress = message.candidate.address;
463
- this.remotePort = message.candidate.port;
464
- this.remoteProtocol = message.candidate.protocol;
465
- this.remoteIpFamily = this.remoteAddress?.includes('::') ? 'ipv6' : 'ipv4';
466
- return this.#connection.addIceCandidate(new wrtc.RTCIceCandidate(message.candidate));
467
- }
491
+ let ignoreOffer = false;
468
492
  try {
469
- if (message.sdp) {
470
- if (message.sdp.type === 'offer') {
471
- // debug(`incoming offer ${this.#channelName}`)
472
- await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
473
- const answer = await this.#connection.createAnswer();
474
- await this.#connection.setLocalDescription(answer);
475
- this._sendMessage({ 'sdp': this.#connection.localDescription });
493
+ if (message.description) {
494
+ const offerCollision = message.description.type === "offer" &&
495
+ (this.#makingOffer || this.#connection.signalingState !== "stable");
496
+ ignoreOffer = this.initiator && offerCollision;
497
+ if (ignoreOffer) {
498
+ return;
499
+ }
500
+ await this.#connection.setRemoteDescription(message.description);
501
+ if (message.description.type === "offer") {
502
+ await this.#connection.setLocalDescription();
503
+ this._sendMessage({ description: this.#connection.localDescription });
504
+ }
505
+ }
506
+ else if (message.candidate) {
507
+ try {
508
+ await this.#connection.addIceCandidate(message.candidate);
476
509
  }
477
- if (message.sdp.type === 'answer') {
478
- // debug(`incoming answer ${this.#channelName}`)
479
- await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
510
+ catch (err) {
511
+ if (!ignoreOffer) {
512
+ throw err;
513
+ }
480
514
  }
481
515
  }
482
516
  }
483
517
  catch (e) {
518
+ pubsub.publish('connection closed', this);
484
519
  console.log(e);
520
+ this.close();
485
521
  }
486
522
  }
487
523
  close() {
@@ -539,12 +575,18 @@ class Client {
539
575
  throw new Error(`No star available to connect`);
540
576
  }
541
577
  }
578
+ this.setupListeners();
542
579
  const peers = await this.socketClient.peernet.join({ id: this.id });
543
580
  for (const id of peers) {
544
581
  if (id !== this.id && !this.#connections[id])
545
582
  this.#connections[id] = await new Peer({ channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
546
583
  }
547
- this.setupListeners();
584
+ pubsub.subscribe('connection closed', (peer) => {
585
+ this.removePeer(peer.peerId);
586
+ setTimeout(() => {
587
+ this.peerJoined(peer.peerId);
588
+ }, 1000);
589
+ });
548
590
  }
549
591
  setupListeners() {
550
592
  this.socketClient.subscribe('peer:joined', this.peerJoined);
@@ -581,15 +623,10 @@ class Client {
581
623
  this.setupListeners();
582
624
  for (const id of peers) {
583
625
  if (id !== this.id) {
584
- // close connection
585
- if (this.#connections[id]) {
586
- if (this.#connections[id].connected)
587
- await this.#connections[id].close();
588
- delete this.#connections[id];
626
+ if (!this.#connections[id]) {
627
+ if (id !== this.id)
628
+ this.#connections[id] = await new Peer({ channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
589
629
  }
590
- // reconnect
591
- if (id !== this.id)
592
- this.#connections[id] = await new Peer({ channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
593
630
  }
594
631
  }
595
632
  }
@@ -1,4 +1,4 @@
1
- import { M as MultiWallet, e as encrypt, b as base58$1 } from './peernet-7ba6837f.js';
1
+ import { M as MultiWallet, e as encrypt, b as base58$1 } from './peernet-4aaa825c.js';
2
2
  import './value-157ab062.js';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { F as FormatInterface } from './peernet-7ba6837f.js';
1
+ import { F as FormatInterface } from './peernet-4aaa825c.js';
2
2
  import './value-157ab062.js';
3
3
 
4
4
  var proto$b = {
@@ -16082,7 +16082,7 @@ class Identity {
16082
16082
  globalThis.peernet.selectedAccount = new TextDecoder().decode(selected);
16083
16083
  }
16084
16084
  else {
16085
- const importee = await import(/* webpackChunkName: "generate-account" */ './index-84ee0e0b.js');
16085
+ const importee = await import(/* webpackChunkName: "generate-account" */ './index-c0652eae.js');
16086
16086
  const { identity, accounts } = await importee.default(password, this.network);
16087
16087
  await globalThis.accountStore.put('public', JSON.stringify({ walletId: identity.walletId }));
16088
16088
  await globalThis.walletStore.put('version', String(1));
@@ -16143,6 +16143,9 @@ class Peernet {
16143
16143
  stars;
16144
16144
  networkVersion;
16145
16145
  bw;
16146
+ autoStart = true;
16147
+ #starting = false;
16148
+ #started = false;
16146
16149
  /**
16147
16150
  * @access public
16148
16151
  * @param {Object} options
@@ -16161,6 +16164,7 @@ class Peernet {
16161
16164
  * @property {String} network - current network
16162
16165
  */
16163
16166
  this.network = options.network || 'leofcoin';
16167
+ this.autoStart = options.autoStart === undefined ? true : options.autoStart;
16164
16168
  this.stars = options.stars;
16165
16169
  const parts = this.network.split(':');
16166
16170
  this.networkVersion = options.networkVersion || parts.length > 1 ? parts[1] : 'mainnet';
@@ -16248,7 +16252,7 @@ class Peernet {
16248
16252
  this.root = options.root;
16249
16253
  const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile
16250
16254
  // FolderMessageResponse
16251
- } = await import(/* webpackChunkName: "messages" */ './messages-def41fbf.js');
16255
+ } = await import(/* webpackChunkName: "messages" */ './messages-0fcc3d4e.js');
16252
16256
  /**
16253
16257
  * proto Object containing protos
16254
16258
  * @type {Object}
@@ -16297,12 +16301,6 @@ class Peernet {
16297
16301
  * @see DataHandler
16298
16302
  */
16299
16303
  pubsub.subscribe('peer:data', dataHandler);
16300
- const importee = await import('./client-bbd6e332.js');
16301
- /**
16302
- * @access public
16303
- * @type {PeernetClient}
16304
- */
16305
- this.client = new importee.default(this.id, this.networkVersion, this.stars);
16306
16304
  if (globalThis.navigator) {
16307
16305
  globalThis.addEventListener('beforeunload', async () => this.client.close());
16308
16306
  }
@@ -16313,8 +16311,23 @@ class Peernet {
16313
16311
  process.exit();
16314
16312
  });
16315
16313
  }
16314
+ if (this.autoStart)
16315
+ await this.start();
16316
16316
  return this;
16317
16317
  }
16318
+ async start() {
16319
+ if (this.#starting || this.#started)
16320
+ return;
16321
+ this.#starting = true;
16322
+ const importee = await import('./client-ff436f6a.js');
16323
+ /**
16324
+ * @access public
16325
+ * @type {PeernetClient}
16326
+ */
16327
+ this.client = new importee.default(this.id, this.networkVersion, this.stars);
16328
+ this.#started = true;
16329
+ this.#starting = false;
16330
+ }
16318
16331
  addRequestHandler(name, method) {
16319
16332
  this.requestProtos[name] = method;
16320
16333
  }
@@ -1,2 +1,2 @@
1
- export { P as default } from './peernet-7ba6837f.js';
1
+ export { P as default } from './peernet-4aaa825c.js';
2
2
  import './value-157ab062.js';
@@ -401,6 +401,9 @@ class Peernet {
401
401
  stars;
402
402
  networkVersion;
403
403
  bw;
404
+ autoStart = true;
405
+ #starting = false;
406
+ #started = false;
404
407
  /**
405
408
  * @access public
406
409
  * @param {Object} options
@@ -419,6 +422,7 @@ class Peernet {
419
422
  * @property {String} network - current network
420
423
  */
421
424
  this.network = options.network || 'leofcoin';
425
+ this.autoStart = options.autoStart === undefined ? true : options.autoStart;
422
426
  this.stars = options.stars;
423
427
  const parts = this.network.split(':');
424
428
  this.networkVersion = options.networkVersion || parts.length > 1 ? parts[1] : 'mainnet';
@@ -555,12 +559,6 @@ class Peernet {
555
559
  * @see DataHandler
556
560
  */
557
561
  pubsub.subscribe('peer:data', dataHandler);
558
- const importee = await import('@leofcoin/peernet-swarm/client');
559
- /**
560
- * @access public
561
- * @type {PeernetClient}
562
- */
563
- this.client = new importee.default(this.id, this.networkVersion, this.stars);
564
562
  if (globalThis.navigator) {
565
563
  globalThis.addEventListener('beforeunload', async () => this.client.close());
566
564
  }
@@ -571,8 +569,23 @@ class Peernet {
571
569
  process.exit();
572
570
  });
573
571
  }
572
+ if (this.autoStart)
573
+ await this.start();
574
574
  return this;
575
575
  }
576
+ async start() {
577
+ if (this.#starting || this.#started)
578
+ return;
579
+ this.#starting = true;
580
+ const importee = await import('@leofcoin/peernet-swarm/client');
581
+ /**
582
+ * @access public
583
+ * @type {PeernetClient}
584
+ */
585
+ this.client = new importee.default(this.id, this.networkVersion, this.stars);
586
+ this.#started = true;
587
+ this.#starting = false;
588
+ }
576
589
  addRequestHandler(name, method) {
577
590
  this.requestProtos[name] = method;
578
591
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/peernet",
3
- "version": "1.0.10",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "main": "src/peernet.js",
6
6
  "exports": {
@@ -29,7 +29,7 @@
29
29
  "@leofcoin/generate-account": "^2.0.0",
30
30
  "@leofcoin/identity-utils": "^1.0.0",
31
31
  "@leofcoin/multi-wallet": "^3.0.1",
32
- "@leofcoin/peernet-swarm": "^0.5.0",
32
+ "@leofcoin/peernet-swarm": "^1.0.0",
33
33
  "@leofcoin/storage": "^3.0.0",
34
34
  "@types/node": "^18.11.18",
35
35
  "@vandeurenglenn/base32": "^1.1.0",
package/src/peernet.ts CHANGED
@@ -43,6 +43,10 @@ export default class Peernet {
43
43
  up: number
44
44
  down: number
45
45
  }
46
+ autoStart: boolean = true
47
+ #starting: boolean = false
48
+ #started: boolean = false
49
+
46
50
  /**
47
51
  * @access public
48
52
  * @param {Object} options
@@ -56,11 +60,12 @@ export default class Peernet {
56
60
  * @example
57
61
  * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
58
62
  */
59
- constructor(options: options, password) {
63
+ constructor(options, password) {
60
64
  /**
61
65
  * @property {String} network - current network
62
66
  */
63
67
  this.network = options.network || 'leofcoin'
68
+ this.autoStart = options.autoStart === undefined ? true : options.autoStart
64
69
  this.stars = options.stars
65
70
  const parts = this.network.split(':')
66
71
  this.networkVersion = options.networkVersion || parts.length > 1 ? parts[1] : 'mainnet'
@@ -235,13 +240,6 @@ export default class Peernet {
235
240
  */
236
241
  pubsub.subscribe('peer:data', dataHandler)
237
242
 
238
-
239
- const importee = await import('@leofcoin/peernet-swarm/client')
240
- /**
241
- * @access public
242
- * @type {PeernetClient}
243
- */
244
- this.client = new importee.default(this.id, this.networkVersion, this.stars)
245
243
  if (globalThis.navigator) {
246
244
  globalThis.addEventListener('beforeunload', async () => this.client.close());
247
245
  } else {
@@ -251,9 +249,24 @@ export default class Peernet {
251
249
  process.exit()
252
250
  });
253
251
  }
252
+ if (this.autoStart) await this.start()
254
253
  return this
255
254
  }
256
255
 
256
+ async start() {
257
+ if (this.#starting || this.#started) return
258
+
259
+ this.#starting = true
260
+ const importee = await import('@leofcoin/peernet-swarm/client')
261
+ /**
262
+ * @access public
263
+ * @type {PeernetClient}
264
+ */
265
+ this.client = new importee.default(this.id, this.networkVersion, this.stars)
266
+ this.#started = true
267
+ this.#starting = false
268
+ }
269
+
257
270
  addRequestHandler(name, method) {
258
271
  this.requestProtos[name] = method
259
272
  }