@le-space/aleph-bootstrap 0.6.23 → 0.6.25

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.
package/README.md CHANGED
@@ -27,20 +27,21 @@ The package defaults to the shared relay-bootstrap namespace:
27
27
 
28
28
  - channel: `simple-todo`
29
29
  - ref: `simple-todo-bootstrap`
30
- - post type: `relay-bootstrap`
30
+ - post type: `relay-bootstrap-v2`
31
31
 
32
- All values are overrideable per app or environment.
32
+ The channel and ref are overrideable per app or environment. The post type is
33
+ fixed to `relay-bootstrap-v2`.
33
34
 
34
35
  ## Discovery Trust Modes
35
36
 
36
- The package accepts both:
37
+ The package accepts two signing modes for v2 records:
37
38
 
38
- - legacy wallet-signed bootstrap posts
39
+ - wallet-signed bootstrap posts
39
40
  - dual-key-attested bootstrap posts
40
41
 
41
42
  By default, discovery will:
42
43
 
43
- - accept legacy posts
44
+ - accept wallet-signed v2 posts
44
45
  - verify dual-key records when they are present
45
46
  - ignore malformed or invalid dual-key records
46
47
 
package/index.d.ts CHANGED
@@ -3,8 +3,7 @@ import { bootstrap } from '@libp2p/bootstrap';
3
3
  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
- declare const DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
7
- declare const DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
6
+ declare const DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap-v2";
8
7
  declare const DEFAULT_BOOTSTRAP_MAX_AGE_MS: number;
9
8
  declare const DEFAULT_BOOTSTRAP_PAGINATION = 50;
10
9
  declare const DEFAULT_BOOTSTRAP_MAX_PAGES = 5;
@@ -80,8 +79,6 @@ interface DiscoverAlephBootstrapOptions {
80
79
  apiHost?: string;
81
80
  channel?: string;
82
81
  ref?: string;
83
- postType?: string;
84
- postTypes?: string[];
85
82
  page?: number;
86
83
  pagination?: number;
87
84
  maxPages?: number;
@@ -104,19 +101,17 @@ interface CreateRelayBootstrapPostOptions {
104
101
  registrationId?: string;
105
102
  ref?: string;
106
103
  channel?: string;
107
- postType?: string;
108
104
  profile?: string;
109
105
  version?: string;
110
106
  ownerAddress?: string;
111
107
  publisherAddress?: string;
112
108
  authorization?: RelayBootstrapAuthorizationRecord;
113
109
  relayProof?: RelayBootstrapProofRecord;
114
- compact?: boolean;
115
110
  compactMultiaddrLimit?: number;
116
111
  now?: number;
117
112
  hasher: (payload: string) => Promise<string> | string;
118
113
  }
119
- type RelayBootstrapTrustMode = "legacy-wallet-signed" | "dual-key-attested";
114
+ type RelayBootstrapTrustMode = "wallet-signed" | "dual-key-attested";
120
115
  declare function relayBootstrapMultiaddrsHash(addrs: readonly string[]): string;
121
116
  declare function selectCompactRelayBootstrapMultiaddrs(addrs: readonly string[], limit?: number): string[];
122
117
  declare function dedupeMultiaddrs(addrs: readonly string[]): string[];
@@ -129,14 +124,12 @@ declare function buildRelayBootstrapPostContent(args: {
129
124
  browserMultiaddrs?: string[];
130
125
  registrationId?: string;
131
126
  ref?: string;
132
- postType?: string;
133
127
  profile?: string;
134
128
  version?: string;
135
129
  ownerAddress?: string;
136
130
  publisherAddress?: string;
137
131
  authorization?: RelayBootstrapAuthorizationRecord;
138
132
  relayProof?: RelayBootstrapProofRecord;
139
- compact?: boolean;
140
133
  compactMultiaddrLimit?: number;
141
134
  now?: number;
142
135
  }): RelayBootstrapPostContent;
@@ -172,7 +165,6 @@ declare function signRelayBootstrapProof(args: {
172
165
  profile?: string;
173
166
  version?: string;
174
167
  updatedAt?: number;
175
- compact?: boolean;
176
168
  compactMultiaddrLimit?: number;
177
169
  signer: RelayBootstrapProofSigner;
178
170
  }): Promise<RelayBootstrapProofRecord>;
@@ -196,4 +188,4 @@ declare function createLibp2pAlephBootstrap(options?: DiscoverAlephBootstrapOpti
196
188
  tagName?: string;
197
189
  }): Promise<ReturnType<typeof bootstrap>>;
