@zeroxyz/cli 1.2.0 → 1.3.0

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 (2) hide show
  1. package/dist/index.js +91 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -76582,7 +76582,7 @@ init_esm_shims();
76582
76582
 
76583
76583
  // package.json
76584
76584
  var package_default = {
76585
- version: "1.2.0"};
76585
+ version: "1.3.0"};
76586
76586
 
76587
76587
  // src/app.ts
76588
76588
  init_esm_shims();
@@ -77578,7 +77578,7 @@ init_esm_shims();
77578
77578
  // ../sdk/dist/index.js
77579
77579
  init_esm_shims();
77580
77580
 
77581
- // ../sdk/dist/chunk-SLXRHGE4.js
77581
+ // ../sdk/dist/chunk-RPL7VC32.js
77582
77582
  init_esm_shims();
77583
77583
 
77584
77584
  // ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
@@ -143021,6 +143021,16 @@ var ZeroPaymentError = class extends ZeroError {
143021
143021
  this.name = "ZeroPaymentError";
143022
143022
  }
143023
143023
  };
143024
+ var ZeroInsufficientFundsError = class extends ZeroError {
143025
+ have;
143026
+ need;
143027
+ constructor(message2, init) {
143028
+ super("insufficient_funds", message2, { cause: init.cause });
143029
+ this.name = "ZeroInsufficientFundsError";
143030
+ this.have = init.have;
143031
+ this.need = init.need;
143032
+ }
143033
+ };
143024
143034
  var ZeroSessionCloseFailedError = class extends ZeroError {
143025
143035
  session;
143026
143036
  response;
@@ -143361,7 +143371,12 @@ var FETCH_SKIP_REASONS = Object.freeze({
143361
143371
  bodyReadFailed: "body_read_failed",
143362
143372
  mppSessionCloseFailedNotRecorded: "mpp_session_close_failed_not_recorded",
143363
143373
  paidButStill402NotRecorded: FETCH_WARNINGS.paidButStill402NotRecorded,
143364
- paymentSettlementUnconfirmed: FETCH_WARNINGS.paymentSettlementUnconfirmed
143374
+ paymentSettlementUnconfirmed: FETCH_WARNINGS.paymentSettlementUnconfirmed,
143375
+ // Pre-sign abort: deliberately NOT recorded as a run — the wallet was
143376
+ // empty before we reached the capability, so charging it as a 402 would
143377
+ // corrupt cap reliability. The wallet funnel is tracked via the
143378
+ // fetch_executed.outcome analytics event instead.
143379
+ insufficientFunds: "insufficient_funds_not_recorded"
143365
143380
  });
143366
143381
  var MAX_RECEIPT_HEADER_BYTES = 8 * 1024;
143367
143382
  var decodeSessionReceiptHeader = (header) => {
@@ -143503,6 +143518,7 @@ var Payments = class {
143503
143518
  );
143504
143519
  let capturedAmount = null;
143505
143520
  let capturedNetwork;
143521
+ let preflightError = null;
143506
143522
  const x402 = registerExactEvmScheme(new x402Client(), { signer: account });
143507
143523
  x402.onBeforePaymentCreation(async (context) => {
143508
143524
  const selected = context.selectedRequirements;
@@ -143536,6 +143552,29 @@ var Payments = class {
143536
143552
  reason: `Payment of ${capturedAmount} USDC exceeds maxPay ${input.maxPay}`
143537
143553
  };
143538
143554
  }
143555
+ const detected = networkToChain(capturedNetwork);
143556
+ const balanceChain = detected === "base-sepolia" ? "base-sepolia" : "base";
143557
+ let balance = null;
143558
+ try {
143559
+ balance = await this.readUsdcBalance(account.address, balanceChain);
143560
+ } catch (readErr) {
143561
+ this.client.logger?.({
143562
+ level: "warn",
143563
+ message: "Pre-flight balance read failed; proceeding to attempt payment",
143564
+ meta: {
143565
+ chain: balanceChain,
143566
+ error: readErr instanceof Error ? readErr.message : String(readErr)
143567
+ }
143568
+ });
143569
+ }
143570
+ if (balance !== null && balance < rawAmountUnits) {
143571
+ const have = formatUnits(balance, 6);
143572
+ preflightError = new ZeroInsufficientFundsError(
143573
+ `wallet has ${have} USDC on Base, needs ${capturedAmount}.`,
143574
+ { have, need: capturedAmount }
143575
+ );
143576
+ return { abort: true, reason: preflightError.message };
143577
+ }
143539
143578
  });
143540
143579
  const configuredFetch = buildConfiguredFetch(this.client, {
143541
143580
  timeoutMs: input.timeoutMs
@@ -143556,6 +143595,7 @@ var Payments = class {
143556
143595
  signal: input.signal
143557
143596
  });
143558
143597
  } catch (err) {
143598
+ if (preflightError) throw preflightError;
143559
143599
  if (err instanceof ZeroError) throw err;
143560
143600
  throw new ZeroPaymentError(
143561
143601
  `x402 payment failed: ${err instanceof Error ? err.message : String(err)}`,
@@ -143800,23 +143840,29 @@ var Payments = class {
143800
143840
  );
143801
143841
  if (tempoBalance < requiredRaw) {
143802
143842
  if (coerced.chain === "tempo-testnet") {
143803
- throw new ZeroPaymentError(
143804
- `Insufficient pathUSD on Tempo testnet: have ${formatUnits(tempoBalance, 6)}, need ${capturedAmount}. Fund via the Tempo testnet faucet: https://docs.tempo.xyz/quickstart/faucet`
143843
+ const have = formatUnits(tempoBalance, 6);
143844
+ throw new ZeroInsufficientFundsError(
143845
+ `Insufficient pathUSD on Tempo testnet: have ${have}, need ${capturedAmount}. Fund via the Tempo testnet faucet: https://docs.tempo.xyz/quickstart/faucet`,
143846
+ { have, need: capturedAmount }
143805
143847
  );
143806
143848
  }
143807
- await this.bridgeBaseToTempo(account, requiredRaw - tempoBalance);
143849
+ await this.bridgeBaseToTempo(account, requiredRaw - tempoBalance, {
143850
+ isSessionDeposit: challenge2.intent === "session",
143851
+ depositTotal: capturedAmount
143852
+ });
143808
143853
  }
143809
143854
  return capturedAmount;
143810
143855
  };
143811
- bridgeBaseToTempo = async (account, requiredAmount) => {
143856
+ bridgeBaseToTempo = async (account, requiredAmount, depositContext) => {
143812
143857
  this.ensureRelayClient();
143813
143858
  const baseBalance = await this.readUsdcBalance(account.address, "base");
143814
143859
  const buffer3 = calculateBuffer(baseBalance);
143815
143860
  const bridgeAmount = requiredAmount + buffer3;
143816
143861
  if (baseBalance < bridgeAmount) {
143817
- throw new ZeroPaymentError(
143818
- `Insufficient Base USDC to bridge: have ${formatUnits(baseBalance, 6)}, need ${formatUnits(bridgeAmount, 6)} (${formatUnits(requiredAmount, 6)} + ${formatUnits(buffer3, 6)} buffer). This capability uses an MPP payment channel, which is pre-funded up front. Either fund your wallet on Base, or pass \`maxPay\` to size a smaller channel (e.g. \`maxPay: '0.05'\` for a ~5-cent channel sized for a single cheap call).`
143819
- );
143862
+ const have = formatUnits(baseBalance, 6);
143863
+ const need = formatUnits(bridgeAmount, 6);
143864
+ const message2 = depositContext?.isSessionDeposit ? `wallet has ${have} USDC on Base, but this capability pre-funds a ${depositContext.depositTotal} USDC MPP payment channel up front (the channel is deposited before the call, so it asks for more than a single charge). Needs ${need} on Base to open it \u2014 fund the wallet, or pass a smaller \`maxPay\` (e.g. '0.05') to size the channel down to one cheap call.` : `wallet has ${have} USDC on Base, needs ${need} to fund this capability's MPP payment channel (${formatUnits(requiredAmount, 6)} + ${formatUnits(buffer3, 6)} buffer). Tip: pass a smaller \`maxPay\` (e.g. '0.05') to size a cheaper channel.`;
143865
+ throw new ZeroInsufficientFundsError(message2, { have, need });
143820
143866
  }
143821
143867
  this.client.logger?.({
143822
143868
  level: "info",
@@ -144034,7 +144080,7 @@ var Payments = class {
144034
144080
  };
144035
144081
  };
144036
144082
  var package_default2 = {
144037
- version: "0.2.0"
144083
+ version: "0.4.0"
144038
144084
  };
144039
144085
  var SDK_VERSION2 = package_default2.version;
144040
144086
  var userWalletDtoSchema = external_exports3.object({
@@ -145395,6 +145441,15 @@ var clientFetch = async (client, url4, opts = {}) => {
145395
145441
  session: err.session
145396
145442
  };
145397
145443
  warnings.push(FETCH_WARNINGS.mppSessionCloseFailed);
145444
+ } else if (err instanceof ZeroInsufficientFundsError) {
145445
+ return errorFetchResult(
145446
+ startedAt,
145447
+ err.message,
145448
+ FETCH_SKIP_REASONS.insufficientFunds,
145449
+ capabilityIdRequested,
145450
+ "insufficient_funds",
145451
+ null
145452
+ );
145398
145453
  } else if (err instanceof ZeroPaymentError || err instanceof ZeroAuthError) {
145399
145454
  const result2 = errorFetchResult(
145400
145455
  startedAt,
@@ -145592,8 +145647,15 @@ var searchResultSchema = external_exports3.object({
145592
145647
  slug: external_exports3.string(),
145593
145648
  name: external_exports3.string(),
145594
145649
  canonicalName: external_exports3.string().nullable().optional(),
145650
+ brandName: external_exports3.string().nullable().optional(),
145595
145651
  description: external_exports3.string(),
145596
145652
  whatItDoes: external_exports3.string().nullable().optional(),
145653
+ // HTTP verb the capability expects. Surfaced on the search row so a caller
145654
+ // can tell GET from POST without a `capabilities.get()` round-trip — enough
145655
+ // to `fetch()` a no-body GET directly. POST bodies still need `get()` for
145656
+ // the `bodySchema`. Optional (not required) so a response that omits it —
145657
+ // an older API deploy — still parses rather than failing the whole search.
145658
+ method: external_exports3.string().optional(),
145597
145659
  url: external_exports3.string(),
145598
145660
  urlTemplate: external_exports3.string().nullable().optional(),
145599
145661
  cost: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }),
@@ -146341,6 +146403,14 @@ var OUTCOMES = {
146341
146403
  errorClass: "payment_rejected",
146342
146404
  reviewable: false
146343
146405
  },
146406
+ // Wallet can't cover the call (pre-sign abort). A funding condition, not
146407
+ // a cap failure — the SDK records no run, so this is the only surviving
146408
+ // signal. Not reviewable (we never reached the capability).
146409
+ insufficient_funds: {
146410
+ exitCode: 1,
146411
+ errorClass: "insufficient_funds",
146412
+ reviewable: false
146413
+ },
146344
146414
  server_error: { exitCode: 0, errorClass: "upstream_4xx", reviewable: true }
146345
146415
  };
146346
146416
  var cliErrorClassFor = (outcome, status, walletAddress) => {
@@ -146757,6 +146827,16 @@ var fetchCommand = (appContext) => new Command("fetch").description(
146757
146827
  ` Payment failed: ${resultError ?? "could not complete payment"}`
146758
146828
  );
146759
146829
  if (legacyMigrateHint) console.error(` ${legacyMigrateHint}`);
146830
+ } else if (outcome === "insufficient_funds") {
146831
+ console.error(
146832
+ ` Insufficient funds: ${resultError ?? "wallet can't cover this call"}`
146833
+ );
146834
+ if (!resultError?.includes("faucet")) {
146835
+ console.error(
146836
+ " Top off your wallet with `zero wallet fund`, then retry."
146837
+ );
146838
+ }
146839
+ if (legacyMigrateHint) console.error(` ${legacyMigrateHint}`);
146760
146840
  } else if (outcome === "payment_rejected") {
146761
146841
  console.error(
146762
146842
  ` Upstream returned 402 after payment was sent \u2014 the seller's facilitator rejected the credential${messageSuffix}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",