diff --git a/README.md b/README.md
index 7444a746..0dd672b7 100644
--- a/README.md
+++ b/README.md
@@ -60,15 +60,29 @@ import 'ipld-explorer-components/dist/components/loader/Loader.css'
**NOTE:** PRs adding an old IPLDFormat codec would need the old `blockcodec-to-ipld-format` tool which has many out of date deps. We will only accept PRs for adding BlockCodec interface codecs.
-To add another codec you will need to:
+To add another codec you will need to update all locations containing the comment `// #WhenAddingNewCodec`:
-1. Add a dependency on the codec to this package
-1. Add the codec in the switch statement in src/lib/codec-importer.ts
-1. Add a unit test to src/lib/resolve-ipld-path.test.js and ensure that calling `resolveIpldPath` returns the expected results
- * If the default `resolveFn` in src/lib/get-codec-for-cid.ts doesn't resolve your paths correctly, you will need to add a resolver method for your codec to the `codecResolverMap` in src/lib/get-codec-for-cid.ts
+1. Add a dependency on the codec to this package (if it's not already in multiformats or other package)
+1. Add the codec in the switch statement in [./src/lib/codec-importer.ts](./src/lib/codec-importer.ts)
+1. Update [./src/lib/get-codec-name-from-code.ts](./src/lib/get-codec-name-from-code.ts) to return the codec name for your codec
+1. Add a unit test to [./src/lib/resolve-ipld-path.test.js](./src/lib/resolve-ipld-path.test.js) and ensure that calling `resolveIpldPath` returns the expected results
+ * If the default `resolveFn` in [./src/lib/get-codec-for-cid.ts](./src/lib/get-codec-for-cid.ts) doesn't resolve your paths correctly, you will need to add a resolver method for your codec to the `codecResolverMap` in [./src/lib/get-codec-for-cid.ts](./src/lib/get-codec-for-cid.ts)
see https://github.com/ipfs/ipld-explorer-components/pull/360#discussion_r1206251817 for history.
+### Adding another hasher
+
+To add another hasher you will need to update all locations containing the comment `// #WhenAddingNewHasher`:
+
+1. Add a dependency on the hasher to this package (if it's not already in multiformats or other package)
+1. Add the hasher in the switch statement in [./src/lib/get-codec-for-cid.ts](./src/lib/get-codec-for-cid.ts)
+1. Update [./src/lib/hash-importer.ts](./src/lib/hash-importer.ts)
+ - Update `SupportedHashers` to include your hasher type
+ - Update `getHasherForCode` to return your hasher
+1. Update the hasher codes used by the `hashers` property passed to Helia init in [./src/lib/init-helia.ts](./src/lib/init-helia.ts)
+
+see https://github.com/ipfs/ipld-explorer-components/pull/395 for an example.
+
### Redux-bundler requirements
These components use [redux-bundler](https://reduxbundler.com/) and your app will need to use a redux-bundler provider in order to propogate the properties and selectors. You can find a basic example of this in ./dev/devPage.jsx.
diff --git a/package.json b/package.json
index bd086798..21c3fc66 100644
--- a/package.json
+++ b/package.json
@@ -248,6 +248,7 @@
},
"peerDependencies": {
"@loadable/component": "^5.14.1",
+ "blake3-multihash": "^0.0.4",
"i18next": "^21.6.16",
"i18next-browser-languagedetector": "^6.1.0",
"i18next-http-backend": "^1.2.1",
diff --git a/src/components/StartExploringPage.jsx b/src/components/StartExploringPage.jsx
index 49497443..a05609b9 100644
--- a/src/components/StartExploringPage.jsx
+++ b/src/components/StartExploringPage.jsx
@@ -59,6 +59,9 @@ const StartExploringPage = ({ t, embed, runTour = false, joyrideCallback }) => (
*/}
+
+
+
@@ -68,6 +71,9 @@ const StartExploringPage = ({ t, embed, runTour = false, joyrideCallback }) => (
+
+
+
diff --git a/src/lib/codec-importer.ts b/src/lib/codec-importer.ts
index 00169b92..cb6516d9 100644
--- a/src/lib/codec-importer.ts
+++ b/src/lib/codec-importer.ts
@@ -15,6 +15,7 @@ export default async function codecImporter>
}
+// #WhenAddingNewCodec (maybe)
const codecResolverMap: Record = {
'dag-pb': async (node, path) => {
if (!isPBNode(node)) {
diff --git a/src/lib/get-codec-name-from-code.ts b/src/lib/get-codec-name-from-code.ts
index b4353d20..3e807658 100644
--- a/src/lib/get-codec-name-from-code.ts
+++ b/src/lib/get-codec-name-from-code.ts
@@ -2,6 +2,7 @@
* Converts supported codec codes from https://github.com/multiformats/multicodec/blob/master/table.csv to their names.
*/
export default function getCodecNameFromCode (code: number): string {
+ // #WhenAddingNewCodec
switch (code) {
case 113:
return 'dag-cbor'
diff --git a/src/lib/hash-importer.ts b/src/lib/hash-importer.ts
index 7a179514..e152ef8f 100644
--- a/src/lib/hash-importer.ts
+++ b/src/lib/hash-importer.ts
@@ -3,12 +3,14 @@ import * as sha3 from '@multiformats/sha3'
import { type Hasher, from } from 'multiformats/hashes/hasher'
import * as sha2 from 'multiformats/hashes/sha2'
+// #WhenAddingNewHasher
export type SupportedHashers = typeof sha2.sha256 |
typeof sha2.sha512 |
Hasher<'keccak-256', 27> |
Hasher<'sha1', 17> |
Hasher<'blake2b-512', 45632> |
- Hasher<'sha3-512', 20>
+ Hasher<'sha3-512', 20> |
+ Hasher<'blake3', 30>
export async function getHashersForCodes (code: number, ...codes: number[]): Promise {
return Promise.all(codes.map(getHasherForCode))
@@ -26,6 +28,7 @@ function getBoundHasher (hasher: T): T {
}
export async function getHasherForCode (code: number): Promise {
+ // #WhenAddingNewHasher
switch (code) {
case sha2.sha256.code:
return getBoundHasher(sha2.sha256)
@@ -36,7 +39,7 @@ export async function getHasherForCode (code: number): Promise
return getBoundHasher(from({
name: 'sha1',
code,
- encode: async (data: Uint8Array) => {
+ encode: async (data: Uint8Array): Promise => {
const crypto = globalThis.crypto ?? (await import('crypto')).webcrypto
const hashBuffer = await crypto.subtle.digest('SHA-1', data)
return new Uint8Array(hashBuffer)
@@ -46,7 +49,15 @@ export async function getHasherForCode (code: number): Promise
return getBoundHasher(sha3.sha3512)
case sha3.keccak256.code: // keccak-256
return getBoundHasher(sha3.keccak256)
-
+ case 30:
+ return getBoundHasher(from({
+ name: 'blake3',
+ code,
+ encode: async (data: Uint8Array): Promise => {
+ const { digest } = await import('blake3-multihash')
+ return (await digest(data)).digest
+ }
+ }))
default:
throw new Error(`unknown multihasher code '${code}'`)
}
diff --git a/src/lib/init-helia.ts b/src/lib/init-helia.ts
index 95ced917..0281f358 100644
--- a/src/lib/init-helia.ts
+++ b/src/lib/init-helia.ts
@@ -59,7 +59,8 @@ export default async function initHelia (kuboGatewayOptions: KuboGatewayOptions)
trustlessGateway(),
trustlessGateway({ gateways: [`${kuboGatewayOptions.protocol ?? 'http'}://${kuboGatewayOptions.host}:${kuboGatewayOptions.port}`] })
],
- hashers: await getHashersForCodes(17, 18, 19, 20, 27),
+ // #WhenAddingNewHasher
+ hashers: await getHashersForCodes(17, 18, 19, 20, 27, 30),
datastore,
blockstore,
// @ts-expect-error - libp2p types are borked right now
@@ -71,7 +72,9 @@ export default async function initHelia (kuboGatewayOptions: KuboGatewayOptions)
await Promise.allSettled([
addDagNodeToHelia(helia, 'dag-json', { hello: 'world' }), // baguqeerasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea
addDagNodeToHelia(helia, 'dag-cbor', { hello: 'world' }, 27), // bafyrwigbexamue2ba3hmtai7hwlcmd6ekiqsduyf5avv7oz6ln3radvjde
- addDagNodeToHelia(helia, 'json', { hello: 'world' }, 20) // bagaaifcavabu6fzheerrmtxbbwv7jjhc3kaldmm7lbnvfopyrthcvod4m6ygpj3unrcggkzhvcwv5wnhc5ufkgzlsji7agnmofovc2g4a3ui7ja
+ addDagNodeToHelia(helia, 'json', { hello: 'world' }, 20), // bagaaifcavabu6fzheerrmtxbbwv7jjhc3kaldmm7lbnvfopyrthcvod4m6ygpj3unrcggkzhvcwv5wnhc5ufkgzlsji7agnmofovc2g4a3ui7ja
+ addDagNodeToHelia(helia, 'json', { hello: 'world' }, 30), // bagaaihraf4oq2kddg6o5ewlu6aol6xab75xkwbgzx2dlot7cdun7iirve23a
+ addDagNodeToHelia(helia, 'raw', (new TextEncoder()).encode('hello'), 30) // bafkr4ihkr4ld3m4gqkjf4reryxsy2s5tkbxprqkow6fin2iiyvreuzzab4
])
return helia
diff --git a/src/lib/resolve-ipld-path.test.js b/src/lib/resolve-ipld-path.test.js
index d2985038..097d850e 100644
--- a/src/lib/resolve-ipld-path.test.js
+++ b/src/lib/resolve-ipld-path.test.js
@@ -8,6 +8,7 @@ import { addDagNodeToHelia } from './helpers'
import resolveIpldPath, { findLinkPath } from './resolve-ipld-path'
import { createHeliaMock } from '../../test/unit/heliaMock'
+// #WhenAddingNewCodec
describe('resolveIpldPath', () => {
/**
* @type {import('@helia/interface').Helia}