@haven_ai/sdk 0.1.30-alpha.0 → 0.1.32-alpha.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.
- package/README.md +110 -91
- package/dist/index.cjs +175 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +127 -37
- package/dist/index.d.ts +127 -37
- package/dist/index.js +175 -109
- package/dist/index.js.map +1 -1
- package/examples/mcp-x402-sse.ts +2 -2
- package/examples/x402_openapi_python.py +8 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -18,33 +18,40 @@ var AgentPaymentPhase = {
|
|
|
18
18
|
PaymentSubmitted: "payment_submitted",
|
|
19
19
|
/** The direct payment is confirmed; the agent does not need to do more for this payment id. */
|
|
20
20
|
PaymentConfirmed: "payment_confirmed",
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* #2115: RETIRED wire value — no live rail produces it. It described the
|
|
23
|
+
* Safe rail's approval queue, which no longer exists. Kept so a stored value
|
|
24
|
+
* still typechecks; see `AgentPaymentPhaseDescriptions` below for the
|
|
25
|
+
* agent-visible wording, which this comment used to contradict.
|
|
26
|
+
*/
|
|
22
27
|
UserApprovalRequired: "user_approval_required",
|
|
23
|
-
/**
|
|
28
|
+
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
24
29
|
UserExecutionRequired: "user_execution_required",
|
|
25
|
-
/**
|
|
30
|
+
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
26
31
|
WaitingForAdditionalApprovals: "waiting_for_additional_approvals",
|
|
27
32
|
/** The Haven funding leg was sent; the agent can continue the merchant/protocol leg. */
|
|
28
33
|
FundingSent: "funding_sent",
|
|
29
|
-
/** The
|
|
34
|
+
/** The payment was rejected and cannot proceed; the agent should stop and tell the user. */
|
|
30
35
|
Rejected: "rejected",
|
|
31
|
-
/** The payment
|
|
36
|
+
/** The payment expired before completion. */
|
|
32
37
|
Expired: "expired",
|
|
33
38
|
/** Haven could not complete the payment; the agent should stop and surface the failure. */
|
|
34
39
|
Failed: "failed",
|
|
35
40
|
/**
|
|
36
41
|
* Pre-flight check determined the delegate's existing balance plus the
|
|
37
|
-
* remaining on-chain
|
|
38
|
-
* payment intent was created.
|
|
39
|
-
*
|
|
40
|
-
*
|
|
42
|
+
* remaining on-chain budget cannot cover the requested amount, so no
|
|
43
|
+
* payment intent was created. The account must be funded or the agent's
|
|
44
|
+
* budget raised before retrying — #2115: the old wording contrasted this
|
|
45
|
+
* with `UserApprovalRequired` as if that were a live alternative, and named
|
|
46
|
+
* the retired rail's Safe and per-token allowance as the fix.
|
|
41
47
|
*/
|
|
42
48
|
InsufficientFunds: "insufficient_funds",
|
|
43
49
|
/**
|
|
44
|
-
* Haven's funding leg (
|
|
45
|
-
* merchant rejected the x402 retry. The delegate
|
|
46
|
-
* USDC that was never settled to the merchant. The
|
|
47
|
-
* the user, and wait for the sweep flow to reclaim
|
|
50
|
+
* Haven's funding leg (account → delegate, the #946 EIP-3009 bridge)
|
|
51
|
+
* confirmed on-chain, but the merchant rejected the x402 retry. The delegate
|
|
52
|
+
* wallet may hold stranded USDC that was never settled to the merchant. The
|
|
53
|
+
* agent should stop, tell the user, and wait for the sweep flow to reclaim
|
|
54
|
+
* the funds.
|
|
48
55
|
*/
|
|
49
56
|
FundedButUnsettled: "funded_but_unsettled"
|
|
50
57
|
};
|
|
@@ -55,9 +62,12 @@ var AgentPaymentNextAction = {
|
|
|
55
62
|
CheckStatusLater: "check_status_later",
|
|
56
63
|
/** No further agent action is required for this payment id. */
|
|
57
64
|
None: "none",
|
|
58
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* #2115: RETIRED wire value — no live rail produces it and nothing maps to
|
|
67
|
+
* it. Stop and tell the user rather than polling; no approval will arrive.
|
|
68
|
+
*/
|
|
59
69
|
WaitForUserApproval: "wait_for_user_approval",
|
|
60
|
-
/**
|
|
70
|
+
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user rather than polling. */
|
|
61
71
|
WaitForUserToCompletePayment: "wait_for_user_to_complete_payment",
|
|
62
72
|
/** Resume this payment id and retry the original x402 request with the merchant payment header. */
|
|
63
73
|
RetryOriginalX402Request: "retry_original_x402_request",
|
|
@@ -147,29 +157,29 @@ var AgentPaymentPhaseDescriptions = {
|
|
|
147
157
|
[AgentPaymentPhase.AgentSignatureRequired]: "The agent must sign and submit the prepared payment before Haven can relay it.",
|
|
148
158
|
[AgentPaymentPhase.PaymentSubmitted]: "Haven has received the signed payment and the agent should poll for confirmation.",
|
|
149
159
|
[AgentPaymentPhase.PaymentConfirmed]: "The direct payment is confirmed; the agent does not need to do more for this payment id.",
|
|
150
|
-
[AgentPaymentPhase.UserApprovalRequired]: "
|
|
151
|
-
[AgentPaymentPhase.UserExecutionRequired]: "
|
|
152
|
-
[AgentPaymentPhase.WaitingForAdditionalApprovals]: "
|
|
160
|
+
[AgentPaymentPhase.UserApprovalRequired]: "Retired wire value: no live rail produces it. It described the Safe rail's approval queue, which no longer exists \u2014 an out-of-policy payment is declined before any money moves. If it is ever seen, stop and tell the user; no approval is pending.",
|
|
161
|
+
[AgentPaymentPhase.UserExecutionRequired]: "Retired wire value: no live rail produces it. Stop and tell the user.",
|
|
162
|
+
[AgentPaymentPhase.WaitingForAdditionalApprovals]: "Retired wire value: no live rail produces it. Stop and tell the user.",
|
|
153
163
|
[AgentPaymentPhase.FundingSent]: "The Haven funding leg was sent; the agent can continue the merchant/protocol leg.",
|
|
154
|
-
[AgentPaymentPhase.Rejected]: "The
|
|
155
|
-
[AgentPaymentPhase.Expired]: "The payment
|
|
164
|
+
[AgentPaymentPhase.Rejected]: "The payment was rejected and cannot proceed; the agent should stop and tell the user.",
|
|
165
|
+
[AgentPaymentPhase.Expired]: "The payment expired before completion.",
|
|
156
166
|
[AgentPaymentPhase.Failed]: "Haven could not complete the payment; the agent should stop and surface the failure.",
|
|
157
|
-
[AgentPaymentPhase.InsufficientFunds]: "Pre-flight check determined the delegate balance plus the remaining on-chain
|
|
158
|
-
[AgentPaymentPhase.FundedButUnsettled]: "Haven's funding leg confirmed on-chain but the merchant rejected the x402 retry. The delegate wallet may hold stranded funds. The agent should stop and wait for the wallet owner to sweep the stranded funds back to the
|
|
167
|
+
[AgentPaymentPhase.InsufficientFunds]: "Pre-flight check determined the delegate balance plus the remaining on-chain budget cannot cover the requested amount, so no payment was created. The account must be funded or the agent budget raised before retrying.",
|
|
168
|
+
[AgentPaymentPhase.FundedButUnsettled]: "Haven's funding leg confirmed on-chain but the merchant rejected the x402 retry. The delegate wallet may hold stranded funds. The agent should stop and wait for the wallet owner to sweep the stranded funds back to the account."
|
|
159
169
|
};
|
|
160
170
|
var AgentPaymentNextActionDescriptions = {
|
|
161
171
|
[AgentPaymentNextAction.SignAndSubmitPayment]: "Sign with the delegate key and submit the payment to Haven.",
|
|
162
172
|
[AgentPaymentNextAction.CheckStatusLater]: "Poll getPaymentStatus later using this payment id.",
|
|
163
173
|
[AgentPaymentNextAction.None]: "No further agent action is required for this payment id.",
|
|
164
|
-
[AgentPaymentNextAction.WaitForUserApproval]: "
|
|
165
|
-
[AgentPaymentNextAction.WaitForUserToCompletePayment]: "
|
|
174
|
+
[AgentPaymentNextAction.WaitForUserApproval]: "Retired wire value: no live rail produces it, and nothing maps to it. It described a per-payment approval queue that no longer exists. If it is ever seen, stop and tell the user rather than polling \u2014 no approval will arrive.",
|
|
175
|
+
[AgentPaymentNextAction.WaitForUserToCompletePayment]: "Retired wire value: no live rail produces it. Stop and tell the user rather than polling.",
|
|
166
176
|
[AgentPaymentNextAction.RetryOriginalX402Request]: "Resume this payment id and retry the original x402 request with the merchant payment header.",
|
|
167
177
|
[AgentPaymentNextAction.StopAndTellUser]: "Stop retrying this payment and tell the user what happened.",
|
|
168
178
|
[AgentPaymentNextAction.RequestAgainIfUserStillWantsIt]: "Ask again only if the user still wants the payment after expiry.",
|
|
169
179
|
[AgentPaymentNextAction.PaymentWindowExpired]: "The x402 funding/quote window expired. Re-quote with the same idempotency key before asking the signer to build a merchant payment header again.",
|
|
170
|
-
[AgentPaymentNextAction.FundSafeOrRaiseAllowance]: "Stop and tell the user that the
|
|
180
|
+
[AgentPaymentNextAction.FundSafeOrRaiseAllowance]: "Stop and tell the user that the account needs to be funded or the agent budget raised before the payment can succeed.",
|
|
171
181
|
[AgentPaymentNextAction.RetryWithExplicitContext]: "Retry the same tool call, this time passing merchant_url, tool_name, arguments, and mcp_transport explicitly \u2014 the server had no stored context to rehydrate for this payment id.",
|
|
172
|
-
[AgentPaymentNextAction.SweepStrandedFunds]: "Tell the user that funds may be stranded in the delegate wallet and prompt them to initiate a sweep in Haven to return them to the originating
|
|
182
|
+
[AgentPaymentNextAction.SweepStrandedFunds]: "Tell the user that funds may be stranded in the delegate wallet and prompt them to initiate a sweep in Haven to return them to the originating account."
|
|
173
183
|
};
|
|
174
184
|
var AgentPaymentFailureCodeDescriptions = {
|
|
175
185
|
[AgentPaymentFailureCode.PriceExceedsMax]: "The merchant-authoritative x402 amount exceeds the caller's max_amount cap. No funding transfer was created; ask the user before retrying with a larger cap.",
|
|
@@ -212,7 +222,7 @@ var AgentPaymentWarningCode = {
|
|
|
212
222
|
AllowanceReadOptimistic: "ALLOWANCE_READ_OPTIMISTIC"
|
|
213
223
|
};
|
|
214
224
|
var AgentPaymentRailDescriptions = {
|
|
215
|
-
[AgentPaymentRail.Direct]: "Standard Haven payment from the user-controlled
|
|
225
|
+
[AgentPaymentRail.Direct]: "Standard Haven payment from the user-controlled account, redeeming the agent's on-chain budget delegation.",
|
|
216
226
|
[AgentPaymentRail.X402]: "x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg.",
|
|
217
227
|
[AgentPaymentRail.Mpp]: "Categorical MPP rail value used as a resume-state discriminator. Response bodies carry a granular mpp_* value instead.",
|
|
218
228
|
[AgentPaymentRail.MppDemo]: "Haven internal MPP demo rail. Not for production traffic.",
|
|
@@ -1146,10 +1156,10 @@ function nextActionForStatus(status) {
|
|
|
1146
1156
|
if (status === "pending_signature") return AgentPaymentNextAction.SignAndSubmitPayment;
|
|
1147
1157
|
if (status === "submitted") return AgentPaymentNextAction.CheckStatusLater;
|
|
1148
1158
|
if (status === "confirmed") return AgentPaymentNextAction.None;
|
|
1149
|
-
if (status === "pending" || status === "pending_approval") return AgentPaymentNextAction.
|
|
1159
|
+
if (status === "pending" || status === "pending_approval") return AgentPaymentNextAction.StopAndTellUser;
|
|
1150
1160
|
if (status === "approved") return AgentPaymentNextAction.WaitForUserToCompletePayment;
|
|
1151
|
-
if (status === "proposed") return AgentPaymentNextAction.
|
|
1152
|
-
if (status === "executed") return AgentPaymentNextAction.
|
|
1161
|
+
if (status === "proposed") return AgentPaymentNextAction.StopAndTellUser;
|
|
1162
|
+
if (status === "executed") return AgentPaymentNextAction.StopAndTellUser;
|
|
1153
1163
|
if (status === "rejected") return AgentPaymentNextAction.StopAndTellUser;
|
|
1154
1164
|
if (status === "expired") return AgentPaymentNextAction.RequestAgainIfUserStillWantsIt;
|
|
1155
1165
|
if (status === "failed") return AgentPaymentNextAction.StopAndTellUser;
|
|
@@ -1157,10 +1167,10 @@ function nextActionForStatus(status) {
|
|
|
1157
1167
|
}
|
|
1158
1168
|
function messageForState(label, status, paymentId, nextAction) {
|
|
1159
1169
|
if (status === "pending" || status === "pending_approval") {
|
|
1160
|
-
return `${label} is
|
|
1170
|
+
return `${label} is not payable: it is outside the agent's on-chain budget and no approval is pending (payment_id: ${paymentId}). Ask the user to grant or raise the budget in Haven.`;
|
|
1161
1171
|
}
|
|
1162
1172
|
if (status === "executed") {
|
|
1163
|
-
return "
|
|
1173
|
+
return `This payment carries a retired status ("executed") that no live Haven rail produces (payment_id: ${paymentId}). Do not retry it \u2014 tell the user to review this payment in Haven.`;
|
|
1164
1174
|
}
|
|
1165
1175
|
if (status === "rejected") {
|
|
1166
1176
|
return `The user rejected this payment request (payment_id: ${paymentId}).`;
|
|
@@ -1227,7 +1237,7 @@ function throwPaymentStateError(label, raw) {
|
|
|
1227
1237
|
}
|
|
1228
1238
|
if (raw.status === "pending_approval") {
|
|
1229
1239
|
throw new HavenApiError(
|
|
1230
|
-
`${label} exceeds the on-chain
|
|
1240
|
+
`${label} exceeds the agent's on-chain budget and was declined; no approval is pending and none will arrive (payment_id: ${raw.payment_id}).`,
|
|
1231
1241
|
statusCode,
|
|
1232
1242
|
raw
|
|
1233
1243
|
);
|
|
@@ -1771,13 +1781,18 @@ function requestInitFromSnapshot(request) {
|
|
|
1771
1781
|
body: request.body
|
|
1772
1782
|
};
|
|
1773
1783
|
}
|
|
1784
|
+
function noCompatiblePaymentOptionError(accepts) {
|
|
1785
|
+
const erc7710Only = selectErc7710PaymentOption(accepts) !== null;
|
|
1786
|
+
return new HavenApiError(
|
|
1787
|
+
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC." + (erc7710Only ? " The only Haven-compatible option this merchant advertises is tagged extra.assetTransferMethod: 'erc7710' (direct settlement), which this EIP-3009 payment path cannot settle \u2014 the limitation is the settlement scheme, not the asset. Paying this merchant requires a delegation-rail erc7710 flow (settleX402Erc7710, or the hosted MCP purchase tools)." : ""),
|
|
1788
|
+
400
|
|
1789
|
+
);
|
|
1790
|
+
}
|
|
1774
1791
|
function buildX402Quote(paymentRequired, request, idempotencyKey, mcpTransport) {
|
|
1775
|
-
const
|
|
1792
|
+
const standard = selectStandardPaymentOption(paymentRequired.accepts);
|
|
1793
|
+
const option = standard ?? selectErc7710PaymentOption(paymentRequired.accepts);
|
|
1776
1794
|
if (!option) {
|
|
1777
|
-
throw
|
|
1778
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
1779
|
-
400
|
|
1780
|
-
);
|
|
1795
|
+
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
1781
1796
|
}
|
|
1782
1797
|
const token = resolveTokenFromAddress(option.asset, option.network);
|
|
1783
1798
|
return {
|
|
@@ -1785,6 +1800,7 @@ function buildX402Quote(paymentRequired, request, idempotencyKey, mcpTransport)
|
|
|
1785
1800
|
idempotencyKey: idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option),
|
|
1786
1801
|
paymentRequired,
|
|
1787
1802
|
accepted: option,
|
|
1803
|
+
acceptedScheme: standard ? "standard" : "erc7710",
|
|
1788
1804
|
request,
|
|
1789
1805
|
...mcpTransport ? { mcpTransport } : {},
|
|
1790
1806
|
resourceUrl: paymentRequired.resource.url,
|
|
@@ -2278,6 +2294,9 @@ var X402Erc7710 = class {
|
|
|
2278
2294
|
// becomes a loud mismatch instead of a silent reroute to the 3009 leg.
|
|
2279
2295
|
payTo: merchantPayTo,
|
|
2280
2296
|
settlementScheme: "erc7710",
|
|
2297
|
+
// #2041: sent only when the caller supplied one, so an omitting caller's
|
|
2298
|
+
// request body is byte-identical to the pre-#2041 shape.
|
|
2299
|
+
...options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {},
|
|
2281
2300
|
amount: amountAtomic,
|
|
2282
2301
|
asset: option.asset,
|
|
2283
2302
|
network: option.network,
|
|
@@ -2439,6 +2458,8 @@ function toolError(err) {
|
|
|
2439
2458
|
|
|
2440
2459
|
// src/merchant-completion.ts
|
|
2441
2460
|
var MERCHANT_BODY_SNIPPET_LIMIT = 1e3;
|
|
2461
|
+
var EVIDENCE_RETRY_DELAYS_MS = [1e3, 2e3, 4e3];
|
|
2462
|
+
var EVIDENCE_RETRYABLE_STATUS = 503;
|
|
2442
2463
|
var MerchantCompletion = class {
|
|
2443
2464
|
post;
|
|
2444
2465
|
merchantTransport;
|
|
@@ -2446,7 +2467,9 @@ var MerchantCompletion = class {
|
|
|
2446
2467
|
getAgent;
|
|
2447
2468
|
delegateAddress;
|
|
2448
2469
|
x402Wallet;
|
|
2470
|
+
sleep;
|
|
2449
2471
|
constructor(options) {
|
|
2472
|
+
this.sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2450
2473
|
this.post = options.post;
|
|
2451
2474
|
this.merchantTransport = options.merchantTransport;
|
|
2452
2475
|
this.getPaymentStatus = options.getPaymentStatus;
|
|
@@ -2620,22 +2643,29 @@ var MerchantCompletion = class {
|
|
|
2620
2643
|
}
|
|
2621
2644
|
}
|
|
2622
2645
|
async reportEvidence(input) {
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2646
|
+
const body = {
|
|
2647
|
+
paymentId: input.paymentId,
|
|
2648
|
+
rail: input.rail,
|
|
2649
|
+
txHash: input.txHash,
|
|
2650
|
+
resourceUrl: input.resourceUrl,
|
|
2651
|
+
merchantStatus: input.merchantStatus,
|
|
2652
|
+
challengePayload: input.challengePayload,
|
|
2653
|
+
selectedPayment: input.selectedPayment,
|
|
2654
|
+
paymentProofHeaderName: input.paymentProofHeaderName,
|
|
2655
|
+
paymentProofHeader: input.paymentProofHeader,
|
|
2656
|
+
protocolReceiptHeaderName: input.protocolReceiptHeaderName,
|
|
2657
|
+
protocolReceiptHeader: input.protocolReceiptHeader,
|
|
2658
|
+
protocolReceiptPayload: input.protocolReceiptHeader ? parseProtocolReceiptHeader(input.protocolReceiptHeader) : void 0
|
|
2659
|
+
};
|
|
2660
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
2661
|
+
try {
|
|
2662
|
+
await this.post("/machine-payments/evidence", body);
|
|
2663
|
+
return;
|
|
2664
|
+
} catch (err) {
|
|
2665
|
+
const retryable = err instanceof HavenApiError && err.statusCode === EVIDENCE_RETRYABLE_STATUS;
|
|
2666
|
+
if (!retryable || attempt >= EVIDENCE_RETRY_DELAYS_MS.length) return;
|
|
2667
|
+
await this.sleep(EVIDENCE_RETRY_DELAYS_MS[attempt]);
|
|
2668
|
+
}
|
|
2639
2669
|
}
|
|
2640
2670
|
}
|
|
2641
2671
|
};
|
|
@@ -2685,7 +2715,10 @@ function mapCatalogEntry(entry) {
|
|
|
2685
2715
|
asset: entry.asset,
|
|
2686
2716
|
network: entry.network,
|
|
2687
2717
|
status: entry.status,
|
|
2688
|
-
verifiedAt: entry.verified_at
|
|
2718
|
+
verifiedAt: entry.verified_at,
|
|
2719
|
+
source: entry.source,
|
|
2720
|
+
domainVerified: entry.domain_verified,
|
|
2721
|
+
verifiedPayable: entry.verified_payable
|
|
2689
2722
|
};
|
|
2690
2723
|
}
|
|
2691
2724
|
var HavenClient = class {
|
|
@@ -2842,10 +2875,7 @@ var HavenClient = class {
|
|
|
2842
2875
|
async createX402Intent(paymentRequired, options = {}) {
|
|
2843
2876
|
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
2844
2877
|
if (!option) {
|
|
2845
|
-
throw
|
|
2846
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
2847
|
-
400
|
|
2848
|
-
);
|
|
2878
|
+
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
2849
2879
|
}
|
|
2850
2880
|
const fundingTo = options.delegateAddress ?? (await this.getAgent()).delegateAddress;
|
|
2851
2881
|
if (!fundingTo) {
|
|
@@ -3121,7 +3151,7 @@ var HavenClient = class {
|
|
|
3121
3151
|
return status;
|
|
3122
3152
|
}
|
|
3123
3153
|
/**
|
|
3124
|
-
* Discover payable services from Haven's
|
|
3154
|
+
* Discover payable services from Haven's merchant catalog (epic #1717).
|
|
3125
3155
|
*
|
|
3126
3156
|
* Read-only: returns catalog entries (price, rail, protocol) so an agent
|
|
3127
3157
|
* can choose a service and pay it with the regular payment tools in the
|
|
@@ -3134,7 +3164,39 @@ var HavenClient = class {
|
|
|
3134
3164
|
if (options.rail) params.set("rail", options.rail);
|
|
3135
3165
|
const query = params.size > 0 ? `?${params.toString()}` : "";
|
|
3136
3166
|
const raw = await this.get(`/catalog${query}`);
|
|
3137
|
-
|
|
3167
|
+
let entries = raw.entries.map(mapCatalogEntry);
|
|
3168
|
+
if (options.verified === "verified") entries = entries.filter((e) => e.source === "ingestion");
|
|
3169
|
+
if (options.verified === "operator") entries = entries.filter((e) => e.source === "operator");
|
|
3170
|
+
return entries;
|
|
3171
|
+
}
|
|
3172
|
+
/**
|
|
3173
|
+
* Submit a merchant's payable (x402/MCP) endpoint to the Verified Payable
|
|
3174
|
+
* Directory (epic #1717, #1716). Queue-only: writes a submission row and
|
|
3175
|
+
* returns the id + verify_token. The request path makes no outbound
|
|
3176
|
+
* request; domain-ownership proof and the read-only quote probe run later
|
|
3177
|
+
* on the leader-locked monitor. Ownership proof is ALWAYS required before
|
|
3178
|
+
* any listing — this method cannot skip it. `website` is a honeypot field
|
|
3179
|
+
* that bots fill; leave it unset.
|
|
3180
|
+
*/
|
|
3181
|
+
async submitCatalogEntry(resourceUrl, options = {}) {
|
|
3182
|
+
const accepted = await this.post("/catalog/submit", {
|
|
3183
|
+
resource_url: resourceUrl,
|
|
3184
|
+
...options.website ? { website: options.website } : {}
|
|
3185
|
+
});
|
|
3186
|
+
return {
|
|
3187
|
+
id: accepted.id,
|
|
3188
|
+
verifyToken: accepted.verify_token,
|
|
3189
|
+
status: accepted.status
|
|
3190
|
+
};
|
|
3191
|
+
}
|
|
3192
|
+
/**
|
|
3193
|
+
* Fetch one submission's coarse status by id (epic #1717, #1716). Public
|
|
3194
|
+
* and read-only. While the submission can still prove ownership the
|
|
3195
|
+
* response carries the exact well-known / DNS-TXT `instructions`; the
|
|
3196
|
+
* verify token is never returned here.
|
|
3197
|
+
*/
|
|
3198
|
+
async getCatalogSubmissionStatus(id) {
|
|
3199
|
+
return this.get(`/catalog/submit/${encodeURIComponent(id)}`);
|
|
3138
3200
|
}
|
|
3139
3201
|
/**
|
|
3140
3202
|
* Fetch one curated catalog entry by id (#1306).
|
|
@@ -3209,10 +3271,7 @@ var HavenClient = class {
|
|
|
3209
3271
|
}
|
|
3210
3272
|
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
3211
3273
|
if (!option) {
|
|
3212
|
-
throw
|
|
3213
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
3214
|
-
400
|
|
3215
|
-
);
|
|
3274
|
+
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
3216
3275
|
}
|
|
3217
3276
|
const idempotencyKey = options.idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option);
|
|
3218
3277
|
const cached = this.fundingLeg.cachedReceipt(idempotencyKey);
|
|
@@ -3352,10 +3411,7 @@ var HavenClient = class {
|
|
|
3352
3411
|
}
|
|
3353
3412
|
const option = selectStandardPaymentOption(input.paymentRequired.accepts);
|
|
3354
3413
|
if (!option) {
|
|
3355
|
-
throw
|
|
3356
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
3357
|
-
400
|
|
3358
|
-
);
|
|
3414
|
+
throw noCompatiblePaymentOptionError(input.paymentRequired.accepts);
|
|
3359
3415
|
}
|
|
3360
3416
|
const idempotencyKey = input.idempotencyKey ?? buildX402IdempotencyKey(input.paymentRequired, option);
|
|
3361
3417
|
const cached = this.fundingLeg.cachedReceipt(idempotencyKey);
|
|
@@ -3555,11 +3611,12 @@ var HavenClient = class {
|
|
|
3555
3611
|
});
|
|
3556
3612
|
}
|
|
3557
3613
|
} else {
|
|
3558
|
-
|
|
3614
|
+
const evidenceTxHash = input.noFundingLeg ? settlement.settlementTxHash ?? void 0 : fundingTxHash ?? void 0;
|
|
3615
|
+
if (evidenceTxHash) {
|
|
3559
3616
|
await this.merchantCompletion.reportEvidence({
|
|
3560
3617
|
paymentId: evidenceContext.paymentId,
|
|
3561
3618
|
rail: "x402",
|
|
3562
|
-
txHash:
|
|
3619
|
+
txHash: evidenceTxHash,
|
|
3563
3620
|
resourceUrl: evidenceContext.resourceUrl,
|
|
3564
3621
|
merchantStatus: surfaced.status,
|
|
3565
3622
|
paymentProofHeaderName: "X-PAYMENT",
|
|
@@ -3732,19 +3789,19 @@ var toolDescriptions = {
|
|
|
3732
3789
|
payX402: {
|
|
3733
3790
|
summary: "Pay an inspected x402 quote. The delegate key signs locally; Haven only validates and relays signed, on-chain-constrained payment transactions.",
|
|
3734
3791
|
selectionGuidance: "Do not use this for read-only allowance, budget, spend-limit, remaining-amount, reset-period, or what-can-I-spend questions; use the allowance lookup tool instead.",
|
|
3735
|
-
behavior: "Signs the
|
|
3736
|
-
nextActionGuidance: "
|
|
3792
|
+
behavior: "Signs the payment locally and returns the merchant response. Settlement is either direct account-to-merchant with no funding leg, or a bridge that first redeems the agent's budget delegation to fund the delegate wallet for an EIP-3009 authorization. A payment outside the on-chain budget is declined before any money moves; nothing is queued for a human to approve later.",
|
|
3793
|
+
nextActionGuidance: "Preserve the returned resume_state \u2014 it identifies this payment if you need to ask about it later. This tool performs the merchant retry itself, so do not wait on a signal while the call is in flight. If the process crashes after this call and a later haven_get_payment_status reports nextAction=retry_original_x402_request, Haven's funding leg confirmed but no merchant response was ever recorded \u2014 call the resume tool with the preserved resume_state or payment_id instead of paying again. If the response carries phase=insufficient_funds and nextAction=fund_safe_or_raise_allowance, the payment cannot be retried until the account is funded or the agent budget raised \u2014 stop and tell the user the shortfall reported on the response."
|
|
3737
3794
|
},
|
|
3738
3795
|
payX402OneShot: {
|
|
3739
3796
|
summary: "Fetch an x402 paid HTTP resource in a single call. Handles the full probe -> pay -> retry round trip and returns the merchant response.",
|
|
3740
3797
|
selectionGuidance: "Prefer this over the quote+pay split when the agent just wants the paid resource and does not need to inspect the price first. If you already have a quote from haven_quote_x402, use haven_pay_x402_quote instead. Do not use for read-only allowance, budget, spend-limit, remaining-amount, reset-period, or what-can-I-spend questions; use the allowance lookup tool instead.",
|
|
3741
|
-
behavior: "Calls the URL, parses any HTTP 402 x402 challenge, signs the
|
|
3742
|
-
nextActionGuidance: "
|
|
3798
|
+
behavior: "Calls the URL, parses any HTTP 402 x402 challenge, signs the payment locally, then retries the original request with the X-PAYMENT header and returns the merchant response. Settlement is either direct account-to-merchant with no funding leg, or a bridge that first redeems the agent's budget delegation to fund the delegate wallet for an EIP-3009 authorization. A payment outside the on-chain budget is declined before any money moves; nothing is queued for a human to approve later. If the resource returns a non-402 status, returns it unchanged without contacting Haven.",
|
|
3799
|
+
nextActionGuidance: "Preserve the returned resume_state or paymentId \u2014 either identifies this payment if you need to ask about it later. This tool performs the merchant retry itself, so do not wait on a signal while the call is in flight. If the process crashes after this call and a later haven_get_payment_status reports nextAction=retry_original_x402_request, Haven's funding leg confirmed but no merchant response was ever recorded \u2014 call the resume tool with the preserved resume_state or payment_id instead of paying again. If the response carries phase=insufficient_funds and nextAction=fund_safe_or_raise_allowance, the payment cannot be retried until the account is funded or the agent budget raised \u2014 stop and tell the user the shortfall reported on the response."
|
|
3743
3800
|
},
|
|
3744
3801
|
resumeX402: {
|
|
3745
|
-
summary: "Resume an x402 payment
|
|
3746
|
-
behavior: "Accepts either resume_state or payment_id, validates the original x402 details against the
|
|
3747
|
-
nextActionGuidance: "Only
|
|
3802
|
+
summary: "Resume an x402 payment whose Haven-side authorization already succeeded but whose merchant retry did not complete.",
|
|
3803
|
+
behavior: "Accepts either resume_state or payment_id, validates the original x402 details against the authorized Haven funding, and retries the merchant request with the X-PAYMENT header. No new Haven payment is created.",
|
|
3804
|
+
nextActionGuidance: "Only call this after haven_get_payment_status reports nextAction=retry_original_x402_request \u2014 that means Haven's funding leg confirmed but no merchant response was ever recorded, most often because the process crashed between funding and the merchant retry. Any other nextAction reports a conflict instead of retrying, so do not call this speculatively. Do not start a new merchant session and do not pay again \u2014 that would pay twice for one resource."
|
|
3748
3805
|
},
|
|
3749
3806
|
// #1328: quoteMpp / payMpp / resumeMpp (the mpp_demo challenge/quote/resume
|
|
3750
3807
|
// fragments) are retired along with the client surface they described —
|
|
@@ -3752,24 +3809,24 @@ var toolDescriptions = {
|
|
|
3752
3809
|
// deleted `/demo/mpp/*` route. Use the x402 fragments above instead.
|
|
3753
3810
|
getPaymentStatus: {
|
|
3754
3811
|
summary: "Fetch structured Haven payment status, including phase and nextAction taxonomy for agent recovery.",
|
|
3755
|
-
behavior: "Accepts a payment intent
|
|
3812
|
+
behavior: "Accepts a payment intent id and returns the full state taxonomy (phase, nextAction, rail, amount, merchant, resource url, idempotency key, message).",
|
|
3756
3813
|
nextActionGuidance: ""
|
|
3757
3814
|
},
|
|
3758
3815
|
getResumeState: {
|
|
3759
3816
|
summary: "Rehydrate stored x402 resume_state by payment_id.",
|
|
3760
|
-
behavior: "Returns the context
|
|
3817
|
+
behavior: "Returns the x402 context the agent originally received when the payment was authorized, reconstructed from Haven's database. This is context only; signing still happens locally when a resume tool is called.",
|
|
3761
3818
|
nextActionGuidance: ""
|
|
3762
3819
|
},
|
|
3763
3820
|
getAgent: {
|
|
3764
3821
|
summary: "Return the authenticated agent identity AND its live spend authority in one call: Haven wallet, delegate, chain, raw status, spend_authority_readiness, and per-token remaining allowance (atomic + human-readable). The recommended first call in a new session to confirm who you are and whether Haven will let you spend right now.",
|
|
3765
3822
|
selectionGuidance: "Use this as the one-shot orientation/bootstrap at the start of a session, or whenever you need to confirm identity together with whether the agent can spend right now. For a detailed per-token breakdown (configured vs spent vs reset window) use haven_get_allowances.",
|
|
3766
|
-
behavior:
|
|
3823
|
+
behavior: `Reads identity plus the live spend-authority snapshot in one shot \u2014 the agent's active on-chain budget delegation. spend_authority_readiness (readiness is a deprecated alias, same value) is "ready" when at least one token has remaining spend authority, "needs_approval" when the agent is active but has none, and "revoked" when the credential is not active. It covers hosted identity + on-chain spend authority ONLY \u2014 the hosted server cannot see the LOCAL signer, so "ready" does not mean the signer can start; verify the signer with a signer tool call or connect --doctor. An over-budget payment is declined before any money moves: there is no approval queue, so ask the owner to grant or raise the budget in Haven rather than waiting for an approval. allowances[] carries remainingAtomic and remainingDisplay per token. Identity fields (id, name, status, safeAddress, delegateAddress, chainId) are unchanged from before.`,
|
|
3767
3824
|
nextActionGuidance: ""
|
|
3768
3825
|
},
|
|
3769
3826
|
getAllowances: {
|
|
3770
3827
|
summary: "Return configured and on-chain allowance state for the authenticated agent. On-chain allowance is the real spend gate.",
|
|
3771
3828
|
selectionGuidance: "Use this when the user asks about allowance, budget, spend limit, remaining amount, remaining allowance, remaining budget, daily limit, reset period, what can I spend, or what the agent can still spend.",
|
|
3772
|
-
behavior: "Returns the per-token spend authority for the account
|
|
3829
|
+
behavior: "Returns the per-token spend authority for the account: the active budget delegation (remaining = the period budget, which re-arms natively at the period boundary). An over-budget payment is declined before any money moves; nothing queues. Configured amounts from Haven are returned alongside.",
|
|
3773
3830
|
nextActionGuidance: ""
|
|
3774
3831
|
},
|
|
3775
3832
|
listReceipts: {
|
|
@@ -3787,15 +3844,21 @@ var toolDescriptions = {
|
|
|
3787
3844
|
payMcpTool: {
|
|
3788
3845
|
summary: "Call a named tool on an MCP merchant that requires an x402 payment, handling the full initialize \u2192 pay \u2192 retry round trip in one call.",
|
|
3789
3846
|
selectionGuidance: "Use this when the agent wants to call a specific tool on an MCP merchant (e.g. Soundside, Coinbase Bazaar) and payment is required. Prefer this over haven_pay_x402 when you know the merchant_url and tool_name \u2014 it builds the JSON-RPC envelope internally. Use haven_pay_x402 for arbitrary HTTP resources. Do NOT use for read-only allowance or budget questions \u2014 use haven_get_allowances.",
|
|
3790
|
-
behavior: "Builds the JSON-RPC tools/call envelope, runs the MCP Streamable-HTTP initialize handshake automatically (if the endpoint is MCP-shaped), pays any HTTP 402 x402 challenge
|
|
3791
|
-
nextActionGuidance: "
|
|
3847
|
+
behavior: "Builds the JSON-RPC tools/call envelope, runs the MCP Streamable-HTTP initialize handshake automatically (if the endpoint is MCP-shaped), pays any HTTP 402 x402 challenge against the agent's on-chain budget delegation, and retries the request, returning the JSON-RPC result (the actual merchant output) on success. Amounts within the remaining on-chain budget execute automatically; anything outside it is declined before any money moves \u2014 follow the response's nextAction when present.",
|
|
3848
|
+
nextActionGuidance: "On a decline, report the reason to the user and ask them to raise the budget in Haven \u2014 there is no approval queue to wait on. This tool retries the merchant itself while it runs, so do not wait on a signal mid-call. If the process crashes after payment, a later haven_get_payment_status call may report nextAction=retry_original_x402_request \u2014 resume via haven_resume_x402_payment instead of paying again."
|
|
3792
3849
|
},
|
|
3793
3850
|
discoverTools: {
|
|
3794
3851
|
summary: "Step 1 of a purchase: discover payable services from Haven's curated merchant catalog \u2014 names, prices, and which pay tool to use next.",
|
|
3795
|
-
selectionGuidance: "Use this when the user asks what the agent can buy, pay for, or which paid services exist \u2014 or when you need a resource URL for a service the user described. Do NOT use for balance, budget, or spend-limit questions \u2014 use haven_get_allowances. Do NOT use to pay \u2014 each returned entry names the pay tool to use next.",
|
|
3796
|
-
behavior: "Use each entry's suggested_tool field first \u2014 it names the exact next call. Read-only lookup against Haven's curated catalog; entries are periodically re-verified against the live merchant and degraded entries are flagged. Use category for a case-insensitive category filter (for example, VPN or vpn), or search for a product name, category, or description term. Returns name, description, price, rail, resource URL, tool_name, tool_arguments, and
|
|
3852
|
+
selectionGuidance: "Use this when the user asks what the agent can buy, pay for, or which paid services exist \u2014 or when you need a resource URL for a service the user described. Use verified=verified to show only self-submitted directory entries that passed domain-ownership proof and a live quote probe \u2014 never treat those badges as proof of merchant honesty, quality, or reliability. Do NOT use for balance, budget, or spend-limit questions \u2014 use haven_get_allowances. Do NOT use to pay \u2014 each returned entry names the pay tool to use next.",
|
|
3853
|
+
behavior: "Use each entry's suggested_tool field first \u2014 it names the exact next call. Read-only lookup against Haven's curated catalog; entries are periodically re-verified against the live merchant and degraded entries are flagged. Use category for a case-insensitive category filter (for example, VPN or vpn), or search for a product name, category, or description term. Returns name, description, price, rail, resource URL, tool_name, tool_arguments, suggested_tool, and the provenance badges source/domain_verified/verified_payable. The catalog price (price_display/price_atomic, marked price_is_indicative) is a last-verified hint, NOT authoritative \u2014 the real price comes from the merchant's live 402 at pay time. Never creates a payment, signature, or approval.",
|
|
3797
3854
|
nextActionGuidance: `Pick an entry and pay it with the tool named in suggested_tool, passing the entry's resource_url, tool_name, and tool_arguments for MCP merchants. Confirm the price from the live pay-tool result (not the catalog), and pass the user's cap as max_amount_human in whole tokens ("no more than 1 USDC" \u2192 max_amount_human: "1") \u2014 never convert it to atomic units by hand.`
|
|
3798
3855
|
},
|
|
3856
|
+
submitCatalogEntry: {
|
|
3857
|
+
summary: "Submit a merchant's payable (x402/MCP) endpoint to Haven's Verified Payable Directory for verification and listing.",
|
|
3858
|
+
selectionGuidance: "Use this when a merchant or seller asks to be listed in the directory, or when you have discovered a payable endpoint and want it registered. The submission is queue-only: it books a spot and returns a verify_token. The seller must then prove control of the domain (a well-known line or DNS TXT record); only after that plus a live quote probe does the entry become listed. Do NOT use to pay \u2014 check the returned status with getCatalogSubmissionStatus instead.",
|
|
3859
|
+
behavior: "Sends the https resource_url to Haven's public submission endpoint. The request path makes no outbound request to the merchant. Returns id + verify_token + status; the verify_token is shown exactly once. Ownership proof is always required later and cannot be skipped from the agent side. The website field is a honeypot for bots \u2014 leave it unset.",
|
|
3860
|
+
nextActionGuidance: "Give the verify_token and the well-known instructions (from getCatalogSubmissionStatus) to the merchant so they can publish the proof line, then poll the submission status until it reaches verified_payable or failed."
|
|
3861
|
+
},
|
|
3799
3862
|
sweep_delegate: {
|
|
3800
3863
|
summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating Safe.",
|
|
3801
3864
|
selectionGuidance: "Use this when the user instructs you to recover stranded funds on the delegate wallet, or when a payment status returns nextAction=sweep_stranded_funds. Do NOT use for normal payments \u2014 use haven_pay_x402. Do NOT use to read balances only \u2014 use haven_get_allowances.",
|
|
@@ -3805,8 +3868,8 @@ var toolDescriptions = {
|
|
|
3805
3868
|
send: {
|
|
3806
3869
|
summary: "Send ETH or USDC directly from the agent's Haven wallet to a recipient address.",
|
|
3807
3870
|
selectionGuidance: "Use this for plain transfers \u2014 refunding a user, paying a freelancer, topping up a co-agent's wallet, or moving funds between addresses. Do NOT use for x402 paid endpoints \u2014 use haven_pay_x402 instead. Do NOT use for read-only allowance, budget, or what-can-I-spend questions \u2014 use haven_get_allowances.",
|
|
3808
|
-
behavior: "Sends the requested amount
|
|
3809
|
-
nextActionGuidance: "
|
|
3871
|
+
behavior: "Sends the requested amount by redeeming the agent's on-chain budget delegation, account to recipient with no funding leg. Budget, recipient and expiry are enforced on-chain while the transfer is prepared, so a request outside them is declined before any money moves and before the agent is asked to sign \u2014 it is never queued for a human to approve later. The agent's signing key signs the account's typed data; Haven never receives the key.",
|
|
3872
|
+
nextActionGuidance: "On a decline, report the reason to the user and ask them to grant or raise the budget in Haven \u2014 there is nothing to poll and no approval will arrive. After a successful send, poll haven_get_payment_status until nextAction=none."
|
|
3810
3873
|
}
|
|
3811
3874
|
};
|
|
3812
3875
|
|
|
@@ -3877,7 +3940,7 @@ var authorizeX402Schema = {
|
|
|
3877
3940
|
},
|
|
3878
3941
|
idempotencyKey: {
|
|
3879
3942
|
type: "string",
|
|
3880
|
-
description: "Stable caller-supplied key for this user intent. Reuse it when resuming
|
|
3943
|
+
description: "Stable caller-supplied key for this user intent. Reuse it when resuming the same payment."
|
|
3881
3944
|
}
|
|
3882
3945
|
},
|
|
3883
3946
|
required: ["url", "payTo", "amount", "asset", "network"]
|
|
@@ -3887,7 +3950,7 @@ var resumeX402Schema = {
|
|
|
3887
3950
|
properties: {
|
|
3888
3951
|
payment_id: {
|
|
3889
3952
|
type: "string",
|
|
3890
|
-
description: "The payment
|
|
3953
|
+
description: "The payment ID returned by authorize_x402_payment."
|
|
3891
3954
|
},
|
|
3892
3955
|
url: {
|
|
3893
3956
|
type: "string",
|
|
@@ -3920,11 +3983,11 @@ var resumeX402Schema = {
|
|
|
3920
3983
|
},
|
|
3921
3984
|
required: ["payment_id", "url", "payTo", "amount", "asset", "network"]
|
|
3922
3985
|
};
|
|
3923
|
-
var MAKE_PAYMENT_DESCRIPTION = "Request and sign a payment from the user-controlled
|
|
3924
|
-
var GET_STATUS_DESCRIPTION = toolDescriptions.getPaymentStatus.summary + " Accepts payment intent IDs
|
|
3986
|
+
var MAKE_PAYMENT_DESCRIPTION = "Request and sign a payment from the user-controlled account within its on-chain budget. For read-only allowance, budget, spend-limit, remaining-amount, or reset-period questions, use get_allowances instead of making a payment. Haven authenticates the agent and relays the signed transaction that redeems the agent budget delegation; it does not hold keys or control funds. Gnosis Chain tokens: EURe, USDC.e, xDAI. Base tokens: USDC, ETH.";
|
|
3987
|
+
var GET_STATUS_DESCRIPTION = toolDescriptions.getPaymentStatus.summary + " Accepts payment intent IDs. Returns the current status, phase, next_action, transaction hash if available, and payment details.";
|
|
3925
3988
|
var GET_ALLOWANCES_DESCRIPTION = composeDescription(toolDescriptions.getAllowances);
|
|
3926
|
-
var AUTHORIZE_X402_DESCRIPTION = composeDescription(toolDescriptions.payX402) + " In this SDK tool set, the allowance lookup tool is get_allowances. When a paid API returns x402 payment requirements, use this tool to sign with the agent-owned delegate key
|
|
3927
|
-
var RESUME_X402_DESCRIPTION = toolDescriptions.resumeX402.summary + "
|
|
3989
|
+
var AUTHORIZE_X402_DESCRIPTION = composeDescription(toolDescriptions.payX402) + " In this SDK tool set, the allowance lookup tool is get_allowances. When a paid API returns x402 payment requirements, use this tool to sign with the agent-owned delegate key; funding, when the scheme needs it, is redeemed from the agent budget delegation and is bounded by it. Haven relays signed transactions only; the agent key authorizes payment and on-chain limits enforce spend. A payment outside the on-chain budget is declined before any money moves \u2014 report the decline and ask the user to raise the budget in Haven; do not loop retries and do not wait for an approval, because none is queued. Preserve the original merchant/MCP session and x402 details. Use the returned payment_header as the X-PAYMENT header on the retry request when doing a manual HTTP retry.";
|
|
3990
|
+
var RESUME_X402_DESCRIPTION = toolDescriptions.resumeX402.summary + " Only call this after get_payment_status reports nextAction=retry_original_x402_request \u2014 that means Haven's funding leg confirmed but no merchant response was ever recorded (typically a crash between funding and the merchant retry). Any other nextAction reports a conflict instead of retrying \u2014 do not call this speculatively, and do not pay again.";
|
|
3928
3991
|
var SWEEP_DELEGATE_DESCRIPTION = composeDescription(toolDescriptions.sweep_delegate);
|
|
3929
3992
|
var sweepDelegateSchema = {
|
|
3930
3993
|
type: "object",
|
|
@@ -4034,8 +4097,8 @@ description: Pay for things from the user's Haven wallet within their agent rule
|
|
|
4034
4097
|
|
|
4035
4098
|
This skill lets the agent make payments from the user's Haven wallet through
|
|
4036
4099
|
the Haven MCP tools. Every payment is checked against the agent's on-chain
|
|
4037
|
-
budget before money moves;
|
|
4038
|
-
|
|
4100
|
+
budget before money moves; a payment above the remaining budget is declined \u2014
|
|
4101
|
+
nothing is paid past the rules the user set.
|
|
4039
4102
|
|
|
4040
4103
|
Hosted tools run in the \`mcp__haven__\` namespace. Local signing tools run in
|
|
4041
4104
|
the \`mcp__haven-signer__\` namespace and keep the delegate key on this machine.
|
|
@@ -4079,8 +4142,8 @@ spending:
|
|
|
4079
4142
|
(configured, spent, reset window) when you need more than the summary.
|
|
4080
4143
|
|
|
4081
4144
|
Budgets reset on a period the user chose. If a payment exceeds the remaining
|
|
4082
|
-
budget it is
|
|
4083
|
-
|
|
4145
|
+
budget it is declined before any money moves \u2014 tell the user; they can raise
|
|
4146
|
+
the budget in the Haven dashboard, or wait for the period reset.
|
|
4084
4147
|
|
|
4085
4148
|
## Paying
|
|
4086
4149
|
|
|
@@ -4122,8 +4185,8 @@ context (\`merchant_url\`, \`tool_name\`, \`arguments\`, \`mcp_transport\`)
|
|
|
4122
4185
|
server-side from \`payment_id\`. Pass those four fields explicitly only as a
|
|
4123
4186
|
version-skew fallback when Haven has no stored context for the id \u2014 both or
|
|
4124
4187
|
none together, never just one. If the settle result carries \`settled: false\`,
|
|
4125
|
-
funding
|
|
4126
|
-
do not re-pay.
|
|
4188
|
+
funding has not confirmed \u2014 follow the result's guidance fields and check
|
|
4189
|
+
status later, do not re-pay.
|
|
4127
4190
|
|
|
4128
4191
|
Step-by-step alternative (also key-safe; for an older signer or backend, or
|
|
4129
4192
|
when you already have a merchant URL and tool name instead of a
|
|
@@ -4146,8 +4209,12 @@ merchant leg for you.
|
|
|
4146
4209
|
recipient, amount, and token for a plain transfer. For an arbitrary,
|
|
4147
4210
|
non-MCP x402 paywall: \`mcp__haven__haven_quote_x402\` to get a quote, then
|
|
4148
4211
|
\`mcp__haven__haven_pay_x402_quote\` \u2014 follow the result's guidance fields
|
|
4149
|
-
first
|
|
4150
|
-
|
|
4212
|
+
first and sign in the local Haven signer. The pay tool performs the merchant
|
|
4213
|
+
retry itself, so do not wait on a signal while it runs. If the process
|
|
4214
|
+
crashes after payment, a later \`mcp__haven__haven_get_payment_status\` call
|
|
4215
|
+
may report \`nextAction: 'retry_original_x402_request'\` \u2014 only then call
|
|
4216
|
+
\`mcp__haven__haven_resume_x402_payment\` with the preserved resume state or
|
|
4217
|
+
payment id, instead of paying again.
|
|
4151
4218
|
|
|
4152
4219
|
**Catalog tool arguments:** when \`haven_discover_tools\` returns
|
|
4153
4220
|
\`tool_arguments\`, pass that object unchanged as the pay tool's
|
|
@@ -4163,14 +4230,14 @@ Haven authorizes for that call \u2014 a ceiling the merchant settles at or below
|
|
|
4163
4230
|
so present it as the most the user will pay.
|
|
4164
4231
|
|
|
4165
4232
|
**Status:** \`mcp__haven__haven_get_payment_status\` with a \`payment_id\` to
|
|
4166
|
-
check on
|
|
4233
|
+
check on in-flight payments. Do not poll in a tight loop.
|
|
4167
4234
|
|
|
4168
|
-
##
|
|
4235
|
+
## Declines and stop signals
|
|
4169
4236
|
|
|
4170
|
-
- A
|
|
4171
|
-
budget
|
|
4172
|
-
|
|
4173
|
-
- \`safe_to_continue: false\` on a guidance block is
|
|
4237
|
+
- A payment outside the agent's rules \u2014 above the remaining budget, wrong
|
|
4238
|
+
recipient, or expired budget \u2014 is declined before any money moves. Nothing
|
|
4239
|
+
is queued; tell the user, who can raise the budget in Haven.
|
|
4240
|
+
- \`safe_to_continue: false\` on a guidance block is a stop signal in
|
|
4174
4241
|
machine-readable form: stop and involve the user before calling anything
|
|
4175
4242
|
else for this payment.
|
|
4176
4243
|
- Never ask the user for private keys. Signing happens only in the local Haven
|
|
@@ -4184,7 +4251,6 @@ Haven tool failures are shaped like \`{ success: false, code, message, ... }\`
|
|
|
4184
4251
|
or older \`{ error, status, details? }\` responses. Branch on \`code\` when
|
|
4185
4252
|
present and surface \`message\` or \`error\` verbatim. Common cases:
|
|
4186
4253
|
|
|
4187
|
-
- \`pending_approval\`: queued for the user's approval (see above).
|
|
4188
4254
|
- \`insufficient_funds\`: the Haven wallet doesn't hold enough of that token.
|
|
4189
4255
|
Suggest the user add funds in the Haven dashboard.
|
|
4190
4256
|
- \`PRICE_EXCEEDS_MAX\`: the live merchant price exceeded your cap. No funds
|