@le-space/ui 0.6.4 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/ui",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "description": "Floating Aleph sponsor relay UI components for Svelte and React.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,9 +44,9 @@
44
44
  "url": "https://github.com/NiKrause/relay-button/issues"
45
45
  },
46
46
  "dependencies": {
47
- "@le-space/browser": "0.6.4",
48
- "@le-space/core": "0.6.4",
49
- "viem": "^2.38.5"
47
+ "@le-space/browser": "0.6.5",
48
+ "@le-space/core": "0.6.5",
49
+ "viem": "^2.53.1"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": ">=18",
package/react/index.js CHANGED
@@ -43,7 +43,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
43
43
  var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
44
44
 
45
45
  // src/shared/package-version.ts
46
- var UI_PACKAGE_VERSION = "0.6.4";
46
+ var UI_PACKAGE_VERSION = "0.6.5";
47
47
 
48
48
  // src/shared/format.ts
49
49
  function shortHash(value, head = 8, tail = 6) {
@@ -2333,9 +2333,11 @@ async function configureUcanStore(args) {
2333
2333
  proxy_url: args.proxyUrl ?? void 0,
2334
2334
  service_did: args.serviceDid ?? void 0,
2335
2335
  service_origin: args.serviceOrigin ?? void 0,
2336
+ public_storage_origin: args.publicStorageOrigin ?? void 0,
2336
2337
  webauthn_origin: args.webauthnOrigin ?? void 0,
2337
2338
  webauthn_origin_fallbacks: args.webauthnOriginFallbacks ?? void 0,
2338
2339
  admin_did: args.adminDid ?? void 0,
2340
+ admin_api_token: args.adminApiToken ?? void 0,
2339
2341
  bootstrap_package: args.bootstrapPackage ?? void 0,
2340
2342
  no_start: args.noStart === true ? true : void 0
2341
2343
  };
@@ -2434,13 +2436,15 @@ async function fetchUcGoPeerMetadata(args) {
2434
2436
  }
2435
2437
 
2436
2438
  // ../aleph-bootstrap/src/index.ts
2437
- import { recoverMessageAddress } from "viem";
2439
+ import { keccak256, recoverMessageAddress, stringToHex } from "viem";
2438
2440
  var DEFAULT_ALEPH_API_HOST3 = "https://api.aleph.im";
2439
2441
  var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
2440
2442
  var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
2441
2443
  var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
2444
+ var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
2442
2445
  var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
2443
2446
  var DEFAULT_BOOTSTRAP_PAGINATION = 50;
2447
+ var DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
2444
2448
  var RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
2445
2449
  function serializeOwnerAuthorizationPayload(payload) {
2446
2450
  return JSON.stringify({
@@ -2458,14 +2462,41 @@ function serializeOwnerAuthorizationPayload(payload) {
2458
2462
  function serializeRelayProofPayload(payload) {
2459
2463
  return JSON.stringify({
2460
2464
  peerId: payload.peerId,
2461
- multiaddrs: dedupeMultiaddrs(payload.multiaddrs),
2465
+ multiaddrs: payload.multiaddrs ? dedupeMultiaddrs(payload.multiaddrs) : void 0,
2462
2466
  browserMultiaddrs: payload.browserMultiaddrs ? dedupeMultiaddrs(payload.browserMultiaddrs) : void 0,
2467
+ multiaddrsHash: payload.multiaddrsHash,
2468
+ browserMultiaddrsHash: payload.browserMultiaddrsHash,
2463
2469
  registrationId: payload.registrationId,
2464
2470
  profile: payload.profile,
2465
2471
  version: payload.version,
2466
2472
  updatedAt: payload.updatedAt
2467
2473
  });
2468
2474
  }
2475
+ function relayBootstrapMultiaddrsHash(addrs) {
2476
+ return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
2477
+ }
2478
+ function compactPostType(postType) {
2479
+ return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2480
+ }
2481
+ function browserMultiaddrPreference(addr) {
2482
+ const normalized = addr.toLowerCase();
2483
+ if (normalized.includes("/tcp/443/tls/ws/")) return 0;
2484
+ if (normalized.includes("/tls/ws/")) return 1;
2485
+ if (normalized.includes("/webtransport/")) return 2;
2486
+ if (normalized.includes("/webrtc-direct/")) return 3;
2487
+ if (normalized.includes("/ws")) return 4;
2488
+ return 5;
2489
+ }
2490
+ function selectCompactRelayBootstrapMultiaddrs(addrs, limit = DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT) {
2491
+ const entries = filterPublicMultiaddrs(addrs, {
2492
+ browserDialableOnly: true
2493
+ }).map((addr, index) => ({ addr, index }));
2494
+ entries.sort((left, right) => {
2495
+ const preference = browserMultiaddrPreference(left.addr) - browserMultiaddrPreference(right.addr);
2496
+ return preference !== 0 ? preference : left.index - right.index;
2497
+ });
2498
+ return entries.map((entry) => entry.addr).slice(0, Math.max(1, Math.floor(limit)));
2499
+ }
2469
2500
  function asTrimmedString(value) {
2470
2501
  return typeof value === "string" && value.trim() ? value.trim() : null;
2471
2502
  }
@@ -2621,8 +2652,10 @@ function normalizeRelayBootstrapProofPayload(value) {
2621
2652
  const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter((entry) => typeof entry === "string") : void 0;
2622
2653
  return {
2623
2654
  peerId,
2624
- multiaddrs: dedupeMultiaddrs(multiaddrs),
2655
+ multiaddrs: multiaddrs.length > 0 ? dedupeMultiaddrs(multiaddrs) : void 0,
2625
2656
  browserMultiaddrs: browserMultiaddrs ? dedupeMultiaddrs(browserMultiaddrs) : void 0,
2657
+ multiaddrsHash: asTrimmedString(payload.multiaddrsHash) ?? void 0,
2658
+ browserMultiaddrsHash: asTrimmedString(payload.browserMultiaddrsHash) ?? void 0,
2626
2659
  registrationId: asTrimmedString(payload.registrationId) ?? void 0,
2627
2660
  profile: asTrimmedString(payload.profile) ?? void 0,
2628
2661
  version: asTrimmedString(payload.version) ?? void 0,
@@ -2654,16 +2687,24 @@ function normalizeRelayBootstrapPostRecord(value) {
2654
2687
  function buildRelayBootstrapPostContent(args) {
2655
2688
  const now = args.now ?? Date.now() / 1e3;
2656
2689
  const updatedAt = args.now ?? Date.now();
2690
+ const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
2691
+ const compact = args.compact ?? compactPostType(postType);
2692
+ const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
2693
+ const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2694
+ browserDialableOnly: true
2695
+ }) : void 0;
2696
+ const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
2697
+ fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
2698
+ args.compactMultiaddrLimit
2699
+ );
2657
2700
  return {
2658
- type: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
2701
+ type: postType,
2659
2702
  address: args.sender,
2660
2703
  ...args.ref ? { ref: args.ref } : {},
2661
2704
  content: {
2662
2705
  peerId: args.peerId,
2663
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
2664
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2665
- browserDialableOnly: true
2666
- }) : void 0,
2706
+ multiaddrs: compact ? compactMultiaddrs : fullMultiaddrs,
2707
+ browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
2667
2708
  registrationId: args.registrationId,
2668
2709
  profile: args.profile,
2669
2710
  version: args.version,
@@ -2693,6 +2734,8 @@ async function createRelayBootstrapPost(args) {
2693
2734
  publisherAddress: args.publisherAddress,
2694
2735
  authorization: args.authorization,
2695
2736
  relayProof: args.relayProof,
2737
+ compact: args.compact,
2738
+ compactMultiaddrLimit: args.compactMultiaddrLimit,
2696
2739
  now: nowMillis
2697
2740
  });
2698
2741
  itemContent.time = nowSeconds;
@@ -2730,12 +2773,20 @@ async function signRelayBootstrapAuthorization(args) {
2730
2773
  };
2731
2774
  }
2732
2775
  async function signRelayBootstrapProof(args) {
2776
+ const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
2777
+ const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2778
+ browserDialableOnly: true
2779
+ }) : void 0;
2780
+ const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
2781
+ fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
2782
+ args.compactMultiaddrLimit
2783
+ );
2784
+ const compact = args.compact ?? false;
2733
2785
  const payload = {
2734
2786
  peerId: args.peerId,
2735
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
2736
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2737
- browserDialableOnly: true
2738
- }) : void 0,
2787
+ multiaddrs: compact ? void 0 : fullMultiaddrs,
2788
+ browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
2789
+ multiaddrsHash: compact ? relayBootstrapMultiaddrsHash(compactMultiaddrs) : void 0,
2739
2790
  registrationId: args.registrationId,
2740
2791
  profile: args.profile,
2741
2792
  version: args.version,
@@ -2782,7 +2833,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
2782
2833
  throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
2783
2834
  }
2784
2835
  const payload = await response.json();
2785
- return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null);
2836
+ return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
2786
2837
  }
