@le-space/ui 0.3.27 → 0.3.28
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 +168 -11
- package/shared/index.d.ts +1 -1
- package/shared/index.js +168 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@le-space/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.28",
|
|
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.28",
|
|
40
|
+
"@le-space/core": "0.3.28",
|
|
41
41
|
"viem": "^2.38.5"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
package/react/index.js
CHANGED
|
@@ -28,7 +28,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
28
28
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
29
29
|
|
|
30
30
|
// src/shared/package-version.ts
|
|
31
|
-
var UI_PACKAGE_VERSION = "0.3.
|
|
31
|
+
var UI_PACKAGE_VERSION = "0.3.28";
|
|
32
32
|
|
|
33
33
|
// src/shared/format.ts
|
|
34
34
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -1878,6 +1878,13 @@ async function waitForVmRuntime(args) {
|
|
|
1878
1878
|
}
|
|
1879
1879
|
|
|
1880
1880
|
// ../core/src/guest.ts
|
|
1881
|
+
function proxyHostnameFromUrl(value) {
|
|
1882
|
+
try {
|
|
1883
|
+
return value ? new URL(value).hostname : null;
|
|
1884
|
+
} catch {
|
|
1885
|
+
return null;
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1881
1888
|
async function defaultHttpProbe(fetch2, url, timeoutMs = 1e4) {
|
|
1882
1889
|
try {
|
|
1883
1890
|
const controller = new AbortController();
|
|
@@ -2119,6 +2126,59 @@ async function fetchUcGoPeerMetadata(args) {
|
|
|
2119
2126
|
`Relay metadata did not become ready after ${attempts} attempts: ${lastError ? lastError : typeof lastPayload === "string" ? lastPayload : JSON.stringify(lastPayload ?? {})}`
|
|
2120
2127
|
);
|
|
2121
2128
|
}
|
|
2129
|
+
async function verifyUcGoPeerReachability(args) {
|
|
2130
|
+
const checks = {};
|
|
2131
|
+
const mappedPorts2 = args.mappedPorts ?? {};
|
|
2132
|
+
const hostIpv4 = args.hostIpv4;
|
|
2133
|
+
const skippedInternalPorts = new Set(
|
|
2134
|
+
(args.skipInternalPorts ?? ["80"]).map((value) => String(value))
|
|
2135
|
+
);
|
|
2136
|
+
const httpProbe = args.httpProbe ?? ((url, timeoutMs) => defaultHttpProbe(args.fetch, url, timeoutMs));
|
|
2137
|
+
if (hostIpv4) {
|
|
2138
|
+
for (const [internalPort, mapping] of Object.entries(mappedPorts2)) {
|
|
2139
|
+
if (skippedInternalPorts.has(String(internalPort))) continue;
|
|
2140
|
+
if (mapping?.tcp === true && mapping?.host) {
|
|
2141
|
+
checks[`tcp:${internalPort}`] = {
|
|
2142
|
+
host: hostIpv4,
|
|
2143
|
+
port: mapping.host,
|
|
2144
|
+
...await args.tcpProbe(
|
|
2145
|
+
hostIpv4,
|
|
2146
|
+
mapping.host,
|
|
2147
|
+
Number(args.tcpTimeoutMs ?? 5e3)
|
|
2148
|
+
)
|
|
2149
|
+
};
|
|
2150
|
+
} else if (mapping?.udp === true && mapping?.host) {
|
|
2151
|
+
checks[`udp:${internalPort}`] = {
|
|
2152
|
+
host: hostIpv4,
|
|
2153
|
+
port: mapping.host,
|
|
2154
|
+
ok: null,
|
|
2155
|
+
note: "UDP mapping published; CI does not perform an application-level UDP handshake probe."
|
|
2156
|
+
};
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
if (args.proxyUrl && args.verifyProxyHttp !== false) {
|
|
2161
|
+
checks["https:proxy"] = await httpProbe(
|
|
2162
|
+
args.proxyUrl,
|
|
2163
|
+
Number(args.httpTimeoutMs ?? 1e4)
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
const proxyHostname = proxyHostnameFromUrl(args.proxyUrl);
|
|
2167
|
+
if (proxyHostname) {
|
|
2168
|
+
checks["tcp:proxy-443"] = await args.tcpProbe(
|
|
2169
|
+
proxyHostname,
|
|
2170
|
+
443,
|
|
2171
|
+
Number(args.tcpTimeoutMs ?? 5e3)
|
|
2172
|
+
);
|
|
2173
|
+
}
|
|
2174
|
+
const failedChecks = Object.entries(checks).filter(
|
|
2175
|
+
([, value]) => value?.ok === false
|
|
2176
|
+
);
|
|
2177
|
+
return {
|
|
2178
|
+
ok: failedChecks.length === 0,
|
|
2179
|
+
checks
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2122
2182
|
|
|
2123
2183
|
// ../aleph-bootstrap/src/index.ts
|
|
2124
2184
|
import { recoverMessageAddress } from "viem";
|
|
@@ -3219,6 +3279,8 @@ var UI_DEPLOY_WAIT_ATTEMPTS = 60;
|
|
|
3219
3279
|
var UI_DEPLOY_WAIT_DELAY_MS = 5e3;
|
|
3220
3280
|
var UI_RUNTIME_WAIT_ATTEMPTS = 40;
|
|
3221
3281
|
var UI_RUNTIME_WAIT_DELAY_MS = 5e3;
|
|
3282
|
+
var UI_REACHABILITY_VERIFY_ATTEMPTS = 25;
|
|
3283
|
+
var UI_REACHABILITY_VERIFY_DELAY_MS = 3e3;
|
|
3222
3284
|
function hasUsableRuntime(details) {
|
|
3223
3285
|
return Boolean(details.hostIpv4) || Boolean(details.vmIpv4) || details.mappedPorts.length > 0 || Boolean(details.webUrl) || Boolean(details.execution);
|
|
3224
3286
|
}
|
|
@@ -3325,15 +3387,16 @@ var SponsorRelayController = class {
|
|
|
3325
3387
|
this.progressEmitter.emit(nextEvent);
|
|
3326
3388
|
}
|
|
3327
3389
|
async configureRelayBootstrapRegistration(args) {
|
|
3390
|
+
let runtime = args.runtime;
|
|
3328
3391
|
const profile = relayProfileForManifest(this.state.manifest);
|
|
3329
3392
|
if (!profile) return;
|
|
3330
3393
|
if (!this.state.wallet.address) {
|
|
3331
3394
|
throw new Error("A connected wallet is required to register relay bootstrap addresses.");
|
|
3332
3395
|
}
|
|
3333
|
-
if (!
|
|
3396
|
+
if (!runtime.hostIpv4) {
|
|
3334
3397
|
throw new Error("Relay runtime did not expose a host IPv4 address.");
|
|
3335
3398
|
}
|
|
3336
|
-
|
|
3399
|
+
let mappedPorts2 = runtime.mappedPorts ?? {};
|
|
3337
3400
|
const setupPort = mappedPorts2["80"]?.host ?? null;
|
|
3338
3401
|
if (!setupPort) {
|
|
3339
3402
|
throw new Error("Relay runtime did not expose the temporary setup endpoint.");
|
|
@@ -3348,7 +3411,7 @@ var SponsorRelayController = class {
|
|
|
3348
3411
|
detail: "Waiting for the guest setup endpoint before collecting relay metadata."
|
|
3349
3412
|
});
|
|
3350
3413
|
const setupHealth = await waitForSetupEndpoint({
|
|
3351
|
-
hostIpv4:
|
|
3414
|
+
hostIpv4: runtime.hostIpv4,
|
|
3352
3415
|
setupPort,
|
|
3353
3416
|
fetch: (url, init) => fetch(url, init),
|
|
3354
3417
|
attempts: 15,
|
|
@@ -3374,12 +3437,12 @@ var SponsorRelayController = class {
|
|
|
3374
3437
|
throw new Error("OrbitDB relay runtime is missing required mapped TCP/WS ports.");
|
|
3375
3438
|
}
|
|
3376
3439
|
const configureResult = await configureOrbitdbRelaySetup2({
|
|
3377
|
-
hostIpv4:
|
|
3378
|
-
publicIpv6:
|
|
3440
|
+
hostIpv4: runtime.hostIpv4,
|
|
3441
|
+
publicIpv6: runtime.ipv6,
|
|
3379
3442
|
setupPort,
|
|
3380
3443
|
tcpPort,
|
|
3381
3444
|
wsPort,
|
|
3382
|
-
proxyUrl:
|
|
3445
|
+
proxyUrl: runtime.proxyUrl ?? void 0,
|
|
3383
3446
|
metricsPort: mappedPorts2["9090"]?.host ?? null,
|
|
3384
3447
|
metricsHttpsPort: mappedPorts2["443"]?.host ?? null,
|
|
3385
3448
|
webrtcPort: mappedPorts2["9093"]?.host ?? null,
|
|
@@ -3396,6 +3459,51 @@ var SponsorRelayController = class {
|
|
|
3396
3459
|
if (!args.deploymentToken) {
|
|
3397
3460
|
throw new Error("Missing deployment token for Aleph bootstrap config handoff.");
|
|
3398
3461
|
}
|
|
3462
|
+
if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
|
|
3463
|
+
this.emitProgress({
|
|
3464
|
+
stage: "deployment-confirmed",
|
|
3465
|
+
label: "Waiting for HTTPS route",
|
|
3466
|
+
progress: 93,
|
|
3467
|
+
status: "warning",
|
|
3468
|
+
itemHash: args.itemHash,
|
|
3469
|
+
detail: "The relay received a 2n6 hostname, but it is not active yet. Waiting before handing HTTPS config to the guest."
|
|
3470
|
+
});
|
|
3471
|
+
let latestRuntime = runtime;
|
|
3472
|
+
for (let attempt = 0; attempt < UI_RUNTIME_WAIT_ATTEMPTS; attempt += 1) {
|
|
3473
|
+
if (latestRuntime.webAccess?.active === true) {
|
|
3474
|
+
break;
|
|
3475
|
+
}
|
|
3476
|
+
await new Promise(
|
|
3477
|
+
(resolve) => globalThis.setTimeout(resolve, UI_RUNTIME_WAIT_DELAY_MS)
|
|
3478
|
+
);
|
|
3479
|
+
latestRuntime = await fetchVmRuntime({
|
|
3480
|
+
itemHash: args.itemHash,
|
|
3481
|
+
fetch: (url, init) => fetch(url, init),
|
|
3482
|
+
crnHash: runtime.selectedCrn?.hash ?? runtime.allocation?.crnHash ?? void 0,
|
|
3483
|
+
crns: this.state.crns,
|
|
3484
|
+
crnListUrl: this.props.crnListUrl
|
|
3485
|
+
}).catch(() => latestRuntime);
|
|
3486
|
+
this.trace("deploy:bootstrap-proxy-activation", {
|
|
3487
|
+
itemHash: args.itemHash,
|
|
3488
|
+
attempt: attempt + 1,
|
|
3489
|
+
attempts: UI_RUNTIME_WAIT_ATTEMPTS,
|
|
3490
|
+
active: latestRuntime.webAccess?.active === true,
|
|
3491
|
+
proxyUrl: latestRuntime.proxyUrl ?? null
|
|
3492
|
+
});
|
|
3493
|
+
}
|
|
3494
|
+
runtime = latestRuntime;
|
|
3495
|
+
mappedPorts2 = runtime.mappedPorts ?? mappedPorts2;
|
|
3496
|
+
if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
|
|
3497
|
+
throw new Error(
|
|
3498
|
+
"Aleph reserved a 2n6 proxy URL, but it never became active in time. Aborting guest HTTPS configuration to avoid a broken Caddy setup."
|
|
3499
|
+
);
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
if (!runtime.hostIpv4) {
|
|
3503
|
+
throw new Error("Relay runtime lost its host IPv4 address while waiting for HTTPS activation.");
|
|
3504
|
+
}
|
|
3505
|
+
const runtimeHostIpv4 = runtime.hostIpv4;
|
|
3506
|
+
const activeProxyUrl = runtime.webAccess?.active === true ? runtime.proxyUrl ?? null : null;
|
|
3399
3507
|
this.emitProgress({
|
|
3400
3508
|
stage: "deployment-confirmed",
|
|
3401
3509
|
label: "Publishing relay config",
|
|
@@ -3413,9 +3521,9 @@ var SponsorRelayController = class {
|
|
|
3413
3521
|
expiresAt: new Date(Date.now() + 30 * 6e4).toISOString(),
|
|
3414
3522
|
status: "pending",
|
|
3415
3523
|
runtime: {
|
|
3416
|
-
publicIpv4:
|
|
3417
|
-
publicIpv6:
|
|
3418
|
-
proxyUrl:
|
|
3524
|
+
publicIpv4: runtimeHostIpv4,
|
|
3525
|
+
publicIpv6: runtime.ipv6 ?? null,
|
|
3526
|
+
proxyUrl: activeProxyUrl,
|
|
3419
3527
|
mappedPorts: mappedPorts2
|
|
3420
3528
|
},
|
|
3421
3529
|
bootstrap: {
|
|
@@ -3481,7 +3589,7 @@ var SponsorRelayController = class {
|
|
|
3481
3589
|
detail: "Waiting for the relay to report its final public multiaddrs."
|
|
3482
3590
|
});
|
|
3483
3591
|
const relayMetadata = await fetchRelayMetadataForRuntime({
|
|
3484
|
-
runtime
|
|
3592
|
+
runtime,
|
|
3485
3593
|
fetch: (url, init) => fetch(url, init),
|
|
3486
3594
|
preferSecureMetadata: profile === "uc-go-peer",
|
|
3487
3595
|
attempts: 80,
|
|
@@ -3514,6 +3622,55 @@ var SponsorRelayController = class {
|
|
|
3514
3622
|
if (!relayMetadata) {
|
|
3515
3623
|
throw new Error("Relay metadata did not include a peer ID and public multiaddrs.");
|
|
3516
3624
|
}
|
|
3625
|
+
if (profile === "uc-go-peer" && runtime.proxyUrl) {
|
|
3626
|
+
this.emitProgress({
|
|
3627
|
+
stage: "publishing-bootstrap",
|
|
3628
|
+
label: "Verifying reachability",
|
|
3629
|
+
progress: 96,
|
|
3630
|
+
status: "info",
|
|
3631
|
+
itemHash: args.itemHash,
|
|
3632
|
+
detail: "Checking that the secure relay endpoint is reachable before trusting the deployment as ready."
|
|
3633
|
+
});
|
|
3634
|
+
const verificationUrl = (() => {
|
|
3635
|
+
try {
|
|
3636
|
+
return new URL("/bootstrap/metadata", runtime.proxyUrl).toString();
|
|
3637
|
+
} catch {
|
|
3638
|
+
return runtime.proxyUrl ?? "";
|
|
3639
|
+
}
|
|
3640
|
+
})();
|
|
3641
|
+
let verificationResult = null;
|
|
3642
|
+
for (let attempt = 0; attempt < UI_REACHABILITY_VERIFY_ATTEMPTS; attempt += 1) {
|
|
3643
|
+
verificationResult = await verifyUcGoPeerReachability({
|
|
3644
|
+
proxyUrl: verificationUrl,
|
|
3645
|
+
verifyProxyHttp: true,
|
|
3646
|
+
fetch: (url, init) => fetch(url, init),
|
|
3647
|
+
tcpProbe: async () => ({ ok: null })
|
|
3648
|
+
});
|
|
3649
|
+
this.trace("deploy:reachability-verification-attempt", {
|
|
3650
|
+
itemHash: args.itemHash,
|
|
3651
|
+
attempt: attempt + 1,
|
|
3652
|
+
attempts: UI_REACHABILITY_VERIFY_ATTEMPTS,
|
|
3653
|
+
verificationUrl,
|
|
3654
|
+
ok: verificationResult.ok,
|
|
3655
|
+
checks: verificationResult.checks
|
|
3656
|
+
});
|
|
3657
|
+
const proxyHttpCheck2 = verificationResult.checks["https:proxy"];
|
|
3658
|
+
if (verificationResult.ok && proxyHttpCheck2?.ok === true) {
|
|
3659
|
+
break;
|
|
3660
|
+
}
|
|
3661
|
+
if (attempt < UI_REACHABILITY_VERIFY_ATTEMPTS - 1) {
|
|
3662
|
+
await new Promise(
|
|
3663
|
+
(resolve) => globalThis.setTimeout(resolve, UI_REACHABILITY_VERIFY_DELAY_MS)
|
|
3664
|
+
);
|
|
3665
|
+
}
|
|
3666
|
+
}
|
|
3667
|
+
const proxyHttpCheck = verificationResult?.checks["https:proxy"];
|
|
3668
|
+
if (!verificationResult?.ok || proxyHttpCheck?.ok !== true) {
|
|
3669
|
+
throw new Error(
|
|
3670
|
+
proxyHttpCheck?.error ? `Secure relay endpoint did not become reachable in time: ${proxyHttpCheck.error}` : "Secure relay endpoint did not become reachable in time."
|
|
3671
|
+
);
|
|
3672
|
+
}
|
|
3673
|
+
}
|
|
3517
3674
|
const { peerId } = relayMetadata;
|
|
3518
3675
|
const registrationId = createRelayBootstrapRegistrationId(
|
|
3519
3676
|
profile,
|
package/shared/index.d.ts
CHANGED
|
@@ -290,7 +290,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
|
|
|
290
290
|
declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
|
|
291
291
|
declare const DEPLOYMENT_PENDING_WARNING_MS: number;
|
|
292
292
|
|
|
293
|
-
declare const UI_PACKAGE_VERSION = "0.3.
|
|
293
|
+
declare const UI_PACKAGE_VERSION = "0.3.28";
|
|
294
294
|
|
|
295
295
|
interface RootfsRequiredPortForward {
|
|
296
296
|
port: number;
|
package/shared/index.js
CHANGED
|
@@ -27,7 +27,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
27
27
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
28
28
|
|
|
29
29
|
// src/shared/package-version.ts
|
|
30
|
-
var UI_PACKAGE_VERSION = "0.3.
|
|
30
|
+
var UI_PACKAGE_VERSION = "0.3.28";
|
|
31
31
|
|
|
32
32
|
// src/shared/format.ts
|
|
33
33
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -1877,6 +1877,13 @@ async function waitForVmRuntime(args) {
|
|
|
1877
1877
|
}
|
|
1878
1878
|
|
|
1879
1879
|
// ../core/src/guest.ts
|
|
1880
|
+
function proxyHostnameFromUrl(value) {
|
|
1881
|
+
try {
|
|
1882
|
+
return value ? new URL(value).hostname : null;
|
|
1883
|
+
} catch {
|
|
1884
|
+
return null;
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1880
1887
|
async function defaultHttpProbe(fetch2, url, timeoutMs = 1e4) {
|
|
1881
1888
|
try {
|
|
1882
1889
|
const controller = new AbortController();
|
|
@@ -2118,6 +2125,59 @@ async function fetchUcGoPeerMetadata(args) {
|
|
|
2118
2125
|
`Relay metadata did not become ready after ${attempts} attempts: ${lastError ? lastError : typeof lastPayload === "string" ? lastPayload : JSON.stringify(lastPayload ?? {})}`
|
|
2119
2126
|
);
|
|
2120
2127
|
}
|
|
2128
|
+
async function verifyUcGoPeerReachability(args) {
|
|
2129
|
+
const checks = {};
|
|
2130
|
+
const mappedPorts2 = args.mappedPorts ?? {};
|
|
2131
|
+
const hostIpv4 = args.hostIpv4;
|
|
2132
|
+
const skippedInternalPorts = new Set(
|
|
2133
|
+
(args.skipInternalPorts ?? ["80"]).map((value) => String(value))
|
|
2134
|
+
);
|
|
2135
|
+
const httpProbe = args.httpProbe ?? ((url, timeoutMs) => defaultHttpProbe(args.fetch, url, timeoutMs));
|
|
2136
|
+
if (hostIpv4) {
|
|
2137
|
+
for (const [internalPort, mapping] of Object.entries(mappedPorts2)) {
|
|
2138
|
+
if (skippedInternalPorts.has(String(internalPort))) continue;
|
|
2139
|
+
if (mapping?.tcp === true && mapping?.host) {
|
|
2140
|
+
checks[`tcp:${internalPort}`] = {
|
|
2141
|
+
host: hostIpv4,
|
|
2142
|
+
port: mapping.host,
|
|
2143
|
+
...await args.tcpProbe(
|
|
2144
|
+
hostIpv4,
|
|
2145
|
+
mapping.host,
|
|
2146
|
+
Number(args.tcpTimeoutMs ?? 5e3)
|
|
2147
|
+
)
|
|
2148
|
+
};
|
|
2149
|
+
} else if (mapping?.udp === true && mapping?.host) {
|
|
2150
|
+
checks[`udp:${internalPort}`] = {
|
|
2151
|
+
host: hostIpv4,
|
|
2152
|
+
port: mapping.host,
|
|
2153
|
+
ok: null,
|
|
2154
|
+
note: "UDP mapping published; CI does not perform an application-level UDP handshake probe."
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
if (args.proxyUrl && args.verifyProxyHttp !== false) {
|
|
2160
|
+
checks["https:proxy"] = await httpProbe(
|
|
2161
|
+
args.proxyUrl,
|
|
2162
|
+
Number(args.httpTimeoutMs ?? 1e4)
|
|
2163
|
+
);
|
|
2164
|
+
}
|
|
2165
|
+
const proxyHostname = proxyHostnameFromUrl(args.proxyUrl);
|
|
2166
|
+
if (proxyHostname) {
|
|
2167
|
+
checks["tcp:proxy-443"] = await args.tcpProbe(
|
|
2168
|
+
proxyHostname,
|
|
2169
|
+
443,
|
|
2170
|
+
Number(args.tcpTimeoutMs ?? 5e3)
|
|
2171
|
+
);
|
|
2172
|
+
}
|
|
2173
|
+
const failedChecks = Object.entries(checks).filter(
|
|
2174
|
+
([, value]) => value?.ok === false
|
|
2175
|
+
);
|
|
2176
|
+
return {
|
|
2177
|
+
ok: failedChecks.length === 0,
|
|
2178
|
+
checks
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2121
2181
|
|
|
2122
2182
|
// ../aleph-bootstrap/src/index.ts
|
|
2123
2183
|
import { recoverMessageAddress } from "viem";
|
|
@@ -3218,6 +3278,8 @@ var UI_DEPLOY_WAIT_ATTEMPTS = 60;
|
|
|
3218
3278
|
var UI_DEPLOY_WAIT_DELAY_MS = 5e3;
|
|
3219
3279
|
var UI_RUNTIME_WAIT_ATTEMPTS = 40;
|
|
3220
3280
|
var UI_RUNTIME_WAIT_DELAY_MS = 5e3;
|
|
3281
|
+
var UI_REACHABILITY_VERIFY_ATTEMPTS = 25;
|
|
3282
|
+
var UI_REACHABILITY_VERIFY_DELAY_MS = 3e3;
|
|
3221
3283
|
function hasUsableRuntime(details) {
|
|
3222
3284
|
return Boolean(details.hostIpv4) || Boolean(details.vmIpv4) || details.mappedPorts.length > 0 || Boolean(details.webUrl) || Boolean(details.execution);
|
|
3223
3285
|
}
|
|
@@ -3324,15 +3386,16 @@ var SponsorRelayController = class {
|
|
|
3324
3386
|
this.progressEmitter.emit(nextEvent);
|
|
3325
3387
|
}
|
|
3326
3388
|
async configureRelayBootstrapRegistration(args) {
|
|
3389
|
+
let runtime = args.runtime;
|
|
3327
3390
|
const profile = relayProfileForManifest(this.state.manifest);
|
|
3328
3391
|
if (!profile) return;
|
|
3329
3392
|
if (!this.state.wallet.address) {
|
|
3330
3393
|
throw new Error("A connected wallet is required to register relay bootstrap addresses.");
|
|
3331
3394
|
}
|
|
3332
|
-
if (!
|
|
3395
|
+
if (!runtime.hostIpv4) {
|
|
3333
3396
|
throw new Error("Relay runtime did not expose a host IPv4 address.");
|
|
3334
3397
|
}
|
|
3335
|
-
|
|
3398
|
+
let mappedPorts2 = runtime.mappedPorts ?? {};
|
|
3336
3399
|
const setupPort = mappedPorts2["80"]?.host ?? null;
|
|
3337
3400
|
if (!setupPort) {
|
|
3338
3401
|
throw new Error("Relay runtime did not expose the temporary setup endpoint.");
|
|
@@ -3347,7 +3410,7 @@ var SponsorRelayController = class {
|
|
|
3347
3410
|
detail: "Waiting for the guest setup endpoint before collecting relay metadata."
|
|
3348
3411
|
});
|
|
3349
3412
|
const setupHealth = await waitForSetupEndpoint({
|
|
3350
|
-
hostIpv4:
|
|
3413
|
+
hostIpv4: runtime.hostIpv4,
|
|
3351
3414
|
setupPort,
|
|
3352
3415
|
fetch: (url, init) => fetch(url, init),
|
|
3353
3416
|
attempts: 15,
|
|
@@ -3373,12 +3436,12 @@ var SponsorRelayController = class {
|
|
|
3373
3436
|
throw new Error("OrbitDB relay runtime is missing required mapped TCP/WS ports.");
|
|
3374
3437
|
}
|
|
3375
3438
|
const configureResult = await configureOrbitdbRelaySetup2({
|
|
3376
|
-
hostIpv4:
|
|
3377
|
-
publicIpv6:
|
|
3439
|
+
hostIpv4: runtime.hostIpv4,
|
|
3440
|
+
publicIpv6: runtime.ipv6,
|
|
3378
3441
|
setupPort,
|
|
3379
3442
|
tcpPort,
|
|
3380
3443
|
wsPort,
|
|
3381
|
-
proxyUrl:
|
|
3444
|
+
proxyUrl: runtime.proxyUrl ?? void 0,
|
|
3382
3445
|
metricsPort: mappedPorts2["9090"]?.host ?? null,
|
|
3383
3446
|
metricsHttpsPort: mappedPorts2["443"]?.host ?? null,
|
|
3384
3447
|
webrtcPort: mappedPorts2["9093"]?.host ?? null,
|
|
@@ -3395,6 +3458,51 @@ var SponsorRelayController = class {
|
|
|
3395
3458
|
if (!args.deploymentToken) {
|
|
3396
3459
|
throw new Error("Missing deployment token for Aleph bootstrap config handoff.");
|
|
3397
3460
|
}
|
|
3461
|
+
if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
|
|
3462
|
+
this.emitProgress({
|
|
3463
|
+
stage: "deployment-confirmed",
|
|
3464
|
+
label: "Waiting for HTTPS route",
|
|
3465
|
+
progress: 93,
|
|
3466
|
+
status: "warning",
|
|
3467
|
+
itemHash: args.itemHash,
|
|
3468
|
+
detail: "The relay received a 2n6 hostname, but it is not active yet. Waiting before handing HTTPS config to the guest."
|
|
3469
|
+
});
|
|
3470
|
+
let latestRuntime = runtime;
|
|
3471
|
+
for (let attempt = 0; attempt < UI_RUNTIME_WAIT_ATTEMPTS; attempt += 1) {
|
|
3472
|
+
if (latestRuntime.webAccess?.active === true) {
|
|
3473
|
+
break;
|
|
3474
|
+
}
|
|
3475
|
+
await new Promise(
|
|
3476
|
+
(resolve) => globalThis.setTimeout(resolve, UI_RUNTIME_WAIT_DELAY_MS)
|
|
3477
|
+
);
|
|
3478
|
+
latestRuntime = await fetchVmRuntime({
|
|
3479
|
+
itemHash: args.itemHash,
|
|
3480
|
+
fetch: (url, init) => fetch(url, init),
|
|
3481
|
+
crnHash: runtime.selectedCrn?.hash ?? runtime.allocation?.crnHash ?? void 0,
|
|
3482
|
+
crns: this.state.crns,
|
|
3483
|
+
crnListUrl: this.props.crnListUrl
|
|
3484
|
+
}).catch(() => latestRuntime);
|
|
3485
|
+
this.trace("deploy:bootstrap-proxy-activation", {
|
|
3486
|
+
itemHash: args.itemHash,
|
|
3487
|
+
attempt: attempt + 1,
|
|
3488
|
+
attempts: UI_RUNTIME_WAIT_ATTEMPTS,
|
|
3489
|
+
active: latestRuntime.webAccess?.active === true,
|
|
3490
|
+
proxyUrl: latestRuntime.proxyUrl ?? null
|
|
3491
|
+
});
|
|
3492
|
+
}
|
|
3493
|
+
runtime = latestRuntime;
|
|
3494
|
+
mappedPorts2 = runtime.mappedPorts ?? mappedPorts2;
|
|
3495
|
+
if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
|
|
3496
|
+
throw new Error(
|
|
3497
|
+
"Aleph reserved a 2n6 proxy URL, but it never became active in time. Aborting guest HTTPS configuration to avoid a broken Caddy setup."
|
|
3498
|
+
);
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
if (!runtime.hostIpv4) {
|
|
3502
|
+
throw new Error("Relay runtime lost its host IPv4 address while waiting for HTTPS activation.");
|
|
3503
|
+
}
|
|
3504
|
+
const runtimeHostIpv4 = runtime.hostIpv4;
|
|
3505
|
+
const activeProxyUrl = runtime.webAccess?.active === true ? runtime.proxyUrl ?? null : null;
|
|
3398
3506
|
this.emitProgress({
|
|
3399
3507
|
stage: "deployment-confirmed",
|
|
3400
3508
|
label: "Publishing relay config",
|
|
@@ -3412,9 +3520,9 @@ var SponsorRelayController = class {
|
|
|
3412
3520
|
expiresAt: new Date(Date.now() + 30 * 6e4).toISOString(),
|
|
3413
3521
|
status: "pending",
|
|
3414
3522
|
runtime: {
|
|
3415
|
-
publicIpv4:
|
|
3416
|
-
publicIpv6:
|
|
3417
|
-
proxyUrl:
|
|
3523
|
+
publicIpv4: runtimeHostIpv4,
|
|
3524
|
+
publicIpv6: runtime.ipv6 ?? null,
|
|
3525
|
+
proxyUrl: activeProxyUrl,
|
|
3418
3526
|
mappedPorts: mappedPorts2
|
|
3419
3527
|
},
|
|
3420
3528
|
bootstrap: {
|
|
@@ -3480,7 +3588,7 @@ var SponsorRelayController = class {
|
|
|
3480
3588
|
detail: "Waiting for the relay to report its final public multiaddrs."
|
|
3481
3589
|
});
|
|
3482
3590
|
const relayMetadata = await fetchRelayMetadataForRuntime({
|
|
3483
|
-
runtime
|
|
3591
|
+
runtime,
|
|
3484
3592
|
fetch: (url, init) => fetch(url, init),
|
|
3485
3593
|
preferSecureMetadata: profile === "uc-go-peer",
|
|
3486
3594
|
attempts: 80,
|
|
@@ -3513,6 +3621,55 @@ var SponsorRelayController = class {
|
|
|
3513
3621
|
if (!relayMetadata) {
|
|
3514
3622
|
throw new Error("Relay metadata did not include a peer ID and public multiaddrs.");
|
|
3515
3623
|
}
|
|
3624
|
+
if (profile === "uc-go-peer" && runtime.proxyUrl) {
|
|
3625
|
+
this.emitProgress({
|
|
3626
|
+
stage: "publishing-bootstrap",
|
|
3627
|
+
label: "Verifying reachability",
|
|
3628
|
+
progress: 96,
|
|
3629
|
+
status: "info",
|
|
3630
|
+
itemHash: args.itemHash,
|
|
3631
|
+
detail: "Checking that the secure relay endpoint is reachable before trusting the deployment as ready."
|
|
3632
|
+
});
|
|
3633
|
+
const verificationUrl = (() => {
|
|
3634
|
+
try {
|
|
3635
|
+
return new URL("/bootstrap/metadata", runtime.proxyUrl).toString();
|
|
3636
|
+
} catch {
|
|
3637
|
+
return runtime.proxyUrl ?? "";
|
|
3638
|
+
}
|
|
3639
|
+
})();
|
|
3640
|
+
let verificationResult = null;
|
|
3641
|
+
for (let attempt = 0; attempt < UI_REACHABILITY_VERIFY_ATTEMPTS; attempt += 1) {
|
|
3642
|
+
verificationResult = await verifyUcGoPeerReachability({
|
|
3643
|
+
proxyUrl: verificationUrl,
|
|
3644
|
+
verifyProxyHttp: true,
|
|
3645
|
+
fetch: (url, init) => fetch(url, init),
|
|
3646
|
+
tcpProbe: async () => ({ ok: null })
|
|
3647
|
+
});
|
|
3648
|
+
this.trace("deploy:reachability-verification-attempt", {
|
|
3649
|
+
itemHash: args.itemHash,
|
|
3650
|
+
attempt: attempt + 1,
|
|
3651
|
+
attempts: UI_REACHABILITY_VERIFY_ATTEMPTS,
|
|
3652
|
+
verificationUrl,
|
|
3653
|
+
ok: verificationResult.ok,
|
|
3654
|
+
checks: verificationResult.checks
|
|
3655
|
+
});
|
|
3656
|
+
const proxyHttpCheck2 = verificationResult.checks["https:proxy"];
|
|
3657
|
+
if (verificationResult.ok && proxyHttpCheck2?.ok === true) {
|
|
3658
|
+
break;
|
|
3659
|
+
}
|
|
3660
|
+
if (attempt < UI_REACHABILITY_VERIFY_ATTEMPTS - 1) {
|
|
3661
|
+
await new Promise(
|
|
3662
|
+
(resolve) => globalThis.setTimeout(resolve, UI_REACHABILITY_VERIFY_DELAY_MS)
|
|
3663
|
+
);
|
|
3664
|
+
}
|
|
3665
|
+
}
|
|
3666
|
+
const proxyHttpCheck = verificationResult?.checks["https:proxy"];
|
|
3667
|
+
if (!verificationResult?.ok || proxyHttpCheck?.ok !== true) {
|
|
3668
|
+
throw new Error(
|
|
3669
|
+
proxyHttpCheck?.error ? `Secure relay endpoint did not become reachable in time: ${proxyHttpCheck.error}` : "Secure relay endpoint did not become reachable in time."
|
|
3670
|
+
);
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3516
3673
|
const { peerId } = relayMetadata;
|
|
3517
3674
|
const registrationId = createRelayBootstrapRegistrationId(
|
|
3518
3675
|
profile,
|