Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: support paths in @helia/ipns #410

Merged
merged 5 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/interop/src/ipns-http.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('@helia/ipns - http', () => {

const key = peerIdFromString(res.name)

const resolvedCid = await name.resolve(key)
const { cid: resolvedCid } = await name.resolve(key)
expect(resolvedCid.toString()).to.equal(cid.toString())
})
})
10 changes: 5 additions & 5 deletions packages/interop/src/ipns-pubsub.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { createHeliaNode } from './fixtures/create-helia.js'
import { createKuboNode } from './fixtures/create-kubo.js'
import { keyTypes } from './fixtures/key-types.js'
import { waitFor } from './fixtures/wait-for.js'
import type { IPNS } from '@helia/ipns'
import type { IPNS, ResolveResult } from '@helia/ipns'
import type { Libp2p, PubSub } from '@libp2p/interface'
import type { Keychain } from '@libp2p/keychain'
import type { HeliaLibp2p } from 'helia'
Expand Down Expand Up @@ -161,12 +161,12 @@ keyTypes.filter(keyType => keyType !== 'RSA').forEach(keyType => {
key: keyName
})

let resolvedCid: CID | undefined
let resolveResult: ResolveResult | undefined

// we should get an update eventually
await waitFor(async () => {
try {
resolvedCid = await name.resolve(peerId)
resolveResult = await name.resolve(peerId)

return true
} catch {
Expand All @@ -177,11 +177,11 @@ keyTypes.filter(keyType => keyType !== 'RSA').forEach(keyType => {
message: 'Helia could not resolve the IPNS record'
})

if (resolvedCid == null) {
if (resolveResult == null) {
throw new Error('Failed to resolve CID')
}

expect(resolvedCid.toString()).to.equal(cid.toString())
expect(resolveResult.cid.toString()).to.equal(cid.toString())
})
})
})
2 changes: 1 addition & 1 deletion packages/interop/src/ipns.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ keyTypes.forEach(type => {
key: keyName
})

const resolvedCid = await name.resolve(key)
const { cid: resolvedCid } = await name.resolve(key)
expect(resolvedCid.toString()).to.equal(cid.toString())
})
})
Expand Down
95 changes: 83 additions & 12 deletions packages/ipns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ IPNS operations using a Helia node

With IPNSRouting routers:

```typescript
```TypeScript
import { createHelia } from 'helia'
import { ipns } from '@helia/ipns'
import { unixfs } from '@helia/unixfs'
Expand All @@ -41,7 +41,78 @@ const cid = await fs.add(Uint8Array.from([0, 1, 2, 3, 4]))
await name.publish(peerId, cid)

// resolve the name
const cid = name.resolve(peerId)
const result = name.resolve(peerId)

console.info(result.cid, result.path)
```

## Example - Publishing a recursive record

A recursive record is a one that points to another record rather than to a
value.

```TypeScript
import { createHelia } from 'helia'
import { ipns } from '@helia/ipns'
import { unixfs } from '@helia/unixfs'

const helia = await createHelia()
const name = ipns(helia)

// create a public key to publish as an IPNS name
const keyInfo = await helia.libp2p.services.keychain.createKey('my-key')
const peerId = await helia.libp2p.services.keychain.exportPeerId(keyInfo.name)

// store some data to publish
const fs = unixfs(helia)
const cid = await fs.add(Uint8Array.from([0, 1, 2, 3, 4]))

// publish the name
await name.publish(peerId, cid)

// create another public key to re-publish the original record
const recursiveKeyInfo = await helia.libp2p.services.keychain.createKey('my-recursive-key')
const recursivePeerId = await helia.libp2p.services.keychain.exportPeerId(recursiveKeyInfo.name)

// publish the recursive name
await name.publish(recursivePeerId, peerId)

// resolve the name recursively - it resolves until a CID is found
const result = name.resolve(recursivePeerId)
console.info(result.cid.toString() === cid.toString()) // true
```

## Example - Publishing a record with a path

It is possible to publish CIDs with an associated path.

```TypeScript
import { createHelia } from 'helia'
import { ipns } from '@helia/ipns'
import { unixfs } from '@helia/unixfs'

