@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/index.js
CHANGED
|
@@ -152,7 +152,6 @@ var ENV_SOURCE_SCRIPT_NAME = "compute-source-env.sh";
|
|
|
152
152
|
var KMS_CLIENT_BINARY_NAME = "kms-client";
|
|
153
153
|
var KMS_SIGNING_KEY_NAME = "kms-signing-public-key.pem";
|
|
154
154
|
var TLS_KEYGEN_BINARY_NAME = "tls-keygen";
|
|
155
|
-
var DRAIN_WATCHER_BINARY_NAME = "ecloud-drain-watcher";
|
|
156
155
|
var CADDYFILE_NAME = "Caddyfile";
|
|
157
156
|
var LAYERED_BUILD_DIR_PREFIX = "ecloud-layered-build";
|
|
158
157
|
|
|
@@ -439,12 +438,14 @@ USER root
|
|
|
439
438
|
{{/if}}
|
|
440
439
|
|
|
441
440
|
# Copy core TEE components
|
|
441
|
+
# CA bundle for kms-client / tls-keygen to validate HTTPS calls to
|
|
442
|
+
# eigencloud.xyz endpoints. Bundled at a non-standard path and consumed
|
|
443
|
+
# only via SSL_CERT_FILE in compute-source-env.sh, so the user's
|
|
444
|
+
# /etc/ssl/ is never touched.
|
|
445
|
+
COPY --from=alpine:3.20.10 /etc/ssl/certs/ca-certificates.crt /usr/local/share/eigenx-ca-certs.crt
|
|
442
446
|
COPY compute-source-env.sh /usr/local/bin/
|
|
443
447
|
COPY kms-client /usr/local/bin/
|
|
444
448
|
COPY kms-signing-public-key.pem /usr/local/bin/
|
|
445
|
-
{{#if includeDrainWatcher}}
|
|
446
|
-
COPY ecloud-drain-watcher /usr/local/bin/
|
|
447
|
-
{{/if}}
|
|
448
449
|
|
|
449
450
|
{{#if includeTLS}}
|
|
450
451
|
# Copy Caddy from official image
|
|
@@ -458,8 +459,7 @@ COPY Caddyfile /etc/caddy/
|
|
|
458
459
|
{{#if originalUser}}
|
|
459
460
|
# Make binaries executable (755 for executables, 644 for keys)
|
|
460
461
|
RUN chmod 755 /usr/local/bin/compute-source-env.sh \\
|
|
461
|
-
&& chmod 755 /usr/local/bin/kms-client{{#if
|
|
462
|
-
&& chmod 755 /usr/local/bin/ecloud-drain-watcher{{/if}}{{#if includeTLS}} \\
|
|
462
|
+
&& chmod 755 /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
463
463
|
&& chmod 755 /usr/local/bin/tls-keygen \\
|
|
464
464
|
&& chmod 755 /usr/local/bin/caddy{{/if}} \\
|
|
465
465
|
&& chmod 644 /usr/local/bin/kms-signing-public-key.pem
|
|
@@ -469,8 +469,7 @@ ENV __ECLOUD_ORIGINAL_USER={{originalUser}}
|
|
|
469
469
|
{{else}}
|
|
470
470
|
# Make binaries executable (preserve existing permissions, just add execute)
|
|
471
471
|
RUN chmod +x /usr/local/bin/compute-source-env.sh \\
|
|
472
|
-
&& chmod +x /usr/local/bin/kms-client{{#if
|
|
473
|
-
&& chmod +x /usr/local/bin/ecloud-drain-watcher{{/if}}{{#if includeTLS}} \\
|
|
472
|
+
&& chmod +x /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
474
473
|
&& chmod +x /usr/local/bin/tls-keygen{{/if}}
|
|
475
474
|
{{/if}}
|
|
476
475
|
|
|
@@ -483,36 +482,8 @@ LABEL tee.launch_policy.log_redirect={{logRedirect}}
|
|
|
483
482
|
LABEL tee.launch_policy.monitoring_memory_allow={{resourceUsageAllow}}
|
|
484
483
|
{{/if}}
|
|
485
484
|
|
|
486
|
-
# Allow-list the envvars the ecloud-platform sets via GCE \`tee-env-*\`
|
|
487
|
-
# metadata. Without this label, Confidential Space's launcher rejects
|
|
488
|
-
# any \`tee-env-*\` override at container-start with
|
|
489
|
-
# "env var {...} is not allowed to be overridden on this image" and
|
|
490
|
-
# exits with code 1 \u2014 which terminates the VM before the entrypoint
|
|
491
|
-
# ever runs. User-supplied env vars flow through KMS (not tee-env-*)
|
|
492
|
-
# and don't need to be listed here.
|
|
493
|
-
#
|
|
494
|
-
# Entries:
|
|
495
|
-
# - ECLOUD_PD_EXPECTED set on PD-backed apps so the entrypoint
|
|
496
|
-
# (compute-source-env.sh) knows to wait for
|
|
497
|
-
# the persistent disk before exec'ing the
|
|
498
|
-
# user workload.
|
|
499
|
-
# - ECLOUD_PLATFORM_HOST the platform-routed hostname
|
|
500
|
-
# (<addr>.<env>.eigencloud.xyz) so the
|
|
501
|
-
# entrypoint's setup_tls can issue an ACME
|
|
502
|
-
# cert for it. Injected by the CLI into
|
|
503
|
-
# publicEnv at deploy/upgrade time and
|
|
504
|
-
# propagated by ecloud-platform's
|
|
505
|
-
# compute.go as a tee-env-* metadata key.
|
|
506
|
-
#
|
|
507
|
-
# The CS launcher parses this label as a comma-separated list
|
|
508
|
-
# (go-tpm-tools/launcher/spec/launch_policy.go:185 \u2014 strings.Split
|
|
509
|
-
# on ","). Quotes are not required; keep the value bare for
|
|
510
|
-
# consistency with compute-tee's and eigenx-kms's existing labels.
|
|
511
|
-
LABEL tee.launch_policy.allow_env_override=ECLOUD_PD_EXPECTED,ECLOUD_PLATFORM_HOST
|
|
512
|
-
|
|
513
485
|
LABEL eigenx_cli_version={{ecloudCLIVersion}}
|
|
514
486
|
LABEL eigenx_vm_image=eigen
|
|
515
|
-
LABEL eigenx_container_contract=v1
|
|
516
487
|
|
|
517
488
|
{{#if includeTLS}}
|
|
518
489
|
# Expose both HTTP and HTTPS ports for Caddy
|
|
@@ -534,54 +505,11 @@ import Handlebars2 from "handlebars";
|
|
|
534
505
|
|
|
535
506
|
// src/client/common/templates/compute-source-env.sh.tmpl
|
|
536
507
|
var compute_source_env_sh_default = `#!/bin/sh
|
|
537
|
-
# EigenCompute container entrypoint script
|
|
538
|
-
# This script handles KMS secret fetching, TLS setup, and privilege dropping
|
|
539
|
-
# before executing the user's application.
|
|
540
|
-
#
|
|
541
|
-
# Handlebars template variables (replaced at build time by the CLI):
|
|
542
|
-
# kmsServerURL - URL of the KMS server
|
|
543
|
-
# userAPIURL - URL of the user API (ecloud-platform)
|
|
544
|
-
# The KMS signing public key is copied into the image as
|
|
545
|
-
# /usr/local/bin/kms-signing-public-key.pem at layer-build time by the CLI.
|
|
546
|
-
#
|
|
547
|
-
# ecloud-platform divergence from compute-tee:
|
|
548
|
-
# This script emits ECLOUD_READY / ECLOUD_FAIL / ECLOUD_AWAITING_USERDATA /
|
|
549
|
-
# ECLOUD_DETACHED markers to stdout at key lifecycle points. The GCP
|
|
550
|
-
# provisioner's serial-console watcher in ecloud-platform
|
|
551
|
-
# (pkg/services/infraService/providers/gcp/compute.go) parses those
|
|
552
|
-
# markers to gate "VM ready" and to coordinate the prewarm-detach
|
|
553
|
-
# upgrade flow. Without the markers, the platform's waitForStartupReady
|
|
554
|
-
# times out at ~10 minutes per deploy, rollback fires, and the VM is
|
|
555
|
-
# deleted \u2014 seen in dev on 2026-05-04 with an older copy of this
|
|
556
|
-
# template that lacked the markers.
|
|
557
|
-
#
|
|
558
|
-
# Prewarm-detach contract:
|
|
559
|
-
# - If ECLOUD_PD_EXPECTED=1 and /mnt/disks/userdata is not present at boot,
|
|
560
|
-
# emit ECLOUD_AWAITING_USERDATA and wait until the disk is attached.
|
|
561
|
-
# - On SIGTERM (drain-requested), forward to child, wait for exit, sync
|
|
562
|
-
# + unmount /mnt/disks/userdata, emit ECLOUD_DETACHED, exit.
|
|
563
|
-
# - ECLOUD_READY is emitted once runtime is bootstrapped (same as before).
|
|
564
|
-
# - ECLOUD_FAIL is emitted on any unrecoverable setup error.
|
|
565
|
-
# Keep the markers on any line that resolves a lifecycle outcome.
|
|
566
|
-
#
|
|
567
|
-
# This file is kept in lockstep with
|
|
568
|
-
# ecloud-platform/pkg/services/buildService/assets/compute-source-env.sh.tmpl
|
|
569
|
-
# \u2014 if you change one, change the other. Differences vs the platform copy
|
|
570
|
-
# are intentionally minimal:
|
|
571
|
-
# - Handlebars placeholders use the CLI's naming (kmsServerURL,
|
|
572
|
-
# userAPIURL) rather than the platform's (KMS_SERVER_URL,
|
|
573
|
-
# USER_API_URL). (See top of file for real placeholder syntax \u2014
|
|
574
|
-
# not repeated here so Handlebars doesn't expand it in this comment.)
|
|
575
|
-
# - KMS signing key is read from a file the CLI copies into the image,
|
|
576
|
-
# not heredoc-embedded in the script, because the CLI's image
|
|
577
|
-
# layering writes it as a separate file (kms-signing-public-key.pem).
|
|
578
|
-
# - TLS binary is \`tls-keygen\` (CLI-bundled) not \`tls-client\`.
|
|
579
|
-
|
|
580
508
|
echo "compute-source-env.sh: Running setup script..."
|
|
581
509
|
|
|
582
510
|
# Fetch and source environment variables from KMS
|
|
583
511
|
echo "Fetching secrets from KMS..."
|
|
584
|
-
if /usr/local/bin/kms-client \\
|
|
512
|
+
if SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt /usr/local/bin/kms-client \\
|
|
585
513
|
--kms-server-url "{{kmsServerURL}}" \\
|
|
586
514
|
--kms-signing-key-file /usr/local/bin/kms-signing-public-key.pem \\
|
|
587
515
|
--userapi-url "{{userAPIURL}}" \\
|
|
@@ -592,187 +520,93 @@ if /usr/local/bin/kms-client \\
|
|
|
592
520
|
else
|
|
593
521
|
echo "compute-source-env.sh: ERROR - Failed to fetch environment variables from KMS"
|
|
594
522
|
echo "compute-source-env.sh: Exiting - cannot start user workload without KMS secrets"
|
|
595
|
-
echo "ECLOUD_FAIL kms_bootstrap"
|
|
596
523
|
exit 1
|
|
597
524
|
fi
|
|
598
525
|
|
|
599
|
-
#
|
|
600
|
-
# produced fullchain/privkey into $1's output directory ($2). Returns
|
|
601
|
-
# 0 on success, non-zero on any failure (caller decides whether that's
|
|
602
|
-
# fatal). tls-keygen writes to /run/tls/{fullchain,privkey}.pem by
|
|
603
|
-
# default; we move those to a per-host subdirectory so the two-site
|
|
604
|
-
# Caddyfile can select the right cert by path.
|
|
605
|
-
issue_cert_for() {
|
|
606
|
-
local host="$1"
|
|
607
|
-
local cert_dir="$2"
|
|
608
|
-
local mnemonic="$3"
|
|
609
|
-
local challenge="$4"
|
|
610
|
-
local staging_flag="$5"
|
|
611
|
-
|
|
612
|
-
echo "compute-source-env.sh: Obtaining TLS certificate for $host (challenge=$challenge)..."
|
|
613
|
-
# Remove any stale default outputs from a prior tls-keygen run
|
|
614
|
-
rm -f /run/tls/fullchain.pem /run/tls/privkey.pem
|
|
615
|
-
if ! MNEMONIC="$mnemonic" DOMAIN="$host" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
|
|
616
|
-
-challenge "$challenge" \\
|
|
617
|
-
$staging_flag; then
|
|
618
|
-
return 1
|
|
619
|
-
fi
|
|
620
|
-
mkdir -p "$cert_dir"
|
|
621
|
-
mv /run/tls/fullchain.pem "$cert_dir/fullchain.pem"
|
|
622
|
-
mv /run/tls/privkey.pem "$cert_dir/privkey.pem"
|
|
623
|
-
echo "compute-source-env.sh: Cert for $host written to $cert_dir"
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
# Setup TLS: issues certs for
|
|
627
|
-
# - ECLOUD_PLATFORM_HOST (platform-routed <addr>.<env>.eigencloud.xyz),
|
|
628
|
-
# when the CLI/platform has set it
|
|
629
|
-
# - DOMAIN (user-supplied custom domain), when set and non-localhost
|
|
630
|
-
#
|
|
631
|
-
# No client-side DNS precheck. Earlier versions tried to gate ACME on
|
|
632
|
-
# "does this hostname resolve to my external IP" but that's wrong for
|
|
633
|
-
# the platform-routing model (DNS points at the shared nginx NLB, not
|
|
634
|
-
# the VM) and was preventing cert issuance on the production path.
|
|
635
|
-
# tls-client (eigencompute-containers/tls-client) does its own DNS
|
|
636
|
-
# poll before calling ACME and surfaces a clear error when challenges
|
|
637
|
-
# can't reach the VM, which is the right place for that check \u2014
|
|
638
|
-
# attempting it here from inside the VM cannot tell platform-routed
|
|
639
|
-
# from compute-tee-routed apps.
|
|
526
|
+
# Setup TLS if tls-keygen is present (which means TLS was configured at build time)
|
|
640
527
|
setup_tls() {
|
|
641
528
|
# If tls-keygen isn't present, TLS wasn't configured during build
|
|
642
529
|
if [ ! -x /usr/local/bin/tls-keygen ]; then
|
|
643
530
|
echo "compute-source-env.sh: TLS not configured (no tls-keygen binary)"
|
|
644
531
|
return 0
|
|
645
532
|
fi
|
|
646
|
-
|
|
647
|
-
local
|
|
648
|
-
local user_domain="\${DOMAIN:-}"
|
|
533
|
+
|
|
534
|
+
local domain="\${DOMAIN:-}"
|
|
649
535
|
local mnemonic="\${MNEMONIC:-}"
|
|
650
|
-
|
|
651
|
-
#
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
# If the user set DOMAIN to the same value as the platform
|
|
658
|
-
# hostname, collapse them. Without this we'd burn a second ACME
|
|
659
|
-
# issuance for the exact same name (each VM boot counts against
|
|
660
|
-
# Let's Encrypt's 5-certs-per-domain-per-week limit), and Caddy
|
|
661
|
-
# would then refuse to start because two site blocks bound to
|
|
662
|
-
# the same address is a config error. Also unset DOMAIN so the
|
|
663
|
-
# DOMAIN site block in the Caddyfile falls back to its
|
|
664
|
-
# "localhost.user.invalid" placeholder and stays dormant.
|
|
665
|
-
if [ -n "$platform_host" ] && [ "$user_domain" = "$platform_host" ]; then
|
|
666
|
-
echo "compute-source-env.sh: DOMAIN matches ECLOUD_PLATFORM_HOST; skipping duplicate cert"
|
|
667
|
-
user_domain=""
|
|
668
|
-
unset DOMAIN
|
|
669
|
-
fi
|
|
670
|
-
|
|
671
|
-
if [ -z "$platform_host" ] && [ -z "$user_domain" ]; then
|
|
672
|
-
echo "compute-source-env.sh: TLS skipped (neither ECLOUD_PLATFORM_HOST nor DOMAIN set)"
|
|
673
|
-
return 0
|
|
536
|
+
|
|
537
|
+
# Since tls-keygen is present, TLS is expected - validate requirements
|
|
538
|
+
if [ -z "$domain" ] || [ "$domain" = "localhost" ]; then
|
|
539
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but DOMAIN not configured or is localhost"
|
|
540
|
+
echo "compute-source-env.sh: Set DOMAIN environment variable to a valid domain"
|
|
541
|
+
exit 1
|
|
674
542
|
fi
|
|
675
|
-
|
|
543
|
+
|
|
676
544
|
if [ -z "$mnemonic" ]; then
|
|
677
|
-
echo "compute-source-env.sh: ERROR - TLS
|
|
678
|
-
echo "
|
|
545
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but MNEMONIC not available"
|
|
546
|
+
echo "compute-source-env.sh: Cannot obtain TLS certificate without mnemonic"
|
|
679
547
|
exit 1
|
|
680
548
|
fi
|
|
681
|
-
|
|
549
|
+
|
|
682
550
|
if [ ! -x /usr/local/bin/caddy ]; then
|
|
683
|
-
echo "compute-source-env.sh: ERROR - TLS
|
|
684
|
-
echo "ECLOUD_FAIL tls_caddy_missing"
|
|
551
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but Caddy not found"
|
|
685
552
|
exit 1
|
|
686
553
|
fi
|
|
687
|
-
|
|
554
|
+
|
|
555
|
+
echo "compute-source-env.sh: Setting up TLS for domain: $domain"
|
|
556
|
+
|
|
557
|
+
# Obtain TLS certificate using ACME
|
|
558
|
+
# Default to http-01, but allow override via ACME_CHALLENGE env var
|
|
688
559
|
local challenge="\${ACME_CHALLENGE:-http-01}"
|
|
560
|
+
|
|
561
|
+
# Check if we should use staging (for testing)
|
|
689
562
|
local staging_flag=""
|
|
690
563
|
if [ "\${ACME_STAGING:-false}" = "true" ]; then
|
|
691
564
|
staging_flag="-staging"
|
|
692
|
-
echo "compute-source-env.sh: Using Let's Encrypt STAGING environment"
|
|
693
|
-
fi
|
|
694
|
-
|
|
695
|
-
local certs_issued=0
|
|
696
|
-
|
|
697
|
-
if [ -n "$platform_host" ]; then
|
|
698
|
-
if issue_cert_for "$platform_host" "/run/tls/platform" "$mnemonic" "$challenge" "$staging_flag"; then
|
|
699
|
-
certs_issued=$((certs_issued + 1))
|
|
700
|
-
else
|
|
701
|
-
echo "compute-source-env.sh: ERROR - failed to issue cert for platform host $platform_host"
|
|
702
|
-
echo "ECLOUD_FAIL tls_setup"
|
|
703
|
-
exit 1
|
|
704
|
-
fi
|
|
705
|
-
fi
|
|
706
|
-
|
|
707
|
-
if [ -n "$user_domain" ]; then
|
|
708
|
-
if issue_cert_for "$user_domain" "/run/tls/domain" "$mnemonic" "$challenge" "$staging_flag"; then
|
|
709
|
-
certs_issued=$((certs_issued + 1))
|
|
710
|
-
else
|
|
711
|
-
echo "compute-source-env.sh: ERROR - failed to issue cert for user domain $user_domain"
|
|
712
|
-
echo "ECLOUD_FAIL tls_setup"
|
|
713
|
-
exit 1
|
|
714
|
-
fi
|
|
565
|
+
echo "compute-source-env.sh: Using Let's Encrypt STAGING environment (certificates won't be trusted)"
|
|
715
566
|
fi
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
567
|
+
|
|
568
|
+
echo "compute-source-env.sh: Obtaining TLS certificate using $challenge challenge..."
|
|
569
|
+
# Pass the API URL for certificate persistence
|
|
570
|
+
if ! SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt \\
|
|
571
|
+
MNEMONIC="$mnemonic" DOMAIN="$domain" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
|
|
572
|
+
-challenge "$challenge" \\
|
|
573
|
+
$staging_flag; then
|
|
574
|
+
echo "compute-source-env.sh: ERROR - Failed to obtain TLS certificate"
|
|
575
|
+
echo "compute-source-env.sh: Certificate issuance failed for $domain"
|
|
576
|
+
exit 1
|
|
720
577
|
fi
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
#
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
# receive real traffic (its hostname falls back to
|
|
730
|
-
# localhost.{platform,user}.invalid, which Caddy routes by SNI and
|
|
731
|
-
# never matches public traffic), so the symlink is never actually
|
|
732
|
-
# presented. Skipped when a user-supplied Caddyfile is in use,
|
|
733
|
-
# since we don't know what cert paths it references.
|
|
734
|
-
if [ -d /run/tls/platform ] && [ ! -e /run/tls/domain/fullchain.pem ]; then
|
|
735
|
-
mkdir -p /run/tls/domain
|
|
736
|
-
ln -sf /run/tls/platform/fullchain.pem /run/tls/domain/fullchain.pem
|
|
737
|
-
ln -sf /run/tls/platform/privkey.pem /run/tls/domain/privkey.pem
|
|
738
|
-
elif [ -d /run/tls/domain ] && [ ! -e /run/tls/platform/fullchain.pem ]; then
|
|
739
|
-
mkdir -p /run/tls/platform
|
|
740
|
-
ln -sf /run/tls/domain/fullchain.pem /run/tls/platform/fullchain.pem
|
|
741
|
-
ln -sf /run/tls/domain/privkey.pem /run/tls/platform/privkey.pem
|
|
578
|
+
|
|
579
|
+
echo "compute-source-env.sh: TLS certificate obtained successfully"
|
|
580
|
+
|
|
581
|
+
# Validate Caddyfile before starting
|
|
582
|
+
if ! /usr/local/bin/caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile 2>/dev/null; then
|
|
583
|
+
echo "compute-source-env.sh: ERROR - Invalid Caddyfile"
|
|
584
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
585
|
+
exit 1
|
|
742
586
|
fi
|
|
743
|
-
|
|
744
|
-
#
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
#
|
|
748
|
-
if [
|
|
749
|
-
if ! /usr/local/bin/caddy
|
|
750
|
-
echo "compute-source-env.sh: ERROR -
|
|
751
|
-
echo "
|
|
587
|
+
|
|
588
|
+
# Start Caddy in background
|
|
589
|
+
echo "compute-source-env.sh: Starting Caddy reverse proxy..."
|
|
590
|
+
|
|
591
|
+
# Check if Caddy logs should be enabled
|
|
592
|
+
if [ "\${ENABLE_CADDY_LOGS:-false}" = "true" ]; then
|
|
593
|
+
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1; then
|
|
594
|
+
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
595
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
752
596
|
exit 1
|
|
753
597
|
fi
|
|
754
|
-
|
|
755
|
-
echo "compute-source-env.sh: Starting Caddy reverse proxy..."
|
|
756
|
-
if [ "\${ENABLE_CADDY_LOGS:-false}" = "true" ]; then
|
|
757
|
-
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1; then
|
|
758
|
-
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
759
|
-
echo "ECLOUD_FAIL tls_caddy_start"
|
|
760
|
-
exit 1
|
|
761
|
-
fi
|
|
762
|
-
else
|
|
763
|
-
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then
|
|
764
|
-
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
765
|
-
echo "ECLOUD_FAIL tls_caddy_start"
|
|
766
|
-
exit 1
|
|
767
|
-
fi
|
|
768
|
-
fi
|
|
769
|
-
|
|
770
|
-
sleep 2
|
|
771
|
-
echo "compute-source-env.sh: Caddy started successfully"
|
|
772
598
|
else
|
|
773
|
-
|
|
599
|
+
# Redirect Caddy output to /dev/null to silence logs
|
|
600
|
+
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then
|
|
601
|
+
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
602
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
603
|
+
exit 1
|
|
604
|
+
fi
|
|
774
605
|
fi
|
|
775
|
-
|
|
606
|
+
|
|
607
|
+
# Give Caddy a moment to fully initialize
|
|
608
|
+
sleep 2
|
|
609
|
+
echo "compute-source-env.sh: Caddy started successfully"
|
|
776
610
|
return 0
|
|
777
611
|
}
|
|
778
612
|
|
|
@@ -783,309 +617,15 @@ setup_tls
|
|
|
783
617
|
export KMS_SERVER_URL="{{kmsServerURL}}"
|
|
784
618
|
export KMS_PUBLIC_KEY="$(cat /usr/local/bin/kms-signing-public-key.pem)"
|
|
785
619
|
|
|
786
|
-
# \u2500\u2500 Prewarm-detach: wait for PD if expected \u2500\u2500
|
|
787
|
-
# Orchestrator sets ECLOUD_PD_EXPECTED=1 on apps using StorageBackend=pd.
|
|
788
|
-
# When the prewarm path is used, the new VM boots WITHOUT the disk; we
|
|
789
|
-
# signal awaiting-userdata and poll until the disk is attached.
|
|
790
|
-
USERDATA_MOUNT="/mnt/disks/userdata"
|
|
791
|
-
USERDATA_DEV="/dev/disk/by-id/google-persistent_storage_1"
|
|
792
|
-
|
|
793
|
-
# userdata_mount_backing_dev resolves the kernel device that currently
|
|
794
|
-
# backs $USERDATA_MOUNT (or empty string if not mounted). The output is
|
|
795
|
-
# canonicalized via readlink so we can compare against $USERDATA_DEV
|
|
796
|
-
# without caring whether the mount table records the symlinked
|
|
797
|
-
# /dev/disk/by-id/... path or the underlying /dev/sdb-style path.
|
|
798
|
-
#
|
|
799
|
-
# Tries findmnt first (clean structured output), falls back to parsing
|
|
800
|
-
# /proc/self/mountinfo so we don't add a hard dependency on util-linux
|
|
801
|
-
# being present in the image.
|
|
802
|
-
userdata_mount_backing_dev() {
|
|
803
|
-
if command -v findmnt >/dev/null 2>&1; then
|
|
804
|
-
local src
|
|
805
|
-
src=$(findmnt -n -o SOURCE -- "$USERDATA_MOUNT" 2>/dev/null) || return 0
|
|
806
|
-
[ -n "$src" ] || return 0
|
|
807
|
-
readlink -f "$src" 2>/dev/null || echo "$src"
|
|
808
|
-
return 0
|
|
809
|
-
fi
|
|
810
|
-
# /proc/self/mountinfo line shape (kernel docs): mount-id parent-id
|
|
811
|
-
# major:minor root mount-point ... So column 5 is the mount point and
|
|
812
|
-
# the device path lives in the optional fields after the "-" separator.
|
|
813
|
-
# We just need the major:minor \u2192 device mapping; awk + a /sys lookup
|
|
814
|
-
# is cleaner than parsing the mountinfo's optional-field section.
|
|
815
|
-
local maj_min dev_basename
|
|
816
|
-
maj_min=$(awk -v mp="$USERDATA_MOUNT" '$5 == mp { print $3 }' /proc/self/mountinfo 2>/dev/null | head -1)
|
|
817
|
-
[ -n "$maj_min" ] || return 0
|
|
818
|
-
dev_basename=$(readlink "/sys/dev/block/\${maj_min}" 2>/dev/null | awk -F/ '{print $NF}')
|
|
819
|
-
[ -n "$dev_basename" ] || return 0
|
|
820
|
-
readlink -f "/dev/\${dev_basename}" 2>/dev/null || echo "/dev/\${dev_basename}"
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
# expected_userdata_dev resolves $USERDATA_DEV through any symlinks so
|
|
824
|
-
# string-compare against userdata_mount_backing_dev is meaningful even
|
|
825
|
-
# when the kernel hands us a /dev/nvme0n1-style path while
|
|
826
|
-
# /dev/disk/by-id/google-persistent_storage_1 is the symlink GCE
|
|
827
|
-
# publishes.
|
|
828
|
-
expected_userdata_dev() {
|
|
829
|
-
if [ -e "$USERDATA_DEV" ]; then
|
|
830
|
-
readlink -f "$USERDATA_DEV" 2>/dev/null || echo "$USERDATA_DEV"
|
|
831
|
-
else
|
|
832
|
-
echo "$USERDATA_DEV"
|
|
833
|
-
fi
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
wait_for_userdata() {
|
|
837
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" != "1" ]; then
|
|
838
|
-
return 0
|
|
839
|
-
fi
|
|
840
|
-
if mountpoint -q "$USERDATA_MOUNT" 2>/dev/null; then
|
|
841
|
-
# The mount slot is taken \u2014 but is it taken by the PD we're
|
|
842
|
-
# about to attach, or by something else? The Confidential Space
|
|
843
|
-
# TEE runtime's SetupSecondaryEncryptedVolume step probes for a
|
|
844
|
-
# secondary GCE disk once at boot, doesn't see it (because the
|
|
845
|
-
# orchestrator hasn't called AttachPD yet \u2014 the contract says
|
|
846
|
-
# the new VM signals awaiting-userdata FIRST), and falls back
|
|
847
|
-
# to mounting an encrypted folder on the BOOT disk at this same
|
|
848
|
-
# path. If we accept that mount as-is, the user app boots on a
|
|
849
|
-
# fresh empty filesystem and the orchestrator's late AttachPD
|
|
850
|
-
# silently lands on a VM that's already serving from boot disk.
|
|
851
|
-
# See docs/solutions/2026-05-15-prewarm-detach-pd-preservation-boot-race.md
|
|
852
|
-
# in ecloud-platform.
|
|
853
|
-
local backing expected
|
|
854
|
-
backing=$(userdata_mount_backing_dev)
|
|
855
|
-
expected=$(expected_userdata_dev)
|
|
856
|
-
if [ -n "$backing" ] && [ "$backing" = "$expected" ]; then
|
|
857
|
-
echo "compute-source-env.sh: userdata already mounted at $USERDATA_MOUNT (backed by $backing)"
|
|
858
|
-
return 0
|
|
859
|
-
fi
|
|
860
|
-
# Mount slot taken, but NOT by our PD. This is the runtime
|
|
861
|
-
# premount on boot disk. Try to recover by lazy-unmounting (the
|
|
862
|
-
# filesystem is fresh and unused \u2014 no app has written to it
|
|
863
|
-
# yet), then fall through to the normal wait-for-PD loop.
|
|
864
|
-
echo "compute-source-env.sh: WARNING - $USERDATA_MOUNT premounted by TEE runtime fallback (backing=\${backing:-unknown}, expected=$expected); attempting recovery"
|
|
865
|
-
if ! umount -l "$USERDATA_MOUNT" 2>/dev/null; then
|
|
866
|
-
# Lazy unmount should never fail under normal circumstances \u2014
|
|
867
|
-
# it doesn't wait for open files, just detaches the namespace.
|
|
868
|
-
# If it did fail, we have no path forward: the orchestrator's
|
|
869
|
-
# strict-mode WaitAwaitingUserdata gate (ecloud-platform PR
|
|
870
|
-
# #174) catches our ECLOUD_FAIL within one poll tick and
|
|
871
|
-
# rolls back, leaving the user's data safe on the old VM.
|
|
872
|
-
echo "ECLOUD_FAIL pd_runtime_premount_unrecoverable"
|
|
873
|
-
exit 1
|
|
874
|
-
fi
|
|
875
|
-
echo "compute-source-env.sh: unmounted runtime fallback at $USERDATA_MOUNT, waiting for real PD"
|
|
876
|
-
fi
|
|
877
|
-
# Refuse to proceed if the tools we need for safe first-attach
|
|
878
|
-
# detection are missing. Without blkid we cannot tell an empty new
|
|
879
|
-
# disk from an already-formatted one \u2014 running mkfs.ext4 on the
|
|
880
|
-
# latter would destroy data.
|
|
881
|
-
if ! command -v blkid >/dev/null 2>&1; then
|
|
882
|
-
echo "ECLOUD_FAIL pd_tools_missing"
|
|
883
|
-
exit 1
|
|
884
|
-
fi
|
|
885
|
-
echo "ECLOUD_AWAITING_USERDATA"
|
|
886
|
-
echo "compute-source-env.sh: waiting for PD at $USERDATA_DEV..."
|
|
887
|
-
# Poll for up to 10 minutes (120 * 5s). The orchestrator's overall
|
|
888
|
-
# attach timeout is shorter; the ceiling here just bounds the wait
|
|
889
|
-
# for manual / diagnostic scenarios.
|
|
890
|
-
local i=0
|
|
891
|
-
local mount_failures=0
|
|
892
|
-
while [ "$i" -lt 120 ]; do
|
|
893
|
-
if [ -e "$USERDATA_DEV" ]; then
|
|
894
|
-
mkdir -p "$USERDATA_MOUNT"
|
|
895
|
-
if mount -o noatime "$USERDATA_DEV" "$USERDATA_MOUNT" 2>/dev/null; then
|
|
896
|
-
echo "compute-source-env.sh: PD mounted at $USERDATA_MOUNT"
|
|
897
|
-
return 0
|
|
898
|
-
fi
|
|
899
|
-
# Disk present but mount failed. Check whether it has a
|
|
900
|
-
# recognized filesystem. \`blkid -s TYPE -o value\` prints the
|
|
901
|
-
# FS type (empty if none). We only mkfs when there is
|
|
902
|
-
# demonstrably NO filesystem \u2014 never on the basis of blkid
|
|
903
|
-
# returning non-zero alone, which could mean "blkid missing"
|
|
904
|
-
# or "device busy".
|
|
905
|
-
local fstype
|
|
906
|
-
fstype=$(blkid -s TYPE -o value "$USERDATA_DEV" 2>/dev/null)
|
|
907
|
-
if [ -z "$fstype" ]; then
|
|
908
|
-
echo "compute-source-env.sh: formatting $USERDATA_DEV (first attach)"
|
|
909
|
-
mkfs.ext4 -F -L eclouddata "$USERDATA_DEV" >/dev/null 2>&1 || {
|
|
910
|
-
echo "ECLOUD_FAIL pd_mkfs_failed"
|
|
911
|
-
exit 1
|
|
912
|
-
}
|
|
913
|
-
mount -o noatime "$USERDATA_DEV" "$USERDATA_MOUNT" || {
|
|
914
|
-
echo "ECLOUD_FAIL pd_mount_after_format_failed"
|
|
915
|
-
exit 1
|
|
916
|
-
}
|
|
917
|
-
return 0
|
|
918
|
-
fi
|
|
919
|
-
# Disk has a filesystem but mount still failed. Give it a
|
|
920
|
-
# few retries to cover transient cases (device busy, udev
|
|
921
|
-
# still settling), but don't pretend this is an attach
|
|
922
|
-
# timeout if it persists.
|
|
923
|
-
mount_failures=$((mount_failures + 1))
|
|
924
|
-
if [ "$mount_failures" -ge 6 ]; then
|
|
925
|
-
echo "ECLOUD_FAIL pd_mount_failed"
|
|
926
|
-
exit 1
|
|
927
|
-
fi
|
|
928
|
-
else
|
|
929
|
-
# Device disappeared (e.g. udev re-enumeration between
|
|
930
|
-
# attach and mount). Reset the consecutive-failure counter
|
|
931
|
-
# so only true back-to-back mount failures trip
|
|
932
|
-
# pd_mount_failed; a device blip should not steal retries.
|
|
933
|
-
mount_failures=0
|
|
934
|
-
fi
|
|
935
|
-
i=$((i + 1))
|
|
936
|
-
sleep 5
|
|
937
|
-
done
|
|
938
|
-
echo "ECLOUD_FAIL pd_attach_timeout"
|
|
939
|
-
exit 1
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
wait_for_userdata
|
|
943
|
-
|
|
944
|
-
# \u2500\u2500 Prewarm-detach: install SIGTERM handler for graceful drain \u2500\u2500
|
|
945
|
-
# Orchestrator signals drain by setting the instance metadata key
|
|
946
|
-
# ECLOUD_DRAIN_REQUESTED=1, which a host-level agent translates into
|
|
947
|
-
# SIGTERM on PID 1. On SIGTERM we:
|
|
948
|
-
# 1. Forward to the child (wakes the user's app for graceful exit)
|
|
949
|
-
# 2. Wait for child exit
|
|
950
|
-
# 3. Sync + unmount the PD
|
|
951
|
-
# 4. Emit ECLOUD_DETACHED so the orchestrator can proceed to detach
|
|
952
|
-
CHILD_PID=""
|
|
953
|
-
_DRAIN_IN_PROGRESS=0
|
|
954
|
-
|
|
955
|
-
drain_handler() {
|
|
956
|
-
# Guard against re-entry if SIGTERM arrives twice (e.g. both the
|
|
957
|
-
# drain_watcher and an external signal fire in quick succession).
|
|
958
|
-
if [ "$_DRAIN_IN_PROGRESS" = "1" ]; then
|
|
959
|
-
return 0
|
|
960
|
-
fi
|
|
961
|
-
_DRAIN_IN_PROGRESS=1
|
|
962
|
-
echo "compute-source-env.sh: received drain signal, forwarding to child pgid=$CHILD_PID"
|
|
963
|
-
if [ -n "$CHILD_PID" ]; then
|
|
964
|
-
# Send to the process group so intermediate wrappers (su, sh -c,
|
|
965
|
-
# etc.) don't swallow the signal. The leading \`-\` targets the
|
|
966
|
-
# pgid, which equals the direct child's pid for a shell-backgrounded
|
|
967
|
-
# process. Fall back to the pid alone if pgid signaling fails
|
|
968
|
-
# (e.g. kernel older than 3.9 or PID namespace edge cases).
|
|
969
|
-
kill -TERM -"$CHILD_PID" 2>/dev/null || kill -TERM "$CHILD_PID" 2>/dev/null || true
|
|
970
|
-
# Give the app up to 30s to exit cleanly.
|
|
971
|
-
local i=0
|
|
972
|
-
while [ "$i" -lt 30 ] && kill -0 "$CHILD_PID" 2>/dev/null; do
|
|
973
|
-
i=$((i + 1))
|
|
974
|
-
sleep 1
|
|
975
|
-
done
|
|
976
|
-
if kill -0 "$CHILD_PID" 2>/dev/null; then
|
|
977
|
-
echo "compute-source-env.sh: child did not exit in 30s, sending SIGKILL"
|
|
978
|
-
kill -KILL -"$CHILD_PID" 2>/dev/null || kill -KILL "$CHILD_PID" 2>/dev/null || true
|
|
979
|
-
# Reap the process so its in-flight I/O is flushed to the
|
|
980
|
-
# filesystem before we sync + unmount. SIGKILL schedules
|
|
981
|
-
# death; wait guarantees it's complete.
|
|
982
|
-
wait "$CHILD_PID" 2>/dev/null || true
|
|
983
|
-
fi
|
|
984
|
-
fi
|
|
985
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" = "1" ] && mountpoint -q "$USERDATA_MOUNT" 2>/dev/null; then
|
|
986
|
-
sync
|
|
987
|
-
if umount "$USERDATA_MOUNT" 2>/dev/null; then
|
|
988
|
-
echo "compute-source-env.sh: unmounted $USERDATA_MOUNT cleanly"
|
|
989
|
-
else
|
|
990
|
-
# Force lazy unmount as last resort \u2014 orchestrator still needs
|
|
991
|
-
# the DETACHED signal to proceed.
|
|
992
|
-
umount -l "$USERDATA_MOUNT" 2>/dev/null || true
|
|
993
|
-
echo "compute-source-env.sh: WARNING - used lazy unmount on $USERDATA_MOUNT"
|
|
994
|
-
fi
|
|
995
|
-
# ECLOUD_DETACHED is strictly a PD-lifecycle signal. Only emit
|
|
996
|
-
# it when we actually had a PD mount in play, so serial-log
|
|
997
|
-
# parsers and alerting for non-PD apps don't see spurious
|
|
998
|
-
# lifecycle markers on routine container SIGTERM.
|
|
999
|
-
echo "ECLOUD_DETACHED"
|
|
1000
|
-
fi
|
|
1001
|
-
# Always exit 0: drain is a managed shutdown and the orchestrator
|
|
1002
|
-
# waits on ECLOUD_DETACHED, not the container exit code. Forwarding
|
|
1003
|
-
# the child's exit status here would make a crash-during-drain look
|
|
1004
|
-
# like a drain failure to whatever reads the container exit code.
|
|
1005
|
-
exit 0
|
|
1006
|
-
}
|
|
1007
|
-
trap drain_handler TERM
|
|
1008
|
-
|
|
1009
|
-
# \u2500\u2500 Prewarm-detach: background drain watcher \u2500\u2500
|
|
1010
|
-
# Container metadata delivery in Confidential Space is limited, so we
|
|
1011
|
-
# poll the instance metadata server for ECLOUD_DRAIN_REQUESTED and
|
|
1012
|
-
# raise SIGTERM on ourselves when it flips to "1".
|
|
1013
|
-
#
|
|
1014
|
-
# Try wget first (present in most Alpine bases), fall back to curl.
|
|
1015
|
-
# If neither is present, drain watcher is disabled \u2014 the orchestrator
|
|
1016
|
-
# will hit its drain timeout and fail the upgrade explicitly, which is
|
|
1017
|
-
# the correct behavior (we cannot silently ignore a drain request).
|
|
1018
|
-
_fetch_drain_flag() {
|
|
1019
|
-
local url="http://metadata.google.internal/computeMetadata/v1/instance/attributes/ECLOUD_DRAIN_REQUESTED"
|
|
1020
|
-
if command -v wget >/dev/null 2>&1; then
|
|
1021
|
-
wget -q --tries=1 --timeout=2 --header='Metadata-Flavor: Google' -O - "$url" 2>/dev/null
|
|
1022
|
-
elif command -v curl >/dev/null 2>&1; then
|
|
1023
|
-
curl -sf --max-time 2 -H 'Metadata-Flavor: Google' "$url" 2>/dev/null
|
|
1024
|
-
else
|
|
1025
|
-
return 2
|
|
1026
|
-
fi
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
drain_watcher() {
|
|
1030
|
-
# Preflight: confirm we have an HTTP client
|
|
1031
|
-
if ! _fetch_drain_flag >/dev/null 2>&1; then
|
|
1032
|
-
# Either no http client available OR metadata server not
|
|
1033
|
-
# responding yet. If no client, give up and log; otherwise the
|
|
1034
|
-
# loop below will retry.
|
|
1035
|
-
if ! command -v wget >/dev/null 2>&1 && ! command -v curl >/dev/null 2>&1; then
|
|
1036
|
-
echo "compute-source-env.sh: WARNING - no wget/curl; drain_watcher disabled"
|
|
1037
|
-
return 0
|
|
1038
|
-
fi
|
|
1039
|
-
fi
|
|
1040
|
-
while true; do
|
|
1041
|
-
local v
|
|
1042
|
-
v=$(_fetch_drain_flag || true)
|
|
1043
|
-
if [ "$v" = "1" ]; then
|
|
1044
|
-
echo "compute-source-env.sh: drain_watcher saw ECLOUD_DRAIN_REQUESTED=1, signaling PID 1"
|
|
1045
|
-
# The CS launcher runs this script directly as PID 1, so
|
|
1046
|
-
# kill -TERM 1 delivers SIGTERM to the shell that installed
|
|
1047
|
-
# the drain_handler trap. If the launch mechanism ever
|
|
1048
|
-
# wraps this script in another process, this assumption
|
|
1049
|
-
# breaks and drain will silently no-op \u2014 audit here.
|
|
1050
|
-
kill -TERM 1 2>/dev/null || true
|
|
1051
|
-
return 0
|
|
1052
|
-
fi
|
|
1053
|
-
sleep 2
|
|
1054
|
-
done
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" = "1" ]; then
|
|
1058
|
-
# Assumption: the orchestrator only flips ECLOUD_DRAIN_REQUESTED=1
|
|
1059
|
-
# after observing ECLOUD_AWAITING_USERDATA (old VM) or
|
|
1060
|
-
# ECLOUD_READY (new VM), so CHILD_PID is always set by the time
|
|
1061
|
-
# drain_handler fires. If drain somehow arrived in the tiny window
|
|
1062
|
-
# between this watcher spawn and CHILD_PID assignment below,
|
|
1063
|
-
# drain_handler would skip the child-kill branch and still emit
|
|
1064
|
-
# ECLOUD_DETACHED \u2014 harmless because there's nothing to drain yet.
|
|
1065
|
-
if [ -x /usr/local/bin/ecloud-drain-watcher ]; then
|
|
1066
|
-
/usr/local/bin/ecloud-drain-watcher &
|
|
1067
|
-
else
|
|
1068
|
-
drain_watcher &
|
|
1069
|
-
fi
|
|
1070
|
-
fi
|
|
1071
|
-
|
|
1072
620
|
echo "compute-source-env.sh: Environment sourced."
|
|
1073
|
-
echo "ECLOUD_READY runtime_bootstrapped"
|
|
1074
621
|
|
|
1075
622
|
# Drop privileges to original user for the application command
|
|
1076
623
|
if [ -n "$__ECLOUD_ORIGINAL_USER" ] && [ "$(id -u)" = "0" ]; then
|
|
1077
624
|
echo "compute-source-env.sh: Dropping privileges to user: $__ECLOUD_ORIGINAL_USER"
|
|
1078
|
-
|
|
1079
|
-
su -s /bin/sh "$__ECLOUD_ORIGINAL_USER" -c 'exec "$@"' -- sh "$@" &
|
|
1080
|
-
CHILD_PID=$!
|
|
1081
|
-
wait "$CHILD_PID"
|
|
1082
|
-
exit $?
|
|
625
|
+
exec su -s /bin/sh "$__ECLOUD_ORIGINAL_USER" -c 'exec "$@"' -- sh "$@"
|
|
1083
626
|
fi
|
|
1084
627
|
|
|
1085
|
-
"$@"
|
|
1086
|
-
CHILD_PID=$!
|
|
1087
|
-
wait "$CHILD_PID"
|
|
1088
|
-
exit $?
|
|
628
|
+
exec "$@"
|
|
1089
629
|
`;
|
|
1090
630
|
|
|
1091
631
|
// src/client/common/templates/scriptTemplate.ts
|
|
@@ -1094,14 +634,6 @@ function processScriptTemplate(data) {
|
|
|
1094
634
|
return template(data);
|
|
1095
635
|
}
|
|
1096
636
|
|
|
1097
|
-
// src/client/common/templates/Caddyfile.default.tmpl
|
|
1098
|
-
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';
|
|
1099
|
-
|
|
1100
|
-
// src/client/common/templates/caddyfileTemplate.ts
|
|
1101
|
-
function getDefaultCaddyfile() {
|
|
1102
|
-
return Caddyfile_default_default;
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
637
|
// keys/mainnet-alpha/prod/kms-encryption-public-key.pem
|
|
1106
638
|
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-----";
|
|
1107
639
|
|
|
@@ -1276,9 +808,15 @@ async function layerLocalImage(options, logger) {
|
|
|
1276
808
|
const imageConfig = await extractImageConfig(docker, sourceImageRef);
|
|
1277
809
|
const originalCmd = imageConfig.cmd.length > 0 ? imageConfig.cmd : imageConfig.entrypoint;
|
|
1278
810
|
const originalUser = imageConfig.user;
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
811
|
+
let includeTLS = false;
|
|
812
|
+
if (envFilePath && fs.existsSync(envFilePath)) {
|
|
813
|
+
const envContent = fs.readFileSync(envFilePath, "utf-8");
|
|
814
|
+
const domainMatch = envContent.match(/^DOMAIN=(.+)$/m);
|
|
815
|
+
if (domainMatch && domainMatch[1] && domainMatch[1] !== "localhost") {
|
|
816
|
+
includeTLS = true;
|
|
817
|
+
logger.debug(`Found DOMAIN=${domainMatch[1]} in ${envFilePath}, including TLS components`);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
1282
820
|
const layeredDockerfileContent = processDockerfileTemplate({
|
|
1283
821
|
baseImage: sourceImageRef,
|
|
1284
822
|
originalCmd: JSON.stringify(originalCmd),
|
|
@@ -1286,9 +824,8 @@ async function layerLocalImage(options, logger) {
|
|
|
1286
824
|
logRedirect,
|
|
1287
825
|
resourceUsageAllow,
|
|
1288
826
|
includeTLS,
|
|
1289
|
-
ecloudCLIVersion: "0.1.0"
|
|
827
|
+
ecloudCLIVersion: "0.1.0"
|
|
1290
828
|
// TODO: Get from package.json
|
|
1291
|
-
includeDrainWatcher
|
|
1292
829
|
});
|
|
1293
830
|
const scriptContent = processScriptTemplate({
|
|
1294
831
|
kmsServerURL: environmentConfig.kmsServerURL,
|
|
@@ -1298,8 +835,7 @@ async function layerLocalImage(options, logger) {
|
|
|
1298
835
|
environmentConfig,
|
|
1299
836
|
layeredDockerfileContent,
|
|
1300
837
|
scriptContent,
|
|
1301
|
-
includeTLS
|
|
1302
|
-
includeDrainWatcher ? drainWatcherSource : void 0
|
|
838
|
+
includeTLS
|
|
1303
839
|
// logger
|
|
1304
840
|
);
|
|
1305
841
|
try {
|
|
@@ -1314,7 +850,7 @@ async function layerLocalImage(options, logger) {
|
|
|
1314
850
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
1315
851
|
}
|
|
1316
852
|
}
|
|
1317
|
-
async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileContent, scriptContent, includeTLS
|
|
853
|
+
async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileContent, scriptContent, includeTLS) {
|
|
1318
854
|
const tempDir = fs.mkdtempSync(path2.join(os.tmpdir(), LAYERED_BUILD_DIR_PREFIX));
|
|
1319
855
|
try {
|
|
1320
856
|
const layeredDockerfilePath = path2.join(tempDir, LAYERED_DOCKERFILE_NAME);
|
|
@@ -1338,11 +874,6 @@ async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileCo
|
|
|
1338
874
|
}
|
|
1339
875
|
fs.copyFileSync(kmsClientSource, kmsClientPath);
|
|
1340
876
|
fs.chmodSync(kmsClientPath, 493);
|
|
1341
|
-
if (drainWatcherSource && fs.existsSync(drainWatcherSource)) {
|
|
1342
|
-
const drainWatcherPath = path2.join(tempDir, DRAIN_WATCHER_BINARY_NAME);
|
|
1343
|
-
fs.copyFileSync(drainWatcherSource, drainWatcherPath);
|
|
1344
|
-
fs.chmodSync(drainWatcherPath, 493);
|
|
1345
|
-
}
|
|
1346
877
|
if (includeTLS) {
|
|
1347
878
|
const tlsKeygenPath = path2.join(tempDir, TLS_KEYGEN_BINARY_NAME);
|
|
1348
879
|
const tlsKeygenSource = findBinary("tls-keygen-linux-amd64");
|
|
@@ -1353,13 +884,15 @@ async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileCo
|
|
|
1353
884
|
}
|
|
1354
885
|
fs.copyFileSync(tlsKeygenSource, tlsKeygenPath);
|
|
1355
886
|
fs.chmodSync(tlsKeygenPath, 493);
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
fs.
|
|
887
|
+
const caddyfilePath = path2.join(process.cwd(), CADDYFILE_NAME);
|
|
888
|
+
if (fs.existsSync(caddyfilePath)) {
|
|
889
|
+
const caddyfileContent = fs.readFileSync(caddyfilePath);
|
|
890
|
+
const destCaddyfilePath = path2.join(tempDir, CADDYFILE_NAME);
|
|
891
|
+
fs.writeFileSync(destCaddyfilePath, caddyfileContent, { mode: 420 });
|
|
1361
892
|
} else {
|
|
1362
|
-
|
|
893
|
+
throw new Error(
|
|
894
|
+
"TLS is enabled (DOMAIN is set) but Caddyfile not found. Run configure TLS to set up TLS configuration"
|
|
895
|
+
);
|
|
1363
896
|
}
|
|
1364
897
|
}
|
|
1365
898
|
return tempDir;
|
|
@@ -1427,16 +960,7 @@ async function extractDigestFromSinglePlatform(manifest, imageRef) {
|
|
|
1427
960
|
architecture: inspectData[0].Architecture
|
|
1428
961
|
} : null;
|
|
1429
962
|
if (!config) {
|
|
1430
|
-
|
|
1431
|
-
const digest = hexStringToBytes32(manifest.config.digest);
|
|
1432
|
-
const registry = extractRegistryName(imageRef);
|
|
1433
|
-
return {
|
|
1434
|
-
digest,
|
|
1435
|
-
registry,
|
|
1436
|
-
platform: DOCKER_PLATFORM
|
|
1437
|
-
};
|
|
1438
|
-
}
|
|
1439
|
-
throw new Error(`Could not determine platform for ${imageRef}`);
|
|
963
|
+
throw createPlatformErrorMessage(imageRef, ["unknown (could not determine architecture)"]);
|
|
1440
964
|
}
|
|
1441
965
|
const platform2 = `${config.os}/${config.architecture}`;
|
|
1442
966
|
if (platform2 === DOCKER_PLATFORM) {
|
|
@@ -1508,14 +1032,11 @@ Image: ${imageRef}
|
|
|
1508
1032
|
Found platform(s): ${platforms.join(", ")}
|
|
1509
1033
|
Required platform: ${DOCKER_PLATFORM}
|
|
1510
1034
|
|
|
1511
|
-
To fix
|
|
1512
|
-
1.
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
docker push ${imageRef}
|
|
1517
|
-
|
|
1518
|
-
2. Or use the SDK to build with the correct platform automatically.`;
|
|
1035
|
+
To fix, either:
|
|
1036
|
+
1. Rebuild the image for ${DOCKER_PLATFORM} and push it:
|
|
1037
|
+
docker buildx build --platform ${DOCKER_PLATFORM} -t ${imageRef} --push .
|
|
1038
|
+
2. Or use a verifiable build (--verifiable --repo <repo> --commit <sha>), which
|
|
1039
|
+
builds server-side and needs no local Docker.`;
|
|
1519
1040
|
return new Error(errorMsg);
|
|
1520
1041
|
}
|
|
1521
1042
|
|
|
@@ -1620,6 +1141,8 @@ async function prepareRelease(options, logger) {
|
|
|
1620
1141
|
logger.info(`Waiting ${REGISTRY_PROPAGATION_WAIT_SECONDS} seconds for registry propagation...`);
|
|
1621
1142
|
await new Promise((resolve2) => setTimeout(resolve2, REGISTRY_PROPAGATION_WAIT_SECONDS * 1e3));
|
|
1622
1143
|
} else {
|
|
1144
|
+
logger.info("Verifying image platform (linux/amd64)...");
|
|
1145
|
+
await getImageDigestAndName(imageRef);
|
|
1623
1146
|
logger.info("Checking if image needs layering...");
|
|
1624
1147
|
finalImageRef = await layerRemoteImageIfNeeded(
|
|
1625
1148
|
{
|
|
@@ -1778,6 +1301,13 @@ function extractRegistryNameNoDocker(imageRef) {
|
|
|
1778
1301
|
import { encodeFunctionData, encodeAbiParameters, decodeErrorResult } from "viem";
|
|
1779
1302
|
|
|
1780
1303
|
// src/client/common/types/index.ts
|
|
1304
|
+
var EMPTY_CONTAINER_POLICY = {
|
|
1305
|
+
args: [],
|
|
1306
|
+
cmdOverride: [],
|
|
1307
|
+
env: [],
|
|
1308
|
+
envOverride: [],
|
|
1309
|
+
restartPolicy: ""
|
|
1310
|
+
};
|
|
1781
1311
|
var noopLogger = {
|
|
1782
1312
|
debug: () => {
|
|
1783
1313
|
},
|
|
@@ -3018,49 +2548,1594 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
3018
2548
|
} else {
|
|
3019
2549
|
revertReason = callError.message || "Unknown reason";
|
|
3020
2550
|
}
|
|
3021
|
-
}
|
|
3022
|
-
throw new Error(`Transaction reverted: ${hash}. Reason: ${revertReason}`);
|
|
2551
|
+
}
|
|
2552
|
+
throw new Error(`Transaction reverted: ${hash}. Reason: ${revertReason}`);
|
|
2553
|
+
}
|
|
2554
|
+
return hash;
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
// src/client/common/contract/caller.ts
|
|
2558
|
+
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
2559
|
+
|
|
2560
|
+
// src/client/common/utils/helpers.ts
|
|
2561
|
+
import { extractChain, createPublicClient, createWalletClient, http, fallback } from "viem";
|
|
2562
|
+
import { sepolia as sepolia2 } from "viem/chains";
|
|
2563
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
2564
|
+
function getChainFromID(chainID, fallback2 = sepolia2) {
|
|
2565
|
+
const id = Number(chainID);
|
|
2566
|
+
return extractChain({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
2567
|
+
}
|
|
2568
|
+
function createClients(options) {
|
|
2569
|
+
const { privateKey, rpcUrl, chainId } = options;
|
|
2570
|
+
const privateKeyHex = addHexPrefix(privateKey);
|
|
2571
|
+
const account = privateKeyToAccount(privateKeyHex);
|
|
2572
|
+
const chain = getChainFromID(chainId);
|
|
2573
|
+
const transport = typeof rpcUrl === "string" ? http(rpcUrl) : fallback(rpcUrl.map((url) => http(url)));
|
|
2574
|
+
const publicClient = createPublicClient({
|
|
2575
|
+
chain,
|
|
2576
|
+
transport
|
|
2577
|
+
});
|
|
2578
|
+
const walletClient = createWalletClient({
|
|
2579
|
+
account,
|
|
2580
|
+
chain,
|
|
2581
|
+
transport
|
|
2582
|
+
});
|
|
2583
|
+
return { walletClient, publicClient };
|
|
2584
|
+
}
|
|
2585
|
+
function addHexPrefix(value) {
|
|
2586
|
+
return value.startsWith("0x") ? value : `0x${value}`;
|
|
2587
|
+
}
|
|
2588
|
+
function stripHexPrefix(value) {
|
|
2589
|
+
return value.startsWith("0x") ? value.slice(2) : value;
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
// src/client/common/abis/AppController.json
|
|
2593
|
+
var AppController_default = [
|
|
2594
|
+
{
|
|
2595
|
+
type: "constructor",
|
|
2596
|
+
inputs: [
|
|
2597
|
+
{
|
|
2598
|
+
name: "_version",
|
|
2599
|
+
type: "string",
|
|
2600
|
+
internalType: "string"
|
|
2601
|
+
},
|
|
2602
|
+
{
|
|
2603
|
+
name: "_permissionController",
|
|
2604
|
+
type: "address",
|
|
2605
|
+
internalType: "contractIPermissionController"
|
|
2606
|
+
},
|
|
2607
|
+
{
|
|
2608
|
+
name: "_releaseManager",
|
|
2609
|
+
type: "address",
|
|
2610
|
+
internalType: "contractIReleaseManager"
|
|
2611
|
+
},
|
|
2612
|
+
{
|
|
2613
|
+
name: "_computeAVSRegistrar",
|
|
2614
|
+
type: "address",
|
|
2615
|
+
internalType: "contractIComputeAVSRegistrar"
|
|
2616
|
+
},
|
|
2617
|
+
{
|
|
2618
|
+
name: "_computeOperator",
|
|
2619
|
+
type: "address",
|
|
2620
|
+
internalType: "contractIComputeOperator"
|
|
2621
|
+
},
|
|
2622
|
+
{
|
|
2623
|
+
name: "_appBeacon",
|
|
2624
|
+
type: "address",
|
|
2625
|
+
internalType: "contractIBeacon"
|
|
2626
|
+
}
|
|
2627
|
+
],
|
|
2628
|
+
stateMutability: "nonpayable"
|
|
2629
|
+
},
|
|
2630
|
+
{
|
|
2631
|
+
type: "function",
|
|
2632
|
+
name: "API_PERMISSION_TYPEHASH",
|
|
2633
|
+
inputs: [],
|
|
2634
|
+
outputs: [
|
|
2635
|
+
{
|
|
2636
|
+
name: "",
|
|
2637
|
+
type: "bytes32",
|
|
2638
|
+
internalType: "bytes32"
|
|
2639
|
+
}
|
|
2640
|
+
],
|
|
2641
|
+
stateMutability: "view"
|
|
2642
|
+
},
|
|
2643
|
+
{
|
|
2644
|
+
type: "function",
|
|
2645
|
+
name: "appBeacon",
|
|
2646
|
+
inputs: [],
|
|
2647
|
+
outputs: [
|
|
2648
|
+
{
|
|
2649
|
+
name: "",
|
|
2650
|
+
type: "address",
|
|
2651
|
+
internalType: "contractIBeacon"
|
|
2652
|
+
}
|
|
2653
|
+
],
|
|
2654
|
+
stateMutability: "view"
|
|
2655
|
+
},
|
|
2656
|
+
{
|
|
2657
|
+
type: "function",
|
|
2658
|
+
name: "calculateApiPermissionDigestHash",
|
|
2659
|
+
inputs: [
|
|
2660
|
+
{
|
|
2661
|
+
name: "permission",
|
|
2662
|
+
type: "bytes4",
|
|
2663
|
+
internalType: "bytes4"
|
|
2664
|
+
},
|
|
2665
|
+
{
|
|
2666
|
+
name: "expiry",
|
|
2667
|
+
type: "uint256",
|
|
2668
|
+
internalType: "uint256"
|
|
2669
|
+
}
|
|
2670
|
+
],
|
|
2671
|
+
outputs: [
|
|
2672
|
+
{
|
|
2673
|
+
name: "",
|
|
2674
|
+
type: "bytes32",
|
|
2675
|
+
internalType: "bytes32"
|
|
2676
|
+
}
|
|
2677
|
+
],
|
|
2678
|
+
stateMutability: "view"
|
|
2679
|
+
},
|
|
2680
|
+
{
|
|
2681
|
+
type: "function",
|
|
2682
|
+
name: "calculateAppId",
|
|
2683
|
+
inputs: [
|
|
2684
|
+
{
|
|
2685
|
+
name: "deployer",
|
|
2686
|
+
type: "address",
|
|
2687
|
+
internalType: "address"
|
|
2688
|
+
},
|
|
2689
|
+
{
|
|
2690
|
+
name: "salt",
|
|
2691
|
+
type: "bytes32",
|
|
2692
|
+
internalType: "bytes32"
|
|
2693
|
+
}
|
|
2694
|
+
],
|
|
2695
|
+
outputs: [
|
|
2696
|
+
{
|
|
2697
|
+
name: "",
|
|
2698
|
+
type: "address",
|
|
2699
|
+
internalType: "contractIApp"
|
|
2700
|
+
}
|
|
2701
|
+
],
|
|
2702
|
+
stateMutability: "view"
|
|
2703
|
+
},
|
|
2704
|
+
{
|
|
2705
|
+
type: "function",
|
|
2706
|
+
name: "computeAVSRegistrar",
|
|
2707
|
+
inputs: [],
|
|
2708
|
+
outputs: [
|
|
2709
|
+
{
|
|
2710
|
+
name: "",
|
|
2711
|
+
type: "address",
|
|
2712
|
+
internalType: "contractIComputeAVSRegistrar"
|
|
2713
|
+
}
|
|
2714
|
+
],
|
|
2715
|
+
stateMutability: "view"
|
|
2716
|
+
},
|
|
2717
|
+
{
|
|
2718
|
+
type: "function",
|
|
2719
|
+
name: "computeOperator",
|
|
2720
|
+
inputs: [],
|
|
2721
|
+
outputs: [
|
|
2722
|
+
{
|
|
2723
|
+
name: "",
|
|
2724
|
+
type: "address",
|
|
2725
|
+
internalType: "contractIComputeOperator"
|
|
2726
|
+
}
|
|
2727
|
+
],
|
|
2728
|
+
stateMutability: "view"
|
|
2729
|
+
},
|
|
2730
|
+
{
|
|
2731
|
+
type: "function",
|
|
2732
|
+
name: "confirmUpgrade",
|
|
2733
|
+
inputs: [
|
|
2734
|
+
{
|
|
2735
|
+
name: "app",
|
|
2736
|
+
type: "address",
|
|
2737
|
+
internalType: "contractIApp"
|
|
2738
|
+
}
|
|
2739
|
+
],
|
|
2740
|
+
outputs: [],
|
|
2741
|
+
stateMutability: "nonpayable"
|
|
2742
|
+
},
|
|
2743
|
+
{
|
|
2744
|
+
type: "function",
|
|
2745
|
+
name: "createApp",
|
|
2746
|
+
inputs: [
|
|
2747
|
+
{
|
|
2748
|
+
name: "salt",
|
|
2749
|
+
type: "bytes32",
|
|
2750
|
+
internalType: "bytes32"
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
name: "release",
|
|
2754
|
+
type: "tuple",
|
|
2755
|
+
internalType: "structIAppController.Release",
|
|
2756
|
+
components: [
|
|
2757
|
+
{
|
|
2758
|
+
name: "rmsRelease",
|
|
2759
|
+
type: "tuple",
|
|
2760
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
2761
|
+
components: [
|
|
2762
|
+
{
|
|
2763
|
+
name: "artifacts",
|
|
2764
|
+
type: "tuple[]",
|
|
2765
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
2766
|
+
components: [
|
|
2767
|
+
{
|
|
2768
|
+
name: "digest",
|
|
2769
|
+
type: "bytes32",
|
|
2770
|
+
internalType: "bytes32"
|
|
2771
|
+
},
|
|
2772
|
+
{
|
|
2773
|
+
name: "registry",
|
|
2774
|
+
type: "string",
|
|
2775
|
+
internalType: "string"
|
|
2776
|
+
}
|
|
2777
|
+
]
|
|
2778
|
+
},
|
|
2779
|
+
{
|
|
2780
|
+
name: "upgradeByTime",
|
|
2781
|
+
type: "uint32",
|
|
2782
|
+
internalType: "uint32"
|
|
2783
|
+
}
|
|
2784
|
+
]
|
|
2785
|
+
},
|
|
2786
|
+
{
|
|
2787
|
+
name: "publicEnv",
|
|
2788
|
+
type: "bytes",
|
|
2789
|
+
internalType: "bytes"
|
|
2790
|
+
},
|
|
2791
|
+
{
|
|
2792
|
+
name: "encryptedEnv",
|
|
2793
|
+
type: "bytes",
|
|
2794
|
+
internalType: "bytes"
|
|
2795
|
+
},
|
|
2796
|
+
{
|
|
2797
|
+
name: "containerPolicy",
|
|
2798
|
+
type: "tuple",
|
|
2799
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
2800
|
+
components: [
|
|
2801
|
+
{
|
|
2802
|
+
name: "args",
|
|
2803
|
+
type: "string[]",
|
|
2804
|
+
internalType: "string[]"
|
|
2805
|
+
},
|
|
2806
|
+
{
|
|
2807
|
+
name: "cmdOverride",
|
|
2808
|
+
type: "string[]",
|
|
2809
|
+
internalType: "string[]"
|
|
2810
|
+
},
|
|
2811
|
+
{
|
|
2812
|
+
name: "env",
|
|
2813
|
+
type: "tuple[]",
|
|
2814
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2815
|
+
components: [
|
|
2816
|
+
{
|
|
2817
|
+
name: "key",
|
|
2818
|
+
type: "string",
|
|
2819
|
+
internalType: "string"
|
|
2820
|
+
},
|
|
2821
|
+
{
|
|
2822
|
+
name: "value",
|
|
2823
|
+
type: "string",
|
|
2824
|
+
internalType: "string"
|
|
2825
|
+
}
|
|
2826
|
+
]
|
|
2827
|
+
},
|
|
2828
|
+
{
|
|
2829
|
+
name: "envOverride",
|
|
2830
|
+
type: "tuple[]",
|
|
2831
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2832
|
+
components: [
|
|
2833
|
+
{
|
|
2834
|
+
name: "key",
|
|
2835
|
+
type: "string",
|
|
2836
|
+
internalType: "string"
|
|
2837
|
+
},
|
|
2838
|
+
{
|
|
2839
|
+
name: "value",
|
|
2840
|
+
type: "string",
|
|
2841
|
+
internalType: "string"
|
|
2842
|
+
}
|
|
2843
|
+
]
|
|
2844
|
+
},
|
|
2845
|
+
{
|
|
2846
|
+
name: "restartPolicy",
|
|
2847
|
+
type: "string",
|
|
2848
|
+
internalType: "string"
|
|
2849
|
+
}
|
|
2850
|
+
]
|
|
2851
|
+
}
|
|
2852
|
+
]
|
|
2853
|
+
}
|
|
2854
|
+
],
|
|
2855
|
+
outputs: [
|
|
2856
|
+
{
|
|
2857
|
+
name: "app",
|
|
2858
|
+
type: "address",
|
|
2859
|
+
internalType: "contractIApp"
|
|
2860
|
+
}
|
|
2861
|
+
],
|
|
2862
|
+
stateMutability: "nonpayable"
|
|
2863
|
+
},
|
|
2864
|
+
{
|
|
2865
|
+
type: "function",
|
|
2866
|
+
name: "createAppWithIsolatedBilling",
|
|
2867
|
+
inputs: [
|
|
2868
|
+
{
|
|
2869
|
+
name: "salt",
|
|
2870
|
+
type: "bytes32",
|
|
2871
|
+
internalType: "bytes32"
|
|
2872
|
+
},
|
|
2873
|
+
{
|
|
2874
|
+
name: "release",
|
|
2875
|
+
type: "tuple",
|
|
2876
|
+
internalType: "structIAppController.Release",
|
|
2877
|
+
components: [
|
|
2878
|
+
{
|
|
2879
|
+
name: "rmsRelease",
|
|
2880
|
+
type: "tuple",
|
|
2881
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
2882
|
+
components: [
|
|
2883
|
+
{
|
|
2884
|
+
name: "artifacts",
|
|
2885
|
+
type: "tuple[]",
|
|
2886
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
2887
|
+
components: [
|
|
2888
|
+
{
|
|
2889
|
+
name: "digest",
|
|
2890
|
+
type: "bytes32",
|
|
2891
|
+
internalType: "bytes32"
|
|
2892
|
+
},
|
|
2893
|
+
{
|
|
2894
|
+
name: "registry",
|
|
2895
|
+
type: "string",
|
|
2896
|
+
internalType: "string"
|
|
2897
|
+
}
|
|
2898
|
+
]
|
|
2899
|
+
},
|
|
2900
|
+
{
|
|
2901
|
+
name: "upgradeByTime",
|
|
2902
|
+
type: "uint32",
|
|
2903
|
+
internalType: "uint32"
|
|
2904
|
+
}
|
|
2905
|
+
]
|
|
2906
|
+
},
|
|
2907
|
+
{
|
|
2908
|
+
name: "publicEnv",
|
|
2909
|
+
type: "bytes",
|
|
2910
|
+
internalType: "bytes"
|
|
2911
|
+
},
|
|
2912
|
+
{
|
|
2913
|
+
name: "encryptedEnv",
|
|
2914
|
+
type: "bytes",
|
|
2915
|
+
internalType: "bytes"
|
|
2916
|
+
},
|
|
2917
|
+
{
|
|
2918
|
+
name: "containerPolicy",
|
|
2919
|
+
type: "tuple",
|
|
2920
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
2921
|
+
components: [
|
|
2922
|
+
{
|
|
2923
|
+
name: "args",
|
|
2924
|
+
type: "string[]",
|
|
2925
|
+
internalType: "string[]"
|
|
2926
|
+
},
|
|
2927
|
+
{
|
|
2928
|
+
name: "cmdOverride",
|
|
2929
|
+
type: "string[]",
|
|
2930
|
+
internalType: "string[]"
|
|
2931
|
+
},
|
|
2932
|
+
{
|
|
2933
|
+
name: "env",
|
|
2934
|
+
type: "tuple[]",
|
|
2935
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2936
|
+
components: [
|
|
2937
|
+
{
|
|
2938
|
+
name: "key",
|
|
2939
|
+
type: "string",
|
|
2940
|
+
internalType: "string"
|
|
2941
|
+
},
|
|
2942
|
+
{
|
|
2943
|
+
name: "value",
|
|
2944
|
+
type: "string",
|
|
2945
|
+
internalType: "string"
|
|
2946
|
+
}
|
|
2947
|
+
]
|
|
2948
|
+
},
|
|
2949
|
+
{
|
|
2950
|
+
name: "envOverride",
|
|
2951
|
+
type: "tuple[]",
|
|
2952
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2953
|
+
components: [
|
|
2954
|
+
{
|
|
2955
|
+
name: "key",
|
|
2956
|
+
type: "string",
|
|
2957
|
+
internalType: "string"
|
|
2958
|
+
},
|
|
2959
|
+
{
|
|
2960
|
+
name: "value",
|
|
2961
|
+
type: "string",
|
|
2962
|
+
internalType: "string"
|
|
2963
|
+
}
|
|
2964
|
+
]
|
|
2965
|
+
},
|
|
2966
|
+
{
|
|
2967
|
+
name: "restartPolicy",
|
|
2968
|
+
type: "string",
|
|
2969
|
+
internalType: "string"
|
|
2970
|
+
}
|
|
2971
|
+
]
|
|
2972
|
+
}
|
|
2973
|
+
]
|
|
2974
|
+
}
|
|
2975
|
+
],
|
|
2976
|
+
outputs: [
|
|
2977
|
+
{
|
|
2978
|
+
name: "app",
|
|
2979
|
+
type: "address",
|
|
2980
|
+
internalType: "contractIApp"
|
|
2981
|
+
}
|
|
2982
|
+
],
|
|
2983
|
+
stateMutability: "nonpayable"
|
|
2984
|
+
},
|
|
2985
|
+
{
|
|
2986
|
+
type: "function",
|
|
2987
|
+
name: "createEmptyApp",
|
|
2988
|
+
inputs: [
|
|
2989
|
+
{
|
|
2990
|
+
name: "salt",
|
|
2991
|
+
type: "bytes32",
|
|
2992
|
+
internalType: "bytes32"
|
|
2993
|
+
}
|
|
2994
|
+
],
|
|
2995
|
+
outputs: [
|
|
2996
|
+
{
|
|
2997
|
+
name: "app",
|
|
2998
|
+
type: "address",
|
|
2999
|
+
internalType: "contractIApp"
|
|
3000
|
+
}
|
|
3001
|
+
],
|
|
3002
|
+
stateMutability: "nonpayable"
|
|
3003
|
+
},
|
|
3004
|
+
{
|
|
3005
|
+
type: "function",
|
|
3006
|
+
name: "createEmptyAppWithIsolatedBilling",
|
|
3007
|
+
inputs: [
|
|
3008
|
+
{
|
|
3009
|
+
name: "salt",
|
|
3010
|
+
type: "bytes32",
|
|
3011
|
+
internalType: "bytes32"
|
|
3012
|
+
}
|
|
3013
|
+
],
|
|
3014
|
+
outputs: [
|
|
3015
|
+
{
|
|
3016
|
+
name: "app",
|
|
3017
|
+
type: "address",
|
|
3018
|
+
internalType: "contractIApp"
|
|
3019
|
+
}
|
|
3020
|
+
],
|
|
3021
|
+
stateMutability: "nonpayable"
|
|
3022
|
+
},
|
|
3023
|
+
{
|
|
3024
|
+
type: "function",
|
|
3025
|
+
name: "domainSeparator",
|
|
3026
|
+
inputs: [],
|
|
3027
|
+
outputs: [
|
|
3028
|
+
{
|
|
3029
|
+
name: "",
|
|
3030
|
+
type: "bytes32",
|
|
3031
|
+
internalType: "bytes32"
|
|
3032
|
+
}
|
|
3033
|
+
],
|
|
3034
|
+
stateMutability: "view"
|
|
3035
|
+
},
|
|
3036
|
+
{
|
|
3037
|
+
type: "function",
|
|
3038
|
+
name: "getActiveAppCount",
|
|
3039
|
+
inputs: [
|
|
3040
|
+
{
|
|
3041
|
+
name: "user",
|
|
3042
|
+
type: "address",
|
|
3043
|
+
internalType: "address"
|
|
3044
|
+
}
|
|
3045
|
+
],
|
|
3046
|
+
outputs: [
|
|
3047
|
+
{
|
|
3048
|
+
name: "",
|
|
3049
|
+
type: "uint32",
|
|
3050
|
+
internalType: "uint32"
|
|
3051
|
+
}
|
|
3052
|
+
],
|
|
3053
|
+
stateMutability: "view"
|
|
3054
|
+
},
|
|
3055
|
+
{
|
|
3056
|
+
type: "function",
|
|
3057
|
+
name: "getAppCreator",
|
|
3058
|
+
inputs: [
|
|
3059
|
+
{
|
|
3060
|
+
name: "app",
|
|
3061
|
+
type: "address",
|
|
3062
|
+
internalType: "contractIApp"
|
|
3063
|
+
}
|
|
3064
|
+
],
|
|
3065
|
+
outputs: [
|
|
3066
|
+
{
|
|
3067
|
+
name: "",
|
|
3068
|
+
type: "address",
|
|
3069
|
+
internalType: "address"
|
|
3070
|
+
}
|
|
3071
|
+
],
|
|
3072
|
+
stateMutability: "view"
|
|
3073
|
+
},
|
|
3074
|
+
{
|
|
3075
|
+
type: "function",
|
|
3076
|
+
name: "getAppLatestReleaseBlockNumber",
|
|
3077
|
+
inputs: [
|
|
3078
|
+
{
|
|
3079
|
+
name: "app",
|
|
3080
|
+
type: "address",
|
|
3081
|
+
internalType: "contractIApp"
|
|
3082
|
+
}
|
|
3083
|
+
],
|
|
3084
|
+
outputs: [
|
|
3085
|
+
{
|
|
3086
|
+
name: "",
|
|
3087
|
+
type: "uint32",
|
|
3088
|
+
internalType: "uint32"
|
|
3089
|
+
}
|
|
3090
|
+
],
|
|
3091
|
+
stateMutability: "view"
|
|
3092
|
+
},
|
|
3093
|
+
{
|
|
3094
|
+
type: "function",
|
|
3095
|
+
name: "getAppOperatorSetId",
|
|
3096
|
+
inputs: [
|
|
3097
|
+
{
|
|
3098
|
+
name: "app",
|
|
3099
|
+
type: "address",
|
|
3100
|
+
internalType: "contractIApp"
|
|
3101
|
+
}
|
|
3102
|
+
],
|
|
3103
|
+
outputs: [
|
|
3104
|
+
{
|
|
3105
|
+
name: "",
|
|
3106
|
+
type: "uint32",
|
|
3107
|
+
internalType: "uint32"
|
|
3108
|
+
}
|
|
3109
|
+
],
|
|
3110
|
+
stateMutability: "view"
|
|
3111
|
+
},
|
|
3112
|
+
{
|
|
3113
|
+
type: "function",
|
|
3114
|
+
name: "getAppPendingReleaseBlockNumber",
|
|
3115
|
+
inputs: [
|
|
3116
|
+
{
|
|
3117
|
+
name: "app",
|
|
3118
|
+
type: "address",
|
|
3119
|
+
internalType: "contractIApp"
|
|
3120
|
+
}
|
|
3121
|
+
],
|
|
3122
|
+
outputs: [
|
|
3123
|
+
{
|
|
3124
|
+
name: "",
|
|
3125
|
+
type: "uint32",
|
|
3126
|
+
internalType: "uint32"
|
|
3127
|
+
}
|
|
3128
|
+
],
|
|
3129
|
+
stateMutability: "view"
|
|
3130
|
+
},
|
|
3131
|
+
{
|
|
3132
|
+
type: "function",
|
|
3133
|
+
name: "getAppStatus",
|
|
3134
|
+
inputs: [
|
|
3135
|
+
{
|
|
3136
|
+
name: "app",
|
|
3137
|
+
type: "address",
|
|
3138
|
+
internalType: "contractIApp"
|
|
3139
|
+
}
|
|
3140
|
+
],
|
|
3141
|
+
outputs: [
|
|
3142
|
+
{
|
|
3143
|
+
name: "",
|
|
3144
|
+
type: "uint8",
|
|
3145
|
+
internalType: "enumIAppController.AppStatus"
|
|
3146
|
+
}
|
|
3147
|
+
],
|
|
3148
|
+
stateMutability: "view"
|
|
3149
|
+
},
|
|
3150
|
+
{
|
|
3151
|
+
type: "function",
|
|
3152
|
+
name: "getApps",
|
|
3153
|
+
inputs: [
|
|
3154
|
+
{
|
|
3155
|
+
name: "offset",
|
|
3156
|
+
type: "uint256",
|
|
3157
|
+
internalType: "uint256"
|
|
3158
|
+
},
|
|
3159
|
+
{
|
|
3160
|
+
name: "limit",
|
|
3161
|
+
type: "uint256",
|
|
3162
|
+
internalType: "uint256"
|
|
3163
|
+
}
|
|
3164
|
+
],
|
|
3165
|
+
outputs: [
|
|
3166
|
+
{
|
|
3167
|
+
name: "apps",
|
|
3168
|
+
type: "address[]",
|
|
3169
|
+
internalType: "contractIApp[]"
|
|
3170
|
+
},
|
|
3171
|
+
{
|
|
3172
|
+
name: "appConfigsMem",
|
|
3173
|
+
type: "tuple[]",
|
|
3174
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3175
|
+
components: [
|
|
3176
|
+
{
|
|
3177
|
+
name: "creator",
|
|
3178
|
+
type: "address",
|
|
3179
|
+
internalType: "address"
|
|
3180
|
+
},
|
|
3181
|
+
{
|
|
3182
|
+
name: "operatorSetId",
|
|
3183
|
+
type: "uint32",
|
|
3184
|
+
internalType: "uint32"
|
|
3185
|
+
},
|
|
3186
|
+
{
|
|
3187
|
+
name: "latestReleaseBlockNumber",
|
|
3188
|
+
type: "uint32",
|
|
3189
|
+
internalType: "uint32"
|
|
3190
|
+
},
|
|
3191
|
+
{
|
|
3192
|
+
name: "pendingReleaseBlockNumber",
|
|
3193
|
+
type: "uint32",
|
|
3194
|
+
internalType: "uint32"
|
|
3195
|
+
},
|
|
3196
|
+
{
|
|
3197
|
+
name: "status",
|
|
3198
|
+
type: "uint8",
|
|
3199
|
+
internalType: "enumIAppController.AppStatus"
|
|
3200
|
+
}
|
|
3201
|
+
]
|
|
3202
|
+
}
|
|
3203
|
+
],
|
|
3204
|
+
stateMutability: "view"
|
|
3205
|
+
},
|
|
3206
|
+
{
|
|
3207
|
+
type: "function",
|
|
3208
|
+
name: "getAppsByBillingAccount",
|
|
3209
|
+
inputs: [
|
|
3210
|
+
{
|
|
3211
|
+
name: "account",
|
|
3212
|
+
type: "address",
|
|
3213
|
+
internalType: "address"
|
|
3214
|
+
},
|
|
3215
|
+
{
|
|
3216
|
+
name: "offset",
|
|
3217
|
+
type: "uint256",
|
|
3218
|
+
internalType: "uint256"
|
|
3219
|
+
},
|
|
3220
|
+
{
|
|
3221
|
+
name: "limit",
|
|
3222
|
+
type: "uint256",
|
|
3223
|
+
internalType: "uint256"
|
|
3224
|
+
}
|
|
3225
|
+
],
|
|
3226
|
+
outputs: [
|
|
3227
|
+
{
|
|
3228
|
+
name: "apps",
|
|
3229
|
+
type: "address[]",
|
|
3230
|
+
internalType: "contractIApp[]"
|
|
3231
|
+
},
|
|
3232
|
+
{
|
|
3233
|
+
name: "appConfigsMem",
|
|
3234
|
+
type: "tuple[]",
|
|
3235
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3236
|
+
components: [
|
|
3237
|
+
{
|
|
3238
|
+
name: "creator",
|
|
3239
|
+
type: "address",
|
|
3240
|
+
internalType: "address"
|
|
3241
|
+
},
|
|
3242
|
+
{
|
|
3243
|
+
name: "operatorSetId",
|
|
3244
|
+
type: "uint32",
|
|
3245
|
+
internalType: "uint32"
|
|
3246
|
+
},
|
|
3247
|
+
{
|
|
3248
|
+
name: "latestReleaseBlockNumber",
|
|
3249
|
+
type: "uint32",
|
|
3250
|
+
internalType: "uint32"
|
|
3251
|
+
},
|
|
3252
|
+
{
|
|
3253
|
+
name: "pendingReleaseBlockNumber",
|
|
3254
|
+
type: "uint32",
|
|
3255
|
+
internalType: "uint32"
|
|
3256
|
+
},
|
|
3257
|
+
{
|
|
3258
|
+
name: "status",
|
|
3259
|
+
type: "uint8",
|
|
3260
|
+
internalType: "enumIAppController.AppStatus"
|
|
3261
|
+
}
|
|
3262
|
+
]
|
|
3263
|
+
}
|
|
3264
|
+
],
|
|
3265
|
+
stateMutability: "view"
|
|
3266
|
+
},
|
|
3267
|
+
{
|
|
3268
|
+
type: "function",
|
|
3269
|
+
name: "getAppsByCreator",
|
|
3270
|
+
inputs: [
|
|
3271
|
+
{
|
|
3272
|
+
name: "creator",
|
|
3273
|
+
type: "address",
|
|
3274
|
+
internalType: "address"
|
|
3275
|
+
},
|
|
3276
|
+
{
|
|
3277
|
+
name: "offset",
|
|
3278
|
+
type: "uint256",
|
|
3279
|
+
internalType: "uint256"
|
|
3280
|
+
},
|
|
3281
|
+
{
|
|
3282
|
+
name: "limit",
|
|
3283
|
+
type: "uint256",
|
|
3284
|
+
internalType: "uint256"
|
|
3285
|
+
}
|
|
3286
|
+
],
|
|
3287
|
+
outputs: [
|
|
3288
|
+
{
|
|
3289
|
+
name: "apps",
|
|
3290
|
+
type: "address[]",
|
|
3291
|
+
internalType: "contractIApp[]"
|
|
3292
|
+
},
|
|
3293
|
+
{
|
|
3294
|
+
name: "appConfigsMem",
|
|
3295
|
+
type: "tuple[]",
|
|
3296
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3297
|
+
components: [
|
|
3298
|
+
{
|
|
3299
|
+
name: "creator",
|
|
3300
|
+
type: "address",
|
|
3301
|
+
internalType: "address"
|
|
3302
|
+
},
|
|
3303
|
+
{
|
|
3304
|
+
name: "operatorSetId",
|
|
3305
|
+
type: "uint32",
|
|
3306
|
+
internalType: "uint32"
|
|
3307
|
+
},
|
|
3308
|
+
{
|
|
3309
|
+
name: "latestReleaseBlockNumber",
|
|
3310
|
+
type: "uint32",
|
|
3311
|
+
internalType: "uint32"
|
|
3312
|
+
},
|
|
3313
|
+
{
|
|
3314
|
+
name: "pendingReleaseBlockNumber",
|
|
3315
|
+
type: "uint32",
|
|
3316
|
+
internalType: "uint32"
|
|
3317
|
+
},
|
|
3318
|
+
{
|
|
3319
|
+
name: "status",
|
|
3320
|
+
type: "uint8",
|
|
3321
|
+
internalType: "enumIAppController.AppStatus"
|
|
3322
|
+
}
|
|
3323
|
+
]
|
|
3324
|
+
}
|
|
3325
|
+
],
|
|
3326
|
+
stateMutability: "view"
|
|
3327
|
+
},
|
|
3328
|
+
{
|
|
3329
|
+
type: "function",
|
|
3330
|
+
name: "getAppsByDeveloper",
|
|
3331
|
+
inputs: [
|
|
3332
|
+
{
|
|
3333
|
+
name: "developer",
|
|
3334
|
+
type: "address",
|
|
3335
|
+
internalType: "address"
|
|
3336
|
+
},
|
|
3337
|
+
{
|
|
3338
|
+
name: "offset",
|
|
3339
|
+
type: "uint256",
|
|
3340
|
+
internalType: "uint256"
|
|
3341
|
+
},
|
|
3342
|
+
{
|
|
3343
|
+
name: "limit",
|
|
3344
|
+
type: "uint256",
|
|
3345
|
+
internalType: "uint256"
|
|
3346
|
+
}
|
|
3347
|
+
],
|
|
3348
|
+
outputs: [
|
|
3349
|
+
{
|
|
3350
|
+
name: "apps",
|
|
3351
|
+
type: "address[]",
|
|
3352
|
+
internalType: "contractIApp[]"
|
|
3353
|
+
},
|
|
3354
|
+
{
|
|
3355
|
+
name: "appConfigsMem",
|
|
3356
|
+
type: "tuple[]",
|
|
3357
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3358
|
+
components: [
|
|
3359
|
+
{
|
|
3360
|
+
name: "creator",
|
|
3361
|
+
type: "address",
|
|
3362
|
+
internalType: "address"
|
|
3363
|
+
},
|
|
3364
|
+
{
|
|
3365
|
+
name: "operatorSetId",
|
|
3366
|
+
type: "uint32",
|
|
3367
|
+
internalType: "uint32"
|
|
3368
|
+
},
|
|
3369
|
+
{
|
|
3370
|
+
name: "latestReleaseBlockNumber",
|
|
3371
|
+
type: "uint32",
|
|
3372
|
+
internalType: "uint32"
|
|
3373
|
+
},
|
|
3374
|
+
{
|
|
3375
|
+
name: "pendingReleaseBlockNumber",
|
|
3376
|
+
type: "uint32",
|
|
3377
|
+
internalType: "uint32"
|
|
3378
|
+
},
|
|
3379
|
+
{
|
|
3380
|
+
name: "status",
|
|
3381
|
+
type: "uint8",
|
|
3382
|
+
internalType: "enumIAppController.AppStatus"
|
|
3383
|
+
}
|
|
3384
|
+
]
|
|
3385
|
+
}
|
|
3386
|
+
],
|
|
3387
|
+
stateMutability: "view"
|
|
3388
|
+
},
|
|
3389
|
+
{
|
|
3390
|
+
type: "function",
|
|
3391
|
+
name: "getBillingAccount",
|
|
3392
|
+
inputs: [
|
|
3393
|
+
{
|
|
3394
|
+
name: "app",
|
|
3395
|
+
type: "address",
|
|
3396
|
+
internalType: "contractIApp"
|
|
3397
|
+
}
|
|
3398
|
+
],
|
|
3399
|
+
outputs: [
|
|
3400
|
+
{
|
|
3401
|
+
name: "",
|
|
3402
|
+
type: "address",
|
|
3403
|
+
internalType: "address"
|
|
3404
|
+
}
|
|
3405
|
+
],
|
|
3406
|
+
stateMutability: "view"
|
|
3407
|
+
},
|
|
3408
|
+
{
|
|
3409
|
+
type: "function",
|
|
3410
|
+
name: "getBillingType",
|
|
3411
|
+
inputs: [
|
|
3412
|
+
{
|
|
3413
|
+
name: "app",
|
|
3414
|
+
type: "address",
|
|
3415
|
+
internalType: "contractIApp"
|
|
3416
|
+
}
|
|
3417
|
+
],
|
|
3418
|
+
outputs: [
|
|
3419
|
+
{
|
|
3420
|
+
name: "",
|
|
3421
|
+
type: "uint8",
|
|
3422
|
+
internalType: "enumIAppController.BillingType"
|
|
3423
|
+
}
|
|
3424
|
+
],
|
|
3425
|
+
stateMutability: "view"
|
|
3426
|
+
},
|
|
3427
|
+
{
|
|
3428
|
+
type: "function",
|
|
3429
|
+
name: "getMaxActiveAppsPerUser",
|
|
3430
|
+
inputs: [
|
|
3431
|
+
{
|
|
3432
|
+
name: "user",
|
|
3433
|
+
type: "address",
|
|
3434
|
+
internalType: "address"
|
|
3435
|
+
}
|
|
3436
|
+
],
|
|
3437
|
+
outputs: [
|
|
3438
|
+
{
|
|
3439
|
+
name: "",
|
|
3440
|
+
type: "uint32",
|
|
3441
|
+
internalType: "uint32"
|
|
3442
|
+
}
|
|
3443
|
+
],
|
|
3444
|
+
stateMutability: "view"
|
|
3445
|
+
},
|
|
3446
|
+
{
|
|
3447
|
+
type: "function",
|
|
3448
|
+
name: "globalActiveAppCount",
|
|
3449
|
+
inputs: [],
|
|
3450
|
+
outputs: [
|
|
3451
|
+
{
|
|
3452
|
+
name: "",
|
|
3453
|
+
type: "uint32",
|
|
3454
|
+
internalType: "uint32"
|
|
3455
|
+
}
|
|
3456
|
+
],
|
|
3457
|
+
stateMutability: "view"
|
|
3458
|
+
},
|
|
3459
|
+
{
|
|
3460
|
+
type: "function",
|
|
3461
|
+
name: "initialize",
|
|
3462
|
+
inputs: [
|
|
3463
|
+
{
|
|
3464
|
+
name: "admin",
|
|
3465
|
+
type: "address",
|
|
3466
|
+
internalType: "address"
|
|
3467
|
+
}
|
|
3468
|
+
],
|
|
3469
|
+
outputs: [],
|
|
3470
|
+
stateMutability: "nonpayable"
|
|
3471
|
+
},
|
|
3472
|
+
{
|
|
3473
|
+
type: "function",
|
|
3474
|
+
name: "maxGlobalActiveApps",
|
|
3475
|
+
inputs: [],
|
|
3476
|
+
outputs: [
|
|
3477
|
+
{
|
|
3478
|
+
name: "",
|
|
3479
|
+
type: "uint32",
|
|
3480
|
+
internalType: "uint32"
|
|
3481
|
+
}
|
|
3482
|
+
],
|
|
3483
|
+
stateMutability: "view"
|
|
3484
|
+
},
|
|
3485
|
+
{
|
|
3486
|
+
type: "function",
|
|
3487
|
+
name: "permissionController",
|
|
3488
|
+
inputs: [],
|
|
3489
|
+
outputs: [
|
|
3490
|
+
{
|
|
3491
|
+
name: "",
|
|
3492
|
+
type: "address",
|
|
3493
|
+
internalType: "contractIPermissionController"
|
|
3494
|
+
}
|
|
3495
|
+
],
|
|
3496
|
+
stateMutability: "view"
|
|
3497
|
+
},
|
|
3498
|
+
{
|
|
3499
|
+
type: "function",
|
|
3500
|
+
name: "releaseManager",
|
|
3501
|
+
inputs: [],
|
|
3502
|
+
outputs: [
|
|
3503
|
+
{
|
|
3504
|
+
name: "",
|
|
3505
|
+
type: "address",
|
|
3506
|
+
internalType: "contractIReleaseManager"
|
|
3507
|
+
}
|
|
3508
|
+
],
|
|
3509
|
+
stateMutability: "view"
|
|
3510
|
+
},
|
|
3511
|
+
{
|
|
3512
|
+
type: "function",
|
|
3513
|
+
name: "setMaxActiveAppsPerUser",
|
|
3514
|
+
inputs: [
|
|
3515
|
+
{
|
|
3516
|
+
name: "user",
|
|
3517
|
+
type: "address",
|
|
3518
|
+
internalType: "address"
|
|
3519
|
+
},
|
|
3520
|
+
{
|
|
3521
|
+
name: "limit",
|
|
3522
|
+
type: "uint32",
|
|
3523
|
+
internalType: "uint32"
|
|
3524
|
+
}
|
|
3525
|
+
],
|
|
3526
|
+
outputs: [],
|
|
3527
|
+
stateMutability: "nonpayable"
|
|
3528
|
+
},
|
|
3529
|
+
{
|
|
3530
|
+
type: "function",
|
|
3531
|
+
name: "setMaxGlobalActiveApps",
|
|
3532
|
+
inputs: [
|
|
3533
|
+
{
|
|
3534
|
+
name: "limit",
|
|
3535
|
+
type: "uint32",
|
|
3536
|
+
internalType: "uint32"
|
|
3537
|
+
}
|
|
3538
|
+
],
|
|
3539
|
+
outputs: [],
|
|
3540
|
+
stateMutability: "nonpayable"
|
|
3541
|
+
},
|
|
3542
|
+
{
|
|
3543
|
+
type: "function",
|
|
3544
|
+
name: "startApp",
|
|
3545
|
+
inputs: [
|
|
3546
|
+
{
|
|
3547
|
+
name: "app",
|
|
3548
|
+
type: "address",
|
|
3549
|
+
internalType: "contractIApp"
|
|
3550
|
+
}
|
|
3551
|
+
],
|
|
3552
|
+
outputs: [],
|
|
3553
|
+
stateMutability: "nonpayable"
|
|
3554
|
+
},
|
|
3555
|
+
{
|
|
3556
|
+
type: "function",
|
|
3557
|
+
name: "stopApp",
|
|
3558
|
+
inputs: [
|
|
3559
|
+
{
|
|
3560
|
+
name: "app",
|
|
3561
|
+
type: "address",
|
|
3562
|
+
internalType: "contractIApp"
|
|
3563
|
+
}
|
|
3564
|
+
],
|
|
3565
|
+
outputs: [],
|
|
3566
|
+
stateMutability: "nonpayable"
|
|
3567
|
+
},
|
|
3568
|
+
{
|
|
3569
|
+
type: "function",
|
|
3570
|
+
name: "suspend",
|
|
3571
|
+
inputs: [
|
|
3572
|
+
{
|
|
3573
|
+
name: "account",
|
|
3574
|
+
type: "address",
|
|
3575
|
+
internalType: "address"
|
|
3576
|
+
},
|
|
3577
|
+
{
|
|
3578
|
+
name: "apps",
|
|
3579
|
+
type: "address[]",
|
|
3580
|
+
internalType: "contractIApp[]"
|
|
3581
|
+
}
|
|
3582
|
+
],
|
|
3583
|
+
outputs: [],
|
|
3584
|
+
stateMutability: "nonpayable"
|
|
3585
|
+
},
|
|
3586
|
+
{
|
|
3587
|
+
type: "function",
|
|
3588
|
+
name: "terminateApp",
|
|
3589
|
+
inputs: [
|
|
3590
|
+
{
|
|
3591
|
+
name: "app",
|
|
3592
|
+
type: "address",
|
|
3593
|
+
internalType: "contractIApp"
|
|
3594
|
+
}
|
|
3595
|
+
],
|
|
3596
|
+
outputs: [],
|
|
3597
|
+
stateMutability: "nonpayable"
|
|
3598
|
+
},
|
|
3599
|
+
{
|
|
3600
|
+
type: "function",
|
|
3601
|
+
name: "terminateAppByAdmin",
|
|
3602
|
+
inputs: [
|
|
3603
|
+
{
|
|
3604
|
+
name: "app",
|
|
3605
|
+
type: "address",
|
|
3606
|
+
internalType: "contractIApp"
|
|
3607
|
+
}
|
|
3608
|
+
],
|
|
3609
|
+
outputs: [],
|
|
3610
|
+
stateMutability: "nonpayable"
|
|
3611
|
+
},
|
|
3612
|
+
{
|
|
3613
|
+
type: "function",
|
|
3614
|
+
name: "updateAppMetadataURI",
|
|
3615
|
+
inputs: [
|
|
3616
|
+
{
|
|
3617
|
+
name: "app",
|
|
3618
|
+
type: "address",
|
|
3619
|
+
internalType: "contractIApp"
|
|
3620
|
+
},
|
|
3621
|
+
{
|
|
3622
|
+
name: "metadataURI",
|
|
3623
|
+
type: "string",
|
|
3624
|
+
internalType: "string"
|
|
3625
|
+
}
|
|
3626
|
+
],
|
|
3627
|
+
outputs: [],
|
|
3628
|
+
stateMutability: "nonpayable"
|
|
3629
|
+
},
|
|
3630
|
+
{
|
|
3631
|
+
type: "function",
|
|
3632
|
+
name: "upgradeApp",
|
|
3633
|
+
inputs: [
|
|
3634
|
+
{
|
|
3635
|
+
name: "app",
|
|
3636
|
+
type: "address",
|
|
3637
|
+
internalType: "contractIApp"
|
|
3638
|
+
},
|
|
3639
|
+
{
|
|
3640
|
+
name: "release",
|
|
3641
|
+
type: "tuple",
|
|
3642
|
+
internalType: "structIAppController.Release",
|
|
3643
|
+
components: [
|
|
3644
|
+
{
|
|
3645
|
+
name: "rmsRelease",
|
|
3646
|
+
type: "tuple",
|
|
3647
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
3648
|
+
components: [
|
|
3649
|
+
{
|
|
3650
|
+
name: "artifacts",
|
|
3651
|
+
type: "tuple[]",
|
|
3652
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
3653
|
+
components: [
|
|
3654
|
+
{
|
|
3655
|
+
name: "digest",
|
|
3656
|
+
type: "bytes32",
|
|
3657
|
+
internalType: "bytes32"
|
|
3658
|
+
},
|
|
3659
|
+
{
|
|
3660
|
+
name: "registry",
|
|
3661
|
+
type: "string",
|
|
3662
|
+
internalType: "string"
|
|
3663
|
+
}
|
|
3664
|
+
]
|
|
3665
|
+
},
|
|
3666
|
+
{
|
|
3667
|
+
name: "upgradeByTime",
|
|
3668
|
+
type: "uint32",
|
|
3669
|
+
internalType: "uint32"
|
|
3670
|
+
}
|
|
3671
|
+
]
|
|
3672
|
+
},
|
|
3673
|
+
{
|
|
3674
|
+
name: "publicEnv",
|
|
3675
|
+
type: "bytes",
|
|
3676
|
+
internalType: "bytes"
|
|
3677
|
+
},
|
|
3678
|
+
{
|
|
3679
|
+
name: "encryptedEnv",
|
|
3680
|
+
type: "bytes",
|
|
3681
|
+
internalType: "bytes"
|
|
3682
|
+
},
|
|
3683
|
+
{
|
|
3684
|
+
name: "containerPolicy",
|
|
3685
|
+
type: "tuple",
|
|
3686
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
3687
|
+
components: [
|
|
3688
|
+
{
|
|
3689
|
+
name: "args",
|
|
3690
|
+
type: "string[]",
|
|
3691
|
+
internalType: "string[]"
|
|
3692
|
+
},
|
|
3693
|
+
{
|
|
3694
|
+
name: "cmdOverride",
|
|
3695
|
+
type: "string[]",
|
|
3696
|
+
internalType: "string[]"
|
|
3697
|
+
},
|
|
3698
|
+
{
|
|
3699
|
+
name: "env",
|
|
3700
|
+
type: "tuple[]",
|
|
3701
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3702
|
+
components: [
|
|
3703
|
+
{
|
|
3704
|
+
name: "key",
|
|
3705
|
+
type: "string",
|
|
3706
|
+
internalType: "string"
|
|
3707
|
+
},
|
|
3708
|
+
{
|
|
3709
|
+
name: "value",
|
|
3710
|
+
type: "string",
|
|
3711
|
+
internalType: "string"
|
|
3712
|
+
}
|
|
3713
|
+
]
|
|
3714
|
+
},
|
|
3715
|
+
{
|
|
3716
|
+
name: "envOverride",
|
|
3717
|
+
type: "tuple[]",
|
|
3718
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3719
|
+
components: [
|
|
3720
|
+
{
|
|
3721
|
+
name: "key",
|
|
3722
|
+
type: "string",
|
|
3723
|
+
internalType: "string"
|
|
3724
|
+
},
|
|
3725
|
+
{
|
|
3726
|
+
name: "value",
|
|
3727
|
+
type: "string",
|
|
3728
|
+
internalType: "string"
|
|
3729
|
+
}
|
|
3730
|
+
]
|
|
3731
|
+
},
|
|
3732
|
+
{
|
|
3733
|
+
name: "restartPolicy",
|
|
3734
|
+
type: "string",
|
|
3735
|
+
internalType: "string"
|
|
3736
|
+
}
|
|
3737
|
+
]
|
|
3738
|
+
}
|
|
3739
|
+
]
|
|
3740
|
+
}
|
|
3741
|
+
],
|
|
3742
|
+
outputs: [
|
|
3743
|
+
{
|
|
3744
|
+
name: "",
|
|
3745
|
+
type: "uint256",
|
|
3746
|
+
internalType: "uint256"
|
|
3747
|
+
}
|
|
3748
|
+
],
|
|
3749
|
+
stateMutability: "nonpayable"
|
|
3750
|
+
},
|
|
3751
|
+
{
|
|
3752
|
+
type: "function",
|
|
3753
|
+
name: "version",
|
|
3754
|
+
inputs: [],
|
|
3755
|
+
outputs: [
|
|
3756
|
+
{
|
|
3757
|
+
name: "",
|
|
3758
|
+
type: "string",
|
|
3759
|
+
internalType: "string"
|
|
3760
|
+
}
|
|
3761
|
+
],
|
|
3762
|
+
stateMutability: "view"
|
|
3763
|
+
},
|
|
3764
|
+
{
|
|
3765
|
+
type: "event",
|
|
3766
|
+
name: "AppCreated",
|
|
3767
|
+
inputs: [
|
|
3768
|
+
{
|
|
3769
|
+
name: "creator",
|
|
3770
|
+
type: "address",
|
|
3771
|
+
indexed: true,
|
|
3772
|
+
internalType: "address"
|
|
3773
|
+
},
|
|
3774
|
+
{
|
|
3775
|
+
name: "app",
|
|
3776
|
+
type: "address",
|
|
3777
|
+
indexed: true,
|
|
3778
|
+
internalType: "contractIApp"
|
|
3779
|
+
},
|
|
3780
|
+
{
|
|
3781
|
+
name: "operatorSetId",
|
|
3782
|
+
type: "uint32",
|
|
3783
|
+
indexed: false,
|
|
3784
|
+
internalType: "uint32"
|
|
3785
|
+
}
|
|
3786
|
+
],
|
|
3787
|
+
anonymous: false
|
|
3788
|
+
},
|
|
3789
|
+
{
|
|
3790
|
+
type: "event",
|
|
3791
|
+
name: "AppMetadataURIUpdated",
|
|
3792
|
+
inputs: [
|
|
3793
|
+
{
|
|
3794
|
+
name: "app",
|
|
3795
|
+
type: "address",
|
|
3796
|
+
indexed: true,
|
|
3797
|
+
internalType: "contractIApp"
|
|
3798
|
+
},
|
|
3799
|
+
{
|
|
3800
|
+
name: "metadataURI",
|
|
3801
|
+
type: "string",
|
|
3802
|
+
indexed: false,
|
|
3803
|
+
internalType: "string"
|
|
3804
|
+
}
|
|
3805
|
+
],
|
|
3806
|
+
anonymous: false
|
|
3807
|
+
},
|
|
3808
|
+
{
|
|
3809
|
+
type: "event",
|
|
3810
|
+
name: "AppStarted",
|
|
3811
|
+
inputs: [
|
|
3812
|
+
{
|
|
3813
|
+
name: "app",
|
|
3814
|
+
type: "address",
|
|
3815
|
+
indexed: true,
|
|
3816
|
+
internalType: "contractIApp"
|
|
3817
|
+
}
|
|
3818
|
+
],
|
|
3819
|
+
anonymous: false
|
|
3820
|
+
},
|
|
3821
|
+
{
|
|
3822
|
+
type: "event",
|
|
3823
|
+
name: "AppStopped",
|
|
3824
|
+
inputs: [
|
|
3825
|
+
{
|
|
3826
|
+
name: "app",
|
|
3827
|
+
type: "address",
|
|
3828
|
+
indexed: true,
|
|
3829
|
+
internalType: "contractIApp"
|
|
3830
|
+
}
|
|
3831
|
+
],
|
|
3832
|
+
anonymous: false
|
|
3833
|
+
},
|
|
3834
|
+
{
|
|
3835
|
+
type: "event",
|
|
3836
|
+
name: "AppSuspended",
|
|
3837
|
+
inputs: [
|
|
3838
|
+
{
|
|
3839
|
+
name: "app",
|
|
3840
|
+
type: "address",
|
|
3841
|
+
indexed: true,
|
|
3842
|
+
internalType: "contractIApp"
|
|
3843
|
+
}
|
|
3844
|
+
],
|
|
3845
|
+
anonymous: false
|
|
3846
|
+
},
|
|
3847
|
+
{
|
|
3848
|
+
type: "event",
|
|
3849
|
+
name: "AppTerminated",
|
|
3850
|
+
inputs: [
|
|
3851
|
+
{
|
|
3852
|
+
name: "app",
|
|
3853
|
+
type: "address",
|
|
3854
|
+
indexed: true,
|
|
3855
|
+
internalType: "contractIApp"
|
|
3856
|
+
}
|
|
3857
|
+
],
|
|
3858
|
+
anonymous: false
|
|
3859
|
+
},
|
|
3860
|
+
{
|
|
3861
|
+
type: "event",
|
|
3862
|
+
name: "AppTerminatedByAdmin",
|
|
3863
|
+
inputs: [
|
|
3864
|
+
{
|
|
3865
|
+
name: "app",
|
|
3866
|
+
type: "address",
|
|
3867
|
+
indexed: true,
|
|
3868
|
+
internalType: "contractIApp"
|
|
3869
|
+
}
|
|
3870
|
+
],
|
|
3871
|
+
anonymous: false
|
|
3872
|
+
},
|
|
3873
|
+
{
|
|
3874
|
+
type: "event",
|
|
3875
|
+
name: "AppUpgraded",
|
|
3876
|
+
inputs: [
|
|
3877
|
+
{
|
|
3878
|
+
name: "app",
|
|
3879
|
+
type: "address",
|
|
3880
|
+
indexed: true,
|
|
3881
|
+
internalType: "contractIApp"
|
|
3882
|
+
},
|
|
3883
|
+
{
|
|
3884
|
+
name: "rmsReleaseId",
|
|
3885
|
+
type: "uint256",
|
|
3886
|
+
indexed: false,
|
|
3887
|
+
internalType: "uint256"
|
|
3888
|
+
},
|
|
3889
|
+
{
|
|
3890
|
+
name: "release",
|
|
3891
|
+
type: "tuple",
|
|
3892
|
+
indexed: false,
|
|
3893
|
+
internalType: "structIAppController.Release",
|
|
3894
|
+
components: [
|
|
3895
|
+
{
|
|
3896
|
+
name: "rmsRelease",
|
|
3897
|
+
type: "tuple",
|
|
3898
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
3899
|
+
components: [
|
|
3900
|
+
{
|
|
3901
|
+
name: "artifacts",
|
|
3902
|
+
type: "tuple[]",
|
|
3903
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
3904
|
+
components: [
|
|
3905
|
+
{
|
|
3906
|
+
name: "digest",
|
|
3907
|
+
type: "bytes32",
|
|
3908
|
+
internalType: "bytes32"
|
|
3909
|
+
},
|
|
3910
|
+
{
|
|
3911
|
+
name: "registry",
|
|
3912
|
+
type: "string",
|
|
3913
|
+
internalType: "string"
|
|
3914
|
+
}
|
|
3915
|
+
]
|
|
3916
|
+
},
|
|
3917
|
+
{
|
|
3918
|
+
name: "upgradeByTime",
|
|
3919
|
+
type: "uint32",
|
|
3920
|
+
internalType: "uint32"
|
|
3921
|
+
}
|
|
3922
|
+
]
|
|
3923
|
+
},
|
|
3924
|
+
{
|
|
3925
|
+
name: "publicEnv",
|
|
3926
|
+
type: "bytes",
|
|
3927
|
+
internalType: "bytes"
|
|
3928
|
+
},
|
|
3929
|
+
{
|
|
3930
|
+
name: "encryptedEnv",
|
|
3931
|
+
type: "bytes",
|
|
3932
|
+
internalType: "bytes"
|
|
3933
|
+
},
|
|
3934
|
+
{
|
|
3935
|
+
name: "containerPolicy",
|
|
3936
|
+
type: "tuple",
|
|
3937
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
3938
|
+
components: [
|
|
3939
|
+
{
|
|
3940
|
+
name: "args",
|
|
3941
|
+
type: "string[]",
|
|
3942
|
+
internalType: "string[]"
|
|
3943
|
+
},
|
|
3944
|
+
{
|
|
3945
|
+
name: "cmdOverride",
|
|
3946
|
+
type: "string[]",
|
|
3947
|
+
internalType: "string[]"
|
|
3948
|
+
},
|
|
3949
|
+
{
|
|
3950
|
+
name: "env",
|
|
3951
|
+
type: "tuple[]",
|
|
3952
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3953
|
+
components: [
|
|
3954
|
+
{
|
|
3955
|
+
name: "key",
|
|
3956
|
+
type: "string",
|
|
3957
|
+
internalType: "string"
|
|
3958
|
+
},
|
|
3959
|
+
{
|
|
3960
|
+
name: "value",
|
|
3961
|
+
type: "string",
|
|
3962
|
+
internalType: "string"
|
|
3963
|
+
}
|
|
3964
|
+
]
|
|
3965
|
+
},
|
|
3966
|
+
{
|
|
3967
|
+
name: "envOverride",
|
|
3968
|
+
type: "tuple[]",
|
|
3969
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3970
|
+
components: [
|
|
3971
|
+
{
|
|
3972
|
+
name: "key",
|
|
3973
|
+
type: "string",
|
|
3974
|
+
internalType: "string"
|
|
3975
|
+
},
|
|
3976
|
+
{
|
|
3977
|
+
name: "value",
|
|
3978
|
+
type: "string",
|
|
3979
|
+
internalType: "string"
|
|
3980
|
+
}
|
|
3981
|
+
]
|
|
3982
|
+
},
|
|
3983
|
+
{
|
|
3984
|
+
name: "restartPolicy",
|
|
3985
|
+
type: "string",
|
|
3986
|
+
internalType: "string"
|
|
3987
|
+
}
|
|
3988
|
+
]
|
|
3989
|
+
}
|
|
3990
|
+
]
|
|
3991
|
+
}
|
|
3992
|
+
],
|
|
3993
|
+
anonymous: false
|
|
3994
|
+
},
|
|
3995
|
+
{
|
|
3996
|
+
type: "event",
|
|
3997
|
+
name: "GlobalMaxActiveAppsSet",
|
|
3998
|
+
inputs: [
|
|
3999
|
+
{
|
|
4000
|
+
name: "limit",
|
|
4001
|
+
type: "uint32",
|
|
4002
|
+
indexed: false,
|
|
4003
|
+
internalType: "uint32"
|
|
4004
|
+
}
|
|
4005
|
+
],
|
|
4006
|
+
anonymous: false
|
|
4007
|
+
},
|
|
4008
|
+
{
|
|
4009
|
+
type: "event",
|
|
4010
|
+
name: "Initialized",
|
|
4011
|
+
inputs: [
|
|
4012
|
+
{
|
|
4013
|
+
name: "version",
|
|
4014
|
+
type: "uint8",
|
|
4015
|
+
indexed: false,
|
|
4016
|
+
internalType: "uint8"
|
|
4017
|
+
}
|
|
4018
|
+
],
|
|
4019
|
+
anonymous: false
|
|
4020
|
+
},
|
|
4021
|
+
{
|
|
4022
|
+
type: "event",
|
|
4023
|
+
name: "MaxActiveAppsSet",
|
|
4024
|
+
inputs: [
|
|
4025
|
+
{
|
|
4026
|
+
name: "user",
|
|
4027
|
+
type: "address",
|
|
4028
|
+
indexed: true,
|
|
4029
|
+
internalType: "address"
|
|
4030
|
+
},
|
|
4031
|
+
{
|
|
4032
|
+
name: "limit",
|
|
4033
|
+
type: "uint32",
|
|
4034
|
+
indexed: false,
|
|
4035
|
+
internalType: "uint32"
|
|
4036
|
+
}
|
|
4037
|
+
],
|
|
4038
|
+
anonymous: false
|
|
4039
|
+
},
|
|
4040
|
+
{
|
|
4041
|
+
type: "event",
|
|
4042
|
+
name: "UpgradeConfirmed",
|
|
4043
|
+
inputs: [
|
|
4044
|
+
{
|
|
4045
|
+
name: "app",
|
|
4046
|
+
type: "address",
|
|
4047
|
+
indexed: true,
|
|
4048
|
+
internalType: "contractIApp"
|
|
4049
|
+
},
|
|
4050
|
+
{
|
|
4051
|
+
name: "pendingReleaseBlockNumber",
|
|
4052
|
+
type: "uint32",
|
|
4053
|
+
indexed: false,
|
|
4054
|
+
internalType: "uint32"
|
|
4055
|
+
}
|
|
4056
|
+
],
|
|
4057
|
+
anonymous: false
|
|
4058
|
+
},
|
|
4059
|
+
{
|
|
4060
|
+
type: "error",
|
|
4061
|
+
name: "AccountHasActiveApps",
|
|
4062
|
+
inputs: []
|
|
4063
|
+
},
|
|
4064
|
+
{
|
|
4065
|
+
type: "error",
|
|
4066
|
+
name: "AppAlreadyExists",
|
|
4067
|
+
inputs: []
|
|
4068
|
+
},
|
|
4069
|
+
{
|
|
4070
|
+
type: "error",
|
|
4071
|
+
name: "AppDoesNotExist",
|
|
4072
|
+
inputs: []
|
|
4073
|
+
},
|
|
4074
|
+
{
|
|
4075
|
+
type: "error",
|
|
4076
|
+
name: "GlobalMaxActiveAppsExceeded",
|
|
4077
|
+
inputs: []
|
|
4078
|
+
},
|
|
4079
|
+
{
|
|
4080
|
+
type: "error",
|
|
4081
|
+
name: "InvalidAppStatus",
|
|
4082
|
+
inputs: []
|
|
4083
|
+
},
|
|
4084
|
+
{
|
|
4085
|
+
type: "error",
|
|
4086
|
+
name: "InvalidPermissions",
|
|
4087
|
+
inputs: []
|
|
4088
|
+
},
|
|
4089
|
+
{
|
|
4090
|
+
type: "error",
|
|
4091
|
+
name: "InvalidReleaseMetadataURI",
|
|
4092
|
+
inputs: []
|
|
4093
|
+
},
|
|
4094
|
+
{
|
|
4095
|
+
type: "error",
|
|
4096
|
+
name: "InvalidShortString",
|
|
4097
|
+
inputs: []
|
|
4098
|
+
},
|
|
4099
|
+
{
|
|
4100
|
+
type: "error",
|
|
4101
|
+
name: "InvalidSignature",
|
|
4102
|
+
inputs: []
|
|
4103
|
+
},
|
|
4104
|
+
{
|
|
4105
|
+
type: "error",
|
|
4106
|
+
name: "MaxActiveAppsExceeded",
|
|
4107
|
+
inputs: []
|
|
4108
|
+
},
|
|
4109
|
+
{
|
|
4110
|
+
type: "error",
|
|
4111
|
+
name: "MoreThanOneArtifact",
|
|
4112
|
+
inputs: []
|
|
4113
|
+
},
|
|
4114
|
+
{
|
|
4115
|
+
type: "error",
|
|
4116
|
+
name: "NoPendingUpgrade",
|
|
4117
|
+
inputs: []
|
|
4118
|
+
},
|
|
4119
|
+
{
|
|
4120
|
+
type: "error",
|
|
4121
|
+
name: "SignatureExpired",
|
|
4122
|
+
inputs: []
|
|
4123
|
+
},
|
|
4124
|
+
{
|
|
4125
|
+
type: "error",
|
|
4126
|
+
name: "StringTooLong",
|
|
4127
|
+
inputs: [
|
|
4128
|
+
{
|
|
4129
|
+
name: "str",
|
|
4130
|
+
type: "string",
|
|
4131
|
+
internalType: "string"
|
|
4132
|
+
}
|
|
4133
|
+
]
|
|
3023
4134
|
}
|
|
3024
|
-
|
|
3025
|
-
}
|
|
3026
|
-
|
|
3027
|
-
// src/client/common/contract/caller.ts
|
|
3028
|
-
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
3029
|
-
|
|
3030
|
-
// src/client/common/utils/helpers.ts
|
|
3031
|
-
import { extractChain, createPublicClient, createWalletClient, http, fallback } from "viem";
|
|
3032
|
-
import { sepolia as sepolia2 } from "viem/chains";
|
|
3033
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
3034
|
-
function getChainFromID(chainID, fallback2 = sepolia2) {
|
|
3035
|
-
const id = Number(chainID);
|
|
3036
|
-
return extractChain({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
3037
|
-
}
|
|
3038
|
-
function createClients(options) {
|
|
3039
|
-
const { privateKey, rpcUrl, chainId } = options;
|
|
3040
|
-
const privateKeyHex = addHexPrefix(privateKey);
|
|
3041
|
-
const account = privateKeyToAccount(privateKeyHex);
|
|
3042
|
-
const chain = getChainFromID(chainId);
|
|
3043
|
-
const transport = typeof rpcUrl === "string" ? http(rpcUrl) : fallback(rpcUrl.map((url) => http(url)));
|
|
3044
|
-
const publicClient = createPublicClient({
|
|
3045
|
-
chain,
|
|
3046
|
-
transport
|
|
3047
|
-
});
|
|
3048
|
-
const walletClient = createWalletClient({
|
|
3049
|
-
account,
|
|
3050
|
-
chain,
|
|
3051
|
-
transport
|
|
3052
|
-
});
|
|
3053
|
-
return { walletClient, publicClient };
|
|
3054
|
-
}
|
|
3055
|
-
function addHexPrefix(value) {
|
|
3056
|
-
return value.startsWith("0x") ? value : `0x${value}`;
|
|
3057
|
-
}
|
|
3058
|
-
function stripHexPrefix(value) {
|
|
3059
|
-
return value.startsWith("0x") ? value.slice(2) : value;
|
|
3060
|
-
}
|
|
4135
|
+
];
|
|
3061
4136
|
|
|
3062
|
-
// src/client/common/abis/AppController.json
|
|
3063
|
-
var
|
|
4137
|
+
// src/client/common/abis/AppController.v1_4.json
|
|
4138
|
+
var AppController_v1_4_default = [
|
|
3064
4139
|
{
|
|
3065
4140
|
type: "constructor",
|
|
3066
4141
|
inputs: [
|
|
@@ -4744,6 +5819,38 @@ var PermissionController_default = [
|
|
|
4744
5819
|
];
|
|
4745
5820
|
|
|
4746
5821
|
// src/client/common/contract/caller.ts
|
|
5822
|
+
function appControllerAbiFor(environmentConfig) {
|
|
5823
|
+
return environmentConfig.releaseAbiVersion === "v1.4" ? AppController_v1_4_default : AppController_default;
|
|
5824
|
+
}
|
|
5825
|
+
function supportsContainerPolicy(environmentConfig) {
|
|
5826
|
+
return environmentConfig.releaseAbiVersion !== "v1.4";
|
|
5827
|
+
}
|
|
5828
|
+
function containerPolicyForViem(policy = EMPTY_CONTAINER_POLICY) {
|
|
5829
|
+
return {
|
|
5830
|
+
args: policy.args,
|
|
5831
|
+
cmdOverride: policy.cmdOverride,
|
|
5832
|
+
env: policy.env.map((e) => ({ key: e.key, value: e.value })),
|
|
5833
|
+
envOverride: policy.envOverride.map((e) => ({ key: e.key, value: e.value })),
|
|
5834
|
+
restartPolicy: policy.restartPolicy
|
|
5835
|
+
};
|
|
5836
|
+
}
|
|
5837
|
+
function releaseForViem(release, environmentConfig) {
|
|
5838
|
+
const base = {
|
|
5839
|
+
rmsRelease: {
|
|
5840
|
+
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
5841
|
+
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
5842
|
+
registry: artifact.registry
|
|
5843
|
+
})),
|
|
5844
|
+
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
5845
|
+
},
|
|
5846
|
+
publicEnv: bytesToHex(release.publicEnv),
|
|
5847
|
+
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
5848
|
+
};
|
|
5849
|
+
if (!supportsContainerPolicy(environmentConfig)) {
|
|
5850
|
+
return base;
|
|
5851
|
+
}
|
|
5852
|
+
return { ...base, containerPolicy: containerPolicyForViem(release.containerPolicy) };
|
|
5853
|
+
}
|
|
4747
5854
|
function formatETH(wei) {
|
|
4748
5855
|
const eth = Number(wei) / 1e18;
|
|
4749
5856
|
const costStr = eth.toFixed(6);
|
|
@@ -4781,7 +5888,7 @@ async function calculateAppID(options) {
|
|
|
4781
5888
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4782
5889
|
const appID = await publicClient.readContract({
|
|
4783
5890
|
address: environmentConfig.appControllerAddress,
|
|
4784
|
-
abi:
|
|
5891
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4785
5892
|
functionName: "calculateAppId",
|
|
4786
5893
|
args: [ownerAddress, saltHex]
|
|
4787
5894
|
});
|
|
@@ -4805,22 +5912,12 @@ async function prepareDeployBatch(options, logger = noopLogger) {
|
|
|
4805
5912
|
const saltHexString = bytesToHex(salt).slice(2);
|
|
4806
5913
|
const paddedSaltHex = saltHexString.padStart(64, "0");
|
|
4807
5914
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4808
|
-
const
|
|
4809
|
-
rmsRelease: {
|
|
4810
|
-
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4811
|
-
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4812
|
-
registry: artifact.registry
|
|
4813
|
-
})),
|
|
4814
|
-
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4815
|
-
},
|
|
4816
|
-
publicEnv: bytesToHex(release.publicEnv),
|
|
4817
|
-
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
4818
|
-
};
|
|
5915
|
+
const release_ = releaseForViem(release, environmentConfig);
|
|
4819
5916
|
const functionName = options.billTo === "app" ? "createAppWithIsolatedBilling" : "createApp";
|
|
4820
5917
|
const createData = encodeFunctionData2({
|
|
4821
|
-
abi:
|
|
5918
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4822
5919
|
functionName,
|
|
4823
|
-
args: [saltHex,
|
|
5920
|
+
args: [saltHex, release_]
|
|
4824
5921
|
});
|
|
4825
5922
|
const acceptAdminData = encodeFunctionData2({
|
|
4826
5923
|
abi: PermissionController_default,
|
|
@@ -4908,21 +6005,11 @@ async function prepareUpgradeBatch(options) {
|
|
|
4908
6005
|
publicLogs,
|
|
4909
6006
|
needsPermissionChange
|
|
4910
6007
|
} = options;
|
|
4911
|
-
const
|
|
4912
|
-
rmsRelease: {
|
|
4913
|
-
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4914
|
-
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4915
|
-
registry: artifact.registry
|
|
4916
|
-
})),
|
|
4917
|
-
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4918
|
-
},
|
|
4919
|
-
publicEnv: bytesToHex(release.publicEnv),
|
|
4920
|
-
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
4921
|
-
};
|
|
6008
|
+
const release_ = releaseForViem(release, environmentConfig);
|
|
4922
6009
|
const upgradeData = encodeFunctionData2({
|
|
4923
|
-
abi:
|
|
6010
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4924
6011
|
functionName: "upgradeApp",
|
|
4925
|
-
args: [appID,
|
|
6012
|
+
args: [appID, release_]
|
|
4926
6013
|
});
|
|
4927
6014
|
const executions = [
|
|
4928
6015
|
{
|
|
@@ -5056,7 +6143,7 @@ ${pendingMessage}`);
|
|
|
5056
6143
|
if (callError.data) {
|
|
5057
6144
|
try {
|
|
5058
6145
|
const decoded = decodeErrorResult2({
|
|
5059
|
-
abi:
|
|
6146
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5060
6147
|
data: callError.data
|
|
5061
6148
|
});
|
|
5062
6149
|
const formattedError = formatAppControllerError(decoded);
|
|
@@ -5109,7 +6196,7 @@ function formatAppControllerError(decoded) {
|
|
|
5109
6196
|
async function getActiveAppCount(publicClient, environmentConfig, user) {
|
|
5110
6197
|
const count = await publicClient.readContract({
|
|
5111
6198
|
address: environmentConfig.appControllerAddress,
|
|
5112
|
-
abi:
|
|
6199
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5113
6200
|
functionName: "getActiveAppCount",
|
|
5114
6201
|
args: [user]
|
|
5115
6202
|
});
|
|
@@ -5118,7 +6205,7 @@ async function getActiveAppCount(publicClient, environmentConfig, user) {
|
|
|
5118
6205
|
async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
|
|
5119
6206
|
const quota = await publicClient.readContract({
|
|
5120
6207
|
address: environmentConfig.appControllerAddress,
|
|
5121
|
-
abi:
|
|
6208
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5122
6209
|
functionName: "getMaxActiveAppsPerUser",
|
|
5123
6210
|
args: [user]
|
|
5124
6211
|
});
|
|
@@ -5127,7 +6214,7 @@ async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
|
|
|
5127
6214
|
async function getAppsByDeveloper(publicClient, environmentConfig, developer, offset, limit) {
|
|
5128
6215
|
const result = await publicClient.readContract({
|
|
5129
6216
|
address: environmentConfig.appControllerAddress,
|
|
5130
|
-
abi:
|
|
6217
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5131
6218
|
functionName: "getAppsByDeveloper",
|
|
5132
6219
|
args: [developer, offset, limit]
|
|
5133
6220
|
});
|
|
@@ -5139,7 +6226,7 @@ async function getAppsByDeveloper(publicClient, environmentConfig, developer, of
|
|
|
5139
6226
|
async function getBillingType(publicClient, environmentConfig, app) {
|
|
5140
6227
|
const result = await publicClient.readContract({
|
|
5141
6228
|
address: environmentConfig.appControllerAddress,
|
|
5142
|
-
abi:
|
|
6229
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5143
6230
|
functionName: "getBillingType",
|
|
5144
6231
|
args: [app]
|
|
5145
6232
|
});
|
|
@@ -5148,7 +6235,7 @@ async function getBillingType(publicClient, environmentConfig, app) {
|
|
|
5148
6235
|
async function getAppsByBillingAccount(publicClient, environmentConfig, account, offset, limit) {
|
|
5149
6236
|
const result = await publicClient.readContract({
|
|
5150
6237
|
address: environmentConfig.appControllerAddress,
|
|
5151
|
-
abi:
|
|
6238
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5152
6239
|
functionName: "getAppsByBillingAccount",
|
|
5153
6240
|
args: [account, offset, limit]
|
|
5154
6241
|
});
|
|
@@ -5182,7 +6269,7 @@ async function getAppLatestReleaseBlockNumbers(publicClient, environmentConfig,
|
|
|
5182
6269
|
appIDs.map(
|
|
5183
6270
|
(appID) => publicClient.readContract({
|
|
5184
6271
|
address: environmentConfig.appControllerAddress,
|
|
5185
|
-
abi:
|
|
6272
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5186
6273
|
functionName: "getAppLatestReleaseBlockNumber",
|
|
5187
6274
|
args: [appID]
|
|
5188
6275
|
}).catch(() => null)
|
|
@@ -5261,6 +6348,35 @@ async function undelegate(options, logger = noopLogger) {
|
|
|
5261
6348
|
return hash;
|
|
5262
6349
|
}
|
|
5263
6350
|
|
|
6351
|
+
// src/client/common/gas/insufficientGas.ts
|
|
6352
|
+
import { formatEther } from "viem";
|
|
6353
|
+
var InsufficientGasError = class extends Error {
|
|
6354
|
+
constructor(args) {
|
|
6355
|
+
const requiredEth = formatEther(args.requiredWei);
|
|
6356
|
+
const availableEth = formatEther(args.availableWei);
|
|
6357
|
+
super(
|
|
6358
|
+
`Insufficient ETH for gas: wallet ${args.address} has ${availableEth} ETH but this transaction needs ~${requiredEth} ETH.
|
|
6359
|
+
Compute credits do not pay on-chain gas \u2014 fund the wallet with ETH and retry.`
|
|
6360
|
+
);
|
|
6361
|
+
this.name = "InsufficientGasError";
|
|
6362
|
+
this.address = args.address;
|
|
6363
|
+
this.requiredWei = args.requiredWei;
|
|
6364
|
+
this.availableWei = args.availableWei;
|
|
6365
|
+
this.requiredEth = requiredEth;
|
|
6366
|
+
this.availableEth = availableEth;
|
|
6367
|
+
}
|
|
6368
|
+
};
|
|
6369
|
+
async function assertSufficientGas(args) {
|
|
6370
|
+
const availableWei = await args.publicClient.getBalance({ address: args.address });
|
|
6371
|
+
if (availableWei < args.gasEstimate.maxCostWei) {
|
|
6372
|
+
throw new InsufficientGasError({
|
|
6373
|
+
address: args.address,
|
|
6374
|
+
requiredWei: args.gasEstimate.maxCostWei,
|
|
6375
|
+
availableWei
|
|
6376
|
+
});
|
|
6377
|
+
}
|
|
6378
|
+
}
|
|
6379
|
+
|
|
5264
6380
|
// src/client/common/utils/userapi.ts
|
|
5265
6381
|
import axios2 from "axios";
|
|
5266
6382
|
|
|
@@ -5324,6 +6440,7 @@ import axios from "axios";
|
|
|
5324
6440
|
var MAX_RETRIES = 5;
|
|
5325
6441
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
5326
6442
|
var MAX_BACKOFF_MS = 3e4;
|
|
6443
|
+
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
|
|
5327
6444
|
function sleep(ms) {
|
|
5328
6445
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
5329
6446
|
}
|
|
@@ -5343,7 +6460,7 @@ async function requestWithRetry(config) {
|
|
|
5343
6460
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
5344
6461
|
const res = await axios({ ...config, validateStatus: () => true });
|
|
5345
6462
|
lastResponse = res;
|
|
5346
|
-
if (res.status
|
|
6463
|
+
if (!RETRYABLE_STATUSES.has(res.status)) {
|
|
5347
6464
|
return res;
|
|
5348
6465
|
}
|
|
5349
6466
|
if (attempt < MAX_RETRIES) {
|
|
@@ -5372,7 +6489,7 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
|
5372
6489
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
5373
6490
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
5374
6491
|
function getDefaultClientId() {
|
|
5375
|
-
const version = true ? "1.0.0
|
|
6492
|
+
const version = true ? "1.0.0" : "0.0.0";
|
|
5376
6493
|
return `ecloud-sdk/v${version}`;
|
|
5377
6494
|
}
|
|
5378
6495
|
var UserApiClient = class {
|
|
@@ -5407,7 +6524,6 @@ var UserApiClient = class {
|
|
|
5407
6524
|
status: app.app_status,
|
|
5408
6525
|
ip: app.ip,
|
|
5409
6526
|
machineType: app.machine_type,
|
|
5410
|
-
hostname: app.hostname,
|
|
5411
6527
|
profile: app.profile,
|
|
5412
6528
|
metrics: app.metrics,
|
|
5413
6529
|
evmAddresses,
|
|
@@ -5473,28 +6589,6 @@ var UserApiClient = class {
|
|
|
5473
6589
|
status: app.app_status || app.App_Status || ""
|
|
5474
6590
|
}));
|
|
5475
6591
|
}
|
|
5476
|
-
/**
|
|
5477
|
-
* Get deployments for an app from the gRPC-gateway endpoint.
|
|
5478
|
-
* Returns deployment records including upgrade_phase for tracking upgrade progress.
|
|
5479
|
-
*
|
|
5480
|
-
* Endpoint: GET /v1/apps/:appAddress/deployments
|
|
5481
|
-
*/
|
|
5482
|
-
async getDeployments(appAddress) {
|
|
5483
|
-
const endpoint = `${this.config.userApiServerURL}/v1/apps/${appAddress}/deployments`;
|
|
5484
|
-
const response = await this.makeEIP712AuthenticatedRequest(endpoint);
|
|
5485
|
-
const result = await response.json();
|
|
5486
|
-
const deployments = result.deployments || [];
|
|
5487
|
-
return deployments.map((dep) => ({
|
|
5488
|
-
id: dep.id || "",
|
|
5489
|
-
externalId: dep.external_id || dep.externalId || "",
|
|
5490
|
-
endpoint: dep.endpoint || "",
|
|
5491
|
-
releaseId: dep.release_id || dep.releaseId || "",
|
|
5492
|
-
upgradePhase: dep.upgrade_phase || dep.upgradePhase || "",
|
|
5493
|
-
replacesDeploymentId: dep.replaces_deployment_id || dep.replacesDeploymentId || "",
|
|
5494
|
-
createdAt: dep.created_at || dep.createdAt || "",
|
|
5495
|
-
updatedAt: dep.updated_at || dep.updatedAt || ""
|
|
5496
|
-
}));
|
|
5497
|
-
}
|
|
5498
6592
|
/**
|
|
5499
6593
|
* Upload app profile information with optional image
|
|
5500
6594
|
*
|
|
@@ -5628,48 +6722,6 @@ Please check:
|
|
|
5628
6722
|
"X-eigenx-expiry": expiry.toString()
|
|
5629
6723
|
};
|
|
5630
6724
|
}
|
|
5631
|
-
/**
|
|
5632
|
-
* Make an EIP-712 authenticated request to the gRPC-gateway endpoints.
|
|
5633
|
-
* Uses the billing/compute auth pattern: Authorization + X-Account + X-Expiry headers.
|
|
5634
|
-
*/
|
|
5635
|
-
async makeEIP712AuthenticatedRequest(url) {
|
|
5636
|
-
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
5637
|
-
const { signature } = await calculateBillingAuthSignature({
|
|
5638
|
-
walletClient: this.walletClient,
|
|
5639
|
-
product: "compute",
|
|
5640
|
-
expiry
|
|
5641
|
-
});
|
|
5642
|
-
const headers = {
|
|
5643
|
-
Authorization: `Bearer ${signature}`,
|
|
5644
|
-
"X-Account": this.address,
|
|
5645
|
-
"X-Expiry": expiry.toString(),
|
|
5646
|
-
"x-client-id": this.clientId
|
|
5647
|
-
};
|
|
5648
|
-
try {
|
|
5649
|
-
const response = await requestWithRetry({
|
|
5650
|
-
method: "GET",
|
|
5651
|
-
url,
|
|
5652
|
-
headers,
|
|
5653
|
-
maxRedirects: 0,
|
|
5654
|
-
withCredentials: true
|
|
5655
|
-
});
|
|
5656
|
-
const status = response.status;
|
|
5657
|
-
if (status < 200 || status >= 300) {
|
|
5658
|
-
const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
5659
|
-
throw new Error(`gRPC-gateway request failed: ${status} - ${body}`);
|
|
5660
|
-
}
|
|
5661
|
-
return {
|
|
5662
|
-
json: async () => response.data,
|
|
5663
|
-
text: async () => typeof response.data === "string" ? response.data : JSON.stringify(response.data)
|
|
5664
|
-
};
|
|
5665
|
-
} catch (error) {
|
|
5666
|
-
if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
|
|
5667
|
-
const cause = error.cause?.message || error.cause || error.message;
|
|
5668
|
-
throw new Error(`Failed to connect to API at ${url}: ${cause}`);
|
|
5669
|
-
}
|
|
5670
|
-
throw error;
|
|
5671
|
-
}
|
|
5672
|
-
}
|
|
5673
6725
|
// ==========================================================================
|
|
5674
6726
|
// SIWE Session Management
|
|
5675
6727
|
// ==========================================================================
|
|
@@ -5775,8 +6827,36 @@ function transformAppRelease(raw) {
|
|
|
5775
6827
|
|
|
5776
6828
|
// src/client/common/contract/watcher.ts
|
|
5777
6829
|
var WATCH_POLL_INTERVAL_SECONDS = 5;
|
|
6830
|
+
var WATCH_HEARTBEAT_INTERVAL_SECONDS = 30;
|
|
6831
|
+
var WATCH_DEFAULT_TIMEOUT_SECONDS = 10 * 60;
|
|
5778
6832
|
var APP_STATUS_RUNNING = "Running";
|
|
5779
6833
|
var APP_STATUS_FAILED = "Failed";
|
|
6834
|
+
var WatchTimeoutError = class extends Error {
|
|
6835
|
+
constructor(args) {
|
|
6836
|
+
super(
|
|
6837
|
+
args.message ?? `Timed out after ${args.elapsedSeconds}s waiting for app ${args.appId} (last status: ${args.lastStatus ?? "unknown"})`
|
|
6838
|
+
);
|
|
6839
|
+
this.name = "WatchTimeoutError";
|
|
6840
|
+
this.appId = args.appId;
|
|
6841
|
+
this.elapsedSeconds = args.elapsedSeconds;
|
|
6842
|
+
this.lastStatus = args.lastStatus;
|
|
6843
|
+
this.timeoutSeconds = args.timeoutSeconds;
|
|
6844
|
+
}
|
|
6845
|
+
};
|
|
6846
|
+
function resolveWatchTimeoutSeconds(explicit) {
|
|
6847
|
+
if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0) {
|
|
6848
|
+
return Math.floor(explicit);
|
|
6849
|
+
}
|
|
6850
|
+
const raw = process.env.ECLOUD_WATCH_TIMEOUT_SECONDS;
|
|
6851
|
+
if (raw === void 0 || raw === "") {
|
|
6852
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
6853
|
+
}
|
|
6854
|
+
const parsed = Number(raw);
|
|
6855
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
6856
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
6857
|
+
}
|
|
6858
|
+
return Math.floor(parsed);
|
|
6859
|
+
}
|
|
5780
6860
|
async function watchUntilRunning(options, logger) {
|
|
5781
6861
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
5782
6862
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
@@ -5807,8 +6887,20 @@ async function watchUntilRunning(options, logger) {
|
|
|
5807
6887
|
return false;
|
|
5808
6888
|
};
|
|
5809
6889
|
const startTime = Date.now();
|
|
6890
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
5810
6891
|
let lastLoggedStatus;
|
|
6892
|
+
let lastHeartbeatAt = startTime;
|
|
5811
6893
|
while (true) {
|
|
6894
|
+
const elapsedMs = Date.now() - startTime;
|
|
6895
|
+
const elapsed = Math.round(elapsedMs / 1e3);
|
|
6896
|
+
if (elapsed >= timeoutSeconds) {
|
|
6897
|
+
throw new WatchTimeoutError({
|
|
6898
|
+
appId,
|
|
6899
|
+
elapsedSeconds: elapsed,
|
|
6900
|
+
lastStatus: lastLoggedStatus,
|
|
6901
|
+
timeoutSeconds
|
|
6902
|
+
});
|
|
6903
|
+
}
|
|
5812
6904
|
try {
|
|
5813
6905
|
const info = await userApiClient.getInfos([appId], 1);
|
|
5814
6906
|
if (info.length === 0) {
|
|
@@ -5818,62 +6910,35 @@ async function watchUntilRunning(options, logger) {
|
|
|
5818
6910
|
const appInfo = info[0];
|
|
5819
6911
|
const currentStatus = appInfo.status;
|
|
5820
6912
|
const currentIP = appInfo.ip || "";
|
|
5821
|
-
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5822
6913
|
if (currentStatus !== lastLoggedStatus) {
|
|
5823
6914
|
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
5824
6915
|
lastLoggedStatus = currentStatus;
|
|
6916
|
+
lastHeartbeatAt = Date.now();
|
|
6917
|
+
} else if (Date.now() - lastHeartbeatAt >= WATCH_HEARTBEAT_INTERVAL_SECONDS * 1e3) {
|
|
6918
|
+
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
6919
|
+
lastHeartbeatAt = Date.now();
|
|
5825
6920
|
}
|
|
5826
6921
|
if (stopCondition(currentStatus, currentIP)) {
|
|
5827
6922
|
return currentIP || void 0;
|
|
5828
6923
|
}
|
|
5829
6924
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5830
6925
|
} catch (error) {
|
|
6926
|
+
if (error instanceof WatchTimeoutError) {
|
|
6927
|
+
throw error;
|
|
6928
|
+
}
|
|
5831
6929
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
5832
6930
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5833
6931
|
}
|
|
5834
6932
|
}
|
|
5835
6933
|
}
|
|
5836
6934
|
var APP_STATUS_STOPPED = "Stopped";
|
|
5837
|
-
var UPGRADE_PHASE_LABELS = {
|
|
5838
|
-
provisioning: "Provisioning new instance",
|
|
5839
|
-
health_check: "Running health checks",
|
|
5840
|
-
draining: "Switching traffic & draining old instance",
|
|
5841
|
-
complete: "Complete",
|
|
5842
|
-
rolling_back: "Rolling back",
|
|
5843
|
-
rollback_done: "Rollback complete",
|
|
5844
|
-
db_handoff: "Database handoff",
|
|
5845
|
-
// Prewarm-detach phases
|
|
5846
|
-
awaiting_userdata: "Waiting for instance readiness",
|
|
5847
|
-
draining_old: "Draining old instance",
|
|
5848
|
-
detached: "Detaching storage",
|
|
5849
|
-
attached_to_new: "Attaching storage to new instance",
|
|
5850
|
-
finalizing: "Finalizing new instance",
|
|
5851
|
-
flipping: "Switching traffic",
|
|
5852
|
-
teardown_old: "Cleaning up old instance"
|
|
5853
|
-
};
|
|
5854
|
-
async function fetchUpgradePhase(userApiClient, appId) {
|
|
5855
|
-
try {
|
|
5856
|
-
const deployments = await userApiClient.getDeployments(appId);
|
|
5857
|
-
if (deployments.length === 0) return void 0;
|
|
5858
|
-
const sorted = [...deployments].sort((a, b) => {
|
|
5859
|
-
const ta = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
5860
|
-
const tb = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
5861
|
-
return tb - ta;
|
|
5862
|
-
});
|
|
5863
|
-
return sorted[0].upgradePhase || void 0;
|
|
5864
|
-
} catch {
|
|
5865
|
-
return void 0;
|
|
5866
|
-
}
|
|
5867
|
-
}
|
|
5868
6935
|
async function watchUntilUpgradeComplete(options, logger) {
|
|
5869
6936
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
6937
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
5870
6938
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
5871
6939
|
let initialStatus;
|
|
5872
6940
|
let initialIP;
|
|
5873
6941
|
let hasChanged = false;
|
|
5874
|
-
const startTime = Date.now();
|
|
5875
|
-
let lastLoggedStatus;
|
|
5876
|
-
let lastLoggedPhase;
|
|
5877
6942
|
const stopCondition = (status, ip) => {
|
|
5878
6943
|
if (!initialStatus) {
|
|
5879
6944
|
initialStatus = status;
|
|
@@ -5907,37 +6972,44 @@ async function watchUntilUpgradeComplete(options, logger) {
|
|
|
5907
6972
|
}
|
|
5908
6973
|
return false;
|
|
5909
6974
|
};
|
|
6975
|
+
const startTime = Date.now();
|
|
6976
|
+
const deadline = startTime + timeoutSeconds * 1e3;
|
|
6977
|
+
let lastLoggedStatus;
|
|
6978
|
+
let lastObservedStatus;
|
|
5910
6979
|
while (true) {
|
|
6980
|
+
if (Date.now() >= deadline) {
|
|
6981
|
+
const elapsedSeconds = Math.round((Date.now() - startTime) / 1e3);
|
|
6982
|
+
throw new WatchTimeoutError({
|
|
6983
|
+
appId,
|
|
6984
|
+
lastStatus: lastObservedStatus,
|
|
6985
|
+
elapsedSeconds,
|
|
6986
|
+
timeoutSeconds
|
|
6987
|
+
});
|
|
6988
|
+
}
|
|
5911
6989
|
try {
|
|
5912
|
-
const
|
|
5913
|
-
|
|
5914
|
-
fetchUpgradePhase(userApiClient, appId)
|
|
5915
|
-
]);
|
|
5916
|
-
if (infoResult.length === 0) {
|
|
6990
|
+
const info = await userApiClient.getInfos([appId], 1);
|
|
6991
|
+
if (info.length === 0) {
|
|
5917
6992
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5918
6993
|
continue;
|
|
5919
6994
|
}
|
|
5920
|
-
const appInfo =
|
|
6995
|
+
const appInfo = info[0];
|
|
5921
6996
|
const currentStatus = appInfo.status;
|
|
5922
6997
|
const currentIP = appInfo.ip || "";
|
|
6998
|
+
lastObservedStatus = currentStatus;
|
|
5923
6999
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5924
|
-
if (
|
|
5925
|
-
const label = UPGRADE_PHASE_LABELS[upgradePhase] || upgradePhase;
|
|
5926
|
-
logger.info(`Phase: ${label} (${elapsed}s)`);
|
|
5927
|
-
lastLoggedPhase = upgradePhase;
|
|
5928
|
-
}
|
|
5929
|
-
if (!upgradePhase && currentStatus !== lastLoggedStatus) {
|
|
7000
|
+
if (currentStatus !== lastLoggedStatus) {
|
|
5930
7001
|
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
5931
7002
|
lastLoggedStatus = currentStatus;
|
|
5932
7003
|
}
|
|
5933
7004
|
if (stopCondition(currentStatus, currentIP)) {
|
|
5934
|
-
const totalElapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5935
|
-
logger.info(`Upgrade completed in ${totalElapsed}s`);
|
|
5936
7005
|
return;
|
|
5937
7006
|
}
|
|
5938
7007
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5939
7008
|
} catch (error) {
|
|
5940
|
-
if (error
|
|
7009
|
+
if (error instanceof WatchTimeoutError) {
|
|
7010
|
+
throw error;
|
|
7011
|
+
}
|
|
7012
|
+
if (typeof error?.message === "string" && error.message.includes("Failed")) {
|
|
5941
7013
|
throw error;
|
|
5942
7014
|
}
|
|
5943
7015
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
@@ -6268,14 +7340,13 @@ var BILLING_ENVIRONMENTS = {
|
|
|
6268
7340
|
billingApiServerURL: "https://billingapi.eigencloud.xyz"
|
|
6269
7341
|
}
|
|
6270
7342
|
};
|
|
6271
|
-
var PLATFORM_ENV_TESTNET_SEPOLIA = "testnet-sepolia";
|
|
6272
|
-
var PLATFORM_ENV_MAINNET_ETHEREUM = "mainnet-ethereum";
|
|
6273
|
-
var DEFAULT_APP_BASE_DOMAIN = "eigencloud.xyz";
|
|
6274
7343
|
var ENVIRONMENTS = {
|
|
6275
7344
|
"sepolia-dev": {
|
|
6276
7345
|
name: "sepolia",
|
|
6277
7346
|
build: "dev",
|
|
6278
7347
|
appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92",
|
|
7348
|
+
releaseAbiVersion: "v1.5",
|
|
7349
|
+
// AppController upgraded to v1.5.x (containerPolicy)
|
|
6279
7350
|
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
6280
7351
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
6281
7352
|
kmsServerURL: "http://10.128.0.57:8080",
|
|
@@ -6283,14 +7354,14 @@ var ENVIRONMENTS = {
|
|
|
6283
7354
|
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com",
|
|
6284
7355
|
usdcCreditsAddress: "0xbdA3897c3A428763B59015C64AB766c288C97376",
|
|
6285
7356
|
baseUsdcCreditsAddress: "0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac",
|
|
6286
|
-
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
6287
|
-
platformEnv: PLATFORM_ENV_TESTNET_SEPOLIA,
|
|
6288
|
-
appBaseDomain: DEFAULT_APP_BASE_DOMAIN
|
|
7357
|
+
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
6289
7358
|
},
|
|
6290
7359
|
sepolia: {
|
|
6291
7360
|
name: "sepolia",
|
|
6292
7361
|
build: "prod",
|
|
6293
7362
|
appControllerAddress: "0x0dd810a6ffba6a9820a10d97b659f07d8d23d4E2",
|
|
7363
|
+
releaseAbiVersion: "v1.4",
|
|
7364
|
+
// prod still on AppController v1.4.0 (3-field Release)
|
|
6294
7365
|
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
6295
7366
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
6296
7367
|
kmsServerURL: "http://10.128.15.203:8080",
|
|
@@ -6299,22 +7370,20 @@ var ENVIRONMENTS = {
|
|
|
6299
7370
|
billingRPCURL: "https://ethereum-rpc.publicnode.com",
|
|
6300
7371
|
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d",
|
|
6301
7372
|
baseUsdcCreditsAddress: "0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac",
|
|
6302
|
-
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
6303
|
-
platformEnv: PLATFORM_ENV_TESTNET_SEPOLIA,
|
|
6304
|
-
appBaseDomain: DEFAULT_APP_BASE_DOMAIN
|
|
7373
|
+
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
6305
7374
|
},
|
|
6306
7375
|
"mainnet-alpha": {
|
|
6307
7376
|
name: "mainnet-alpha",
|
|
6308
7377
|
build: "prod",
|
|
6309
7378
|
appControllerAddress: "0xc38d35Fc995e75342A21CBd6D770305b142Fbe67",
|
|
7379
|
+
releaseAbiVersion: "v1.4",
|
|
7380
|
+
// prod still on AppController v1.4.0 (3-field Release)
|
|
6310
7381
|
permissionControllerAddress: ChainAddresses[MAINNET_CHAIN_ID].PermissionController,
|
|
6311
7382
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
6312
7383
|
kmsServerURL: "http://10.128.0.2:8080",
|
|
6313
7384
|
userApiServerURL: "https://userapi-compute.eigencloud.xyz",
|
|
6314
7385
|
defaultRPCURL: "https://ethereum-rpc.publicnode.com",
|
|
6315
|
-
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d"
|
|
6316
|
-
platformEnv: PLATFORM_ENV_MAINNET_ETHEREUM,
|
|
6317
|
-
appBaseDomain: DEFAULT_APP_BASE_DOMAIN
|
|
7386
|
+
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d"
|
|
6318
7387
|
}
|
|
6319
7388
|
};
|
|
6320
7389
|
var CHAIN_ID_TO_ENVIRONMENT = {
|
|
@@ -6374,7 +7443,7 @@ function getBillingEnvironmentConfig(build) {
|
|
|
6374
7443
|
};
|
|
6375
7444
|
}
|
|
6376
7445
|
function getBuildType() {
|
|
6377
|
-
const buildTimeType = true ? "
|
|
7446
|
+
const buildTimeType = true ? "prod"?.toLowerCase() : void 0;
|
|
6378
7447
|
const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
|
|
6379
7448
|
const buildType = buildTimeType || runtimeType;
|
|
6380
7449
|
if (buildType === "dev") {
|
|
@@ -6691,6 +7760,63 @@ var BillingApiClient = class {
|
|
|
6691
7760
|
return resp.json();
|
|
6692
7761
|
}
|
|
6693
7762
|
// ==========================================================================
|
|
7763
|
+
// Admin - Coupon Methods
|
|
7764
|
+
// ==========================================================================
|
|
7765
|
+
async createCoupon(amountCents) {
|
|
7766
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/coupons`;
|
|
7767
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "POST", "compute", { amountCents });
|
|
7768
|
+
return resp.json();
|
|
7769
|
+
}
|
|
7770
|
+
async listCoupons(opts) {
|
|
7771
|
+
const params = new URLSearchParams();
|
|
7772
|
+
if (opts?.offset !== void 0) params.set("offset", opts.offset.toString());
|
|
7773
|
+
if (opts?.limit !== void 0) params.set("limit", opts.limit.toString());
|
|
7774
|
+
if (opts?.active !== void 0) params.set("active", opts.active.toString());
|
|
7775
|
+
if (opts?.redeemed !== void 0) params.set("redeemed", opts.redeemed.toString());
|
|
7776
|
+
const qs = params.toString();
|
|
7777
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/coupons${qs ? `?${qs}` : ""}`;
|
|
7778
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "GET", "compute");
|
|
7779
|
+
return resp.json();
|
|
7780
|
+
}
|
|
7781
|
+
async getCoupon(id) {
|
|
7782
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/coupons/${id}`;
|
|
7783
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "GET", "compute");
|
|
7784
|
+
return resp.json();
|
|
7785
|
+
}
|
|
7786
|
+
async deactivateCoupon(id) {
|
|
7787
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/coupons/${id}/deactivate`;
|
|
7788
|
+
await this.makeAuthenticatedRequest(endpoint, "POST", "compute");
|
|
7789
|
+
}
|
|
7790
|
+
async redeemCouponForUser(id, address) {
|
|
7791
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/coupons/${id}/redeem`;
|
|
7792
|
+
await this.makeAuthenticatedRequest(endpoint, "POST", "compute", { address });
|
|
7793
|
+
}
|
|
7794
|
+
// ==========================================================================
|
|
7795
|
+
// Admin - Admin Management Methods
|
|
7796
|
+
// ==========================================================================
|
|
7797
|
+
async addAdmin(address) {
|
|
7798
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/admins`;
|
|
7799
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "POST", "compute", { address });
|
|
7800
|
+
return resp.json();
|
|
7801
|
+
}
|
|
7802
|
+
async removeAdmin(address) {
|
|
7803
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/admins/${address}`;
|
|
7804
|
+
await this.makeAuthenticatedRequest(endpoint, "DELETE", "compute");
|
|
7805
|
+
}
|
|
7806
|
+
async listAdmins() {
|
|
7807
|
+
const endpoint = `${this.config.billingApiServerURL}/admin/admins`;
|
|
7808
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "GET", "compute");
|
|
7809
|
+
return resp.json();
|
|
7810
|
+
}
|
|
7811
|
+
// ==========================================================================
|
|
7812
|
+
// User - Coupon Redemption
|
|
7813
|
+
// ==========================================================================
|
|
7814
|
+
async redeemCoupon(code) {
|
|
7815
|
+
const endpoint = `${this.config.billingApiServerURL}/v1/coupons/redeem`;
|
|
7816
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "POST", "compute", { code });
|
|
7817
|
+
return resp.json();
|
|
7818
|
+
}
|
|
7819
|
+
// ==========================================================================
|
|
6694
7820
|
// Internal Methods
|
|
6695
7821
|
// ==========================================================================
|
|
6696
7822
|
/**
|
|
@@ -7106,6 +8232,11 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
7106
8232
|
executions: batch.executions,
|
|
7107
8233
|
authorizationList
|
|
7108
8234
|
});
|
|
8235
|
+
await assertSufficientGas({
|
|
8236
|
+
publicClient: batch.publicClient,
|
|
8237
|
+
address: batch.walletClient.account.address,
|
|
8238
|
+
gasEstimate
|
|
8239
|
+
});
|
|
7109
8240
|
const data = {
|
|
7110
8241
|
appId: batch.appId,
|
|
7111
8242
|
salt: batch.salt,
|
|
@@ -7364,6 +8495,11 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
7364
8495
|
executions: batch.executions,
|
|
7365
8496
|
authorizationList
|
|
7366
8497
|
});
|
|
8498
|
+
await assertSufficientGas({
|
|
8499
|
+
publicClient: batch.publicClient,
|
|
8500
|
+
address: batch.walletClient.account.address,
|
|
8501
|
+
gasEstimate
|
|
8502
|
+
});
|
|
7367
8503
|
const data = {
|
|
7368
8504
|
appId: batch.appId,
|
|
7369
8505
|
salt: batch.salt,
|
|
@@ -7400,7 +8536,7 @@ async function executeDeploy(options) {
|
|
|
7400
8536
|
}
|
|
7401
8537
|
);
|
|
7402
8538
|
}
|
|
7403
|
-
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
8539
|
+
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
7404
8540
|
return withSDKTelemetry(
|
|
7405
8541
|
{
|
|
7406
8542
|
functionName: "watchDeployment",
|
|
@@ -7416,7 +8552,8 @@ async function watchDeployment(appId, walletClient, publicClient, environmentCon
|
|
|
7416
8552
|
walletClient,
|
|
7417
8553
|
publicClient,
|
|
7418
8554
|
environmentConfig,
|
|
7419
|
-
appId
|
|
8555
|
+
appId,
|
|
8556
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
7420
8557
|
},
|
|
7421
8558
|
logger
|
|
7422
8559
|
);
|
|
@@ -7512,6 +8649,11 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
7512
8649
|
executions: batch.executions,
|
|
7513
8650
|
authorizationList
|
|
7514
8651
|
});
|
|
8652
|
+
await assertSufficientGas({
|
|
8653
|
+
publicClient: batch.publicClient,
|
|
8654
|
+
address: batch.walletClient.account.address,
|
|
8655
|
+
gasEstimate
|
|
8656
|
+
});
|
|
7515
8657
|
const data = {
|
|
7516
8658
|
appId: batch.appId,
|
|
7517
8659
|
executions: batch.executions,
|
|
@@ -7701,6 +8843,11 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
7701
8843
|
executions: batch.executions,
|
|
7702
8844
|
authorizationList
|
|
7703
8845
|
});
|
|
8846
|
+
await assertSufficientGas({
|
|
8847
|
+
publicClient: batch.publicClient,
|
|
8848
|
+
address: batch.walletClient.account.address,
|
|
8849
|
+
gasEstimate
|
|
8850
|
+
});
|
|
7704
8851
|
const data = {
|
|
7705
8852
|
appId: batch.appId,
|
|
7706
8853
|
executions: batch.executions,
|
|
@@ -7735,7 +8882,7 @@ async function executeUpgrade(options) {
|
|
|
7735
8882
|
}
|
|
7736
8883
|
);
|
|
7737
8884
|
}
|
|
7738
|
-
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
8885
|
+
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
7739
8886
|
return withSDKTelemetry(
|
|
7740
8887
|
{
|
|
7741
8888
|
functionName: "watchUpgrade",
|
|
@@ -7751,7 +8898,8 @@ async function watchUpgrade(appId, walletClient, publicClient, environmentConfig
|
|
|
7751
8898
|
walletClient,
|
|
7752
8899
|
publicClient,
|
|
7753
8900
|
environmentConfig,
|
|
7754
|
-
appId
|
|
8901
|
+
appId,
|
|
8902
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
7755
8903
|
},
|
|
7756
8904
|
logger
|
|
7757
8905
|
);
|
|
@@ -8443,7 +9591,7 @@ function createAppModule(ctx) {
|
|
|
8443
9591
|
}
|
|
8444
9592
|
const account = walletClient.account;
|
|
8445
9593
|
const environment = getEnvironmentConfig(ctx.environment);
|
|
8446
|
-
const logger = getLogger(ctx.verbose);
|
|
9594
|
+
const logger = ctx.logger ?? getLogger(ctx.verbose);
|
|
8447
9595
|
return {
|
|
8448
9596
|
async create(opts) {
|
|
8449
9597
|
return createApp(opts, logger);
|
|
@@ -8555,14 +9703,15 @@ function createAppModule(ctx) {
|
|
|
8555
9703
|
imageRef: result.imageRef
|
|
8556
9704
|
};
|
|
8557
9705
|
},
|
|
8558
|
-
async watchDeployment(appId) {
|
|
9706
|
+
async watchDeployment(appId, opts) {
|
|
8559
9707
|
return watchDeployment(
|
|
8560
9708
|
appId,
|
|
8561
9709
|
walletClient,
|
|
8562
9710
|
publicClient,
|
|
8563
9711
|
environment,
|
|
8564
9712
|
logger,
|
|
8565
|
-
skipTelemetry
|
|
9713
|
+
skipTelemetry,
|
|
9714
|
+
opts
|
|
8566
9715
|
);
|
|
8567
9716
|
},
|
|
8568
9717
|
// Granular upgrade control
|
|
@@ -8620,8 +9769,16 @@ function createAppModule(ctx) {
|
|
|
8620
9769
|
imageRef: result.imageRef
|
|
8621
9770
|
};
|
|
8622
9771
|
},
|
|
8623
|
-
async watchUpgrade(appId) {
|
|
8624
|
-
return watchUpgrade(
|
|
9772
|
+
async watchUpgrade(appId, opts) {
|
|
9773
|
+
return watchUpgrade(
|
|
9774
|
+
appId,
|
|
9775
|
+
walletClient,
|
|
9776
|
+
publicClient,
|
|
9777
|
+
environment,
|
|
9778
|
+
logger,
|
|
9779
|
+
skipTelemetry,
|
|
9780
|
+
opts
|
|
9781
|
+
);
|
|
8625
9782
|
},
|
|
8626
9783
|
// Profile management
|
|
8627
9784
|
async setProfile(appId, profile) {
|
|
@@ -9111,6 +10268,9 @@ function createBillingModule(config) {
|
|
|
9111
10268
|
},
|
|
9112
10269
|
hasBaseSupport() {
|
|
9113
10270
|
return !!baseUsdcCreditsAddress && !!baseRPCURL;
|
|
10271
|
+
},
|
|
10272
|
+
async redeemCoupon(code) {
|
|
10273
|
+
return billingApi.redeemCoupon(code);
|
|
9114
10274
|
}
|
|
9115
10275
|
};
|
|
9116
10276
|
return module;
|
|
@@ -9546,6 +10706,44 @@ function transformVerifyResult(raw) {
|
|
|
9546
10706
|
};
|
|
9547
10707
|
}
|
|
9548
10708
|
|
|
10709
|
+
// src/client/modules/admin/index.ts
|
|
10710
|
+
function createAdminModule(config) {
|
|
10711
|
+
const { verbose = false, walletClient } = config;
|
|
10712
|
+
if (!walletClient.account) {
|
|
10713
|
+
throw new Error("WalletClient must have an account attached");
|
|
10714
|
+
}
|
|
10715
|
+
const address = walletClient.account.address;
|
|
10716
|
+
const billingEnvConfig = getBillingEnvironmentConfig(getBuildType());
|
|
10717
|
+
const billingApi = new BillingApiClient(billingEnvConfig, walletClient, { verbose });
|
|
10718
|
+
return {
|
|
10719
|
+
address,
|
|
10720
|
+
async createCoupon(amountCents) {
|
|
10721
|
+
return billingApi.createCoupon(amountCents);
|
|
10722
|
+
},
|
|
10723
|
+
async listCoupons(opts) {
|
|
10724
|
+
return billingApi.listCoupons(opts);
|
|
10725
|
+
},
|
|
10726
|
+
async getCoupon(id) {
|
|
10727
|
+
return billingApi.getCoupon(id);
|
|
10728
|
+
},
|
|
10729
|
+
async deactivateCoupon(id) {
|
|
10730
|
+
return billingApi.deactivateCoupon(id);
|
|
10731
|
+
},
|
|
10732
|
+
async redeemCouponForUser(id, userAddress) {
|
|
10733
|
+
return billingApi.redeemCouponForUser(id, userAddress);
|
|
10734
|
+
},
|
|
10735
|
+
async addAdmin(adminAddress) {
|
|
10736
|
+
return billingApi.addAdmin(adminAddress);
|
|
10737
|
+
},
|
|
10738
|
+
async removeAdmin(adminAddress) {
|
|
10739
|
+
return billingApi.removeAdmin(adminAddress);
|
|
10740
|
+
},
|
|
10741
|
+
async listAdmins() {
|
|
10742
|
+
return billingApi.listAdmins();
|
|
10743
|
+
}
|
|
10744
|
+
};
|
|
10745
|
+
}
|
|
10746
|
+
|
|
9549
10747
|
// src/client/common/auth/keyring.ts
|
|
9550
10748
|
import { AsyncEntry, findCredentials } from "@napi-rs/keyring";
|
|
9551
10749
|
import { privateKeyToAddress } from "viem/accounts";
|
|
@@ -10090,8 +11288,10 @@ export {
|
|
|
10090
11288
|
BuildError,
|
|
10091
11289
|
BuildFailedError,
|
|
10092
11290
|
ConflictError,
|
|
11291
|
+
EMPTY_CONTAINER_POLICY,
|
|
10093
11292
|
ERC20_default as ERC20ABI,
|
|
10094
11293
|
ForbiddenError,
|
|
11294
|
+
InsufficientGasError,
|
|
10095
11295
|
JwtProvider,
|
|
10096
11296
|
NoopClient,
|
|
10097
11297
|
NotFoundError,
|
|
@@ -10101,14 +11301,18 @@ export {
|
|
|
10101
11301
|
TimeoutError,
|
|
10102
11302
|
USDCCredits_default as USDCCreditsABI,
|
|
10103
11303
|
UserApiClient,
|
|
11304
|
+
WATCH_DEFAULT_TIMEOUT_SECONDS,
|
|
11305
|
+
WatchTimeoutError,
|
|
10104
11306
|
addHexPrefix,
|
|
10105
11307
|
addMetric,
|
|
10106
11308
|
addMetricWithDimensions,
|
|
11309
|
+
assertSufficientGas,
|
|
10107
11310
|
assertValidFilePath,
|
|
10108
11311
|
assertValidImageReference,
|
|
10109
11312
|
assertValidPrivateKey,
|
|
10110
11313
|
calculateAppID,
|
|
10111
11314
|
checkERC7702Delegation,
|
|
11315
|
+
createAdminModule,
|
|
10112
11316
|
createApp,
|
|
10113
11317
|
createAppEnvironment,
|
|
10114
11318
|
createBillingModule,
|