@le-space/ui 0.3.22 → 0.3.24
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 +3 -3
- package/react/index.js +348 -4
- package/shared/index.d.ts +1 -1
- package/shared/index.js +348 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@le-space/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.24",
|
|
4
4
|
"description": "Floating Aleph sponsor relay UI components for Svelte and React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@le-space/browser": "0.3.
|
|
40
|
-
"@le-space/core": "0.3.
|
|
39
|
+
"@le-space/browser": "0.3.24",
|
|
40
|
+
"@le-space/core": "0.3.24",
|
|
41
41
|
"viem": "^2.38.5"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
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.
|
|
42
|
+
var UI_PACKAGE_VERSION = "0.3.24";
|
|
43
43
|
|
|
44
44
|
// src/shared/format.ts
|
|
45
45
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -2152,6 +2152,31 @@ 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
|
+
}
|
|
2155
2180
|
function asTrimmedString(value) {
|
|
2156
2181
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
2157
2182
|
}
|
|
@@ -2163,9 +2188,48 @@ function asNumber4(value) {
|
|
|
2163
2188
|
}
|
|
2164
2189
|
return null;
|
|
2165
2190
|
}
|
|
2191
|
+
function normalizeHost(host) {
|
|
2192
|
+
return host.trim().toLowerCase();
|
|
2193
|
+
}
|
|
2166
2194
|
function normalizeAddress(address) {
|
|
2167
2195
|
return address.trim().toLowerCase();
|
|
2168
2196
|
}
|
|
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
|
+
}
|
|
2169
2233
|
function dedupeMultiaddrs(addrs) {
|
|
2170
2234
|
const seen = /* @__PURE__ */ new Set();
|
|
2171
2235
|
const result = [];
|
|
@@ -2177,6 +2241,33 @@ function dedupeMultiaddrs(addrs) {
|
|
|
2177
2241
|
}
|
|
2178
2242
|
return result;
|
|
2179
2243
|
}
|
|
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
|
+
}
|
|
2180
2271
|
function normalizeRelayBootstrapContent(value) {
|
|
2181
2272
|
if (!value || typeof value !== "object") return null;
|
|
2182
2273
|
const content = value;
|
|
@@ -2271,6 +2362,104 @@ function normalizeRelayBootstrapPostRecord(value) {
|
|
|
2271
2362
|
content: normalizeRelayBootstrapContent(entry.content)
|
|
2272
2363
|
};
|
|
2273
2364
|
}
|
|
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
|
+
}
|
|
2274
2463
|
async function fetchAlephBootstrapPosts(options = {}) {
|
|
2275
2464
|
const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
2276
2465
|
if (typeof fetchImpl !== "function") {
|
|
@@ -2389,6 +2578,109 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2389
2578
|
}
|
|
2390
2579
|
return null;
|
|
2391
2580
|
}
|
|
2581
|
+
async function publishRelayBootstrapRegistration(args) {
|
|
2582
|
+
const publisherAddress = args.publisherAddress ?? args.sender;
|
|
2583
|
+
const ownerAddress = args.ownerAddress;
|
|
2584
|
+
let ownerAuthorization = args.ownerAuthorization;
|
|
2585
|
+
let relayProof = args.relayProof;
|
|
2586
|
+
if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
|
|
2587
|
+
ownerAuthorization = await signRelayBootstrapAuthorization({
|
|
2588
|
+
ownerAddress,
|
|
2589
|
+
publisherAddress,
|
|
2590
|
+
peerId: args.peerId,
|
|
2591
|
+
registrationId: args.registrationId,
|
|
2592
|
+
profile: args.profile,
|
|
2593
|
+
version: args.version,
|
|
2594
|
+
instanceItemHash: args.instanceItemHash,
|
|
2595
|
+
issuedAt: args.authorizationIssuedAt ?? args.now ?? Date.now(),
|
|
2596
|
+
expiresAt: args.authorizationExpiresAt,
|
|
2597
|
+
signer: args.ownerSigner
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
if (!relayProof && args.publisherSigner) {
|
|
2601
|
+
relayProof = await signRelayBootstrapProof({
|
|
2602
|
+
publisherAddress,
|
|
2603
|
+
peerId: args.peerId,
|
|
2604
|
+
multiaddrs: args.multiaddrs,
|
|
2605
|
+
browserMultiaddrs: args.browserMultiaddrs,
|
|
2606
|
+
registrationId: args.registrationId,
|
|
2607
|
+
profile: args.profile,
|
|
2608
|
+
version: args.version,
|
|
2609
|
+
updatedAt: args.now ?? Date.now(),
|
|
2610
|
+
signer: args.publisherSigner
|
|
2611
|
+
});
|
|
2612
|
+
}
|
|
2613
|
+
const unsigned = await createRelayBootstrapPost({
|
|
2614
|
+
sender: args.sender,
|
|
2615
|
+
peerId: args.peerId,
|
|
2616
|
+
multiaddrs: args.multiaddrs,
|
|
2617
|
+
browserMultiaddrs: args.browserMultiaddrs,
|
|
2618
|
+
registrationId: args.registrationId,
|
|
2619
|
+
channel: args.channel,
|
|
2620
|
+
ref: args.ref,
|
|
2621
|
+
postType: args.postType,
|
|
2622
|
+
profile: args.profile,
|
|
2623
|
+
version: args.version,
|
|
2624
|
+
ownerAddress,
|
|
2625
|
+
publisherAddress,
|
|
2626
|
+
authorization: ownerAuthorization,
|
|
2627
|
+
relayProof,
|
|
2628
|
+
now: args.now,
|
|
2629
|
+
hasher: args.hasher
|
|
2630
|
+
});
|
|
2631
|
+
const content = JSON.parse(unsigned.item_content);
|
|
2632
|
+
if ((content.content?.multiaddrs?.length ?? 0) === 0) {
|
|
2633
|
+
return {
|
|
2634
|
+
status: "skipped",
|
|
2635
|
+
reason: "No public relay multiaddrs remained after filtering.",
|
|
2636
|
+
publishedMultiaddrs: [],
|
|
2637
|
+
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? []
|
|
2638
|
+
};
|
|
2639
|
+
}
|
|
2640
|
+
const message = await signAlephMessage(unsigned, args.signer);
|
|
2641
|
+
const { response, httpStatus } = await broadcastAlephMessage2(message, {
|
|
2642
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2643
|
+
sync: args.sync ?? true,
|
|
2644
|
+
fetch: args.fetch
|
|
2645
|
+
});
|
|
2646
|
+
let forgottenHashes = [];
|
|
2647
|
+
let forgetResult;
|
|
2648
|
+
if (args.forgetPrevious && args.registrationId) {
|
|
2649
|
+
const previousPosts = await fetchAlephBootstrapPosts({
|
|
2650
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2651
|
+
channel: args.channel,
|
|
2652
|
+
ref: args.ref,
|
|
2653
|
+
postType: args.postType,
|
|
2654
|
+
fetch: args.fetch
|
|
2655
|
+
});
|
|
2656
|
+
forgottenHashes = previousPosts.filter(
|
|
2657
|
+
(post) => post.address?.toLowerCase() === args.sender.toLowerCase() && post.content?.registrationId === args.registrationId && (post.itemHash ?? post.hash) != null && (post.itemHash ?? post.hash) !== unsigned.item_hash
|
|
2658
|
+
).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean);
|
|
2659
|
+
if (forgottenHashes.length > 0) {
|
|
2660
|
+
forgetResult = await forgetAlephMessages({
|
|
2661
|
+
sender: args.sender,
|
|
2662
|
+
hashes: forgottenHashes,
|
|
2663
|
+
reason: args.forgetPreviousReason ?? `Replace older relay bootstrap records for ${args.registrationId}`,
|
|
2664
|
+
signer: args.signer,
|
|
2665
|
+
hasher: args.hasher,
|
|
2666
|
+
fetch: args.fetch,
|
|
2667
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2668
|
+
sync: args.sync ?? true
|
|
2669
|
+
});
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
return {
|
|
2673
|
+
status: "published",
|
|
2674
|
+
itemHash: unsigned.item_hash,
|
|
2675
|
+
message,
|
|
2676
|
+
response,
|
|
2677
|
+
httpStatus,
|
|
2678
|
+
publishedMultiaddrs: content.content?.multiaddrs ?? [],
|
|
2679
|
+
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
|
|
2680
|
+
forgottenHashes,
|
|
2681
|
+
forgetResult
|
|
2682
|
+
};
|
|
2683
|
+
}
|
|
2392
2684
|
|
|
2393
2685
|
// ../core/src/bootstrap-config.ts
|
|
2394
2686
|
var VM_BOOTSTRAP_CONFIG_AGGREGATE_KEY = "vm-bootstrap-config";
|
|
@@ -3216,9 +3508,61 @@ var SponsorRelayController = class {
|
|
|
3216
3508
|
visibleRegistration
|
|
3217
3509
|
});
|
|
3218
3510
|
if (!visibleRegistration) {
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3511
|
+
this.trace("deploy:bootstrap-registration-fallback-start", {
|
|
3512
|
+
itemHash: args.itemHash,
|
|
3513
|
+
registrationId,
|
|
3514
|
+
peerId,
|
|
3515
|
+
probeMultiaddrCount: relayMetadata.probeMultiaddrs.length,
|
|
3516
|
+
browserBootstrapMultiaddrCount: relayMetadata.browserBootstrapMultiaddrs.length
|
|
3517
|
+
});
|
|
3518
|
+
this.emitProgress({
|
|
3519
|
+
stage: "publishing-bootstrap",
|
|
3520
|
+
label: "Publishing bootstrap fallback",
|
|
3521
|
+
progress: 98,
|
|
3522
|
+
status: "warning",
|
|
3523
|
+
itemHash: args.itemHash,
|
|
3524
|
+
detail: "Guest bootstrap registration was delayed. Publishing the relay bootstrap record from the browser."
|
|
3525
|
+
});
|
|
3526
|
+
const fallbackPublication = await publishRelayBootstrapRegistration({
|
|
3527
|
+
sender: this.state.wallet.address,
|
|
3528
|
+
signer: personalSign,
|
|
3529
|
+
hasher: sha256Hex,
|
|
3530
|
+
fetch: asJsonFetch,
|
|
3531
|
+
apiHost: this.client.apiHost,
|
|
3532
|
+
peerId,
|
|
3533
|
+
multiaddrs: relayMetadata.probeMultiaddrs,
|
|
3534
|
+
browserMultiaddrs: relayMetadata.browserBootstrapMultiaddrs,
|
|
3535
|
+
registrationId,
|
|
3536
|
+
profile,
|
|
3537
|
+
sync: true,
|
|
3538
|
+
forgetPrevious: true
|
|
3539
|
+
});
|
|
3540
|
+
this.trace("deploy:bootstrap-registration-fallback-published", {
|
|
3541
|
+
itemHash: args.itemHash,
|
|
3542
|
+
registrationId,
|
|
3543
|
+
peerId,
|
|
3544
|
+
fallbackPublication
|
|
3545
|
+
});
|
|
3546
|
+
const fallbackVisibleRegistration = await waitForRelayBootstrapRegistration({
|
|
3547
|
+
sender: this.state.wallet.address,
|
|
3548
|
+
registrationId,
|
|
3549
|
+
peerId,
|
|
3550
|
+
fetch: asJsonFetch,
|
|
3551
|
+
apiHost: this.client.apiHost,
|
|
3552
|
+
attempts: 24,
|
|
3553
|
+
delayMs: 2500
|
|
3554
|
+
});
|
|
3555
|
+
this.trace("deploy:bootstrap-registration-fallback-visible", {
|
|
3556
|
+
itemHash: args.itemHash,
|
|
3557
|
+
registrationId,
|
|
3558
|
+
peerId,
|
|
3559
|
+
fallbackVisibleRegistration
|
|
3560
|
+
});
|
|
3561
|
+
if (!fallbackVisibleRegistration) {
|
|
3562
|
+
throw new Error(
|
|
3563
|
+
"Relay bootstrap registration did not become visible on Aleph."
|
|
3564
|
+
);
|
|
3565
|
+
}
|
|
3222
3566
|
}
|
|
3223
3567
|
if (profile === "uc-go-peer" && args.deploymentToken) {
|
|
3224
3568
|
await deleteVmBootstrapConfig({
|
package/shared/index.d.ts
CHANGED
|
@@ -304,7 +304,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
|
|
|
304
304
|
declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
|
|
305
305
|
declare const DEPLOYMENT_PENDING_WARNING_MS: number;
|
|
306
306
|
|
|
307
|
-
declare const UI_PACKAGE_VERSION = "0.3.
|
|
307
|
+
declare const UI_PACKAGE_VERSION = "0.3.24";
|
|
308
308
|
|
|
309
309
|
interface RootfsRequiredPortForward {
|
|
310
310
|
port: number;
|
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.
|
|
41
|
+
var UI_PACKAGE_VERSION = "0.3.24";
|
|
42
42
|
|
|
43
43
|
// src/shared/format.ts
|
|
44
44
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -2151,6 +2151,31 @@ 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
|
+
}
|
|
2154
2179
|
function asTrimmedString(value) {
|
|
2155
2180
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
2156
2181
|
}
|
|
@@ -2162,9 +2187,48 @@ function asNumber4(value) {
|
|
|
2162
2187
|
}
|
|
2163
2188
|
return null;
|
|
2164
2189
|
}
|
|
2190
|
+
function normalizeHost(host) {
|
|
2191
|
+
return host.trim().toLowerCase();
|
|
2192
|
+
}
|
|
2165
2193
|
function normalizeAddress(address) {
|
|
2166
2194
|
return address.trim().toLowerCase();
|
|
2167
2195
|
}
|
|
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
|
+
}
|
|
2168
2232
|
function dedupeMultiaddrs(addrs) {
|
|
2169
2233
|
const seen = /* @__PURE__ */ new Set();
|
|
2170
2234
|
const result = [];
|
|
@@ -2176,6 +2240,33 @@ function dedupeMultiaddrs(addrs) {
|
|
|
2176
2240
|
}
|
|
2177
2241
|
return result;
|
|
2178
2242
|
}
|
|
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
|
+
}
|
|
2179
2270
|
function normalizeRelayBootstrapContent(value) {
|
|
2180
2271
|
if (!value || typeof value !== "object") return null;
|
|
2181
2272
|
const content = value;
|
|
@@ -2270,6 +2361,104 @@ function normalizeRelayBootstrapPostRecord(value) {
|
|
|
2270
2361
|
content: normalizeRelayBootstrapContent(entry.content)
|
|
2271
2362
|
};
|
|
2272
2363
|
}
|
|
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
|
+
}
|
|
2273
2462
|
async function fetchAlephBootstrapPosts(options = {}) {
|
|
2274
2463
|
const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
2275
2464
|
if (typeof fetchImpl !== "function") {
|
|
@@ -2388,6 +2577,109 @@ async function waitForRelayBootstrapRegistration(args) {
|
|
|
2388
2577
|
}
|
|
2389
2578
|
return null;
|
|
2390
2579
|
}
|
|
2580
|
+
async function publishRelayBootstrapRegistration(args) {
|
|
2581
|
+
const publisherAddress = args.publisherAddress ?? args.sender;
|
|
2582
|
+
const ownerAddress = args.ownerAddress;
|
|
2583
|
+
let ownerAuthorization = args.ownerAuthorization;
|
|
2584
|
+
let relayProof = args.relayProof;
|
|
2585
|
+
if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
|
|
2586
|
+
ownerAuthorization = await signRelayBootstrapAuthorization({
|
|
2587
|
+
ownerAddress,
|
|
2588
|
+
publisherAddress,
|
|
2589
|
+
peerId: args.peerId,
|
|
2590
|
+
registrationId: args.registrationId,
|
|
2591
|
+
profile: args.profile,
|
|
2592
|
+
version: args.version,
|
|
2593
|
+
instanceItemHash: args.instanceItemHash,
|
|
2594
|
+
issuedAt: args.authorizationIssuedAt ?? args.now ?? Date.now(),
|
|
2595
|
+
expiresAt: args.authorizationExpiresAt,
|
|
2596
|
+
signer: args.ownerSigner
|
|
2597
|
+
});
|
|
2598
|
+
}
|
|
2599
|
+
if (!relayProof && args.publisherSigner) {
|
|
2600
|
+
relayProof = await signRelayBootstrapProof({
|
|
2601
|
+
publisherAddress,
|
|
2602
|
+
peerId: args.peerId,
|
|
2603
|
+
multiaddrs: args.multiaddrs,
|
|
2604
|
+
browserMultiaddrs: args.browserMultiaddrs,
|
|
2605
|
+
registrationId: args.registrationId,
|
|
2606
|
+
profile: args.profile,
|
|
2607
|
+
version: args.version,
|
|
2608
|
+
updatedAt: args.now ?? Date.now(),
|
|
2609
|
+
signer: args.publisherSigner
|
|
2610
|
+
});
|
|
2611
|
+
}
|
|
2612
|
+
const unsigned = await createRelayBootstrapPost({
|
|
2613
|
+
sender: args.sender,
|
|
2614
|
+
peerId: args.peerId,
|
|
2615
|
+
multiaddrs: args.multiaddrs,
|
|
2616
|
+
browserMultiaddrs: args.browserMultiaddrs,
|
|
2617
|
+
registrationId: args.registrationId,
|
|
2618
|
+
channel: args.channel,
|
|
2619
|
+
ref: args.ref,
|
|
2620
|
+
postType: args.postType,
|
|
2621
|
+
profile: args.profile,
|
|
2622
|
+
version: args.version,
|
|
2623
|
+
ownerAddress,
|
|
2624
|
+
publisherAddress,
|
|
2625
|
+
authorization: ownerAuthorization,
|
|
2626
|
+
relayProof,
|
|
2627
|
+
now: args.now,
|
|
2628
|
+
hasher: args.hasher
|
|
2629
|
+
});
|
|
2630
|
+
const content = JSON.parse(unsigned.item_content);
|
|
2631
|
+
if ((content.content?.multiaddrs?.length ?? 0) === 0) {
|
|
2632
|
+
return {
|
|
2633
|
+
status: "skipped",
|
|
2634
|
+
reason: "No public relay multiaddrs remained after filtering.",
|
|
2635
|
+
publishedMultiaddrs: [],
|
|
2636
|
+
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? []
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
const message = await signAlephMessage(unsigned, args.signer);
|
|
2640
|
+
const { response, httpStatus } = await broadcastAlephMessage2(message, {
|
|
2641
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2642
|
+
sync: args.sync ?? true,
|
|
2643
|
+
fetch: args.fetch
|
|
2644
|
+
});
|
|
2645
|
+
let forgottenHashes = [];
|
|
2646
|
+
let forgetResult;
|
|
2647
|
+
if (args.forgetPrevious && args.registrationId) {
|
|
2648
|
+
const previousPosts = await fetchAlephBootstrapPosts({
|
|
2649
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2650
|
+
channel: args.channel,
|
|
2651
|
+
ref: args.ref,
|
|
2652
|
+
postType: args.postType,
|
|
2653
|
+
fetch: args.fetch
|
|
2654
|
+
});
|
|
2655
|
+
forgottenHashes = previousPosts.filter(
|
|
2656
|
+
(post) => post.address?.toLowerCase() === args.sender.toLowerCase() && post.content?.registrationId === args.registrationId && (post.itemHash ?? post.hash) != null && (post.itemHash ?? post.hash) !== unsigned.item_hash
|
|
2657
|
+
).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean);
|
|
2658
|
+
if (forgottenHashes.length > 0) {
|
|
2659
|
+
forgetResult = await forgetAlephMessages({
|
|
2660
|
+
sender: args.sender,
|
|
2661
|
+
hashes: forgottenHashes,
|
|
2662
|
+
reason: args.forgetPreviousReason ?? `Replace older relay bootstrap records for ${args.registrationId}`,
|
|
2663
|
+
signer: args.signer,
|
|
2664
|
+
hasher: args.hasher,
|
|
2665
|
+
fetch: args.fetch,
|
|
2666
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2667
|
+
sync: args.sync ?? true
|
|
2668
|
+
});
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
return {
|
|
2672
|
+
status: "published",
|
|
2673
|
+
itemHash: unsigned.item_hash,
|
|
2674
|
+
message,
|
|
2675
|
+
response,
|
|
2676
|
+
httpStatus,
|
|
2677
|
+
publishedMultiaddrs: content.content?.multiaddrs ?? [],
|
|
2678
|
+
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
|
|
2679
|
+
forgottenHashes,
|
|
2680
|
+
forgetResult
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2391
2683
|
|
|
2392
2684
|
// ../core/src/bootstrap-config.ts
|
|
2393
2685
|
var VM_BOOTSTRAP_CONFIG_AGGREGATE_KEY = "vm-bootstrap-config";
|
|
@@ -3215,9 +3507,61 @@ var SponsorRelayController = class {
|
|
|
3215
3507
|
visibleRegistration
|
|
3216
3508
|
});
|
|
3217
3509
|
if (!visibleRegistration) {
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3510
|
+
this.trace("deploy:bootstrap-registration-fallback-start", {
|
|
3511
|
+
itemHash: args.itemHash,
|
|
3512
|
+
registrationId,
|
|
3513
|
+
peerId,
|
|
3514
|
+
probeMultiaddrCount: relayMetadata.probeMultiaddrs.length,
|
|
3515
|
+
browserBootstrapMultiaddrCount: relayMetadata.browserBootstrapMultiaddrs.length
|
|
3516
|
+
});
|
|
3517
|
+
this.emitProgress({
|
|
3518
|
+
stage: "publishing-bootstrap",
|
|
3519
|
+
label: "Publishing bootstrap fallback",
|
|
3520
|
+
progress: 98,
|
|
3521
|
+
status: "warning",
|
|
3522
|
+
itemHash: args.itemHash,
|
|
3523
|
+
detail: "Guest bootstrap registration was delayed. Publishing the relay bootstrap record from the browser."
|
|
3524
|
+
});
|
|
3525
|
+
const fallbackPublication = await publishRelayBootstrapRegistration({
|
|
3526
|
+
sender: this.state.wallet.address,
|
|
3527
|
+
signer: personalSign,
|
|
3528
|
+
hasher: sha256Hex,
|
|
3529
|
+
fetch: asJsonFetch,
|
|
3530
|
+
apiHost: this.client.apiHost,
|
|
3531
|
+
peerId,
|
|
3532
|
+
multiaddrs: relayMetadata.probeMultiaddrs,
|
|
3533
|
+
browserMultiaddrs: relayMetadata.browserBootstrapMultiaddrs,
|
|
3534
|
+
registrationId,
|
|
3535
|
+
profile,
|
|
3536
|
+
sync: true,
|
|
3537
|
+
forgetPrevious: true
|
|
3538
|
+
});
|
|
3539
|
+
this.trace("deploy:bootstrap-registration-fallback-published", {
|
|
3540
|
+
itemHash: args.itemHash,
|
|
3541
|
+
registrationId,
|
|
3542
|
+
peerId,
|
|
3543
|
+
fallbackPublication
|
|
3544
|
+
});
|
|
3545
|
+
const fallbackVisibleRegistration = await waitForRelayBootstrapRegistration({
|
|
3546
|
+
sender: this.state.wallet.address,
|
|
3547
|
+
registrationId,
|
|
3548
|
+
peerId,
|
|
3549
|
+
fetch: asJsonFetch,
|
|
3550
|
+
apiHost: this.client.apiHost,
|
|
3551
|
+
attempts: 24,
|
|
3552
|
+
delayMs: 2500
|
|
3553
|
+
});
|
|
3554
|
+
this.trace("deploy:bootstrap-registration-fallback-visible", {
|
|
3555
|
+
itemHash: args.itemHash,
|
|
3556
|
+
registrationId,
|
|
3557
|
+
peerId,
|
|
3558
|
+
fallbackVisibleRegistration
|
|
3559
|
+
});
|
|
3560
|
+
if (!fallbackVisibleRegistration) {
|
|
3561
|
+
throw new Error(
|
|
3562
|
+
"Relay bootstrap registration did not become visible on Aleph."
|
|
3563
|
+
);
|
|
3564
|
+
}
|
|
3221
3565
|
}
|
|
3222
3566
|
if (profile === "uc-go-peer" && args.deploymentToken) {
|
|
3223
3567
|
await deleteVmBootstrapConfig({
|