@helia/delegated-routing-v1-http-api-client 6.0.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,16 +7,20 @@
7
7
  ".:DelegatedRoutingV1HttpApiClientInit": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/interfaces/_helia_delegated-routing-v1-http-api-client.DelegatedRoutingV1HttpApiClientInit.html",
8
8
  "FilterOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/interfaces/_helia_delegated-routing-v1-http-api-client.FilterOptions.html",
9
9
  ".:FilterOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/interfaces/_helia_delegated-routing-v1-http-api-client.FilterOptions.html",
10
- "GetIPNSOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/interfaces/_helia_delegated-routing-v1-http-api-client.GetIPNSOptions.html",
11
- ".:GetIPNSOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/interfaces/_helia_delegated-routing-v1-http-api-client.GetIPNSOptions.html",
12
10
  "PeerRecord": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/interfaces/_helia_delegated-routing-v1-http-api-client.PeerRecord.html",
13
11
  ".:PeerRecord": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/interfaces/_helia_delegated-routing-v1-http-api-client.PeerRecord.html",
14
12
  "GetClosestPeersOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetClosestPeersOptions.html",
15
13
  ".:GetClosestPeersOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetClosestPeersOptions.html",
14
+ "GetIPNSOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetIPNSOptions.html",
15
+ ".:GetIPNSOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetIPNSOptions.html",
16
16
  "GetPeersOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetPeersOptions.html",
17
17
  ".:GetPeersOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetPeersOptions.html",
18
18
  "GetProvidersOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetProvidersOptions.html",
19
19
  ".:GetProvidersOptions": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/types/_helia_delegated-routing-v1-http-api-client.GetProvidersOptions.html",
20
20
  "delegatedRoutingV1HttpApiClient": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/functions/_helia_delegated-routing-v1-http-api-client.delegatedRoutingV1HttpApiClient.html",
21
- ".:delegatedRoutingV1HttpApiClient": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/functions/_helia_delegated-routing-v1-http-api-client.delegatedRoutingV1HttpApiClient.html"
21
+ ".:delegatedRoutingV1HttpApiClient": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/functions/_helia_delegated-routing-v1-http-api-client.delegatedRoutingV1HttpApiClient.html",
22
+ "delegatedRoutingV1HttpApiClientContentRouting": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/functions/_helia_delegated-routing-v1-http-api-client.delegatedRoutingV1HttpApiClientContentRouting.html",
23
+ ".:delegatedRoutingV1HttpApiClientContentRouting": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/functions/_helia_delegated-routing-v1-http-api-client.delegatedRoutingV1HttpApiClientContentRouting.html",
24
+ "delegatedRoutingV1HttpApiClientPeerRouting": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/functions/_helia_delegated-routing-v1-http-api-client.delegatedRoutingV1HttpApiClientPeerRouting.html",
25
+ ".:delegatedRoutingV1HttpApiClientPeerRouting": "https://ipfs.github.io/helia-delegated-routing-v1-http-api/functions/_helia_delegated-routing-v1-http-api-client.delegatedRoutingV1HttpApiClientPeerRouting.html"
22
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helia/delegated-routing-v1-http-api-client",
3
- "version": "6.0.0",
3
+ "version": "7.0.0",
4
4
  "description": "A Delegated Routing V1 HTTP API client",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/ipfs/helia-delegated-routing-v1-http-api/tree/main/packages/client#readme",
@@ -29,7 +29,8 @@
29
29
  "exports": {
30
30
  ".": {
31
31
  "types": "./dist/src/index.d.ts",
32
- "import": "./dist/src/index.js"
32
+ "import": "./dist/src/index.js",
33
+ "module-sync": "./dist/src/index.js"
33
34
  }
34
35
  },
35
36
  "release": {
@@ -144,20 +145,20 @@
144
145
  "@multiformats/multiaddr": "^13.0.1",
145
146
  "any-signal": "^4.1.1",
146
147
  "browser-readablestream-to-it": "^2.0.9",
147
- "ipns": "^10.0.2",
148
148
  "it-first": "^3.0.8",
149
149
  "it-map": "^3.1.3",
150
- "it-ndjson": "^1.1.3",
151
- "multiformats": "^13.3.6",
150
+ "it-ndjson": "^2.0.0",
151
+ "multiformats": "^14.0.0",
152
152
  "p-defer": "^4.0.1",
153
153
  "p-queue": "^9.0.0",
154
- "uint8arrays": "^5.1.0"
154
+ "uint8arrays": "^6.1.1"
155
155
  },
