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 +19 -0
- package/dist/server-bundle.cjs +43 -4
- package/package.json +1 -1
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
|
package/dist/server-bundle.cjs
CHANGED
|
@@ -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.
|
|
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)
|
|
23538
|
-
|
|
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),
|