@le-space/ui 0.3.17 → 0.3.19

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/shared/index.js CHANGED
@@ -38,7 +38,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
38
38
  var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
39
39
 
40
40
  // src/shared/package-version.ts
41
- var UI_PACKAGE_VERSION = "0.3.17";
41
+ var UI_PACKAGE_VERSION = "0.3.19";
42
42
 
43
43
  // src/shared/format.ts
44
44
  function shortHash(value, head = 8, tail = 6) {
@@ -1218,14 +1218,14 @@ async function inspectDeploymentResult2(itemHash, options) {
1218
1218
  async function waitForDeploymentResult2(itemHash, options) {
1219
1219
  const attempts = Math.max(1, Number(options.attempts ?? 15));
1220
1220
  const delayMs = Math.max(0, Number(options.delayMs ?? 2e3));
1221
- const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1221
+ const sleep2 = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1222
1222
  let lastResult = await inspectDeploymentResult2(itemHash, options);
1223
1223
  options.onAttempt?.(lastResult, 1, attempts);
1224
1224
  for (let attempt = 1; attempt < attempts; attempt += 1) {
1225
1225
  if (lastResult.status === "processed" || lastResult.status === "rejected") {
1226
1226
  return lastResult;
1227
1227
  }
1228
- await sleep(delayMs);
1228
+ await sleep2(delayMs);
1229
1229
  lastResult = await inspectDeploymentResult2(itemHash, options);
1230
1230
  options.onAttempt?.(lastResult, attempt + 1, attempts);
1231
1231
  }
@@ -1883,14 +1883,14 @@ async function fetchVmRuntime(args) {
1883
1883
  async function waitForVmRuntime(args) {
1884
1884
  const attempts = Math.max(1, Number(args.attempts ?? 20));
1885
1885
  const delayMs = Math.max(0, Number(args.delayMs ?? 4e3));
1886
- const sleep = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1886
+ const sleep2 = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1887
1887
  let lastRuntime = await fetchVmRuntime(args);
1888
1888
  args.onAttempt?.(lastRuntime, 1, attempts);
1889
1889
  for (let attempt = 0; attempt < attempts - 1; attempt += 1) {
1890
1890
  if (lastRuntime.hostIpv4 && Object.keys(lastRuntime.mappedPorts ?? {}).length > 0) {
1891
1891
  return lastRuntime;
1892
1892
  }
1893
- await sleep(delayMs);
1893
+ await sleep2(delayMs);
1894
1894
  lastRuntime = await fetchVmRuntime(args);
1895
1895
  args.onAttempt?.(lastRuntime, attempt + 2, attempts);
1896
1896
  }
@@ -1969,7 +1969,7 @@ function isRetryableAllocationNotifyReason(reason) {
1969
1969
  async function notifyCrnAllocationWithRetry(args) {
1970
1970
  const attempts = Math.max(1, Number(args.attempts ?? 6));
1971
1971
  const delayMs = Math.max(0, Number(args.delayMs ?? 2e3));
1972
- const sleep = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1972
+ const sleep2 = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1973
1973
  let lastResult = null;
1974
1974
  for (let attempt = 0; attempt < attempts; attempt += 1) {
1975
1975
  args.onProgress?.({
@@ -1995,7 +1995,7 @@ async function notifyCrnAllocationWithRetry(args) {
1995
1995
  return result;
1996
1996
  }
1997
1997
  if (attempt < attempts - 1) {
1998
- await sleep(delayMs);
1998
+ await sleep2(delayMs);
1999
1999
  }
2000
2000
  }
2001
2001
  return lastResult ?? {
@@ -2006,7 +2006,7 @@ async function notifyCrnAllocationWithRetry(args) {
2006
2006
  async function waitForSetupEndpoint(args) {
2007
2007
  const attempts = Math.max(1, Number(args.attempts ?? 15));
2008
2008
  const delayMs = Math.max(0, Number(args.delayMs ?? 4e3));
2009
- const sleep = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
2009
+ const sleep2 = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
2010
2010
  const url = `http://${args.hostIpv4}:${args.setupPort}/health`;
2011
2011
  let result = await defaultHttpProbe(
2012
2012
  args.fetch,
@@ -2016,7 +2016,7 @@ async function waitForSetupEndpoint(args) {
2016
2016
  args.onAttempt?.(result, 1, attempts);
2017
2017
  for (let attempt = 1; attempt < attempts; attempt += 1) {
2018
2018
  if (result.ok) return result;
2019
- await sleep(delayMs);
2019
+ await sleep2(delayMs);
2020
2020
  result = await defaultHttpProbe(
2021
2021
  args.fetch,
2022
2022
  url,
@@ -2075,7 +2075,7 @@ async function configureOrbitdbRelaySetup2(args) {
2075
2075
  async function fetchUcGoPeerMetadata(args) {
2076
2076
  const attempts = Math.max(1, Number(args.attempts ?? 60));
2077
2077
  const delayMs = Math.max(0, Number(args.delayMs ?? 3e3));
2078
- const sleep = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
2078
+ const sleep2 = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
2079
2079
  let lastPayload = null;
2080
2080
  let lastError = null;
2081
2081
  for (let attempt = 0; attempt < attempts; attempt += 1) {
@@ -2135,7 +2135,7 @@ async function fetchUcGoPeerMetadata(args) {
2135
2135
  clearTimeout(timeout);
2136
2136
  }
2137
2137
  if (attempt < attempts - 1) {
2138
- await sleep(delayMs);
2138
+ await sleep2(delayMs);
2139
2139
  }
2140
2140
  }
2141
2141
  throw new Error(
@@ -2151,31 +2151,6 @@ var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
2151
2151
  var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
2152
2152
  var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
2153
2153
  var DEFAULT_BOOTSTRAP_PAGINATION = 50;
2154
- var RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
2155
- function serializeOwnerAuthorizationPayload(payload) {
2156
- return JSON.stringify({
2157
- ownerAddress: payload.ownerAddress,
2158
- publisherAddress: payload.publisherAddress,
2159
- peerId: payload.peerId,
2160
- registrationId: payload.registrationId,
2161
- profile: payload.profile,
2162
- version: payload.version,
2163
- instanceItemHash: payload.instanceItemHash,
2164
- issuedAt: payload.issuedAt,
2165
- expiresAt: payload.expiresAt
2166
- });
2167
- }
2168
- function serializeRelayProofPayload(payload) {
2169
- return JSON.stringify({
2170
- peerId: payload.peerId,
2171
- multiaddrs: dedupeMultiaddrs(payload.multiaddrs),
2172
- browserMultiaddrs: payload.browserMultiaddrs ? dedupeMultiaddrs(payload.browserMultiaddrs) : void 0,
2173
- registrationId: payload.registrationId,
2174
- profile: payload.profile,
2175
- version: payload.version,
2176
- updatedAt: payload.updatedAt
2177
- });
2178
- }
2179
2154
  function asTrimmedString(value) {
2180
2155
  return typeof value === "string" && value.trim() ? value.trim() : null;
2181
2156
  }
@@ -2187,48 +2162,9 @@ function asNumber4(value) {
2187
2162
  }
2188
2163
  return null;
2189
2164
  }
2190
- function normalizeHost(host) {
2191
- return host.trim().toLowerCase();
2192
- }
2193
2165
  function normalizeAddress(address) {
2194
2166
  return address.trim().toLowerCase();
2195
2167
  }
2196
- function normalizeSignature(signature) {
2197
- const trimmed = signature.trim();
2198
- return trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
2199
- }
2200
- function splitMultiaddr(addr) {
2201
- return addr.split("/").filter(Boolean);
2202
- }
2203
- function isPrivateIpv4(ip) {
2204
- const parts = ip.split(".").map((part) => Number(part));
2205
- if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
2206
- return false;
2207
- }
2208
- if (parts[0] === 10) return true;
2209
- if (parts[0] === 127) return true;
2210
- if (parts[0] === 0) return true;
2211
- if (parts[0] === 169 && parts[1] === 254) return true;
2212
- if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true;
2213
- if (parts[0] === 192 && parts[1] === 168) return true;
2214
- if (parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127) return true;
2215
- return false;
2216
- }
2217
- function isPrivateIpv6(ip) {
2218
- const normalized = ip.trim().toLowerCase();
2219
- return normalized === "::1" || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("fe8") || normalized.startsWith("fe9") || normalized.startsWith("fea") || normalized.startsWith("feb");
2220
- }
2221
- function isLocalHostname(host) {
2222
- const normalized = normalizeHost(host);
2223
- return normalized === "localhost" || normalized.endsWith(".localhost") || normalized.endsWith(".local");
2224
- }
2225
- function hasPeerId(addr) {
2226
- return splitMultiaddr(addr).includes("p2p");
2227
- }
2228
- function isBrowserDialableMultiaddr(addr) {
2229
- const normalized = addr.toLowerCase();
2230
- return normalized.includes("/ws") || normalized.includes("/wss") || normalized.includes("/webtransport") || normalized.includes("/webrtc-direct");
2231
- }
2232
2168
  function dedupeMultiaddrs(addrs) {
2233
2169
  const seen = /* @__PURE__ */ new Set();
2234
2170
  const result = [];
@@ -2240,33 +2176,6 @@ function dedupeMultiaddrs(addrs) {
2240
2176
  }
2241
2177
  return result;
2242
2178
  }
2243
- function isPublicMultiaddr(addr) {
2244
- const parts = splitMultiaddr(addr);
2245
- for (let index = 0; index < parts.length; index += 1) {
2246
- const protocol = parts[index];
2247
- const value = parts[index + 1];
2248
- if (protocol === "ip4" && value) {
2249
- return !isPrivateIpv4(value);
2250
- }
2251
- if (protocol === "ip6" && value) {
2252
- return !isPrivateIpv6(value);
2253
- }
2254
- if ((protocol === "dns4" || protocol === "dns6" || protocol === "dnsaddr") && value) {
2255
- return !isLocalHostname(value);
2256
- }
2257
- }
2258
- return false;
2259
- }
2260
- function filterPublicMultiaddrs(addrs, options = {}) {
2261
- return dedupeMultiaddrs(addrs).filter((addr) => {
2262
- if (!isPublicMultiaddr(addr)) return false;
2263
- if (options.requirePeerId !== false && !hasPeerId(addr)) return false;
2264
- if (options.browserDialableOnly && !isBrowserDialableMultiaddr(addr)) {
2265
- return false;
2266
- }
2267
- return true;
2268
- });
2269
- }
2270
2179
  function normalizeRelayBootstrapContent(value) {
2271
2180
  if (!value || typeof value !== "object") return null;
2272
2181
  const content = value;
@@ -2361,104 +2270,6 @@ function normalizeRelayBootstrapPostRecord(value) {
2361
2270
  content: normalizeRelayBootstrapContent(entry.content)
2362
2271
  };
2363
2272
  }
2364
- function buildRelayBootstrapPostContent(args) {
2365
- const now = args.now ?? Date.now() / 1e3;
2366
- const updatedAt = args.now ?? Date.now();
2367
- return {
2368
- type: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
2369
- address: args.sender,
2370
- ...args.ref ? { ref: args.ref } : {},
2371
- content: {
2372
- peerId: args.peerId,
2373
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
2374
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2375
- browserDialableOnly: true
2376
- }) : void 0,
2377
- registrationId: args.registrationId,
2378
- profile: args.profile,
2379
- version: args.version,
2380
- ownerAddress: args.ownerAddress,
2381
- publisherAddress: args.publisherAddress,
2382
- authorization: args.authorization,
2383
- relayProof: args.relayProof,
2384
- updatedAt: Math.round(updatedAt)
2385
- },
2386
- time: now
2387
- };
2388
- }
2389
- async function createRelayBootstrapPost(args) {
2390
- const nowMillis = args.now ?? Date.now();
2391
- const nowSeconds = nowMillis / 1e3;
2392
- const itemContent = buildRelayBootstrapPostContent({
2393
- sender: args.sender,
2394
- peerId: args.peerId,
2395
- multiaddrs: args.multiaddrs,
2396
- browserMultiaddrs: args.browserMultiaddrs,
2397
- registrationId: args.registrationId,
2398
- ref: args.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF,
2399
- postType: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
2400
- profile: args.profile,
2401
- version: args.version,
2402
- ownerAddress: args.ownerAddress,
2403
- publisherAddress: args.publisherAddress,
2404
- authorization: args.authorization,
2405
- relayProof: args.relayProof,
2406
- now: nowMillis
2407
- });
2408
- itemContent.time = nowSeconds;
2409
- const serialized = JSON.stringify(itemContent);
2410
- const itemHash = await args.hasher(serialized);
2411
- return {
2412
- channel: args.channel ?? DEFAULT_ALEPH_BOOTSTRAP_CHANNEL,
2413
- sender: args.sender,
2414
- chain: "ETH",
2415
- type: "POST",
2416
- time: nowSeconds,
2417
- item_type: "inline",
2418
- item_content: serialized,
2419
- item_hash: itemHash
2420
- };
2421
- }
2422
- async function signRelayBootstrapAuthorization(args) {
2423
- const payload = {
2424
- ownerAddress: args.ownerAddress,
2425
- publisherAddress: args.publisherAddress,
2426
- peerId: args.peerId,
2427
- registrationId: args.registrationId,
2428
- profile: args.profile,
2429
- version: args.version,
2430
- instanceItemHash: args.instanceItemHash,
2431
- issuedAt: args.issuedAt ?? Date.now(),
2432
- expiresAt: args.expiresAt
2433
- };
2434
- const serialized = serializeOwnerAuthorizationPayload(payload);
2435
- const signature = await args.signer(args.ownerAddress, serialized);
2436
- return {
2437
- scheme: RELAY_BOOTSTRAP_SIGNATURE_SCHEME,
2438
- payload,
2439
- signature: normalizeSignature(signature)
2440
- };
2441
- }
2442
- async function signRelayBootstrapProof(args) {
2443
- const payload = {
2444
- peerId: args.peerId,
2445
- multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
2446
- browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
2447
- browserDialableOnly: true
2448
- }) : void 0,
2449
- registrationId: args.registrationId,
2450
- profile: args.profile,
2451
- version: args.version,
2452
- updatedAt: args.updatedAt ?? Date.now()
2453
- };
2454
- const serialized = serializeRelayProofPayload(payload);
2455
- const signature = await args.signer(args.publisherAddress, serialized);
2456
- return {
2457
- scheme: RELAY_BOOTSTRAP_SIGNATURE_SCHEME,
2458
- payload,
2459
- signature: normalizeSignature(signature)
2460
- };
2461
- }
2462
2273
  async function fetchAlephBootstrapPosts(options = {}) {
2463
2274
  const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
2464
2275
  if (typeof fetchImpl !== "function") {
@@ -2530,108 +2341,52 @@ function selectCurrentRelayBootstrapPosts(posts, options = {}) {
2530
2341
  }
2531
2342
 
2532
2343
  // ../core/src/bootstrap-registration.ts
2533
- async function publishRelayBootstrapRegistration(args) {
2534
- const publisherAddress = args.publisherAddress ?? args.sender;
2535
- const ownerAddress = args.ownerAddress;
2536
- let ownerAuthorization = args.ownerAuthorization;
2537
- let relayProof = args.relayProof;
2538
- if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
2539
- ownerAuthorization = await signRelayBootstrapAuthorization({
2540
- ownerAddress,
2541
- publisherAddress,
2542
- peerId: args.peerId,
2543
- registrationId: args.registrationId,
2544
- profile: args.profile,
2545
- version: args.version,
2546
- instanceItemHash: args.instanceItemHash,
2547
- issuedAt: args.authorizationIssuedAt ?? args.now ?? Date.now(),
2548
- expiresAt: args.authorizationExpiresAt,
2549
- signer: args.ownerSigner
2550
- });
2551
- }
2552
- if (!relayProof && args.publisherSigner) {
2553
- relayProof = await signRelayBootstrapProof({
2554
- publisherAddress,
2555
- peerId: args.peerId,
2556
- multiaddrs: args.multiaddrs,
2557
- browserMultiaddrs: args.browserMultiaddrs,
2558
- registrationId: args.registrationId,
2559
- profile: args.profile,
2560
- version: args.version,
2561
- updatedAt: args.now ?? Date.now(),
2562
- signer: args.publisherSigner
2563
- });
2564
- }
2565
- const unsigned = await createRelayBootstrapPost({
2566
- sender: args.sender,
2567
- peerId: args.peerId,
2568
- multiaddrs: args.multiaddrs,
2569
- browserMultiaddrs: args.browserMultiaddrs,
2570
- registrationId: args.registrationId,
2571
- channel: args.channel,
2572
- ref: args.ref,
2573
- postType: args.postType,
2574
- profile: args.profile,
2575
- version: args.version,
2576
- ownerAddress,
2577
- publisherAddress,
2578
- authorization: ownerAuthorization,
2579
- relayProof,
2580
- now: args.now,
2581
- hasher: args.hasher
2582
- });
2583
- const content = JSON.parse(unsigned.item_content);
2584
- if ((content.content?.multiaddrs?.length ?? 0) === 0) {
2585
- return {
2586
- status: "skipped",
2587
- reason: "No public relay multiaddrs remained after filtering.",
2588
- publishedMultiaddrs: [],
2589
- publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? []
2590
- };
2591
- }
2592
- const message = await signAlephMessage(unsigned, args.signer);
2593
- const { response, httpStatus } = await broadcastAlephMessage2(message, {
2594
- apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
2595
- sync: args.sync ?? true,
2596
- fetch: args.fetch
2597
- });
2598
- let forgottenHashes = [];
2599
- let forgetResult;
2600
- if (args.forgetPrevious && args.registrationId) {
2601
- const previousPosts = await fetchAlephBootstrapPosts({
2344
+ function sleep(ms) {
2345
+ return new Promise((resolve) => setTimeout(resolve, ms));
2346
+ }
2347
+ async function waitForRelayBootstrapRegistration(args) {
2348
+ const attempts = Math.max(1, Number(args.attempts ?? 10));
2349
+ const delayMs = Math.max(0, Number(args.delayMs ?? 2e3));
2350
+ const expectedSender = args.sender?.trim().toLowerCase() || null;
2351
+ const expectedRegistrationId = args.registrationId?.trim() || null;
2352
+ const expectedPeerId = args.peerId?.trim() || null;
2353
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
2354
+ const posts = await fetchAlephBootstrapPosts({
2602
2355
  apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
2603
2356
  channel: args.channel,
2604
2357
  ref: args.ref,
2605
2358
  postType: args.postType,
2606
2359
  fetch: args.fetch
2607
2360
  });
2608
- forgottenHashes = previousPosts.filter(
2609
- (post) => post.address?.toLowerCase() === args.sender.toLowerCase() && post.content?.registrationId === args.registrationId && (post.itemHash ?? post.hash) != null && (post.itemHash ?? post.hash) !== unsigned.item_hash
2610
- ).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean);
2611
- if (forgottenHashes.length > 0) {
2612
- forgetResult = await forgetAlephMessages({
2613
- sender: args.sender,
2614
- hashes: forgottenHashes,
2615
- reason: args.forgetPreviousReason ?? `Replace older relay bootstrap records for ${args.registrationId}`,
2616
- signer: args.signer,
2617
- hasher: args.hasher,
2618
- fetch: args.fetch,
2619
- apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
2620
- sync: args.sync ?? true
2621
- });
2361
+ const currentPosts = selectCurrentRelayBootstrapPosts(posts);
2362
+ const match = currentPosts.find((post) => {
2363
+ if (expectedSender && post.address?.toLowerCase() !== expectedSender) {
2364
+ return false;
2365
+ }
2366
+ if (expectedRegistrationId && post.content?.registrationId === expectedRegistrationId) {
2367
+ return true;
2368
+ }
2369
+ if (expectedPeerId && post.content?.peerId === expectedPeerId) {
2370
+ return true;
2371
+ }
2372
+ return false;
2373
+ });
2374
+ if (match?.content) {
2375
+ return {
2376
+ itemHash: match.itemHash ?? null,
2377
+ hash: match.hash ?? null,
2378
+ sender: typeof match.address === "string" ? match.address : null,
2379
+ registrationId: match.content.registrationId,
2380
+ peerId: match.content.peerId,
2381
+ multiaddrs: Array.isArray(match.content.multiaddrs) ? match.content.multiaddrs : [],
2382
+ browserMultiaddrs: Array.isArray(match.content.browserMultiaddrs) ? match.content.browserMultiaddrs : []
2383
+ };
2384
+ }
2385
+ if (attempt < attempts - 1) {
2386
+ await sleep(delayMs);
2622
2387
  }
2623
2388
  }
2624
- return {
2625
- status: "published",
2626
- itemHash: unsigned.item_hash,
2627
- message,
2628
- response,
2629
- httpStatus,
2630
- publishedMultiaddrs: content.content?.multiaddrs ?? [],
2631
- publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
2632
- forgottenHashes,
2633
- forgetResult
2634
- };
2389
+ return null;
2635
2390
  }
2636
2391
 
2637
2392
  // ../core/src/bootstrap-config.ts
@@ -2786,24 +2541,6 @@ function extractRelayMetadata(payload) {
2786
2541
  browserBootstrapMultiaddrs
2787
2542
  };
2788
2543
  }
2789
- async function fetchOwnerInstances(address, options) {
2790
- const url = new URL("/api/v0/messages.json", options.apiHost ?? DEFAULT_ALEPH_API_HOST2);
2791
- url.searchParams.set("msgTypes", "INSTANCE");
2792
- url.searchParams.set("addresses", address);
2793
- url.searchParams.set("message_statuses", "processed,pending,rejected,removing");
2794
- url.searchParams.set("pagination", "100");
2795
- url.searchParams.set("page", "1");
2796
- url.searchParams.set("sortOrder", "-1");
2797
- const response = await options.fetch(url.toString(), { cache: "no-cache" });
2798
- if (!response.ok) {
2799
- throw new Error(`Instance list request failed: ${response.status}`);
2800
- }
2801
- const payload = await response.json();
2802
- return (payload.messages ?? []).map((message) => ({
2803
- ...message,
2804
- status: typeof message.status === "string" && message.status.trim() ? message.status : message.confirmed ? "processed" : "pending"
2805
- }));
2806
- }
2807
2544
  async function fetchRelayMetadataForRuntime(args) {
2808
2545
  const setupPort = args.runtime.mappedPorts?.["80"]?.host ?? 80;
2809
2546
  const metadataUrl = args.preferSecureMetadata ? secureBootstrapMetadataUrl(args.runtime.proxyUrl) : null;
@@ -2830,123 +2567,6 @@ async function fetchRelayMetadataForRuntime(args) {
2830
2567
  }).catch(() => null);
2831
2568
  return extractRelayMetadata(payload);
2832
2569
  }
2833
- async function reconcileOwnerRelayBootstrapRegistrations(args) {
2834
- const result = {
2835
- refreshedRegistrations: [],
2836
- forgottenHashes: [],
2837
- skippedInstanceHashes: [],
2838
- errors: []
2839
- };
2840
- const liveRegistrationIds = /* @__PURE__ */ new Set();
2841
- if (args.current?.registrationId) {
2842
- liveRegistrationIds.add(args.current.registrationId);
2843
- result.refreshedRegistrations.push(args.current.registrationId);
2844
- }
2845
- const instances = await fetchOwnerInstances(args.instanceOwnerAddress, {
2846
- apiHost: args.apiHost,
2847
- fetch: args.fetch
2848
- });
2849
- const processedInstances = instances.filter((instance) => {
2850
- const status = String(instance.status ?? "").trim().toLowerCase();
2851
- return status === "processed";
2852
- });
2853
- for (const instance of processedInstances) {
2854
- if (instance.item_hash === args.current?.itemHash) continue;
2855
- const registrationId = createRelayBootstrapRegistrationId(
2856
- args.profile,
2857
- instance.content?.metadata?.name,
2858
- instance.item_hash
2859
- );
2860
- try {
2861
- const runtime = await fetchVmRuntime({
2862
- itemHash: instance.item_hash,
2863
- fetch: args.fetch,
2864
- crns: args.crns,
2865
- crnListUrl: args.crnListUrl
2866
- });
2867
- if (!runtime.hostIpv4 || Object.keys(runtime.mappedPorts ?? {}).length === 0) {
2868
- result.skippedInstanceHashes.push(instance.item_hash);
2869
- continue;
2870
- }
2871
- const relayMetadata = await fetchRelayMetadataForRuntime({
2872
- runtime,
2873
- fetch: args.fetch,
2874
- preferSecureMetadata: args.preferSecureMetadata,
2875
- attempts: 3,
2876
- delayMs: 1e3,
2877
- timeoutMs: 1e4
2878
- });
2879
- if (!relayMetadata) {
2880
- result.skippedInstanceHashes.push(instance.item_hash);
2881
- continue;
2882
- }
2883
- liveRegistrationIds.add(registrationId);
2884
- await publishRelayBootstrapRegistration({
2885
- sender: args.sender,
2886
- signer: args.signer,
2887
- hasher: args.hasher,
2888
- fetch: args.fetch,
2889
- apiHost: args.apiHost,
2890
- channel: args.channel,
2891
- ref: args.ref,
2892
- postType: args.postType,
2893
- peerId: relayMetadata.peerId,
2894
- multiaddrs: relayMetadata.probeMultiaddrs,
2895
- browserMultiaddrs: relayMetadata.browserBootstrapMultiaddrs,
2896
- registrationId,
2897
- ownerAddress: args.ownerAddress,
2898
- publisherAddress: args.publisherAddress,
2899
- ownerSigner: args.ownerSigner,
2900
- publisherSigner: args.publisherSigner,
2901
- forgetPrevious: true,
2902
- profile: args.profile,
2903
- version: args.version,
2904
- instanceItemHash: instance.item_hash,
2905
- sync: true
2906
- });
2907
- result.refreshedRegistrations.push(registrationId);
2908
- } catch (error) {
2909
- result.errors.push({
2910
- phase: "publish",
2911
- itemHash: instance.item_hash,
2912
- registrationId,
2913
- message: error instanceof Error ? error.message : String(error)
2914
- });
2915
- }
2916
- }
2917
- try {
2918
- const bootstrapPosts = await fetchAlephBootstrapPosts({
2919
- apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST2,
2920
- channel: args.channel,
2921
- ref: args.ref,
2922
- postType: args.postType,
2923
- fetch: args.fetch
2924
- });
2925
- const currentPosts = selectCurrentRelayBootstrapPosts(bootstrapPosts);
2926
- const staleHashes = currentPosts.filter(
2927
- (post) => post.address?.toLowerCase() === args.sender.toLowerCase() && post.content?.profile === args.profile && post.content?.registrationId && !liveRegistrationIds.has(post.content.registrationId)
2928
- ).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean);
2929
- if (staleHashes.length > 0) {
2930
- await forgetAlephMessages({
2931
- sender: args.sender,
2932
- hashes: staleHashes,
2933
- reason: `Forget stale ${args.profile} relay bootstrap registrations after owner reconcile`,
2934
- signer: args.signer,
2935
- hasher: args.hasher,
2936
- fetch: args.fetch,
2937
- apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST2,
2938
- sync: true
2939
- });
2940
- result.forgottenHashes.push(...staleHashes);
2941
- }
2942
- } catch (error) {
2943
- result.errors.push({
2944
- phase: "forget",
2945
- message: error instanceof Error ? error.message : String(error)
2946
- });
2947
- }
2948
- return result;
2949
- }
2950
2570
 
2951
2571
  // src/shared/events.ts
2952
2572
  function createDeploymentProgressEmitter() {
@@ -3566,7 +3186,7 @@ var SponsorRelayController = class {
3566
3186
  if (!relayMetadata) {
3567
3187
  throw new Error("Relay metadata did not include a peer ID and public multiaddrs.");
3568
3188
  }
3569
- const { peerId, probeMultiaddrs, browserBootstrapMultiaddrs } = relayMetadata;
3189
+ const { peerId } = relayMetadata;
3570
3190
  const registrationId = createRelayBootstrapRegistrationId(
3571
3191
  profile,
3572
3192
  this.state.instanceName.trim(),
@@ -3574,57 +3194,30 @@ var SponsorRelayController = class {
3574
3194
  );
3575
3195
  this.emitProgress({
3576
3196
  stage: "publishing-bootstrap",
3577
- label: "Publishing bootstrap registration",
3197
+ label: "Waiting for guest bootstrap registration",
3578
3198
  progress: 96,
3579
3199
  status: "info",
3580
3200
  itemHash: args.itemHash,
3581
- detail: "Writing the relay bootstrap registration to Aleph."
3201
+ detail: "Waiting for the relay VM to publish its own bootstrap registration to Aleph."
3582
3202
  });
3583
- const publication = await publishRelayBootstrapRegistration({
3584
- sender: this.state.wallet.address,
3585
- signer: personalSign,
3586
- hasher: sha256Hex,
3203
+ const visibleRegistration = await waitForRelayBootstrapRegistration({
3204
+ registrationId,
3205
+ peerId,
3587
3206
  fetch: asJsonFetch,
3588
3207
  apiHost: this.client.apiHost,
3589
- peerId,
3590
- multiaddrs: probeMultiaddrs,
3591
- browserMultiaddrs: browserBootstrapMultiaddrs,
3592
- registrationId,
3593
- profile,
3594
- version: this.state.manifest?.version,
3595
- forgetPrevious: true,
3596
- sync: true
3208
+ attempts: 24,
3209
+ delayMs: 2500
3597
3210
  });
3598
- this.trace("deploy:bootstrap-registration", {
3211
+ this.trace("deploy:bootstrap-registration-visible", {
3599
3212
  itemHash: args.itemHash,
3213
+ registrationId,
3600
3214
  peerId,
3601
- metadata: relayMetadata,
3602
- publication
3215
+ visibleRegistration
3603
3216
  });
3604
- const reconcileResult = await reconcileOwnerRelayBootstrapRegistrations({
3605
- instanceOwnerAddress: this.state.wallet.address,
3606
- sender: this.state.wallet.address,
3607
- signer: personalSign,
3608
- hasher: sha256Hex,
3609
- fetch: asJsonFetch,
3610
- profile,
3611
- apiHost: this.client.apiHost,
3612
- crns: this.state.crns,
3613
- crnListUrl: this.props.crnListUrl,
3614
- preferSecureMetadata: profile === "uc-go-peer",
3615
- current: {
3616
- itemHash: args.itemHash,
3617
- registrationId,
3618
- peerId,
3619
- probeMultiaddrs,
3620
- browserBootstrapMultiaddrs
3621
- }
3622
- });
3623
- if (reconcileResult.errors.length > 0) {
3624
- this.trace("deploy:owner-bootstrap-reconcile-errors", {
3625
- itemHash: args.itemHash,
3626
- errors: reconcileResult.errors
3627
- });
3217
+ if (!visibleRegistration) {
3218
+ throw new Error(
3219
+ "Relay bootstrap registration did not become visible on Aleph."
3220
+ );
3628
3221
  }
3629
3222
  if (profile === "uc-go-peer" && args.deploymentToken) {
3630
3223
  await deleteVmBootstrapConfig({
@@ -4115,12 +3708,14 @@ var SponsorRelayController = class {
4115
3708
  for (const [candidateIndex, candidateCrn] of orderedCrns.entries()) {
4116
3709
  let attemptItemHash = null;
4117
3710
  let attemptDeploymentToken = null;
3711
+ const crnAttemptLabel = `CRN ${candidateIndex + 1}/${orderedCrns.length}`;
3712
+ const crnDisplayName = candidateCrn.name ?? candidateCrn.hash;
4118
3713
  this.emitProgress({
4119
3714
  stage: "selecting-crn",
4120
- label: "Selecting CRN",
3715
+ label: `Selecting ${crnAttemptLabel}`,
4121
3716
  progress: 18,
4122
3717
  status: "info",
4123
- detail: `Trying ${candidateCrn.name ?? candidateCrn.hash} (${candidateIndex + 1}/${orderedCrns.length})`
3718
+ detail: `Trying ${crnDisplayName}`
4124
3719
  });
4125
3720
  try {
4126
3721
  const profile = relayProfileForManifest(this.state.manifest);
@@ -4330,7 +3925,7 @@ var SponsorRelayController = class {
4330
3925
  return;
4331
3926
  } catch (error) {
4332
3927
  lastError = error instanceof Error ? error : new Error(String(error));
4333
- const attemptLabel = candidateCrn.name ?? candidateCrn.hash;
3928
+ const attemptLabel = crnDisplayName;
4334
3929
  attemptErrors.push(`${attemptLabel}: ${lastError.message}`);
4335
3930
  this.trace("deploy:crn-attempt-error", {
4336
3931
  crnHash: candidateCrn.hash,
@@ -4399,7 +3994,7 @@ var SponsorRelayController = class {
4399
3994
  if (candidateIndex < orderedCrns.length - 1) {
4400
3995
  this.emitProgress({
4401
3996
  stage: "selecting-crn",
4402
- label: "Retrying another CRN",
3997
+ label: `Retrying after ${crnAttemptLabel}`,
4403
3998
  progress: 20,
4404
3999
  status: "warning",
4405
4000
  itemHash: attemptItemHash,
@@ -4461,29 +4056,6 @@ var SponsorRelayController = class {
4461
4056
  this.emitProgress(event);
4462
4057
  }
4463
4058
  });
4464
- const profile = relayProfileForManifest(this.state.manifest);
4465
- if (profile) {
4466
- await reconcileOwnerRelayBootstrapRegistrations({
4467
- instanceOwnerAddress: this.state.wallet.address,
4468
- sender: this.state.wallet.address,
4469
- signer: personalSign,
4470
- hasher: sha256Hex,
4471
- fetch: asJsonFetch,
4472
- profile,
4473
- apiHost: this.client.apiHost,
4474
- crns: this.state.crns,
4475
- crnListUrl: this.props.crnListUrl,
4476
- preferSecureMetadata: profile === "uc-go-peer"
4477
- }).catch(
4478
- (error) => {
4479
- this.trace("delete:owner-bootstrap-reconcile-error", {
4480
- instanceHash,
4481
- profile,
4482
- error: error instanceof Error ? error.message : String(error)
4483
- });
4484
- }
4485
- );
4486
- }
4487
4059
  this.patch({
4488
4060
  busy: { deletingInstanceHash: null },
4489
4061
  statusText: `Deletion submitted for ${instanceHash}`