156
156
  "devDependencies": {
157
157
  "@libp2p/crypto": "^5.1.3",
158
158
  "@libp2p/logger": "^6.0.5",
159
- "aegir": "^47.0.10",
159
+ "aegir": "^48.0.4",
160
160
  "body-parser": "^2.2.0",
161
+ "ipns": "^11.0.0",
161
162
  "it-all": "^3.0.8",
162
163
  "wherearewe": "^2.0.1"
163
164
  },
package/src/client.ts CHANGED
@@ -1,20 +1,17 @@
1
- import { InvalidParametersError, NotFoundError, contentRoutingSymbol, isPeerId, peerRoutingSymbol, setMaxListeners } from '@libp2p/interface'
1
+ import { InvalidParametersError, NotFoundError, setMaxListeners } from '@libp2p/interface'
2
2
  import { peerIdFromString } from '@libp2p/peer-id'
3
3
  import { multiaddr } from '@multiformats/multiaddr'
4
4
  import { anySignal } from 'any-signal'
5
5
  import toIt from 'browser-readablestream-to-it'
6
- import { unmarshalIPNSRecord, marshalIPNSRecord, multihashToIPNSRoutingKey } from 'ipns'
7
- import { ipnsValidator } from 'ipns/validator'
8
6
  import { parse as ndjson } from 'it-ndjson'
9
7
  import { CID } from 'multiformats/cid'
10
8
  import defer from 'p-defer'
11
9
  import PQueue from 'p-queue'
12
- import { BadResponseError, InvalidRequestError } from './errors.js'
13
- import { DelegatedRoutingV1HttpApiClientContentRouting, DelegatedRoutingV1HttpApiClientPeerRouting } from './routings.js'
14
- import type { DelegatedRoutingV1HttpApiClient as DelegatedRoutingV1HttpApiClientInterface, DelegatedRoutingV1HttpApiClientInit, GetProvidersOptions, GetPeersOptions, GetIPNSOptions, PeerRecord, DelegatedRoutingV1HttpApiClientComponents, GetClosestPeersOptions } from './index.js'
15
- import type { ContentRouting, PeerRouting, AbortOptions, PeerId, Logger } from '@libp2p/interface'
10
+ import { withArrayBuffer } from 'uint8arrays/with-array-buffer'
11
+ import { BadResponseError, InvalidRequestError } from './errors.ts'
12
+ import type { DelegatedRoutingV1HttpApiClient as DelegatedRoutingV1HttpApiClientInterface, DelegatedRoutingV1HttpApiClientInit, GetProvidersOptions, GetPeersOptions, GetIPNSOptions, PeerRecord, DelegatedRoutingV1HttpApiClientComponents, GetClosestPeersOptions } from './index.ts'
13
+ import type { AbortOptions, Logger } from '@libp2p/interface'
16
14
  import type { Multiaddr } from '@multiformats/multiaddr'
17
- import type { IPNSRecord } from 'ipns'
18
15
 
19
16
  const defaultValues = {
20
17
  concurrentRequests: 4,
@@ -29,8 +26,6 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
29
26
  private readonly httpQueue: PQueue
30
27
  private readonly shutDownController: AbortController
31
28
  private readonly timeout: number
32
- private readonly contentRouting: ContentRouting
33
- private readonly peerRouting: PeerRouting
34
29
  private readonly filterAddrs?: string[]
35
30
  private readonly filterProtocols?: string[]
36
31
  private readonly inFlightRequests: Map<string, Promise<Response>>
@@ -55,21 +50,11 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
55
50
  this.timeout = init.timeout ?? defaultValues.timeout
56
51
  this.filterAddrs = init.filterAddrs
57
52
  this.filterProtocols = init.filterProtocols
58
- this.contentRouting = new DelegatedRoutingV1HttpApiClientContentRouting(this)
59
- this.peerRouting = new DelegatedRoutingV1HttpApiClientPeerRouting(this)
60
53
 
61
54
  this.cacheName = init.cacheName ?? defaultValues.cacheName
62
55
  this.cacheTTL = init.cacheTTL ?? defaultValues.cacheTTL
63
56
  }
