@layr-labs/ecloud-sdk 1.0.0-devep8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +2 -2
- package/dist/billing.cjs +70 -13
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.d.cts +2 -1
- package/dist/billing.d.ts +2 -1
- package/dist/billing.js +70 -13
- package/dist/billing.js.map +1 -1
- package/dist/browser.cjs +1696 -140
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +5 -4
- package/dist/browser.d.ts +5 -4
- package/dist/browser.js +1695 -140
- 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 +1881 -812
- package/dist/compute.cjs.map +1 -1
- package/dist/compute.d.cts +3 -2
- package/dist/compute.d.ts +3 -2
- package/dist/compute.js +1869 -800
- package/dist/compute.js.map +1 -1
- package/dist/{helpers-NGE0oIa9.d.ts → helpers-CkcuSkNM.d.ts} +17 -191
- package/dist/{helpers-0Tz3MuQK.d.cts → helpers-fmu7es2L.d.cts} +17 -191
- package/dist/{index-DFqQ7v8_.d.cts → index-BVnxNfqb.d.cts} +65 -3
- package/dist/{index-DFqQ7v8_.d.ts → index-BVnxNfqb.d.ts} +65 -3
- package/dist/index.cjs +2013 -803
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +72 -240
- package/dist/index.d.ts +72 -240
- package/dist/index.js +1992 -788
- 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 +4 -5
- package/dist/compute-DfFZvbPD.d.cts +0 -194
- package/dist/compute-GcTgGp_x.d.ts +0 -194
- package/tools/ecloud-drain-watcher-linux-amd64 +0 -0
package/dist/compute.js
CHANGED
|
@@ -148,7 +148,6 @@ var ENV_SOURCE_SCRIPT_NAME = "compute-source-env.sh";
|
|
|
148
148
|
var KMS_CLIENT_BINARY_NAME = "kms-client";
|
|
149
149
|
var KMS_SIGNING_KEY_NAME = "kms-signing-public-key.pem";
|
|
150
150
|
var TLS_KEYGEN_BINARY_NAME = "tls-keygen";
|
|
151
|
-
var DRAIN_WATCHER_BINARY_NAME = "ecloud-drain-watcher";
|
|
152
151
|
var CADDYFILE_NAME = "Caddyfile";
|
|
153
152
|
var LAYERED_BUILD_DIR_PREFIX = "ecloud-layered-build";
|
|
154
153
|
|
|
@@ -435,12 +434,14 @@ USER root
|
|
|
435
434
|
{{/if}}
|
|
436
435
|
|
|
437
436
|
# Copy core TEE components
|
|
437
|
+
# CA bundle for kms-client / tls-keygen to validate HTTPS calls to
|
|
438
|
+
# eigencloud.xyz endpoints. Bundled at a non-standard path and consumed
|
|
439
|
+
# only via SSL_CERT_FILE in compute-source-env.sh, so the user's
|
|
440
|
+
# /etc/ssl/ is never touched.
|
|
441
|
+
COPY --from=alpine:3.20.10 /etc/ssl/certs/ca-certificates.crt /usr/local/share/eigenx-ca-certs.crt
|
|
438
442
|
COPY compute-source-env.sh /usr/local/bin/
|
|
439
443
|
COPY kms-client /usr/local/bin/
|
|
440
444
|
COPY kms-signing-public-key.pem /usr/local/bin/
|
|
441
|
-
{{#if includeDrainWatcher}}
|
|
442
|
-
COPY ecloud-drain-watcher /usr/local/bin/
|
|
443
|
-
{{/if}}
|
|
444
445
|
|
|
445
446
|
{{#if includeTLS}}
|
|
446
447
|
# Copy Caddy from official image
|
|
@@ -454,8 +455,7 @@ COPY Caddyfile /etc/caddy/
|
|
|
454
455
|
{{#if originalUser}}
|
|
455
456
|
# Make binaries executable (755 for executables, 644 for keys)
|
|
456
457
|
RUN chmod 755 /usr/local/bin/compute-source-env.sh \\
|
|
457
|
-
&& chmod 755 /usr/local/bin/kms-client{{#if
|
|
458
|
-
&& chmod 755 /usr/local/bin/ecloud-drain-watcher{{/if}}{{#if includeTLS}} \\
|
|
458
|
+
&& chmod 755 /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
459
459
|
&& chmod 755 /usr/local/bin/tls-keygen \\
|
|
460
460
|
&& chmod 755 /usr/local/bin/caddy{{/if}} \\
|
|
461
461
|
&& chmod 644 /usr/local/bin/kms-signing-public-key.pem
|
|
@@ -465,8 +465,7 @@ ENV __ECLOUD_ORIGINAL_USER={{originalUser}}
|
|
|
465
465
|
{{else}}
|
|
466
466
|
# Make binaries executable (preserve existing permissions, just add execute)
|
|
467
467
|
RUN chmod +x /usr/local/bin/compute-source-env.sh \\
|
|
468
|
-
&& chmod +x /usr/local/bin/kms-client{{#if
|
|
469
|
-
&& chmod +x /usr/local/bin/ecloud-drain-watcher{{/if}}{{#if includeTLS}} \\
|
|
468
|
+
&& chmod +x /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
470
469
|
&& chmod +x /usr/local/bin/tls-keygen{{/if}}
|
|
471
470
|
{{/if}}
|
|
472
471
|
|
|
@@ -479,36 +478,8 @@ LABEL tee.launch_policy.log_redirect={{logRedirect}}
|
|
|
479
478
|
LABEL tee.launch_policy.monitoring_memory_allow={{resourceUsageAllow}}
|
|
480
479
|
{{/if}}
|
|
481
480
|
|
|
482
|
-
# Allow-list the envvars the ecloud-platform sets via GCE \`tee-env-*\`
|
|
483
|
-
# metadata. Without this label, Confidential Space's launcher rejects
|
|
484
|
-
# any \`tee-env-*\` override at container-start with
|
|
485
|
-
# "env var {...} is not allowed to be overridden on this image" and
|
|
486
|
-
# exits with code 1 \u2014 which terminates the VM before the entrypoint
|
|
487
|
-
# ever runs. User-supplied env vars flow through KMS (not tee-env-*)
|
|
488
|
-
# and don't need to be listed here.
|
|
489
|
-
#
|
|
490
|
-
# Entries:
|
|
491
|
-
# - ECLOUD_PD_EXPECTED set on PD-backed apps so the entrypoint
|
|
492
|
-
# (compute-source-env.sh) knows to wait for
|
|
493
|
-
# the persistent disk before exec'ing the
|
|
494
|
-
# user workload.
|
|
495
|
-
# - ECLOUD_PLATFORM_HOST the platform-routed hostname
|
|
496
|
-
# (<addr>.<env>.eigencloud.xyz) so the
|
|
497
|
-
# entrypoint's setup_tls can issue an ACME
|
|
498
|
-
# cert for it. Injected by the CLI into
|
|
499
|
-
# publicEnv at deploy/upgrade time and
|
|
500
|
-
# propagated by ecloud-platform's
|
|
501
|
-
# compute.go as a tee-env-* metadata key.
|
|
502
|
-
#
|
|
503
|
-
# The CS launcher parses this label as a comma-separated list
|
|
504
|
-
# (go-tpm-tools/launcher/spec/launch_policy.go:185 \u2014 strings.Split
|
|
505
|
-
# on ","). Quotes are not required; keep the value bare for
|
|
506
|
-
# consistency with compute-tee's and eigenx-kms's existing labels.
|
|
507
|
-
LABEL tee.launch_policy.allow_env_override=ECLOUD_PD_EXPECTED,ECLOUD_PLATFORM_HOST
|
|
508
|
-
|
|
509
481
|
LABEL eigenx_cli_version={{ecloudCLIVersion}}
|
|
510
482
|
LABEL eigenx_vm_image=eigen
|
|
511
|
-
LABEL eigenx_container_contract=v1
|
|
512
483
|
|
|
513
484
|
{{#if includeTLS}}
|
|
514
485
|
# Expose both HTTP and HTTPS ports for Caddy
|
|
@@ -530,54 +501,11 @@ import Handlebars2 from "handlebars";
|
|
|
530
501
|
|
|
531
502
|
// src/client/common/templates/compute-source-env.sh.tmpl
|
|
532
503
|
var compute_source_env_sh_default = `#!/bin/sh
|
|
533
|
-
# EigenCompute container entrypoint script
|
|
534
|
-
# This script handles KMS secret fetching, TLS setup, and privilege dropping
|
|
535
|
-
# before executing the user's application.
|
|
536
|
-
#
|
|
537
|
-
# Handlebars template variables (replaced at build time by the CLI):
|
|
538
|
-
# kmsServerURL - URL of the KMS server
|
|
539
|
-
# userAPIURL - URL of the user API (ecloud-platform)
|
|
540
|
-
# The KMS signing public key is copied into the image as
|
|
541
|
-
# /usr/local/bin/kms-signing-public-key.pem at layer-build time by the CLI.
|
|
542
|
-
#
|
|
543
|
-
# ecloud-platform divergence from compute-tee:
|
|
544
|
-
# This script emits ECLOUD_READY / ECLOUD_FAIL / ECLOUD_AWAITING_USERDATA /
|
|
545
|
-
# ECLOUD_DETACHED markers to stdout at key lifecycle points. The GCP
|
|
546
|
-
# provisioner's serial-console watcher in ecloud-platform
|
|
547
|
-
# (pkg/services/infraService/providers/gcp/compute.go) parses those
|
|
548
|
-
# markers to gate "VM ready" and to coordinate the prewarm-detach
|
|
549
|
-
# upgrade flow. Without the markers, the platform's waitForStartupReady
|
|
550
|
-
# times out at ~10 minutes per deploy, rollback fires, and the VM is
|
|
551
|
-
# deleted \u2014 seen in dev on 2026-05-04 with an older copy of this
|
|
552
|
-
# template that lacked the markers.
|
|
553
|
-
#
|
|
554
|
-
# Prewarm-detach contract:
|
|
555
|
-
# - If ECLOUD_PD_EXPECTED=1 and /mnt/disks/userdata is not present at boot,
|
|
556
|
-
# emit ECLOUD_AWAITING_USERDATA and wait until the disk is attached.
|
|
557
|
-
# - On SIGTERM (drain-requested), forward to child, wait for exit, sync
|
|
558
|
-
# + unmount /mnt/disks/userdata, emit ECLOUD_DETACHED, exit.
|
|
559
|
-
# - ECLOUD_READY is emitted once runtime is bootstrapped (same as before).
|
|
560
|
-
# - ECLOUD_FAIL is emitted on any unrecoverable setup error.
|
|
561
|
-
# Keep the markers on any line that resolves a lifecycle outcome.
|
|
562
|
-
#
|
|
563
|
-
# This file is kept in lockstep with
|
|
564
|
-
# ecloud-platform/pkg/services/buildService/assets/compute-source-env.sh.tmpl
|
|
565
|
-
# \u2014 if you change one, change the other. Differences vs the platform copy
|
|
566
|
-
# are intentionally minimal:
|
|
567
|
-
# - Handlebars placeholders use the CLI's naming (kmsServerURL,
|
|
568
|
-
# userAPIURL) rather than the platform's (KMS_SERVER_URL,
|
|
569
|
-
# USER_API_URL). (See top of file for real placeholder syntax \u2014
|
|
570
|
-
# not repeated here so Handlebars doesn't expand it in this comment.)
|
|
571
|
-
# - KMS signing key is read from a file the CLI copies into the image,
|
|
572
|
-
# not heredoc-embedded in the script, because the CLI's image
|
|
573
|
-
# layering writes it as a separate file (kms-signing-public-key.pem).
|
|
574
|
-
# - TLS binary is \`tls-keygen\` (CLI-bundled) not \`tls-client\`.
|
|
575
|
-
|
|
576
504
|
echo "compute-source-env.sh: Running setup script..."
|
|
577
505
|
|
|
578
506
|
# Fetch and source environment variables from KMS
|
|
579
507
|
echo "Fetching secrets from KMS..."
|
|
580
|
-
if /usr/local/bin/kms-client \\
|
|
508
|
+
if SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt /usr/local/bin/kms-client \\
|
|
581
509
|
--kms-server-url "{{kmsServerURL}}" \\
|
|
582
510
|
--kms-signing-key-file /usr/local/bin/kms-signing-public-key.pem \\
|
|
583
511
|
--userapi-url "{{userAPIURL}}" \\
|
|
@@ -588,187 +516,93 @@ if /usr/local/bin/kms-client \\
|
|
|
588
516
|
else
|
|
589
517
|
echo "compute-source-env.sh: ERROR - Failed to fetch environment variables from KMS"
|
|
590
518
|
echo "compute-source-env.sh: Exiting - cannot start user workload without KMS secrets"
|
|
591
|
-
echo "ECLOUD_FAIL kms_bootstrap"
|
|
592
519
|
exit 1
|
|
593
520
|
fi
|
|
594
521
|
|
|
595
|
-
#
|
|
596
|
-
# produced fullchain/privkey into $1's output directory ($2). Returns
|
|
597
|
-
# 0 on success, non-zero on any failure (caller decides whether that's
|
|
598
|
-
# fatal). tls-keygen writes to /run/tls/{fullchain,privkey}.pem by
|
|
599
|
-
# default; we move those to a per-host subdirectory so the two-site
|
|
600
|
-
# Caddyfile can select the right cert by path.
|
|
601
|
-
issue_cert_for() {
|
|
602
|
-
local host="$1"
|
|
603
|
-
local cert_dir="$2"
|
|
604
|
-
local mnemonic="$3"
|
|
605
|
-
local challenge="$4"
|
|
606
|
-
local staging_flag="$5"
|
|
607
|
-
|
|
608
|
-
echo "compute-source-env.sh: Obtaining TLS certificate for $host (challenge=$challenge)..."
|
|
609
|
-
# Remove any stale default outputs from a prior tls-keygen run
|
|
610
|
-
rm -f /run/tls/fullchain.pem /run/tls/privkey.pem
|
|
611
|
-
if ! MNEMONIC="$mnemonic" DOMAIN="$host" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
|
|
612
|
-
-challenge "$challenge" \\
|
|
613
|
-
$staging_flag; then
|
|
614
|
-
return 1
|
|
615
|
-
fi
|
|
616
|
-
mkdir -p "$cert_dir"
|
|
617
|
-
mv /run/tls/fullchain.pem "$cert_dir/fullchain.pem"
|
|
618
|
-
mv /run/tls/privkey.pem "$cert_dir/privkey.pem"
|
|
619
|
-
echo "compute-source-env.sh: Cert for $host written to $cert_dir"
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
# Setup TLS: issues certs for
|
|
623
|
-
# - ECLOUD_PLATFORM_HOST (platform-routed <addr>.<env>.eigencloud.xyz),
|
|
624
|
-
# when the CLI/platform has set it
|
|
625
|
-
# - DOMAIN (user-supplied custom domain), when set and non-localhost
|
|
626
|
-
#
|
|
627
|
-
# No client-side DNS precheck. Earlier versions tried to gate ACME on
|
|
628
|
-
# "does this hostname resolve to my external IP" but that's wrong for
|
|
629
|
-
# the platform-routing model (DNS points at the shared nginx NLB, not
|
|
630
|
-
# the VM) and was preventing cert issuance on the production path.
|
|
631
|
-
# tls-client (eigencompute-containers/tls-client) does its own DNS
|
|
632
|
-
# poll before calling ACME and surfaces a clear error when challenges
|
|
633
|
-
# can't reach the VM, which is the right place for that check \u2014
|
|
634
|
-
# attempting it here from inside the VM cannot tell platform-routed
|
|
635
|
-
# from compute-tee-routed apps.
|
|
522
|
+
# Setup TLS if tls-keygen is present (which means TLS was configured at build time)
|
|
636
523
|
setup_tls() {
|
|
637
524
|
# If tls-keygen isn't present, TLS wasn't configured during build
|
|
638
525
|
if [ ! -x /usr/local/bin/tls-keygen ]; then
|
|
639
526
|
echo "compute-source-env.sh: TLS not configured (no tls-keygen binary)"
|
|
640
527
|
return 0
|
|
641
528
|
fi
|
|
642
|
-
|
|
643
|
-
local
|
|
644
|
-
local user_domain="\${DOMAIN:-}"
|
|
529
|
+
|
|
530
|
+
local domain="\${DOMAIN:-}"
|
|
645
531
|
local mnemonic="\${MNEMONIC:-}"
|
|
646
|
-
|
|
647
|
-
#
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
# If the user set DOMAIN to the same value as the platform
|
|
654
|
-
# hostname, collapse them. Without this we'd burn a second ACME
|
|
655
|
-
# issuance for the exact same name (each VM boot counts against
|
|
656
|
-
# Let's Encrypt's 5-certs-per-domain-per-week limit), and Caddy
|
|
657
|
-
# would then refuse to start because two site blocks bound to
|
|
658
|
-
# the same address is a config error. Also unset DOMAIN so the
|
|
659
|
-
# DOMAIN site block in the Caddyfile falls back to its
|
|
660
|
-
# "localhost.user.invalid" placeholder and stays dormant.
|
|
661
|
-
if [ -n "$platform_host" ] && [ "$user_domain" = "$platform_host" ]; then
|
|
662
|
-
echo "compute-source-env.sh: DOMAIN matches ECLOUD_PLATFORM_HOST; skipping duplicate cert"
|
|
663
|
-
user_domain=""
|
|
664
|
-
unset DOMAIN
|
|
665
|
-
fi
|
|
666
|
-
|
|
667
|
-
if [ -z "$platform_host" ] && [ -z "$user_domain" ]; then
|
|
668
|
-
echo "compute-source-env.sh: TLS skipped (neither ECLOUD_PLATFORM_HOST nor DOMAIN set)"
|
|
669
|
-
return 0
|
|
532
|
+
|
|
533
|
+
# Since tls-keygen is present, TLS is expected - validate requirements
|
|
534
|
+
if [ -z "$domain" ] || [ "$domain" = "localhost" ]; then
|
|
535
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but DOMAIN not configured or is localhost"
|
|
536
|
+
echo "compute-source-env.sh: Set DOMAIN environment variable to a valid domain"
|
|
537
|
+
exit 1
|
|
670
538
|
fi
|
|
671
|
-
|
|
539
|
+
|
|
672
540
|
if [ -z "$mnemonic" ]; then
|
|
673
|
-
echo "compute-source-env.sh: ERROR - TLS
|
|
674
|
-
echo "
|
|
541
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but MNEMONIC not available"
|
|
542
|
+
echo "compute-source-env.sh: Cannot obtain TLS certificate without mnemonic"
|
|
675
543
|
exit 1
|
|
676
544
|
fi
|
|
677
|
-
|
|
545
|
+
|
|
678
546
|
if [ ! -x /usr/local/bin/caddy ]; then
|
|
679
|
-
echo "compute-source-env.sh: ERROR - TLS
|
|
680
|
-
echo "ECLOUD_FAIL tls_caddy_missing"
|
|
547
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but Caddy not found"
|
|
681
548
|
exit 1
|
|
682
549
|
fi
|
|
683
|
-
|
|
550
|
+
|
|
551
|
+
echo "compute-source-env.sh: Setting up TLS for domain: $domain"
|
|
552
|
+
|
|
553
|
+
# Obtain TLS certificate using ACME
|
|
554
|
+
# Default to http-01, but allow override via ACME_CHALLENGE env var
|
|
684
555
|
local challenge="\${ACME_CHALLENGE:-http-01}"
|
|
556
|
+
|
|
557
|
+
# Check if we should use staging (for testing)
|
|
685
558
|
local staging_flag=""
|
|
686
559
|
if [ "\${ACME_STAGING:-false}" = "true" ]; then
|
|
687
560
|
staging_flag="-staging"
|
|
688
|
-
echo "compute-source-env.sh: Using Let's Encrypt STAGING environment"
|
|
689
|
-
fi
|
|
690
|
-
|
|
691
|
-
local certs_issued=0
|
|
692
|
-
|
|
693
|
-
if [ -n "$platform_host" ]; then
|
|
694
|
-
if issue_cert_for "$platform_host" "/run/tls/platform" "$mnemonic" "$challenge" "$staging_flag"; then
|
|
695
|
-
certs_issued=$((certs_issued + 1))
|
|
696
|
-
else
|
|
697
|
-
echo "compute-source-env.sh: ERROR - failed to issue cert for platform host $platform_host"
|
|
698
|
-
echo "ECLOUD_FAIL tls_setup"
|
|
699
|
-
exit 1
|
|
700
|
-
fi
|
|
701
|
-
fi
|
|
702
|
-
|
|
703
|
-
if [ -n "$user_domain" ]; then
|
|
704
|
-
if issue_cert_for "$user_domain" "/run/tls/domain" "$mnemonic" "$challenge" "$staging_flag"; then
|
|
705
|
-
certs_issued=$((certs_issued + 1))
|
|
706
|
-
else
|
|
707
|
-
echo "compute-source-env.sh: ERROR - failed to issue cert for user domain $user_domain"
|
|
708
|
-
echo "ECLOUD_FAIL tls_setup"
|
|
709
|
-
exit 1
|
|
710
|
-
fi
|
|
561
|
+
echo "compute-source-env.sh: Using Let's Encrypt STAGING environment (certificates won't be trusted)"
|
|
711
562
|
fi
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
563
|
+
|
|
564
|
+
echo "compute-source-env.sh: Obtaining TLS certificate using $challenge challenge..."
|
|
565
|
+
# Pass the API URL for certificate persistence
|
|
566
|
+
if ! SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt \\
|
|
567
|
+
MNEMONIC="$mnemonic" DOMAIN="$domain" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
|
|
568
|
+
-challenge "$challenge" \\
|
|
569
|
+
$staging_flag; then
|
|
570
|
+
echo "compute-source-env.sh: ERROR - Failed to obtain TLS certificate"
|
|
571
|
+
echo "compute-source-env.sh: Certificate issuance failed for $domain"
|
|
572
|
+
exit 1
|
|
716
573
|
fi
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
#
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
# receive real traffic (its hostname falls back to
|
|
726
|
-
# localhost.{platform,user}.invalid, which Caddy routes by SNI and
|
|
727
|
-
# never matches public traffic), so the symlink is never actually
|
|
728
|
-
# presented. Skipped when a user-supplied Caddyfile is in use,
|
|
729
|
-
# since we don't know what cert paths it references.
|
|
730
|
-
if [ -d /run/tls/platform ] && [ ! -e /run/tls/domain/fullchain.pem ]; then
|
|
731
|
-
mkdir -p /run/tls/domain
|
|
732
|
-
ln -sf /run/tls/platform/fullchain.pem /run/tls/domain/fullchain.pem
|
|
733
|
-
ln -sf /run/tls/platform/privkey.pem /run/tls/domain/privkey.pem
|
|
734
|
-
elif [ -d /run/tls/domain ] && [ ! -e /run/tls/platform/fullchain.pem ]; then
|
|
735
|
-
mkdir -p /run/tls/platform
|
|
736
|
-
ln -sf /run/tls/domain/fullchain.pem /run/tls/platform/fullchain.pem
|
|
737
|
-
ln -sf /run/tls/domain/privkey.pem /run/tls/platform/privkey.pem
|
|
574
|
+
|
|
575
|
+
echo "compute-source-env.sh: TLS certificate obtained successfully"
|
|
576
|
+
|
|
577
|
+
# Validate Caddyfile before starting
|
|
578
|
+
if ! /usr/local/bin/caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile 2>/dev/null; then
|
|
579
|
+
echo "compute-source-env.sh: ERROR - Invalid Caddyfile"
|
|
580
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
581
|
+
exit 1
|
|
738
582
|
fi
|
|
739
|
-
|
|
740
|
-
#
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
#
|
|
744
|
-
if [
|
|
745
|
-
if ! /usr/local/bin/caddy
|
|
746
|
-
echo "compute-source-env.sh: ERROR -
|
|
747
|
-
echo "
|
|
583
|
+
|
|
584
|
+
# Start Caddy in background
|
|
585
|
+
echo "compute-source-env.sh: Starting Caddy reverse proxy..."
|
|
586
|
+
|
|
587
|
+
# Check if Caddy logs should be enabled
|
|
588
|
+
if [ "\${ENABLE_CADDY_LOGS:-false}" = "true" ]; then
|
|
589
|
+
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1; then
|
|
590
|
+
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
591
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
748
592
|
exit 1
|
|
749
593
|
fi
|
|
750
|
-
|
|
751
|
-
echo "compute-source-env.sh: Starting Caddy reverse proxy..."
|
|
752
|
-
if [ "\${ENABLE_CADDY_LOGS:-false}" = "true" ]; then
|
|
753
|
-
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1; then
|
|
754
|
-
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
755
|
-
echo "ECLOUD_FAIL tls_caddy_start"
|
|
756
|
-
exit 1
|
|
757
|
-
fi
|
|
758
|
-
else
|
|
759
|
-
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then
|
|
760
|
-
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
761
|
-
echo "ECLOUD_FAIL tls_caddy_start"
|
|
762
|
-
exit 1
|
|
763
|
-
fi
|
|
764
|
-
fi
|
|
765
|
-
|
|
766
|
-
sleep 2
|
|
767
|
-
echo "compute-source-env.sh: Caddy started successfully"
|
|
768
594
|
else
|
|
769
|
-
|
|
595
|
+
# Redirect Caddy output to /dev/null to silence logs
|
|
596
|
+
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then
|
|
597
|
+
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
598
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
599
|
+
exit 1
|
|
600
|
+
fi
|
|
770
601
|
fi
|
|
771
|
-
|
|
602
|
+
|
|
603
|
+
# Give Caddy a moment to fully initialize
|
|
604
|
+
sleep 2
|
|
605
|
+
echo "compute-source-env.sh: Caddy started successfully"
|
|
772
606
|
return 0
|
|
773
607
|
}
|
|
774
608
|
|
|
@@ -779,309 +613,15 @@ setup_tls
|
|
|
779
613
|
export KMS_SERVER_URL="{{kmsServerURL}}"
|
|
780
614
|
export KMS_PUBLIC_KEY="$(cat /usr/local/bin/kms-signing-public-key.pem)"
|
|
781
615
|
|
|
782
|
-
# \u2500\u2500 Prewarm-detach: wait for PD if expected \u2500\u2500
|
|
783
|
-
# Orchestrator sets ECLOUD_PD_EXPECTED=1 on apps using StorageBackend=pd.
|
|
784
|
-
# When the prewarm path is used, the new VM boots WITHOUT the disk; we
|
|
785
|
-
# signal awaiting-userdata and poll until the disk is attached.
|
|
786
|
-
USERDATA_MOUNT="/mnt/disks/userdata"
|
|
787
|
-
USERDATA_DEV="/dev/disk/by-id/google-persistent_storage_1"
|
|
788
|
-
|
|
789
|
-
# userdata_mount_backing_dev resolves the kernel device that currently
|
|
790
|
-
# backs $USERDATA_MOUNT (or empty string if not mounted). The output is
|
|
791
|
-
# canonicalized via readlink so we can compare against $USERDATA_DEV
|
|
792
|
-
# without caring whether the mount table records the symlinked
|
|
793
|
-
# /dev/disk/by-id/... path or the underlying /dev/sdb-style path.
|
|
794
|
-
#
|
|
795
|
-
# Tries findmnt first (clean structured output), falls back to parsing
|
|
796
|
-
# /proc/self/mountinfo so we don't add a hard dependency on util-linux
|
|
797
|
-
# being present in the image.
|
|
798
|
-
userdata_mount_backing_dev() {
|
|
799
|
-
if command -v findmnt >/dev/null 2>&1; then
|
|
800
|
-
local src
|
|
801
|
-
src=$(findmnt -n -o SOURCE -- "$USERDATA_MOUNT" 2>/dev/null) || return 0
|
|
802
|
-
[ -n "$src" ] || return 0
|
|
803
|
-
readlink -f "$src" 2>/dev/null || echo "$src"
|
|
804
|
-
return 0
|
|
805
|
-
fi
|
|
806
|
-
# /proc/self/mountinfo line shape (kernel docs): mount-id parent-id
|
|
807
|
-
# major:minor root mount-point ... So column 5 is the mount point and
|
|
808
|
-
# the device path lives in the optional fields after the "-" separator.
|
|
809
|
-
# We just need the major:minor \u2192 device mapping; awk + a /sys lookup
|
|
810
|
-
# is cleaner than parsing the mountinfo's optional-field section.
|
|
811
|
-
local maj_min dev_basename
|
|
812
|
-
maj_min=$(awk -v mp="$USERDATA_MOUNT" '$5 == mp { print $3 }' /proc/self/mountinfo 2>/dev/null | head -1)
|
|
813
|
-
[ -n "$maj_min" ] || return 0
|
|
814
|
-
dev_basename=$(readlink "/sys/dev/block/\${maj_min}" 2>/dev/null | awk -F/ '{print $NF}')
|
|
815
|
-
[ -n "$dev_basename" ] || return 0
|
|
816
|
-
readlink -f "/dev/\${dev_basename}" 2>/dev/null || echo "/dev/\${dev_basename}"
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
# expected_userdata_dev resolves $USERDATA_DEV through any symlinks so
|
|
820
|
-
# string-compare against userdata_mount_backing_dev is meaningful even
|
|
821
|
-
# when the kernel hands us a /dev/nvme0n1-style path while
|
|
822
|
-
# /dev/disk/by-id/google-persistent_storage_1 is the symlink GCE
|
|
823
|
-
# publishes.
|
|
824
|
-
expected_userdata_dev() {
|
|
825
|
-
if [ -e "$USERDATA_DEV" ]; then
|
|
826
|
-
readlink -f "$USERDATA_DEV" 2>/dev/null || echo "$USERDATA_DEV"
|
|
827
|
-
else
|
|
828
|
-
echo "$USERDATA_DEV"
|
|
829
|
-
fi
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
wait_for_userdata() {
|
|
833
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" != "1" ]; then
|
|
834
|
-
return 0
|
|
835
|
-
fi
|
|
836
|
-
if mountpoint -q "$USERDATA_MOUNT" 2>/dev/null; then
|
|
837
|
-
# The mount slot is taken \u2014 but is it taken by the PD we're
|
|
838
|
-
# about to attach, or by something else? The Confidential Space
|
|
839
|
-
# TEE runtime's SetupSecondaryEncryptedVolume step probes for a
|
|
840
|
-
# secondary GCE disk once at boot, doesn't see it (because the
|
|
841
|
-
# orchestrator hasn't called AttachPD yet \u2014 the contract says
|
|
842
|
-
# the new VM signals awaiting-userdata FIRST), and falls back
|
|
843
|
-
# to mounting an encrypted folder on the BOOT disk at this same
|
|
844
|
-
# path. If we accept that mount as-is, the user app boots on a
|
|
845
|
-
# fresh empty filesystem and the orchestrator's late AttachPD
|
|
846
|
-
# silently lands on a VM that's already serving from boot disk.
|
|
847
|
-
# See docs/solutions/2026-05-15-prewarm-detach-pd-preservation-boot-race.md
|
|
848
|
-
# in ecloud-platform.
|
|
849
|
-
local backing expected
|
|
850
|
-
backing=$(userdata_mount_backing_dev)
|
|
851
|
-
expected=$(expected_userdata_dev)
|
|
852
|
-
if [ -n "$backing" ] && [ "$backing" = "$expected" ]; then
|
|
853
|
-
echo "compute-source-env.sh: userdata already mounted at $USERDATA_MOUNT (backed by $backing)"
|
|
854
|
-
return 0
|
|
855
|
-
fi
|
|
856
|
-
# Mount slot taken, but NOT by our PD. This is the runtime
|
|
857
|
-
# premount on boot disk. Try to recover by lazy-unmounting (the
|
|
858
|
-
# filesystem is fresh and unused \u2014 no app has written to it
|
|
859
|
-
# yet), then fall through to the normal wait-for-PD loop.
|
|
860
|
-
echo "compute-source-env.sh: WARNING - $USERDATA_MOUNT premounted by TEE runtime fallback (backing=\${backing:-unknown}, expected=$expected); attempting recovery"
|
|
861
|
-
if ! umount -l "$USERDATA_MOUNT" 2>/dev/null; then
|
|
862
|
-
# Lazy unmount should never fail under normal circumstances \u2014
|
|
863
|
-
# it doesn't wait for open files, just detaches the namespace.
|
|
864
|
-
# If it did fail, we have no path forward: the orchestrator's
|
|
865
|
-
# strict-mode WaitAwaitingUserdata gate (ecloud-platform PR
|
|
866
|
-
# #174) catches our ECLOUD_FAIL within one poll tick and
|
|
867
|
-
# rolls back, leaving the user's data safe on the old VM.
|
|
868
|
-
echo "ECLOUD_FAIL pd_runtime_premount_unrecoverable"
|
|
869
|
-
exit 1
|
|
870
|
-
fi
|
|
871
|
-
echo "compute-source-env.sh: unmounted runtime fallback at $USERDATA_MOUNT, waiting for real PD"
|
|
872
|
-
fi
|
|
873
|
-
# Refuse to proceed if the tools we need for safe first-attach
|
|
874
|
-
# detection are missing. Without blkid we cannot tell an empty new
|
|
875
|
-
# disk from an already-formatted one \u2014 running mkfs.ext4 on the
|
|
876
|
-
# latter would destroy data.
|
|
877
|
-
if ! command -v blkid >/dev/null 2>&1; then
|
|
878
|
-
echo "ECLOUD_FAIL pd_tools_missing"
|
|
879
|
-
exit 1
|
|
880
|
-
fi
|
|
881
|
-
echo "ECLOUD_AWAITING_USERDATA"
|
|
882
|
-
echo "compute-source-env.sh: waiting for PD at $USERDATA_DEV..."
|
|
883
|
-
# Poll for up to 10 minutes (120 * 5s). The orchestrator's overall
|
|
884
|
-
# attach timeout is shorter; the ceiling here just bounds the wait
|
|
885
|
-
# for manual / diagnostic scenarios.
|
|
886
|
-
local i=0
|
|
887
|
-
local mount_failures=0
|
|
888
|
-
while [ "$i" -lt 120 ]; do
|
|
889
|
-
if [ -e "$USERDATA_DEV" ]; then
|
|
890
|
-
mkdir -p "$USERDATA_MOUNT"
|
|
891
|
-
if mount -o noatime "$USERDATA_DEV" "$USERDATA_MOUNT" 2>/dev/null; then
|
|
892
|
-
echo "compute-source-env.sh: PD mounted at $USERDATA_MOUNT"
|
|
893
|
-
return 0
|
|
894
|
-
fi
|
|
895
|
-
# Disk present but mount failed. Check whether it has a
|
|
896
|
-
# recognized filesystem. \`blkid -s TYPE -o value\` prints the
|
|
897
|
-
# FS type (empty if none). We only mkfs when there is
|
|
898
|
-
# demonstrably NO filesystem \u2014 never on the basis of blkid
|
|
899
|
-
# returning non-zero alone, which could mean "blkid missing"
|
|
900
|
-
# or "device busy".
|
|
901
|
-
local fstype
|
|
902
|
-
fstype=$(blkid -s TYPE -o value "$USERDATA_DEV" 2>/dev/null)
|
|
903
|
-
if [ -z "$fstype" ]; then
|
|
904
|
-
echo "compute-source-env.sh: formatting $USERDATA_DEV (first attach)"
|
|
905
|
-
mkfs.ext4 -F -L eclouddata "$USERDATA_DEV" >/dev/null 2>&1 || {
|
|
906
|
-
echo "ECLOUD_FAIL pd_mkfs_failed"
|
|
907
|
-
exit 1
|
|
908
|
-
}
|
|
909
|
-
mount -o noatime "$USERDATA_DEV" "$USERDATA_MOUNT" || {
|
|
910
|
-
echo "ECLOUD_FAIL pd_mount_after_format_failed"
|
|
911
|
-
exit 1
|
|
912
|
-
}
|
|
913
|
-
return 0
|
|
914
|
-
fi
|
|
915
|
-
# Disk has a filesystem but mount still failed. Give it a
|
|
916
|
-
# few retries to cover transient cases (device busy, udev
|
|
917
|
-
# still settling), but don't pretend this is an attach
|
|
918
|
-
# timeout if it persists.
|
|
919
|
-
mount_failures=$((mount_failures + 1))
|
|
920
|
-
if [ "$mount_failures" -ge 6 ]; then
|
|
921
|
-
echo "ECLOUD_FAIL pd_mount_failed"
|
|
922
|
-
exit 1
|
|
923
|
-
fi
|
|
924
|
-
else
|
|
925
|
-
# Device disappeared (e.g. udev re-enumeration between
|
|
926
|
-
# attach and mount). Reset the consecutive-failure counter
|
|
927
|
-
# so only true back-to-back mount failures trip
|
|
928
|
-
# pd_mount_failed; a device blip should not steal retries.
|
|
929
|
-
mount_failures=0
|
|
930
|
-
fi
|
|
931
|
-
i=$((i + 1))
|
|
932
|
-
sleep 5
|
|
933
|
-
done
|
|
934
|
-
echo "ECLOUD_FAIL pd_attach_timeout"
|
|
935
|
-
exit 1
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
wait_for_userdata
|
|
939
|
-
|
|
940
|
-
# \u2500\u2500 Prewarm-detach: install SIGTERM handler for graceful drain \u2500\u2500
|
|
941
|
-
# Orchestrator signals drain by setting the instance metadata key
|
|
942
|
-
# ECLOUD_DRAIN_REQUESTED=1, which a host-level agent translates into
|
|
943
|
-
# SIGTERM on PID 1. On SIGTERM we:
|
|
944
|
-
# 1. Forward to the child (wakes the user's app for graceful exit)
|
|
945
|
-
# 2. Wait for child exit
|
|
946
|
-
# 3. Sync + unmount the PD
|
|
947
|
-
# 4. Emit ECLOUD_DETACHED so the orchestrator can proceed to detach
|
|
948
|
-
CHILD_PID=""
|
|
949
|
-
_DRAIN_IN_PROGRESS=0
|
|
950
|
-
|
|
951
|
-
drain_handler() {
|
|
952
|
-
# Guard against re-entry if SIGTERM arrives twice (e.g. both the
|
|
953
|
-
# drain_watcher and an external signal fire in quick succession).
|
|
954
|
-
if [ "$_DRAIN_IN_PROGRESS" = "1" ]; then
|
|
955
|
-
return 0
|
|
956
|
-
fi
|
|
957
|
-
_DRAIN_IN_PROGRESS=1
|
|
958
|
-
echo "compute-source-env.sh: received drain signal, forwarding to child pgid=$CHILD_PID"
|
|
959
|
-
if [ -n "$CHILD_PID" ]; then
|
|
960
|
-
# Send to the process group so intermediate wrappers (su, sh -c,
|
|
961
|
-
# etc.) don't swallow the signal. The leading \`-\` targets the
|
|
962
|
-
# pgid, which equals the direct child's pid for a shell-backgrounded
|
|
963
|
-
# process. Fall back to the pid alone if pgid signaling fails
|
|
964
|
-
# (e.g. kernel older than 3.9 or PID namespace edge cases).
|
|
965
|
-
kill -TERM -"$CHILD_PID" 2>/dev/null || kill -TERM "$CHILD_PID" 2>/dev/null || true
|
|
966
|
-
# Give the app up to 30s to exit cleanly.
|
|
967
|
-
local i=0
|
|
968
|
-
while [ "$i" -lt 30 ] && kill -0 "$CHILD_PID" 2>/dev/null; do
|
|
969
|
-
i=$((i + 1))
|
|
970
|
-
sleep 1
|
|
971
|
-
done
|
|
972
|
-
if kill -0 "$CHILD_PID" 2>/dev/null; then
|
|
973
|
-
echo "compute-source-env.sh: child did not exit in 30s, sending SIGKILL"
|
|
974
|
-
kill -KILL -"$CHILD_PID" 2>/dev/null || kill -KILL "$CHILD_PID" 2>/dev/null || true
|
|
975
|
-
# Reap the process so its in-flight I/O is flushed to the
|
|
976
|
-
# filesystem before we sync + unmount. SIGKILL schedules
|
|
977
|
-
# death; wait guarantees it's complete.
|
|
978
|
-
wait "$CHILD_PID" 2>/dev/null || true
|
|
979
|
-
fi
|
|
980
|
-
fi
|
|
981
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" = "1" ] && mountpoint -q "$USERDATA_MOUNT" 2>/dev/null; then
|
|
982
|
-
sync
|
|
983
|
-
if umount "$USERDATA_MOUNT" 2>/dev/null; then
|
|
984
|
-
echo "compute-source-env.sh: unmounted $USERDATA_MOUNT cleanly"
|
|
985
|
-
else
|
|
986
|
-
# Force lazy unmount as last resort \u2014 orchestrator still needs
|
|
987
|
-
# the DETACHED signal to proceed.
|
|
988
|
-
umount -l "$USERDATA_MOUNT" 2>/dev/null || true
|
|
989
|
-
echo "compute-source-env.sh: WARNING - used lazy unmount on $USERDATA_MOUNT"
|
|
990
|
-
fi
|
|
991
|
-
# ECLOUD_DETACHED is strictly a PD-lifecycle signal. Only emit
|
|
992
|
-
# it when we actually had a PD mount in play, so serial-log
|
|
993
|
-
# parsers and alerting for non-PD apps don't see spurious
|
|
994
|
-
# lifecycle markers on routine container SIGTERM.
|
|
995
|
-
echo "ECLOUD_DETACHED"
|
|
996
|
-
fi
|
|
997
|
-
# Always exit 0: drain is a managed shutdown and the orchestrator
|
|
998
|
-
# waits on ECLOUD_DETACHED, not the container exit code. Forwarding
|
|
999
|
-
# the child's exit status here would make a crash-during-drain look
|
|
1000
|
-
# like a drain failure to whatever reads the container exit code.
|
|
1001
|
-
exit 0
|
|
1002
|
-
}
|
|
1003
|
-
trap drain_handler TERM
|
|
1004
|
-
|
|
1005
|
-
# \u2500\u2500 Prewarm-detach: background drain watcher \u2500\u2500
|
|
1006
|
-
# Container metadata delivery in Confidential Space is limited, so we
|
|
1007
|
-
# poll the instance metadata server for ECLOUD_DRAIN_REQUESTED and
|
|
1008
|
-
# raise SIGTERM on ourselves when it flips to "1".
|
|
1009
|
-
#
|
|
1010
|
-
# Try wget first (present in most Alpine bases), fall back to curl.
|
|
1011
|
-
# If neither is present, drain watcher is disabled \u2014 the orchestrator
|
|
1012
|
-
# will hit its drain timeout and fail the upgrade explicitly, which is
|
|
1013
|
-
# the correct behavior (we cannot silently ignore a drain request).
|
|
1014
|
-
_fetch_drain_flag() {
|
|
1015
|
-
local url="http://metadata.google.internal/computeMetadata/v1/instance/attributes/ECLOUD_DRAIN_REQUESTED"
|
|
1016
|
-
if command -v wget >/dev/null 2>&1; then
|
|
1017
|
-
wget -q --tries=1 --timeout=2 --header='Metadata-Flavor: Google' -O - "$url" 2>/dev/null
|
|
1018
|
-
elif command -v curl >/dev/null 2>&1; then
|
|
1019
|
-
curl -sf --max-time 2 -H 'Metadata-Flavor: Google' "$url" 2>/dev/null
|
|
1020
|
-
else
|
|
1021
|
-
return 2
|
|
1022
|
-
fi
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
drain_watcher() {
|
|
1026
|
-
# Preflight: confirm we have an HTTP client
|
|
1027
|
-
if ! _fetch_drain_flag >/dev/null 2>&1; then
|
|
1028
|
-
# Either no http client available OR metadata server not
|
|
1029
|
-
# responding yet. If no client, give up and log; otherwise the
|
|
1030
|
-
# loop below will retry.
|
|
1031
|
-
if ! command -v wget >/dev/null 2>&1 && ! command -v curl >/dev/null 2>&1; then
|
|
1032
|
-
echo "compute-source-env.sh: WARNING - no wget/curl; drain_watcher disabled"
|
|
1033
|
-
return 0
|
|
1034
|
-
fi
|
|
1035
|
-
fi
|
|
1036
|
-
while true; do
|
|
1037
|
-
local v
|
|
1038
|
-
v=$(_fetch_drain_flag || true)
|
|
1039
|
-
if [ "$v" = "1" ]; then
|
|
1040
|
-
echo "compute-source-env.sh: drain_watcher saw ECLOUD_DRAIN_REQUESTED=1, signaling PID 1"
|
|
1041
|
-
# The CS launcher runs this script directly as PID 1, so
|
|
1042
|
-
# kill -TERM 1 delivers SIGTERM to the shell that installed
|
|
1043
|
-
# the drain_handler trap. If the launch mechanism ever
|
|
1044
|
-
# wraps this script in another process, this assumption
|
|
1045
|
-
# breaks and drain will silently no-op \u2014 audit here.
|
|
1046
|
-
kill -TERM 1 2>/dev/null || true
|
|
1047
|
-
return 0
|
|
1048
|
-
fi
|
|
1049
|
-
sleep 2
|
|
1050
|
-
done
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" = "1" ]; then
|
|
1054
|
-
# Assumption: the orchestrator only flips ECLOUD_DRAIN_REQUESTED=1
|
|
1055
|
-
# after observing ECLOUD_AWAITING_USERDATA (old VM) or
|
|
1056
|
-
# ECLOUD_READY (new VM), so CHILD_PID is always set by the time
|
|
1057
|
-
# drain_handler fires. If drain somehow arrived in the tiny window
|
|
1058
|
-
# between this watcher spawn and CHILD_PID assignment below,
|
|
1059
|
-
# drain_handler would skip the child-kill branch and still emit
|
|
1060
|
-
# ECLOUD_DETACHED \u2014 harmless because there's nothing to drain yet.
|
|
1061
|
-
if [ -x /usr/local/bin/ecloud-drain-watcher ]; then
|
|
1062
|
-
/usr/local/bin/ecloud-drain-watcher &
|
|
1063
|
-
else
|
|
1064
|
-
drain_watcher &
|
|
1065
|
-
fi
|
|
1066
|
-
fi
|
|
1067
|
-
|
|
1068
616
|
echo "compute-source-env.sh: Environment sourced."
|
|
1069
|
-
echo "ECLOUD_READY runtime_bootstrapped"
|
|
1070
617
|
|
|
1071
618
|
# Drop privileges to original user for the application command
|
|
1072
619
|
if [ -n "$__ECLOUD_ORIGINAL_USER" ] && [ "$(id -u)" = "0" ]; then
|
|
1073
620
|
echo "compute-source-env.sh: Dropping privileges to user: $__ECLOUD_ORIGINAL_USER"
|
|
1074
|
-
|
|
1075
|
-
su -s /bin/sh "$__ECLOUD_ORIGINAL_USER" -c 'exec "$@"' -- sh "$@" &
|
|
1076
|
-
CHILD_PID=$!
|
|
1077
|
-
wait "$CHILD_PID"
|
|
1078
|
-
exit $?
|
|
621
|
+
exec su -s /bin/sh "$__ECLOUD_ORIGINAL_USER" -c 'exec "$@"' -- sh "$@"
|
|
1079
622
|
fi
|
|
1080
623
|
|
|
1081
|
-
"$@"
|
|
1082
|
-
CHILD_PID=$!
|
|
1083
|
-
wait "$CHILD_PID"
|
|
1084
|
-
exit $?
|
|
624
|
+
exec "$@"
|
|
1085
625
|
`;
|
|
1086
626
|
|
|
1087
627
|
// src/client/common/templates/scriptTemplate.ts
|
|
@@ -1090,14 +630,6 @@ function processScriptTemplate(data) {
|
|
|
1090
630
|
return template(data);
|
|
1091
631
|
}
|
|
1092
632
|
|
|
1093
|
-
// src/client/common/templates/Caddyfile.default.tmpl
|
|
1094
|
-
var Caddyfile_default_default = '# Caddy configuration for automatic HTTPS\n#\n# Two sites can be configured at runtime via env vars that\n# ecloud-platform / the CLI inject into tee-env metadata:\n#\n# ECLOUD_PLATFORM_HOST \u2014 the platform-derived hostname\n# (<addr>.<env>.eigencloud.xyz). Always set\n# for platform-routed apps. Cert at\n# /run/tls/platform/fullchain.pem.\n# DOMAIN \u2014 optional user-supplied custom domain.\n# Cert at /run/tls/domain/fullchain.pem.\n#\n# When a variable is unset, Caddy substitutes the default listed\n# after the colon. We use distinct defaults per site so each block\n# binds to a unique name at bootstrap \u2014 both blocks overlapping\n# on "localhost" would cause Caddy to reject the config.\n{$ECLOUD_PLATFORM_HOST:localhost.platform.invalid} {\n tls /run/tls/platform/fullchain.pem /run/tls/platform/privkey.pem\n\n reverse_proxy localhost:{$APP_PORT:3000} {\n health_uri /health\n health_interval 30s\n health_timeout 5s\n health_status 200\n }\n\n header {\n X-Content-Type-Options "nosniff"\n X-Frame-Options "DENY"\n X-XSS-Protection "1; mode=block"\n Referrer-Policy "strict-origin-when-cross-origin"\n -Server\n }\n\n log {\n output stdout\n format console\n level INFO\n }\n\n request_body {\n max_size 10MB\n }\n}\n\n{$DOMAIN:localhost.user.invalid} {\n tls /run/tls/domain/fullchain.pem /run/tls/domain/privkey.pem\n\n reverse_proxy localhost:{$APP_PORT:3000} {\n health_uri /health\n health_interval 30s\n health_timeout 5s\n health_status 200\n }\n\n header {\n X-Content-Type-Options "nosniff"\n X-Frame-Options "DENY"\n X-XSS-Protection "1; mode=block"\n Referrer-Policy "strict-origin-when-cross-origin"\n -Server\n }\n\n log {\n output stdout\n format console\n level INFO\n }\n\n request_body {\n max_size 10MB\n }\n}\n\n# HTTP endpoint (optional, for health checks or redirects)\n:80 {\n # Redirect to HTTPS for any real (non-placeholder) host\n @for_domain expression {host} != "localhost.platform.invalid" && {host} != "localhost.user.invalid" && {host} != "localhost"\n redir @for_domain https://{host}{uri} permanent\n\n # Health check endpoint (always available via HTTP)\n handle /health {\n respond "OK" 200\n }\n}\n';
|
|
1095
|
-
|
|
1096
|
-
// src/client/common/templates/caddyfileTemplate.ts
|
|
1097
|
-
function getDefaultCaddyfile() {
|
|
1098
|
-
return Caddyfile_default_default;
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
633
|
// keys/mainnet-alpha/prod/kms-encryption-public-key.pem
|
|
1102
634
|
var kms_encryption_public_key_default = "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0kHU86k17ofCIGcJKDcf\nAFurFhSLeWmOL0bwWLCeVnTPG0MMHtJOq+woE0XXSWw6lzm+jzavBBTwKde1dgal\nAp91vULAZFMUpiUdd2dNUVtvU89qW0Pgf1Eu5FDj7BkY/SnyECbWJM4ga0BmpiGy\nnQwLNN9mMGhjVoVLn2zwEGZ7JzS9Nz11EZKO/k/9DcO6LaoIFmKuvVf3jl6lvZg8\naeA0LoZXjkycHlRUt/kfKwZnhakUaYHP1ksV7ZNmolS5GYDTSKGB2KPPNR1s4/Xu\nu8zeEFC8HuGRU8XuuBeaAunitnGhbNVREUNJGff6HZOGB6CIFNXjbQETeZ3p5uro\n0v+hd1QqQYBv7+DEaMCmGnJNGAyIMr2mn4vr7wGsIj0HonlSHmQ8rmdUhL2ocNTc\nLhKgZiZmBuDpSbFW/r53R2G7CHcqaqGeUBnT54QCH4zsYKw0/4dOtwFxQpTyBf9/\n+k+KaWEJYKkx9d9OzKGyAvzrTDVOFoajddiJ6LPvRlMdOUQr3hl4IAC0/nh9lhHq\nD0R+i5WAU96TkdAe7B7iTGH2D22k0KUPR6Q9W3aF353SLxQAMPNrgG4QQufAdRJn\nAF+8ntun5TkTqjTWRSwAsUJZ1z4wb96DympWJbDi0OciJRZ3Fz3j9+amC43yCHGg\naaEMjdt35ewbztUSc04F10MCAwEAAQ==\n-----END PUBLIC KEY-----";
|
|
1103
635
|
|
|
@@ -1272,9 +804,15 @@ async function layerLocalImage(options, logger) {
|
|
|
1272
804
|
const imageConfig = await extractImageConfig(docker, sourceImageRef);
|
|
1273
805
|
const originalCmd = imageConfig.cmd.length > 0 ? imageConfig.cmd : imageConfig.entrypoint;
|
|
1274
806
|
const originalUser = imageConfig.user;
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
807
|
+
let includeTLS = false;
|
|
808
|
+
if (envFilePath && fs.existsSync(envFilePath)) {
|
|
809
|
+
const envContent = fs.readFileSync(envFilePath, "utf-8");
|
|
810
|
+
const domainMatch = envContent.match(/^DOMAIN=(.+)$/m);
|
|
811
|
+
if (domainMatch && domainMatch[1] && domainMatch[1] !== "localhost") {
|
|
812
|
+
includeTLS = true;
|
|
813
|
+
logger.debug(`Found DOMAIN=${domainMatch[1]} in ${envFilePath}, including TLS components`);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
1278
816
|
const layeredDockerfileContent = processDockerfileTemplate({
|
|
1279
817
|
baseImage: sourceImageRef,
|
|
1280
818
|
originalCmd: JSON.stringify(originalCmd),
|
|
@@ -1282,9 +820,8 @@ async function layerLocalImage(options, logger) {
|
|
|
1282
820
|
logRedirect,
|
|
1283
821
|
resourceUsageAllow,
|
|
1284
822
|
includeTLS,
|
|
1285
|
-
ecloudCLIVersion: "0.1.0"
|
|
823
|
+
ecloudCLIVersion: "0.1.0"
|
|
1286
824
|
// TODO: Get from package.json
|
|
1287
|
-
includeDrainWatcher
|
|
1288
825
|
});
|
|
1289
826
|
const scriptContent = processScriptTemplate({
|
|
1290
827
|
kmsServerURL: environmentConfig.kmsServerURL,
|
|
@@ -1294,8 +831,7 @@ async function layerLocalImage(options, logger) {
|
|
|
1294
831
|
environmentConfig,
|
|
1295
832
|
layeredDockerfileContent,
|
|
1296
833
|
scriptContent,
|
|
1297
|
-
includeTLS
|
|
1298
|
-
includeDrainWatcher ? drainWatcherSource : void 0
|
|
834
|
+
includeTLS
|
|
1299
835
|
// logger
|
|
1300
836
|
);
|
|
1301
837
|
try {
|
|
@@ -1310,7 +846,7 @@ async function layerLocalImage(options, logger) {
|
|
|
1310
846
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
1311
847
|
}
|
|
1312
848
|
}
|
|
1313
|
-
async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileContent, scriptContent, includeTLS
|
|
849
|
+
async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileContent, scriptContent, includeTLS) {
|
|
1314
850
|
const tempDir = fs.mkdtempSync(path2.join(os.tmpdir(), LAYERED_BUILD_DIR_PREFIX));
|
|
1315
851
|
try {
|
|
1316
852
|
const layeredDockerfilePath = path2.join(tempDir, LAYERED_DOCKERFILE_NAME);
|
|
@@ -1334,11 +870,6 @@ async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileCo
|
|
|
1334
870
|
}
|
|
1335
871
|
fs.copyFileSync(kmsClientSource, kmsClientPath);
|
|
1336
872
|
fs.chmodSync(kmsClientPath, 493);
|
|
1337
|
-
if (drainWatcherSource && fs.existsSync(drainWatcherSource)) {
|
|
1338
|
-
const drainWatcherPath = path2.join(tempDir, DRAIN_WATCHER_BINARY_NAME);
|
|
1339
|
-
fs.copyFileSync(drainWatcherSource, drainWatcherPath);
|
|
1340
|
-
fs.chmodSync(drainWatcherPath, 493);
|
|
1341
|
-
}
|
|
1342
873
|
if (includeTLS) {
|
|
1343
874
|
const tlsKeygenPath = path2.join(tempDir, TLS_KEYGEN_BINARY_NAME);
|
|
1344
875
|
const tlsKeygenSource = findBinary("tls-keygen-linux-amd64");
|
|
@@ -1349,13 +880,15 @@ async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileCo
|
|
|
1349
880
|
}
|
|
1350
881
|
fs.copyFileSync(tlsKeygenSource, tlsKeygenPath);
|
|
1351
882
|
fs.chmodSync(tlsKeygenPath, 493);
|
|
1352
|
-
const
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
fs.
|
|
883
|
+
const caddyfilePath = path2.join(process.cwd(), CADDYFILE_NAME);
|
|
884
|
+
if (fs.existsSync(caddyfilePath)) {
|
|
885
|
+
const caddyfileContent = fs.readFileSync(caddyfilePath);
|
|
886
|
+
const destCaddyfilePath = path2.join(tempDir, CADDYFILE_NAME);
|
|
887
|
+
fs.writeFileSync(destCaddyfilePath, caddyfileContent, { mode: 420 });
|
|
1357
888
|
} else {
|
|
1358
|
-
|
|
889
|
+
throw new Error(
|
|
890
|
+
"TLS is enabled (DOMAIN is set) but Caddyfile not found. Run configure TLS to set up TLS configuration"
|
|
891
|
+
);
|
|
1359
892
|
}
|
|
1360
893
|
}
|
|
1361
894
|
return tempDir;
|
|
@@ -1423,16 +956,7 @@ async function extractDigestFromSinglePlatform(manifest, imageRef) {
|
|
|
1423
956
|
architecture: inspectData[0].Architecture
|
|
1424
957
|
} : null;
|
|
1425
958
|
if (!config) {
|
|
1426
|
-
|
|
1427
|
-
const digest = hexStringToBytes32(manifest.config.digest);
|
|
1428
|
-
const registry = extractRegistryName(imageRef);
|
|
1429
|
-
return {
|
|
1430
|
-
digest,
|
|
1431
|
-
registry,
|
|
1432
|
-
platform: DOCKER_PLATFORM
|
|
1433
|
-
};
|
|
1434
|
-
}
|
|
1435
|
-
throw new Error(`Could not determine platform for ${imageRef}`);
|
|
959
|
+
throw createPlatformErrorMessage(imageRef, ["unknown (could not determine architecture)"]);
|
|
1436
960
|
}
|
|
1437
961
|
const platform2 = `${config.os}/${config.architecture}`;
|
|
1438
962
|
if (platform2 === DOCKER_PLATFORM) {
|
|
@@ -1504,14 +1028,11 @@ Image: ${imageRef}
|
|
|
1504
1028
|
Found platform(s): ${platforms.join(", ")}
|
|
1505
1029
|
Required platform: ${DOCKER_PLATFORM}
|
|
1506
1030
|
|
|
1507
|
-
To fix
|
|
1508
|
-
1.
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
docker push ${imageRef}
|
|
1513
|
-
|
|
1514
|
-
2. Or use the SDK to build with the correct platform automatically.`;
|
|
1031
|
+
To fix, either:
|
|
1032
|
+
1. Rebuild the image for ${DOCKER_PLATFORM} and push it:
|
|
1033
|
+
docker buildx build --platform ${DOCKER_PLATFORM} -t ${imageRef} --push .
|
|
1034
|
+
2. Or use a verifiable build (--verifiable --repo <repo> --commit <sha>), which
|
|
1035
|
+
builds server-side and needs no local Docker.`;
|
|
1515
1036
|
return new Error(errorMsg);
|
|
1516
1037
|
}
|
|
1517
1038
|
|
|
@@ -1616,6 +1137,8 @@ async function prepareRelease(options, logger) {
|
|
|
1616
1137
|
logger.info(`Waiting ${REGISTRY_PROPAGATION_WAIT_SECONDS} seconds for registry propagation...`);
|
|
1617
1138
|
await new Promise((resolve2) => setTimeout(resolve2, REGISTRY_PROPAGATION_WAIT_SECONDS * 1e3));
|
|
1618
1139
|
} else {
|
|
1140
|
+
logger.info("Verifying image platform (linux/amd64)...");
|
|
1141
|
+
await getImageDigestAndName(imageRef);
|
|
1619
1142
|
logger.info("Checking if image needs layering...");
|
|
1620
1143
|
finalImageRef = await layerRemoteImageIfNeeded(
|
|
1621
1144
|
{
|
|
@@ -1774,6 +1297,13 @@ function extractRegistryNameNoDocker(imageRef) {
|
|
|
1774
1297
|
import { encodeFunctionData, encodeAbiParameters, decodeErrorResult } from "viem";
|
|
1775
1298
|
|
|
1776
1299
|
// src/client/common/types/index.ts
|
|
1300
|
+
var EMPTY_CONTAINER_POLICY = {
|
|
1301
|
+
args: [],
|
|
1302
|
+
cmdOverride: [],
|
|
1303
|
+
env: [],
|
|
1304
|
+
envOverride: [],
|
|
1305
|
+
restartPolicy: ""
|
|
1306
|
+
};
|
|
1777
1307
|
var noopLogger = {
|
|
1778
1308
|
debug: () => {
|
|
1779
1309
|
},
|
|
@@ -3014,32 +2544,1577 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
3014
2544
|
} else {
|
|
3015
2545
|
revertReason = callError.message || "Unknown reason";
|
|
3016
2546
|
}
|
|
3017
|
-
}
|
|
3018
|
-
throw new Error(`Transaction reverted: ${hash}. Reason: ${revertReason}`);
|
|
2547
|
+
}
|
|
2548
|
+
throw new Error(`Transaction reverted: ${hash}. Reason: ${revertReason}`);
|
|
2549
|
+
}
|
|
2550
|
+
return hash;
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
// src/client/common/contract/caller.ts
|
|
2554
|
+
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
2555
|
+
|
|
2556
|
+
// src/client/common/utils/helpers.ts
|
|
2557
|
+
import { extractChain, createPublicClient, createWalletClient, http, fallback } from "viem";
|
|
2558
|
+
import { sepolia as sepolia2 } from "viem/chains";
|
|
2559
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
2560
|
+
function getChainFromID(chainID, fallback2 = sepolia2) {
|
|
2561
|
+
const id = Number(chainID);
|
|
2562
|
+
return extractChain({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
2563
|
+
}
|
|
2564
|
+
function addHexPrefix(value) {
|
|
2565
|
+
return value.startsWith("0x") ? value : `0x${value}`;
|
|
2566
|
+
}
|
|
2567
|
+
function stripHexPrefix(value) {
|
|
2568
|
+
return value.startsWith("0x") ? value.slice(2) : value;
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
// src/client/common/abis/AppController.json
|
|
2572
|
+
var AppController_default = [
|
|
2573
|
+
{
|
|
2574
|
+
type: "constructor",
|
|
2575
|
+
inputs: [
|
|
2576
|
+
{
|
|
2577
|
+
name: "_version",
|
|
2578
|
+
type: "string",
|
|
2579
|
+
internalType: "string"
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
name: "_permissionController",
|
|
2583
|
+
type: "address",
|
|
2584
|
+
internalType: "contractIPermissionController"
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
name: "_releaseManager",
|
|
2588
|
+
type: "address",
|
|
2589
|
+
internalType: "contractIReleaseManager"
|
|
2590
|
+
},
|
|
2591
|
+
{
|
|
2592
|
+
name: "_computeAVSRegistrar",
|
|
2593
|
+
type: "address",
|
|
2594
|
+
internalType: "contractIComputeAVSRegistrar"
|
|
2595
|
+
},
|
|
2596
|
+
{
|
|
2597
|
+
name: "_computeOperator",
|
|
2598
|
+
type: "address",
|
|
2599
|
+
internalType: "contractIComputeOperator"
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
name: "_appBeacon",
|
|
2603
|
+
type: "address",
|
|
2604
|
+
internalType: "contractIBeacon"
|
|
2605
|
+
}
|
|
2606
|
+
],
|
|
2607
|
+
stateMutability: "nonpayable"
|
|
2608
|
+
},
|
|
2609
|
+
{
|
|
2610
|
+
type: "function",
|
|
2611
|
+
name: "API_PERMISSION_TYPEHASH",
|
|
2612
|
+
inputs: [],
|
|
2613
|
+
outputs: [
|
|
2614
|
+
{
|
|
2615
|
+
name: "",
|
|
2616
|
+
type: "bytes32",
|
|
2617
|
+
internalType: "bytes32"
|
|
2618
|
+
}
|
|
2619
|
+
],
|
|
2620
|
+
stateMutability: "view"
|
|
2621
|
+
},
|
|
2622
|
+
{
|
|
2623
|
+
type: "function",
|
|
2624
|
+
name: "appBeacon",
|
|
2625
|
+
inputs: [],
|
|
2626
|
+
outputs: [
|
|
2627
|
+
{
|
|
2628
|
+
name: "",
|
|
2629
|
+
type: "address",
|
|
2630
|
+
internalType: "contractIBeacon"
|
|
2631
|
+
}
|
|
2632
|
+
],
|
|
2633
|
+
stateMutability: "view"
|
|
2634
|
+
},
|
|
2635
|
+
{
|
|
2636
|
+
type: "function",
|
|
2637
|
+
name: "calculateApiPermissionDigestHash",
|
|
2638
|
+
inputs: [
|
|
2639
|
+
{
|
|
2640
|
+
name: "permission",
|
|
2641
|
+
type: "bytes4",
|
|
2642
|
+
internalType: "bytes4"
|
|
2643
|
+
},
|
|
2644
|
+
{
|
|
2645
|
+
name: "expiry",
|
|
2646
|
+
type: "uint256",
|
|
2647
|
+
internalType: "uint256"
|
|
2648
|
+
}
|
|
2649
|
+
],
|
|
2650
|
+
outputs: [
|
|
2651
|
+
{
|
|
2652
|
+
name: "",
|
|
2653
|
+
type: "bytes32",
|
|
2654
|
+
internalType: "bytes32"
|
|
2655
|
+
}
|
|
2656
|
+
],
|
|
2657
|
+
stateMutability: "view"
|
|
2658
|
+
},
|
|
2659
|
+
{
|
|
2660
|
+
type: "function",
|
|
2661
|
+
name: "calculateAppId",
|
|
2662
|
+
inputs: [
|
|
2663
|
+
{
|
|
2664
|
+
name: "deployer",
|
|
2665
|
+
type: "address",
|
|
2666
|
+
internalType: "address"
|
|
2667
|
+
},
|
|
2668
|
+
{
|
|
2669
|
+
name: "salt",
|
|
2670
|
+
type: "bytes32",
|
|
2671
|
+
internalType: "bytes32"
|
|
2672
|
+
}
|
|
2673
|
+
],
|
|
2674
|
+
outputs: [
|
|
2675
|
+
{
|
|
2676
|
+
name: "",
|
|
2677
|
+
type: "address",
|
|
2678
|
+
internalType: "contractIApp"
|
|
2679
|
+
}
|
|
2680
|
+
],
|
|
2681
|
+
stateMutability: "view"
|
|
2682
|
+
},
|
|
2683
|
+
{
|
|
2684
|
+
type: "function",
|
|
2685
|
+
name: "computeAVSRegistrar",
|
|
2686
|
+
inputs: [],
|
|
2687
|
+
outputs: [
|
|
2688
|
+
{
|
|
2689
|
+
name: "",
|
|
2690
|
+
type: "address",
|
|
2691
|
+
internalType: "contractIComputeAVSRegistrar"
|
|
2692
|
+
}
|
|
2693
|
+
],
|
|
2694
|
+
stateMutability: "view"
|
|
2695
|
+
},
|
|
2696
|
+
{
|
|
2697
|
+
type: "function",
|
|
2698
|
+
name: "computeOperator",
|
|
2699
|
+
inputs: [],
|
|
2700
|
+
outputs: [
|
|
2701
|
+
{
|
|
2702
|
+
name: "",
|
|
2703
|
+
type: "address",
|
|
2704
|
+
internalType: "contractIComputeOperator"
|
|
2705
|
+
}
|
|
2706
|
+
],
|
|
2707
|
+
stateMutability: "view"
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
type: "function",
|
|
2711
|
+
name: "confirmUpgrade",
|
|
2712
|
+
inputs: [
|
|
2713
|
+
{
|
|
2714
|
+
name: "app",
|
|
2715
|
+
type: "address",
|
|
2716
|
+
internalType: "contractIApp"
|
|
2717
|
+
}
|
|
2718
|
+
],
|
|
2719
|
+
outputs: [],
|
|
2720
|
+
stateMutability: "nonpayable"
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
type: "function",
|
|
2724
|
+
name: "createApp",
|
|
2725
|
+
inputs: [
|
|
2726
|
+
{
|
|
2727
|
+
name: "salt",
|
|
2728
|
+
type: "bytes32",
|
|
2729
|
+
internalType: "bytes32"
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
name: "release",
|
|
2733
|
+
type: "tuple",
|
|
2734
|
+
internalType: "structIAppController.Release",
|
|
2735
|
+
components: [
|
|
2736
|
+
{
|
|
2737
|
+
name: "rmsRelease",
|
|
2738
|
+
type: "tuple",
|
|
2739
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
2740
|
+
components: [
|
|
2741
|
+
{
|
|
2742
|
+
name: "artifacts",
|
|
2743
|
+
type: "tuple[]",
|
|
2744
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
2745
|
+
components: [
|
|
2746
|
+
{
|
|
2747
|
+
name: "digest",
|
|
2748
|
+
type: "bytes32",
|
|
2749
|
+
internalType: "bytes32"
|
|
2750
|
+
},
|
|
2751
|
+
{
|
|
2752
|
+
name: "registry",
|
|
2753
|
+
type: "string",
|
|
2754
|
+
internalType: "string"
|
|
2755
|
+
}
|
|
2756
|
+
]
|
|
2757
|
+
},
|
|
2758
|
+
{
|
|
2759
|
+
name: "upgradeByTime",
|
|
2760
|
+
type: "uint32",
|
|
2761
|
+
internalType: "uint32"
|
|
2762
|
+
}
|
|
2763
|
+
]
|
|
2764
|
+
},
|
|
2765
|
+
{
|
|
2766
|
+
name: "publicEnv",
|
|
2767
|
+
type: "bytes",
|
|
2768
|
+
internalType: "bytes"
|
|
2769
|
+
},
|
|
2770
|
+
{
|
|
2771
|
+
name: "encryptedEnv",
|
|
2772
|
+
type: "bytes",
|
|
2773
|
+
internalType: "bytes"
|
|
2774
|
+
},
|
|
2775
|
+
{
|
|
2776
|
+
name: "containerPolicy",
|
|
2777
|
+
type: "tuple",
|
|
2778
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
2779
|
+
components: [
|
|
2780
|
+
{
|
|
2781
|
+
name: "args",
|
|
2782
|
+
type: "string[]",
|
|
2783
|
+
internalType: "string[]"
|
|
2784
|
+
},
|
|
2785
|
+
{
|
|
2786
|
+
name: "cmdOverride",
|
|
2787
|
+
type: "string[]",
|
|
2788
|
+
internalType: "string[]"
|
|
2789
|
+
},
|
|
2790
|
+
{
|
|
2791
|
+
name: "env",
|
|
2792
|
+
type: "tuple[]",
|
|
2793
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2794
|
+
components: [
|
|
2795
|
+
{
|
|
2796
|
+
name: "key",
|
|
2797
|
+
type: "string",
|
|
2798
|
+
internalType: "string"
|
|
2799
|
+
},
|
|
2800
|
+
{
|
|
2801
|
+
name: "value",
|
|
2802
|
+
type: "string",
|
|
2803
|
+
internalType: "string"
|
|
2804
|
+
}
|
|
2805
|
+
]
|
|
2806
|
+
},
|
|
2807
|
+
{
|
|
2808
|
+
name: "envOverride",
|
|
2809
|
+
type: "tuple[]",
|
|
2810
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2811
|
+
components: [
|
|
2812
|
+
{
|
|
2813
|
+
name: "key",
|
|
2814
|
+
type: "string",
|
|
2815
|
+
internalType: "string"
|
|
2816
|
+
},
|
|
2817
|
+
{
|
|
2818
|
+
name: "value",
|
|
2819
|
+
type: "string",
|
|
2820
|
+
internalType: "string"
|
|
2821
|
+
}
|
|
2822
|
+
]
|
|
2823
|
+
},
|
|
2824
|
+
{
|
|
2825
|
+
name: "restartPolicy",
|
|
2826
|
+
type: "string",
|
|
2827
|
+
internalType: "string"
|
|
2828
|
+
}
|
|
2829
|
+
]
|
|
2830
|
+
}
|
|
2831
|
+
]
|
|
2832
|
+
}
|
|
2833
|
+
],
|
|
2834
|
+
outputs: [
|
|
2835
|
+
{
|
|
2836
|
+
name: "app",
|
|
2837
|
+
type: "address",
|
|
2838
|
+
internalType: "contractIApp"
|
|
2839
|
+
}
|
|
2840
|
+
],
|
|
2841
|
+
stateMutability: "nonpayable"
|
|
2842
|
+
},
|
|
2843
|
+
{
|
|
2844
|
+
type: "function",
|
|
2845
|
+
name: "createAppWithIsolatedBilling",
|
|
2846
|
+
inputs: [
|
|
2847
|
+
{
|
|
2848
|
+
name: "salt",
|
|
2849
|
+
type: "bytes32",
|
|
2850
|
+
internalType: "bytes32"
|
|
2851
|
+
},
|
|
2852
|
+
{
|
|
2853
|
+
name: "release",
|
|
2854
|
+
type: "tuple",
|
|
2855
|
+
internalType: "structIAppController.Release",
|
|
2856
|
+
components: [
|
|
2857
|
+
{
|
|
2858
|
+
name: "rmsRelease",
|
|
2859
|
+
type: "tuple",
|
|
2860
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
2861
|
+
components: [
|
|
2862
|
+
{
|
|
2863
|
+
name: "artifacts",
|
|
2864
|
+
type: "tuple[]",
|
|
2865
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
2866
|
+
components: [
|
|
2867
|
+
{
|
|
2868
|
+
name: "digest",
|
|
2869
|
+
type: "bytes32",
|
|
2870
|
+
internalType: "bytes32"
|
|
2871
|
+
},
|
|
2872
|
+
{
|
|
2873
|
+
name: "registry",
|
|
2874
|
+
type: "string",
|
|
2875
|
+
internalType: "string"
|
|
2876
|
+
}
|
|
2877
|
+
]
|
|
2878
|
+
},
|
|
2879
|
+
{
|
|
2880
|
+
name: "upgradeByTime",
|
|
2881
|
+
type: "uint32",
|
|
2882
|
+
internalType: "uint32"
|
|
2883
|
+
}
|
|
2884
|
+
]
|
|
2885
|
+
},
|
|
2886
|
+
{
|
|
2887
|
+
name: "publicEnv",
|
|
2888
|
+
type: "bytes",
|
|
2889
|
+
internalType: "bytes"
|
|
2890
|
+
},
|
|
2891
|
+
{
|
|
2892
|
+
name: "encryptedEnv",
|
|
2893
|
+
type: "bytes",
|
|
2894
|
+
internalType: "bytes"
|
|
2895
|
+
},
|
|
2896
|
+
{
|
|
2897
|
+
name: "containerPolicy",
|
|
2898
|
+
type: "tuple",
|
|
2899
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
2900
|
+
components: [
|
|
2901
|
+
{
|
|
2902
|
+
name: "args",
|
|
2903
|
+
type: "string[]",
|
|
2904
|
+
internalType: "string[]"
|
|
2905
|
+
},
|
|
2906
|
+
{
|
|
2907
|
+
name: "cmdOverride",
|
|
2908
|
+
type: "string[]",
|
|
2909
|
+
internalType: "string[]"
|
|
2910
|
+
},
|
|
2911
|
+
{
|
|
2912
|
+
name: "env",
|
|
2913
|
+
type: "tuple[]",
|
|
2914
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2915
|
+
components: [
|
|
2916
|
+
{
|
|
2917
|
+
name: "key",
|
|
2918
|
+
type: "string",
|
|
2919
|
+
internalType: "string"
|
|
2920
|
+
},
|
|
2921
|
+
{
|
|
2922
|
+
name: "value",
|
|
2923
|
+
type: "string",
|
|
2924
|
+
internalType: "string"
|
|
2925
|
+
}
|
|
2926
|
+
]
|
|
2927
|
+
},
|
|
2928
|
+
{
|
|
2929
|
+
name: "envOverride",
|
|
2930
|
+
type: "tuple[]",
|
|
2931
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2932
|
+
components: [
|
|
2933
|
+
{
|
|
2934
|
+
name: "key",
|
|
2935
|
+
type: "string",
|
|
2936
|
+
internalType: "string"
|
|
2937
|
+
},
|
|
2938
|
+
{
|
|
2939
|
+
name: "value",
|
|
2940
|
+
type: "string",
|
|
2941
|
+
internalType: "string"
|
|
2942
|
+
}
|
|
2943
|
+
]
|
|
2944
|
+
},
|
|
2945
|
+
{
|
|
2946
|
+
name: "restartPolicy",
|
|
2947
|
+
type: "string",
|
|
2948
|
+
internalType: "string"
|
|
2949
|
+
}
|
|
2950
|
+
]
|
|
2951
|
+
}
|
|
2952
|
+
]
|
|
2953
|
+
}
|
|
2954
|
+
],
|
|
2955
|
+
outputs: [
|
|
2956
|
+
{
|
|
2957
|
+
name: "app",
|
|
2958
|
+
type: "address",
|
|
2959
|
+
internalType: "contractIApp"
|
|
2960
|
+
}
|
|
2961
|
+
],
|
|
2962
|
+
stateMutability: "nonpayable"
|
|
2963
|
+
},
|
|
2964
|
+
{
|
|
2965
|
+
type: "function",
|
|
2966
|
+
name: "createEmptyApp",
|
|
2967
|
+
inputs: [
|
|
2968
|
+
{
|
|
2969
|
+
name: "salt",
|
|
2970
|
+
type: "bytes32",
|
|
2971
|
+
internalType: "bytes32"
|
|
2972
|
+
}
|
|
2973
|
+
],
|
|
2974
|
+
outputs: [
|
|
2975
|
+
{
|
|
2976
|
+
name: "app",
|
|
2977
|
+
type: "address",
|
|
2978
|
+
internalType: "contractIApp"
|
|
2979
|
+
}
|
|
2980
|
+
],
|
|
2981
|
+
stateMutability: "nonpayable"
|
|
2982
|
+
},
|
|
2983
|
+
{
|
|
2984
|
+
type: "function",
|
|
2985
|
+
name: "createEmptyAppWithIsolatedBilling",
|
|
2986
|
+
inputs: [
|
|
2987
|
+
{
|
|
2988
|
+
name: "salt",
|
|
2989
|
+
type: "bytes32",
|
|
2990
|
+
internalType: "bytes32"
|
|
2991
|
+
}
|
|
2992
|
+
],
|
|
2993
|
+
outputs: [
|
|
2994
|
+
{
|
|
2995
|
+
name: "app",
|
|
2996
|
+
type: "address",
|
|
2997
|
+
internalType: "contractIApp"
|
|
2998
|
+
}
|
|
2999
|
+
],
|
|
3000
|
+
stateMutability: "nonpayable"
|
|
3001
|
+
},
|
|
3002
|
+
{
|
|
3003
|
+
type: "function",
|
|
3004
|
+
name: "domainSeparator",
|
|
3005
|
+
inputs: [],
|
|
3006
|
+
outputs: [
|
|
3007
|
+
{
|
|
3008
|
+
name: "",
|
|
3009
|
+
type: "bytes32",
|
|
3010
|
+
internalType: "bytes32"
|
|
3011
|
+
}
|
|
3012
|
+
],
|
|
3013
|
+
stateMutability: "view"
|
|
3014
|
+
},
|
|
3015
|
+
{
|
|
3016
|
+
type: "function",
|
|
3017
|
+
name: "getActiveAppCount",
|
|
3018
|
+
inputs: [
|
|
3019
|
+
{
|
|
3020
|
+
name: "user",
|
|
3021
|
+
type: "address",
|
|
3022
|
+
internalType: "address"
|
|
3023
|
+
}
|
|
3024
|
+
],
|
|
3025
|
+
outputs: [
|
|
3026
|
+
{
|
|
3027
|
+
name: "",
|
|
3028
|
+
type: "uint32",
|
|
3029
|
+
internalType: "uint32"
|
|
3030
|
+
}
|
|
3031
|
+
],
|
|
3032
|
+
stateMutability: "view"
|
|
3033
|
+
},
|
|
3034
|
+
{
|
|
3035
|
+
type: "function",
|
|
3036
|
+
name: "getAppCreator",
|
|
3037
|
+
inputs: [
|
|
3038
|
+
{
|
|
3039
|
+
name: "app",
|
|
3040
|
+
type: "address",
|
|
3041
|
+
internalType: "contractIApp"
|
|
3042
|
+
}
|
|
3043
|
+
],
|
|
3044
|
+
outputs: [
|
|
3045
|
+
{
|
|
3046
|
+
name: "",
|
|
3047
|
+
type: "address",
|
|
3048
|
+
internalType: "address"
|
|
3049
|
+
}
|
|
3050
|
+
],
|
|
3051
|
+
stateMutability: "view"
|
|
3052
|
+
},
|
|
3053
|
+
{
|
|
3054
|
+
type: "function",
|
|
3055
|
+
name: "getAppLatestReleaseBlockNumber",
|
|
3056
|
+
inputs: [
|
|
3057
|
+
{
|
|
3058
|
+
name: "app",
|
|
3059
|
+
type: "address",
|
|
3060
|
+
internalType: "contractIApp"
|
|
3061
|
+
}
|
|
3062
|
+
],
|
|
3063
|
+
outputs: [
|
|
3064
|
+
{
|
|
3065
|
+
name: "",
|
|
3066
|
+
type: "uint32",
|
|
3067
|
+
internalType: "uint32"
|
|
3068
|
+
}
|
|
3069
|
+
],
|
|
3070
|
+
stateMutability: "view"
|
|
3071
|
+
},
|
|
3072
|
+
{
|
|
3073
|
+
type: "function",
|
|
3074
|
+
name: "getAppOperatorSetId",
|
|
3075
|
+
inputs: [
|
|
3076
|
+
{
|
|
3077
|
+
name: "app",
|
|
3078
|
+
type: "address",
|
|
3079
|
+
internalType: "contractIApp"
|
|
3080
|
+
}
|
|
3081
|
+
],
|
|
3082
|
+
outputs: [
|
|
3083
|
+
{
|
|
3084
|
+
name: "",
|
|
3085
|
+
type: "uint32",
|
|
3086
|
+
internalType: "uint32"
|
|
3087
|
+
}
|
|
3088
|
+
],
|
|
3089
|
+
stateMutability: "view"
|
|
3090
|
+
},
|
|
3091
|
+
{
|
|
3092
|
+
type: "function",
|
|
3093
|
+
name: "getAppPendingReleaseBlockNumber",
|
|
3094
|
+
inputs: [
|
|
3095
|
+
{
|
|
3096
|
+
name: "app",
|
|
3097
|
+
type: "address",
|
|
3098
|
+
internalType: "contractIApp"
|
|
3099
|
+
}
|
|
3100
|
+
],
|
|
3101
|
+
outputs: [
|
|
3102
|
+
{
|
|
3103
|
+
name: "",
|
|
3104
|
+
type: "uint32",
|
|
3105
|
+
internalType: "uint32"
|
|
3106
|
+
}
|
|
3107
|
+
],
|
|
3108
|
+
stateMutability: "view"
|
|
3109
|
+
},
|
|
3110
|
+
{
|
|
3111
|
+
type: "function",
|
|
3112
|
+
name: "getAppStatus",
|
|
3113
|
+
inputs: [
|
|
3114
|
+
{
|
|
3115
|
+
name: "app",
|
|
3116
|
+
type: "address",
|
|
3117
|
+
internalType: "contractIApp"
|
|
3118
|
+
}
|
|
3119
|
+
],
|
|
3120
|
+
outputs: [
|
|
3121
|
+
{
|
|
3122
|
+
name: "",
|
|
3123
|
+
type: "uint8",
|
|
3124
|
+
internalType: "enumIAppController.AppStatus"
|
|
3125
|
+
}
|
|
3126
|
+
],
|
|
3127
|
+
stateMutability: "view"
|
|
3128
|
+
},
|
|
3129
|
+
{
|
|
3130
|
+
type: "function",
|
|
3131
|
+
name: "getApps",
|
|
3132
|
+
inputs: [
|
|
3133
|
+
{
|
|
3134
|
+
name: "offset",
|
|
3135
|
+
type: "uint256",
|
|
3136
|
+
internalType: "uint256"
|
|
3137
|
+
},
|
|
3138
|
+
{
|
|
3139
|
+
name: "limit",
|
|
3140
|
+
type: "uint256",
|
|
3141
|
+
internalType: "uint256"
|
|
3142
|
+
}
|
|
3143
|
+
],
|
|
3144
|
+
outputs: [
|
|
3145
|
+
{
|
|
3146
|
+
name: "apps",
|
|
3147
|
+
type: "address[]",
|
|
3148
|
+
internalType: "contractIApp[]"
|
|
3149
|
+
},
|
|
3150
|
+
{
|
|
3151
|
+
name: "appConfigsMem",
|
|
3152
|
+
type: "tuple[]",
|
|
3153
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3154
|
+
components: [
|
|
3155
|
+
{
|
|
3156
|
+
name: "creator",
|
|
3157
|
+
type: "address",
|
|
3158
|
+
internalType: "address"
|
|
3159
|
+
},
|
|
3160
|
+
{
|
|
3161
|
+
name: "operatorSetId",
|
|
3162
|
+
type: "uint32",
|
|
3163
|
+
internalType: "uint32"
|
|
3164
|
+
},
|
|
3165
|
+
{
|
|
3166
|
+
name: "latestReleaseBlockNumber",
|
|
3167
|
+
type: "uint32",
|
|
3168
|
+
internalType: "uint32"
|
|
3169
|
+
},
|
|
3170
|
+
{
|
|
3171
|
+
name: "pendingReleaseBlockNumber",
|
|
3172
|
+
type: "uint32",
|
|
3173
|
+
internalType: "uint32"
|
|
3174
|
+
},
|
|
3175
|
+
{
|
|
3176
|
+
name: "status",
|
|
3177
|
+
type: "uint8",
|
|
3178
|
+
internalType: "enumIAppController.AppStatus"
|
|
3179
|
+
}
|
|
3180
|
+
]
|
|
3181
|
+
}
|
|
3182
|
+
],
|
|
3183
|
+
stateMutability: "view"
|
|
3184
|
+
},
|
|
3185
|
+
{
|
|
3186
|
+
type: "function",
|
|
3187
|
+
name: "getAppsByBillingAccount",
|
|
3188
|
+
inputs: [
|
|
3189
|
+
{
|
|
3190
|
+
name: "account",
|
|
3191
|
+
type: "address",
|
|
3192
|
+
internalType: "address"
|
|
3193
|
+
},
|
|
3194
|
+
{
|
|
3195
|
+
name: "offset",
|
|
3196
|
+
type: "uint256",
|
|
3197
|
+
internalType: "uint256"
|
|
3198
|
+
},
|
|
3199
|
+
{
|
|
3200
|
+
name: "limit",
|
|
3201
|
+
type: "uint256",
|
|
3202
|
+
internalType: "uint256"
|
|
3203
|
+
}
|
|
3204
|
+
],
|
|
3205
|
+
outputs: [
|
|
3206
|
+
{
|
|
3207
|
+
name: "apps",
|
|
3208
|
+
type: "address[]",
|
|
3209
|
+
internalType: "contractIApp[]"
|
|
3210
|
+
},
|
|
3211
|
+
{
|
|
3212
|
+
name: "appConfigsMem",
|
|
3213
|
+
type: "tuple[]",
|
|
3214
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3215
|
+
components: [
|
|
3216
|
+
{
|
|
3217
|
+
name: "creator",
|
|
3218
|
+
type: "address",
|
|
3219
|
+
internalType: "address"
|
|
3220
|
+
},
|
|
3221
|
+
{
|
|
3222
|
+
name: "operatorSetId",
|
|
3223
|
+
type: "uint32",
|
|
3224
|
+
internalType: "uint32"
|
|
3225
|
+
},
|
|
3226
|
+
{
|
|
3227
|
+
name: "latestReleaseBlockNumber",
|
|
3228
|
+
type: "uint32",
|
|
3229
|
+
internalType: "uint32"
|
|
3230
|
+
},
|
|
3231
|
+
{
|
|
3232
|
+
name: "pendingReleaseBlockNumber",
|
|
3233
|
+
type: "uint32",
|
|
3234
|
+
internalType: "uint32"
|
|
3235
|
+
},
|
|
3236
|
+
{
|
|
3237
|
+
name: "status",
|
|
3238
|
+
type: "uint8",
|
|
3239
|
+
internalType: "enumIAppController.AppStatus"
|
|
3240
|
+
}
|
|
3241
|
+
]
|
|
3242
|
+
}
|
|
3243
|
+
],
|
|
3244
|
+
stateMutability: "view"
|
|
3245
|
+
},
|
|
3246
|
+
{
|
|
3247
|
+
type: "function",
|
|
3248
|
+
name: "getAppsByCreator",
|
|
3249
|
+
inputs: [
|
|
3250
|
+
{
|
|
3251
|
+
name: "creator",
|
|
3252
|
+
type: "address",
|
|
3253
|
+
internalType: "address"
|
|
3254
|
+
},
|
|
3255
|
+
{
|
|
3256
|
+
name: "offset",
|
|
3257
|
+
type: "uint256",
|
|
3258
|
+
internalType: "uint256"
|
|
3259
|
+
},
|
|
3260
|
+
{
|
|
3261
|
+
name: "limit",
|
|
3262
|
+
type: "uint256",
|
|
3263
|
+
internalType: "uint256"
|
|
3264
|
+
}
|
|
3265
|
+
],
|
|
3266
|
+
outputs: [
|
|
3267
|
+
{
|
|
3268
|
+
name: "apps",
|
|
3269
|
+
type: "address[]",
|
|
3270
|
+
internalType: "contractIApp[]"
|
|
3271
|
+
},
|
|
3272
|
+
{
|
|
3273
|
+
name: "appConfigsMem",
|
|
3274
|
+
type: "tuple[]",
|
|
3275
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3276
|
+
components: [
|
|
3277
|
+
{
|
|
3278
|
+
name: "creator",
|
|
3279
|
+
type: "address",
|
|
3280
|
+
internalType: "address"
|
|
3281
|
+
},
|
|
3282
|
+
{
|
|
3283
|
+
name: "operatorSetId",
|
|
3284
|
+
type: "uint32",
|
|
3285
|
+
internalType: "uint32"
|
|
3286
|
+
},
|
|
3287
|
+
{
|
|
3288
|
+
name: "latestReleaseBlockNumber",
|
|
3289
|
+
type: "uint32",
|
|
3290
|
+
internalType: "uint32"
|
|
3291
|
+
},
|
|
3292
|
+
{
|
|
3293
|
+
name: "pendingReleaseBlockNumber",
|
|
3294
|
+
type: "uint32",
|
|
3295
|
+
internalType: "uint32"
|
|
3296
|
+
},
|
|
3297
|
+
{
|
|
3298
|
+
name: "status",
|
|
3299
|
+
type: "uint8",
|
|
3300
|
+
internalType: "enumIAppController.AppStatus"
|
|
3301
|
+
}
|
|
3302
|
+
]
|
|
3303
|
+
}
|
|
3304
|
+
],
|
|
3305
|
+
stateMutability: "view"
|
|
3306
|
+
},
|
|
3307
|
+
{
|
|
3308
|
+
type: "function",
|
|
3309
|
+
name: "getAppsByDeveloper",
|
|
3310
|
+
inputs: [
|
|
3311
|
+
{
|
|
3312
|
+
name: "developer",
|
|
3313
|
+
type: "address",
|
|
3314
|
+
internalType: "address"
|
|
3315
|
+
},
|
|
3316
|
+
{
|
|
3317
|
+
name: "offset",
|
|
3318
|
+
type: "uint256",
|
|
3319
|
+
internalType: "uint256"
|
|
3320
|
+
},
|
|
3321
|
+
{
|
|
3322
|
+
name: "limit",
|
|
3323
|
+
type: "uint256",
|
|
3324
|
+
internalType: "uint256"
|
|
3325
|
+
}
|
|
3326
|
+
],
|
|
3327
|
+
outputs: [
|
|
3328
|
+
{
|
|
3329
|
+
name: "apps",
|
|
3330
|
+
type: "address[]",
|
|
3331
|
+
internalType: "contractIApp[]"
|
|
3332
|
+
},
|
|
3333
|
+
{
|
|
3334
|
+
name: "appConfigsMem",
|
|
3335
|
+
type: "tuple[]",
|
|
3336
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3337
|
+
components: [
|
|
3338
|
+
{
|
|
3339
|
+
name: "creator",
|
|
3340
|
+
type: "address",
|
|
3341
|
+
internalType: "address"
|
|
3342
|
+
},
|
|
3343
|
+
{
|
|
3344
|
+
name: "operatorSetId",
|
|
3345
|
+
type: "uint32",
|
|
3346
|
+
internalType: "uint32"
|
|
3347
|
+
},
|
|
3348
|
+
{
|
|
3349
|
+
name: "latestReleaseBlockNumber",
|
|
3350
|
+
type: "uint32",
|
|
3351
|
+
internalType: "uint32"
|
|
3352
|
+
},
|
|
3353
|
+
{
|
|
3354
|
+
name: "pendingReleaseBlockNumber",
|
|
3355
|
+
type: "uint32",
|
|
3356
|
+
internalType: "uint32"
|
|
3357
|
+
},
|
|
3358
|
+
{
|
|
3359
|
+
name: "status",
|
|
3360
|
+
type: "uint8",
|
|
3361
|
+
internalType: "enumIAppController.AppStatus"
|
|
3362
|
+
}
|
|
3363
|
+
]
|
|
3364
|
+
}
|
|
3365
|
+
],
|
|
3366
|
+
stateMutability: "view"
|
|
3367
|
+
},
|
|
3368
|
+
{
|
|
3369
|
+
type: "function",
|
|
3370
|
+
name: "getBillingAccount",
|
|
3371
|
+
inputs: [
|
|
3372
|
+
{
|
|
3373
|
+
name: "app",
|
|
3374
|
+
type: "address",
|
|
3375
|
+
internalType: "contractIApp"
|
|
3376
|
+
}
|
|
3377
|
+
],
|
|
3378
|
+
outputs: [
|
|
3379
|
+
{
|
|
3380
|
+
name: "",
|
|
3381
|
+
type: "address",
|
|
3382
|
+
internalType: "address"
|
|
3383
|
+
}
|
|
3384
|
+
],
|
|
3385
|
+
stateMutability: "view"
|
|
3386
|
+
},
|
|
3387
|
+
{
|
|
3388
|
+
type: "function",
|
|
3389
|
+
name: "getBillingType",
|
|
3390
|
+
inputs: [
|
|
3391
|
+
{
|
|
3392
|
+
name: "app",
|
|
3393
|
+
type: "address",
|
|
3394
|
+
internalType: "contractIApp"
|
|
3395
|
+
}
|
|
3396
|
+
],
|
|
3397
|
+
outputs: [
|
|
3398
|
+
{
|
|
3399
|
+
name: "",
|
|
3400
|
+
type: "uint8",
|
|
3401
|
+
internalType: "enumIAppController.BillingType"
|
|
3402
|
+
}
|
|
3403
|
+
],
|
|
3404
|
+
stateMutability: "view"
|
|
3405
|
+
},
|
|
3406
|
+
{
|
|
3407
|
+
type: "function",
|
|
3408
|
+
name: "getMaxActiveAppsPerUser",
|
|
3409
|
+
inputs: [
|
|
3410
|
+
{
|
|
3411
|
+
name: "user",
|
|
3412
|
+
type: "address",
|
|
3413
|
+
internalType: "address"
|
|
3414
|
+
}
|
|
3415
|
+
],
|
|
3416
|
+
outputs: [
|
|
3417
|
+
{
|
|
3418
|
+
name: "",
|
|
3419
|
+
type: "uint32",
|
|
3420
|
+
internalType: "uint32"
|
|
3421
|
+
}
|
|
3422
|
+
],
|
|
3423
|
+
stateMutability: "view"
|
|
3424
|
+
},
|
|
3425
|
+
{
|
|
3426
|
+
type: "function",
|
|
3427
|
+
name: "globalActiveAppCount",
|
|
3428
|
+
inputs: [],
|
|
3429
|
+
outputs: [
|
|
3430
|
+
{
|
|
3431
|
+
name: "",
|
|
3432
|
+
type: "uint32",
|
|
3433
|
+
internalType: "uint32"
|
|
3434
|
+
}
|
|
3435
|
+
],
|
|
3436
|
+
stateMutability: "view"
|
|
3437
|
+
},
|
|
3438
|
+
{
|
|
3439
|
+
type: "function",
|
|
3440
|
+
name: "initialize",
|
|
3441
|
+
inputs: [
|
|
3442
|
+
{
|
|
3443
|
+
name: "admin",
|
|
3444
|
+
type: "address",
|
|
3445
|
+
internalType: "address"
|
|
3446
|
+
}
|
|
3447
|
+
],
|
|
3448
|
+
outputs: [],
|
|
3449
|
+
stateMutability: "nonpayable"
|
|
3450
|
+
},
|
|
3451
|
+
{
|
|
3452
|
+
type: "function",
|
|
3453
|
+
name: "maxGlobalActiveApps",
|
|
3454
|
+
inputs: [],
|
|
3455
|
+
outputs: [
|
|
3456
|
+
{
|
|
3457
|
+
name: "",
|
|
3458
|
+
type: "uint32",
|
|
3459
|
+
internalType: "uint32"
|
|
3460
|
+
}
|
|
3461
|
+
],
|
|
3462
|
+
stateMutability: "view"
|
|
3463
|
+
},
|
|
3464
|
+
{
|
|
3465
|
+
type: "function",
|
|
3466
|
+
name: "permissionController",
|
|
3467
|
+
inputs: [],
|
|
3468
|
+
outputs: [
|
|
3469
|
+
{
|
|
3470
|
+
name: "",
|
|
3471
|
+
type: "address",
|
|
3472
|
+
internalType: "contractIPermissionController"
|
|
3473
|
+
}
|
|
3474
|
+
],
|
|
3475
|
+
stateMutability: "view"
|
|
3476
|
+
},
|
|
3477
|
+
{
|
|
3478
|
+
type: "function",
|
|
3479
|
+
name: "releaseManager",
|
|
3480
|
+
inputs: [],
|
|
3481
|
+
outputs: [
|
|
3482
|
+
{
|
|
3483
|
+
name: "",
|
|
3484
|
+
type: "address",
|
|
3485
|
+
internalType: "contractIReleaseManager"
|
|
3486
|
+
}
|
|
3487
|
+
],
|
|
3488
|
+
stateMutability: "view"
|
|
3489
|
+
},
|
|
3490
|
+
{
|
|
3491
|
+
type: "function",
|
|
3492
|
+
name: "setMaxActiveAppsPerUser",
|
|
3493
|
+
inputs: [
|
|
3494
|
+
{
|
|
3495
|
+
name: "user",
|
|
3496
|
+
type: "address",
|
|
3497
|
+
internalType: "address"
|
|
3498
|
+
},
|
|
3499
|
+
{
|
|
3500
|
+
name: "limit",
|
|
3501
|
+
type: "uint32",
|
|
3502
|
+
internalType: "uint32"
|
|
3503
|
+
}
|
|
3504
|
+
],
|
|
3505
|
+
outputs: [],
|
|
3506
|
+
stateMutability: "nonpayable"
|
|
3507
|
+
},
|
|
3508
|
+
{
|
|
3509
|
+
type: "function",
|
|
3510
|
+
name: "setMaxGlobalActiveApps",
|
|
3511
|
+
inputs: [
|
|
3512
|
+
{
|
|
3513
|
+
name: "limit",
|
|
3514
|
+
type: "uint32",
|
|
3515
|
+
internalType: "uint32"
|
|
3516
|
+
}
|
|
3517
|
+
],
|
|
3518
|
+
outputs: [],
|
|
3519
|
+
stateMutability: "nonpayable"
|
|
3520
|
+
},
|
|
3521
|
+
{
|
|
3522
|
+
type: "function",
|
|
3523
|
+
name: "startApp",
|
|
3524
|
+
inputs: [
|
|
3525
|
+
{
|
|
3526
|
+
name: "app",
|
|
3527
|
+
type: "address",
|
|
3528
|
+
internalType: "contractIApp"
|
|
3529
|
+
}
|
|
3530
|
+
],
|
|
3531
|
+
outputs: [],
|
|
3532
|
+
stateMutability: "nonpayable"
|
|
3533
|
+
},
|
|
3534
|
+
{
|
|
3535
|
+
type: "function",
|
|
3536
|
+
name: "stopApp",
|
|
3537
|
+
inputs: [
|
|
3538
|
+
{
|
|
3539
|
+
name: "app",
|
|
3540
|
+
type: "address",
|
|
3541
|
+
internalType: "contractIApp"
|
|
3542
|
+
}
|
|
3543
|
+
],
|
|
3544
|
+
outputs: [],
|
|
3545
|
+
stateMutability: "nonpayable"
|
|
3546
|
+
},
|
|
3547
|
+
{
|
|
3548
|
+
type: "function",
|
|
3549
|
+
name: "suspend",
|
|
3550
|
+
inputs: [
|
|
3551
|
+
{
|
|
3552
|
+
name: "account",
|
|
3553
|
+
type: "address",
|
|
3554
|
+
internalType: "address"
|
|
3555
|
+
},
|
|
3556
|
+
{
|
|
3557
|
+
name: "apps",
|
|
3558
|
+
type: "address[]",
|
|
3559
|
+
internalType: "contractIApp[]"
|
|
3560
|
+
}
|
|
3561
|
+
],
|
|
3562
|
+
outputs: [],
|
|
3563
|
+
stateMutability: "nonpayable"
|
|
3564
|
+
},
|
|
3565
|
+
{
|
|
3566
|
+
type: "function",
|
|
3567
|
+
name: "terminateApp",
|
|
3568
|
+
inputs: [
|
|
3569
|
+
{
|
|
3570
|
+
name: "app",
|
|
3571
|
+
type: "address",
|
|
3572
|
+
internalType: "contractIApp"
|
|
3573
|
+
}
|
|
3574
|
+
],
|
|
3575
|
+
outputs: [],
|
|
3576
|
+
stateMutability: "nonpayable"
|
|
3577
|
+
},
|
|
3578
|
+
{
|
|
3579
|
+
type: "function",
|
|
3580
|
+
name: "terminateAppByAdmin",
|
|
3581
|
+
inputs: [
|
|
3582
|
+
{
|
|
3583
|
+
name: "app",
|
|
3584
|
+
type: "address",
|
|
3585
|
+
internalType: "contractIApp"
|
|
3586
|
+
}
|
|
3587
|
+
],
|
|
3588
|
+
outputs: [],
|
|
3589
|
+
stateMutability: "nonpayable"
|
|
3590
|
+
},
|
|
3591
|
+
{
|
|
3592
|
+
type: "function",
|
|
3593
|
+
name: "updateAppMetadataURI",
|
|
3594
|
+
inputs: [
|
|
3595
|
+
{
|
|
3596
|
+
name: "app",
|
|
3597
|
+
type: "address",
|
|
3598
|
+
internalType: "contractIApp"
|
|
3599
|
+
},
|
|
3600
|
+
{
|
|
3601
|
+
name: "metadataURI",
|
|
3602
|
+
type: "string",
|
|
3603
|
+
internalType: "string"
|
|
3604
|
+
}
|
|
3605
|
+
],
|
|
3606
|
+
outputs: [],
|
|
3607
|
+
stateMutability: "nonpayable"
|
|
3608
|
+
},
|
|
3609
|
+
{
|
|
3610
|
+
type: "function",
|
|
3611
|
+
name: "upgradeApp",
|
|
3612
|
+
inputs: [
|
|
3613
|
+
{
|
|
3614
|
+
name: "app",
|
|
3615
|
+
type: "address",
|
|
3616
|
+
internalType: "contractIApp"
|
|
3617
|
+
},
|
|
3618
|
+
{
|
|
3619
|
+
name: "release",
|
|
3620
|
+
type: "tuple",
|
|
3621
|
+
internalType: "structIAppController.Release",
|
|
3622
|
+
components: [
|
|
3623
|
+
{
|
|
3624
|
+
name: "rmsRelease",
|
|
3625
|
+
type: "tuple",
|
|
3626
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
3627
|
+
components: [
|
|
3628
|
+
{
|
|
3629
|
+
name: "artifacts",
|
|
3630
|
+
type: "tuple[]",
|
|
3631
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
3632
|
+
components: [
|
|
3633
|
+
{
|
|
3634
|
+
name: "digest",
|
|
3635
|
+
type: "bytes32",
|
|
3636
|
+
internalType: "bytes32"
|
|
3637
|
+
},
|
|
3638
|
+
{
|
|
3639
|
+
name: "registry",
|
|
3640
|
+
type: "string",
|
|
3641
|
+
internalType: "string"
|
|
3642
|
+
}
|
|
3643
|
+
]
|
|
3644
|
+
},
|
|
3645
|
+
{
|
|
3646
|
+
name: "upgradeByTime",
|
|
3647
|
+
type: "uint32",
|
|
3648
|
+
internalType: "uint32"
|
|
3649
|
+
}
|
|
3650
|
+
]
|
|
3651
|
+
},
|
|
3652
|
+
{
|
|
3653
|
+
name: "publicEnv",
|
|
3654
|
+
type: "bytes",
|
|
3655
|
+
internalType: "bytes"
|
|
3656
|
+
},
|
|
3657
|
+
{
|
|
3658
|
+
name: "encryptedEnv",
|
|
3659
|
+
type: "bytes",
|
|
3660
|
+
internalType: "bytes"
|
|
3661
|
+
},
|
|
3662
|
+
{
|
|
3663
|
+
name: "containerPolicy",
|
|
3664
|
+
type: "tuple",
|
|
3665
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
3666
|
+
components: [
|
|
3667
|
+
{
|
|
3668
|
+
name: "args",
|
|
3669
|
+
type: "string[]",
|
|
3670
|
+
internalType: "string[]"
|
|
3671
|
+
},
|
|
3672
|
+
{
|
|
3673
|
+
name: "cmdOverride",
|
|
3674
|
+
type: "string[]",
|
|
3675
|
+
internalType: "string[]"
|
|
3676
|
+
},
|
|
3677
|
+
{
|
|
3678
|
+
name: "env",
|
|
3679
|
+
type: "tuple[]",
|
|
3680
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3681
|
+
components: [
|
|
3682
|
+
{
|
|
3683
|
+
name: "key",
|
|
3684
|
+
type: "string",
|
|
3685
|
+
internalType: "string"
|
|
3686
|
+
},
|
|
3687
|
+
{
|
|
3688
|
+
name: "value",
|
|
3689
|
+
type: "string",
|
|
3690
|
+
internalType: "string"
|
|
3691
|
+
}
|
|
3692
|
+
]
|
|
3693
|
+
},
|
|
3694
|
+
{
|
|
3695
|
+
name: "envOverride",
|
|
3696
|
+
type: "tuple[]",
|
|
3697
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3698
|
+
components: [
|
|
3699
|
+
{
|
|
3700
|
+
name: "key",
|
|
3701
|
+
type: "string",
|
|
3702
|
+
internalType: "string"
|
|
3703
|
+
},
|
|
3704
|
+
{
|
|
3705
|
+
name: "value",
|
|
3706
|
+
type: "string",
|
|
3707
|
+
internalType: "string"
|
|
3708
|
+
}
|
|
3709
|
+
]
|
|
3710
|
+
},
|
|
3711
|
+
{
|
|
3712
|
+
name: "restartPolicy",
|
|
3713
|
+
type: "string",
|
|
3714
|
+
internalType: "string"
|
|
3715
|
+
}
|
|
3716
|
+
]
|
|
3717
|
+
}
|
|
3718
|
+
]
|
|
3719
|
+
}
|
|
3720
|
+
],
|
|
3721
|
+
outputs: [
|
|
3722
|
+
{
|
|
3723
|
+
name: "",
|
|
3724
|
+
type: "uint256",
|
|
3725
|
+
internalType: "uint256"
|
|
3726
|
+
}
|
|
3727
|
+
],
|
|
3728
|
+
stateMutability: "nonpayable"
|
|
3729
|
+
},
|
|
3730
|
+
{
|
|
3731
|
+
type: "function",
|
|
3732
|
+
name: "version",
|
|
3733
|
+
inputs: [],
|
|
3734
|
+
outputs: [
|
|
3735
|
+
{
|
|
3736
|
+
name: "",
|
|
3737
|
+
type: "string",
|
|
3738
|
+
internalType: "string"
|
|
3739
|
+
}
|
|
3740
|
+
],
|
|
3741
|
+
stateMutability: "view"
|
|
3742
|
+
},
|
|
3743
|
+
{
|
|
3744
|
+
type: "event",
|
|
3745
|
+
name: "AppCreated",
|
|
3746
|
+
inputs: [
|
|
3747
|
+
{
|
|
3748
|
+
name: "creator",
|
|
3749
|
+
type: "address",
|
|
3750
|
+
indexed: true,
|
|
3751
|
+
internalType: "address"
|
|
3752
|
+
},
|
|
3753
|
+
{
|
|
3754
|
+
name: "app",
|
|
3755
|
+
type: "address",
|
|
3756
|
+
indexed: true,
|
|
3757
|
+
internalType: "contractIApp"
|
|
3758
|
+
},
|
|
3759
|
+
{
|
|
3760
|
+
name: "operatorSetId",
|
|
3761
|
+
type: "uint32",
|
|
3762
|
+
indexed: false,
|
|
3763
|
+
internalType: "uint32"
|
|
3764
|
+
}
|
|
3765
|
+
],
|
|
3766
|
+
anonymous: false
|
|
3767
|
+
},
|
|
3768
|
+
{
|
|
3769
|
+
type: "event",
|
|
3770
|
+
name: "AppMetadataURIUpdated",
|
|
3771
|
+
inputs: [
|
|
3772
|
+
{
|
|
3773
|
+
name: "app",
|
|
3774
|
+
type: "address",
|
|
3775
|
+
indexed: true,
|
|
3776
|
+
internalType: "contractIApp"
|
|
3777
|
+
},
|
|
3778
|
+
{
|
|
3779
|
+
name: "metadataURI",
|
|
3780
|
+
type: "string",
|
|
3781
|
+
indexed: false,
|
|
3782
|
+
internalType: "string"
|
|
3783
|
+
}
|
|
3784
|
+
],
|
|
3785
|
+
anonymous: false
|
|
3786
|
+
},
|
|
3787
|
+
{
|
|
3788
|
+
type: "event",
|
|
3789
|
+
name: "AppStarted",
|
|
3790
|
+
inputs: [
|
|
3791
|
+
{
|
|
3792
|
+
name: "app",
|
|
3793
|
+
type: "address",
|
|
3794
|
+
indexed: true,
|
|
3795
|
+
internalType: "contractIApp"
|
|
3796
|
+
}
|
|
3797
|
+
],
|
|
3798
|
+
anonymous: false
|
|
3799
|
+
},
|
|
3800
|
+
{
|
|
3801
|
+
type: "event",
|
|
3802
|
+
name: "AppStopped",
|
|
3803
|
+
inputs: [
|
|
3804
|
+
{
|
|
3805
|
+
name: "app",
|
|
3806
|
+
type: "address",
|
|
3807
|
+
indexed: true,
|
|
3808
|
+
internalType: "contractIApp"
|
|
3809
|
+
}
|
|
3810
|
+
],
|
|
3811
|
+
anonymous: false
|
|
3812
|
+
},
|
|
3813
|
+
{
|
|
3814
|
+
type: "event",
|
|
3815
|
+
name: "AppSuspended",
|
|
3816
|
+
inputs: [
|
|
3817
|
+
{
|
|
3818
|
+
name: "app",
|
|
3819
|
+
type: "address",
|
|
3820
|
+
indexed: true,
|
|
3821
|
+
internalType: "contractIApp"
|
|
3822
|
+
}
|
|
3823
|
+
],
|
|
3824
|
+
anonymous: false
|
|
3825
|
+
},
|
|
3826
|
+
{
|
|
3827
|
+
type: "event",
|
|
3828
|
+
name: "AppTerminated",
|
|
3829
|
+
inputs: [
|
|
3830
|
+
{
|
|
3831
|
+
name: "app",
|
|
3832
|
+
type: "address",
|
|
3833
|
+
indexed: true,
|
|
3834
|
+
internalType: "contractIApp"
|
|
3835
|
+
}
|
|
3836
|
+
],
|
|
3837
|
+
anonymous: false
|
|
3838
|
+
},
|
|
3839
|
+
{
|
|
3840
|
+
type: "event",
|
|
3841
|
+
name: "AppTerminatedByAdmin",
|
|
3842
|
+
inputs: [
|
|
3843
|
+
{
|
|
3844
|
+
name: "app",
|
|
3845
|
+
type: "address",
|
|
3846
|
+
indexed: true,
|
|
3847
|
+
internalType: "contractIApp"
|
|
3848
|
+
}
|
|
3849
|
+
],
|
|
3850
|
+
anonymous: false
|
|
3851
|
+
},
|
|
3852
|
+
{
|
|
3853
|
+
type: "event",
|
|
3854
|
+
name: "AppUpgraded",
|
|
3855
|
+
inputs: [
|
|
3856
|
+
{
|
|
3857
|
+
name: "app",
|
|
3858
|
+
type: "address",
|
|
3859
|
+
indexed: true,
|
|
3860
|
+
internalType: "contractIApp"
|
|
3861
|
+
},
|
|
3862
|
+
{
|
|
3863
|
+
name: "rmsReleaseId",
|
|
3864
|
+
type: "uint256",
|
|
3865
|
+
indexed: false,
|
|
3866
|
+
internalType: "uint256"
|
|
3867
|
+
},
|
|
3868
|
+
{
|
|
3869
|
+
name: "release",
|
|
3870
|
+
type: "tuple",
|
|
3871
|
+
indexed: false,
|
|
3872
|
+
internalType: "structIAppController.Release",
|
|
3873
|
+
components: [
|
|
3874
|
+
{
|
|
3875
|
+
name: "rmsRelease",
|
|
3876
|
+
type: "tuple",
|
|
3877
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
3878
|
+
components: [
|
|
3879
|
+
{
|
|
3880
|
+
name: "artifacts",
|
|
3881
|
+
type: "tuple[]",
|
|
3882
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
3883
|
+
components: [
|
|
3884
|
+
{
|
|
3885
|
+
name: "digest",
|
|
3886
|
+
type: "bytes32",
|
|
3887
|
+
internalType: "bytes32"
|
|
3888
|
+
},
|
|
3889
|
+
{
|
|
3890
|
+
name: "registry",
|
|
3891
|
+
type: "string",
|
|
3892
|
+
internalType: "string"
|
|
3893
|
+
}
|
|
3894
|
+
]
|
|
3895
|
+
},
|
|
3896
|
+
{
|
|
3897
|
+
name: "upgradeByTime",
|
|
3898
|
+
type: "uint32",
|
|
3899
|
+
internalType: "uint32"
|
|
3900
|
+
}
|
|
3901
|
+
]
|
|
3902
|
+
},
|
|
3903
|
+
{
|
|
3904
|
+
name: "publicEnv",
|
|
3905
|
+
type: "bytes",
|
|
3906
|
+
internalType: "bytes"
|
|
3907
|
+
},
|
|
3908
|
+
{
|
|
3909
|
+
name: "encryptedEnv",
|
|
3910
|
+
type: "bytes",
|
|
3911
|
+
internalType: "bytes"
|
|
3912
|
+
},
|
|
3913
|
+
{
|
|
3914
|
+
name: "containerPolicy",
|
|
3915
|
+
type: "tuple",
|
|
3916
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
3917
|
+
components: [
|
|
3918
|
+
{
|
|
3919
|
+
name: "args",
|
|
3920
|
+
type: "string[]",
|
|
3921
|
+
internalType: "string[]"
|
|
3922
|
+
},
|
|
3923
|
+
{
|
|
3924
|
+
name: "cmdOverride",
|
|
3925
|
+
type: "string[]",
|
|
3926
|
+
internalType: "string[]"
|
|
3927
|
+
},
|
|
3928
|
+
{
|
|
3929
|
+
name: "env",
|
|
3930
|
+
type: "tuple[]",
|
|
3931
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3932
|
+
components: [
|
|
3933
|
+
{
|
|
3934
|
+
name: "key",
|
|
3935
|
+
type: "string",
|
|
3936
|
+
internalType: "string"
|
|
3937
|
+
},
|
|
3938
|
+
{
|
|
3939
|
+
name: "value",
|
|
3940
|
+
type: "string",
|
|
3941
|
+
internalType: "string"
|
|
3942
|
+
}
|
|
3943
|
+
]
|
|
3944
|
+
},
|
|
3945
|
+
{
|
|
3946
|
+
name: "envOverride",
|
|
3947
|
+
type: "tuple[]",
|
|
3948
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3949
|
+
components: [
|
|
3950
|
+
{
|
|
3951
|
+
name: "key",
|
|
3952
|
+
type: "string",
|
|
3953
|
+
internalType: "string"
|
|
3954
|
+
},
|
|
3955
|
+
{
|
|
3956
|
+
name: "value",
|
|
3957
|
+
type: "string",
|
|
3958
|
+
internalType: "string"
|
|
3959
|
+
}
|
|
3960
|
+
]
|
|
3961
|
+
},
|
|
3962
|
+
{
|
|
3963
|
+
name: "restartPolicy",
|
|
3964
|
+
type: "string",
|
|
3965
|
+
internalType: "string"
|
|
3966
|
+
}
|
|
3967
|
+
]
|
|
3968
|
+
}
|
|
3969
|
+
]
|
|
3970
|
+
}
|
|
3971
|
+
],
|
|
3972
|
+
anonymous: false
|
|
3973
|
+
},
|
|
3974
|
+
{
|
|
3975
|
+
type: "event",
|
|
3976
|
+
name: "GlobalMaxActiveAppsSet",
|
|
3977
|
+
inputs: [
|
|
3978
|
+
{
|
|
3979
|
+
name: "limit",
|
|
3980
|
+
type: "uint32",
|
|
3981
|
+
indexed: false,
|
|
3982
|
+
internalType: "uint32"
|
|
3983
|
+
}
|
|
3984
|
+
],
|
|
3985
|
+
anonymous: false
|
|
3986
|
+
},
|
|
3987
|
+
{
|
|
3988
|
+
type: "event",
|
|
3989
|
+
name: "Initialized",
|
|
3990
|
+
inputs: [
|
|
3991
|
+
{
|
|
3992
|
+
name: "version",
|
|
3993
|
+
type: "uint8",
|
|
3994
|
+
indexed: false,
|
|
3995
|
+
internalType: "uint8"
|
|
3996
|
+
}
|
|
3997
|
+
],
|
|
3998
|
+
anonymous: false
|
|
3999
|
+
},
|
|
4000
|
+
{
|
|
4001
|
+
type: "event",
|
|
4002
|
+
name: "MaxActiveAppsSet",
|
|
4003
|
+
inputs: [
|
|
4004
|
+
{
|
|
4005
|
+
name: "user",
|
|
4006
|
+
type: "address",
|
|
4007
|
+
indexed: true,
|
|
4008
|
+
internalType: "address"
|
|
4009
|
+
},
|
|
4010
|
+
{
|
|
4011
|
+
name: "limit",
|
|
4012
|
+
type: "uint32",
|
|
4013
|
+
indexed: false,
|
|
4014
|
+
internalType: "uint32"
|
|
4015
|
+
}
|
|
4016
|
+
],
|
|
4017
|
+
anonymous: false
|
|
4018
|
+
},
|
|
4019
|
+
{
|
|
4020
|
+
type: "event",
|
|
4021
|
+
name: "UpgradeConfirmed",
|
|
4022
|
+
inputs: [
|
|
4023
|
+
{
|
|
4024
|
+
name: "app",
|
|
4025
|
+
type: "address",
|
|
4026
|
+
indexed: true,
|
|
4027
|
+
internalType: "contractIApp"
|
|
4028
|
+
},
|
|
4029
|
+
{
|
|
4030
|
+
name: "pendingReleaseBlockNumber",
|
|
4031
|
+
type: "uint32",
|
|
4032
|
+
indexed: false,
|
|
4033
|
+
internalType: "uint32"
|
|
4034
|
+
}
|
|
4035
|
+
],
|
|
4036
|
+
anonymous: false
|
|
4037
|
+
},
|
|
4038
|
+
{
|
|
4039
|
+
type: "error",
|
|
4040
|
+
name: "AccountHasActiveApps",
|
|
4041
|
+
inputs: []
|
|
4042
|
+
},
|
|
4043
|
+
{
|
|
4044
|
+
type: "error",
|
|
4045
|
+
name: "AppAlreadyExists",
|
|
4046
|
+
inputs: []
|
|
4047
|
+
},
|
|
4048
|
+
{
|
|
4049
|
+
type: "error",
|
|
4050
|
+
name: "AppDoesNotExist",
|
|
4051
|
+
inputs: []
|
|
4052
|
+
},
|
|
4053
|
+
{
|
|
4054
|
+
type: "error",
|
|
4055
|
+
name: "GlobalMaxActiveAppsExceeded",
|
|
4056
|
+
inputs: []
|
|
4057
|
+
},
|
|
4058
|
+
{
|
|
4059
|
+
type: "error",
|
|
4060
|
+
name: "InvalidAppStatus",
|
|
4061
|
+
inputs: []
|
|
4062
|
+
},
|
|
4063
|
+
{
|
|
4064
|
+
type: "error",
|
|
4065
|
+
name: "InvalidPermissions",
|
|
4066
|
+
inputs: []
|
|
4067
|
+
},
|
|
4068
|
+
{
|
|
4069
|
+
type: "error",
|
|
4070
|
+
name: "InvalidReleaseMetadataURI",
|
|
4071
|
+
inputs: []
|
|
4072
|
+
},
|
|
4073
|
+
{
|
|
4074
|
+
type: "error",
|
|
4075
|
+
name: "InvalidShortString",
|
|
4076
|
+
inputs: []
|
|
4077
|
+
},
|
|
4078
|
+
{
|
|
4079
|
+
type: "error",
|
|
4080
|
+
name: "InvalidSignature",
|
|
4081
|
+
inputs: []
|
|
4082
|
+
},
|
|
4083
|
+
{
|
|
4084
|
+
type: "error",
|
|
4085
|
+
name: "MaxActiveAppsExceeded",
|
|
4086
|
+
inputs: []
|
|
4087
|
+
},
|
|
4088
|
+
{
|
|
4089
|
+
type: "error",
|
|
4090
|
+
name: "MoreThanOneArtifact",
|
|
4091
|
+
inputs: []
|
|
4092
|
+
},
|
|
4093
|
+
{
|
|
4094
|
+
type: "error",
|
|
4095
|
+
name: "NoPendingUpgrade",
|
|
4096
|
+
inputs: []
|
|
4097
|
+
},
|
|
4098
|
+
{
|
|
4099
|
+
type: "error",
|
|
4100
|
+
name: "SignatureExpired",
|
|
4101
|
+
inputs: []
|
|
4102
|
+
},
|
|
4103
|
+
{
|
|
4104
|
+
type: "error",
|
|
4105
|
+
name: "StringTooLong",
|
|
4106
|
+
inputs: [
|
|
4107
|
+
{
|
|
4108
|
+
name: "str",
|
|
4109
|
+
type: "string",
|
|
4110
|
+
internalType: "string"
|
|
4111
|
+
}
|
|
4112
|
+
]
|
|
3019
4113
|
}
|
|
3020
|
-
|
|
3021
|
-
}
|
|
3022
|
-
|
|
3023
|
-
// src/client/common/contract/caller.ts
|
|
3024
|
-
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
3025
|
-
|
|
3026
|
-
// src/client/common/utils/helpers.ts
|
|
3027
|
-
import { extractChain, createPublicClient, createWalletClient, http, fallback } from "viem";
|
|
3028
|
-
import { sepolia as sepolia2 } from "viem/chains";
|
|
3029
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
3030
|
-
function getChainFromID(chainID, fallback2 = sepolia2) {
|
|
3031
|
-
const id = Number(chainID);
|
|
3032
|
-
return extractChain({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
3033
|
-
}
|
|
3034
|
-
function addHexPrefix(value) {
|
|
3035
|
-
return value.startsWith("0x") ? value : `0x${value}`;
|
|
3036
|
-
}
|
|
3037
|
-
function stripHexPrefix(value) {
|
|
3038
|
-
return value.startsWith("0x") ? value.slice(2) : value;
|
|
3039
|
-
}
|
|
4114
|
+
];
|
|
3040
4115
|
|
|
3041
|
-
// src/client/common/abis/AppController.json
|
|
3042
|
-
var
|
|
4116
|
+
// src/client/common/abis/AppController.v1_4.json
|
|
4117
|
+
var AppController_v1_4_default = [
|
|
3043
4118
|
{
|
|
3044
4119
|
type: "constructor",
|
|
3045
4120
|
inputs: [
|
|
@@ -4723,6 +5798,38 @@ var PermissionController_default = [
|
|
|
4723
5798
|
];
|
|
4724
5799
|
|
|
4725
5800
|
// src/client/common/contract/caller.ts
|
|
5801
|
+
function appControllerAbiFor(environmentConfig) {
|
|
5802
|
+
return environmentConfig.releaseAbiVersion === "v1.4" ? AppController_v1_4_default : AppController_default;
|
|
5803
|
+
}
|
|
5804
|
+
function supportsContainerPolicy(environmentConfig) {
|
|
5805
|
+
return environmentConfig.releaseAbiVersion !== "v1.4";
|
|
5806
|
+
}
|
|
5807
|
+
function containerPolicyForViem(policy = EMPTY_CONTAINER_POLICY) {
|
|
5808
|
+
return {
|
|
5809
|
+
args: policy.args,
|
|
5810
|
+
cmdOverride: policy.cmdOverride,
|
|
5811
|
+
env: policy.env.map((e) => ({ key: e.key, value: e.value })),
|
|
5812
|
+
envOverride: policy.envOverride.map((e) => ({ key: e.key, value: e.value })),
|
|
5813
|
+
restartPolicy: policy.restartPolicy
|
|
5814
|
+
};
|
|
5815
|
+
}
|
|
5816
|
+
function releaseForViem(release, environmentConfig) {
|
|
5817
|
+
const base = {
|
|
5818
|
+
rmsRelease: {
|
|
5819
|
+
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
5820
|
+
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
5821
|
+
registry: artifact.registry
|
|
5822
|
+
})),
|
|
5823
|
+
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
5824
|
+
},
|
|
5825
|
+
publicEnv: bytesToHex(release.publicEnv),
|
|
5826
|
+
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
5827
|
+
};
|
|
5828
|
+
if (!supportsContainerPolicy(environmentConfig)) {
|
|
5829
|
+
return base;
|
|
5830
|
+
}
|
|
5831
|
+
return { ...base, containerPolicy: containerPolicyForViem(release.containerPolicy) };
|
|
5832
|
+
}
|
|
4726
5833
|
function formatETH(wei) {
|
|
4727
5834
|
const eth = Number(wei) / 1e18;
|
|
4728
5835
|
const costStr = eth.toFixed(6);
|
|
@@ -4739,7 +5846,7 @@ async function calculateAppID(options) {
|
|
|
4739
5846
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4740
5847
|
const appID = await publicClient.readContract({
|
|
4741
5848
|
address: environmentConfig.appControllerAddress,
|
|
4742
|
-
abi:
|
|
5849
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4743
5850
|
functionName: "calculateAppId",
|
|
4744
5851
|
args: [ownerAddress, saltHex]
|
|
4745
5852
|
});
|
|
@@ -4763,22 +5870,12 @@ async function prepareDeployBatch(options, logger = noopLogger) {
|
|
|
4763
5870
|
const saltHexString = bytesToHex(salt).slice(2);
|
|
4764
5871
|
const paddedSaltHex = saltHexString.padStart(64, "0");
|
|
4765
5872
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4766
|
-
const
|
|
4767
|
-
rmsRelease: {
|
|
4768
|
-
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4769
|
-
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4770
|
-
registry: artifact.registry
|
|
4771
|
-
})),
|
|
4772
|
-
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4773
|
-
},
|
|
4774
|
-
publicEnv: bytesToHex(release.publicEnv),
|
|
4775
|
-
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
4776
|
-
};
|
|
5873
|
+
const release_ = releaseForViem(release, environmentConfig);
|
|
4777
5874
|
const functionName = options.billTo === "app" ? "createAppWithIsolatedBilling" : "createApp";
|
|
4778
5875
|
const createData = encodeFunctionData2({
|
|
4779
|
-
abi:
|
|
5876
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4780
5877
|
functionName,
|
|
4781
|
-
args: [saltHex,
|
|
5878
|
+
args: [saltHex, release_]
|
|
4782
5879
|
});
|
|
4783
5880
|
const acceptAdminData = encodeFunctionData2({
|
|
4784
5881
|
abi: PermissionController_default,
|
|
@@ -4866,21 +5963,11 @@ async function prepareUpgradeBatch(options) {
|
|
|
4866
5963
|
publicLogs,
|
|
4867
5964
|
needsPermissionChange
|
|
4868
5965
|
} = options;
|
|
4869
|
-
const
|
|
4870
|
-
rmsRelease: {
|
|
4871
|
-
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4872
|
-
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4873
|
-
registry: artifact.registry
|
|
4874
|
-
})),
|
|
4875
|
-
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4876
|
-
},
|
|
4877
|
-
publicEnv: bytesToHex(release.publicEnv),
|
|
4878
|
-
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
4879
|
-
};
|
|
5966
|
+
const release_ = releaseForViem(release, environmentConfig);
|
|
4880
5967
|
const upgradeData = encodeFunctionData2({
|
|
4881
|
-
abi:
|
|
5968
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4882
5969
|
functionName: "upgradeApp",
|
|
4883
|
-
args: [appID,
|
|
5970
|
+
args: [appID, release_]
|
|
4884
5971
|
});
|
|
4885
5972
|
const executions = [
|
|
4886
5973
|
{
|
|
@@ -5014,7 +6101,7 @@ ${pendingMessage}`);
|
|
|
5014
6101
|
if (callError.data) {
|
|
5015
6102
|
try {
|
|
5016
6103
|
const decoded = decodeErrorResult2({
|
|
5017
|
-
abi:
|
|
6104
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5018
6105
|
data: callError.data
|
|
5019
6106
|
});
|
|
5020
6107
|
const formattedError = formatAppControllerError(decoded);
|
|
@@ -5067,7 +6154,7 @@ function formatAppControllerError(decoded) {
|
|
|
5067
6154
|
async function getActiveAppCount(publicClient, environmentConfig, user) {
|
|
5068
6155
|
const count = await publicClient.readContract({
|
|
5069
6156
|
address: environmentConfig.appControllerAddress,
|
|
5070
|
-
abi:
|
|
6157
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5071
6158
|
functionName: "getActiveAppCount",
|
|
5072
6159
|
args: [user]
|
|
5073
6160
|
});
|
|
@@ -5076,7 +6163,7 @@ async function getActiveAppCount(publicClient, environmentConfig, user) {
|
|
|
5076
6163
|
async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
|
|
5077
6164
|
const quota = await publicClient.readContract({
|
|
5078
6165
|
address: environmentConfig.appControllerAddress,
|
|
5079
|
-
abi:
|
|
6166
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5080
6167
|
functionName: "getMaxActiveAppsPerUser",
|
|
5081
6168
|
args: [user]
|
|
5082
6169
|
});
|
|
@@ -5085,7 +6172,7 @@ async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
|
|
|
5085
6172
|
async function getBillingType(publicClient, environmentConfig, app) {
|
|
5086
6173
|
const result = await publicClient.readContract({
|
|
5087
6174
|
address: environmentConfig.appControllerAddress,
|
|
5088
|
-
abi:
|
|
6175
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5089
6176
|
functionName: "getBillingType",
|
|
5090
6177
|
args: [app]
|
|
5091
6178
|
});
|
|
@@ -5094,7 +6181,7 @@ async function getBillingType(publicClient, environmentConfig, app) {
|
|
|
5094
6181
|
async function getAppsByBillingAccount(publicClient, environmentConfig, account, offset, limit) {
|
|
5095
6182
|
const result = await publicClient.readContract({
|
|
5096
6183
|
address: environmentConfig.appControllerAddress,
|
|
5097
|
-
abi:
|
|
6184
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5098
6185
|
functionName: "getAppsByBillingAccount",
|
|
5099
6186
|
args: [account, offset, limit]
|
|
5100
6187
|
});
|
|
@@ -5148,6 +6235,35 @@ async function undelegate(options, logger = noopLogger) {
|
|
|
5148
6235
|
return hash;
|
|
5149
6236
|
}
|
|
5150
6237
|
|
|
6238
|
+
// src/client/common/gas/insufficientGas.ts
|
|
6239
|
+
import { formatEther } from "viem";
|
|
6240
|
+
var InsufficientGasError = class extends Error {
|
|
6241
|
+
constructor(args) {
|
|
6242
|
+
const requiredEth = formatEther(args.requiredWei);
|
|
6243
|
+
const availableEth = formatEther(args.availableWei);
|
|
6244
|
+
super(
|
|
6245
|
+
`Insufficient ETH for gas: wallet ${args.address} has ${availableEth} ETH but this transaction needs ~${requiredEth} ETH.
|
|
6246
|
+
Compute credits do not pay on-chain gas \u2014 fund the wallet with ETH and retry.`
|
|
6247
|
+
);
|
|
6248
|
+
this.name = "InsufficientGasError";
|
|
6249
|
+
this.address = args.address;
|
|
6250
|
+
this.requiredWei = args.requiredWei;
|
|
6251
|
+
this.availableWei = args.availableWei;
|
|
6252
|
+
this.requiredEth = requiredEth;
|
|
6253
|
+
this.availableEth = availableEth;
|
|
6254
|
+
}
|
|
6255
|
+
};
|
|
6256
|
+
async function assertSufficientGas(args) {
|
|
6257
|
+
const availableWei = await args.publicClient.getBalance({ address: args.address });
|
|
6258
|
+
if (availableWei < args.gasEstimate.maxCostWei) {
|
|
6259
|
+
throw new InsufficientGasError({
|
|
6260
|
+
address: args.address,
|
|
6261
|
+
requiredWei: args.gasEstimate.maxCostWei,
|
|
6262
|
+
availableWei
|
|
6263
|
+
});
|
|
6264
|
+
}
|
|
6265
|
+
}
|
|
6266
|
+
|
|
5151
6267
|
// src/client/common/utils/userapi.ts
|
|
5152
6268
|
import axios2 from "axios";
|
|
5153
6269
|
|
|
@@ -5174,43 +6290,13 @@ async function calculatePermissionSignature(options) {
|
|
|
5174
6290
|
});
|
|
5175
6291
|
return { signature, digest };
|
|
5176
6292
|
}
|
|
5177
|
-
var generateBillingSigData = (product, expiry) => {
|
|
5178
|
-
return {
|
|
5179
|
-
domain: {
|
|
5180
|
-
name: "EigenCloud Billing API",
|
|
5181
|
-
version: "1"
|
|
5182
|
-
},
|
|
5183
|
-
types: {
|
|
5184
|
-
BillingAuth: [
|
|
5185
|
-
{ name: "product", type: "string" },
|
|
5186
|
-
{ name: "expiry", type: "uint256" }
|
|
5187
|
-
]
|
|
5188
|
-
},
|
|
5189
|
-
primaryType: "BillingAuth",
|
|
5190
|
-
message: {
|
|
5191
|
-
product,
|
|
5192
|
-
expiry
|
|
5193
|
-
}
|
|
5194
|
-
};
|
|
5195
|
-
};
|
|
5196
|
-
async function calculateBillingAuthSignature(options) {
|
|
5197
|
-
const { walletClient, product, expiry } = options;
|
|
5198
|
-
const account = walletClient.account;
|
|
5199
|
-
if (!account) {
|
|
5200
|
-
throw new Error("WalletClient must have an account attached");
|
|
5201
|
-
}
|
|
5202
|
-
const signature = await walletClient.signTypedData({
|
|
5203
|
-
account,
|
|
5204
|
-
...generateBillingSigData(product, expiry)
|
|
5205
|
-
});
|
|
5206
|
-
return { signature, expiry };
|
|
5207
|
-
}
|
|
5208
6293
|
|
|
5209
6294
|
// src/client/common/utils/retry.ts
|
|
5210
6295
|
import axios from "axios";
|
|
5211
6296
|
var MAX_RETRIES = 5;
|
|
5212
6297
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
5213
6298
|
var MAX_BACKOFF_MS = 3e4;
|
|
6299
|
+
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
|
|
5214
6300
|
function sleep(ms) {
|
|
5215
6301
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
5216
6302
|
}
|
|
@@ -5230,7 +6316,7 @@ async function requestWithRetry(config) {
|
|
|
5230
6316
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
5231
6317
|
const res = await axios({ ...config, validateStatus: () => true });
|
|
5232
6318
|
lastResponse = res;
|
|
5233
|
-
if (res.status
|
|
6319
|
+
if (!RETRYABLE_STATUSES.has(res.status)) {
|
|
5234
6320
|
return res;
|
|
5235
6321
|
}
|
|
5236
6322
|
if (attempt < MAX_RETRIES) {
|
|
@@ -5259,7 +6345,7 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
|
5259
6345
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
5260
6346
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
5261
6347
|
function getDefaultClientId() {
|
|
5262
|
-
const version = true ? "1.0.0
|
|
6348
|
+
const version = true ? "1.0.0" : "0.0.0";
|
|
5263
6349
|
return `ecloud-sdk/v${version}`;
|
|
5264
6350
|
}
|
|
5265
6351
|
var UserApiClient = class {
|
|
@@ -5294,7 +6380,6 @@ var UserApiClient = class {
|
|
|
5294
6380
|
status: app.app_status,
|
|
5295
6381
|
ip: app.ip,
|
|
5296
6382
|
machineType: app.machine_type,
|
|
5297
|
-
hostname: app.hostname,
|
|
5298
6383
|
profile: app.profile,
|
|
5299
6384
|
metrics: app.metrics,
|
|
5300
6385
|
evmAddresses,
|
|
@@ -5360,28 +6445,6 @@ var UserApiClient = class {
|
|
|
5360
6445
|
status: app.app_status || app.App_Status || ""
|
|
5361
6446
|
}));
|
|
5362
6447
|
}
|
|
5363
|
-
/**
|
|
5364
|
-
* Get deployments for an app from the gRPC-gateway endpoint.
|
|
5365
|
-
* Returns deployment records including upgrade_phase for tracking upgrade progress.
|
|
5366
|
-
*
|
|
5367
|
-
* Endpoint: GET /v1/apps/:appAddress/deployments
|
|
5368
|
-
*/
|
|
5369
|
-
async getDeployments(appAddress) {
|
|
5370
|
-
const endpoint = `${this.config.userApiServerURL}/v1/apps/${appAddress}/deployments`;
|
|
5371
|
-
const response = await this.makeEIP712AuthenticatedRequest(endpoint);
|
|
5372
|
-
const result = await response.json();
|
|
5373
|
-
const deployments = result.deployments || [];
|
|
5374
|
-
return deployments.map((dep) => ({
|
|
5375
|
-
id: dep.id || "",
|
|
5376
|
-
externalId: dep.external_id || dep.externalId || "",
|
|
5377
|
-
endpoint: dep.endpoint || "",
|
|
5378
|
-
releaseId: dep.release_id || dep.releaseId || "",
|
|
5379
|
-
upgradePhase: dep.upgrade_phase || dep.upgradePhase || "",
|
|
5380
|
-
replacesDeploymentId: dep.replaces_deployment_id || dep.replacesDeploymentId || "",
|
|
5381
|
-
createdAt: dep.created_at || dep.createdAt || "",
|
|
5382
|
-
updatedAt: dep.updated_at || dep.updatedAt || ""
|
|
5383
|
-
}));
|
|
5384
|
-
}
|
|
5385
6448
|
/**
|
|
5386
6449
|
* Upload app profile information with optional image
|
|
5387
6450
|
*
|
|
@@ -5515,48 +6578,6 @@ Please check:
|
|
|
5515
6578
|
"X-eigenx-expiry": expiry.toString()
|
|
5516
6579
|
};
|
|
5517
6580
|
}
|
|
5518
|
-
/**
|
|
5519
|
-
* Make an EIP-712 authenticated request to the gRPC-gateway endpoints.
|
|
5520
|
-
* Uses the billing/compute auth pattern: Authorization + X-Account + X-Expiry headers.
|
|
5521
|
-
*/
|
|
5522
|
-
async makeEIP712AuthenticatedRequest(url) {
|
|
5523
|
-
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
5524
|
-
const { signature } = await calculateBillingAuthSignature({
|
|
5525
|
-
walletClient: this.walletClient,
|
|
5526
|
-
product: "compute",
|
|
5527
|
-
expiry
|
|
5528
|
-
});
|
|
5529
|
-
const headers = {
|
|
5530
|
-
Authorization: `Bearer ${signature}`,
|
|
5531
|
-
"X-Account": this.address,
|
|
5532
|
-
"X-Expiry": expiry.toString(),
|
|
5533
|
-
"x-client-id": this.clientId
|
|
5534
|
-
};
|
|
5535
|
-
try {
|
|
5536
|
-
const response = await requestWithRetry({
|
|
5537
|
-
method: "GET",
|
|
5538
|
-
url,
|
|
5539
|
-
headers,
|
|
5540
|
-
maxRedirects: 0,
|
|
5541
|
-
withCredentials: true
|
|
5542
|
-
});
|
|
5543
|
-
const status = response.status;
|
|
5544
|
-
if (status < 200 || status >= 300) {
|
|
5545
|
-
const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
5546
|
-
throw new Error(`gRPC-gateway request failed: ${status} - ${body}`);
|
|
5547
|
-
}
|
|
5548
|
-
return {
|
|
5549
|
-
json: async () => response.data,
|
|
5550
|
-
text: async () => typeof response.data === "string" ? response.data : JSON.stringify(response.data)
|
|
5551
|
-
};
|
|
5552
|
-
} catch (error) {
|
|
5553
|
-
if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
|
|
5554
|
-
const cause = error.cause?.message || error.cause || error.message;
|
|
5555
|
-
throw new Error(`Failed to connect to API at ${url}: ${cause}`);
|
|
5556
|
-
}
|
|
5557
|
-
throw error;
|
|
5558
|
-
}
|
|
5559
|
-
}
|
|
5560
6581
|
// ==========================================================================
|
|
5561
6582
|
// SIWE Session Management
|
|
5562
6583
|
// ==========================================================================
|
|
@@ -5662,8 +6683,36 @@ function transformAppRelease(raw) {
|
|
|
5662
6683
|
|
|
5663
6684
|
// src/client/common/contract/watcher.ts
|
|
5664
6685
|
var WATCH_POLL_INTERVAL_SECONDS = 5;
|
|
6686
|
+
var WATCH_HEARTBEAT_INTERVAL_SECONDS = 30;
|
|
6687
|
+
var WATCH_DEFAULT_TIMEOUT_SECONDS = 10 * 60;
|
|
5665
6688
|
var APP_STATUS_RUNNING = "Running";
|
|
5666
6689
|
var APP_STATUS_FAILED = "Failed";
|
|
6690
|
+
var WatchTimeoutError = class extends Error {
|
|
6691
|
+
constructor(args) {
|
|
6692
|
+
super(
|
|
6693
|
+
args.message ?? `Timed out after ${args.elapsedSeconds}s waiting for app ${args.appId} (last status: ${args.lastStatus ?? "unknown"})`
|
|
6694
|
+
);
|
|
6695
|
+
this.name = "WatchTimeoutError";
|
|
6696
|
+
this.appId = args.appId;
|
|
6697
|
+
this.elapsedSeconds = args.elapsedSeconds;
|
|
6698
|
+
this.lastStatus = args.lastStatus;
|
|
6699
|
+
this.timeoutSeconds = args.timeoutSeconds;
|
|
6700
|
+
}
|
|
6701
|
+
};
|
|
6702
|
+
function resolveWatchTimeoutSeconds(explicit) {
|
|
6703
|
+
if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0) {
|
|
6704
|
+
return Math.floor(explicit);
|
|
6705
|
+
}
|
|
6706
|
+
const raw = process.env.ECLOUD_WATCH_TIMEOUT_SECONDS;
|
|
6707
|
+
if (raw === void 0 || raw === "") {
|
|
6708
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
6709
|
+
}
|
|
6710
|
+
const parsed = Number(raw);
|
|
6711
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
6712
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
6713
|
+
}
|
|
6714
|
+
return Math.floor(parsed);
|
|
6715
|
+
}
|
|
5667
6716
|
async function watchUntilRunning(options, logger) {
|
|
5668
6717
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
5669
6718
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
@@ -5694,8 +6743,20 @@ async function watchUntilRunning(options, logger) {
|
|
|
5694
6743
|
return false;
|
|
5695
6744
|
};
|
|
5696
6745
|
const startTime = Date.now();
|
|
6746
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
5697
6747
|
let lastLoggedStatus;
|
|
6748
|
+
let lastHeartbeatAt = startTime;
|
|
5698
6749
|
while (true) {
|
|
6750
|
+
const elapsedMs = Date.now() - startTime;
|
|
6751
|
+
const elapsed = Math.round(elapsedMs / 1e3);
|
|
6752
|
+
if (elapsed >= timeoutSeconds) {
|
|
6753
|
+
throw new WatchTimeoutError({
|
|
6754
|
+
appId,
|
|
6755
|
+
elapsedSeconds: elapsed,
|
|
6756
|
+
lastStatus: lastLoggedStatus,
|
|
6757
|
+
timeoutSeconds
|
|
6758
|
+
});
|
|
6759
|
+
}
|
|
5699
6760
|
try {
|
|
5700
6761
|
const info = await userApiClient.getInfos([appId], 1);
|
|
5701
6762
|
if (info.length === 0) {
|
|
@@ -5705,62 +6766,35 @@ async function watchUntilRunning(options, logger) {
|
|
|
5705
6766
|
const appInfo = info[0];
|
|
5706
6767
|
const currentStatus = appInfo.status;
|
|
5707
6768
|
const currentIP = appInfo.ip || "";
|
|
5708
|
-
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5709
6769
|
if (currentStatus !== lastLoggedStatus) {
|
|
5710
6770
|
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
5711
6771
|
lastLoggedStatus = currentStatus;
|
|
6772
|
+
lastHeartbeatAt = Date.now();
|
|
6773
|
+
} else if (Date.now() - lastHeartbeatAt >= WATCH_HEARTBEAT_INTERVAL_SECONDS * 1e3) {
|
|
6774
|
+
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
6775
|
+
lastHeartbeatAt = Date.now();
|
|
5712
6776
|
}
|
|
5713
6777
|
if (stopCondition(currentStatus, currentIP)) {
|
|
5714
6778
|
return currentIP || void 0;
|
|
5715
6779
|
}
|
|
5716
6780
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5717
6781
|
} catch (error) {
|
|
6782
|
+
if (error instanceof WatchTimeoutError) {
|
|
6783
|
+
throw error;
|
|
6784
|
+
}
|
|
5718
6785
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
5719
6786
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5720
6787
|
}
|
|
5721
6788
|
}
|
|
5722
6789
|
}
|
|
5723
6790
|
var APP_STATUS_STOPPED = "Stopped";
|
|
5724
|
-
var UPGRADE_PHASE_LABELS = {
|
|
5725
|
-
provisioning: "Provisioning new instance",
|
|
5726
|
-
health_check: "Running health checks",
|
|
5727
|
-
draining: "Switching traffic & draining old instance",
|
|
5728
|
-
complete: "Complete",
|
|
5729
|
-
rolling_back: "Rolling back",
|
|
5730
|
-
rollback_done: "Rollback complete",
|
|
5731
|
-
db_handoff: "Database handoff",
|
|
5732
|
-
// Prewarm-detach phases
|
|
5733
|
-
awaiting_userdata: "Waiting for instance readiness",
|
|
5734
|
-
draining_old: "Draining old instance",
|
|
5735
|
-
detached: "Detaching storage",
|
|
5736
|
-
attached_to_new: "Attaching storage to new instance",
|
|
5737
|
-
finalizing: "Finalizing new instance",
|
|
5738
|
-
flipping: "Switching traffic",
|
|
5739
|
-
teardown_old: "Cleaning up old instance"
|
|
5740
|
-
};
|
|
5741
|
-
async function fetchUpgradePhase(userApiClient, appId) {
|
|
5742
|
-
try {
|
|
5743
|
-
const deployments = await userApiClient.getDeployments(appId);
|
|
5744
|
-
if (deployments.length === 0) return void 0;
|
|
5745
|
-
const sorted = [...deployments].sort((a, b) => {
|
|
5746
|
-
const ta = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
5747
|
-
const tb = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
5748
|
-
return tb - ta;
|
|
5749
|
-
});
|
|
5750
|
-
return sorted[0].upgradePhase || void 0;
|
|
5751
|
-
} catch {
|
|
5752
|
-
return void 0;
|
|
5753
|
-
}
|
|
5754
|
-
}
|
|
5755
6791
|
async function watchUntilUpgradeComplete(options, logger) {
|
|
5756
6792
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
6793
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
5757
6794
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
5758
6795
|
let initialStatus;
|
|
5759
6796
|
let initialIP;
|
|
5760
6797
|
let hasChanged = false;
|
|
5761
|
-
const startTime = Date.now();
|
|
5762
|
-
let lastLoggedStatus;
|
|
5763
|
-
let lastLoggedPhase;
|
|
5764
6798
|
const stopCondition = (status, ip) => {
|
|
5765
6799
|
if (!initialStatus) {
|
|
5766
6800
|
initialStatus = status;
|
|
@@ -5794,37 +6828,44 @@ async function watchUntilUpgradeComplete(options, logger) {
|
|
|
5794
6828
|
}
|
|
5795
6829
|
return false;
|
|
5796
6830
|
};
|
|
6831
|
+
const startTime = Date.now();
|
|
6832
|
+
const deadline = startTime + timeoutSeconds * 1e3;
|
|
6833
|
+
let lastLoggedStatus;
|
|
6834
|
+
let lastObservedStatus;
|
|
5797
6835
|
while (true) {
|
|
6836
|
+
if (Date.now() >= deadline) {
|
|
6837
|
+
const elapsedSeconds = Math.round((Date.now() - startTime) / 1e3);
|
|
6838
|
+
throw new WatchTimeoutError({
|
|
6839
|
+
appId,
|
|
6840
|
+
lastStatus: lastObservedStatus,
|
|
6841
|
+
elapsedSeconds,
|
|
6842
|
+
timeoutSeconds
|
|
6843
|
+
});
|
|
6844
|
+
}
|
|
5798
6845
|
try {
|
|
5799
|
-
const
|
|
5800
|
-
|
|
5801
|
-
fetchUpgradePhase(userApiClient, appId)
|
|
5802
|
-
]);
|
|
5803
|
-
if (infoResult.length === 0) {
|
|
6846
|
+
const info = await userApiClient.getInfos([appId], 1);
|
|
6847
|
+
if (info.length === 0) {
|
|
5804
6848
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5805
6849
|
continue;
|
|
5806
6850
|
}
|
|
5807
|
-
const appInfo =
|
|
6851
|
+
const appInfo = info[0];
|
|
5808
6852
|
const currentStatus = appInfo.status;
|
|
5809
6853
|
const currentIP = appInfo.ip || "";
|
|
6854
|
+
lastObservedStatus = currentStatus;
|
|
5810
6855
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5811
|
-
if (
|
|
5812
|
-
const label = UPGRADE_PHASE_LABELS[upgradePhase] || upgradePhase;
|
|
5813
|
-
logger.info(`Phase: ${label} (${elapsed}s)`);
|
|
5814
|
-
lastLoggedPhase = upgradePhase;
|
|
5815
|
-
}
|
|
5816
|
-
if (!upgradePhase && currentStatus !== lastLoggedStatus) {
|
|
6856
|
+
if (currentStatus !== lastLoggedStatus) {
|
|
5817
6857
|
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
5818
6858
|
lastLoggedStatus = currentStatus;
|
|
5819
6859
|
}
|
|
5820
6860
|
if (stopCondition(currentStatus, currentIP)) {
|
|
5821
|
-
const totalElapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5822
|
-
logger.info(`Upgrade completed in ${totalElapsed}s`);
|
|
5823
6861
|
return;
|
|
5824
6862
|
}
|
|
5825
6863
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5826
6864
|
} catch (error) {
|
|
5827
|
-
if (error
|
|
6865
|
+
if (error instanceof WatchTimeoutError) {
|
|
6866
|
+
throw error;
|
|
6867
|
+
}
|
|
6868
|
+
if (typeof error?.message === "string" && error.message.includes("Failed")) {
|
|
5828
6869
|
throw error;
|
|
5829
6870
|
}
|
|
5830
6871
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
@@ -5935,14 +6976,13 @@ var ChainAddresses = {
|
|
|
5935
6976
|
PermissionController: "0x44632dfBdCb6D3E21EF613B0ca8A6A0c618F5a37"
|
|
5936
6977
|
}
|
|
5937
6978
|
};
|
|
5938
|
-
var PLATFORM_ENV_TESTNET_SEPOLIA = "testnet-sepolia";
|
|
5939
|
-
var PLATFORM_ENV_MAINNET_ETHEREUM = "mainnet-ethereum";
|
|
5940
|
-
var DEFAULT_APP_BASE_DOMAIN = "eigencloud.xyz";
|
|
5941
6979
|
var ENVIRONMENTS = {
|
|
5942
6980
|
"sepolia-dev": {
|
|
5943
6981
|
name: "sepolia",
|
|
5944
6982
|
build: "dev",
|
|
5945
6983
|
appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92",
|
|
6984
|
+
releaseAbiVersion: "v1.5",
|
|
6985
|
+
// AppController upgraded to v1.5.x (containerPolicy)
|
|
5946
6986
|
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
5947
6987
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5948
6988
|
kmsServerURL: "http://10.128.0.57:8080",
|
|
@@ -5950,14 +6990,14 @@ var ENVIRONMENTS = {
|
|
|
5950
6990
|
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com",
|
|
5951
6991
|
usdcCreditsAddress: "0xbdA3897c3A428763B59015C64AB766c288C97376",
|
|
5952
6992
|
baseUsdcCreditsAddress: "0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac",
|
|
5953
|
-
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
5954
|
-
platformEnv: PLATFORM_ENV_TESTNET_SEPOLIA,
|
|
5955
|
-
appBaseDomain: DEFAULT_APP_BASE_DOMAIN
|
|
6993
|
+
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
5956
6994
|
},
|
|
5957
6995
|
sepolia: {
|
|
5958
6996
|
name: "sepolia",
|
|
5959
6997
|
build: "prod",
|
|
5960
6998
|
appControllerAddress: "0x0dd810a6ffba6a9820a10d97b659f07d8d23d4E2",
|
|
6999
|
+
releaseAbiVersion: "v1.4",
|
|
7000
|
+
// prod still on AppController v1.4.0 (3-field Release)
|
|
5961
7001
|
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
5962
7002
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5963
7003
|
kmsServerURL: "http://10.128.15.203:8080",
|
|
@@ -5966,22 +7006,20 @@ var ENVIRONMENTS = {
|
|
|
5966
7006
|
billingRPCURL: "https://ethereum-rpc.publicnode.com",
|
|
5967
7007
|
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d",
|
|
5968
7008
|
baseUsdcCreditsAddress: "0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac",
|
|
5969
|
-
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
5970
|
-
platformEnv: PLATFORM_ENV_TESTNET_SEPOLIA,
|
|
5971
|
-
appBaseDomain: DEFAULT_APP_BASE_DOMAIN
|
|
7009
|
+
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
5972
7010
|
},
|
|
5973
7011
|
"mainnet-alpha": {
|
|
5974
7012
|
name: "mainnet-alpha",
|
|
5975
7013
|
build: "prod",
|
|
5976
7014
|
appControllerAddress: "0xc38d35Fc995e75342A21CBd6D770305b142Fbe67",
|
|
7015
|
+
releaseAbiVersion: "v1.4",
|
|
7016
|
+
// prod still on AppController v1.4.0 (3-field Release)
|
|
5977
7017
|
permissionControllerAddress: ChainAddresses[MAINNET_CHAIN_ID].PermissionController,
|
|
5978
7018
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5979
7019
|
kmsServerURL: "http://10.128.0.2:8080",
|
|
5980
7020
|
userApiServerURL: "https://userapi-compute.eigencloud.xyz",
|
|
5981
7021
|
defaultRPCURL: "https://ethereum-rpc.publicnode.com",
|
|
5982
|
-
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d"
|
|
5983
|
-
platformEnv: PLATFORM_ENV_MAINNET_ETHEREUM,
|
|
5984
|
-
appBaseDomain: DEFAULT_APP_BASE_DOMAIN
|
|
7022
|
+
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d"
|
|
5985
7023
|
}
|
|
5986
7024
|
};
|
|
5987
7025
|
var CHAIN_ID_TO_ENVIRONMENT = {
|
|
@@ -6025,7 +7063,7 @@ function getEnvironmentConfig(environment, chainID) {
|
|
|
6025
7063
|
};
|
|
6026
7064
|
}
|
|
6027
7065
|
function getBuildType() {
|
|
6028
|
-
const buildTimeType = true ? "
|
|
7066
|
+
const buildTimeType = true ? "prod"?.toLowerCase() : void 0;
|
|
6029
7067
|
const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
|
|
6030
7068
|
const buildType = buildTimeType || runtimeType;
|
|
6031
7069
|
if (buildType === "dev") {
|
|
@@ -6376,6 +7414,11 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
6376
7414
|
executions: batch.executions,
|
|
6377
7415
|
authorizationList
|
|
6378
7416
|
});
|
|
7417
|
+
await assertSufficientGas({
|
|
7418
|
+
publicClient: batch.publicClient,
|
|
7419
|
+
address: batch.walletClient.account.address,
|
|
7420
|
+
gasEstimate
|
|
7421
|
+
});
|
|
6379
7422
|
const data = {
|
|
6380
7423
|
appId: batch.appId,
|
|
6381
7424
|
salt: batch.salt,
|
|
@@ -6634,6 +7677,11 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
6634
7677
|
executions: batch.executions,
|
|
6635
7678
|
authorizationList
|
|
6636
7679
|
});
|
|
7680
|
+
await assertSufficientGas({
|
|
7681
|
+
publicClient: batch.publicClient,
|
|
7682
|
+
address: batch.walletClient.account.address,
|
|
7683
|
+
gasEstimate
|
|
7684
|
+
});
|
|
6637
7685
|
const data = {
|
|
6638
7686
|
appId: batch.appId,
|
|
6639
7687
|
salt: batch.salt,
|
|
@@ -6670,7 +7718,7 @@ async function executeDeploy(options) {
|
|
|
6670
7718
|
}
|
|
6671
7719
|
);
|
|
6672
7720
|
}
|
|
6673
|
-
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
7721
|
+
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
6674
7722
|
return withSDKTelemetry(
|
|
6675
7723
|
{
|
|
6676
7724
|
functionName: "watchDeployment",
|
|
@@ -6686,7 +7734,8 @@ async function watchDeployment(appId, walletClient, publicClient, environmentCon
|
|
|
6686
7734
|
walletClient,
|
|
6687
7735
|
publicClient,
|
|
6688
7736
|
environmentConfig,
|
|
6689
|
-
appId
|
|
7737
|
+
appId,
|
|
7738
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
6690
7739
|
},
|
|
6691
7740
|
logger
|
|
6692
7741
|
);
|
|
@@ -6782,6 +7831,11 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
6782
7831
|
executions: batch.executions,
|
|
6783
7832
|
authorizationList
|
|
6784
7833
|
});
|
|
7834
|
+
await assertSufficientGas({
|
|
7835
|
+
publicClient: batch.publicClient,
|
|
7836
|
+
address: batch.walletClient.account.address,
|
|
7837
|
+
gasEstimate
|
|
7838
|
+
});
|
|
6785
7839
|
const data = {
|
|
6786
7840
|
appId: batch.appId,
|
|
6787
7841
|
executions: batch.executions,
|
|
@@ -6971,6 +8025,11 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
6971
8025
|
executions: batch.executions,
|
|
6972
8026
|
authorizationList
|
|
6973
8027
|
});
|
|
8028
|
+
await assertSufficientGas({
|
|
8029
|
+
publicClient: batch.publicClient,
|
|
8030
|
+
address: batch.walletClient.account.address,
|
|
8031
|
+
gasEstimate
|
|
8032
|
+
});
|
|
6974
8033
|
const data = {
|
|
6975
8034
|
appId: batch.appId,
|
|
6976
8035
|
executions: batch.executions,
|
|
@@ -7005,7 +8064,7 @@ async function executeUpgrade(options) {
|
|
|
7005
8064
|
}
|
|
7006
8065
|
);
|
|
7007
8066
|
}
|
|
7008
|
-
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
8067
|
+
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
7009
8068
|
return withSDKTelemetry(
|
|
7010
8069
|
{
|
|
7011
8070
|
functionName: "watchUpgrade",
|
|
@@ -7021,7 +8080,8 @@ async function watchUpgrade(appId, walletClient, publicClient, environmentConfig
|
|
|
7021
8080
|
walletClient,
|
|
7022
8081
|
publicClient,
|
|
7023
8082
|
environmentConfig,
|
|
7024
|
-
appId
|
|
8083
|
+
appId,
|
|
8084
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
7025
8085
|
},
|
|
7026
8086
|
logger
|
|
7027
8087
|
);
|
|
@@ -7713,7 +8773,7 @@ function createAppModule(ctx) {
|
|
|
7713
8773
|
}
|
|
7714
8774
|
const account = walletClient.account;
|
|
7715
8775
|
const environment = getEnvironmentConfig(ctx.environment);
|
|
7716
|
-
const logger = getLogger(ctx.verbose);
|
|
8776
|
+
const logger = ctx.logger ?? getLogger(ctx.verbose);
|
|
7717
8777
|
return {
|
|
7718
8778
|
async create(opts) {
|
|
7719
8779
|
return createApp(opts, logger);
|
|
@@ -7825,14 +8885,15 @@ function createAppModule(ctx) {
|
|
|
7825
8885
|
imageRef: result.imageRef
|
|
7826
8886
|
};
|
|
7827
8887
|
},
|
|
7828
|
-
async watchDeployment(appId) {
|
|
8888
|
+
async watchDeployment(appId, opts) {
|
|
7829
8889
|
return watchDeployment(
|
|
7830
8890
|
appId,
|
|
7831
8891
|
walletClient,
|
|
7832
8892
|
publicClient,
|
|
7833
8893
|
environment,
|
|
7834
8894
|
logger,
|
|
7835
|
-
skipTelemetry
|
|
8895
|
+
skipTelemetry,
|
|
8896
|
+
opts
|
|
7836
8897
|
);
|
|
7837
8898
|
},
|
|
7838
8899
|
// Granular upgrade control
|
|
@@ -7890,8 +8951,16 @@ function createAppModule(ctx) {
|
|
|
7890
8951
|
imageRef: result.imageRef
|
|
7891
8952
|
};
|
|
7892
8953
|
},
|
|
7893
|
-
async watchUpgrade(appId) {
|
|
7894
|
-
return watchUpgrade(
|
|
8954
|
+
async watchUpgrade(appId, opts) {
|
|
8955
|
+
return watchUpgrade(
|
|
8956
|
+
appId,
|
|
8957
|
+
walletClient,
|
|
8958
|
+
publicClient,
|
|
8959
|
+
environment,
|
|
8960
|
+
logger,
|
|
8961
|
+
skipTelemetry,
|
|
8962
|
+
opts
|
|
8963
|
+
);
|
|
7895
8964
|
},
|
|
7896
8965
|
// Profile management
|
|
7897
8966
|
async setProfile(appId, profile) {
|