@layr-labs/ecloud-cli 1.0.0-dev.3 → 1.0.0-devep1
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/commands/billing/__tests__/status.test.js +23 -4
- package/dist/commands/billing/__tests__/status.test.js.map +1 -1
- package/dist/commands/billing/__tests__/top-up.test.js +89 -273
- package/dist/commands/billing/__tests__/top-up.test.js.map +1 -1
- package/dist/commands/billing/status.js +23 -4
- package/dist/commands/billing/status.js.map +1 -1
- package/dist/commands/billing/top-up.js +79 -151
- package/dist/commands/billing/top-up.js.map +1 -1
- package/dist/commands/compute/app/deploy.js +1 -1
- package/dist/commands/compute/app/deploy.js.map +1 -1
- package/dist/commands/compute/app/info.js +1 -1
- package/dist/commands/compute/app/info.js.map +1 -1
- package/dist/commands/compute/app/list.js +1 -1
- package/dist/commands/compute/app/list.js.map +1 -1
- package/dist/commands/compute/app/logs.js +1 -1
- package/dist/commands/compute/app/logs.js.map +1 -1
- package/dist/commands/compute/app/profile/set.js +1 -1
- package/dist/commands/compute/app/profile/set.js.map +1 -1
- package/dist/commands/compute/app/releases.js +1 -1
- package/dist/commands/compute/app/releases.js.map +1 -1
- package/dist/commands/compute/app/start.js +1 -1
- package/dist/commands/compute/app/start.js.map +1 -1
- package/dist/commands/compute/app/stop.js +1 -1
- package/dist/commands/compute/app/stop.js.map +1 -1
- package/dist/commands/compute/app/terminate.js +1 -1
- package/dist/commands/compute/app/terminate.js.map +1 -1
- package/dist/commands/compute/app/upgrade.js +1 -1
- package/dist/commands/compute/app/upgrade.js.map +1 -1
- package/dist/commands/compute/build/info.js +1 -1
- package/dist/commands/compute/build/info.js.map +1 -1
- package/dist/commands/compute/build/list.js +1 -1
- package/dist/commands/compute/build/list.js.map +1 -1
- package/dist/commands/compute/build/logs.js +1 -1
- package/dist/commands/compute/build/logs.js.map +1 -1
- package/dist/commands/compute/build/status.js +1 -1
- package/dist/commands/compute/build/status.js.map +1 -1
- package/dist/commands/compute/build/submit.js +1 -1
- package/dist/commands/compute/build/submit.js.map +1 -1
- package/dist/commands/compute/build/verify.js +1 -1
- package/dist/commands/compute/build/verify.js.map +1 -1
- package/dist/commands/compute/undelegate.js +1 -1
- package/dist/commands/compute/undelegate.js.map +1 -1
- package/dist/hooks/init/__tests__/version-check.test.js +1 -1
- package/dist/hooks/init/__tests__/version-check.test.js.map +1 -1
- package/dist/hooks/init/version-check.js +1 -1
- package/dist/hooks/init/version-check.js.map +1 -1
- package/package.json +2 -2
- package/dist/commands/billing/list-cards.js +0 -409
- package/dist/commands/billing/list-cards.js.map +0 -1
|
@@ -316,8 +316,7 @@ async function createBillingClient(flags) {
|
|
|
316
316
|
// src/commands/billing/top-up.ts
|
|
317
317
|
import { formatUnits } from "viem";
|
|
318
318
|
import chalk2 from "chalk";
|
|
319
|
-
import { input as input2
|
|
320
|
-
import open from "open";
|
|
319
|
+
import { input as input2 } from "@inquirer/prompts";
|
|
321
320
|
|
|
322
321
|
// src/telemetry.ts
|
|
323
322
|
import {
|
|
@@ -381,22 +380,12 @@ async function withTelemetry(command, action) {
|
|
|
381
380
|
var POLL_INTERVAL_MS = 5e3;
|
|
382
381
|
var POLL_TIMEOUT_MS = 3 * 60 * 1e3;
|
|
383
382
|
var BillingTopUp = class _BillingTopUp extends Command {
|
|
384
|
-
static description = "Purchase EigenCompute credits with USDC
|
|
385
|
-
static examples = [
|
|
386
|
-
"<%= config.bin %> billing top-up",
|
|
387
|
-
"<%= config.bin %> billing top-up --method usdc --amount 50",
|
|
388
|
-
"<%= config.bin %> billing top-up --method card --amount 25"
|
|
389
|
-
];
|
|
383
|
+
static description = "Purchase EigenCompute credits with USDC";
|
|
390
384
|
static flags = {
|
|
391
385
|
...commonFlags,
|
|
392
|
-
method: Flags2.string({
|
|
393
|
-
required: false,
|
|
394
|
-
description: "Payment method: usdc (on-chain) or card (credit card)",
|
|
395
|
-
options: ["usdc", "card"]
|
|
396
|
-
}),
|
|
397
386
|
amount: Flags2.string({
|
|
398
387
|
required: false,
|
|
399
|
-
description: "Amount to spend (
|
|
388
|
+
description: "Amount of USDC to spend (e.g., '50')"
|
|
400
389
|
}),
|
|
401
390
|
account: Flags2.string({
|
|
402
391
|
required: false,
|
|
@@ -432,157 +421,96 @@ ${chalk2.bold("Purchase EigenCompute credits")}`);
|
|
|
432
421
|
const remaining = status.remainingCredits ?? 0;
|
|
433
422
|
const applied = status.creditsApplied ?? 0;
|
|
434
423
|
baselineTotal = remaining + applied;
|
|
435
|
-
|
|
424
|
+
if (status.remainingCredits !== void 0) {
|
|
425
|
+
this.log(` ${chalk2.bold("Credits:")} ${chalk2.cyan(`$${status.remainingCredits.toFixed(2)}`)}`);
|
|
426
|
+
}
|
|
436
427
|
} catch {
|
|
437
428
|
this.debug("Could not fetch current credit balance");
|
|
438
429
|
}
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
});
|
|
446
|
-
if (method === "usdc") {
|
|
447
|
-
await this.handleUsdc(billing, flags, walletAddress, targetAccount, baselineTotal);
|
|
448
|
-
} else {
|
|
449
|
-
await this.handleCard(billing, flags, baselineTotal);
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
async handleUsdc(billing, flags, walletAddress, targetAccount, baselineTotal) {
|
|
454
|
-
const onChainState = await billing.getTopUpInfo();
|
|
455
|
-
const { usdcBalance, minimumPurchase } = onChainState;
|
|
456
|
-
const balanceFormatted = formatUnits(usdcBalance, 6);
|
|
457
|
-
this.log(` ${chalk2.bold("USDC:")} ${balanceFormatted} USDC`);
|
|
458
|
-
if (usdcBalance === BigInt(0)) {
|
|
459
|
-
this.log(`
|
|
430
|
+
const onChainState = await billing.getTopUpInfo();
|
|
431
|
+
const { usdcBalance, minimumPurchase } = onChainState;
|
|
432
|
+
const balanceFormatted = formatUnits(usdcBalance, 6);
|
|
433
|
+
this.log(` ${chalk2.bold("USDC:")} ${balanceFormatted} USDC`);
|
|
434
|
+
if (usdcBalance === BigInt(0)) {
|
|
435
|
+
this.log(`
|
|
460
436
|
${chalk2.yellow(" No USDC in wallet.")}`);
|
|
461
|
-
|
|
462
|
-
|
|
437
|
+
this.log(` Send USDC on Sepolia to: ${chalk2.cyan(walletAddress)}`);
|
|
438
|
+
this.log(` Then re-run: ${chalk2.cyan("ecloud billing top-up")}
|
|
463
439
|
`);
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
const minimumFormatted = formatUnits(minimumPurchase, 6);
|
|
467
|
-
const amountStr = flags.amount ?? await input2({
|
|
468
|
-
message: `How much USDC to spend on credits? (minimum: ${minimumFormatted})`,
|
|
469
|
-
validate: (val) => {
|
|
470
|
-
const n = parseFloat(val);
|
|
471
|
-
if (isNaN(n) || n <= 0) return "Enter a positive number";
|
|
472
|
-
const raw = BigInt(Math.round(n * 1e6));
|
|
473
|
-
if (raw < minimumPurchase)
|
|
474
|
-
return `Minimum purchase is ${minimumFormatted} USDC`;
|
|
475
|
-
if (raw > usdcBalance)
|
|
476
|
-
return `Insufficient balance. You have ${balanceFormatted} USDC`;
|
|
477
|
-
return true;
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
const amountFloat = parseFloat(amountStr);
|
|
481
|
-
const amountRaw = BigInt(Math.round(amountFloat * 1e6));
|
|
482
|
-
if (amountRaw < minimumPurchase) {
|
|
483
|
-
this.error(`Minimum purchase is ${minimumFormatted} USDC`);
|
|
484
|
-
}
|
|
485
|
-
if (amountRaw > usdcBalance) {
|
|
486
|
-
this.error(
|
|
487
|
-
`Insufficient USDC balance. You have ${balanceFormatted} USDC but requested ${amountFloat.toFixed(2)}`
|
|
488
|
-
);
|
|
489
|
-
}
|
|
490
|
-
this.log(`
|
|
491
|
-
Purchasing ${chalk2.bold(`$${amountFloat.toFixed(2)}`)} in credits...`);
|
|
492
|
-
const { txHash } = await billing.topUp({
|
|
493
|
-
amount: amountRaw,
|
|
494
|
-
account: targetAccount
|
|
495
|
-
});
|
|
496
|
-
this.log(` ${chalk2.green("\u2713")} Transaction confirmed: ${txHash}`);
|
|
497
|
-
await this.pollForCredits(billing, flags, baselineTotal, amountFloat);
|
|
498
|
-
}
|
|
499
|
-
async handleCard(billing, flags, baselineTotal) {
|
|
500
|
-
const MINIMUM_DOLLARS = 5;
|
|
501
|
-
const amountStr = flags.amount ?? await input2({
|
|
502
|
-
message: `How many dollars of credits to purchase? (minimum: $${MINIMUM_DOLLARS})`,
|
|
503
|
-
validate: (val) => {
|
|
504
|
-
const n = parseInt(val, 10);
|
|
505
|
-
if (isNaN(n) || n <= 0) return "Enter a positive whole number";
|
|
506
|
-
if (n.toString() !== val.trim()) return "Enter a whole dollar amount (no cents)";
|
|
507
|
-
if (n < MINIMUM_DOLLARS) return `Minimum purchase is $${MINIMUM_DOLLARS}`;
|
|
508
|
-
return true;
|
|
440
|
+
return;
|
|
509
441
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
choices.push({ value: "new", name: "Add a new card" });
|
|
524
|
-
const selection = await select2({
|
|
525
|
-
message: "Which card would you like to use?",
|
|
526
|
-
choices
|
|
442
|
+
const minimumFormatted = formatUnits(minimumPurchase, 6);
|
|
443
|
+
const amountStr = flags.amount ?? await input2({
|
|
444
|
+
message: `How much USDC to spend on credits? (minimum: ${minimumFormatted})`,
|
|
445
|
+
validate: (val) => {
|
|
446
|
+
const n = parseFloat(val);
|
|
447
|
+
if (isNaN(n) || n <= 0) return "Enter a positive number";
|
|
448
|
+
const raw = BigInt(Math.round(n * 1e6));
|
|
449
|
+
if (raw < minimumPurchase)
|
|
450
|
+
return `Minimum purchase is ${minimumFormatted} USDC`;
|
|
451
|
+
if (raw > usdcBalance)
|
|
452
|
+
return `Insufficient balance. You have ${balanceFormatted} USDC`;
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
527
455
|
});
|
|
528
|
-
|
|
529
|
-
|
|
456
|
+
const amountFloat = parseFloat(amountStr);
|
|
457
|
+
const amountRaw = BigInt(Math.round(amountFloat * 1e6));
|
|
458
|
+
if (amountRaw < minimumPurchase) {
|
|
459
|
+
this.error(`Minimum purchase is ${minimumFormatted} USDC`);
|
|
530
460
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
const result = await billing.purchaseCredits(amountCents, paymentMethodId);
|
|
535
|
-
if (result.checkoutUrl) {
|
|
536
|
-
this.log(`
|
|
537
|
-
${chalk2.cyan(result.checkoutUrl)}`);
|
|
538
|
-
this.log(chalk2.gray(" Opening checkout in browser..."));
|
|
539
|
-
await open(result.checkoutUrl);
|
|
540
|
-
} else if (result.checkoutSessionId) {
|
|
541
|
-
this.error(
|
|
542
|
-
"Checkout session created but no URL was returned. Please contact support."
|
|
543
|
-
);
|
|
544
|
-
} else {
|
|
545
|
-
this.log(` ${chalk2.green("\u2713")} Payment submitted`);
|
|
546
|
-
}
|
|
547
|
-
await this.pollForCredits(billing, flags, baselineTotal, dollars);
|
|
548
|
-
}
|
|
549
|
-
async pollForCredits(billing, flags, baselineTotal, amountPurchased) {
|
|
550
|
-
this.log(chalk2.gray("\n Waiting for credits to appear..."));
|
|
551
|
-
const startTime = Date.now();
|
|
552
|
-
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
553
|
-
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
554
|
-
try {
|
|
555
|
-
const status = await billing.getStatus({
|
|
556
|
-
productId: flags.product
|
|
557
|
-
});
|
|
558
|
-
const remaining = status.remainingCredits ?? 0;
|
|
559
|
-
const applied = status.creditsApplied ?? 0;
|
|
560
|
-
const currentTotal = remaining + applied;
|
|
561
|
-
this.debug(
|
|
562
|
-
`Poll: remaining=${remaining}, applied=${applied}, total=${currentTotal}, baseline=${baselineTotal}`
|
|
461
|
+
if (amountRaw > usdcBalance) {
|
|
462
|
+
this.error(
|
|
463
|
+
`Insufficient USDC balance. You have ${balanceFormatted} USDC but requested ${amountFloat.toFixed(2)}`
|
|
563
464
|
);
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
465
|
+
}
|
|
466
|
+
this.log(`
|
|
467
|
+
Purchasing ${chalk2.bold(`$${amountFloat.toFixed(2)}`)} in credits...`);
|
|
468
|
+
const { txHash } = await billing.topUp({
|
|
469
|
+
amount: amountRaw,
|
|
470
|
+
account: targetAccount
|
|
471
|
+
});
|
|
472
|
+
this.log(` ${chalk2.green("\u2713")} Transaction confirmed: ${txHash}`);
|
|
473
|
+
this.log(chalk2.gray("\n Waiting for credits to appear..."));
|
|
474
|
+
const startTime = Date.now();
|
|
475
|
+
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
476
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
477
|
+
try {
|
|
478
|
+
const status = await billing.getStatus({
|
|
479
|
+
productId: flags.product
|
|
480
|
+
});
|
|
481
|
+
const remaining = status.remainingCredits ?? 0;
|
|
482
|
+
const applied = status.creditsApplied ?? 0;
|
|
483
|
+
const currentTotal = remaining + applied;
|
|
484
|
+
this.debug(`Poll: remaining=${remaining}, applied=${applied}, total=${currentTotal}, baseline=${baselineTotal}`);
|
|
485
|
+
if (baselineTotal === void 0 || currentTotal > baselineTotal) {
|
|
486
|
+
const creditsAdded = baselineTotal !== void 0 ? currentTotal - baselineTotal : void 0;
|
|
487
|
+
const isMatched = creditsAdded !== void 0 && Math.abs(creditsAdded - amountFloat * 2) < 0.01;
|
|
488
|
+
const appliedFromTopUp = creditsAdded !== void 0 ? creditsAdded - remaining : 0;
|
|
489
|
+
this.log(`
|
|
490
|
+
${chalk2.green("\u2713")} Credits received: ${chalk2.cyan(`$${(creditsAdded ?? amountFloat).toFixed(2)}`)}`);
|
|
491
|
+
if (isMatched) {
|
|
492
|
+
this.log(` ${chalk2.green("\u2713")} Includes $${amountFloat.toFixed(2)} match bonus!`);
|
|
493
|
+
}
|
|
494
|
+
if (remaining > 0) {
|
|
495
|
+
this.log(` Remaining balance: ${chalk2.cyan(`$${remaining.toFixed(2)}`)}`);
|
|
496
|
+
}
|
|
497
|
+
if (appliedFromTopUp > 0) {
|
|
498
|
+
this.log(` ${chalk2.gray(`$${appliedFromTopUp.toFixed(2)} applied to current bill`)}`);
|
|
499
|
+
}
|
|
500
|
+
this.log();
|
|
501
|
+
return;
|
|
572
502
|
}
|
|
573
|
-
|
|
574
|
-
|
|
503
|
+
} catch {
|
|
504
|
+
this.debug("Error polling for credit balance");
|
|
575
505
|
}
|
|
576
|
-
} catch {
|
|
577
|
-
this.debug("Error polling for credit balance");
|
|
578
506
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
`
|
|
507
|
+
this.log(
|
|
508
|
+
`
|
|
582
509
|
${chalk2.yellow("\u26A0")} Credits haven't appeared yet. This can take a few minutes.`
|
|
583
|
-
|
|
584
|
-
|
|
510
|
+
);
|
|
511
|
+
this.log(` ${chalk2.gray("Check your balance:")} ecloud billing status
|
|
585
512
|
`);
|
|
513
|
+
});
|
|
586
514
|
}
|
|
587
515
|
};
|
|
588
516
|
export {
|