64
57
 
65
- get [contentRoutingSymbol] (): ContentRouting {
66
- return this.contentRouting
67
- }
68
-
69
- get [peerRoutingSymbol] (): PeerRouting {
70
- return this.peerRouting
71
- }
72
-
73
58
  isStarted (): boolean {
74
59
  return this.started
75
60
  }
@@ -120,15 +105,14 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
120
105
 
121
106
  // https://specs.ipfs.tech/routing/http-routing-v1/
122
107
  const url = new URL(`${this.url}routing/v1/providers/${cid}`)
123
-
124
108
  this.#addFilterParams(url, options.filterAddrs, options.filterProtocols)
125
- const getOptions = {
109
+
110
+ const res = await this.#makeRequest(url.toString(), {
126
111
  headers: {
127
112
  accept: 'application/x-ndjson, application/json;q=0.8'
128
113
  },
129
114
  signal
130
- }
131
- const res = await this.#makeRequest(url.toString(), getOptions)
115
+ })
132
116
 
133
117
  if (!res.ok) {
134
118
  // Per IPIP-0513: Handle 404 as empty results (not an error)
@@ -194,8 +178,8 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
194
178
  }
195
179
  }
196
180
 
197
- async * getPeers (peerId: PeerId, options: GetPeersOptions = {}): AsyncGenerator<PeerRecord> {
198
- this.log('getPeers starts: %c', peerId)
181
+ async * getPeers (cid: CID, options: GetPeersOptions = {}): AsyncGenerator<PeerRecord> {
182
+ this.log('getPeers starts: %c', cid)
199
183
 
200
184
  const timeoutSignal = AbortSignal.timeout(this.timeout)
201
185
  const signal = anySignal([this.shutDownController.signal, timeoutSignal, options.signal])
@@ -212,11 +196,15 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
212
196
  await onStart.promise
213
197
 
214
198
  // https://specs.ipfs.tech/routing/http-routing-v1/
215
- const url = new URL(`${this.url}routing/v1/peers/${peerId.toCID().toString()}`)
199
+ const url = new URL(`${this.url}routing/v1/peers/${cid}`)
216
200
  this.#addFilterParams(url, options.filterAddrs, options.filterProtocols)
217
201
 
218
- const getOptions = { headers: { Accept: 'application/x-ndjson' }, signal }
219
- const res = await this.#makeRequest(url.toString(), getOptions)
202
+ const res = await this.#makeRequest(url.toString(), {
203
+ headers: {
204
+ Accept: 'application/x-ndjson'
205
+ },
206
+ signal
207
+ })
220
208
 
221
209
  // Per IPIP-0513: Handle 404 as empty results (not an error)
222
210
  // Old servers return 404, new servers return 200 with empty array
@@ -260,19 +248,17 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
260
248
  } finally {
261
249
  signal.clear()
262
250
  onFinish.resolve()
263
- this.log('getPeers finished: %c', peerId)
251
+ this.log('getPeers finished: %c', cid)
264
252
  }
265
253
  }
266
254
 
