@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/dist/compute.cjs CHANGED
@@ -167,7 +167,7 @@ __export(compute_exports, {
167
167
  module.exports = __toCommonJS(compute_exports);
168
168
 
169
169
  // src/client/modules/compute/app/index.ts
170
- var import_viem6 = require("viem");
170
+ var import_viem7 = require("viem");
171
171
 
172
172
  // src/client/common/docker/build.ts
173
173
  var child_process = __toESM(require("child_process"), 1);
@@ -456,7 +456,74 @@ var PushPermissionError = class extends Error {
456
456
  var import_handlebars = __toESM(require("handlebars"), 1);
457
457
 
458
458
  // src/client/common/templates/Dockerfile.layered.tmpl
459
- var Dockerfile_layered_default = '{{#if includeTLS}}\n# Get Caddy from official image\nFROM caddy:2.10.2-alpine AS caddy\n{{/if}}\n\nFROM {{baseImage}}\n\n{{#if originalUser}}\n# Switch to root to perform setup (base image has non-root USER: {{originalUser}})\nUSER root\n{{/if}}\n\n# Copy core TEE components\nCOPY compute-source-env.sh /usr/local/bin/\nCOPY kms-client /usr/local/bin/\nCOPY kms-signing-public-key.pem /usr/local/bin/\n\n{{#if includeTLS}}\n# Copy Caddy from official image\nCOPY --from=caddy /usr/bin/caddy /usr/local/bin/caddy\n\n# Copy TLS components\nCOPY tls-keygen /usr/local/bin/\nCOPY Caddyfile /etc/caddy/\n{{/if}}\n\n{{#if originalUser}}\n# Make binaries executable (755 for executables, 644 for keys)\nRUN chmod 755 /usr/local/bin/compute-source-env.sh \\\n && chmod 755 /usr/local/bin/kms-client{{#if includeTLS}} \\\n && chmod 755 /usr/local/bin/tls-keygen \\\n && chmod 755 /usr/local/bin/caddy{{/if}} \\\n && chmod 644 /usr/local/bin/kms-signing-public-key.pem\n\n# Store original user - entrypoint will drop privileges to this user after TEE setup\nENV __ECLOUD_ORIGINAL_USER={{originalUser}}\n{{else}}\n# Make binaries executable (preserve existing permissions, just add execute)\nRUN chmod +x /usr/local/bin/compute-source-env.sh \\\n && chmod +x /usr/local/bin/kms-client{{#if includeTLS}} \\\n && chmod +x /usr/local/bin/tls-keygen{{/if}}\n{{/if}}\n\n{{#if logRedirect}}\n\nLABEL tee.launch_policy.log_redirect={{logRedirect}}\n{{/if}}\n{{#if resourceUsageAllow}}\n\nLABEL tee.launch_policy.monitoring_memory_allow={{resourceUsageAllow}}\n{{/if}}\n\nLABEL eigenx_cli_version={{ecloudCLIVersion}}\nLABEL eigenx_vm_image=eigen\n\n{{#if includeTLS}}\n# Expose both HTTP and HTTPS ports for Caddy\nEXPOSE 80 443\n{{/if}}\n\nENTRYPOINT ["/usr/local/bin/compute-source-env.sh"]\nCMD {{{originalCmd}}}\n';
459
+ var Dockerfile_layered_default = `{{#if includeTLS}}
460
+ # Get Caddy from official image
461
+ FROM caddy:2.10.2-alpine AS caddy
462
+ {{/if}}
463
+
464
+ FROM {{baseImage}}
465
+
466
+ {{#if originalUser}}
467
+ # Switch to root to perform setup (base image has non-root USER: {{originalUser}})
468
+ USER root
469
+ {{/if}}
470
+
471
+ # Copy core TEE components
472
+ # CA bundle for kms-client / tls-keygen to validate HTTPS calls to
473
+ # eigencloud.xyz endpoints. Bundled at a non-standard path and consumed
474
+ # only via SSL_CERT_FILE in compute-source-env.sh, so the user's
475
+ # /etc/ssl/ is never touched.
476
+ COPY --from=alpine:3.20.10 /etc/ssl/certs/ca-certificates.crt /usr/local/share/eigenx-ca-certs.crt
477
+ COPY compute-source-env.sh /usr/local/bin/
478
+ COPY kms-client /usr/local/bin/
479
+ COPY kms-signing-public-key.pem /usr/local/bin/
480
+
481
+ {{#if includeTLS}}
482
+ # Copy Caddy from official image
483
+ COPY --from=caddy /usr/bin/caddy /usr/local/bin/caddy
484
+
485
+ # Copy TLS components
486
+ COPY tls-keygen /usr/local/bin/
487
+ COPY Caddyfile /etc/caddy/
488
+ {{/if}}
489
+
490
+ {{#if originalUser}}
491
+ # Make binaries executable (755 for executables, 644 for keys)
492
+ RUN chmod 755 /usr/local/bin/compute-source-env.sh \\
493
+ && chmod 755 /usr/local/bin/kms-client{{#if includeTLS}} \\
494
+ && chmod 755 /usr/local/bin/tls-keygen \\
495
+ && chmod 755 /usr/local/bin/caddy{{/if}} \\
496
+ && chmod 644 /usr/local/bin/kms-signing-public-key.pem
497
+
498
+ # Store original user - entrypoint will drop privileges to this user after TEE setup
499
+ ENV __ECLOUD_ORIGINAL_USER={{originalUser}}
500
+ {{else}}
501
+ # Make binaries executable (preserve existing permissions, just add execute)
502
+ RUN chmod +x /usr/local/bin/compute-source-env.sh \\
503
+ && chmod +x /usr/local/bin/kms-client{{#if includeTLS}} \\
504
+ && chmod +x /usr/local/bin/tls-keygen{{/if}}
505
+ {{/if}}
506
+
507
+ {{#if logRedirect}}
508
+
509
+ LABEL tee.launch_policy.log_redirect={{logRedirect}}
510
+ {{/if}}
511
+ {{#if resourceUsageAllow}}
512
+
513
+ LABEL tee.launch_policy.monitoring_memory_allow={{resourceUsageAllow}}
514
+ {{/if}}
515
+
516
+ LABEL eigenx_cli_version={{ecloudCLIVersion}}
517
+ LABEL eigenx_vm_image=eigen
518
+
519
+ {{#if includeTLS}}
520
+ # Expose both HTTP and HTTPS ports for Caddy
521
+ EXPOSE 80 443
522
+ {{/if}}
523
+
524
+ ENTRYPOINT ["/usr/local/bin/compute-source-env.sh"]
525
+ CMD {{{originalCmd}}}
526
+ `;
460
527
 
461
528
  // src/client/common/templates/dockerfileTemplate.ts
462
529
  function processDockerfileTemplate(data) {
@@ -473,7 +540,7 @@ echo "compute-source-env.sh: Running setup script..."
473
540
 
474
541
  # Fetch and source environment variables from KMS
475
542
  echo "Fetching secrets from KMS..."
476
- if /usr/local/bin/kms-client \\
543
+ if SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt /usr/local/bin/kms-client \\
477
544
  --kms-server-url "{{kmsServerURL}}" \\
478
545
  --kms-signing-key-file /usr/local/bin/kms-signing-public-key.pem \\
479
546
  --userapi-url "{{userAPIURL}}" \\
@@ -531,7 +598,8 @@ setup_tls() {
531
598
 
532
599
  echo "compute-source-env.sh: Obtaining TLS certificate using $challenge challenge..."
533
600
  # Pass the API URL for certificate persistence
534
- if ! MNEMONIC="$mnemonic" DOMAIN="$domain" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
601
+ if ! SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt \\
602
+ MNEMONIC="$mnemonic" DOMAIN="$domain" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
535
603
  -challenge "$challenge" \\
536
604
  $staging_flag; then
537
605
  echo "compute-source-env.sh: ERROR - Failed to obtain TLS certificate"
@@ -924,16 +992,7 @@ async function extractDigestFromSinglePlatform(manifest, imageRef) {
924
992
  architecture: inspectData[0].Architecture
925
993
  } : null;
926
994
  if (!config) {
927
- if (manifest.config?.digest) {
928
- const digest = hexStringToBytes32(manifest.config.digest);
929
- const registry = extractRegistryName(imageRef);
930
- return {
931
- digest,
932
- registry,
933
- platform: DOCKER_PLATFORM
934
- };
935
- }
936
- throw new Error(`Could not determine platform for ${imageRef}`);
995
+ throw createPlatformErrorMessage(imageRef, ["unknown (could not determine architecture)"]);
937
996
  }
938
997
  const platform2 = `${config.os}/${config.architecture}`;
939
998
  if (platform2 === DOCKER_PLATFORM) {
@@ -1005,14 +1064,11 @@ Image: ${imageRef}
1005
1064
  Found platform(s): ${platforms.join(", ")}
1006
1065
  Required platform: ${DOCKER_PLATFORM}
1007
1066
 
1008
- To fix this issue:
1009
- 1. Manual fix:
1010
- a. Rebuild your image with the correct platform:
1011
- docker build --platform ${DOCKER_PLATFORM} -t ${imageRef} .
1012
- b. Push the rebuilt image to your remote registry:
1013
- docker push ${imageRef}
1014
-
1015
- 2. Or use the SDK to build with the correct platform automatically.`;
1067
+ To fix, either:
1068
+ 1. Rebuild the image for ${DOCKER_PLATFORM} and push it:
1069
+ docker buildx build --platform ${DOCKER_PLATFORM} -t ${imageRef} --push .
1070
+ 2. Or use a verifiable build (--verifiable --repo <repo> --commit <sha>), which
1071
+ builds server-side and needs no local Docker.`;
1016
1072
  return new Error(errorMsg);
1017
1073
  }
1018
1074
 
@@ -1117,6 +1173,8 @@ async function prepareRelease(options, logger) {
1117
1173
  logger.info(`Waiting ${REGISTRY_PROPAGATION_WAIT_SECONDS} seconds for registry propagation...`);
1118
1174
  await new Promise((resolve2) => setTimeout(resolve2, REGISTRY_PROPAGATION_WAIT_SECONDS * 1e3));
1119
1175
  } else {
1176
+ logger.info("Verifying image platform (linux/amd64)...");
1177
+ await getImageDigestAndName(imageRef);
1120
1178
  logger.info("Checking if image needs layering...");
1121
1179
  finalImageRef = await layerRemoteImageIfNeeded(
1122
1180
  {
@@ -6213,12 +6271,41 @@ async function undelegate(options, logger = noopLogger) {
6213
6271
  return hash;
6214
6272
  }
6215
6273
 
6274
+ // src/client/common/gas/insufficientGas.ts
6275
+ var import_viem4 = require("viem");
6276
+ var InsufficientGasError = class extends Error {
6277
+ constructor(args) {
6278
+ const requiredEth = (0, import_viem4.formatEther)(args.requiredWei);
6279
+ const availableEth = (0, import_viem4.formatEther)(args.availableWei);
6280
+ super(
6281
+ `Insufficient ETH for gas: wallet ${args.address} has ${availableEth} ETH but this transaction needs ~${requiredEth} ETH.
6282
+ Compute credits do not pay on-chain gas \u2014 fund the wallet with ETH and retry.`
6283
+ );
6284
+ this.name = "InsufficientGasError";
6285
+ this.address = args.address;
6286
+ this.requiredWei = args.requiredWei;
6287
+ this.availableWei = args.availableWei;
6288
+ this.requiredEth = requiredEth;
6289
+ this.availableEth = availableEth;
6290
+ }
6291
+ };
6292
+ async function assertSufficientGas(args) {
6293
+ const availableWei = await args.publicClient.getBalance({ address: args.address });
6294
+ if (availableWei < args.gasEstimate.maxCostWei) {
6295
+ throw new InsufficientGasError({
6296
+ address: args.address,
6297
+ requiredWei: args.gasEstimate.maxCostWei,
6298
+ availableWei
6299
+ });
6300
+ }
6301
+ }
6302
+
6216
6303
  // src/client/common/utils/userapi.ts
6217
6304
  var import_axios2 = __toESM(require("axios"), 1);
6218
6305
 
6219
6306
  // src/client/common/utils/auth.ts
6220
- var import_viem4 = require("viem");
6221
- var APP_CONTROLLER_ABI = (0, import_viem4.parseAbi)([
6307
+ var import_viem5 = require("viem");
6308
+ var APP_CONTROLLER_ABI = (0, import_viem5.parseAbi)([
6222
6309
  "function calculateApiPermissionDigestHash(bytes4 permission, uint256 expiry) view returns (bytes32)"
6223
6310
  ]);
6224
6311
  async function calculatePermissionSignature(options) {
@@ -6245,6 +6332,7 @@ var import_axios = __toESM(require("axios"), 1);
6245
6332
  var MAX_RETRIES = 5;
6246
6333
  var INITIAL_BACKOFF_MS = 1e3;
6247
6334
  var MAX_BACKOFF_MS = 3e4;
6335
+ var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
6248
6336
  function sleep(ms) {
6249
6337
  return new Promise((resolve2) => setTimeout(resolve2, ms));
6250
6338
  }
@@ -6264,7 +6352,7 @@ async function requestWithRetry(config) {
6264
6352
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
6265
6353
  const res = await (0, import_axios.default)({ ...config, validateStatus: () => true });
6266
6354
  lastResponse = res;
6267
- if (res.status !== 429) {
6355
+ if (!RETRYABLE_STATUSES.has(res.status)) {
6268
6356
  return res;
6269
6357
  }
6270
6358
  if (attempt < MAX_RETRIES) {
@@ -6293,7 +6381,7 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
6293
6381
  var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
6294
6382
  var CanUpdateAppProfilePermission = "0x036fef61";
6295
6383
  function getDefaultClientId() {
6296
- const version = true ? "1.0.0-dev.7" : "0.0.0";
6384
+ const version = true ? "1.0.0-dev.8" : "0.0.0";
6297
6385
  return `ecloud-sdk/v${version}`;
6298
6386
  }
6299
6387
  var UserApiClient = class {
@@ -6631,8 +6719,36 @@ function transformAppRelease(raw) {
6631
6719
 
6632
6720
  // src/client/common/contract/watcher.ts
6633
6721
  var WATCH_POLL_INTERVAL_SECONDS = 5;
6722
+ var WATCH_HEARTBEAT_INTERVAL_SECONDS = 30;
6723
+ var WATCH_DEFAULT_TIMEOUT_SECONDS = 10 * 60;
6634
6724
  var APP_STATUS_RUNNING = "Running";
6635
6725
  var APP_STATUS_FAILED = "Failed";
6726
+ var WatchTimeoutError = class extends Error {
6727
+ constructor(args) {
6728
+ super(
6729
+ args.message ?? `Timed out after ${args.elapsedSeconds}s waiting for app ${args.appId} (last status: ${args.lastStatus ?? "unknown"})`
6730
+ );
6731
+ this.name = "WatchTimeoutError";
6732
+ this.appId = args.appId;
6733
+ this.elapsedSeconds = args.elapsedSeconds;
6734
+ this.lastStatus = args.lastStatus;
6735
+ this.timeoutSeconds = args.timeoutSeconds;
6736
+ }
6737
+ };
6738
+ function resolveWatchTimeoutSeconds(explicit) {
6739
+ if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0) {
6740
+ return Math.floor(explicit);
6741
+ }
6742
+ const raw = process.env.ECLOUD_WATCH_TIMEOUT_SECONDS;
6743
+ if (raw === void 0 || raw === "") {
6744
+ return WATCH_DEFAULT_TIMEOUT_SECONDS;
6745
+ }
6746
+ const parsed = Number(raw);
6747
+ if (!Number.isFinite(parsed) || parsed <= 0) {
6748
+ return WATCH_DEFAULT_TIMEOUT_SECONDS;
6749
+ }
6750
+ return Math.floor(parsed);
6751
+ }
6636
6752
  async function watchUntilRunning(options, logger) {
6637
6753
  const { walletClient, publicClient, environmentConfig, appId } = options;
6638
6754
  const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
@@ -6663,8 +6779,20 @@ async function watchUntilRunning(options, logger) {
6663
6779
  return false;
6664
6780
  };
6665
6781
  const startTime = Date.now();
6782
+ const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
6666
6783
  let lastLoggedStatus;
6784
+ let lastHeartbeatAt = startTime;
6667
6785
  while (true) {
6786
+ const elapsedMs = Date.now() - startTime;
6787
+ const elapsed = Math.round(elapsedMs / 1e3);
6788
+ if (elapsed >= timeoutSeconds) {
6789
+ throw new WatchTimeoutError({
6790
+ appId,
6791
+ elapsedSeconds: elapsed,
6792
+ lastStatus: lastLoggedStatus,
6793
+ timeoutSeconds
6794
+ });
6795
+ }
6668
6796
  try {
6669
6797
  const info = await userApiClient.getInfos([appId], 1);
6670
6798
  if (info.length === 0) {
@@ -6674,16 +6802,22 @@ async function watchUntilRunning(options, logger) {
6674
6802
  const appInfo = info[0];
6675
6803
  const currentStatus = appInfo.status;
6676
6804
  const currentIP = appInfo.ip || "";
6677
- const elapsed = Math.round((Date.now() - startTime) / 1e3);
6678
6805
  if (currentStatus !== lastLoggedStatus) {
6679
6806
  logger.info(`Status: ${currentStatus} (${elapsed}s)`);
6680
6807
  lastLoggedStatus = currentStatus;
6808
+ lastHeartbeatAt = Date.now();
6809
+ } else if (Date.now() - lastHeartbeatAt >= WATCH_HEARTBEAT_INTERVAL_SECONDS * 1e3) {
6810
+ logger.info(`Status: ${currentStatus} (${elapsed}s)`);
6811
+ lastHeartbeatAt = Date.now();
6681
6812
  }
6682
6813
  if (stopCondition(currentStatus, currentIP)) {
6683
6814
  return currentIP || void 0;
6684
6815
  }
6685
6816
  await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
6686
6817
  } catch (error) {
6818
+ if (error instanceof WatchTimeoutError) {
6819
+ throw error;
6820
+ }
6687
6821
  logger.warn(`Failed to fetch app info: ${error.message}`);
6688
6822
  await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
6689
6823
  }
@@ -6692,6 +6826,7 @@ async function watchUntilRunning(options, logger) {
6692
6826
  var APP_STATUS_STOPPED = "Stopped";
6693
6827
  async function watchUntilUpgradeComplete(options, logger) {
6694
6828
  const { walletClient, publicClient, environmentConfig, appId } = options;
6829
+ const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
6695
6830
  const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
6696
6831
  let initialStatus;
6697
6832
  let initialIP;
@@ -6729,7 +6864,20 @@ async function watchUntilUpgradeComplete(options, logger) {
6729
6864
  }
6730
6865
  return false;
6731
6866
  };
6867
+ const startTime = Date.now();
6868
+ const deadline = startTime + timeoutSeconds * 1e3;
6869
+ let lastLoggedStatus;
6870
+ let lastObservedStatus;
6732
6871
  while (true) {
6872
+ if (Date.now() >= deadline) {
6873
+ const elapsedSeconds = Math.round((Date.now() - startTime) / 1e3);
6874
+ throw new WatchTimeoutError({
6875
+ appId,
6876
+ lastStatus: lastObservedStatus,
6877
+ elapsedSeconds,
6878
+ timeoutSeconds
6879
+ });
6880
+ }
6733
6881
  try {
6734
6882
  const info = await userApiClient.getInfos([appId], 1);
6735
6883
  if (info.length === 0) {
@@ -6739,11 +6887,23 @@ async function watchUntilUpgradeComplete(options, logger) {
6739
6887
  const appInfo = info[0];
6740
6888
  const currentStatus = appInfo.status;
6741
6889
  const currentIP = appInfo.ip || "";
6890
+ lastObservedStatus = currentStatus;
6891
+ const elapsed = Math.round((Date.now() - startTime) / 1e3);
6892
+ if (currentStatus !== lastLoggedStatus) {
6893
+ logger.info(`Status: ${currentStatus} (${elapsed}s)`);
6894
+ lastLoggedStatus = currentStatus;
6895
+ }
6742
6896
  if (stopCondition(currentStatus, currentIP)) {
6743
6897
  return;
6744
6898
  }
6745
6899
  await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
6746
6900
  } catch (error) {
6901
+ if (error instanceof WatchTimeoutError) {
6902
+ throw error;
6903
+ }
6904
+ if (typeof error?.message === "string" && error.message.includes("Failed")) {
6905
+ throw error;
6906
+ }
6747
6907
  logger.warn(`Failed to fetch app info: ${error.message}`);
6748
6908
  await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
6749
6909
  }
@@ -6755,7 +6915,7 @@ function sleep2(ms) {
6755
6915
 
6756
6916
  // src/client/common/utils/validation.ts
6757
6917
  var import_fs = __toESM(require("fs"), 1);
6758
- var import_viem5 = require("viem");
6918
+ var import_viem6 = require("viem");
6759
6919
  function validateAppName(name) {
6760
6920
  if (!name) {
6761
6921
  throw new Error("App name cannot be empty");
@@ -6803,7 +6963,7 @@ function validateAppID(appID) {
6803
6963
  throw new Error("App ID is required");
6804
6964
  }
6805
6965
  const normalized = typeof appID === "string" ? addHexPrefix(appID) : appID;
6806
- if ((0, import_viem5.isAddress)(normalized)) {
6966
+ if ((0, import_viem6.isAddress)(normalized)) {
6807
6967
  return normalized;
6808
6968
  }
6809
6969
  throw new Error(`Invalid app ID: '${appID}' is not a valid address`);
@@ -7290,6 +7450,11 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
7290
7450
  executions: batch.executions,
7291
7451
  authorizationList
7292
7452
  });
7453
+ await assertSufficientGas({
7454
+ publicClient: batch.publicClient,
7455
+ address: batch.walletClient.account.address,
7456
+ gasEstimate
7457
+ });
7293
7458
  const data = {
7294
7459
  appId: batch.appId,
7295
7460
  salt: batch.salt,
@@ -7548,6 +7713,11 @@ async function prepareDeploy(options, logger = defaultLogger) {
7548
7713
  executions: batch.executions,
7549
7714
  authorizationList
7550
7715
  });
7716
+ await assertSufficientGas({
7717
+ publicClient: batch.publicClient,
7718
+ address: batch.walletClient.account.address,
7719
+ gasEstimate
7720
+ });
7551
7721
  const data = {
7552
7722
  appId: batch.appId,
7553
7723
  salt: batch.salt,
@@ -7584,7 +7754,7 @@ async function executeDeploy(options) {
7584
7754
  }
7585
7755
  );
7586
7756
  }
7587
- async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
7757
+ async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
7588
7758
  return withSDKTelemetry(
7589
7759
  {
7590
7760
  functionName: "watchDeployment",
@@ -7600,7 +7770,8 @@ async function watchDeployment(appId, walletClient, publicClient, environmentCon
7600
7770
  walletClient,
7601
7771
  publicClient,
7602
7772
  environmentConfig,
7603
- appId
7773
+ appId,
7774
+ timeoutSeconds: opts?.timeoutSeconds
7604
7775
  },
7605
7776
  logger
7606
7777
  );
@@ -7696,6 +7867,11 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
7696
7867
  executions: batch.executions,
7697
7868
  authorizationList
7698
7869
  });
7870
+ await assertSufficientGas({
7871
+ publicClient: batch.publicClient,
7872
+ address: batch.walletClient.account.address,
7873
+ gasEstimate
7874
+ });
7699
7875
  const data = {
7700
7876
  appId: batch.appId,
7701
7877
  executions: batch.executions,
@@ -7885,6 +8061,11 @@ async function prepareUpgrade(options, logger = defaultLogger) {
7885
8061
  executions: batch.executions,
7886
8062
  authorizationList
7887
8063
  });
8064
+ await assertSufficientGas({
8065
+ publicClient: batch.publicClient,
8066
+ address: batch.walletClient.account.address,
8067
+ gasEstimate
8068
+ });
7888
8069
  const data = {
7889
8070
  appId: batch.appId,
7890
8071
  executions: batch.executions,
@@ -7919,7 +8100,7 @@ async function executeUpgrade(options) {
7919
8100
  }
7920
8101
  );
7921
8102
  }
7922
- async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
8103
+ async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
7923
8104
  return withSDKTelemetry(
7924
8105
  {
7925
8106
  functionName: "watchUpgrade",
@@ -7935,7 +8116,8 @@ async function watchUpgrade(appId, walletClient, publicClient, environmentConfig
7935
8116
  walletClient,
7936
8117
  publicClient,
7937
8118
  environmentConfig,
7938
- appId
8119
+ appId,
8120
+ timeoutSeconds: opts?.timeoutSeconds
7939
8121
  },
7940
8122
  logger
7941
8123
  );
@@ -8593,27 +8775,27 @@ async function logs(options, walletClient, publicClient, environmentConfig, logg
8593
8775
  }
8594
8776
 
8595
8777
  // src/client/modules/compute/app/index.ts
8596
- var CONTROLLER_ABI = (0, import_viem6.parseAbi)([
8778
+ var CONTROLLER_ABI = (0, import_viem7.parseAbi)([
8597
8779
  "function startApp(address appId)",
8598
8780
  "function stopApp(address appId)",
8599
8781
  "function terminateApp(address appId)"
8600
8782
  ]);
8601
8783
  function encodeStartAppData(appId) {
8602
- return (0, import_viem6.encodeFunctionData)({
8784
+ return (0, import_viem7.encodeFunctionData)({
8603
8785
  abi: CONTROLLER_ABI,
8604
8786
  functionName: "startApp",
8605
8787
  args: [appId]
8606
8788
  });
8607
8789
  }
8608
8790
  function encodeStopAppData(appId) {
8609
- return (0, import_viem6.encodeFunctionData)({
8791
+ return (0, import_viem7.encodeFunctionData)({
8610
8792
  abi: CONTROLLER_ABI,
8611
8793
  functionName: "stopApp",
8612
8794
  args: [appId]
8613
8795
  });
8614
8796
  }
8615
8797
  function encodeTerminateAppData(appId) {
8616
- return (0, import_viem6.encodeFunctionData)({
8798
+ return (0, import_viem7.encodeFunctionData)({
8617
8799
  abi: CONTROLLER_ABI,
8618
8800
  functionName: "terminateApp",
8619
8801
  args: [appId]
@@ -8627,7 +8809,7 @@ function createAppModule(ctx) {
8627
8809
  }
8628
8810
  const account = walletClient.account;
8629
8811
  const environment = getEnvironmentConfig(ctx.environment);
8630
- const logger = getLogger(ctx.verbose);
8812
+ const logger = ctx.logger ?? getLogger(ctx.verbose);
8631
8813
  return {
8632
8814
  async create(opts) {
8633
8815
  return createApp(opts, logger);
@@ -8739,14 +8921,15 @@ function createAppModule(ctx) {
8739
8921
  imageRef: result.imageRef
8740
8922
  };
8741
8923
  },
8742
- async watchDeployment(appId) {
8924
+ async watchDeployment(appId, opts) {
8743
8925
  return watchDeployment(
8744
8926
  appId,
8745
8927
  walletClient,
8746
8928
  publicClient,
8747
8929
  environment,
8748
8930
  logger,
8749
- skipTelemetry
8931
+ skipTelemetry,
8932
+ opts
8750
8933
  );
8751
8934
  },
8752
8935
  // Granular upgrade control
@@ -8804,8 +8987,16 @@ function createAppModule(ctx) {
8804
8987
  imageRef: result.imageRef
8805
8988
  };
8806
8989
  },
8807
- async watchUpgrade(appId) {
8808
- return watchUpgrade(appId, walletClient, publicClient, environment, logger, skipTelemetry);
8990
+ async watchUpgrade(appId, opts) {
8991
+ return watchUpgrade(
8992
+ appId,
8993
+ walletClient,
8994
+ publicClient,
8995
+ environment,
8996
+ logger,
8997
+ skipTelemetry,
8998
+ opts
8999
+ );
8809
9000
  },
8810
9001
  // Profile management
8811
9002
  async setProfile(appId, profile) {
@@ -8856,7 +9047,7 @@ function createAppModule(ctx) {
8856
9047
  },
8857
9048
  async () => {
8858
9049
  const pendingMessage = `Starting app ${appId}...`;
8859
- const data = (0, import_viem6.encodeFunctionData)({
9050
+ const data = (0, import_viem7.encodeFunctionData)({
8860
9051
  abi: CONTROLLER_ABI,
8861
9052
  functionName: "startApp",
8862
9053
  args: [appId]
@@ -8888,7 +9079,7 @@ function createAppModule(ctx) {
8888
9079
  },
8889
9080
  async () => {
8890
9081
  const pendingMessage = `Stopping app ${appId}...`;
8891
- const data = (0, import_viem6.encodeFunctionData)({
9082
+ const data = (0, import_viem7.encodeFunctionData)({
8892
9083
  abi: CONTROLLER_ABI,
8893
9084
  functionName: "stopApp",
8894
9085
  args: [appId]
@@ -8920,7 +9111,7 @@ function createAppModule(ctx) {
8920
9111
  },
8921
9112
  async () => {
8922
9113
  const pendingMessage = `Terminating app ${appId}...`;
8923
- const data = (0, import_viem6.encodeFunctionData)({
9114
+ const data = (0, import_viem7.encodeFunctionData)({
8924
9115
  abi: CONTROLLER_ABI,
8925
9116
  functionName: "terminateApp",
8926
9117
  args: [appId]