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