@layr-labs/ecloud-cli 0.4.0-dev.1 → 0.4.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.
Files changed (70) hide show
  1. package/VERSION +2 -0
  2. package/bin/dev.js +0 -0
  3. package/dist/commands/auth/generate.js +0 -0
  4. package/dist/commands/auth/login.js +0 -0
  5. package/dist/commands/auth/logout.js +0 -0
  6. package/dist/commands/auth/migrate.js +0 -0
  7. package/dist/commands/auth/whoami.js +1 -0
  8. package/dist/commands/auth/whoami.js.map +1 -1
  9. package/dist/commands/billing/__tests__/status.test.js +89 -22
  10. package/dist/commands/billing/__tests__/status.test.js.map +1 -1
  11. package/dist/commands/billing/__tests__/subscribe.test.js +88 -20
  12. package/dist/commands/billing/__tests__/subscribe.test.js.map +1 -1
  13. package/dist/commands/billing/__tests__/top-up.test.js +139 -201
  14. package/dist/commands/billing/__tests__/top-up.test.js.map +1 -1
  15. package/dist/commands/billing/cancel.js +88 -19
  16. package/dist/commands/billing/cancel.js.map +1 -1
  17. package/dist/commands/billing/status.js +89 -21
  18. package/dist/commands/billing/status.js.map +1 -1
  19. package/dist/commands/billing/subscribe.js +88 -19
  20. package/dist/commands/billing/subscribe.js.map +1 -1
  21. package/dist/commands/billing/top-up.js +102 -91
  22. package/dist/commands/billing/top-up.js.map +1 -1
  23. package/dist/commands/compute/app/configure/tls.js +0 -0
  24. package/dist/commands/compute/app/create.js +1 -0
  25. package/dist/commands/compute/app/create.js.map +1 -1
  26. package/dist/commands/compute/app/deploy.js +38 -24
  27. package/dist/commands/compute/app/deploy.js.map +1 -1
  28. package/dist/commands/compute/app/info.js +2 -1
  29. package/dist/commands/compute/app/info.js.map +1 -1
  30. package/dist/commands/compute/app/list.js +2 -1
  31. package/dist/commands/compute/app/list.js.map +1 -1
  32. package/dist/commands/compute/app/logs.js +5 -8
  33. package/dist/commands/compute/app/logs.js.map +1 -1
  34. package/dist/commands/compute/app/profile/set.js +5 -8
  35. package/dist/commands/compute/app/profile/set.js.map +1 -1
  36. package/dist/commands/compute/app/releases.js +2 -1
  37. package/dist/commands/compute/app/releases.js.map +1 -1
  38. package/dist/commands/compute/app/start.js +5 -8
  39. package/dist/commands/compute/app/start.js.map +1 -1
  40. package/dist/commands/compute/app/stop.js +5 -8
  41. package/dist/commands/compute/app/stop.js.map +1 -1
  42. package/dist/commands/compute/app/terminate.js +5 -8
  43. package/dist/commands/compute/app/terminate.js.map +1 -1
  44. package/dist/commands/compute/app/upgrade.js +36 -14
  45. package/dist/commands/compute/app/upgrade.js.map +1 -1
  46. package/dist/commands/compute/build/info.js +9 -12
  47. package/dist/commands/compute/build/info.js.map +1 -1
  48. package/dist/commands/compute/build/list.js +9 -12
  49. package/dist/commands/compute/build/list.js.map +1 -1
  50. package/dist/commands/compute/build/logs.js +9 -12
  51. package/dist/commands/compute/build/logs.js.map +1 -1
  52. package/dist/commands/compute/build/status.js +9 -12
  53. package/dist/commands/compute/build/status.js.map +1 -1
  54. package/dist/commands/compute/build/submit.js +32 -10
  55. package/dist/commands/compute/build/submit.js.map +1 -1
  56. package/dist/commands/compute/build/verify.js +9 -12
  57. package/dist/commands/compute/build/verify.js.map +1 -1
  58. package/dist/commands/compute/environment/list.js +0 -0
  59. package/dist/commands/compute/environment/set.js +1 -0
  60. package/dist/commands/compute/environment/set.js.map +1 -1
  61. package/dist/commands/compute/environment/show.js +0 -0
  62. package/dist/commands/compute/undelegate.js +5 -8
  63. package/dist/commands/compute/undelegate.js.map +1 -1
  64. package/dist/commands/telemetry/disable.js +0 -0
  65. package/dist/commands/telemetry/enable.js +0 -0
  66. package/dist/commands/telemetry/status.js +0 -0
  67. package/dist/commands/upgrade.js +0 -0
  68. package/dist/commands/version.js +0 -0
  69. package/package.json +15 -14
  70. package/LICENSE +0 -7
