diff --git a/SPEC/BOOTSTRAP.md b/SPEC/BOOTSTRAP.md new file mode 100644 index 000000000..a009d18a2 --- /dev/null +++ b/SPEC/BOOTSTRAP.md @@ -0,0 +1,43 @@ +Bootstrap API +============= + +> Manipulates the `bootstrap list`, which contains + the addresses of the bootstrap nodes. These are the trusted peers from + which to learn about other peers in the network. + +> Only edit this list if you understand the risks of adding or removing nodes from this list. + +#### `add` + +> Add a peer address to the bootstrap list + +##### `Go` **WIP** + +##### `JavaScript` - ipfs.bootstrap.add(addr, [opts,] callback) + +- `addr` is a [multiaddr](https://github.com/multiformats/js-multiaddr) to a peer node +- `opts.default` if true, add the default peers to the list +- `callback` must follow `function (err, res) {}` signature, where `err` is an error if the operation was not successful. `res.Peers` is an array of added addresses. + +#### `list` + +> List all peer addresses in the bootstrap list + +##### `Go` **WIP** + +##### `JavaScript` - ipfs.bootstrap.list(callback) + +- `callback` must follow `function (err, res) {}` signature, where `err` is an error if the operation was not successful. `res.Peers` is an array of addresses. + + +#### `rm` + +> Remove a peer address from the bootstrap list + +##### `Go` **WIP** + +##### `JavaScript` - ipfs.bootstrap.rm(peer, [opt,] callback) + +- `addr` is a [multiaddr](https://github.com/multiformats/js-multiaddr) to a peer node +- `opts.all` if true, remove all peers from the list +- `callback` must follow `function (err, res) {}` signature, where `err` is an error if the operation was not successful. `res.Peers` is an array of removed addresses. diff --git a/js/src/bootstrap.js b/js/src/bootstrap.js new file mode 100644 index 000000000..cb81ddbf2 --- /dev/null +++ b/js/src/bootstrap.js @@ -0,0 +1,116 @@ +/* eslint-env mocha */ +/* eslint max-nested-callbacks: ["error", 8] */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) + +const invalidArg = 'this/Is/So/Invalid/' +const validIp4 = '/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z' + +module.exports = (common) => { + describe('.bootstrap', function () { + this.timeout(100 * 1000) + + let ipfs + let peers + + before(function (done) { + // CI takes longer to instantiate the daemon, so we need to increase the + // timeout for the before step + this.timeout(60 * 1000) + + common.setup((err, factory) => { + expect(err).to.not.exist() + factory.spawnNode((err, node) => { + expect(err).to.not.exist() + ipfs = node + done() + }) + }) + }) + + after((done) => common.teardown(done)) + + describe('.add', () => { + it('returns an error when called with an invalid arg', (done) => { + ipfs.bootstrap.add(invalidArg, (err) => { + expect(err).to.be.an.instanceof(Error) + done() + }) + }) + + it('returns a list of containing the bootstrap peer when called with a valid arg (ip4)', (done) => { + ipfs.bootstrap.add(validIp4, (err, res) => { + expect(err).to.not.exist() + expect(res).to.be.eql({ Peers: [validIp4] }) + peers = res.Peers + expect(peers).to.exist() + expect(peers.length).to.eql(1) + done() + }) + }) + + it('returns a list of bootstrap peers when called with the default option', (done) => { + ipfs.bootstrap.add(null, { default: true }, (err, res) => { + expect(err).to.not.exist() + peers = res.Peers + expect(peers).to.exist() + expect(peers.length).to.above(1) + done() + }) + }) + }) + + describe('.list', () => { + it('returns a list of peers', (done) => { + ipfs.bootstrap.list((err, res) => { + expect(err).to.not.exist() + peers = res.Peers + expect(peers).to.exist() + done() + }) + }) + }) + + describe('.rm', () => { + it('returns an error when called with an invalid arg', (done) => { + ipfs.bootstrap.rm(invalidArg, (err) => { + expect(err).to.be.an.instanceof(Error) + done() + }) + }) + + it('returns empty list because no peers removed when called without an arg or options', (done) => { + ipfs.bootstrap.rm(null, (err, res) => { + expect(err).to.not.exist() + peers = res.Peers + expect(peers).to.exist() + expect(peers.length).to.eql(0) + done() + }) + }) + + it('returns list containing the peer removed when called with a valid arg (ip4)', (done) => { + ipfs.bootstrap.rm(null, (err, res) => { + expect(err).to.not.exist() + peers = res.Peers + expect(peers).to.exist() + expect(peers.length).to.eql(0) + done() + }) + }) + + it('returns list of all peers removed when all option is passed', (done) => { + ipfs.bootstrap.rm(null, { all: true }, (err, res) => { + expect(err).to.not.exist() + peers = res.Peers + expect(peers).to.exist() + done() + }) + }) + }) + }) +} diff --git a/js/src/index.js b/js/src/index.js index 53beb2acd..9f527e190 100644 --- a/js/src/index.js +++ b/js/src/index.js @@ -15,3 +15,4 @@ exports.pubsub = require('./pubsub') exports.key = require('./key') exports.stats = require('./stats') exports.repo = require('./repo') +exports.bootstrap = require('./bootstrap')