diff --git a/SPEC/BITSWAP.md b/SPEC/BITSWAP.md index 9b97dc62..245f3a13 100644 --- a/SPEC/BITSWAP.md +++ b/SPEC/BITSWAP.md @@ -3,9 +3,6 @@ * [bitswap.wantlist](#bitswapwantlist) * [bitswap.stat](#bitswapstat) -### ⚠️ Note -Although not listed in the documentation, all the following APIs that actually return a **promise** can also accept a **final callback** parameter. - ### `bitswap.wantlist` > Returns the wantlist, optionally filtered by peer ID @@ -16,23 +13,18 @@ Although not listed in the documentation, all the following APIs that actually r | Type | Description | | -------- | -------- | -| `Promise` | An object representing the wantlist | - -the returned object contains the following keys: - -- `Keys` An array of objects containing the following keys: - - `/` A string multihash +| `Promise` | An array of [CID][cid]s currently in the wantlist | **Example:** ```JavaScript const list = await ipfs.bitswap.wantlist() console.log(list) -// { Keys: [{ '/': 'QmHash' }] } +// [ CID('QmHash') ] const list2 = await ipfs.bitswap.wantlist(peerId) console.log(list2) -// { Keys: [{ '/': 'QmHash' }] } +// [ CID('QmHash') ] ``` A great source of [examples][] can be found in the tests for this API. @@ -51,11 +43,11 @@ Note: `bitswap.stat` and `stats.bitswap` can be used interchangeably. | -------- | -------- | | `Promise` | An object that contains information about the bitswap agent | -the returned object contains the following keys: +The returned object contains the following keys: - `provideBufLen` is an integer. -- `wantlist` (array of CIDs) -- `peers` (array of peer IDs) +- `wantlist` (array of [CID][cid]s) +- `peers` (array of peer IDs as [CID][cid] instances) - `blocksReceived` is a [BigNumber Int][1] - `dataReceived` is a [BigNumber Int][1] - `blocksSent` is a [BigNumber Int][1] @@ -70,17 +62,17 @@ const stats = await ipfs.bitswap.stat() console.log(stats) // { // provideBufLen: 0, -// wantlist: [ { '/': 'QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM' } ], +// wantlist: [ CID('QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM') ], // peers: -// [ 'QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', -// 'QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', -// 'QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd' ], +// [ CID('QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM'), +// CID('QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu'), +// CID('QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd') ], // blocksReceived: 0, // dataReceived: 0, // blocksSent: 0, // dataSent: 0, // dupBlksReceived: 0, -// dupDataReceived: 0 +// dupDataReceived: 0 // } ``` @@ -88,3 +80,4 @@ A great source of [examples][] can be found in the tests for this API. [1]: https://github.com/MikeMcl/bignumber.js/ [examples]: https://github.com/ipfs/interface-ipfs-core/blob/master/src/bitswap +[cid]: https://www.npmjs.com/package/cids diff --git a/SPEC/BLOCK.md b/SPEC/BLOCK.md index 1c303725..a3a20d13 100644 --- a/SPEC/BLOCK.md +++ b/SPEC/BLOCK.md @@ -5,9 +5,6 @@ * [block.rm](#blockrm) * [block.stat](#blockstat) -### ⚠️ Note -Although not listed in the documentation, all the following APIs that actually return a **promise** can also accept a **final callback** parameter. - #### `block.get` > Get a raw IPFS block. @@ -114,22 +111,32 @@ A great source of [examples][] can be found in the tests for this API. `options` is an Object that can contain the following properties: -- force (boolean): Ignores nonexistent blocks. -- quiet (boolean): write minimal output +- `force` (boolean): Ignores nonexistent blocks. +- `quiet` (boolean): write minimal output **Returns** | Type | Description | | -------- | -------- | -| `Promise` | An array of objects containing hash and (potentially) error strings | +| `AsyncIterable` | An async iterable that yields objects containing hash and (potentially) error strings | -Note: If an error string is present for a given object in the returned array, the block with that hash was not removed and the string will contain the reason why, for example if the block was pinned. +Each object yielded is of the form: + +```js +{ + hash: string, + error: string +} +``` + +Note: If an error string is present for a given object, the block with that hash was not removed and the string will contain the reason why, for example if the block was pinned. **Example:** ```JavaScript -const result = await ipfs.block.rm(cid) -console.log(result[0].hash) +for await (const result of ipfs.block.rm(cid)) { + console.log(result.hash) +} ``` A great source of [examples][] can be found in the tests for this API. diff --git a/SPEC/BOOTSTRAP.md b/SPEC/BOOTSTRAP.md index ba562a57..2dbe5ce0 100644 --- a/SPEC/BOOTSTRAP.md +++ b/SPEC/BOOTSTRAP.md @@ -4,15 +4,12 @@ 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. +> Only edit this list if you understand the risks of adding or removing nodes * [bootstrap.add](#bootstrapadd) * [bootstrap.list](#bootstraplist) * [bootstrap.rm](#bootstraprm) -### ⚠️ Note -Although not listed in the documentation, all the following APIs that actually return a **promise** can also accept a **final callback** parameter. - #### `bootstrap.add` > Add a peer address to the bootstrap list diff --git a/SPEC/CONFIG.md b/SPEC/CONFIG.md index 5dd37790..725a59d4 100644 --- a/SPEC/CONFIG.md +++ b/SPEC/CONFIG.md @@ -6,9 +6,6 @@ * [config.profiles.list](#configprofileslist) * [config.profiles.apply](#configprofilesapply) -### ⚠️ Note -Although not listed in the documentation, all the following APIs that actually return a **promise** can also accept a **final callback** parameter. - #### `config.get` > Returns the currently being used config. If the daemon is off, it returns the stored config. diff --git a/SPEC/DAG.md b/SPEC/DAG.md index 270a30f6..c4ef9c49 100644 --- a/SPEC/DAG.md +++ b/SPEC/DAG.md @@ -10,9 +10,6 @@ _Explore the DAG API through interactive coding challenges in our ProtoSchool tu - _[P2P data links with content addressing](https://proto.school/#/basics/) (beginner)_ - _[Blogging on the Decentralized Web](https://proto.school/#/blog/) (intermediate)_ -### ⚠️ Note -Although not listed in the documentation, all the following APIs that actually return a **promise** can also accept a **final callback** parameter. - #### `dag.put` > Store an IPLD format node diff --git a/SPEC/DHT.md b/SPEC/DHT.md index 31c8a5d3..f856555f 100644 --- a/SPEC/DHT.md +++ b/SPEC/DHT.md @@ -7,79 +7,80 @@ * [dht.put](#dhtput) * [dht.query](#dhtquery) -### ⚠️ Note -Although not listed in the documentation, all the following APIs that actually return a **promise** can also accept a **final callback** parameter. - #### `dht.findPeer` -> Retrieve the Peer Info of a reachable node in the network. +> Find the multiaddresses associated with a Peer ID ##### `ipfs.dht.findPeer(peerId)` -Where `peerId` is a IPFS/libp2p Id from [PeerId](https://github.com/libp2p/js-peer-id) type. +Where `peerId` is a Peer ID in `String`, [`CID`](https://github.com/multiformats/js-cid) or [`PeerId`](https://github.com/libp2p/js-peer-id) format. **Returns** | Type | Description | | -------- | -------- | -| `Promise` | An object type [`PeerInfo`](https://github.com/libp2p/js-peer-info) | +| `Promise<{ id: CID, addrs: Multiaddr[] }>` | A promise that resolves to an object with `id` and `addrs`. `id` is a [`CID`](https://github.com/multiformats/js-cid) - the peer's ID and `addrs` is an array of [Multiaddr](https://github.com/multiformats/js-multiaddr/) - addresses for the peer. | **Example:** ```JavaScript -var id = PeerId.create() - -const peerInfo = await ipfs.dht.findPeer(id) -// peerInfo will contain the multiaddrs of that peer -const id = peerInfo.id -const addrs = peerInfo.multiaddrs +const info = await ipfs.dht.findPeer('QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt') + +console.log(info.id.toString()) +/* +QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt +*/ + +info.addrs.forEach(addr => console.log(addr.toString())) +/* +/ip4/147.75.94.115/udp/4001/quic +/ip6/2604:1380:3000:1f00::1/udp/4001/quic +/dnsaddr/bootstrap.libp2p.io +/ip6/2604:1380:3000:1f00::1/tcp/4001 +/ip4/147.75.94.115/tcp/4001 +*/ ``` A great source of [examples][] can be found in the tests for this API. #### `dht.findProvs` -> Retrieve the providers for content that is addressed by an hash. +> Find peers that can provide a specific value, given a CID. -##### `ipfs.dht.findProvs(hash, [options])` +##### `ipfs.dht.findProvs(cid, [options])` -Where `hash` is a multihash. +Where `cid` is a CID as a `String`, `Buffer` or [`CID`](https://github.com/multiformats/js-cid) instance. -`options` an optional object with the following properties - - `timeout` - a maximum timeout in milliseconds - - `maxNumProviders` - a maximum number of providers to find +`options` an optional object with the following properties: + - `numProviders` - the number of providers to find. Default: 20 + +Note that if `options.numProviders` are not found an error will be thrown. **Returns** | Type | Description | | -------- | -------- | -| `Promise` | An array of type [`PeerInfo`](https://github.com/libp2p/js-peer-info) | - -each entry of the returned array is composed by the peerId, as well as an array with its adresses. +| `AsyncIterable<{ id: CID, addrs: Multiaddr[] }>` | A async iterable that yields objects with `id` and `addrs`. `id` is a [`CID`](https://github.com/multiformats/js-cid) - the peer's ID and `addrs` is an array of [Multiaddr](https://github.com/multiformats/js-multiaddr/) - addresses for the peer. | **Example:** ```JavaScript -const provs = await ipfs.dht.findProvs(multihash) -provs.forEach(prov => { - console.log(prov.id.toB58String()) -}) - -const provs2 = await ipfs.dht.findProvs(multihash, { timeout: 4000 }) -provs2.forEach(prov => { - console.log(prov.id.toB58String()) -}) +const providers = ipfs.dht.findProvs('QmdPAhQRxrDKqkGPvQzBvjYe3kU8kiEEAd2J6ETEamKAD9') + +for await (const provider of providers) { + console.log(provider.id.toString()) +} ``` A great source of [examples][] can be found in the tests for this API. #### `dht.get` -> Retrieve a value from DHT +> Given a key, query the routing system for its best value. ##### `ipfs.dht.get(key)` -Where `key` is a Buffer. +Where `key` is a `Buffer`. **Returns** @@ -99,70 +100,158 @@ A great source of [examples][] can be found in the tests for this API. > Announce to the network that you are providing given values. -##### `ipfs.dht.provide(cid)` +##### `ipfs.dht.provide(cid, [options])` + +Where `cid` is a CID or array of CIDs as a `String`, `Buffer` or [`CID`](https://github.com/multiformats/js-cid) instance. -Where `cid` is a CID or array of CIDs. +`options` an optional object with the following properties: + - `recursive` - boolean, set to `true` to recursively provide the entire graph. Default `false`. **Returns** | Type | Description | | -------- | -------- | -| `Promise` | If action is successfully completed. Otherwise an error will be thrown | +| `AsyncIterable` | DHT query messages. See example below for structure. | + +Note: You must consume the iterable to completion to complete the provide operation. **Example:** ```JavaScript -await ipfs.dht.provide(cid) +for await (const message of ipfs.dht.provide('QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR')) { + console.log(message) +} + +/* +Prints objects like: + +{ + extra: 'dial backoff', + id: CID(QmWtewmnzJiQevJPSmG9s8aC7yRfK2WXTCdRc1pCbDFu6z), + responses: [ + { + addrs: [ + Multiaddr(/ip4/127.0.0.1/tcp/4001), + Multiaddr(/ip4/172.20.0.3/tcp/4001), + Multiaddr(/ip4/35.178.190.196/tcp/1024) + ], + id: CID(QmRz5Nth4jTFuJJKcjyb6uwvrhxWbruRvamKY2PJxwJKw8) + } + ], + type: 1 +} + +For message `type` values, see: +https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L15-L24 +*/ +``` + +Alternatively you can simply "consume" the iterable: + +```js +const { consume } = require('streaming-iterables') +await consume(ipfs.dht.provide('QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR')) ``` A great source of [examples][] can be found in the tests for this API. #### `dht.put` -> Store a value on the DHT +> Write a key/value pair to the routing system. ##### `ipfs.dht.put(key, value)` -Where `key` is a Buffer and `value` is a Buffer. +Where `key` is a `Buffer` and `value` is a `Buffer`. **Returns** | Type | Description | | -------- | -------- | -| `Promise` | If action is successfully completed. Otherwise an error will be thrown | +| `AsyncIterable` | DHT query messages. See example below for structure. | **Example:** ```JavaScript -await ipfs.dht.put(key, value) +for await (const message of ipfs.dht.put(key, value)) { + console.log(message) +} + +/* +Prints objects like: + +{ + extra: 'dial backoff', + id: CID(QmWtewmnzJiQevJPSmG9s8aC7yRfK2WXTCdRc1pCbDFu6z), + responses: [ + { + addrs: [ + Multiaddr(/ip4/127.0.0.1/tcp/4001), + Multiaddr(/ip4/172.20.0.3/tcp/4001), + Multiaddr(/ip4/35.178.190.196/tcp/1024) + ], + id: CID(QmRz5Nth4jTFuJJKcjyb6uwvrhxWbruRvamKY2PJxwJKw8) + } + ], + type: 1 +} + +For message `type` values, see: +https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L15-L24 +*/ +``` + +Alternatively you can simply "consume" the iterable: + +```js +const { consume } = require('streaming-iterables') +await consume(ipfs.dht.put(key, value)) ``` A great source of [examples][] can be found in the tests for this API. #### `dht.query` -> Queries the network for the 'closest peers' to a given key. 'closest' is defined by the rules of the underlying Peer Routing mechanism. +> Find the closest Peer IDs to a given Peer ID by querying the DHT. ##### `ipfs.dht.query(peerId)` -Where `peerId` is a IPFS/libp2p Id of type [PeerId](https://github.com/libp2p/js-peer-id). +Where `peerId` is a Peer ID in `String`, [`CID`](https://github.com/multiformats/js-cid) or [`PeerId`](https://github.com/libp2p/js-peer-id) format. **Returns** | Type | Description | | -------- | -------- | -| `Promise` | An array of objects of type [PeerInfo](https://github.com/libp2p/js-peer-info) | +| `AsyncIterable` | DHT query messages. See example below for structure. | **Example:** ```JavaScript -const id = PeerId.create() - -const peerInfos = await ipfs.dht.query(id) - -peerInfos.forEach(p => { - console.log(p.id.toB58String()) -}) +for await (const info of ipfs.dht.query('QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt')) { + console.log(info) +} + +/* +Prints objects like: + +{ + extra: 'dial backoff', + id: CID(QmWtewmnzJiQevJPSmG9s8aC7yRfK2WXTCdRc1pCbDFu6z), + responses: [ + { + addrs: [ + Multiaddr(/ip4/127.0.0.1/tcp/4001), + Multiaddr(/ip4/172.20.0.3/tcp/4001), + Multiaddr(/ip4/35.178.190.196/tcp/1024) + ], + id: CID(QmRz5Nth4jTFuJJKcjyb6uwvrhxWbruRvamKY2PJxwJKw8) + } + ], + type: 1 +} + +For message `type` values, see: +https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L15-L24 +*/ ``` A great source of [examples][] can be found in the tests for this API. diff --git a/SPEC/FILES.md b/SPEC/FILES.md index d85cc86c..cdc18df6 100644 --- a/SPEC/FILES.md +++ b/SPEC/FILES.md @@ -4,104 +4,117 @@ #### The Regular API The regular, top-level API for add, cat, get and ls Files on IPFS - - [add](#add) - - [addFromFs](#addfromfs) - - [addFromStream](#addfromstream) - - [addFromURL](#addfromurl) - - [addPullStream](#addpullstream) - - [addReadableStream](#addreadablestream) - - [cat](#cat) - - [catPullStream](#catpullstream) - - [catReadableStream](#catreadablestream) - - [get](#get) - - [getPullStream](#getpullstream) - - [getReadableStream](#getreadablestream) - - [ls](#ls) - - [lsPullStream](#lspullstream) - - [lsReadableStream](#lsreadablestream) +- [add](#add) +- [cat](#cat) +- [get](#get) +- [ls](#ls) #### The Files API The Files API, aka MFS (Mutable File System) +- [files.chmod](#fileschmod) +- [files.cp](#filescp) +- [files.flush](#filesflush) +- [files.ls](#filesls) +- [files.mkdir](#filesmkdir) +- [files.mv](#filesmv) +- [files.read](#filesread) +- [files.rm](#filesrm) +- [files.stat](#filesstat) +- [files.touch](#filestouch) +- [files.write](#fileswrite) _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - - [files.chmod](#fileschmod) - - [files.cp](#filescp) - - [files.flush](#filesflush) - - [files.ls](#filesls) - - [files.lsReadableStream](#fileslsreadablestream) - - [files.lsPullStream](#fileslspullstream) - - [files.mkdir](#filesmkdir) - - [files.mv](#filesmv) - - [files.read](#filesread) - - [files.readPullStream](#filesreadpullstream) - - [files.readReadableStream](#filesreadreadablestream) - - [files.rm](#filesrm) - - [files.stat](#filesstat) - - [files.touch](#filestouch) - - [files.write](#fileswrite) - -### ⚠️ Note -Although not listed in the documentation, all the following APIs that actually return a **promise** can also accept a **final callback** parameter. #### `add` -> Add files and data to IPFS. +> Import files and data into IPFS. ##### `ipfs.add(data, [options])` Where `data` may be: -- a [`Buffer instance`][b] -- a [`Readable Stream`][rs] -- a [`Pull Stream`][ps] -- a [`File`][file] -- an array of objects, each of the form: -```JavaScript +* `Bytes` (alias for `Buffer`|`ArrayBuffer`|`TypedArray`) [single file] +* `Bloby` (alias for: `Blob`|`File`) [single file] +* `string` [single file] +* `FileObject` (see below for definition) [single file] +* `Iterable` [single file] +* `Iterable` [single file] +* `Iterable` [multiple files] +* `Iterable` [multiple files] +* `Iterable` [multiple files] +* `AsyncIterable` [single file] +* `AsyncIterable` [multiple files] +* `AsyncIterable` [multiple files] +* `AsyncIterable` [multiple files] + +`FileObject` is a plain JS object of the following form: + +```js { - path: '/tmp/myfile.txt', // The file path - content: // A Buffer, Readable Stream, Pull Stream or File with the contents of the file - mode: // optional integer mode to store the entry with - mtime: