@layr-labs/ecloud-sdk 0.2.0-dev → 0.2.0-dev.2
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 +19 -0
- 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 +2 -2
- package/dist/chunk-2RORGPLX.js +434 -0
- package/dist/chunk-2RORGPLX.js.map +1 -0
- package/dist/{chunk-HLH3AMQF.js → chunk-4SKRNFKQ.js} +2 -227
- package/dist/chunk-4SKRNFKQ.js.map +1 -0
- package/dist/{chunk-34DXGQ35.js → chunk-ZEZS5CNB.js} +30 -106
- package/dist/chunk-ZEZS5CNB.js.map +1 -0
- package/dist/compute.cjs +1 -79
- package/dist/compute.cjs.map +1 -1
- package/dist/compute.js +2 -2
- package/dist/index.cjs +101 -782
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -303
- package/dist/index.d.ts +86 -303
- package/dist/index.js +17 -616
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-34DXGQ35.js.map +0 -1
- package/dist/chunk-HLH3AMQF.js.map +0 -1
- package/dist/chunk-LINGJMAS.js +0 -180
- package/dist/chunk-LINGJMAS.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createBillingModule
|
|
3
|
-
|
|
2
|
+
createBillingModule,
|
|
3
|
+
deleteLegacyPrivateKey,
|
|
4
|
+
deletePrivateKey,
|
|
5
|
+
generateNewPrivateKey,
|
|
6
|
+
getAddressFromPrivateKey,
|
|
7
|
+
getLegacyKeys,
|
|
8
|
+
getLegacyPrivateKey,
|
|
9
|
+
getPrivateKey,
|
|
10
|
+
getPrivateKeyWithSource,
|
|
11
|
+
keyExists,
|
|
12
|
+
listStoredKeys,
|
|
13
|
+
requirePrivateKey,
|
|
14
|
+
storePrivateKey,
|
|
15
|
+
validatePrivateKey
|
|
16
|
+
} from "./chunk-2RORGPLX.js";
|
|
4
17
|
import {
|
|
5
18
|
PRIMARY_LANGUAGES,
|
|
6
19
|
assertValidFilePath,
|
|
@@ -27,9 +40,7 @@ import {
|
|
|
27
40
|
getTemplate,
|
|
28
41
|
logs,
|
|
29
42
|
prepareDeploy,
|
|
30
|
-
prepareDeployFromVerifiableBuild,
|
|
31
43
|
prepareUpgrade,
|
|
32
|
-
prepareUpgradeFromVerifiableBuild,
|
|
33
44
|
sanitizeString,
|
|
34
45
|
sanitizeURL,
|
|
35
46
|
sanitizeXURL,
|
|
@@ -51,7 +62,7 @@ import {
|
|
|
51
62
|
validateXURL,
|
|
52
63
|
watchDeployment,
|
|
53
64
|
watchUpgrade
|
|
54
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-4SKRNFKQ.js";
|
|
55
66
|
import {
|
|
56
67
|
NoopClient,
|
|
57
68
|
PostHogClient,
|
|
@@ -59,7 +70,6 @@ import {
|
|
|
59
70
|
addHexPrefix,
|
|
60
71
|
addMetric,
|
|
61
72
|
addMetricWithDimensions,
|
|
62
|
-
calculateBillingAuthSignature,
|
|
63
73
|
createAppEnvironment,
|
|
64
74
|
createMetricsContext,
|
|
65
75
|
createTelemetryClient,
|
|
@@ -67,609 +77,14 @@ import {
|
|
|
67
77
|
getAvailableEnvironments,
|
|
68
78
|
getBuildType,
|
|
69
79
|
getEnvironmentConfig,
|
|
70
|
-
getLogger,
|
|
71
80
|
getPostHogAPIKey,
|
|
72
81
|
getPostHogEndpoint,
|
|
73
82
|
isEnvironmentAvailable,
|
|
74
83
|
isMainnet,
|
|
75
84
|
isNoopClient,
|
|
76
85
|
isSubscriptionActive,
|
|
77
|
-
stripHexPrefix,
|
|
78
86
|
withSDKTelemetry
|
|
79
|
-
} from "./chunk-
|
|
80
|
-
|
|
81
|
-
// src/client/common/utils/buildapi.ts
|
|
82
|
-
import axios from "axios";
|
|
83
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
84
|
-
var BuildApiClient = class {
|
|
85
|
-
constructor(options) {
|
|
86
|
-
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
87
|
-
this.clientId = options.clientId;
|
|
88
|
-
if (options.privateKey) {
|
|
89
|
-
this.account = privateKeyToAccount(options.privateKey);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
async submitBuild(payload) {
|
|
93
|
-
return this.authenticatedJsonRequest("/builds", "POST", payload);
|
|
94
|
-
}
|
|
95
|
-
async getBuild(buildId) {
|
|
96
|
-
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
97
|
-
}
|
|
98
|
-
async getBuildByDigest(digest) {
|
|
99
|
-
return this.publicJsonRequest(`/builds/image/${encodeURIComponent(digest)}`);
|
|
100
|
-
}
|
|
101
|
-
async verify(identifier) {
|
|
102
|
-
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
103
|
-
}
|
|
104
|
-
async getLogs(buildId) {
|
|
105
|
-
return this.authenticatedTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
106
|
-
}
|
|
107
|
-
async listBuilds(params) {
|
|
108
|
-
const res = await axios({
|
|
109
|
-
url: `${this.baseUrl}/builds`,
|
|
110
|
-
method: "GET",
|
|
111
|
-
params,
|
|
112
|
-
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
113
|
-
timeout: 6e4,
|
|
114
|
-
validateStatus: () => true
|
|
115
|
-
});
|
|
116
|
-
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
117
|
-
return res.data;
|
|
118
|
-
}
|
|
119
|
-
async publicJsonRequest(path) {
|
|
120
|
-
const res = await axios({
|
|
121
|
-
url: `${this.baseUrl}${path}`,
|
|
122
|
-
method: "GET",
|
|
123
|
-
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
124
|
-
timeout: 6e4,
|
|
125
|
-
validateStatus: () => true
|
|
126
|
-
});
|
|
127
|
-
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
128
|
-
return res.data;
|
|
129
|
-
}
|
|
130
|
-
async authenticatedJsonRequest(path, method, body) {
|
|
131
|
-
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
132
|
-
const headers = {
|
|
133
|
-
"Content-Type": "application/json"
|
|
134
|
-
};
|
|
135
|
-
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
136
|
-
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
137
|
-
const { signature } = await calculateBillingAuthSignature({
|
|
138
|
-
account: this.account,
|
|
139
|
-
product: "compute",
|
|
140
|
-
expiry
|
|
141
|
-
});
|
|
142
|
-
headers.Authorization = `Bearer ${signature}`;
|
|
143
|
-
headers["X-eigenx-expiry"] = expiry.toString();
|
|
144
|
-
headers["X-Account"] = this.account.address;
|
|
145
|
-
const res = await axios({
|
|
146
|
-
url: `${this.baseUrl}${path}`,
|
|
147
|
-
method,
|
|
148
|
-
headers,
|
|
149
|
-
data: body,
|
|
150
|
-
timeout: 6e4,
|
|
151
|
-
validateStatus: () => true
|
|
152
|
-
});
|
|
153
|
-
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
154
|
-
return res.data;
|
|
155
|
-
}
|
|
156
|
-
async authenticatedTextRequest(path) {
|
|
157
|
-
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
158
|
-
const headers = {};
|
|
159
|
-
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
160
|
-
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
161
|
-
const { signature } = await calculateBillingAuthSignature({
|
|
162
|
-
account: this.account,
|
|
163
|
-
product: "compute",
|
|
164
|
-
expiry
|
|
165
|
-
});
|
|
166
|
-
headers.Authorization = `Bearer ${signature}`;
|
|
167
|
-
headers["X-eigenx-expiry"] = expiry.toString();
|
|
168
|
-
headers["X-Account"] = this.account.address;
|
|
169
|
-
const res = await axios({
|
|
170
|
-
url: `${this.baseUrl}${path}`,
|
|
171
|
-
method: "GET",
|
|
172
|
-
headers,
|
|
173
|
-
timeout: 6e4,
|
|
174
|
-
responseType: "text",
|
|
175
|
-
validateStatus: () => true
|
|
176
|
-
});
|
|
177
|
-
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
178
|
-
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
function buildApiHttpError(res) {
|
|
182
|
-
const status = res.status;
|
|
183
|
-
const body = typeof res.data === "string" ? res.data : res.data ? JSON.stringify(res.data) : "";
|
|
184
|
-
const url = res.config?.url ? ` ${res.config.url}` : "";
|
|
185
|
-
return new Error(`BuildAPI request failed: ${status}${url} - ${body || "Unknown error"}`);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// src/client/modules/build/types.ts
|
|
189
|
-
var BUILD_STATUS = {
|
|
190
|
-
BUILDING: "building",
|
|
191
|
-
SUCCESS: "success",
|
|
192
|
-
FAILED: "failed"
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
// src/client/modules/build/errors.ts
|
|
196
|
-
var BuildError = class extends Error {
|
|
197
|
-
constructor(message) {
|
|
198
|
-
super(message);
|
|
199
|
-
this.name = "BuildError";
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
var AuthRequiredError = class extends BuildError {
|
|
203
|
-
constructor(message = "Authentication required") {
|
|
204
|
-
super(message);
|
|
205
|
-
this.name = "AuthRequiredError";
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
var BuildFailedError = class extends BuildError {
|
|
209
|
-
constructor(message, buildId) {
|
|
210
|
-
super(message);
|
|
211
|
-
this.buildId = buildId;
|
|
212
|
-
this.name = "BuildFailedError";
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
var ConflictError = class extends BuildError {
|
|
216
|
-
constructor(message = "Build already in progress") {
|
|
217
|
-
super(message);
|
|
218
|
-
this.name = "ConflictError";
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
var NotFoundError = class extends BuildError {
|
|
222
|
-
constructor(message = "Build not found") {
|
|
223
|
-
super(message);
|
|
224
|
-
this.name = "NotFoundError";
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
var ForbiddenError = class extends BuildError {
|
|
228
|
-
constructor(message = "Permission denied") {
|
|
229
|
-
super(message);
|
|
230
|
-
this.name = "ForbiddenError";
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
var TimeoutError = class extends BuildError {
|
|
234
|
-
constructor(message = "Operation timed out") {
|
|
235
|
-
super(message);
|
|
236
|
-
this.name = "TimeoutError";
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
var BadRequestError = class extends BuildError {
|
|
240
|
-
constructor(message = "Bad request") {
|
|
241
|
-
super(message);
|
|
242
|
-
this.name = "BadRequestError";
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
// src/client/modules/build/index.ts
|
|
247
|
-
var DEFAULT_POLL_INTERVAL = 2e3;
|
|
248
|
-
var DEFAULT_TIMEOUT = 30 * 60 * 1e3;
|
|
249
|
-
function createBuildModule(config) {
|
|
250
|
-
const { verbose = false, skipTelemetry = false } = config;
|
|
251
|
-
const logger = getLogger(verbose);
|
|
252
|
-
const environment = config.environment || "sepolia";
|
|
253
|
-
const environmentConfig = getEnvironmentConfig(environment);
|
|
254
|
-
const api = new BuildApiClient({
|
|
255
|
-
baseUrl: environmentConfig.userApiServerURL,
|
|
256
|
-
privateKey: config.privateKey ? addHexPrefix(config.privateKey) : void 0,
|
|
257
|
-
clientId: config.clientId
|
|
258
|
-
});
|
|
259
|
-
return {
|
|
260
|
-
async submit(request) {
|
|
261
|
-
return withSDKTelemetry(
|
|
262
|
-
{
|
|
263
|
-
functionName: "build.submit",
|
|
264
|
-
skipTelemetry,
|
|
265
|
-
properties: { environment, repoUrl: request.repoUrl }
|
|
266
|
-
},
|
|
267
|
-
async () => {
|
|
268
|
-
if (!config.privateKey) throw new AuthRequiredError("Private key required for submit()");
|
|
269
|
-
const data = await api.submitBuild({
|
|
270
|
-
repo_url: request.repoUrl,
|
|
271
|
-
git_ref: request.gitRef,
|
|
272
|
-
dockerfile_path: request.dockerfilePath ?? "Dockerfile",
|
|
273
|
-
caddyfile_path: request.caddyfilePath,
|
|
274
|
-
build_context_path: request.buildContextPath ?? ".",
|
|
275
|
-
dependencies: request.dependencies ?? []
|
|
276
|
-
});
|
|
277
|
-
logger.debug(`Submitted build: ${data.build_id}`);
|
|
278
|
-
return { buildId: data.build_id };
|
|
279
|
-
}
|
|
280
|
-
);
|
|
281
|
-
},
|
|
282
|
-
async list(options) {
|
|
283
|
-
const { billingAddress, limit, offset } = options;
|
|
284
|
-
return withSDKTelemetry(
|
|
285
|
-
{
|
|
286
|
-
functionName: "build.list",
|
|
287
|
-
skipTelemetry,
|
|
288
|
-
properties: {
|
|
289
|
-
environment,
|
|
290
|
-
billingAddress,
|
|
291
|
-
...limit !== void 0 ? { limit: String(limit) } : {},
|
|
292
|
-
...offset !== void 0 ? { offset: String(offset) } : {}
|
|
293
|
-
}
|
|
294
|
-
},
|
|
295
|
-
async () => {
|
|
296
|
-
const data = await api.listBuilds({
|
|
297
|
-
billing_address: billingAddress,
|
|
298
|
-
limit,
|
|
299
|
-
offset
|
|
300
|
-
});
|
|
301
|
-
return Array.isArray(data) ? data.map(transformBuild) : [];
|
|
302
|
-
}
|
|
303
|
-
);
|
|
304
|
-
},
|
|
305
|
-
async get(buildId) {
|
|
306
|
-
return withSDKTelemetry(
|
|
307
|
-
{ functionName: "build.get", skipTelemetry, properties: { environment, buildId } },
|
|
308
|
-
async () => transformBuild(await api.getBuild(buildId))
|
|
309
|
-
);
|
|
310
|
-
},
|
|
311
|
-
async getByDigest(digest) {
|
|
312
|
-
return withSDKTelemetry(
|
|
313
|
-
{ functionName: "build.getByDigest", skipTelemetry, properties: { environment, digest } },
|
|
314
|
-
async () => transformBuild(await api.getBuildByDigest(digest))
|
|
315
|
-
);
|
|
316
|
-
},
|
|
317
|
-
async verify(identifier) {
|
|
318
|
-
return withSDKTelemetry(
|
|
319
|
-
{ functionName: "build.verify", skipTelemetry, properties: { environment, identifier } },
|
|
320
|
-
async () => transformVerifyResult(await api.verify(identifier))
|
|
321
|
-
);
|
|
322
|
-
},
|
|
323
|
-
async getLogs(buildId) {
|
|
324
|
-
return withSDKTelemetry(
|
|
325
|
-
{ functionName: "build.getLogs", skipTelemetry, properties: { environment, buildId } },
|
|
326
|
-
async () => {
|
|
327
|
-
if (!config.privateKey) throw new AuthRequiredError("Private key required for getLogs()");
|
|
328
|
-
return api.getLogs(buildId);
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
},
|
|
332
|
-
async submitAndWait(request, options = {}) {
|
|
333
|
-
const { buildId } = await this.submit(request);
|
|
334
|
-
return this.waitForBuild(buildId, options);
|
|
335
|
-
},
|
|
336
|
-
async waitForBuild(buildId, options = {}) {
|
|
337
|
-
const {
|
|
338
|
-
onLog,
|
|
339
|
-
onProgress,
|
|
340
|
-
pollIntervalMs = DEFAULT_POLL_INTERVAL,
|
|
341
|
-
timeoutMs = DEFAULT_TIMEOUT
|
|
342
|
-
} = options;
|
|
343
|
-
const startTime = Date.now();
|
|
344
|
-
let lastLogLength = 0;
|
|
345
|
-
while (true) {
|
|
346
|
-
if (Date.now() - startTime > timeoutMs) {
|
|
347
|
-
throw new TimeoutError(`Build timed out after ${timeoutMs}ms`);
|
|
348
|
-
}
|
|
349
|
-
const build = await this.get(buildId);
|
|
350
|
-
let logs2 = "";
|
|
351
|
-
try {
|
|
352
|
-
logs2 = await this.getLogs(buildId);
|
|
353
|
-
if (onLog && logs2.length > lastLogLength) {
|
|
354
|
-
onLog(logs2.slice(lastLogLength));
|
|
355
|
-
lastLogLength = logs2.length;
|
|
356
|
-
}
|
|
357
|
-
} catch {
|
|
358
|
-
}
|
|
359
|
-
onProgress?.({ build, logs: logs2 });
|
|
360
|
-
if (build.status === BUILD_STATUS.SUCCESS) return build;
|
|
361
|
-
if (build.status === BUILD_STATUS.FAILED) {
|
|
362
|
-
throw new BuildFailedError(build.errorMessage ?? "Build failed", buildId);
|
|
363
|
-
}
|
|
364
|
-
await sleep(pollIntervalMs);
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {
|
|
368
|
-
let lastLength = 0;
|
|
369
|
-
while (true) {
|
|
370
|
-
const build = await this.get(buildId);
|
|
371
|
-
let logs2 = "";
|
|
372
|
-
try {
|
|
373
|
-
logs2 = await this.getLogs(buildId);
|
|
374
|
-
} catch {
|
|
375
|
-
}
|
|
376
|
-
if (logs2.length > lastLength) {
|
|
377
|
-
yield {
|
|
378
|
-
content: logs2.slice(lastLength),
|
|
379
|
-
totalLength: logs2.length,
|
|
380
|
-
isComplete: build.status !== BUILD_STATUS.BUILDING,
|
|
381
|
-
finalStatus: build.status !== BUILD_STATUS.BUILDING ? build.status : void 0
|
|
382
|
-
};
|
|
383
|
-
lastLength = logs2.length;
|
|
384
|
-
}
|
|
385
|
-
if (build.status !== BUILD_STATUS.BUILDING) break;
|
|
386
|
-
await sleep(pollIntervalMs);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
function sleep(ms) {
|
|
392
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
393
|
-
}
|
|
394
|
-
function transformBuild(raw) {
|
|
395
|
-
return {
|
|
396
|
-
buildId: raw.build_id,
|
|
397
|
-
billingAddress: raw.billing_address,
|
|
398
|
-
repoUrl: raw.repo_url,
|
|
399
|
-
gitRef: raw.git_ref,
|
|
400
|
-
status: raw.status,
|
|
401
|
-
buildType: raw.build_type,
|
|
402
|
-
imageName: raw.image_name,
|
|
403
|
-
imageUrl: raw.image_url,
|
|
404
|
-
imageDigest: raw.image_digest,
|
|
405
|
-
provenanceJson: raw.provenance_json ?? void 0,
|
|
406
|
-
provenanceSignature: raw.provenance_signature ?? void 0,
|
|
407
|
-
errorMessage: raw.error_message ?? void 0,
|
|
408
|
-
createdAt: raw.created_at,
|
|
409
|
-
updatedAt: raw.updated_at,
|
|
410
|
-
dependencies: raw.dependencies ? Object.fromEntries(Object.entries(raw.dependencies).map(([k, v]) => [k, transformBuild(v)])) : void 0
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
function transformVerifyResult(raw) {
|
|
414
|
-
if (raw.status === "verified") {
|
|
415
|
-
return {
|
|
416
|
-
status: "verified",
|
|
417
|
-
buildId: raw.build_id,
|
|
418
|
-
imageUrl: raw.image_url,
|
|
419
|
-
imageDigest: raw.image_digest,
|
|
420
|
-
repoUrl: raw.repo_url,
|
|
421
|
-
gitRef: raw.git_ref,
|
|
422
|
-
provenanceJson: raw.provenance_json,
|
|
423
|
-
provenanceSignature: raw.provenance_signature,
|
|
424
|
-
payloadType: raw.payload_type,
|
|
425
|
-
payload: raw.payload
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
return {
|
|
429
|
-
status: "failed",
|
|
430
|
-
error: raw.error,
|
|
431
|
-
buildId: raw.build_id
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// src/client/common/auth/keyring.ts
|
|
436
|
-
import { AsyncEntry, findCredentials } from "@napi-rs/keyring";
|
|
437
|
-
import { privateKeyToAddress } from "viem/accounts";
|
|
438
|
-
var SERVICE_NAME = "ecloud";
|
|
439
|
-
var ACCOUNT_NAME = "key";
|
|
440
|
-
var EIGENX_SERVICE_NAME = "eigenx-cli";
|
|
441
|
-
var EIGENX_DEV_SERVICE_NAME = "eigenx-cli-dev";
|
|
442
|
-
var EIGENX_ACCOUNT_PREFIX = "eigenx-";
|
|
443
|
-
var GO_KEYRING_BASE64_PREFIX = "go-keyring-base64:";
|
|
444
|
-
var GO_KEYRING_ENCODED_PREFIX = "go-keyring-encoded:";
|
|
445
|
-
async function storePrivateKey(privateKey) {
|
|
446
|
-
const normalizedKey = normalizePrivateKey(privateKey);
|
|
447
|
-
const isValid = validatePrivateKey(normalizedKey);
|
|
448
|
-
if (!isValid) {
|
|
449
|
-
throw new Error("Invalid private key format");
|
|
450
|
-
}
|
|
451
|
-
const entry = new AsyncEntry(SERVICE_NAME, ACCOUNT_NAME);
|
|
452
|
-
try {
|
|
453
|
-
await entry.setPassword(normalizedKey);
|
|
454
|
-
} catch (err) {
|
|
455
|
-
throw new Error(
|
|
456
|
-
`Failed to store key in OS keyring: ${err?.message ?? err}. Ensure keyring service is available.`
|
|
457
|
-
);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
async function getPrivateKey() {
|
|
461
|
-
const entry = new AsyncEntry(SERVICE_NAME, ACCOUNT_NAME);
|
|
462
|
-
try {
|
|
463
|
-
const key = await entry.getPassword();
|
|
464
|
-
if (key && validatePrivateKey(key)) {
|
|
465
|
-
return key;
|
|
466
|
-
}
|
|
467
|
-
} catch {
|
|
468
|
-
}
|
|
469
|
-
return null;
|
|
470
|
-
}
|
|
471
|
-
async function deletePrivateKey() {
|
|
472
|
-
const entry = new AsyncEntry(SERVICE_NAME, ACCOUNT_NAME);
|
|
473
|
-
try {
|
|
474
|
-
await entry.deletePassword();
|
|
475
|
-
return true;
|
|
476
|
-
} catch {
|
|
477
|
-
console.warn("No key found in keyring");
|
|
478
|
-
return false;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
async function listStoredKeys() {
|
|
482
|
-
const keys = [];
|
|
483
|
-
const creds = findCredentials(SERVICE_NAME);
|
|
484
|
-
for (const cred of creds) {
|
|
485
|
-
if (cred.account === ACCOUNT_NAME) {
|
|
486
|
-
try {
|
|
487
|
-
const address = getAddressFromPrivateKey(cred.password);
|
|
488
|
-
keys.push({ address });
|
|
489
|
-
} catch (err) {
|
|
490
|
-
console.warn(`Warning: Invalid key found, skipping: ${err}`);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
return keys;
|
|
495
|
-
}
|
|
496
|
-
async function keyExists() {
|
|
497
|
-
const key = await getPrivateKey();
|
|
498
|
-
return key !== null;
|
|
499
|
-
}
|
|
500
|
-
async function getLegacyKeys() {
|
|
501
|
-
const keys = [];
|
|
502
|
-
try {
|
|
503
|
-
const eigenxCreds = findCredentials(EIGENX_SERVICE_NAME);
|
|
504
|
-
for (const cred of eigenxCreds) {
|
|
505
|
-
const accountName = cred.account;
|
|
506
|
-
if (!accountName.startsWith(EIGENX_ACCOUNT_PREFIX)) {
|
|
507
|
-
continue;
|
|
508
|
-
}
|
|
509
|
-
const environment = accountName.substring(EIGENX_ACCOUNT_PREFIX.length);
|
|
510
|
-
try {
|
|
511
|
-
const decodedKey = decodeGoKeyringValue(cred.password);
|
|
512
|
-
const address = getAddressFromPrivateKey(decodedKey);
|
|
513
|
-
keys.push({ environment, address, source: "eigenx" });
|
|
514
|
-
} catch (err) {
|
|
515
|
-
console.warn(
|
|
516
|
-
`Warning: Invalid key found for ${environment} (eigenx-cli), skipping: ${err}`
|
|
517
|
-
);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
} catch {
|
|
521
|
-
}
|
|
522
|
-
try {
|
|
523
|
-
const eigenxDevCreds = findCredentials(EIGENX_DEV_SERVICE_NAME);
|
|
524
|
-
for (const cred of eigenxDevCreds) {
|
|
525
|
-
const accountName = cred.account;
|
|
526
|
-
if (!accountName.startsWith(EIGENX_ACCOUNT_PREFIX)) {
|
|
527
|
-
continue;
|
|
528
|
-
}
|
|
529
|
-
const environment = accountName.substring(EIGENX_ACCOUNT_PREFIX.length);
|
|
530
|
-
try {
|
|
531
|
-
const decodedKey = decodeGoKeyringValue(cred.password);
|
|
532
|
-
const address = getAddressFromPrivateKey(decodedKey);
|
|
533
|
-
keys.push({ environment, address, source: "eigenx-dev" });
|
|
534
|
-
} catch (err) {
|
|
535
|
-
console.warn(
|
|
536
|
-
`Warning: Invalid key found for ${environment} (eigenx-dev), skipping: ${err}`
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
} catch {
|
|
541
|
-
}
|
|
542
|
-
return keys;
|
|
543
|
-
}
|
|
544
|
-
async function getLegacyPrivateKey(environment, source) {
|
|
545
|
-
const serviceName = source === "eigenx" ? EIGENX_SERVICE_NAME : EIGENX_DEV_SERVICE_NAME;
|
|
546
|
-
const accountName = EIGENX_ACCOUNT_PREFIX + environment;
|
|
547
|
-
const entry = new AsyncEntry(serviceName, accountName);
|
|
548
|
-
try {
|
|
549
|
-
const rawKey = await entry.getPassword();
|
|
550
|
-
if (rawKey) {
|
|
551
|
-
const decodedKey = decodeGoKeyringValue(rawKey);
|
|
552
|
-
if (validatePrivateKey(decodedKey)) {
|
|
553
|
-
return decodedKey;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
} catch {
|
|
557
|
-
}
|
|
558
|
-
return null;
|
|
559
|
-
}
|
|
560
|
-
async function deleteLegacyPrivateKey(environment, source) {
|
|
561
|
-
const serviceName = source === "eigenx" ? EIGENX_SERVICE_NAME : EIGENX_DEV_SERVICE_NAME;
|
|
562
|
-
const accountName = EIGENX_ACCOUNT_PREFIX + environment;
|
|
563
|
-
const entry = new AsyncEntry(serviceName, accountName);
|
|
564
|
-
try {
|
|
565
|
-
await entry.deletePassword();
|
|
566
|
-
return true;
|
|
567
|
-
} catch {
|
|
568
|
-
console.warn(`No key found for ${environment} in ${source}`);
|
|
569
|
-
return false;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
function validatePrivateKey(privateKey) {
|
|
573
|
-
try {
|
|
574
|
-
getAddressFromPrivateKey(privateKey);
|
|
575
|
-
return true;
|
|
576
|
-
} catch {
|
|
577
|
-
return false;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
function getAddressFromPrivateKey(privateKey) {
|
|
581
|
-
const normalized = normalizePrivateKey(privateKey);
|
|
582
|
-
return privateKeyToAddress(normalized);
|
|
583
|
-
}
|
|
584
|
-
function decodeGoKeyringValue(rawValue) {
|
|
585
|
-
if (rawValue.startsWith(GO_KEYRING_BASE64_PREFIX)) {
|
|
586
|
-
const encoded = rawValue.substring(GO_KEYRING_BASE64_PREFIX.length);
|
|
587
|
-
try {
|
|
588
|
-
const decoded = Buffer.from(encoded, "base64").toString("utf8");
|
|
589
|
-
return decoded;
|
|
590
|
-
} catch (err) {
|
|
591
|
-
console.warn(`Warning: Failed to decode go-keyring base64 value: ${err}`);
|
|
592
|
-
return rawValue;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
if (rawValue.startsWith(GO_KEYRING_ENCODED_PREFIX)) {
|
|
596
|
-
const encoded = rawValue.substring(GO_KEYRING_ENCODED_PREFIX.length);
|
|
597
|
-
try {
|
|
598
|
-
const decoded = Buffer.from(encoded, "hex").toString("utf8");
|
|
599
|
-
return decoded;
|
|
600
|
-
} catch (err) {
|
|
601
|
-
console.warn(`Warning: Failed to decode go-keyring hex value: ${err}`);
|
|
602
|
-
return rawValue;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
return rawValue;
|
|
606
|
-
}
|
|
607
|
-
function normalizePrivateKey(privateKey) {
|
|
608
|
-
if (!privateKey.startsWith("0x")) {
|
|
609
|
-
return `0x${privateKey}`;
|
|
610
|
-
}
|
|
611
|
-
return privateKey;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// src/client/common/auth/resolver.ts
|
|
615
|
-
async function getPrivateKeyWithSource(options) {
|
|
616
|
-
if (options.privateKey) {
|
|
617
|
-
if (!validatePrivateKey(options.privateKey)) {
|
|
618
|
-
throw new Error(
|
|
619
|
-
"Invalid private key format provided via command flag. Please check and try again."
|
|
620
|
-
);
|
|
621
|
-
}
|
|
622
|
-
return {
|
|
623
|
-
key: options.privateKey,
|
|
624
|
-
source: "command flag"
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
const envKey = process.env.ECLOUD_PRIVATE_KEY;
|
|
628
|
-
if (envKey) {
|
|
629
|
-
if (!validatePrivateKey(envKey)) {
|
|
630
|
-
throw new Error(
|
|
631
|
-
"Invalid private key format provided via environment variable. Please check and try again."
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
|
-
return {
|
|
635
|
-
key: envKey,
|
|
636
|
-
source: "environment variable (ECLOUD_PRIVATE_KEY)"
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
const keyringKey = await getPrivateKey();
|
|
640
|
-
if (keyringKey) {
|
|
641
|
-
return {
|
|
642
|
-
key: keyringKey,
|
|
643
|
-
source: "stored credentials"
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
return null;
|
|
647
|
-
}
|
|
648
|
-
async function requirePrivateKey(options) {
|
|
649
|
-
const result = await getPrivateKeyWithSource({
|
|
650
|
-
privateKey: options.privateKey
|
|
651
|
-
});
|
|
652
|
-
if (!result) {
|
|
653
|
-
throw new Error(
|
|
654
|
-
`Private key required. Please provide it via:
|
|
655
|
-
\u2022 Keyring: ecloud auth login
|
|
656
|
-
\u2022 Flag: --private-key YOUR_KEY
|
|
657
|
-
\u2022 Environment: export ECLOUD_PRIVATE_KEY=YOUR_KEY`
|
|
658
|
-
);
|
|
659
|
-
}
|
|
660
|
-
return result;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// src/client/common/auth/generate.ts
|
|
664
|
-
import { generatePrivateKey, privateKeyToAddress as privateKeyToAddress2 } from "viem/accounts";
|
|
665
|
-
function generateNewPrivateKey() {
|
|
666
|
-
const privateKey = generatePrivateKey();
|
|
667
|
-
const address = privateKeyToAddress2(privateKey);
|
|
668
|
-
return {
|
|
669
|
-
privateKey,
|
|
670
|
-
address
|
|
671
|
-
};
|
|
672
|
-
}
|
|
87
|
+
} from "./chunk-ZEZS5CNB.js";
|
|
673
88
|
|
|
674
89
|
// src/client/common/utils/instance.ts
|
|
675
90
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
@@ -724,20 +139,10 @@ function createECloudClient(cfg) {
|
|
|
724
139
|
};
|
|
725
140
|
}
|
|
726
141
|
export {
|
|
727
|
-
AuthRequiredError,
|
|
728
|
-
BUILD_STATUS,
|
|
729
|
-
BadRequestError,
|
|
730
|
-
BuildError,
|
|
731
|
-
BuildFailedError,
|
|
732
|
-
ConflictError,
|
|
733
|
-
ForbiddenError,
|
|
734
142
|
NoopClient,
|
|
735
|
-
NotFoundError,
|
|
736
143
|
PRIMARY_LANGUAGES,
|
|
737
144
|
PostHogClient,
|
|
738
|
-
TimeoutError,
|
|
739
145
|
UserApiClient,
|
|
740
|
-
addHexPrefix,
|
|
741
146
|
addMetric,
|
|
742
147
|
addMetricWithDimensions,
|
|
743
148
|
assertValidFilePath,
|
|
@@ -747,7 +152,6 @@ export {
|
|
|
747
152
|
createApp,
|
|
748
153
|
createAppEnvironment,
|
|
749
154
|
createBillingModule,
|
|
750
|
-
createBuildModule,
|
|
751
155
|
createComputeModule,
|
|
752
156
|
createECloudClient,
|
|
753
157
|
createMetricsContext,
|
|
@@ -791,15 +195,12 @@ export {
|
|
|
791
195
|
listStoredKeys,
|
|
792
196
|
logs,
|
|
793
197
|
prepareDeploy,
|
|
794
|
-
prepareDeployFromVerifiableBuild,
|
|
795
198
|
prepareUpgrade,
|
|
796
|
-
prepareUpgradeFromVerifiableBuild,
|
|
797
199
|
requirePrivateKey,
|
|
798
200
|
sanitizeString,
|
|
799
201
|
sanitizeURL,
|
|
800
202
|
sanitizeXURL,
|
|
801
203
|
storePrivateKey,
|
|
802
|
-
stripHexPrefix,
|
|
803
204
|
validateAppID,
|
|
804
205
|
validateAppName,
|
|
805
206
|
validateCreateAppParams,
|