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,263 @@
1
+ /*
2
+ Adapter library for IPFS, so the rest of the business logic doesn't need to
3
+ know specifics about the IPFS API.
4
+ */
5
+
6
+ // The amount of time to wait to connect to a peer, in milliseconds.
7
+ // Increasing the time makes the network slower but more resilient to latency.
8
+ // Decreasing the time makes the network faster, but more smaller and more fragile.
9
+ // import bootstapNodes from '../../config/bootstrap-circuit-relays.js'
10
+ import { multiaddr } from '@multiformats/multiaddr'
11
+
12
+ const CONNECTION_TIMEOUT = 10000
13
+
14
+ class IpfsAdapter {
15
+ constructor (localConfig = {}) {
16
+ // Input Validation
17
+ this.ipfs = localConfig.ipfs
18
+ if (!this.ipfs) {
19
+ throw new Error(
20
+ 'An instance of IPFS must be passed when instantiating the IPFS adapter library.'
21
+ )
22
+ }
23
+ this.log = localConfig.log
24
+ if (!this.log) {
25
+ throw new Error(
26
+ 'A status log handler must be specified when instantiating IPFS adapter library.'
27
+ )
28
+ }
29
+
30
+ // 'embedded' node type used as default, will use embedded js-ipfs.
31
+ // Alternative is 'external' which will use ipfs-http-client to control an
32
+ // external IPFS node.
33
+ this.nodeType = localConfig.nodeType
34
+ if (!this.nodeType) {
35
+ // console.log('No node type specified. Assuming embedded js-ipfs.')
36
+ this.nodeType = 'embedded'
37
+ }
38
+
39
+ // Port Settings. Defaults are overwritten if specified in the localConfig.
40
+ this.tcpPort = 4001
41
+ if (localConfig.tcpPort) this.tcpPort = localConfig.tcpPort
42
+ this.wsPort = 4003
43
+ if (localConfig.wsPort) this.wsPort = localConfig.wsPort
44
+
45
+ // Placeholders that will be filled in after the node finishes initializing.
46
+ this.ipfsPeerId = ''
47
+ this.ipfsMultiaddrs = ''
48
+
49
+ // Encapsulate dependencies
50
+ this.multiaddr = multiaddr
51
+ }
52
+
53
+ // Start the IPFS node if it hasn't already been started.
54
+ // Update the state of this adapter with the IPFS node information.
55
+ async start () {
56
+ try {
57
+ // Wait until the IPFS creation Promise has resolved, and the node is
58
+ // fully instantiated.
59
+ this.ipfs = await this.ipfs
60
+
61
+ // Get ID information about this IPFS node.
62
+ // const id2 = await this.ipfs.id()
63
+ // this.state.ipfsPeerId = id2.id
64
+ // this.ipfsPeerId = id2.id
65
+ this.ipfsPeerId = this.ipfs.libp2p.peerId.toString()
66
+
67
+ // Get multiaddrs that can be used to connect to this node.
68
+ // const addrs = id2.addresses.map(elem => elem.toString())
69
+ const addrs = this.ipfs.libp2p.getMultiaddrs().map(elem => elem.toString())
70
+ // this.state.ipfsMultiaddrs = addrs
71
+ this.ipfsMultiaddrs = addrs
72
+
73
+ // Remove bootstrap nodes, as we have our own bootstrap nodes, and the
74
+ // the default ones can spam our nodes with a ton of bandwidth.
75
+ // await this.ipfs.config.set('Bootstrap', [
76
+ // bootstapNodes.node[0].multiaddr,
77
+ // bootstapNodes.node[1].multiaddr
78
+ // ])
79
+
80
+ // Settings specific to embedded js-ipfs.
81
+ // if (this.nodeType === 'embedded') {
82
+ // // Also remove default Delegates, as they are the same as the default
83
+ // // Bootstrap nodes.
84
+ // await this.ipfs.config.set('Addresses.Delegates', [])
85
+ // }
86
+
87
+ // Settings specific to external go-ipfs node.
88
+ // if (this.nodeType === 'external') {
89
+ // // Enable RelayClient
90
+ // // https://github.com/ipfs/go-ipfs/blob/master/docs/config.md#swarmrelayclient
91
+ // // https://github.com/ipfs/go-ipfs/releases/tag/v0.11.0
92
+ // await this.ipfs.config.set('Swarm.RelayClient.Enabled', true)
93
+
94
+ // // Enable hole punching for better p2p interaction.
95
+ // // https://github.com/ipfs/go-ipfs/blob/master/docs/config.md#swarmenableholepunching
96
+ // await this.ipfs.config.set('Swarm.EnableHolePunching', true)
97
+
98
+ // // Enable websocket connections
99
+ // await this.ipfs.config.set('Addresses.Swarm', [
100
+ // `/ip4/0.0.0.0/tcp/${this.tcpPort}`,
101
+ // `/ip6/::/tcp/${this.tcpPort}`,
102
+ // // `/ip4/0.0.0.0/udp/${this.tcpPort}/quic`,
103
+ // // `/ip6/::/udp/${this.tcpPort}/quic`,
104
+ // `/ip4/0.0.0.0/tcp/${this.wsPort}`, // Websockets
105
+ // `/ip6/::/tcp/${this.wsPort}`
106
+ // ])
107
+
108
+ // // Disable scanning of IP ranges. This is largely driven by Hetzner
109
+ // await this.ipfs.config.set('Swarm.AddrFilters', [
110
+ // '/ip4/10.0.0.0/ipcidr/8',
111
+ // '/ip4/100.0.0.0/ipcidr/8',
112
+ // '/ip4/169.254.0.0/ipcidr/16',
113
+ // '/ip4/172.16.0.0/ipcidr/12',
114
+ // '/ip4/192.0.0.0/ipcidr/24',
115
+ // '/ip4/192.0.2.0/ipcidr/24',
116
+ // '/ip4/192.168.0.0/ipcidr/16',
117
+ // '/ip4/198.18.0.0/ipcidr/15',
118
+ // '/ip4/198.51.100.0/ipcidr/24',
119
+ // '/ip4/203.0.113.0/ipcidr/24',
120
+ // '/ip4/240.0.0.0/ipcidr/4',
121
+ // '/ip6/100::/ipcidr/64',
122
+ // '/ip6/2001:2::/ipcidr/48',
123
+ // '/ip6/2001:db8::/ipcidr/32',
124
+ // '/ip6/fc00::/ipcidr/7',
125
+ // '/ip6/fe80::/ipcidr/10'
126
+ // ])
127
+
128
+ // // go-ipfs v0.10.0
129
+ // // await this.ipfs.config.set('Swarm.EnableRelayHop', true)
130
+ // // await this.ipfs.config.set('Swarm.EnableAutoRelay', true)
131
+
132
+ // // Disable peer discovery
133
+ // // await this.ipfs.config.set('Routing.Type', 'none')
134
+ // }
135
+
136
+ // Disable preloading
137
+ // await this.ipfs.config.set('preload.enabled', false)
138
+
139
+ // Reduce the default number of peers thisNode connects to at one time.
140
+ // await this.ipfs.config.set('Swarm.ConnMgr', {
141
+ // LowWater: 10,
142
+ // HighWater: 30,
143
+ // GracePeriod: '2s'
144
+ // })
145
+
146
+ // Reduce the storage size, as this node should not be retaining much data.
147
+ // await this.ipfs.config.set('Datastore.StorageMax', '2GB')
148
+ } catch (err) {
149
+ console.error('Error in ipfs-adapter.js/start()')
150
+ throw err
151
+ }
152
+ }
153
+
154
+ // Attempts to connect to an IPFS peer, given its IPFS multiaddr.
155
+ // Returns true if the connection succeeded. Otherwise returns false.
156
+ async connectToPeer (ipfsAddr) {
157
+ try {
158
+ // TODO: Throw error if ipfs ID is passed, instead of a multiaddr.
159
+ console.log('ipfsAddr: ', ipfsAddr)
160
+
161
+ // await this.ipfs.swarm.connect(ipfsAddr, { timeout: CONNECTION_TIMEOUT })
162
+ await this.ipfs.libp2p.dial(this.multiaddr(ipfsAddr))
163
+
164
+ this.log.statusLog(1, `Successfully connected to peer node ${ipfsAddr}`)
165
+
166
+ return true
167
+ } catch (err) {
168
+ /* exit quietly */
169
+ console.warn(
170
+ `Error trying to connect to peer node ${ipfsAddr}: ${err.message}`
171
+ )
172
+
173
+ // if (this.debugLevel === 1) {
174
+ // this.statusLog(
175
+ // `status: Error trying to connect to peer node ${ipfsAddr}`
176
+ // )
177
+ // } else if (this.debugLevel === 2) {
178
+ // this.statusLog(
179
+ // `status: Error trying to connect to peer node ${ipfsAddr}: `,
180
+ // err
181
+ // )
182
+ // }
183
+ this.log.statusLog(2, `Error trying to connect to peer node ${ipfsAddr}`)
184
+ // console.log(`Error trying to connect to peer node ${ipfsAddr}: `, err)
185
+
186
+ // this.log.statusLog(
187
+ // 3,
188
+ // `Error trying to connect to peer node ${ipfsAddr}: `,
189
+ // err
190
+ // )
191
+
192
+ return false
193
+ }
194
+ }
195
+
196
+ // Disconnect from a peer.
197
+ async disconnectFromPeer (ipfsId) {
198
+ try {
199
+ // TODO: If given a multiaddr, extract the IPFS ID.
200
+
201
+ // Get the list of peers that we're connected to.
202
+ const connectedPeers = await this.getPeers()
203
+ // console.log('connectedPeers: ', connectedPeers)
204
+
205
+ // See if we're connected to the given IPFS ID
206
+ const connectedPeer = connectedPeers.filter(x => x.peer === ipfsId)
207
+
208
+ // If we're not connected, exit.
209
+ if (!connectedPeer.length) {
210
+ // console.log(`debug: Not connected to ${ipfsId}`)
211
+ return true
212
+ }
213
+
214
+ // If connected, disconnect from the peer.
215
+ await this.ipfs.swarm.disconnect(connectedPeer[0].addr, {
216
+ timeout: CONNECTION_TIMEOUT
217
+ })
218
+
219
+ return true
220
+ } catch (err) {
221
+ // exit quietly
222
+ return false
223
+ }
224
+ }
225
+
226
+ async disconnectFromMultiaddr (multiaddr) {
227
+ try {
228
+ await this.ipfs.swarm.disconnect(multiaddr, {
229
+ timeout: CONNECTION_TIMEOUT
230
+ })
231
+
232
+ return true
233
+ } catch (err) {
234
+ return false
235
+ }
236
+ }
237
+
238
+ // Get a list of all the IPFS peers This Node is connected to.
239
+ async getPeers () {
240
+ try {
241
+ // console.log('this.ipfs.libp2p: ', this.ipfs.libp2p)
242
+
243
+ // Get connected peers
244
+ // const connectedPeers = await this.ipfs.swarm.peers({
245
+ // direction: true,
246
+ // streams: true,
247
+ // verbose: true,
248
+ // latency: true
249
+ // })
250
+ let connectedPeers = await this.ipfs.libp2p.getPeers()
251
+ connectedPeers = connectedPeers.map(x => x.toString())
252
+ console.log('connectedPeers: ', connectedPeers)
253
+
254
+ return connectedPeers
255
+ } catch (err) {
256
+ console.error('Error in ipfs-adapter.js/getPeers(): ', err)
257
+ throw err
258
+ }
259
+ }
260
+ }
261
+
262
+ // module.exports = IpfsAdapter
263
+ export default IpfsAdapter
@@ -0,0 +1,44 @@
1
+ /*
2
+ Controls the verbosity of the status log
3
+
4
+ Default verbosity is zero, which is the least verbose messages.
5
+ As the value increases, the amount of messages also increases.
6
+
7
+ 0 - Normal logs
8
+ 1 - More information on connections and error connections.
9
+ 2 - Verbose Error messages
10
+ 3 - Error messages about connections.
11
+ */
12
+
13
+ // const util = require('util')
14
+ import util from 'util'
15
+
16
+ class LogsAdapter {
17
+ constructor (localConfig = {}) {
18
+ // Default to debugLevel 0 if not specified.
19
+ this.debugLevel = localConfig.debugLevel
20
+ if (!this.debugLevel) this.debugLevel = 0
21
+
22
+ this.logHandler = localConfig.statusLog
23
+ if (!this.logHandler) {
24
+ throw new Error(
25
+ 'statusLog must be specified when instantiating Logs adapter library.'
26
+ )
27
+ }
28
+ }
29
+
30
+ // Print out the data, if the log level is less than or equal to the debug
31
+ // level set when instantiating the library.
32
+ statusLog (level, str, object) {
33
+ if (level <= this.debugLevel) {
34
+ if (object === undefined) {
35
+ this.logHandler('status: ' + str)
36
+ } else {
37
+ this.logHandler('status: ' + str + ' ' + util.inspect(object))
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+ // module.exports = LogsAdapter
44
+ export default LogsAdapter
@@ -0,0 +1,86 @@
1
+ # Pubsub Adapter
2
+
3
+ The [index.js](./index.js) file contains the primary PubSub adapter, which controls the pubsub channel connections between peers. [messaging.js](./messaging.js) controls the message handling for communicating over pubsub channels.
4
+
5
+ Because IPFS nodes are constantly changing their network connections, it's frequently observed that pubsub messages between peers get 'lost'. Version 6 and older used [orbit-db](https://www.npmjs.com/package/orbit-db) to prevent these lost messages. However, it turned out to not be a very scalable solution. Orbit-db is way too CPU heavy to work as a speedy form of inter-node communication.
6
+
7
+ Version 7 introduced the [messaging.js](./messaging.js) library. The primary problem this library solves is the 'lost message' issue. The IPFS pubsub channels handle the bulk of the low-level messaging.
8
+
9
+ ## Messaging Protocol
10
+
11
+ To handle 'lost messages', two peers engage in a message-acknowledge scheme:
12
+
13
+ Happy Path:
14
+
15
+ - Node 1 publishes a message to the pubsub channel for Node 2.
16
+ - Node 2 publishes an ACK (acknowledge) message to the pubsub channel for Node 1.
17
+ - If both messages are received, the transaction is complete.
18
+
19
+ Each message is wrapped in a data object with the following properties:
20
+
21
+ - timestamp
22
+ - UUID
23
+ - sender (IPFS ID)
24
+ - receiver (IPFS ID)
25
+ - payload
26
+
27
+ If Node 1 does not receive an ACK message after 5 seconds, it will publish the message to the pubsub channel again. It will do this every 5 seconds, until either an ACK message is received or a retry threshold is met (3 tries).
28
+
29
+ Node 2 will attempt to send an ACK message any time it receives a message.
30
+
31
+ It's important to note that two pubsub channels are used. Node 1 sends data on Node 2's pubsub channel. Node 2 responds by publishing data on Node 1's pubsub channel.
32
+
33
+ ## Libraries
34
+
35
+ To understand the relationships between the messaing (messaging.js) and pubsub (index.js) libraries, and comparison to the [OSI model](https://www.imperva.com/learn/application-security/osi-model/) can be made. In the OSI model, from top to bottom, there is:
36
+
37
+ - A presentation layer (6).
38
+ - A session layer (5)
39
+ - A transport layer (4)
40
+
41
+ Analogously:
42
+ - The pubsub library ([index.js](./index.js)) is like the presentation layer (6).
43
+ - The messaging library ([messaging.js](./messaging.js)) is like the session layer (5).
44
+ - The IPFS pubsub API is like the transport layer (4).
45
+
46
+ The point is that there are two different communication protocols happening at the same time:
47
+ - The underlying messaging protocol described here *does not* care about the content of the messages. It's just trying to ensure messages are passes reliably.
48
+ - The message handling in the pubsub library *does* care about the content of the messages.
49
+
50
+
51
+ ## Example
52
+
53
+ Here is an example of an RPC command wrapped inside of a message envelope. The payload contains the encrypted RPC command. Notice the message itself has a UUID (universally unique identifier).
54
+
55
+ ```javascript
56
+ {
57
+ "timestamp": "2022-03-03T18:03:01.217Z",
58
+ "uuid": "e0f08e3f-6e23-43ea-8fa9-39b828fd4fdc",
59
+ "sender": "12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa",
60
+ "receiver": "12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f",
61
+ "payload": "0453769b22a27adbb288bb2a05c19605a1fb033d4aeca92dfbf59f5c61732f89e6668a9a645dea3fe82e1bda20b8b11e713586b2c39d33f00dcf8fddac401263c320f06136a494e965f34193c3c6bb670a146c2ec06cdb5fd564b11a25c8715d574b8e1fd57f90e697c1edf21eb27ec0c431ce83293a4611e9593a53490c220019867208a1e241f23851c91646521b2e47"
62
+ }
63
+ ```
64
+
65
+ Once the payload is decrypted and parsed, it looks like this. Notice that the RPC command has it's own UUID.
66
+
67
+ ```javascript
68
+ {
69
+ jsonrpc: '2.0',
70
+ id: 'bb788af4-b7d1-4650-a7ae-bfd03b7f5140',
71
+ method: 'bch',
72
+ params: {
73
+ endpoint: 'utxos',
74
+ address: 'bitcoincash:qr2u4f2dmva6yvf3npkd5lquryp09qk7gs5vxl423h'
75
+ }
76
+ }
77
+ ```
78
+
79
+ ### Workflow
80
+
81
+ Using the above RPC command as an example, here is the messaging workflow between Node 1 and Node 2:
82
+
83
+ - Node 1 sends the RPC command to Node 2
84
+ - Node 2 immediately responds with an ACK message
85
+ - Node 2 processes the RPC command and sends the response to Node 1
86
+ - Node 1 immediately reponds with an ACK message
@@ -0,0 +1,117 @@
1
+ /*
2
+ This adapter is designed to poll the /about JSON RPC endpoint for IPFS Service
3
+ Providers that leverage ipfs-coord. This allows other consumers of the
4
+ ipfs-coord library to measure the latency between themselves and potential
5
+ Circuit Relays.
6
+
7
+ Using these metrics, IPFS nodes can prioritize the Circuit Relays with the
8
+ lowest latency. At scale, this allows the entire IPFS subnet to adapt to
9
+ changing network conditions.
10
+ */
11
+
12
+ class AboutAdapter {
13
+ constructor (localConfig = {}) {
14
+ // Time to wait for a reponse from the RPC.
15
+ this.waitPeriod = 10000
16
+
17
+ // Used to pass asynchronous data when pubsub data is received.
18
+ this.incomingData = false
19
+ }
20
+
21
+ // Query the /about JSON RPC endpoint for a subnet peer.
22
+ // This function will return true on success or false on failure or timeout
23
+ // of 10 seconds.
24
+ // This function is used to measure the time for a response from the peer.
25
+ async queryAbout (ipfsId, thisNode) {
26
+ try {
27
+ // console.log(`Querying Relay ${ipfsId}`)
28
+ // console.log('thisNode: ', thisNode)
29
+
30
+ // Generate the JSON RPC command
31
+ const idNum = Math.floor(Math.random() * 10000).toString()
32
+ const id = `metrics${idNum}`
33
+ const cmdStr = `{"jsonrpc":"2.0","id":"${id}","method":"about"}`
34
+ // console.log(`cmdStr: ${cmdStr}`)
35
+
36
+ // console.log(`Sending JSON RPC /about command to ${ipfsId}`)
37
+ const result = await this.sendRPC(ipfsId, cmdStr, id, thisNode)
38
+ // console.log('sendRPC result: ', result)
39
+
40
+ return result
41
+ } catch (err) {
42
+ console.error('Error in queryAbout()')
43
+
44
+ // Do not throw an error.
45
+ return false
46
+ }
47
+ }
48
+
49
+ // This function is called by pubsub.captureMetrics() when a response is
50
+ // recieved to an /about request. The data is used by sendRPC().
51
+ relayMetricsReceived (inData) {
52
+ this.incomingData = inData
53
+ }
54
+
55
+ // Send the RPC command to the service, wait a period of time for a response.
56
+ // Timeout if a response is not recieved.
57
+ async sendRPC (ipfsId, cmdStr, id, thisNode) {
58
+ try {
59
+ let retData = this.incomingData
60
+
61
+ // Send the RPC command to the server/service.
62
+ await thisNode.useCases.peer.sendPrivateMessage(ipfsId, cmdStr, thisNode)
63
+
64
+ // Used for calculating the timeout.
65
+ const start = new Date()
66
+ let now = start
67
+ let timeDiff = 0
68
+
69
+ // Wait for the response from the server. Exit once the response is
70
+ // recieved, or a timeout occurs.
71
+ do {
72
+ await thisNode.useCases.peer.adapters.bch.bchjs.Util.sleep(250)
73
+
74
+ now = new Date()
75
+
76
+ timeDiff = now.getTime() - start.getTime()
77
+ // console.log('timeDiff: ', timeDiff)
78
+
79
+ retData = this.incomingData
80
+
81
+ // If data came in on the event emitter, analize it.
82
+ if (retData) {
83
+ // console.log('retData: ', retData)
84
+
85
+ const jsonData = JSON.parse(retData)
86
+ const respId = jsonData.id
87
+
88
+ // If the JSON RPC ID matches, then it's the response thisNode was
89
+ // waiting for.
90
+ if (respId === id) {
91
+ // responseRecieved = true
92
+ // this.eventEmitter.removeListener('relayMetrics', cb)
93
+
94
+ retData = false
95
+
96
+ return true
97
+ }
98
+ }
99
+
100
+ // console.log('retData: ', retData)
101
+ } while (
102
+ // Exit once the RPC data comes back, or if a period of time passes.
103
+ timeDiff < this.waitPeriod
104
+ )
105
+
106
+ // this.eventEmitter.removeListener('relayMetrics', cb)
107
+ return false
108
+ } catch (err) {
109
+ console.error('Error in sendRPC')
110
+ // this.eventEmitter.removeListener('relayMetrics', cb)
111
+ throw err
112
+ }
113
+ }
114
+ }
115
+
116
+ // module.exports = AboutAdapter
117
+ export default AboutAdapter