@@ -9,9 +9,7 @@ import {
9
9
  createBillingModule,
10
10
  createBuildModule,
11
11
  getEnvironmentConfig as getEnvironmentConfig3,
12
- requirePrivateKey,
13
- getPrivateKeyWithSource,
14
- addHexPrefix as addHexPrefix2
12
+ requirePrivateKey
15
13
  } from "@layr-labs/ecloud-sdk";
16
14
 
17
15
  // src/flags.ts
@@ -166,6 +164,7 @@ var CONFIG_DIR = path2.join(os2.homedir(), ".eigenx");
166
164
  var APPS_DIR = path2.join(CONFIG_DIR, "apps");
167
165
 
168
166
  // src/utils/prompts.ts
167
+ import { execSync } from "child_process";
169
168
  async function getPrivateKeyInteractive(privateKey) {
170
169
  if (privateKey) {
171
170
  if (!validatePrivateKeyFormat(privateKey)) {
@@ -173,8 +172,8 @@ async function getPrivateKeyInteractive(privateKey) {
173
172
  }
174
173
  return privateKey;
175
174
  }
176
- const { getPrivateKeyWithSource: getPrivateKeyWithSource2 } = await import("@layr-labs/ecloud-sdk");
177
- const result = await getPrivateKeyWithSource2({ privateKey: void 0 });
175
+ const { getPrivateKeyWithSource } = await import("@layr-labs/ecloud-sdk");
176
+ const result = await getPrivateKeyWithSource({ privateKey: void 0 });
178
177
  if (result) {
179
178
  return result.key;
180
179
  }
@@ -193,6 +192,50 @@ async function getPrivateKeyInteractive(privateKey) {
193
192
  });
194
193
  return key.trim();
195
194
  }
195
+ async function getEnvironmentInteractive(environment) {
196
+ if (environment) {
197
+ try {
198
+ getEnvironmentConfig2(environment);
199
+ if (!isEnvironmentAvailable(environment)) {
200
+ throw new Error(`Environment ${environment} is not available in this build`);
201
+ }
202
+ return environment;
203
+ } catch {
204
+ }
205
+ }
206
+ const availableEnvs = getAvailableEnvironments();
207
+ let defaultEnv;
208
+ const configDefaultEnv = getDefaultEnvironment();
209
+ if (configDefaultEnv && availableEnvs.includes(configDefaultEnv)) {
210
+ try {
211
+ getEnvironmentConfig2(configDefaultEnv);
212
+ defaultEnv = configDefaultEnv;
213
+ } catch {
214
+ }
215
+ }
216
+ const choices = [];
217
+ if (availableEnvs.includes("sepolia")) {
218
+ choices.push({ name: "sepolia - Ethereum Sepolia testnet", value: "sepolia" });
219
+ }
220
+ if (availableEnvs.includes("sepolia-dev")) {
221
+ choices.push({ name: "sepolia-dev - Ethereum Sepolia testnet (dev)", value: "sepolia-dev" });
222
+ }
223
+ if (availableEnvs.includes("mainnet-alpha")) {
224
+ choices.push({
225
+ name: "mainnet-alpha - Ethereum mainnet (\u26A0\uFE0F uses real funds)",
226
+ value: "mainnet-alpha"
227
+ });
228
+ }
229
+ if (choices.length === 0) {
230
+ throw new Error("No environments available in this build");
231
+ }
232
+ const env = await select({
233
+ message: "Select environment:",
234
+ choices,
235
+ default: defaultEnv
236
+ });
237
+ return env;
238
+ }
196
239
  var MAX_IMAGE_SIZE = 4 * 1024 * 1024;
197
240
 
198
241
  // src/flags.ts
@@ -219,38 +262,41 @@ var commonFlags = {
219
262
  default: false
220
263
  })
221
264
  };
265
+ async function validateCommonFlags(flags, options) {
266
+ flags["environment"] = await getEnvironmentInteractive(flags["environment"]);
267
+ if (options?.requirePrivateKey !== false) {
268
+ flags["private-key"] = await getPrivateKeyInteractive(flags["private-key"]);
269
+ }
270
+ return flags;
271
+ }
222
272
 
223
273
  // src/client.ts