198
190
 
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 };
191
+ export { type CreateRelayBootstrapPostOptions, DEFAULT_ALEPH_API_HOST, DEFAULT_ALEPH_BOOTSTRAP_CHANNEL, 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
@@ -4,8 +4,7 @@ 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
- var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
8
- var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
7
+ var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap-v2";
9
8
  var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
10
9
  var DEFAULT_BOOTSTRAP_PAGINATION = 50;
11
10
  var DEFAULT_BOOTSTRAP_MAX_PAGES = 5;
@@ -40,9 +39,6 @@ function serializeRelayProofPayload(payload) {
40
39
  function relayBootstrapMultiaddrsHash(addrs) {
41
40
  return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
42
41
  }
43
- function compactPostType(postType) {
44
- return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
45
- }
46
42
  function browserMultiaddrPreference(addr) {
47
43
  const normalized = addr.toLowerCase();
48
44
  if (normalized.includes("/tcp/443/tls/ws/")) return 0;
@@ -278,8 +274,6 @@ function normalizeRelayBootstrapPostRecord(value) {
278
274
  function buildRelayBootstrapPostContent(args) {
279
275
  const now = args.now ?? Date.now() / 1e3;
280
276
  const updatedAt = args.now ?? Date.now();
281
- const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
282
- const compact = args.compact ?? compactPostType(postType);
283
277
  const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
284
278
  const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
285
279
  browserDialableOnly: true
@@ -289,13 +283,13 @@ function buildRelayBootstrapPostContent(args) {
289
283
  args.compactMultiaddrLimit
290
284
  );
291
285
  return {
292
- type: postType,
286
+ type: DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
293
287
  address: args.sender,
294
288
  ...args.ref ? { ref: args.ref } : {},
295
289
  content: {
296
290
  peerId: args.peerId,
297
- multiaddrs: compact ? compactMultiaddrs : fullMultiaddrs,
298
- browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
291
+ multiaddrs: compactMultiaddrs,
292
+ browserMultiaddrs: void 0,
299
293
  registrationId: args.registrationId,
300
294
  profile: args.profile,
301
295
  version: args.version,
@@ -318,14 +312,12 @@ async function createRelayBootstrapPost(args) {
318
312
  browserMultiaddrs: args.browserMultiaddrs,
319
313
  registrationId: args.registrationId,
320
314
  ref: args.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF,
321
- postType: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
322
315
  profile: args.profile,
323
316
  version: args.version,
324
317
  ownerAddress: args.ownerAddress,
325
318
  publisherAddress: args.publisherAddress,
326
319
  authorization: args.authorization,
327
320
  relayProof: args.relayProof,
328
- compact: args.compact,
329
321
  compactMultiaddrLimit: args.compactMultiaddrLimit,
330
322
  now: nowMillis
331
323
  });
@@ -347,7 +339,7 @@ function relayBootstrapTrustMode(content) {
347
339
  if (content?.authorization && content?.relayProof && content.authorization.payload.publisherAddress && content.relayProof.payload.peerId) {
348
340
  return "dual-key-attested";
349
341
  }
350
- return "legacy-wallet-signed";
342
+ return "wallet-signed";
351
343
  }
352
344
  async function signRelayBootstrapAuthorization(args) {
353
345
  const payload = {
@@ -378,12 +370,11 @@ async function signRelayBootstrapProof(args) {
378
370
  fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
379
371
  args.compactMultiaddrLimit
380
372
  );
381
- const compact = args.compact ?? false;
382
373
  const payload = {
383
374
  peerId: args.peerId,
384
- multiaddrs: compact ? void 0 : fullMultiaddrs,
385
- browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
386
- multiaddrsHash: compact ? relayBootstrapMultiaddrsHash(compactMultiaddrs) : void 0,
375
+ multiaddrs: void 0,
376
+ browserMultiaddrs: void 0,
377
+ multiaddrsHash: relayBootstrapMultiaddrsHash(compactMultiaddrs),
387
378
  registrationId: args.registrationId,
388
379
  profile: args.profile,
389
380
  version: args.version,
@@ -538,10 +529,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
538
529
  options.channel ?? DEFAULT_ALEPH_BOOTSTRAP_CHANNEL
539
530
  );
540
531
  url.searchParams.set("refs", options.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF);
541
- url.searchParams.set(
542
- "types",
543
- options.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
544
- );
532
+ url.searchParams.set("types", DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE);
545
533
  url.searchParams.set(
546
534
  "pagination",
547
535
  String(options.pagination ?? DEFAULT_BOOTSTRAP_PAGINATION)
@@ -555,7 +543,21 @@ async function fetchAlephBootstrapPosts(options = {}) {
555
543
  throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
556
544
  }
557
545
  const payload = await response.json();
558
- return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
546
+ const posts = (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
547
+ posts.forEach(assertSupportedRelayBootstrapPost);
548
+ return posts;
549
+ }
550
+ function assertSupportedRelayBootstrapPost(post) {
551
+ if (post.type === "relay-bootstrap") {
552
+ throw new Error(
553
+ "Legacy relay-bootstrap record encountered. Only relay-bootstrap-v2 is supported."
554
+ );
555
+ }
556
+ if (post.type && post.type !== DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE) {
557
+ throw new Error(
558
+ `Unsupported relay bootstrap post type: ${post.type}. Expected ${DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE}.`
559
+ );
560
+ }
559
561
  }
560
562
  function compareRelayBootstrapPostRecency(left, right) {
561
563
  const leftUpdatedAt = left.content?.updatedAt ?? 0;
@@ -577,6 +579,7 @@ function selectCurrentRelayBootstrapPosts(posts, options = {}) {
577
579
  const now = options.now ?? Date.now();
578
580
  const selected = /* @__PURE__ */ new Map();
579
581
  for (const post of posts) {
582
+ assertSupportedRelayBootstrapPost(post);
580
583
  const content = post.content;
581
584
  if (!content) continue;
582
585
  if (now - content.updatedAt > maxAgeMs) continue;
@@ -599,7 +602,7 @@ async function filterTrustedRelayBootstrapPosts(posts, options = {}) {
599
602
  const content = post.content;
600
603
  if (!content) continue;
601
604
  const trustMode = relayBootstrapTrustMode(content);
602
- if (trustMode === "legacy-wallet-signed") {
605
+ if (trustMode === "wallet-signed") {
603
606
  if (!requireDualKeyAttestation) {
604
607
  trusted.push(post);
605
608
  }
@@ -621,38 +624,31 @@ async function discoverAlephBootstrapMultiaddrs(options = {}) {
621
624
  const pagination = options.pagination ?? DEFAULT_BOOTSTRAP_PAGINATION;
622
625
  const startPage = options.page ?? 1;
623
626
  const maxPages = Math.max(1, options.maxPages ?? DEFAULT_BOOTSTRAP_MAX_PAGES);
624
- const postTypes = options.postType != null ? [options.postType] : options.postTypes && options.postTypes.length > 0 ? options.postTypes : [
625
- DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
626
- DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
627
- ];
628
- for (const postType of postTypes) {
629
- const collectedPosts = [];
630
- for (let offset = 0; offset < maxPages; offset += 1) {
631
- const page = startPage + offset;
632
- const pagePosts = await fetchAlephBootstrapPosts({
633
- ...options,
634
- postType,
635
- page,
636
- pagination
637
- });
638
- collectedPosts.push(...pagePosts);
639
- const selectedPosts = selectCurrentRelayBootstrapPosts(collectedPosts, {
640
- maxAgeMs: options.maxAgeMs
641
- });
642
- const trustedPosts = await filterTrustedRelayBootstrapPosts(selectedPosts, {
643
- requireDualKeyAttestation: options.requireDualKeyAttestation,
644
- verifyDualKeyAttestation: options.verifyDualKeyAttestation
645
- });
646
- const addrs = relayBootstrapPostsToMultiaddrs(
647
- trustedPosts,
648
- browserDialableOnly
649
- );
650
- if (addrs.length > 0) {
651
- return addrs;
652
- }
653
- if (pagePosts.length < pagination) {
654
- break;
655
- }
627
+ const collectedPosts = [];
628
+ for (let offset = 0; offset < maxPages; offset += 1) {
629
+ const page = startPage + offset;
630
+ const pagePosts = await fetchAlephBootstrapPosts({
631
+ ...options,
632
+ page,
633
+ pagination
634
+ });
635
+ collectedPosts.push(...pagePosts);
636
+ const selectedPosts = selectCurrentRelayBootstrapPosts(collectedPosts, {
637
+ maxAgeMs: options.maxAgeMs
638
+ });
639
+ const trustedPosts = await filterTrustedRelayBootstrapPosts(selectedPosts, {
640
+ requireDualKeyAttestation: options.requireDualKeyAttestation,
641
+ verifyDualKeyAttestation: options.verifyDualKeyAttestation
642
+ });
643
+ const addrs = relayBootstrapPostsToMultiaddrs(
644
+ trustedPosts,
645
+ browserDialableOnly
646
+ );
647
+ if (addrs.length > 0) {
648
+ return addrs;
649
+ }
650
+ if (pagePosts.length < pagination) {
651
+ break;
656
652
  }
657
653
  }
658
654
  return [];
@@ -682,7 +678,6 @@ async function createLibp2pAlephBootstrap(options = {}) {
682
678
  export {
683
679
  DEFAULT_ALEPH_API_HOST,
684
680
  DEFAULT_ALEPH_BOOTSTRAP_CHANNEL,
685
- DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
686
681
  DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
687
682
  DEFAULT_ALEPH_BOOTSTRAP_REF,
688
683
  DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/aleph-bootstrap",
3
- "version": "0.6.23",
3
+ "version": "0.6.25",
4
4
  "description": "Aleph-backed libp2p bootstrap discovery and relay registration helpers.",
5
5
  "license": "MIT",
6
6
  "type": "module",