2787
2838
  function compareRelayBootstrapPostRecency(left, right) {
2788
2839
  const leftUpdatedAt = left.content?.updatedAt ?? 0;
@@ -2829,12 +2880,14 @@ async function waitForRelayBootstrapRegistration(args) {
2829
2880
  const expectedSender = args.sender?.trim().toLowerCase() || null;
2830
2881
  const expectedRegistrationId = args.registrationId?.trim() || null;
2831
2882
  const expectedPeerId = args.peerId?.trim() || null;
2883
+ const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2884
+ const sleepImpl = args.sleep ?? sleep;
2832
2885
  for (let attempt = 0; attempt < attempts; attempt += 1) {
2833
2886
  const posts = await fetchAlephBootstrapPosts({
2834
2887
  apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
2835
2888
  channel: args.channel,
2836
2889
  ref: args.ref,
2837
- postType: args.postType,
2890
+ postType,
2838
2891
  fetch: args.fetch
2839
2892
  });
2840
2893
  const currentPosts = selectCurrentRelayBootstrapPosts(posts);
@@ -2865,7 +2918,7 @@ async function waitForRelayBootstrapRegistration(args) {
2865
2918
  }
2866
2919
  args.onAttempt?.(null, attempt + 1, attempts);
2867
2920
  if (attempt < attempts - 1) {
2868
- await sleep(delayMs);
2921
+ await sleepImpl(delayMs);
2869
2922
  }
2870
2923
  }
2871
2924
  return null;
@@ -2873,6 +2926,8 @@ async function waitForRelayBootstrapRegistration(args) {
2873
2926
  async function publishRelayBootstrapRegistration(args) {
2874
2927
  const publisherAddress = args.publisherAddress ?? args.sender;
2875
2928
  const ownerAddress = args.ownerAddress;
2929
+ const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2930
+ const compact = postType === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2876
2931
  let ownerAuthorization = args.ownerAuthorization;
2877
2932
  let relayProof = args.relayProof;
2878
2933
  if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
@@ -2899,6 +2954,8 @@ async function publishRelayBootstrapRegistration(args) {
2899
2954
  profile: args.profile,
2900
2955
  version: args.version,
2901
2956
  updatedAt: args.now ?? Date.now(),
2957
+ compact,
2958
+ compactMultiaddrLimit: args.compactMultiaddrLimit,
2902
2959
  signer: args.publisherSigner
2903
2960
  });
2904
2961
  }
@@ -2910,13 +2967,15 @@ async function publishRelayBootstrapRegistration(args) {
2910
2967
  registrationId: args.registrationId,
2911
2968
  channel: args.channel,
2912
2969
  ref: args.ref,
2913
- postType: args.postType,
2970
+ postType,
2914
2971
  profile: args.profile,
2915
2972
  version: args.version,
2916
2973
  ownerAddress,
2917
2974
  publisherAddress,
2918
2975
  authorization: ownerAuthorization,
2919
2976
  relayProof,
2977
+ compact,
2978
+ compactMultiaddrLimit: args.compactMultiaddrLimit,
2920
2979
  now: args.now,
2921
2980
  hasher: args.hasher
2922
2981
  });
@@ -2938,16 +2997,33 @@ async function publishRelayBootstrapRegistration(args) {
2938
2997
  let forgottenHashes = [];
2939
2998
  let forgetResult;
2940
2999
  if (args.forgetPrevious && args.registrationId) {
2941
- const previousPosts = await fetchAlephBootstrapPosts({
2942
- apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
2943
- channel: args.channel,
2944
- ref: args.ref,
2945
- postType: args.postType,
2946
- fetch: args.fetch
2947
- });
2948
- forgottenHashes = previousPosts.filter(
2949
- (post) => post.address?.toLowerCase() === args.sender.toLowerCase() && post.content?.registrationId === args.registrationId && (post.itemHash ?? post.hash) != null && (post.itemHash ?? post.hash) !== unsigned.item_hash
2950
- ).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean);
3000
+ const previousPostTypes = compact ? [postType, DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE] : [postType];
3001
+ const previousPosts = (await Promise.all(
3002
+ previousPostTypes.map(
3003
+ (previousPostType) => fetchAlephBootstrapPosts({
3004
+ apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
3005
+ channel: args.channel,
3006
+ ref: args.ref,
3007
+ postType: previousPostType,
3008
+ fetch: args.fetch
3009
+ })
3010
+ )
3011
+ )).flat();
3012
+ const forgottenHashSet = new Set(
3013
+ previousPosts.filter((post) => {
3014
+ const hash = post.itemHash ?? post.hash;
3015
+ if (!hash || hash === unsigned.item_hash) return false;
3016
+ if (post.address?.toLowerCase() !== args.sender.toLowerCase()) {
3017
+ return false;
3018
+ }
3019
+ const content2 = post.content;
3020
+ if (!content2) return false;
3021
+ if (content2.registrationId === args.registrationId) return true;
3022
+ if (content2.peerId !== args.peerId) return false;
3023
+ return !args.profile || content2.profile === args.profile;
3024
+ }).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean)
3025
+ );
3026
+ forgottenHashes = [...forgottenHashSet];
2951
3027
  if (forgottenHashes.length > 0) {
2952
3028
  forgetResult = await forgetAlephMessages({
2953
3029
  sender: args.sender,
@@ -2968,7 +3044,7 @@ async function publishRelayBootstrapRegistration(args) {
2968
3044
  response,
2969
3045
  httpStatus,
2970
3046
  publishedMultiaddrs: content.content?.multiaddrs ?? [],
2971
- publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
3047
+ publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? content.content?.multiaddrs ?? [],
2972
3048
  forgottenHashes,
2973
3049
  forgetResult
2974
3050
  };
@@ -4118,6 +4194,8 @@ var SponsorRelayController = class {
4118
4194
  setupPort,
4119
4195
  proxyUrl: serviceProxyUrl,
4120
4196
  webauthnOrigin: serviceProxyUrl,
4197
+ serviceDid: bootstrapValidation.bootstrapPackage.serviceDid,
4198
+ serviceOrigin: bootstrapValidation.bootstrapPackage.serviceOrigin,
4121
4199
  adminDid: bootstrapValidation.bootstrapPackage.adminDid,
4122
4200
  bootstrapPackage: bootstrapValidation.bootstrapPackage,
4123
4201
  fetch: (url, init) => fetch(url, init),
@@ -5020,10 +5098,18 @@ var SponsorRelayController = class {
5020
5098
  const [nextBalance, rawInstances, rawBootstrapPosts] = await Promise.all([
5021
5099
  this.client.fetchBalance(this.state.wallet.address),
5022
5100
  this.state.showInstances ? this.client.fetchInstances(this.state.wallet.address) : Promise.resolve([]),
5023
- bootstrapEnabled ? fetchAlephBootstrapPosts({
5024
- apiHost: this.client.apiHost,
5025
- fetch
5026
- }).catch(() => []) : Promise.resolve([])
5101
+ bootstrapEnabled ? Promise.all(
5102
+ [
5103
+ DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
5104
+ DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
5105
+ ].map(
5106
+ (postType) => fetchAlephBootstrapPosts({
5107
+ apiHost: this.client.apiHost,
5108
+ postType,
5109
+ fetch
5110
+ }).catch(() => [])
5111
+ )
5112
+ ).then((pages) => pages.flat()) : Promise.resolve([])
5027
5113
  ]);
5028
5114
  balance = nextBalance;
5029
5115
  instances = await Promise.all(
package/shared/index.d.ts CHANGED
@@ -330,7 +330,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
330
330
  declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
331
331
  declare const DEPLOYMENT_PENDING_WARNING_MS: number;
332
332
 
333
- declare const UI_PACKAGE_VERSION = "0.6.4";
333
+ declare const UI_PACKAGE_VERSION = "0.6.5";
334
334
 
335
335
  interface RootfsRequiredPortForward {
336
336
  port: number;
package/shared/index.js CHANGED
@@ -42,7 +42,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
42
42
  var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
43
43
 
44
44
  // src/shared/package-version.ts
45
- var UI_PACKAGE_VERSION = "0.6.4";
45
+ var UI_PACKAGE_VERSION = "0.6.5";
46
46
 
47
47
  // src/shared/format.ts
48
48
  function shortHash(value, head = 8, tail = 6) {
@@ -2332,9 +2332,11 @@ async function configureUcanStore(args) {
2332
2332
  proxy_url: args.proxyUrl ?? void 0,
2333
2333
  service_did: args.serviceDid ?? void 0,
2334
2334
  service_origin: args.serviceOrigin ?? void 0,
2335
+ public_storage_origin: args.publicStorageOrigin ?? void 0,
2335
2336
  webauthn_origin: args.webauthnOrigin ?? void 0,
2336
2337
  webauthn_origin_fallbacks: args.webauthnOriginFallbacks ?? void 0,
2337
2338
  admin_did: args.adminDid ?? void 0,
2339
+ admin_api_token: args.adminApiToken ?? void 0,
2338
2340
  bootstrap_package: args.bootstrapPackage ?? void 0,
2339
2341
  no_start: args.noStart === true ? true : void 0
2340
2342
  };
@@ -2433,13 +2435,15 @@ async function fetchUcGoPeerMetadata(args) {
2433
2435
  }
2434
2436
 
2435
2437
  // ../aleph-bootstrap/src/index.ts
2436
- import { recoverMessageAddress } from "viem";
2438
+ import { keccak256, recoverMessageAddress, stringToHex } from "viem";
2437
2439
  var DEFAULT_ALEPH_API_HOST3 = "https://api.aleph.im";
2438
2440
  var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
2439
2441
  var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
2440
2442
  var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
2443
+ var DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE = "relay-bootstrap-v2";
2441
2444
  var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
2442
2445
  var DEFAULT_BOOTSTRAP_PAGINATION = 50;
2446
+ var DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT = 3;
2443
2447
  var RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
2444
2448
  function serializeOwnerAuthorizationPayload(payload) {
2445
2449
  return JSON.stringify({
@@ -2457,14 +2461,41 @@ function serializeOwnerAuthorizationPayload(payload) {
2457
2461
  function serializeRelayProofPayload(payload) {
2458
2462
  return JSON.stringify({
2459
2463
  peerId: payload.peerId,
2460
- multiaddrs: dedupeMultiaddrs(payload.multiaddrs),
2464
+ multiaddrs: payload.multiaddrs ? dedupeMultiaddrs(payload.multiaddrs) : void 0,
2461
2465
  browserMultiaddrs: payload.browserMultiaddrs ? dedupeMultiaddrs(payload.browserMultiaddrs) : void 0,
2466
+ multiaddrsHash: payload.multiaddrsHash,
2467
+ browserMultiaddrsHash: payload.browserMultiaddrsHash,
2462
2468
  registrationId: payload.registrationId,
2463
2469
  profile: payload.profile,
2464
2470
  version: payload.version,
2465
2471
  updatedAt: payload.updatedAt
2466
2472
  });
2467
2473
  }
2474
+ function relayBootstrapMultiaddrsHash(addrs) {
2475
+ return keccak256(stringToHex(JSON.stringify(dedupeMultiaddrs(addrs))));
2476
+ }
2477
+ function compactPostType(postType) {
2478
+ return (postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE) === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2479
+ }
2480
+ function browserMultiaddrPreference(addr) {
2481
+ const normalized = addr.toLowerCase();
2482
+ if (normalized.includes("/tcp/443/tls/ws/")) return 0;
2483
+ if (normalized.includes("/tls/ws/")) return 1;
2484
+ if (normalized.includes("/webtransport/")) return 2;
2485
+ if (normalized.includes("/webrtc-direct/")) return 3;
2486
+ if (normalized.includes("/ws")) return 4;
2487
+ return 5;
2488
+ }
2489
+ function selectCompactRelayBootstrapMultiaddrs(addrs, limit = DEFAULT_BOOTSTRAP_COMPACT_MULTIADDR_LIMIT) {
2490
+ const entries = filterPublicMultiaddrs(addrs, {
2491
+ browserDialableOnly: true
2492
+ }).map((addr, index) => ({ addr, index }));
2493
+ entries.sort((left, right) => {
2494
+ const preference = browserMultiaddrPreference(left.addr) - browserMultiaddrPreference(right.addr);
2495
+ return preference !== 0 ? preference : left.index - right.index;
2496
+ });
2497
+ return entries.map((entry) => entry.addr).slice(0, Math.max(1, Math.floor(limit)));
2498
+ }
2468
2499
  function asTrimmedString(value) {
2469
2500
  return typeof value === "string" && value.trim() ? value.trim() : null;
2470
2501
  }
@@ -2620,8 +2651,10 @@ function normalizeRelayBootstrapProofPayload(value) {
2620
2651
  const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter((entry) => typeof entry === "string") : void 0;
2621
2652
  return {
2622
2653
  peerId,
2623
- multiaddrs: dedupeMultiaddrs(multiaddrs),
2654
+ multiaddrs: multiaddrs.length > 0 ? dedupeMultiaddrs(multiaddrs) : void 0,
2624
2655
  browserMultiaddrs: browserMultiaddrs ? dedupeMultiaddrs(browserMultiaddrs) : void 0,
2656
+ multiaddrsHash: asTrimmedString(payload.multiaddrsHash) ?? void 0,
2657
+ browserMultiaddrsHash: asTrimmedString(payload.browserMultiaddrsHash) ?? void 0,
2625
2658
  registrationId: asTrimmedString(payload.registrationId) ?? void 0,
2626
2659
  profile: asTrimmedString(payload.profile) ?? void 0,
2627
2660
  version: asTrimmedString(payload.version) ?? void 0,
@@ -2653,16 +2686,24 @@ function normalizeRelayBootstrapPostRecord(value) {
2653
2686
  function buildRelayBootstrapPostContent(args) {
2654
2687
  const now = args.now ?? Date.now() / 1e3;
2655
2688
  const updatedAt = args.now ?? Date.now();
2689
+ const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE;
2690
+ const compact = args.compact ?? compactPostType(postType);
2691
+ const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
2692
+ const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2693
+ browserDialableOnly: true
2694
+ }) : void 0;
2695
+ const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
2696
+ fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
2697
+ args.compactMultiaddrLimit
2698
+ );
2656
2699
  return {
2657
- type: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
2700
+ type: postType,
2658
2701
  address: args.sender,
2659
2702
  ...args.ref ? { ref: args.ref } : {},
2660
2703
  content: {
2661
2704
  peerId: args.peerId,
2662
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
2663
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2664
- browserDialableOnly: true
2665
- }) : void 0,
2705
+ multiaddrs: compact ? compactMultiaddrs : fullMultiaddrs,
2706
+ browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
2666
2707
  registrationId: args.registrationId,
2667
2708
  profile: args.profile,
2668
2709
  version: args.version,
@@ -2692,6 +2733,8 @@ async function createRelayBootstrapPost(args) {
2692
2733
  publisherAddress: args.publisherAddress,
2693
2734
  authorization: args.authorization,
2694
2735
  relayProof: args.relayProof,
2736
+ compact: args.compact,
2737
+ compactMultiaddrLimit: args.compactMultiaddrLimit,
2695
2738
  now: nowMillis
2696
2739
  });
2697
2740
  itemContent.time = nowSeconds;
@@ -2729,12 +2772,20 @@ async function signRelayBootstrapAuthorization(args) {
2729
2772
  };
2730
2773
  }
2731
2774
  async function signRelayBootstrapProof(args) {
2775
+ const fullMultiaddrs = filterPublicMultiaddrs(args.multiaddrs);
2776
+ const fullBrowserMultiaddrs = args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2777
+ browserDialableOnly: true
2778
+ }) : void 0;
2779
+ const compactMultiaddrs = selectCompactRelayBootstrapMultiaddrs(
2780
+ fullBrowserMultiaddrs && fullBrowserMultiaddrs.length > 0 ? fullBrowserMultiaddrs : fullMultiaddrs,
2781
+ args.compactMultiaddrLimit
2782
+ );
2783
+ const compact = args.compact ?? false;
2732
2784
  const payload = {
2733
2785
  peerId: args.peerId,
2734
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
2735
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2736
- browserDialableOnly: true
2737
- }) : void 0,
2786
+ multiaddrs: compact ? void 0 : fullMultiaddrs,
2787
+ browserMultiaddrs: compact ? void 0 : fullBrowserMultiaddrs,
2788
+ multiaddrsHash: compact ? relayBootstrapMultiaddrsHash(compactMultiaddrs) : void 0,
2738
2789
  registrationId: args.registrationId,
2739
2790
  profile: args.profile,
2740
2791
  version: args.version,
@@ -2781,7 +2832,7 @@ async function fetchAlephBootstrapPosts(options = {}) {
2781
2832
  throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
2782
2833
  }
2783
2834
  const payload = await response.json();
2784
- return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null);
2835
+ return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null).sort((left, right) => compareRelayBootstrapPostRecency(right, left));
2785
2836
  }
2786
2837
  function compareRelayBootstrapPostRecency(left, right) {
2787
2838
  const leftUpdatedAt = left.content?.updatedAt ?? 0;
@@ -2828,12 +2879,14 @@ async function waitForRelayBootstrapRegistration(args) {
2828
2879
  const expectedSender = args.sender?.trim().toLowerCase() || null;
2829
2880
  const expectedRegistrationId = args.registrationId?.trim() || null;
2830
2881
  const expectedPeerId = args.peerId?.trim() || null;
2882
+ const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2883
+ const sleepImpl = args.sleep ?? sleep;
2831
2884
  for (let attempt = 0; attempt < attempts; attempt += 1) {
2832
2885
  const posts = await fetchAlephBootstrapPosts({
2833
2886
  apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
2834
2887
  channel: args.channel,
2835
2888
  ref: args.ref,
2836
- postType: args.postType,
2889
+ postType,
2837
2890
  fetch: args.fetch
2838
2891
  });
2839
2892
  const currentPosts = selectCurrentRelayBootstrapPosts(posts);
@@ -2864,7 +2917,7 @@ async function waitForRelayBootstrapRegistration(args) {
2864
2917
  }
2865
2918
  args.onAttempt?.(null, attempt + 1, attempts);
2866
2919
  if (attempt < attempts - 1) {
2867
- await sleep(delayMs);
2920
+ await sleepImpl(delayMs);
2868
2921
  }
2869
2922
  }
2870
2923
  return null;
@@ -2872,6 +2925,8 @@ async function waitForRelayBootstrapRegistration(args) {
2872
2925
  async function publishRelayBootstrapRegistration(args) {
2873
2926
  const publisherAddress = args.publisherAddress ?? args.sender;
2874
2927
  const ownerAddress = args.ownerAddress;
2928
+ const postType = args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2929
+ const compact = postType === DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE;
2875
2930
  let ownerAuthorization = args.ownerAuthorization;
2876
2931
  let relayProof = args.relayProof;
2877
2932
  if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
@@ -2898,6 +2953,8 @@ async function publishRelayBootstrapRegistration(args) {
2898
2953
  profile: args.profile,
2899
2954
  version: args.version,
2900
2955
  updatedAt: args.now ?? Date.now(),
2956
+ compact,
2957
+ compactMultiaddrLimit: args.compactMultiaddrLimit,
2901
2958
  signer: args.publisherSigner
2902
2959
  });
2903
2960
  }
@@ -2909,13 +2966,15 @@ async function publishRelayBootstrapRegistration(args) {
2909
2966
  registrationId: args.registrationId,
2910
2967
  channel: args.channel,
2911
2968
  ref: args.ref,
2912
- postType: args.postType,
2969
+ postType,
2913
2970
  profile: args.profile,
2914
2971
  version: args.version,
2915
2972
  ownerAddress,
2916
2973
  publisherAddress,
2917
2974
  authorization: ownerAuthorization,
2918
2975
  relayProof,
2976
+ compact,
2977
+ compactMultiaddrLimit: args.compactMultiaddrLimit,
2919
2978
  now: args.now,
2920
2979
  hasher: args.hasher
2921
2980
  });
@@ -2937,16 +2996,33 @@ async function publishRelayBootstrapRegistration(args) {
2937
2996
  let forgottenHashes = [];
2938
2997
  let forgetResult;
2939
2998
  if (args.forgetPrevious && args.registrationId) {
2940
- const previousPosts = await fetchAlephBootstrapPosts({
2941
- apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
2942
- channel: args.channel,
2943
- ref: args.ref,
2944
- postType: args.postType,
2945
- fetch: args.fetch
2946
- });
2947
- forgottenHashes = previousPosts.filter(
2948
- (post) => post.address?.toLowerCase() === args.sender.toLowerCase() && post.content?.registrationId === args.registrationId && (post.itemHash ?? post.hash) != null && (post.itemHash ?? post.hash) !== unsigned.item_hash
2949
- ).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean);
2999
+ const previousPostTypes = compact ? [postType, DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE] : [postType];
3000
+ const previousPosts = (await Promise.all(
3001
+ previousPostTypes.map(
3002
+ (previousPostType) => fetchAlephBootstrapPosts({
3003
+ apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
3004
+ channel: args.channel,
3005
+ ref: args.ref,
3006
+ postType: previousPostType,
3007
+ fetch: args.fetch
3008
+ })
3009
+ )
3010
+ )).flat();
3011
+ const forgottenHashSet = new Set(
3012
+ previousPosts.filter((post) => {
3013
+ const hash = post.itemHash ?? post.hash;
3014
+ if (!hash || hash === unsigned.item_hash) return false;
3015
+ if (post.address?.toLowerCase() !== args.sender.toLowerCase()) {
3016
+ return false;
3017
+ }
3018
+ const content2 = post.content;
3019
+ if (!content2) return false;
3020
+ if (content2.registrationId === args.registrationId) return true;
3021
+ if (content2.peerId !== args.peerId) return false;
3022
+ return !args.profile || content2.profile === args.profile;
3023
+ }).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean)
3024
+ );
3025
+ forgottenHashes = [...forgottenHashSet];
2950
3026
  if (forgottenHashes.length > 0) {
2951
3027
  forgetResult = await forgetAlephMessages({
2952
3028
  sender: args.sender,
@@ -2967,7 +3043,7 @@ async function publishRelayBootstrapRegistration(args) {
2967
3043
  response,
2968
3044
  httpStatus,
2969
3045
  publishedMultiaddrs: content.content?.multiaddrs ?? [],
2970
- publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
3046
+ publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? content.content?.multiaddrs ?? [],
2971
3047
  forgottenHashes,
2972
3048
  forgetResult
2973
3049
  };
@@ -4117,6 +4193,8 @@ var SponsorRelayController = class {
4117
4193
  setupPort,
4118
4194
  proxyUrl: serviceProxyUrl,
4119
4195
  webauthnOrigin: serviceProxyUrl,
4196
+ serviceDid: bootstrapValidation.bootstrapPackage.serviceDid,
4197
+ serviceOrigin: bootstrapValidation.bootstrapPackage.serviceOrigin,
4120
4198
  adminDid: bootstrapValidation.bootstrapPackage.adminDid,
4121
4199
  bootstrapPackage: bootstrapValidation.bootstrapPackage,
4122
4200
  fetch: (url, init) => fetch(url, init),
@@ -5019,10 +5097,18 @@ var SponsorRelayController = class {
5019
5097
  const [nextBalance, rawInstances, rawBootstrapPosts] = await Promise.all([
5020
5098
  this.client.fetchBalance(this.state.wallet.address),
5021
5099
  this.state.showInstances ? this.client.fetchInstances(this.state.wallet.address) : Promise.resolve([]),
5022
- bootstrapEnabled ? fetchAlephBootstrapPosts({
5023
- apiHost: this.client.apiHost,
5024
- fetch
5025
- }).catch(() => []) : Promise.resolve([])
5100
+ bootstrapEnabled ? Promise.all(
5101
+ [
5102
+ DEFAULT_ALEPH_BOOTSTRAP_COMPACT_POST_TYPE,
5103
+ DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
5104
+ ].map(
5105
+ (postType) => fetchAlephBootstrapPosts({
5106
+ apiHost: this.client.apiHost,
5107
+ postType,
5108
+ fetch
5109
+ }).catch(() => [])
5110
+ )
5111
+ ).then((pages) => pages.flat()) : Promise.resolve([])
5026
5112
  ]);
5027
5113
  balance = nextBalance;
5028
5114
  instances = await Promise.all(