224
- import { createWalletClient, custom } from "viem";
225
- import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
226
274
  async function createBillingClient(flags) {
227
- const result = await getPrivateKeyWithSource({
275
+ flags = await validateCommonFlags(flags);
276
+ const environment = flags.environment;
277
+ const environmentConfig = getEnvironmentConfig3(environment);
278
+ const rpcUrl = flags["rpc-url"] || environmentConfig.billingRPCURL || environmentConfig.defaultRPCURL;
279
+ const { key: privateKey, source } = await requirePrivateKey({
228
280
  privateKey: flags["private-key"]
229
281
  });
230
- const privateKey = await getPrivateKeyInteractive(result?.key);
231
- const account = privateKeyToAccount4(addHexPrefix2(privateKey));
232
- const walletClient = createWalletClient({
233
- account,
234
- transport: custom({
235
- async request() {
236
- throw new Error("RPC not available - billing uses local signing only");
237
- }
238
- })
282
+ if (flags.verbose) {
283
+ console.log(`Using private key from: ${source}`);
284
+ }
285
+ const { walletClient, publicClient } = createViemClients({
286
+ privateKey,
287
+ rpcUrl,
288
+ environment
239
289
  });
240
290
  return createBillingModule({
241
- verbose: flags.verbose ?? false,
291
+ verbose: flags.verbose,
242
292
  walletClient,
293
+ publicClient,
294
+ environment,
243
295
  skipTelemetry: true
244
- // CLI already has telemetry, skip SDK telemetry
245
296
  });
246
297
  }
247
298
 
248
299
  // src/commands/billing/top-up.ts
249
- import {
250
- getEnvironmentConfig as getEnvironmentConfig4,
251
- USDCCreditsABI,
252
- ERC20ABI
253
- } from "@layr-labs/ecloud-sdk";
254
300
  import { formatUnits } from "viem";
255
301
  import chalk2 from "chalk";
256
302
  import { input as input2 } from "@inquirer/prompts";
@@ -340,19 +386,7 @@ var BillingTopUp = class _BillingTopUp extends Command {
340
386
  return withTelemetry(this, async () => {
341
387
  const { flags } = await this.parse(_BillingTopUp);
342
388
  const billing = await createBillingClient(flags);
343
- const privateKey = await getPrivateKeyInteractive(flags["private-key"]);
344
- const { publicClient, walletClient, address: walletAddress } = createViemClients({
345
- privateKey,
346
- rpcUrl: flags["rpc-url"],
347
- environment: flags.environment
348
- });
349
- const environmentConfig = getEnvironmentConfig4(flags.environment);
350
- const usdcCreditsAddress = environmentConfig.usdcCreditsAddress;
351
- if (!usdcCreditsAddress) {
352
- this.error(
353
- `USDCCredits contract is not configured for environment "${flags.environment}". USDC credit purchasing is only available on environments with a deployed USDCCredits contract.`
354
- );
355
- }
389
+ const walletAddress = billing.address;
356
390
  const targetAccount = flags.account ?? walletAddress;
357
391
  this.log(`
358
392
  ${chalk2.bold("Purchase EigenCompute credits")}`);
@@ -362,34 +396,22 @@ ${chalk2.bold("Purchase EigenCompute credits")}`);
362
396
  if (targetAccount !== walletAddress) {
363
397
  this.log(` ${chalk2.bold("Target:")} ${targetAccount}`);
364
398
  }
365
- let currentCredits;
399
+ let baselineTotal;
366
400
  try {
367
401
  const status = await billing.getStatus({
368
402
  productId: flags.product
369
403
  });
370
- currentCredits = status.remainingCredits;
371
- if (currentCredits !== void 0) {
372
- this.log(` ${chalk2.bold("Credits:")} ${chalk2.cyan(`$${currentCredits.toFixed(2)}`)}`);
404
+ const remaining = status.remainingCredits ?? 0;
405
+ const applied = status.creditsApplied ?? 0;
406
+ baselineTotal = remaining + applied;
407
+ if (status.remainingCredits !== void 0) {
408
+ this.log(` ${chalk2.bold("Credits:")} ${chalk2.cyan(`$${status.remainingCredits.toFixed(2)}`)}`);
373
409
  }
374
410
  } catch {
375
411
  this.debug("Could not fetch current credit balance");
376
412
  }
377
- const usdcAddress = await publicClient.readContract({
378
- address: usdcCreditsAddress,
379
- abi: USDCCreditsABI,
380
- functionName: "usdc"
381
- });
382
- const minimumPurchase = await publicClient.readContract({
383
- address: usdcCreditsAddress,
384
- abi: USDCCreditsABI,
385
- functionName: "minimumPurchase"
386
- });
387
- const usdcBalance = await publicClient.readContract({
388
- address: usdcAddress,
389
- abi: ERC20ABI,
390
- functionName: "balanceOf",
391
- args: [walletAddress]
392
- });
413
+ const onChainState = await billing.getTopUpInfo();
414
+ const { usdcBalance, minimumPurchase } = onChainState;
393
415
  const balanceFormatted = formatUnits(usdcBalance, 6);
394
416
  this.log(` ${chalk2.bold("USDC:")} ${balanceFormatted} USDC`);
395
417
  if (usdcBalance === BigInt(0)) {
@@ -426,36 +448,11 @@ ${chalk2.yellow(" No USDC in wallet.")}`);
426
448
  }
427
449
  this.log(`
428
450
  Purchasing ${chalk2.bold(`$${amountFloat.toFixed(2)}`)} in credits...`);
429
- const currentAllowance = await publicClient.readContract({
430
- address: usdcAddress,
431
- abi: ERC20ABI,
432
- functionName: "allowance",
433
- args: [walletAddress, usdcCreditsAddress]
434
- });
435
- if (currentAllowance < amountRaw) {
436
- this.log(chalk2.gray(" Approving USDC spend..."));
437
- const approveTx = await walletClient.writeContract({
438
- address: usdcAddress,
439
- abi: ERC20ABI,
440
- functionName: "approve",
441
- args: [usdcCreditsAddress, amountRaw],
442
- chain: walletClient.chain,
443
- account: walletClient.account
444
- });
445
- await publicClient.waitForTransactionReceipt({ hash: approveTx });
446
- this.log(` ${chalk2.green("\u2713")} Approved`);
447
- }
448
- this.log(chalk2.gray(" Submitting credit purchase..."));
449
- const purchaseTx = await walletClient.writeContract({
450
- address: usdcCreditsAddress,
451
- abi: USDCCreditsABI,
452
- functionName: "purchaseCreditsFor",
453
- args: [amountRaw, targetAccount],
454
- chain: walletClient.chain,
455
- account: walletClient.account
451
+ const { txHash } = await billing.topUp({
452
+ amount: amountRaw,
453
+ account: targetAccount
456
454
  });
457
- const receipt = await publicClient.waitForTransactionReceipt({ hash: purchaseTx });
458
- this.log(` ${chalk2.green("\u2713")} Transaction confirmed: ${receipt.transactionHash}`);
455
+ this.log(` ${chalk2.green("\u2713")} Transaction confirmed: ${txHash}`);
459
456
  this.log(chalk2.gray("\n Waiting for credits to appear..."));
460
457
  const startTime = Date.now();
461
458
  while (Date.now() - startTime < POLL_TIMEOUT_MS) {
@@ -464,11 +461,25 @@ ${chalk2.yellow(" No USDC in wallet.")}`);
464
461
  const status = await billing.getStatus({
465
462
  productId: flags.product
466
463
  });
467
- if (status.remainingCredits !== void 0 && (currentCredits === void 0 || status.remainingCredits > currentCredits)) {
468
- this.log(
469
- `
470
- ${chalk2.green("\u2713")} Credits received! Balance: ${chalk2.cyan(`$${status.remainingCredits.toFixed(2)}`)}`
471
- );
464
+ const remaining = status.remainingCredits ?? 0;
465
+ const applied = status.creditsApplied ?? 0;
466
+ const currentTotal = remaining + applied;
467
+ this.debug(`Poll: remaining=${remaining}, applied=${applied}, total=${currentTotal}, baseline=${baselineTotal}`);
468
+ if (baselineTotal === void 0 || currentTotal > baselineTotal) {
469
+ const creditsAdded = baselineTotal !== void 0 ? currentTotal - baselineTotal : void 0;
470
+ const isMatched = creditsAdded !== void 0 && Math.abs(creditsAdded - amountFloat * 2) < 0.01;
471
+ const appliedFromTopUp = creditsAdded !== void 0 ? creditsAdded - remaining : 0;
472
+ this.log(`
473
+ ${chalk2.green("\u2713")} Credits received: ${chalk2.cyan(`$${(creditsAdded ?? amountFloat).toFixed(2)}`)}`);
474
+ if (isMatched) {
475
+ this.log(` ${chalk2.green("\u2713")} Includes $${amountFloat.toFixed(2)} match bonus!`);
476
+ }
477
+ if (remaining > 0) {
478
+ this.log(` Remaining balance: ${chalk2.cyan(`$${remaining.toFixed(2)}`)}`);
479
+ }
480
+ if (appliedFromTopUp > 0) {
481
+ this.log(` ${chalk2.gray(`$${appliedFromTopUp.toFixed(2)} applied to current bill`)}`);
482
+ }
472
483
  this.log();
473
484
  return;
474
485
  }