267
- async * getClosestPeers (key: CID | PeerId, options: GetClosestPeersOptions = {}): AsyncGenerator<PeerRecord> {
255
+ async * getClosestPeers (key: CID, options: GetClosestPeersOptions = {}): AsyncGenerator<PeerRecord> {
268
256
  let target: string
269
257
 
270
- if (isPeerId(key)) {
271
- target = key.toCID().toString()
272
- } else if (CID.asCID(key) === key || key instanceof CID) {
258
+ if (CID.asCID(key) === key || key instanceof CID) {
273
259
  target = key.toV1().toString()
274
260
  } else {
275
- throw new InvalidParametersError('Key must be CID or PeerId')
261
+ throw new InvalidParametersError('Key must be CID')
276
262
  }
277
263
 
278
264
  this.log('getClosestPeers starts: %s', target)
@@ -295,8 +281,12 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
295
281
  const url = new URL(`${this.url}routing/v1/dht/closest/peers/${target}`)
296
282
  this.#addFilterParams(url, options.filterAddrs, options.filterProtocols)
297
283
 
298
- const getOptions = { headers: { Accept: 'application/x-ndjson' }, signal }
299
- const res = await this.#makeRequest(url.toString(), getOptions)
284
+ const res = await this.#makeRequest(url.toString(), {
285
+ headers: {
286
+ Accept: 'application/x-ndjson'
287
+ },
288
+ signal
289
+ })
300
290
 
301
291
  // Per IPIP-0513: Handle 404 as empty results (not an error)
302
292
  // Old servers return 404, new servers return 200 with empty array
@@ -344,8 +334,8 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
344
334
  }
345
335
  }
346
336
 
347
- async getIPNS (libp2pKey: CID<unknown, 0x72, 0x00 | 0x12, 1>, options: GetIPNSOptions = {}): Promise<IPNSRecord> {
348
- this.log('getIPNS starts: %s', libp2pKey)
337
+ async getIPNS (cid: CID, options: GetIPNSOptions = {}): Promise<Uint8Array<ArrayBuffer>> {
338
+ this.log('getIPNS starts: %c', cid)
349
339
 
350
340
  const timeoutSignal = AbortSignal.timeout(this.timeout)
351
341
  const signal = anySignal([this.shutDownController.signal, timeoutSignal, options.signal])
@@ -359,13 +349,17 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
359
349
  })
360
350
 
361
351
  // https://specs.ipfs.tech/routing/http-routing-v1/
362
- const resource = `${this.url}routing/v1/ipns/${libp2pKey}`
352
+ const resource = `${this.url}routing/v1/ipns/${cid}`
363
353
 
364
354
  try {
365
355
  await onStart.promise
366
356
 
367
- const getOptions = { headers: { Accept: 'application/vnd.ipfs.ipns-record' }, signal }
368
- const res = await this.#makeRequest(resource, getOptions)
357
+ const res = await this.#makeRequest(resource, {
358
+ headers: {
359
+ Accept: 'application/vnd.ipfs.ipns-record'
360
+ },
361
+ signal
362
+ })
369
363
 
370
364
  this.log('getIPNS GET %s %d', resource, res.status)
371
365
 
@@ -398,13 +392,8 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
398
392
  }
399
393
 
400
394
  const buf = await res.arrayBuffer()
401
- const body = new Uint8Array(buf, 0, buf.byteLength)
402
395
 
403
- if (options.validate !== false) {
404
- await ipnsValidator(multihashToIPNSRoutingKey(libp2pKey.multihash), body)
405
- }
406
-
407
- return unmarshalIPNSRecord(body)
396
+ return new Uint8Array(buf, 0, buf.byteLength)
408
397
  } catch (err: any) {
409
398
  this.log.error('getIPNS GET %s error - %e', resource, err)
410
399
 
@@ -412,11 +401,11 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
412
401
  } finally {
413
402
  signal.clear()
414
403
  onFinish.resolve()
415
- this.log('getIPNS finished: %s', libp2pKey)
404
+ this.log('getIPNS finished: %c', cid)
416
405
  }
417
406
  }
418
407
 
