agentic-wallet-mcp 0.9.1 → 0.9.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/CHANGELOG.md CHANGED
@@ -8,6 +8,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  > Entries for 0.5.0 and earlier were reconstructed from commit history when this file was
9
9
  > introduced in 0.6.0, so they summarise each release rather than being exhaustive.
10
10
 
11
+ ## [0.9.2] — 3 September 2026
12
+
13
+ ### Fixed
14
+
15
+ - **`request_ai_birthcert_verification`'s sponsored-payment path no longer surfaces a facilitator
16
+ insufficient-funds rejection as an opaque, unhandled MCP tool error.** A `461407`
17
+ (`X402_INSUFFICIENT_FUNDS`) rejection from the facilitator's `/prepare` endpoint is now reshaped
18
+ into a clean `{ error }` result naming the asset and amount, instead of falling through every
19
+ error branch and throwing raw.
20
+ - **That message now renders amounts in human units, not raw base units.** A raw base-unit count
21
+ next to a token symbol (e.g. "requires 1,000,000 of JMYR") reads as a million *whole* tokens —
22
+ for a 6-decimal asset the actual requirement was 1 JMYR, a 1,000,000x misreading that could lead
23
+ to a drastically oversized top-up. Amounts are now resolved through the same symbol/decimals
24
+ formatter the rest of the wallet already uses.
25
+ - **The reported "current balance" is read from the facilitator's structured response field when
26
+ available**, falling back to parsing it out of the free-text error message only for an
27
+ older/unfixed facilitator — the free-text format was never a stable contract between the two
28
+ services.
29
+
11
30
  ## [0.9.1] — 28 August 2026
12
31
 
13
32
  ### Fixed
@@ -12549,7 +12549,7 @@ var import_node_path6 = require("node:path");
12549
12549
  // package.json
