@le-space/ui 0.7.0 → 0.9.0
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 +62 -0
- package/react/index.js +907 -165
- package/shared/index.d.ts +72 -2
- package/shared/index.js +477 -41
- package/styles.css +6 -0
- package/svelte/SponsorRelayFab.svelte +286 -0
- package/svelte/styles/theme.css +6 -0
package/react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/react/SponsorRelayFab.tsx
|
|
2
|
-
import
|
|
2
|
+
import React2 from "react";
|
|
3
3
|
|
|
4
4
|
// src/shared/constants.ts
|
|
5
5
|
var DEFAULT_INSTANCE_NAME = "sponsor-relay";
|
|
@@ -43,7 +43,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
43
43
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
44
44
|
|
|
45
45
|
// src/shared/package-version.ts
|
|
46
|
-
var UI_PACKAGE_VERSION = "0.
|
|
46
|
+
var UI_PACKAGE_VERSION = "0.9.0";
|
|
47
47
|
|
|
48
48
|
// src/shared/format.ts
|
|
49
49
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -141,6 +141,8 @@ var DEFAULT_ALEPH_API_HOSTS = [
|
|
|
141
141
|
];
|
|
142
142
|
var DEFAULT_ALEPH_API_HOST = DEFAULT_ALEPH_API_HOSTS[0] ?? "https://api2.aleph.im";
|
|
143
143
|
var DEFAULT_CRN_LIST_URL = "https://crns-list.aleph.sh/crns.json";
|
|
144
|
+
var DEFAULT_CRN_AGGREGATE_ADDRESS = "0xa1B3bb7d2332383D96b7796B908fB7f7F3c2Be10";
|
|
145
|
+
var DEFAULT_CRN_AGGREGATE_KEY = "corechannel";
|
|
144
146
|
var DEFAULT_ALEPH_SCHEDULER_API_HOST = "https://scheduler.api.aleph.cloud";
|
|
145
147
|
var DEFAULT_2N6_API_HOST = "https://api.2n6.me";
|
|
146
148
|
function normalizeMessageStatus(status) {
|
|
@@ -195,7 +197,7 @@ async function fetchBalance(address, apiHost = DEFAULT_ALEPH_API_HOST) {
|
|
|
195
197
|
if (!response.ok) throw new Error(`Balance request failed: ${response.status}`);
|
|
196
198
|
return await response.json();
|
|
197
199
|
}
|
|
198
|
-
async function
|
|
200
|
+
async function fetchCrnsFromList(url = DEFAULT_CRN_LIST_URL) {
|
|
199
201
|
const requestUrl = new URL(url);
|
|
200
202
|
requestUrl.searchParams.set("filter_inactive", "true");
|
|
201
203
|
const response = await fetchWithTimeout(requestUrl, { cache: "no-cache" });
|
|
@@ -203,6 +205,130 @@ async function fetchCrns(url = DEFAULT_CRN_LIST_URL) {
|
|
|
203
205
|
const payload = await response.json();
|
|
204
206
|
return payload.crns ?? [];
|
|
205
207
|
}
|
|
208
|
+
function asFiniteNumber(value) {
|
|
209
|
+
if (value == null || value === "") return null;
|
|
210
|
+
const numeric = typeof value === "number" ? value : Number(value);
|
|
211
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
212
|
+
}
|
|
213
|
+
function normalizeCrnAddress(value) {
|
|
214
|
+
const address = asString(value);
|
|
215
|
+
if (!address) return null;
|
|
216
|
+
const withScheme = /^https?:\/\//i.test(address) ? address : `https://${address}`;
|
|
217
|
+
try {
|
|
218
|
+
return new URL(withScheme).toString().replace(/\/+$/, "");
|
|
219
|
+
} catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function mapResourceNodesToCrns(resourceNodes) {
|
|
224
|
+
if (!Array.isArray(resourceNodes)) return [];
|
|
225
|
+
const crns = [];
|
|
226
|
+
for (const node of resourceNodes) {
|
|
227
|
+
if (!node || typeof node !== "object") continue;
|
|
228
|
+
const entry = node;
|
|
229
|
+
const hash = asString(entry.hash);
|
|
230
|
+
const address = normalizeCrnAddress(entry.address);
|
|
231
|
+
const type = asString(entry.type)?.toLowerCase();
|
|
232
|
+
const status = asString(entry.status)?.toLowerCase();
|
|
233
|
+
if (!hash || !address) continue;
|
|
234
|
+
if (entry.inactive_since != null || entry.locked === true) continue;
|
|
235
|
+
if (type && type !== "compute") continue;
|
|
236
|
+
if (status && status !== "linked" && status !== "active") continue;
|
|
237
|
+
if (!asString(entry.parent)) continue;
|
|
238
|
+
const score = asFiniteNumber(entry.score) ?? asFiniteNumber(entry.scoreV1);
|
|
239
|
+
const performance = asFiniteNumber(entry.performance);
|
|
240
|
+
const decentralization = asFiniteNumber(entry.decentralization);
|
|
241
|
+
crns.push({
|
|
242
|
+
hash,
|
|
243
|
+
address,
|
|
244
|
+
name: asString(entry.name) ?? hash,
|
|
245
|
+
...score == null ? {} : { score },
|
|
246
|
+
...performance == null ? {} : { performance },
|
|
247
|
+
...decentralization == null ? {} : { decentralization }
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return crns;
|
|
251
|
+
}
|
|
252
|
+
async function fetchCrnsFromAggregate(apiHosts = DEFAULT_ALEPH_API_HOSTS, address = DEFAULT_CRN_AGGREGATE_ADDRESS) {
|
|
253
|
+
const hosts = apiHosts.length > 0 ? apiHosts : DEFAULT_ALEPH_API_HOSTS;
|
|
254
|
+
let lastError = null;
|
|
255
|
+
for (const apiHost of hosts) {
|
|
256
|
+
try {
|
|
257
|
+
const url = new URL(`/api/v0/aggregates/${address}.json`, apiHost);
|
|
258
|
+
url.searchParams.set("keys", DEFAULT_CRN_AGGREGATE_KEY);
|
|
259
|
+
const response = await fetchWithTimeout(url, { cache: "no-cache" });
|
|
260
|
+
if (!response.ok) {
|
|
261
|
+
lastError = new Error(`CRN aggregate request failed: ${response.status}`);
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
const payload = await response.json();
|
|
265
|
+
const crns = mapResourceNodesToCrns(payload?.data?.corechannel?.resource_nodes);
|
|
266
|
+
if (crns.length > 0) return crns;
|
|
267
|
+
lastError = new Error("CRN aggregate contained no deployable resource nodes");
|
|
268
|
+
} catch (error) {
|
|
269
|
+
lastError = error;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError ?? "CRN aggregate request failed"));
|
|
273
|
+
}
|
|
274
|
+
async function fetchCrnsWithSource(url = DEFAULT_CRN_LIST_URL, options = {}) {
|
|
275
|
+
const apiHosts = options.apiHosts ?? DEFAULT_ALEPH_API_HOSTS;
|
|
276
|
+
const source = options.source ?? "auto";
|
|
277
|
+
if (source === "aggregate") {
|
|
278
|
+
return {
|
|
279
|
+
crns: await fetchCrnsFromAggregate(apiHosts, options.aggregateAddress),
|
|
280
|
+
source: "aggregate"
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
let listError;
|
|
284
|
+
try {
|
|
285
|
+
const crns = await fetchCrnsFromList(url);
|
|
286
|
+
if (crns.length > 0) return { crns, source: "list" };
|
|
287
|
+
listError = new Error("CRN list returned no entries");
|
|
288
|
+
} catch (error) {
|
|
289
|
+
listError = error instanceof Error ? error : new Error(String(error));
|
|
290
|
+
}
|
|
291
|
+
if (source === "list") throw listError;
|
|
292
|
+
return {
|
|
293
|
+
crns: await fetchCrnsFromAggregate(apiHosts, options.aggregateAddress),
|
|
294
|
+
source: "aggregate",
|
|
295
|
+
listError
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
async function fetchCrns(url = DEFAULT_CRN_LIST_URL, options = {}) {
|
|
299
|
+
return (await fetchCrnsWithSource(url, options)).crns;
|
|
300
|
+
}
|
|
301
|
+
async function probeCrnAvailability(crn) {
|
|
302
|
+
const address = String(crn.address ?? "").trim();
|
|
303
|
+
if (!address) return "unreachable";
|
|
304
|
+
const lookup = await fetchCrnExecutionMap(address);
|
|
305
|
+
if (lookup.payload !== null) return "reachable";
|
|
306
|
+
return lookup.blocked ? "unknown" : "unreachable";
|
|
307
|
+
}
|
|
308
|
+
async function filterReachableCrns(crns, options = {}) {
|
|
309
|
+
const limit = Math.max(1, Number(options.limit) || 5);
|
|
310
|
+
const probed = crns.slice(0, limit);
|
|
311
|
+
if (probed.length === 0) return [...crns];
|
|
312
|
+
const verdicts = await Promise.all(
|
|
313
|
+
probed.map(async (crn) => {
|
|
314
|
+
try {
|
|
315
|
+
return { crn, verdict: await probeCrnAvailability(crn) };
|
|
316
|
+
} catch {
|
|
317
|
+
return { crn, verdict: "unknown" };
|
|
318
|
+
}
|
|
319
|
+
})
|
|
320
|
+
);
|
|
321
|
+
const kept = verdicts.filter((entry) => entry.verdict !== "unreachable").map((entry) => entry.crn);
|
|
322
|
+
if (kept.length === 0) {
|
|
323
|
+
options.onDiagnostic?.(`No CRN answered its executions endpoint (${probed.length} probed); keeping the unverified order`);
|
|
324
|
+
return [...crns];
|
|
325
|
+
}
|
|
326
|
+
const dropped = probed.length - kept.length;
|
|
327
|
+
if (dropped > 0) {
|
|
328
|
+
options.onDiagnostic?.(`Skipping ${dropped} unreachable CRN${dropped === 1 ? "" : "s"} of ${probed.length} probed`);
|
|
329
|
+
}
|
|
330
|
+
return [...kept, ...crns.slice(limit)];
|
|
331
|
+
}
|
|
206
332
|
async function fetchInstances(address, apiHost = DEFAULT_ALEPH_API_HOST) {
|
|
207
333
|
const url = new URL("/api/v0/messages.json", apiHost);
|
|
208
334
|
url.searchParams.set("msgTypes", "INSTANCE");
|
|
@@ -857,18 +983,23 @@ function createAlephBrowserClient(options = {}) {
|
|
|
857
983
|
const apiHosts = options.apiHosts === void 0 && options.apiHost === void 0 ? [...DEFAULT_ALEPH_API_HOSTS] : normalizeApiHosts(options.apiHosts, options.apiHost ?? DEFAULT_ALEPH_API_HOST);
|
|
858
984
|
const apiHost = apiHosts[0] ?? DEFAULT_ALEPH_API_HOST;
|
|
859
985
|
const crnListUrl = options.crnListUrl ?? DEFAULT_CRN_LIST_URL;
|
|
986
|
+
const crnSource = options.crnSource ?? "auto";
|
|
860
987
|
const schedulerApiHost = options.schedulerApiHost ?? DEFAULT_ALEPH_SCHEDULER_API_HOST;
|
|
861
988
|
const twoN6ApiHost = options.twoN6ApiHost ?? DEFAULT_2N6_API_HOST;
|
|
862
989
|
return {
|
|
863
990
|
apiHost,
|
|
864
991
|
apiHosts,
|
|
865
992
|
crnListUrl,
|
|
993
|
+
crnSource,
|
|
866
994
|
schedulerApiHost,
|
|
867
995
|
fetchBalance(address) {
|
|
868
996
|
return withApiHostFallback(apiHosts, (host) => fetchBalance(address, host));
|
|
869
997
|
},
|
|
870
998
|
fetchCrns() {
|
|
871
|
-
return fetchCrns(crnListUrl);
|
|
999
|
+
return fetchCrns(crnListUrl, { apiHosts, source: crnSource });
|
|
1000
|
+
},
|
|
1001
|
+
fetchCrnsWithSource(source) {
|
|
1002
|
+
return fetchCrnsWithSource(crnListUrl, { apiHosts, source: source ?? crnSource });
|
|
872
1003
|
},
|
|
873
1004
|
fetchInstances(address) {
|
|
874
1005
|
return withApiHostFallback(apiHosts, (host) => fetchInstances(address, host));
|
|
@@ -943,6 +1074,15 @@ var DEFAULT_ALEPH_API_HOST2 = "https://api.aleph.im";
|
|
|
943
1074
|
|
|
944
1075
|
// ../core/src/crns.ts
|
|
945
1076
|
var DEFAULT_CRN_LIST_URL2 = "https://crns-list.aleph.sh/crns.json";
|
|
1077
|
+
var DEFAULT_CRN_AGGREGATE_ADDRESS2 = "0xa1B3bb7d2332383D96b7796B908fB7f7F3c2Be10";
|
|
1078
|
+
var DEFAULT_CRN_AGGREGATE_KEY2 = "corechannel";
|
|
1079
|
+
var DEFAULT_CRN_AGGREGATE_API_HOSTS = [
|
|
1080
|
+
"https://api2.aleph.im",
|
|
1081
|
+
"https://api.aleph.im"
|
|
1082
|
+
];
|
|
1083
|
+
function asString2(value) {
|
|
1084
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
1085
|
+
}
|
|
946
1086
|
function compatibleCrns(crns, excludedHashes = []) {
|
|
947
1087
|
const excluded = new Set(excludedHashes.filter(Boolean));
|
|
948
1088
|
return [...crns].filter((crn) => {
|
|
@@ -976,7 +1116,7 @@ function filterDeployableCrns(crns, options = {}) {
|
|
|
976
1116
|
compatibleCrns(crns, options.excludedHashes).filter((crn) => hasCrnCapacity(crn, options.spec))
|
|
977
1117
|
);
|
|
978
1118
|
}
|
|
979
|
-
async function
|
|
1119
|
+
async function fetchCrnsFromList2(options) {
|
|
980
1120
|
const requestUrl = new URL(options.url ?? DEFAULT_CRN_LIST_URL2);
|
|
981
1121
|
requestUrl.searchParams.set("filter_inactive", "true");
|
|
982
1122
|
const response = await options.fetch(requestUrl.toString(), {
|
|
@@ -988,6 +1128,101 @@ async function fetchCrns2(options) {
|
|
|
988
1128
|
const payload = await response.json();
|
|
989
1129
|
return Array.isArray(payload?.crns) ? payload.crns : [];
|
|
990
1130
|
}
|
|
1131
|
+
function normalizeCrnAddress2(value) {
|
|
1132
|
+
const address = asString2(value);
|
|
1133
|
+
if (!address) return null;
|
|
1134
|
+
const withScheme = /^https?:\/\//i.test(address) ? address : `https://${address}`;
|
|
1135
|
+
try {
|
|
1136
|
+
return new URL(withScheme).toString().replace(/\/+$/, "");
|
|
1137
|
+
} catch {
|
|
1138
|
+
return null;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
function aggregateScore(node) {
|
|
1142
|
+
for (const candidate of [node.score, node.scoreV1]) {
|
|
1143
|
+
if (candidate == null || candidate === "") continue;
|
|
1144
|
+
const numeric = typeof candidate === "number" ? candidate : Number(candidate);
|
|
1145
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
1146
|
+
}
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
function isDeployableResourceNode(node) {
|
|
1150
|
+
if (!asString2(node.hash)) return false;
|
|
1151
|
+
if (!normalizeCrnAddress2(node.address)) return false;
|
|
1152
|
+
if (node.inactive_since != null) return false;
|
|
1153
|
+
if (node.locked === true) return false;
|
|
1154
|
+
const type = asString2(node.type)?.toLowerCase();
|
|
1155
|
+
if (type && type !== "compute") return false;
|
|
1156
|
+
const status = asString2(node.status)?.toLowerCase();
|
|
1157
|
+
if (status && status !== "linked" && status !== "active") return false;
|
|
1158
|
+
return Boolean(asString2(node.parent));
|
|
1159
|
+
}
|
|
1160
|
+
function mapResourceNodesToCrns2(resourceNodes) {
|
|
1161
|
+
if (!Array.isArray(resourceNodes)) return [];
|
|
1162
|
+
return resourceNodes.filter((node) => Boolean(node) && typeof node === "object").filter(isDeployableResourceNode).map((node) => {
|
|
1163
|
+
const record = {
|
|
1164
|
+
hash: asString2(node.hash),
|
|
1165
|
+
address: normalizeCrnAddress2(node.address)
|
|
1166
|
+
};
|
|
1167
|
+
const name = asString2(node.name);
|
|
1168
|
+
if (name) record.name = name;
|
|
1169
|
+
const score = aggregateScore(node);
|
|
1170
|
+
if (score != null) record.score = score;
|
|
1171
|
+
return record;
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
async function fetchCrnsFromAggregate2(options) {
|
|
1175
|
+
const apiHosts = options.apiHosts?.length ? options.apiHosts : DEFAULT_CRN_AGGREGATE_API_HOSTS;
|
|
1176
|
+
const address = options.address ?? DEFAULT_CRN_AGGREGATE_ADDRESS2;
|
|
1177
|
+
const aggregateKey = options.aggregateKey ?? DEFAULT_CRN_AGGREGATE_KEY2;
|
|
1178
|
+
let lastError = null;
|
|
1179
|
+
for (const apiHost of apiHosts) {
|
|
1180
|
+
try {
|
|
1181
|
+
const url = new URL(`/api/v0/aggregates/${address}.json`, apiHost);
|
|
1182
|
+
url.searchParams.set("keys", aggregateKey);
|
|
1183
|
+
const response = await options.fetch(url.toString(), { cache: "no-cache" });
|
|
1184
|
+
if (!response.ok) {
|
|
1185
|
+
lastError = new Error(`CRN aggregate request failed: ${response.status}`);
|
|
1186
|
+
continue;
|
|
1187
|
+
}
|
|
1188
|
+
const payload = await response.json();
|
|
1189
|
+
const crns = mapResourceNodesToCrns2(payload?.data?.corechannel?.resource_nodes);
|
|
1190
|
+
if (crns.length > 0) return crns;
|
|
1191
|
+
lastError = new Error("CRN aggregate contained no deployable resource nodes");
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
lastError = error;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError ?? "CRN aggregate request failed"));
|
|
1197
|
+
}
|
|
1198
|
+
async function fetchCrnsWithSource2(options) {
|
|
1199
|
+
const aggregateOptions = {
|
|
1200
|
+
fetch: options.fetch,
|
|
1201
|
+
apiHosts: options.aggregateApiHosts,
|
|
1202
|
+
address: options.aggregateAddress
|
|
1203
|
+
};
|
|
1204
|
+
if (options.preferAggregate) {
|
|
1205
|
+
return { crns: await fetchCrnsFromAggregate2(aggregateOptions), source: "aggregate" };
|
|
1206
|
+
}
|
|
1207
|
+
let listError;
|
|
1208
|
+
try {
|
|
1209
|
+
const crns = await fetchCrnsFromList2({ url: options.url, fetch: options.fetch });
|
|
1210
|
+
if (crns.length > 0) return { crns, source: "list" };
|
|
1211
|
+
listError = new Error("CRN list returned no entries");
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
listError = error instanceof Error ? error : new Error(String(error));
|
|
1214
|
+
}
|
|
1215
|
+
options.onDiagnostic?.(`CRN list unavailable (${listError.message}); falling back to the ${DEFAULT_CRN_AGGREGATE_KEY2} aggregate`);
|
|
1216
|
+
try {
|
|
1217
|
+
return { crns: await fetchCrnsFromAggregate2(aggregateOptions), source: "aggregate", listError };
|
|
1218
|
+
} catch (aggregateError) {
|
|
1219
|
+
const message = aggregateError instanceof Error ? aggregateError.message : String(aggregateError);
|
|
1220
|
+
throw new Error(`${listError.message}; CRN aggregate fallback failed: ${message}`);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
async function fetchCrns2(options) {
|
|
1224
|
+
return (await fetchCrnsWithSource2(options)).crns;
|
|
1225
|
+
}
|
|
991
1226
|
|
|
992
1227
|
// ../core/src/port-forwarding.ts
|
|
993
1228
|
var DEFAULT_INSTANCE_PORT_FORWARDS = [
|
|
@@ -1077,7 +1312,7 @@ async function fetchPortForwardAggregate(address, options) {
|
|
|
1077
1312
|
}
|
|
1078
1313
|
|
|
1079
1314
|
// ../core/src/aleph-normalizers.ts
|
|
1080
|
-
function
|
|
1315
|
+
function asString3(value) {
|
|
1081
1316
|
return typeof value === "string" && value.trim() ? value : null;
|
|
1082
1317
|
}
|
|
1083
1318
|
function asNumber2(value) {
|
|
@@ -1092,7 +1327,7 @@ function normalizeMessageStatus2(status) {
|
|
|
1092
1327
|
return "unknown";
|
|
1093
1328
|
}
|
|
1094
1329
|
function normalizeProxyUrl2(value) {
|
|
1095
|
-
const stringValue =
|
|
1330
|
+
const stringValue = asString3(value);
|
|
1096
1331
|
if (!stringValue) return null;
|
|
1097
1332
|
if (/^https?:\/\//i.test(stringValue)) return stringValue;
|
|
1098
1333
|
return `https://${stringValue}`;
|
|
@@ -1187,22 +1422,22 @@ function normalizeExecution2(item, crnUrl) {
|
|
|
1187
1422
|
version: "v2",
|
|
1188
1423
|
running: typeof v2Item.running === "boolean" ? v2Item.running : void 0,
|
|
1189
1424
|
networking: {
|
|
1190
|
-
ipv4_network:
|
|
1191
|
-
host_ipv4:
|
|
1192
|
-
ipv6_network:
|
|
1193
|
-
ipv6_ip:
|
|
1194
|
-
ipv4_ip:
|
|
1425
|
+
ipv4_network: asString3(networking.ipv4_network),
|
|
1426
|
+
host_ipv4: asString3(networking.host_ipv4),
|
|
1427
|
+
ipv6_network: asString3(networking.ipv6_network),
|
|
1428
|
+
ipv6_ip: asString3(networking.ipv6_ip),
|
|
1429
|
+
ipv4_ip: asString3(networking.ipv4_ip),
|
|
1195
1430
|
proxy_url: extractProxyUrl2(v2Item, networking),
|
|
1196
1431
|
mapped_ports: mappedPorts2
|
|
1197
1432
|
},
|
|
1198
1433
|
status: v2Item.status ? {
|
|
1199
|
-
defined_at:
|
|
1200
|
-
preparing_at:
|
|
1201
|
-
prepared_at:
|
|
1202
|
-
starting_at:
|
|
1203
|
-
started_at:
|
|
1204
|
-
stopping_at:
|
|
1205
|
-
stopped_at:
|
|
1434
|
+
defined_at: asString3(v2Item.status.defined_at),
|
|
1435
|
+
preparing_at: asString3(v2Item.status.preparing_at),
|
|
1436
|
+
prepared_at: asString3(v2Item.status.prepared_at),
|
|
1437
|
+
starting_at: asString3(v2Item.status.starting_at),
|
|
1438
|
+
started_at: asString3(v2Item.status.started_at),
|
|
1439
|
+
stopping_at: asString3(v2Item.status.stopping_at),
|
|
1440
|
+
stopped_at: asString3(v2Item.status.stopped_at)
|
|
1206
1441
|
} : null
|
|
1207
1442
|
};
|
|
1208
1443
|
}
|
|
@@ -1210,8 +1445,8 @@ function normalizeExecution2(item, crnUrl) {
|
|
|
1210
1445
|
crnUrl,
|
|
1211
1446
|
version: "v1",
|
|
1212
1447
|
networking: {
|
|
1213
|
-
ipv4: networking && "ipv4" in networking ?
|
|
1214
|
-
ipv6: networking && "ipv6" in networking ?
|
|
1448
|
+
ipv4: networking && "ipv4" in networking ? asString3(networking.ipv4) : null,
|
|
1449
|
+
ipv6: networking && "ipv6" in networking ? asString3(networking.ipv6) : null
|
|
1215
1450
|
},
|
|
1216
1451
|
status: null
|
|
1217
1452
|
};
|
|
@@ -1373,7 +1608,7 @@ async function broadcastAlephMessage2(message, options) {
|
|
|
1373
1608
|
// ../core/src/runtime.ts
|
|
1374
1609
|
var DEFAULT_SCHEDULER_ALLOCATION_URL = "https://scheduler.api.aleph.cloud/api/v0/allocation";
|
|
1375
1610
|
var DEFAULT_TWO_N_SIX_HASH_URL = "https://api.2n6.me/api/hash";
|
|
1376
|
-
function
|
|
1611
|
+
function asString4(value) {
|
|
1377
1612
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
1378
1613
|
}
|
|
1379
1614
|
function asNumber3(value) {
|
|
@@ -1415,17 +1650,17 @@ async function fetchSchedulerAllocation2(itemHash, options) {
|
|
|
1415
1650
|
const node = payload?.node;
|
|
1416
1651
|
return {
|
|
1417
1652
|
source: "scheduler",
|
|
1418
|
-
crnHash:
|
|
1419
|
-
crnUrl:
|
|
1653
|
+
crnHash: asString4(node?.node_id),
|
|
1654
|
+
crnUrl: asString4(node?.url),
|
|
1420
1655
|
node: node ? {
|
|
1421
|
-
node_id:
|
|
1422
|
-
url:
|
|
1423
|
-
ipv6:
|
|
1656
|
+
node_id: asString4(node.node_id) ?? void 0,
|
|
1657
|
+
url: asString4(node.url) ?? void 0,
|
|
1658
|
+
ipv6: asString4(node.ipv6),
|
|
1424
1659
|
supports_ipv6: typeof node.supports_ipv6 === "boolean" ? node.supports_ipv6 : void 0
|
|
1425
1660
|
} : null,
|
|
1426
|
-
vmIpv6:
|
|
1661
|
+
vmIpv6: asString4(payload?.vm_ipv6),
|
|
1427
1662
|
period: payload?.period ? {
|
|
1428
|
-
start_timestamp:
|
|
1663
|
+
start_timestamp: asString4(payload.period.start_timestamp) ?? void 0,
|
|
1429
1664
|
duration_seconds: asNumber3(payload.period.duration_seconds) ?? void 0
|
|
1430
1665
|
} : null
|
|
1431
1666
|
};
|
|
@@ -1440,7 +1675,7 @@ async function fetch2n6WebAccessUrl2(itemHash, options) {
|
|
|
1440
1675
|
return {
|
|
1441
1676
|
url: normalizeProxyUrl2(payload?.url ?? payload?.subdomain),
|
|
1442
1677
|
active: typeof payload?.active === "boolean" ? payload.active : null,
|
|
1443
|
-
subdomain:
|
|
1678
|
+
subdomain: asString4(payload?.subdomain)
|
|
1444
1679
|
};
|
|
1445
1680
|
}
|
|
1446
1681
|
async function fetchCrnExecutionMap2(crnUrl, options) {
|
|
@@ -1660,7 +1895,7 @@ function utf8Hex(value) {
|
|
|
1660
1895
|
function normalizeHexSignature(signature) {
|
|
1661
1896
|
return signature.startsWith("0x") ? signature : `0x${signature}`;
|
|
1662
1897
|
}
|
|
1663
|
-
function
|
|
1898
|
+
function asString5(value) {
|
|
1664
1899
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
1665
1900
|
}
|
|
1666
1901
|
function trimTrailingSlashes(value) {
|
|
@@ -1737,14 +1972,14 @@ async function fetchInstanceNodeHash(args) {
|
|
|
1737
1972
|
apiHost: args.apiHost
|
|
1738
1973
|
});
|
|
1739
1974
|
const payload = envelope;
|
|
1740
|
-
return
|
|
1975
|
+
return asString5(payload?.content?.requirements?.node?.node_hash) ?? asString5(payload?.message?.content?.requirements?.node?.node_hash) ?? null;
|
|
1741
1976
|
}
|
|
1742
1977
|
async function resolveInstanceCrn(args) {
|
|
1743
|
-
const providedCrnUrl =
|
|
1978
|
+
const providedCrnUrl = asString5(args.crnUrl);
|
|
1744
1979
|
if (providedCrnUrl) {
|
|
1745
1980
|
return {
|
|
1746
1981
|
crnUrl: trimTrailingSlashes(providedCrnUrl),
|
|
1747
|
-
crnHash:
|
|
1982
|
+
crnHash: asString5(args.crnHash),
|
|
1748
1983
|
source: "provided"
|
|
1749
1984
|
};
|
|
1750
1985
|
}
|
|
@@ -1755,11 +1990,11 @@ async function resolveInstanceCrn(args) {
|
|
|
1755
1990
|
if (allocation?.crnUrl) {
|
|
1756
1991
|
return {
|
|
1757
1992
|
crnUrl: trimTrailingSlashes(allocation.crnUrl),
|
|
1758
|
-
crnHash:
|
|
1993
|
+
crnHash: asString5(allocation.crnHash),
|
|
1759
1994
|
source: "scheduler"
|
|
1760
1995
|
};
|
|
1761
1996
|
}
|
|
1762
|
-
const manualCrnHash =
|
|
1997
|
+
const manualCrnHash = asString5(args.crnHash) ?? await fetchInstanceNodeHash({
|
|
1763
1998
|
instanceHash: args.instanceHash,
|
|
1764
1999
|
fetch: args.fetch,
|
|
1765
2000
|
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST2
|
|
@@ -3825,6 +4060,7 @@ function defaultState(props = {}) {
|
|
|
3825
4060
|
},
|
|
3826
4061
|
balance: null,
|
|
3827
4062
|
crns: [],
|
|
4063
|
+
crnSource: null,
|
|
3828
4064
|
selectedCrn: null,
|
|
3829
4065
|
crnOptions: [],
|
|
3830
4066
|
crnPinnedByUser: false,
|
|
@@ -3832,7 +4068,8 @@ function defaultState(props = {}) {
|
|
|
3832
4068
|
bootstrapRegistrations: [],
|
|
3833
4069
|
orphanBootstrapRegistrations: [],
|
|
3834
4070
|
lastDeploymentHash: null,
|
|
3835
|
-
deploymentProgress: IDLE_DEPLOYMENT_PROGRESS
|
|
4071
|
+
deploymentProgress: IDLE_DEPLOYMENT_PROGRESS,
|
|
4072
|
+
instanceAddresses: {}
|
|
3836
4073
|
};
|
|
3837
4074
|
}
|
|
3838
4075
|
function manifestLoadErrorState(error) {
|
|
@@ -3853,6 +4090,17 @@ function isDebugEnabled(props) {
|
|
|
3853
4090
|
return false;
|
|
3854
4091
|
}
|
|
3855
4092
|
}
|
|
4093
|
+
function crnSourcePreference(props) {
|
|
4094
|
+
const fromStorage = (() => {
|
|
4095
|
+
try {
|
|
4096
|
+
return globalThis.localStorage?.getItem("LE_SPACE_CRN_SOURCE") ?? null;
|
|
4097
|
+
} catch {
|
|
4098
|
+
return null;
|
|
4099
|
+
}
|
|
4100
|
+
})();
|
|
4101
|
+
const raw = (fromStorage ?? props.crnSource ?? "auto").trim().toLowerCase();
|
|
4102
|
+
return raw === "aggregate" || raw === "list" ? raw : "auto";
|
|
4103
|
+
}
|
|
3856
4104
|
async function sha256Hex(payload) {
|
|
3857
4105
|
const digest = await globalThis.crypto.subtle.digest(
|
|
3858
4106
|
"SHA-256",
|
|
@@ -3860,6 +4108,83 @@ async function sha256Hex(payload) {
|
|
|
3860
4108
|
);
|
|
3861
4109
|
return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3862
4110
|
}
|
|
4111
|
+
function hostnameOfUrl(value) {
|
|
4112
|
+
if (!value) return null;
|
|
4113
|
+
try {
|
|
4114
|
+
return new URL(value).hostname || null;
|
|
4115
|
+
} catch {
|
|
4116
|
+
return null;
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
function emptyInstanceAddresses() {
|
|
4120
|
+
return {
|
|
4121
|
+
status: "idle",
|
|
4122
|
+
groups: [],
|
|
4123
|
+
pwaEnv: null,
|
|
4124
|
+
payload: null,
|
|
4125
|
+
peerId: null,
|
|
4126
|
+
version: null,
|
|
4127
|
+
fetchedAt: null,
|
|
4128
|
+
error: null,
|
|
4129
|
+
sourceUrl: null
|
|
4130
|
+
};
|
|
4131
|
+
}
|
|
4132
|
+
var TRANSPORT_LABELS = {
|
|
4133
|
+
tcp: "TCP",
|
|
4134
|
+
websocket: "WebSocket",
|
|
4135
|
+
webrtc: "WebRTC",
|
|
4136
|
+
direct_tcp: "Direct TCP",
|
|
4137
|
+
autotls_wss: "AutoTLS WSS",
|
|
4138
|
+
proxy_wss: "Proxy WSS",
|
|
4139
|
+
webtransport: "WebTransport",
|
|
4140
|
+
webrtc_direct: "WebRTC Direct",
|
|
4141
|
+
browser_bootstrap: "Browser bootstrap",
|
|
4142
|
+
probe: "Probe"
|
|
4143
|
+
};
|
|
4144
|
+
function transportLabel(key) {
|
|
4145
|
+
return TRANSPORT_LABELS[key] ?? key.replace(/[_-]+/g, " ").replace(/^./, (first) => first.toUpperCase());
|
|
4146
|
+
}
|
|
4147
|
+
function addressList(value) {
|
|
4148
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && Boolean(entry.trim())) : [];
|
|
4149
|
+
}
|
|
4150
|
+
function parseInstanceAddressPayload(payload) {
|
|
4151
|
+
const groups = [];
|
|
4152
|
+
const byTransport = payload.byTransport;
|
|
4153
|
+
if (byTransport && typeof byTransport === "object") {
|
|
4154
|
+
for (const [key, value] of Object.entries(
|
|
4155
|
+
byTransport
|
|
4156
|
+
)) {
|
|
4157
|
+
const addresses = addressList(value);
|
|
4158
|
+
if (addresses.length > 0) {
|
|
4159
|
+
groups.push({ key, label: transportLabel(key), addresses });
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
4164
|
+
if (!key.endsWith("_multiaddrs")) continue;
|
|
4165
|
+
const addresses = addressList(value);
|
|
4166
|
+
if (addresses.length === 0) continue;
|
|
4167
|
+
const groupKey = key.replace(/_multiaddrs$/, "");
|
|
4168
|
+
groups.push({
|
|
4169
|
+
key: groupKey,
|
|
4170
|
+
label: transportLabel(groupKey),
|
|
4171
|
+
addresses
|
|
4172
|
+
});
|
|
4173
|
+
}
|
|
4174
|
+
const pwaEnvRaw = payload.pwa_env;
|
|
4175
|
+
const pwaEnv = pwaEnvRaw && typeof pwaEnvRaw === "object" ? Object.fromEntries(
|
|
4176
|
+
Object.entries(pwaEnvRaw).filter(([, entry]) => typeof entry === "string").map(([entryKey, entry]) => [entryKey, entry])
|
|
4177
|
+
) : null;
|
|
4178
|
+
const peerId = typeof payload.peerId === "string" ? payload.peerId : typeof payload.peer_id === "string" ? payload.peer_id : null;
|
|
4179
|
+
return {
|
|
4180
|
+
...emptyInstanceAddresses(),
|
|
4181
|
+
groups,
|
|
4182
|
+
pwaEnv,
|
|
4183
|
+
payload,
|
|
4184
|
+
peerId,
|
|
4185
|
+
version: typeof payload.version === "string" ? payload.version : null
|
|
4186
|
+
};
|
|
4187
|
+
}
|
|
3863
4188
|
function mappedPorts(execution) {
|
|
3864
4189
|
return Object.entries(execution?.networking?.mapped_ports ?? {}).map(
|
|
3865
4190
|
([port, mapping]) => ({
|
|
@@ -4008,6 +4333,7 @@ async function inspectInstanceRuntime(args) {
|
|
|
4008
4333
|
vmIpv4: null,
|
|
4009
4334
|
webUrl: null,
|
|
4010
4335
|
sshCommand: null,
|
|
4336
|
+
proxyHostname: null,
|
|
4011
4337
|
mappedPorts: [],
|
|
4012
4338
|
execution: null,
|
|
4013
4339
|
error: null
|
|
@@ -4072,6 +4398,7 @@ async function inspectInstanceRuntime(args) {
|
|
|
4072
4398
|
details.ipv6 = execution.networking.ipv6_ip ?? execution.networking.ipv6 ?? details.ipv6;
|
|
4073
4399
|
details.vmIpv4 = execution.networking.ipv4_ip ?? null;
|
|
4074
4400
|
details.webUrl = execution.networking.proxy_url ?? details.webUrl;
|
|
4401
|
+
details.proxyHostname = hostnameOfUrl(details.webUrl);
|
|
4075
4402
|
details.mappedPorts = mappedPorts(execution);
|
|
4076
4403
|
details.sshCommand = buildSshCommand(details.hostIpv4, details.mappedPorts);
|
|
4077
4404
|
return { details, lookup };
|
|
@@ -4150,6 +4477,7 @@ var SponsorRelayController = class {
|
|
|
4150
4477
|
apiHost: props.apiHost,
|
|
4151
4478
|
apiHosts: props.apiHosts,
|
|
4152
4479
|
crnListUrl: props.crnListUrl,
|
|
4480
|
+
crnSource: crnSourcePreference(props),
|
|
4153
4481
|
schedulerApiHost: props.schedulerApiHost,
|
|
4154
4482
|
twoN6ApiHost: props.twoN6ApiHost
|
|
4155
4483
|
});
|
|
@@ -4421,10 +4749,14 @@ var SponsorRelayController = class {
|
|
|
4421
4749
|
detail: "Publishing the host port mapping into the guest relay configuration."
|
|
4422
4750
|
});
|
|
4423
4751
|
const tcpPort = mappedPorts2["9091"]?.host ?? 0;
|
|
4424
|
-
const wsPort = mappedPorts2["9092"]?.host ??
|
|
4752
|
+
const wsPort = mappedPorts2["9092"]?.host ?? 0;
|
|
4425
4753
|
if (!tcpPort || !wsPort) {
|
|
4754
|
+
const missing = [
|
|
4755
|
+
tcpPort ? null : "9091 (libp2p TCP)",
|
|
4756
|
+
wsPort ? null : "9092 (libp2p WebSocket)"
|
|
4757
|
+
].filter(Boolean);
|
|
4426
4758
|
throw new Error(
|
|
4427
|
-
|
|
4759
|
+
`OrbitDB relay runtime has no mapped host port for ${missing.join(" and ")}. Deploy a rootfs whose manifest requests these forwards.`
|
|
4428
4760
|
);
|
|
4429
4761
|
}
|
|
4430
4762
|
const configureResult = await configureOrbitdbRelaySetup2({
|
|
@@ -5368,10 +5700,18 @@ var SponsorRelayController = class {
|
|
|
5368
5700
|
statusText: currentProfile === "ucan-store" ? "Refreshing service deployment data" : "Refreshing relay deployment data"
|
|
5369
5701
|
});
|
|
5370
5702
|
try {
|
|
5371
|
-
const [pricingSummary,
|
|
5703
|
+
const [pricingSummary, crnList] = await Promise.all([
|
|
5372
5704
|
fetchInstancePricing(this.client.apiHost),
|
|
5373
|
-
this.client.
|
|
5705
|
+
this.client.fetchCrnsWithSource(crnSourcePreference(this.props))
|
|
5374
5706
|
]);
|
|
5707
|
+
const { crns, source: crnSource } = crnList;
|
|
5708
|
+
if (crnList.listError) {
|
|
5709
|
+
this.trace("crns:fallback", {
|
|
5710
|
+
source: crnSource,
|
|
5711
|
+
count: crns.length,
|
|
5712
|
+
listError: crnList.listError.message
|
|
5713
|
+
});
|
|
5714
|
+
}
|
|
5375
5715
|
const manifestState = await resolveManifest({
|
|
5376
5716
|
manifestUrl: this.state.manifestUrl,
|
|
5377
5717
|
manifestJson: this.state.manifestJson
|
|
@@ -5407,6 +5747,7 @@ var SponsorRelayController = class {
|
|
|
5407
5747
|
vmIpv4: null,
|
|
5408
5748
|
webUrl: null,
|
|
5409
5749
|
sshCommand: null,
|
|
5750
|
+
proxyHostname: null,
|
|
5410
5751
|
mappedPorts: [],
|
|
5411
5752
|
execution: null,
|
|
5412
5753
|
error: null
|
|
@@ -5520,6 +5861,7 @@ var SponsorRelayController = class {
|
|
|
5520
5861
|
},
|
|
5521
5862
|
balance,
|
|
5522
5863
|
crns,
|
|
5864
|
+
crnSource,
|
|
5523
5865
|
instances,
|
|
5524
5866
|
bootstrapRegistrations,
|
|
5525
5867
|
orphanBootstrapRegistrations,
|
|
@@ -5597,10 +5939,21 @@ var SponsorRelayController = class {
|
|
|
5597
5939
|
}
|
|
5598
5940
|
});
|
|
5599
5941
|
const preferredCrnHash = this.state.selectedCrn?.hash ?? null;
|
|
5600
|
-
const
|
|
5942
|
+
const rankedCrns = [
|
|
5601
5943
|
...compatibleCrns2.filter((crn) => crn.hash === preferredCrnHash),
|
|
5602
5944
|
...compatibleCrns2.filter((crn) => crn.hash !== preferredCrnHash)
|
|
5603
5945
|
].slice(0, 5);
|
|
5946
|
+
const orderedCrns = this.state.crnSource === "aggregate" ? await filterReachableCrns(rankedCrns, {
|
|
5947
|
+
limit: rankedCrns.length,
|
|
5948
|
+
onDiagnostic: (message) => this.trace("crns:probe", { message })
|
|
5949
|
+
}).then(
|
|
5950
|
+
(reachable) => preferredCrnHash && !reachable.some((crn) => crn.hash === preferredCrnHash) ? [
|
|
5951
|
+
...rankedCrns.filter(
|
|
5952
|
+
(crn) => crn.hash === preferredCrnHash
|
|
5953
|
+
),
|
|
5954
|
+
...reachable
|
|
5955
|
+
] : reachable
|
|
5956
|
+
) : rankedCrns;
|
|
5604
5957
|
if (orderedCrns.length === 0) {
|
|
5605
5958
|
throw new Error(
|
|
5606
5959
|
"No compatible CRN is currently available for this tier."
|
|
@@ -5822,6 +6175,9 @@ var SponsorRelayController = class {
|
|
|
5822
6175
|
vmIpv4: runtime.execution?.networking?.ipv4_ip ?? null,
|
|
5823
6176
|
webUrl: runtime.webAccessUrl ?? runtime.proxyUrl ?? runtime.execution?.networking?.proxy_url ?? null,
|
|
5824
6177
|
sshCommand: runtime.sshCommand ?? null,
|
|
6178
|
+
proxyHostname: hostnameOfUrl(
|
|
6179
|
+
runtime.proxyUrl ?? runtime.webAccessUrl ?? runtime.execution?.networking?.proxy_url ?? null
|
|
6180
|
+
),
|
|
5825
6181
|
mappedPorts: runtime.execution != null ? mappedPorts(runtime.execution) : runtimeMappedPorts(runtime.mappedPorts),
|
|
5826
6182
|
execution: runtime.execution ?? null,
|
|
5827
6183
|
error: null
|
|
@@ -5919,6 +6275,9 @@ var SponsorRelayController = class {
|
|
|
5919
6275
|
vmIpv4: latestRuntime.execution?.networking?.ipv4_ip ?? null,
|
|
5920
6276
|
webUrl: latestRuntime.webAccessUrl ?? latestRuntime.proxyUrl ?? latestRuntime.execution?.networking?.proxy_url ?? null,
|
|
5921
6277
|
sshCommand: latestRuntime.sshCommand ?? null,
|
|
6278
|
+
proxyHostname: hostnameOfUrl(
|
|
6279
|
+
latestRuntime.proxyUrl ?? latestRuntime.webAccessUrl ?? latestRuntime.execution?.networking?.proxy_url ?? null
|
|
6280
|
+
),
|
|
5922
6281
|
mappedPorts: latestRuntime.execution != null ? mappedPorts(latestRuntime.execution) : runtimeMappedPorts(latestRuntime.mappedPorts),
|
|
5923
6282
|
execution: latestRuntime.execution ?? null,
|
|
5924
6283
|
error: null
|
|
@@ -6099,6 +6458,82 @@ var SponsorRelayController = class {
|
|
|
6099
6458
|
});
|
|
6100
6459
|
}
|
|
6101
6460
|
}
|
|
6461
|
+
/**
|
|
6462
|
+
* Read one deployment's own address document over its HTTPS proxy.
|
|
6463
|
+
*
|
|
6464
|
+
* The mapped ports are plain HTTP, which a browser on an HTTPS page refuses to
|
|
6465
|
+
* fetch, so the proxy hostname is the only way in. Deliberately single-shot:
|
|
6466
|
+
* unlike the deploy-time readiness probe this backs a button someone pressed,
|
|
6467
|
+
* and a caller who wants newer data presses it again.
|
|
6468
|
+
*/
|
|
6469
|
+
async loadInstanceAddresses(instanceHash, options = {}) {
|
|
6470
|
+
const existing = this.state.instanceAddresses[instanceHash];
|
|
6471
|
+
if (!options.force && existing && existing.status !== "idle") return;
|
|
6472
|
+
const record = this.state.instances.find(
|
|
6473
|
+
(entry) => entry.instance.item_hash === instanceHash
|
|
6474
|
+
);
|
|
6475
|
+
const proxyHostname = record?.details.proxyHostname ?? null;
|
|
6476
|
+
if (!proxyHostname) {
|
|
6477
|
+
this.patchInstanceAddresses(instanceHash, {
|
|
6478
|
+
...emptyInstanceAddresses(),
|
|
6479
|
+
status: "unsupported",
|
|
6480
|
+
error: "This deployment has no HTTPS proxy hostname yet, so its addresses cannot be read from the browser."
|
|
6481
|
+
});
|
|
6482
|
+
return;
|
|
6483
|
+
}
|
|
6484
|
+
const sourceUrl = `https://${proxyHostname}/multiaddrs`;
|
|
6485
|
+
this.patchInstanceAddresses(instanceHash, {
|
|
6486
|
+
...existing ?? emptyInstanceAddresses(),
|
|
6487
|
+
status: "loading",
|
|
6488
|
+
sourceUrl,
|
|
6489
|
+
error: null
|
|
6490
|
+
});
|
|
6491
|
+
try {
|
|
6492
|
+
const abort = new AbortController();
|
|
6493
|
+
const timeout = globalThis.setTimeout(() => abort.abort(), 1e4);
|
|
6494
|
+
const response = await fetch(sourceUrl, {
|
|
6495
|
+
cache: "no-cache",
|
|
6496
|
+
signal: abort.signal
|
|
6497
|
+
});
|
|
6498
|
+
globalThis.clearTimeout(timeout);
|
|
6499
|
+
if (response.status === 404) {
|
|
6500
|
+
this.patchInstanceAddresses(instanceHash, {
|
|
6501
|
+
...emptyInstanceAddresses(),
|
|
6502
|
+
status: "unsupported",
|
|
6503
|
+
sourceUrl,
|
|
6504
|
+
fetchedAt: Date.now(),
|
|
6505
|
+
error: "This profile does not publish an address document."
|
|
6506
|
+
});
|
|
6507
|
+
return;
|
|
6508
|
+
}
|
|
6509
|
+
if (!response.ok) {
|
|
6510
|
+
throw new Error(`${sourceUrl} answered ${response.status}.`);
|
|
6511
|
+
}
|
|
6512
|
+
const payload = await response.json();
|
|
6513
|
+
this.patchInstanceAddresses(instanceHash, {
|
|
6514
|
+
...parseInstanceAddressPayload(payload),
|
|
6515
|
+
status: "ready",
|
|
6516
|
+
sourceUrl,
|
|
6517
|
+
fetchedAt: Date.now(),
|
|
6518
|
+
error: null
|
|
6519
|
+
});
|
|
6520
|
+
} catch (error) {
|
|
6521
|
+
this.patchInstanceAddresses(instanceHash, {
|
|
6522
|
+
...this.state.instanceAddresses[instanceHash] ?? emptyInstanceAddresses(),
|
|
6523
|
+
status: "error",
|
|
6524
|
+
sourceUrl,
|
|
6525
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6526
|
+
});
|
|
6527
|
+
}
|
|
6528
|
+
}
|
|
6529
|
+
patchInstanceAddresses(instanceHash, value) {
|
|
6530
|
+
this.patch({
|
|
6531
|
+
instanceAddresses: {
|
|
6532
|
+
...this.state.instanceAddresses,
|
|
6533
|
+
[instanceHash]: value
|
|
6534
|
+
}
|
|
6535
|
+
});
|
|
6536
|
+
}
|
|
6102
6537
|
async deleteInstance(instanceHash) {
|
|
6103
6538
|
this.trace("delete:start", { instanceHash });
|
|
6104
6539
|
if (!this.state.wallet.address) {
|
|
@@ -6272,8 +6707,45 @@ function createSponsorRelayController(props = {}) {
|
|
|
6272
6707
|
return new SponsorRelayController(props);
|
|
6273
6708
|
}
|
|
6274
6709
|
|
|
6710
|
+
// src/react/components/CopyButton.tsx
|
|
6711
|
+
import { useEffect, useRef, useState } from "react";
|
|
6712
|
+
import { jsx } from "react/jsx-runtime";
|
|
6713
|
+
var copyButtonStyle = {
|
|
6714
|
+
borderRadius: "999px",
|
|
6715
|
+
border: "1px solid var(--rb-border)",
|
|
6716
|
+
background: "transparent",
|
|
6717
|
+
color: "var(--rb-muted)",
|
|
6718
|
+
padding: "0.28rem 0.7rem",
|
|
6719
|
+
fontFamily: "var(--rb-font-mono, monospace)",
|
|
6720
|
+
fontSize: "0.6563rem",
|
|
6721
|
+
fontWeight: 700,
|
|
6722
|
+
lineHeight: 1,
|
|
6723
|
+
textTransform: "uppercase",
|
|
6724
|
+
letterSpacing: "0.06em",
|
|
6725
|
+
cursor: "pointer",
|
|
6726
|
+
flexShrink: 0
|
|
6727
|
+
};
|
|
6728
|
+
function CopyButton({ text, label = "Copy" }) {
|
|
6729
|
+
const [copied, setCopied] = useState(false);
|
|
6730
|
+
const timer = useRef(null);
|
|
6731
|
+
useEffect(
|
|
6732
|
+
() => () => {
|
|
6733
|
+
if (timer.current) clearTimeout(timer.current);
|
|
6734
|
+
},
|
|
6735
|
+
[]
|
|
6736
|
+
);
|
|
6737
|
+
const handleCopy = async () => {
|
|
6738
|
+
if (!text) return;
|
|
6739
|
+
await navigator.clipboard.writeText(text);
|
|
6740
|
+
setCopied(true);
|
|
6741
|
+
if (timer.current) clearTimeout(timer.current);
|
|
6742
|
+
timer.current = setTimeout(() => setCopied(false), 1200);
|
|
6743
|
+
};
|
|
6744
|
+
return /* @__PURE__ */ jsx("button", { type: "button", style: copyButtonStyle, onClick: () => void handleCopy(), children: copied ? "Copied" : label });
|
|
6745
|
+
}
|
|
6746
|
+
|
|
6275
6747
|
// src/react/hooks/useSponsorRelayController.ts
|
|
6276
|
-
import { useEffect, useMemo, useSyncExternalStore } from "react";
|
|
6748
|
+
import { useEffect as useEffect2, useMemo, useSyncExternalStore } from "react";
|
|
6277
6749
|
function useSponsorRelayController(props) {
|
|
6278
6750
|
const controller = useMemo(
|
|
6279
6751
|
() => createSponsorRelayController(props),
|
|
@@ -6281,6 +6753,7 @@ function useSponsorRelayController(props) {
|
|
|
6281
6753
|
props.apiHost,
|
|
6282
6754
|
props.apiHosts,
|
|
6283
6755
|
props.crnListUrl,
|
|
6756
|
+
props.crnSource,
|
|
6284
6757
|
props.debug,
|
|
6285
6758
|
props.instanceName,
|
|
6286
6759
|
props.manifestJson,
|
|
@@ -6293,12 +6766,12 @@ function useSponsorRelayController(props) {
|
|
|
6293
6766
|
props.ucanStoreBootstrap
|
|
6294
6767
|
]
|
|
6295
6768
|
);
|
|
6296
|
-
|
|
6769
|
+
useEffect2(() => {
|
|
6297
6770
|
controller.updateProps({
|
|
6298
6771
|
debug: props.debug
|
|
6299
6772
|
});
|
|
6300
6773
|
}, [controller, props.debug]);
|
|
6301
|
-
|
|
6774
|
+
useEffect2(() => {
|
|
6302
6775
|
void controller.init();
|
|
6303
6776
|
return () => {
|
|
6304
6777
|
controller.destroy();
|
|
@@ -6313,7 +6786,7 @@ function useSponsorRelayController(props) {
|
|
|
6313
6786
|
}
|
|
6314
6787
|
|
|
6315
6788
|
// src/react/SponsorRelayFab.tsx
|
|
6316
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6789
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
6317
6790
|
var THEME_CSS = `
|
|
6318
6791
|
:root {
|
|
6319
6792
|
--rb-font-body: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
@@ -6332,6 +6805,8 @@ var THEME_CSS = `
|
|
|
6332
6805
|
--rb-panel-shadow: 0 28px 80px rgba(4, 6, 12, 0.55);
|
|
6333
6806
|
--rb-surface: rgba(11, 14, 21, 0.55);
|
|
6334
6807
|
--rb-field-bg: rgba(11, 14, 21, 0.85);
|
|
6808
|
+
/* Opaque on purpose - see optionStyle. */
|
|
6809
|
+
--rb-menu-bg: #0b0e15;
|
|
6335
6810
|
--rb-accent: var(--rb-coral);
|
|
6336
6811
|
--rb-accent-contrast: #0b0e15;
|
|
6337
6812
|
--rb-link: var(--rb-cyan);
|
|
@@ -6356,6 +6831,7 @@ var THEME_CSS = `
|
|
|
6356
6831
|
--rb-panel-shadow: 0 28px 80px rgba(20, 27, 46, 0.18);
|
|
6357
6832
|
--rb-surface: rgba(20, 27, 46, 0.04);
|
|
6358
6833
|
--rb-field-bg: #ffffff;
|
|
6834
|
+
--rb-menu-bg: #ffffff;
|
|
6359
6835
|
--rb-accent-contrast: #ffffff;
|
|
6360
6836
|
--rb-launcher-start: #ffffff;
|
|
6361
6837
|
--rb-launcher-end: #f2f5fa;
|
|
@@ -6399,6 +6875,10 @@ var fieldStyle = {
|
|
|
6399
6875
|
fontSize: "0.8125rem",
|
|
6400
6876
|
lineHeight: 1.4
|
|
6401
6877
|
};
|
|
6878
|
+
var optionStyle = {
|
|
6879
|
+
background: "var(--rb-menu-bg)",
|
|
6880
|
+
color: "var(--rb-text)"
|
|
6881
|
+
};
|
|
6402
6882
|
var secondaryButtonStyle = {
|
|
6403
6883
|
borderRadius: "0.5rem",
|
|
6404
6884
|
border: "1px solid var(--rb-border)",
|
|
@@ -6433,6 +6913,53 @@ var containedContentStyle = {
|
|
|
6433
6913
|
wordBreak: "break-word",
|
|
6434
6914
|
whiteSpace: "normal"
|
|
6435
6915
|
};
|
|
6916
|
+
var tabBarStyle = {
|
|
6917
|
+
display: "flex",
|
|
6918
|
+
gap: "0.35rem",
|
|
6919
|
+
margin: "0.55rem 0 0.5rem",
|
|
6920
|
+
borderBottom: "1px solid var(--rb-border)"
|
|
6921
|
+
};
|
|
6922
|
+
var tabStyle = (active) => ({
|
|
6923
|
+
border: 0,
|
|
6924
|
+
borderBottom: `2px solid ${active ? "var(--rb-accent)" : "transparent"}`,
|
|
6925
|
+
background: "transparent",
|
|
6926
|
+
color: active ? "var(--rb-text)" : "var(--rb-muted)",
|
|
6927
|
+
padding: "0.35rem 0.6rem",
|
|
6928
|
+
fontFamily: "var(--rb-font-mono, monospace)",
|
|
6929
|
+
fontSize: "0.6875rem",
|
|
6930
|
+
fontWeight: 700,
|
|
6931
|
+
textTransform: "uppercase",
|
|
6932
|
+
letterSpacing: "0.06em",
|
|
6933
|
+
cursor: "pointer"
|
|
6934
|
+
});
|
|
6935
|
+
var addressRowStyle = {
|
|
6936
|
+
display: "flex",
|
|
6937
|
+
alignItems: "center",
|
|
6938
|
+
justifyContent: "space-between",
|
|
6939
|
+
gap: "0.5rem",
|
|
6940
|
+
padding: "0.25rem 0",
|
|
6941
|
+
borderTop: "1px solid var(--rb-border)"
|
|
6942
|
+
};
|
|
6943
|
+
var payloadStyle = {
|
|
6944
|
+
maxHeight: "20rem",
|
|
6945
|
+
overflow: "auto",
|
|
6946
|
+
padding: "0.5rem",
|
|
6947
|
+
border: "1px solid var(--rb-border)",
|
|
6948
|
+
borderRadius: "0.5rem",
|
|
6949
|
+
fontFamily: "var(--rb-font-mono, monospace)",
|
|
6950
|
+
fontSize: "0.6875rem",
|
|
6951
|
+
lineHeight: 1.5
|
|
6952
|
+
};
|
|
6953
|
+
function addressTabLabel(addresses) {
|
|
6954
|
+
if (!addresses?.groups.length && addresses?.pwaEnv) return "Endpoints";
|
|
6955
|
+
return "Multiaddresses";
|
|
6956
|
+
}
|
|
6957
|
+
function copyAllText(addresses) {
|
|
6958
|
+
return addresses.groups.flatMap((group) => group.addresses).join("\n");
|
|
6959
|
+
}
|
|
6960
|
+
function pwaEnvText(addresses) {
|
|
6961
|
+
return Object.entries(addresses.pwaEnv ?? {}).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
6962
|
+
}
|
|
6436
6963
|
var dangerButtonStyle = {
|
|
6437
6964
|
borderRadius: "0.5rem",
|
|
6438
6965
|
border: "1px solid rgba(255, 77, 106, 0.45)",
|
|
@@ -6614,12 +7141,19 @@ function SponsorRelayFab(props) {
|
|
|
6614
7141
|
(state.bootstrapRegistrations ?? []).filter((entry) => entry.confirmed && entry.instanceItemHash).map((entry) => [entry.instanceItemHash, entry])
|
|
6615
7142
|
);
|
|
6616
7143
|
const orphanRegistrations = state.orphanBootstrapRegistrations ?? [];
|
|
6617
|
-
const [successFlash, setSuccessFlash] =
|
|
6618
|
-
const [hovered, setHovered] =
|
|
6619
|
-
const
|
|
6620
|
-
const
|
|
6621
|
-
|
|
6622
|
-
|
|
7144
|
+
const [successFlash, setSuccessFlash] = React2.useState(false);
|
|
7145
|
+
const [hovered, setHovered] = React2.useState(false);
|
|
7146
|
+
const [instanceTabs, setInstanceTabs] = React2.useState({});
|
|
7147
|
+
const selectInstanceTab = (itemHash, tab) => {
|
|
7148
|
+
setInstanceTabs((current) => ({ ...current, [itemHash]: tab }));
|
|
7149
|
+
if (tab !== "general") {
|
|
7150
|
+
void controller.loadInstanceAddresses(itemHash);
|
|
7151
|
+
}
|
|
7152
|
+
};
|
|
7153
|
+
const launcherRef = React2.useRef(null);
|
|
7154
|
+
const [inlinePanelStyle, setInlinePanelStyle] = React2.useState(null);
|
|
7155
|
+
const [compactInlineLabel, setCompactInlineLabel] = React2.useState(false);
|
|
7156
|
+
React2.useEffect(() => {
|
|
6623
7157
|
if (state.deploymentProgress.stage !== "completed" || state.deploymentProgress.status !== "success") {
|
|
6624
7158
|
return;
|
|
6625
7159
|
}
|
|
@@ -6635,7 +7169,7 @@ function SponsorRelayFab(props) {
|
|
|
6635
7169
|
state.deploymentProgress.status,
|
|
6636
7170
|
state.deploymentProgress.timestamp
|
|
6637
7171
|
]);
|
|
6638
|
-
|
|
7172
|
+
React2.useEffect(() => {
|
|
6639
7173
|
if (state.deploymentProgress.stage !== "completed") {
|
|
6640
7174
|
return;
|
|
6641
7175
|
}
|
|
@@ -6646,7 +7180,7 @@ function SponsorRelayFab(props) {
|
|
|
6646
7180
|
window.clearTimeout(timeout);
|
|
6647
7181
|
};
|
|
6648
7182
|
}, [state.deploymentProgress.stage, state.deploymentProgress.timestamp]);
|
|
6649
|
-
|
|
7183
|
+
React2.useEffect(() => {
|
|
6650
7184
|
if (launcherMode !== "inline" || !state.open) {
|
|
6651
7185
|
return;
|
|
6652
7186
|
}
|
|
@@ -6676,7 +7210,7 @@ function SponsorRelayFab(props) {
|
|
|
6676
7210
|
window.removeEventListener("scroll", updateInlinePanelStyle, true);
|
|
6677
7211
|
};
|
|
6678
7212
|
}, [launcherMode, state.open]);
|
|
6679
|
-
|
|
7213
|
+
React2.useEffect(() => {
|
|
6680
7214
|
if (launcherMode !== "inline") {
|
|
6681
7215
|
setCompactInlineLabel(false);
|
|
6682
7216
|
return;
|
|
@@ -6715,7 +7249,7 @@ function SponsorRelayFab(props) {
|
|
|
6715
7249
|
const rootfsBlocked = state.rootfsHealth.tone === "error";
|
|
6716
7250
|
const deployCallToAction = state.wallet.connected ? state.busy.deploying ? "Deploying\u2026" : rootfsBlocked ? "Deployment blocked \u2014 Rootfs unavailable" : deploymentButtonLabel(state) : "Connect MetaMask";
|
|
6717
7251
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6718
|
-
/* @__PURE__ */
|
|
7252
|
+
/* @__PURE__ */ jsx2("style", { children: THEME_CSS }),
|
|
6719
7253
|
/* @__PURE__ */ jsxs(
|
|
6720
7254
|
"button",
|
|
6721
7255
|
{
|
|
@@ -6773,7 +7307,7 @@ function SponsorRelayFab(props) {
|
|
|
6773
7307
|
flex: "none"
|
|
6774
7308
|
},
|
|
6775
7309
|
children: [
|
|
6776
|
-
/* @__PURE__ */
|
|
7310
|
+
/* @__PURE__ */ jsx2(
|
|
6777
7311
|
"line",
|
|
6778
7312
|
{
|
|
6779
7313
|
x1: "17",
|
|
@@ -6785,8 +7319,8 @@ function SponsorRelayFab(props) {
|
|
|
6785
7319
|
strokeLinecap: "round"
|
|
6786
7320
|
}
|
|
6787
7321
|
),
|
|
6788
|
-
/* @__PURE__ */
|
|
6789
|
-
/* @__PURE__ */
|
|
7322
|
+
/* @__PURE__ */ jsx2("circle", { cx: "11.5", cy: "20.5", r: "7", fill: "var(--rb-coral)" }),
|
|
7323
|
+
/* @__PURE__ */ jsx2(
|
|
6790
7324
|
"circle",
|
|
6791
7325
|
{
|
|
6792
7326
|
cx: "23.5",
|
|
@@ -6800,7 +7334,7 @@ function SponsorRelayFab(props) {
|
|
|
6800
7334
|
]
|
|
6801
7335
|
}
|
|
6802
7336
|
),
|
|
6803
|
-
/* @__PURE__ */
|
|
7337
|
+
/* @__PURE__ */ jsx2("span", { children: launcherLabel })
|
|
6804
7338
|
]
|
|
6805
7339
|
}
|
|
6806
7340
|
),
|
|
@@ -6824,7 +7358,7 @@ function SponsorRelayFab(props) {
|
|
|
6824
7358
|
boxShadow: launcherMode === "floating" ? void 0 : `inset 0 1px 0 rgba(255,255,255,0.08), 0 6px 16px ${progressToneColor(indicator.tone)}22`
|
|
6825
7359
|
},
|
|
6826
7360
|
children: [
|
|
6827
|
-
/* @__PURE__ */
|
|
7361
|
+
/* @__PURE__ */ jsx2(
|
|
6828
7362
|
"span",
|
|
6829
7363
|
{
|
|
6830
7364
|
"aria-hidden": "true",
|
|
@@ -6840,7 +7374,7 @@ function SponsorRelayFab(props) {
|
|
|
6840
7374
|
}
|
|
6841
7375
|
}
|
|
6842
7376
|
),
|
|
6843
|
-
/* @__PURE__ */
|
|
7377
|
+
/* @__PURE__ */ jsx2("span", { children: indicator.label })
|
|
6844
7378
|
]
|
|
6845
7379
|
}
|
|
6846
7380
|
)
|
|
@@ -6848,7 +7382,7 @@ function SponsorRelayFab(props) {
|
|
|
6848
7382
|
}
|
|
6849
7383
|
),
|
|
6850
7384
|
state.open ? /* @__PURE__ */ jsxs("div", { children: [
|
|
6851
|
-
/* @__PURE__ */
|
|
7385
|
+
/* @__PURE__ */ jsx2(
|
|
6852
7386
|
"div",
|
|
6853
7387
|
{
|
|
6854
7388
|
onClick: () => controller.setOpen(false),
|
|
@@ -6887,8 +7421,8 @@ function SponsorRelayFab(props) {
|
|
|
6887
7421
|
letterSpacing: "0.08em"
|
|
6888
7422
|
},
|
|
6889
7423
|
children: [
|
|
6890
|
-
/* @__PURE__ */
|
|
6891
|
-
/* @__PURE__ */
|
|
7424
|
+
/* @__PURE__ */ jsx2("span", { children: "Aleph VM credit deployer" }),
|
|
7425
|
+
/* @__PURE__ */ jsx2(
|
|
6892
7426
|
"span",
|
|
6893
7427
|
{
|
|
6894
7428
|
style: {
|
|
@@ -6904,7 +7438,7 @@ function SponsorRelayFab(props) {
|
|
|
6904
7438
|
]
|
|
6905
7439
|
}
|
|
6906
7440
|
),
|
|
6907
|
-
/* @__PURE__ */
|
|
7441
|
+
/* @__PURE__ */ jsx2(
|
|
6908
7442
|
"h2",
|
|
6909
7443
|
{
|
|
6910
7444
|
style: {
|
|
@@ -6917,7 +7451,7 @@ function SponsorRelayFab(props) {
|
|
|
6917
7451
|
}
|
|
6918
7452
|
)
|
|
6919
7453
|
] }),
|
|
6920
|
-
/* @__PURE__ */
|
|
7454
|
+
/* @__PURE__ */ jsx2(
|
|
6921
7455
|
"button",
|
|
6922
7456
|
{
|
|
6923
7457
|
type: "button",
|
|
@@ -6929,8 +7463,8 @@ function SponsorRelayFab(props) {
|
|
|
6929
7463
|
]
|
|
6930
7464
|
}
|
|
6931
7465
|
),
|
|
6932
|
-
/* @__PURE__ */
|
|
6933
|
-
state.errorText ? /* @__PURE__ */
|
|
7466
|
+
/* @__PURE__ */ jsx2("p", { style: { color: "var(--rb-muted)" }, children: state.statusText }),
|
|
7467
|
+
state.errorText ? /* @__PURE__ */ jsx2("p", { style: { color: "var(--rb-danger)" }, children: state.errorText }) : null,
|
|
6934
7468
|
pollingState ? /* @__PURE__ */ jsxs(
|
|
6935
7469
|
"div",
|
|
6936
7470
|
{
|
|
@@ -6955,7 +7489,7 @@ function SponsorRelayFab(props) {
|
|
|
6955
7489
|
gap: "0.45rem"
|
|
6956
7490
|
},
|
|
6957
7491
|
children: [
|
|
6958
|
-
/* @__PURE__ */
|
|
7492
|
+
/* @__PURE__ */ jsx2(
|
|
6959
7493
|
"span",
|
|
6960
7494
|
{
|
|
6961
7495
|
"aria-hidden": "true",
|
|
@@ -6969,11 +7503,11 @@ function SponsorRelayFab(props) {
|
|
|
6969
7503
|
}
|
|
6970
7504
|
}
|
|
6971
7505
|
),
|
|
6972
|
-
/* @__PURE__ */
|
|
7506
|
+
/* @__PURE__ */ jsx2("strong", { style: { fontSize: "0.88rem" }, children: pollingState.label })
|
|
6973
7507
|
]
|
|
6974
7508
|
}
|
|
6975
7509
|
),
|
|
6976
|
-
/* @__PURE__ */
|
|
7510
|
+
/* @__PURE__ */ jsx2("small", { style: { color: "var(--rb-muted)", lineHeight: 1.35 }, children: pollingState.detail })
|
|
6977
7511
|
]
|
|
6978
7512
|
}
|
|
6979
7513
|
) : null,
|
|
@@ -7008,7 +7542,7 @@ function SponsorRelayFab(props) {
|
|
|
7008
7542
|
minWidth: 0
|
|
7009
7543
|
},
|
|
7010
7544
|
children: [
|
|
7011
|
-
/* @__PURE__ */
|
|
7545
|
+
/* @__PURE__ */ jsx2(
|
|
7012
7546
|
"span",
|
|
7013
7547
|
{
|
|
7014
7548
|
style: {
|
|
@@ -7030,7 +7564,7 @@ function SponsorRelayFab(props) {
|
|
|
7030
7564
|
children: progressBadgeLabel(state.deploymentProgress.stage)
|
|
7031
7565
|
}
|
|
7032
7566
|
),
|
|
7033
|
-
/* @__PURE__ */
|
|
7567
|
+
/* @__PURE__ */ jsx2(
|
|
7034
7568
|
"strong",
|
|
7035
7569
|
{
|
|
7036
7570
|
style: {
|
|
@@ -7065,7 +7599,7 @@ function SponsorRelayFab(props) {
|
|
|
7065
7599
|
]
|
|
7066
7600
|
}
|
|
7067
7601
|
),
|
|
7068
|
-
/* @__PURE__ */
|
|
7602
|
+
/* @__PURE__ */ jsx2(
|
|
7069
7603
|
"div",
|
|
7070
7604
|
{
|
|
7071
7605
|
style: {
|
|
@@ -7076,7 +7610,7 @@ function SponsorRelayFab(props) {
|
|
|
7076
7610
|
background: "rgba(168, 179, 199, 0.18)",
|
|
7077
7611
|
overflow: "hidden"
|
|
7078
7612
|
},
|
|
7079
|
-
children: /* @__PURE__ */
|
|
7613
|
+
children: /* @__PURE__ */ jsx2(
|
|
7080
7614
|
"div",
|
|
7081
7615
|
{
|
|
7082
7616
|
style: {
|
|
@@ -7118,7 +7652,7 @@ function SponsorRelayFab(props) {
|
|
|
7118
7652
|
]
|
|
7119
7653
|
}
|
|
7120
7654
|
) : null,
|
|
7121
|
-
state.deploymentProgress.detail ? /* @__PURE__ */
|
|
7655
|
+
state.deploymentProgress.detail ? /* @__PURE__ */ jsx2(
|
|
7122
7656
|
"div",
|
|
7123
7657
|
{
|
|
7124
7658
|
style: {
|
|
@@ -7130,7 +7664,7 @@ function SponsorRelayFab(props) {
|
|
|
7130
7664
|
children: state.deploymentProgress.detail
|
|
7131
7665
|
}
|
|
7132
7666
|
) : null,
|
|
7133
|
-
state.deploymentProgress.error ? /* @__PURE__ */
|
|
7667
|
+
state.deploymentProgress.error ? /* @__PURE__ */ jsx2(
|
|
7134
7668
|
"div",
|
|
7135
7669
|
{
|
|
7136
7670
|
style: {
|
|
@@ -7152,7 +7686,7 @@ function SponsorRelayFab(props) {
|
|
|
7152
7686
|
{
|
|
7153
7687
|
style: { display: "grid", gap: "0.75rem", marginTop: "0.9rem" },
|
|
7154
7688
|
children: [
|
|
7155
|
-
/* @__PURE__ */
|
|
7689
|
+
/* @__PURE__ */ jsx2(
|
|
7156
7690
|
"input",
|
|
7157
7691
|
{
|
|
7158
7692
|
style: fieldStyle,
|
|
@@ -7161,7 +7695,7 @@ function SponsorRelayFab(props) {
|
|
|
7161
7695
|
placeholder: "Instance name"
|
|
7162
7696
|
}
|
|
7163
7697
|
),
|
|
7164
|
-
/* @__PURE__ */
|
|
7698
|
+
/* @__PURE__ */ jsx2(
|
|
7165
7699
|
"select",
|
|
7166
7700
|
{
|
|
7167
7701
|
style: fieldStyle,
|
|
@@ -7172,11 +7706,11 @@ function SponsorRelayFab(props) {
|
|
|
7172
7706
|
const vcpus = unit ? unit.vcpus * tier.compute_units : null;
|
|
7173
7707
|
const memoryMiB = unit ? unit.memory_mib * tier.compute_units : null;
|
|
7174
7708
|
const diskMiB = unit ? unit.disk_mib * tier.compute_units : null;
|
|
7175
|
-
return /* @__PURE__ */
|
|
7709
|
+
return /* @__PURE__ */ jsx2("option", { style: optionStyle, value: tier.id, children: `${tier.id} ${formatTierSpecLabel(vcpus, memoryMiB, diskMiB)}` }, tier.id);
|
|
7176
7710
|
})
|
|
7177
7711
|
}
|
|
7178
7712
|
),
|
|
7179
|
-
/* @__PURE__ */
|
|
7713
|
+
/* @__PURE__ */ jsx2(
|
|
7180
7714
|
"div",
|
|
7181
7715
|
{
|
|
7182
7716
|
style: {
|
|
@@ -7200,7 +7734,7 @@ function SponsorRelayFab(props) {
|
|
|
7200
7734
|
event.currentTarget.open
|
|
7201
7735
|
),
|
|
7202
7736
|
children: [
|
|
7203
|
-
/* @__PURE__ */
|
|
7737
|
+
/* @__PURE__ */ jsx2("summary", { children: "Advanced" }),
|
|
7204
7738
|
/* @__PURE__ */ jsxs(
|
|
7205
7739
|
"div",
|
|
7206
7740
|
{
|
|
@@ -7210,7 +7744,7 @@ function SponsorRelayFab(props) {
|
|
|
7210
7744
|
marginTop: "0.65rem"
|
|
7211
7745
|
},
|
|
7212
7746
|
children: [
|
|
7213
|
-
/* @__PURE__ */
|
|
7747
|
+
/* @__PURE__ */ jsx2(
|
|
7214
7748
|
"input",
|
|
7215
7749
|
{
|
|
7216
7750
|
style: fieldStyle,
|
|
@@ -7219,7 +7753,7 @@ function SponsorRelayFab(props) {
|
|
|
7219
7753
|
placeholder: "Manifest URL"
|
|
7220
7754
|
}
|
|
7221
7755
|
),
|
|
7222
|
-
/* @__PURE__ */
|
|
7756
|
+
/* @__PURE__ */ jsx2(
|
|
7223
7757
|
"textarea",
|
|
7224
7758
|
{
|
|
7225
7759
|
style: fieldStyle,
|
|
@@ -7237,8 +7771,8 @@ function SponsorRelayFab(props) {
|
|
|
7237
7771
|
event.currentTarget.open
|
|
7238
7772
|
),
|
|
7239
7773
|
children: [
|
|
7240
|
-
/* @__PURE__ */
|
|
7241
|
-
/* @__PURE__ */
|
|
7774
|
+
/* @__PURE__ */ jsx2("summary", { children: "Paste Manifest" }),
|
|
7775
|
+
/* @__PURE__ */ jsx2(
|
|
7242
7776
|
"textarea",
|
|
7243
7777
|
{
|
|
7244
7778
|
style: { ...fieldStyle, marginTop: "0.65rem" },
|
|
@@ -7251,7 +7785,7 @@ function SponsorRelayFab(props) {
|
|
|
7251
7785
|
}
|
|
7252
7786
|
),
|
|
7253
7787
|
stateDeploymentProfile(state) === "ucan-store" ? /* @__PURE__ */ jsxs("details", { open: true, children: [
|
|
7254
|
-
/* @__PURE__ */
|
|
7788
|
+
/* @__PURE__ */ jsx2("summary", { children: "UCAN Store Bootstrap" }),
|
|
7255
7789
|
/* @__PURE__ */ jsxs(
|
|
7256
7790
|
"div",
|
|
7257
7791
|
{
|
|
@@ -7261,7 +7795,7 @@ function SponsorRelayFab(props) {
|
|
|
7261
7795
|
marginTop: "0.65rem"
|
|
7262
7796
|
},
|
|
7263
7797
|
children: [
|
|
7264
|
-
/* @__PURE__ */
|
|
7798
|
+
/* @__PURE__ */ jsx2(
|
|
7265
7799
|
"input",
|
|
7266
7800
|
{
|
|
7267
7801
|
style: fieldStyle,
|
|
@@ -7273,7 +7807,7 @@ function SponsorRelayFab(props) {
|
|
|
7273
7807
|
placeholder: "Admin DID"
|
|
7274
7808
|
}
|
|
7275
7809
|
),
|
|
7276
|
-
/* @__PURE__ */
|
|
7810
|
+
/* @__PURE__ */ jsx2(
|
|
7277
7811
|
"input",
|
|
7278
7812
|
{
|
|
7279
7813
|
style: fieldStyle,
|
|
@@ -7285,7 +7819,7 @@ function SponsorRelayFab(props) {
|
|
|
7285
7819
|
placeholder: "Service DID override (optional)"
|
|
7286
7820
|
}
|
|
7287
7821
|
),
|
|
7288
|
-
/* @__PURE__ */
|
|
7822
|
+
/* @__PURE__ */ jsx2(
|
|
7289
7823
|
"input",
|
|
7290
7824
|
{
|
|
7291
7825
|
style: fieldStyle,
|
|
@@ -7297,7 +7831,7 @@ function SponsorRelayFab(props) {
|
|
|
7297
7831
|
placeholder: "Space DID"
|
|
7298
7832
|
}
|
|
7299
7833
|
),
|
|
7300
|
-
/* @__PURE__ */
|
|
7834
|
+
/* @__PURE__ */ jsx2(
|
|
7301
7835
|
"textarea",
|
|
7302
7836
|
{
|
|
7303
7837
|
style: fieldStyle,
|
|
@@ -7310,7 +7844,7 @@ function SponsorRelayFab(props) {
|
|
|
7310
7844
|
placeholder: "Root delegation proof"
|
|
7311
7845
|
}
|
|
7312
7846
|
),
|
|
7313
|
-
/* @__PURE__ */
|
|
7847
|
+
/* @__PURE__ */ jsx2(
|
|
7314
7848
|
"textarea",
|
|
7315
7849
|
{
|
|
7316
7850
|
style: fieldStyle,
|
|
@@ -7332,7 +7866,7 @@ function SponsorRelayFab(props) {
|
|
|
7332
7866
|
gridTemplateColumns: "repeat(auto-fit, minmax(10rem, 1fr))"
|
|
7333
7867
|
},
|
|
7334
7868
|
children: [
|
|
7335
|
-
/* @__PURE__ */
|
|
7869
|
+
/* @__PURE__ */ jsx2(
|
|
7336
7870
|
"input",
|
|
7337
7871
|
{
|
|
7338
7872
|
style: fieldStyle,
|
|
@@ -7344,7 +7878,7 @@ function SponsorRelayFab(props) {
|
|
|
7344
7878
|
placeholder: "Default expiration (seconds)"
|
|
7345
7879
|
}
|
|
7346
7880
|
),
|
|
7347
|
-
/* @__PURE__ */
|
|
7881
|
+
/* @__PURE__ */ jsx2(
|
|
7348
7882
|
"input",
|
|
7349
7883
|
{
|
|
7350
7884
|
style: fieldStyle,
|
|
@@ -7359,7 +7893,7 @@ function SponsorRelayFab(props) {
|
|
|
7359
7893
|
]
|
|
7360
7894
|
}
|
|
7361
7895
|
),
|
|
7362
|
-
/* @__PURE__ */
|
|
7896
|
+
/* @__PURE__ */ jsx2(
|
|
7363
7897
|
"input",
|
|
7364
7898
|
{
|
|
7365
7899
|
style: fieldStyle,
|
|
@@ -7371,7 +7905,7 @@ function SponsorRelayFab(props) {
|
|
|
7371
7905
|
placeholder: "PWA origin override (optional, defaults to current page origin)"
|
|
7372
7906
|
}
|
|
7373
7907
|
),
|
|
7374
|
-
/* @__PURE__ */
|
|
7908
|
+
/* @__PURE__ */ jsx2(
|
|
7375
7909
|
"input",
|
|
7376
7910
|
{
|
|
7377
7911
|
style: fieldStyle,
|
|
@@ -7383,7 +7917,7 @@ function SponsorRelayFab(props) {
|
|
|
7383
7917
|
placeholder: "Service origin override (optional, defaults to runtime proxy URL)"
|
|
7384
7918
|
}
|
|
7385
7919
|
),
|
|
7386
|
-
/* @__PURE__ */
|
|
7920
|
+
/* @__PURE__ */ jsx2(
|
|
7387
7921
|
"div",
|
|
7388
7922
|
{
|
|
7389
7923
|
style: {
|
|
@@ -7417,20 +7951,21 @@ function SponsorRelayFab(props) {
|
|
|
7417
7951
|
formatNumber(state.pricingSummary.requiredCredits, 0),
|
|
7418
7952
|
" credits required"
|
|
7419
7953
|
] }),
|
|
7420
|
-
/* @__PURE__ */
|
|
7421
|
-
/* @__PURE__ */
|
|
7954
|
+
/* @__PURE__ */ jsx2("div", { children: state.rootfsHealth.label }),
|
|
7955
|
+
/* @__PURE__ */ jsx2("div", { children: /* @__PURE__ */ jsxs(
|
|
7422
7956
|
"select",
|
|
7423
7957
|
{
|
|
7958
|
+
style: fieldStyle,
|
|
7424
7959
|
"aria-label": "Select CRN",
|
|
7425
7960
|
value: state.crnPinnedByUser ? state.selectedCrn?.hash ?? "" : "",
|
|
7426
7961
|
onChange: (event) => controller.selectCrn(event.currentTarget.value || null),
|
|
7427
7962
|
children: [
|
|
7428
|
-
/* @__PURE__ */ jsxs("option", { value: "", children: [
|
|
7963
|
+
/* @__PURE__ */ jsxs("option", { style: optionStyle, value: "", children: [
|
|
7429
7964
|
"Auto (",
|
|
7430
7965
|
state.crnOptions[0]?.name ?? "best score",
|
|
7431
7966
|
")"
|
|
7432
7967
|
] }),
|
|
7433
|
-
state.crnOptions.map((option) => /* @__PURE__ */
|
|
7968
|
+
state.crnOptions.map((option) => /* @__PURE__ */ jsx2("option", { style: optionStyle, value: option.hash, children: (option.name ?? option.hash.slice(0, 8)) + (option.score != null ? ` \xB7 ${option.score.toFixed(2)}` : "") }, option.hash))
|
|
7434
7969
|
]
|
|
7435
7970
|
}
|
|
7436
7971
|
) }),
|
|
@@ -7458,11 +7993,11 @@ function SponsorRelayFab(props) {
|
|
|
7458
7993
|
color: "var(--rb-text)"
|
|
7459
7994
|
},
|
|
7460
7995
|
children: [
|
|
7461
|
-
/* @__PURE__ */
|
|
7462
|
-
/* @__PURE__ */
|
|
7996
|
+
/* @__PURE__ */ jsx2("strong", { children: "Rootfs unavailable \u2014 deployment blocked" }),
|
|
7997
|
+
/* @__PURE__ */ jsx2("span", { style: { fontSize: "0.82rem", lineHeight: 1.45 }, children: state.rootfsHealth.detail }),
|
|
7463
7998
|
/* @__PURE__ */ jsxs("span", { style: { fontSize: "0.75rem", lineHeight: 1.4 }, children: [
|
|
7464
7999
|
"This is separate from the connected MetaMask balance. The manifest must reference an Aleph rootfs STORE with status ",
|
|
7465
|
-
/* @__PURE__ */
|
|
8000
|
+
/* @__PURE__ */ jsx2("code", { children: "processed" }),
|
|
7466
8001
|
"."
|
|
7467
8002
|
] }),
|
|
7468
8003
|
state.manifest?.rootfsItemHash ? /* @__PURE__ */ jsxs("code", { style: { fontSize: "0.7rem", overflowWrap: "anywhere" }, children: [
|
|
@@ -7471,14 +8006,14 @@ function SponsorRelayFab(props) {
|
|
|
7471
8006
|
state.rootfsResolution?.messageStatus ? ` \xB7 Aleph status: ${state.rootfsResolution.messageStatus}` : ""
|
|
7472
8007
|
] }) : null,
|
|
7473
8008
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: [
|
|
7474
|
-
/* @__PURE__ */
|
|
7475
|
-
/* @__PURE__ */
|
|
7476
|
-
/^https?:\/\//.test(state.manifestUrl) ? /* @__PURE__ */
|
|
8009
|
+
/* @__PURE__ */ jsx2("button", { type: "button", onClick: () => void controller.refresh(), disabled: state.busy.refreshing, style: { ...secondaryButtonStyle, padding: "0.55rem 0.7rem" }, children: state.busy.refreshing ? "Checking\u2026" : "Retry validation" }),
|
|
8010
|
+
/* @__PURE__ */ jsx2("button", { type: "button", onClick: () => controller.setShowAdvanced(true), style: { ...secondaryButtonStyle, padding: "0.55rem 0.7rem" }, children: "Edit manifest URL" }),
|
|
8011
|
+
/^https?:\/\//.test(state.manifestUrl) ? /* @__PURE__ */ jsx2("a", { href: state.manifestUrl, target: "_blank", rel: "noreferrer", style: { color: "var(--rb-link)", alignSelf: "center", fontSize: "0.78rem" }, children: "Open manifest" }) : null
|
|
7477
8012
|
] })
|
|
7478
8013
|
]
|
|
7479
8014
|
}
|
|
7480
8015
|
) : null,
|
|
7481
|
-
/* @__PURE__ */
|
|
8016
|
+
/* @__PURE__ */ jsx2(
|
|
7482
8017
|
"button",
|
|
7483
8018
|
{
|
|
7484
8019
|
type: "button",
|
|
@@ -7518,7 +8053,7 @@ function SponsorRelayFab(props) {
|
|
|
7518
8053
|
open: true,
|
|
7519
8054
|
style: containedContentStyle,
|
|
7520
8055
|
children: [
|
|
7521
|
-
/* @__PURE__ */
|
|
8056
|
+
/* @__PURE__ */ jsx2("summary", { style: containedContentStyle, children: /* @__PURE__ */ jsxs(
|
|
7522
8057
|
"span",
|
|
7523
8058
|
{
|
|
7524
8059
|
style: {
|
|
@@ -7544,7 +8079,7 @@ function SponsorRelayFab(props) {
|
|
|
7544
8079
|
fontWeight: 700
|
|
7545
8080
|
},
|
|
7546
8081
|
children: [
|
|
7547
|
-
/* @__PURE__ */
|
|
8082
|
+
/* @__PURE__ */ jsx2(
|
|
7548
8083
|
"span",
|
|
7549
8084
|
{
|
|
7550
8085
|
"aria-hidden": "true",
|
|
@@ -7574,57 +8109,264 @@ function SponsorRelayFab(props) {
|
|
|
7574
8109
|
marginTop: "0.55rem"
|
|
7575
8110
|
},
|
|
7576
8111
|
children: [
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
8112
|
+
(() => {
|
|
8113
|
+
const itemHash = entry.instance.item_hash;
|
|
8114
|
+
const tab = instanceTabs[itemHash] ?? "general";
|
|
8115
|
+
const addresses = state.instanceAddresses?.[itemHash] ?? null;
|
|
8116
|
+
const refreshRow = /* @__PURE__ */ jsxs(
|
|
8117
|
+
"div",
|
|
8118
|
+
{
|
|
8119
|
+
style: {
|
|
8120
|
+
display: "flex",
|
|
8121
|
+
alignItems: "center",
|
|
8122
|
+
justifyContent: "space-between",
|
|
8123
|
+
gap: "0.5rem",
|
|
8124
|
+
marginBottom: "0.5rem"
|
|
8125
|
+
},
|
|
8126
|
+
children: [
|
|
8127
|
+
/* @__PURE__ */ jsx2(
|
|
8128
|
+
"span",
|
|
8129
|
+
{
|
|
8130
|
+
style: {
|
|
8131
|
+
color: "var(--rb-muted)",
|
|
8132
|
+
fontSize: "0.6875rem",
|
|
8133
|
+
overflowWrap: "anywhere"
|
|
8134
|
+
},
|
|
8135
|
+
children: addresses?.sourceUrl ?? "Reading from the deployment"
|
|
8136
|
+
}
|
|
8137
|
+
),
|
|
8138
|
+
/* @__PURE__ */ jsx2(
|
|
8139
|
+
"button",
|
|
8140
|
+
{
|
|
8141
|
+
type: "button",
|
|
8142
|
+
style: secondaryButtonStyle,
|
|
8143
|
+
disabled: addresses?.status === "loading",
|
|
8144
|
+
onClick: () => void controller.loadInstanceAddresses(
|
|
8145
|
+
itemHash,
|
|
8146
|
+
{ force: true }
|
|
8147
|
+
),
|
|
8148
|
+
children: addresses?.status === "loading" ? "Loading\u2026" : "Refresh"
|
|
8149
|
+
}
|
|
8150
|
+
)
|
|
8151
|
+
]
|
|
8152
|
+
}
|
|
8153
|
+
);
|
|
8154
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8155
|
+
/* @__PURE__ */ jsx2("div", { style: tabBarStyle, role: "tablist", children: [
|
|
8156
|
+
["general", "General"],
|
|
8157
|
+
["addresses", addressTabLabel(addresses)],
|
|
8158
|
+
["health", "Health"]
|
|
8159
|
+
].map(([key, label]) => /* @__PURE__ */ jsx2(
|
|
8160
|
+
"button",
|
|
8161
|
+
{
|
|
8162
|
+
type: "button",
|
|
8163
|
+
role: "tab",
|
|
8164
|
+
"aria-selected": tab === key,
|
|
8165
|
+
style: tabStyle(tab === key),
|
|
8166
|
+
onClick: () => selectInstanceTab(itemHash, key),
|
|
8167
|
+
children: label
|
|
8168
|
+
},
|
|
8169
|
+
key
|
|
8170
|
+
)) }),
|
|
8171
|
+
tab === "addresses" ? /* @__PURE__ */ jsxs("div", { style: containedContentStyle, children: [
|
|
8172
|
+
refreshRow,
|
|
8173
|
+
addresses?.status === "loading" && !addresses.groups.length ? /* @__PURE__ */ jsx2("div", { children: "Reading the deployment's address document\u2026" }) : addresses?.status === "unsupported" || addresses?.status === "error" ? /* @__PURE__ */ jsx2("div", { children: addresses.error }) : addresses?.groups.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8174
|
+
addresses.peerId ? /* @__PURE__ */ jsxs("div", { style: addressRowStyle, children: [
|
|
8175
|
+
/* @__PURE__ */ jsx2("code", { children: addresses.peerId }),
|
|
8176
|
+
/* @__PURE__ */ jsx2(CopyButton, { text: addresses.peerId })
|
|
8177
|
+
] }) : null,
|
|
8178
|
+
addresses.groups.map((group) => /* @__PURE__ */ jsxs(
|
|
8179
|
+
"div",
|
|
8180
|
+
{
|
|
8181
|
+
style: { marginBottom: "0.75rem" },
|
|
8182
|
+
children: [
|
|
8183
|
+
/* @__PURE__ */ jsxs(
|
|
8184
|
+
"div",
|
|
8185
|
+
{
|
|
8186
|
+
style: {
|
|
8187
|
+
display: "flex",
|
|
8188
|
+
alignItems: "center",
|
|
8189
|
+
justifyContent: "space-between",
|
|
8190
|
+
gap: "0.5rem"
|
|
8191
|
+
},
|
|
8192
|
+
children: [
|
|
8193
|
+
/* @__PURE__ */ jsx2("strong", { children: group.label }),
|
|
8194
|
+
/* @__PURE__ */ jsx2(
|
|
8195
|
+
CopyButton,
|
|
8196
|
+
{
|
|
8197
|
+
text: group.addresses.join("\n"),
|
|
8198
|
+
label: "Copy group"
|
|
8199
|
+
}
|
|
8200
|
+
)
|
|
8201
|
+
]
|
|
8202
|
+
}
|
|
8203
|
+
),
|
|
8204
|
+
group.addresses.map((address) => /* @__PURE__ */ jsxs(
|
|
8205
|
+
"div",
|
|
8206
|
+
{
|
|
8207
|
+
style: addressRowStyle,
|
|
8208
|
+
children: [
|
|
8209
|
+
/* @__PURE__ */ jsx2("code", { children: address }),
|
|
8210
|
+
/* @__PURE__ */ jsx2(CopyButton, { text: address })
|
|
8211
|
+
]
|
|
8212
|
+
},
|
|
8213
|
+
address
|
|
8214
|
+
))
|
|
8215
|
+
]
|
|
8216
|
+
},
|
|
8217
|
+
group.key
|
|
8218
|
+
)),
|
|
8219
|
+
/* @__PURE__ */ jsxs(
|
|
8220
|
+
"div",
|
|
8221
|
+
{
|
|
8222
|
+
style: { display: "flex", gap: "0.5rem" },
|
|
8223
|
+
children: [
|
|
8224
|
+
/* @__PURE__ */ jsx2(
|
|
8225
|
+
CopyButton,
|
|
8226
|
+
{
|
|
8227
|
+
text: copyAllText(addresses),
|
|
8228
|
+
label: "Copy all"
|
|
8229
|
+
}
|
|
8230
|
+
),
|
|
8231
|
+
/* @__PURE__ */ jsx2(
|
|
8232
|
+
CopyButton,
|
|
8233
|
+
{
|
|
8234
|
+
text: JSON.stringify(
|
|
8235
|
+
addresses.payload,
|
|
8236
|
+
null,
|
|
8237
|
+
2
|
|
8238
|
+
),
|
|
8239
|
+
label: "Copy JSON"
|
|
8240
|
+
}
|
|
8241
|
+
)
|
|
8242
|
+
]
|
|
8243
|
+
}
|
|
8244
|
+
)
|
|
8245
|
+
] }) : addresses?.pwaEnv ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8246
|
+
/* @__PURE__ */ jsxs(
|
|
8247
|
+
"div",
|
|
8248
|
+
{
|
|
8249
|
+
style: {
|
|
8250
|
+
display: "flex",
|
|
8251
|
+
alignItems: "center",
|
|
8252
|
+
justifyContent: "space-between",
|
|
8253
|
+
gap: "0.5rem"
|
|
8254
|
+
},
|
|
8255
|
+
children: [
|
|
8256
|
+
/* @__PURE__ */ jsx2("strong", { children: "PWA environment" }),
|
|
8257
|
+
/* @__PURE__ */ jsx2(
|
|
8258
|
+
CopyButton,
|
|
8259
|
+
{
|
|
8260
|
+
text: pwaEnvText(addresses),
|
|
8261
|
+
label: "Copy block"
|
|
8262
|
+
}
|
|
8263
|
+
)
|
|
8264
|
+
]
|
|
8265
|
+
}
|
|
8266
|
+
),
|
|
8267
|
+
Object.entries(addresses.pwaEnv).map(
|
|
8268
|
+
([key, value]) => /* @__PURE__ */ jsxs(
|
|
8269
|
+
"div",
|
|
8270
|
+
{
|
|
8271
|
+
style: addressRowStyle,
|
|
8272
|
+
children: [
|
|
8273
|
+
/* @__PURE__ */ jsx2("code", { children: `${key}=${value}` }),
|
|
8274
|
+
/* @__PURE__ */ jsx2(
|
|
8275
|
+
CopyButton,
|
|
8276
|
+
{
|
|
8277
|
+
text: `${key}=${value}`
|
|
8278
|
+
}
|
|
8279
|
+
)
|
|
8280
|
+
]
|
|
8281
|
+
},
|
|
8282
|
+
key
|
|
8283
|
+
)
|
|
8284
|
+
)
|
|
8285
|
+
] }) : /* @__PURE__ */ jsx2("div", { children: "This deployment reports no addresses yet." })
|
|
8286
|
+
] }) : null,
|
|
8287
|
+
tab === "health" ? /* @__PURE__ */ jsxs("div", { style: containedContentStyle, children: [
|
|
8288
|
+
refreshRow,
|
|
8289
|
+
addresses?.payload ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8290
|
+
/* @__PURE__ */ jsx2("pre", { style: payloadStyle, children: JSON.stringify(
|
|
8291
|
+
addresses.payload,
|
|
8292
|
+
null,
|
|
8293
|
+
2
|
|
8294
|
+
) }),
|
|
8295
|
+
/* @__PURE__ */ jsx2(
|
|
8296
|
+
CopyButton,
|
|
8297
|
+
{
|
|
8298
|
+
text: JSON.stringify(
|
|
8299
|
+
addresses.payload,
|
|
8300
|
+
null,
|
|
8301
|
+
2
|
|
8302
|
+
),
|
|
8303
|
+
label: "Copy JSON"
|
|
8304
|
+
}
|
|
8305
|
+
)
|
|
8306
|
+
] }) : addresses?.status === "loading" ? /* @__PURE__ */ jsx2("div", { children: "Reading the deployment's health document\u2026" }) : /* @__PURE__ */ jsx2("div", { children: addresses?.error ?? "No health document read yet." })
|
|
8307
|
+
] }) : null
|
|
8308
|
+
] });
|
|
8309
|
+
})(),
|
|
8310
|
+
(instanceTabs[entry.instance.item_hash] ?? "general") !== "general" ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8311
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8312
|
+
"Status: ",
|
|
8313
|
+
entry.details.messageStatus
|
|
8314
|
+
] }),
|
|
8315
|
+
bootstrapUiEnabled && confirmedRegistration ? /* @__PURE__ */ jsxs("div", { children: [
|
|
8316
|
+
"Bootstrap registration:",
|
|
8317
|
+
" ",
|
|
8318
|
+
shortHash(
|
|
8319
|
+
confirmedRegistration.messageHash ?? confirmedRegistration.content?.registrationId ?? "confirmed",
|
|
8320
|
+
14,
|
|
8321
|
+
8
|
|
8322
|
+
)
|
|
8323
|
+
] }) : null,
|
|
8324
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8325
|
+
"Host IPv4: ",
|
|
8326
|
+
entry.details.hostIpv4 ?? "-"
|
|
8327
|
+
] }),
|
|
8328
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8329
|
+
"IPv6: ",
|
|
8330
|
+
entry.details.ipv6 ?? "-"
|
|
8331
|
+
] }),
|
|
8332
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8333
|
+
"VM IPv4: ",
|
|
8334
|
+
entry.details.vmIpv4 ?? "-"
|
|
8335
|
+
] }),
|
|
8336
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8337
|
+
"SSH: ",
|
|
8338
|
+
entry.details.sshCommand ?? "-"
|
|
8339
|
+
] }),
|
|
8340
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8341
|
+
"Ports: ",
|
|
8342
|
+
joinMappedPorts(entry.details.mappedPorts)
|
|
8343
|
+
] }),
|
|
8344
|
+
entry.details.proxyHostname ? /* @__PURE__ */ jsxs("div", { style: addressRowStyle, children: [
|
|
8345
|
+
/* @__PURE__ */ jsxs("code", { children: [
|
|
8346
|
+
"Proxy: ",
|
|
8347
|
+
entry.details.proxyHostname
|
|
8348
|
+
] }),
|
|
8349
|
+
/* @__PURE__ */ jsx2(CopyButton, { text: entry.details.proxyHostname })
|
|
8350
|
+
] }) : null,
|
|
8351
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8352
|
+
"Submitted:",
|
|
8353
|
+
" ",
|
|
8354
|
+
formatDateTime(
|
|
8355
|
+
entry.instance.reception_time ?? entry.instance.time
|
|
8356
|
+
)
|
|
8357
|
+
] }),
|
|
8358
|
+
/* @__PURE__ */ jsx2(
|
|
8359
|
+
"button",
|
|
8360
|
+
{
|
|
8361
|
+
type: "button",
|
|
8362
|
+
style: dangerButtonStyle,
|
|
8363
|
+
onClick: () => void controller.deleteInstance(
|
|
8364
|
+
entry.instance.item_hash
|
|
8365
|
+
),
|
|
8366
|
+
children: state.busy.deletingInstanceHash === entry.instance.item_hash ? "Deleting\u2026" : "Delete"
|
|
8367
|
+
}
|
|
7615
8368
|
)
|
|
7616
|
-
] })
|
|
7617
|
-
/* @__PURE__ */ jsx(
|
|
7618
|
-
"button",
|
|
7619
|
-
{
|
|
7620
|
-
type: "button",
|
|
7621
|
-
style: dangerButtonStyle,
|
|
7622
|
-
onClick: () => void controller.deleteInstance(
|
|
7623
|
-
entry.instance.item_hash
|
|
7624
|
-
),
|
|
7625
|
-
children: state.busy.deletingInstanceHash === entry.instance.item_hash ? "Deleting\u2026" : "Delete"
|
|
7626
|
-
}
|
|
7627
|
-
)
|
|
8369
|
+
] })
|
|
7628
8370
|
]
|
|
7629
8371
|
}
|
|
7630
8372
|
)
|
|
@@ -7647,8 +8389,8 @@ function SponsorRelayFab(props) {
|
|
|
7647
8389
|
},
|
|
7648
8390
|
children: [
|
|
7649
8391
|
/* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "0.2rem" }, children: [
|
|
7650
|
-
/* @__PURE__ */
|
|
7651
|
-
/* @__PURE__ */
|
|
8392
|
+
/* @__PURE__ */ jsx2("strong", { children: "Orphan bootstrap registrations" }),
|
|
8393
|
+
/* @__PURE__ */ jsx2("small", { style: { color: "var(--rb-muted)", lineHeight: 1.35 }, children: "Current-wallet registrations without a matching instance. Forget them directly from here." })
|
|
7652
8394
|
] }),
|
|
7653
8395
|
orphanRegistrations.map((entry) => {
|
|
7654
8396
|
const registrationHash = entry.messageHash ?? entry.hash ?? null;
|
|
@@ -7665,7 +8407,7 @@ function SponsorRelayFab(props) {
|
|
|
7665
8407
|
border: "1px solid var(--rb-border)"
|
|
7666
8408
|
},
|
|
7667
8409
|
children: [
|
|
7668
|
-
/* @__PURE__ */
|
|
8410
|
+
/* @__PURE__ */ jsx2(
|
|
7669
8411
|
"div",
|
|
7670
8412
|
{
|
|
7671
8413
|
style: {
|
|
@@ -7694,7 +8436,7 @@ function SponsorRelayFab(props) {
|
|
|
7694
8436
|
" ",
|
|
7695
8437
|
formatDateTime(entry.content?.updatedAt ?? entry.time)
|
|
7696
8438
|
] }),
|
|
7697
|
-
/* @__PURE__ */
|
|
8439
|
+
/* @__PURE__ */ jsx2(
|
|
7698
8440
|
"button",
|
|
7699
8441
|
{
|
|
7700
8442
|
type: "button",
|