@libp2p/bootstrap 2.0.0 → 3.0.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/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
  - [Usage](#usage)
15
15
  - [Contribute](#contribute)
16
16
  - [License](#license)
17
- - [Contribution](#contribution)
17
+ - [Contribute](#contribute-1)
18
18
 
19
19
  ## Install
20
20
 
@@ -24,37 +24,49 @@ $ npm i @libp2p/bootstrap
24
24
 
25
25
  ## Usage
26
26
 
27
+ The configured bootstrap peers will be discovered after the configured timeout. This will ensure
28
+ there are some peers in the peer store for the node to use to discover other peers.
29
+
30
+ They will be tagged with a tag with the name `'bootstrap'` tag, the value `50` and it will expire
31
+ after two minutes which means the nodes connections may be closed if the maximum number of
32
+ connections is reached.
33
+
34
+ Clients that need constant connections to bootstrap nodes (e.g. browsers) can set the TTL to `Infinity`.
35
+
27
36
  ```JavaScript
28
- const Libp2p = require('libp2p')
29
- const Bootstrap = require('libp2p-bootstrap')
30
- const TCP = require('libp2p-tcp')
31
- const { NOISE } = require('libp2p-noise')
32
- const MPLEX = require('libp2p-mplex')
37
+ import { createLibp2p } from 'libp2p'
38
+ import { Bootstrap } from '@libp2p/bootstrap'
39
+ import { TCP } from 'libp2p/tcp'
40
+ import { Noise } from '@libp2p/noise'
41
+ import { Mplex } from '@libp2p/mplex'
33
42
 
34
43
  let options = {
35
- modules: {
36
- transport: [ TCP ],
37
- peerDiscovery: [ Bootstrap ],
38
- streamMuxer: [ MPLEX ],
39
- encryption: [ NOISE ]
40
- },
41
- config: {
42
- peerDiscovery: {
43
- [Bootstrap.tag]: {
44
- list: [ // a list of bootstrap peer multiaddrs to connect to on node startup
45
- "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
46
- "/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
47
- "/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
48
- ],
49
- interval: 5000 // default is 10 ms,
50
- enabled: true
51
- }
52
- }
53
- }
44
+ transports: [
45
+ new TCP()
46
+ ],
47
+ streamMuxers: [
48
+ new Mplex()
49
+ ],
50
+ connectionEncryption: [
51
+ new Noise()
52
+ ],
53
+ peerDiscovery: [
54
+ new Bootstrap({
55
+ list: [ // a list of bootstrap peer multiaddrs to connect to on node startup
56
+ "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
57
+ "/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
58
+ "/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
59
+ ],
60
+ timeout: 1000, // in ms,
61
+ tagName: 'bootstrap',
62
+ tagValue: 50,
63
+ tagTTL: 120000 // in ms
64
+ })
65
+ ]
54
66
  }
55
67
 
56
68
  async function start () {
57
- let libp2p = await Libp2p.create(options)
69
+ let libp2p = await createLibp2p(options)
58
70
 
59
71
  libp2p.on('peer:discovery', function (peerId) {
60
72
  console.log('found peer: ', peerId.toB58String())
@@ -81,6 +93,6 @@ Licensed under either of
81
93
  - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
82
94
  - MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
83
95
 
84
- ## Contribution
96
+ ## Contribute
85
97
 
86
98
  Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
@@ -1,25 +1,41 @@
1
1
  import { EventEmitter } from '@libp2p/interfaces/events';
2
2
  import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery';
3
3
  import { symbol } from '@libp2p/interface-peer-discovery';
4
+ import { Components, Initializable } from '@libp2p/components';
4
5
  export interface BootstrapOptions {
5
6
  /**
6
7
  * The list of peer addresses in multi-address format
7
8
  */
8
9
  list: string[];
9
10
  /**
10
- * The interval between emitting addresses in milliseconds
11
+ * How long to wait before discovering bootstrap nodes
11
12
  */
12
- interval?: number;
13
+ timeout?: number;
14
+ /**
15
+ * Tag a bootstrap peer with this name before "discovering" it (default: 'bootstrap')
16
+ */
17
+ tagName?: string;
18
+ /**
19
+ * The bootstrap peer tag will have this value (default: 50)
20
+ */
21
+ tagValue?: number;
22
+ /**
23
+ * Cause the bootstrap peer tag to be removed after this number of ms (default: 2 minutes)
24
+ */
25
+ tagTTL?: number;
13
26
  }
14
27
  /**
15
28
  * Emits 'peer' events on a regular interval for each peer in the provided list.
16
29
  */
17
- export declare class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
30
+ export declare class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Initializable {
18
31
  static tag: string;
19
32
  private timer?;
20
33
  private readonly list;
21
- private readonly interval;
34
+ private readonly timeout;
35
+ private components;
36
+ private readonly _init;
22
37
  constructor(options?: BootstrapOptions);
38
+ init(components: Components): void;
23
39
  get [symbol](): true;
24
40
  get [Symbol.toStringTag](): string;
25
41
  isStarted(): boolean;
@@ -30,7 +46,7 @@ export declare class Bootstrap extends EventEmitter<PeerDiscoveryEvents> impleme
30
46
  /**
31
47
  * Emit each address in the list as a PeerInfo
32
48
  */
33
- _discoverBootstrapPeers(): void;
49
+ _discoverBootstrapPeers(): Promise<void>;
34
50
  /**
35
51
  * Stop emitting events
36
52
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAG1F,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AAIzD,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAA;IAEd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,YAAY,CAAC,mBAAmB,CAAE,YAAW,aAAa;IACvF,MAAM,CAAC,GAAG,SAAc;IAExB,OAAO,CAAC,KAAK,CAAC,CAAgC;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAEpB,OAAO,GAAE,gBAA+B;IAiCrD,IAAI,CAAC,MAAM,CAAC,IAAK,IAAI,CAEpB;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAEvB;IAED,SAAS;IAIT;;OAEG;IACH,KAAK;IAUL;;OAEG;IACH,uBAAuB;IAUvB;;OAEG;IACH,IAAI;CAOL"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAG1F,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAS9D,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAA;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,YAAY,CAAC,mBAAmB,CAAE,YAAW,aAAa,EAAE,aAAa;IACtG,MAAM,CAAC,GAAG,SAAc;IAExB,OAAO,CAAC,KAAK,CAAC,CAA+B;IAC7C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;gBAE3B,OAAO,GAAE,gBAA+B;IAmCrD,IAAI,CAAE,UAAU,EAAE,UAAU;IAI5B,IAAI,CAAC,MAAM,CAAC,IAAK,IAAI,CAEpB;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAEvB;IAED,SAAS;IAIT;;OAEG;IACH,KAAK;IAcL;;OAEG;IACG,uBAAuB;IAoB7B;;OAEG;IACH,IAAI;CAOL"}
package/dist/src/index.js CHANGED
@@ -1,10 +1,15 @@
1
- import { Multiaddr } from '@multiformats/multiaddr';
1
+ import { multiaddr } from '@multiformats/multiaddr';
2
2
  import { P2P } from '@multiformats/mafmt';
3
3
  import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events';
4
4
  import { logger } from '@libp2p/logger';
5
5
  import { peerIdFromString } from '@libp2p/peer-id';
6
6
  import { symbol } from '@libp2p/interface-peer-discovery';
7
+ import { Components } from '@libp2p/components';
7
8
  const log = logger('libp2p:bootstrap');
9
+ const DEFAULT_BOOTSTRAP_TAG_NAME = 'bootstrap';
10
+ const DEFAULT_BOOTSTRAP_TAG_VALUE = 50;
11
+ const DEFAULT_BOOTSTRAP_TAG_TTL = 120000;
12
+ const DEFAULT_BOOTSTRAP_DISCOVERY_TIMEOUT = 1000;
8
13
  /**
9
14
  * Emits 'peer' events on a regular interval for each peer in the provided list.
10
15
  */
@@ -14,14 +19,15 @@ export class Bootstrap extends EventEmitter {
14
19
  throw new Error('Bootstrap requires a list of peer addresses');
15
20
  }
16
21
  super();
17
- this.interval = options.interval ?? 10000;
22
+ this.components = new Components();
23
+ this.timeout = options.timeout ?? DEFAULT_BOOTSTRAP_DISCOVERY_TIMEOUT;
18
24
  this.list = [];
19
25
  for (const candidate of options.list) {
20
26
  if (!P2P.matches(candidate)) {
21
27
  log.error('Invalid multiaddr');
22
28
  continue;
23
29
  }
24
- const ma = new Multiaddr(candidate);
30
+ const ma = multiaddr(candidate);
25
31
  const peerIdStr = ma.getPeerId();
26
32
  if (peerIdStr == null) {
27
33
  log.error('Invalid bootstrap multiaddr without peer id');
@@ -34,6 +40,10 @@ export class Bootstrap extends EventEmitter {
34
40
  };
35
41
  this.list.push(peerData);
36
42
  }
43
+ this._init = options;
44
+ }
45
+ init(components) {
46
+ this.components = components;
37
47
  }
38
48
  get [symbol]() {
39
49
  return true;
@@ -48,30 +58,42 @@ export class Bootstrap extends EventEmitter {
48
58
  * Start emitting events
49
59
  */
50
60
  start() {
51
- if (this.timer != null) {
61
+ if (this.isStarted()) {
52
62
  return;
53
63
  }
54
- this.timer = setInterval(() => this._discoverBootstrapPeers(), this.interval);
55
- log('Starting bootstrap node discovery');
56
- this._discoverBootstrapPeers();
64
+ log('Starting bootstrap node discovery, discovering peers after %s ms', this.timeout);
65
+ this.timer = setTimeout(() => {
66
+ void this._discoverBootstrapPeers()
67
+ .catch(err => {
68
+ log.error(err);
69
+ });
70
+ }, this.timeout);
57
71
  }
58
72
  /**
59
73
  * Emit each address in the list as a PeerInfo
60
74
  */
61
- _discoverBootstrapPeers() {
75
+ async _discoverBootstrapPeers() {
62
76
  if (this.timer == null) {
63
77
  return;
64
78
  }
65
- this.list.forEach((peerData) => {
79
+ for (const peerData of this.list) {
80
+ await this.components.getPeerStore().tagPeer(peerData.id, this._init.tagName ?? DEFAULT_BOOTSTRAP_TAG_NAME, {
81
+ value: this._init.tagValue ?? DEFAULT_BOOTSTRAP_TAG_VALUE,
82
+ ttl: this._init.tagTTL ?? DEFAULT_BOOTSTRAP_TAG_TTL
83
+ });
84
+ // check we are still running
85
+ if (this.timer == null) {
86
+ return;
87
+ }
66
88
  this.dispatchEvent(new CustomEvent('peer', { detail: peerData }));
67
- });
89
+ }
68
90
  }
69
91
  /**
70
92
  * Stop emitting events
71
93
  */
72
94
  stop() {
73
95
  if (this.timer != null) {
74
- clearInterval(this.timer);
96
+ clearTimeout(this.timer);
75
97
  }
76
98
  this.timer = undefined;
77
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libp2p/bootstrap",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "Node.js IPFS Implementation of the railing process of a Node through a bootstrap peer list",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/libp2p/js-libp2p-bootstrap#readme",
@@ -65,15 +65,15 @@
65
65
  "release": "patch"
66
66
  },
67
67
  {
68
- "type": "chore",
68
+ "type": "docs",
69
69
  "release": "patch"
70
70
  },
71
71
  {
72
- "type": "docs",
72
+ "type": "test",
73
73
  "release": "patch"
74
74
  },
75
75
  {
76
- "type": "test",
76
+ "type": "deps",
77
77
  "release": "patch"
78
78
  },
79
79
  {
@@ -103,7 +103,11 @@
103
103
  },
104
104
  {
105
105
  "type": "docs",
106
- "section": "Trivial Changes"
106
+ "section": "Documentation"
107
+ },
108
+ {
109
+ "type": "deps",
110
+ "section": "Dependencies"
107
111
  },
108
112
  {
109
113
  "type": "test",
@@ -134,17 +138,21 @@
134
138
  "release": "aegir release"
135
139
  },
136
140
  "dependencies": {
137
- "@libp2p/interface-peer-discovery": "^1.0.0",
138
- "@libp2p/interface-peer-info": "^1.0.1",
139
- "@libp2p/interfaces": "^3.0.2",
140
- "@libp2p/logger": "^2.0.0",
141
- "@libp2p/peer-id": "^1.1.9",
142
- "@multiformats/mafmt": "^11.0.2",
143
- "@multiformats/multiaddr": "^10.1.7"
141
+ "@libp2p/components": "^2.0.0",
142
+ "@libp2p/interface-peer-discovery": "^1.0.1",
143
+ "@libp2p/interface-peer-info": "^1.0.3",
144
+ "@libp2p/interfaces": "^3.0.3",
145
+ "@libp2p/logger": "^2.0.1",
146
+ "@libp2p/peer-id": "^1.1.15",
147
+ "@multiformats/mafmt": "^11.0.3",
148
+ "@multiformats/multiaddr": "^11.0.0"
144
149
  },
145
150
  "devDependencies": {
146
- "@libp2p/interface-peer-discovery-compliance-tests": "^1.0.0",
147
- "@libp2p/interface-peer-id": "^1.0.2",
148
- "aegir": "^37.2.0"
151
+ "@libp2p/interface-peer-discovery-compliance-tests": "^1.0.2",
152
+ "@libp2p/interface-peer-id": "^1.0.4",
153
+ "@libp2p/peer-store": "^3.1.5",
154
+ "aegir": "^37.5.3",
155
+ "datastore-core": "^8.0.1",
156
+ "delay": "^5.0.0"
149
157
  }
150
158
  }
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Multiaddr } from '@multiformats/multiaddr'
1
+ import { multiaddr } from '@multiformats/multiaddr'
2
2
  import { P2P } from '@multiformats/mafmt'
3
3
  import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
4
4
  import { logger } from '@libp2p/logger'
@@ -6,9 +6,15 @@ import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface-peer-
6
6
  import type { PeerInfo } from '@libp2p/interface-peer-info'
7
7
  import { peerIdFromString } from '@libp2p/peer-id'
8
8
  import { symbol } from '@libp2p/interface-peer-discovery'
9
+ import { Components, Initializable } from '@libp2p/components'
9
10
 
10
11
  const log = logger('libp2p:bootstrap')
11
12
 
13
+ const DEFAULT_BOOTSTRAP_TAG_NAME = 'bootstrap'
14
+ const DEFAULT_BOOTSTRAP_TAG_VALUE = 50
15
+ const DEFAULT_BOOTSTRAP_TAG_TTL = 120000
16
+ const DEFAULT_BOOTSTRAP_DISCOVERY_TIMEOUT = 1000
17
+
12
18
  export interface BootstrapOptions {
13
19
  /**
14
20
  * The list of peer addresses in multi-address format
@@ -16,20 +22,37 @@ export interface BootstrapOptions {
16
22
  list: string[]
17
23
 
18
24
  /**
19
- * The interval between emitting addresses in milliseconds
25
+ * How long to wait before discovering bootstrap nodes
26
+ */
27
+ timeout?: number
28
+
29
+ /**
30
+ * Tag a bootstrap peer with this name before "discovering" it (default: 'bootstrap')
31
+ */
32
+ tagName?: string
33
+
34
+ /**
35
+ * The bootstrap peer tag will have this value (default: 50)
36
+ */
37
+ tagValue?: number
38
+
39
+ /**
40
+ * Cause the bootstrap peer tag to be removed after this number of ms (default: 2 minutes)
20
41
  */
21
- interval?: number
42
+ tagTTL?: number
22
43
  }
23
44
 
24
45
  /**
25
46
  * Emits 'peer' events on a regular interval for each peer in the provided list.
26
47
  */
27
- export class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
48
+ export class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Initializable {
28
49
  static tag = 'bootstrap'
29
50
 
30
- private timer?: ReturnType<typeof setInterval>
51
+ private timer?: ReturnType<typeof setTimeout>
31
52
  private readonly list: PeerInfo[]
32
- private readonly interval: number
53
+ private readonly timeout: number
54
+ private components: Components = new Components()
55
+ private readonly _init: BootstrapOptions
33
56
 
34
57
  constructor (options: BootstrapOptions = { list: [] }) {
35
58
  if (options.list == null || options.list.length === 0) {
@@ -37,7 +60,7 @@ export class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements Peer
37
60
  }
38
61
  super()
39
62
 
40
- this.interval = options.interval ?? 10000
63
+ this.timeout = options.timeout ?? DEFAULT_BOOTSTRAP_DISCOVERY_TIMEOUT
41
64
  this.list = []
42
65
 
43
66
  for (const candidate of options.list) {
@@ -46,7 +69,7 @@ export class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements Peer
46
69
  continue
47
70
  }
48
71
 
49
- const ma = new Multiaddr(candidate)
72
+ const ma = multiaddr(candidate)
50
73
  const peerIdStr = ma.getPeerId()
51
74
 
52
75
  if (peerIdStr == null) {
@@ -62,6 +85,12 @@ export class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements Peer
62
85
 
63
86
  this.list.push(peerData)
64
87
  }
88
+
89
+ this._init = options
90
+ }
91
+
92
+ init (components: Components) {
93
+ this.components = components
65
94
  }
66
95
 
67
96
  get [symbol] (): true {
@@ -80,26 +109,40 @@ export class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements Peer
80
109
  * Start emitting events
81
110
  */
82
111
  start () {
83
- if (this.timer != null) {
112
+ if (this.isStarted()) {
84
113
  return
85
114
  }
86
115
 
87
- this.timer = setInterval(() => this._discoverBootstrapPeers(), this.interval)
88
- log('Starting bootstrap node discovery')
89
- this._discoverBootstrapPeers()
116
+ log('Starting bootstrap node discovery, discovering peers after %s ms', this.timeout)
117
+ this.timer = setTimeout(() => {
118
+ void this._discoverBootstrapPeers()
119
+ .catch(err => {
120
+ log.error(err)
121
+ })
122
+ }, this.timeout)
90
123
  }
91
124
 
92
125
  /**
93
126
  * Emit each address in the list as a PeerInfo
94
127
  */
95
- _discoverBootstrapPeers () {
128
+ async _discoverBootstrapPeers () {
96
129
  if (this.timer == null) {
97
130
  return
98
131
  }
99
132
 
100
- this.list.forEach((peerData) => {
133
+ for (const peerData of this.list) {
134
+ await this.components.getPeerStore().tagPeer(peerData.id, this._init.tagName ?? DEFAULT_BOOTSTRAP_TAG_NAME, {
135
+ value: this._init.tagValue ?? DEFAULT_BOOTSTRAP_TAG_VALUE,
136
+ ttl: this._init.tagTTL ?? DEFAULT_BOOTSTRAP_TAG_TTL
137
+ })
138
+
139
+ // check we are still running
140
+ if (this.timer == null) {
141
+ return
142
+ }
143
+
101
144
  this.dispatchEvent(new CustomEvent<PeerInfo>('peer', { detail: peerData }))
102
- })
145
+ }
103
146
  }
104
147
 
105
148
  /**
@@ -107,7 +150,7 @@ export class Bootstrap extends EventEmitter<PeerDiscoveryEvents> implements Peer
107
150
  */
108
151
  stop () {
109
152
  if (this.timer != null) {
110
- clearInterval(this.timer)
153
+ clearTimeout(this.timer)
111
154
  }
112
155
 
113
156
  this.timer = undefined