{"id":20747337,"url":"https://github.com/ether1project/js-ethofs","last_synced_at":"2026-07-02T12:32:45.497Z","repository":{"id":101311943,"uuid":"162212442","full_name":"Ether1Project/js-ethofs","owner":"Ether1Project","description":"JS Implementation of ethoFS (ethoFS Version of js-ipfs)","archived":false,"fork":false,"pushed_at":"2018-12-18T01:44:40.000Z","size":8755,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-30T19:42:04.506Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ether1Project.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-18T01:28:31.000Z","updated_at":"2018-12-18T01:45:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"a528aa68-0fc2-417d-bcdc-820e629c3c43","html_url":"https://github.com/Ether1Project/js-ethofs","commit_stats":null,"previous_names":[],"tags_count":106,"template":false,"template_full_name":null,"purl":"pkg:github/Ether1Project/js-ethofs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ether1Project%2Fjs-ethofs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ether1Project%2Fjs-ethofs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ether1Project%2Fjs-ethofs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ether1Project%2Fjs-ethofs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ether1Project","download_url":"https://codeload.github.com/Ether1Project/js-ethofs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ether1Project%2Fjs-ethofs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35048062,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T08:12:45.158Z","updated_at":"2026-07-02T12:32:45.455Z","avatar_url":"https://github.com/Ether1Project.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003ca href=\"https://ipfs.io\"\u003e\n    \u003cimg src=\"https://ipfs.io/ipfs/QmVk7srrwahXLNmcDYvyUEJptyoxpndnRa57YJ11L4jV26/ipfs.js.png\" alt=\"IPFS in JavaScript logo\" /\u003e\n  \u003c/a\u003e\n\u003c/h1\u003e\n\n\u003ch3 align=\"center\"\u003eThe JavaScript implementation of the IPFS protocol.\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"http://protocol.ai\"\u003e\u003cimg src=\"https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"http://ipfs.io/\"\u003e\u003cimg src=\"https://img.shields.io/badge/project-IPFS-blue.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"http://webchat.freenode.net/?channels=%23ipfs\"\u003e\u003cimg src=\"https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ipfs/team-mgmt/blob/master/MGMT_JS_CORE_DEV.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/team-mgmt-blue.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ipfs/interface-ipfs-core\"\u003e\u003cimg src=\"https://img.shields.io/badge/interface--ipfs--core-API%20Docs-blue.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://ci.ipfs.team/job/ipfs/job/js-ipfs/job/master/\"\u003e\u003cimg src=\"https://ci.ipfs.team/buildStatus/icon?job=ipfs/js-ipfs/master\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/ipfs/js-ipfs\"\u003e\u003cimg src=\"https://codecov.io/gh/ipfs/js-ipfs/branch/master/graph/badge.svg\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://david-dm.org/ipfs/js-ipfs\"\u003e\u003cimg src=\"https://david-dm.org/ipfs/js-ipfs.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/feross/standard\"\u003e\u003cimg src=\"https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat\"\u003e\u003c/a\u003e\n  \u003ca href=\"\"\u003e\u003cimg src=\"https://img.shields.io/badge/npm-%3E%3D6.0.0-orange.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"\"\u003e\u003cimg src=\"https://img.shields.io/badge/Node.js-%3E%3D10.0.0-orange.svg?style=flat\" /\u003e\u003c/a\u003e\n  \u003cbr\u003e\n\u003c/p\u003e\n\n### Project status - `Alpha`\n\nWe've come a long way, but this project is still in Alpha, lots of development is happening, API might change, beware of the Dragons 🐉..\n\n**Want to get started?** Check our [examples folder](/examples) to learn how to spawn an IPFS node in Node.js and in the Browser.\n\nYou can check the development status at the [Kanban Board](https://waffle.io/ipfs/js-ipfs).\n\n[![Throughput Graph](https://graphs.waffle.io/ipfs/js-ipfs/throughput.svg)](https://waffle.io/ipfs/js-ipfs/metrics/throughput)\n\n**Please read this:** DHT (automatic content discovery) and Circuit Relay (pierce through NATs and dial between any node in the network) are two fundamental pieces that are not finalized yet. There are multiple applications that can be built without these two services but nevertheless they are fundamental to get that magic IPFS experience. If you want to track progress or contribute, please follow:\n\n- DHT: https://github.com/ipfs/js-ipfs/pull/856\n- ✅ Relay: https://github.com/ipfs/js-ipfs/pull/1063\n\n[**`Weekly Core Dev Calls`**](https://github.com/ipfs/pm/issues/650)\n\n## Tech Lead\n\n[David Dias](https://github.com/daviddias)\n\n## Lead Maintainer\n\n[Alan Shaw](https://github.com/alanshaw)\n\n## Table of Contents\n\n- [Install](#install)\n  - [npm](#npm)\n  - [Use in Node.js](#use-in-nodejs)\n  - [Through command line tool](#through-command-line-tool)\n  - [Use in the browser](#use-in-the-browser)\n- [Usage](#usage)\n  - [IPFS CLI](#ipfs-cli)\n  - [IPFS Daemon](#ipfs-daemon)\n  - [IPFS Module (use IPFS as a module in Node.js or in the Browser)](#ipfs-module)\n  - [Tutorials and Examples](#tutorials-and-examples)\n  - [API Docs](#api)\n    - [Constructor](#ipfs-constructor)\n    - [Events](#events)\n    - [start](#nodestartcallback)\n    - [stop](#nodestopcallback)\n    - [Core API](#core-api)\n      - [Files](#files)\n      - [Graph](#graph)\n      - [Name](#name)\n      - [Crypto and Key Management](#crypto-and-key-management)\n      - [Network](#network)\n      - [Node Management](#node-management)\n      - [Domain data types](#domain-data-types)\n      - [Util](#util)\n- [FAQ](#faq)\n- [Running js-ipfs with Docker](#running-js-ipfs-with-docker)\n- [Packages](#packages)\n- [Development](#development)\n  - [Clone and install dependencies](#clone-and-install-dependencies)\n  - [Run Tests](#run-tests)\n  - [Lint](#lint)\n  - [Build a dist version](#build-a-dist-version)\n- [Contribute](#contribute)\n  - [Want to hack on IPFS?](#want-to-hack-on-ipfs)\n- [License](#license)\n\n## Install\n\n### npm\n\nThis project is available through [npm](https://www.npmjs.com/). To install run\n\n```bash\n\u003e npm install ipfs --save\n```\n\nWe support both the Current and Active LTS versions of Node.js. Please see [nodejs.org](https://nodejs.org/) for what these currently are.\n\nThis project is tested on OSX \u0026 Linux, expected to work on Windows.\n\n### Use in Node.js\n\nTo create an IPFS node programmatically:\n\n```js\nconst IPFS = require('ipfs')\nconst node = new IPFS()\n\nnode.on('ready', () =\u003e {\n  // Ready to use!\n  // See https://github.com/ipfs/js-ipfs#core-api\n})\n```\n\n### Through command line tool\n\nIn order to use js-ipfs as a CLI, you must install it with the `global` flag. Run the following (even if you have ipfs installed locally):\n\n```bash\nnpm install ipfs --global\n```\n\nThe CLI is available by using the command `jsipfs` in your terminal. This is aliased, instead of using `ipfs`, to make sure it does not conflict with the [Go implementation](https://github.com/ipfs/go-ipfs).\n\n### Use in the browser\n\nLearn how to bundle with browserify and webpack in the [`examples`](https://github.com/ipfs/js-ipfs/tree/master/examples) folder.\n\n\nYou can also load it using a `\u003cscript\u003e` using the [unpkg](https://unpkg.com) CDN or the [jsDelivr](https://www.jsdelivr.com/package/npm/ipfs) CDN. Inserting one of the following lines will make a `Ipfs` object available in the global namespace.\n\n```html\n\u003c!-- loading the minified version --\u003e\n\u003cscript src=\"https://unpkg.com/ipfs/dist/index.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/ipfs/dist/index.min.js\"\u003e\u003c/script\u003e\n\n\u003c!-- loading the human-readable (not minified) version --\u003e\n\u003cscript src=\"https://unpkg.com/ipfs/dist/index.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/ipfs/dist/index.js\"\u003e\u003c/script\u003e\n```\n\nInserting one of the above lines will make an `Ipfs` object available in the global namespace:\n\n```html\n\u003cscript\u003e\nconst node = new window.Ipfs()\n\nnode.on('ready', () =\u003e {\n  // Ready to use!\n  // See https://github.com/ipfs/js-ipfs#core-api\n})\n\u003c/script\u003e\n```\n\n## Usage\n\n### IPFS CLI\n\nThe `jsipfs` CLI, available when `js-ipfs` is installed globally, follows(should, it is a WIP) the same interface defined by `go-ipfs`, you can always use the `help` command for help menus.\n\n```sh\n# Install js-ipfs globally\n\u003e npm install ipfs --global\n\u003e jsipfs --help\nCommands:\n  bitswap               A set of commands to manipulate the bitswap agent.\n  block                 Manipulate raw IPFS blocks.\n  bootstrap             Show or edit the list of bootstrap peers.\n  commands              List all available commands\n  config \u003ckey\u003e [value]  Get and set IPFS config values\n  daemon                Start a long-running daemon process\n# ...\n```\n\n`js-ipfs` uses some different default config values, so that they don't clash directly with a go-ipfs node running in the same machine. These are:\n\n- default repo location: `~/.jsipfs` (can be changed with env variable `IPFS_PATH`)\n- default swarm port: `4002`\n- default API port: `5002`\n\n### IPFS Daemon\n\nThe IPFS Daemon exposes the API defined [`http-api-spec`](https://github.com/ipfs/http-api-spec). You can use any of the IPFS HTTP-API client libraries with it, such as: [js-ipfs-http-client](https://github.com/ipfs/js-ipfs-http-client).\n\nIf you want a programmatic way to spawn a IPFS Daemon using JavaScript, check out [ipfsd-ctl module](https://github.com/ipfs/js-ipfsd-ctl)\n\n### IPFS Module\n\nUse the IPFS Module as a dependency of a project to __spawn in process instances of IPFS__. Create an instance by calling `new IPFS()` and waiting for its `ready` event:\n\n```js\n// Create the IPFS node instance\nconst node = new IPFS()\n\nnode.on('ready', () =\u003e {\n  // Your node is now ready to use \\o/\n\n  // stopping a node\n  node.stop(() =\u003e {\n    // node is now 'offline'\n  })\n})\n```\n\n### [Tutorials and Examples](/examples)\n\nYou can find some examples and tutorials in the [examples](/examples) folder, these exist to help you get started using `js-ipfs`.\n\n### API\n\n#### IPFS Constructor\n\n```js\nconst node = new IPFS([options])\n```\n\nCreates and returns an instance of an IPFS node. Use the `options` argument to specify advanced configuration. It is an object with any of these properties:\n\n\n##### `options.repo`\n\n| Type | Default |\n|------|---------|\n| string or [`ipfs.Repo`](https://github.com/ipfs/js-ipfs-repo) instance | `'~/.jsipfs'` in Node.js, `'ipfs'` in browsers |\n\nThe file path at which to store the IPFS node’s data. Alternatively, you can set up a customized storage system by providing an [`ipfs.Repo`](https://github.com/ipfs/js-ipfs-repo) instance.\n\nExample:\n\n```js\n// Store data outside your user directory\nconst node = new IPFS({ repo: '/var/ipfs/data' })\n```\n\n##### `options.init`\n\n| Type | Default |\n|------|---------|\n| boolean or object | `true` |\n\nInitialize the repo when creating the IPFS node.\n\nIf you have already initialized a repo before creating your IPFS node (e.g. you are loading a repo that was saved to disk from a previous run of your program), you must make sure to set this to `false`. Note that *initializing* a repo is different from creating an instance of [`ipfs.Repo`](https://github.com/ipfs/js-ipfs-repo). The IPFS constructor sets many special properties when initializing a repo, so you should usually not try and call `repoInstance.init()` yourself.\n\nInstead of a boolean, you may provide an object with custom initialization options. All properties are optional:\n\n- `emptyRepo` (boolean) Whether to remove built-in assets, like the instructional tour and empty mutable file system, from the repo. (Default: `false`)\n- `bits` (number) Number of bits to use in the generated key pair. (Default: `2048`)\n- `privateKey` (string/PeerId) A pre-generated private key to use. Can be either a base64 string or a [PeerId](https://github.com/libp2p/js-peer-id) instance. **NOTE: This overrides `bits`.**\n    ```js\n    // Generating a Peer ID:\n    const PeerId = require('peer-id')\n    PeerId.create({ bits: 2048 }, (err, peerId) =\u003e {\n      // Generates a new Peer ID, complete with public/private keypair\n      // See https://github.com/libp2p/js-peer-id\n    })\n    ```\n- `pass` (string) A passphrase to encrypt keys. You should generally use the [top-level `pass` option](#optionspass) instead of the `init.pass` option (this one will take its value from the top-level option if not set).\n\n##### `options.start`\n\n| Type | Default |\n|------|---------|\n| boolean | `true` |\n\n If `false`, do not automatically start the IPFS node. Instead, you’ll need to manually call [`node.start()`](#nodestartcallback) yourself.\n\n##### `options.pass`\n\n| Type | Default |\n|------|---------|\n| string | `null` |\n\nA passphrase to encrypt/decrypt your keys.\n\n##### `options.silent`\n\n| Type | Default |\n|------|---------|\n| Boolean | `false` |\n\nPrevents all logging output from the IPFS node.\n\n##### `options.relay`\n\n| Type | Default |\n|------|---------|\n| object | `{ enabled: false, hop: { enabled: false, active: false } }` |\n\nConfigure circuit relay (see the [circuit relay tutorial](https://github.com/ipfs/js-ipfs/tree/master/examples/circuit-relaying) to learn more).\n\n- `enabled` (boolean): Enable circuit relay dialer and listener. (Default: `false`)\n- `hop` (object)\n    - `enabled` (boolean): Make this node a relay (other nodes can connect *through* it). (Default: `false`)\n    - `active` (boolean): Make this an *active* relay node. Active relay nodes will attempt to dial a destination peer even if that peer is not yet connected to the relay. (Default: `false`)\n\n##### `options.preload`\n\n| Type | Default |\n|------|---------|\n| object | `{ enabled: true, addresses: [...] }` |\n\nConfigure remote preload nodes. The remote will preload content added on this node, and also attempt to preload objects requested by this node.\n\n- `enabled` (boolean): Enable content preloading (Default: `true`)\n- `addresses` (array): Multiaddr API addresses of nodes that should preload content. **NOTE:** nodes specified here should also be added to your node's bootstrap address list at [`config.Boostrap`](#optionsconfig).\n\n##### `options.EXPERIMENTAL`\n\n| Type | Default |\n|------|---------|\n| object | `{ pubsub: false, sharding: false, dht: false }` |\n\nEnable and configure experimental features.\n\n- `pubsub` (boolean): Enable libp2p pub-sub. (Default: `false`)\n- `ipnsPubsub` (boolean): Enable pub-sub on IPNS. (Default: `false`)\n- `sharding` (boolean): Enable directory sharding. Directories that have many child objects will be represented by multiple DAG nodes instead of just one. It can improve lookup performance when a directory has several thousand files or more. (Default: `false`)\n- `dht` (boolean): Enable KadDHT. **This is currently not interoperable with `go-ipfs`.**\n\n##### `options.config`\n\n| Type | Default |\n|------|---------|\n| object |  [`config-nodejs.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-nodejs.js) in Node.js, [`config-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-browser.js) in browsers |\n\nModify the default IPFS node config. This object will be *merged* with the default config; it will not replace it.\n\n##### `options.libp2p`\n\n| Type | Default |\n|------|---------|\n| object | [`libp2p-nodejs.js`](https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/libp2p-nodejs.js) in Node.js, [`libp2p-browser.js`](https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/libp2p-browser.js) in browsers |\n| function | [`libp2p bundle`](examples/custom-libp2p) |\n\nThe libp2p option allows you to build your libp2p node by configuration, or via a bundle function. If you are looking to just modify the below options, using the object format is the quickest way to get the default features of libp2p. If you need to create a more customized libp2p node, such as with custom transports or peer/content routers that need some of the ipfs data on startup, a custom bundle is a great way to achieve this.\n\nYou can see the bundle in action in the [custom libp2p example](examples/custom-libp2p).\n\n- `modules` (object):\n    - `transport` (Array\u003c[libp2p.Transport](https://github.com/libp2p/interface-transport)\u003e): An array of Libp2p transport classes/instances to use _instead_ of the defaults. See [libp2p/interface-transport](https://github.com/libp2p/interface-transport) for details.\n    - `peerDiscovery` (Array\u003c[libp2p.PeerDiscovery](https://github.com/libp2p/interface-peer-discovery)\u003e): An array of Libp2p peer discovery classes/instances to use _instead_ of the defaults. See [libp2p/peer-discovery](https://github.com/libp2p/interface-peer-discovery) for details. If passing a class, configuration can be passed using the config section below under the key corresponding to you module's unique `tag` (a static property on the class)\n- `config` (object):\n    - `peerDiscovery` (object):\n        - `[PeerDiscovery.tag]` (object): configuration for a peer discovery module\n            - `enabled` (boolean): whether this module is enabled or disabled\n            - `[custom config]` (any): other keys are specific to the module\n\n##### `options.connectionManager`\n\n| Type | Default |\n|------|---------|\n| object | [defaults](https://github.com/libp2p/js-libp2p-connection-manager#create-a-connectionmanager) |\n\nConfigure the libp2p connection manager.\n\n#### Events\n\nIPFS instances are Node.js [EventEmitters](https://nodejs.org/dist/latest-v8.x/docs/api/events.html#events_class_eventemitter). You can listen for events by calling `node.on('event', handler)`:\n\n```js\nconst node = new IPFS({ repo: '/var/ipfs/data' })\nnode.on('error', errorObject =\u003e console.error(errorObject))\n```\n\n- `error` is always accompanied by an `Error` object with information about the error that occurred.\n\n    ```js\n    node.on('error', error =\u003e {\n      console.error(error.message)\n    })\n    ```\n\n- `init` is emitted after a new repo has been initialized. It will not be emitted if you set the `init: false` option on the constructor.\n\n- `ready` is emitted when a node is ready to use. This is the final event you will receive when creating a node (after `init` and `start`).\n\n    When creating a new IPFS node, you should almost always wait for the `ready` event before calling methods or interacting with the node.\n\n- `start` is emitted when a node has started listening for connections. It will not be emitted if you set the `start: false` option on the constructor.\n\n- `stop` is emitted when a node has closed all connections and released access to its repo. This is usually the result of calling [`node.stop()`](#nodestopcallback).\n\n#### `node.start([callback])`\n\nStart listening for connections with other IPFS nodes on the network. In most cases, you do not need to call this method — `new IPFS()` will automatically do it for you.\n\nThis method is asynchronous. There are several ways to be notified when the node has finished starting:\n\n1. If you call `node.start()` with no arguments, it returns a promise.\n\n    ```js\n    const node = new IPFS({ start: false })\n\n    node.on('ready', async () =\u003e {\n      console.log('Node is ready to use!')\n\n      try {\n        await node.start()\n        console.log('Node started!')\n      } catch (error) {\n        console.error('Node failed to start!', error)\n      }\n    })\n    ```\n\n2. If you pass a function as the final argument, it will be called when the node is started (Note: this method will **not** return a promise if you use a callback function).\n\n    ```js\n    const node = new IPFS({ start: false })\n\n    node.on('ready', () =\u003e {\n      console.log('Node is ready to use!')\n\n      node.start(error =\u003e {\n        if (error) {\n          return console.error('Node failed to start!', error)\n        }\n        console.log('Node started!')\n      })\n    })\n    ```\n\n3. You can listen for the [`start` event](#events).\n\n    ```js\n    const node = new IPFS({ start: false })\n\n    node.on('ready', () =\u003e {\n      console.log('Node is ready to use!')\n      node.start()\n    })\n\n    node.on('error', error =\u003e {\n      console.error('Something went terribly wrong!', error)\n    })\n\n    node.on('start', () =\u003e console.log('Node started!'))\n    ```\n\n#### `node.stop([callback])`\n\nClose and stop listening for connections with other IPFS nodes, then release access to the node’s repo.\n\nThis method is asynchronous. There are several ways to be notified when the node has completely stopped:\n\n1. If you call `node.stop()` with no arguments, it returns a promise.\n\n    ```js\n    const node = new IPFS()\n\n    node.on('ready', async () =\u003e {\n      console.log('Node is ready to use!')\n\n      try {\n        await node.stop()\n        console.log('Node stopped!')\n      } catch (error) {\n        console.error('Node failed to stop cleanly!', error)\n      }\n    })\n    ```\n\n2. If you pass a function as the final argument, it will be called when the node is stopped (Note: this method will **not** return a promise if you use a callback function).\n\n    ```js\n    const node = new IPFS()\n\n    node.on('ready', () =\u003e {\n      console.log('Node is ready to use!')\n\n      node.stop(error =\u003e {\n        if (error) {\n          return console.error('Node failed to stop cleanly!', error)\n        }\n        console.log('Node stopped!')\n      })\n    })\n    ```\n\n3. You can listen for the [`stop` event](#events).\n\n    ```js\n    const node = new IPFS()\n\n    node.on('ready', () =\u003e {\n      console.log('Node is ready to use!')\n      node.stop()\n    })\n\n    node.on('error', error =\u003e {\n      console.error('Something went terribly wrong!', error)\n    })\n\n    node.on('stop', () =\u003e console.log('Node stopped!'))\n    ```\n\n#### Core API\n\n[![](https://github.com/ipfs/interface-ipfs-core/raw/master/img/badge.png)](https://github.com/ipfs/interface-ipfs-core)\n\nThe IPFS core API provides all functionality that is not specific to setting up and starting or stopping a node. This API is available directly on an IPFS instance, on the command line (when using the CLI interface), and as an HTTP REST API. For a complete reference, see [![](https://img.shields.io/badge/interface--ipfs--core-API%20Docs-blue.svg)](https://github.com/ipfs/interface-ipfs-core).\n\nThe core API is grouped into several areas:\n\n#### Files\n\n- [Regular Files API](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md)\n  - [`ipfs.add(data, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#add)\n  - [`ipfs.addPullStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addpullstream)\n  - [`ipfs.addReadableStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addreadablestream)\n  - [`ipfs.addFromStream(stream, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromstream)\n  - [`ipfs.addFromFs(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromfs)\n  - [`ipfs.addFromUrl(url, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromurl)\n  - [`ipfs.cat(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#cat)\n  - [`ipfs.catPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catpullstream)\n  - [`ipfs.catReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catreadablestream)\n  - [`ipfs.get(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#get)\n  - [`ipfs.getPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getpullstream)\n  - [`ipfs.getReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getreadablestream)\n  - [`ipfs.ls(ipfsPath, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#ls)\n  - [`ipfs.lsPullStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lspullstream)\n  - [`ipfs.lsReadableStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lsreadablestream)\n- [MFS (mutable file system) specific](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#mutable-file-system)\n  - [`ipfs.files.cp([from, to], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp)\n  - [`ipfs.files.flush([path], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush)\n  - [`ipfs.files.ls([path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesls)\n  - [`ipfs.files.mkdir(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir)\n  - [`ipfs.files.mv([from, to], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmv)\n  - [`ipfs.files.read(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesread)\n  - [`ipfs.files.readPullStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadpullstream)\n  - [`ipfs.files.readReadableStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadreadablestream)\n  - [`ipfs.files.rm(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesrm)\n  - [`ipfs.files.stat(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesstat)\n  - [`ipfs.files.write(path, content, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#fileswrite)\n\n\n#### Graph\n\n- [dag](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/DAG.md)\n  - [`ipfs.dag.put(dagNode, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/DAG.md#dagput)\n  - [`ipfs.dag.get(cid, [path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/DAG.md#dagget)\n  - [`ipfs.dag.tree(cid, [path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/DAG.md#dagtree)\n\n- [pin](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md)\n  - [`ipfs.pin.add(hash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinadd)\n  - [`ipfs.pin.ls([hash], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinls)\n  - [`ipfs.pin.rm(hash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinrm)\n\n- [object (legacy)](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md)\n  - [`ipfs.object.new([template], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectnew)\n  - [`ipfs.object.put(obj, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectput)\n  - [`ipfs.object.get(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectget)\n  - [`ipfs.object.data(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectdata)\n  - [`ipfs.object.links(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectlinks)\n  - [`ipfs.object.stat(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectstat)\n  - [`ipfs.object.patch.addLink(multihash, DAGLink, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectpatchaddlink)\n  - [`ipfs.object.patch.rmLink(multihash, DAGLink, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectpatchrmlink)\n  - [`ipfs.object.patch.appendData(multihash, data, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectpatchappenddata)\n  - [`ipfs.object.patch.setData(multihash, data, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/OBJECT.md#objectpatchsetdata)\n\n#### Block\n\n- [block](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/BLOCK.md)\n  - [`ipfs.block.get(cid, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/BLOCK.md#blockget)\n  - [`ipfs.block.put(block, cid, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/BLOCK.md#blockput)\n  - [`ipfs.block.stat(cid, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/BLOCK.md#blockstat)\n- [bitswap](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/BITSWAP.md)\n  - [`ipfs.bitswap.wantlist([peerId], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapwantlist)\n  - [`ipfs.bitswap.stat([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapstat)\n\n#### Name\n\n- [name](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md)\n  - [`ipfs.name.publish(value, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepublish)\n  - [`ipfs.name.pubsub.cancel(arg, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubcancel)\n  - [`ipfs.name.pubsub.state([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubstate)\n  - [`ipfs.name.pubsub.subs([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubsubs)\n  - [`ipfs.name.resolve(value, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#nameresolve)\n\n#### Crypto and Key Management\n\n- [key](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/KEY.md)\n  - [`ipfs.key.export(name, password, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyexport)\n  - [`ipfs.key.gen(name, options, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keygen)\n  - [`ipfs.key.import(name, pem, password, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyimport)\n  - [`ipfs.key.list([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keylist)\n  - [`ipfs.key.rename(oldName, newName, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrename)\n  - [`ipfs.key.rm(name, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrm)\n\n- crypto (not implemented yet)\n\n#### Network\n\n- [bootstrap](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/BOOTSTRAP.md)\n  - [`ipfs.bootstrap.list([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraplist)\n  - [`ipfs.bootstrap.add(addr, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstrapadd)\n  - [`ipfs.bootstrap.rm(peer, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraprm)\n\n- dht (not implemented yet)\n\n- [pubsub](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/PUBSUB.md)\n  - [`ipfs.pubsub.subscribe(topic, handler, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/PUBSUB.md#pubsubsubscribe)\n  - [`ipfs.pubsub.unsubscribe(topic, handler, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/PUBSUB.md#pubsubunsubscribe)\n  - [`ipfs.pubsub.publish(topic, data, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/PUBSUB.md#pubsubpublish)\n  - [`ipfs.pubsub.ls(topic, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/PUBSUB.md#pubsubls)\n  - [`ipfs.pubsub.peers(topic, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/PUBSUB.md#pubsubpeers)\n\n- [libp2p](https://github.com/libp2p/interface-libp2p). Every IPFS instance also exposes the libp2p SPEC at `ipfs.libp2p`. The formal interface for this SPEC hasn't been defined but you can find documentation at its implementations:\n  - [Node.js bundle](./src/core/runtime/libp2p-nodejs.js)\n  - [Browser Bundle](./src/core/runtime/libp2p-browser.js)\n  - [libp2p baseclass](https://github.com/libp2p/js-libp2p)\n\n- [swarm](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/SWARM.md)\n  - [`ipfs.swarm.addrs([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/SWARM.md#swarmaddrs)\n  - [`ipfs.swarm.connect(addr, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/SWARM.md#swarmconnect)\n  - [`ipfs.swarm.disconnect(addr, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/SWARM.md#swarmdisconnect)\n  - [`ipfs.swarm.peers([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/SWARM.md#swarmpeers)\n\n#### Node Management\n\n- [miscellaneous operations](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md)\n  - [`ipfs.id([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#id)\n  - [`ipfs.version([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#version)\n  - [`ipfs.ping(peerId, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#ping)\n  - [`ipfs.pingReadableStream(peerId, [options])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#pingreadablestream)\n  - [`ipfs.pingPullStream(peerId, [options])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#pingpullstream)\n  - `ipfs.init([options], [callback])`\n  - `ipfs.start([callback])`\n  - [`ipfs.stop([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#stop)\n  - `ipfs.isOnline()`\n  - [`ipfs.resolve(name, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#resolve)\n\n- [repo](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/REPO.md)\n  - `ipfs.repo.init`\n  - [`ipfs.repo.stat([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/REPO.md#repostat)\n  - [`ipfs.repo.version([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/REPO.md#repoversion)\n  - `ipfs.repo.gc([options], [callback])` (not implemented yet)\n\n- [stats](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/STATS.md)\n  - [`ipfs.stats.bitswap([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/STATS.md#statsbitswap)\n  - [`ipfs.stats.bw([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/STATS.md#statsbw)\n  - [`ipfs.stats.bwPullStream([options]) -\u003e Pull Stream`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/STATS.md#statsbwpullstream)\n  - [`ipfs.stats.bwReadableStream([options]) -\u003e Readable Stream`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/STATS.md#statsbwreadablestream)\n  - [`ipfs.stats.repo([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/STATS.md#statsrepo)\n\n- [config](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/CONFIG.md)\n  - [`ipfs.config.get([key], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/CONFIG.md#configget)\n  - [`ipfs.config.set(key, value, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/CONFIG.md#configset)\n  - [`ipfs.config.replace(config, [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/CONFIG.md#configreplace)\n\n#### Domain data types\n\nA set of data types are exposed directly from the IPFS instance under `ipfs.types`. That way you're not required to import/require the following.\n\n- [`ipfs.types.Buffer`](https://www.npmjs.com/package/buffer)\n- [`ipfs.types.PeerId`](https://github.com/libp2p/js-peer-id)\n- [`ipfs.types.PeerInfo`](https://github.com/libp2p/js-peer-info)\n- [`ipfs.types.multiaddr`](https://github.com/multiformats/js-multiaddr)\n- [`ipfs.types.multibase`](https://github.com/multiformats/js-multibase)\n- [`ipfs.types.multihash`](https://github.com/multiformats/js-multihash)\n- [`ipfs.types.CID`](https://github.com/ipld/js-cid)\n- [`ipfs.types.dagPB`](https://github.com/ipld/js-ipld-dag-pb)\n- [`ipfs.types.dagCBOR`](https://github.com/ipld/js-ipld-dag-cbor)\n\n#### Util\n\nA set of utils are exposed directly from the IPFS instance under `ipfs.util`. That way you're not required to import/require the following:\n\n- [`ipfs.util.crypto`](https://github.com/libp2p/js-libp2p-crypto)\n- [`ipfs.util.isIPFS`](https://github.com/ipfs-shipyard/is-ipfs)\n\n## FAQ\n\n#### How to enable WebRTC support for js-ipfs in the Browser\n\nTo add a WebRTC transport to your js-ipfs node, you must add a WebRTC multiaddr. To do that, simple override the config.Addresses.Swarm array which contains all the multiaddrs which the IPFS node will use. See below:\n\n```JavaScript\nconst node = new IPFS({\n  config: {\n    Addresses: {\n      Swarm: [\n        '/dns4/wrtc-star.discovery.libp2p.io/tcp/443/wss/p2p-webrtc-star'\n      ]\n    }\n  }\n})\n\nnode.on('ready', () =\u003e {\n  // your instance with WebRTC is ready\n})\n```\n\n**Important:** This transport usage is kind of unstable and several users have experienced crashes. Track development of a solution at https://github.com/ipfs/js-ipfs/issues/1088.\n\n#### Is there WebRTC support for js-ipfs with Node.js?\n\nYes, however, bear in mind that there isn't a 100% stable solution to use WebRTC in Node.js, use it at your own risk. The most tested options are:\n\n- [wrtc](https://npmjs.org/wrtc) - Follow the install instructions.\n- [electron-webrtc](https://npmjs.org/electron-webrtc)\n\nTo add WebRTC support in a IPFS node instance, do:\n\n```JavaScript\nconst wrtc = require('wrtc') // or require('electron-webrtc')()\nconst WStar = require('libp2p-webrtc-star')\nconst wstar = new WStar({ wrtc })\n\nconst node = new IPFS({\n  repo: 'your-repo-path',\n  // start: false,\n  config: {\n    Addresses: {\n      Swarm: [\n        \"/ip4/0.0.0.0/tcp/4002\",\n        \"/ip4/127.0.0.1/tcp/4003/ws\",\n        \"/dns4/wrtc-star.discovery.libp2p.io/tcp/443/wss/p2p-webrtc-star\"\n      ]\n    }\n  },\n  libp2p: {\n    modules: {\n      transport: [wstar],\n      peerDiscovery: [wstar.discovery]\n    }\n  }\n})\n\nnode.on('ready', () =\u003e {\n  // your instance with WebRTC is ready\n})\n```\n\nTo add WebRTC support to the IPFS daemon, you only need to install one of the WebRTC modules globally:\n\n```bash\nnpm install wrtc --global\n# or\nnpm install electron-webrtc --global\n```\n\nThen, update your IPFS Daemon config to include the multiaddr for this new transport on the `Addresses.Swarm` array. Add: `\"/dns4/wrtc-star.discovery.libp2p.io/wss/p2p-webrtc-star\"`\n\n#### How can I configure an IPFS node to use a custom `signaling endpoint` for my WebRTC transport?\n\nYou'll need to execute a compatible `signaling server` ([libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star) works) and include the correct configuration param for your IPFS node:\n\n- provide the [`multiaddr`](https://github.com/multiformats/multiaddr) for the `signaling server`\n\n```JavaScript\nconst node = new IPFS({\n  repo: 'your-repo-path',\n  config: {\n    Addresses: {\n      Swarm: [\n        '/ip4/127.0.0.1/tcp/9090/ws/p2p-webrtc-star'\n      ]\n    }\n  }\n})\n```\n\nThe code above assumes you are running a local `signaling server` on port `9090`. Provide the correct values accordingly.\n\n#### Is there a more stable alternative to webrtc-star that offers a similar functionality?\n\nYes, websocket-star! A WebSockets based transport that uses a Relay to route the messages. To enable it, just do:\n\n```JavaScript\nconst node = new IPFS({\n  config: {\n    Addresses: {\n      Swarm: [\n        '/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star'\n      ]\n    }\n  }\n})\n\nnode.on('ready', () =\u003e {\n  // your instance with websocket-star is ready\n})\n```\n\n#### I see some slowness when hopping between tabs Chrome with IPFS nodes, is there a reason why?\n\nYes, unfortunately, due to [Chrome aggressive resource throttling policy](https://github.com/ipfs/js-ipfs/issues/611), it cuts freezes the execution of any background tab, turning an IPFS node that was running on that webpage into a vegetable state.\n\nA way to mitigate this in Chrome, is to run your IPFS node inside a Service Worker, so that the IPFS instance runs in a background process. You can learn how to install an IPFS node as a service worker in here the repo [ipfs-service-worker](https://github.com/ipfs/ipfs-service-worker)\n\n#### Can I use IPFS in my Electron App?\n\nYes you can and in many ways. Read https://github.com/ipfs/notes/issues/256 for the multiple options.\n\nIf your [electron-rebuild step is failing](https://github.com/ipfs/js-ipfs/issues/843), all you need to do is:\n\n```bash\n# Electron's version.\nexport npm_config_target=2.0.0\n# The architecture of Electron, can be ia32 or x64.\nexport npm_config_arch=x64\nexport npm_config_target_arch=x64\n# Download headers for Electron.\nexport npm_config_disturl=https://atom.io/download/electron\n# Tell node-pre-gyp that we are building for Electron.\nexport npm_config_runtime=electron\n# Tell node-pre-gyp to build module from source code.\nexport npm_config_build_from_source=true\n# Install all dependencies, and store cache to ~/.electron-gyp.\nHOME=~/.electron-gyp npm install\n```\n\nIf you find any other issue, please check the [`Electron Support` issue](https://github.com/ipfs/js-ipfs/issues/843).\n\n#### Have more questions?\n\nAsk for help in our forum at https://discuss.ipfs.io or in IRC (#ipfs on Freenode).\n\n## Running js-ipfs with Docker\n\nWe have automatic Docker builds setup with Docker Hub: https://hub.docker.com/r/ipfs/js-ipfs/\n\nAll branches in the Github repository maps to a tag in Docker Hub, except `master` Git branch which is mapped to `latest` Docker tag.\n\nYou can run js-ipfs like this:\n\n```\n$ docker run -it -p 4002:4002 -p 4003:4003 -p 5002:5002 -p 9090:9090 ipfs/js-ipfs:latest\n\ninitializing ipfs node at /root/.jsipfs\ngenerating 2048-bit RSA keypair...done\npeer identity: Qmbd5jx8YF1QLhvwfLbCTWXGyZLyEJHrPbtbpRESvYs4FS\nto get started, enter:\n\n         jsipfs files cat /ipfs/QmfGBRT6BbWJd7yUc2uYdaUZJBbnEFvTqehPFoSMQ6wgdr/readme\n\nInitializing daemon...\nUsing wrtc for webrtc support\nSwarm listening on /ip4/127.0.0.1/tcp/4003/ws/ipfs/Qmbd5jx8YF1QLhvwfLbCTWXGyZLyEJHrPbtbpRESvYs4FS\nSwarm listening on /ip4/172.17.0.2/tcp/4003/ws/ipfs/Qmbd5jx8YF1QLhvwfLbCTWXGyZLyEJHrPbtbpRESvYs4FS\nSwarm listening on /ip4/127.0.0.1/tcp/4002/ipfs/Qmbd5jx8YF1QLhvwfLbCTWXGyZLyEJHrPbtbpRESvYs4FS\nSwarm listening on /ip4/172.17.0.2/tcp/4002/ipfs/Qmbd5jx8YF1QLhvwfLbCTWXGyZLyEJHrPbtbpRESvYs4FS\nAPI is listening on: /ip4/0.0.0.0/tcp/5002\nGateway (readonly) is listening on: /ip4/0.0.0.0/tcp/9090\nDaemon is ready\n\n$ curl --silent localhost:5002/api/v0/id | jq .ID\n\"Qmbd5jx8YF1QLhvwfLbCTWXGyZLyEJHrPbtbpRESvYs4FS\"\n```\n\n\n## Packages\n\nListing of the main packages used in the IPFS ecosystem. There are also three specifications worth linking here:\n\n- [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core)\n- [`http-api-spec`](https://github.com/ipfs/http-api-spec)\n- [`cli spec`](https://github.com/ipfs/specs/tree/master/public-api/cli)\n\n\u003e This table is generated using the module `package-table` with `package-table --data=package-list.json`.\n\n| Package | Version | Deps | CI | Coverage | Lead Maintainer |\n| ---------|---------|---------|---------|---------|--------- |\n| **Files** |\n| [`ipfs-unixfs-engine`](//github.com/ipfs/js-ipfs-unixfs-engine) | [![npm](https://img.shields.io/npm/v/ipfs-unixfs-engine.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/js-ipfs-unixfs-engine/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-unixfs-engine.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-unixfs-engine) | N/A | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-unixfs-engine/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/js-ipfs-unixfs-engine) | [Alex Potsides](mailto:alex.potsides@protocol.ai) |\n| **DAG** |\n| [`ipld`](//github.com/ipld/js-ipld) | [![npm](https://img.shields.io/npm/v/ipld.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipld/js-ipld/releases) | [![Deps](https://david-dm.org/ipld/js-ipld.svg?style=flat-square)](https://david-dm.org/ipld/js-ipld) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipld/js-ipld/master)](https://ci.ipfs.team/job/ipld/job/js-ipld/job/master/) | [![codecov](https://codecov.io/gh/ipld/js-ipld/branch/master/graph/badge.svg)](https://codecov.io/gh/ipld/js-ipld) | [Volker Mische](mailto:volker.mische@gmail.com) |\n| [`ipld-dag-pb`](//github.com/ipld/js-ipld-dag-pb) | [![npm](https://img.shields.io/npm/v/ipld-dag-pb.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipld/js-ipld-dag-pb/releases) | [![Deps](https://david-dm.org/ipld/js-ipld-dag-pb.svg?style=flat-square)](https://david-dm.org/ipld/js-ipld-dag-pb) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipld/js-ipld-dag-pb/master)](https://ci.ipfs.team/job/ipld/job/js-ipld-dag-pb/job/master/) | [![codecov](https://codecov.io/gh/ipld/js-ipld-dag-pb/branch/master/graph/badge.svg)](https://codecov.io/gh/ipld/js-ipld-dag-pb) | [Volker Mische](mailto:volker.mische@gmail.com) |\n| [`ipld-dag-cbor`](//github.com/ipld/js-ipld-dag-cbor) | [![npm](https://img.shields.io/npm/v/ipld-dag-cbor.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipld/js-ipld-dag-cbor/releases) | [![Deps](https://david-dm.org/ipld/js-ipld-dag-cbor.svg?style=flat-square)](https://david-dm.org/ipld/js-ipld-dag-cbor) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipld/js-ipld-dag-cbor/master)](https://ci.ipfs.team/job/ipld/job/js-ipld-dag-cbor/job/master/) | [![codecov](https://codecov.io/gh/ipld/js-ipld-dag-cbor/branch/master/graph/badge.svg)](https://codecov.io/gh/ipld/js-ipld-dag-cbor) | [Volker Mische](mailto:volker.mische@gmail.com) |\n| **Repo** |\n| [`ipfs-repo`](//github.com/ipfs/js-ipfs-repo) | [![npm](https://img.shields.io/npm/v/ipfs-repo.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/js-ipfs-repo/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-repo.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-repo) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipfs/js-ipfs-repo/master)](https://ci.ipfs.team/job/ipfs/job/js-ipfs-repo/job/master/) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-repo/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/js-ipfs-repo) | [Jacob Heun](mailto:jacobheun@gmail.com) |\n| **Exchange** |\n| [`ipfs-block-service`](//github.com/ipfs/js-ipfs-block-service) | [![npm](https://img.shields.io/npm/v/ipfs-block-service.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/js-ipfs-block-service/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-block-service.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-block-service) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipfs/js-ipfs-block-service/master)](https://ci.ipfs.team/job/ipfs/job/js-ipfs-block-service/job/master/) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-block-service/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/js-ipfs-block-service) | N/A |\n| [`ipfs-bitswap`](//github.com/ipfs/js-ipfs-bitswap) | [![npm](https://img.shields.io/npm/v/ipfs-bitswap.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/js-ipfs-bitswap/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-bitswap.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-bitswap) | N/A | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-bitswap/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/js-ipfs-bitswap) | [Volker Mische](mailto:volker.mische@gmail.com) |\n| **libp2p** |\n| [`libp2p`](//github.com/libp2p/js-libp2p) | [![npm](https://img.shields.io/npm/v/libp2p.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-libp2p/master)](https://ci.ipfs.team/job/libp2p/job/js-libp2p/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p) | [Jacob Heun](mailto:jacobheun@gmail.com) |\n| [`libp2p-circuit`](//github.com/libp2p/js-libp2p-circuit) | [![npm](https://img.shields.io/npm/v/libp2p-circuit.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-circuit/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-circuit.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-circuit) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-libp2p-circuit/master)](https://ci.ipfs.team/job/libp2p/job/js-libp2p-circuit/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-circuit/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-circuit) | [Jacob Heun](mailto:jacobheun@gmail.com) |\n| [`libp2p-floodsub`](//github.com/libp2p/js-libp2p-floodsub) | [![npm](https://img.shields.io/npm/v/libp2p-floodsub.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-floodsub.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-floodsub) | N/A | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-floodsub/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-floodsub) | N/A |\n| [`libp2p-kad-dht`](//github.com/libp2p/js-libp2p-kad-dht) | [![npm](https://img.shields.io/npm/v/libp2p-kad-dht.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-kad-dht/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-kad-dht.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-kad-dht) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-libp2p-kad-dht/master)](https://ci.ipfs.team/job/libp2p/job/js-libp2p-kad-dht/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-kad-dht/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-kad-dht) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |\n| [`libp2p-mdns`](//github.com/libp2p/js-libp2p-mdns) | [![npm](https://img.shields.io/npm/v/libp2p-mdns.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-mdns/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-mdns.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-mdns) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-libp2p-mdns/master)](https://ci.ipfs.team/job/libp2p/job/js-libp2p-mdns/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-mdns/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-mdns) | N/A |\n| [`libp2p-mplex`](//github.com/libp2p/js-libp2p-mplex) | [![npm](https://img.shields.io/npm/v/libp2p-mplex.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-mplex/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-mplex.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-mplex) | N/A | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-mplex/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-mplex) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |\n| [`libp2p-railing`](//github.com/libp2p/js-libp2p-railing) | [![npm](https://img.shields.io/npm/v/libp2p-railing.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-railing/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-railing.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-railing) | N/A | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-railing/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-railing) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |\n| [`libp2p-secio`](//github.com/libp2p/js-libp2p-secio) | [![npm](https://img.shields.io/npm/v/libp2p-secio.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-secio/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-secio.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-secio) | N/A | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-secio/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-secio) | N/A |\n| [`libp2p-tcp`](//github.com/libp2p/js-libp2p-tcp) | [![npm](https://img.shields.io/npm/v/libp2p-tcp.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-tcp/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-tcp.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-tcp) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-libp2p-tcp/master)](https://ci.ipfs.team/job/libp2p/job/js-libp2p-tcp/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-tcp/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-tcp) | [Jacob Heun](mailto:jacobheun@gmail.com) |\n| [`libp2p-webrtc-star`](//github.com/libp2p/js-libp2p-webrtc-star) | [![npm](https://img.shields.io/npm/v/libp2p-webrtc-star.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-webrtc-star/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-webrtc-star.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-webrtc-star) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-libp2p-webrtc-star/master)](https://ci.ipfs.team/job/libp2p/job/js-libp2p-webrtc-star/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-webrtc-star/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-webrtc-star) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |\n| [`libp2p-websocket-star`](//github.com/libp2p/js-libp2p-websocket-star) | [![npm](https://img.shields.io/npm/v/libp2p-websocket-star.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-websocket-star/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-websocket-star.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websocket-star) | N/A | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-websocket-star/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-websocket-star) | [Jacob Heun](mailto:jacobheun@gmail.com) |\n| [`libp2p-websockets`](//github.com/libp2p/js-libp2p-websockets) | [![npm](https://img.shields.io/npm/v/libp2p-websockets.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-websockets/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-websockets.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websockets) | N/A | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-websockets/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-websockets) | N/A |\n| **Data Types** |\n| [`ipfs-block`](//github.com/ipfs/js-ipfs-block) | [![npm](https://img.shields.io/npm/v/ipfs-block.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/js-ipfs-block/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-block.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-block) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipfs/js-ipfs-block/master)](https://ci.ipfs.team/job/ipfs/job/js-ipfs-block/job/master/) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-block/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/js-ipfs-block) | N/A |\n| [`ipfs-unixfs`](//github.com/ipfs/js-ipfs-unixfs) | [![npm](https://img.shields.io/npm/v/ipfs-unixfs.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/js-ipfs-unixfs/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-unixfs.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-unixfs) | N/A | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-unixfs/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/js-ipfs-unixfs) | [Alex Potsides](mailto:alex.potsides@protocol.ai) |\n| [`peer-id`](//github.com/libp2p/js-peer-id) | [![npm](https://img.shields.io/npm/v/peer-id.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-peer-id/releases) | [![Deps](https://david-dm.org/libp2p/js-peer-id.svg?style=flat-square)](https://david-dm.org/libp2p/js-peer-id) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-peer-id/master)](https://ci.ipfs.team/job/libp2p/job/js-peer-id/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-peer-id/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-peer-id) | [Pedro Teixeira](mailto:i@pgte.me) |\n| [`peer-info`](//github.com/libp2p/js-peer-info) | [![npm](https://img.shields.io/npm/v/peer-info.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-peer-info/releases) | [![Deps](https://david-dm.org/libp2p/js-peer-info.svg?style=flat-square)](https://david-dm.org/libp2p/js-peer-info) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-peer-info/master)](https://ci.ipfs.team/job/libp2p/job/js-peer-info/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-peer-info/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-peer-info) | N/A |\n| [`multiaddr`](//github.com/multiformats/js-multiaddr) | [![npm](https://img.shields.io/npm/v/multiaddr.svg?maxAge=86400\u0026style=flat-square)](//github.com/multiformats/js-multiaddr/releases) | [![Deps](https://david-dm.org/multiformats/js-multiaddr.svg?style=flat-square)](https://david-dm.org/multiformats/js-multiaddr) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=multiformats/js-multiaddr/master)](https://ci.ipfs.team/job/multiformats/job/js-multiaddr/job/master/) | [![codecov](https://codecov.io/gh/multiformats/js-multiaddr/branch/master/graph/badge.svg)](https://codecov.io/gh/multiformats/js-multiaddr) | N/A |\n| [`multihashes`](//github.com/multiformats/js-multihash) | [![npm](https://img.shields.io/npm/v/multihashes.svg?maxAge=86400\u0026style=flat-square)](//github.com/multiformats/js-multihash/releases) | [![Deps](https://david-dm.org/multiformats/js-multihash.svg?style=flat-square)](https://david-dm.org/multiformats/js-multihash) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=multiformats/js-multihash/master)](https://ci.ipfs.team/job/multiformats/job/js-multihash/job/master/) | [![codecov](https://codecov.io/gh/multiformats/js-multihash/branch/master/graph/badge.svg)](https://codecov.io/gh/multiformats/js-multihash) | [David Dias](mailto:daviddias@ipfs.io) |\n| **Crypto** |\n| [`libp2p-crypto`](//github.com/libp2p/js-libp2p-crypto) | [![npm](https://img.shields.io/npm/v/libp2p-crypto.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-crypto/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-crypto.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-crypto) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=libp2p/js-libp2p-crypto/master)](https://ci.ipfs.team/job/libp2p/job/js-libp2p-crypto/job/master/) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-crypto/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-crypto) | [Friedel Ziegelmayer](mailto:dignifiedquire@gmail.com) |\n| [`libp2p-keychain`](//github.com/libp2p/js-libp2p-keychain) | [![npm](https://img.shields.io/npm/v/libp2p-keychain.svg?maxAge=86400\u0026style=flat-square)](//github.com/libp2p/js-libp2p-keychain/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-keychain.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-keychain) | N/A | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-keychain/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/js-libp2p-keychain) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |\n| **Generics/Utils** |\n| [`ipfs-http-client`](//github.com/ipfs/js-ipfs-http-client) | [![npm](https://img.shields.io/npm/v/ipfs-http-client.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/js-ipfs-http-client/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-http-client.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-http-client) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipfs/js-ipfs-http-client/master)](https://ci.ipfs.team/job/ipfs/job/js-ipfs-http-client/job/master/) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-http-client/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/js-ipfs-http-client) | [Alan Shaw](mailto:alan@tableflip.io) |\n| [`ipfs-multipart`](//github.com/ipfs/ipfs-multipart) | [![npm](https://img.shields.io/npm/v/ipfs-multipart.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/ipfs-multipart/releases) | [![Deps](https://david-dm.org/ipfs/ipfs-multipart.svg?style=flat-square)](https://david-dm.org/ipfs/ipfs-multipart) | N/A | [![codecov](https://codecov.io/gh/ipfs/ipfs-multipart/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/ipfs-multipart) | N/A |\n| [`is-ipfs`](//github.com/ipfs/is-ipfs) | [![npm](https://img.shields.io/npm/v/is-ipfs.svg?maxAge=86400\u0026style=flat-square)](//github.com/ipfs/is-ipfs/releases) | [![Deps](https://david-dm.org/ipfs/is-ipfs.svg?style=flat-square)](https://david-dm.org/ipfs/is-ipfs) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=ipfs/is-ipfs/master)](https://ci.ipfs.team/job/ipfs/job/is-ipfs/job/master/) | [![codecov](https://codecov.io/gh/ipfs/is-ipfs/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/is-ipfs) | [Marcin Rataj](mailto:lidel@lidel.org) |\n| [`multihashing`](//github.com/multiformats/js-multihashing) | [![npm](https://img.shields.io/npm/v/multihashing.svg?maxAge=86400\u0026style=flat-square)](//github.com/multiformats/js-multihashing/releases) | [![Deps](https://david-dm.org/multiformats/js-multihashing.svg?style=flat-square)](https://david-dm.org/multiformats/js-multihashing) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=multiformats/js-multihashing/master)](https://ci.ipfs.team/job/multiformats/job/js-multihashing/job/master/) | [![codecov](https://codecov.io/gh/multiformats/js-multihashing/branch/master/graph/badge.svg)](https://codecov.io/gh/multiformats/js-multihashing) | N/A |\n| [`mafmt`](//github.com/multiformats/js-mafmt) | [![npm](https://img.shields.io/npm/v/mafmt.svg?maxAge=86400\u0026style=flat-square)](//github.com/multiformats/js-mafmt/releases) | [![Deps](https://david-dm.org/multiformats/js-mafmt.svg?style=flat-square)](https://david-dm.org/multiformats/js-mafmt) | [![jenkins](https://ci.ipfs.team/buildStatus/icon?job=multiformats/js-mafmt/master)](https://ci.ipfs.team/job/multiformats/job/js-mafmt/job/master/) | [![codecov](https://codecov.io/gh/multiformats/js-mafmt/branch/master/graph/badge.svg)](https://codecov.io/gh/multiformats/js-mafmt) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |\n\n## Development\n\n### Clone and install dependencies\n\n```sh\n\u003e git clone https://github.com/ipfs/js-ipfs.git\n\u003e cd js-ipfs\n\u003e npm install\n```\n\n### Run tests\n\n```sh\n# run all the unit tests\n\u003e npm test\n\n# run just IPFS tests in Node.js\n\u003e npm run test:node\n\n# run just IPFS core tests\n\u003e npm run test:node:core\n\n# run just IPFS HTTP-API tests\n\u003e npm run test:node:http\n\n# run just IPFS CLI tests\n\u003e npm run test:node:cli\n\n# run just IPFS core tests in the Browser (Chrome)\n\u003e npm run test:browser\n\n# run some interface tests (block API) on Node.js\n\u003e npm run test:node:interface -- --grep '.block'\n```\n\n### Run interop tests\n\nRun the interop tests with https://github.com/ipfs/interop\n\n### Run benchmark tests\n\n```sh\n# run all the benchmark tests\n\u003e npm run benchmark\n\n# run just IPFS benchmarks in Node.js\n\u003e npm run benchmark:node\n\n# run just IPFS benchmarks in Node.js for an IPFS instance\n\u003e npm run benchmark:node:core\n\n# run just IPFS benchmarks in Node.js for an IPFS daemon\n\u003e npm run benchmark:node:http\n\n# run just IPFS benchmarks in the browser (Chrome)\n\u003e npm run benchmark:browser\n```\n\n### Lint\n\n**Conforming to linting rules is a prerequisite to commit to js-ipfs.**\n\n```sh\n\u003e npm run lint\n```\n\n### Build a dist version\n\n```sh\n\u003e npm run build\n```\n\n### [Runtime Support](https://github.com/ipfs/js-ipfs/issues/536)\n\n### Code Architecture and folder Structure\n\n![](/img/overview.png)\n\n##### Source code\n\n```Bash\n\u003e tree src -L 2\nsrc                 # Main source code folder\n├── cli             # Implementation of the IPFS CLI\n│   └── ...\n├── http            # The HTTP-API implementation of IPFS as defined by http-api-spec\n├── core            # IPFS implementation, the core (what gets loaded in browser)\n│   ├── components  # Each of IPFS subcomponent\n│   └── ...\n└── ...\n```\n\n### Monitoring\n\nThe HTTP API exposed with js-ipfs can also be used for exposing metrics about\nthe running js-ipfs node and other Node.js metrics.\n\nTo enable it, you need to set the environment variable `IPFS_MONITORING` (any value)\n\nOnce the environment variable is set and the js-ipfs daemon is running, you can get\nthe metrics (in prometheus format) by making a GET request to the following endpoint:\n\n```\nhttp://localhost:5002/debug/metrics/prometheus\n```\n\n### IPFS Architecture\n\n![](/img/architecture.png)\n\n[Annotated version](https://user-images.githubusercontent.com/1211152/47606420-b6265780-da13-11e8-923b-b365a8534e0e.png)j\n\nWhat does this image explain?\n\n- IPFS uses `ipfs-repo` which picks `fs` or `indexeddb` as its storage drivers, depending if it is running in Node.js or in the Browser.\n- The exchange protocol, `bitswap`, uses the Block Service which in turn uses the Repo, offering a get and put of blocks to the IPFS implementation.\n- The DAG API (previously Object) comes from the IPLD Resolver, it can support several IPLD Formats (i.e: dag-pb, dag-cbor, etc).\n- The Files API uses `ipfs-unixfs-engine` to import and export files to and from IPFS.\n- libp2p, the network stack of IPFS, uses libp2p to dial and listen for connections, to use the DHT, for discovery mechanisms, and more.\n\n## Contribute\n\nIPFS implementation in JavaScript is a work in progress. As such, there's a few things you can do right now to help out:\n\n- Go through the modules below and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically.\n- **Perform code reviews**. More eyes will help (a) speed the project along, (b) ensure quality, and (c) reduce possible future bugs.\n- Take a look at go-ipfs and some of the planning repositories or issues: for instance, the [libp2p spec](https://github.com/ipfs/specs/pull/19). Contributions here that would be most helpful are **top-level comments** about how it should look based on our understanding. Again, the more eyes the better.\n- **Add tests**. There can never be enough tests.\n\n### Want to hack on IPFS?\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n## License\n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fipfs%2Fjs-ipfs.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fipfs%2Fjs-ipfs?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fether1project%2Fjs-ethofs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fether1project%2Fjs-ethofs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fether1project%2Fjs-ethofs/lists"}