helia-coord 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.
Files changed (57) hide show
  1. package/.on-save.json +8 -0
  2. package/PEDIGREE.md +3 -0
  3. package/README.md +3 -0
  4. package/config/bootstrap-circuit-relays.js +48 -0
  5. package/examples/start-external.js +56 -0
  6. package/index.js +129 -0
  7. package/lib/adapters/bch-adapter.js +94 -0
  8. package/lib/adapters/encryption-adapter.js +123 -0
  9. package/lib/adapters/gist.js +42 -0
  10. package/lib/adapters/index.js +66 -0
  11. package/lib/adapters/ipfs-adapter.js +263 -0
  12. package/lib/adapters/logs-adapter.js +44 -0
  13. package/lib/adapters/pubsub-adapter/README.md +86 -0
  14. package/lib/adapters/pubsub-adapter/about-adapter.js +117 -0
  15. package/lib/adapters/pubsub-adapter/index.js +275 -0
  16. package/lib/adapters/pubsub-adapter/messaging.js +389 -0
  17. package/lib/adapters/pubsub-adapter/msg-router.js +58 -0
  18. package/lib/adapters/pubsub-adapter/resend-msg.js +58 -0
  19. package/lib/controllers/index.js +24 -0
  20. package/lib/controllers/timer-controller.js +417 -0
  21. package/lib/entities/this-node-entity.js +102 -0
  22. package/lib/use-cases/index.js +36 -0
  23. package/lib/use-cases/peer-use-cases.js +146 -0
  24. package/lib/use-cases/pubsub-use-cases.js +56 -0
  25. package/lib/use-cases/relay-use-cases.js +479 -0
  26. package/lib/use-cases/schema.js +158 -0
  27. package/lib/use-cases/this-node-use-cases.js +443 -0
  28. package/lib/util/utils.js +12 -0
  29. package/package.json +52 -0
  30. package/test/mocks/adapter-mock.js +119 -0
  31. package/test/mocks/circuit-relay-mocks.js +67 -0
  32. package/test/mocks/ipfs-mock.js +46 -0
  33. package/test/mocks/peers-mock.js +75 -0
  34. package/test/mocks/pubsub-mocks.js +37 -0
  35. package/test/mocks/thisnode-mocks.js +82 -0
  36. package/test/mocks/use-case-mocks.js +24 -0
  37. package/test/unit/adapters/bch-adapter-unit.js +96 -0
  38. package/test/unit/adapters/encryption-adapter-unit.js +129 -0
  39. package/test/unit/adapters/gist.unit.adapters.js +58 -0
  40. package/test/unit/adapters/index-adapters-unit.js +79 -0
  41. package/test/unit/adapters/ipfs-adapter-unit.js +215 -0
  42. package/test/unit/adapters/logs-adapter-unit.js +55 -0
  43. package/test/unit/adapters/pubsub/about-adapter-unit.js +129 -0
  44. package/test/unit/adapters/pubsub/messaging-adapter-unit.js +576 -0
  45. package/test/unit/adapters/pubsub/pubsub-adapter-unit.js +367 -0
  46. package/test/unit/adapters/pubsub/resend-msg-adapter-unit.js +58 -0
  47. package/test/unit/controllers/controllers-index-unit.js +30 -0
  48. package/test/unit/controllers/timer-controller-unit.js +261 -0
  49. package/test/unit/entities/this-node.unit.entity.js +157 -0
  50. package/test/unit/index-unit.js +160 -0
  51. package/test/unit/use-cases/peer.unit.use-cases.js +186 -0
  52. package/test/unit/use-cases/pubsub.unit.use-cases.js +114 -0
  53. package/test/unit/use-cases/relay-use-cases-unit.js +658 -0
  54. package/test/unit/use-cases/schema-use-case-unit.js +101 -0
  55. package/test/unit/use-cases/this-node-use-cases-unit.js +427 -0
  56. package/test/unit/use-cases/use-cases-index-unit.js +47 -0
  57. package/test/unit/util/utils-unit.js +31 -0
