/* eslint no-console: ["off"] */ 'use strict' const IPFS = require('ipfs') const assert = require('assert').strict const { generate: writeKey } = require('libp2p/src/pnet') const path = require('path') const fs = require('fs') const privateLibp2pBundle = require('./libp2p-bundle') const { mkdirp } = require('./utils') // Create two separate repo paths so we can run two nodes and check their output const repo1 = path.resolve('./tmp', 'repo1', '.ipfs') const repo2 = path.resolve('./tmp', 'repo2', '.ipfs') mkdirp(repo1) mkdirp(repo2) // Create a buffer and write the swarm key to it const swarmKey = Buffer.alloc(95) writeKey(swarmKey) // This key is for the `TASK` mentioned in the writeFileSync calls below const otherSwarmKey = Buffer.alloc(95) writeKey(otherSwarmKey) // Add the swarm key to both repos const swarmKey1Path = path.resolve(repo1, 'swarm.key') const swarmKey2Path = path.resolve(repo2, 'swarm.key') fs.writeFileSync(swarmKey1Path, swarmKey) // TASK: switch the commented out line below so we're using a different key, to see the nodes fail to connect fs.writeFileSync(swarmKey2Path, swarmKey) // fs.writeFileSync(swarmKey2Path, otherSwarmKey) // Create the first ipfs node const node1 = new IPFS({ repo: repo1, libp2p: privateLibp2pBundle(swarmKey1Path), config: { Addresses: { // Set the swarm address so we dont get port collision on the nodes Swarm: ['/ip4/0.0.0.0/tcp/9101'] } } }) // Create the second ipfs node const node2 = new IPFS({ repo: repo2, libp2p: privateLibp2pBundle(swarmKey2Path), config: { Addresses: { // Set the swarm address so we dont get port collision on the nodes Swarm: ['/ip4/0.0.0.0/tcp/9102'] } } }) console.log('auto starting the nodes...') // `nodesStarted` keeps track of how many of our nodes have started let nodesStarted = 0 /** * Calls `connectAndTalk` when both nodes have started * @returns {void} */ const didStartHandler = () => { if (++nodesStarted === 2) { // If both nodes are up, start talking connectAndTalk() } } /** * Exits the process when all started nodes have stopped * @returns {void} */ const didStopHandler = () => { if (--nodesStarted < 1) { console.log('all nodes stopped, exiting.') process.exit(0) } } /** * Stops the running nodes * @param {Error} err An optional error to log to the console * @returns {void} */ const doStop = (err) => { if (err) { console.error(err) } console.log('Shutting down...') node1.stop() node2.stop() } /** * Connects the IPFS nodes and transfers data between them * @returns {void} */ const connectAndTalk = async () => { console.log('connecting the nodes...') const node2Id = await node2.id() const dataToAdd = Buffer.from('Hello, private friend!') // Connect the nodes // This will error when different private keys are used try { await node1.swarm.connect(node2Id.addresses[0]) } catch (err) { return doStop(err) } console.log('the nodes are connected, let\'s add some data') // Add some data to node 1 let addedCID try { addedCID = await node1.add(dataToAdd) } catch (err) { return doStop(err) } console.log(`added ${addedCID[0].path} to the node1`) // Retrieve the data from node 2 let cattedData try { cattedData = await node2.cat(addedCID[0].path) } catch (err) { return doStop(err) } assert.deepEqual(cattedData.toString(), dataToAdd.toString(), 'Should have equal data') console.log(`successfully retrieved "${dataToAdd.toString()}" from node2`) doStop() } // Wait for the nodes to boot node1.once('start', didStartHandler) node2.once('start', didStartHandler) // Listen for the nodes stopping so we can cleanup node1.once('stop', didStopHandler) node2.once('stop', didStopHandler)