419
- async putIPNS (libp2pKey: CID<unknown, 0x72, 0x00 | 0x12, 1>, record: IPNSRecord, options: AbortOptions = {}): Promise<void> {
408
+ async putIPNS (libp2pKey: CID, record: Uint8Array, options: AbortOptions = {}): Promise<void> {
420
409
  this.log('putIPNS starts: %c', libp2pKey)
421
410
 
422
411
  const timeoutSignal = AbortSignal.timeout(this.timeout)
@@ -436,10 +425,14 @@ export class DelegatedRoutingV1HttpApiClient implements DelegatedRoutingV1HttpAp
436
425
  try {
437
426
  await onStart.promise
438
427
 
439
- const body = marshalIPNSRecord(record)
440
-
441
- const getOptions = { method: 'PUT', headers: { 'Content-Type': 'application/vnd.ipfs.ipns-record' }, body, signal }
442
- const res = await this.#makeRequest(resource, getOptions)
428
+ const res = await this.#makeRequest(resource, {
429
+ method: 'PUT',
430
+ headers: {
431
+ 'Content-Type': 'application/vnd.ipfs.ipns-record'
432
+ },
433
+ body: withArrayBuffer(record),
434
+ signal
435
+ })
443
436
 
444
437
  this.log('putIPNS PUT %s %d', resource, res.status)
445
438
 
@@ -0,0 +1 @@
1
+ export const CODE_LIBP2P_KEY = 0x72
package/src/index.ts CHANGED
@@ -98,10 +98,10 @@
98
98
  * ```
99
99
  */
100
100
 
101
- import { DelegatedRoutingV1HttpApiClient as DelegatedRoutingV1HttpApiClientClass } from './client.js'
102
- import type { AbortOptions, ComponentLogger, PeerId } from '@libp2p/interface'
101
+ import { DelegatedRoutingV1HttpApiClient as DelegatedRoutingV1HttpApiClientClass } from './client.ts'
102
+ import { DelegatedRoutingV1HttpApiClientContentRouting, DelegatedRoutingV1HttpApiClientPeerRouting } from './routings.ts'
103
+ import type { AbortOptions, ComponentLogger, ContentRouting, PeerId, PeerRouting } from '@libp2p/interface'
103
104
  import type { Multiaddr } from '@multiformats/multiaddr'
104
- import type { IPNSRecord } from 'ipns'
105
105
  import type { CID } from 'multiformats/cid'
106
106
 
107
107
  /**
@@ -179,16 +179,7 @@ export interface DelegatedRoutingV1HttpApiClientComponents {
179
179
  logger: ComponentLogger
180
180
  }
181
181
 
182
- export interface GetIPNSOptions extends AbortOptions {
183
- /**
184
- * By default incoming IPNS records are validated, pass false here to skip
185
- * validation and just return the record.
186
- *
187
- * @default true
188
- */
189
- validate?: boolean
190
- }
191
-
182
+ export type GetIPNSOptions = AbortOptions
192
183
  export type GetProvidersOptions = FilterOptions & AbortOptions
193
184
  export type GetPeersOptions = FilterOptions & AbortOptions
194
185
  export type GetClosestPeersOptions = FilterOptions & AbortOptions
@@ -207,25 +198,25 @@ export interface DelegatedRoutingV1HttpApiClient {
207
198
 
208
199
  /**
209
200
  * Returns an async generator of {@link PeerRecord}s for the provided
210
- * {@link PeerId}
201
+ * {@link CID}
211
202
  */
212
- getPeers(peerId: PeerId, options?: GetPeersOptions): AsyncGenerator<PeerRecord>
203
+ getPeers(cid: CID, options?: GetPeersOptions): AsyncGenerator<PeerRecord>
213
204
 
214
205
  /**
215
206
  * Returns an async generator of {@link PeerRecord}s of the closest peers to
216
207
  * the supplied key
217
208
  */
218
- getClosestPeers (key: CID | PeerId, options?: GetClosestPeersOptions): AsyncGenerator<PeerRecord>
209
+ getClosestPeers (cid: CID, options?: GetClosestPeersOptions): AsyncGenerator<PeerRecord>
219
210
 
220
211
  /**
221
- * Returns a promise of a {@link IPNSRecord} for the given {@link MultihashDigest}
212
+ * Returns a promise of a serialized IPNS record for passed CID
222
213
  */
223
- getIPNS(libp2pKey: CID<unknown, 0x72, 0x00 | 0x12, 1>, options?: GetIPNSOptions): Promise<IPNSRecord>
214
+ getIPNS(cid: CID, options?: GetIPNSOptions): Promise<Uint8Array<ArrayBuffer>>
224
215
 
225
216
  /**
226
- * Publishes the given {@link IPNSRecord} for the provided {@link MultihashDigest}
217
+ * Publishes a serialized IPNS record for the passed CID
227
218
  */
228
- putIPNS(libp2pKey: CID<unknown, 0x72, 0x00 | 0x12, 1>, record: IPNSRecord, options?: AbortOptions): Promise<void>
219
+ putIPNS(cid: CID, record: Uint8Array, options?: AbortOptions): Promise<void>
229
220
 
230
221
  /**
231
222
  * Create the request/response cache used to ensure duplicate requests aren't
@@ -246,3 +237,11 @@ export interface DelegatedRoutingV1HttpApiClient {
246
237
  export function delegatedRoutingV1HttpApiClient (init: DelegatedRoutingV1HttpApiClientInit): (components: DelegatedRoutingV1HttpApiClientComponents) => DelegatedRoutingV1HttpApiClient {
247
238
  return (components) => new DelegatedRoutingV1HttpApiClientClass(components, init)
248
239
  }
240
+
241
+ export function delegatedRoutingV1HttpApiClientContentRouting (init: DelegatedRoutingV1HttpApiClientInit): (components: DelegatedRoutingV1HttpApiClientComponents) => ContentRouting {
242
+ return (components) => new DelegatedRoutingV1HttpApiClientContentRouting(delegatedRoutingV1HttpApiClient(init)(components))
243
+ }
244
+
245
+ export function delegatedRoutingV1HttpApiClientPeerRouting (init: DelegatedRoutingV1HttpApiClientInit): (components: DelegatedRoutingV1HttpApiClientComponents) => PeerRouting {
246
+ return (components) => new DelegatedRoutingV1HttpApiClientPeerRouting(delegatedRoutingV1HttpApiClient(init)(components))
247
+ }
package/src/routings.ts CHANGED
@@ -1,14 +1,15 @@
1
- import { NotFoundError } from '@libp2p/interface'
2
- import { peerIdFromMultihash } from '@libp2p/peer-id'
3
- import { marshalIPNSRecord, multihashFromIPNSRoutingKey, unmarshalIPNSRecord } from 'ipns'
1
+ import { contentRoutingSymbol, NotFoundError, peerRoutingSymbol } from '@libp2p/interface'
4
2
  import first from 'it-first'
5
3
  import map from 'it-map'
6
4
  import { digest } from 'multiformats'
7
5
  import { CID } from 'multiformats/cid'
6
+ import * as raw from 'multiformats/codecs/raw'
7
+ import * as Digest from 'multiformats/hashes/digest'
8
+ import { identity } from 'multiformats/hashes/identity'
8
9
  import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
9
10
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
10
- import type { DelegatedRoutingV1HttpApiClient } from './index.js'
11
- import type { ContentRouting, PeerRouting, AbortOptions, PeerId, PeerInfo, Provider } from '@libp2p/interface'
11
+ import type { DelegatedRoutingV1HttpApiClient } from './index.ts'
12
+ import type { ContentRouting, PeerRouting, AbortOptions, PeerId, PeerInfo, Provider, Startable } from '@libp2p/interface'
12
13
 
13
14
  const IPNS_PREFIX = uint8ArrayFromString('/ipns/')
14
15
 
@@ -19,13 +20,25 @@ function isIPNSKey (key: Uint8Array): boolean {
19
20
  /**
20
21
  * Wrapper class to convert [http-routing-v1 content events](https://specs.ipfs.tech/routing/http-routing-v1/#response-body) into returned values
21
22
  */
22
- export class DelegatedRoutingV1HttpApiClientContentRouting implements ContentRouting {
23
+ export class DelegatedRoutingV1HttpApiClientContentRouting implements ContentRouting, Startable {
23
24
  private readonly client: DelegatedRoutingV1HttpApiClient
24
25
 
25
26
  constructor (client: DelegatedRoutingV1HttpApiClient) {
26
27
  this.client = client
27
28
  }
28
29
 
30
+ get [contentRoutingSymbol] (): ContentRouting {
31
+ return this
32
+ }
33
+
34
+ async start (): Promise<void> {
35
+ await this.client.start()
36
+ }
37
+
38
+ async stop (): Promise<void> {
39
+ await this.client.stop()
40
+ }
41
+
29
42
  async * findProviders (cid: CID, options: AbortOptions = {}): AsyncIterable<Provider> {
30
43
  try {
31
44
  yield * map(this.client.getProviders(cid, options), (record) => {
@@ -59,11 +72,10 @@ export class DelegatedRoutingV1HttpApiClientContentRouting implements ContentRou
59
72
  return
60
73
  }
61
74
 
62
- const digest = multihashFromIPNSRoutingKey(key)
75
+ const digest = Digest.decode(key.slice(IPNS_PREFIX.length))
63
76
  const cid = CID.createV1(0x72, digest)
64
- const record = unmarshalIPNSRecord(value)
65
77
 
66
- await this.client.putIPNS(cid, record, options)
78
+ await this.client.putIPNS(cid, value, options)
67
79
  }
68
80
 
69
81
  async get (key: Uint8Array, options?: AbortOptions): Promise<Uint8Array> {
@@ -71,13 +83,11 @@ export class DelegatedRoutingV1HttpApiClientContentRouting implements ContentRou
71
83
  throw new NotFoundError('Not found')
72
84
  }
73
85
 
74
- const digest = multihashFromIPNSRoutingKey(key)
86
+ const digest = Digest.decode(key.slice(IPNS_PREFIX.length))
75
87
  const cid = CID.createV1(0x72, digest)
76
88
 
77
89
  try {
78
- const record = await this.client.getIPNS(cid, options)
79
-
80
- return marshalIPNSRecord(record)
90
+ return await this.client.getIPNS(cid, options)
81
91
  } catch (err: any) {
82
92
  // BadResponseError is thrown when the response had no body, which means
83
93
  // the record couldn't be found
@@ -97,15 +107,27 @@ export class DelegatedRoutingV1HttpApiClientContentRouting implements ContentRou
97
107
  /**
98
108
  * Wrapper class to convert [http-routing-v1](https://specs.ipfs.tech/routing/http-routing-v1/#response-body-0) events into expected libp2p values
99
109
  */
100
- export class DelegatedRoutingV1HttpApiClientPeerRouting implements PeerRouting {
110
+ export class DelegatedRoutingV1HttpApiClientPeerRouting implements PeerRouting, Startable {
101
111
  private readonly client: DelegatedRoutingV1HttpApiClient
102
112
 
103
113
  constructor (client: DelegatedRoutingV1HttpApiClient) {
104
114
  this.client = client
105
115
  }
106
116
 
117
+ get [peerRoutingSymbol] (): PeerRouting {
118
+ return this
119
+ }
120
+
121
+ async start (): Promise<void> {
122
+ await this.client.start()
123
+ }
124
+
125
+ async stop (): Promise<void> {
126
+ await this.client.stop()
127
+ }
128
+
107
129
  async findPeer (peerId: PeerId, options: AbortOptions = {}): Promise<PeerInfo> {
108
- const peer = await first(this.client.getPeers(peerId, options))
130
+ const peer = await first(this.client.getPeers(peerId.toCID(), options))
109
131
 
110
132
  if (peer != null) {
111
133
  return {
@@ -118,15 +140,19 @@ export class DelegatedRoutingV1HttpApiClientPeerRouting implements PeerRouting {
118
140
  }
119
141
 
120
142
  async * getClosestPeers (key: Uint8Array, options: AbortOptions = {}): AsyncIterable<PeerInfo> {
121
- let cidOrPeer: CID | PeerId
143
+ let cid: CID
122
144
 
123
145
  try {
124
- cidOrPeer = CID.decode(key)
146
+ cid = CID.decode(key)
125
147
  } catch {
126
- cidOrPeer = peerIdFromMultihash(digest.decode(key))
148
+ try {
149
+ cid = CID.createV1(0x72, digest.decode(key))
150
+ } catch {
151
+ cid = CID.createV1(raw.code, identity.digest(key))
152
+ }
127
153
  }
128
154
 
129
- for await (const peer of this.client.getClosestPeers(cidOrPeer, options)) {
155
+ for await (const peer of this.client.getClosestPeers(cid, options)) {
130
156
  yield {
131
157
  id: peer.ID,
132
158
  multiaddrs: peer.Addrs ?? []