const helia = await createHelia()
const name = ipns(helia)

// create a public key to publish as an IPNS name
const keyInfo = await helia.libp2p.services.keychain.createKey('my-key')
const peerId = await helia.libp2p.services.keychain.exportPeerId(keyInfo.name)

// store some data to publish
const fs = unixfs(helia)
const fileCid = await fs.add(Uint8Array.from([0, 1, 2, 3, 4]))

// store the file in a directory
const dirCid = await fs.mkdir()
const finalDirCid = await fs.cp(fileCid, dirCid, '/foo.txt')

// publish the name
await name.publish(peerId, `/ipfs/${finalDirCid}/foo.txt)

// resolve the name
const result = name.resolve(peerId)

console.info(result.cid, result.path) // QmFoo.. 'foo.txt'
```

## Example - Using custom PubSub router
Expand All @@ -60,7 +131,7 @@ This router is only suitable for networks where IPNS updates are frequent
and multiple peers are listening on the topic(s), otherwise update messages
may fail to be published with "Insufficient peers" errors.

```typescript
```TypeScript
import { createHelia, libp2pDefaults } from 'helia'
import { ipns } from '@helia/ipns'
import { pubsub } from '@helia/ipns/routing'
Expand Down Expand Up @@ -91,14 +162,14 @@ const cid = await fs.add(Uint8Array.from([0, 1, 2, 3, 4]))
await name.publish(peerId, cid)

// resolve the name
const cid = name.resolve(peerId)
const { cid, path } = name.resolve(peerId)
```

## Example - Using custom DNS over HTTPS resolvers

With default DNSResolver resolvers:

```typescript
```TypeScript
import { createHelia } from 'helia'
import { ipns } from '@helia/ipns'
import { unixfs } from '@helia/unixfs'
Expand All @@ -111,14 +182,14 @@ const name = ipns(helia, {
]
})

const cid = name.resolveDns('some-domain-with-dnslink-entry.com')
const { cid, path } = name.resolveDns('some-domain-with-dnslink-entry.com')
```

## Example - Resolving a domain with a dnslink entry

Calling `resolveDns` with the `@helia/ipns` instance:

```typescript
```TypeScript
// resolve a CID from a TXT record in a DNS zone file, using the default
// resolver for the current platform eg:
// > dig _dnslink.ipfs.io TXT
Expand All @@ -128,7 +199,7 @@ Calling `resolveDns` with the `@helia/ipns` instance:
// ;; ANSWER SECTION:
// _dnslink.website.ipfs.io. 60 IN TXT "dnslink=/ipfs/QmWebsite"

const cid = name.resolveDns('ipfs.io')
const { cid, path } = name.resolveDns('ipfs.io')

console.info(cid)
// QmWebsite
Expand All @@ -142,11 +213,11 @@ response which can increase browser bundle sizes.

If this is a concern, use the DNS-JSON-Over-HTTPS resolver instead.

```typescript
```TypeScript
// use DNS-Over-HTTPS
import { dnsOverHttps } from '@helia/ipns/dns-resolvers'

const cid = name.resolveDns('ipfs.io', {
const { cid, path } = name.resolveDns('ipfs.io', {
resolvers: [
dnsOverHttps('https://mozilla.cloudflare-dns.com/dns-query')
]
Expand All @@ -158,11 +229,11 @@ const cid = name.resolveDns('ipfs.io', {
DNS-JSON-Over-HTTPS resolvers use the RFC 8427 `application/dns-json` and can
result in a smaller browser bundle due to the response being plain JSON.

```typescript
```TypeScript
// use DNS-JSON-Over-HTTPS
import { dnsJsonOverHttps } from '@helia/ipns/dns-resolvers'

const cid = name.resolveDns('ipfs.io', {
const { cid, path } = name.resolveDns('ipfs.io', {
resolvers: [
dnsJsonOverHttps('https://mozilla.cloudflare-dns.com/dns-query')
]
Expand Down
Loading
Loading