@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.js
CHANGED
|
@@ -16,33 +16,40 @@ var AgentPaymentPhase = {
|
|
|
16
16
|
PaymentSubmitted: "payment_submitted",
|
|
17
17
|
/** The direct payment is confirmed; the agent does not need to do more for this payment id. */
|
|
18
18
|
PaymentConfirmed: "payment_confirmed",
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* #2115: RETIRED wire value — no live rail produces it. It described the
|
|
21
|
+
* Safe rail's approval queue, which no longer exists. Kept so a stored value
|
|
22
|
+
* still typechecks; see `AgentPaymentPhaseDescriptions` below for the
|
|
23
|
+
* agent-visible wording, which this comment used to contradict.
|
|
24
|
+
*/
|
|
20
25
|
UserApprovalRequired: "user_approval_required",
|
|
21
|
-
/**
|
|
26
|
+
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
22
27
|
UserExecutionRequired: "user_execution_required",
|
|
23
|
-
/**
|
|
28
|
+
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
24
29
|
WaitingForAdditionalApprovals: "waiting_for_additional_approvals",
|
|
25
30
|
/** The Haven funding leg was sent; the agent can continue the merchant/protocol leg. */
|
|
26
31
|
FundingSent: "funding_sent",
|
|
27
|
-
/** The
|
|
32
|
+
/** The payment was rejected and cannot proceed; the agent should stop and tell the user. */
|
|
28
33
|
Rejected: "rejected",
|
|
29
|
-
/** The payment
|
|
34
|
+
/** The payment expired before completion. */
|
|
30
35
|
Expired: "expired",
|
|
31
36
|
/** Haven could not complete the payment; the agent should stop and surface the failure. */
|
|
32
37
|
Failed: "failed",
|
|
33
38
|
/**
|
|
34
39
|
* Pre-flight check determined the delegate's existing balance plus the
|
|
35
|
-
* remaining on-chain
|
|
36
|
-
* payment intent was created.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
40
|
+
* remaining on-chain budget cannot cover the requested amount, so no
|
|
41
|
+
* payment intent was created. The account must be funded or the agent's
|
|
42
|
+
* budget raised before retrying — #2115: the old wording contrasted this
|
|
43
|
+
* with `UserApprovalRequired` as if that were a live alternative, and named
|
|
44
|
+
* the retired rail's Safe and per-token allowance as the fix.
|
|
39
45
|
*/
|
|
40
46
|
InsufficientFunds: "insufficient_funds",
|
|
41
47
|
/**
|
|
42
|
-
* Haven's funding leg (
|
|
43
|
-
* merchant rejected the x402 retry. The delegate
|
|
44
|
-
* USDC that was never settled to the merchant. The
|
|
45
|
-
* the user, and wait for the sweep flow to reclaim
|
|
48
|
+
* Haven's funding leg (account → delegate, the #946 EIP-3009 bridge)
|
|
49
|
+
* confirmed on-chain, but the merchant rejected the x402 retry. The delegate
|
|
50
|
+
* wallet may hold stranded USDC that was never settled to the merchant. The
|
|
51
|
+
* agent should stop, tell the user, and wait for the sweep flow to reclaim
|
|
52
|
+
* the funds.
|
|
46
53
|
*/
|
|
47
54
|
FundedButUnsettled: "funded_but_unsettled"
|
|
48
55
|
};
|
|
@@ -53,9 +60,12 @@ var AgentPaymentNextAction = {
|
|
|
53
60
|
CheckStatusLater: "check_status_later",
|
|
54
61
|
/** No further agent action is required for this payment id. */
|
|
55
62
|
None: "none",
|
|
56
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* #2115: RETIRED wire value — no live rail produces it and nothing maps to
|
|
65
|
+
* it. Stop and tell the user rather than polling; no approval will arrive.
|
|
66
|
+
*/
|
|
57
67
|
WaitForUserApproval: "wait_for_user_approval",
|
|
58
|
-
/**
|
|
68
|
+
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user rather than polling. */
|
|
59
69
|
WaitForUserToCompletePayment: "wait_for_user_to_complete_payment",
|
|
60
70
|
/** Resume this payment id and retry the original x402 request with the merchant payment header. */
|
|
61
71
|
RetryOriginalX402Request: "retry_original_x402_request",
|
|
@@ -145,29 +155,29 @@ var AgentPaymentPhaseDescriptions = {
|
|
|
145
155
|
[AgentPaymentPhase.AgentSignatureRequired]: "The agent must sign and submit the prepared payment before Haven can relay it.",
|
|
146
156
|
[AgentPaymentPhase.PaymentSubmitted]: "Haven has received the signed payment and the agent should poll for confirmation.",
|
|
147
157
|
[AgentPaymentPhase.PaymentConfirmed]: "The direct payment is confirmed; the agent does not need to do more for this payment id.",
|
|
148
|
-
[AgentPaymentPhase.UserApprovalRequired]: "
|
|
149
|
-
[AgentPaymentPhase.UserExecutionRequired]: "
|
|
150
|
-
[AgentPaymentPhase.WaitingForAdditionalApprovals]: "
|
|
158
|
+
[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.",
|
|
159
|
+
[AgentPaymentPhase.UserExecutionRequired]: "Retired wire value: no live rail produces it. Stop and tell the user.",
|
|
160
|
+
[AgentPaymentPhase.WaitingForAdditionalApprovals]: "Retired wire value: no live rail produces it. Stop and tell the user.",
|
|
151
161
|
[AgentPaymentPhase.FundingSent]: "The Haven funding leg was sent; the agent can continue the merchant/protocol leg.",
|
|
152
|
-
[AgentPaymentPhase.Rejected]: "The
|
|
153
|
-
[AgentPaymentPhase.Expired]: "The payment
|
|
162
|
+
[AgentPaymentPhase.Rejected]: "The payment was rejected and cannot proceed; the agent should stop and tell the user.",
|
|
163
|
+
[AgentPaymentPhase.Expired]: "The payment expired before completion.",
|
|
154
164
|
[AgentPaymentPhase.Failed]: "Haven could not complete the payment; the agent should stop and surface the failure.",
|
|
155
|
-
[AgentPaymentPhase.InsufficientFunds]: "Pre-flight check determined the delegate balance plus the remaining on-chain
|
|
156
|
-
[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
|
|
165
|
+
[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.",
|
|
166
|
+
[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."
|
|
157
167
|
};
|
|
158
168
|
var AgentPaymentNextActionDescriptions = {
|
|
159
169
|
[AgentPaymentNextAction.SignAndSubmitPayment]: "Sign with the delegate key and submit the payment to Haven.",
|
|
160
170
|
[AgentPaymentNextAction.CheckStatusLater]: "Poll getPaymentStatus later using this payment id.",
|
|
161
171
|
[AgentPaymentNextAction.None]: "No further agent action is required for this payment id.",
|
|
162
|
-
[AgentPaymentNextAction.WaitForUserApproval]: "
|
|
163
|
-
[AgentPaymentNextAction.WaitForUserToCompletePayment]: "
|
|
172
|
+
[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.",
|
|
173
|
+
[AgentPaymentNextAction.WaitForUserToCompletePayment]: "Retired wire value: no live rail produces it. Stop and tell the user rather than polling.",
|
|
164
174
|
[AgentPaymentNextAction.RetryOriginalX402Request]: "Resume this payment id and retry the original x402 request with the merchant payment header.",
|
|
165
175
|
[AgentPaymentNextAction.StopAndTellUser]: "Stop retrying this payment and tell the user what happened.",
|
|
166
176
|
[AgentPaymentNextAction.RequestAgainIfUserStillWantsIt]: "Ask again only if the user still wants the payment after expiry.",
|
|
167
177
|
[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.",
|
|
168
|
-
[AgentPaymentNextAction.FundSafeOrRaiseAllowance]: "Stop and tell the user that the
|
|
178
|
+
[AgentPaymentNextAction.FundSafeOrRaiseAllowance]: "Stop and tell the user that the account needs to be funded or the agent budget raised before the payment can succeed.",
|
|
169
179
|
[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.",
|
|
170
|
-
[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
|
|
180
|
+
[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."
|
|
171
181
|
};
|
|
172
182
|
var AgentPaymentFailureCodeDescriptions = {
|
|
173
183
|
[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.",
|
|
@@ -210,7 +220,7 @@ var AgentPaymentWarningCode = {
|
|
|
210
220
|
AllowanceReadOptimistic: "ALLOWANCE_READ_OPTIMISTIC"
|
|
211
221
|
};
|
|
212
222
|
var AgentPaymentRailDescriptions = {
|
|
213
|
-
[AgentPaymentRail.Direct]: "Standard Haven payment from the user-controlled
|
|
223
|
+
[AgentPaymentRail.Direct]: "Standard Haven payment from the user-controlled account, redeeming the agent's on-chain budget delegation.",
|
|
214
224
|
[AgentPaymentRail.X402]: "x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg.",
|
|
215
225
|
[AgentPaymentRail.Mpp]: "Categorical MPP rail value used as a resume-state discriminator. Response bodies carry a granular mpp_* value instead.",
|
|
216
226
|
[AgentPaymentRail.MppDemo]: "Haven internal MPP demo rail. Not for production traffic.",
|
|
@@ -1144,10 +1154,10 @@ function nextActionForStatus(status) {
|
|
|
1144
1154
|
if (status === "pending_signature") return AgentPaymentNextAction.SignAndSubmitPayment;
|
|
1145
1155
|
if (status === "submitted") return AgentPaymentNextAction.CheckStatusLater;
|
|
1146
1156
|
if (status === "confirmed") return AgentPaymentNextAction.None;
|
|
1147
|
-
if (status === "pending" || status === "pending_approval") return AgentPaymentNextAction.
|
|
1157
|
+
if (status === "pending" || status === "pending_approval") return AgentPaymentNextAction.StopAndTellUser;
|
|
1148
1158
|
if (status === "approved") return AgentPaymentNextAction.WaitForUserToCompletePayment;
|
|
1149
|
-
if (status === "proposed") return AgentPaymentNextAction.
|
|
1150
|
-
if (status === "executed") return AgentPaymentNextAction.
|
|
1159
|
+
if (status === "proposed") return AgentPaymentNextAction.StopAndTellUser;
|
|
1160
|
+
if (status === "executed") return AgentPaymentNextAction.StopAndTellUser;
|
|
1151
1161
|
if (status === "rejected") return AgentPaymentNextAction.StopAndTellUser;
|
|
1152
1162
|
if (status === "expired") return AgentPaymentNextAction.RequestAgainIfUserStillWantsIt;
|
|
1153
1163
|
if (status === "failed") return AgentPaymentNextAction.StopAndTellUser;
|
|
@@ -1155,10 +1165,10 @@ function nextActionForStatus(status) {
|
|
|
1155
1165
|
}
|
|
1156
1166
|
function messageForState(label, status, paymentId, nextAction) {
|
|
1157
1167
|
if (status === "pending" || status === "pending_approval") {
|
|
1158
|
-
return `${label} is
|
|
1168
|
+
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.`;
|
|
1159
1169
|
}
|
|
1160
1170
|
if (status === "executed") {
|
|
1161
|
-
return "
|
|
1171
|
+
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.`;
|
|
1162
1172
|
}
|
|
1163
1173
|
if (status === "rejected") {
|
|
1164
1174
|
return `The user rejected this payment request (payment_id: ${paymentId}).`;
|
|
@@ -1225,7 +1235,7 @@ function throwPaymentStateError(label, raw) {
|
|
|
1225
1235
|
}
|
|
1226
1236
|
if (raw.status === "pending_approval") {
|
|
1227
1237
|
throw new HavenApiError(
|
|
1228
|
-
`${label} exceeds the on-chain
|
|
1238
|
+
`${label} exceeds the agent's on-chain budget and was declined; no approval is pending and none will arrive (payment_id: ${raw.payment_id}).`,
|
|
1229
1239
|
statusCode,
|
|
1230
1240
|
raw
|
|
1231
1241
|
);
|
|
@@ -1769,13 +1779,18 @@ function requestInitFromSnapshot(request) {
|
|
|
1769
1779
|
body: request.body
|
|
1770
1780
|
};
|
|
1771
1781
|
}
|
|
1782
|
+
function noCompatiblePaymentOptionError(accepts) {
|
|
1783
|
+
const erc7710Only = selectErc7710PaymentOption(accepts) !== null;
|
|
1784
|
+
return new HavenApiError(
|
|
1785
|
+
"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)." : ""),
|
|
1786
|
+
400
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1772
1789
|
function buildX402Quote(paymentRequired, request, idempotencyKey, mcpTransport) {
|
|
1773
|
-
const
|
|
1790
|
+
const standard = selectStandardPaymentOption(paymentRequired.accepts);
|
|
1791
|
+
const option = standard ?? selectErc7710PaymentOption(paymentRequired.accepts);
|
|
1774
1792
|
if (!option) {
|
|
1775
|
-
throw
|
|
1776
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
1777
|
-
400
|
|
1778
|
-
);
|
|
1793
|
+
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
1779
1794
|
}
|
|
1780
1795
|
const token = resolveTokenFromAddress(option.asset, option.network);
|
|
1781
1796
|
return {
|
|
@@ -1783,6 +1798,7 @@ function buildX402Quote(paymentRequired, request, idempotencyKey, mcpTransport)
|
|
|
1783
1798
|
idempotencyKey: idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option),
|
|
1784
1799
|
paymentRequired,
|
|
1785
1800
|
accepted: option,
|
|
1801
|
+
acceptedScheme: standard ? "standard" : "erc7710",
|
|
1786
1802
|
request,
|
|
1787
1803
|
...mcpTransport ? { mcpTransport } : {},
|
|
1788
1804
|
resourceUrl: paymentRequired.resource.url,
|
|
@@ -2276,6 +2292,9 @@ var X402Erc7710 = class {
|
|
|
2276
2292
|
// becomes a loud mismatch instead of a silent reroute to the 3009 leg.
|
|
2277
2293
|
payTo: merchantPayTo,
|
|
2278
2294
|
settlementScheme: "erc7710",
|
|
2295
|
+
// #2041: sent only when the caller supplied one, so an omitting caller's
|
|
2296
|
+
// request body is byte-identical to the pre-#2041 shape.
|
|
2297
|
+
...options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {},
|
|
2279
2298
|
amount: amountAtomic,
|
|
2280
2299
|
asset: option.asset,
|
|
2281
2300
|
network: option.network,
|
|
@@ -2437,6 +2456,8 @@ function toolError(err) {
|
|
|
2437
2456
|
|
|
2438
2457
|
// src/merchant-completion.ts
|
|
2439
2458
|
var MERCHANT_BODY_SNIPPET_LIMIT = 1e3;
|
|
2459
|
+
var EVIDENCE_RETRY_DELAYS_MS = [1e3, 2e3, 4e3];
|
|
2460
|
+
var EVIDENCE_RETRYABLE_STATUS = 503;
|
|
2440
2461
|
var MerchantCompletion = class {
|
|
2441
2462
|
post;
|
|
2442
2463
|
merchantTransport;
|
|
@@ -2444,7 +2465,9 @@ var MerchantCompletion = class {
|
|
|
2444
2465
|
getAgent;
|
|
2445
2466
|
delegateAddress;
|
|
2446
2467
|
x402Wallet;
|
|
2468
|
+
sleep;
|
|
2447
2469
|
constructor(options) {
|
|
2470
|
+
this.sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2448
2471
|
this.post = options.post;
|
|
2449
2472
|
this.merchantTransport = options.merchantTransport;
|
|
2450
2473
|
this.getPaymentStatus = options.getPaymentStatus;
|
|
@@ -2618,22 +2641,29 @@ var MerchantCompletion = class {
|
|
|
2618
2641
|
}
|
|
2619
2642
|
}
|
|
2620
2643
|
async reportEvidence(input) {
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2644
|
+
const body = {
|
|
2645
|
+
paymentId: input.paymentId,
|
|
2646
|
+
rail: input.rail,
|
|
2647
|
+
txHash: input.txHash,
|
|
2648
|
+
resourceUrl: input.resourceUrl,
|
|
2649
|
+
merchantStatus: input.merchantStatus,
|
|
2650
|
+
challengePayload: input.challengePayload,
|
|
2651
|
+
selectedPayment: input.selectedPayment,
|
|
2652
|
+
paymentProofHeaderName: input.paymentProofHeaderName,
|
|
2653
|
+
paymentProofHeader: input.paymentProofHeader,
|
|
2654
|
+
protocolReceiptHeaderName: input.protocolReceiptHeaderName,
|
|
2655
|
+
protocolReceiptHeader: input.protocolReceiptHeader,
|
|
2656
|
+
protocolReceiptPayload: input.protocolReceiptHeader ? parseProtocolReceiptHeader(input.protocolReceiptHeader) : void 0
|
|
2657
|
+
};
|
|
2658
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
2659
|
+
try {
|
|
2660
|
+
await this.post("/machine-payments/evidence", body);
|
|
2661
|
+
return;
|
|
2662
|
+
} catch (err) {
|
|
2663
|
+
const retryable = err instanceof HavenApiError && err.statusCode === EVIDENCE_RETRYABLE_STATUS;
|
|
2664
|
+
if (!retryable || attempt >= EVIDENCE_RETRY_DELAYS_MS.length) return;
|
|
2665
|
+
await this.sleep(EVIDENCE_RETRY_DELAYS_MS[attempt]);
|
|
2666
|
+
}
|
|
2637
2667
|
}
|
|
2638
2668
|
}
|
|
2639
2669
|
};
|
|
@@ -2683,7 +2713,10 @@ function mapCatalogEntry(entry) {
|
|
|
2683
2713
|
asset: entry.asset,
|
|
2684
2714
|
network: entry.network,
|
|
2685
2715
|
status: entry.status,
|
|
2686
|
-
verifiedAt: entry.verified_at
|
|
2716
|
+
verifiedAt: entry.verified_at,
|
|
2717
|
+
source: entry.source,
|
|
2718
|
+
domainVerified: entry.domain_verified,
|
|
2719
|
+
verifiedPayable: entry.verified_payable
|
|
2687
2720
|
};
|
|
2688
2721
|
}
|
|
2689
2722
|
var HavenClient = class {
|
|
@@ -2840,10 +2873,7 @@ var HavenClient = class {
|
|
|
2840
2873
|
async createX402Intent(paymentRequired, options = {}) {
|
|
2841
2874
|
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
2842
2875
|
if (!option) {
|
|
2843
|
-
throw
|
|
2844
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
2845
|
-
400
|
|
2846
|
-
);
|
|
2876
|
+
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
2847
2877
|
}
|
|
2848
2878
|
const fundingTo = options.delegateAddress ?? (await this.getAgent()).delegateAddress;
|
|
2849
2879
|
if (!fundingTo) {
|
|
@@ -3119,7 +3149,7 @@ var HavenClient = class {
|
|
|
3119
3149
|
return status;
|
|
3120
3150
|
}
|
|
3121
3151
|
/**
|
|
3122
|
-
* Discover payable services from Haven's
|
|
3152
|
+
* Discover payable services from Haven's merchant catalog (epic #1717).
|
|
3123
3153
|
*
|
|
3124
3154
|
* Read-only: returns catalog entries (price, rail, protocol) so an agent
|
|
3125
3155
|
* can choose a service and pay it with the regular payment tools in the
|
|
@@ -3132,7 +3162,39 @@ var HavenClient = class {
|
|
|
3132
3162
|
if (options.rail) params.set("rail", options.rail);
|
|
3133
3163
|
const query = params.size > 0 ? `?${params.toString()}` : "";
|
|
3134
3164
|
const raw = await this.get(`/catalog${query}`);
|
|
3135
|
-
|
|
3165
|
+
let entries = raw.entries.map(mapCatalogEntry);
|
|
3166
|
+
if (options.verified === "verified") entries = entries.filter((e) => e.source === "ingestion");
|
|
3167
|
+
if (options.verified === "operator") entries = entries.filter((e) => e.source === "operator");
|
|
3168
|
+
return entries;
|
|
3169
|
+
}
|
|
3170
|
+
/**
|
|
3171
|
+
* Submit a merchant's payable (x402/MCP) endpoint to the Verified Payable
|
|
3172
|
+
* Directory (epic #1717, #1716). Queue-only: writes a submission row and
|
|
3173
|
+
* returns the id + verify_token. The request path makes no outbound
|
|
3174
|
+
* request; domain-ownership proof and the read-only quote probe run later
|
|
3175
|
+
* on the leader-locked monitor. Ownership proof is ALWAYS required before
|
|
3176
|
+
* any listing — this method cannot skip it. `website` is a honeypot field
|
|
3177
|
+
* that bots fill; leave it unset.
|
|
3178
|
+
*/
|
|
3179
|
+
async submitCatalogEntry(resourceUrl, options = {}) {
|
|
3180
|
+
const accepted = await this.post("/catalog/submit", {
|
|
3181
|
+
resource_url: resourceUrl,
|
|
3182
|
+
...options.website ? { website: options.website } : {}
|
|
3183
|
+
});
|
|
3184
|
+
return {
|
|
3185
|
+
id: accepted.id,
|
|
3186
|
+
verifyToken: accepted.verify_token,
|
|
3187
|
+
status: accepted.status
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
/**
|
|
3191
|
+
* Fetch one submission's coarse status by id (epic #1717, #1716). Public
|
|
3192
|
+
* and read-only. While the submission can still prove ownership the
|
|
3193
|
+
* response carries the exact well-known / DNS-TXT `instructions`; the
|
|
3194
|
+
* verify token is never returned here.
|
|
3195
|
+
*/
|
|
3196
|
+
async getCatalogSubmissionStatus(id) {
|
|
3197
|
+
return this.get(`/catalog/submit/${encodeURIComponent(id)}`);
|
|
3136
3198
|
}
|
|
3137
3199
|
/**
|
|
3138
3200
|
* Fetch one curated catalog entry by id (#1306).
|
|
@@ -3207,10 +3269,7 @@ var HavenClient = class {
|
|
|
3207
3269
|
}
|
|
3208
3270
|
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
3209
3271
|
if (!option) {
|
|
3210
|
-
throw
|
|
3211
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
3212
|
-
400
|
|
3213
|
-
);
|
|
3272
|
+
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
3214
3273
|
}
|
|
3215
3274
|
const idempotencyKey = options.idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option);
|
|
3216
3275
|
const cached = this.fundingLeg.cachedReceipt(idempotencyKey);
|
|
@@ -3350,10 +3409,7 @@ var HavenClient = class {
|
|
|
3350
3409
|
}
|
|
3351
3410
|
const option = selectStandardPaymentOption(input.paymentRequired.accepts);
|
|
3352
3411
|
if (!option) {
|
|
3353
|
-
throw
|
|
3354
|
-
"No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
|
|
3355
|
-
400
|
|
3356
|
-
);
|
|
3412
|
+
throw noCompatiblePaymentOptionError(input.paymentRequired.accepts);
|
|
3357
3413
|
}
|
|
3358
3414
|
const idempotencyKey = input.idempotencyKey ?? buildX402IdempotencyKey(input.paymentRequired, option);
|
|
3359
3415
|
const cached = this.fundingLeg.cachedReceipt(idempotencyKey);
|
|
@@ -3553,11 +3609,12 @@ var HavenClient = class {
|
|
|
3553
3609
|
});
|
|
3554
3610
|
}
|
|
3555
3611
|
} else {
|
|
3556
|
-
|
|
3612
|
+
const evidenceTxHash = input.noFundingLeg ? settlement.settlementTxHash ?? void 0 : fundingTxHash ?? void 0;
|
|
3613
|
+
if (evidenceTxHash) {
|
|
3557
3614
|
await this.merchantCompletion.reportEvidence({
|
|
3558
3615
|
paymentId: evidenceContext.paymentId,
|
|
3559
3616
|
rail: "x402",
|
|
3560
|
-
txHash:
|
|
3617
|
+
txHash: evidenceTxHash,
|
|
3561
3618
|
resourceUrl: evidenceContext.resourceUrl,
|
|
3562
3619
|
merchantStatus: surfaced.status,
|
|
3563
3620
|
paymentProofHeaderName: "X-PAYMENT",
|
|
@@ -3730,19 +3787,19 @@ var toolDescriptions = {
|
|
|
3730
3787
|
payX402: {
|
|
3731
3788
|
summary: "Pay an inspected x402 quote. The delegate key signs locally; Haven only validates and relays signed, on-chain-constrained payment transactions.",
|
|
3732
3789
|
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.",
|
|
3733
|
-
behavior: "Signs the
|
|
3734
|
-
nextActionGuidance: "
|
|
3790
|
+
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.",
|
|
3791
|
+
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."
|
|
3735
3792
|
},
|
|
3736
3793
|
payX402OneShot: {
|
|
3737
3794
|
summary: "Fetch an x402 paid HTTP resource in a single call. Handles the full probe -> pay -> retry round trip and returns the merchant response.",
|
|
3738
3795
|
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.",
|
|
3739
|
-
behavior: "Calls the URL, parses any HTTP 402 x402 challenge, signs the
|
|
3740
|
-
nextActionGuidance: "
|
|
3796
|
+
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.",
|
|
3797
|
+
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."
|
|
3741
3798
|
},
|
|
3742
3799
|
resumeX402: {
|
|
3743
|
-
summary: "Resume an x402 payment
|
|
3744
|
-
behavior: "Accepts either resume_state or payment_id, validates the original x402 details against the
|
|
3745
|
-
nextActionGuidance: "Only
|
|
3800
|
+
summary: "Resume an x402 payment whose Haven-side authorization already succeeded but whose merchant retry did not complete.",
|
|
3801
|
+
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.",
|
|
3802
|
+
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."
|
|
3746
3803
|
},
|
|
3747
3804
|
// #1328: quoteMpp / payMpp / resumeMpp (the mpp_demo challenge/quote/resume
|
|
3748
3805
|
// fragments) are retired along with the client surface they described —
|
|
@@ -3750,24 +3807,24 @@ var toolDescriptions = {
|
|
|
3750
3807
|
// deleted `/demo/mpp/*` route. Use the x402 fragments above instead.
|
|
3751
3808
|
getPaymentStatus: {
|
|
3752
3809
|
summary: "Fetch structured Haven payment status, including phase and nextAction taxonomy for agent recovery.",
|
|
3753
|
-
behavior: "Accepts a payment intent
|
|
3810
|
+
behavior: "Accepts a payment intent id and returns the full state taxonomy (phase, nextAction, rail, amount, merchant, resource url, idempotency key, message).",
|
|
3754
3811
|
nextActionGuidance: ""
|
|
3755
3812
|
},
|
|
3756
3813
|
getResumeState: {
|
|
3757
3814
|
summary: "Rehydrate stored x402 resume_state by payment_id.",
|
|
3758
|
-
behavior: "Returns the context
|
|
3815
|
+
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.",
|
|
3759
3816
|
nextActionGuidance: ""
|
|
3760
3817
|
},
|
|
3761
3818
|
getAgent: {
|
|
3762
3819
|
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.",
|
|
3763
3820
|
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.",
|
|
3764
|
-
behavior:
|
|
3821
|
+
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.`,
|
|
3765
3822
|
nextActionGuidance: ""
|
|
3766
3823
|
},
|
|
3767
3824
|
getAllowances: {
|
|
3768
3825
|
summary: "Return configured and on-chain allowance state for the authenticated agent. On-chain allowance is the real spend gate.",
|
|
3769
3826
|
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.",
|
|
3770
|
-
behavior: "Returns the per-token spend authority for the account
|
|
3827
|
+
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.",
|
|
3771
3828
|
nextActionGuidance: ""
|
|
3772
3829
|
},
|
|
3773
3830
|
listReceipts: {
|
|
@@ -3785,15 +3842,21 @@ var toolDescriptions = {
|
|
|
3785
3842
|
payMcpTool: {
|
|
3786
3843
|
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.",
|
|
3787
3844
|
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.",
|
|
3788
|
-
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
|
|
3789
|
-
nextActionGuidance: "
|
|
3845
|
+
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.",
|
|
3846
|
+
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."
|
|
3790
3847
|
},
|
|
3791
3848
|
discoverTools: {
|
|
3792
3849
|
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.",
|
|
3793
|
-
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.",
|
|
3794
|
-
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
|
|
3850
|
+
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.",
|
|
3851
|
+
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.",
|
|
3795
3852
|
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.`
|
|
3796
3853
|
},
|
|
3854
|
+
submitCatalogEntry: {
|
|
3855
|
+
summary: "Submit a merchant's payable (x402/MCP) endpoint to Haven's Verified Payable Directory for verification and listing.",
|
|
3856
|
+
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.",
|
|
3857
|
+
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.",
|
|
3858
|
+
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."
|
|
3859
|
+
},
|
|
3797
3860
|
sweep_delegate: {
|
|
3798
3861
|
summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating Safe.",
|
|
3799
3862
|
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.",
|
|
@@ -3803,8 +3866,8 @@ var toolDescriptions = {
|
|
|
3803
3866
|
send: {
|
|
3804
3867
|
summary: "Send ETH or USDC directly from the agent's Haven wallet to a recipient address.",
|
|
3805
3868
|
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.",
|
|
3806
|
-
behavior: "Sends the requested amount
|
|
3807
|
-
nextActionGuidance: "
|
|
3869
|
+
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.",
|
|
3870
|
+
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."
|
|
3808
3871
|
}
|
|
3809
3872
|
};
|
|
3810
3873
|
|
|
@@ -3875,7 +3938,7 @@ var authorizeX402Schema = {
|
|
|
3875
3938
|
},
|
|
3876
3939
|
idempotencyKey: {
|
|
3877
3940
|
type: "string",
|
|
3878
|
-
description: "Stable caller-supplied key for this user intent. Reuse it when resuming
|
|
3941
|
+
description: "Stable caller-supplied key for this user intent. Reuse it when resuming the same payment."
|
|
3879
3942
|
}
|
|
3880
3943
|
},
|
|
3881
3944
|
required: ["url", "payTo", "amount", "asset", "network"]
|
|
@@ -3885,7 +3948,7 @@ var resumeX402Schema = {
|
|
|
3885
3948
|
properties: {
|
|
3886
3949
|
payment_id: {
|
|
3887
3950
|
type: "string",
|
|
3888
|
-
description: "The payment
|
|
3951
|
+
description: "The payment ID returned by authorize_x402_payment."
|
|
3889
3952
|
},
|
|
3890
3953
|
url: {
|
|
3891
3954
|
type: "string",
|
|
@@ -3918,11 +3981,11 @@ var resumeX402Schema = {
|
|
|
3918
3981
|
},
|
|
3919
3982
|
required: ["payment_id", "url", "payTo", "amount", "asset", "network"]
|
|
3920
3983
|
};
|
|
3921
|
-
var MAKE_PAYMENT_DESCRIPTION = "Request and sign a payment from the user-controlled
|
|
3922
|
-
var GET_STATUS_DESCRIPTION = toolDescriptions.getPaymentStatus.summary + " Accepts payment intent IDs
|
|
3984
|
+
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.";
|
|
3985
|
+
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.";
|
|
3923
3986
|
var GET_ALLOWANCES_DESCRIPTION = composeDescription(toolDescriptions.getAllowances);
|
|
3924
|
-
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
|
|
3925
|
-
var RESUME_X402_DESCRIPTION = toolDescriptions.resumeX402.summary + "
|
|
3987
|
+
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.";
|
|
3988
|
+
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.";
|
|
3926
3989
|
var SWEEP_DELEGATE_DESCRIPTION = composeDescription(toolDescriptions.sweep_delegate);
|
|
3927
3990
|
var sweepDelegateSchema = {
|
|
3928
3991
|
type: "object",
|
|
@@ -4032,8 +4095,8 @@ description: Pay for things from the user's Haven wallet within their agent rule
|
|
|
4032
4095
|
|
|
4033
4096
|
This skill lets the agent make payments from the user's Haven wallet through
|
|
4034
4097
|
the Haven MCP tools. Every payment is checked against the agent's on-chain
|
|
4035
|
-
budget before money moves;
|
|
4036
|
-
|
|
4098
|
+
budget before money moves; a payment above the remaining budget is declined \u2014
|
|
4099
|
+
nothing is paid past the rules the user set.
|
|
4037
4100
|
|
|
4038
4101
|
Hosted tools run in the \`mcp__haven__\` namespace. Local signing tools run in
|
|
4039
4102
|
the \`mcp__haven-signer__\` namespace and keep the delegate key on this machine.
|
|
@@ -4077,8 +4140,8 @@ spending:
|
|
|
4077
4140
|
(configured, spent, reset window) when you need more than the summary.
|
|
4078
4141
|
|
|
4079
4142
|
Budgets reset on a period the user chose. If a payment exceeds the remaining
|
|
4080
|
-
budget it is
|
|
4081
|
-
|
|
4143
|
+
budget it is declined before any money moves \u2014 tell the user; they can raise
|
|
4144
|
+
the budget in the Haven dashboard, or wait for the period reset.
|
|
4082
4145
|
|
|
4083
4146
|
## Paying
|
|
4084
4147
|
|
|
@@ -4120,8 +4183,8 @@ context (\`merchant_url\`, \`tool_name\`, \`arguments\`, \`mcp_transport\`)
|
|
|
4120
4183
|
server-side from \`payment_id\`. Pass those four fields explicitly only as a
|
|
4121
4184
|
version-skew fallback when Haven has no stored context for the id \u2014 both or
|
|
4122
4185
|
none together, never just one. If the settle result carries \`settled: false\`,
|
|
4123
|
-
funding
|
|
4124
|
-
do not re-pay.
|
|
4186
|
+
funding has not confirmed \u2014 follow the result's guidance fields and check
|
|
4187
|
+
status later, do not re-pay.
|
|
4125
4188
|
|
|
4126
4189
|
Step-by-step alternative (also key-safe; for an older signer or backend, or
|
|
4127
4190
|
when you already have a merchant URL and tool name instead of a
|
|
@@ -4144,8 +4207,12 @@ merchant leg for you.
|
|
|
4144
4207
|
recipient, amount, and token for a plain transfer. For an arbitrary,
|
|
4145
4208
|
non-MCP x402 paywall: \`mcp__haven__haven_quote_x402\` to get a quote, then
|
|
4146
4209
|
\`mcp__haven__haven_pay_x402_quote\` \u2014 follow the result's guidance fields
|
|
4147
|
-
first
|
|
4148
|
-
|
|
4210
|
+
first and sign in the local Haven signer. The pay tool performs the merchant
|
|
4211
|
+
retry itself, so do not wait on a signal while it runs. If the process
|
|
4212
|
+
crashes after payment, a later \`mcp__haven__haven_get_payment_status\` call
|
|
4213
|
+
may report \`nextAction: 'retry_original_x402_request'\` \u2014 only then call
|
|
4214
|
+
\`mcp__haven__haven_resume_x402_payment\` with the preserved resume state or
|
|
4215
|
+
payment id, instead of paying again.
|
|
4149
4216
|
|
|
4150
4217
|
**Catalog tool arguments:** when \`haven_discover_tools\` returns
|
|
4151
4218
|
\`tool_arguments\`, pass that object unchanged as the pay tool's
|
|
@@ -4161,14 +4228,14 @@ Haven authorizes for that call \u2014 a ceiling the merchant settles at or below
|
|
|
4161
4228
|
so present it as the most the user will pay.
|
|
4162
4229
|
|
|
4163
4230
|
**Status:** \`mcp__haven__haven_get_payment_status\` with a \`payment_id\` to
|
|
4164
|
-
check on
|
|
4231
|
+
check on in-flight payments. Do not poll in a tight loop.
|
|
4165
4232
|
|
|
4166
|
-
##
|
|
4233
|
+
## Declines and stop signals
|
|
4167
4234
|
|
|
4168
|
-
- A
|
|
4169
|
-
budget
|
|
4170
|
-
|
|
4171
|
-
- \`safe_to_continue: false\` on a guidance block is
|
|
4235
|
+
- A payment outside the agent's rules \u2014 above the remaining budget, wrong
|
|
4236
|
+
recipient, or expired budget \u2014 is declined before any money moves. Nothing
|
|
4237
|
+
is queued; tell the user, who can raise the budget in Haven.
|
|
4238
|
+
- \`safe_to_continue: false\` on a guidance block is a stop signal in
|
|
4172
4239
|
machine-readable form: stop and involve the user before calling anything
|
|
4173
4240
|
else for this payment.
|
|
4174
4241
|
- Never ask the user for private keys. Signing happens only in the local Haven
|
|
@@ -4182,7 +4249,6 @@ Haven tool failures are shaped like \`{ success: false, code, message, ... }\`
|
|
|
4182
4249
|
or older \`{ error, status, details? }\` responses. Branch on \`code\` when
|
|
4183
4250
|
present and surface \`message\` or \`error\` verbatim. Common cases:
|
|
4184
4251
|
|
|
4185
|
-
- \`pending_approval\`: queued for the user's approval (see above).
|
|
4186
4252
|
- \`insufficient_funds\`: the Haven wallet doesn't hold enough of that token.
|
|
4187
4253
|
Suggest the user add funds in the Haven dashboard.
|
|
4188
4254
|
- \`PRICE_EXCEEDS_MAX\`: the live merchant price exceeded your cap. No funds
|