@le-space/ui 0.3.24 → 0.3.25
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.d.ts +0 -14
- package/react/index.js +116 -79
- package/shared/index.d.ts +2 -18
- package/shared/index.js +115 -79
- package/svelte/SponsorRelayFab.svelte +0 -28
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@le-space/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.25",
|
|
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.25",
|
|
40
|
+
"@le-space/core": "0.3.25",
|
|
41
41
|
"viem": "^2.38.5"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
package/react/index.d.ts
CHANGED
|
@@ -189,7 +189,6 @@ type DeploymentProgressListener = (event: DeploymentProgressEvent) => void;
|
|
|
189
189
|
|
|
190
190
|
type SponsorRelayHealthTone = 'ok' | 'caution' | 'error' | 'idle';
|
|
191
191
|
interface SponsorRelayProps {
|
|
192
|
-
libp2p?: unknown;
|
|
193
192
|
debug?: boolean;
|
|
194
193
|
manifestUrl?: string;
|
|
195
194
|
manifestJson?: string;
|
|
@@ -224,16 +223,6 @@ interface SponsorRelayRootfsHealth {
|
|
|
224
223
|
label: string;
|
|
225
224
|
detail: string | null;
|
|
226
225
|
}
|
|
227
|
-
interface RelayPingState {
|
|
228
|
-
tone: SponsorRelayHealthTone;
|
|
229
|
-
sent: boolean;
|
|
230
|
-
received: boolean;
|
|
231
|
-
lastPeerId: string | null;
|
|
232
|
-
lastLatencyMs: number | null;
|
|
233
|
-
lastSentAt: number | null;
|
|
234
|
-
lastReceivedAt: number | null;
|
|
235
|
-
error: string | null;
|
|
236
|
-
}
|
|
237
226
|
interface CompactInstanceDetails {
|
|
238
227
|
messageStatus: string;
|
|
239
228
|
allocationSource: string | null;
|
|
@@ -284,7 +273,6 @@ interface SponsorRelayState {
|
|
|
284
273
|
crns: Crn[];
|
|
285
274
|
selectedCrn: Crn | null;
|
|
286
275
|
instances: CompactInstanceRecord[];
|
|
287
|
-
relayPing: RelayPingState;
|
|
288
276
|
lastDeploymentHash: string | null;
|
|
289
277
|
deploymentProgress: DeploymentProgressEvent;
|
|
290
278
|
}
|
|
@@ -295,7 +283,6 @@ declare class SponsorRelayController {
|
|
|
295
283
|
private subscribers;
|
|
296
284
|
private client;
|
|
297
285
|
private refreshTimer;
|
|
298
|
-
private pingTimer;
|
|
299
286
|
private manifestRefreshTimer;
|
|
300
287
|
private stopWalletWatch;
|
|
301
288
|
private props;
|
|
@@ -335,7 +322,6 @@ declare class SponsorRelayController {
|
|
|
335
322
|
connectWallet(): Promise<void>;
|
|
336
323
|
private refreshWalletDerivedState;
|
|
337
324
|
refresh(): Promise<void>;
|
|
338
|
-
refreshRelayPing(): Promise<void>;
|
|
339
325
|
deploy(): Promise<void>;
|
|
340
326
|
deleteInstance(instanceHash: string): Promise<void>;
|
|
341
327
|
}
|
package/react/index.js
CHANGED
|
@@ -10,16 +10,6 @@ var ROOTFS_MISSING_STATE = {
|
|
|
10
10
|
label: "manifest missing",
|
|
11
11
|
detail: "Provide a manifest URL or paste manifest JSON."
|
|
12
12
|
};
|
|
13
|
-
var RELAY_PING_IDLE_STATE = {
|
|
14
|
-
tone: "idle",
|
|
15
|
-
sent: false,
|
|
16
|
-
received: false,
|
|
17
|
-
lastPeerId: null,
|
|
18
|
-
lastLatencyMs: null,
|
|
19
|
-
lastSentAt: null,
|
|
20
|
-
lastReceivedAt: null,
|
|
21
|
-
error: null
|
|
22
|
-
};
|
|
23
13
|
var IDLE_DEPLOYMENT_PROGRESS = {
|
|
24
14
|
stage: "idle",
|
|
25
15
|
label: "Ready",
|
|
@@ -31,7 +21,6 @@ var IDLE_DEPLOYMENT_PROGRESS = {
|
|
|
31
21
|
timestamp: Date.now()
|
|
32
22
|
};
|
|
33
23
|
var REFRESH_INTERVAL_MS = 3e4;
|
|
34
|
-
var RELAY_PING_INTERVAL_MS = 2e4;
|
|
35
24
|
var MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS = 400;
|
|
36
25
|
var INSTANCE_RUNTIME_STALE_REFRESH_MS = 5 * 6e4;
|
|
37
26
|
var STALE_INSTANCE_ALLOCATION_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
@@ -39,7 +28,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
39
28
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
40
29
|
|
|
41
30
|
// src/shared/package-version.ts
|
|
42
|
-
var UI_PACKAGE_VERSION = "0.3.
|
|
31
|
+
var UI_PACKAGE_VERSION = "0.3.25";
|
|
43
32
|
|
|
44
33
|
// src/shared/format.ts
|
|
45
34
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -2684,6 +2673,16 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2684
2673
|
|
|
2685
2674
|
// ../core/src/bootstrap-config.ts
|
|
2686
2675
|
var VM_BOOTSTRAP_CONFIG_AGGREGATE_KEY = "vm-bootstrap-config";
|
|
2676
|
+
var VM_BOOTSTRAP_CONFIG_SIGNAL_REF = "vm-bootstrap-config";
|
|
2677
|
+
var VM_BOOTSTRAP_CONFIG_SIGNAL_POST_TYPE = "vm-bootstrap-config-status";
|
|
2678
|
+
function parseJsonObject(value) {
|
|
2679
|
+
try {
|
|
2680
|
+
const parsed = JSON.parse(value);
|
|
2681
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
2682
|
+
} catch {
|
|
2683
|
+
return null;
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2687
2686
|
async function fetchVmBootstrapConfigAggregate(address, options) {
|
|
2688
2687
|
const requestUrl = new URL(`/api/v0/aggregates/${address}.json`, options.apiHost ?? DEFAULT_ALEPH_API_HOST2);
|
|
2689
2688
|
requestUrl.searchParams.set("keys", VM_BOOTSTRAP_CONFIG_AGGREGATE_KEY);
|
|
@@ -2803,6 +2802,82 @@ async function deleteVmBootstrapConfig(args) {
|
|
|
2803
2802
|
aggregate: content
|
|
2804
2803
|
};
|
|
2805
2804
|
}
|
|
2805
|
+
function normalizeVmBootstrapConfigSignalRecord(value) {
|
|
2806
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
2807
|
+
const candidate = value;
|
|
2808
|
+
const deploymentToken = typeof candidate.deploymentToken === "string" ? candidate.deploymentToken.trim() : "";
|
|
2809
|
+
const status = typeof candidate.status === "string" ? candidate.status.trim() : "";
|
|
2810
|
+
const profile = typeof candidate.profile === "string" ? candidate.profile.trim() : "";
|
|
2811
|
+
const ownerAddress = typeof candidate.ownerAddress === "string" ? candidate.ownerAddress.trim() : "";
|
|
2812
|
+
const instanceItemHash = typeof candidate.instanceItemHash === "string" ? candidate.instanceItemHash.trim() : "";
|
|
2813
|
+
const updatedAt = typeof candidate.updatedAt === "string" ? candidate.updatedAt.trim() : "";
|
|
2814
|
+
if (!deploymentToken || !status || !profile || !ownerAddress || !instanceItemHash || !updatedAt) {
|
|
2815
|
+
return null;
|
|
2816
|
+
}
|
|
2817
|
+
return {
|
|
2818
|
+
deploymentToken,
|
|
2819
|
+
status,
|
|
2820
|
+
profile,
|
|
2821
|
+
ownerAddress,
|
|
2822
|
+
instanceItemHash,
|
|
2823
|
+
updatedAt,
|
|
2824
|
+
publisherAddress: typeof candidate.publisherAddress === "string" && candidate.publisherAddress.trim() ? candidate.publisherAddress.trim() : null,
|
|
2825
|
+
authorization: candidate.authorization
|
|
2826
|
+
};
|
|
2827
|
+
}
|
|
2828
|
+
async function fetchVmBootstrapConfigSignals(args) {
|
|
2829
|
+
const requestUrl = new URL("/api/v0/posts.json", args.apiHost ?? DEFAULT_ALEPH_API_HOST2);
|
|
2830
|
+
requestUrl.searchParams.set("refs", args.ref ?? VM_BOOTSTRAP_CONFIG_SIGNAL_REF);
|
|
2831
|
+
requestUrl.searchParams.set("types", args.postType ?? VM_BOOTSTRAP_CONFIG_SIGNAL_POST_TYPE);
|
|
2832
|
+
requestUrl.searchParams.set("pagination", String(Math.max(1, Number(args.pagination ?? 100))));
|
|
2833
|
+
requestUrl.searchParams.set("page", String(Math.max(1, Number(args.page ?? 1))));
|
|
2834
|
+
requestUrl.searchParams.set("sortOrder", "-1");
|
|
2835
|
+
const response = await args.fetch(requestUrl.toString(), { cache: "no-cache" });
|
|
2836
|
+
if (!response.ok) {
|
|
2837
|
+
throw new Error(`VM bootstrap config signal request failed: ${response.status}`);
|
|
2838
|
+
}
|
|
2839
|
+
const payload = await response.json();
|
|
2840
|
+
const expectedDeploymentToken = args.deploymentToken?.trim() ?? "";
|
|
2841
|
+
const expectedOwnerAddress = args.ownerAddress?.trim().toLowerCase() ?? "";
|
|
2842
|
+
const expectedInstanceItemHash = args.instanceItemHash?.trim() ?? "";
|
|
2843
|
+
return (payload.posts ?? []).map((entry) => {
|
|
2844
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return null;
|
|
2845
|
+
const parsed = "content" in entry && entry.content && typeof entry.content === "object" && !Array.isArray(entry.content) ? entry.content : "item_content" in entry && typeof entry.item_content === "string" ? parseJsonObject(entry.item_content) : null;
|
|
2846
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
2847
|
+
const content = "deploymentToken" in parsed ? parsed : "content" in parsed && parsed.content && typeof parsed.content === "object" && !Array.isArray(parsed.content) ? parsed.content : null;
|
|
2848
|
+
if (!content || typeof content !== "object" || Array.isArray(content)) return null;
|
|
2849
|
+
return normalizeVmBootstrapConfigSignalRecord(content);
|
|
2850
|
+
}).filter((entry) => {
|
|
2851
|
+
if (!entry) return false;
|
|
2852
|
+
if (expectedDeploymentToken && entry.deploymentToken !== expectedDeploymentToken) return false;
|
|
2853
|
+
if (expectedOwnerAddress && entry.ownerAddress.toLowerCase() !== expectedOwnerAddress) return false;
|
|
2854
|
+
if (expectedInstanceItemHash && entry.instanceItemHash !== expectedInstanceItemHash) return false;
|
|
2855
|
+
return true;
|
|
2856
|
+
});
|
|
2857
|
+
}
|
|
2858
|
+
async function waitForVmBootstrapConfigSignal(args) {
|
|
2859
|
+
const attempts = Math.max(1, Number(args.attempts ?? 24));
|
|
2860
|
+
const delayMs = Math.max(0, Number(args.delayMs ?? 2500));
|
|
2861
|
+
const sleep2 = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2862
|
+
const expectedStatus = args.expectedStatus ?? "applied";
|
|
2863
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
2864
|
+
const signals = await fetchVmBootstrapConfigSignals({
|
|
2865
|
+
deploymentToken: args.deploymentToken,
|
|
2866
|
+
ownerAddress: args.ownerAddress,
|
|
2867
|
+
instanceItemHash: args.instanceItemHash,
|
|
2868
|
+
fetch: args.fetch,
|
|
2869
|
+
apiHost: args.apiHost,
|
|
2870
|
+
ref: args.ref,
|
|
2871
|
+
postType: args.postType
|
|
2872
|
+
}).catch(() => []);
|
|
2873
|
+
const match = signals.find((entry) => entry.status === expectedStatus) ?? null;
|
|
2874
|
+
if (match) return match;
|
|
2875
|
+
if (attempt < attempts - 1) {
|
|
2876
|
+
await sleep2(delayMs);
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
return null;
|
|
2880
|
+
}
|
|
2806
2881
|
|
|
2807
2882
|
// ../core/src/bootstrap-reconcile.ts
|
|
2808
2883
|
function createRelayBootstrapRegistrationId(profile, instanceName, itemHash) {
|
|
@@ -2941,7 +3016,6 @@ function defaultState(props = {}) {
|
|
|
2941
3016
|
crns: [],
|
|
2942
3017
|
selectedCrn: null,
|
|
2943
3018
|
instances: [],
|
|
2944
|
-
relayPing: RELAY_PING_IDLE_STATE,
|
|
2945
3019
|
lastDeploymentHash: null,
|
|
2946
3020
|
deploymentProgress: IDLE_DEPLOYMENT_PROGRESS
|
|
2947
3021
|
};
|
|
@@ -3154,57 +3228,6 @@ function compatibleCrnsForTier(crns, state) {
|
|
|
3154
3228
|
);
|
|
3155
3229
|
return filterDeployableCrns(crns, { spec });
|
|
3156
3230
|
}
|
|
3157
|
-
async function pingPeer(libp2p) {
|
|
3158
|
-
if (!libp2p || typeof libp2p !== "object") {
|
|
3159
|
-
return RELAY_PING_IDLE_STATE;
|
|
3160
|
-
}
|
|
3161
|
-
const candidate = libp2p;
|
|
3162
|
-
const peers = candidate.getPeers?.() ?? [];
|
|
3163
|
-
const firstPeer = peers[0];
|
|
3164
|
-
if (!firstPeer) {
|
|
3165
|
-
return {
|
|
3166
|
-
...RELAY_PING_IDLE_STATE,
|
|
3167
|
-
tone: "caution",
|
|
3168
|
-
error: "No connected relay peers available."
|
|
3169
|
-
};
|
|
3170
|
-
}
|
|
3171
|
-
const sentAt = Date.now();
|
|
3172
|
-
try {
|
|
3173
|
-
const pingFn = candidate.services?.ping?.ping?.bind(candidate.services.ping) ?? candidate.ping?.bind(candidate);
|
|
3174
|
-
if (!pingFn) {
|
|
3175
|
-
return {
|
|
3176
|
-
...RELAY_PING_IDLE_STATE,
|
|
3177
|
-
tone: "caution",
|
|
3178
|
-
sent: true,
|
|
3179
|
-
lastPeerId: String(firstPeer),
|
|
3180
|
-
lastSentAt: sentAt,
|
|
3181
|
-
error: "libp2p ping service not available."
|
|
3182
|
-
};
|
|
3183
|
-
}
|
|
3184
|
-
const latency = await pingFn(firstPeer);
|
|
3185
|
-
return {
|
|
3186
|
-
tone: "ok",
|
|
3187
|
-
sent: true,
|
|
3188
|
-
received: true,
|
|
3189
|
-
lastPeerId: String(firstPeer),
|
|
3190
|
-
lastLatencyMs: Number(latency),
|
|
3191
|
-
lastSentAt: sentAt,
|
|
3192
|
-
lastReceivedAt: Date.now(),
|
|
3193
|
-
error: null
|
|
3194
|
-
};
|
|
3195
|
-
} catch (error) {
|
|
3196
|
-
return {
|
|
3197
|
-
tone: "error",
|
|
3198
|
-
sent: true,
|
|
3199
|
-
received: false,
|
|
3200
|
-
lastPeerId: String(firstPeer),
|
|
3201
|
-
lastLatencyMs: null,
|
|
3202
|
-
lastSentAt: sentAt,
|
|
3203
|
-
lastReceivedAt: null,
|
|
3204
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3205
|
-
};
|
|
3206
|
-
}
|
|
3207
|
-
}
|
|
3208
3231
|
var UI_DEPLOY_WAIT_ATTEMPTS = 60;
|
|
3209
3232
|
var UI_DEPLOY_WAIT_DELAY_MS = 5e3;
|
|
3210
3233
|
var UI_RUNTIME_WAIT_ATTEMPTS = 40;
|
|
@@ -3235,7 +3258,6 @@ var SponsorRelayController = class {
|
|
|
3235
3258
|
subscribers = /* @__PURE__ */ new Set();
|
|
3236
3259
|
client;
|
|
3237
3260
|
refreshTimer = null;
|
|
3238
|
-
pingTimer = null;
|
|
3239
3261
|
manifestRefreshTimer = null;
|
|
3240
3262
|
stopWalletWatch = null;
|
|
3241
3263
|
props;
|
|
@@ -3291,8 +3313,7 @@ var SponsorRelayController = class {
|
|
|
3291
3313
|
...patch,
|
|
3292
3314
|
busy: patch.busy ? { ...this.state.busy, ...patch.busy } : this.state.busy,
|
|
3293
3315
|
wallet: patch.wallet ? { ...this.state.wallet, ...patch.wallet } : this.state.wallet,
|
|
3294
|
-
pricingSummary: patch.pricingSummary ? { ...this.state.pricingSummary, ...patch.pricingSummary } : this.state.pricingSummary
|
|
3295
|
-
relayPing: patch.relayPing ? { ...this.state.relayPing, ...patch.relayPing } : this.state.relayPing
|
|
3316
|
+
pricingSummary: patch.pricingSummary ? { ...this.state.pricingSummary, ...patch.pricingSummary } : this.state.pricingSummary
|
|
3296
3317
|
};
|
|
3297
3318
|
this.emit();
|
|
3298
3319
|
}
|
|
@@ -3436,6 +3457,33 @@ var SponsorRelayController = class {
|
|
|
3436
3457
|
aggregateItemHash: bootstrapConfigPublication.aggregateItemHash,
|
|
3437
3458
|
aggregateStatus: bootstrapConfigPublication.aggregateStatus
|
|
3438
3459
|
});
|
|
3460
|
+
this.emitProgress({
|
|
3461
|
+
stage: "deployment-confirmed",
|
|
3462
|
+
label: "Waiting for guest config",
|
|
3463
|
+
progress: 94,
|
|
3464
|
+
status: "info",
|
|
3465
|
+
itemHash: args.itemHash,
|
|
3466
|
+
detail: "Waiting for the relay VM to acknowledge that it consumed the Aleph bootstrap config."
|
|
3467
|
+
});
|
|
3468
|
+
const bootstrapConfigSignal = await waitForVmBootstrapConfigSignal({
|
|
3469
|
+
deploymentToken: args.deploymentToken,
|
|
3470
|
+
ownerAddress: this.state.wallet.address,
|
|
3471
|
+
instanceItemHash: args.itemHash,
|
|
3472
|
+
fetch: asJsonFetch,
|
|
3473
|
+
apiHost: this.client.apiHost,
|
|
3474
|
+
attempts: 40,
|
|
3475
|
+
delayMs: 3e3
|
|
3476
|
+
});
|
|
3477
|
+
this.trace("deploy:bootstrap-config-signal-visible", {
|
|
3478
|
+
itemHash: args.itemHash,
|
|
3479
|
+
deploymentToken: args.deploymentToken,
|
|
3480
|
+
bootstrapConfigSignal
|
|
3481
|
+
});
|
|
3482
|
+
if (!bootstrapConfigSignal) {
|
|
3483
|
+
throw new Error(
|
|
3484
|
+
"The relay VM did not confirm that it applied the Aleph bootstrap config in time."
|
|
3485
|
+
);
|
|
3486
|
+
}
|
|
3439
3487
|
}
|
|
3440
3488
|
this.emitProgress({
|
|
3441
3489
|
stage: "publishing-bootstrap",
|
|
@@ -3726,16 +3774,11 @@ var SponsorRelayController = class {
|
|
|
3726
3774
|
this.refreshTimer = setInterval(() => {
|
|
3727
3775
|
void this.refresh();
|
|
3728
3776
|
}, REFRESH_INTERVAL_MS);
|
|
3729
|
-
this.pingTimer = setInterval(() => {
|
|
3730
|
-
void this.refreshRelayPing();
|
|
3731
|
-
}, RELAY_PING_INTERVAL_MS);
|
|
3732
|
-
await this.refreshRelayPing();
|
|
3733
3777
|
this.patch({ ready: true });
|
|
3734
3778
|
this.trace("init:ready");
|
|
3735
3779
|
}
|
|
3736
3780
|
destroy() {
|
|
3737
3781
|
if (this.refreshTimer) clearInterval(this.refreshTimer);
|
|
3738
|
-
if (this.pingTimer) clearInterval(this.pingTimer);
|
|
3739
3782
|
if (this.manifestRefreshTimer) clearTimeout(this.manifestRefreshTimer);
|
|
3740
3783
|
this.stopWalletWatch?.();
|
|
3741
3784
|
}
|
|
@@ -3991,11 +4034,6 @@ var SponsorRelayController = class {
|
|
|
3991
4034
|
});
|
|
3992
4035
|
}
|
|
3993
4036
|
}
|
|
3994
|
-
async refreshRelayPing() {
|
|
3995
|
-
const relayPing = await pingPeer(this.props.libp2p);
|
|
3996
|
-
this.patch({ relayPing });
|
|
3997
|
-
this.trace("libp2p:relay-ping", relayPing);
|
|
3998
|
-
}
|
|
3999
4037
|
async deploy() {
|
|
4000
4038
|
this.trace("deploy:start", {
|
|
4001
4039
|
wallet: this.state.wallet.address,
|
|
@@ -4467,10 +4505,9 @@ function useSponsorRelayController(props) {
|
|
|
4467
4505
|
);
|
|
4468
4506
|
useEffect(() => {
|
|
4469
4507
|
controller.updateProps({
|
|
4470
|
-
libp2p: props.libp2p,
|
|
4471
4508
|
debug: props.debug
|
|
4472
4509
|
});
|
|
4473
|
-
}, [controller, props.debug
|
|
4510
|
+
}, [controller, props.debug]);
|
|
4474
4511
|
useEffect(() => {
|
|
4475
4512
|
void controller.init();
|
|
4476
4513
|
return () => {
|
package/shared/index.d.ts
CHANGED
|
@@ -187,7 +187,6 @@ type DeploymentProgressListener = (event: DeploymentProgressEvent) => void;
|
|
|
187
187
|
|
|
188
188
|
type SponsorRelayHealthTone = 'ok' | 'caution' | 'error' | 'idle';
|
|
189
189
|
interface SponsorRelayProps {
|
|
190
|
-
libp2p?: unknown;
|
|
191
190
|
debug?: boolean;
|
|
192
191
|
manifestUrl?: string;
|
|
193
192
|
manifestJson?: string;
|
|
@@ -222,16 +221,6 @@ interface SponsorRelayRootfsHealth {
|
|
|
222
221
|
label: string;
|
|
223
222
|
detail: string | null;
|
|
224
223
|
}
|
|
225
|
-
interface RelayPingState {
|
|
226
|
-
tone: SponsorRelayHealthTone;
|
|
227
|
-
sent: boolean;
|
|
228
|
-
received: boolean;
|
|
229
|
-
lastPeerId: string | null;
|
|
230
|
-
lastLatencyMs: number | null;
|
|
231
|
-
lastSentAt: number | null;
|
|
232
|
-
lastReceivedAt: number | null;
|
|
233
|
-
error: string | null;
|
|
234
|
-
}
|
|
235
224
|
interface CompactInstanceDetails {
|
|
236
225
|
messageStatus: string;
|
|
237
226
|
allocationSource: string | null;
|
|
@@ -282,7 +271,6 @@ interface SponsorRelayState {
|
|
|
282
271
|
crns: Crn[];
|
|
283
272
|
selectedCrn: Crn | null;
|
|
284
273
|
instances: CompactInstanceRecord[];
|
|
285
|
-
relayPing: RelayPingState;
|
|
286
274
|
lastDeploymentHash: string | null;
|
|
287
275
|
deploymentProgress: DeploymentProgressEvent;
|
|
288
276
|
}
|
|
@@ -292,10 +280,8 @@ declare const DEFAULT_INSTANCE_NAME = "sponsor-relay";
|
|
|
292
280
|
declare const DEFAULT_MANIFEST_URL = "./rootfs-manifest.json";
|
|
293
281
|
declare const DEFAULT_TIER_ID = "tier-1";
|
|
294
282
|
declare const ROOTFS_MISSING_STATE: SponsorRelayRootfsHealth;
|
|
295
|
-
declare const RELAY_PING_IDLE_STATE: RelayPingState;
|
|
296
283
|
declare const IDLE_DEPLOYMENT_PROGRESS: DeploymentProgressEvent;
|
|
297
284
|
declare const REFRESH_INTERVAL_MS = 30000;
|
|
298
|
-
declare const RELAY_PING_INTERVAL_MS = 20000;
|
|
299
285
|
declare const MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS = 400;
|
|
300
286
|
declare const INSTANCE_RUNTIME_READY_REFRESH_MS = 30000;
|
|
301
287
|
declare const INSTANCE_RUNTIME_PENDING_REFRESH_MS = 45000;
|
|
@@ -304,7 +290,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
|
|
|
304
290
|
declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
|
|
305
291
|
declare const DEPLOYMENT_PENDING_WARNING_MS: number;
|
|
306
292
|
|
|
307
|
-
declare const UI_PACKAGE_VERSION = "0.3.
|
|
293
|
+
declare const UI_PACKAGE_VERSION = "0.3.25";
|
|
308
294
|
|
|
309
295
|
interface RootfsRequiredPortForward {
|
|
310
296
|
port: number;
|
|
@@ -345,7 +331,6 @@ declare class SponsorRelayController {
|
|
|
345
331
|
private subscribers;
|
|
346
332
|
private client;
|
|
347
333
|
private refreshTimer;
|
|
348
|
-
private pingTimer;
|
|
349
334
|
private manifestRefreshTimer;
|
|
350
335
|
private stopWalletWatch;
|
|
351
336
|
private props;
|
|
@@ -385,7 +370,6 @@ declare class SponsorRelayController {
|
|
|
385
370
|
connectWallet(): Promise<void>;
|
|
386
371
|
private refreshWalletDerivedState;
|
|
387
372
|
refresh(): Promise<void>;
|
|
388
|
-
refreshRelayPing(): Promise<void>;
|
|
389
373
|
deploy(): Promise<void>;
|
|
390
374
|
deleteInstance(instanceHash: string): Promise<void>;
|
|
391
375
|
}
|
|
@@ -398,4 +382,4 @@ interface DeploymentProgressEmitter {
|
|
|
398
382
|
}
|
|
399
383
|
declare function createDeploymentProgressEmitter(): DeploymentProgressEmitter;
|
|
400
384
|
|
|
401
|
-
export { type CompactInstanceDetails, type CompactInstanceRecord, DEFAULT_INSTANCE_NAME, DEFAULT_MANIFEST_URL, DEFAULT_TIER_ID, DEPLOYMENT_PENDING_WARNING_MS, type DeploymentProgressEmitter, type EthereumProviderLike, IDLE_DEPLOYMENT_PROGRESS, INSTANCE_RUNTIME_PENDING_REFRESH_MS, INSTANCE_RUNTIME_READY_REFRESH_MS, INSTANCE_RUNTIME_STALE_REFRESH_MS, MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS, RECENT_INSTANCE_RUNTIME_GRACE_MS, REFRESH_INTERVAL_MS,
|
|
385
|
+
export { type CompactInstanceDetails, type CompactInstanceRecord, DEFAULT_INSTANCE_NAME, DEFAULT_MANIFEST_URL, DEFAULT_TIER_ID, DEPLOYMENT_PENDING_WARNING_MS, type DeploymentProgressEmitter, type EthereumProviderLike, IDLE_DEPLOYMENT_PROGRESS, INSTANCE_RUNTIME_PENDING_REFRESH_MS, INSTANCE_RUNTIME_READY_REFRESH_MS, INSTANCE_RUNTIME_STALE_REFRESH_MS, MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS, RECENT_INSTANCE_RUNTIME_GRACE_MS, REFRESH_INTERVAL_MS, ROOTFS_MISSING_STATE, STALE_INSTANCE_ALLOCATION_COOLDOWN_MS, SponsorRelayController, type SponsorRelayHealthTone, type SponsorRelayPricingSummary, type SponsorRelayProps, type SponsorRelayRootfsHealth, type SponsorRelayState, type SponsorRelaySubscriber, type SponsorRelayWalletState, UI_PACKAGE_VERSION, buildSshCommand, connectWallet, createDeploymentProgressEmitter, createSponsorRelayController, formatDateTime, formatNumber, formatTierSpecLabel, getEthereumProvider, joinMappedPorts, joinRequiredPortForwards, personalSign, resolveManifestSource, shortHash, toChecksumAddress, watchWallet };
|
package/shared/index.js
CHANGED
|
@@ -7,16 +7,6 @@ var ROOTFS_MISSING_STATE = {
|
|
|
7
7
|
label: "manifest missing",
|
|
8
8
|
detail: "Provide a manifest URL or paste manifest JSON."
|
|
9
9
|
};
|
|
10
|
-
var RELAY_PING_IDLE_STATE = {
|
|
11
|
-
tone: "idle",
|
|
12
|
-
sent: false,
|
|
13
|
-
received: false,
|
|
14
|
-
lastPeerId: null,
|
|
15
|
-
lastLatencyMs: null,
|
|
16
|
-
lastSentAt: null,
|
|
17
|
-
lastReceivedAt: null,
|
|
18
|
-
error: null
|
|
19
|
-
};
|
|
20
10
|
var IDLE_DEPLOYMENT_PROGRESS = {
|
|
21
11
|
stage: "idle",
|
|
22
12
|
label: "Ready",
|
|
@@ -28,7 +18,6 @@ var IDLE_DEPLOYMENT_PROGRESS = {
|
|
|
28
18
|
timestamp: Date.now()
|
|
29
19
|
};
|
|
30
20
|
var REFRESH_INTERVAL_MS = 3e4;
|
|
31
|
-
var RELAY_PING_INTERVAL_MS = 2e4;
|
|
32
21
|
var MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS = 400;
|
|
33
22
|
var INSTANCE_RUNTIME_READY_REFRESH_MS = 3e4;
|
|
34
23
|
var INSTANCE_RUNTIME_PENDING_REFRESH_MS = 45e3;
|
|
@@ -38,7 +27,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
38
27
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
39
28
|
|
|
40
29
|
// src/shared/package-version.ts
|
|
41
|
-
var UI_PACKAGE_VERSION = "0.3.
|
|
30
|
+
var UI_PACKAGE_VERSION = "0.3.25";
|
|
42
31
|
|
|
43
32
|
// src/shared/format.ts
|
|
44
33
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -2683,6 +2672,16 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2683
2672
|
|
|
2684
2673
|
// ../core/src/bootstrap-config.ts
|
|
2685
2674
|
var VM_BOOTSTRAP_CONFIG_AGGREGATE_KEY = "vm-bootstrap-config";
|
|
2675
|
+
var VM_BOOTSTRAP_CONFIG_SIGNAL_REF = "vm-bootstrap-config";
|
|
2676
|
+
var VM_BOOTSTRAP_CONFIG_SIGNAL_POST_TYPE = "vm-bootstrap-config-status";
|
|
2677
|
+
function parseJsonObject(value) {
|
|
2678
|
+
try {
|
|
2679
|
+
const parsed = JSON.parse(value);
|
|
2680
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
2681
|
+
} catch {
|
|
2682
|
+
return null;
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2686
2685
|
async function fetchVmBootstrapConfigAggregate(address, options) {
|
|
2687
2686
|
const requestUrl = new URL(`/api/v0/aggregates/${address}.json`, options.apiHost ?? DEFAULT_ALEPH_API_HOST2);
|
|
2688
2687
|
requestUrl.searchParams.set("keys", VM_BOOTSTRAP_CONFIG_AGGREGATE_KEY);
|
|
@@ -2802,6 +2801,82 @@ async function deleteVmBootstrapConfig(args) {
|
|
|
2802
2801
|
aggregate: content
|
|
2803
2802
|
};
|
|
2804
2803
|
}
|
|
2804
|
+
function normalizeVmBootstrapConfigSignalRecord(value) {
|
|
2805
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
2806
|
+
const candidate = value;
|
|
2807
|
+
const deploymentToken = typeof candidate.deploymentToken === "string" ? candidate.deploymentToken.trim() : "";
|
|
2808
|
+
const status = typeof candidate.status === "string" ? candidate.status.trim() : "";
|
|
2809
|
+
const profile = typeof candidate.profile === "string" ? candidate.profile.trim() : "";
|
|
2810
|
+
const ownerAddress = typeof candidate.ownerAddress === "string" ? candidate.ownerAddress.trim() : "";
|
|
2811
|
+
const instanceItemHash = typeof candidate.instanceItemHash === "string" ? candidate.instanceItemHash.trim() : "";
|
|
2812
|
+
const updatedAt = typeof candidate.updatedAt === "string" ? candidate.updatedAt.trim() : "";
|
|
2813
|
+
if (!deploymentToken || !status || !profile || !ownerAddress || !instanceItemHash || !updatedAt) {
|
|
2814
|
+
return null;
|
|
2815
|
+
}
|
|
2816
|
+
return {
|
|
2817
|
+
deploymentToken,
|
|
2818
|
+
status,
|
|
2819
|
+
profile,
|
|
2820
|
+
ownerAddress,
|
|
2821
|
+
instanceItemHash,
|
|
2822
|
+
updatedAt,
|
|
2823
|
+
publisherAddress: typeof candidate.publisherAddress === "string" && candidate.publisherAddress.trim() ? candidate.publisherAddress.trim() : null,
|
|
2824
|
+
authorization: candidate.authorization
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
async function fetchVmBootstrapConfigSignals(args) {
|
|
2828
|
+
const requestUrl = new URL("/api/v0/posts.json", args.apiHost ?? DEFAULT_ALEPH_API_HOST2);
|
|
2829
|
+
requestUrl.searchParams.set("refs", args.ref ?? VM_BOOTSTRAP_CONFIG_SIGNAL_REF);
|
|
2830
|
+
requestUrl.searchParams.set("types", args.postType ?? VM_BOOTSTRAP_CONFIG_SIGNAL_POST_TYPE);
|
|
2831
|
+
requestUrl.searchParams.set("pagination", String(Math.max(1, Number(args.pagination ?? 100))));
|
|
2832
|
+
requestUrl.searchParams.set("page", String(Math.max(1, Number(args.page ?? 1))));
|
|
2833
|
+
requestUrl.searchParams.set("sortOrder", "-1");
|
|
2834
|
+
const response = await args.fetch(requestUrl.toString(), { cache: "no-cache" });
|
|
2835
|
+
if (!response.ok) {
|
|
2836
|
+
throw new Error(`VM bootstrap config signal request failed: ${response.status}`);
|
|
2837
|
+
}
|
|
2838
|
+
const payload = await response.json();
|
|
2839
|
+
const expectedDeploymentToken = args.deploymentToken?.trim() ?? "";
|
|
2840
|
+
const expectedOwnerAddress = args.ownerAddress?.trim().toLowerCase() ?? "";
|
|
2841
|
+
const expectedInstanceItemHash = args.instanceItemHash?.trim() ?? "";
|
|
2842
|
+
return (payload.posts ?? []).map((entry) => {
|
|
2843
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return null;
|
|
2844
|
+
const parsed = "content" in entry && entry.content && typeof entry.content === "object" && !Array.isArray(entry.content) ? entry.content : "item_content" in entry && typeof entry.item_content === "string" ? parseJsonObject(entry.item_content) : null;
|
|
2845
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
2846
|
+
const content = "deploymentToken" in parsed ? parsed : "content" in parsed && parsed.content && typeof parsed.content === "object" && !Array.isArray(parsed.content) ? parsed.content : null;
|
|
2847
|
+
if (!content || typeof content !== "object" || Array.isArray(content)) return null;
|
|
2848
|
+
return normalizeVmBootstrapConfigSignalRecord(content);
|
|
2849
|
+
}).filter((entry) => {
|
|
2850
|
+
if (!entry) return false;
|
|
2851
|
+
if (expectedDeploymentToken && entry.deploymentToken !== expectedDeploymentToken) return false;
|
|
2852
|
+
if (expectedOwnerAddress && entry.ownerAddress.toLowerCase() !== expectedOwnerAddress) return false;
|
|
2853
|
+
if (expectedInstanceItemHash && entry.instanceItemHash !== expectedInstanceItemHash) return false;
|
|
2854
|
+
return true;
|
|
2855
|
+
});
|
|
2856
|
+
}
|
|
2857
|
+
async function waitForVmBootstrapConfigSignal(args) {
|
|
2858
|
+
const attempts = Math.max(1, Number(args.attempts ?? 24));
|
|
2859
|
+
const delayMs = Math.max(0, Number(args.delayMs ?? 2500));
|
|
2860
|
+
const sleep2 = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2861
|
+
const expectedStatus = args.expectedStatus ?? "applied";
|
|
2862
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
2863
|
+
const signals = await fetchVmBootstrapConfigSignals({
|
|
2864
|
+
deploymentToken: args.deploymentToken,
|
|
2865
|
+
ownerAddress: args.ownerAddress,
|
|
2866
|
+
instanceItemHash: args.instanceItemHash,
|
|
2867
|
+
fetch: args.fetch,
|
|
2868
|
+
apiHost: args.apiHost,
|
|
2869
|
+
ref: args.ref,
|
|
2870
|
+
postType: args.postType
|
|
2871
|
+
}).catch(() => []);
|
|
2872
|
+
const match = signals.find((entry) => entry.status === expectedStatus) ?? null;
|
|
2873
|
+
if (match) return match;
|
|
2874
|
+
if (attempt < attempts - 1) {
|
|
2875
|
+
await sleep2(delayMs);
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
return null;
|
|
2879
|
+
}
|
|
2805
2880
|
|
|
2806
2881
|
// ../core/src/bootstrap-reconcile.ts
|
|
2807
2882
|
function createRelayBootstrapRegistrationId(profile, instanceName, itemHash) {
|
|
@@ -2940,7 +3015,6 @@ function defaultState(props = {}) {
|
|
|
2940
3015
|
crns: [],
|
|
2941
3016
|
selectedCrn: null,
|
|
2942
3017
|
instances: [],
|
|
2943
|
-
relayPing: RELAY_PING_IDLE_STATE,
|
|
2944
3018
|
lastDeploymentHash: null,
|
|
2945
3019
|
deploymentProgress: IDLE_DEPLOYMENT_PROGRESS
|
|
2946
3020
|
};
|
|
@@ -3153,57 +3227,6 @@ function compatibleCrnsForTier(crns, state) {
|
|
|
3153
3227
|
);
|
|
3154
3228
|
return filterDeployableCrns(crns, { spec });
|
|
3155
3229
|
}
|
|
3156
|
-
async function pingPeer(libp2p) {
|
|
3157
|
-
if (!libp2p || typeof libp2p !== "object") {
|
|
3158
|
-
return RELAY_PING_IDLE_STATE;
|
|
3159
|
-
}
|
|
3160
|
-
const candidate = libp2p;
|
|
3161
|
-
const peers = candidate.getPeers?.() ?? [];
|
|
3162
|
-
const firstPeer = peers[0];
|
|
3163
|
-
if (!firstPeer) {
|
|
3164
|
-
return {
|
|
3165
|
-
...RELAY_PING_IDLE_STATE,
|
|
3166
|
-
tone: "caution",
|
|
3167
|
-
error: "No connected relay peers available."
|
|
3168
|
-
};
|
|
3169
|
-
}
|
|
3170
|
-
const sentAt = Date.now();
|
|
3171
|
-
try {
|
|
3172
|
-
const pingFn = candidate.services?.ping?.ping?.bind(candidate.services.ping) ?? candidate.ping?.bind(candidate);
|
|
3173
|
-
if (!pingFn) {
|
|
3174
|
-
return {
|
|
3175
|
-
...RELAY_PING_IDLE_STATE,
|
|
3176
|
-
tone: "caution",
|
|
3177
|
-
sent: true,
|
|
3178
|
-
lastPeerId: String(firstPeer),
|
|
3179
|
-
lastSentAt: sentAt,
|
|
3180
|
-
error: "libp2p ping service not available."
|
|
3181
|
-
};
|
|
3182
|
-
}
|
|
3183
|
-
const latency = await pingFn(firstPeer);
|
|
3184
|
-
return {
|
|
3185
|
-
tone: "ok",
|
|
3186
|
-
sent: true,
|
|
3187
|
-
received: true,
|
|
3188
|
-
lastPeerId: String(firstPeer),
|
|
3189
|
-
lastLatencyMs: Number(latency),
|
|
3190
|
-
lastSentAt: sentAt,
|
|
3191
|
-
lastReceivedAt: Date.now(),
|
|
3192
|
-
error: null
|
|
3193
|
-
};
|
|
3194
|
-
} catch (error) {
|
|
3195
|
-
return {
|
|
3196
|
-
tone: "error",
|
|
3197
|
-
sent: true,
|
|
3198
|
-
received: false,
|
|
3199
|
-
lastPeerId: String(firstPeer),
|
|
3200
|
-
lastLatencyMs: null,
|
|
3201
|
-
lastSentAt: sentAt,
|
|
3202
|
-
lastReceivedAt: null,
|
|
3203
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3204
|
-
};
|
|
3205
|
-
}
|
|
3206
|
-
}
|
|
3207
3230
|
var UI_DEPLOY_WAIT_ATTEMPTS = 60;
|
|
3208
3231
|
var UI_DEPLOY_WAIT_DELAY_MS = 5e3;
|
|
3209
3232
|
var UI_RUNTIME_WAIT_ATTEMPTS = 40;
|
|
@@ -3234,7 +3257,6 @@ var SponsorRelayController = class {
|
|
|
3234
3257
|
subscribers = /* @__PURE__ */ new Set();
|
|
3235
3258
|
client;
|
|
3236
3259
|
refreshTimer = null;
|
|
3237
|
-
pingTimer = null;
|
|
3238
3260
|
manifestRefreshTimer = null;
|
|
3239
3261
|
stopWalletWatch = null;
|
|
3240
3262
|
props;
|
|
@@ -3290,8 +3312,7 @@ var SponsorRelayController = class {
|
|
|
3290
3312
|
...patch,
|
|
3291
3313
|
busy: patch.busy ? { ...this.state.busy, ...patch.busy } : this.state.busy,
|
|
3292
3314
|
wallet: patch.wallet ? { ...this.state.wallet, ...patch.wallet } : this.state.wallet,
|
|
3293
|
-
pricingSummary: patch.pricingSummary ? { ...this.state.pricingSummary, ...patch.pricingSummary } : this.state.pricingSummary
|
|
3294
|
-
relayPing: patch.relayPing ? { ...this.state.relayPing, ...patch.relayPing } : this.state.relayPing
|
|
3315
|
+
pricingSummary: patch.pricingSummary ? { ...this.state.pricingSummary, ...patch.pricingSummary } : this.state.pricingSummary
|
|
3295
3316
|
};
|
|
3296
3317
|
this.emit();
|
|
3297
3318
|
}
|
|
@@ -3435,6 +3456,33 @@ var SponsorRelayController = class {
|
|
|
3435
3456
|
aggregateItemHash: bootstrapConfigPublication.aggregateItemHash,
|
|
3436
3457
|
aggregateStatus: bootstrapConfigPublication.aggregateStatus
|
|
3437
3458
|
});
|
|
3459
|
+
this.emitProgress({
|
|
3460
|
+
stage: "deployment-confirmed",
|
|
3461
|
+
label: "Waiting for guest config",
|
|
3462
|
+
progress: 94,
|
|
3463
|
+
status: "info",
|
|
3464
|
+
itemHash: args.itemHash,
|
|
3465
|
+
detail: "Waiting for the relay VM to acknowledge that it consumed the Aleph bootstrap config."
|
|
3466
|
+
});
|
|
3467
|
+
const bootstrapConfigSignal = await waitForVmBootstrapConfigSignal({
|
|
3468
|
+
deploymentToken: args.deploymentToken,
|
|
3469
|
+
ownerAddress: this.state.wallet.address,
|
|
3470
|
+
instanceItemHash: args.itemHash,
|
|
3471
|
+
fetch: asJsonFetch,
|
|
3472
|
+
apiHost: this.client.apiHost,
|
|
3473
|
+
attempts: 40,
|
|
3474
|
+
delayMs: 3e3
|
|
3475
|
+
});
|
|
3476
|
+
this.trace("deploy:bootstrap-config-signal-visible", {
|
|
3477
|
+
itemHash: args.itemHash,
|
|
3478
|
+
deploymentToken: args.deploymentToken,
|
|
3479
|
+
bootstrapConfigSignal
|
|
3480
|
+
});
|
|
3481
|
+
if (!bootstrapConfigSignal) {
|
|
3482
|
+
throw new Error(
|
|
3483
|
+
"The relay VM did not confirm that it applied the Aleph bootstrap config in time."
|
|
3484
|
+
);
|
|
3485
|
+
}
|
|
3438
3486
|
}
|
|
3439
3487
|
this.emitProgress({
|
|
3440
3488
|
stage: "publishing-bootstrap",
|
|
@@ -3725,16 +3773,11 @@ var SponsorRelayController = class {
|
|
|
3725
3773
|
this.refreshTimer = setInterval(() => {
|
|
3726
3774
|
void this.refresh();
|
|
3727
3775
|
}, REFRESH_INTERVAL_MS);
|
|
3728
|
-
this.pingTimer = setInterval(() => {
|
|
3729
|
-
void this.refreshRelayPing();
|
|
3730
|
-
}, RELAY_PING_INTERVAL_MS);
|
|
3731
|
-
await this.refreshRelayPing();
|
|
3732
3776
|
this.patch({ ready: true });
|
|
3733
3777
|
this.trace("init:ready");
|
|
3734
3778
|
}
|
|
3735
3779
|
destroy() {
|
|
3736
3780
|
if (this.refreshTimer) clearInterval(this.refreshTimer);
|
|
3737
|
-
if (this.pingTimer) clearInterval(this.pingTimer);
|
|
3738
3781
|
if (this.manifestRefreshTimer) clearTimeout(this.manifestRefreshTimer);
|
|
3739
3782
|
this.stopWalletWatch?.();
|
|
3740
3783
|
}
|
|
@@ -3990,11 +4033,6 @@ var SponsorRelayController = class {
|
|
|
3990
4033
|
});
|
|
3991
4034
|
}
|
|
3992
4035
|
}
|
|
3993
|
-
async refreshRelayPing() {
|
|
3994
|
-
const relayPing = await pingPeer(this.props.libp2p);
|
|
3995
|
-
this.patch({ relayPing });
|
|
3996
|
-
this.trace("libp2p:relay-ping", relayPing);
|
|
3997
|
-
}
|
|
3998
4036
|
async deploy() {
|
|
3999
4037
|
this.trace("deploy:start", {
|
|
4000
4038
|
wallet: this.state.wallet.address,
|
|
@@ -4456,8 +4494,6 @@ export {
|
|
|
4456
4494
|
MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS,
|
|
4457
4495
|
RECENT_INSTANCE_RUNTIME_GRACE_MS,
|
|
4458
4496
|
REFRESH_INTERVAL_MS,
|
|
4459
|
-
RELAY_PING_IDLE_STATE,
|
|
4460
|
-
RELAY_PING_INTERVAL_MS,
|
|
4461
4497
|
ROOTFS_MISSING_STATE,
|
|
4462
4498
|
STALE_INSTANCE_ALLOCATION_COOLDOWN_MS,
|
|
4463
4499
|
SponsorRelayController,
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
import StatusLed from './components/StatusLed.svelte'
|
|
9
9
|
import './styles/theme.css'
|
|
10
10
|
|
|
11
|
-
export let libp2p = null
|
|
12
11
|
export let manifestUrl = './rootfs-manifest.json'
|
|
13
12
|
export let manifestJson = ''
|
|
14
13
|
export let sshPublicKey = ''
|
|
@@ -23,7 +22,6 @@ export let apiHost = undefined
|
|
|
23
22
|
export let twoN6ApiHost = undefined
|
|
24
23
|
|
|
25
24
|
const controller = createSponsorRelayController({
|
|
26
|
-
libp2p,
|
|
27
25
|
manifestUrl,
|
|
28
26
|
manifestJson,
|
|
29
27
|
sshPublicKey,
|
|
@@ -106,17 +104,6 @@ export let apiHost = undefined
|
|
|
106
104
|
</div>
|
|
107
105
|
</div>
|
|
108
106
|
|
|
109
|
-
<div class="ping-strip">
|
|
110
|
-
<div>
|
|
111
|
-
<span class="mini-label">relay ping sent</span>
|
|
112
|
-
<div class="mini-row"><StatusLed tone={state.relayPing.sent ? 'caution' : state.relayPing.tone} pulse={state.relayPing.sent} /><strong>{state.relayPing.sent ? 'sent' : 'idle'}</strong></div>
|
|
113
|
-
</div>
|
|
114
|
-
<div>
|
|
115
|
-
<span class="mini-label">relay pong received</span>
|
|
116
|
-
<div class="mini-row"><StatusLed tone={state.relayPing.received ? 'ok' : state.relayPing.tone} pulse={state.relayPing.received} /><strong>{state.relayPing.received ? `${formatNumber(state.relayPing.lastLatencyMs, 0)} ms` : 'waiting'}</strong></div>
|
|
117
|
-
</div>
|
|
118
|
-
</div>
|
|
119
|
-
|
|
120
107
|
{#if state.errorText}
|
|
121
108
|
<p class="alert error">{state.errorText}</p>
|
|
122
109
|
{/if}
|
|
@@ -327,7 +314,6 @@ export let apiHost = undefined
|
|
|
327
314
|
|
|
328
315
|
.panel-head,
|
|
329
316
|
.status-strip,
|
|
330
|
-
.ping-strip,
|
|
331
317
|
.actions,
|
|
332
318
|
.section-head,
|
|
333
319
|
.instance-topline,
|
|
@@ -364,7 +350,6 @@ export let apiHost = undefined
|
|
|
364
350
|
}
|
|
365
351
|
|
|
366
352
|
.eyebrow,
|
|
367
|
-
.mini-label,
|
|
368
353
|
.field span,
|
|
369
354
|
.metric-card span,
|
|
370
355
|
.mono-block span,
|
|
@@ -440,19 +425,6 @@ export let apiHost = undefined
|
|
|
440
425
|
gap: 0.7rem;
|
|
441
426
|
}
|
|
442
427
|
|
|
443
|
-
.ping-strip {
|
|
444
|
-
margin-top: 0.9rem;
|
|
445
|
-
padding: 0.85rem;
|
|
446
|
-
border-radius: 1rem;
|
|
447
|
-
background: rgba(1, 118, 206, 0.08);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
.mini-row {
|
|
451
|
-
display: flex;
|
|
452
|
-
gap: 0.5rem;
|
|
453
|
-
align-items: center;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
428
|
.alert {
|
|
457
429
|
margin: 0.8rem 0 0;
|
|
458
430
|
padding: 0.75rem 0.85rem;
|