@le-space/ui 0.3.0 → 0.3.3
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 +4 -0
- package/react/index.js +496 -55
- package/shared/index.d.ts +7 -1
- package/shared/index.js +397 -14
- package/styles.css +9 -5
- package/svelte/SponsorRelayFab.svelte +67 -18
- package/svelte/components/LauncherButton.svelte +3 -3
- package/svelte/styles/theme.css +9 -5
package/shared/index.d.ts
CHANGED
|
@@ -260,6 +260,7 @@ interface SponsorRelayState {
|
|
|
260
260
|
sshPublicKey: string;
|
|
261
261
|
instanceName: string;
|
|
262
262
|
tierId: string;
|
|
263
|
+
showAdvanced: boolean;
|
|
263
264
|
showInstances: boolean;
|
|
264
265
|
showPasteManifest: boolean;
|
|
265
266
|
busy: {
|
|
@@ -294,6 +295,7 @@ declare const RELAY_PING_IDLE_STATE: RelayPingState;
|
|
|
294
295
|
declare const IDLE_DEPLOYMENT_PROGRESS: DeploymentProgressEvent;
|
|
295
296
|
declare const REFRESH_INTERVAL_MS = 30000;
|
|
296
297
|
declare const RELAY_PING_INTERVAL_MS = 20000;
|
|
298
|
+
declare const MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS = 400;
|
|
297
299
|
declare const INSTANCE_RUNTIME_READY_REFRESH_MS = 30000;
|
|
298
300
|
declare const INSTANCE_RUNTIME_PENDING_REFRESH_MS = 45000;
|
|
299
301
|
declare const INSTANCE_RUNTIME_STALE_REFRESH_MS: number;
|
|
@@ -311,6 +313,7 @@ interface RootfsRequiredPortForward {
|
|
|
311
313
|
declare function shortHash(value: string | null | undefined, head?: number, tail?: number): string;
|
|
312
314
|
declare function formatNumber(value: number | null | undefined, digits?: number): string;
|
|
313
315
|
declare function formatDateTime(value: string | number | null | undefined): string;
|
|
316
|
+
declare function formatTierSpecLabel(vcpus: number | null | undefined, memoryMiB: number | null | undefined, diskMiB: number | null | undefined): string;
|
|
314
317
|
declare function buildSshCommand(hostIpv4: string | null, mappedPorts: CompactInstanceRecord["details"]["mappedPorts"]): string | null;
|
|
315
318
|
declare function joinMappedPorts(mappedPorts: CompactInstanceRecord["details"]["mappedPorts"]): string;
|
|
316
319
|
declare function joinRequiredPortForwards(portForwards: ReadonlyArray<RootfsRequiredPortForward> | null | undefined): string;
|
|
@@ -340,6 +343,7 @@ declare class SponsorRelayController {
|
|
|
340
343
|
private client;
|
|
341
344
|
private refreshTimer;
|
|
342
345
|
private pingTimer;
|
|
346
|
+
private manifestRefreshTimer;
|
|
343
347
|
private stopWalletWatch;
|
|
344
348
|
private props;
|
|
345
349
|
private progressEmitter;
|
|
@@ -368,11 +372,13 @@ declare class SponsorRelayController {
|
|
|
368
372
|
toggleOpen(): void;
|
|
369
373
|
setManifestUrl(manifestUrl: string): void;
|
|
370
374
|
setManifestJson(manifestJson: string): void;
|
|
375
|
+
setShowAdvanced(showAdvanced: boolean): void;
|
|
371
376
|
setShowPasteManifest(showPasteManifest: boolean): void;
|
|
372
377
|
setSshPublicKey(sshPublicKey: string): void;
|
|
373
378
|
setInstanceName(instanceName: string): void;
|
|
374
379
|
setTierId(tierId: string): void;
|
|
375
380
|
private recomputePricingSummary;
|
|
381
|
+
private queueManifestRefresh;
|
|
376
382
|
connectWallet(): Promise<void>;
|
|
377
383
|
private refreshWalletDerivedState;
|
|
378
384
|
refresh(): Promise<void>;
|
|
@@ -389,4 +395,4 @@ interface DeploymentProgressEmitter {
|
|
|
389
395
|
}
|
|
390
396
|
declare function createDeploymentProgressEmitter(): DeploymentProgressEmitter;
|
|
391
397
|
|
|
392
|
-
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, RECENT_INSTANCE_RUNTIME_GRACE_MS, REFRESH_INTERVAL_MS, RELAY_PING_IDLE_STATE, RELAY_PING_INTERVAL_MS, ROOTFS_MISSING_STATE, type RelayPingState, STALE_INSTANCE_ALLOCATION_COOLDOWN_MS, SponsorRelayController, type SponsorRelayHealthTone, type SponsorRelayPricingSummary, type SponsorRelayProps, type SponsorRelayRootfsHealth, type SponsorRelayState, type SponsorRelaySubscriber, type SponsorRelayWalletState, buildSshCommand, connectWallet, createDeploymentProgressEmitter, createSponsorRelayController, formatDateTime, formatNumber, getEthereumProvider, joinMappedPorts, joinRequiredPortForwards, personalSign, resolveManifestSource, shortHash, toChecksumAddress, watchWallet };
|
|
398
|
+
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, RELAY_PING_IDLE_STATE, RELAY_PING_INTERVAL_MS, ROOTFS_MISSING_STATE, type RelayPingState, STALE_INSTANCE_ALLOCATION_COOLDOWN_MS, SponsorRelayController, type SponsorRelayHealthTone, type SponsorRelayPricingSummary, type SponsorRelayProps, type SponsorRelayRootfsHealth, type SponsorRelayState, type SponsorRelaySubscriber, type SponsorRelayWalletState, buildSshCommand, connectWallet, createDeploymentProgressEmitter, createSponsorRelayController, formatDateTime, formatNumber, formatTierSpecLabel, getEthereumProvider, joinMappedPorts, joinRequiredPortForwards, personalSign, resolveManifestSource, shortHash, toChecksumAddress, watchWallet };
|
package/shared/index.js
CHANGED
|
@@ -29,6 +29,7 @@ var IDLE_DEPLOYMENT_PROGRESS = {
|
|
|
29
29
|
};
|
|
30
30
|
var REFRESH_INTERVAL_MS = 3e4;
|
|
31
31
|
var RELAY_PING_INTERVAL_MS = 2e4;
|
|
32
|
+
var MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS = 400;
|
|
32
33
|
var INSTANCE_RUNTIME_READY_REFRESH_MS = 3e4;
|
|
33
34
|
var INSTANCE_RUNTIME_PENDING_REFRESH_MS = 45e3;
|
|
34
35
|
var INSTANCE_RUNTIME_STALE_REFRESH_MS = 5 * 6e4;
|
|
@@ -56,6 +57,12 @@ function formatDateTime(value) {
|
|
|
56
57
|
if (Number.isNaN(date.getTime())) return String(value);
|
|
57
58
|
return date.toLocaleString();
|
|
58
59
|
}
|
|
60
|
+
function formatTierSpecLabel(vcpus, memoryMiB, diskMiB) {
|
|
61
|
+
if (vcpus == null || !Number.isFinite(vcpus) || memoryMiB == null || !Number.isFinite(memoryMiB) || diskMiB == null || !Number.isFinite(diskMiB)) {
|
|
62
|
+
return "-";
|
|
63
|
+
}
|
|
64
|
+
return `(${formatNumber(vcpus, 0)} vCPU \xB7 ${formatNumber(memoryMiB / 1024, 1)} GiB RAM \xB7 ${formatNumber(diskMiB / 1024, 0)} GiB disk)`;
|
|
65
|
+
}
|
|
59
66
|
function buildSshCommand(hostIpv4, mappedPorts2) {
|
|
60
67
|
if (!hostIpv4) return null;
|
|
61
68
|
const sshPort = mappedPorts2.find((entry) => entry.label.startsWith("22/"))?.hostPort ?? 22;
|
|
@@ -401,6 +408,18 @@ function extractReferenceHashes(details) {
|
|
|
401
408
|
if (!Array.isArray(errors)) return [];
|
|
402
409
|
return errors.filter((value) => typeof value === "string");
|
|
403
410
|
}
|
|
411
|
+
function extractInsufficientBalanceMessage(details) {
|
|
412
|
+
if (!details || typeof details !== "object" || !("errors" in details)) return null;
|
|
413
|
+
const errors = details.errors;
|
|
414
|
+
const firstError = Array.isArray(errors) && errors[0] && typeof errors[0] === "object" ? errors[0] : null;
|
|
415
|
+
const accountBalance = typeof firstError?.account_balance === "number" || typeof firstError?.account_balance === "string" ? Number(firstError.account_balance) : Number.NaN;
|
|
416
|
+
const requiredBalance = typeof firstError?.required_balance === "number" || typeof firstError?.required_balance === "string" ? Number(firstError.required_balance) : Number.NaN;
|
|
417
|
+
if (!Number.isFinite(accountBalance) || !Number.isFinite(requiredBalance)) {
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
const shortfall = requiredBalance - accountBalance;
|
|
421
|
+
return shortfall > 0 ? `insufficient Aleph balance: ${accountBalance.toFixed(3)} available, ${requiredBalance.toFixed(3)} required, ${shortfall.toFixed(3)} short` : `insufficient Aleph balance: ${accountBalance.toFixed(3)} available, ${requiredBalance.toFixed(3)} required`;
|
|
422
|
+
}
|
|
404
423
|
function describeRejectedDeployment(payload, references, rootfsRef) {
|
|
405
424
|
const errorCode = typeof payload.error_code === "number" ? payload.error_code : null;
|
|
406
425
|
const pendingReferences = references.filter((reference) => reference.status === "pending");
|
|
@@ -415,6 +434,10 @@ function describeRejectedDeployment(payload, references, rootfsRef) {
|
|
|
415
434
|
if (missingReferences.length > 0) {
|
|
416
435
|
return `Aleph rejected this deployment because referenced message(s) were not found on Aleph: ${missingReferences.map((reference) => reference.itemHash).join(", ")}.`;
|
|
417
436
|
}
|
|
437
|
+
const insufficientBalanceMessage = extractInsufficientBalanceMessage(payload.details);
|
|
438
|
+
if (insufficientBalanceMessage) {
|
|
439
|
+
return `Aleph rejected this deployment due to ${insufficientBalanceMessage}.`;
|
|
440
|
+
}
|
|
418
441
|
const referencedHashes = extractReferenceHashes(payload.details);
|
|
419
442
|
if (referencedHashes.length > 0) {
|
|
420
443
|
return `Aleph rejected this deployment${errorCode ? ` (error ${errorCode})` : ""}. Referenced message(s): ${referencedHashes.join(", ")}.`;
|
|
@@ -1027,6 +1050,20 @@ function extractReferenceHashes2(details) {
|
|
|
1027
1050
|
if (!Array.isArray(errors)) return [];
|
|
1028
1051
|
return errors.filter((value) => typeof value === "string");
|
|
1029
1052
|
}
|
|
1053
|
+
function extractInsufficientBalanceMessage2(details) {
|
|
1054
|
+
if (!details || typeof details !== "object" || !("errors" in details)) {
|
|
1055
|
+
return null;
|
|
1056
|
+
}
|
|
1057
|
+
const errors = details.errors;
|
|
1058
|
+
const firstError = Array.isArray(errors) && errors[0] && typeof errors[0] === "object" ? errors[0] : null;
|
|
1059
|
+
const accountBalance = typeof firstError?.account_balance === "number" || typeof firstError?.account_balance === "string" ? Number(firstError.account_balance) : Number.NaN;
|
|
1060
|
+
const requiredBalance = typeof firstError?.required_balance === "number" || typeof firstError?.required_balance === "string" ? Number(firstError.required_balance) : Number.NaN;
|
|
1061
|
+
if (!Number.isFinite(accountBalance) || !Number.isFinite(requiredBalance)) {
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
const shortfall = requiredBalance - accountBalance;
|
|
1065
|
+
return shortfall > 0 ? `insufficient Aleph balance: ${accountBalance.toFixed(3)} available, ${requiredBalance.toFixed(3)} required, ${shortfall.toFixed(3)} short` : `insufficient Aleph balance: ${accountBalance.toFixed(3)} available, ${requiredBalance.toFixed(3)} required`;
|
|
1066
|
+
}
|
|
1030
1067
|
function describeRejectedDeployment2(payload, references, rootfsRef) {
|
|
1031
1068
|
const errorCode = typeof payload.error_code === "number" ? payload.error_code : null;
|
|
1032
1069
|
const pendingReferences = references.filter((reference) => reference.status === "pending");
|
|
@@ -1041,6 +1078,10 @@ function describeRejectedDeployment2(payload, references, rootfsRef) {
|
|
|
1041
1078
|
if (missingReferences.length > 0) {
|
|
1042
1079
|
return `Aleph rejected this deployment because referenced message(s) were not found on Aleph: ${missingReferences.map((reference) => reference.itemHash).join(", ")}.`;
|
|
1043
1080
|
}
|
|
1081
|
+
const insufficientBalanceMessage = extractInsufficientBalanceMessage2(payload.details);
|
|
1082
|
+
if (insufficientBalanceMessage) {
|
|
1083
|
+
return `Aleph rejected this deployment due to ${insufficientBalanceMessage}.`;
|
|
1084
|
+
}
|
|
1044
1085
|
const referencedHashes = extractReferenceHashes2(payload.details);
|
|
1045
1086
|
if (referencedHashes.length > 0) {
|
|
1046
1087
|
return `Aleph rejected this deployment${errorCode ? ` (error ${errorCode})` : ""}. Referenced message(s): ${referencedHashes.join(", ")}.`;
|
|
@@ -1453,6 +1494,14 @@ function buildPaymentQuote(tier, pricing, balance) {
|
|
|
1453
1494
|
label: "credits"
|
|
1454
1495
|
};
|
|
1455
1496
|
}
|
|
1497
|
+
function describeRejectedInstanceBroadcast(response) {
|
|
1498
|
+
const balanceMessage = extractInsufficientBalanceMessage2(response.details);
|
|
1499
|
+
if (balanceMessage) {
|
|
1500
|
+
return `Aleph rejected this deployment due to ${balanceMessage}.`;
|
|
1501
|
+
}
|
|
1502
|
+
const errorCode = typeof response.error_code === "number" ? response.error_code : null;
|
|
1503
|
+
return `Aleph rejected this deployment${errorCode ? ` (error ${errorCode})` : ""}.`;
|
|
1504
|
+
}
|
|
1456
1505
|
function createInstanceContent(args) {
|
|
1457
1506
|
const sshKey = normalizeSshPublicKey(args.sshPublicKey);
|
|
1458
1507
|
if (!sshKey) {
|
|
@@ -1569,9 +1618,9 @@ async function deployInstance(args) {
|
|
|
1569
1618
|
label: status === "processed" ? "Deployment accepted by Aleph" : status === "rejected" ? "Deployment rejected by Aleph" : "Deployment submitted to Aleph",
|
|
1570
1619
|
progress: status === "processed" ? 88 : status === "rejected" ? 100 : 78,
|
|
1571
1620
|
status: status === "processed" ? "success" : status === "rejected" ? "error" : "warning",
|
|
1572
|
-
detail: status === "rejected" ?
|
|
1621
|
+
detail: status === "rejected" ? describeRejectedInstanceBroadcast(response) : null,
|
|
1573
1622
|
itemHash: message.item_hash,
|
|
1574
|
-
error: status === "rejected" ?
|
|
1623
|
+
error: status === "rejected" ? describeRejectedInstanceBroadcast(response) : null,
|
|
1575
1624
|
timestamp: Date.now()
|
|
1576
1625
|
});
|
|
1577
1626
|
return {
|
|
@@ -1580,7 +1629,7 @@ async function deployInstance(args) {
|
|
|
1580
1629
|
status,
|
|
1581
1630
|
message,
|
|
1582
1631
|
response,
|
|
1583
|
-
rejectionReason: status === "rejected" ?
|
|
1632
|
+
rejectionReason: status === "rejected" ? describeRejectedInstanceBroadcast(response) : null
|
|
1584
1633
|
};
|
|
1585
1634
|
}
|
|
1586
1635
|
|
|
@@ -1970,7 +2019,13 @@ async function configureUcGoPeer(args) {
|
|
|
1970
2019
|
ws_port: args.wsPort ?? void 0,
|
|
1971
2020
|
udp_port: args.udpPort ?? void 0,
|
|
1972
2021
|
quic_port: args.quicPort ?? void 0,
|
|
1973
|
-
webrtc_port: args.webrtcPort ?? void 0
|
|
2022
|
+
webrtc_port: args.webrtcPort ?? void 0,
|
|
2023
|
+
bootstrap_publisher_private_key: args.bootstrapPublisherPrivateKey ?? void 0,
|
|
2024
|
+
bootstrap_publisher_libp2p_identity_b64: args.bootstrapPublisherLibp2pIdentityBase64 ?? void 0,
|
|
2025
|
+
bootstrap_owner_private_key: args.bootstrapOwnerPrivateKey ?? void 0,
|
|
2026
|
+
bootstrap_owner_authorization_b64: args.bootstrapOwnerAuthorizationBase64 ?? void 0,
|
|
2027
|
+
bootstrap_registration_id: args.bootstrapRegistrationId ?? void 0,
|
|
2028
|
+
no_start: args.noStart === true ? true : void 0
|
|
1974
2029
|
};
|
|
1975
2030
|
try {
|
|
1976
2031
|
const response = await args.fetch(
|
|
@@ -2010,7 +2065,13 @@ async function configureOrbitdbRelaySetup2(args) {
|
|
|
2010
2065
|
metrics_port: args.metricsPort ?? void 0,
|
|
2011
2066
|
metrics_https_port: args.metricsHttpsPort ?? void 0,
|
|
2012
2067
|
webrtc_port: args.webrtcPort ?? void 0,
|
|
2013
|
-
quic_port: args.quicPort ?? void 0
|
|
2068
|
+
quic_port: args.quicPort ?? void 0,
|
|
2069
|
+
bootstrap_publisher_private_key: args.bootstrapPublisherPrivateKey ?? void 0,
|
|
2070
|
+
bootstrap_publisher_libp2p_identity_hex: args.bootstrapPublisherLibp2pIdentityHex ?? void 0,
|
|
2071
|
+
bootstrap_owner_private_key: args.bootstrapOwnerPrivateKey ?? void 0,
|
|
2072
|
+
bootstrap_owner_authorization_b64: args.bootstrapOwnerAuthorizationBase64 ?? void 0,
|
|
2073
|
+
bootstrap_registration_id: args.bootstrapRegistrationId ?? void 0,
|
|
2074
|
+
no_start: args.noStart === true ? true : void 0
|
|
2014
2075
|
};
|
|
2015
2076
|
try {
|
|
2016
2077
|
const response = await args.fetch(
|
|
@@ -2084,14 +2145,56 @@ async function fetchUcGoPeerMetadata(args) {
|
|
|
2084
2145
|
}
|
|
2085
2146
|
|
|
2086
2147
|
// ../aleph-bootstrap/src/index.ts
|
|
2148
|
+
import { recoverMessageAddress } from "viem";
|
|
2087
2149
|
var DEFAULT_ALEPH_API_HOST3 = "https://api2.aleph.im";
|
|
2088
2150
|
var DEFAULT_ALEPH_BOOTSTRAP_CHANNEL = "simple-todo";
|
|
2089
2151
|
var DEFAULT_ALEPH_BOOTSTRAP_REF = "simple-todo-bootstrap";
|
|
2090
2152
|
var DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE = "relay-bootstrap";
|
|
2091
2153
|
var DEFAULT_BOOTSTRAP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2154
|
+
var DEFAULT_BOOTSTRAP_PAGINATION = 50;
|
|
2155
|
+
var RELAY_BOOTSTRAP_SIGNATURE_SCHEME = "personal_sign";
|
|
2156
|
+
function serializeOwnerAuthorizationPayload(payload) {
|
|
2157
|
+
return JSON.stringify({
|
|
2158
|
+
ownerAddress: payload.ownerAddress,
|
|
2159
|
+
publisherAddress: payload.publisherAddress,
|
|
2160
|
+
peerId: payload.peerId,
|
|
2161
|
+
registrationId: payload.registrationId,
|
|
2162
|
+
profile: payload.profile,
|
|
2163
|
+
version: payload.version,
|
|
2164
|
+
instanceItemHash: payload.instanceItemHash,
|
|
2165
|
+
issuedAt: payload.issuedAt,
|
|
2166
|
+
expiresAt: payload.expiresAt
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
function serializeRelayProofPayload(payload) {
|
|
2170
|
+
return JSON.stringify({
|
|
2171
|
+
peerId: payload.peerId,
|
|
2172
|
+
multiaddrs: dedupeMultiaddrs(payload.multiaddrs),
|
|
2173
|
+
browserMultiaddrs: payload.browserMultiaddrs ? dedupeMultiaddrs(payload.browserMultiaddrs) : void 0,
|
|
2174
|
+
registrationId: payload.registrationId,
|
|
2175
|
+
profile: payload.profile,
|
|
2176
|
+
version: payload.version,
|
|
2177
|
+
updatedAt: payload.updatedAt
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
function asTrimmedString(value) {
|
|
2181
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
2182
|
+
}
|
|
2183
|
+
function asNumber4(value) {
|
|
2184
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2185
|
+
if (typeof value === "string" && value.trim()) {
|
|
2186
|
+
const parsed = Number(value);
|
|
2187
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
2188
|
+
}
|
|
2189
|
+
return null;
|
|
2190
|
+
}
|
|
2092
2191
|
function normalizeHost(host) {
|
|
2093
2192
|
return host.trim().toLowerCase();
|
|
2094
2193
|
}
|
|
2194
|
+
function normalizeSignature(signature) {
|
|
2195
|
+
const trimmed = signature.trim();
|
|
2196
|
+
return trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
|
|
2197
|
+
}
|
|
2095
2198
|
function splitMultiaddr(addr) {
|
|
2096
2199
|
return addr.split("/").filter(Boolean);
|
|
2097
2200
|
}
|
|
@@ -2162,6 +2265,100 @@ function filterPublicMultiaddrs(addrs, options = {}) {
|
|
|
2162
2265
|
return true;
|
|
2163
2266
|
});
|
|
2164
2267
|
}
|
|
2268
|
+
function normalizeRelayBootstrapContent(value) {
|
|
2269
|
+
if (!value || typeof value !== "object") return null;
|
|
2270
|
+
const content = value;
|
|
2271
|
+
const peerId = asTrimmedString(content.peerId);
|
|
2272
|
+
const updatedAt = asNumber4(content.updatedAt);
|
|
2273
|
+
if (!peerId || updatedAt == null) return null;
|
|
2274
|
+
const multiaddrs = Array.isArray(content.multiaddrs) ? content.multiaddrs.filter((entry) => typeof entry === "string") : [];
|
|
2275
|
+
const browserMultiaddrs = Array.isArray(content.browserMultiaddrs) ? content.browserMultiaddrs.filter((entry) => typeof entry === "string") : void 0;
|
|
2276
|
+
return {
|
|
2277
|
+
peerId,
|
|
2278
|
+
multiaddrs: dedupeMultiaddrs(multiaddrs),
|
|
2279
|
+
browserMultiaddrs: browserMultiaddrs ? dedupeMultiaddrs(browserMultiaddrs) : void 0,
|
|
2280
|
+
registrationId: asTrimmedString(content.registrationId) ?? void 0,
|
|
2281
|
+
profile: asTrimmedString(content.profile) ?? void 0,
|
|
2282
|
+
version: asTrimmedString(content.version) ?? void 0,
|
|
2283
|
+
ownerAddress: asTrimmedString(content.ownerAddress) ?? void 0,
|
|
2284
|
+
publisherAddress: asTrimmedString(content.publisherAddress) ?? void 0,
|
|
2285
|
+
authorization: normalizeRelayBootstrapAuthorizationRecord(content.authorization) ?? void 0,
|
|
2286
|
+
relayProof: normalizeRelayBootstrapProofRecord(content.relayProof) ?? void 0,
|
|
2287
|
+
updatedAt
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
function normalizeRelayBootstrapAuthorizationPayload(value) {
|
|
2291
|
+
if (!value || typeof value !== "object") return null;
|
|
2292
|
+
const payload = value;
|
|
2293
|
+
const ownerAddress = asTrimmedString(payload.ownerAddress);
|
|
2294
|
+
const publisherAddress = asTrimmedString(payload.publisherAddress);
|
|
2295
|
+
const peerId = asTrimmedString(payload.peerId);
|
|
2296
|
+
const issuedAt = asNumber4(payload.issuedAt);
|
|
2297
|
+
const expiresAt = asNumber4(payload.expiresAt) ?? void 0;
|
|
2298
|
+
if (!ownerAddress || !publisherAddress || !peerId || issuedAt == null) {
|
|
2299
|
+
return null;
|
|
2300
|
+
}
|
|
2301
|
+
return {
|
|
2302
|
+
ownerAddress,
|
|
2303
|
+
publisherAddress,
|
|
2304
|
+
peerId,
|
|
2305
|
+
registrationId: asTrimmedString(payload.registrationId) ?? void 0,
|
|
2306
|
+
profile: asTrimmedString(payload.profile) ?? void 0,
|
|
2307
|
+
version: asTrimmedString(payload.version) ?? void 0,
|
|
2308
|
+
instanceItemHash: asTrimmedString(payload.instanceItemHash) ?? void 0,
|
|
2309
|
+
issuedAt,
|
|
2310
|
+
expiresAt
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
function normalizeRelayBootstrapAuthorizationRecord(value) {
|
|
2314
|
+
if (!value || typeof value !== "object") return null;
|
|
2315
|
+
const record = value;
|
|
2316
|
+
const scheme = asTrimmedString(record.scheme);
|
|
2317
|
+
const signature = asTrimmedString(record.signature);
|
|
2318
|
+
const payload = normalizeRelayBootstrapAuthorizationPayload(record.payload);
|
|
2319
|
+
if (!scheme || !signature || !payload) return null;
|
|
2320
|
+
return { scheme, signature, payload };
|
|
2321
|
+
}
|
|
2322
|
+
function normalizeRelayBootstrapProofPayload(value) {
|
|
2323
|
+
if (!value || typeof value !== "object") return null;
|
|
2324
|
+
const payload = value;
|
|
2325
|
+
const peerId = asTrimmedString(payload.peerId);
|
|
2326
|
+
const updatedAt = asNumber4(payload.updatedAt);
|
|
2327
|
+
if (!peerId || updatedAt == null) return null;
|
|
2328
|
+
const multiaddrs = Array.isArray(payload.multiaddrs) ? payload.multiaddrs.filter((entry) => typeof entry === "string") : [];
|
|
2329
|
+
const browserMultiaddrs = Array.isArray(payload.browserMultiaddrs) ? payload.browserMultiaddrs.filter((entry) => typeof entry === "string") : void 0;
|
|
2330
|
+
return {
|
|
2331
|
+
peerId,
|
|
2332
|
+
multiaddrs: dedupeMultiaddrs(multiaddrs),
|
|
2333
|
+
browserMultiaddrs: browserMultiaddrs ? dedupeMultiaddrs(browserMultiaddrs) : void 0,
|
|
2334
|
+
registrationId: asTrimmedString(payload.registrationId) ?? void 0,
|
|
2335
|
+
profile: asTrimmedString(payload.profile) ?? void 0,
|
|
2336
|
+
version: asTrimmedString(payload.version) ?? void 0,
|
|
2337
|
+
updatedAt
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
function normalizeRelayBootstrapProofRecord(value) {
|
|
2341
|
+
if (!value || typeof value !== "object") return null;
|
|
2342
|
+
const record = value;
|
|
2343
|
+
const scheme = asTrimmedString(record.scheme);
|
|
2344
|
+
const signature = asTrimmedString(record.signature);
|
|
2345
|
+
const payload = normalizeRelayBootstrapProofPayload(record.payload);
|
|
2346
|
+
if (!scheme || !signature || !payload) return null;
|
|
2347
|
+
return { scheme, signature, payload };
|
|
2348
|
+
}
|
|
2349
|
+
function normalizeRelayBootstrapPostRecord(value) {
|
|
2350
|
+
if (!value || typeof value !== "object") return null;
|
|
2351
|
+
const entry = value;
|
|
2352
|
+
return {
|
|
2353
|
+
hash: asTrimmedString(entry.hash),
|
|
2354
|
+
itemHash: asTrimmedString(entry.item_hash),
|
|
2355
|
+
address: asTrimmedString(entry.address),
|
|
2356
|
+
ref: asTrimmedString(entry.ref),
|
|
2357
|
+
type: asTrimmedString(entry.type),
|
|
2358
|
+
time: asNumber4(entry.time),
|
|
2359
|
+
content: normalizeRelayBootstrapContent(entry.content)
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2165
2362
|
function buildRelayBootstrapPostContent(args) {
|
|
2166
2363
|
const now = args.now ?? Date.now() / 1e3;
|
|
2167
2364
|
const updatedAt = args.now ?? Date.now();
|
|
@@ -2175,8 +2372,13 @@ function buildRelayBootstrapPostContent(args) {
|
|
|
2175
2372
|
browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2176
2373
|
browserDialableOnly: true
|
|
2177
2374
|
}) : void 0,
|
|
2375
|
+
registrationId: args.registrationId,
|
|
2178
2376
|
profile: args.profile,
|
|
2179
2377
|
version: args.version,
|
|
2378
|
+
ownerAddress: args.ownerAddress,
|
|
2379
|
+
publisherAddress: args.publisherAddress,
|
|
2380
|
+
authorization: args.authorization,
|
|
2381
|
+
relayProof: args.relayProof,
|
|
2180
2382
|
updatedAt: Math.round(updatedAt)
|
|
2181
2383
|
},
|
|
2182
2384
|
time: now
|
|
@@ -2190,10 +2392,15 @@ async function createRelayBootstrapPost(args) {
|
|
|
2190
2392
|
peerId: args.peerId,
|
|
2191
2393
|
multiaddrs: args.multiaddrs,
|
|
2192
2394
|
browserMultiaddrs: args.browserMultiaddrs,
|
|
2395
|
+
registrationId: args.registrationId,
|
|
2193
2396
|
ref: args.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF,
|
|
2194
2397
|
postType: args.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE,
|
|
2195
2398
|
profile: args.profile,
|
|
2196
2399
|
version: args.version,
|
|
2400
|
+
ownerAddress: args.ownerAddress,
|
|
2401
|
+
publisherAddress: args.publisherAddress,
|
|
2402
|
+
authorization: args.authorization,
|
|
2403
|
+
relayProof: args.relayProof,
|
|
2197
2404
|
now: nowMillis
|
|
2198
2405
|
});
|
|
2199
2406
|
itemContent.time = nowSeconds;
|
|
@@ -2210,19 +2417,130 @@ async function createRelayBootstrapPost(args) {
|
|
|
2210
2417
|
item_hash: itemHash
|
|
2211
2418
|
};
|
|
2212
2419
|
}
|
|
2420
|
+
async function signRelayBootstrapAuthorization(args) {
|
|
2421
|
+
const payload = {
|
|
2422
|
+
ownerAddress: args.ownerAddress,
|
|
2423
|
+
publisherAddress: args.publisherAddress,
|
|
2424
|
+
peerId: args.peerId,
|
|
2425
|
+
registrationId: args.registrationId,
|
|
2426
|
+
profile: args.profile,
|
|
2427
|
+
version: args.version,
|
|
2428
|
+
instanceItemHash: args.instanceItemHash,
|
|
2429
|
+
issuedAt: args.issuedAt ?? Date.now(),
|
|
2430
|
+
expiresAt: args.expiresAt
|
|
2431
|
+
};
|
|
2432
|
+
const serialized = serializeOwnerAuthorizationPayload(payload);
|
|
2433
|
+
const signature = await args.signer(args.ownerAddress, serialized);
|
|
2434
|
+
return {
|
|
2435
|
+
scheme: RELAY_BOOTSTRAP_SIGNATURE_SCHEME,
|
|
2436
|
+
payload,
|
|
2437
|
+
signature: normalizeSignature(signature)
|
|
2438
|
+
};
|
|
2439
|
+
}
|
|
2440
|
+
async function signRelayBootstrapProof(args) {
|
|
2441
|
+
const payload = {
|
|
2442
|
+
peerId: args.peerId,
|
|
2443
|
+
multiaddrs: filterPublicMultiaddrs(args.multiaddrs),
|
|
2444
|
+
browserMultiaddrs: args.browserMultiaddrs ? filterPublicMultiaddrs(args.browserMultiaddrs, {
|
|
2445
|
+
browserDialableOnly: true
|
|
2446
|
+
}) : void 0,
|
|
2447
|
+
registrationId: args.registrationId,
|
|
2448
|
+
profile: args.profile,
|
|
2449
|
+
version: args.version,
|
|
2450
|
+
updatedAt: args.updatedAt ?? Date.now()
|
|
2451
|
+
};
|
|
2452
|
+
const serialized = serializeRelayProofPayload(payload);
|
|
2453
|
+
const signature = await args.signer(args.publisherAddress, serialized);
|
|
2454
|
+
return {
|
|
2455
|
+
scheme: RELAY_BOOTSTRAP_SIGNATURE_SCHEME,
|
|
2456
|
+
payload,
|
|
2457
|
+
signature: normalizeSignature(signature)
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
2460
|
+
async function fetchAlephBootstrapPosts(options = {}) {
|
|
2461
|
+
const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
2462
|
+
if (typeof fetchImpl !== "function") {
|
|
2463
|
+
throw new Error(
|
|
2464
|
+
"A fetch implementation is required to query Aleph bootstrap posts."
|
|
2465
|
+
);
|
|
2466
|
+
}
|
|
2467
|
+
const url = new URL(
|
|
2468
|
+
"/api/v0/posts.json",
|
|
2469
|
+
options.apiHost ?? DEFAULT_ALEPH_API_HOST3
|
|
2470
|
+
);
|
|
2471
|
+
url.searchParams.set(
|
|
2472
|
+
"channels",
|
|
2473
|
+
options.channel ?? DEFAULT_ALEPH_BOOTSTRAP_CHANNEL
|
|
2474
|
+
);
|
|
2475
|
+
url.searchParams.set("refs", options.ref ?? DEFAULT_ALEPH_BOOTSTRAP_REF);
|
|
2476
|
+
url.searchParams.set(
|
|
2477
|
+
"types",
|
|
2478
|
+
options.postType ?? DEFAULT_ALEPH_BOOTSTRAP_POST_TYPE
|
|
2479
|
+
);
|
|
2480
|
+
url.searchParams.set(
|
|
2481
|
+
"pagination",
|
|
2482
|
+
String(options.pagination ?? DEFAULT_BOOTSTRAP_PAGINATION)
|
|
2483
|
+
);
|
|
2484
|
+
url.searchParams.set("page", String(options.page ?? 1));
|
|
2485
|
+
const response = await fetchImpl(url.toString(), {
|
|
2486
|
+
method: "GET",
|
|
2487
|
+
headers: { accept: "application/json" }
|
|
2488
|
+
});
|
|
2489
|
+
if (!response.ok) {
|
|
2490
|
+
throw new Error(`Aleph bootstrap post lookup failed: ${response.status}`);
|
|
2491
|
+
}
|
|
2492
|
+
const payload = await response.json();
|
|
2493
|
+
return (payload.posts ?? []).map((entry) => normalizeRelayBootstrapPostRecord(entry)).filter((entry) => entry != null);
|
|
2494
|
+
}
|
|
2213
2495
|
|
|
2214
2496
|
// ../core/src/bootstrap-registration.ts
|
|
2215
2497
|
async function publishRelayBootstrapRegistration(args) {
|
|
2498
|
+
const publisherAddress = args.publisherAddress ?? args.sender;
|
|
2499
|
+
const ownerAddress = args.ownerAddress;
|
|
2500
|
+
let ownerAuthorization = args.ownerAuthorization;
|
|
2501
|
+
let relayProof = args.relayProof;
|
|
2502
|
+
if (!ownerAuthorization && ownerAddress && args.ownerSigner) {
|
|
2503
|
+
ownerAuthorization = await signRelayBootstrapAuthorization({
|
|
2504
|
+
ownerAddress,
|
|
2505
|
+
publisherAddress,
|
|
2506
|
+
peerId: args.peerId,
|
|
2507
|
+
registrationId: args.registrationId,
|
|
2508
|
+
profile: args.profile,
|
|
2509
|
+
version: args.version,
|
|
2510
|
+
instanceItemHash: args.instanceItemHash,
|
|
2511
|
+
issuedAt: args.authorizationIssuedAt ?? args.now ?? Date.now(),
|
|
2512
|
+
expiresAt: args.authorizationExpiresAt,
|
|
2513
|
+
signer: args.ownerSigner
|
|
2514
|
+
});
|
|
2515
|
+
}
|
|
2516
|
+
if (!relayProof && args.publisherSigner) {
|
|
2517
|
+
relayProof = await signRelayBootstrapProof({
|
|
2518
|
+
publisherAddress,
|
|
2519
|
+
peerId: args.peerId,
|
|
2520
|
+
multiaddrs: args.multiaddrs,
|
|
2521
|
+
browserMultiaddrs: args.browserMultiaddrs,
|
|
2522
|
+
registrationId: args.registrationId,
|
|
2523
|
+
profile: args.profile,
|
|
2524
|
+
version: args.version,
|
|
2525
|
+
updatedAt: args.now ?? Date.now(),
|
|
2526
|
+
signer: args.publisherSigner
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2216
2529
|
const unsigned = await createRelayBootstrapPost({
|
|
2217
2530
|
sender: args.sender,
|
|
2218
2531
|
peerId: args.peerId,
|
|
2219
2532
|
multiaddrs: args.multiaddrs,
|
|
2220
2533
|
browserMultiaddrs: args.browserMultiaddrs,
|
|
2534
|
+
registrationId: args.registrationId,
|
|
2221
2535
|
channel: args.channel,
|
|
2222
2536
|
ref: args.ref,
|
|
2223
2537
|
postType: args.postType,
|
|
2224
2538
|
profile: args.profile,
|
|
2225
2539
|
version: args.version,
|
|
2540
|
+
ownerAddress,
|
|
2541
|
+
publisherAddress,
|
|
2542
|
+
authorization: ownerAuthorization,
|
|
2543
|
+
relayProof,
|
|
2226
2544
|
now: args.now,
|
|
2227
2545
|
hasher: args.hasher
|
|
2228
2546
|
});
|
|
@@ -2241,6 +2559,32 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2241
2559
|
sync: args.sync ?? true,
|
|
2242
2560
|
fetch: args.fetch
|
|
2243
2561
|
});
|
|
2562
|
+
let forgottenHashes = [];
|
|
2563
|
+
let forgetResult;
|
|
2564
|
+
if (args.forgetPrevious && args.registrationId) {
|
|
2565
|
+
const previousPosts = await fetchAlephBootstrapPosts({
|
|
2566
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2567
|
+
channel: args.channel,
|
|
2568
|
+
ref: args.ref,
|
|
2569
|
+
postType: args.postType,
|
|
2570
|
+
fetch: args.fetch
|
|
2571
|
+
});
|
|
2572
|
+
forgottenHashes = previousPosts.filter(
|
|
2573
|
+
(post) => post.address?.toLowerCase() === args.sender.toLowerCase() && post.content?.registrationId === args.registrationId && (post.itemHash ?? post.hash) != null && (post.itemHash ?? post.hash) !== unsigned.item_hash
|
|
2574
|
+
).map((post) => post.itemHash ?? post.hash ?? "").filter(Boolean);
|
|
2575
|
+
if (forgottenHashes.length > 0) {
|
|
2576
|
+
forgetResult = await forgetAlephMessages({
|
|
2577
|
+
sender: args.sender,
|
|
2578
|
+
hashes: forgottenHashes,
|
|
2579
|
+
reason: args.forgetPreviousReason ?? `Replace older relay bootstrap records for ${args.registrationId}`,
|
|
2580
|
+
signer: args.signer,
|
|
2581
|
+
hasher: args.hasher,
|
|
2582
|
+
fetch: args.fetch,
|
|
2583
|
+
apiHost: args.apiHost ?? DEFAULT_ALEPH_API_HOST3,
|
|
2584
|
+
sync: args.sync ?? true
|
|
2585
|
+
});
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2244
2588
|
return {
|
|
2245
2589
|
status: "published",
|
|
2246
2590
|
itemHash: unsigned.item_hash,
|
|
@@ -2248,7 +2592,9 @@ async function publishRelayBootstrapRegistration(args) {
|
|
|
2248
2592
|
response,
|
|
2249
2593
|
httpStatus,
|
|
2250
2594
|
publishedMultiaddrs: content.content?.multiaddrs ?? [],
|
|
2251
|
-
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? []
|
|
2595
|
+
publishedBrowserMultiaddrs: content.content?.browserMultiaddrs ?? [],
|
|
2596
|
+
forgottenHashes,
|
|
2597
|
+
forgetResult
|
|
2252
2598
|
};
|
|
2253
2599
|
}
|
|
2254
2600
|
|
|
@@ -2287,8 +2633,9 @@ function defaultState(props = {}) {
|
|
|
2287
2633
|
sshPublicKey: props.sshPublicKey ?? "",
|
|
2288
2634
|
instanceName: props.instanceName ?? DEFAULT_INSTANCE_NAME,
|
|
2289
2635
|
tierId: DEFAULT_TIER_ID,
|
|
2636
|
+
showAdvanced: Boolean(props.manifestJson?.trim() || props.sshPublicKey?.trim()),
|
|
2290
2637
|
showInstances: props.showInstances ?? true,
|
|
2291
|
-
showPasteManifest:
|
|
2638
|
+
showPasteManifest: Boolean(props.manifestJson?.trim()),
|
|
2292
2639
|
busy: {
|
|
2293
2640
|
connectingWallet: false,
|
|
2294
2641
|
refreshing: false,
|
|
@@ -2324,6 +2671,14 @@ function defaultState(props = {}) {
|
|
|
2324
2671
|
deploymentProgress: IDLE_DEPLOYMENT_PROGRESS
|
|
2325
2672
|
};
|
|
2326
2673
|
}
|
|
2674
|
+
function manifestLoadErrorState(error) {
|
|
2675
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2676
|
+
return {
|
|
2677
|
+
manifest: null,
|
|
2678
|
+
valid: false,
|
|
2679
|
+
errors: [message]
|
|
2680
|
+
};
|
|
2681
|
+
}
|
|
2327
2682
|
function isDebugEnabled(props) {
|
|
2328
2683
|
if (props.debug) {
|
|
2329
2684
|
return true;
|
|
@@ -2606,6 +2961,7 @@ var SponsorRelayController = class {
|
|
|
2606
2961
|
client;
|
|
2607
2962
|
refreshTimer = null;
|
|
2608
2963
|
pingTimer = null;
|
|
2964
|
+
manifestRefreshTimer = null;
|
|
2609
2965
|
stopWalletWatch = null;
|
|
2610
2966
|
props;
|
|
2611
2967
|
progressEmitter = createDeploymentProgressEmitter();
|
|
@@ -2978,6 +3334,7 @@ var SponsorRelayController = class {
|
|
|
2978
3334
|
destroy() {
|
|
2979
3335
|
if (this.refreshTimer) clearInterval(this.refreshTimer);
|
|
2980
3336
|
if (this.pingTimer) clearInterval(this.pingTimer);
|
|
3337
|
+
if (this.manifestRefreshTimer) clearTimeout(this.manifestRefreshTimer);
|
|
2981
3338
|
this.stopWalletWatch?.();
|
|
2982
3339
|
}
|
|
2983
3340
|
setOpen(open) {
|
|
@@ -2988,15 +3345,27 @@ var SponsorRelayController = class {
|
|
|
2988
3345
|
}
|
|
2989
3346
|
setManifestUrl(manifestUrl) {
|
|
2990
3347
|
this.patch({ manifestUrl });
|
|
3348
|
+
this.queueManifestRefresh();
|
|
2991
3349
|
}
|
|
2992
3350
|
setManifestJson(manifestJson) {
|
|
2993
|
-
this.patch({
|
|
3351
|
+
this.patch({
|
|
3352
|
+
manifestJson,
|
|
3353
|
+
showAdvanced: this.state.showAdvanced || Boolean(manifestJson.trim()),
|
|
3354
|
+
showPasteManifest: this.state.showPasteManifest || Boolean(manifestJson.trim())
|
|
3355
|
+
});
|
|
3356
|
+
this.queueManifestRefresh();
|
|
3357
|
+
}
|
|
3358
|
+
setShowAdvanced(showAdvanced) {
|
|
3359
|
+
this.patch({ showAdvanced });
|
|
2994
3360
|
}
|
|
2995
3361
|
setShowPasteManifest(showPasteManifest) {
|
|
2996
3362
|
this.patch({ showPasteManifest });
|
|
2997
3363
|
}
|
|
2998
3364
|
setSshPublicKey(sshPublicKey) {
|
|
2999
|
-
this.patch({
|
|
3365
|
+
this.patch({
|
|
3366
|
+
sshPublicKey,
|
|
3367
|
+
showAdvanced: this.state.showAdvanced || Boolean(sshPublicKey.trim())
|
|
3368
|
+
});
|
|
3000
3369
|
}
|
|
3001
3370
|
setInstanceName(instanceName) {
|
|
3002
3371
|
this.patch({ instanceName });
|
|
@@ -3032,6 +3401,18 @@ var SponsorRelayController = class {
|
|
|
3032
3401
|
selectedCrn
|
|
3033
3402
|
});
|
|
3034
3403
|
}
|
|
3404
|
+
queueManifestRefresh() {
|
|
3405
|
+
if (!this.state.ready) {
|
|
3406
|
+
return;
|
|
3407
|
+
}
|
|
3408
|
+
if (this.manifestRefreshTimer) {
|
|
3409
|
+
clearTimeout(this.manifestRefreshTimer);
|
|
3410
|
+
}
|
|
3411
|
+
this.manifestRefreshTimer = setTimeout(() => {
|
|
3412
|
+
this.manifestRefreshTimer = null;
|
|
3413
|
+
void this.refresh();
|
|
3414
|
+
}, MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS);
|
|
3415
|
+
}
|
|
3035
3416
|
async connectWallet() {
|
|
3036
3417
|
this.patch({
|
|
3037
3418
|
busy: { connectingWallet: true },
|
|
@@ -3085,15 +3466,15 @@ var SponsorRelayController = class {
|
|
|
3085
3466
|
statusText: "Refreshing relay sponsor data"
|
|
3086
3467
|
});
|
|
3087
3468
|
try {
|
|
3088
|
-
const manifestState = await resolveManifest({
|
|
3089
|
-
manifestUrl: this.state.manifestUrl,
|
|
3090
|
-
manifestJson: this.state.manifestJson
|
|
3091
|
-
});
|
|
3092
|
-
const manifest = manifestState.manifest;
|
|
3093
3469
|
const [pricingSummary, crns] = await Promise.all([
|
|
3094
3470
|
fetchInstancePricing(this.client.apiHost),
|
|
3095
3471
|
this.client.fetchCrns()
|
|
3096
3472
|
]);
|
|
3473
|
+
const manifestState = await resolveManifest({
|
|
3474
|
+
manifestUrl: this.state.manifestUrl,
|
|
3475
|
+
manifestJson: this.state.manifestJson
|
|
3476
|
+
}).catch((error) => manifestLoadErrorState(error));
|
|
3477
|
+
const manifest = manifestState.manifest;
|
|
3097
3478
|
let balance = this.state.balance;
|
|
3098
3479
|
let instances = [];
|
|
3099
3480
|
if (this.state.wallet.address) {
|
|
@@ -3545,6 +3926,7 @@ export {
|
|
|
3545
3926
|
INSTANCE_RUNTIME_PENDING_REFRESH_MS,
|
|
3546
3927
|
INSTANCE_RUNTIME_READY_REFRESH_MS,
|
|
3547
3928
|
INSTANCE_RUNTIME_STALE_REFRESH_MS,
|
|
3929
|
+
MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS,
|
|
3548
3930
|
RECENT_INSTANCE_RUNTIME_GRACE_MS,
|
|
3549
3931
|
REFRESH_INTERVAL_MS,
|
|
3550
3932
|
RELAY_PING_IDLE_STATE,
|
|
@@ -3558,6 +3940,7 @@ export {
|
|
|
3558
3940
|
createSponsorRelayController,
|
|
3559
3941
|
formatDateTime,
|
|
3560
3942
|
formatNumber,
|
|
3943
|
+
formatTierSpecLabel,
|
|
3561
3944
|
getEthereumProvider,
|
|
3562
3945
|
joinMappedPorts,
|
|
3563
3946
|
joinRequiredPortForwards,
|