|
| 1 | +# multiformats |
| 2 | + |
| 3 | +This library defines common interfaces and low level building blocks for varios inter-related multiformat technologies (multicodec, multihash, multibase, |
| 4 | +and CID). They can be used to implement custom custom base |
| 5 | +encoders / decoders / codecs, codec encoders /decoders and multihash hashers that comply to the interface that layers above assume. |
| 6 | + |
| 7 | +Library provides implementations for most basics and many others can be found in linked repositories. |
| 8 | + |
| 9 | +## Interfaces |
| 10 | + |
| 11 | +```js |
| 12 | +import { CID } from 'multiformats/cid' |
| 13 | +import * as json from 'multiformats/codecs/json' |
| 14 | +import { sha256 } from 'multiformats/hashes/sha2' |
| 15 | + |
| 16 | +const bytes = json.encode({ hello: 'world' }) |
| 17 | + |
| 18 | +const hash = await sha256.digest(bytes) |
| 19 | +const cid = CID.create(1, json.code, hash) |
| 20 | +//> CID(bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea) |
| 21 | +``` |
| 22 | + |
| 23 | +### Creating Blocks |
| 24 | + |
| 25 | +```js |
| 26 | +import Block from 'multiformats/block' |
| 27 | +import * as codec from '@ipld/dag-cbor' |
| 28 | +import { sha256 as hasher } from 'multiformats/hashes/sha2' |
| 29 | + |
| 30 | +const value = { hello: 'world' } |
| 31 | + |
| 32 | +// encode a block |
| 33 | +let block = await Block.encode({ value, codec, hasher }) |
| 34 | + |
| 35 | +block.value // { hello: 'world' } |
| 36 | +block.bytes // Uint8Array |
| 37 | +block.cid // CID() w/ sha2-256 hash address and dag-cbor codec |
| 38 | + |
| 39 | +// you can also decode blocks from their binary state |
| 40 | +block = await Block.decode({ bytes: block.bytes, codec, hasher }) |
| 41 | + |
| 42 | +// if you have the cid you can also verify the hash on decode |
| 43 | +block = await Block.create({ bytes: block.bytes, cid: block.cid, codec, hasher }) |
| 44 | +``` |
| 45 | + |
| 46 | +### Multibase Encoders / Decoders / Codecs |
| 47 | + |
| 48 | +CIDs can be serialized to string representation using multibase encoders that |
| 49 | +implement [`MultibaseEncoder`](https://github.com/multiformats/js-multiformats/blob/master/src/bases/interface.ts) interface. Library |
| 50 | +provides quite a few implementations that can be imported: |
| 51 | + |
| 52 | +```js |
| 53 | +import { base64 } from "multiformats/bases/base64" |
| 54 | +cid.toString(base64.encoder) |
| 55 | +//> 'mAYAEEiCTojlxqRTl6svwqNJRVM2jCcPBxy+7mRTUfGDzy2gViA' |
| 56 | +``` |
| 57 | + |
| 58 | +Parsing CID string serialized CIDs requires multibase decoder that implements |
| 59 | +[`MultibaseDecoder`](https://github.com/multiformats/js-multiformats/blob/master/src/bases/interface.ts) interface. Library provides a |
| 60 | +decoder for every encoder it provides: |
| 61 | + |
| 62 | +```js |
| 63 | +CID.parse('mAYAEEiCTojlxqRTl6svwqNJRVM2jCcPBxy+7mRTUfGDzy2gViA', base64.decoder) |
| 64 | +//> CID(bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea) |
| 65 | +``` |
| 66 | + |
| 67 | +Dual of multibase encoder & decoder is defined as multibase codec and it exposes |
| 68 | +them as `encoder` and `decoder` properties. For added convenience codecs also |
| 69 | +implement `MultibaseEncoder` and `MultibaseDecoder` interfaces so they could be |
| 70 | +used as either or both: |
| 71 | + |
| 72 | + |
| 73 | +```js |
| 74 | +cid.toString(base64) |
| 75 | +CID.parse(cid.toString(base64), base64) |
| 76 | +``` |
| 77 | + |
| 78 | +**Note:** CID implementation comes bundled with `base32` and `base58btc` |
| 79 | +multibase codecs so that CIDs can be base serialized to (version specific) |
| 80 | +default base encoding and parsed without having to supply base encoders/decoders: |
| 81 | + |
| 82 | +```js |
| 83 | +const v1 = CID.parse('bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea') |
| 84 | +v1.toString() |
| 85 | +//> 'bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea' |
| 86 | + |
| 87 | +const v0 = CID.parse('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') |
| 88 | +v0.toString() |
| 89 | +//> 'QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n' |
| 90 | +v0.toV1().toString() |
| 91 | +//> 'bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku' |
| 92 | +``` |
| 93 | + |
| 94 | +### Multicodec Encoders / Decoders / Codecs |
| 95 | + |
| 96 | +Library defines [`BlockEncoder`, `BlockDecoder` and `BlockCodec` interfaces](https://github.com/multiformats/js-multiformats/blob/master/src/codecs/interface.ts) |
| 97 | +and utility function to take care of the boilerplate when implementing them: |
| 98 | + |
| 99 | +```js |
| 100 | +import { codec } from 'multiformats/codecs/codec' |
| 101 | + |
| 102 | +const json = codec({ |
| 103 | + name: 'json', |
| 104 | + // As per multiformats table |
| 105 | + // https://github.com/multiformats/multicodec/blob/master/table.csv#L113 |
| 106 | + code: 0x0200, |
| 107 | + encode: json => new TextEncoder().encode(JSON.stringify(json)), |
| 108 | + decode: bytes => JSON.parse(new TextDecoder().decode(bytes)) |
| 109 | +}) |
| 110 | +``` |
| 111 | + |
| 112 | +Just like with multibase, here codecs are duals of `encoder` and `decoder` parts, |
| 113 | +but they also implement both interfaces for convenience: |
| 114 | + |
| 115 | +```js |
| 116 | +const hello = json.encoder.encode({ hello: 'world' }) |
| 117 | +json.decode(b1) |
| 118 | +//> { hello: 'world' } |
| 119 | +``` |
| 120 | + |
| 121 | +### Multihash Hashers |
| 122 | + |
| 123 | +This library defines [`MultihashHasher` and `MultihashDigest` interfaces](https://github.com/multiformats/js-multiformats/blob/master/src/hashes/interface.ts) |
| 124 | +and convinient function for implementing them: |
| 125 | + |
| 126 | +```js |
| 127 | +import * as hasher from 'multiformats/hashes/hasher') |
| 128 | + |
| 129 | +const sha256 = hasher.from({ |
| 130 | + // As per multiformats table |
| 131 | + // https://github.com/multiformats/multicodec/blob/master/table.csv#L9 |
| 132 | + name: 'sha2-256', |
| 133 | + code: 0x12, |
| 134 | + |
| 135 | + encode: (input) => new Uint8Array(crypto.createHash('sha256').update(input).digest()) |
| 136 | +}) |
| 137 | + |
| 138 | +const hash = await sha256.digest(json.encode({ hello: 'world' })) |
| 139 | +CID.create(1, json.code, hash) |
| 140 | + |
| 141 | +//> CID(bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea) |
| 142 | +``` |
| 143 | + |
| 144 | + |
| 145 | + |
| 146 | +# Implementations |
| 147 | + |
| 148 | +By default, no base encodings (other than base32 & base58btc), hash functions, |
| 149 | +or codec implementations are included exposed by `multiformats`, you need to |
| 150 | +import the ones you need yourself. |
| 151 | + |
| 152 | +## Multibase codecs |
| 153 | + |
| 154 | +| bases | import | repo | |
| 155 | + --- | --- | --- | |
| 156 | +`base16` | `multiformats/bases/base16` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) | |
| 157 | +`base32`, `base32pad`, `base32hex`, `base32hexpad`, `base32z` | `multiformats/bases/base32` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) | |
| 158 | +`base64`, `base64pad`, `base64url`, `base64urlpad` | `multiformats/bases/base64` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) | |
| 159 | +`base58btc`, `base58flick4` | `multiformats/bases/base58` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) | |
| 160 | + |
| 161 | +## Multihash hashers |
| 162 | + |
| 163 | +| hashes | import | repo | |
| 164 | +| --- | --- | --- | |
| 165 | +| `sha2-256`, `sha2-512` | `multiformats/hashes/sha2` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/src/hashes) | |
| 166 | +| `sha3-224`, `sha3-256`, `sha3-384`,`sha3-512`, `shake-128`, `shake-256`, `keccak-224`, `keccak-256`, `keccak-384`, `keccak-512` | `@multiformats/sha3` | [multiformats/js-sha3](https://github.com/multiformats/js-sha3) | |
| 167 | +| `identity` | `multiformats/hashes/identity` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/src/hashes/identity.js) | |
| 168 | +| `murmur3-128`, `murmur3-32` | `@multiformats/murmur3` | [multiformats/js-murmur3](https://github.com/multiformats/js-murmur3) | |
| 169 | +| `blake2b-*`, `blake2s-*` | `@multiformats/blake2` | [multiformats/js-blake2](https://github.com/multiformats/js-blake2) | |
| 170 | + |
| 171 | +## Codec Implementations (multicodec) |
| 172 | + |
| 173 | +| codec | import | repo | |
| 174 | +| --- | --- | --- | |
| 175 | +| `raw` | `multiformats/codecs/raw` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/src/codecs) | |
| 176 | +| `json` | `multiformats/codecs/json` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/src/codecs) | |
| 177 | +| `dag-cbor` | `@ipld/dag-cbor` | [ipld/js-dag-cbor](https://github.com/ipld/js-dag-cbor) | |
| 178 | +| `dag-json` | `@ipld/dag-json` | [ipld/js-dag-json](https://github.com/ipld/js-dag-json) | |
| 179 | +| `dag-pb` | `@ipld/dag-pb` | [ipld/js-dag-pb](https://github.com/ipld/js-dag-pb) | |
| 180 | +| `dag-jose` | `dag-jose`| [ceramicnetwork/js-dag-jose](https://github.com/ceramicnetwork/js-dag-jose) | |
| 181 | + |
| 182 | + |
| 183 | +## TypeScript support |
| 184 | + |
| 185 | +This project is distributed with type definitions for TypeScript. |
| 186 | + |
| 187 | +[A bug in TypeScript < 4.2](https://github.com/microsoft/TypeScript/issues/41258) causes typechecking errors in these type definitions when compiling a project that uses them. This is fixed in [TypeScript v4.2](https://github.com/microsoft/TypeScript/releases/tag/v4.2.2) so please upgrade if you hit that issue. |
| 188 | + |
| 189 | +## License |
| 190 | + |
| 191 | +Licensed under either of |
| 192 | + |
| 193 | + * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) |
| 194 | + * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) |
| 195 | + |
| 196 | +### Contribution |
| 197 | + |
| 198 | +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. |
0 commit comments