@layr-labs/ecloud-sdk 1.0.0-dev.7 → 1.0.0-dev.8
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/VERSION +2 -2
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.js.map +1 -1
- package/dist/browser.cjs +3 -2
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +3 -2
- package/dist/browser.d.ts +3 -2
- package/dist/browser.js +3 -2
- package/dist/browser.js.map +1 -1
- package/dist/compute-B-V7Dbj9.d.cts +465 -0
- package/dist/compute-BJ_sqrKn.d.ts +465 -0
- package/dist/compute.cjs +236 -45
- package/dist/compute.cjs.map +1 -1
- package/dist/compute.d.cts +2 -1
- package/dist/compute.d.ts +2 -1
- package/dist/compute.js +224 -33
- package/dist/compute.js.map +1 -1
- package/dist/{helpers-BSorDsUi.d.ts → helpers-CkcuSkNM.d.ts} +2 -166
- package/dist/{helpers-Dcp_0i_r.d.cts → helpers-fmu7es2L.d.cts} +2 -166
- package/dist/index.cjs +247 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -242
- package/dist/index.d.ts +50 -242
- package/dist/index.js +228 -33
- package/dist/index.js.map +1 -1
- package/dist/validation-D3yIUF-Z.d.cts +167 -0
- package/dist/validation-D3yIUF-Z.d.ts +167 -0
- package/package.json +1 -1
- package/dist/compute-BqouWhdQ.d.ts +0 -194
- package/dist/compute-DwReciJz.d.cts +0 -194
package/dist/index.cjs
CHANGED
|
@@ -174,6 +174,7 @@ __export(index_exports, {
|
|
|
174
174
|
EMPTY_CONTAINER_POLICY: () => EMPTY_CONTAINER_POLICY,
|
|
175
175
|
ERC20ABI: () => ERC20_default,
|
|
176
176
|
ForbiddenError: () => ForbiddenError,
|
|
177
|
+
InsufficientGasError: () => InsufficientGasError,
|
|
177
178
|
JwtProvider: () => JwtProvider,
|
|
178
179
|
NoopClient: () => NoopClient,
|
|
179
180
|
NotFoundError: () => NotFoundError,
|
|
@@ -183,9 +184,12 @@ __export(index_exports, {
|
|
|
183
184
|
TimeoutError: () => TimeoutError,
|
|
184
185
|
USDCCreditsABI: () => USDCCredits_default,
|
|
185
186
|
UserApiClient: () => UserApiClient,
|
|
187
|
+
WATCH_DEFAULT_TIMEOUT_SECONDS: () => WATCH_DEFAULT_TIMEOUT_SECONDS,
|
|
188
|
+
WatchTimeoutError: () => WatchTimeoutError,
|
|
186
189
|
addHexPrefix: () => addHexPrefix,
|
|
187
190
|
addMetric: () => addMetric,
|
|
188
191
|
addMetricWithDimensions: () => addMetricWithDimensions,
|
|
192
|
+
assertSufficientGas: () => assertSufficientGas,
|
|
189
193
|
assertValidFilePath: () => assertValidFilePath,
|
|
190
194
|
assertValidImageReference: () => assertValidImageReference,
|
|
191
195
|
assertValidPrivateKey: () => assertValidPrivateKey,
|
|
@@ -287,7 +291,7 @@ __export(index_exports, {
|
|
|
287
291
|
module.exports = __toCommonJS(index_exports);
|
|
288
292
|
|
|
289
293
|
// src/client/modules/compute/app/index.ts
|
|
290
|
-
var
|
|
294
|
+
var import_viem7 = require("viem");
|
|
291
295
|
|
|
292
296
|
// src/client/common/docker/build.ts
|
|
293
297
|
var child_process = __toESM(require("child_process"), 1);
|
|
@@ -576,7 +580,74 @@ var PushPermissionError = class extends Error {
|
|
|
576
580
|
var import_handlebars = __toESM(require("handlebars"), 1);
|
|
577
581
|
|
|
578
582
|
// src/client/common/templates/Dockerfile.layered.tmpl
|
|
579
|
-
var Dockerfile_layered_default =
|
|
583
|
+
var Dockerfile_layered_default = `{{#if includeTLS}}
|
|
584
|
+
# Get Caddy from official image
|
|
585
|
+
FROM caddy:2.10.2-alpine AS caddy
|
|
586
|
+
{{/if}}
|
|
587
|
+
|
|
588
|
+
FROM {{baseImage}}
|
|
589
|
+
|
|
590
|
+
{{#if originalUser}}
|
|
591
|
+
# Switch to root to perform setup (base image has non-root USER: {{originalUser}})
|
|
592
|
+
USER root
|
|
593
|
+
{{/if}}
|
|
594
|
+
|
|
595
|
+
# Copy core TEE components
|
|
596
|
+
# CA bundle for kms-client / tls-keygen to validate HTTPS calls to
|
|
597
|
+
# eigencloud.xyz endpoints. Bundled at a non-standard path and consumed
|
|
598
|
+
# only via SSL_CERT_FILE in compute-source-env.sh, so the user's
|
|
599
|
+
# /etc/ssl/ is never touched.
|
|
600
|
+
COPY --from=alpine:3.20.10 /etc/ssl/certs/ca-certificates.crt /usr/local/share/eigenx-ca-certs.crt
|
|
601
|
+
COPY compute-source-env.sh /usr/local/bin/
|
|
602
|
+
COPY kms-client /usr/local/bin/
|
|
603
|
+
COPY kms-signing-public-key.pem /usr/local/bin/
|
|
604
|
+
|
|
605
|
+
{{#if includeTLS}}
|
|
606
|
+
# Copy Caddy from official image
|
|
607
|
+
COPY --from=caddy /usr/bin/caddy /usr/local/bin/caddy
|
|
608
|
+
|
|
609
|
+
# Copy TLS components
|
|
610
|
+
COPY tls-keygen /usr/local/bin/
|
|
611
|
+
COPY Caddyfile /etc/caddy/
|
|
612
|
+
{{/if}}
|
|
613
|
+
|
|
614
|
+
{{#if originalUser}}
|
|
615
|
+
# Make binaries executable (755 for executables, 644 for keys)
|
|
616
|
+
RUN chmod 755 /usr/local/bin/compute-source-env.sh \\
|
|
617
|
+
&& chmod 755 /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
618
|
+
&& chmod 755 /usr/local/bin/tls-keygen \\
|
|
619
|
+
&& chmod 755 /usr/local/bin/caddy{{/if}} \\
|
|
620
|
+
&& chmod 644 /usr/local/bin/kms-signing-public-key.pem
|
|
621
|
+
|
|
622
|
+
# Store original user - entrypoint will drop privileges to this user after TEE setup
|
|
623
|
+
ENV __ECLOUD_ORIGINAL_USER={{originalUser}}
|
|
624
|
+
{{else}}
|
|
625
|
+
# Make binaries executable (preserve existing permissions, just add execute)
|
|
626
|
+
RUN chmod +x /usr/local/bin/compute-source-env.sh \\
|
|
627
|
+
&& chmod +x /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
628
|
+
&& chmod +x /usr/local/bin/tls-keygen{{/if}}
|
|
629
|
+
{{/if}}
|
|
630
|
+
|
|
631
|
+
{{#if logRedirect}}
|
|
632
|
+
|
|
633
|
+
LABEL tee.launch_policy.log_redirect={{logRedirect}}
|
|
634
|
+
{{/if}}
|
|
635
|
+
{{#if resourceUsageAllow}}
|
|
636
|
+
|
|
637
|
+
LABEL tee.launch_policy.monitoring_memory_allow={{resourceUsageAllow}}
|
|
638
|
+
{{/if}}
|
|
639
|
+
|
|
640
|
+
LABEL eigenx_cli_version={{ecloudCLIVersion}}
|
|
641
|
+
LABEL eigenx_vm_image=eigen
|
|
642
|
+
|
|
643
|
+
{{#if includeTLS}}
|
|
644
|
+
# Expose both HTTP and HTTPS ports for Caddy
|
|
645
|
+
EXPOSE 80 443
|
|
646
|
+
{{/if}}
|
|
647
|
+
|
|
648
|
+
ENTRYPOINT ["/usr/local/bin/compute-source-env.sh"]
|
|
649
|
+
CMD {{{originalCmd}}}
|
|
650
|
+
`;
|
|
580
651
|
|
|
581
652
|
// src/client/common/templates/dockerfileTemplate.ts
|
|
582
653
|
function processDockerfileTemplate(data) {
|
|
@@ -593,7 +664,7 @@ echo "compute-source-env.sh: Running setup script..."
|
|
|
593
664
|
|
|
594
665
|
# Fetch and source environment variables from KMS
|
|
595
666
|
echo "Fetching secrets from KMS..."
|
|
596
|
-
if /usr/local/bin/kms-client \\
|
|
667
|
+
if SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt /usr/local/bin/kms-client \\
|
|
597
668
|
--kms-server-url "{{kmsServerURL}}" \\
|
|
598
669
|
--kms-signing-key-file /usr/local/bin/kms-signing-public-key.pem \\
|
|
599
670
|
--userapi-url "{{userAPIURL}}" \\
|
|
@@ -651,7 +722,8 @@ setup_tls() {
|
|
|
651
722
|
|
|
652
723
|
echo "compute-source-env.sh: Obtaining TLS certificate using $challenge challenge..."
|
|
653
724
|
# Pass the API URL for certificate persistence
|
|
654
|
-
if !
|
|
725
|
+
if ! SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt \\
|
|
726
|
+
MNEMONIC="$mnemonic" DOMAIN="$domain" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
|
|
655
727
|
-challenge "$challenge" \\
|
|
656
728
|
$staging_flag; then
|
|
657
729
|
echo "compute-source-env.sh: ERROR - Failed to obtain TLS certificate"
|
|
@@ -1044,16 +1116,7 @@ async function extractDigestFromSinglePlatform(manifest, imageRef) {
|
|
|
1044
1116
|
architecture: inspectData[0].Architecture
|
|
1045
1117
|
} : null;
|
|
1046
1118
|
if (!config) {
|
|
1047
|
-
|
|
1048
|
-
const digest = hexStringToBytes32(manifest.config.digest);
|
|
1049
|
-
const registry = extractRegistryName(imageRef);
|
|
1050
|
-
return {
|
|
1051
|
-
digest,
|
|
1052
|
-
registry,
|
|
1053
|
-
platform: DOCKER_PLATFORM
|
|
1054
|
-
};
|
|
1055
|
-
}
|
|
1056
|
-
throw new Error(`Could not determine platform for ${imageRef}`);
|
|
1119
|
+
throw createPlatformErrorMessage(imageRef, ["unknown (could not determine architecture)"]);
|
|
1057
1120
|
}
|
|
1058
1121
|
const platform2 = `${config.os}/${config.architecture}`;
|
|
1059
1122
|
if (platform2 === DOCKER_PLATFORM) {
|
|
@@ -1125,14 +1188,11 @@ Image: ${imageRef}
|
|
|
1125
1188
|
Found platform(s): ${platforms.join(", ")}
|
|
1126
1189
|
Required platform: ${DOCKER_PLATFORM}
|
|
1127
1190
|
|
|
1128
|
-
To fix
|
|
1129
|
-
1.
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
docker push ${imageRef}
|
|
1134
|
-
|
|
1135
|
-
2. Or use the SDK to build with the correct platform automatically.`;
|
|
1191
|
+
To fix, either:
|
|
1192
|
+
1. Rebuild the image for ${DOCKER_PLATFORM} and push it:
|
|
1193
|
+
docker buildx build --platform ${DOCKER_PLATFORM} -t ${imageRef} --push .
|
|
1194
|
+
2. Or use a verifiable build (--verifiable --repo <repo> --commit <sha>), which
|
|
1195
|
+
builds server-side and needs no local Docker.`;
|
|
1136
1196
|
return new Error(errorMsg);
|
|
1137
1197
|
}
|
|
1138
1198
|
|
|
@@ -1237,6 +1297,8 @@ async function prepareRelease(options, logger) {
|
|
|
1237
1297
|
logger.info(`Waiting ${REGISTRY_PROPAGATION_WAIT_SECONDS} seconds for registry propagation...`);
|
|
1238
1298
|
await new Promise((resolve2) => setTimeout(resolve2, REGISTRY_PROPAGATION_WAIT_SECONDS * 1e3));
|
|
1239
1299
|
} else {
|
|
1300
|
+
logger.info("Verifying image platform (linux/amd64)...");
|
|
1301
|
+
await getImageDigestAndName(imageRef);
|
|
1240
1302
|
logger.info("Checking if image needs layering...");
|
|
1241
1303
|
finalImageRef = await layerRemoteImageIfNeeded(
|
|
1242
1304
|
{
|
|
@@ -6442,12 +6504,41 @@ async function undelegate(options, logger = noopLogger) {
|
|
|
6442
6504
|
return hash;
|
|
6443
6505
|
}
|
|
6444
6506
|
|
|
6507
|
+
// src/client/common/gas/insufficientGas.ts
|
|
6508
|
+
var import_viem4 = require("viem");
|
|
6509
|
+
var InsufficientGasError = class extends Error {
|
|
6510
|
+
constructor(args) {
|
|
6511
|
+
const requiredEth = (0, import_viem4.formatEther)(args.requiredWei);
|
|
6512
|
+
const availableEth = (0, import_viem4.formatEther)(args.availableWei);
|
|
6513
|
+
super(
|
|
6514
|
+
`Insufficient ETH for gas: wallet ${args.address} has ${availableEth} ETH but this transaction needs ~${requiredEth} ETH.
|
|
6515
|
+
Compute credits do not pay on-chain gas \u2014 fund the wallet with ETH and retry.`
|
|
6516
|
+
);
|
|
6517
|
+
this.name = "InsufficientGasError";
|
|
6518
|
+
this.address = args.address;
|
|
6519
|
+
this.requiredWei = args.requiredWei;
|
|
6520
|
+
this.availableWei = args.availableWei;
|
|
6521
|
+
this.requiredEth = requiredEth;
|
|
6522
|
+
this.availableEth = availableEth;
|
|
6523
|
+
}
|
|
6524
|
+
};
|
|
6525
|
+
async function assertSufficientGas(args) {
|
|
6526
|
+
const availableWei = await args.publicClient.getBalance({ address: args.address });
|
|
6527
|
+
if (availableWei < args.gasEstimate.maxCostWei) {
|
|
6528
|
+
throw new InsufficientGasError({
|
|
6529
|
+
address: args.address,
|
|
6530
|
+
requiredWei: args.gasEstimate.maxCostWei,
|
|
6531
|
+
availableWei
|
|
6532
|
+
});
|
|
6533
|
+
}
|
|
6534
|
+
}
|
|
6535
|
+
|
|
6445
6536
|
// src/client/common/utils/userapi.ts
|
|
6446
6537
|
var import_axios2 = __toESM(require("axios"), 1);
|
|
6447
6538
|
|
|
6448
6539
|
// src/client/common/utils/auth.ts
|
|
6449
|
-
var
|
|
6450
|
-
var APP_CONTROLLER_ABI = (0,
|
|
6540
|
+
var import_viem5 = require("viem");
|
|
6541
|
+
var APP_CONTROLLER_ABI = (0, import_viem5.parseAbi)([
|
|
6451
6542
|
"function calculateApiPermissionDigestHash(bytes4 permission, uint256 expiry) view returns (bytes32)"
|
|
6452
6543
|
]);
|
|
6453
6544
|
async function calculatePermissionSignature(options) {
|
|
@@ -6505,6 +6596,7 @@ var import_axios = __toESM(require("axios"), 1);
|
|
|
6505
6596
|
var MAX_RETRIES = 5;
|
|
6506
6597
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
6507
6598
|
var MAX_BACKOFF_MS = 3e4;
|
|
6599
|
+
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
|
|
6508
6600
|
function sleep(ms) {
|
|
6509
6601
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
6510
6602
|
}
|
|
@@ -6524,7 +6616,7 @@ async function requestWithRetry(config) {
|
|
|
6524
6616
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
6525
6617
|
const res = await (0, import_axios.default)({ ...config, validateStatus: () => true });
|
|
6526
6618
|
lastResponse = res;
|
|
6527
|
-
if (res.status
|
|
6619
|
+
if (!RETRYABLE_STATUSES.has(res.status)) {
|
|
6528
6620
|
return res;
|
|
6529
6621
|
}
|
|
6530
6622
|
if (attempt < MAX_RETRIES) {
|
|
@@ -6553,7 +6645,7 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
|
6553
6645
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
6554
6646
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
6555
6647
|
function getDefaultClientId() {
|
|
6556
|
-
const version = true ? "1.0.0-dev.
|
|
6648
|
+
const version = true ? "1.0.0-dev.8" : "0.0.0";
|
|
6557
6649
|
return `ecloud-sdk/v${version}`;
|
|
6558
6650
|
}
|
|
6559
6651
|
var UserApiClient = class {
|
|
@@ -6891,8 +6983,36 @@ function transformAppRelease(raw) {
|
|
|
6891
6983
|
|
|
6892
6984
|
// src/client/common/contract/watcher.ts
|
|
6893
6985
|
var WATCH_POLL_INTERVAL_SECONDS = 5;
|
|
6986
|
+
var WATCH_HEARTBEAT_INTERVAL_SECONDS = 30;
|
|
6987
|
+
var WATCH_DEFAULT_TIMEOUT_SECONDS = 10 * 60;
|
|
6894
6988
|
var APP_STATUS_RUNNING = "Running";
|
|
6895
6989
|
var APP_STATUS_FAILED = "Failed";
|
|
6990
|
+
var WatchTimeoutError = class extends Error {
|
|
6991
|
+
constructor(args) {
|
|
6992
|
+
super(
|
|
6993
|
+
args.message ?? `Timed out after ${args.elapsedSeconds}s waiting for app ${args.appId} (last status: ${args.lastStatus ?? "unknown"})`
|
|
6994
|
+
);
|
|
6995
|
+
this.name = "WatchTimeoutError";
|
|
6996
|
+
this.appId = args.appId;
|
|
6997
|
+
this.elapsedSeconds = args.elapsedSeconds;
|
|
6998
|
+
this.lastStatus = args.lastStatus;
|
|
6999
|
+
this.timeoutSeconds = args.timeoutSeconds;
|
|
7000
|
+
}
|
|
7001
|
+
};
|
|
7002
|
+
function resolveWatchTimeoutSeconds(explicit) {
|
|
7003
|
+
if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0) {
|
|
7004
|
+
return Math.floor(explicit);
|
|
7005
|
+
}
|
|
7006
|
+
const raw = process.env.ECLOUD_WATCH_TIMEOUT_SECONDS;
|
|
7007
|
+
if (raw === void 0 || raw === "") {
|
|
7008
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
7009
|
+
}
|
|
7010
|
+
const parsed = Number(raw);
|
|
7011
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
7012
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
7013
|
+
}
|
|
7014
|
+
return Math.floor(parsed);
|
|
7015
|
+
}
|
|
6896
7016
|
async function watchUntilRunning(options, logger) {
|
|
6897
7017
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
6898
7018
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
@@ -6923,8 +7043,20 @@ async function watchUntilRunning(options, logger) {
|
|
|
6923
7043
|
return false;
|
|
6924
7044
|
};
|
|
6925
7045
|
const startTime = Date.now();
|
|
7046
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
6926
7047
|
let lastLoggedStatus;
|
|
7048
|
+
let lastHeartbeatAt = startTime;
|
|
6927
7049
|
while (true) {
|
|
7050
|
+
const elapsedMs = Date.now() - startTime;
|
|
7051
|
+
const elapsed = Math.round(elapsedMs / 1e3);
|
|
7052
|
+
if (elapsed >= timeoutSeconds) {
|
|
7053
|
+
throw new WatchTimeoutError({
|
|
7054
|
+
appId,
|
|
7055
|
+
elapsedSeconds: elapsed,
|
|
7056
|
+
lastStatus: lastLoggedStatus,
|
|
7057
|
+
timeoutSeconds
|
|
7058
|
+
});
|
|
7059
|
+
}
|
|
6928
7060
|
try {
|
|
6929
7061
|
const info = await userApiClient.getInfos([appId], 1);
|
|
6930
7062
|
if (info.length === 0) {
|
|
@@ -6934,16 +7066,22 @@ async function watchUntilRunning(options, logger) {
|
|
|
6934
7066
|
const appInfo = info[0];
|
|
6935
7067
|
const currentStatus = appInfo.status;
|
|
6936
7068
|
const currentIP = appInfo.ip || "";
|
|
6937
|
-
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
6938
7069
|
if (currentStatus !== lastLoggedStatus) {
|
|
6939
7070
|
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
6940
7071
|
lastLoggedStatus = currentStatus;
|
|
7072
|
+
lastHeartbeatAt = Date.now();
|
|
7073
|
+
} else if (Date.now() - lastHeartbeatAt >= WATCH_HEARTBEAT_INTERVAL_SECONDS * 1e3) {
|
|
7074
|
+
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
7075
|
+
lastHeartbeatAt = Date.now();
|
|
6941
7076
|
}
|
|
6942
7077
|
if (stopCondition(currentStatus, currentIP)) {
|
|
6943
7078
|
return currentIP || void 0;
|
|
6944
7079
|
}
|
|
6945
7080
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
6946
7081
|
} catch (error) {
|
|
7082
|
+
if (error instanceof WatchTimeoutError) {
|
|
7083
|
+
throw error;
|
|
7084
|
+
}
|
|
6947
7085
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
6948
7086
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
6949
7087
|
}
|
|
@@ -6952,6 +7090,7 @@ async function watchUntilRunning(options, logger) {
|
|
|
6952
7090
|
var APP_STATUS_STOPPED = "Stopped";
|
|
6953
7091
|
async function watchUntilUpgradeComplete(options, logger) {
|
|
6954
7092
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
7093
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
6955
7094
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
6956
7095
|
let initialStatus;
|
|
6957
7096
|
let initialIP;
|
|
@@ -6989,7 +7128,20 @@ async function watchUntilUpgradeComplete(options, logger) {
|
|
|
6989
7128
|
}
|
|
6990
7129
|
return false;
|
|
6991
7130
|
};
|
|
7131
|
+
const startTime = Date.now();
|
|
7132
|
+
const deadline = startTime + timeoutSeconds * 1e3;
|
|
7133
|
+
let lastLoggedStatus;
|
|
7134
|
+
let lastObservedStatus;
|
|
6992
7135
|
while (true) {
|
|
7136
|
+
if (Date.now() >= deadline) {
|
|
7137
|
+
const elapsedSeconds = Math.round((Date.now() - startTime) / 1e3);
|
|
7138
|
+
throw new WatchTimeoutError({
|
|
7139
|
+
appId,
|
|
7140
|
+
lastStatus: lastObservedStatus,
|
|
7141
|
+
elapsedSeconds,
|
|
7142
|
+
timeoutSeconds
|
|
7143
|
+
});
|
|
7144
|
+
}
|
|
6993
7145
|
try {
|
|
6994
7146
|
const info = await userApiClient.getInfos([appId], 1);
|
|
6995
7147
|
if (info.length === 0) {
|
|
@@ -6999,11 +7151,23 @@ async function watchUntilUpgradeComplete(options, logger) {
|
|
|
6999
7151
|
const appInfo = info[0];
|
|
7000
7152
|
const currentStatus = appInfo.status;
|
|
7001
7153
|
const currentIP = appInfo.ip || "";
|
|
7154
|
+
lastObservedStatus = currentStatus;
|
|
7155
|
+
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
7156
|
+
if (currentStatus !== lastLoggedStatus) {
|
|
7157
|
+
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
7158
|
+
lastLoggedStatus = currentStatus;
|
|
7159
|
+
}
|
|
7002
7160
|
if (stopCondition(currentStatus, currentIP)) {
|
|
7003
7161
|
return;
|
|
7004
7162
|
}
|
|
7005
7163
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
7006
7164
|
} catch (error) {
|
|
7165
|
+
if (error instanceof WatchTimeoutError) {
|
|
7166
|
+
throw error;
|
|
7167
|
+
}
|
|
7168
|
+
if (typeof error?.message === "string" && error.message.includes("Failed")) {
|
|
7169
|
+
throw error;
|
|
7170
|
+
}
|
|
7007
7171
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
7008
7172
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
7009
7173
|
}
|
|
@@ -7016,7 +7180,7 @@ function sleep2(ms) {
|
|
|
7016
7180
|
// src/client/common/utils/validation.ts
|
|
7017
7181
|
var import_fs = __toESM(require("fs"), 1);
|
|
7018
7182
|
var import_path = __toESM(require("path"), 1);
|
|
7019
|
-
var
|
|
7183
|
+
var import_viem6 = require("viem");
|
|
7020
7184
|
function validateAppName(name) {
|
|
7021
7185
|
if (!name) {
|
|
7022
7186
|
throw new Error("App name cannot be empty");
|
|
@@ -7168,7 +7332,7 @@ function validateAppID(appID) {
|
|
|
7168
7332
|
throw new Error("App ID is required");
|
|
7169
7333
|
}
|
|
7170
7334
|
const normalized = typeof appID === "string" ? addHexPrefix(appID) : appID;
|
|
7171
|
-
if ((0,
|
|
7335
|
+
if ((0, import_viem6.isAddress)(normalized)) {
|
|
7172
7336
|
return normalized;
|
|
7173
7337
|
}
|
|
7174
7338
|
throw new Error(`Invalid app ID: '${appID}' is not a valid address`);
|
|
@@ -8224,6 +8388,11 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
8224
8388
|
executions: batch.executions,
|
|
8225
8389
|
authorizationList
|
|
8226
8390
|
});
|
|
8391
|
+
await assertSufficientGas({
|
|
8392
|
+
publicClient: batch.publicClient,
|
|
8393
|
+
address: batch.walletClient.account.address,
|
|
8394
|
+
gasEstimate
|
|
8395
|
+
});
|
|
8227
8396
|
const data = {
|
|
8228
8397
|
appId: batch.appId,
|
|
8229
8398
|
salt: batch.salt,
|
|
@@ -8482,6 +8651,11 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
8482
8651
|
executions: batch.executions,
|
|
8483
8652
|
authorizationList
|
|
8484
8653
|
});
|
|
8654
|
+
await assertSufficientGas({
|
|
8655
|
+
publicClient: batch.publicClient,
|
|
8656
|
+
address: batch.walletClient.account.address,
|
|
8657
|
+
gasEstimate
|
|
8658
|
+
});
|
|
8485
8659
|
const data = {
|
|
8486
8660
|
appId: batch.appId,
|
|
8487
8661
|
salt: batch.salt,
|
|
@@ -8518,7 +8692,7 @@ async function executeDeploy(options) {
|
|
|
8518
8692
|
}
|
|
8519
8693
|
);
|
|
8520
8694
|
}
|
|
8521
|
-
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
8695
|
+
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
8522
8696
|
return withSDKTelemetry(
|
|
8523
8697
|
{
|
|
8524
8698
|
functionName: "watchDeployment",
|
|
@@ -8534,7 +8708,8 @@ async function watchDeployment(appId, walletClient, publicClient, environmentCon
|
|
|
8534
8708
|
walletClient,
|
|
8535
8709
|
publicClient,
|
|
8536
8710
|
environmentConfig,
|
|
8537
|
-
appId
|
|
8711
|
+
appId,
|
|
8712
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
8538
8713
|
},
|
|
8539
8714
|
logger
|
|
8540
8715
|
);
|
|
@@ -8630,6 +8805,11 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
8630
8805
|
executions: batch.executions,
|
|
8631
8806
|
authorizationList
|
|
8632
8807
|
});
|
|
8808
|
+
await assertSufficientGas({
|
|
8809
|
+
publicClient: batch.publicClient,
|
|
8810
|
+
address: batch.walletClient.account.address,
|
|
8811
|
+
gasEstimate
|
|
8812
|
+
});
|
|
8633
8813
|
const data = {
|
|
8634
8814
|
appId: batch.appId,
|
|
8635
8815
|
executions: batch.executions,
|
|
@@ -8819,6 +8999,11 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
8819
8999
|
executions: batch.executions,
|
|
8820
9000
|
authorizationList
|
|
8821
9001
|
});
|
|
9002
|
+
await assertSufficientGas({
|
|
9003
|
+
publicClient: batch.publicClient,
|
|
9004
|
+
address: batch.walletClient.account.address,
|
|
9005
|
+
gasEstimate
|
|
9006
|
+
});
|
|
8822
9007
|
const data = {
|
|
8823
9008
|
appId: batch.appId,
|
|
8824
9009
|
executions: batch.executions,
|
|
@@ -8853,7 +9038,7 @@ async function executeUpgrade(options) {
|
|
|
8853
9038
|
}
|
|
8854
9039
|
);
|
|
8855
9040
|
}
|
|
8856
|
-
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
9041
|
+
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
8857
9042
|
return withSDKTelemetry(
|
|
8858
9043
|
{
|
|
8859
9044
|
functionName: "watchUpgrade",
|
|
@@ -8869,7 +9054,8 @@ async function watchUpgrade(appId, walletClient, publicClient, environmentConfig
|
|
|
8869
9054
|
walletClient,
|
|
8870
9055
|
publicClient,
|
|
8871
9056
|
environmentConfig,
|
|
8872
|
-
appId
|
|
9057
|
+
appId,
|
|
9058
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
8873
9059
|
},
|
|
8874
9060
|
logger
|
|
8875
9061
|
);
|
|
@@ -9527,27 +9713,27 @@ async function logs(options, walletClient, publicClient, environmentConfig, logg
|
|
|
9527
9713
|
}
|
|
9528
9714
|
|
|
9529
9715
|
// src/client/modules/compute/app/index.ts
|
|
9530
|
-
var CONTROLLER_ABI = (0,
|
|
9716
|
+
var CONTROLLER_ABI = (0, import_viem7.parseAbi)([
|
|
9531
9717
|
"function startApp(address appId)",
|
|
9532
9718
|
"function stopApp(address appId)",
|
|
9533
9719
|
"function terminateApp(address appId)"
|
|
9534
9720
|
]);
|
|
9535
9721
|
function encodeStartAppData(appId) {
|
|
9536
|
-
return (0,
|
|
9722
|
+
return (0, import_viem7.encodeFunctionData)({
|
|
9537
9723
|
abi: CONTROLLER_ABI,
|
|
9538
9724
|
functionName: "startApp",
|
|
9539
9725
|
args: [appId]
|
|
9540
9726
|
});
|
|
9541
9727
|
}
|
|
9542
9728
|
function encodeStopAppData(appId) {
|
|
9543
|
-
return (0,
|
|
9729
|
+
return (0, import_viem7.encodeFunctionData)({
|
|
9544
9730
|
abi: CONTROLLER_ABI,
|
|
9545
9731
|
functionName: "stopApp",
|
|
9546
9732
|
args: [appId]
|
|
9547
9733
|
});
|
|
9548
9734
|
}
|
|
9549
9735
|
function encodeTerminateAppData(appId) {
|
|
9550
|
-
return (0,
|
|
9736
|
+
return (0, import_viem7.encodeFunctionData)({
|
|
9551
9737
|
abi: CONTROLLER_ABI,
|
|
9552
9738
|
functionName: "terminateApp",
|
|
9553
9739
|
args: [appId]
|
|
@@ -9561,7 +9747,7 @@ function createAppModule(ctx) {
|
|
|
9561
9747
|
}
|
|
9562
9748
|
const account = walletClient.account;
|
|
9563
9749
|
const environment = getEnvironmentConfig(ctx.environment);
|
|
9564
|
-
const logger = getLogger(ctx.verbose);
|
|
9750
|
+
const logger = ctx.logger ?? getLogger(ctx.verbose);
|
|
9565
9751
|
return {
|
|
9566
9752
|
async create(opts) {
|
|
9567
9753
|
return createApp(opts, logger);
|
|
@@ -9673,14 +9859,15 @@ function createAppModule(ctx) {
|
|
|
9673
9859
|
imageRef: result.imageRef
|
|
9674
9860
|
};
|
|
9675
9861
|
},
|
|
9676
|
-
async watchDeployment(appId) {
|
|
9862
|
+
async watchDeployment(appId, opts) {
|
|
9677
9863
|
return watchDeployment(
|
|
9678
9864
|
appId,
|
|
9679
9865
|
walletClient,
|
|
9680
9866
|
publicClient,
|
|
9681
9867
|
environment,
|
|
9682
9868
|
logger,
|
|
9683
|
-
skipTelemetry
|
|
9869
|
+
skipTelemetry,
|
|
9870
|
+
opts
|
|
9684
9871
|
);
|
|
9685
9872
|
},
|
|
9686
9873
|
// Granular upgrade control
|
|
@@ -9738,8 +9925,16 @@ function createAppModule(ctx) {
|
|
|
9738
9925
|
imageRef: result.imageRef
|
|
9739
9926
|
};
|
|
9740
9927
|
},
|
|
9741
|
-
async watchUpgrade(appId) {
|
|
9742
|
-
return watchUpgrade(
|
|
9928
|
+
async watchUpgrade(appId, opts) {
|
|
9929
|
+
return watchUpgrade(
|
|
9930
|
+
appId,
|
|
9931
|
+
walletClient,
|
|
9932
|
+
publicClient,
|
|
9933
|
+
environment,
|
|
9934
|
+
logger,
|
|
9935
|
+
skipTelemetry,
|
|
9936
|
+
opts
|
|
9937
|
+
);
|
|
9743
9938
|
},
|
|
9744
9939
|
// Profile management
|
|
9745
9940
|
async setProfile(appId, profile) {
|
|
@@ -9790,7 +9985,7 @@ function createAppModule(ctx) {
|
|
|
9790
9985
|
},
|
|
9791
9986
|
async () => {
|
|
9792
9987
|
const pendingMessage = `Starting app ${appId}...`;
|
|
9793
|
-
const data = (0,
|
|
9988
|
+
const data = (0, import_viem7.encodeFunctionData)({
|
|
9794
9989
|
abi: CONTROLLER_ABI,
|
|
9795
9990
|
functionName: "startApp",
|
|
9796
9991
|
args: [appId]
|
|
@@ -9822,7 +10017,7 @@ function createAppModule(ctx) {
|
|
|
9822
10017
|
},
|
|
9823
10018
|
async () => {
|
|
9824
10019
|
const pendingMessage = `Stopping app ${appId}...`;
|
|
9825
|
-
const data = (0,
|
|
10020
|
+
const data = (0, import_viem7.encodeFunctionData)({
|
|
9826
10021
|
abi: CONTROLLER_ABI,
|
|
9827
10022
|
functionName: "stopApp",
|
|
9828
10023
|
args: [appId]
|
|
@@ -9854,7 +10049,7 @@ function createAppModule(ctx) {
|
|
|
9854
10049
|
},
|
|
9855
10050
|
async () => {
|
|
9856
10051
|
const pendingMessage = `Terminating app ${appId}...`;
|
|
9857
|
-
const data = (0,
|
|
10052
|
+
const data = (0, import_viem7.encodeFunctionData)({
|
|
9858
10053
|
abi: CONTROLLER_ABI,
|
|
9859
10054
|
functionName: "terminateApp",
|
|
9860
10055
|
args: [appId]
|
|
@@ -9921,7 +10116,7 @@ function createComputeModule(config) {
|
|
|
9921
10116
|
}
|
|
9922
10117
|
|
|
9923
10118
|
// src/client/modules/billing/index.ts
|
|
9924
|
-
var
|
|
10119
|
+
var import_viem8 = require("viem");
|
|
9925
10120
|
|
|
9926
10121
|
// src/client/common/abis/USDCCredits.json
|
|
9927
10122
|
var USDCCredits_default = [
|
|
@@ -10106,7 +10301,7 @@ function createBillingModule(config) {
|
|
|
10106
10301
|
executions.push({
|
|
10107
10302
|
target: usdcAddress,
|
|
10108
10303
|
value: 0n,
|
|
10109
|
-
callData: (0,
|
|
10304
|
+
callData: (0, import_viem8.encodeFunctionData)({
|
|
10110
10305
|
abi: ERC20_default,
|
|
10111
10306
|
functionName: "approve",
|
|
10112
10307
|
args: [creditsAddress, opts.amount]
|
|
@@ -10116,7 +10311,7 @@ function createBillingModule(config) {
|
|
|
10116
10311
|
executions.push({
|
|
10117
10312
|
target: creditsAddress,
|
|
10118
10313
|
value: 0n,
|
|
10119
|
-
callData: (0,
|
|
10314
|
+
callData: (0, import_viem8.encodeFunctionData)({
|
|
10120
10315
|
abi: USDCCredits_default,
|
|
10121
10316
|
functionName: "purchaseCreditsFor",
|
|
10122
10317
|
args: [opts.amount, targetAccount]
|
|
@@ -11253,6 +11448,7 @@ var JwtProvider = class {
|
|
|
11253
11448
|
EMPTY_CONTAINER_POLICY,
|
|
11254
11449
|
ERC20ABI,
|
|
11255
11450
|
ForbiddenError,
|
|
11451
|
+
InsufficientGasError,
|
|
11256
11452
|
JwtProvider,
|
|
11257
11453
|
NoopClient,
|
|
11258
11454
|
NotFoundError,
|
|
@@ -11262,9 +11458,12 @@ var JwtProvider = class {
|
|
|
11262
11458
|
TimeoutError,
|
|
11263
11459
|
USDCCreditsABI,
|
|
11264
11460
|
UserApiClient,
|
|
11461
|
+
WATCH_DEFAULT_TIMEOUT_SECONDS,
|
|
11462
|
+
WatchTimeoutError,
|
|
11265
11463
|
addHexPrefix,
|
|
11266
11464
|
addMetric,
|
|
11267
11465
|
addMetricWithDimensions,
|
|
11466
|
+
assertSufficientGas,
|
|
11268
11467
|
assertValidFilePath,
|
|
11269
11468
|
assertValidImageReference,
|
|
11270
11469
|
assertValidPrivateKey,
|