12550
12550
  var package_default = {
12551
12551
  name: "agentic-wallet-mcp",
12552
- version: "0.9.1",
12552
+ version: "0.9.2",
12553
12553
  description: "Agent-facing MCP wallet for Zetrix \u2014 orchestrates x401 identity proof, x402 payment, and MBI VC issuance",
12554
12554
  keywords: [
12555
12555
  "mcp",
@@ -23496,6 +23496,7 @@ var DEFINITIVE_PREPARE_REFUSALS = /* @__PURE__ */ new Set([
23496
23496
  461415
23497
23497
  // X402_UNSUPPORTED_ASSET — sponsorship is ZTP-20 only
23498
23498
  ]);
23499
+ var FACILITATOR_INSUFFICIENT_FUNDS_CODE = 461407;
23499
23500
  function facilitatorErrorCode(err) {
23500
23501
  const m = /"errorCode"\s*:\s*(\d{6})/.exec(err instanceof Error ? err.message : String(err));
23501
23502
  return m ? Number(m[1]) : void 0;
@@ -23515,6 +23516,41 @@ function isDefinitiveSponsorshipFailure(err) {
23515
23516
  if (code === void 0) return false;
23516
23517
  return DEFINITIVE_PREPARE_REFUSALS.has(code);
23517
23518
  }
23519
+ var FacilitatorInsufficientFundsError = class extends Error {
23520
+ constructor(requiredHuman, availableHuman, rawMessage) {
23521
+ super(
23522
+ `insufficient funds: the sponsored payment requires ${requiredHuman}` + (availableHuman !== void 0 ? ` \u2014 this wallet currently holds ${availableHuman}` : " and this wallet does not hold enough of it") + ` (facilitator: ${rawMessage})`
23523
+ );
23524
+ this.name = "FacilitatorInsufficientFundsError";
23525
+ }
23526
+ };
23527
+ function extractFacilitatorBalance(rawMessage) {
23528
+ const braceIdx = rawMessage.indexOf("{");
23529
+ if (braceIdx !== -1) {
23530
+ try {
23531
+ const body = JSON.parse(rawMessage.slice(braceIdx));
23532
+ const detail = body.messages?.[0]?.detail;
23533
+ if (Array.isArray(detail) && detail.length >= 3 && detail[2] !== null && detail[2] !== void 0) {
23534
+ return String(detail[2]);
23535
+ }
23536
+ } catch {
23537
+ }
23538
+ }
23539
+ const m = /insufficient_funds \[[^,]+,\s*[^,]+,\s*([^\]]+)\]/.exec(rawMessage);
23540
+ return m ? m[1].trim() : void 0;
23541
+ }
23542
+ async function toFacilitatorInsufficientFundsError(err, accept, formatAssetAmount) {
23543
+ if (!(err instanceof PrepareStageError)) return err;
23544
+ if (facilitatorErrorCode(err.cause) !== FACILITATOR_INSUFFICIENT_FUNDS_CODE) return err;
23545
+ const asset = accept.asset ?? "";
23546
+ const maxAmountRequired = accept.maxAmountRequired ?? "";
23547
+ if (!asset || !maxAmountRequired) return err;
23548
+ const rawMessage = err.cause instanceof Error ? err.cause.message : String(err.cause);
23549
+ const requiredHuman = formatAssetAmount ? await formatAssetAmount(asset, maxAmountRequired) : `${maxAmountRequired} of asset "${asset}"`;
23550
+ const availableRaw = extractFacilitatorBalance(rawMessage);
23551
+ const availableHuman = availableRaw !== void 0 && formatAssetAmount ? await formatAssetAmount(asset, availableRaw) : availableRaw;
23552
+ return new FacilitatorInsufficientFundsError(requiredHuman, availableHuman, rawMessage);
23553
+ }
23518
23554
  async function attemptCandidate(deps, accept, buildBody, onQueued) {
23519
23555
  let xPayment;
23520
23556
  try {
@@ -23534,8 +23570,9 @@ async function payAndCreateSession(deps, buildBody, onQueued) {
23534
23570
  return await attemptCandidate(deps, primary, buildBody, onQueued);
23535
23571
  } catch (err) {
23536
23572
  const fallback = candidates[1];
23537
- if (!fallback || !isSponsored(primary) || isSponsored(fallback)) throw err;
23538
- if (!isDefinitiveSponsorshipFailure(err)) throw err;
23573
+ if (!fallback || !isSponsored(primary) || isSponsored(fallback) || !isDefinitiveSponsorshipFailure(err)) {
23574
+ throw await toFacilitatorInsufficientFundsError(err, primary, deps.formatAssetAmount);
23575
+ }
23539
23576
  return await attemptCandidate(deps, fallback, buildBody, onQueued);
23540
23577
  }
23541
23578
  }
@@ -23605,6 +23642,7 @@ async function requestAiBirthcertVerificationLocked(deps, agentName, input) {
23605
23642
  if (err instanceof PaymentReadinessError) return { error: `insufficient funds: ${err.message}` };
23606
23643
  if (err instanceof PaymentCapError) return { error: err.message };
23607
23644
  if (err instanceof NoPaymentOptionsError) return { error: err.message };
23645
+ if (err instanceof FacilitatorInsufficientFundsError) return { error: err.message };
23608
23646
  if (err instanceof SettlementStillQueuedError) {
23609
23647
  try {
23610
23648
  await deps.sessionStore.set({
@@ -24015,7 +24053,8 @@ async function main() {
24015
24053
  cache: vcCache,
24016
24054
  quarantine: downloadQuarantine,
24017
24055
  gasPreference: config2.gasPreference,
24018
- maxSettlementAttempts: config2.maxSettlementAttempts
24056
+ maxSettlementAttempts: config2.maxSettlementAttempts,
24057
+ formatAssetAmount
24019
24058
  };
24020
24059
  return {
24021
24060
  request: (input) => requestAiBirthcertVerification(verifyAiBirthcertDeps, input),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-wallet-mcp",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Agent-facing MCP wallet for Zetrix — orchestrates x401 identity proof, x402 payment, and MBI VC issuance",
5
5
  "keywords": [
6
6
  "mcp",