diff --git a/packages/interop/src/ipns-http.spec.ts b/packages/interop/src/ipns-http.spec.ts index a892bee81..d4c0ec8c9 100644 --- a/packages/interop/src/ipns-http.spec.ts +++ b/packages/interop/src/ipns-http.spec.ts @@ -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()) }) }) diff --git a/packages/interop/src/ipns-pubsub.spec.ts b/packages/interop/src/ipns-pubsub.spec.ts index bef1f039b..6885b16c9 100644 --- a/packages/interop/src/ipns-pubsub.spec.ts +++ b/packages/interop/src/ipns-pubsub.spec.ts @@ -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' @@ -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 { @@ -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()) }) }) }) diff --git a/packages/interop/src/ipns.spec.ts b/packages/interop/src/ipns.spec.ts index 7bb29b195..8fa1e3316 100644 --- a/packages/interop/src/ipns.spec.ts +++ b/packages/interop/src/ipns.spec.ts @@ -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()) }) }) diff --git a/packages/ipns/README.md b/packages/ipns/README.md index b0a72a0fb..4901d49d7 100644 --- a/packages/ipns/README.md +++ b/packages/ipns/README.md @@ -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' @@ -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 @@ -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' @@ -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' @@ -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 @@ -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 @@ -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') ] @@ -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') ] diff --git a/packages/ipns/src/index.ts b/packages/ipns/src/index.ts index adcad2eea..14d52f0d5 100644 --- a/packages/ipns/src/index.ts +++ b/packages/ipns/src/index.ts @@ -7,7 +7,7 @@ * * With {@link IPNSRouting} routers: * - * ```typescript + * ```TypeScript * import { createHelia } from 'helia' * import { ipns } from '@helia/ipns' * import { unixfs } from '@helia/unixfs' @@ -27,7 +27,78 @@ * 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 @@ -46,7 +117,7 @@ * 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' @@ -77,14 +148,14 @@ * 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 {@link DNSResolver} resolvers: * - * ```typescript + * ```TypeScript * import { createHelia } from 'helia' * import { ipns } from '@helia/ipns' * import { unixfs } from '@helia/unixfs' @@ -97,14 +168,14 @@ * ] * }) * - * 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 @@ -114,7 +185,7 @@ * // ;; 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 @@ -128,11 +199,11 @@ * * 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') * ] @@ -144,11 +215,11 @@ * 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') * ] @@ -266,24 +337,29 @@ export interface RepublishOptions extends AbortOptions, ProgressOptions + publish(key: PeerId, value: CID | PeerId | string, options?: PublishOptions): Promise /** * Accepts a public key formatted as a libp2p PeerID and resolves the IPNS record * corresponding to that public key until a value is found */ - resolve(key: PeerId, options?: ResolveOptions): Promise + resolve(key: PeerId, options?: ResolveOptions): Promise /** * Resolve a CID from a dns-link style IPNS record */ - resolveDns(domain: string, options?: ResolveDNSOptions): Promise + resolveDns(domain: string, options?: ResolveDNSOptions): Promise /** * Periodically republish all IPNS records found in the datastore @@ -313,7 +389,7 @@ class DefaultIPNS implements IPNS { this.defaultResolvers = resolvers.length > 0 ? resolvers : [defaultResolver()] } - async publish (key: PeerId, value: CID | PeerId, options: PublishOptions = {}): Promise { + async publish (key: PeerId, value: CID | PeerId | string, options: PublishOptions = {}): Promise { try { let sequenceNumber = 1n const routingKey = peerIdToRoutingKey(key) @@ -343,14 +419,14 @@ class DefaultIPNS implements IPNS { } } - async resolve (key: PeerId, options: ResolveOptions = {}): Promise { + async resolve (key: PeerId, options: ResolveOptions = {}): Promise { const routingKey = peerIdToRoutingKey(key) const record = await this.#findIpnsRecord(routingKey, options) return this.#resolve(record.value, options) } - async resolveDns (domain: string, options: ResolveDNSOptions = {}): Promise { + async resolveDns (domain: string, options: ResolveDNSOptions = {}): Promise { const resolvers = options.resolvers ?? this.defaultResolvers const dnslink = await Promise.any( @@ -396,17 +472,28 @@ class DefaultIPNS implements IPNS { }, options.interval ?? DEFAULT_REPUBLISH_INTERVAL_MS) } - async #resolve (ipfsPath: string, options: ResolveOptions = {}): Promise { + async #resolve (ipfsPath: string, options: ResolveOptions = {}): Promise { const parts = ipfsPath.split('/') - - if (parts.length === 3) { + try { const scheme = parts[1] if (scheme === 'ipns') { - return this.resolve(peerIdFromString(parts[2]), options) + const { cid } = await this.resolve(peerIdFromString(parts[2]), options) + const path = parts.slice(3).join('/') + return { + cid, + path + } } else if (scheme === 'ipfs') { - return CID.parse(parts[2]) + const cid = CID.parse(parts[2]) + const path = parts.slice(3).join('/') + return { + cid, + path + } } + } catch (err) { + log.error('error parsing ipfs path', err) } log.error('invalid ipfs path %s', ipfsPath) diff --git a/packages/ipns/test/publish.spec.ts b/packages/ipns/test/publish.spec.ts index 1609cdb0d..d8e1ba337 100644 --- a/packages/ipns/test/publish.spec.ts +++ b/packages/ipns/test/publish.spec.ts @@ -3,6 +3,7 @@ import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { expect } from 'aegir/chai' import { MemoryDatastore } from 'datastore-core' +import { base36 } from 'multiformats/bases/base36' import { CID } from 'multiformats/cid' import Sinon from 'sinon' import { type StubbedInstance, stubInterface } from 'sinon-ts' @@ -67,4 +68,40 @@ describe('publish', () => { expect(onProgress).to.have.property('called', true) }) + + it('should publish recursively', async () => { + const key = await createEd25519PeerId() + const record = await name.publish(key, cid, { + offline: true + }) + + expect(record.value).to.equal(`/ipfs/${cid.toV1().toString()}`) + + const recursiveKey = await createEd25519PeerId() + const recursiveRecord = await name.publish(recursiveKey, key, { + offline: true + }) + + expect(recursiveRecord.value).to.equal(`/ipns/${key.toCID().toString(base36)}`) + + const recursiveResult = await name.resolve(recursiveKey) + expect(recursiveResult.cid.toString()).to.equal(cid.toV1().toString()) + }) + + it('should publish record with a path', async () => { + const path = '/foo/bar/baz' + const fullPath = `/ipfs/${cid}/${path}` + + const key = await createEd25519PeerId() + const record = await name.publish(key, fullPath, { + offline: true + }) + + expect(record.value).to.equal(fullPath) + + const result = await name.resolve(key) + + expect(result.cid.toString()).to.equal(cid.toString()) + expect(result.path).to.equal(path) + }) }) diff --git a/packages/ipns/test/resolve-dns.spec.ts b/packages/ipns/test/resolve-dns.spec.ts index 2ee10f161..7adc0dbc9 100644 --- a/packages/ipns/test/resolve-dns.spec.ts +++ b/packages/ipns/test/resolve-dns.spec.ts @@ -1,8 +1,10 @@ /* eslint-env mocha */ +import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { expect } from 'aegir/chai' import { MemoryDatastore } from 'datastore-core' import { type Datastore } from 'interface-datastore' +import { CID } from 'multiformats/cid' import { stub } from 'sinon' import { type StubbedInstance, stubInterface } from 'sinon-ts' import { type IPNSRouting, ipns } from '../src/index.js' @@ -27,7 +29,7 @@ describe('resolveDns', () => { const result = await name.resolveDns('foobar.baz', { nocache: true, offline: true }) expect(stubbedResolver1.called).to.be.true() expect(stubbedResolver1.calledWith('foobar.baz')).to.be.true() - expect(result.toString()).to.equal('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') + expect(result.cid.toString()).to.equal('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') }) it('should allow overriding of resolvers passed in constructor', async () => { @@ -39,6 +41,49 @@ describe('resolveDns', () => { expect(stubbedResolver1.called).to.be.false() expect(stubbedResolver2.called).to.be.true() expect(stubbedResolver2.calledWith('foobar.baz')).to.be.true() - expect(result.toString()).to.equal('bafkreibm6jg3ux5qumhcn2b3flc3tyu6dmlb4xa7u5bf44yegnrjhc4yeq') + expect(result.cid.toString()).to.equal('bafkreibm6jg3ux5qumhcn2b3flc3tyu6dmlb4xa7u5bf44yegnrjhc4yeq') + }) + + it('should support trailing slash in returned dnslink value', async () => { + // see https://github.com/ipfs/helia/issues/402 + const stubbedResolver1 = stub().returns('dnslink=/ipfs/bafybeifcaqowoyito3qvsmbwbiugsu4umlxn4ehu223hvtubbfvwyuxjoe/') + + const name = ipns({ datastore, routing: heliaRouting }, { routers: [customRouting], resolvers: [stubbedResolver1] }) + const result = await name.resolveDns('foobar.baz', { nocache: true }) + expect(stubbedResolver1.called).to.be.true() + expect(stubbedResolver1.calledWith('foobar.baz')).to.be.true() + expect(result.cid.toString()).to.equal('bafybeifcaqowoyito3qvsmbwbiugsu4umlxn4ehu223hvtubbfvwyuxjoe', 'doesn\'t support trailing slashes') + }) + + it('should support paths in returned dnslink value', async () => { + // see https://github.com/ipfs/helia/issues/402 + const stubbedResolver1 = stub().returns('dnslink=/ipfs/bafybeifcaqowoyito3qvsmbwbiugsu4umlxn4ehu223hvtubbfvwyuxjoe/foobar/path/123') + + const name = ipns({ datastore, routing: heliaRouting }, { routers: [customRouting], resolvers: [stubbedResolver1] }) + const result = await name.resolveDns('foobar.baz', { nocache: true }) + expect(stubbedResolver1.called).to.be.true() + expect(stubbedResolver1.calledWith('foobar.baz')).to.be.true() + expect(result.cid.toString()).to.equal('bafybeifcaqowoyito3qvsmbwbiugsu4umlxn4ehu223hvtubbfvwyuxjoe', 'doesn\'t support trailing slashes') + expect(result.path).to.equal('foobar/path/123') + }) + + it('should resolve recursive dnslink -> /', async () => { + const cid = CID.parse('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') + const key = await createEd25519PeerId() + const stubbedResolver1 = stub().returns(`dnslink=/ipns/${key.toString()}/foobar/path/123`) + const name = ipns({ datastore, routing: heliaRouting }, { routers: [customRouting], resolvers: [stubbedResolver1] }) + + await name.publish(key, cid) + + const result = await name.resolveDns('foobar.baz', { nocache: true }) + + if (result == null) { + throw new Error('Did not resolve entry') + } + + expect(stubbedResolver1.called).to.be.true() + expect(stubbedResolver1.calledWith('foobar.baz')).to.be.true() + expect(result.cid.toString()).to.equal(cid.toV1().toString()) + expect(result.path).to.equal('foobar/path/123') }) }) diff --git a/packages/ipns/test/resolve.spec.ts b/packages/ipns/test/resolve.spec.ts index 386b377bf..001ad8efa 100644 --- a/packages/ipns/test/resolve.spec.ts +++ b/packages/ipns/test/resolve.spec.ts @@ -41,7 +41,7 @@ describe('resolve', () => { throw new Error('Did not resolve entry') } - expect(resolvedValue.toString()).to.equal(cid.toV1().toString()) + expect(resolvedValue.cid.toString()).to.equal(cid.toV1().toString()) expect(heliaRouting.get.called).to.be.true() expect(customRouting.get.called).to.be.true() @@ -65,7 +65,7 @@ describe('resolve', () => { throw new Error('Did not resolve entry') } - expect(resolvedValue.toString()).to.equal(cid.toV1().toString()) + expect(resolvedValue.cid.toString()).to.equal(cid.toV1().toString()) }) it('should resolve a recursive record', async () => { @@ -80,7 +80,22 @@ describe('resolve', () => { throw new Error('Did not resolve entry') } - expect(resolvedValue.toString()).to.equal(cid.toV1().toString()) + expect(resolvedValue.cid.toString()).to.equal(cid.toV1().toString()) + }) + + it('should resolve a recursive record with path', async () => { + const key1 = await createEd25519PeerId() + const key2 = await createEd25519PeerId() + await name.publish(key2, cid) + await name.publish(key1, key2) + + const resolvedValue = await name.resolve(key1) + + if (resolvedValue == null) { + throw new Error('Did not resolve entry') + } + + expect(resolvedValue.cid.toString()).to.equal(cid.toV1().toString()) }) it('should emit progress events', async function () { @@ -108,7 +123,7 @@ describe('resolve', () => { customRouting.get.withArgs(customRoutingKey).resolves(marshalledRecord) const result = await name.resolve(peerId) - expect(result.toString()).to.equal(cid.toV1().toString(), 'incorrect record resolved') + expect(result.cid.toString()).to.equal(cid.toV1().toString(), 'incorrect record resolved') expect(datastore.has(dhtKey)).to.be.true('did not cache record locally') }) @@ -129,7 +144,7 @@ describe('resolve', () => { customRouting.get.withArgs(customRoutingKey).resolves(marshalledRecordB) const result = await name.resolve(peerId) - expect(result.toString()).to.equal(cid.toV1().toString(), 'incorrect record resolved') + expect(result.cid.toString()).to.equal(cid.toV1().toString(), 'incorrect record resolved') const cached = await datastore.get(dhtKey) const record = Record.deserialize(cached)