@le-space/aleph-bootstrap 0.6.3 → 0.6.5

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.
Files changed (3) hide show
  1. package/index.d.ts +16 -2
  2. package/index.js +113 -41
  3. package/package.json +2 -2
package/index.d.ts CHANGED
@@ -4,9 +4,11 @@ declare const DEFAULT_ALEPH_API_HOST = "https://api.aleph.im";
4
4
  declare const DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
5
5
  declare const DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
6
6
  declare const DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
7
+ declare const DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
7
8
  declare const DEFAULT_BOOTSTRAP_MAX_AGE_MS: number;
8
9
  declare const DEFAULT_BOOTSTRAP_PAGINATION = 50;
9
10
  declare const DEFAULT_BOOTSTRAP_MAX_PAGES = 5;
11
+ declare const DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
10
12
  declare const RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
11
13
  interface RelayBootstrapAuthorizationPayload {
12
14
  ownerAddress: string;
@@ -26,8 +28,10 @@ interface RelayBootstrapAuthorizationRecord {
26
28
  }
27
29
  interface RelayBootstrapProofPayload {
28
30
  peerId: string;
29
- multiaddrs: string[];
31
+ multiaddrs?: string[];
30
32
  browserMultiaddrs?: string[];
33
+ multiaddrsHash?: string;
34
+ browserMultiaddrsHash?: string;
31
35
  registrationId?: string;
32
36
  profile?: string;
33
37
  version?: string;
@@ -77,10 +81,12 @@ interface DiscoverAlephBootstrapOptions {
77
81
  channel?: string;
78
82
  ref?: string;
79
83
  postType?: string;
84
+ postTypes?: string[];
80
85
  page?: number;
81
86
  pagination?: number;
82
87
  maxPages?: number;
83
88
  maxAgeMs?: number;
89
+ compactMultiaddrLimit?: number;
84
90
  browserDialableOnly?: boolean;
85
91
  requireDualKeyAttestation?: boolean;
86
92
  verifyDualKeyAttestation?: boolean;
@@ -105,10 +111,14 @@ interface CreateRelayBootstrapPostOptions {
105
111
  publisherAddress?: string;
106
112
  authorization?: RelayBootstrapAuthorizationRecord;
107
113
  relayProof?: RelayBootstrapProofRecord;
114
+ compact?: boolean;
115
+ compactMultiaddrLimit?: number;
108
116
  now?: number;
109
117
  hasher: (payload: string) => Promise<string> | string;
110
118
  }
111
119
  type RelayBootstrapTrustMode = "legacy-wallet-signed" | "dual-key-attested";
120
+ declare function relayBootstrapMultiaddrsHash(addrs: readonly string[]): string;
121
+ declare function selectCompactRelayBootstrapMultiaddrs(addrs: readonly string[], limit?: number): string[];
112
122
  declare function dedupeMultiaddrs(addrs: readonly string[]): string[];
113
123
  declare function isPublicMultiaddr(addr: string): boolean;
114
124
  declare function filterPublicMultiaddrs(addrs: readonly string[], options?: FilterPublicMultiaddrsOptions): string[];
@@ -126,6 +136,8 @@ declare function buildRelayBootstrapPostContent(args: {
126
136
  publisherAddress?: string;
127
137
  authorization?: RelayBootstrapAuthorizationRecord;
128
138
  relayProof?: RelayBootstrapProofRecord;
139
+ compact?: boolean;
140
+ compactMultiaddrLimit?: number;
129
141
  now?: number;
130
142
  }): RelayBootstrapPostContent;
131
143
  declare function createRelayBootstrapPost(args: CreateRelayBootstrapPostOptions): Promise<{
@@ -160,6 +172,8 @@ declare function signRelayBootstrapProof(args: {
160
172
  profile?: string;
161
173
  version?: string;
162
174
  updatedAt?: number;
175
+ compact?: boolean;
176
+ compactMultiaddrLimit?: number;
163
177
  signer: RelayBootstrapProofSigner;
164
178
  }): Promise<RelayBootstrapProofRecord>;
165
179
  declare function verifyRelayBootstrapAuthorization(authorization: RelayBootstrapAuthorizationRecord | null | undefined, options?: {
@@ -182,4 +196,4 @@ declare function createLibp2pAlephBootstrap(options?: DiscoverAlephBootstrapOpti
182
196
  tagName?: string;
183
197
  }): Promise<ReturnType<typeof bootstrap>>;
184
198
 
185
- export { type CreateRelayBootstrapPostOptions, DEFAULT_ALEPH_API_HOST, DEFAULT_ALEPH_BOOTSTRAP_CHANNEL, DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE, DEFAULT_ALEPH_BOOTSTRAP_REF, DEFAULT_BOOTSTRAP_MAX_AGE_MS, DEFAULT_BOOTSTRAP_MAX_PAGES, DEFAULT_BOOTSTRAP_PAGINATION, type DiscoverAlephBootstrapOptions, type FilterPublicMultiaddrsOptions, RELAY_BOOTSTRAP_SIGNATURE_SCHEME, type RelayBootstrapAuthorizationPayload, type RelayBootstrapAuthorizationRecord, type RelayBootstrapContent, type RelayBootstrapPostContent, type RelayBootstrapPostRecord, type RelayBootstrapProofPayload, type RelayBootstrapProofRecord, type RelayBootstrapProofSigner, type RelayBootstrapTrustMode, type RelayBootstrapVerificationResult, buildRelayBootstrapPostContent, createLibp2pAlephBootstrap, createRelayBootstrapPost, dedupeMultiaddrs, discoverAlephBootstrapMultiaddrs, fetchAlephBootstrapPosts, filterPublicMultiaddrs, isPublicMultiaddr, relayBootstrapTrustMode, selectCurrentRelayBootstrapPosts, signRelayBootstrapAuthorization, signRelayBootstrapProof, verifyRelayBootstrapAuthorization, verifyRelayBootstrapDualKeyContent, verifyRelayBootstrapProof };
199
+ export { type CreateRelayBootstrapPostOptions, DEFAULT_ALEPH_API_HOST, DEFAULT_ALEPH_BOOTSTRAP_CHANNEL, DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE, DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE, DEFAULT_ALEPH_BOOTSTRAP_REF, DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT, DEFAULT_BOOTSTRAP_MAX_AGE_MS, DEFAULT_BOOTSTRAP_MAX_PAGES, DEFAULT_BOOTSTRAP_PAGINATION, type DiscoverAlephBootstrapOptions, type FilterPublicMultiaddrsOptions, RELAY_BOOTSTRAP_SIGNATURE_SCHEME, type RelayBootstrapAuthorizationPayload, type RelayBootstrapAuthorizationRecord, type RelayBootstrapContent, type RelayBootstrapPostContent, type RelayBootstrapPostRecord, type RelayBootstrapProofPayload, type RelayBootstrapProofRecord, type RelayBootstrapProofSigner, type RelayBootstrapTrustMode, type RelayBootstrapVerificationResult, buildRelayBootstrapPostContent, createLibp2pAlephBootstrap, createRelayBootstrapPost, dedupeMultiaddrs, discoverAlephBootstrapMultiaddrs, fetchAlephBootstrapPosts, filterPublicMultiaddrs, isPublicMultiaddr, relayBootstrapMultiaddrsHash, relayBootstrapTrustMode, selectCompactRelayBootstrapMultiaddrs, selectCurrentRelayBootstrapPosts, signRelayBootstrapAuthorization, signRelayBootstrapProof, verifyRelayBootstrapAuthorization, verifyRelayBootstrapDualKeyContent, verifyRelayBootstrapProof };
package/index.js CHANGED
@@ -1,13 +1,15 @@
1
1
  // src/index.ts
2
2
  import { bootstrap } from "@libp2p/bootstrap";
3
- import { recoverMessageAddress } from "viem";
3
+ import { keccak256, recoverMessageAddress, stringToHex } from "viem";
4
4
  var DEFAULT_ALEPH_API_HOST = "https://api.aleph.im";
5
5
  var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
6
6
  var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
7
7
  var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
8
+ var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
8
9
  var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
9
10
  var DEFAULT_BOOTSTRAP_PAGINATION = 50;
10
11
  var DEFAULT_BOOTSTRAP_MAX_PAGES = 5;
12
+ var DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
11
13
  var RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
12
14
  function serializeOwnerAuthorizationPayload(payload) {
13
15
  return JSON.stringify({
@@ -25,14 +27,41 @@ function serializeOwnerAuthorizationPayload(payload) {
25
27
  function serializeRelayProofPayload(payload) {
26
28
  return JSON.stringify({
27
29
  peerId: payload.peerId,
28
- multiaddrs: dedupeMultiaddrs(payload.multiaddrs),
30
+ multiaddrs: payload.multiaddrs ? dedupeMultiaddrs(payload.multiaddrs) : void 0,
29
31
  browserMultiaddrs: payload.browserMultiaddrs ? dedupeMultiaddrs(payload.browserMultiaddrs) : void 0,
32
+ multiaddrsHash: payload.multiaddrsHash,
33
+ browserMultiaddrsHash: payload.browserMultiaddrsHash,
30
34
  registrationId: payload.registrationId,
31
35
  profile: payload.profile,
32
36
  version: payload.version,
33
37
  updatedAt: payload.updatedAt
34
38
  });
35
39
  }
40
+ function relayBootstrapMultiaddrsHash(addrs) {
41
+ return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
42
+ }
43
+ function compactPostType(postType) {
44
+ return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
45
+ }
46
+ function browserMultiaddrPreference(addr) {
47
+ const normalized = addr.toLowerCase();
48
+ if (normalized.includes("/tcp/443/tls/ws/")) return 0;
49
+ if (normalized.includes("/tls/ws/")) return 1;
50
+ if (normalized.includes("/webtransport/")) return 2;
51
+ if (normalized.includes("/webrtc-direct/")) return 3;
52
+ if (normalized.includes("/ws")) return 4;
53
+ return 5;
54
+ }
55
+ function selectCompactRelayBootstrapMultiaddrs(addrs, limit = DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT) {
56
+ const entries = filterPublicMultiaddrs(addrs, {
57
+ browserDialableOnly: true
58
+ }).map((addr, index) => ({ addr, index }));
59
+ entries.sort((left, right) => {
60
+ const preference = browserMultiaddrPreference(left.addr) - browserMultiaddrPreference(right.addr);
61
+ return preference !== 0 ? preference : left.index - right.index;
62
+ });
63
+ return entries.map((entry) => entry.addr).slice(0, Math.max(1, Math.floor(limit)));
64
+ }
36
65
  async function recoverAddressForSignature(payload, signature) {
37
66
  return recoverMessageAddress({
38
67
  message: payload,
@@ -194,8 +223,10 @@ function normalizeRelayBootstrapProofPayload(value) {
194
223
  const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter((entry) => typeof entry === "string") : void 0;
195
224
  return {
196
225
  peerId,
197
- multiaddrs: dedupeMultiaddrs(multiaddrs),
226
+ multiaddrs: multiaddrs.length > 0 ? dedupeMultiaddrs(multiaddrs) : void 0,
198
227
  browserMultiaddrs: browserMultiaddrs ? dedupeMultiaddrs(browserMultiaddrs) : void 0,
228
+ multiaddrsHash: asTrimmedString(payload.multiaddrsHash) ?? void 0,
229
+ browserMultiaddrsHash: asTrimmedString(payload.browserMultiaddrsHash) ?? void 0,
199
230
  registrationId: asTrimmedString(payload.registrationId) ?? void 0,
200
231
  profile: asTrimmedString(payload.profile) ?? void 0,
201
232
  version: asTrimmedString(payload.version) ?? void 0,
@@ -227,16 +258,24 @@ function normalizeRelayBootstrapPostRecord(value) {
227
258
  function buildRelayBootstrapPostContent(args) {
228
259
  const now = args.now ?? Date.now() / 1e3;
229
260
  const updatedAt = args.now ?? Date.now();
261
+ const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
262
+ const compact = args.compact ?? compactPostType(postType);
263
+ const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
264
+ const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
265
+ browserDialableOnly: true
266
+ }) : void 0;
267
+ const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
268
+ fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
269
+ args.compactMultiaddrLimit
270
+ );
230
271
  return {
231
- type: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
272
+ type: postType,
232
273
  address: args.sender,
233
274
  ...args.ref ? { ref: args.ref } : {},
234
275
  content: {
235
276
  peerId: args.peerId,
236
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
237
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
238
- browserDialableOnly: true
239
- }) : void 0,
277
+ multiaddrs: compact ? compactMultiaddrs : fullMultiaddrs,
278
+ browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
240
279
  registrationId: args.registrationId,
241
280
  profile: args.profile,
242
281
  version: args.version,
@@ -266,6 +305,8 @@ async function createRelayBootstrapPost(args) {
266
305
  publisherAddress: args.publisherAddress,
267
306
  authorization: args.authorization,
268
307
  relayProof: args.relayProof,
308
+ compact: args.compact,
309
+ compactMultiaddrLimit: args.compactMultiaddrLimit,
269
310
  now: nowMillis
270
311
  });
271
312
  itemContent.time = nowSeconds;
@@ -309,12 +350,20 @@ async function signRelayBootstrapAuthorization(args) {
309
350
  };
310
351
  }
311
352
  async function signRelayBootstrapProof(args) {
353
+ const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
354
+ const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
355
+ browserDialableOnly: true
356
+ }) : void 0;
357
+ const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
358
+ fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
359
+ args.compactMultiaddrLimit
360
+ );
361
+ const compact = args.compact ?? false;
312
362
  const payload = {
313
363
  peerId: args.peerId,
314
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
315
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
316
- browserDialableOnly: true
317
- }) : void 0,
364
+ multiaddrs: compact ? void 0 : fullMultiaddrs,
365
+ browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
366
+ multiaddrsHash: compact ? relayBootstrapMultiaddrsHash(compactMultiaddrs) : void 0,
318
367
  registrationId: args.registrationId,
319
368
  profile: args.profile,
320
369
  version: args.version,
@@ -432,11 +481,23 @@ async function verifyRelayBootstrapDualKeyContent(content, options = {}) {
432
481
  if (proofPayload.updatedAt !== content.updatedAt) {
433
482
  errors.push("Relay proof updatedAt does not match the bootstrap content.");
434
483
  }
435
- if (JSON.stringify(dedupeMultiaddrs(proofPayload.multiaddrs)) !== JSON.stringify(dedupeMultiaddrs(content.multiaddrs))) {
484
+ if (proofPayload.multiaddrsHash) {
485
+ if (proofPayload.multiaddrsHash !== relayBootstrapMultiaddrsHash(content.multiaddrs)) {
486
+ errors.push("Relay proof multiaddrs hash does not match the bootstrap content.");
487
+ }
488
+ } else if (JSON.stringify(dedupeMultiaddrs(proofPayload.multiaddrs ?? [])) !== JSON.stringify(dedupeMultiaddrs(content.multiaddrs))) {
436
489
  errors.push("Relay proof multiaddrs do not match the bootstrap content.");
437
490
  }
438
- if (JSON.stringify(dedupeMultiaddrs(proofPayload.browserMultiaddrs ?? [])) !== JSON.stringify(dedupeMultiaddrs(content.browserMultiaddrs ?? []))) {
439
- errors.push("Relay proof browserMultiaddrs do not match the bootstrap content.");
491
+ if (proofPayload.browserMultiaddrsHash) {
492
+ if (proofPayload.browserMultiaddrsHash !== relayBootstrapMultiaddrsHash(content.browserMultiaddrs ?? [])) {
493
+ errors.push(
494
+ "Relay proof browserMultiaddrs hash does not match the bootstrap content."
495
+ );
496
+ }
497
+ } else if (proofPayload.browserMultiaddrs || content.browserMultiaddrs) {
498
+ if (JSON.stringify(dedupeMultiaddrs(proofPayload.browserMultiaddrs ?? [])) !== JSON.stringify(dedupeMultiaddrs(content.browserMultiaddrs ?? []))) {
499
+ errors.push("Relay proof browserMultiaddrs do not match the bootstrap content.");
500
+ }
440
501
  }
441
502
  }
442
503
  return { ok: errors.length === 0, errors };
@@ -474,7 +535,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
474
535
  throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
475
536
  }
476
537
  const payload = await response.json();
477
- return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null);
538
+ return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
478
539
  }
479
540
  function compareRelayBootstrapPostRecency(left, right) {
480
541
  const leftUpdatedAt = left.content?.updatedAt ?? 0;
@@ -540,31 +601,38 @@ async function discoverAlephBootstrapMultiaddrs(options = {}) {
540
601
  const pagination = options.pagination ?? DEFAULT_BOOTSTRAP_PAGINATION;
541
602
  const startPage = options.page ?? 1;
542
603
  const maxPages = Math.max(1, options.maxPages ?? DEFAULT_BOOTSTRAP_MAX_PAGES);
543
- const collectedPosts = [];
544
- for (let offset = 0; offset < maxPages; offset += 1) {
545
- const page = startPage + offset;
546
- const pagePosts = await fetchAlephBootstrapPosts({
547
- ...options,
548
- page,
549
- pagination
550
- });
551
- collectedPosts.push(...pagePosts);
552
- const selectedPosts = selectCurrentRelayBootstrapPosts(collectedPosts, {
553
- maxAgeMs: options.maxAgeMs
554
- });
555
- const trustedPosts = await filterTrustedRelayBootstrapPosts(selectedPosts, {
556
- requireDualKeyAttestation: options.requireDualKeyAttestation,
557
- verifyDualKeyAttestation: options.verifyDualKeyAttestation
558
- });
559
- const addrs = relayBootstrapPostsToMultiaddrs(
560
- trustedPosts,
561
- browserDialableOnly
562
- );
563
- if (addrs.length > 0) {
564
- return addrs;
565
- }
566
- if (pagePosts.length < pagination) {
567
- break;
604
+ const postTypes = options.postType != null ? [options.postType] : options.postTypes && options.postTypes.length > 0 ? options.postTypes : [
605
+ DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
606
+ DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
607
+ ];
608
+ for (const postType of postTypes) {
609
+ const collectedPosts = [];
610
+ for (let offset = 0; offset < maxPages; offset += 1) {
611
+ const page = startPage + offset;
612
+ const pagePosts = await fetchAlephBootstrapPosts({
613
+ ...options,
614
+ postType,
615
+ page,
616
+ pagination
617
+ });
618
+ collectedPosts.push(...pagePosts);
619
+ const selectedPosts = selectCurrentRelayBootstrapPosts(collectedPosts, {
620
+ maxAgeMs: options.maxAgeMs
621
+ });
622
+ const trustedPosts = await filterTrustedRelayBootstrapPosts(selectedPosts, {
623
+ requireDualKeyAttestation: options.requireDualKeyAttestation,
624
+ verifyDualKeyAttestation: options.verifyDualKeyAttestation
625
+ });
626
+ const addrs = relayBootstrapPostsToMultiaddrs(
627
+ trustedPosts,
628
+ browserDialableOnly
629
+ );
630
+ if (addrs.length > 0) {
631
+ return addrs;
632
+ }
633
+ if (pagePosts.length < pagination) {
634
+ break;
635
+ }
568
636
  }
569
637
  }
570
638
  return [];
@@ -594,8 +662,10 @@ async function createLibp2pAlephBootstrap(options = {}) {
594
662
  export {
595
663
  DEFAULT_ALEPH_API_HOST,
596
664
  DEFAULT_ALEPH_BOOTSTRAP_CHANNEL,
665
+ DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
597
666
  DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
598
667
  DEFAULT_ALEPH_BOOTSTRAP_REF,
668
+ DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT,
599
669
  DEFAULT_BOOTSTRAP_MAX_AGE_MS,
600
670
  DEFAULT_BOOTSTRAP_MAX_PAGES,
601
671
  DEFAULT_BOOTSTRAP_PAGINATION,
@@ -608,7 +678,9 @@ export {
608
678
  fetchAlephBootstrapPosts,
609
679
  filterPublicMultiaddrs,
610
680
  isPublicMultiaddr,
681
+ relayBootstrapMultiaddrsHash,
611
682
  relayBootstrapTrustMode,
683
+ selectCompactRelayBootstrapMultiaddrs,
612
684
  selectCurrentRelayBootstrapPosts,
613
685
  signRelayBootstrapAuthorization,
614
686
  signRelayBootstrapProof,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/aleph-bootstrap",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "Aleph-backed libp2p bootstrap discovery and relay registration helpers.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,6 +25,6 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@libp2p/bootstrap": "^11.0.46",
28
- "viem": "^2.38.5"
28
+ "viem": "^2.53.1"
29
29
  }
30
30
  }