@layr-labs/ecloud-cli 1.0.0-dev.1 → 1.0.0-dev.3

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 CHANGED
@@ -1,2 +1,2 @@
1
- version=1.0.0-dev.1
2
- commit=2f1f9686f28371adcd7521bfd335c15cd928f61d
1
+ version=1.0.0-dev.3
2
+ commit=6bdd35bcdef2b55443165112b1eb91ff4cc06e27
@@ -319,7 +319,7 @@ async function createBillingClient(flags) {
319
319
  // src/commands/billing/top-up.ts
320
320
  import { formatUnits } from "viem";
321
321
  import chalk2 from "chalk";
322
- import { input as input2, select as select2, confirm } from "@inquirer/prompts";
322
+ import { input as input2, select as select2 } from "@inquirer/prompts";
323
323
  import open from "open";
324
324
 
325
325
  // src/telemetry.ts
@@ -517,17 +517,19 @@ ${chalk2.yellow(" No USDC in wallet.")}`);
517
517
  }
518
518
  const amountCents = dollars * 100;
519
519
  const { paymentMethods } = await billing.getPaymentMethods();
520
- let useExistingCard = false;
521
520
  let paymentMethodId;
522
521
  if (paymentMethods.length > 0) {
523
- const card = paymentMethods[0];
524
- const lastFour = card.stripePaymentMethodId.slice(-4);
525
- useExistingCard = await confirm({
526
- message: `Use card on file (ending in ${lastFour})?`,
527
- default: true
522
+ const choices = paymentMethods.map((card) => ({
523
+ value: card.id,
524
+ name: `${card.brand.charAt(0).toUpperCase() + card.brand.slice(1)} ending in ${card.last4}`
525
+ }));
526
+ choices.push({ value: "new", name: "Add a new card" });
527
+ const selection = await select2({
528
+ message: "Which card would you like to use?",
529
+ choices
528
530
  });
529
- if (useExistingCard) {
530
- paymentMethodId = card.id;
531
+ if (selection !== "new") {
532
+ paymentMethodId = selection;
531
533
  }
532
534
  }
533
535
  this.log(`
@@ -538,6 +540,10 @@ ${chalk2.yellow(" No USDC in wallet.")}`);
538
540
  ${chalk2.cyan(result.checkoutUrl)}`);
539
541
  this.log(chalk2.gray(" Opening checkout in browser..."));
540
542
  await open(result.checkoutUrl);
543
+ } else if (result.checkoutSessionId) {
544
+ this.error(
545
+ "Checkout session created but no URL was returned. Please contact support."
546
+ );
541
547
  } else {
542
548
  this.log(` ${chalk2.green("\u2713")} Payment submitted`);
543
549
  }
@@ -584,7 +590,7 @@ ${chalk2.yellow(" No USDC in wallet.")}`);
584
590
  };
585
591
 
586
592
  // src/commands/billing/__tests__/top-up.test.ts
587
- import { input as input3, select as select3, confirm as confirm2 } from "@inquirer/prompts";
593
+ import { input as input3, select as select3 } from "@inquirer/prompts";
588
594
  vi.mock("../../../client", () => ({
589
595
  createBillingClient: vi.fn()
590
596
  }));
@@ -593,8 +599,7 @@ vi.mock("../../../telemetry", () => ({
593
599
  }));
594
600
  vi.mock("@inquirer/prompts", () => ({
595
601
  input: vi.fn(),
596
- select: vi.fn(),
597
- confirm: vi.fn()
602
+ select: vi.fn()
598
603
  }));
599
604
  vi.mock("open", () => ({
600
605
  default: vi.fn()
@@ -753,14 +758,23 @@ describe("ecloud billing top-up", () => {
753
758
  expect(fullOutput).toContain("Transaction confirmed");
754
759
  expect(fullOutput).toContain("Credits haven't appeared yet");
755
760
  });
756
- it("credit card: charges existing card on file", async () => {
761
+ it("credit card: charges selected card on file", async () => {
757
762
  mockBilling.getStatus.mockResolvedValueOnce({ subscriptionStatus: "active", remainingCredits: 10 }).mockResolvedValueOnce({ subscriptionStatus: "active", remainingCredits: 35 });
758
763
  mockBilling.getPaymentMethods.mockResolvedValue({
759
764
  paymentMethods: [
760
765
  {
761
766
  id: "029641fc-3e5c-11f1-986c-5601121cbf6d",
762
767
  stripePaymentMethodId: "pm_1ABC1234",
768
+ brand: "visa",
769
+ last4: "1234",
763
770
  createdAt: "2026-04-20T15:00:00Z"
771
+ },
772
+ {
773
+ id: "139752fd-4e6d-22f2-a97d-6712232dcg7e",
774
+ stripePaymentMethodId: "pm_2DEF5678",
775
+ brand: "mastercard",
776
+ last4: "5678",
777
+ createdAt: "2026-04-21T10:00:00Z"
764
778
  }
765
779
  ]
766
780
  });
@@ -768,7 +782,7 @@ describe("ecloud billing top-up", () => {
768
782
  purchaseId: "a1b2c3d4",
769
783
  amountCents: "2500"
770
784
  });
771
- confirm2.mockResolvedValue(true);
785
+ select3.mockResolvedValue("029641fc-3e5c-11f1-986c-5601121cbf6d");
772
786
  const cmd = createCommand({ amount: "25", method: "card" });
773
787
  const promise = cmd.run();
774
788
  for (let i = 0; i < 10; i++) {
@@ -780,7 +794,7 @@ describe("ecloud billing top-up", () => {
780
794
  expect(fullOutput).toContain("Payment submitted");
781
795
  expect(fullOutput).toContain("Credits received");
782
796
  });
783
- it("credit card: opens checkout when user declines existing card", async () => {
797
+ it("credit card: opens checkout when user selects add new card", async () => {
784
798
  const openMock = (await import("open")).default;
785
799
  mockBilling.getStatus.mockResolvedValue({ subscriptionStatus: "active", remainingCredits: 10 });
786
800
  mockBilling.getPaymentMethods.mockResolvedValue({
@@ -788,6 +802,8 @@ describe("ecloud billing top-up", () => {
788
802
  {
789
803
  id: "029641fc-3e5c-11f1-986c-5601121cbf6d",
790
804
  stripePaymentMethodId: "pm_1ABC1234",
805
+ brand: "visa",
806
+ last4: "1234",
791
807
  createdAt: "2026-04-20T15:00:00Z"
792
808
  }
793
809
  ]
@@ -797,7 +813,7 @@ describe("ecloud billing top-up", () => {
797
813
  checkoutUrl: "https://checkout.stripe.com/test",
798
814
  amountCents: "2500"
799
815
  });
800
- confirm2.mockResolvedValue(false);
816
+ select3.mockResolvedValue("new");
801
817
  const cmd = createCommand({ amount: "25", method: "card" });
802
818
  const promise = cmd.run();
803
819
  await vi.advanceTimersByTimeAsync(2e5);
@@ -821,7 +837,7 @@ describe("ecloud billing top-up", () => {
821
837
  await vi.advanceTimersByTimeAsync(2e5);
822
838
  await promise;
823
839
  const fullOutput = logOutput.join("\n");
824
- expect(confirm2).not.toHaveBeenCalled();
840
+ expect(select3).not.toHaveBeenCalled();
825
841
  expect(mockBilling.purchaseCredits).toHaveBeenCalledWith(5e3, void 0);
826
842
  expect(openMock).toHaveBeenCalledWith("https://checkout.stripe.com/test");
827
843
  expect(fullOutput).toContain("https://checkout.stripe.com/test");