@le-space/ui 0.1.55 → 0.1.56
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 +1 -1
- package/react/index.d.ts +2 -2
- package/react/index.js +134 -14
- package/shared/index.d.ts +2 -2
- package/shared/index.js +134 -14
package/package.json
CHANGED
package/react/index.d.ts
CHANGED
|
@@ -174,12 +174,12 @@ interface RootfsResolution {
|
|
|
174
174
|
gatewayError?: string | null;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
type DeploymentProgressStage =
|
|
177
|
+
type DeploymentProgressStage = "idle" | "validating" | "loading-manifest" | "verifying-rootfs" | "loading-pricing" | "loading-balance" | "selecting-crn" | "building-message" | "signing-message" | "broadcasting" | "notifying-crn" | "waiting-for-aleph" | "deployment-confirmed" | "deployment-rejected" | "building-delete-message" | "signing-delete-message" | "broadcasting-delete" | "delete-completed" | "refreshing-instances" | "completed" | "error";
|
|
178
178
|
interface DeploymentProgressEvent {
|
|
179
179
|
stage: DeploymentProgressStage;
|
|
180
180
|
label: string;
|
|
181
181
|
progress: number;
|
|
182
|
-
status:
|
|
182
|
+
status: "info" | "success" | "warning" | "error";
|
|
183
183
|
itemHash?: string | null;
|
|
184
184
|
detail?: string | null;
|
|
185
185
|
error?: string | null;
|
package/react/index.js
CHANGED
|
@@ -1228,6 +1228,88 @@ async function deployInstance(args) {
|
|
|
1228
1228
|
};
|
|
1229
1229
|
}
|
|
1230
1230
|
|
|
1231
|
+
// ../core/src/guest.ts
|
|
1232
|
+
async function notifyCrnAllocation2(args) {
|
|
1233
|
+
const normalizedCrnUrl = typeof args.crnUrl === "string" ? args.crnUrl.trim().replace(/\/+$/, "") : "";
|
|
1234
|
+
if (!normalizedCrnUrl) {
|
|
1235
|
+
return {
|
|
1236
|
+
status: "skipped",
|
|
1237
|
+
reason: "No CRN URL available for allocation notification."
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
try {
|
|
1241
|
+
const response = await args.fetch(
|
|
1242
|
+
`${normalizedCrnUrl}/control/allocation/notify`,
|
|
1243
|
+
{
|
|
1244
|
+
method: "POST",
|
|
1245
|
+
headers: {
|
|
1246
|
+
"content-type": "application/json"
|
|
1247
|
+
},
|
|
1248
|
+
body: JSON.stringify({ instance: args.itemHash })
|
|
1249
|
+
}
|
|
1250
|
+
);
|
|
1251
|
+
const payload = await response.json().catch(() => null);
|
|
1252
|
+
const responseText = payload == null ? "" : typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
1253
|
+
if (!response.ok) {
|
|
1254
|
+
return {
|
|
1255
|
+
status: "unconfirmed",
|
|
1256
|
+
reason: `CRN allocation notify returned ${response.status}${responseText ? ` ${responseText}` : ""}.`,
|
|
1257
|
+
payload
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
return {
|
|
1261
|
+
status: "confirmed",
|
|
1262
|
+
payload
|
|
1263
|
+
};
|
|
1264
|
+
} catch (error) {
|
|
1265
|
+
return {
|
|
1266
|
+
status: "unconfirmed",
|
|
1267
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
function isRetryableAllocationNotifyReason(reason) {
|
|
1272
|
+
const normalized = String(reason ?? "").toLowerCase();
|
|
1273
|
+
return normalized.includes("503") && (normalized.includes("node hash not yet discovered") || normalized.includes("cannot accept targeted allocations"));
|
|
1274
|
+
}
|
|
1275
|
+
async function notifyCrnAllocationWithRetry(args) {
|
|
1276
|
+
const attempts = Math.max(1, Number(args.attempts ?? 6));
|
|
1277
|
+
const delayMs = Math.max(0, Number(args.delayMs ?? 2e3));
|
|
1278
|
+
const sleep = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
1279
|
+
let lastResult = null;
|
|
1280
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
1281
|
+
args.onProgress?.({
|
|
1282
|
+
stage: "notifying-crn",
|
|
1283
|
+
label: "Notifying selected CRN",
|
|
1284
|
+
progress: 84,
|
|
1285
|
+
status: "info",
|
|
1286
|
+
itemHash: args.itemHash,
|
|
1287
|
+
detail: `${attempt + 1}/${attempts} ${String(args.crnUrl ?? "").trim() || "selected CRN"}`,
|
|
1288
|
+
error: null,
|
|
1289
|
+
timestamp: Date.now()
|
|
1290
|
+
});
|
|
1291
|
+
const result = await notifyCrnAllocation2({
|
|
1292
|
+
crnUrl: args.crnUrl,
|
|
1293
|
+
itemHash: args.itemHash,
|
|
1294
|
+
fetch: args.fetch
|
|
1295
|
+
});
|
|
1296
|
+
if (result.status === "confirmed" || result.status === "skipped") {
|
|
1297
|
+
return result;
|
|
1298
|
+
}
|
|
1299
|
+
lastResult = result;
|
|
1300
|
+
if (!isRetryableAllocationNotifyReason(result.reason)) {
|
|
1301
|
+
return result;
|
|
1302
|
+
}
|
|
1303
|
+
if (attempt < attempts - 1) {
|
|
1304
|
+
await sleep(delayMs);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
return lastResult ?? {
|
|
1308
|
+
status: "unconfirmed",
|
|
1309
|
+
reason: "CRN allocation notify was not confirmed."
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1231
1313
|
// src/shared/events.ts
|
|
1232
1314
|
function createDeploymentProgressEmitter() {
|
|
1233
1315
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -1301,14 +1383,19 @@ function defaultState(props = {}) {
|
|
|
1301
1383
|
};
|
|
1302
1384
|
}
|
|
1303
1385
|
async function sha256Hex(payload) {
|
|
1304
|
-
const digest = await globalThis.crypto.subtle.digest(
|
|
1386
|
+
const digest = await globalThis.crypto.subtle.digest(
|
|
1387
|
+
"SHA-256",
|
|
1388
|
+
new TextEncoder().encode(payload)
|
|
1389
|
+
);
|
|
1305
1390
|
return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1306
1391
|
}
|
|
1307
1392
|
function mappedPorts(execution) {
|
|
1308
|
-
return Object.entries(execution?.networking?.mapped_ports ?? {}).map(
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1393
|
+
return Object.entries(execution?.networking?.mapped_ports ?? {}).map(
|
|
1394
|
+
([port, mapping]) => ({
|
|
1395
|
+
label: `${port}/${mapping.udp ? "udp" : "tcp"}`,
|
|
1396
|
+
hostPort: mapping.host ?? null
|
|
1397
|
+
})
|
|
1398
|
+
);
|
|
1312
1399
|
}
|
|
1313
1400
|
function rootfsHealth(args) {
|
|
1314
1401
|
if (!args.manifestState.valid || !args.manifestState.manifest) {
|
|
@@ -1366,7 +1453,9 @@ async function resolveManifest(args) {
|
|
|
1366
1453
|
}
|
|
1367
1454
|
async function inspectInstanceRuntime(args) {
|
|
1368
1455
|
const details = {
|
|
1369
|
-
messageStatus: String(
|
|
1456
|
+
messageStatus: String(
|
|
1457
|
+
args.instance.status ?? (args.instance.confirmed ? "processed" : "unknown")
|
|
1458
|
+
).toLowerCase(),
|
|
1370
1459
|
allocationSource: null,
|
|
1371
1460
|
crnUrl: null,
|
|
1372
1461
|
hostIpv4: null,
|
|
@@ -1397,11 +1486,15 @@ async function inspectInstanceRuntime(args) {
|
|
|
1397
1486
|
details.allocationSource = allocation?.source ?? null;
|
|
1398
1487
|
details.crnUrl = allocation?.crnUrl ?? null;
|
|
1399
1488
|
details.ipv6 = allocation?.vmIpv6 ?? null;
|
|
1400
|
-
details.webUrl = await args.client.fetch2n6WebAccessUrl(
|
|
1489
|
+
details.webUrl = await args.client.fetch2n6WebAccessUrl(
|
|
1490
|
+
args.instance.item_hash
|
|
1491
|
+
);
|
|
1401
1492
|
if (!allocation?.crnUrl) {
|
|
1402
1493
|
return details;
|
|
1403
1494
|
}
|
|
1404
|
-
const executionLookup = await args.client.fetchCrnExecutionMap(
|
|
1495
|
+
const executionLookup = await args.client.fetchCrnExecutionMap(
|
|
1496
|
+
allocation.crnUrl
|
|
1497
|
+
);
|
|
1405
1498
|
const executionPayload = executionLookup.payload?.[args.instance.item_hash];
|
|
1406
1499
|
if (!executionPayload) {
|
|
1407
1500
|
return details;
|
|
@@ -1429,7 +1522,10 @@ function compatibleCrnsForTier(crns, state) {
|
|
|
1429
1522
|
if (!state.pricingSummary.pricing || !state.pricingSummary.tier) {
|
|
1430
1523
|
return [];
|
|
1431
1524
|
}
|
|
1432
|
-
const spec = tierSpec(
|
|
1525
|
+
const spec = tierSpec(
|
|
1526
|
+
state.pricingSummary.pricing,
|
|
1527
|
+
state.pricingSummary.tier
|
|
1528
|
+
);
|
|
1433
1529
|
return filterDeployableCrns(crns, { spec });
|
|
1434
1530
|
}
|
|
1435
1531
|
async function pingPeer(libp2p) {
|
|
@@ -1719,8 +1815,14 @@ var SponsorRelayController = class {
|
|
|
1719
1815
|
status: "info",
|
|
1720
1816
|
detail: manifest.rootfsItemHash
|
|
1721
1817
|
});
|
|
1722
|
-
rootfsVerified = await verifyRootfsExists(
|
|
1723
|
-
|
|
1818
|
+
rootfsVerified = await verifyRootfsExists(
|
|
1819
|
+
manifest.rootfsItemHash,
|
|
1820
|
+
this.client.apiHost
|
|
1821
|
+
);
|
|
1822
|
+
rootfsResolution = await resolveRootfsReference(
|
|
1823
|
+
manifest.rootfsItemHash,
|
|
1824
|
+
this.client.apiHost
|
|
1825
|
+
);
|
|
1724
1826
|
}
|
|
1725
1827
|
this.patch({
|
|
1726
1828
|
manifestState,
|
|
@@ -1775,7 +1877,9 @@ var SponsorRelayController = class {
|
|
|
1775
1877
|
return;
|
|
1776
1878
|
}
|
|
1777
1879
|
if (!this.state.manifest || !this.state.rootfsVerified || !this.state.pricingSummary.pricing || !this.state.pricingSummary.tier) {
|
|
1778
|
-
this.patch({
|
|
1880
|
+
this.patch({
|
|
1881
|
+
errorText: "Manifest, rootfs, and pricing must be ready before deploying."
|
|
1882
|
+
});
|
|
1779
1883
|
return;
|
|
1780
1884
|
}
|
|
1781
1885
|
this.patch({
|
|
@@ -1791,7 +1895,10 @@ var SponsorRelayController = class {
|
|
|
1791
1895
|
status: "info",
|
|
1792
1896
|
detail: "Checking wallet, manifest, rootfs, pricing, and SSH key."
|
|
1793
1897
|
});
|
|
1794
|
-
const spec = tierSpec(
|
|
1898
|
+
const spec = tierSpec(
|
|
1899
|
+
this.state.pricingSummary.pricing,
|
|
1900
|
+
this.state.pricingSummary.tier
|
|
1901
|
+
);
|
|
1795
1902
|
this.emitProgress({
|
|
1796
1903
|
stage: "selecting-crn",
|
|
1797
1904
|
label: "Selecting CRN",
|
|
@@ -1804,7 +1911,10 @@ var SponsorRelayController = class {
|
|
|
1804
1911
|
name: this.state.instanceName.trim(),
|
|
1805
1912
|
sshPublicKey: this.state.sshPublicKey.trim(),
|
|
1806
1913
|
rootfsItemHash: this.state.manifest.rootfsItemHash,
|
|
1807
|
-
rootfsSizeMiB: Math.max(
|
|
1914
|
+
rootfsSizeMiB: Math.max(
|
|
1915
|
+
this.state.manifest.rootfsSizeMiB,
|
|
1916
|
+
spec.diskMiB
|
|
1917
|
+
),
|
|
1808
1918
|
vcpus: spec.vcpus,
|
|
1809
1919
|
memoryMiB: spec.memoryMiB,
|
|
1810
1920
|
rootfsVersion: this.state.manifest.version,
|
|
@@ -1827,6 +1937,16 @@ var SponsorRelayController = class {
|
|
|
1827
1937
|
statusText: `Deployment submitted: ${result.itemHash}`,
|
|
1828
1938
|
lastDeploymentHash: result.itemHash
|
|
1829
1939
|
});
|
|
1940
|
+
if (result.status === "processed" && this.state.selectedCrn?.address) {
|
|
1941
|
+
await notifyCrnAllocationWithRetry({
|
|
1942
|
+
crnUrl: this.state.selectedCrn.address,
|
|
1943
|
+
itemHash: result.itemHash,
|
|
1944
|
+
fetch: (url, init) => fetch(url, init),
|
|
1945
|
+
onProgress: (event) => {
|
|
1946
|
+
this.emitProgress(event);
|
|
1947
|
+
}
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1830
1950
|
this.emitProgress({
|
|
1831
1951
|
stage: "refreshing-instances",
|
|
1832
1952
|
label: "Refreshing instances",
|
package/shared/index.d.ts
CHANGED
|
@@ -172,12 +172,12 @@ interface RootfsResolution {
|
|
|
172
172
|
gatewayError?: string | null;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
type DeploymentProgressStage =
|
|
175
|
+
type DeploymentProgressStage = "idle" | "validating" | "loading-manifest" | "verifying-rootfs" | "loading-pricing" | "loading-balance" | "selecting-crn" | "building-message" | "signing-message" | "broadcasting" | "notifying-crn" | "waiting-for-aleph" | "deployment-confirmed" | "deployment-rejected" | "building-delete-message" | "signing-delete-message" | "broadcasting-delete" | "delete-completed" | "refreshing-instances" | "completed" | "error";
|
|
176
176
|
interface DeploymentProgressEvent {
|
|
177
177
|
stage: DeploymentProgressStage;
|
|
178
178
|
label: string;
|
|
179
179
|
progress: number;
|
|
180
|
-
status:
|
|
180
|
+
status: "info" | "success" | "warning" | "error";
|
|
181
181
|
itemHash?: string | null;
|
|
182
182
|
detail?: string | null;
|
|
183
183
|
error?: string | null;
|
package/shared/index.js
CHANGED
|
@@ -1225,6 +1225,88 @@ async function deployInstance(args) {
|
|
|
1225
1225
|
};
|
|
1226
1226
|
}
|
|
1227
1227
|
|
|
1228
|
+
// ../core/src/guest.ts
|
|
1229
|
+
async function notifyCrnAllocation2(args) {
|
|
1230
|
+
const normalizedCrnUrl = typeof args.crnUrl === "string" ? args.crnUrl.trim().replace(/\/+$/, "") : "";
|
|
1231
|
+
if (!normalizedCrnUrl) {
|
|
1232
|
+
return {
|
|
1233
|
+
status: "skipped",
|
|
1234
|
+
reason: "No CRN URL available for allocation notification."
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
try {
|
|
1238
|
+
const response = await args.fetch(
|
|
1239
|
+
`${normalizedCrnUrl}/control/allocation/notify`,
|
|
1240
|
+
{
|
|
1241
|
+
method: "POST",
|
|
1242
|
+
headers: {
|
|
1243
|
+
"content-type": "application/json"
|
|
1244
|
+
},
|
|
1245
|
+
body: JSON.stringify({ instance: args.itemHash })
|
|
1246
|
+
}
|
|
1247
|
+
);
|
|
1248
|
+
const payload = await response.json().catch(() => null);
|
|
1249
|
+
const responseText = payload == null ? "" : typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
1250
|
+
if (!response.ok) {
|
|
1251
|
+
return {
|
|
1252
|
+
status: "unconfirmed",
|
|
1253
|
+
reason: `CRN allocation notify returned ${response.status}${responseText ? ` ${responseText}` : ""}.`,
|
|
1254
|
+
payload
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
return {
|
|
1258
|
+
status: "confirmed",
|
|
1259
|
+
payload
|
|
1260
|
+
};
|
|
1261
|
+
} catch (error) {
|
|
1262
|
+
return {
|
|
1263
|
+
status: "unconfirmed",
|
|
1264
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
function isRetryableAllocationNotifyReason(reason) {
|
|
1269
|
+
const normalized = String(reason ?? "").toLowerCase();
|
|
1270
|
+
return normalized.includes("503") && (normalized.includes("node hash not yet discovered") || normalized.includes("cannot accept targeted allocations"));
|
|
1271
|
+
}
|
|
1272
|
+
async function notifyCrnAllocationWithRetry(args) {
|
|
1273
|
+
const attempts = Math.max(1, Number(args.attempts ?? 6));
|
|
1274
|
+
const delayMs = Math.max(0, Number(args.delayMs ?? 2e3));
|
|
1275
|
+
const sleep = args.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
1276
|
+
let lastResult = null;
|
|
1277
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
1278
|
+
args.onProgress?.({
|
|
1279
|
+
stage: "notifying-crn",
|
|
1280
|
+
label: "Notifying selected CRN",
|
|
1281
|
+
progress: 84,
|
|
1282
|
+
status: "info",
|
|
1283
|
+
itemHash: args.itemHash,
|
|
1284
|
+
detail: `${attempt + 1}/${attempts} ${String(args.crnUrl ?? "").trim() || "selected CRN"}`,
|
|
1285
|
+
error: null,
|
|
1286
|
+
timestamp: Date.now()
|
|
1287
|
+
});
|
|
1288
|
+
const result = await notifyCrnAllocation2({
|
|
1289
|
+
crnUrl: args.crnUrl,
|
|
1290
|
+
itemHash: args.itemHash,
|
|
1291
|
+
fetch: args.fetch
|
|
1292
|
+
});
|
|
1293
|
+
if (result.status === "confirmed" || result.status === "skipped") {
|
|
1294
|
+
return result;
|
|
1295
|
+
}
|
|
1296
|
+
lastResult = result;
|
|
1297
|
+
if (!isRetryableAllocationNotifyReason(result.reason)) {
|
|
1298
|
+
return result;
|
|
1299
|
+
}
|
|
1300
|
+
if (attempt < attempts - 1) {
|
|
1301
|
+
await sleep(delayMs);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
return lastResult ?? {
|
|
1305
|
+
status: "unconfirmed",
|
|
1306
|
+
reason: "CRN allocation notify was not confirmed."
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1228
1310
|
// src/shared/events.ts
|
|
1229
1311
|
function createDeploymentProgressEmitter() {
|
|
1230
1312
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -1298,14 +1380,19 @@ function defaultState(props = {}) {
|
|
|
1298
1380
|
};
|
|
1299
1381
|
}
|
|
1300
1382
|
async function sha256Hex(payload) {
|
|
1301
|
-
const digest = await globalThis.crypto.subtle.digest(
|
|
1383
|
+
const digest = await globalThis.crypto.subtle.digest(
|
|
1384
|
+
"SHA-256",
|
|
1385
|
+
new TextEncoder().encode(payload)
|
|
1386
|
+
);
|
|
1302
1387
|
return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1303
1388
|
}
|
|
1304
1389
|
function mappedPorts(execution) {
|
|
1305
|
-
return Object.entries(execution?.networking?.mapped_ports ?? {}).map(
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1390
|
+
return Object.entries(execution?.networking?.mapped_ports ?? {}).map(
|
|
1391
|
+
([port, mapping]) => ({
|
|
1392
|
+
label: `${port}/${mapping.udp ? "udp" : "tcp"}`,
|
|
1393
|
+
hostPort: mapping.host ?? null
|
|
1394
|
+
})
|
|
1395
|
+
);
|
|
1309
1396
|
}
|
|
1310
1397
|
function rootfsHealth(args) {
|
|
1311
1398
|
if (!args.manifestState.valid || !args.manifestState.manifest) {
|
|
@@ -1363,7 +1450,9 @@ async function resolveManifest(args) {
|
|
|
1363
1450
|
}
|
|
1364
1451
|
async function inspectInstanceRuntime(args) {
|
|
1365
1452
|
const details = {
|
|
1366
|
-
messageStatus: String(
|
|
1453
|
+
messageStatus: String(
|
|
1454
|
+
args.instance.status ?? (args.instance.confirmed ? "processed" : "unknown")
|
|
1455
|
+
).toLowerCase(),
|
|
1367
1456
|
allocationSource: null,
|
|
1368
1457
|
crnUrl: null,
|
|
1369
1458
|
hostIpv4: null,
|
|
@@ -1394,11 +1483,15 @@ async function inspectInstanceRuntime(args) {
|
|
|
1394
1483
|
details.allocationSource = allocation?.source ?? null;
|
|
1395
1484
|
details.crnUrl = allocation?.crnUrl ?? null;
|
|
1396
1485
|
details.ipv6 = allocation?.vmIpv6 ?? null;
|
|
1397
|
-
details.webUrl = await args.client.fetch2n6WebAccessUrl(
|
|
1486
|
+
details.webUrl = await args.client.fetch2n6WebAccessUrl(
|
|
1487
|
+
args.instance.item_hash
|
|
1488
|
+
);
|
|
1398
1489
|
if (!allocation?.crnUrl) {
|
|
1399
1490
|
return details;
|
|
1400
1491
|
}
|
|
1401
|
-
const executionLookup = await args.client.fetchCrnExecutionMap(
|
|
1492
|
+
const executionLookup = await args.client.fetchCrnExecutionMap(
|
|
1493
|
+
allocation.crnUrl
|
|
1494
|
+
);
|
|
1402
1495
|
const executionPayload = executionLookup.payload?.[args.instance.item_hash];
|
|
1403
1496
|
if (!executionPayload) {
|
|
1404
1497
|
return details;
|
|
@@ -1426,7 +1519,10 @@ function compatibleCrnsForTier(crns, state) {
|
|
|
1426
1519
|
if (!state.pricingSummary.pricing || !state.pricingSummary.tier) {
|
|
1427
1520
|
return [];
|
|
1428
1521
|
}
|
|
1429
|
-
const spec = tierSpec(
|
|
1522
|
+
const spec = tierSpec(
|
|
1523
|
+
state.pricingSummary.pricing,
|
|
1524
|
+
state.pricingSummary.tier
|
|
1525
|
+
);
|
|
1430
1526
|
return filterDeployableCrns(crns, { spec });
|
|
1431
1527
|
}
|
|
1432
1528
|
async function pingPeer(libp2p) {
|
|
@@ -1716,8 +1812,14 @@ var SponsorRelayController = class {
|
|
|
1716
1812
|
status: "info",
|
|
1717
1813
|
detail: manifest.rootfsItemHash
|
|
1718
1814
|
});
|
|
1719
|
-
rootfsVerified = await verifyRootfsExists(
|
|
1720
|
-
|
|
1815
|
+
rootfsVerified = await verifyRootfsExists(
|
|
1816
|
+
manifest.rootfsItemHash,
|
|
1817
|
+
this.client.apiHost
|
|
1818
|
+
);
|
|
1819
|
+
rootfsResolution = await resolveRootfsReference(
|
|
1820
|
+
manifest.rootfsItemHash,
|
|
1821
|
+
this.client.apiHost
|
|
1822
|
+
);
|
|
1721
1823
|
}
|
|
1722
1824
|
this.patch({
|
|
1723
1825
|
manifestState,
|
|
@@ -1772,7 +1874,9 @@ var SponsorRelayController = class {
|
|
|
1772
1874
|
return;
|
|
1773
1875
|
}
|
|
1774
1876
|
if (!this.state.manifest || !this.state.rootfsVerified || !this.state.pricingSummary.pricing || !this.state.pricingSummary.tier) {
|
|
1775
|
-
this.patch({
|
|
1877
|
+
this.patch({
|
|
1878
|
+
errorText: "Manifest, rootfs, and pricing must be ready before deploying."
|
|
1879
|
+
});
|
|
1776
1880
|
return;
|
|
1777
1881
|
}
|
|
1778
1882
|
this.patch({
|
|
@@ -1788,7 +1892,10 @@ var SponsorRelayController = class {
|
|
|
1788
1892
|
status: "info",
|
|
1789
1893
|
detail: "Checking wallet, manifest, rootfs, pricing, and SSH key."
|
|
1790
1894
|
});
|
|
1791
|
-
const spec = tierSpec(
|
|
1895
|
+
const spec = tierSpec(
|
|
1896
|
+
this.state.pricingSummary.pricing,
|
|
1897
|
+
this.state.pricingSummary.tier
|
|
1898
|
+
);
|
|
1792
1899
|
this.emitProgress({
|
|
1793
1900
|
stage: "selecting-crn",
|
|
1794
1901
|
label: "Selecting CRN",
|
|
@@ -1801,7 +1908,10 @@ var SponsorRelayController = class {
|
|
|
1801
1908
|
name: this.state.instanceName.trim(),
|
|
1802
1909
|
sshPublicKey: this.state.sshPublicKey.trim(),
|
|
1803
1910
|
rootfsItemHash: this.state.manifest.rootfsItemHash,
|
|
1804
|
-
rootfsSizeMiB: Math.max(
|
|
1911
|
+
rootfsSizeMiB: Math.max(
|
|
1912
|
+
this.state.manifest.rootfsSizeMiB,
|
|
1913
|
+
spec.diskMiB
|
|
1914
|
+
),
|
|
1805
1915
|
vcpus: spec.vcpus,
|
|
1806
1916
|
memoryMiB: spec.memoryMiB,
|
|
1807
1917
|
rootfsVersion: this.state.manifest.version,
|
|
@@ -1824,6 +1934,16 @@ var SponsorRelayController = class {
|
|
|
1824
1934
|
statusText: `Deployment submitted: ${result.itemHash}`,
|
|
1825
1935
|
lastDeploymentHash: result.itemHash
|
|
1826
1936
|
});
|
|
1937
|
+
if (result.status === "processed" && this.state.selectedCrn?.address) {
|
|
1938
|
+
await notifyCrnAllocationWithRetry({
|
|
1939
|
+
crnUrl: this.state.selectedCrn.address,
|
|
1940
|
+
itemHash: result.itemHash,
|
|
1941
|
+
fetch: (url, init) => fetch(url, init),
|
|
1942
|
+
onProgress: (event) => {
|
|
1943
|
+
this.emitProgress(event);
|
|
1944
|
+
}
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1827
1947
|
this.emitProgress({
|
|
1828
1948
|
stage: "refreshing-instances",
|
|
1829
1949
|
label: "Refreshing instances",
|