helia-coord 1.6.0 → 1.7.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/examples/create-helia-node.js +2 -1
- package/examples/webrtc/README.md +5 -0
- package/examples/webrtc/node1/create-helia-node.js +159 -0
- package/examples/webrtc/node1/start-node.js +77 -0
- package/examples/webrtc/relay/create-helia-node.js +171 -0
- package/examples/webrtc/relay/start-node.js +71 -0
- package/lib/controllers/timer-controller.js +24 -1
- package/lib/use-cases/peer-use-cases.js +85 -3
- package/package.json +4 -1
- package/test/unit/use-cases/peer.unit.use-cases.js +79 -76
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# webRTC example
|
|
2
|
+
|
|
3
|
+
This directory contains example code that attempts to follow the [this libp2p webRTC README](https://github.com/libp2p/js-libp2p/tree/main/packages/transport-webrtc) in order to connect a two nodes running behind NATs, through a public Circuit Relay server.
|
|
4
|
+
|
|
5
|
+
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This library creates a Helia IPFS node. This is done prior to attaching
|
|
3
|
+
helia-coord to the node.
|
|
4
|
+
This library is called by start-node.js.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Global npm libraries
|
|
8
|
+
import { createHelia } from 'helia'
|
|
9
|
+
import fs from 'fs'
|
|
10
|
+
import { FsBlockstore } from 'blockstore-fs'
|
|
11
|
+
import { FsDatastore } from 'datastore-fs'
|
|
12
|
+
import { createLibp2p } from 'libp2p'
|
|
13
|
+
import { tcp } from '@libp2p/tcp'
|
|
14
|
+
import { noise } from '@chainsafe/libp2p-noise'
|
|
15
|
+
import { yamux } from '@chainsafe/libp2p-yamux'
|
|
16
|
+
// import { bootstrap } from '@libp2p/bootstrap'
|
|
17
|
+
// import { identifyService } from 'libp2p/identify'
|
|
18
|
+
import { identify } from '@libp2p/identify'
|
|
19
|
+
// import { circuitRelayTransport } from 'libp2p/circuit-relay'
|
|
20
|
+
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
|
|
21
|
+
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
|
|
22
|
+
import { webSockets } from '@libp2p/websockets'
|
|
23
|
+
import { publicIpv4 } from 'public-ip'
|
|
24
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
25
|
+
import { webRTC } from '@libp2p/webrtc'
|
|
26
|
+
import { ping } from '@libp2p/ping'
|
|
27
|
+
|
|
28
|
+
const ROOT_DIR = './'
|
|
29
|
+
const IPFS_DIR = './.ipfsdata/ipfs'
|
|
30
|
+
|
|
31
|
+
class CreateHeliaNode {
|
|
32
|
+
constructor () {
|
|
33
|
+
this.publicIp = publicIpv4
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Start an IPFS node.
|
|
37
|
+
async start () {
|
|
38
|
+
try {
|
|
39
|
+
// Ensure the directory structure exists that is needed by the IPFS node to store data.
|
|
40
|
+
this.ensureBlocksDir()
|
|
41
|
+
|
|
42
|
+
// Create an IPFS node
|
|
43
|
+
const ipfs = await this.createNode()
|
|
44
|
+
// console.log('ipfs: ', ipfs)
|
|
45
|
+
|
|
46
|
+
this.id = ipfs.libp2p.peerId.toString()
|
|
47
|
+
console.log('IPFS ID: ', this.id)
|
|
48
|
+
|
|
49
|
+
// Attempt to guess our ip4 IP address.
|
|
50
|
+
const ip4 = await this.publicIp()
|
|
51
|
+
let detectedMultiaddr = `/ip4/${ip4}/tcp/4001/p2p/${this.id}`
|
|
52
|
+
detectedMultiaddr = multiaddr(detectedMultiaddr)
|
|
53
|
+
|
|
54
|
+
// Get the multiaddrs for the node.
|
|
55
|
+
const multiaddrs = ipfs.libp2p.getMultiaddrs()
|
|
56
|
+
multiaddrs.push(detectedMultiaddr)
|
|
57
|
+
console.log('Multiaddrs: ', multiaddrs)
|
|
58
|
+
|
|
59
|
+
this.multiaddrs = multiaddrs
|
|
60
|
+
|
|
61
|
+
// Signal that this adapter is ready.
|
|
62
|
+
this.isReady = true
|
|
63
|
+
|
|
64
|
+
this.ipfs = ipfs
|
|
65
|
+
|
|
66
|
+
return this.ipfs
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error('Error in start()')
|
|
69
|
+
|
|
70
|
+
throw err
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// This function creates an IPFS node using Helia.
|
|
75
|
+
// It returns the node as an object.
|
|
76
|
+
async createNode () {
|
|
77
|
+
try {
|
|
78
|
+
// Create block and data stores.
|
|
79
|
+
const blockstore = new FsBlockstore(`${IPFS_DIR}/blockstore`)
|
|
80
|
+
const datastore = new FsDatastore(`${IPFS_DIR}/datastore`)
|
|
81
|
+
|
|
82
|
+
// Configure services
|
|
83
|
+
const services = {
|
|
84
|
+
identify: identify(),
|
|
85
|
+
pubsub: gossipsub({ allowPublishToZeroTopicPeers: true }),
|
|
86
|
+
ping: ping()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// libp2p is the networking layer that underpins Helia
|
|
90
|
+
const libp2p = await createLibp2p({
|
|
91
|
+
datastore,
|
|
92
|
+
addresses: {
|
|
93
|
+
listen: [
|
|
94
|
+
'/ip4/127.0.0.1/tcp/0',
|
|
95
|
+
'/ip4/0.0.0.0/tcp/4001',
|
|
96
|
+
'/ip4/0.0.0.0/tcp/4003/ws',
|
|
97
|
+
'/webrtc',
|
|
98
|
+
'/p2p-circuit'
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
transports: [
|
|
102
|
+
tcp(),
|
|
103
|
+
webSockets(),
|
|
104
|
+
circuitRelayTransport({ discoverRelays: 3 }),
|
|
105
|
+
webRTC()
|
|
106
|
+
],
|
|
107
|
+
connectionEncrypters: [
|
|
108
|
+
noise()
|
|
109
|
+
],
|
|
110
|
+
streamMuxers: [
|
|
111
|
+
yamux()
|
|
112
|
+
],
|
|
113
|
+
services
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
// create a Helia node
|
|
117
|
+
const helia = await createHelia({
|
|
118
|
+
blockstore,
|
|
119
|
+
datastore,
|
|
120
|
+
libp2p
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
return helia
|
|
124
|
+
} catch (err) {
|
|
125
|
+
console.error('Error creating Helia node: ', err)
|
|
126
|
+
|
|
127
|
+
throw err
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async stop () {
|
|
132
|
+
await this.ipfs.stop()
|
|
133
|
+
|
|
134
|
+
return true
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Ensure that the directories exist to store blocks from the IPFS network.
|
|
138
|
+
// This function is called at startup, before the IPFS node is started.
|
|
139
|
+
ensureBlocksDir () {
|
|
140
|
+
try {
|
|
141
|
+
!fs.existsSync(`${ROOT_DIR}.ipfsdata`) && fs.mkdirSync(`${ROOT_DIR}.ipfsdata`)
|
|
142
|
+
|
|
143
|
+
!fs.existsSync(`${IPFS_DIR}`) && fs.mkdirSync(`${IPFS_DIR}`)
|
|
144
|
+
|
|
145
|
+
!fs.existsSync(`${IPFS_DIR}/blockstore`) && fs.mkdirSync(`${IPFS_DIR}/blockstore`)
|
|
146
|
+
|
|
147
|
+
!fs.existsSync(`${IPFS_DIR}/datastore`) && fs.mkdirSync(`${IPFS_DIR}/datastore`)
|
|
148
|
+
|
|
149
|
+
// !fs.existsSync(`${IPFS_DIR}/datastore/peers`) && fs.mkdirSync(`${IPFS_DIR}/datastore/peers`)
|
|
150
|
+
|
|
151
|
+
return true
|
|
152
|
+
} catch (err) {
|
|
153
|
+
console.error('Error in ensureBlocksDir(): ', err)
|
|
154
|
+
throw err
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export default CreateHeliaNode
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
1. Starts node.
|
|
3
|
+
2. Waits to connect to Circuit Relay.
|
|
4
|
+
3. Connects to remote node.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Global npm libraries
|
|
8
|
+
import SlpWallet from 'minimal-slp-wallet'
|
|
9
|
+
import { WebRTC } from '@multiformats/multiaddr-matcher'
|
|
10
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
11
|
+
import delay from 'delay'
|
|
12
|
+
|
|
13
|
+
// Local libraries
|
|
14
|
+
// import IpfsCoord from '../index.js'
|
|
15
|
+
import CreateHeliaNode from './create-helia-node.js'
|
|
16
|
+
|
|
17
|
+
const relayMA = '/ip4/5.78.70.29/tcp/4001/p2p/12D3KooWNbQrdvEpzKuZ6rxkAF9vBH56HeGJ9drmrF9bhBJBa2Nq'
|
|
18
|
+
// const remoteMa = '12D3KooWDaKkuwzCNEWUEfjYSh7SCjqpEdx7PW4pAD5P5CFZQmqW'
|
|
19
|
+
|
|
20
|
+
async function start () {
|
|
21
|
+
try {
|
|
22
|
+
// Create an instance of bch-js and IPFS.
|
|
23
|
+
const wallet = new SlpWallet()
|
|
24
|
+
await wallet.walletInfoPromise
|
|
25
|
+
|
|
26
|
+
const createHeliaNode = new CreateHeliaNode()
|
|
27
|
+
const thisNode = await createHeliaNode.start()
|
|
28
|
+
|
|
29
|
+
const relayMultiaddr = multiaddr(relayMA)
|
|
30
|
+
console.log('Relay multiaddr: ', relayMultiaddr)
|
|
31
|
+
await thisNode.libp2p.dial(relayMultiaddr, {
|
|
32
|
+
signal: AbortSignal.timeout(10000)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
console.log('Connected to relay.')
|
|
36
|
+
|
|
37
|
+
let webRTCMultiaddr
|
|
38
|
+
|
|
39
|
+
// wait for the listener to make a reservation on the relay
|
|
40
|
+
while (true) {
|
|
41
|
+
webRTCMultiaddr = thisNode.libp2p.getMultiaddrs().find(ma => WebRTC.matches(ma))
|
|
42
|
+
console.log('WebRTC multiaddr: ', webRTCMultiaddr)
|
|
43
|
+
const allAddrs = thisNode.libp2p.getMultiaddrs()
|
|
44
|
+
console.log('All multiaddrs: ', allAddrs)
|
|
45
|
+
|
|
46
|
+
// const mas = thisNode.libp2p.getMultiaddrs()
|
|
47
|
+
// console.log('Multiaddrs: ', mas)
|
|
48
|
+
|
|
49
|
+
if (webRTCMultiaddr != null) {
|
|
50
|
+
break
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// try again later
|
|
54
|
+
const now = new Date()
|
|
55
|
+
console.log('Waiting for reservation...', now.toISOString())
|
|
56
|
+
await delay(1000)
|
|
57
|
+
}
|
|
58
|
+
console.log('WebRTC multiaddr: ', webRTCMultiaddr)
|
|
59
|
+
|
|
60
|
+
// Pass bch-js and IPFS to ipfs-coord when instantiating it.
|
|
61
|
+
// const ipfsCoord = new IpfsCoord({
|
|
62
|
+
// ipfs,
|
|
63
|
+
// wallet,
|
|
64
|
+
// type: 'node.js',
|
|
65
|
+
// // type: 'browser'
|
|
66
|
+
// nodeType: 'external',
|
|
67
|
+
// debugLevel: 2
|
|
68
|
+
// })
|
|
69
|
+
|
|
70
|
+
// await ipfsCoord.start()
|
|
71
|
+
// console.log('IPFS and the coordination library is ready.')
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error('Error in start(): ', err)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
start()
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This library creates a Helia IPFS node. This is done prior to attaching
|
|
3
|
+
helia-coord to the node.
|
|
4
|
+
This library is called by start-node.js.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Global npm libraries
|
|
8
|
+
import { createHelia } from 'helia'
|
|
9
|
+
import fs from 'fs'
|
|
10
|
+
import { FsBlockstore } from 'blockstore-fs'
|
|
11
|
+
import { FsDatastore } from 'datastore-fs'
|
|
12
|
+
import { createLibp2p } from 'libp2p'
|
|
13
|
+
import { tcp } from '@libp2p/tcp'
|
|
14
|
+
import { noise } from '@chainsafe/libp2p-noise'
|
|
15
|
+
import { yamux } from '@chainsafe/libp2p-yamux'
|
|
16
|
+
// import { bootstrap } from '@libp2p/bootstrap'
|
|
17
|
+
// import { identifyService } from 'libp2p/identify'
|
|
18
|
+
import { identify } from '@libp2p/identify'
|
|
19
|
+
// import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
|
|
20
|
+
import { circuitRelayServer, circuitRelayTransport } from '@libp2p/circuit-relay-v2'
|
|
21
|
+
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
|
|
22
|
+
import { webSockets } from '@libp2p/websockets'
|
|
23
|
+
import { publicIpv4 } from 'public-ip'
|
|
24
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
25
|
+
import { webRTC } from '@libp2p/webrtc'
|
|
26
|
+
import { ping } from '@libp2p/ping'
|
|
27
|
+
|
|
28
|
+
const ROOT_DIR = './'
|
|
29
|
+
const IPFS_DIR = './.ipfsdata/ipfs'
|
|
30
|
+
|
|
31
|
+
class CreateHeliaNode {
|
|
32
|
+
constructor () {
|
|
33
|
+
this.publicIp = publicIpv4
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Start an IPFS node.
|
|
37
|
+
async start () {
|
|
38
|
+
try {
|
|
39
|
+
// Ensure the directory structure exists that is needed by the IPFS node to store data.
|
|
40
|
+
this.ensureBlocksDir()
|
|
41
|
+
|
|
42
|
+
// Create an IPFS node
|
|
43
|
+
const ipfs = await this.createNode()
|
|
44
|
+
// console.log('ipfs: ', ipfs)
|
|
45
|
+
|
|
46
|
+
this.id = ipfs.libp2p.peerId.toString()
|
|
47
|
+
console.log('IPFS ID: ', this.id)
|
|
48
|
+
|
|
49
|
+
// Attempt to guess our ip4 IP address.
|
|
50
|
+
const ip4 = await this.publicIp()
|
|
51
|
+
let detectedMultiaddr = `/ip4/${ip4}/tcp/4001/p2p/${this.id}`
|
|
52
|
+
detectedMultiaddr = multiaddr(detectedMultiaddr)
|
|
53
|
+
|
|
54
|
+
// Get the multiaddrs for the node.
|
|
55
|
+
const multiaddrs = ipfs.libp2p.getMultiaddrs()
|
|
56
|
+
multiaddrs.push(detectedMultiaddr)
|
|
57
|
+
console.log('Multiaddrs: ', multiaddrs)
|
|
58
|
+
|
|
59
|
+
this.multiaddrs = multiaddrs
|
|
60
|
+
|
|
61
|
+
// Signal that this adapter is ready.
|
|
62
|
+
this.isReady = true
|
|
63
|
+
|
|
64
|
+
this.ipfs = ipfs
|
|
65
|
+
|
|
66
|
+
return this.ipfs
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error('Error in start()')
|
|
69
|
+
|
|
70
|
+
throw err
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// This function creates an IPFS node using Helia.
|
|
75
|
+
// It returns the node as an object.
|
|
76
|
+
async createNode () {
|
|
77
|
+
try {
|
|
78
|
+
// Create block and data stores.
|
|
79
|
+
const blockstore = new FsBlockstore(`${IPFS_DIR}/blockstore`)
|
|
80
|
+
const datastore = new FsDatastore(`${IPFS_DIR}/datastore`)
|
|
81
|
+
|
|
82
|
+
// Configure services
|
|
83
|
+
const services = {
|
|
84
|
+
identify: identify(),
|
|
85
|
+
pubsub: gossipsub({ allowPublishToZeroTopicPeers: true }),
|
|
86
|
+
ping: ping(),
|
|
87
|
+
relay: circuitRelayServer({ // makes the node function as a relay server
|
|
88
|
+
hopTimeout: 30 * 1000, // incoming relay requests must be resolved within this time limit
|
|
89
|
+
advertise: true,
|
|
90
|
+
reservations: {
|
|
91
|
+
maxReservations: 15, // how many peers are allowed to reserve relay slots on this server
|
|
92
|
+
reservationClearInterval: 300 * 1000, // how often to reclaim stale reservations
|
|
93
|
+
applyDefaultLimit: true, // whether to apply default data/duration limits to each relayed connection
|
|
94
|
+
defaultDurationLimit: 2 * 60 * 1000, // the default maximum amount of time a relayed connection can be open for
|
|
95
|
+
defaultDataLimit: BigInt(2 << 7), // the default maximum number of bytes that can be transferred over a relayed connection
|
|
96
|
+
maxInboundHopStreams: 32, // how many inbound HOP streams are allow simultaneously
|
|
97
|
+
maxOutboundHopStreams: 64 // how many outbound HOP streams are allow simultaneously
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// libp2p is the networking layer that underpins Helia
|
|
103
|
+
const libp2p = await createLibp2p({
|
|
104
|
+
datastore,
|
|
105
|
+
addresses: {
|
|
106
|
+
listen: [
|
|
107
|
+
'/ip4/127.0.0.1/tcp/0',
|
|
108
|
+
'/ip4/0.0.0.0/tcp/4001',
|
|
109
|
+
'/ip4/0.0.0.0/tcp/4003/ws',
|
|
110
|
+
'/webrtc'
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
transports: [
|
|
114
|
+
tcp(),
|
|
115
|
+
webSockets(),
|
|
116
|
+
circuitRelayTransport({ discoverRelays: 3 }),
|
|
117
|
+
webRTC()
|
|
118
|
+
],
|
|
119
|
+
connectionEncrypters: [
|
|
120
|
+
noise()
|
|
121
|
+
],
|
|
122
|
+
streamMuxers: [
|
|
123
|
+
yamux()
|
|
124
|
+
],
|
|
125
|
+
services
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
// create a Helia node
|
|
129
|
+
const helia = await createHelia({
|
|
130
|
+
blockstore,
|
|
131
|
+
datastore,
|
|
132
|
+
libp2p
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return helia
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.error('Error creating Helia node: ', err)
|
|
138
|
+
|
|
139
|
+
throw err
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async stop () {
|
|
144
|
+
await this.ipfs.stop()
|
|
145
|
+
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Ensure that the directories exist to store blocks from the IPFS network.
|
|
150
|
+
// This function is called at startup, before the IPFS node is started.
|
|
151
|
+
ensureBlocksDir () {
|
|
152
|
+
try {
|
|
153
|
+
!fs.existsSync(`${ROOT_DIR}.ipfsdata`) && fs.mkdirSync(`${ROOT_DIR}.ipfsdata`)
|
|
154
|
+
|
|
155
|
+
!fs.existsSync(`${IPFS_DIR}`) && fs.mkdirSync(`${IPFS_DIR}`)
|
|
156
|
+
|
|
157
|
+
!fs.existsSync(`${IPFS_DIR}/blockstore`) && fs.mkdirSync(`${IPFS_DIR}/blockstore`)
|
|
158
|
+
|
|
159
|
+
!fs.existsSync(`${IPFS_DIR}/datastore`) && fs.mkdirSync(`${IPFS_DIR}/datastore`)
|
|
160
|
+
|
|
161
|
+
// !fs.existsSync(`${IPFS_DIR}/datastore/peers`) && fs.mkdirSync(`${IPFS_DIR}/datastore/peers`)
|
|
162
|
+
|
|
163
|
+
return true
|
|
164
|
+
} catch (err) {
|
|
165
|
+
console.error('Error in ensureBlocksDir(): ', err)
|
|
166
|
+
throw err
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export default CreateHeliaNode
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/*
|
|
2
|
+
1. Starts node.
|
|
3
|
+
2. Waits to connect to Circuit Relay.
|
|
4
|
+
3. Connects to remote node.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Global npm libraries
|
|
8
|
+
import SlpWallet from 'minimal-slp-wallet'
|
|
9
|
+
import { WebRTC } from '@multiformats/multiaddr-matcher'
|
|
10
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
11
|
+
import delay from 'delay'
|
|
12
|
+
|
|
13
|
+
// Local libraries
|
|
14
|
+
// import IpfsCoord from '../index.js'
|
|
15
|
+
import CreateHeliaNode from './create-helia-node.js'
|
|
16
|
+
|
|
17
|
+
const relayMA = '/ip4/5.78.70.29/tcp/4001/p2p/12D3KooWNbQrdvEpzKuZ6rxkAF9vBH56HeGJ9drmrF9bhBJBa2Nq'
|
|
18
|
+
// const remoteMa = '12D3KooWDaKkuwzCNEWUEfjYSh7SCjqpEdx7PW4pAD5P5CFZQmqW'
|
|
19
|
+
|
|
20
|
+
async function start () {
|
|
21
|
+
try {
|
|
22
|
+
// Create an instance of bch-js and IPFS.
|
|
23
|
+
const wallet = new SlpWallet()
|
|
24
|
+
await wallet.walletInfoPromise
|
|
25
|
+
|
|
26
|
+
const createHeliaNode = new CreateHeliaNode()
|
|
27
|
+
const thisNode = await createHeliaNode.start()
|
|
28
|
+
|
|
29
|
+
await thisNode.libp2p.dial(multiaddr(relayMA), {
|
|
30
|
+
signal: AbortSignal.timeout(10000)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
console.log('Connected to relay.')
|
|
34
|
+
|
|
35
|
+
let webRTCMultiaddr
|
|
36
|
+
|
|
37
|
+
// wait for the listener to make a reservation on the relay
|
|
38
|
+
while (true) {
|
|
39
|
+
webRTCMultiaddr = thisNode.libp2p.getMultiaddrs().find(ma => WebRTC.matches(ma))
|
|
40
|
+
// const mas = thisNode.libp2p.getMultiaddrs()
|
|
41
|
+
// console.log('Multiaddrs: ', mas)
|
|
42
|
+
|
|
43
|
+
if (webRTCMultiaddr != null) {
|
|
44
|
+
break
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// try again later
|
|
48
|
+
const now = new Date()
|
|
49
|
+
console.log('Waiting for reservation...', now.toISOString())
|
|
50
|
+
await delay(1000)
|
|
51
|
+
}
|
|
52
|
+
console.log('WebRTC multiaddr: ', webRTCMultiaddr)
|
|
53
|
+
|
|
54
|
+
// Pass bch-js and IPFS to ipfs-coord when instantiating it.
|
|
55
|
+
// const ipfsCoord = new IpfsCoord({
|
|
56
|
+
// ipfs,
|
|
57
|
+
// wallet,
|
|
58
|
+
// type: 'node.js',
|
|
59
|
+
// // type: 'browser'
|
|
60
|
+
// nodeType: 'external',
|
|
61
|
+
// debugLevel: 2
|
|
62
|
+
// })
|
|
63
|
+
|
|
64
|
+
// await ipfsCoord.start()
|
|
65
|
+
// console.log('IPFS and the coordination library is ready.')
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error('Error in start(): ', err)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
start()
|
|
@@ -48,6 +48,7 @@ class TimerControllers {
|
|
|
48
48
|
this.relaySearchInterval = 63000 * 2
|
|
49
49
|
this.checkBlacklistInterval = 64000 * 2
|
|
50
50
|
this.listPubsubChannelsInterval = 65000 * 2
|
|
51
|
+
this.getWebRtcMultiaddrInterval = 66000 * 2
|
|
51
52
|
|
|
52
53
|
// Bind 'this' object to all subfunctions
|
|
53
54
|
this.startTimers = this.startTimers.bind(this)
|
|
@@ -58,6 +59,7 @@ class TimerControllers {
|
|
|
58
59
|
this.managePeers = this.managePeers.bind(this)
|
|
59
60
|
this.blacklist = this.blacklist.bind(this)
|
|
60
61
|
this.searchForRelays = this.searchForRelays.bind(this)
|
|
62
|
+
this.getWebRtcMultiaddr = this.getWebRtcMultiaddr.bind(this)
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
startTimers (thisNode) {
|
|
@@ -89,6 +91,10 @@ class TimerControllers {
|
|
|
89
91
|
await _this.listPubsubChannels()
|
|
90
92
|
}, this.listPubsubChannelsInterval)
|
|
91
93
|
|
|
94
|
+
this.getWebRtcMultiaddrHandle = setInterval(async function () {
|
|
95
|
+
await _this.getWebRtcMultiaddr(thisNode, useCases)
|
|
96
|
+
}, this.getWebRtcMultiaddrInterval)
|
|
97
|
+
|
|
92
98
|
// DEBUG: report the state of thisNode.
|
|
93
99
|
// setInterval(function () {
|
|
94
100
|
// const tempThisNode = clonedeep(thisNode)
|
|
@@ -114,7 +120,8 @@ class TimerControllers {
|
|
|
114
120
|
peerTimerHandle: this.peerTimerHandle,
|
|
115
121
|
relaySearchHandle: this.relaySearchHandle,
|
|
116
122
|
checkBlacklistHandle: this.checkBlacklistHandle,
|
|
117
|
-
listPubsubChannelsHandle: this.listPubsubChannelsHandle
|
|
123
|
+
listPubsubChannelsHandle: this.listPubsubChannelsHandle,
|
|
124
|
+
getWebRtcMultiaddrHandle: this.getWebRtcMultiaddrHandle
|
|
118
125
|
}
|
|
119
126
|
}
|
|
120
127
|
|
|
@@ -126,6 +133,7 @@ class TimerControllers {
|
|
|
126
133
|
clearInterval(this.relaySearchHandle)
|
|
127
134
|
clearInterval(this.checkBlacklistHandle)
|
|
128
135
|
clearInterval(this.listPubsubChannelsHandle)
|
|
136
|
+
clearInterval(this.getWebRtcMultiaddrHandle)
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
async listPubsubChannels () {
|
|
@@ -405,6 +413,21 @@ class TimerControllers {
|
|
|
405
413
|
return false
|
|
406
414
|
}
|
|
407
415
|
}
|
|
416
|
+
|
|
417
|
+
// Extract any webRTC multiaddrs from the node's list of multiaddrs.
|
|
418
|
+
// Add them to the announcement object.
|
|
419
|
+
getWebRtcMultiaddr (thisNode, useCases) {
|
|
420
|
+
try {
|
|
421
|
+
console.log('---->Entering getWebRtcMultiaddr() Timer Controller.<----')
|
|
422
|
+
|
|
423
|
+
useCases.peer.getWebRtcMultiaddr({ thisNode })
|
|
424
|
+
} catch (err) {
|
|
425
|
+
console.error('Error in timer-controller.js/getWebRtcMultiaddr(): ', err)
|
|
426
|
+
|
|
427
|
+
// Note: Do not throw an error. This is a top-level function.
|
|
428
|
+
return false
|
|
429
|
+
}
|
|
430
|
+
}
|
|
408
431
|
}
|
|
409
432
|
|
|
410
433
|
export default TimerControllers
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Global npm libraries
|
|
6
6
|
import { multiaddr } from '@multiformats/multiaddr'
|
|
7
7
|
import globalConfig from '../../config/global-config.js'
|
|
8
|
+
import { WebRTC } from '@multiformats/multiaddr-matcher'
|
|
8
9
|
|
|
9
10
|
// Local libraries
|
|
10
11
|
import Util from '../util/utils.js'
|
|
@@ -32,7 +33,6 @@ class PeerUseCases {
|
|
|
32
33
|
|
|
33
34
|
// Bind 'this' object to all subfunctions.
|
|
34
35
|
this.updateThisNode = this.updateThisNode.bind(this)
|
|
35
|
-
this.updateThisNode = this.updateThisNode.bind(this)
|
|
36
36
|
this.connectToPeer = this.connectToPeer.bind(this)
|
|
37
37
|
this.sendPrivateMessage = this.sendPrivateMessage.bind(this)
|
|
38
38
|
this.addSubnetPeer = this.addSubnetPeer.bind(this)
|
|
@@ -41,6 +41,7 @@ class PeerUseCases {
|
|
|
41
41
|
this.queryAbout = this.queryAbout.bind(this)
|
|
42
42
|
this.sendRPC = this.sendRPC.bind(this)
|
|
43
43
|
this.relayMetricsHandler = this.relayMetricsHandler.bind(this)
|
|
44
|
+
this.getWebRtcMultiaddr = this.getWebRtcMultiaddr.bind(this)
|
|
44
45
|
|
|
45
46
|
// Inject the relayMetricsHandler function into the pubsub adapter.
|
|
46
47
|
this.adapters.pubsub.injectMetricsHandler(this.relayMetricsHandler)
|
|
@@ -315,7 +316,7 @@ class PeerUseCases {
|
|
|
315
316
|
// console.log('this.thisNode: ', this.thisNode)
|
|
316
317
|
|
|
317
318
|
// const relays = this.cr.state.relays
|
|
318
|
-
const relays = this.thisNode.relayData
|
|
319
|
+
// const relays = this.thisNode.relayData
|
|
319
320
|
const peers = this.thisNode.peerList
|
|
320
321
|
// console.log('peers: ', peers)
|
|
321
322
|
|
|
@@ -387,7 +388,7 @@ class PeerUseCases {
|
|
|
387
388
|
for (let j = 0; j < filteredMultiaddrs.length; j++) {
|
|
388
389
|
const multiaddr = filteredMultiaddrs[j]
|
|
389
390
|
this.adapters.log.statusLog(1,
|
|
390
|
-
`Trying a direct
|
|
391
|
+
`Trying a direct connection to peer ${thisPeer} with this multiaddr: ${multiaddr}.`
|
|
391
392
|
)
|
|
392
393
|
|
|
393
394
|
// Attempt to connect to the node through a circuit relay.
|
|
@@ -426,6 +427,49 @@ class PeerUseCases {
|
|
|
426
427
|
|
|
427
428
|
// Skip this section if the peer has a preference for direct connection.
|
|
428
429
|
if (connectPref !== 'direct') {
|
|
430
|
+
// Retrieve the webRTC multiaddrs from the peers announcement object.
|
|
431
|
+
const filteredMultiaddrs = peerData.data.ipfsMultiaddrs.filter(x => x.includes('/p2p-circuit/webrtc'))
|
|
432
|
+
this.adapters.log.statusLog(1, 'webRTC filteredMultiaddrs: ', filteredMultiaddrs)
|
|
433
|
+
|
|
434
|
+
// If the peer has no webRTC multiaddrs, then skip this peer
|
|
435
|
+
if (filteredMultiaddrs.length === 0) {
|
|
436
|
+
this.adapters.log.statusLog(1, `Peer ${thisPeer} has no webRTC multiaddrs. Skipping.`)
|
|
437
|
+
continue
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Loop through each webRTC multiaddr and attempt to connect to the peer.
|
|
441
|
+
for (let j = 0; j < filteredMultiaddrs.length; j++) {
|
|
442
|
+
const multiaddr = filteredMultiaddrs[j]
|
|
443
|
+
this.adapters.log.statusLog(1, `Trying to connect to peer ${thisPeer} through webRTC multiaddr: ${multiaddr}.`)
|
|
444
|
+
|
|
445
|
+
connected = await this.adapters.ipfs.connectToPeer({ multiaddr })
|
|
446
|
+
|
|
447
|
+
// If the connection was successful, break out of the relay loop.
|
|
448
|
+
// Otherwise try to connect through the next relay.
|
|
449
|
+
if (connected.success) {
|
|
450
|
+
this.adapters.log.statusLog(1,
|
|
451
|
+
`Successfully connected to peer ${thisPeer} through CR connection: ${multiaddr}.`
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
// Add the connection multiaddr for this peer to the thisNode object.
|
|
455
|
+
this.updatePeerConnectionInfo({ thisPeer })
|
|
456
|
+
|
|
457
|
+
// Add the connection multiaddr to the peer, so that we can see
|
|
458
|
+
// exactly how we're connected to the peer.
|
|
459
|
+
const thisPeerData = this.thisNode.peerData.filter(x => x.from === thisPeer)
|
|
460
|
+
thisPeerData[0].data.connectionAddr = multiaddr
|
|
461
|
+
peerData.data.connectionAddr = multiaddr
|
|
462
|
+
|
|
463
|
+
// Break out of the loop once we've made a successful connection.
|
|
464
|
+
break
|
|
465
|
+
} else {
|
|
466
|
+
this.adapters.log.statusLog(1,
|
|
467
|
+
`Failed to connect to peer ${thisPeer} through CR connection: ${multiaddr}. Reason: ${connected.details}`
|
|
468
|
+
)
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/*
|
|
429
473
|
// Sort the Circuit Relays by the average of the aboutLatency
|
|
430
474
|
// array. Connect to peers through the Relays with the lowest latencies
|
|
431
475
|
// first.
|
|
@@ -483,6 +527,7 @@ class PeerUseCases {
|
|
|
483
527
|
}
|
|
484
528
|
}
|
|
485
529
|
}
|
|
530
|
+
*/
|
|
486
531
|
}
|
|
487
532
|
|
|
488
533
|
if (connected.success) {
|
|
@@ -636,6 +681,43 @@ class PeerUseCases {
|
|
|
636
681
|
relayMetricsHandler (inData) {
|
|
637
682
|
this.incomingData = inData
|
|
638
683
|
}
|
|
684
|
+
|
|
685
|
+
// Extract any webRTC multiaddrs from the node's list of multiaddrs.
|
|
686
|
+
// Add them to the announcement object.
|
|
687
|
+
getWebRtcMultiaddr (inObj = {}) {
|
|
688
|
+
try {
|
|
689
|
+
console.log('---->Entering getWebRtcMultiaddr() Use Case.<----')
|
|
690
|
+
|
|
691
|
+
const { thisNode } = inObj
|
|
692
|
+
|
|
693
|
+
// Get multiaddrs that can be used to connect to this node.
|
|
694
|
+
const addrs = this.adapters.ipfs.ipfs.libp2p.getMultiaddrs()
|
|
695
|
+
|
|
696
|
+
const webRtcAddrs = addrs.filter(x => WebRTC.matches(x))
|
|
697
|
+
console.log('webRTC addrs: ', webRtcAddrs)
|
|
698
|
+
|
|
699
|
+
// If there are any webRTC multiaddrs, add them to the announcement object.
|
|
700
|
+
if (webRtcAddrs.length) {
|
|
701
|
+
// Remove any previous webRTC multiaddrs from the announcement object.
|
|
702
|
+
const existingMultiaddrs = thisNode.ipfsMultiaddrs
|
|
703
|
+
const noRtcAddrs = existingMultiaddrs.filter(x => !x.includes('/p2p-circuit/webrtc'))
|
|
704
|
+
|
|
705
|
+
// Add the new webRTC multiaddrs to the announcement object.
|
|
706
|
+
webRtcAddrs.forEach(x => {
|
|
707
|
+
noRtcAddrs.push(x.toString())
|
|
708
|
+
})
|
|
709
|
+
|
|
710
|
+
// Add the new webRTC multiaddrs to the announcement object.
|
|
711
|
+
thisNode.ipfsMultiaddrs = noRtcAddrs
|
|
712
|
+
console.log(`Updated thisNode.ipfsMultiaddrs: ${JSON.stringify(thisNode.ipfsMultiaddrs, null, 2)}`)
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// return webRtcAddrs
|
|
716
|
+
} catch (err) {
|
|
717
|
+
console.error('Error in peer-use-cases.js/getWebRtcMultiaddr(): ', err)
|
|
718
|
+
return false
|
|
719
|
+
}
|
|
720
|
+
}
|
|
639
721
|
}
|
|
640
722
|
|
|
641
723
|
export default PeerUseCases
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helia-coord",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.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",
|
|
@@ -26,14 +26,17 @@
|
|
|
26
26
|
"@istanbuljs/esm-loader-hook": "0.2.0",
|
|
27
27
|
"@libp2p/circuit-relay-v2": "3.1.11",
|
|
28
28
|
"@libp2p/identify": "3.0.18",
|
|
29
|
+
"@libp2p/ping": "2.0.18",
|
|
29
30
|
"@libp2p/tcp": "10.0.18",
|
|
30
31
|
"@libp2p/webrtc": "4.1.6",
|
|
31
32
|
"@libp2p/websockets": "9.1.5",
|
|
32
33
|
"@multiformats/multiaddr": "12.3.5",
|
|
34
|
+
"@multiformats/multiaddr-matcher": "1.6.0",
|
|
33
35
|
"blockstore-fs": "2.0.2",
|
|
34
36
|
"chai": "4.3.6",
|
|
35
37
|
"cross-env": "7.0.3",
|
|
36
38
|
"datastore-fs": "10.0.2",
|
|
39
|
+
"delay": "6.0.0",
|
|
37
40
|
"helia": "5.2.0",
|
|
38
41
|
"lodash.clonedeep": "4.5.0",
|
|
39
42
|
"minimal-slp-wallet": "5.12.0",
|
|
@@ -434,31 +434,32 @@ describe('#Use-Cases-Peer', () => {
|
|
|
434
434
|
assert.equal(result, true)
|
|
435
435
|
})
|
|
436
436
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
437
|
+
// 2/16/25 CT: Commented out to try new webRTC connection logic.
|
|
438
|
+
// it('should refresh a connection', async () => {
|
|
439
|
+
// // await uut.createSelf({ type: 'node.js' })
|
|
440
|
+
// // Add a peer that is not in the list of connected peers.
|
|
441
|
+
// const ipfsId = 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsje'
|
|
442
|
+
// uut.thisNode.peerList = [ipfsId]
|
|
443
|
+
// uut.thisNode.peerData = [{ from: ipfsId, data: {} }]
|
|
443
444
|
|
|
444
|
-
|
|
445
|
-
|
|
445
|
+
// // Add a peer
|
|
446
|
+
// await uut.addSubnetPeer(mockData.announceObj)
|
|
446
447
|
|
|
447
|
-
|
|
448
|
-
|
|
448
|
+
// // Force circuit relay to be used.
|
|
449
|
+
// uut.thisNode.relayData = mockData.mockRelayData
|
|
449
450
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
451
|
+
// // Mock dependencies
|
|
452
|
+
// sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.swarmPeers)
|
|
453
|
+
// sandbox.stub(uut.adapters.ipfs, 'connectToPeer').resolves(true)
|
|
454
|
+
// sandbox.stub(uut, 'isFreshPeer').returns(true)
|
|
455
|
+
// sandbox.stub(uut.utils, 'filterMultiaddrs').returns([])
|
|
456
|
+
// sandbox.stub(uut.relayUseCases, 'sortRelays').returns(mockData.mockRelayData)
|
|
456
457
|
|
|
457
|
-
|
|
458
|
-
|
|
458
|
+
// // Connect to that peer.
|
|
459
|
+
// const result = await uut.refreshPeerConnections()
|
|
459
460
|
|
|
460
|
-
|
|
461
|
-
})
|
|
461
|
+
// assert.equal(result, true)
|
|
462
|
+
// })
|
|
462
463
|
|
|
463
464
|
it('should connect directly to circuit relays advertised IP and port', async () => {
|
|
464
465
|
// Add a circuit relay peer with advertised IP and port.
|
|
@@ -520,62 +521,64 @@ describe('#Use-Cases-Peer', () => {
|
|
|
520
521
|
assert.equal(result, true)
|
|
521
522
|
})
|
|
522
523
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
524
|
+
// 2/16/25 CT: Commented out to try new webRTC connection logic.
|
|
525
|
+
// it('should report connection errors when connecting directly to IPFS peers multiaddr', async () => {
|
|
526
|
+
// // Add a circuit relay peer with advertised IP and port.
|
|
527
|
+
// const ipfsId = 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsje'
|
|
528
|
+
// uut.thisNode.peerList = [ipfsId]
|
|
529
|
+
// uut.thisNode.peerData = [{ from: ipfsId, data: {} }]
|
|
530
|
+
|
|
531
|
+
// // Add a peer
|
|
532
|
+
// await uut.addSubnetPeer(mockData.announceObj)
|
|
533
|
+
|
|
534
|
+
// // Force circuit relay to be used.
|
|
535
|
+
// uut.thisNode.relayData = mockData.mockRelayData
|
|
536
|
+
|
|
537
|
+
// // Mock dependencies
|
|
538
|
+
// sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.swarmPeers)
|
|
539
|
+
// sandbox.stub(uut, 'isFreshPeer').returns(true)
|
|
540
|
+
// sandbox.stub(uut.adapters.ipfs, 'connectToPeer')
|
|
541
|
+
// .onCall(0).resolves({ success: false })
|
|
542
|
+
// .onCall(1).resolves({ sucdess: true })
|
|
543
|
+
// sandbox.stub(uut.utils, 'filterMultiaddrs').returns(['/ip4/123.45.6.7/p2p/ipfs-id'])
|
|
544
|
+
// sandbox.stub(uut.relayUseCases, 'sortRelays').returns(mockData.mockRelayData)
|
|
545
|
+
|
|
546
|
+
// // Connect to that peer.
|
|
547
|
+
// const result = await uut.refreshPeerConnections()
|
|
548
|
+
|
|
549
|
+
// assert.equal(result, true)
|
|
550
|
+
// })
|
|
551
|
+
|
|
552
|
+
// 2/16/25 CT: Commented out to try new webRTC connection logic.
|
|
553
|
+
// it('should connect through v2 Circuit Relay', async () => {
|
|
554
|
+
// // Add a circuit relay peer with advertised IP and port.
|
|
555
|
+
// const ipfsId = 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsje'
|
|
556
|
+
// uut.thisNode.peerList = [ipfsId]
|
|
557
|
+
// uut.thisNode.peerData = [{ from: ipfsId, data: {} }]
|
|
558
|
+
|
|
559
|
+
// // Add a peer
|
|
560
|
+
// await uut.addSubnetPeer(mockData.announceObj)
|
|
561
|
+
|
|
562
|
+
// // Force circuit relay to be used.
|
|
563
|
+
// uut.thisNode.relayData = mockData.mockRelayData
|
|
564
|
+
|
|
565
|
+
// // Mock dependencies
|
|
566
|
+
// sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.swarmPeers)
|
|
567
|
+
// sandbox.stub(uut, 'isFreshPeer').returns(true)
|
|
568
|
+
// sandbox.stub(uut.adapters.ipfs, 'connectToPeer')
|
|
569
|
+
// .onCall(0).resolves({ success: true })
|
|
570
|
+
// sandbox.stub(uut.utils, 'filterMultiaddrs').returns([])
|
|
571
|
+
// sandbox.stub(uut.relayUseCases, 'sortRelays').returns([{
|
|
572
|
+
// multiaddr: '/ip4/123.45.6.7/p2p/ipfs-id',
|
|
573
|
+
// connected: true
|
|
574
|
+
// }])
|
|
575
|
+
// sandbox.stub(uut, 'updatePeerConnectionInfo').returns()
|
|
576
|
+
|
|
577
|
+
// // Connect to that peer.
|
|
578
|
+
// const result = await uut.refreshPeerConnections()
|
|
579
|
+
|
|
580
|
+
// assert.equal(result, true)
|
|
581
|
+
// })
|
|
579
582
|
|
|
580
583
|
it('should skip if peer is stale', async () => {
|
|
581
584
|
// Add a peer that is not in the list of connected peers.
|