@@ -0,0 +1,58 @@
1
+ /*
2
+ This library routes incoming pubsub messages to the appropriate handler.
3
+ */
4
+
5
+ // This class routes 'normal' messages, which are broadcast message.
6
+ class BroadcastRouter {
7
+ constructor (localConfig = {}) {
8
+ this.handler = localConfig.handler
9
+ this.thisNode = localConfig.thisNode
10
+ this.parsePubsubMessage = localConfig.parsePubsubMessage
11
+
12
+ this.route = this.route.bind(this)
13
+ }
14
+
15
+ async route (msg) {
16
+ try {
17
+ await this.parsePubsubMessage(msg, this.handler, this.thisNode)
18
+
19
+ return true
20
+ } catch (err) {
21
+ console.error('Error trying to route broadcast pubsub message: ', err)
22
+ // Do not throw an error. This is a top-level handler.
23
+
24
+ return false
25
+ }
26
+ }
27
+ }
28
+
29
+ // This class routes 'private' messages sent on this nodes private, encrypted
30
+ // pubsub channel, which is used for direct communication.
31
+ class PrivateChannelRouter {
32
+ constructor (localConfig = {}) {
33
+ this.messaging = localConfig.messaging
34
+ this.thisNode = localConfig.thisNode
35
+ this.handleNewMessage = localConfig.handleNewMessage
36
+
37
+ this.route = this.route.bind(this)
38
+ }
39
+
40
+ async route (msg) {
41
+ try {
42
+ const msgObj = await this.messaging.handleIncomingData(msg, this.thisNode)
43
+
44
+ // If msgObj is false, then ignore it. Typically indicates an already
45
+ // processed message.
46
+ if (msgObj) { await this.handleNewMessage(msgObj, this.thisNode) }
47
+
48
+ return true
49
+ } catch (err) {
50
+ console.error('Error trying to route private pubsub message: ', err)
51
+ // Do not throw an error. This is a top-level handler.
52
+
53
+ return false
54
+ }
55
+ }
56
+ }
57
+
58
+ export { BroadcastRouter, PrivateChannelRouter }
@@ -0,0 +1,58 @@
1
+ /*
2
+ This class library is used by the messaging.js library to periodically
3
+ resend messages until they are acknowledged.
4
+ */
5
+
6
+ const RETRY_LIMIT = 3
7
+
8
+ class ResendMsg {
9
+ constructor (localConfig = {}) {
10
+ this.msgObj = localConfig.msgObj
11
+ this.msgLib = localConfig.msgLib
12
+
13
+ // Bind the 'this' object to all subfunctions
14
+ this.resend = this.resend.bind(this)
15
+ }
16
+
17
+ // Called by an Interval Timer. This function re-publishes a message to a
18
+ // pubsub channel.
19
+ async resend () {
20
+ try {
21
+ // console.log(`resendMsg() msgObj: ${JSON.stringify(msgObj, null, 2)}`)
22
+
23
+ if (!this.msgObj) {
24
+ console.log('ipfs-coord-esm/lib/adapters/pubsub-adapter/resend-msg.js/resend() given empty message object. Can not resend message. Skipping.')
25
+ return 0
26
+ }
27
+
28
+ const { retryCnt, intervalHandle, receiver } = this.msgObj
29
+
30
+ // Throw an error if the retry count is not an integer.
31
+ const testRetryCnt = parseInt(retryCnt)
32
+ if (isNaN(testRetryCnt)) throw new Error('retryCnt must be an integer')
33
+
34
+ if (retryCnt < RETRY_LIMIT) {
35
+ // Increment the retry
36
+ this.msgObj.retryCnt++
37
+
38
+ // Send message
39
+ await this.msgLib.publishToPubsubChannel(receiver, this.msgObj)
40
+
41
+ return 1
42
+ } else {
43
+ // Retry count exceeded.
44
+
45
+ // Disable the interval handler
46
+ clearInterval(intervalHandle)
47
+
48
+ return 2
49
+ }
50
+ } catch (err) {
51
+ console.error('Error in resendMsg(): ', err)
52
+ // Do not throw an error. This is a top-level function called by an Interval.
53
+ return 0
54
+ }
55
+ }
56
+ }
57
+
58
+ export default ResendMsg
@@ -0,0 +1,24 @@
1
+ /*
2
+ This is a top-level Controllers library. This library loads all other
3
+ controller libraries.
4
+ */
5
+
6
+ // const TimerControllers = require('./timer-controller')
7
+ import TimerControllers from './timer-controller.js'
8
+
9
+ class Controllers {
10
+ constructor (localConfig = {}) {
11
+ // Dependency Injection
12
+ this.adapters = localConfig.adapters
13
+ if (!this.adapters) {
14
+ throw new Error(
15
+ 'Instance of adapters required when instantiating Controllers'
16
+ )
17
+ }
18
+
19
+ // Encapsulate dependencies
20
+ this.timer = new TimerControllers(localConfig)
21
+ }
22
+ }
23
+
24
+ export default Controllers
@@ -0,0 +1,417 @@
1
+ /*
2
+ This Controller library is concerned with timer-based functions that are
3
+ kicked off periodicially. These functions maintain connections and state
4
+ of the IPFS node.
5
+ */
6
+
7
+ // Local libraries
8
+ import Util from '../util/utils.js'
9
+
10
+ const DEFAULT_COORDINATION_ROOM = 'psf-ipfs-coordination-002'
11
+
12
+ class TimerControllers {
13
+ constructor (localConfig = {}) {
14
+ // Dependency Injection
15
+ this.adapters = localConfig.adapters
16
+ if (!this.adapters) {
17
+ throw new Error(
18
+ 'Instance of adapters required when instantiating Timer Controllers'
19
+ )
20
+ }
21
+ this.statusLog = localConfig.statusLog
22
+ if (!this.statusLog) {
23
+ throw new Error(
24
+ 'Handler for status logs required when instantiating Timer Controllers'
25
+ )
26
+ }
27
+
28
+ // Encapsulate dependencies
29
+ this.util = new Util()
30
+ this.sleep = this.util.sleep
31
+
32
+ // state
33
+ this.debugLevel = localConfig.debugLevel
34
+ this.config = localConfig
35
+ this.circuitRelayTimerInterval = 60000
36
+ this.announceTimerInterval = 31000
37
+ this.peerTimerInterval = 2 * 50000
38
+ this.relaySearchInterval = 3 * 60000
39
+ this.checkBlacklistInterval = 30000
40
+ this.listPubsubChannelsInterval = 32000
41
+
42
+ // Bind 'this' object to all subfunctions
43
+ this.startTimers = this.startTimers.bind(this)
44
+ this.stopAllTimers = this.stopAllTimers.bind(this)
45
+ // this.monitorBandwidth = this.monitorBandwidth.bind(this)
46
+ this.manageCircuitRelays = this.manageCircuitRelays.bind(this)
47
+ this.manageAnnouncement = this.manageAnnouncement.bind(this)
48
+ this.managePeers = this.managePeers.bind(this)
49
+ this.blacklist = this.blacklist.bind(this)
50
+ this.searchForRelays = this.searchForRelays.bind(this)
51
+ }
52
+
53
+ startTimers (thisNode, useCases) {
54
+ const _this = this
55
+
56
+ // Periodically maintain the connection to Circuit Relays.
57
+ this.circuitRelayTimerHandle = setInterval(async function () {
58
+ await _this.manageCircuitRelays(thisNode, useCases)
59
+ }, this.circuitRelayTimerInterval) // One Minute
60
+
61
+ // Periodically announce this nodes existance to the network.
62
+ this.announceTimerHandle = setInterval(async function () {
63
+ await _this.manageAnnouncement(thisNode, useCases)
64
+ }, this.announceTimerInterval)
65
+
66
+ // Periodically maintain the connection to other coordination peers.
67
+ this.peerTimerHandle = setInterval(async function () {
68
+ await _this.managePeers(thisNode, useCases)
69
+ }, this.peerTimerInterval)
70
+
71
+ // Periodically try to connect to problematic peers that advertise as
72
+ // potential circuit relays.
73
+ this.relaySearchHandle = setInterval(async function () {
74
+ await _this.searchForRelays(thisNode, useCases)
75
+ }, this.relaySearchInterval)
76
+
77
+ // Periodically ensure we are disconnected from blacklisted peers.
78
+ this.checkBlacklistHandle = setInterval(async function () {
79
+ await _this.blacklist(thisNode, useCases)
80
+ }, this.checkBlacklistInterval)
81
+
82
+ this.listPubsubChannelsHandle = setInterval(async function () {
83
+ await _this.listPubsubChannels()
84
+ }, this.listPubsubChannelsInterval)
85
+
86
+ // Return handles to the different timers.
87
+ return {
88
+ circuitRelayTimerHandle: this.circuitRelayTimerHandle,
89
+ announceTimerHandle: this.announceTimerHandle,
90
+ peerTimerHandle: this.peerTimerHandle,
91
+ relaySearchHandle: this.relaySearchHandle,
92
+ checkBlacklistHandle: this.checkBlacklistHandle,
93
+ listPubsubChannelsHandle: this.listPubsubChannelsHandle
94
+ }
95
+ }
96
+
97
+ // Used mostly for testing. Ensures all timers are stopped.
98
+ async stopAllTimers () {
99
+ clearInterval(this.circuitRelayTimerHandle)
100
+ clearInterval(this.announceTimerHandle)
101
+ clearInterval(this.peerTimerHandle)
102
+ clearInterval(this.relaySearchHandle)
103
+ clearInterval(this.checkBlacklistHandle)
104
+ clearInterval(this.listPubsubChannelsHandle)
105
+ }
106
+
107
+ async listPubsubChannels () {
108
+ const ipfs = this.adapters.ipfs.ipfs
109
+
110
+ // const pubsubChans = await ipfs.pubsub.ls()
111
+ const pubsubChans = ipfs.libp2p.services.pubsub.subscriptions
112
+ console.log(`subscribed pubsub channels: ${JSON.stringify(pubsubChans, null, 2)}`)
113
+ this.adapters.log.statusLog(2, `subscribed pubsub channels: ${JSON.stringify(pubsubChans, null, 2)}`)
114
+
115
+ return true
116
+ }
117
+
118
+ // Dev Note: This is not curently used, but code is left because it may be
119
+ // enabled in the future.
120
+ // Monitor the bandwidth being consumed by IPFS peers.
121
+ // async monitorBandwidth (thisNode, useCases) {
122
+ // try {
123
+ // const ipfs = this.adapters.ipfs.ipfs
124
+
125
+ // // const bw = await ipfs.stats.bw()
126
+ // // console.log('bw: ', bw)
127
+ // for await (const stats of ipfs.stats.bw()) {
128
+ // // console.log(stats)
129
+ // this.adapters.log.statusLog(2, 'Bandwidth stats: ', stats)
130
+ // // this.adapters.log.statusLog(2, `${JSON.stringify(stats, null, 2)}`)
131
+ // }
132
+
133
+ // const bitswap = await ipfs.stats.bitswap()
134
+ // this.adapters.log.statusLog(2, 'bitswap stats: ', bitswap)
135
+ // // this.adapters.log.statusLog(2, `${JSON.stringify(bitswap, null, 2)}`)
136
+
137
+ // return true
138
+
139
+ // } catch (err) {
140
+ // console.error('Error in timer-controller.js/monitorBandwidth(): ', err)
141
+ // // this.adapters.log.statusLog(
142
+ // // 2,
143
+ // // 'Error in timer-controller.jsmonitorBandwidth(): ',
144
+ // // err
145
+ // // )
146
+
147
+ // // Note: Do not throw an error. This is a top-level function.
148
+ // return false
149
+ // }
150
+ // }
151
+
152
+ // This function is intended to be called periodically by setInterval().
153
+ // This function finds circuit relays on the network that can be used
154
+ // to relay data to other nodes behind firewalls.
155
+ async manageCircuitRelays (thisNode, useCases) {
156
+ try {
157
+ this.adapters.log.statusLog(3, 'Entering manageCircuitRelays() Controller.')
158
+
159
+ // Disable the timer while processing is happening.
160
+ clearInterval(this.circuitRelayTimerHandle)
161
+
162
+ // Remove any duplicate entries
163
+ useCases.relays.removeDuplicates(thisNode)
164
+
165
+ // Maintain connections to Relays.
166
+ await useCases.relays.connectToCRs(thisNode)
167
+
168
+ // Update metrics on Relays.
169
+ await useCases.relays.measureRelays(thisNode)
170
+
171
+ const now = new Date()
172
+ this.adapters.log.statusLog(1,
173
+ `Renewed connections to all circuit relays at ${now.toLocaleString()}`
174
+ )
175
+
176
+ // Re-enable the timer interval.
177
+ const _this = this
178
+ this.circuitRelayTimerHandle = setInterval(async function () {
179
+ await _this.manageCircuitRelays(thisNode, useCases)
180
+ }, this.circuitRelayTimerInterval)
181
+
182
+ // console.log('Exiting manageCircuitRelays() Controller.')
183
+
184
+ return true
185
+ } catch (err) {
186
+ console.error(
187
+ 'Error in timer-controller.js/manageCircuitRelays(): ',
188
+ err
189
+ )
190
+ // this.adapters.log.statusLog(
191
+ // 2,
192
+ // 'Error in timer-controller.js/manageCircuitRelays(): ',
193
+ // err
194
+ // )
195
+
196
+ // Re-enable the timer interval.
197
+ const _this = this
198
+ this.circuitRelayTimerHandle = setInterval(async function () {
199
+ await _this.manageCircuitRelays(thisNode, useCases)
200
+ }, this.circuitRelayTimerInterval)
201
+
202
+ // Note: Do not throw an error. This is a top-level function.
203
+ return false
204
+ }
205
+ }
206
+
207
+ // This function is intended to be called periodically by setInterval().
208
+ // Announce the existance of this node to the network.
209
+ async manageAnnouncement (thisNode, useCases) {
210
+ try {
211
+ // console.log('thisNode: ', thisNode)
212
+
213
+ // Disable the timer interval while this function executes.
214
+ clearInterval(this.announceTimerHandle)
215
+
216
+ // Get the information needed for the announcement.
217
+ const announceObj = {
218
+ ipfsId: thisNode.ipfsId,
219
+ ipfsMultiaddrs: thisNode.ipfsMultiaddrs,
220
+ type: thisNode.type,
221
+ // orbitdbId: thisNode.orbit.id,
222
+
223
+ // TODO: Allow node.js apps to pass a config setting to override this.
224
+ isCircuitRelay: false
225
+ }
226
+
227
+ // Generate the announcement message.
228
+ const announceMsgObj = thisNode.schema.announcement(announceObj)
229
+ // console.log(`announceMsgObj: ${JSON.stringify(announceMsgObj, null, 2)}`)
230
+
231
+ const announceMsgStr = JSON.stringify(announceMsgObj)
232
+
233
+ // Publish the announcement to the pubsub channel.
234
+ await this.adapters.pubsub.messaging.publishToPubsubChannel(
235
+ DEFAULT_COORDINATION_ROOM,
236
+ announceMsgStr
237
+ )
238
+
239
+ const now = new Date()
240
+ this.adapters.log.statusLog(
241
+ 1,
242
+ `status: Announced self on ${DEFAULT_COORDINATION_ROOM} pubsub channel at ${now.toLocaleString()}`
243
+ )
244
+
245
+ // Re-enable the timer interval
246
+ const _this = this
247
+ this.announceTimerHandle = setInterval(async function () {
248
+ await _this.manageAnnouncement(thisNode, useCases)
249
+ }, this.announceTimerInterval)
250
+
251
+ return true
252
+ } catch (err) {
253
+ console.error('Error in timer-controller.js/manageAnnouncement(): ', err)
254
+ // this.adapters.log.statusLog(
255
+ // 2,
256
+ // 'Error in timer-controller.js/manageAnnouncement(): ',
257
+ // err
258
+ // )
259
+
260
+ // Re-enable the timer interval
261
+ const _this = this
262
+ this.announceTimerHandle = setInterval(async function () {
263
+ await _this.manageAnnouncement(thisNode, useCases)
264
+ }, this.announceTimerInterval)
265
+
266
+ // Note: Do not throw an error. This is a top-level function.
267
+ return false
268
+ }
269
+ }
270
+
271
+ // This function is intended to be called periodically by setInterval().
272
+ // It refreshes the connection to all subnet peers thisNode is trying to track.
273
+ async managePeers (thisNode, useCases) {
274
+ let success = false
275
+
276
+ try {
277
+ // Disable the timer while processing is happening.
278
+ clearInterval(this.peerTimerHandle)
279
+
280
+ // this.statusLog('managePeers')
281
+ await useCases.thisNode.refreshPeerConnections()
282
+
283
+ // console.error('Error in timer-controller.js/manageAnnouncement(): ', err)
284
+ this.adapters.log.statusLog(
285
+ 1,
286
+ 'Renewed connections to all subnet peers.'
287
+ )
288
+
289
+ // Reinstate the timer interval
290
+ const _this = this
291
+ this.peerTimerHandle = setInterval(async function () {
292
+ await _this.managePeers(thisNode, useCases)
293
+ }, this.peerTimerInterval)
294
+
295
+ success = true
296
+ } catch (err) {
297
+ console.log('Error in timer-controller.js/managePeers(): ', err)
298
+ // this.adapters.log.statusLog(
299
+ // 2,
300
+ // 'Error in timer-controller.js/managePeers(): ',
301
+ // err
302
+ // )
303
+
304
+ // Reinstate the timer interval
305
+ const _this = this
306
+ this.peerTimerHandle = setInterval(async function () {
307
+ await _this.managePeers(thisNode, useCases)
308
+ }, this.peerTimerInterval)
309
+
310
+ // Note: Do not throw an error. This is a top-level function.
311
+ success = false
312
+ }
313
+
314
+ return success
315
+ }
316
+
317
+ // Actively disconnect from blacklisted peers.
318
+ // TODO: Rename this to whitelist, as it's not a whitelist function.
319
+ async blacklist (thisNode, useCases) {
320
+ let success = false
321
+
322
+ try {
323
+ // Disable the timer while processing is happening.
324
+ clearInterval(this.checkBlacklistHandle)
325
+
326
+ // this.statusLog('managePeers')
327
+ // await useCases.thisNode.enforceBlacklist()
328
+ await useCases.thisNode.enforceWhitelist()
329
+
330
+ this.adapters.log.statusLog(1, 'Finished enforcing whitelist.')
331
+
332
+ // Reinstate the timer interval
333
+ const _this = this
334
+ this.checkBlacklistHandle = setInterval(async function () {
335
+ await _this.blacklist(thisNode, useCases)
336
+ }, this.checkBlacklistInterval)
337
+
338
+ success = true
339
+ } catch (err) {
340
+ console.log()
341
+ // this.adapters.log.statusLog('Error in timer-controller.js/blacklist(): ', err)
342
+ // 2,
343
+ // 'Error in timer-controller.js/blacklist(): ',
344
+ // err
345
+ // )
346
+
347
+ // Reinstate the timer interval
348
+ const _this = this
349
+ this.checkBlacklistHandle = setInterval(async function () {
350
+ await _this.blacklist(thisNode, useCases)
351
+ }, this.checkBlacklistInterval)
352
+
353
+ // Note: Do not throw an error. This is a top-level function.
354
+ success = false
355
+ }
356
+
357
+ return success
358
+ }
359
+
360
+ // This method looks for subnet peers that have the isCircuitRelay flag set,
361
+ // but are not in the list of known relays. These represent potential relays
362
+ // that thisNode could not connect to, but it might be able to with another
363
+ // try.
364
+ async searchForRelays (thisNode, useCases) {
365
+ try {
366
+ // console.log('Entering searchForRelays() Controller.')
367
+
368
+ // Disable the timer while processing is happening.
369
+ clearInterval(this.relaySearchHandle)
370
+
371
+ // Get all the known relays.
372
+ const knownRelays = thisNode.relayData.map(x => x.ipfsId)
373
+ // console.log('knownRelays: ', knownRelays)
374
+
375
+ // Get all subnet peers that have their circuit relay flag set.
376
+ let relayPeers = thisNode.peerData.filter(x => x.data.isCircuitRelay)
377
+ relayPeers = relayPeers.map(x => x.from)
378
+ // console.log('relayPeers: ', relayPeers)
379
+
380
+ // Diff the two arrays to get relays peers that are not in the relay list.
381
+ const diffRelayPeers = relayPeers.filter(x => !knownRelays.includes(x))
382
+ // console.log('diffRelayPeers: ', diffRelayPeers)
383
+
384
+ // Try to connect to each potential relay.
385
+ for (let i = 0; i < diffRelayPeers.length; i++) {
386
+ const thisPeer = diffRelayPeers[i]
387
+ await useCases.relays.addRelay(thisPeer, thisNode)
388
+ }
389
+
390
+ // Re-enable the interval timer for this function.
391
+ const _this = this
392
+ this.relaySearchHandle = setInterval(async function () {
393
+ await _this.searchForRelays(thisNode, useCases)
394
+ }, this.relaySearchInterval)
395
+
396
+ return true
397
+ } catch (err) {
398
+ console.error('Error in timer-controller.js/searchForRelays(): ', err)
399
+ // this.adapters.log.statusLog(
400
+ // 2,
401
+ // 'Error in timer-controller.js/searchForRelays(): ',
402
+ // err
403
+ // )
404
+
405
+ // Re-enable the interval timer for this function.
406
+ const _this = this
407
+ this.relaySearchHandle = setInterval(async function () {
408
+ await _this.searchForRelays(thisNode, useCases)
409
+ }, this.relaySearchInterval)
410
+
411
+ // Note: Do not throw an error. This is a top-level function.
412
+ return false
413
+ }
414
+ }
415
+ }
416
+
417
+ export default TimerControllers
@@ -0,0 +1,102 @@
1
+ /*
2
+ This is an Entity library for creating a representation the 'self' or
3
+ the current IPFS node with the adding information of a BCH wallet and
4
+ any future features added to ipfs-coord.
5
+
6
+ There is only one instance of this class library, as there is only one
7
+ IPFS node that is the 'self'.
8
+ */
9
+
10
+ class ThisNodeEntity {
11
+ // The constructor checks the input data and throws an error if any of the
12
+ // required data is missing.
13
+ constructor (localConfig = {}) {
14
+ this.ipfsId = localConfig.ipfsId
15
+ if (!this.ipfsId) {
16
+ throw new Error('ipfsId required when instantiating thisNode Entity')
17
+ }
18
+
19
+ this.ipfsMultiaddrs = localConfig.ipfsMultiaddrs
20
+ if (!this.ipfsMultiaddrs) {
21
+ throw new Error(
22
+ 'ipfsMultiaddrs required when instantiating thisNode Entity'
23
+ )
24
+ }
25
+
26
+ this.bchAddr = localConfig.bchAddr
27
+ if (!this.bchAddr) {
28
+ throw new Error('bchAddr required when instantiating thisNode Entity')
29
+ }
30
+
31
+ this.slpAddr = localConfig.slpAddr
32
+ if (!this.slpAddr) {
33
+ throw new Error('slpAddr required when instantiating thisNode Entity')
34
+ }
35
+
36
+ this.publicKey = localConfig.publicKey
37
+ if (!this.publicKey) {
38
+ throw new Error('publicKey required when instantiating thisNode Entity')
39
+ }
40
+
41
+ this.type = localConfig.type
42
+ if (!this.type) {
43
+ throw new Error(
44
+ "Node type of 'node.js' or 'browser' required when instantiating thisNode Entity"
45
+ )
46
+ }
47
+
48
+ this.schema = localConfig.schema
49
+
50
+ // This Node will keep track of peers, relays, and services.
51
+ // The 'List' array tracks the IPFS ID for that peer.
52
+ // The 'Data' array holds instances of the other Entities.
53
+ this.peerList = []
54
+ this.peerData = []
55
+ this.relayData = []
56
+ this.serviceList = []
57
+ this.serviceData = []
58
+
59
+ // Create a blacklist of nodes that can burden other nodes with excessive bandwidth.
60
+ this.blacklistPeers = [
61
+ // '/dns4/node0.preload.ipfs.io/tcp/443/wss/p2p/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
62
+ 'QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
63
+ // '/dns4/node1.preload.ipfs.io/tcp/443/wss/p2p/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6',
64
+ 'Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6',
65
+ // '/dns4/node2.preload.ipfs.io/tcp/443/wss/p2p/QmV7gnbW5VTcJ3oyM2Xk1rdFBJ3kTkvxc87UFGsun29STS',
66
+ 'QmV7gnbW5VTcJ3oyM2Xk1rdFBJ3kTkvxc87UFGsun29STS',
67
+ // '/dns4/node3.preload.ipfs.io/tcp/443/wss/p2p/QmY7JB6MQXhxHvq7dBDh4HpbH29v4yE9JRadAVpndvzySN'
68
+ 'QmY7JB6MQXhxHvq7dBDh4HpbH29v4yE9JRadAVpndvzySN',
69
+ // '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
70
+ 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
71
+ // '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
72
+ 'QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
73
+ // '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
74
+ 'QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
75
+ // '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
76
+ 'QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
77
+ // '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
78
+ 'QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
79
+ // '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
80
+ 'QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
81
+ ]
82
+ this.blacklistMultiaddrs = [
83
+ '/dns4/node0.preload.ipfs.io/tcp/443/wss/p2p/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
84
+ '/dns4/node1.preload.ipfs.io/tcp/443/wss/p2p/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6',
85
+ '/dns4/node2.preload.ipfs.io/tcp/443/wss/p2p/QmV7gnbW5VTcJ3oyM2Xk1rdFBJ3kTkvxc87UFGsun29STS',
86
+ '/dns4/node3.preload.ipfs.io/tcp/443/wss/p2p/QmY7JB6MQXhxHvq7dBDh4HpbH29v4yE9JRadAVpndvzySN',
87
+ '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
88
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
89
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
90
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
91
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
92
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt',
93
+ '/dns4/node0.delegate.ipfs.io/tcp/443/https',
94
+ '/dns4/node1.delegate.ipfs.io/tcp/443/https',
95
+ '/dns4/node2.delegate.ipfs.io/tcp/443/https',
96
+ '/dns4/node3.delegate.ipfs.io/tcp/443/https'
97
+ ]
98
+ }
99
+ }
100
+
101
+ // module.exports = ThisNodeEntity
102
+ export default ThisNodeEntity
@@ -0,0 +1,36 @@
1
+ /*
2
+ This is a top-level Use Cases library. This library loads all other
3
+ use case libraries, and bundles them into a single object.
4
+ */
5
+
6
+ // Local libraries
7
+ import ThisNodeUseCases from './this-node-use-cases.js'
8
+ import RelayUseCases from './relay-use-cases.js'
9
+ import PubsubUseCases from './pubsub-use-cases.js'
10
+ import PeerUseCases from './peer-use-cases.js'
11
+
12
+ class UseCases {
13
+ constructor (localConfig = {}) {
14
+ this.adapters = localConfig.adapters
15
+ if (!this.adapters) {
16
+ throw new Error(
17
+ 'Must inject instance of adapters when instantiating Use Cases library.'
18
+ )
19
+ }
20
+
21
+ // Encapsulate dependencies
22
+ this.thisNode = new ThisNodeUseCases(localConfig)
23
+
24
+ // Other use-cases depend on the thisNode use case.
25
+ localConfig.thisNodeUseCases = this.thisNode
26
+
27
+ this.relays = new RelayUseCases(localConfig)
28
+ this.pubsub = new PubsubUseCases(localConfig)
29
+ this.peer = new PeerUseCases(localConfig)
30
+
31
+ // Pass the instances of the other use cases to the ThisNode Use Cases.
32
+ this.thisNode.updateUseCases(this)
33
+ }
34
+ }
35
+
36
+ export default UseCases