@layr-labs/ecloud-sdk 0.1.1 → 0.2.0-dev
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 +1 -20
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.d.cts +1 -2
- package/dist/billing.d.ts +1 -2
- package/dist/billing.js +2 -2
- package/dist/{chunk-73YDSHDG.js → chunk-34DXGQ35.js} +107 -31
- package/dist/chunk-34DXGQ35.js.map +1 -0
- package/dist/{chunk-LUFEUEOG.js → chunk-HLH3AMQF.js} +227 -2
- package/dist/chunk-HLH3AMQF.js.map +1 -0
- package/dist/chunk-LINGJMAS.js +180 -0
- package/dist/chunk-LINGJMAS.js.map +1 -0
- package/dist/compute.cjs +80 -2
- package/dist/compute.cjs.map +1 -1
- package/dist/compute.js +2 -2
- package/dist/index.cjs +783 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +303 -86
- package/dist/index.d.ts +303 -86
- package/dist/index.js +616 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-73YDSHDG.js.map +0 -1
- package/dist/chunk-LUFEUEOG.js.map +0 -1
- package/dist/chunk-XNWF467Z.js +0 -434
- package/dist/chunk-XNWF467Z.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -30,10 +30,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AuthRequiredError: () => AuthRequiredError,
|
|
34
|
+
BUILD_STATUS: () => BUILD_STATUS,
|
|
35
|
+
BadRequestError: () => BadRequestError,
|
|
36
|
+
BuildError: () => BuildError,
|
|
37
|
+
BuildFailedError: () => BuildFailedError,
|
|
38
|
+
ConflictError: () => ConflictError,
|
|
39
|
+
ForbiddenError: () => ForbiddenError,
|
|
33
40
|
NoopClient: () => NoopClient,
|
|
41
|
+
NotFoundError: () => NotFoundError,
|
|
34
42
|
PRIMARY_LANGUAGES: () => PRIMARY_LANGUAGES,
|
|
35
43
|
PostHogClient: () => PostHogClient,
|
|
44
|
+
TimeoutError: () => TimeoutError,
|
|
36
45
|
UserApiClient: () => UserApiClient,
|
|
46
|
+
addHexPrefix: () => addHexPrefix,
|
|
37
47
|
addMetric: () => addMetric,
|
|
38
48
|
addMetricWithDimensions: () => addMetricWithDimensions,
|
|
39
49
|
assertValidFilePath: () => assertValidFilePath,
|
|
@@ -43,6 +53,7 @@ __export(index_exports, {
|
|
|
43
53
|
createApp: () => createApp,
|
|
44
54
|
createAppEnvironment: () => createAppEnvironment,
|
|
45
55
|
createBillingModule: () => createBillingModule,
|
|
56
|
+
createBuildModule: () => createBuildModule,
|
|
46
57
|
createComputeModule: () => createComputeModule,
|
|
47
58
|
createECloudClient: () => createECloudClient,
|
|
48
59
|
createMetricsContext: () => createMetricsContext,
|
|
@@ -86,12 +97,15 @@ __export(index_exports, {
|
|
|
86
97
|
listStoredKeys: () => listStoredKeys,
|
|
87
98
|
logs: () => logs,
|
|
88
99
|
prepareDeploy: () => prepareDeploy,
|
|
100
|
+
prepareDeployFromVerifiableBuild: () => prepareDeployFromVerifiableBuild,
|
|
89
101
|
prepareUpgrade: () => prepareUpgrade,
|
|
102
|
+
prepareUpgradeFromVerifiableBuild: () => prepareUpgradeFromVerifiableBuild,
|
|
90
103
|
requirePrivateKey: () => requirePrivateKey,
|
|
91
104
|
sanitizeString: () => sanitizeString,
|
|
92
105
|
sanitizeURL: () => sanitizeURL,
|
|
93
106
|
sanitizeXURL: () => sanitizeXURL,
|
|
94
107
|
storePrivateKey: () => storePrivateKey,
|
|
108
|
+
stripHexPrefix: () => stripHexPrefix,
|
|
95
109
|
validateAppID: () => validateAppID,
|
|
96
110
|
validateAppName: () => validateAppName,
|
|
97
111
|
validateCreateAppParams: () => validateCreateAppParams,
|
|
@@ -206,7 +220,7 @@ function getBillingEnvironmentConfig(build) {
|
|
|
206
220
|
return config;
|
|
207
221
|
}
|
|
208
222
|
function getBuildType() {
|
|
209
|
-
const buildTimeType = true ? "
|
|
223
|
+
const buildTimeType = true ? "dev"?.toLowerCase() : void 0;
|
|
210
224
|
const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
|
|
211
225
|
const buildType = buildTimeType || runtimeType;
|
|
212
226
|
if (buildType === "dev") {
|
|
@@ -1264,6 +1278,64 @@ Please verify the image exists: docker manifest inspect ${finalImageRef}`
|
|
|
1264
1278
|
};
|
|
1265
1279
|
}
|
|
1266
1280
|
|
|
1281
|
+
// src/client/common/release/prebuilt.ts
|
|
1282
|
+
async function createReleaseFromImageDigest(options, logger) {
|
|
1283
|
+
const { imageRef, imageDigest, envFilePath, instanceType, environmentConfig, appId } = options;
|
|
1284
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(imageDigest)) {
|
|
1285
|
+
throw new Error(`imageDigest must be in format sha256:<64 hex>, got: ${imageDigest}`);
|
|
1286
|
+
}
|
|
1287
|
+
let publicEnv = {};
|
|
1288
|
+
let privateEnv = {};
|
|
1289
|
+
if (envFilePath) {
|
|
1290
|
+
logger.info("Parsing environment file...");
|
|
1291
|
+
const parsed = parseAndValidateEnvFile(envFilePath);
|
|
1292
|
+
publicEnv = parsed.public;
|
|
1293
|
+
privateEnv = parsed.private;
|
|
1294
|
+
} else {
|
|
1295
|
+
logger.info("Continuing without environment file");
|
|
1296
|
+
}
|
|
1297
|
+
publicEnv["EIGEN_MACHINE_TYPE_PUBLIC"] = instanceType;
|
|
1298
|
+
logger.info(`Instance type: ${instanceType}`);
|
|
1299
|
+
logger.info("Encrypting environment variables...");
|
|
1300
|
+
const { encryptionKey } = getKMSKeysForEnvironment(environmentConfig.name, environmentConfig.build);
|
|
1301
|
+
const protectedHeaders = getAppProtectedHeaders(appId);
|
|
1302
|
+
const privateEnvBytes = Buffer.from(JSON.stringify(privateEnv));
|
|
1303
|
+
const encryptedEnvStr = await encryptRSAOAEPAndAES256GCM(
|
|
1304
|
+
encryptionKey,
|
|
1305
|
+
privateEnvBytes,
|
|
1306
|
+
protectedHeaders
|
|
1307
|
+
);
|
|
1308
|
+
const digestHex = imageDigest.split(":")[1];
|
|
1309
|
+
const digestBytes = new Uint8Array(Buffer.from(digestHex, "hex"));
|
|
1310
|
+
if (digestBytes.length !== 32) {
|
|
1311
|
+
throw new Error(`Digest must be exactly 32 bytes, got ${digestBytes.length}`);
|
|
1312
|
+
}
|
|
1313
|
+
const registry = extractRegistryNameNoDocker(imageRef);
|
|
1314
|
+
return {
|
|
1315
|
+
rmsRelease: {
|
|
1316
|
+
artifacts: [{ digest: digestBytes, registry }],
|
|
1317
|
+
upgradeByTime: Math.floor(Date.now() / 1e3) + 3600
|
|
1318
|
+
},
|
|
1319
|
+
publicEnv: new Uint8Array(Buffer.from(JSON.stringify(publicEnv))),
|
|
1320
|
+
encryptedEnv: new Uint8Array(Buffer.from(encryptedEnvStr))
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
function extractRegistryNameNoDocker(imageRef) {
|
|
1324
|
+
let name = imageRef;
|
|
1325
|
+
const tagIndex = name.lastIndexOf(":");
|
|
1326
|
+
if (tagIndex !== -1 && !name.substring(tagIndex + 1).includes("/")) {
|
|
1327
|
+
name = name.substring(0, tagIndex);
|
|
1328
|
+
}
|
|
1329
|
+
const digestIndex = name.indexOf("@");
|
|
1330
|
+
if (digestIndex !== -1) {
|
|
1331
|
+
name = name.substring(0, digestIndex);
|
|
1332
|
+
}
|
|
1333
|
+
if ([...name].filter((c) => c === "/").length === 1) {
|
|
1334
|
+
name = `docker.io/${name}`;
|
|
1335
|
+
}
|
|
1336
|
+
return name;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1267
1339
|
// src/client/common/contract/caller.ts
|
|
1268
1340
|
var import_accounts2 = require("viem/accounts");
|
|
1269
1341
|
|
|
@@ -2520,12 +2592,23 @@ function stripHexPrefix(value) {
|
|
|
2520
2592
|
}
|
|
2521
2593
|
|
|
2522
2594
|
// src/client/common/utils/userapi.ts
|
|
2595
|
+
function isJsonObject(value) {
|
|
2596
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2597
|
+
}
|
|
2598
|
+
function readString(obj, key) {
|
|
2599
|
+
const v = obj[key];
|
|
2600
|
+
return typeof v === "string" ? v : void 0;
|
|
2601
|
+
}
|
|
2602
|
+
function readNumber(obj, key) {
|
|
2603
|
+
const v = obj[key];
|
|
2604
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
2605
|
+
}
|
|
2523
2606
|
var MAX_ADDRESS_COUNT = 5;
|
|
2524
2607
|
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
2525
2608
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
2526
2609
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
2527
2610
|
function getDefaultClientId() {
|
|
2528
|
-
const version = true ? "0.
|
|
2611
|
+
const version = true ? "0.2.0-dev" : "0.0.0";
|
|
2529
2612
|
return `ecloud-sdk/v${version}`;
|
|
2530
2613
|
}
|
|
2531
2614
|
var UserApiClient = class {
|
|
@@ -2559,6 +2642,31 @@ var UserApiClient = class {
|
|
|
2559
2642
|
};
|
|
2560
2643
|
});
|
|
2561
2644
|
}
|
|
2645
|
+
/**
|
|
2646
|
+
* Get app details from UserAPI (includes releases and build/provenance info when available).
|
|
2647
|
+
*
|
|
2648
|
+
* Endpoint: GET /apps/:appAddress
|
|
2649
|
+
*/
|
|
2650
|
+
async getApp(appAddress) {
|
|
2651
|
+
const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}`;
|
|
2652
|
+
const res = await this.makeAuthenticatedRequest(endpoint);
|
|
2653
|
+
const raw = await res.json();
|
|
2654
|
+
if (!isJsonObject(raw)) {
|
|
2655
|
+
throw new Error("Unexpected /apps/:id response: expected object");
|
|
2656
|
+
}
|
|
2657
|
+
const id = readString(raw, "id");
|
|
2658
|
+
if (!id) {
|
|
2659
|
+
throw new Error("Unexpected /apps/:id response: missing 'id'");
|
|
2660
|
+
}
|
|
2661
|
+
const releasesRaw = raw.releases;
|
|
2662
|
+
const releases = Array.isArray(releasesRaw) ? releasesRaw.map((r) => transformAppRelease(r)).filter((r) => !!r) : [];
|
|
2663
|
+
return {
|
|
2664
|
+
id,
|
|
2665
|
+
creator: readString(raw, "creator"),
|
|
2666
|
+
contractStatus: readString(raw, "contract_status") ?? readString(raw, "contractStatus"),
|
|
2667
|
+
releases
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2562
2670
|
/**
|
|
2563
2671
|
* Get available SKUs (instance types) from UserAPI
|
|
2564
2672
|
*/
|
|
@@ -2731,6 +2839,48 @@ Please check:
|
|
|
2731
2839
|
};
|
|
2732
2840
|
}
|
|
2733
2841
|
};
|
|
2842
|
+
function transformAppReleaseBuild(raw) {
|
|
2843
|
+
if (!isJsonObject(raw)) return void 0;
|
|
2844
|
+
const depsRaw = raw.dependencies;
|
|
2845
|
+
const deps = isJsonObject(depsRaw) ? Object.fromEntries(
|
|
2846
|
+
Object.entries(depsRaw).flatMap(([digest, depRaw]) => {
|
|
2847
|
+
const parsed = transformAppReleaseBuild(depRaw);
|
|
2848
|
+
return parsed ? [[digest, parsed]] : [];
|
|
2849
|
+
})
|
|
2850
|
+
) : void 0;
|
|
2851
|
+
return {
|
|
2852
|
+
buildId: readString(raw, "build_id") ?? readString(raw, "buildId"),
|
|
2853
|
+
billingAddress: readString(raw, "billing_address") ?? readString(raw, "billingAddress"),
|
|
2854
|
+
repoUrl: readString(raw, "repo_url") ?? readString(raw, "repoUrl"),
|
|
2855
|
+
gitRef: readString(raw, "git_ref") ?? readString(raw, "gitRef"),
|
|
2856
|
+
status: readString(raw, "status"),
|
|
2857
|
+
buildType: readString(raw, "build_type") ?? readString(raw, "buildType"),
|
|
2858
|
+
imageName: readString(raw, "image_name") ?? readString(raw, "imageName"),
|
|
2859
|
+
imageDigest: readString(raw, "image_digest") ?? readString(raw, "imageDigest"),
|
|
2860
|
+
imageUrl: readString(raw, "image_url") ?? readString(raw, "imageUrl"),
|
|
2861
|
+
provenanceJson: raw.provenance_json ?? raw.provenanceJson,
|
|
2862
|
+
provenanceSignature: readString(raw, "provenance_signature") ?? readString(raw, "provenanceSignature"),
|
|
2863
|
+
createdAt: readString(raw, "created_at") ?? readString(raw, "createdAt"),
|
|
2864
|
+
updatedAt: readString(raw, "updated_at") ?? readString(raw, "updatedAt"),
|
|
2865
|
+
errorMessage: readString(raw, "error_message") ?? readString(raw, "errorMessage"),
|
|
2866
|
+
dependencies: deps
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
function transformAppRelease(raw) {
|
|
2870
|
+
if (!isJsonObject(raw)) return void 0;
|
|
2871
|
+
return {
|
|
2872
|
+
appId: readString(raw, "appId") ?? readString(raw, "app_id"),
|
|
2873
|
+
rmsReleaseId: readString(raw, "rmsReleaseId") ?? readString(raw, "rms_release_id"),
|
|
2874
|
+
imageDigest: readString(raw, "imageDigest") ?? readString(raw, "image_digest"),
|
|
2875
|
+
registryUrl: readString(raw, "registryUrl") ?? readString(raw, "registry_url"),
|
|
2876
|
+
publicEnv: readString(raw, "publicEnv") ?? readString(raw, "public_env"),
|
|
2877
|
+
encryptedEnv: readString(raw, "encryptedEnv") ?? readString(raw, "encrypted_env"),
|
|
2878
|
+
upgradeByTime: readNumber(raw, "upgradeByTime") ?? readNumber(raw, "upgrade_by_time"),
|
|
2879
|
+
createdAt: readString(raw, "createdAt") ?? readString(raw, "created_at"),
|
|
2880
|
+
createdAtBlock: readString(raw, "createdAtBlock") ?? readString(raw, "created_at_block"),
|
|
2881
|
+
build: raw.build ? transformAppReleaseBuild(raw.build) : void 0
|
|
2882
|
+
};
|
|
2883
|
+
}
|
|
2734
2884
|
|
|
2735
2885
|
// src/client/common/utils/billing.ts
|
|
2736
2886
|
function isSubscriptionActive(status) {
|
|
@@ -5533,6 +5683,95 @@ async function withSDKTelemetry(options, action) {
|
|
|
5533
5683
|
}
|
|
5534
5684
|
|
|
5535
5685
|
// src/client/modules/compute/app/deploy.ts
|
|
5686
|
+
async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger) {
|
|
5687
|
+
return withSDKTelemetry(
|
|
5688
|
+
{
|
|
5689
|
+
functionName: "prepareDeployFromVerifiableBuild",
|
|
5690
|
+
skipTelemetry: options.skipTelemetry,
|
|
5691
|
+
properties: {
|
|
5692
|
+
environment: options.environment || "sepolia"
|
|
5693
|
+
}
|
|
5694
|
+
},
|
|
5695
|
+
async () => {
|
|
5696
|
+
if (!options.privateKey) throw new Error("privateKey is required for deployment");
|
|
5697
|
+
if (!options.imageRef) throw new Error("imageRef is required for deployment");
|
|
5698
|
+
if (!options.imageDigest) throw new Error("imageDigest is required for deployment");
|
|
5699
|
+
assertValidImageReference(options.imageRef);
|
|
5700
|
+
validateAppName(options.appName);
|
|
5701
|
+
validateLogVisibility(options.logVisibility);
|
|
5702
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(options.imageDigest)) {
|
|
5703
|
+
throw new Error(`imageDigest must be in format sha256:<64 hex>, got: ${options.imageDigest}`);
|
|
5704
|
+
}
|
|
5705
|
+
const { publicLogs } = validateLogVisibility(options.logVisibility);
|
|
5706
|
+
validateResourceUsageMonitoring(options.resourceUsageMonitoring);
|
|
5707
|
+
logger.debug("Performing preflight checks...");
|
|
5708
|
+
const preflightCtx = await doPreflightChecks(
|
|
5709
|
+
{
|
|
5710
|
+
privateKey: options.privateKey,
|
|
5711
|
+
rpcUrl: options.rpcUrl,
|
|
5712
|
+
environment: options.environment
|
|
5713
|
+
},
|
|
5714
|
+
logger
|
|
5715
|
+
);
|
|
5716
|
+
logger.debug("Checking quota availability...");
|
|
5717
|
+
await checkQuotaAvailable(preflightCtx);
|
|
5718
|
+
const salt = generateRandomSalt();
|
|
5719
|
+
logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
|
|
5720
|
+
logger.debug("Calculating app ID...");
|
|
5721
|
+
const appIDToBeDeployed = await calculateAppID(
|
|
5722
|
+
preflightCtx.privateKey,
|
|
5723
|
+
options.rpcUrl || preflightCtx.rpcUrl,
|
|
5724
|
+
preflightCtx.environmentConfig,
|
|
5725
|
+
salt
|
|
5726
|
+
);
|
|
5727
|
+
logger.info(``);
|
|
5728
|
+
logger.info(`App ID: ${appIDToBeDeployed}`);
|
|
5729
|
+
logger.info(``);
|
|
5730
|
+
const release = await createReleaseFromImageDigest(
|
|
5731
|
+
{
|
|
5732
|
+
imageRef: options.imageRef,
|
|
5733
|
+
imageDigest: options.imageDigest,
|
|
5734
|
+
envFilePath: options.envFilePath,
|
|
5735
|
+
instanceType: options.instanceType,
|
|
5736
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
5737
|
+
appId: appIDToBeDeployed
|
|
5738
|
+
},
|
|
5739
|
+
logger
|
|
5740
|
+
);
|
|
5741
|
+
logger.debug("Preparing deploy batch...");
|
|
5742
|
+
const batch = await prepareDeployBatch(
|
|
5743
|
+
{
|
|
5744
|
+
privateKey: preflightCtx.privateKey,
|
|
5745
|
+
rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
|
|
5746
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
5747
|
+
salt,
|
|
5748
|
+
release,
|
|
5749
|
+
publicLogs
|
|
5750
|
+
},
|
|
5751
|
+
logger
|
|
5752
|
+
);
|
|
5753
|
+
logger.debug("Estimating gas...");
|
|
5754
|
+
const gasEstimate = await estimateBatchGas({
|
|
5755
|
+
publicClient: batch.publicClient,
|
|
5756
|
+
environmentConfig: batch.environmentConfig,
|
|
5757
|
+
executions: batch.executions
|
|
5758
|
+
});
|
|
5759
|
+
return {
|
|
5760
|
+
prepared: {
|
|
5761
|
+
batch,
|
|
5762
|
+
appName: options.appName,
|
|
5763
|
+
imageRef: options.imageRef,
|
|
5764
|
+
preflightCtx: {
|
|
5765
|
+
privateKey: preflightCtx.privateKey,
|
|
5766
|
+
rpcUrl: preflightCtx.rpcUrl,
|
|
5767
|
+
environmentConfig: preflightCtx.environmentConfig
|
|
5768
|
+
}
|
|
5769
|
+
},
|
|
5770
|
+
gasEstimate
|
|
5771
|
+
};
|
|
5772
|
+
}
|
|
5773
|
+
);
|
|
5774
|
+
}
|
|
5536
5775
|
function validateDeployOptions(options) {
|
|
5537
5776
|
if (!options.privateKey) {
|
|
5538
5777
|
throw new Error("privateKey is required for deployment");
|
|
@@ -5842,6 +6081,82 @@ async function checkAppLogPermission(preflightCtx, appAddress, logger) {
|
|
|
5842
6081
|
}
|
|
5843
6082
|
|
|
5844
6083
|
// src/client/modules/compute/app/upgrade.ts
|
|
6084
|
+
async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger) {
|
|
6085
|
+
return withSDKTelemetry(
|
|
6086
|
+
{
|
|
6087
|
+
functionName: "prepareUpgradeFromVerifiableBuild",
|
|
6088
|
+
skipTelemetry: options.skipTelemetry,
|
|
6089
|
+
properties: {
|
|
6090
|
+
environment: options.environment || "sepolia"
|
|
6091
|
+
}
|
|
6092
|
+
},
|
|
6093
|
+
async () => {
|
|
6094
|
+
logger.debug("Performing preflight checks...");
|
|
6095
|
+
const preflightCtx = await doPreflightChecks(
|
|
6096
|
+
{
|
|
6097
|
+
privateKey: options.privateKey,
|
|
6098
|
+
rpcUrl: options.rpcUrl,
|
|
6099
|
+
environment: options.environment
|
|
6100
|
+
},
|
|
6101
|
+
logger
|
|
6102
|
+
);
|
|
6103
|
+
const appID = validateUpgradeOptions(options);
|
|
6104
|
+
assertValidImageReference(options.imageRef);
|
|
6105
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(options.imageDigest)) {
|
|
6106
|
+
throw new Error(
|
|
6107
|
+
`imageDigest must be in format sha256:<64 hex>, got: ${options.imageDigest}`
|
|
6108
|
+
);
|
|
6109
|
+
}
|
|
6110
|
+
const { publicLogs } = validateLogVisibility(options.logVisibility);
|
|
6111
|
+
validateResourceUsageMonitoring(options.resourceUsageMonitoring);
|
|
6112
|
+
const envFilePath = options.envFilePath || "";
|
|
6113
|
+
logger.info("Preparing release (verifiable build, no local layering)...");
|
|
6114
|
+
const release = await createReleaseFromImageDigest(
|
|
6115
|
+
{
|
|
6116
|
+
imageRef: options.imageRef,
|
|
6117
|
+
imageDigest: options.imageDigest,
|
|
6118
|
+
envFilePath,
|
|
6119
|
+
instanceType: options.instanceType,
|
|
6120
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
6121
|
+
appId: appID
|
|
6122
|
+
},
|
|
6123
|
+
logger
|
|
6124
|
+
);
|
|
6125
|
+
logger.debug("Checking current log permission state...");
|
|
6126
|
+
const currentlyPublic = await checkAppLogPermission(preflightCtx, appID, logger);
|
|
6127
|
+
const needsPermissionChange = currentlyPublic !== publicLogs;
|
|
6128
|
+
logger.debug("Preparing upgrade batch...");
|
|
6129
|
+
const batch = await prepareUpgradeBatch({
|
|
6130
|
+
privateKey: preflightCtx.privateKey,
|
|
6131
|
+
rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
|
|
6132
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
6133
|
+
appId: appID,
|
|
6134
|
+
release,
|
|
6135
|
+
publicLogs,
|
|
6136
|
+
needsPermissionChange
|
|
6137
|
+
});
|
|
6138
|
+
logger.debug("Estimating gas...");
|
|
6139
|
+
const gasEstimate = await estimateBatchGas({
|
|
6140
|
+
publicClient: batch.publicClient,
|
|
6141
|
+
environmentConfig: batch.environmentConfig,
|
|
6142
|
+
executions: batch.executions
|
|
6143
|
+
});
|
|
6144
|
+
return {
|
|
6145
|
+
prepared: {
|
|
6146
|
+
batch,
|
|
6147
|
+
appId: appID,
|
|
6148
|
+
imageRef: options.imageRef,
|
|
6149
|
+
preflightCtx: {
|
|
6150
|
+
privateKey: preflightCtx.privateKey,
|
|
6151
|
+
rpcUrl: preflightCtx.rpcUrl,
|
|
6152
|
+
environmentConfig: preflightCtx.environmentConfig
|
|
6153
|
+
}
|
|
6154
|
+
},
|
|
6155
|
+
gasEstimate
|
|
6156
|
+
};
|
|
6157
|
+
}
|
|
6158
|
+
);
|
|
6159
|
+
}
|
|
5845
6160
|
function validateUpgradeOptions(options) {
|
|
5846
6161
|
if (!options.privateKey) {
|
|
5847
6162
|
throw new Error("privateKey is required for upgrade");
|
|
@@ -7026,9 +7341,456 @@ Please check:
|
|
|
7026
7341
|
}
|
|
7027
7342
|
};
|
|
7028
7343
|
|
|
7344
|
+
// src/client/modules/billing/index.ts
|
|
7345
|
+
function createBillingModule(config) {
|
|
7346
|
+
const { verbose = false, skipTelemetry = false } = config;
|
|
7347
|
+
const privateKey = addHexPrefix(config.privateKey);
|
|
7348
|
+
const logger = getLogger(verbose);
|
|
7349
|
+
const billingEnvConfig = getBillingEnvironmentConfig(getBuildType());
|
|
7350
|
+
const billingApi = new BillingApiClient(billingEnvConfig, privateKey);
|
|
7351
|
+
return {
|
|
7352
|
+
async subscribe(opts) {
|
|
7353
|
+
return withSDKTelemetry(
|
|
7354
|
+
{
|
|
7355
|
+
functionName: "subscribe",
|
|
7356
|
+
skipTelemetry,
|
|
7357
|
+
// Skip if called from CLI
|
|
7358
|
+
properties: { productId: opts?.productId || "compute" }
|
|
7359
|
+
},
|
|
7360
|
+
async () => {
|
|
7361
|
+
const productId = opts?.productId || "compute";
|
|
7362
|
+
logger.debug(`Checking existing subscription for ${productId}...`);
|
|
7363
|
+
const currentStatus = await billingApi.getSubscription(productId);
|
|
7364
|
+
if (isSubscriptionActive(currentStatus.subscriptionStatus)) {
|
|
7365
|
+
logger.debug(`Subscription already active: ${currentStatus.subscriptionStatus}`);
|
|
7366
|
+
return {
|
|
7367
|
+
type: "already_active",
|
|
7368
|
+
status: currentStatus.subscriptionStatus
|
|
7369
|
+
};
|
|
7370
|
+
}
|
|
7371
|
+
if (currentStatus.subscriptionStatus === "past_due" || currentStatus.subscriptionStatus === "unpaid") {
|
|
7372
|
+
logger.debug(`Subscription has payment issue: ${currentStatus.subscriptionStatus}`);
|
|
7373
|
+
return {
|
|
7374
|
+
type: "payment_issue",
|
|
7375
|
+
status: currentStatus.subscriptionStatus,
|
|
7376
|
+
portalUrl: currentStatus.portalUrl
|
|
7377
|
+
};
|
|
7378
|
+
}
|
|
7379
|
+
logger.debug(`Creating subscription for ${productId}...`);
|
|
7380
|
+
const result = await billingApi.createSubscription(productId);
|
|
7381
|
+
logger.debug(`Checkout URL: ${result.checkoutUrl}`);
|
|
7382
|
+
return {
|
|
7383
|
+
type: "checkout_created",
|
|
7384
|
+
checkoutUrl: result.checkoutUrl
|
|
7385
|
+
};
|
|
7386
|
+
}
|
|
7387
|
+
);
|
|
7388
|
+
},
|
|
7389
|
+
async getStatus(opts) {
|
|
7390
|
+
return withSDKTelemetry(
|
|
7391
|
+
{
|
|
7392
|
+
functionName: "getStatus",
|
|
7393
|
+
skipTelemetry,
|
|
7394
|
+
// Skip if called from CLI
|
|
7395
|
+
properties: { productId: opts?.productId || "compute" }
|
|
7396
|
+
},
|
|
7397
|
+
async () => {
|
|
7398
|
+
const productId = opts?.productId || "compute";
|
|
7399
|
+
logger.debug(`Fetching subscription status for ${productId}...`);
|
|
7400
|
+
const result = await billingApi.getSubscription(productId);
|
|
7401
|
+
logger.debug(`Subscription status: ${result.subscriptionStatus}`);
|
|
7402
|
+
return result;
|
|
7403
|
+
}
|
|
7404
|
+
);
|
|
7405
|
+
},
|
|
7406
|
+
async cancel(opts) {
|
|
7407
|
+
return withSDKTelemetry(
|
|
7408
|
+
{
|
|
7409
|
+
functionName: "cancel",
|
|
7410
|
+
skipTelemetry,
|
|
7411
|
+
// Skip if called from CLI
|
|
7412
|
+
properties: { productId: opts?.productId || "compute" }
|
|
7413
|
+
},
|
|
7414
|
+
async () => {
|
|
7415
|
+
const productId = opts?.productId || "compute";
|
|
7416
|
+
logger.debug(`Checking subscription status for ${productId}...`);
|
|
7417
|
+
const currentStatus = await billingApi.getSubscription(productId);
|
|
7418
|
+
if (!isSubscriptionActive(currentStatus.subscriptionStatus)) {
|
|
7419
|
+
logger.debug(`No active subscription to cancel: ${currentStatus.subscriptionStatus}`);
|
|
7420
|
+
return {
|
|
7421
|
+
type: "no_active_subscription",
|
|
7422
|
+
status: currentStatus.subscriptionStatus
|
|
7423
|
+
};
|
|
7424
|
+
}
|
|
7425
|
+
logger.debug(`Canceling subscription for ${productId}...`);
|
|
7426
|
+
await billingApi.cancelSubscription(productId);
|
|
7427
|
+
logger.debug(`Subscription canceled successfully`);
|
|
7428
|
+
return {
|
|
7429
|
+
type: "canceled"
|
|
7430
|
+
};
|
|
7431
|
+
}
|
|
7432
|
+
);
|
|
7433
|
+
}
|
|
7434
|
+
};
|
|
7435
|
+
}
|
|
7436
|
+
|
|
7437
|
+
// src/client/common/utils/buildapi.ts
|
|
7438
|
+
var import_axios3 = __toESM(require("axios"), 1);
|
|
7439
|
+
var import_accounts6 = require("viem/accounts");
|
|
7440
|
+
var BuildApiClient = class {
|
|
7441
|
+
constructor(options) {
|
|
7442
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
7443
|
+
this.clientId = options.clientId;
|
|
7444
|
+
if (options.privateKey) {
|
|
7445
|
+
this.account = (0, import_accounts6.privateKeyToAccount)(options.privateKey);
|
|
7446
|
+
}
|
|
7447
|
+
}
|
|
7448
|
+
async submitBuild(payload) {
|
|
7449
|
+
return this.authenticatedJsonRequest("/builds", "POST", payload);
|
|
7450
|
+
}
|
|
7451
|
+
async getBuild(buildId) {
|
|
7452
|
+
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
7453
|
+
}
|
|
7454
|
+
async getBuildByDigest(digest) {
|
|
7455
|
+
return this.publicJsonRequest(`/builds/image/${encodeURIComponent(digest)}`);
|
|
7456
|
+
}
|
|
7457
|
+
async verify(identifier) {
|
|
7458
|
+
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
7459
|
+
}
|
|
7460
|
+
async getLogs(buildId) {
|
|
7461
|
+
return this.authenticatedTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
7462
|
+
}
|
|
7463
|
+
async listBuilds(params) {
|
|
7464
|
+
const res = await (0, import_axios3.default)({
|
|
7465
|
+
url: `${this.baseUrl}/builds`,
|
|
7466
|
+
method: "GET",
|
|
7467
|
+
params,
|
|
7468
|
+
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7469
|
+
timeout: 6e4,
|
|
7470
|
+
validateStatus: () => true
|
|
7471
|
+
});
|
|
7472
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7473
|
+
return res.data;
|
|
7474
|
+
}
|
|
7475
|
+
async publicJsonRequest(path8) {
|
|
7476
|
+
const res = await (0, import_axios3.default)({
|
|
7477
|
+
url: `${this.baseUrl}${path8}`,
|
|
7478
|
+
method: "GET",
|
|
7479
|
+
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7480
|
+
timeout: 6e4,
|
|
7481
|
+
validateStatus: () => true
|
|
7482
|
+
});
|
|
7483
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7484
|
+
return res.data;
|
|
7485
|
+
}
|
|
7486
|
+
async authenticatedJsonRequest(path8, method, body) {
|
|
7487
|
+
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
7488
|
+
const headers = {
|
|
7489
|
+
"Content-Type": "application/json"
|
|
7490
|
+
};
|
|
7491
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7492
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
7493
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
7494
|
+
account: this.account,
|
|
7495
|
+
product: "compute",
|
|
7496
|
+
expiry
|
|
7497
|
+
});
|
|
7498
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
7499
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
7500
|
+
headers["X-Account"] = this.account.address;
|
|
7501
|
+
const res = await (0, import_axios3.default)({
|
|
7502
|
+
url: `${this.baseUrl}${path8}`,
|
|
7503
|
+
method,
|
|
7504
|
+
headers,
|
|
7505
|
+
data: body,
|
|
7506
|
+
timeout: 6e4,
|
|
7507
|
+
validateStatus: () => true
|
|
7508
|
+
});
|
|
7509
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7510
|
+
return res.data;
|
|
7511
|
+
}
|
|
7512
|
+
async authenticatedTextRequest(path8) {
|
|
7513
|
+
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
7514
|
+
const headers = {};
|
|
7515
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7516
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
7517
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
7518
|
+
account: this.account,
|
|
7519
|
+
product: "compute",
|
|
7520
|
+
expiry
|
|
7521
|
+
});
|
|
7522
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
7523
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
7524
|
+
headers["X-Account"] = this.account.address;
|
|
7525
|
+
const res = await (0, import_axios3.default)({
|
|
7526
|
+
url: `${this.baseUrl}${path8}`,
|
|
7527
|
+
method: "GET",
|
|
7528
|
+
headers,
|
|
7529
|
+
timeout: 6e4,
|
|
7530
|
+
responseType: "text",
|
|
7531
|
+
validateStatus: () => true
|
|
7532
|
+
});
|
|
7533
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7534
|
+
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
7535
|
+
}
|
|
7536
|
+
};
|
|
7537
|
+
function buildApiHttpError(res) {
|
|
7538
|
+
const status = res.status;
|
|
7539
|
+
const body = typeof res.data === "string" ? res.data : res.data ? JSON.stringify(res.data) : "";
|
|
7540
|
+
const url = res.config?.url ? ` ${res.config.url}` : "";
|
|
7541
|
+
return new Error(`BuildAPI request failed: ${status}${url} - ${body || "Unknown error"}`);
|
|
7542
|
+
}
|
|
7543
|
+
|
|
7544
|
+
// src/client/modules/build/types.ts
|
|
7545
|
+
var BUILD_STATUS = {
|
|
7546
|
+
BUILDING: "building",
|
|
7547
|
+
SUCCESS: "success",
|
|
7548
|
+
FAILED: "failed"
|
|
7549
|
+
};
|
|
7550
|
+
|
|
7551
|
+
// src/client/modules/build/errors.ts
|
|
7552
|
+
var BuildError = class extends Error {
|
|
7553
|
+
constructor(message) {
|
|
7554
|
+
super(message);
|
|
7555
|
+
this.name = "BuildError";
|
|
7556
|
+
}
|
|
7557
|
+
};
|
|
7558
|
+
var AuthRequiredError = class extends BuildError {
|
|
7559
|
+
constructor(message = "Authentication required") {
|
|
7560
|
+
super(message);
|
|
7561
|
+
this.name = "AuthRequiredError";
|
|
7562
|
+
}
|
|
7563
|
+
};
|
|
7564
|
+
var BuildFailedError = class extends BuildError {
|
|
7565
|
+
constructor(message, buildId) {
|
|
7566
|
+
super(message);
|
|
7567
|
+
this.buildId = buildId;
|
|
7568
|
+
this.name = "BuildFailedError";
|
|
7569
|
+
}
|
|
7570
|
+
};
|
|
7571
|
+
var ConflictError = class extends BuildError {
|
|
7572
|
+
constructor(message = "Build already in progress") {
|
|
7573
|
+
super(message);
|
|
7574
|
+
this.name = "ConflictError";
|
|
7575
|
+
}
|
|
7576
|
+
};
|
|
7577
|
+
var NotFoundError = class extends BuildError {
|
|
7578
|
+
constructor(message = "Build not found") {
|
|
7579
|
+
super(message);
|
|
7580
|
+
this.name = "NotFoundError";
|
|
7581
|
+
}
|
|
7582
|
+
};
|
|
7583
|
+
var ForbiddenError = class extends BuildError {
|
|
7584
|
+
constructor(message = "Permission denied") {
|
|
7585
|
+
super(message);
|
|
7586
|
+
this.name = "ForbiddenError";
|
|
7587
|
+
}
|
|
7588
|
+
};
|
|
7589
|
+
var TimeoutError = class extends BuildError {
|
|
7590
|
+
constructor(message = "Operation timed out") {
|
|
7591
|
+
super(message);
|
|
7592
|
+
this.name = "TimeoutError";
|
|
7593
|
+
}
|
|
7594
|
+
};
|
|
7595
|
+
var BadRequestError = class extends BuildError {
|
|
7596
|
+
constructor(message = "Bad request") {
|
|
7597
|
+
super(message);
|
|
7598
|
+
this.name = "BadRequestError";
|
|
7599
|
+
}
|
|
7600
|
+
};
|
|
7601
|
+
|
|
7602
|
+
// src/client/modules/build/index.ts
|
|
7603
|
+
var DEFAULT_POLL_INTERVAL = 2e3;
|
|
7604
|
+
var DEFAULT_TIMEOUT = 30 * 60 * 1e3;
|
|
7605
|
+
function createBuildModule(config) {
|
|
7606
|
+
const { verbose = false, skipTelemetry = false } = config;
|
|
7607
|
+
const logger = getLogger(verbose);
|
|
7608
|
+
const environment = config.environment || "sepolia";
|
|
7609
|
+
const environmentConfig = getEnvironmentConfig(environment);
|
|
7610
|
+
const api = new BuildApiClient({
|
|
7611
|
+
baseUrl: environmentConfig.userApiServerURL,
|
|
7612
|
+
privateKey: config.privateKey ? addHexPrefix(config.privateKey) : void 0,
|
|
7613
|
+
clientId: config.clientId
|
|
7614
|
+
});
|
|
7615
|
+
return {
|
|
7616
|
+
async submit(request) {
|
|
7617
|
+
return withSDKTelemetry(
|
|
7618
|
+
{
|
|
7619
|
+
functionName: "build.submit",
|
|
7620
|
+
skipTelemetry,
|
|
7621
|
+
properties: { environment, repoUrl: request.repoUrl }
|
|
7622
|
+
},
|
|
7623
|
+
async () => {
|
|
7624
|
+
if (!config.privateKey) throw new AuthRequiredError("Private key required for submit()");
|
|
7625
|
+
const data = await api.submitBuild({
|
|
7626
|
+
repo_url: request.repoUrl,
|
|
7627
|
+
git_ref: request.gitRef,
|
|
7628
|
+
dockerfile_path: request.dockerfilePath ?? "Dockerfile",
|
|
7629
|
+
caddyfile_path: request.caddyfilePath,
|
|
7630
|
+
build_context_path: request.buildContextPath ?? ".",
|
|
7631
|
+
dependencies: request.dependencies ?? []
|
|
7632
|
+
});
|
|
7633
|
+
logger.debug(`Submitted build: ${data.build_id}`);
|
|
7634
|
+
return { buildId: data.build_id };
|
|
7635
|
+
}
|
|
7636
|
+
);
|
|
7637
|
+
},
|
|
7638
|
+
async list(options) {
|
|
7639
|
+
const { billingAddress, limit, offset } = options;
|
|
7640
|
+
return withSDKTelemetry(
|
|
7641
|
+
{
|
|
7642
|
+
functionName: "build.list",
|
|
7643
|
+
skipTelemetry,
|
|
7644
|
+
properties: {
|
|
7645
|
+
environment,
|
|
7646
|
+
billingAddress,
|
|
7647
|
+
...limit !== void 0 ? { limit: String(limit) } : {},
|
|
7648
|
+
...offset !== void 0 ? { offset: String(offset) } : {}
|
|
7649
|
+
}
|
|
7650
|
+
},
|
|
7651
|
+
async () => {
|
|
7652
|
+
const data = await api.listBuilds({
|
|
7653
|
+
billing_address: billingAddress,
|
|
7654
|
+
limit,
|
|
7655
|
+
offset
|
|
7656
|
+
});
|
|
7657
|
+
return Array.isArray(data) ? data.map(transformBuild) : [];
|
|
7658
|
+
}
|
|
7659
|
+
);
|
|
7660
|
+
},
|
|
7661
|
+
async get(buildId) {
|
|
7662
|
+
return withSDKTelemetry(
|
|
7663
|
+
{ functionName: "build.get", skipTelemetry, properties: { environment, buildId } },
|
|
7664
|
+
async () => transformBuild(await api.getBuild(buildId))
|
|
7665
|
+
);
|
|
7666
|
+
},
|
|
7667
|
+
async getByDigest(digest) {
|
|
7668
|
+
return withSDKTelemetry(
|
|
7669
|
+
{ functionName: "build.getByDigest", skipTelemetry, properties: { environment, digest } },
|
|
7670
|
+
async () => transformBuild(await api.getBuildByDigest(digest))
|
|
7671
|
+
);
|
|
7672
|
+
},
|
|
7673
|
+
async verify(identifier) {
|
|
7674
|
+
return withSDKTelemetry(
|
|
7675
|
+
{ functionName: "build.verify", skipTelemetry, properties: { environment, identifier } },
|
|
7676
|
+
async () => transformVerifyResult(await api.verify(identifier))
|
|
7677
|
+
);
|
|
7678
|
+
},
|
|
7679
|
+
async getLogs(buildId) {
|
|
7680
|
+
return withSDKTelemetry(
|
|
7681
|
+
{ functionName: "build.getLogs", skipTelemetry, properties: { environment, buildId } },
|
|
7682
|
+
async () => {
|
|
7683
|
+
if (!config.privateKey) throw new AuthRequiredError("Private key required for getLogs()");
|
|
7684
|
+
return api.getLogs(buildId);
|
|
7685
|
+
}
|
|
7686
|
+
);
|
|
7687
|
+
},
|
|
7688
|
+
async submitAndWait(request, options = {}) {
|
|
7689
|
+
const { buildId } = await this.submit(request);
|
|
7690
|
+
return this.waitForBuild(buildId, options);
|
|
7691
|
+
},
|
|
7692
|
+
async waitForBuild(buildId, options = {}) {
|
|
7693
|
+
const {
|
|
7694
|
+
onLog,
|
|
7695
|
+
onProgress,
|
|
7696
|
+
pollIntervalMs = DEFAULT_POLL_INTERVAL,
|
|
7697
|
+
timeoutMs = DEFAULT_TIMEOUT
|
|
7698
|
+
} = options;
|
|
7699
|
+
const startTime = Date.now();
|
|
7700
|
+
let lastLogLength = 0;
|
|
7701
|
+
while (true) {
|
|
7702
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
7703
|
+
throw new TimeoutError(`Build timed out after ${timeoutMs}ms`);
|
|
7704
|
+
}
|
|
7705
|
+
const build = await this.get(buildId);
|
|
7706
|
+
let logs2 = "";
|
|
7707
|
+
try {
|
|
7708
|
+
logs2 = await this.getLogs(buildId);
|
|
7709
|
+
if (onLog && logs2.length > lastLogLength) {
|
|
7710
|
+
onLog(logs2.slice(lastLogLength));
|
|
7711
|
+
lastLogLength = logs2.length;
|
|
7712
|
+
}
|
|
7713
|
+
} catch {
|
|
7714
|
+
}
|
|
7715
|
+
onProgress?.({ build, logs: logs2 });
|
|
7716
|
+
if (build.status === BUILD_STATUS.SUCCESS) return build;
|
|
7717
|
+
if (build.status === BUILD_STATUS.FAILED) {
|
|
7718
|
+
throw new BuildFailedError(build.errorMessage ?? "Build failed", buildId);
|
|
7719
|
+
}
|
|
7720
|
+
await sleep2(pollIntervalMs);
|
|
7721
|
+
}
|
|
7722
|
+
},
|
|
7723
|
+
async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {
|
|
7724
|
+
let lastLength = 0;
|
|
7725
|
+
while (true) {
|
|
7726
|
+
const build = await this.get(buildId);
|
|
7727
|
+
let logs2 = "";
|
|
7728
|
+
try {
|
|
7729
|
+
logs2 = await this.getLogs(buildId);
|
|
7730
|
+
} catch {
|
|
7731
|
+
}
|
|
7732
|
+
if (logs2.length > lastLength) {
|
|
7733
|
+
yield {
|
|
7734
|
+
content: logs2.slice(lastLength),
|
|
7735
|
+
totalLength: logs2.length,
|
|
7736
|
+
isComplete: build.status !== BUILD_STATUS.BUILDING,
|
|
7737
|
+
finalStatus: build.status !== BUILD_STATUS.BUILDING ? build.status : void 0
|
|
7738
|
+
};
|
|
7739
|
+
lastLength = logs2.length;
|
|
7740
|
+
}
|
|
7741
|
+
if (build.status !== BUILD_STATUS.BUILDING) break;
|
|
7742
|
+
await sleep2(pollIntervalMs);
|
|
7743
|
+
}
|
|
7744
|
+
}
|
|
7745
|
+
};
|
|
7746
|
+
}
|
|
7747
|
+
function sleep2(ms) {
|
|
7748
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
7749
|
+
}
|
|
7750
|
+
function transformBuild(raw) {
|
|
7751
|
+
return {
|
|
7752
|
+
buildId: raw.build_id,
|
|
7753
|
+
billingAddress: raw.billing_address,
|
|
7754
|
+
repoUrl: raw.repo_url,
|
|
7755
|
+
gitRef: raw.git_ref,
|
|
7756
|
+
status: raw.status,
|
|
7757
|
+
buildType: raw.build_type,
|
|
7758
|
+
imageName: raw.image_name,
|
|
7759
|
+
imageUrl: raw.image_url,
|
|
7760
|
+
imageDigest: raw.image_digest,
|
|
7761
|
+
provenanceJson: raw.provenance_json ?? void 0,
|
|
7762
|
+
provenanceSignature: raw.provenance_signature ?? void 0,
|
|
7763
|
+
errorMessage: raw.error_message ?? void 0,
|
|
7764
|
+
createdAt: raw.created_at,
|
|
7765
|
+
updatedAt: raw.updated_at,
|
|
7766
|
+
dependencies: raw.dependencies ? Object.fromEntries(Object.entries(raw.dependencies).map(([k, v]) => [k, transformBuild(v)])) : void 0
|
|
7767
|
+
};
|
|
7768
|
+
}
|
|
7769
|
+
function transformVerifyResult(raw) {
|
|
7770
|
+
if (raw.status === "verified") {
|
|
7771
|
+
return {
|
|
7772
|
+
status: "verified",
|
|
7773
|
+
buildId: raw.build_id,
|
|
7774
|
+
imageUrl: raw.image_url,
|
|
7775
|
+
imageDigest: raw.image_digest,
|
|
7776
|
+
repoUrl: raw.repo_url,
|
|
7777
|
+
gitRef: raw.git_ref,
|
|
7778
|
+
provenanceJson: raw.provenance_json,
|
|
7779
|
+
provenanceSignature: raw.provenance_signature,
|
|
7780
|
+
payloadType: raw.payload_type,
|
|
7781
|
+
payload: raw.payload
|
|
7782
|
+
};
|
|
7783
|
+
}
|
|
7784
|
+
return {
|
|
7785
|
+
status: "failed",
|
|
7786
|
+
error: raw.error,
|
|
7787
|
+
buildId: raw.build_id
|
|
7788
|
+
};
|
|
7789
|
+
}
|
|
7790
|
+
|
|
7029
7791
|
// src/client/common/auth/keyring.ts
|
|
7030
7792
|
var import_keyring = require("@napi-rs/keyring");
|
|
7031
|
-
var
|
|
7793
|
+
var import_accounts7 = require("viem/accounts");
|
|
7032
7794
|
var SERVICE_NAME = "ecloud";
|
|
7033
7795
|
var ACCOUNT_NAME = "key";
|
|
7034
7796
|
var EIGENX_SERVICE_NAME = "eigenx-cli";
|
|
@@ -7173,7 +7935,7 @@ function validatePrivateKey2(privateKey) {
|
|
|
7173
7935
|
}
|
|
7174
7936
|
function getAddressFromPrivateKey(privateKey) {
|
|
7175
7937
|
const normalized = normalizePrivateKey(privateKey);
|
|
7176
|
-
return (0,
|
|
7938
|
+
return (0, import_accounts7.privateKeyToAddress)(normalized);
|
|
7177
7939
|
}
|
|
7178
7940
|
function decodeGoKeyringValue(rawValue) {
|
|
7179
7941
|
if (rawValue.startsWith(GO_KEYRING_BASE64_PREFIX)) {
|
|
@@ -7255,111 +8017,16 @@ async function requirePrivateKey(options) {
|
|
|
7255
8017
|
}
|
|
7256
8018
|
|
|
7257
8019
|
// src/client/common/auth/generate.ts
|
|
7258
|
-
var
|
|
8020
|
+
var import_accounts8 = require("viem/accounts");
|
|
7259
8021
|
function generateNewPrivateKey() {
|
|
7260
|
-
const privateKey = (0,
|
|
7261
|
-
const address = (0,
|
|
8022
|
+
const privateKey = (0, import_accounts8.generatePrivateKey)();
|
|
8023
|
+
const address = (0, import_accounts8.privateKeyToAddress)(privateKey);
|
|
7262
8024
|
return {
|
|
7263
8025
|
privateKey,
|
|
7264
8026
|
address
|
|
7265
8027
|
};
|
|
7266
8028
|
}
|
|
7267
8029
|
|
|
7268
|
-
// src/client/modules/billing/index.ts
|
|
7269
|
-
function createBillingModule(config) {
|
|
7270
|
-
const { verbose = false, skipTelemetry = false } = config;
|
|
7271
|
-
const privateKey = addHexPrefix(config.privateKey);
|
|
7272
|
-
const address = getAddressFromPrivateKey(privateKey);
|
|
7273
|
-
const logger = getLogger(verbose);
|
|
7274
|
-
const billingEnvConfig = getBillingEnvironmentConfig(getBuildType());
|
|
7275
|
-
const billingApi = new BillingApiClient(billingEnvConfig, privateKey);
|
|
7276
|
-
return {
|
|
7277
|
-
address,
|
|
7278
|
-
async subscribe(opts) {
|
|
7279
|
-
return withSDKTelemetry(
|
|
7280
|
-
{
|
|
7281
|
-
functionName: "subscribe",
|
|
7282
|
-
skipTelemetry,
|
|
7283
|
-
// Skip if called from CLI
|
|
7284
|
-
properties: { productId: opts?.productId || "compute" }
|
|
7285
|
-
},
|
|
7286
|
-
async () => {
|
|
7287
|
-
const productId = opts?.productId || "compute";
|
|
7288
|
-
logger.debug(`Checking existing subscription for ${productId}...`);
|
|
7289
|
-
const currentStatus = await billingApi.getSubscription(productId);
|
|
7290
|
-
if (isSubscriptionActive(currentStatus.subscriptionStatus)) {
|
|
7291
|
-
logger.debug(`Subscription already active: ${currentStatus.subscriptionStatus}`);
|
|
7292
|
-
return {
|
|
7293
|
-
type: "already_active",
|
|
7294
|
-
status: currentStatus.subscriptionStatus
|
|
7295
|
-
};
|
|
7296
|
-
}
|
|
7297
|
-
if (currentStatus.subscriptionStatus === "past_due" || currentStatus.subscriptionStatus === "unpaid") {
|
|
7298
|
-
logger.debug(`Subscription has payment issue: ${currentStatus.subscriptionStatus}`);
|
|
7299
|
-
return {
|
|
7300
|
-
type: "payment_issue",
|
|
7301
|
-
status: currentStatus.subscriptionStatus,
|
|
7302
|
-
portalUrl: currentStatus.portalUrl
|
|
7303
|
-
};
|
|
7304
|
-
}
|
|
7305
|
-
logger.debug(`Creating subscription for ${productId}...`);
|
|
7306
|
-
const result = await billingApi.createSubscription(productId);
|
|
7307
|
-
logger.debug(`Checkout URL: ${result.checkoutUrl}`);
|
|
7308
|
-
return {
|
|
7309
|
-
type: "checkout_created",
|
|
7310
|
-
checkoutUrl: result.checkoutUrl
|
|
7311
|
-
};
|
|
7312
|
-
}
|
|
7313
|
-
);
|
|
7314
|
-
},
|
|
7315
|
-
async getStatus(opts) {
|
|
7316
|
-
return withSDKTelemetry(
|
|
7317
|
-
{
|
|
7318
|
-
functionName: "getStatus",
|
|
7319
|
-
skipTelemetry,
|
|
7320
|
-
// Skip if called from CLI
|
|
7321
|
-
properties: { productId: opts?.productId || "compute" }
|
|
7322
|
-
},
|
|
7323
|
-
async () => {
|
|
7324
|
-
const productId = opts?.productId || "compute";
|
|
7325
|
-
logger.debug(`Fetching subscription status for ${productId}...`);
|
|
7326
|
-
const result = await billingApi.getSubscription(productId);
|
|
7327
|
-
logger.debug(`Subscription status: ${result.subscriptionStatus}`);
|
|
7328
|
-
return result;
|
|
7329
|
-
}
|
|
7330
|
-
);
|
|
7331
|
-
},
|
|
7332
|
-
async cancel(opts) {
|
|
7333
|
-
return withSDKTelemetry(
|
|
7334
|
-
{
|
|
7335
|
-
functionName: "cancel",
|
|
7336
|
-
skipTelemetry,
|
|
7337
|
-
// Skip if called from CLI
|
|
7338
|
-
properties: { productId: opts?.productId || "compute" }
|
|
7339
|
-
},
|
|
7340
|
-
async () => {
|
|
7341
|
-
const productId = opts?.productId || "compute";
|
|
7342
|
-
logger.debug(`Checking subscription status for ${productId}...`);
|
|
7343
|
-
const currentStatus = await billingApi.getSubscription(productId);
|
|
7344
|
-
if (!isSubscriptionActive(currentStatus.subscriptionStatus)) {
|
|
7345
|
-
logger.debug(`No active subscription to cancel: ${currentStatus.subscriptionStatus}`);
|
|
7346
|
-
return {
|
|
7347
|
-
type: "no_active_subscription",
|
|
7348
|
-
status: currentStatus.subscriptionStatus
|
|
7349
|
-
};
|
|
7350
|
-
}
|
|
7351
|
-
logger.debug(`Canceling subscription for ${productId}...`);
|
|
7352
|
-
await billingApi.cancelSubscription(productId);
|
|
7353
|
-
logger.debug(`Subscription canceled successfully`);
|
|
7354
|
-
return {
|
|
7355
|
-
type: "canceled"
|
|
7356
|
-
};
|
|
7357
|
-
}
|
|
7358
|
-
);
|
|
7359
|
-
}
|
|
7360
|
-
};
|
|
7361
|
-
}
|
|
7362
|
-
|
|
7363
8030
|
// src/client/common/utils/instance.ts
|
|
7364
8031
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
7365
8032
|
try {
|
|
@@ -7414,10 +8081,20 @@ function createECloudClient(cfg) {
|
|
|
7414
8081
|
}
|
|
7415
8082
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7416
8083
|
0 && (module.exports = {
|
|
8084
|
+
AuthRequiredError,
|
|
8085
|
+
BUILD_STATUS,
|
|
8086
|
+
BadRequestError,
|
|
8087
|
+
BuildError,
|
|
8088
|
+
BuildFailedError,
|
|
8089
|
+
ConflictError,
|
|
8090
|
+
ForbiddenError,
|
|
7417
8091
|
NoopClient,
|
|
8092
|
+
NotFoundError,
|
|
7418
8093
|
PRIMARY_LANGUAGES,
|
|
7419
8094
|
PostHogClient,
|
|
8095
|
+
TimeoutError,
|
|
7420
8096
|
UserApiClient,
|
|
8097
|
+
addHexPrefix,
|
|
7421
8098
|
addMetric,
|
|
7422
8099
|
addMetricWithDimensions,
|
|
7423
8100
|
assertValidFilePath,
|
|
@@ -7427,6 +8104,7 @@ function createECloudClient(cfg) {
|
|
|
7427
8104
|
createApp,
|
|
7428
8105
|
createAppEnvironment,
|
|
7429
8106
|
createBillingModule,
|
|
8107
|
+
createBuildModule,
|
|
7430
8108
|
createComputeModule,
|
|
7431
8109
|
createECloudClient,
|
|
7432
8110
|
createMetricsContext,
|
|
@@ -7470,12 +8148,15 @@ function createECloudClient(cfg) {
|
|
|
7470
8148
|
listStoredKeys,
|
|
7471
8149
|
logs,
|
|
7472
8150
|
prepareDeploy,
|
|
8151
|
+
prepareDeployFromVerifiableBuild,
|
|
7473
8152
|
prepareUpgrade,
|
|
8153
|
+
prepareUpgradeFromVerifiableBuild,
|
|
7474
8154
|
requirePrivateKey,
|
|
7475
8155
|
sanitizeString,
|
|
7476
8156
|
sanitizeURL,
|
|
7477
8157
|
sanitizeXURL,
|
|
7478
8158
|
storePrivateKey,
|
|
8159
|
+
stripHexPrefix,
|
|
7479
8160
|
validateAppID,
|
|
7480
8161
|
validateAppName,
|
|
7481
8162
|
validateCreateAppParams,
|