helia-coord 1.7.2 → 1.9.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
@@ -3,3 +3,7 @@
3
3
  This is a fork of [ipfs-coord-esm](https://github.com/Permissionless-Software-Foundation/ipfs-coord-esm), adpted for use with [Helia](https://github.com/ipfs/helia) instead of Kubo.
4
4
 
5
5
  Read the [dev-docs](./dev-docs) for more information.
6
+
7
+ ## Node Version
8
+
9
+ Use node.js v22
@@ -72,6 +72,9 @@ class EncryptionAdapter {
72
72
  if (!peer || !peer.data) {
73
73
  throw new Error('Peer public key is not available yet.')
74
74
  }
75
+ if (!msg || typeof msg !== 'string') {
76
+ throw new Error('Message is required.')
77
+ }
75
78
 
76
79
  const pubKey = peer.data.encryptPubKey
77
80
  // console.log('msg to encrypt: ', msg)
@@ -62,7 +62,7 @@ class Gist {
62
62
 
63
63
  // Retrieve the gist from github.com.
64
64
  const result = await this.axios.get(gistUrl)
65
- console.log('result.data: ', result.data)
65
+ // console.log('result.data: ', result.data)
66
66
 
67
67
  // Get the current content of the gist.
68
68
  const content = result.data
@@ -129,7 +129,7 @@ class Messaging {
129
129
  if (!decryptedPayload) {
130
130
  return false
131
131
  }
132
- this.log.statusLog(2, 'decrypted payload:', decryptedPayload)
132
+ this.log.statusLog(3, 'decrypted payload:', decryptedPayload)
133
133
 
134
134
  // Filter ACK messages from other messages
135
135
  if (decryptedPayload.includes('"apiName":"ACK"')) {
@@ -237,10 +237,9 @@ class Messaging {
237
237
  }
238
238
 
239
239
  const peerData = thisNode.peerData.filter(x => x.from === receiver)
240
-
241
240
  // 3/24/24 CT - Debugging issue with passing data between ipfs-bch-wallet
242
241
  // -service and -consumer.
243
- if (!peerData || !peerData[0].data) {
242
+ if (!peerData || !peerData[0] || !peerData[0].data) {
244
243
  console.log(`peerData[0]: ${JSON.stringify(peerData[0])}`)
245
244
  throw new Error('Required encryption information for peer is not available.')
246
245
  }
@@ -275,7 +274,7 @@ class Messaging {
275
274
 
276
275
  return outMsgObj
277
276
  } catch (err) {
278
- console.error('Error in generateAckMsg()')
277
+ console.error('Error in generateAckMsg()', err)
279
278
  throw err
280
279
  }
281
280
  }
@@ -240,7 +240,6 @@ class PeerUseCases {
240
240
  if (!thisPeerData) return false
241
241
 
242
242
  const dataIndex = this.thisNode.peerData.indexOf(thisPeerData)
243
- // console.log(`dataIndex: ${dataIndex}`)
244
243
 
245
244
  // If the new announceObj is older than the last announceObj, then
246
245
  // ignore it.
@@ -386,24 +385,19 @@ class PeerUseCases {
386
385
  // the multiaddrs in the announcement object.
387
386
  const filteredMultiaddrs = this.utils.filterMultiaddrs(peerData.data.ipfsMultiaddrs)
388
387
  this.adapters.log.statusLog(1, 'filteredMultiaddrs: ', filteredMultiaddrs)
389
-
390
388
  for (let j = 0; j < filteredMultiaddrs.length; j++) {
391
389
  const multiaddr = filteredMultiaddrs[j]
392
390
  this.adapters.log.statusLog(1,
393
391
  `Trying a direct connection to peer ${thisPeer} with this multiaddr: ${multiaddr}.`
394
392
  )
395
-
396
393
  // Attempt to connect to the node through a circuit relay.
397
394
  connected = await this.adapters.ipfs.connectToPeer({ multiaddr })
398
- // console.log('direct connection connected: ', connected)
399
-
400
395
  // If the connection was successful, break out of the relay loop.
401
396
  // Otherwise try to connect through the next relay.
402
397
  if (connected.success) {
403
398
  this.adapters.log.statusLog(1,
404
399
  `Successfully connected to peer ${thisPeer} through direct connection: ${multiaddr}.`
405
400
  )
406
-
407
401
  // Add the connection multiaddr for this peer to the thisNode object.
408
402
  this.updatePeerConnectionInfo({ thisPeer })
409
403
 
@@ -422,7 +416,6 @@ class PeerUseCases {
422
416
  }
423
417
  }
424
418
  }
425
-
426
419
  if (connected.success) {
427
420
  continue
428
421
  }
@@ -443,7 +436,6 @@ class PeerUseCases {
443
436
  for (let j = 0; j < filteredMultiaddrs.length; j++) {
444
437
  const multiaddr = filteredMultiaddrs[j]
445
438
  this.adapters.log.statusLog(1, `Trying to connect to peer ${thisPeer} through webRTC multiaddr: ${multiaddr}.`)
446
-
447
439
  connected = await this.adapters.ipfs.connectToPeer({ multiaddr })
448
440
 
449
441
  // If the connection was successful, break out of the relay loop.
@@ -545,7 +537,7 @@ class PeerUseCases {
545
537
 
546
538
  return true
547
539
  } catch (err) {
548
- console.error('Error in refreshPeerConnections()')
540
+ console.error('Error in refreshPeerConnections()', err)
549
541
  throw err
550
542
  }
551
543
  }
@@ -694,20 +686,18 @@ class PeerUseCases {
694
686
 
695
687
  // Get multiaddrs that can be used to connect to this node.
696
688
  const addrs = this.adapters.ipfs.ipfs.libp2p.getMultiaddrs()
697
-
698
689
  const webRtcAddrs = addrs.filter(x => WebRTC.matches(x))
699
- // console.log('webRTC addrs: ', webRtcAddrs)
700
690
 
701
691
  // If there are any webRTC multiaddrs, add them to the announcement object.
702
692
  if (webRtcAddrs.length) {
703
693
  // Remove any previous webRTC multiaddrs from the announcement object.
704
694
  const existingMultiaddrs = thisNode.ipfsMultiaddrs
705
695
  const noRtcAddrs = existingMultiaddrs.filter(x => !x.includes('/p2p-circuit/webrtc'))
706
-
707
696
  // Add the new webRTC multiaddrs to the announcement object.
708
697
  webRtcAddrs.forEach(x => {
709
698
  noRtcAddrs.push(x.toString())
710
699
  })
700
+ console.log('noRtcAddrs: ', noRtcAddrs)
711
701
 
712
702
  // Add the new webRTC multiaddrs to the announcement object.
713
703
  thisNode.ipfsMultiaddrs = noRtcAddrs
@@ -145,7 +145,7 @@ class RelayUseCases {
145
145
  // Loop through each relay.
146
146
  for (let i = 0; i < knownRelays.length; i++) {
147
147
  const thisRelay = knownRelays[i]
148
- // console.log('thisRelay: ', thisRelay)
148
+ console.log('thisRelay: ', thisRelay)
149
149
 
150
150
  // Get connected peers
151
151
  const connectedPeers = await this.adapters.ipfs.getPeers()
@@ -153,7 +153,7 @@ class RelayUseCases {
153
153
 
154
154
  // Check if target circuit-relay is currently conected to the node.
155
155
  const connectedPeer = connectedPeers.filter(peerId => thisRelay.ipfsId.includes(peerId))
156
- // console.log('connectedPeer: ', connectedPeer)
156
+ console.log('connectedPeer: ', connectedPeer)
157
157
 
158
158
  // Get the peer data corresponding to this relay
159
159
  // let peerData = thisNode.peerData.filter(x => x.from.includes(thisRelay.ipfsId))
@@ -192,19 +192,22 @@ class RelayUseCases {
192
192
  thisNode.peerData[peerIndex].data.connectionAddr = remoteConnection[0].remoteAddr.toString()
193
193
  }
194
194
 
195
- // console.log(`Multiaddr changed to ${thisRelay.multiaddr}`)
195
+ console.log(`Multiaddr changed to ${thisRelay.multiaddr}`)
196
196
 
197
197
  // Debugging: log situations when the relay is connected through
198
198
  // another circuit relay.
199
199
  if (thisRelay.multiaddr.includes('/p2p-circuit')) {
200
200
  for (const connection of libp2p.getConnections()) {
201
- console.log('DEBUG: connection.remoteAddr: ', connection.remoteAddr.toString())
202
201
  // Logs the PeerId string and the observed remote multiaddr of each Connection
202
+ this.adapters.log.statusLog(
203
+ 2,
204
+ `DEBUG: connection.remoteAddr: ${connection.remoteAddr.toString()}`
205
+ )
203
206
  }
204
207
  }
205
208
  } else {
206
209
  // Not connected. Connect to the relay.
207
-
210
+ console.log('Handling zero connected peers')
208
211
  // console.log('peerData: ', peerData)
209
212
 
210
213
  // If this node is not connected, try to connect again.
@@ -213,10 +216,12 @@ class RelayUseCases {
213
216
  { multiaddr: thisRelay.multiaddr }
214
217
  )
215
218
  thisRelay.connected = connStatus.success
216
- // console.log(`thisRelay.connected: ${thisRelay.connected}`)
219
+ console.log(`thisRelay.connected: ${thisRelay.connected}`)
217
220
 
218
221
  // Debugging: Trying to figure out the best way to select the multiaddr
222
+ console.log('relay multiaddr: ', thisRelay.multiaddr)
219
223
  if (thisRelay.connected && !thisRelay.multiaddr.includes('/tcp/')) {
224
+ // 2/25/25 CT: Have not seen this code path executed in a long time.
220
225
  console.log('DEBUG: thisRelay.multiaddr: ', thisRelay.multiaddr)
221
226
 
222
227
  const libp2p = this.adapters.ipfs.ipfs.libp2p
@@ -475,11 +480,8 @@ class RelayUseCases {
475
480
 
476
481
  // Get the peer data.
477
482
  let peerData = thisNode.peerData.filter(x => {
478
- if (!x.data) {
479
- console.log('broken peer data: ', x)
480
- }
481
- // console.log(`x.data.ipfsId: ${x.data.ipfsId}`)
482
- // console.log(`thisRelay.ipfsId: ${thisRelay.ipfsId}`)
483
+ // Skip entries with null or missing data
484
+ if (!x.data) return false
483
485
  return x.data.ipfsId === thisRelay.ipfsId
484
486
  })
485
487
  peerData = peerData[0]
@@ -522,6 +524,8 @@ class RelayUseCases {
522
524
  // Save the new metric value.
523
525
  thisRelay.metrics.aboutLatency.push(diffTime)
524
526
  }
527
+
528
+ return true
525
529
  } catch (err) {
526
530
  console.error('Error in measureRelays(): ', err)
527
531
  throw err
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helia-coord",
3
- "version": "1.7.2",
3
+ "version": "1.9.0",
4
4
  "description": "A JS library for helping IPFS peers coordinate, find a common interest, and stay connected around that interest.",
5
5
  "main": "./index.js",
6
6
  "type": "module",
@@ -21,16 +21,16 @@
21
21
  "homepage": "https://github.com/Permissionless-Software-Foundation/helia-coord#readme",
22
22
  "devDependencies": {
23
23
  "@chainsafe/libp2p-gossipsub": "14.1.0",
24
- "@chainsafe/libp2p-noise": "16.0.1",
25
- "@chainsafe/libp2p-yamux": "7.0.1",
24
+ "@chainsafe/libp2p-noise": "17.0.0",
25
+ "@chainsafe/libp2p-yamux": "8.0.1",
26
26
  "@istanbuljs/esm-loader-hook": "0.2.0",
27
27
  "@libp2p/circuit-relay-v2": "3.2.2",
28
28
  "@libp2p/identify": "3.0.22",
29
29
  "@libp2p/ping": "2.0.22",
30
- "@libp2p/tcp": "10.1.2",
30
+ "@libp2p/tcp": "11.0.10",
31
31
  "@libp2p/webrtc": "5.2.2",
32
- "@libp2p/websockets": "9.2.2",
33
- "@multiformats/multiaddr": "12.3.5",
32
+ "@libp2p/websockets": "10.1.3",
33
+ "@multiformats/multiaddr": "13.0.1",
34
34
  "@multiformats/multiaddr-matcher": "1.6.0",
35
35
  "blockstore-fs": "2.0.2",
36
36
  "chai": "4.3.6",
@@ -39,7 +39,7 @@
39
39
  "delay": "6.0.0",
40
40
  "helia": "5.2.1",
41
41
  "lodash.clonedeep": "4.5.0",
42
- "minimal-slp-wallet": "5.12.0",
42
+ "minimal-slp-wallet": "7.1.4",
43
43
  "mocha": "10.0.0",
44
44
  "nyc": "15.1.0",
45
45
  "public-ip": "6.0.1",
@@ -52,7 +52,7 @@
52
52
  "uuid": "9.0.0"
53
53
  },
54
54
  "peerDependencies": {
55
- "libp2p": ">=2.6.0"
55
+ "libp2p": ">=3.1.3"
56
56
  },
57
57
  "exports": {
58
58
  ".": {
@@ -126,6 +126,56 @@ describe('#Adapters - Encryption', () => {
126
126
  assert.include(err.message, 'pubkey must be a hex string')
127
127
  }
128
128
  })
129
+ it('should throw an error is peer is not provided', async () => {
130
+ try {
131
+ await uut.encryptMsg()
132
+ // console.log('result: ', result)
133
+
134
+ assert.fail('Unexpected code path')
135
+ } catch (err) {
136
+ assert.include(err.message, 'Peer public key is not available yet.')
137
+ }
138
+ })
139
+ it('should throw an error is msg is not provided', async () => {
140
+ try {
141
+ const peer = {
142
+ data: {
143
+ encryptionKey: 'abc123'
144
+ }
145
+ }
146
+
147
+ await uut.encryptMsg(peer)
148
+ // console.log('result: ', result)
149
+
150
+ assert.fail('Unexpected code path')
151
+ } catch (err) {
152
+ assert.include(err.message, 'Message is required.')
153
+ }
154
+ })
155
+ it('should throw an error is peer data is not provided', async () => {
156
+ try {
157
+ const peer = {
158
+ }
159
+
160
+ await uut.encryptMsg(peer, 'testMsg')
161
+ // console.log('result: ', result)
162
+
163
+ assert.fail('Unexpected code path')
164
+ } catch (err) {
165
+ assert.include(err.message, 'Peer public key is not available yet.')
166
+ }
167
+ })
168
+
169
+ it('should throw and error if peer public key is not available', async () => {
170
+ try {
171
+ const peer = {}
172
+ await uut.encryptMsg(peer, 'testMsg')
173
+
174
+ assert.fail('Unexpected code path')
175
+ } catch (err) {
176
+ assert.include(err.message, 'Peer public key is not available yet.')
177
+ }
178
+ })
129
179
 
130
180
  it('should encrypt a string', async () => {
131
181
  // Mock dependencies
@@ -55,4 +55,40 @@ describe('#Adapter-Gist', () => {
55
55
  }
56
56
  })
57
57
  })
58
+
59
+ describe('#getCRList2', () => {
60
+ it('should get data from GitHub', async () => {
61
+ // Mock network dependencies
62
+ sandbox.stub(uut.axios, 'get').resolves({
63
+ data: {
64
+ browser: [],
65
+ node: [],
66
+ recommendedPeers: []
67
+ }
68
+ })
69
+
70
+ const result = await uut.getCRList2()
71
+ // console.log('result: ', result)
72
+
73
+ assert.property(result, 'browser')
74
+ assert.property(result, 'node')
75
+ assert.property(result, 'recommendedPeers')
76
+ assert.isArray(result.browser)
77
+ assert.isArray(result.node)
78
+ assert.isArray(result.recommendedPeers)
79
+ })
80
+
81
+ it('should catch and throw errors', async () => {
82
+ try {
83
+ // Force desired code path
84
+ sandbox.stub(uut.axios, 'get').rejects(new Error('test error'))
85
+
86
+ await uut.getCRList2()
87
+
88
+ assert.fail('Unexpected result')
89
+ } catch (err) {
90
+ assert.include(err.message, 'test error')
91
+ }
92
+ })
93
+ })
58
94
  })
@@ -14,13 +14,14 @@ import ipfsLib from '../../../mocks/ipfs-mock.js'
14
14
  import IPFSAdapter from '../../../../lib/adapters/ipfs-adapter.js'
15
15
  import EncryptionAdapter from '../../../../lib/adapters/encryption-adapter.js'
16
16
  import BchAdapter from '../../../../lib/adapters/bch-adapter.js'
17
- import thisNode from '../../../mocks/thisnode-mocks.js'
17
+ import thisNodeMock from '../../../mocks/thisnode-mocks.js'
18
18
  import ResendMsg from '../../../../lib/adapters/pubsub-adapter/resend-msg.js'
19
19
 
20
20
  describe('#messaging-adapter', () => {
21
21
  let sandbox
22
22
  let uut
23
23
  let ipfs, ipfsAdapter
24
+ let thisNode
24
25
 
25
26
  const log = {
26
27
  statusLog: () => {}
@@ -34,6 +35,8 @@ describe('#messaging-adapter', () => {
34
35
  ipfs = cloneDeep(ipfsLib)
35
36
  ipfsAdapter = new IPFSAdapter({ ipfs, log })
36
37
 
38
+ thisNode = cloneDeep(thisNodeMock)
39
+
37
40
  // Instantiate the Encryption adapater
38
41
  const wallet = new SlpWallet()
39
42
  await wallet.walletInfoPromise
@@ -165,17 +168,53 @@ describe('#messaging-adapter', () => {
165
168
  assert.property(result, 'receiver')
166
169
  assert.property(result, 'payload')
167
170
  })
168
- })
169
171
 
170
- it('should catch and throw errors', async () => {
171
- try {
172
- await uut.generateAckMsg()
172
+ it('should throws error if sender is not found', async () => {
173
+ try {
174
+ const ipfsId = 'unknowPeerId'
175
+ const data = {
176
+ sender: ipfsId,
177
+ uuid: 'fake-uuid'
178
+ }
179
+
180
+ await uut.generateAckMsg(data, thisNode)
181
+
182
+ assert.fail('Unexpected code path')
183
+ } catch (err) {
184
+ console.log(err)
185
+ assert.include(err.message, 'Required encryption information for peer is not available.')
186
+ }
187
+ })
188
+
189
+ it('should catch and throw errors', async () => {
190
+ try {
191
+ await uut.generateAckMsg()
192
+
193
+ assert.fail('Unexpected code path')
194
+ } catch (err) {
195
+ console.log(err)
196
+ assert.include(err.message, 'Cannot read')
197
+ }
198
+ })
173
199
 
174
- assert.fail('Unexpected code path')
175
- } catch (err) {
176
- console.log(err)
177
- assert.include(err.message, 'Cannot read')
178
- }
200
+ it('should throw an error if peerData is not specified', async () => {
201
+ try {
202
+ const ipfsId = '12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa'
203
+ const data = {
204
+ sender: ipfsId,
205
+ uuid: 'fake-uuid'
206
+ }
207
+
208
+ thisNode.peerData = []
209
+
210
+ const result = await uut.generateAckMsg(data, thisNode)
211
+ console.log(result)
212
+
213
+ assert.fail('Unexpected code path')
214
+ } catch (err) {
215
+ assert.include(err.message, 'Required encryption information for peer is not available.')
216
+ }
217
+ })
179
218
  })
180
219
 
181
220
  describe('#publishToPubsubChannel', () => {
@@ -113,7 +113,7 @@ describe('#Adapter - Pubsub', () => {
113
113
  // Mock dependencies
114
114
  sandbox.stub(uut, 'checkForDuplicateMsg').returns(true)
115
115
 
116
- const handler = () => {}
116
+ const handler = () => { }
117
117
 
118
118
  const msg = {
119
119
  detail: {
@@ -133,7 +133,7 @@ describe('#Adapter - Pubsub', () => {
133
133
  // Mock dependencies
134
134
  sandbox.stub(uut, 'checkForDuplicateMsg').returns(true)
135
135
 
136
- const handler = () => {}
136
+ const handler = () => { }
137
137
 
138
138
  const msg = {
139
139
  detail: {
@@ -197,7 +197,7 @@ describe('#Adapter - Pubsub', () => {
197
197
  })
198
198
 
199
199
  it('should throw an error if data can not be parsed', async () => {
200
- const handler = () => {}
200
+ const handler = () => { }
201
201
 
202
202
  // Force desired code path
203
203
  mockData.mockMsg.data = Buffer.from('54234', 'hex')
@@ -212,7 +212,7 @@ describe('#Adapter - Pubsub', () => {
212
212
  // Mock dependencies
213
213
  sandbox.stub(uut, 'checkForDuplicateMsg').returns(false)
214
214
 
215
- const handler = () => {}
215
+ const handler = () => { }
216
216
 
217
217
  const msg = {
218
218
  detail: {
@@ -362,8 +362,8 @@ describe('#Adapter - Pubsub', () => {
362
362
  // sandbox.stub(uut.ipfs.ipfs.pubsub, 'subscribe').resolves()
363
363
 
364
364
  // const chanName = 'test'
365
- const handler = () => {}
366
- const parsePubsubMessage = async () => {}
365
+ const handler = () => { }
366
+ const parsePubsubMessage = async () => { }
367
367
 
368
368
  // Instantiate the Broadcast message router library
369
369
  const bRouterOptions = {
@@ -388,8 +388,8 @@ describe('#Adapter - Pubsub', () => {
388
388
  // sandbox.stub(uut.ipfs.ipfs.pubsub, 'subscribe').resolves()
389
389
 
390
390
  // const chanName = 'test'
391
- const handler = () => {}
392
- const parsePubsubMessage = async () => {}
391
+ const handler = () => { }
392
+ const parsePubsubMessage = async () => { }
393
393
 
394
394
  // Instantiate the Broadcast message router library
395
395
  const bRouterOptions = {
@@ -411,7 +411,7 @@ describe('#Adapter - Pubsub', () => {
411
411
 
412
412
  it('should catch and handle errors, and return false', async () => {
413
413
  // Force and error
414
- const handler = () => {}
414
+ const handler = () => { }
415
415
  const parsePubsubMessage = async () => {
416
416
  throw new Error('test error')
417
417
  }
@@ -440,7 +440,7 @@ describe('#Adapter - Pubsub', () => {
440
440
  const pRouterOptions = {
441
441
  thisNode,
442
442
  messaging: uut.messaging,
443
- handleNewMessage: async () => {}
443
+ handleNewMessage: async () => { }
444
444
  }
445
445
  const privateRouter = new PrivateChannelRouter(pRouterOptions)
446
446
 
@@ -460,7 +460,7 @@ describe('#Adapter - Pubsub', () => {
460
460
  const pRouterOptions = {
461
461
  thisNode,
462
462
  messaging: uut.messaging,
463
- handleNewMessage: async () => {}
463
+ handleNewMessage: async () => { }
464
464
  }
465
465
  const privateRouter = new PrivateChannelRouter(pRouterOptions)
466
466
 
@@ -480,7 +480,7 @@ describe('#Adapter - Pubsub', () => {
480
480
  const pRouterOptions = {
481
481
  thisNode,
482
482
  messaging: uut.messaging,
483
- handleNewMessage: async () => {}
483
+ handleNewMessage: async () => { }
484
484
  }
485
485
  const privateRouter = new PrivateChannelRouter(pRouterOptions)
486
486
 
@@ -516,7 +516,7 @@ describe('#Adapter - Pubsub', () => {
516
516
  it('should subscribe to the coordination channel', async () => {
517
517
  const inObj = {
518
518
  chanName: globalConfig.DEFAULT_COORDINATION_ROOM,
519
- handler: () => {}
519
+ handler: () => { }
520
520
  }
521
521
 
522
522
  const result = await uut.subscribeToCoordChannel(inObj)
@@ -538,4 +538,33 @@ describe('#Adapter - Pubsub', () => {
538
538
  }
539
539
  })
540
540
  })
541
+ describe('checkForDuplicateMsg', () => {
542
+ it('should return true if msg is not duplicated', () => {
543
+ const msgMock = { detail: { sequenceNumber: 1 } }
544
+ const res = uut.checkForDuplicateMsg(msgMock)
545
+ assert.isTrue(res)
546
+ assert.equal(uut.trackedMsgs.length, 1)
547
+ })
548
+ it('should return falase if msg is duplicated', () => {
549
+ const msgMock = { detail: { sequenceNumber: 1 } }
550
+
551
+ uut.trackedMsgs = [msgMock.detail.sequenceNumber]
552
+ const res = uut.checkForDuplicateMsg(msgMock)
553
+ assert.isFalse(res)
554
+ })
555
+ })
556
+ describe('manageMsgCache', () => {
557
+ it('should shift the trackedMsgs if it exceed the limit', () => {
558
+ uut.TRACKED_MSG_SIZE = 2
559
+ uut.trackedMsgs = [1, 2, 3]
560
+ uut.manageMsgCache()
561
+ assert.equal(uut.trackedMsgs.length, 2)
562
+ })
563
+ it('should keep the trackedMsgs length if it does not exceed the limit', () => {
564
+ uut.TRACKED_MSG_SIZE = 4
565
+ uut.trackedMsgs = [1, 2, 3]
566
+ uut.manageMsgCache()
567
+ assert.equal(uut.trackedMsgs.length, 3)
568
+ })
569
+ })
541
570
  })
@@ -59,9 +59,11 @@ describe('#Pubsub-Controller', () => {
59
59
  })
60
60
 
61
61
  it('should overwrite default coinjoin channel handler', () => {
62
- const coinjoinPubsubHandler = () => {}
62
+ const coinjoinPubsubHandler = sandbox.spy()
63
63
 
64
- uut = new PubsubController({ adapters, useCases, coinjoinPubsubHandler })
64
+ const uut = new PubsubController({ adapters, useCases, coinjoinPubsubHandler })
65
+ uut.coinjoinPubsubHandler()
66
+ assert.isTrue(coinjoinPubsubHandler.called)
65
67
  })
66
68
  })
67
69
 
@@ -104,4 +106,12 @@ describe('#Pubsub-Controller', () => {
104
106
  assert.equal(result, false)
105
107
  })
106
108
  })
109
+
110
+ describe('#coinjoinPubsubHandler', () => {
111
+ it('should always return true', () => {
112
+ const result = uut.coinjoinPubsubHandler()
113
+
114
+ assert.equal(result, true)
115
+ })
116
+ })
107
117
  })
@@ -262,6 +262,34 @@ describe('#Use-Cases-Peer', () => {
262
262
  // peerData array should only have one peer.
263
263
  assert.equal(uut.thisNode.peerData.length, 1)
264
264
  })
265
+ it('should persit the multiaddr if it exist', async () => {
266
+ // Mock dependencies
267
+ sandbox.stub(uut, 'isFreshPeer').returns(true)
268
+
269
+ const announceObj = {
270
+ from: 'peerId',
271
+ data: {
272
+ jsonLd: {
273
+ name: 'test'
274
+ },
275
+ orbitdb: 'orbitdbId'
276
+ },
277
+ multiaddr: ['/ip4/123.45.6.7/p2p/ipfs-id']
278
+ }
279
+ uut.updateThisNode({ thisNode })
280
+
281
+ // Add the new peer
282
+ uut.thisNode.peerList.push(announceObj.from)
283
+ uut.thisNode.peerData.push(announceObj)
284
+
285
+ const result = await uut.addSubnetPeer(announceObj)
286
+ // console.log('result: ', result)
287
+
288
+ assert.equal(result, true)
289
+
290
+ // peerData array should only have one peer.
291
+ assert.equal(uut.thisNode.peerData.length, 1)
292
+ })
265
293
 
266
294
  it('should return false if existing peer can not be found', async () => {
267
295
  // Mock dependencies
@@ -399,6 +427,13 @@ describe('#Use-Cases-Peer', () => {
399
427
 
400
428
  assert.equal(result, true)
401
429
  })
430
+ it('should handle Error', () => {
431
+ try {
432
+ uut.isFreshPeer(null)
433
+ } catch (error) {
434
+ assert.include(error.message, 'Cannot read properties of null')
435
+ }
436
+ })
402
437
  })
403
438
 
404
439
  describe('#refreshPeerConnections', () => {
@@ -622,6 +657,84 @@ describe('#Use-Cases-Peer', () => {
622
657
  assert.include(err.message, 'test error')
623
658
  }
624
659
  })
660
+ it('should update logs on fails direct connection', async () => {
661
+ // Add a circuit relay peer with advertised IP and port.
662
+ const ipfsId = 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsje'
663
+ uut.thisNode.peerList = [ipfsId]
664
+ uut.thisNode.peerData = [{ from: ipfsId, data: { ipfsMultiaddrs: [] } }]
665
+
666
+ // Add a peer
667
+ await uut.addSubnetPeer(mockData.announceObj)
668
+
669
+ // Force circuit relay to be used.
670
+ uut.thisNode.relayData = mockData.mockRelayData
671
+
672
+ // Mock dependencies
673
+ sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.swarmPeers)
674
+ sandbox.stub(uut, 'isFreshPeer').returns(true)
675
+ sandbox.stub(uut.adapters.ipfs, 'connectToPeer')
676
+ .onCall(0).resolves({ success: false })
677
+ .resolves({ success: true })
678
+ sandbox.stub(uut.utils, 'filterMultiaddrs').returns(['/ip4/123.45.6.7/p2p/ipfs-id'])
679
+ sandbox.stub(uut, 'updatePeerConnectionInfo').returns()
680
+
681
+ // Connect to that peer.
682
+ const result = await uut.refreshPeerConnections()
683
+
684
+ assert.equal(result, true)
685
+ })
686
+ it('should connect to circuit relay ', async () => {
687
+ // Add a circuit relay peer with advertised IP and port.
688
+ const ipfsId = 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsje'
689
+ uut.thisNode.peerList = [ipfsId]
690
+ uut.thisNode.peerData = [{ from: ipfsId, data: { ipfsMultiaddrs: ['/p2p-circuit/ip4/123.45.6.7/tcp/4001/p2p/ipfs-id'] } }]
691
+
692
+ // Add a peer
693
+ await uut.addSubnetPeer(mockData.announceObj)
694
+
695
+ // Force circuit relay to be used.
696
+ uut.thisNode.relayData = mockData.mockRelayData
697
+
698
+ // Mock dependencies
699
+ sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.swarmPeers)
700
+ sandbox.stub(uut, 'isFreshPeer').returns(true)
701
+ sandbox.stub(uut.adapters.ipfs, 'connectToPeer')
702
+ .onCall(0).resolves({ success: false })
703
+ .resolves({ success: true })
704
+ sandbox.stub(uut.utils, 'filterMultiaddrs').returns(['/ip4/123.45.6.7/p2p/ipfs-id'])
705
+ sandbox.stub(uut, 'updatePeerConnectionInfo').returns()
706
+
707
+ // Connect to that peer.
708
+ const result = await uut.refreshPeerConnections()
709
+
710
+ assert.equal(result, true)
711
+ })
712
+ it('should update logs on fails circuit relay connection', async () => {
713
+ // Add a circuit relay peer with advertised IP and port.
714
+ const ipfsId = 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsje'
715
+ uut.thisNode.peerList = [ipfsId]
716
+ uut.thisNode.peerData = [{ from: ipfsId, data: { ipfsMultiaddrs: ['/p2p-circuit/ip4/123.45.6.7/tcp/4001/p2p/ipfs-id'] } }]
717
+
718
+ // Add a peer
719
+ await uut.addSubnetPeer(mockData.announceObj)
720
+
721
+ // Force circuit relay to be used.
722
+ uut.thisNode.relayData = mockData.mockRelayData
723
+
724
+ // Mock dependencies
725
+ sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.swarmPeers)
726
+ sandbox.stub(uut, 'isFreshPeer').returns(true)
727
+ sandbox.stub(uut.adapters.ipfs, 'connectToPeer')
728
+ .onCall(0).resolves({ success: false })
729
+ .resolves({ success: false })
730
+ sandbox.stub(uut.utils, 'filterMultiaddrs').returns(['/ip4/123.45.6.7/p2p/ipfs-id'])
731
+ sandbox.stub(uut, 'updatePeerConnectionInfo').returns()
732
+
733
+ // Connect to that peer.
734
+ const result = await uut.refreshPeerConnections()
735
+
736
+ assert.equal(result, true)
737
+ })
625
738
  })
626
739
 
627
740
  describe('#sendRPC', () => {
@@ -733,4 +846,102 @@ describe('#Use-Cases-Peer', () => {
733
846
  assert.equal(result, false)
734
847
  })
735
848
  })
849
+
850
+ describe('#updatePeerConnectionInfo', () => {
851
+ it('should update the peer connection info', async () => {
852
+ uut.thisNode.peerData = [{ from: 'peerId' }]
853
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').returns([{ remoteAddr: '/ip4/123.45.6.7/p2p/ipfs-id' }])
854
+ const result = await uut.updatePeerConnectionInfo({ thisPeer: 'peerId' })
855
+ assert.equal(result, true)
856
+ assert.equal(uut.thisNode.peerData[0].multiaddr, '/ip4/123.45.6.7/p2p/ipfs-id')
857
+ })
858
+ it('should return false if the peer is not connected', async () => {
859
+ uut.thisNode.peerData = [{ from: 'peerId' }]
860
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').returns([])
861
+ const result = await uut.updatePeerConnectionInfo({ thisPeer: 'peerId' })
862
+ assert.equal(result, false)
863
+ })
864
+ it('should return false if the peer is not found', async () => {
865
+ uut.thisNode.peerData = [{ from: 'peerId' }]
866
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').returns([{ remoteAddr: '/ip4/123.45.6.7/p2p/ipfs-id' }])
867
+ const result = await uut.updatePeerConnectionInfo({ thisPeer: 'peerId2' })
868
+ assert.equal(result, false)
869
+ })
870
+ it('should handle errors', async () => {
871
+ try {
872
+ uut.thisNode.peerData = [{ from: 'peerId' }]
873
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').throws(new Error('test error'))
874
+ await uut.updatePeerConnectionInfo({ thisPeer: 'peerId' })
875
+ assert.fail('Unexpected code path')
876
+ } catch (error) {
877
+ assert.include(error.message, 'test error')
878
+ }
879
+ })
880
+ })
881
+ describe('#getWebRtcMultiaddr', () => {
882
+ it('should return the webRTC multiaddr', async () => {
883
+ const thisNodeMock = thisNode
884
+ const webRtcMultiaddr1 = '/ip4/127.0.0.1/tcp/5000/ws/p2p-circuit/webrtc/p2p/ipfs-id'
885
+ const webRtcMultiaddr2 = '/ip4/127.0.0.1/tcp/5001/ws/p2p-circuit/webrtc/p2p/ipfs-id2'
886
+
887
+ thisNodeMock.ipfsMultiaddrs = ['/ip4/123.45.6.7/p2p/ipfs-id', webRtcMultiaddr1, webRtcMultiaddr2]
888
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getMultiaddrs').returns([webRtcMultiaddr2])
889
+
890
+ await uut.getWebRtcMultiaddr({ thisNode: thisNodeMock })
891
+
892
+ assert.equal(thisNodeMock.ipfsMultiaddrs.length, 2)
893
+ assert.equal(thisNodeMock.ipfsMultiaddrs[0], '/ip4/123.45.6.7/p2p/ipfs-id')
894
+ assert.equal(thisNodeMock.ipfsMultiaddrs[1], webRtcMultiaddr2, 'expected webRTC multiaddr to be updated')
895
+ })
896
+ it('should return false on error', async () => {
897
+ const result = await uut.getWebRtcMultiaddr(null)
898
+ assert.equal(result, false)
899
+ })
900
+ })
901
+ describe('#getMultiaddrs', () => {
902
+ it('should filter multiaddrs with a low chance of success', async () => {
903
+ const webRtcMultiaddr1 = '/ip4/157.178.192.100/tcp/5000/ws/p2p-circuit/webrtc/p2p/ipfs-id'
904
+ const lowChanceMultiaddrsExamples = [
905
+ '/ip4/127.0.0.1/tcp/4001/p2p/QmHash', // localhost
906
+ '/ip4/192.168.1.100/tcp/4001/p2p/QmHash', // private network (192.168.x.x)
907
+ '/ip4/172.16.0.100/tcp/4001/p2p/QmHash', // private network (172.16-31.x.x)
908
+ '/ip4/10.0.0.100/tcp/4001/p2p/QmHash', // private network (10.x.x.x)
909
+ '/ip4/1.2.3.4/p2p/4001/quic/p2p/QmHash', // QUIC protocol
910
+ '/ip4/1.2.3.4/udp/4001/p2p/QmHash', // UDP protocol
911
+ '/ip4/192.168.0.100/udp/4001/quic/p2p/QmHash', // private network with QUIC
912
+ '/ip4/172.20.0.100/udp/4001/p2p/QmHash' // private network with UDP
913
+
914
+ ]
915
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getMultiaddrs').returns([...lowChanceMultiaddrsExamples, webRtcMultiaddr1])
916
+ const result = await uut.getMultiaddrs()
917
+ assert.equal(result.length, 1)
918
+ assert.equal(result[0], webRtcMultiaddr1)
919
+ })
920
+ it('should return empty array on error', async () => {
921
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getMultiaddrs').throws(new Error('test error'))
922
+ const result = await uut.getMultiaddrs()
923
+ assert.equal(result.length, 0)
924
+ })
925
+ })
926
+ describe('relayMetricsHandler', () => {
927
+ it('should return true', async () => {
928
+ uut.incomingData = 'data'
929
+ await uut.relayMetricsHandler('updated data')
930
+ assert.equal(uut.incomingData, 'updated data')
931
+ })
932
+ })
933
+
934
+ describe('updateThisNode', () => {
935
+ it('should update the thisNode object', async () => {
936
+ const thisNodeMock = { data: 'mock node' }
937
+ const result = await uut.updateThisNode({ thisNode: thisNodeMock })
938
+ assert.equal(result, true)
939
+ assert.equal(uut.thisNode.data, 'mock node')
940
+ })
941
+ it('should keep as default if no data is provided', async () => {
942
+ const result = await uut.updateThisNode()
943
+ assert.equal(result, true)
944
+ assert.isUndefined(uut.thisNode)
945
+ })
946
+ })
736
947
  })
@@ -107,6 +107,22 @@ describe('#pubsub-Use-Cases', () => {
107
107
 
108
108
  assert.equal(result, true)
109
109
  })
110
+ it('should throw an error if controllers are not provided', async () => {
111
+ try {
112
+ sandbox.stub(uut.adapters.pubsub, 'subscribeToCoordChannel').resolves()
113
+
114
+ uut.updateThisNode({
115
+ pubsubChannels: []
116
+ })
117
+
118
+ await uut.initializePubsub()
119
+
120
+ assert.fail('Unexpected code path')
121
+ } catch (err) {
122
+ // console.log(err)
123
+ assert.include(err.message, 'Instance of controllers must be passed to initializePubsub()')
124
+ }
125
+ })
110
126
 
111
127
  it('should catch and throw an error', async () => {
112
128
  try {
@@ -172,6 +172,35 @@ describe('#relay-Use-Cases', () => {
172
172
  // Assert function executed successfully.
173
173
  assert.equal(result, true)
174
174
  })
175
+ it('Should debug when relay connection is not over tcp', async () => {
176
+ // Add a relay that is not over tcp
177
+ thisNode.relayData.push(
178
+ {
179
+ multiaddr:
180
+ '/ip4/139.162.76.54/udp/5269/ws/p2p/QmaKzQTAtoJWYMiG5ATx41uWsMajr1kSxRdtg919s8fK77',
181
+ connected: true,
182
+ updatedAt: '2021-09-20T15:59:12.961Z',
183
+ ipfsId: 'QmaKzQTAtoJWYMiG5ATx41uWsMajr1kSxRdtg919s8fK77',
184
+ isBootstrap: false,
185
+ metrics: { aboutLatency: [] },
186
+ latencyScore: 10000
187
+ }
188
+ )
189
+
190
+ // Mock dependencies
191
+ sandbox.stub(uut, 'sortRelays').returns(thisNode.relayData)
192
+ sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.connectedPeerList01)
193
+ sandbox.stub(uut.adapters.ipfs, 'connectToPeer').resolves({ success: true })
194
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').returns([{
195
+ remoteAddr: '/ip4/116.203.193.74/udp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL/p2p-circuit'
196
+ }])
197
+
198
+ // uut.state.relays = crMockData.circuitRelays
199
+ const result = await uut.connectToCRs(thisNode)
200
+
201
+ // Assert function executed successfully.
202
+ assert.equal(result, true)
203
+ })
175
204
 
176
205
  it('Should skip relays that are already connected', async () => {
177
206
  // Force circuit relay to be used.
@@ -246,7 +275,7 @@ describe('#relay-Use-Cases', () => {
246
275
  sandbox.stub(uut, 'sortRelays').returns(thisNode.relayData)
247
276
  sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.connectedPeerList01)
248
277
  sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').returns([{
249
- remoteAddr: '/ip4/116.203.193.74/tcp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
278
+ remoteAddr: '/ip4/116.203.193.74/tcp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL/p2p-circuit'
250
279
  }])
251
280
 
252
281
  // uut.state.relays = crMockData.circuitRelays
@@ -269,6 +298,85 @@ describe('#relay-Use-Cases', () => {
269
298
 
270
299
  assert.equal(result, false)
271
300
  })
301
+
302
+ it('Should log when CR is connected through another CR, and does not have a tcp transport', async () => {
303
+ // Force relay data to have a p2p-circuit multiaddr
304
+ // mockData.mockRelayData[0].multiaddr = '/ip4/116.203.193.74/tcp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
305
+ mockData.mockRelayData[0].multiaddr = '/ip4/116.203.193.74/udp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL/p2p-circuit/p2p/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
306
+
307
+ // Force circuit relay to be used.
308
+ thisNode.relayData = mockData.mockRelayData
309
+
310
+ // Force mock circuit relay to appear as being already connected.
311
+ mockData.connectedPeerList01.push(mockData.mockRelayData[0].ipfsId)
312
+
313
+ // Force entity data with implicit multiaddr, which will will overwrite
314
+ // the explicit multiaddr provided by the realy.
315
+ thisNode.peerData.push({
316
+ from: 'QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL',
317
+ data: {
318
+ connectionAddr: 'fake-multiaddr'
319
+ }
320
+ })
321
+
322
+ // Mock dependencies
323
+ sandbox.stub(uut, 'sortRelays').returns(thisNode.relayData)
324
+ sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.connectedPeerList01)
325
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').returns([{
326
+ remoteAddr: '/ip4/116.203.193.74/udp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL/p2p-circuit/p2p/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
327
+ }])
328
+
329
+ // uut.state.relays = crMockData.circuitRelays
330
+ const result = await uut.connectToCRs(thisNode)
331
+
332
+ console.log('thisNode.peerData: ', thisNode.peerData)
333
+
334
+ // Assert function executed successfully.
335
+ assert.equal(result, true)
336
+
337
+ // Assert that the multiaddr was overwritten
338
+ // assert.include(thisNode.peerData[0].data.connectionAddr, 'tcp')
339
+ })
340
+
341
+ it('Should log when CR makes a new connection through another CR, and does not have a tcp transport', async () => {
342
+ // Force relay data to have a p2p-circuit multiaddr
343
+ // mockData.mockRelayData[0].multiaddr = '/ip4/116.203.193.74/tcp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
344
+ mockData.mockRelayData[0].multiaddr = '/ip4/116.203.193.74/udp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL/p2p-circuit/p2p/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
345
+
346
+ // Force circuit relay to be used.
347
+ thisNode.relayData = mockData.mockRelayData
348
+
349
+ // Force mock circuit relay to appear as being already connected.
350
+ // mockData.connectedPeerList01.push(mockData.mockRelayData[0].ipfsId)
351
+
352
+ // Force entity data with implicit multiaddr, which will will overwrite
353
+ // the explicit multiaddr provided by the realy.
354
+ thisNode.peerData.push({
355
+ from: 'QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL',
356
+ data: {
357
+ connectionAddr: 'fake-multiaddr'
358
+ }
359
+ })
360
+
361
+ // Mock dependencies
362
+ sandbox.stub(uut, 'sortRelays').returns(thisNode.relayData)
363
+ sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.connectedPeerList01)
364
+ sandbox.stub(uut.adapters.ipfs.ipfs.libp2p, 'getConnections').returns([{
365
+ remoteAddr: '/ip4/116.203.193.74/udp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL/p2p-circuit/p2p/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
366
+ }])
367
+ sandbox.stub(uut.adapters.ipfs, 'connectToPeer').resolves({ success: true })
368
+
369
+ // uut.state.relays = crMockData.circuitRelays
370
+ const result = await uut.connectToCRs(thisNode)
371
+
372
+ console.log('thisNode.peerData: ', thisNode.peerData)
373
+
374
+ // Assert function executed successfully.
375
+ assert.equal(result, true)
376
+
377
+ // Assert that the multiaddr was overwritten
378
+ // assert.include(thisNode.peerData[0].data.connectionAddr, 'tcp')
379
+ })
272
380
  })
273
381
 
274
382
  describe('#addRelay', () => {
@@ -628,7 +736,7 @@ describe('#relay-Use-Cases', () => {
628
736
 
629
737
  // Mock dependencies
630
738
  sandbox.stub(uut.adapters.bch.bchjs.Util, 'sleep').resolves()
631
- sandbox.stub(uut.adapters.pubsub.about, 'queryAbout').resolves(true)
739
+ sandbox.stub(uut.peerUseCases, 'queryAbout').resolves(true)
632
740
 
633
741
  await uut.measureRelays(thisNode)
634
742
  // console.log(
@@ -674,6 +782,33 @@ describe('#relay-Use-Cases', () => {
674
782
  // First element of '1' should have been shifted out and replaced by '2'
675
783
  assert.equal(thisNode.relayData[0].metrics.aboutLatency[0], 2)
676
784
  })
785
+
786
+ it('should ignore a broken peer data', async () => {
787
+ // Mock test data
788
+ const thisNode = {
789
+ relayData: [
790
+ {
791
+ ipfsId: 'testId',
792
+ isBootstrap: false,
793
+ connected: false,
794
+ metrics: {
795
+ aboutLatency: []
796
+ }
797
+ }
798
+ ],
799
+ peerData: [
800
+
801
+ {
802
+ data: null
803
+ }
804
+ ]
805
+ }
806
+
807
+ await uut.measureRelays(thisNode)
808
+ // console.log('thisNode: ', thisNode)
809
+
810
+ assert.equal(thisNode.relayData[0].metrics.aboutLatency.length, 0)
811
+ })
677
812
  })
678
813
 
679
814
  describe('#sortRelays', () => {