A file sharing network based on rabin file chunking and append only feeds of data verified by merkle trees.


A file sharing network based on rabin file chunking and append only feeds of data verified by merkle trees.

npm install hyperdrive

For a more detailed technical information on how it works see SPECIFICATION.md. If you are interested in only using the feed part of the spec see hypercore which implements that.

First create a new feed to share

var hyperdrive = require('hyperdrive')
var level = require('level')
var db = level('./hyperdrive.db')
var drive = hyperdrive(db)
var pack = drive.add('./some-folder')
pack.appendFile('my-file.txt', function (err) {
  if (err) throw err
  pack.finalize(function () {
    var link = pack.id.toString('hex')
    console.log(link, '<-- this is your hyperdrive link')

Then to share it

var disc = require('discovery-channel')()
var hyperdrive = require('hyperdrive')
var net = require('net')
var level = require('level')
var db = levelup('./another-hyperdrive.db')
var drive = hyperdrive(db)
var link = new Buffer({your-hyperdrive-link-from-the-above-example}, 'hex')
var server = net.createServer(function (socket) {
server.listen(0, function () {
  disc.add(link, server.address().port)
  disc.on('peer', function (hashpeer) {
    var socket = net.connect(peer.port, peer.host)

If you run this code on multiple computers you should be able to access the content in the feed by doing

var archive = drive.get(link, './folder-to-store-data-in') // the link identifies/verifies the content 
archive.entry(0, function (errentry) { // get the first entry 
  console.log(entry) // prints {name: 'my-file.txt', ...} 
  var stream = archive.createFileStream(0)
  stream.on('data', function (data) {
    console.log(data) // <-- file data 
  stream.on('end', function () {
    console.log('no more data')

Create a new hyperdrive instance. db should be a levelup instance. You can add a folder to store the file data in as the second argument.

Create a new peer replication duplex stream. This stream should be piped together with another peer stream somewhere else to start replicating the feeds

Add a new archive to share. basefolder will be the root of this archive.

Retrive a finalized archive.

archive.on('file-download', entry, data)

Emitted when a data block if downloaded for a file.

archive.on('file-downloaded', entry)

Emitted when a file is fully downloaded.

Append a file to a non-finalized archive. If you don't specify name the entry will be called filename.

Finalize an archive. After an archive is finalized it will be sharable and will have a .id property.

Wait for the archive to be ready. Afterwards archive.entries will contain the total amount of entries available.

Read the entry metadata stored at index. An metadata entry looks like this

  type: 'file-or-directory',
  name: 'filename',
  mode: fileMode,
  size: fileSize,
  uid: optionalUid,
  gid: optionalGid,
  mtime: optionalMtimeInSeconds,
  ctime: optionalCtimeInSeconds

Downloads the file specified by index and calls the callback when done. You have to call this or create a file stream to download a file.

Create a stream to a file.

Stream out all metadata entries