@haven_ai/sdk 0.4.0-alpha.0 → 0.6.0-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 +54 -3
- package/dist/base64-cD9kR4JL.d.cts +2958 -0
- package/dist/base64-cD9kR4JL.d.ts +2958 -0
- package/dist/chunk-3WSEX3GW.js +1211 -0
- package/dist/chunk-3WSEX3GW.js.map +1 -0
- package/dist/chunk-63GPTEEY.js +939 -0
- package/dist/chunk-63GPTEEY.js.map +1 -0
- package/dist/chunk-CK4NLLMO.cjs +1286 -0
- package/dist/chunk-CK4NLLMO.cjs.map +1 -0
- package/dist/chunk-S42QSWJY.cjs +1000 -0
- package/dist/chunk-S42QSWJY.cjs.map +1 -0
- package/dist/edge.cjs +299 -0
- package/dist/edge.cjs.map +1 -0
- package/dist/edge.d.cts +125 -0
- package/dist/edge.d.ts +125 -0
- package/dist/edge.js +56 -0
- package/dist/edge.js.map +1 -0
- package/dist/index.cjs +1105 -1468
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -2323
- package/dist/index.d.ts +75 -2323
- package/dist/index.js +505 -1230
- package/dist/index.js.map +1 -1
- package/dist/test-support.cjs +215 -0
- package/dist/test-support.cjs.map +1 -0
- package/dist/test-support.d.cts +204 -0
- package/dist/test-support.d.ts +204 -0
- package/dist/test-support.js +200 -0
- package/dist/test-support.js.map +1 -0
- package/package.json +23 -1
package/dist/index.cjs
CHANGED
|
@@ -1,473 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkCK4NLLMO_cjs = require('./chunk-CK4NLLMO.cjs');
|
|
4
|
+
var chunkS42QSWJY_cjs = require('./chunk-S42QSWJY.cjs');
|
|
3
5
|
var viem = require('viem');
|
|
4
6
|
var ethers = require('ethers');
|
|
5
|
-
var crypto = require('crypto');
|
|
6
7
|
var async_hooks = require('async_hooks');
|
|
7
8
|
var schemes = require('x402/schemes');
|
|
8
9
|
var accounts = require('viem/accounts');
|
|
9
10
|
|
|
10
|
-
// src/client.ts
|
|
11
|
-
|
|
12
|
-
// src/connector-channel.ts
|
|
13
|
-
var CONNECTOR_PACKAGE_NAME = "@haven_ai/connect";
|
|
14
|
-
var HAVEN_CONNECTOR_CHANNEL = "alpha";
|
|
15
|
-
var CHANNEL_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
|
|
16
|
-
function isConnectorChannel(value) {
|
|
17
|
-
return CHANNEL_PATTERN.test(value);
|
|
18
|
-
}
|
|
19
|
-
function resolveConnectorChannel(raw, fallback = HAVEN_CONNECTOR_CHANNEL) {
|
|
20
|
-
const trimmed = (raw ?? "").trim();
|
|
21
|
-
if (trimmed === "") return fallback;
|
|
22
|
-
if (!isConnectorChannel(trimmed)) {
|
|
23
|
-
throw new Error(
|
|
24
|
-
`HAVEN_CONNECTOR_CHANNEL is set to ${JSON.stringify(raw)}, which is not a valid npm dist-tag (lowercase letter first, then letters, digits or hyphens). Refusing to start rather than fall back to the default channel, because falling back would hand out the production connector while looking configured.`
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
return trimmed;
|
|
28
|
-
}
|
|
29
|
-
function connectorSpec(channel = HAVEN_CONNECTOR_CHANNEL) {
|
|
30
|
-
return `${CONNECTOR_PACKAGE_NAME}@${channel}`;
|
|
31
|
-
}
|
|
32
|
-
function connectorRerunCommand(args, options) {
|
|
33
|
-
const channel = options?.channel ?? HAVEN_CONNECTOR_CHANNEL;
|
|
34
|
-
const flags = options?.npxFlags ? `${options.npxFlags} ` : "";
|
|
35
|
-
const command = `npx ${flags}${connectorSpec(channel)}`;
|
|
36
|
-
return args ? `${command} ${args}` : command;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// src/types.ts
|
|
40
|
-
var DEFAULT_CONFIRMATION_TIMEOUT_MS = 9e4;
|
|
41
|
-
var AgentPaymentPhase = {
|
|
42
|
-
/** The agent must sign and submit the prepared payment before Haven can relay it. */
|
|
43
|
-
AgentSignatureRequired: "agent_signature_required",
|
|
44
|
-
/** Haven has received the signed payment and the agent should poll for confirmation. */
|
|
45
|
-
PaymentSubmitted: "payment_submitted",
|
|
46
|
-
/** The direct payment is confirmed; the agent does not need to do more for this payment id. */
|
|
47
|
-
PaymentConfirmed: "payment_confirmed",
|
|
48
|
-
/**
|
|
49
|
-
* #2115: RETIRED wire value — no live rail produces it. It described the
|
|
50
|
-
* Safe rail's approval queue, which no longer exists. Kept so a stored value
|
|
51
|
-
* still typechecks; see `AgentPaymentPhaseDescriptions` below for the
|
|
52
|
-
* agent-visible wording, which this comment used to contradict.
|
|
53
|
-
*/
|
|
54
|
-
UserApprovalRequired: "user_approval_required",
|
|
55
|
-
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
56
|
-
UserExecutionRequired: "user_execution_required",
|
|
57
|
-
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
58
|
-
WaitingForAdditionalApprovals: "waiting_for_additional_approvals",
|
|
59
|
-
/** The Haven funding leg was sent; the agent can continue the merchant/protocol leg. */
|
|
60
|
-
FundingSent: "funding_sent",
|
|
61
|
-
/** The payment was rejected and cannot proceed; the agent should stop and tell the user. */
|
|
62
|
-
Rejected: "rejected",
|
|
63
|
-
/** The payment expired before completion. */
|
|
64
|
-
Expired: "expired",
|
|
65
|
-
/** Haven could not complete the payment; the agent should stop and surface the failure. */
|
|
66
|
-
Failed: "failed",
|
|
67
|
-
/**
|
|
68
|
-
* Pre-flight check determined the delegate's existing balance plus the
|
|
69
|
-
* remaining on-chain budget cannot cover the requested amount, so no
|
|
70
|
-
* payment intent was created. The account must be funded or the agent's
|
|
71
|
-
* budget raised before retrying — #2115: the old wording contrasted this
|
|
72
|
-
* with `UserApprovalRequired` as if that were a live alternative, and named
|
|
73
|
-
* the retired rail's Safe and per-token allowance as the fix.
|
|
74
|
-
*/
|
|
75
|
-
InsufficientFunds: "insufficient_funds",
|
|
76
|
-
/**
|
|
77
|
-
* Haven's funding leg (account → delegate, the #946 EIP-3009 bridge)
|
|
78
|
-
* confirmed on-chain, but the merchant rejected the x402 retry. The delegate
|
|
79
|
-
* wallet may hold stranded USDC that was never settled to the merchant. The
|
|
80
|
-
* agent should stop, tell the user, and wait for the sweep flow to reclaim
|
|
81
|
-
* the funds.
|
|
82
|
-
*/
|
|
83
|
-
FundedButUnsettled: "funded_but_unsettled"
|
|
84
|
-
};
|
|
85
|
-
var AgentPaymentNextAction = {
|
|
86
|
-
/** Sign with the delegate key and submit the payment to Haven. */
|
|
87
|
-
SignAndSubmitPayment: "sign_and_submit_payment",
|
|
88
|
-
/** Poll getPaymentStatus later using this payment id. */
|
|
89
|
-
CheckStatusLater: "check_status_later",
|
|
90
|
-
/** No further agent action is required for this payment id. */
|
|
91
|
-
None: "none",
|
|
92
|
-
/**
|
|
93
|
-
* #2115: RETIRED wire value — no live rail produces it and nothing maps to
|
|
94
|
-
* it. Stop and tell the user rather than polling; no approval will arrive.
|
|
95
|
-
*/
|
|
96
|
-
WaitForUserApproval: "wait_for_user_approval",
|
|
97
|
-
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user rather than polling. */
|
|
98
|
-
WaitForUserToCompletePayment: "wait_for_user_to_complete_payment",
|
|
99
|
-
/** Resume this payment id and retry the original x402 request with the merchant payment header. */
|
|
100
|
-
RetryOriginalX402Request: "retry_original_x402_request",
|
|
101
|
-
/** Stop retrying this payment and tell the user what happened. */
|
|
102
|
-
StopAndTellUser: "stop_and_tell_user",
|
|
103
|
-
/** Ask again only if the user still wants the payment after expiry. */
|
|
104
|
-
RequestAgainIfUserStillWantsIt: "request_again_if_user_still_wants_it",
|
|
105
|
-
/** #1307: retry the SAME tool call, supplying the explicit context fields the server could not rehydrate. */
|
|
106
|
-
RetryWithExplicitContext: "retry_with_explicit_context",
|
|
107
|
-
/**
|
|
108
|
-
* The x402 funding/quote window expired. Re-quote the same logical merchant
|
|
109
|
-
* operation with the same idempotency key to stay double-charge-safe.
|
|
110
|
-
*/
|
|
111
|
-
PaymentWindowExpired: "payment_window_expired",
|
|
112
|
-
/**
|
|
113
|
-
* Stop and tell the user that the originating account needs to be funded or
|
|
114
|
-
* the agent's per-token allowance needs to be raised before the payment
|
|
115
|
-
* can succeed. A user approval will not fix this state on its own.
|
|
116
|
-
*
|
|
117
|
-
* #2914: the account-vocabulary spelling, and the only one — the
|
|
118
|
-
* pre-#2907 `fund_safe_or_raise_allowance` wire value (and the
|
|
119
|
-
* `AgentPaymentNextActionAccountAlias` seam #2908 added to bridge it) are
|
|
120
|
-
* retired along with the rest of the #2908 compatibility window.
|
|
121
|
-
*/
|
|
122
|
-
FundAccountOrRaiseAllowance: "fund_account_or_raise_allowance",
|
|
123
|
-
/**
|
|
124
|
-
* The delegate wallet may hold funds that were sent from the Safe but never
|
|
125
|
-
* settled to the merchant. The wallet owner should initiate a sweep to
|
|
126
|
-
* return those funds to the originating Safe.
|
|
127
|
-
*/
|
|
128
|
-
SweepStrandedFunds: "sweep_stranded_funds",
|
|
129
|
-
/**
|
|
130
|
-
* #2970: a `submitted` erc7710 x402 intent whose settlement window has
|
|
131
|
-
* passed with no on-chain settlement evidence Haven could verify. Distinct
|
|
132
|
-
* from {@link CheckStatusLater}, which this REPLACES once the window is
|
|
133
|
-
* past — but it is not futile: Haven's settlement sweep (120s tick) scans
|
|
134
|
-
* each candidate over its own window plus a 120s clock-skew allowance, so
|
|
135
|
-
* it can still attribute the settlement for a short while after this value
|
|
136
|
-
* first appears. Poll {@link CheckStatusLater}'s tool
|
|
137
|
-
* (`haven_get_payment_status`) once more, roughly two minutes later; if it
|
|
138
|
-
* still shows no evidence, tell the user the goods were delivered but
|
|
139
|
-
* Haven holds no verified settlement evidence for this payment. If the
|
|
140
|
-
* agent holds the merchant's real settlement transaction hash (from
|
|
141
|
-
* `PAYMENT-RESPONSE`'s `transaction` field, or a prior settle/complete
|
|
142
|
-
* result's `settlement_tx_hash`), report it with the hosted
|
|
143
|
-
* `haven_report_settlement_evidence` tool instead of waiting —
|
|
144
|
-
* `haven_report_x402_outcome` takes no hash and refuses a non-`confirmed`
|
|
145
|
-
* intent.
|
|
146
|
-
*/
|
|
147
|
-
AwaitingSettlementEvidence: "awaiting_settlement_evidence"
|
|
148
|
-
};
|
|
149
|
-
var AgentPaymentFailureCode = {
|
|
150
|
-
/** A merchant-authoritative x402 price exceeds the caller's pre-funding max_amount cap. */
|
|
151
|
-
PriceExceedsMax: "PRICE_EXCEEDS_MAX",
|
|
152
|
-
/** The x402 funding/quote window expired before the signer or hosted settle step could finish. */
|
|
153
|
-
PaymentWindowExpired: "PAYMENT_WINDOW_EXPIRED",
|
|
154
|
-
/** The merchant rejected the paid retry. On eip3009 the funding leg had succeeded (sweep);
|
|
155
|
-
* on erc7710 there is no funding leg — nothing to sweep, follow the message (#2983). */
|
|
156
|
-
MerchantRejectedAfterFunding: "MERCHANT_REJECTED_AFTER_FUNDING",
|
|
157
|
-
/** #1300 review: funding is on-chain but the merchant never ANSWERED the
|
|
158
|
-
* paid retry within the timeout. NOT proof of rejection — the merchant
|
|
159
|
-
* may still settle late, so the guidance is verify-then-act. On eip3009
|
|
160
|
-
* the funding leg had succeeded (verify-then-sweep); on erc7710 there is
|
|
161
|
-
* no funding leg — nothing to sweep, follow the message (#3000). */
|
|
162
|
-
MerchantUnresponsiveAfterFunding: "MERCHANT_UNRESPONSIVE_AFTER_FUNDING",
|
|
163
|
-
/**
|
|
164
|
-
* #1307: the caller omitted merchant_url/tool_name (asking Haven to
|
|
165
|
-
* rehydrate the stored MCP merchant-call context by payment_id), but no
|
|
166
|
-
* usable context was stored for this intent — either it was never an
|
|
167
|
-
* MCP-tool quote, or the stored context is incomplete. The fallback is
|
|
168
|
-
* mechanical: re-send merchant_url, tool_name, arguments, and
|
|
169
|
-
* mcp_transport explicitly (the version-skew path).
|
|
170
|
-
*/
|
|
171
|
-
MerchantCallContextUnavailable: "MERCHANT_CALL_CONTEXT_UNAVAILABLE",
|
|
172
|
-
/**
|
|
173
|
-
* #1351: the caller supplied BOTH the atomic `max_amount` and the
|
|
174
|
-
* human-denominated `max_amount_human` cap for one purchase. Haven refuses
|
|
175
|
-
* to guess which the user meant — the two differ by a factor of 10^decimals,
|
|
176
|
-
* so picking wrong is exactly the silent-overspend this cap exists to
|
|
177
|
-
* prevent. Rejected before any merchant probe, funding intent, or signature.
|
|
178
|
-
*/
|
|
179
|
-
AmbiguousMaxAmount: "AMBIGUOUS_MAX_AMOUNT",
|
|
180
|
-
/**
|
|
181
|
-
* #1351: a human-denominated cap was supplied, but it cannot be converted to
|
|
182
|
-
* atomic units against THIS quote — either the quote's asset has no known
|
|
183
|
-
* decimals on its network, or the cap carries more fraction digits than the
|
|
184
|
-
* asset can represent (truncating it would silently change the user's cap).
|
|
185
|
-
* The fallback is the exact atomic `max_amount`.
|
|
186
|
-
*/
|
|
187
|
-
MaxAmountUnconvertible: "MAX_AMOUNT_UNCONVERTIBLE",
|
|
188
|
-
/**
|
|
189
|
-
* #2979: the merchant answered a `tools/call` probe with its own
|
|
190
|
-
* machine-readable "cannot settle right now" refusal (HTTP 503,
|
|
191
|
-
* `{ error: 'merchant_not_ready', reason_code, ... }`) instead of a 402
|
|
192
|
-
* challenge — e.g. its settlement wallet is out of gas. No 402 was ever
|
|
193
|
-
* issued and no payment was created; this is honest and (per
|
|
194
|
-
* `retry_after_s`, when present) usually transient, unlike a permanent
|
|
195
|
-
* endpoint miss.
|
|
196
|
-
*/
|
|
197
|
-
MerchantNotReady: "MERCHANT_NOT_READY"
|
|
198
|
-
};
|
|
199
|
-
var AgentPaymentRail = {
|
|
200
|
-
/** Standard Haven payment from the user's Safe through an approved delegate allowance. */
|
|
201
|
-
Direct: "direct",
|
|
202
|
-
/** x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg. */
|
|
203
|
-
X402: "x402",
|
|
204
|
-
/** Machine Payment Protocol family — categorical value used as a resume-state discriminator. */
|
|
205
|
-
Mpp: "mpp",
|
|
206
|
-
/** Haven internal MPP demo rail. Not for production traffic. */
|
|
207
|
-
MppDemo: "mpp_demo",
|
|
208
|
-
/** Crypto-settled MPP rail. */
|
|
209
|
-
MppCrypto: "mpp_crypto",
|
|
210
|
-
/** Stripe-deposit-backed MPP rail. */
|
|
211
|
-
StripeDeposit: "stripe_deposit",
|
|
212
|
-
/** Stripe Payment Token MPP rail. */
|
|
213
|
-
Spt: "spt"
|
|
214
|
-
};
|
|
215
|
-
var AGENT_PAYMENT_PHASE_VALUES = Object.values(AgentPaymentPhase);
|
|
216
|
-
var AGENT_PAYMENT_NEXT_ACTION_VALUES = Object.values(AgentPaymentNextAction);
|
|
217
|
-
var AGENT_PAYMENT_FAILURE_CODE_VALUES = Object.values(AgentPaymentFailureCode);
|
|
218
|
-
var AGENT_PAYMENT_RAIL_VALUES = Object.values(AgentPaymentRail);
|
|
219
|
-
var AgentPaymentPhaseDescriptions = {
|
|
220
|
-
[AgentPaymentPhase.AgentSignatureRequired]: "The agent must sign and submit the prepared payment before Haven can relay it.",
|
|
221
|
-
[AgentPaymentPhase.PaymentSubmitted]: "Haven has received the signed payment and the agent should poll for confirmation.",
|
|
222
|
-
[AgentPaymentPhase.PaymentConfirmed]: "The direct payment is confirmed; the agent does not need to do more for this payment id.",
|
|
223
|
-
[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.",
|
|
224
|
-
[AgentPaymentPhase.UserExecutionRequired]: "Retired wire value: no live rail produces it. Stop and tell the user.",
|
|
225
|
-
[AgentPaymentPhase.WaitingForAdditionalApprovals]: "Retired wire value: no live rail produces it. Stop and tell the user.",
|
|
226
|
-
[AgentPaymentPhase.FundingSent]: "The Haven funding leg was sent; the agent can continue the merchant/protocol leg.",
|
|
227
|
-
[AgentPaymentPhase.Rejected]: "The payment was rejected and cannot proceed; the agent should stop and tell the user.",
|
|
228
|
-
[AgentPaymentPhase.Expired]: "The payment expired before completion.",
|
|
229
|
-
[AgentPaymentPhase.Failed]: "Haven could not complete the payment; the agent should stop and surface the failure.",
|
|
230
|
-
[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.",
|
|
231
|
-
[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."
|
|
232
|
-
};
|
|
233
|
-
var AgentPaymentNextActionDescriptions = {
|
|
234
|
-
[AgentPaymentNextAction.SignAndSubmitPayment]: "Sign with the delegate key and submit the payment to Haven.",
|
|
235
|
-
[AgentPaymentNextAction.CheckStatusLater]: "Poll getPaymentStatus later using this payment id.",
|
|
236
|
-
[AgentPaymentNextAction.None]: "No further agent action is required for this payment id.",
|
|
237
|
-
[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.",
|
|
238
|
-
[AgentPaymentNextAction.WaitForUserToCompletePayment]: "Retired wire value: no live rail produces it. Stop and tell the user rather than polling.",
|
|
239
|
-
[AgentPaymentNextAction.RetryOriginalX402Request]: "Resume this payment id and retry the original x402 request with the merchant payment header.",
|
|
240
|
-
[AgentPaymentNextAction.StopAndTellUser]: "Stop retrying this payment and tell the user what happened.",
|
|
241
|
-
[AgentPaymentNextAction.RequestAgainIfUserStillWantsIt]: "Ask again only if the user still wants the payment after expiry.",
|
|
242
|
-
[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.",
|
|
243
|
-
[AgentPaymentNextAction.FundAccountOrRaiseAllowance]: "Stop and tell the user that the account needs to be funded or the agent budget raised before the payment can succeed.",
|
|
244
|
-
[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.",
|
|
245
|
-
[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.",
|
|
246
|
-
[AgentPaymentNextAction.AwaitingSettlementEvidence]: "The settlement window passed with no verified on-chain evidence yet. If you hold the merchant's real settlement transaction hash, report it with haven_report_settlement_evidence. Otherwise, Haven's settlement sweep may still attribute it within about two minutes \u2014 poll getPaymentStatus once more, then tell the user the goods were delivered but unverified if it still shows nothing."
|
|
247
|
-
};
|
|
248
|
-
var AgentPaymentFailureCodeDescriptions = {
|
|
249
|
-
[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.",
|
|
250
|
-
[AgentPaymentFailureCode.PaymentWindowExpired]: "The x402 funding/quote window expired before the signer or hosted settle step could finish. Re-quote via haven_pay_mcp_tool with the same idempotency key to avoid duplicate funding.",
|
|
251
|
-
[AgentPaymentFailureCode.MerchantRejectedAfterFunding]: "The merchant rejected the paid retry. eip3009: the funding leg succeeded \u2014 stop retrying the merchant and reconcile stranded delegate funds with haven_sweep_delegate. erc7710: no funding leg, nothing to sweep \u2014 follow the message (re-quote later, or check haven_get_payment_status after the window first).",
|
|
252
|
-
[AgentPaymentFailureCode.MerchantUnresponsiveAfterFunding]: "The merchant did not answer the paid retry before the timeout. The merchant may still settle late. eip3009: the funding leg succeeded \u2014 check haven_get_payment_status, retry haven_complete_mcp_tool once, sweep only if no settlement appears. erc7710: no funding leg, nothing to sweep, and haven_complete_mcp_tool has no erc7710 branch \u2014 do not retry it; check haven_get_payment_status after the payment window and re-quote only if it shows no settlement.",
|
|
253
|
-
[AgentPaymentFailureCode.MerchantCallContextUnavailable]: "merchant_url/tool_name were omitted and no stored merchant call context is available for this payment_id. Re-send merchant_url, tool_name, arguments, and mcp_transport explicitly.",
|
|
254
|
-
[AgentPaymentFailureCode.AmbiguousMaxAmount]: "Both max_amount (atomic units) and max_amount_human (whole tokens) were supplied for one purchase. Nothing was contacted and nothing was spent. Re-send with exactly ONE: max_amount_human for a cap the user stated in tokens, max_amount for an exact atomic figure.",
|
|
255
|
-
[AgentPaymentFailureCode.MaxAmountUnconvertible]: "max_amount_human could not be converted to atomic units against this quote's asset \u2014 either its decimals are unknown to Haven or the cap has more decimal places than the asset supports. Nothing was spent. Round the cap, or re-send it as an exact atomic max_amount.",
|
|
256
|
-
[AgentPaymentFailureCode.MerchantNotReady]: 'The merchant refused the probe with its own "cannot settle right now" signal instead of a 402 challenge. No payment was created. Often transient \u2014 retry later (see retry_after_s in the message, if given) rather than treating this as a broken or wrong endpoint.'
|
|
257
|
-
};
|
|
258
|
-
var AgentPaymentWarningCode = {
|
|
259
|
-
/** No max_amount cap was supplied — the live quoted price was accepted as-is. */
|
|
260
|
-
MissingMaxAmount: "MISSING_MAX_AMOUNT",
|
|
261
|
-
/** The signing window closes soon; sign promptly or re-quote with the same idempotency key. */
|
|
262
|
-
QuoteExpiresSoon: "QUOTE_EXPIRES_SOON",
|
|
263
|
-
/** The merchant URL was resolved via discovery — pass the RESOLVED url forward. */
|
|
264
|
-
MerchantUrlDiscovered: "MERCHANT_URL_DISCOVERED",
|
|
265
|
-
/**
|
|
266
|
-
* #1306: the catalog's last-verified price_atomic differs from the LIVE
|
|
267
|
-
* merchant quote for a guided catalog purchase. The catalog price is only
|
|
268
|
-
* ever indicative; the live quote in the same response is authoritative.
|
|
269
|
-
*/
|
|
270
|
-
CatalogPriceDiffers: "CATALOG_PRICE_DIFFERS",
|
|
271
|
-
/**
|
|
272
|
-
* #1306: the rail-aware allowance/budget pre-check could not be read (RPC
|
|
273
|
-
* failure, etc). `sufficient` is reported as null rather than a fabricated
|
|
274
|
-
* true/false — the on-chain policy remains the actual gate either way.
|
|
275
|
-
*/
|
|
276
|
-
AllowanceCheckUnavailable: "ALLOWANCE_CHECK_UNAVAILABLE",
|
|
277
|
-
/**
|
|
278
|
-
* #1319: the delegation-rail read itself SUCCEEDED, but the remaining
|
|
279
|
-
* figure it returned is the #1145 fallback (the full configured budget)
|
|
280
|
-
* rather than a live ERC20PeriodTransferEnforcer read — `sufficient` is a
|
|
281
|
-
* real true/false, just computed from an optimistic number. Distinct from
|
|
282
|
-
* {@link AgentPaymentWarningCode.AllowanceCheckUnavailable}, which fires
|
|
283
|
-
* when the read failed outright and `sufficient` degrades to null. The
|
|
284
|
-
* on-chain policy re-checks at redemption either way; this only says the
|
|
285
|
-
* guidance shown here may be optimistic.
|
|
286
|
-
*/
|
|
287
|
-
AllowanceReadOptimistic: "ALLOWANCE_READ_OPTIMISTIC",
|
|
288
|
-
/**
|
|
289
|
-
* #2991: the quote tools' `expected_settlement_scheme` prediction of what
|
|
290
|
-
* `haven_prepare_catalog_purchase` / `haven_pay_mcp_tool` will actually
|
|
291
|
-
* select could not be computed — the agent's execution rail could not be
|
|
292
|
-
* read from Haven, so `expected_settlement_scheme` is `null` rather than a
|
|
293
|
-
* guess. `accepted_scheme` (the merchant's offer) is unaffected.
|
|
294
|
-
*/
|
|
295
|
-
X402SchemeUnknown: "X402_SCHEME_UNKNOWN",
|
|
296
|
-
/**
|
|
297
|
-
* #2968: the merchant answered 200 and handed over goods, but Haven holds NO
|
|
298
|
-
* on-chain evidence that the payment moved. `settled: false` beside this code
|
|
299
|
-
* is not a failure — it is the absence of proof, and the two must travel
|
|
300
|
-
* together so an agent can tell "the user has the goods" apart from "the
|
|
301
|
-
* money moved". Carries the intent's `expires_at`: after that instant the
|
|
302
|
-
* settlement can no longer land at all.
|
|
303
|
-
*/
|
|
304
|
-
SettlementUnconfirmed: "SETTLEMENT_UNCONFIRMED"
|
|
305
|
-
};
|
|
306
|
-
var AgentPaymentRailDescriptions = {
|
|
307
|
-
[AgentPaymentRail.Direct]: "Standard Haven payment from the user-controlled account, redeeming the agent's on-chain budget delegation.",
|
|
308
|
-
[AgentPaymentRail.X402]: "x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg.",
|
|
309
|
-
[AgentPaymentRail.Mpp]: "Categorical MPP rail value used as a resume-state discriminator. Response bodies carry a granular mpp_* value instead.",
|
|
310
|
-
[AgentPaymentRail.MppDemo]: "Haven internal MPP demo rail. Not for production traffic.",
|
|
311
|
-
[AgentPaymentRail.MppCrypto]: "Crypto-settled MPP rail.",
|
|
312
|
-
[AgentPaymentRail.StripeDeposit]: "Stripe-deposit-backed MPP rail.",
|
|
313
|
-
[AgentPaymentRail.Spt]: "Stripe Payment Token MPP rail."
|
|
314
|
-
};
|
|
315
|
-
var AgentPaymentPhaseSchema = {
|
|
316
|
-
type: "string",
|
|
317
|
-
enum: AGENT_PAYMENT_PHASE_VALUES,
|
|
318
|
-
description: "Stable Haven agent payment state phase.",
|
|
319
|
-
"x-enumDescriptions": AgentPaymentPhaseDescriptions
|
|
320
|
-
};
|
|
321
|
-
var AgentPaymentNextActionSchema = {
|
|
322
|
-
type: "string",
|
|
323
|
-
enum: AGENT_PAYMENT_NEXT_ACTION_VALUES,
|
|
324
|
-
description: "Stable next action an agent should take for a Haven payment state.",
|
|
325
|
-
"x-enumDescriptions": AgentPaymentNextActionDescriptions
|
|
326
|
-
};
|
|
327
|
-
var AgentPaymentFailureCodeSchema = {
|
|
328
|
-
type: "string",
|
|
329
|
-
enum: AGENT_PAYMENT_FAILURE_CODE_VALUES,
|
|
330
|
-
description: "Stable machine-readable failure codes for Haven agent payment recovery paths.",
|
|
331
|
-
"x-enumDescriptions": AgentPaymentFailureCodeDescriptions
|
|
332
|
-
};
|
|
333
|
-
var AgentPaymentRailSchema = {
|
|
334
|
-
type: "string",
|
|
335
|
-
enum: AGENT_PAYMENT_RAIL_VALUES,
|
|
336
|
-
description: "Stable rail identifier for Haven agent payment states.",
|
|
337
|
-
"x-enumDescriptions": AgentPaymentRailDescriptions
|
|
338
|
-
};
|
|
339
|
-
var HavenError = class extends Error {
|
|
340
|
-
constructor(message, code, statusCode, paymentId) {
|
|
341
|
-
super(message);
|
|
342
|
-
this.code = code;
|
|
343
|
-
this.statusCode = statusCode;
|
|
344
|
-
this.paymentId = paymentId;
|
|
345
|
-
this.name = "HavenError";
|
|
346
|
-
}
|
|
347
|
-
code;
|
|
348
|
-
statusCode;
|
|
349
|
-
paymentId;
|
|
350
|
-
};
|
|
351
|
-
var HavenApiError = class extends HavenError {
|
|
352
|
-
constructor(message, statusCode, body, paymentId) {
|
|
353
|
-
super(message, "API_ERROR", statusCode, paymentId);
|
|
354
|
-
this.body = body;
|
|
355
|
-
this.name = "HavenApiError";
|
|
356
|
-
}
|
|
357
|
-
body;
|
|
358
|
-
};
|
|
359
|
-
var MerchantTimeoutError = class extends HavenApiError {
|
|
360
|
-
merchantErrorCode = "merchant_timeout";
|
|
361
|
-
constructor(message) {
|
|
362
|
-
super(message, 504);
|
|
363
|
-
this.name = "MerchantTimeoutError";
|
|
364
|
-
}
|
|
365
|
-
};
|
|
366
|
-
var X402UnexpectedStatusError = class extends HavenApiError {
|
|
367
|
-
x402ErrorCode = "unexpected_non_402_status";
|
|
368
|
-
/**
|
|
369
|
-
* #2979: `body` is the merchant's own JSON, when the non-402 response
|
|
370
|
-
* carried one — e.g. the demo merchant's `/mcp` readiness gate answers
|
|
371
|
-
* `503 { error: 'merchant_not_ready', reason_code, ... }`. Optional and
|
|
372
|
-
* best-effort: a non-JSON or unreadable body leaves this `undefined`, same
|
|
373
|
-
* as before this field existed. Consumers key on it (not on the message
|
|
374
|
-
* string) to distinguish an honest, machine-readable merchant refusal from
|
|
375
|
-
* a genuine "this is not the x402 endpoint" miss, which otherwise look
|
|
376
|
-
* identical — both are just "some non-402 status".
|
|
377
|
-
*/
|
|
378
|
-
constructor(message, statusCode, body) {
|
|
379
|
-
super(message, statusCode, body);
|
|
380
|
-
this.name = "X402UnexpectedStatusError";
|
|
381
|
-
}
|
|
382
|
-
};
|
|
383
|
-
var X402AlreadySettledError = class extends HavenApiError {
|
|
384
|
-
constructor(message, receipt, basis) {
|
|
385
|
-
super(message, 409, void 0, receipt.paymentId);
|
|
386
|
-
this.receipt = receipt;
|
|
387
|
-
this.basis = basis;
|
|
388
|
-
this.name = "X402AlreadySettledError";
|
|
389
|
-
}
|
|
390
|
-
receipt;
|
|
391
|
-
basis;
|
|
392
|
-
x402ErrorCode = "already_settled";
|
|
393
|
-
};
|
|
394
|
-
var HavenPaymentStateError = class extends HavenApiError {
|
|
395
|
-
constructor(message, statusCode, state, body) {
|
|
396
|
-
super(message, statusCode, body, state.paymentId);
|
|
397
|
-
this.state = state;
|
|
398
|
-
this.name = "HavenPaymentStateError";
|
|
399
|
-
}
|
|
400
|
-
state;
|
|
401
|
-
resumeState;
|
|
402
|
-
get status() {
|
|
403
|
-
return this.state.status;
|
|
404
|
-
}
|
|
405
|
-
get phase() {
|
|
406
|
-
return this.state.phase;
|
|
407
|
-
}
|
|
408
|
-
get nextAction() {
|
|
409
|
-
return this.state.nextAction;
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
var HavenSigningError = class extends HavenError {
|
|
413
|
-
constructor(message) {
|
|
414
|
-
super(message, "SIGNING_ERROR");
|
|
415
|
-
this.name = "HavenSigningError";
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
var HavenZeroSettlementHashError = class extends HavenError {
|
|
419
|
-
constructor(paymentId) {
|
|
420
|
-
super(
|
|
421
|
-
"settlement_tx_hash is the zero hash (0x00\u202600), which is never a real settlement transaction \u2014 refused before any report was sent.",
|
|
422
|
-
"ZERO_SETTLEMENT_HASH",
|
|
423
|
-
400,
|
|
424
|
-
paymentId
|
|
425
|
-
);
|
|
426
|
-
this.name = "HavenZeroSettlementHashError";
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
var SignerRefusalCode = {
|
|
430
|
-
/** `SUPPORTED_X402_EXPECTED_VERSIONS` in `@haven_ai/signer` does not include the received version. */
|
|
431
|
-
UnsupportedExpectedContextVersion: "UNSUPPORTED_EXPECTED_CONTEXT_VERSION",
|
|
432
|
-
/** `SUPPORTED_SWEEP_BINDING_VERSIONS` in `@haven_ai/signer` does not include the received version. */
|
|
433
|
-
UnsupportedSweepBindingVersion: "UNSUPPORTED_SWEEP_BINDING_VERSION"
|
|
434
|
-
};
|
|
435
|
-
function signerUpdateFallback(channel = HAVEN_CONNECTOR_CHANNEL) {
|
|
436
|
-
return `Update @haven_ai/signer by rerunning \`${connectorRerunCommand(void 0, { channel })}\`, which reinstalls the pinned MCP runtime, then retry the same signing call. Nothing was signed or spent \u2014 the quote or payment this version came from is unaffected and does not need to be re-quoted.`;
|
|
437
|
-
}
|
|
438
|
-
var SIGNER_UPDATE_FALLBACK = signerUpdateFallback();
|
|
439
|
-
var HavenUnsupportedSignerVersionError = class extends HavenError {
|
|
440
|
-
constructor(message, code, supportedVersions, receivedVersion, fallback) {
|
|
441
|
-
super(message, code);
|
|
442
|
-
this.supportedVersions = supportedVersions;
|
|
443
|
-
this.receivedVersion = receivedVersion;
|
|
444
|
-
this.fallback = fallback;
|
|
445
|
-
this.name = "HavenUnsupportedSignerVersionError";
|
|
446
|
-
}
|
|
447
|
-
supportedVersions;
|
|
448
|
-
receivedVersion;
|
|
449
|
-
fallback;
|
|
450
|
-
};
|
|
451
|
-
var HavenTimeoutError = class extends HavenError {
|
|
452
|
-
constructor(paymentId) {
|
|
453
|
-
super(
|
|
454
|
-
`Timed out waiting for payment ${paymentId} to confirm`,
|
|
455
|
-
"TIMEOUT",
|
|
456
|
-
void 0,
|
|
457
|
-
paymentId
|
|
458
|
-
);
|
|
459
|
-
this.name = "HavenTimeoutError";
|
|
460
|
-
}
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
// src/signer.ts
|
|
464
11
|
function signHash(privateKey, hash) {
|
|
465
12
|
try {
|
|
466
13
|
const signingKey = new ethers.ethers.SigningKey(privateKey);
|
|
467
14
|
const sig = signingKey.sign(hash);
|
|
468
15
|
return sig.serialized;
|
|
469
16
|
} catch (err) {
|
|
470
|
-
throw new HavenSigningError(
|
|
17
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
471
18
|
`Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`
|
|
472
19
|
);
|
|
473
20
|
}
|
|
@@ -483,7 +30,7 @@ async function signTypedDataVerbatim(privateKey, typedData, label) {
|
|
|
483
30
|
typedData.message
|
|
484
31
|
);
|
|
485
32
|
} catch (err) {
|
|
486
|
-
throw new HavenSigningError(
|
|
33
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
487
34
|
`Failed to sign ${label}: ${err instanceof Error ? err.message : String(err)}`
|
|
488
35
|
);
|
|
489
36
|
}
|
|
@@ -498,7 +45,7 @@ function addressFromKey(privateKey) {
|
|
|
498
45
|
try {
|
|
499
46
|
return new ethers.ethers.Wallet(privateKey).address;
|
|
500
47
|
} catch (err) {
|
|
501
|
-
throw new HavenSigningError(
|
|
48
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
502
49
|
`Invalid private key: ${err instanceof Error ? err.message : String(err)}`
|
|
503
50
|
);
|
|
504
51
|
}
|
|
@@ -511,632 +58,43 @@ function verifySignature(hash, signature, expectedAddress) {
|
|
|
511
58
|
return false;
|
|
512
59
|
}
|
|
513
60
|
}
|
|
514
|
-
|
|
515
|
-
// src/base64.ts
|
|
516
|
-
function normalizeBase64(value) {
|
|
517
|
-
const standard = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
518
|
-
const remainder = standard.length % 4;
|
|
519
|
-
return remainder === 0 ? standard : standard + "=".repeat(4 - remainder);
|
|
520
|
-
}
|
|
521
|
-
function encodeBase64Utf8(value) {
|
|
522
|
-
if (typeof Buffer !== "undefined") {
|
|
523
|
-
return Buffer.from(value, "utf8").toString("base64");
|
|
524
|
-
}
|
|
525
|
-
const bytes = new TextEncoder().encode(value);
|
|
526
|
-
let binary = "";
|
|
527
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
528
|
-
binary += String.fromCharCode(bytes[i]);
|
|
529
|
-
}
|
|
530
|
-
return btoa(binary);
|
|
531
|
-
}
|
|
532
|
-
function decodeBase64Utf8(value) {
|
|
533
|
-
const normalized = normalizeBase64(value);
|
|
534
|
-
if (typeof Buffer !== "undefined") {
|
|
535
|
-
return Buffer.from(normalized, "base64").toString("utf8");
|
|
536
|
-
}
|
|
537
|
-
const binary = atob(normalized);
|
|
538
|
-
const bytes = new Uint8Array(binary.length);
|
|
539
|
-
for (let i = 0; i < binary.length; i++) {
|
|
540
|
-
bytes[i] = binary.charCodeAt(i);
|
|
541
|
-
}
|
|
542
|
-
return new TextDecoder().decode(bytes);
|
|
543
|
-
}
|
|
544
|
-
function encodeBase64Json(value) {
|
|
545
|
-
return encodeBase64Utf8(JSON.stringify(value));
|
|
546
|
-
}
|
|
547
|
-
function decodeBase64Json(value, label) {
|
|
548
|
-
try {
|
|
549
|
-
return JSON.parse(decodeBase64Utf8(value));
|
|
550
|
-
} catch (err) {
|
|
551
|
-
if (label) throw new Error(`Failed to decode ${label}`);
|
|
552
|
-
throw err;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// src/sweep.ts
|
|
557
|
-
var SWEEP_BASE_CHAIN_ID = 8453;
|
|
558
|
-
var SWEEP_BASE_SEPOLIA_CHAIN_ID = 84532;
|
|
559
|
-
var SWEEP_BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
560
|
-
var SWEEP_BASE_SEPOLIA_USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
|
|
561
|
-
var USDC_EIP712_DOMAIN_BY_CHAIN = {
|
|
562
|
-
[SWEEP_BASE_CHAIN_ID]: {
|
|
563
|
-
name: "USD Coin",
|
|
564
|
-
version: "2",
|
|
565
|
-
chainId: SWEEP_BASE_CHAIN_ID,
|
|
566
|
-
verifyingContract: SWEEP_BASE_USDC_ADDRESS
|
|
567
|
-
},
|
|
568
|
-
[SWEEP_BASE_SEPOLIA_CHAIN_ID]: {
|
|
569
|
-
name: "USDC",
|
|
570
|
-
version: "2",
|
|
571
|
-
chainId: SWEEP_BASE_SEPOLIA_CHAIN_ID,
|
|
572
|
-
verifyingContract: SWEEP_BASE_SEPOLIA_USDC_ADDRESS
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
var USDC_ADDRESS_BY_CHAIN = {
|
|
576
|
-
[SWEEP_BASE_CHAIN_ID]: SWEEP_BASE_USDC_ADDRESS,
|
|
577
|
-
[SWEEP_BASE_SEPOLIA_CHAIN_ID]: SWEEP_BASE_SEPOLIA_USDC_ADDRESS
|
|
578
|
-
};
|
|
579
|
-
var SWEEPABLE_CHAIN_IDS = Object.keys(USDC_ADDRESS_BY_CHAIN).map(Number);
|
|
580
|
-
function isSweepableChain(chainId) {
|
|
581
|
-
return chainId in USDC_ADDRESS_BY_CHAIN;
|
|
582
|
-
}
|
|
583
|
-
var TRANSFER_WITH_AUTHORIZATION_TYPES = {
|
|
584
|
-
TransferWithAuthorization: [
|
|
585
|
-
{ name: "from", type: "address" },
|
|
586
|
-
{ name: "to", type: "address" },
|
|
587
|
-
{ name: "value", type: "uint256" },
|
|
588
|
-
{ name: "validAfter", type: "uint256" },
|
|
589
|
-
{ name: "validBefore", type: "uint256" },
|
|
590
|
-
{ name: "nonce", type: "bytes32" }
|
|
591
|
-
]
|
|
592
|
-
};
|
|
593
|
-
function sweepUsdcAddress(chainId) {
|
|
594
|
-
const address = USDC_ADDRESS_BY_CHAIN[chainId];
|
|
595
|
-
if (!address) {
|
|
596
|
-
throw new HavenSigningError(
|
|
597
|
-
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
598
|
-
);
|
|
599
|
-
}
|
|
600
|
-
return address;
|
|
601
|
-
}
|
|
602
|
-
function sweepUsdcDomain(chainId) {
|
|
603
|
-
const domain = USDC_EIP712_DOMAIN_BY_CHAIN[chainId];
|
|
604
|
-
if (!domain) {
|
|
605
|
-
throw new HavenSigningError(
|
|
606
|
-
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
607
|
-
);
|
|
608
|
-
}
|
|
609
|
-
return domain;
|
|
610
|
-
}
|
|
611
|
-
function sameAddress(a, b) {
|
|
612
|
-
return a.toLowerCase() === b.toLowerCase();
|
|
613
|
-
}
|
|
614
|
-
function buildSweepTypedData(auth) {
|
|
615
|
-
const domain = sweepUsdcDomain(auth.chainId);
|
|
616
|
-
const expectedToken = sweepUsdcAddress(auth.chainId);
|
|
617
|
-
if (!sameAddress(auth.token, expectedToken)) {
|
|
618
|
-
throw new HavenSigningError(
|
|
619
|
-
`Sweep token ${auth.token} is not the canonical USDC contract for chain ${auth.chainId}.`
|
|
620
|
-
);
|
|
621
|
-
}
|
|
622
|
-
if (!/^0x[0-9a-fA-F]{64}$/.test(auth.nonce)) {
|
|
623
|
-
throw new HavenSigningError("Sweep nonce must be a 0x-prefixed 32-byte hex string.");
|
|
624
|
-
}
|
|
625
|
-
return {
|
|
626
|
-
domain,
|
|
627
|
-
types: TRANSFER_WITH_AUTHORIZATION_TYPES,
|
|
628
|
-
primaryType: "TransferWithAuthorization",
|
|
629
|
-
message: {
|
|
630
|
-
from: auth.from,
|
|
631
|
-
to: auth.to,
|
|
632
|
-
value: BigInt(auth.value),
|
|
633
|
-
validAfter: BigInt(auth.validAfter),
|
|
634
|
-
validBefore: BigInt(auth.validBefore),
|
|
635
|
-
nonce: auth.nonce
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
function buildSweepAuthorizationMessage(auth) {
|
|
640
|
-
return `Haven sweep authorization v1
|
|
641
|
-
${stableStringify({
|
|
642
|
-
version: 1,
|
|
643
|
-
kind: "haven.sweep.authorization",
|
|
644
|
-
from: auth.from.toLowerCase(),
|
|
645
|
-
to: auth.to.toLowerCase(),
|
|
646
|
-
value: auth.value,
|
|
647
|
-
validAfter: auth.validAfter,
|
|
648
|
-
validBefore: auth.validBefore,
|
|
649
|
-
nonce: auth.nonce.toLowerCase(),
|
|
650
|
-
token: auth.token.toLowerCase(),
|
|
651
|
-
chainId: auth.chainId
|
|
652
|
-
})}`;
|
|
653
|
-
}
|
|
654
|
-
function stableStringify(value) {
|
|
655
|
-
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
656
|
-
if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
657
|
-
const object = value;
|
|
658
|
-
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// src/x402.ts
|
|
662
|
-
var BASE_USDC_ADDRESS = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
663
|
-
var BASE_SEPOLIA_USDC_ADDRESS = "0x036cbd53842c5426634e7929541ec2318f3dcf7e";
|
|
664
|
-
var STANDARD_X402_USDC_ADDRESSES = /* @__PURE__ */ new Set([BASE_USDC_ADDRESS, BASE_SEPOLIA_USDC_ADDRESS]);
|
|
665
|
-
var X402_IDEMPOTENCY_BUCKET_MS = 3e5;
|
|
666
|
-
var DECIMAL_ATOMIC_AMOUNT_RE = /^[0-9]+$/;
|
|
667
|
-
var X402_PAYMENT_HEADER_MAX_LENGTH = 65536;
|
|
668
|
-
var BASE64_RE = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
669
|
-
var ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
670
|
-
var SIGNATURE_RE = /^0x[0-9a-fA-F]{130}$/;
|
|
671
|
-
var NONCE_RE = /^0x[0-9a-fA-F]{64}$/;
|
|
672
|
-
var X402PaymentHeaderValidationError = class extends Error {
|
|
673
|
-
constructor() {
|
|
674
|
-
super("Invalid X-PAYMENT header.");
|
|
675
|
-
this.name = "X402PaymentHeaderValidationError";
|
|
676
|
-
}
|
|
677
|
-
};
|
|
678
|
-
function isPositiveDecimalAtomicAmount(value) {
|
|
679
|
-
return DECIMAL_ATOMIC_AMOUNT_RE.test(value) && BigInt(value) > 0n;
|
|
680
|
-
}
|
|
681
|
-
function optionAuthorizationAmount(option) {
|
|
682
|
-
return option.maxAmountRequired ?? option.amount;
|
|
683
|
-
}
|
|
684
|
-
var X402_MAX_AUTHORIZATION_WINDOW_SECONDS = 600;
|
|
685
|
-
var X402_SETTLEMENT_FORWARD_MARGIN_SECONDS = 300;
|
|
686
|
-
function clampAuthorizationWindow(seconds) {
|
|
687
|
-
const requested = typeof seconds === "number" && Number.isFinite(seconds) ? seconds : 30;
|
|
688
|
-
return Math.min(Math.max(Math.floor(requested), 1), X402_MAX_AUTHORIZATION_WINDOW_SECONDS);
|
|
689
|
-
}
|
|
690
|
-
function normalizePaymentOption(value) {
|
|
691
|
-
const candidate = value;
|
|
692
|
-
if (!candidate || typeof candidate !== "object" || typeof candidate.scheme !== "string" || typeof candidate.network !== "string" || typeof candidate.asset !== "string" || typeof candidate.payTo !== "string") {
|
|
693
|
-
return null;
|
|
694
|
-
}
|
|
695
|
-
const amount = typeof candidate.amount === "string" ? candidate.amount : typeof candidate.maxAmountRequired === "string" ? candidate.maxAmountRequired : null;
|
|
696
|
-
if (!amount) return null;
|
|
697
|
-
if (!isPositiveDecimalAtomicAmount(amount)) return null;
|
|
698
|
-
if (candidate.maxAmountRequired !== void 0 && (typeof candidate.maxAmountRequired !== "string" || !isPositiveDecimalAtomicAmount(candidate.maxAmountRequired))) {
|
|
699
|
-
return null;
|
|
700
|
-
}
|
|
701
|
-
return {
|
|
702
|
-
scheme: candidate.scheme,
|
|
703
|
-
network: candidate.network,
|
|
704
|
-
amount,
|
|
705
|
-
maxAmountRequired: candidate.maxAmountRequired,
|
|
706
|
-
resource: candidate.resource,
|
|
707
|
-
description: candidate.description,
|
|
708
|
-
mimeType: candidate.mimeType,
|
|
709
|
-
asset: candidate.asset,
|
|
710
|
-
payTo: candidate.payTo,
|
|
711
|
-
// Keep the merchant offer intact for v2 `accepted` matching. Only the
|
|
712
|
-
// signing conversion may cap its authorization lifetime (#3117).
|
|
713
|
-
// Retain legacy fallback behavior for missing or unusable timeouts.
|
|
714
|
-
// Integer, because the authorize body types it `integer` and the child's
|
|
715
|
-
// timestamp caveat is built from it — the old clamp floored, so keeping a
|
|
716
|
-
// fractional value here would 400 a merchant that used to work (#3117).
|
|
717
|
-
maxTimeoutSeconds: typeof candidate.maxTimeoutSeconds === "number" && Number.isFinite(candidate.maxTimeoutSeconds) && candidate.maxTimeoutSeconds >= 1 ? Math.floor(candidate.maxTimeoutSeconds) : clampAuthorizationWindow(candidate.maxTimeoutSeconds),
|
|
718
|
-
extra: candidate.extra
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
function normalizePaymentRequired(value) {
|
|
722
|
-
const candidate = value;
|
|
723
|
-
if (!candidate || typeof candidate !== "object" || typeof candidate.x402Version !== "number" || !Array.isArray(candidate.accepts)) {
|
|
724
|
-
return null;
|
|
725
|
-
}
|
|
726
|
-
const accepts = candidate.accepts.map((option) => normalizePaymentOption(option)).filter((option) => !!option && typeof option === "object");
|
|
727
|
-
if (accepts.length === 0) return null;
|
|
728
|
-
const first = accepts[0];
|
|
729
|
-
const resourceUrl = candidate.resource?.url ?? first.resource;
|
|
730
|
-
if (!resourceUrl) return null;
|
|
731
|
-
const resource = {
|
|
732
|
-
...candidate.resource && typeof candidate.resource === "object" ? candidate.resource : {},
|
|
733
|
-
url: resourceUrl,
|
|
734
|
-
description: candidate.resource?.description ?? first.description,
|
|
735
|
-
mimeType: candidate.resource?.mimeType ?? first.mimeType
|
|
736
|
-
};
|
|
737
|
-
return {
|
|
738
|
-
x402Version: candidate.x402Version,
|
|
739
|
-
resource,
|
|
740
|
-
accepts,
|
|
741
|
-
error: candidate.error,
|
|
742
|
-
...candidate.extensions && typeof candidate.extensions === "object" ? { extensions: candidate.extensions } : {}
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
var SUPPORTED_X402_NETWORKS = {
|
|
746
|
-
"eip155:100": "Gnosis Chain",
|
|
747
|
-
"eip155:8453": "Base",
|
|
748
|
-
"base": "Base",
|
|
749
|
-
"eip155:84532": "Base Sepolia",
|
|
750
|
-
"base-sepolia": "Base Sepolia"
|
|
751
|
-
};
|
|
752
|
-
var STANDARD_X402_NETWORKS = {
|
|
753
|
-
"eip155:8453": "base",
|
|
754
|
-
"base": "base",
|
|
755
|
-
"eip155:84532": "base-sepolia",
|
|
756
|
-
"base-sepolia": "base-sepolia"
|
|
757
|
-
};
|
|
758
|
-
var GNOSIS_TOKENS = {
|
|
759
|
-
"0x0000000000000000000000000000000000000000": { symbol: "xDAI", decimals: 18 },
|
|
760
|
-
"0xcb444e90d8198415266c6a2724b7900fb12fc56e": { symbol: "EURe", decimals: 18 },
|
|
761
|
-
"0x2a22f9c3b484c3629090feed35f17ff8f88f76f0": { symbol: "USDC.e", decimals: 6 }
|
|
762
|
-
};
|
|
763
|
-
var BASE_TOKENS = {
|
|
764
|
-
"0x0000000000000000000000000000000000000000": { symbol: "ETH", decimals: 18 },
|
|
765
|
-
"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913": { symbol: "USDC", decimals: 6 }
|
|
766
|
-
};
|
|
767
|
-
var BASE_SEPOLIA_TOKENS = {
|
|
768
|
-
"0x0000000000000000000000000000000000000000": { symbol: "ETH", decimals: 18 },
|
|
769
|
-
"0x036cbd53842c5426634e7929541ec2318f3dcf7e": { symbol: "USDC", decimals: 6 }
|
|
770
|
-
};
|
|
771
|
-
var ALL_TOKENS = {
|
|
772
|
-
...GNOSIS_TOKENS,
|
|
773
|
-
...BASE_TOKENS,
|
|
774
|
-
...BASE_SEPOLIA_TOKENS
|
|
775
|
-
};
|
|
776
|
-
var NETWORK_TOKENS = {
|
|
777
|
-
"eip155:100": GNOSIS_TOKENS,
|
|
778
|
-
"eip155:8453": BASE_TOKENS,
|
|
779
|
-
"base": BASE_TOKENS,
|
|
780
|
-
"eip155:84532": BASE_SEPOLIA_TOKENS,
|
|
781
|
-
"base-sepolia": BASE_SEPOLIA_TOKENS
|
|
782
|
-
};
|
|
783
|
-
var X402_PAYMENT_HEADER_NAME = "PAYMENT-SIGNATURE";
|
|
784
|
-
var X402_LEGACY_PAYMENT_HEADER_NAME = "X-PAYMENT";
|
|
785
|
-
var X402_PAYMENT_REQUIRED_HEADER_NAME = "PAYMENT-REQUIRED";
|
|
786
|
-
var X402_PAYMENT_RESPONSE_HEADER_NAME = "PAYMENT-RESPONSE";
|
|
787
|
-
var X402_PAYMENT_HEADER_NAMES_SENT = `${X402_PAYMENT_HEADER_NAME}, ${X402_LEGACY_PAYMENT_HEADER_NAME}`;
|
|
788
|
-
var X402_PAYMENT_HEADER_NAMES = [
|
|
789
|
-
X402_PAYMENT_HEADER_NAME,
|
|
790
|
-
X402_LEGACY_PAYMENT_HEADER_NAME
|
|
791
|
-
];
|
|
792
|
-
function x402PaymentHeaderNamesFor(paymentHeader) {
|
|
793
|
-
const both = [X402_PAYMENT_HEADER_NAME, X402_LEGACY_PAYMENT_HEADER_NAME];
|
|
794
|
-
let decoded;
|
|
795
|
-
try {
|
|
796
|
-
decoded = decodeBase64Json(paymentHeader);
|
|
797
|
-
} catch {
|
|
798
|
-
return both;
|
|
799
|
-
}
|
|
800
|
-
const accepted = decoded?.accepted;
|
|
801
|
-
if (!accepted || typeof accepted !== "object" || Array.isArray(accepted)) return both;
|
|
802
|
-
return isErc7710Option(accepted) ? [X402_PAYMENT_HEADER_NAME] : both;
|
|
803
|
-
}
|
|
804
|
-
function x402PaymentHeaderNamesSent(paymentHeader) {
|
|
805
|
-
return x402PaymentHeaderNamesFor(paymentHeader).join(", ");
|
|
806
|
-
}
|
|
807
|
-
function x402V2PaymentEnvelope(paymentRequired, accepted, payload) {
|
|
808
|
-
const resource = paymentRequired.resource;
|
|
809
|
-
const extensions = paymentRequired.extensions;
|
|
810
|
-
return {
|
|
811
|
-
x402Version: paymentRequired.x402Version,
|
|
812
|
-
...resource && typeof resource === "object" && !Array.isArray(resource) ? { resource } : {},
|
|
813
|
-
accepted,
|
|
814
|
-
payload,
|
|
815
|
-
...extensions && typeof extensions === "object" && !Array.isArray(extensions) ? { extensions } : {}
|
|
816
|
-
};
|
|
817
|
-
}
|
|
818
|
-
function parsePaymentRequired(response) {
|
|
819
|
-
const v2Header = response.headers.get("PAYMENT-REQUIRED");
|
|
820
|
-
if (v2Header) {
|
|
821
|
-
const parsed = normalizePaymentRequired(
|
|
822
|
-
decodeBase64Json(v2Header, "PAYMENT-REQUIRED header")
|
|
823
|
-
);
|
|
824
|
-
if (parsed) return parsed;
|
|
825
|
-
}
|
|
826
|
-
const v1Header = response.headers.get("X-PAYMENT");
|
|
827
|
-
if (v1Header) {
|
|
828
|
-
const parsed = normalizePaymentRequired(
|
|
829
|
-
decodeBase64Json(v1Header, "X-PAYMENT header")
|
|
830
|
-
);
|
|
831
|
-
if (parsed) return parsed;
|
|
832
|
-
}
|
|
833
|
-
throw new Error(
|
|
834
|
-
"No x402 payment headers found in 402 response. Expected PAYMENT-REQUIRED (v2) or X-PAYMENT (v1) header."
|
|
835
|
-
);
|
|
836
|
-
}
|
|
837
|
-
async function parsePaymentRequiredResponse(response) {
|
|
838
|
-
try {
|
|
839
|
-
return parsePaymentRequired(response);
|
|
840
|
-
} catch (headerErr) {
|
|
841
|
-
try {
|
|
842
|
-
const body = await response.clone().json();
|
|
843
|
-
const parsed = normalizePaymentRequired(body);
|
|
844
|
-
if (parsed) return parsed;
|
|
845
|
-
} catch {
|
|
846
|
-
}
|
|
847
|
-
throw headerErr;
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
function selectPaymentOption(accepts) {
|
|
851
|
-
if (!accepts || accepts.length === 0) return null;
|
|
852
|
-
for (const opt of accepts) {
|
|
853
|
-
if (opt.network in SUPPORTED_X402_NETWORKS) {
|
|
854
|
-
const networkTokens = NETWORK_TOKENS[opt.network];
|
|
855
|
-
if (networkTokens?.[opt.asset.toLowerCase()] && isPositiveDecimalAtomicAmount(optionAuthorizationAmount(opt))) {
|
|
856
|
-
return opt;
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
for (const opt of accepts) {
|
|
861
|
-
if (opt.network in SUPPORTED_X402_NETWORKS && isPositiveDecimalAtomicAmount(optionAuthorizationAmount(opt))) {
|
|
862
|
-
return opt;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
return null;
|
|
866
|
-
}
|
|
867
|
-
var ERC7710_ASSET_TRANSFER_METHOD = "erc7710";
|
|
868
|
-
function isEip3009ConstructibleOption(option) {
|
|
869
|
-
const rawMethod = option.extra?.assetTransferMethod;
|
|
870
|
-
if (rawMethod !== void 0 && rawMethod !== "eip3009") return false;
|
|
871
|
-
const rawFlow = option.extra?.paymentFlow;
|
|
872
|
-
if (rawFlow !== void 0 && rawFlow !== "authorization") return false;
|
|
873
|
-
return true;
|
|
874
|
-
}
|
|
875
|
-
function x402AssetTransferMethod(option) {
|
|
876
|
-
const raw = option.extra?.assetTransferMethod;
|
|
877
|
-
return typeof raw === "string" ? raw : null;
|
|
878
|
-
}
|
|
879
|
-
function isErc7710Option(option) {
|
|
880
|
-
return x402AssetTransferMethod(option) === ERC7710_ASSET_TRANSFER_METHOD;
|
|
881
|
-
}
|
|
882
|
-
function x402FacilitatorAddresses(option) {
|
|
883
|
-
const raw = option.extra?.facilitatorAddresses;
|
|
884
|
-
if (!Array.isArray(raw)) return null;
|
|
885
|
-
const addresses = raw.filter((a) => typeof a === "string" && ADDRESS_RE.test(a));
|
|
886
|
-
return addresses.length > 0 ? addresses : null;
|
|
887
|
-
}
|
|
888
|
-
function isPayableStandardOption(opt) {
|
|
889
|
-
return opt.scheme === "exact" && opt.network in STANDARD_X402_NETWORKS && STANDARD_X402_USDC_ADDRESSES.has(opt.asset.toLowerCase()) && isPositiveDecimalAtomicAmount(optionAuthorizationAmount(opt));
|
|
890
|
-
}
|
|
891
|
-
function selectStandardPaymentOption(accepts) {
|
|
892
|
-
if (!accepts || accepts.length === 0) return null;
|
|
893
|
-
for (const opt of accepts) {
|
|
894
|
-
if (opt === null || typeof opt !== "object") continue;
|
|
895
|
-
if (!isEip3009ConstructibleOption(opt)) continue;
|
|
896
|
-
if (isPayableStandardOption(opt)) return opt;
|
|
897
|
-
}
|
|
898
|
-
return null;
|
|
899
|
-
}
|
|
900
|
-
function selectErc7710PaymentOption(accepts) {
|
|
901
|
-
if (!accepts || accepts.length === 0) return null;
|
|
902
|
-
for (const opt of accepts) {
|
|
903
|
-
if (opt === null || typeof opt !== "object") continue;
|
|
904
|
-
if (isErc7710Option(opt) && isPayableStandardOption(opt)) return opt;
|
|
905
|
-
if (!isEip3009ConstructibleOption(opt)) continue;
|
|
906
|
-
}
|
|
907
|
-
return null;
|
|
908
|
-
}
|
|
909
|
-
function selectX402SettlementScheme(accepts, opts) {
|
|
910
|
-
if (opts.delegationRail) {
|
|
911
|
-
const preferred = selectErc7710PaymentOption(accepts);
|
|
912
|
-
if (preferred) {
|
|
913
|
-
return {
|
|
914
|
-
scheme: "erc7710",
|
|
915
|
-
option: preferred,
|
|
916
|
-
facilitatorAddresses: x402FacilitatorAddresses(preferred)
|
|
917
|
-
};
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
const fallback = selectStandardPaymentOption(accepts);
|
|
921
|
-
if (fallback) return { scheme: "eip3009", option: fallback, facilitatorAddresses: null };
|
|
922
|
-
return null;
|
|
923
|
-
}
|
|
924
|
-
function x402AuthorizationAmount(option) {
|
|
925
|
-
const amount = optionAuthorizationAmount(option);
|
|
926
|
-
if (!isPositiveDecimalAtomicAmount(amount)) {
|
|
927
|
-
throw new Error("Invalid x402 amount: must be a positive decimal atomic amount");
|
|
928
|
-
}
|
|
929
|
-
return amount;
|
|
930
|
-
}
|
|
931
|
-
function buildX402ExpectedMessage(context) {
|
|
932
|
-
const version = context.payerDelegate ? 3 : context.typedDataHash ? 2 : 1;
|
|
933
|
-
const payload = {
|
|
934
|
-
version,
|
|
935
|
-
kind: "haven.x402.expected",
|
|
936
|
-
paymentId: context.paymentId,
|
|
937
|
-
payloadHash: context.payloadHash.toLowerCase(),
|
|
938
|
-
resourceUrl: context.resourceUrl,
|
|
939
|
-
merchantTo: context.merchantTo.toLowerCase(),
|
|
940
|
-
amount: context.amount,
|
|
941
|
-
asset: context.asset.toLowerCase(),
|
|
942
|
-
network: context.network
|
|
943
|
-
};
|
|
944
|
-
if (context.expiresAt) {
|
|
945
|
-
payload.expiresAt = context.expiresAt;
|
|
946
|
-
}
|
|
947
|
-
if (context.typedDataHash) {
|
|
948
|
-
payload.typedDataHash = context.typedDataHash.toLowerCase();
|
|
949
|
-
}
|
|
950
|
-
if (context.payerDelegate) {
|
|
951
|
-
payload.payerDelegate = context.payerDelegate.toLowerCase();
|
|
952
|
-
if (context.payerAgentId) {
|
|
953
|
-
payload.payerAgentId = context.payerAgentId;
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
return `Haven x402 expected context v${version}
|
|
957
|
-
${stableStringify2(payload)}`;
|
|
958
|
-
}
|
|
959
|
-
function toStandardPaymentRequirements(paymentRequired, option) {
|
|
960
|
-
const network = STANDARD_X402_NETWORKS[option.network];
|
|
961
|
-
if (!network) {
|
|
962
|
-
throw new Error(`x402 exact payments are not supported on ${option.network}`);
|
|
963
|
-
}
|
|
964
|
-
if (option.scheme !== "exact") {
|
|
965
|
-
throw new Error(`Unsupported x402 scheme: ${option.scheme}`);
|
|
966
|
-
}
|
|
967
|
-
if (!isEip3009ConstructibleOption(option)) {
|
|
968
|
-
throw new Error(
|
|
969
|
-
"Unsupported x402 payment requirements: this SDK constructs EIP-3009 authorization payments only. The merchant advertised a different extra.assetTransferMethod or an unrecognized extra.paymentFlow."
|
|
970
|
-
);
|
|
971
|
-
}
|
|
972
|
-
return {
|
|
973
|
-
scheme: "exact",
|
|
974
|
-
network,
|
|
975
|
-
maxAmountRequired: x402AuthorizationAmount(option),
|
|
976
|
-
resource: option.resource ?? paymentRequired.resource.url,
|
|
977
|
-
description: option.description ?? paymentRequired.resource.description ?? "Haven x402 payment",
|
|
978
|
-
mimeType: option.mimeType ?? paymentRequired.resource.mimeType ?? "application/octet-stream",
|
|
979
|
-
payTo: option.payTo,
|
|
980
|
-
asset: option.asset,
|
|
981
|
-
// Signing-only policy (#715/#3117): parsed and directly supplied options
|
|
982
|
-
// share this cap before the library computes validBefore. Keep the offer
|
|
983
|
-
// echoed in `accepted` unchanged. The forward margin (#1256) adds time
|
|
984
|
-
// for funding/retry, but does not guarantee a merchant timeout above the
|
|
985
|
-
// total bounded lifetime can pass facilitator verification.
|
|
986
|
-
maxTimeoutSeconds: clampAuthorizationWindow(option.maxTimeoutSeconds) + X402_SETTLEMENT_FORWARD_MARGIN_SECONDS,
|
|
987
|
-
extra: option.extra
|
|
988
|
-
};
|
|
989
|
-
}
|
|
990
|
-
async function validateStandardX402PaymentHeader(paymentHeader, context) {
|
|
991
|
-
try {
|
|
992
|
-
if (typeof paymentHeader !== "string" || paymentHeader.length === 0 || paymentHeader.length > X402_PAYMENT_HEADER_MAX_LENGTH || paymentHeader.length % 4 !== 0 || !BASE64_RE.test(paymentHeader)) {
|
|
993
|
-
throw new Error("wire");
|
|
994
|
-
}
|
|
995
|
-
const decoded = decodeBase64Json(paymentHeader);
|
|
996
|
-
if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) throw new Error("shape");
|
|
997
|
-
const version = decoded.x402Version;
|
|
998
|
-
const payload = decoded.payload;
|
|
999
|
-
if (version !== 1 && version !== 2 || !payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1000
|
-
throw new Error("shape");
|
|
1001
|
-
}
|
|
1002
|
-
if (version === 1) {
|
|
1003
|
-
if (!hasOnlyKeys(decoded, ["x402Version", "scheme", "network", "payload"])) throw new Error("shape");
|
|
1004
|
-
if (decoded.scheme !== "exact" || decoded.network !== standardX402WireNetwork(context.network)) {
|
|
1005
|
-
throw new Error("context");
|
|
1006
|
-
}
|
|
1007
|
-
} else {
|
|
1008
|
-
if (!hasOnlyKeys(decoded, ["x402Version", "accepted", "payload"], ["resource", "extensions"])) {
|
|
1009
|
-
throw new Error("shape");
|
|
1010
|
-
}
|
|
1011
|
-
if ("resource" in decoded && (!decoded.resource || typeof decoded.resource !== "object" || Array.isArray(decoded.resource))) {
|
|
1012
|
-
throw new Error("shape");
|
|
1013
|
-
}
|
|
1014
|
-
if ("extensions" in decoded && (!decoded.extensions || typeof decoded.extensions !== "object" || Array.isArray(decoded.extensions))) {
|
|
1015
|
-
throw new Error("shape");
|
|
1016
|
-
}
|
|
1017
|
-
const accepted = selectStandardPaymentOption([decoded.accepted]);
|
|
1018
|
-
if (!accepted || !matchesHeaderContext(accepted, context)) throw new Error("context");
|
|
1019
|
-
}
|
|
1020
|
-
const record = payload;
|
|
1021
|
-
if (!hasOnlyKeys(record, ["signature", "authorization"])) throw new Error("shape");
|
|
1022
|
-
if (typeof record.signature !== "string" || !SIGNATURE_RE.test(record.signature)) throw new Error("shape");
|
|
1023
|
-
const authorization = record.authorization;
|
|
1024
|
-
if (!authorization || typeof authorization !== "object" || Array.isArray(authorization)) throw new Error("shape");
|
|
1025
|
-
const auth = authorization;
|
|
1026
|
-
if (!hasOnlyKeys(auth, ["from", "to", "value", "validAfter", "validBefore", "nonce"])) throw new Error("shape");
|
|
1027
|
-
if (typeof auth.from !== "string" || !ADDRESS_RE.test(auth.from) || typeof auth.to !== "string" || !ADDRESS_RE.test(auth.to) || typeof auth.value !== "string" || !isPositiveDecimalAtomicAmount(auth.value) || typeof auth.validAfter !== "string" || !DECIMAL_ATOMIC_AMOUNT_RE.test(auth.validAfter) || typeof auth.validBefore !== "string" || !DECIMAL_ATOMIC_AMOUNT_RE.test(auth.validBefore) || typeof auth.nonce !== "string" || !NONCE_RE.test(auth.nonce)) {
|
|
1028
|
-
throw new Error("shape");
|
|
1029
|
-
}
|
|
1030
|
-
if (!sameAddress2(auth.from, context.payer) || !sameAddress2(auth.to, context.merchantTo) || auth.value !== context.amountAtomic) {
|
|
1031
|
-
throw new Error("context");
|
|
1032
|
-
}
|
|
1033
|
-
const validAfter = BigInt(auth.validAfter);
|
|
1034
|
-
const validBefore = BigInt(auth.validBefore);
|
|
1035
|
-
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
1036
|
-
if (validBefore <= now || validAfter > validBefore) throw new Error("expired");
|
|
1037
|
-
const typedData = buildSweepTypedData({
|
|
1038
|
-
from: auth.from,
|
|
1039
|
-
to: auth.to,
|
|
1040
|
-
value: auth.value,
|
|
1041
|
-
validAfter: auth.validAfter,
|
|
1042
|
-
validBefore: auth.validBefore,
|
|
1043
|
-
nonce: auth.nonce,
|
|
1044
|
-
token: context.asset,
|
|
1045
|
-
chainId: context.chainId
|
|
1046
|
-
});
|
|
1047
|
-
const recovered = await viem.recoverTypedDataAddress({
|
|
1048
|
-
...typedData,
|
|
1049
|
-
// `buildSweepTypedData` keeps the public domain framework-neutral;
|
|
1050
|
-
// viem brands contract addresses at this crypto call boundary only.
|
|
1051
|
-
domain: {
|
|
1052
|
-
...typedData.domain,
|
|
1053
|
-
verifyingContract: typedData.domain.verifyingContract
|
|
1054
|
-
},
|
|
1055
|
-
message: {
|
|
1056
|
-
...typedData.message,
|
|
1057
|
-
from: typedData.message.from,
|
|
1058
|
-
to: typedData.message.to,
|
|
1059
|
-
nonce: typedData.message.nonce
|
|
1060
|
-
},
|
|
1061
|
-
signature: record.signature
|
|
1062
|
-
});
|
|
1063
|
-
if (!sameAddress2(recovered, context.payer)) throw new Error("recovery");
|
|
1064
|
-
} catch {
|
|
1065
|
-
throw new X402PaymentHeaderValidationError();
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
function hasOnlyKeys(value, required, optional = []) {
|
|
1069
|
-
return Object.keys(value).every((key) => required.includes(key) || optional.includes(key)) && required.every((key) => key in value);
|
|
1070
|
-
}
|
|
1071
|
-
function sameAddress2(left, right) {
|
|
1072
|
-
return left.toLowerCase() === right.toLowerCase();
|
|
1073
|
-
}
|
|
1074
|
-
function standardX402WireNetwork(network) {
|
|
1075
|
-
return STANDARD_X402_NETWORKS[network] ?? null;
|
|
1076
|
-
}
|
|
1077
|
-
function matchesHeaderContext(option, context) {
|
|
1078
|
-
if (option.scheme !== "exact" || !sameAddress2(option.payTo, context.merchantTo) || !sameAddress2(option.asset, context.asset) || option.network !== context.network || x402AuthorizationAmount(option) !== context.amountAtomic) return false;
|
|
1079
|
-
return option.resource === void 0 || option.resource === context.resourceUrl;
|
|
1080
|
-
}
|
|
1081
|
-
function buildX402IdempotencyKey(paymentRequired, option, now = Date.now()) {
|
|
1082
|
-
const bucket = Math.floor(now / X402_IDEMPOTENCY_BUCKET_MS);
|
|
1083
|
-
const material = [
|
|
1084
|
-
paymentRequired.resource.url,
|
|
1085
|
-
paymentRequired.resource.description ?? "",
|
|
1086
|
-
option.payTo.toLowerCase(),
|
|
1087
|
-
option.asset.toLowerCase(),
|
|
1088
|
-
x402AuthorizationAmount(option),
|
|
1089
|
-
option.network,
|
|
1090
|
-
bucket
|
|
1091
|
-
].join("|");
|
|
1092
|
-
return `x402:${crypto.createHash("sha256").update(material).digest("hex").slice(0, 16)}`;
|
|
1093
|
-
}
|
|
1094
|
-
function encodePaymentProof(receipt) {
|
|
1095
|
-
const payload = {
|
|
1096
|
-
x402Version: 2,
|
|
1097
|
-
resource: receipt.resourceUrl ? { url: receipt.resourceUrl } : void 0,
|
|
1098
|
-
accepted: receipt.accepted,
|
|
1099
|
-
payload: {
|
|
1100
|
-
type: "haven_tx_hash",
|
|
1101
|
-
txHash: receipt.txHash,
|
|
1102
|
-
paymentId: receipt.paymentId,
|
|
1103
|
-
settledVia: "haven",
|
|
1104
|
-
payer: receipt.payer,
|
|
1105
|
-
chainId: receipt.chainId
|
|
1106
|
-
}
|
|
1107
|
-
};
|
|
1108
|
-
return encodeBase64Json(payload);
|
|
1109
|
-
}
|
|
1110
|
-
function resolveTokenFromAddress(address, network) {
|
|
1111
|
-
const lower = address.toLowerCase();
|
|
1112
|
-
if (network && network in NETWORK_TOKENS) {
|
|
1113
|
-
return NETWORK_TOKENS[network][lower] ?? null;
|
|
1114
|
-
}
|
|
1115
|
-
return ALL_TOKENS[lower] ?? null;
|
|
1116
|
-
}
|
|
1117
|
-
function stableStringify2(value) {
|
|
1118
|
-
if (value === null || typeof value !== "object") {
|
|
1119
|
-
const primitive = JSON.stringify(value);
|
|
1120
|
-
return primitive === void 0 ? "undefined" : primitive;
|
|
1121
|
-
}
|
|
1122
|
-
if (value instanceof Date) return JSON.stringify(value.toISOString());
|
|
1123
|
-
if (Array.isArray(value)) return `[${value.map((item) => stableStringify2(item)).join(",")}]`;
|
|
1124
|
-
const object = value;
|
|
1125
|
-
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(object[key])}`).join(",")}}`;
|
|
1126
|
-
}
|
|
1127
61
|
var DEFAULT_BASE_URL = "http://localhost:3001";
|
|
1128
62
|
var DEFAULT_REQUEST_TIMEOUT = 3e4;
|
|
63
|
+
function withoutClientHeader(headers) {
|
|
64
|
+
const target = chunkCK4NLLMO_cjs.HAVEN_CLIENT_HEADER.toLowerCase();
|
|
65
|
+
return Object.fromEntries(Object.entries(headers).filter(([name]) => name.toLowerCase() !== target));
|
|
66
|
+
}
|
|
1129
67
|
var HavenApiTransport = class {
|
|
1130
68
|
apiKey;
|
|
1131
69
|
baseUrl;
|
|
1132
70
|
requestTimeout;
|
|
1133
71
|
defaultHeaders;
|
|
72
|
+
clientIdentity;
|
|
1134
73
|
requestContext = new async_hooks.AsyncLocalStorage();
|
|
74
|
+
lastClientUpdate;
|
|
1135
75
|
constructor(config) {
|
|
1136
76
|
this.apiKey = config.apiKey;
|
|
1137
77
|
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
1138
78
|
this.requestTimeout = config.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;
|
|
1139
79
|
this.defaultHeaders = { ...config.defaultHeaders ?? {} };
|
|
80
|
+
this.clientIdentity = config.clientIdentity ?? chunkCK4NLLMO_cjs.SDK_CLIENT_IDENTITY;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The newest `client_update` the backend sent (#3303): inside a
|
|
84
|
+
* `withRequestContext` dispatch, the one that dispatch's own requests
|
|
85
|
+
* received; outside one, the latest this transport has seen.
|
|
86
|
+
*/
|
|
87
|
+
clientUpdate() {
|
|
88
|
+
const store = this.requestContext.getStore();
|
|
89
|
+
return store ? store.clientUpdate : this.lastClientUpdate;
|
|
90
|
+
}
|
|
91
|
+
recordClientUpdate(data) {
|
|
92
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) return;
|
|
93
|
+
const hint = chunkCK4NLLMO_cjs.readClientUpdate(data.client_update);
|
|
94
|
+
if (!hint) return;
|
|
95
|
+
this.lastClientUpdate = hint;
|
|
96
|
+
const store = this.requestContext.getStore();
|
|
97
|
+
if (store) store.clientUpdate = hint;
|
|
1140
98
|
}
|
|
1141
99
|
/** Run `fn` with extra headers scoped to its asynchronous Haven API work. */
|
|
1142
100
|
withRequestContext(headers, fn) {
|
|
@@ -1159,28 +117,34 @@ var HavenApiTransport = class {
|
|
|
1159
117
|
headers: {
|
|
1160
118
|
"Content-Type": "application/json",
|
|
1161
119
|
"Authorization": `Bearer ${this.apiKey}`,
|
|
1162
|
-
...this.defaultHeaders,
|
|
1163
|
-
...contextHeaders
|
|
120
|
+
...withoutClientHeader(this.defaultHeaders),
|
|
121
|
+
...withoutClientHeader(contextHeaders),
|
|
122
|
+
// Last, and any other spelling of it dropped above (fetch would
|
|
123
|
+
// JOIN `x-haven-client` and `X-Haven-Client` into one unparseable
|
|
124
|
+
// value), so neither `defaultHeaders` nor a dispatch context can
|
|
125
|
+
// misname the client; `clientIdentity` is the one way to set it.
|
|
126
|
+
[chunkCK4NLLMO_cjs.HAVEN_CLIENT_HEADER]: this.clientIdentity
|
|
1164
127
|
},
|
|
1165
128
|
body: body ? JSON.stringify(body) : void 0,
|
|
1166
129
|
signal: controller.signal
|
|
1167
130
|
});
|
|
1168
131
|
const data = await res.json();
|
|
132
|
+
this.recordClientUpdate(data);
|
|
1169
133
|
if (!res.ok) {
|
|
1170
134
|
const record = data;
|
|
1171
135
|
const errorText = typeof record.error === "string" ? record.error : void 0;
|
|
1172
136
|
const rawDetails = record.details ?? record.detail;
|
|
1173
137
|
const detailsText = typeof rawDetails === "string" ? rawDetails : rawDetails != null ? JSON.stringify(rawDetails) : void 0;
|
|
1174
138
|
const message = errorText && detailsText ? `${errorText}: ${detailsText}` : errorText ?? detailsText ?? "API request failed";
|
|
1175
|
-
throw new HavenApiError(message, res.status, data);
|
|
139
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(message, res.status, data);
|
|
1176
140
|
}
|
|
1177
141
|
return data;
|
|
1178
142
|
} catch (err) {
|
|
1179
|
-
if (err instanceof HavenApiError) throw err;
|
|
143
|
+
if (err instanceof chunkS42QSWJY_cjs.HavenApiError) throw err;
|
|
1180
144
|
if (err instanceof Error && err.name === "AbortError") {
|
|
1181
|
-
throw new HavenApiError(`Request to ${path} timed out`, 408);
|
|
145
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(`Request to ${path} timed out`, 408);
|
|
1182
146
|
}
|
|
1183
|
-
throw new HavenApiError(
|
|
147
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
1184
148
|
`Request to ${path} failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
1185
149
|
0
|
|
1186
150
|
);
|
|
@@ -1267,14 +231,14 @@ function mapPaymentReceipt(raw) {
|
|
|
1267
231
|
const receipt = {
|
|
1268
232
|
id: raw.id,
|
|
1269
233
|
paymentId: raw.payment_id,
|
|
1270
|
-
|
|
1271
|
-
|
|
234
|
+
source: raw.rail,
|
|
235
|
+
paymentProofStatus: raw.proof_status,
|
|
1272
236
|
txHash: raw.tx_hash,
|
|
1273
237
|
fundingTxHash: raw.funding_tx_hash ?? null,
|
|
1274
238
|
settlementTxHash: raw.settlement_tx_hash ?? null,
|
|
1275
239
|
chainId: raw.chain_id,
|
|
1276
|
-
|
|
1277
|
-
|
|
240
|
+
x402ResourceUrl: raw.resource_url,
|
|
241
|
+
x402MerchantAddress: raw.merchant_address,
|
|
1278
242
|
payerAddress: raw.payer_address,
|
|
1279
243
|
parties: mapParties(raw.parties),
|
|
1280
244
|
settlementAddress: raw.settlement_address,
|
|
@@ -1297,6 +261,9 @@ function mapPaymentReceipt(raw) {
|
|
|
1297
261
|
if ("payment_intent_id" in raw) {
|
|
1298
262
|
receipt.paymentIntentId = raw.payment_intent_id ?? null;
|
|
1299
263
|
}
|
|
264
|
+
if (raw.scope) {
|
|
265
|
+
receipt.scope = { source: raw.scope.source, filter: raw.scope.filter };
|
|
266
|
+
}
|
|
1300
267
|
if ("approval_request_id" in raw) {
|
|
1301
268
|
receipt.approvalRequestId = raw.approval_request_id ?? null;
|
|
1302
269
|
}
|
|
@@ -1320,29 +287,29 @@ function paymentStateStatusCode(status, fallback = 502) {
|
|
|
1320
287
|
return PAYMENT_STATE_STATUS_CODES[status] ?? fallback;
|
|
1321
288
|
}
|
|
1322
289
|
function phaseForStatus(status) {
|
|
1323
|
-
if (status === "pending_signature") return AgentPaymentPhase.AgentSignatureRequired;
|
|
1324
|
-
if (status === "submitted") return AgentPaymentPhase.PaymentSubmitted;
|
|
1325
|
-
if (status === "confirmed") return AgentPaymentPhase.PaymentConfirmed;
|
|
1326
|
-
if (status === "pending" || status === "pending_approval") return AgentPaymentPhase.UserApprovalRequired;
|
|
1327
|
-
if (status === "approved") return AgentPaymentPhase.UserExecutionRequired;
|
|
1328
|
-
if (status === "proposed") return AgentPaymentPhase.WaitingForAdditionalApprovals;
|
|
1329
|
-
if (status === "executed") return AgentPaymentPhase.FundingSent;
|
|
1330
|
-
if (status === "rejected") return AgentPaymentPhase.Rejected;
|
|
1331
|
-
if (status === "expired") return AgentPaymentPhase.Expired;
|
|
1332
|
-
if (status === "failed") return AgentPaymentPhase.Failed;
|
|
290
|
+
if (status === "pending_signature") return chunkS42QSWJY_cjs.AgentPaymentPhase.AgentSignatureRequired;
|
|
291
|
+
if (status === "submitted") return chunkS42QSWJY_cjs.AgentPaymentPhase.PaymentSubmitted;
|
|
292
|
+
if (status === "confirmed") return chunkS42QSWJY_cjs.AgentPaymentPhase.PaymentConfirmed;
|
|
293
|
+
if (status === "pending" || status === "pending_approval") return chunkS42QSWJY_cjs.AgentPaymentPhase.UserApprovalRequired;
|
|
294
|
+
if (status === "approved") return chunkS42QSWJY_cjs.AgentPaymentPhase.UserExecutionRequired;
|
|
295
|
+
if (status === "proposed") return chunkS42QSWJY_cjs.AgentPaymentPhase.WaitingForAdditionalApprovals;
|
|
296
|
+
if (status === "executed") return chunkS42QSWJY_cjs.AgentPaymentPhase.FundingSent;
|
|
297
|
+
if (status === "rejected") return chunkS42QSWJY_cjs.AgentPaymentPhase.Rejected;
|
|
298
|
+
if (status === "expired") return chunkS42QSWJY_cjs.AgentPaymentPhase.Expired;
|
|
299
|
+
if (status === "failed") return chunkS42QSWJY_cjs.AgentPaymentPhase.Failed;
|
|
1333
300
|
return null;
|
|
1334
301
|
}
|
|
1335
302
|
function nextActionForStatus(status) {
|
|
1336
|
-
if (status === "pending_signature") return AgentPaymentNextAction.SignAndSubmitPayment;
|
|
1337
|
-
if (status === "submitted") return AgentPaymentNextAction.CheckStatusLater;
|
|
1338
|
-
if (status === "confirmed") return AgentPaymentNextAction.None;
|
|
1339
|
-
if (status === "pending" || status === "pending_approval") return AgentPaymentNextAction.StopAndTellUser;
|
|
1340
|
-
if (status === "approved") return AgentPaymentNextAction.StopAndTellUser;
|
|
1341
|
-
if (status === "proposed") return AgentPaymentNextAction.StopAndTellUser;
|
|
1342
|
-
if (status === "executed") return AgentPaymentNextAction.StopAndTellUser;
|
|
1343
|
-
if (status === "rejected") return AgentPaymentNextAction.StopAndTellUser;
|
|
1344
|
-
if (status === "expired") return AgentPaymentNextAction.RequestAgainIfUserStillWantsIt;
|
|
1345
|
-
if (status === "failed") return AgentPaymentNextAction.StopAndTellUser;
|
|
303
|
+
if (status === "pending_signature") return chunkS42QSWJY_cjs.AgentPaymentNextAction.SignAndSubmitPayment;
|
|
304
|
+
if (status === "submitted") return chunkS42QSWJY_cjs.AgentPaymentNextAction.CheckStatusLater;
|
|
305
|
+
if (status === "confirmed") return chunkS42QSWJY_cjs.AgentPaymentNextAction.None;
|
|
306
|
+
if (status === "pending" || status === "pending_approval") return chunkS42QSWJY_cjs.AgentPaymentNextAction.StopAndTellUser;
|
|
307
|
+
if (status === "approved") return chunkS42QSWJY_cjs.AgentPaymentNextAction.StopAndTellUser;
|
|
308
|
+
if (status === "proposed") return chunkS42QSWJY_cjs.AgentPaymentNextAction.StopAndTellUser;
|
|
309
|
+
if (status === "executed") return chunkS42QSWJY_cjs.AgentPaymentNextAction.StopAndTellUser;
|
|
310
|
+
if (status === "rejected") return chunkS42QSWJY_cjs.AgentPaymentNextAction.StopAndTellUser;
|
|
311
|
+
if (status === "expired") return chunkS42QSWJY_cjs.AgentPaymentNextAction.RequestAgainIfUserStillWantsIt;
|
|
312
|
+
if (status === "failed") return chunkS42QSWJY_cjs.AgentPaymentNextAction.StopAndTellUser;
|
|
1346
313
|
return null;
|
|
1347
314
|
}
|
|
1348
315
|
function messageForState(label, status, paymentId, nextAction) {
|
|
@@ -1416,17 +383,17 @@ function throwPaymentStateError(label, raw) {
|
|
|
1416
383
|
const statusCode = paymentStateStatusCode(raw.status);
|
|
1417
384
|
const state = paymentStateFromRaw(label, raw);
|
|
1418
385
|
if (state) {
|
|
1419
|
-
throw new HavenPaymentStateError(state.message, statusCode, state, raw);
|
|
386
|
+
throw new chunkS42QSWJY_cjs.HavenPaymentStateError(state.message, statusCode, state, raw);
|
|
1420
387
|
}
|
|
1421
388
|
if (raw.status === "pending_approval") {
|
|
1422
|
-
throw new HavenApiError(
|
|
389
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
1423
390
|
`${label} exceeds the agent's on-chain budget and was declined; no approval is pending and none will arrive (payment_id: ${raw.payment_id}).`,
|
|
1424
391
|
statusCode,
|
|
1425
392
|
raw
|
|
1426
393
|
);
|
|
1427
394
|
}
|
|
1428
395
|
if (raw.status === "expired") {
|
|
1429
|
-
throw new HavenApiError(
|
|
396
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
1430
397
|
`${label} expired before it could be completed (payment_id: ${raw.payment_id}).`,
|
|
1431
398
|
statusCode,
|
|
1432
399
|
raw
|
|
@@ -1434,7 +401,7 @@ function throwPaymentStateError(label, raw) {
|
|
|
1434
401
|
}
|
|
1435
402
|
const paymentId = raw.payment_id ? ` (payment_id: ${raw.payment_id})` : "";
|
|
1436
403
|
const message = raw.error ?? `${label} ${raw.status}${paymentId}`;
|
|
1437
|
-
throw new HavenApiError(message, statusCode, raw);
|
|
404
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(message, statusCode, raw);
|
|
1438
405
|
}
|
|
1439
406
|
|
|
1440
407
|
// src/x402-retry-target.ts
|
|
@@ -1466,7 +433,7 @@ function isSecureX402RetryTarget(url) {
|
|
|
1466
433
|
return RESERVED_SUFFIXES.some((suffix) => host.endsWith(suffix));
|
|
1467
434
|
}
|
|
1468
435
|
var INSECURE_RETRY_TARGET_CODE = "INSECURE_RETRY_TARGET";
|
|
1469
|
-
var HavenInsecureRetryTargetError = class extends HavenError {
|
|
436
|
+
var HavenInsecureRetryTargetError = class extends chunkS42QSWJY_cjs.HavenError {
|
|
1470
437
|
constructor(url) {
|
|
1471
438
|
super(
|
|
1472
439
|
`Refusing to send a payment header to ${url}: the paid x402 retry must go to an https URL (or a loopback / reserved test host). The merchant's challenge declared this resource URL; retry with the https URL you quoted (pass it as \`url\`), and report a merchant whose challenge downgrades the scheme.`,
|
|
@@ -1488,6 +455,10 @@ var MCP_NOTIFICATION_TIMEOUT = 1e4;
|
|
|
1488
455
|
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
1489
456
|
var MCP_ACCEPT = "application/json, text/event-stream";
|
|
1490
457
|
var MCP_CLIENT_INFO = { name: "haven-sdk", version: "1" };
|
|
458
|
+
var MCP_X402_PAYMENT_META_KEY = "x402/payment";
|
|
459
|
+
var MCP_X402_PAYMENT_RESPONSE_META_KEY = "x402/payment-response";
|
|
460
|
+
var X402_RETRY_REJECTED_STATUS = 402;
|
|
461
|
+
var SESSION_NOT_FOUND_NEXT_ACTION = "reinitialize_then_retry_same_payment_header";
|
|
1491
462
|
var McpMerchantTransport = class {
|
|
1492
463
|
merchantTimeout;
|
|
1493
464
|
fetchImpl;
|
|
@@ -1504,7 +475,7 @@ var McpMerchantTransport = class {
|
|
|
1504
475
|
return await this.fetchImpl(url, { ...init, signal });
|
|
1505
476
|
} catch (err) {
|
|
1506
477
|
if (timeoutSignal.aborted) {
|
|
1507
|
-
throw new MerchantTimeoutError(`Merchant request timed out after ${timeoutMs}ms: ${url}`);
|
|
478
|
+
throw new chunkS42QSWJY_cjs.MerchantTimeoutError(`Merchant request timed out after ${timeoutMs}ms: ${url}`);
|
|
1508
479
|
}
|
|
1509
480
|
throw err;
|
|
1510
481
|
}
|
|
@@ -1583,7 +554,7 @@ var McpMerchantTransport = class {
|
|
|
1583
554
|
return response;
|
|
1584
555
|
}
|
|
1585
556
|
const message = selectJsonRpcResult(parseSseJsonRpcMessages(text));
|
|
1586
|
-
if (!message) return response;
|
|
557
|
+
if (!message || !("result" in message || "error" in message)) return response;
|
|
1587
558
|
const body = "result" in message ? message.result : message;
|
|
1588
559
|
const headers = new Headers(response.headers);
|
|
1589
560
|
headers.set("content-type", "application/json");
|
|
@@ -1641,12 +612,62 @@ var McpMerchantTransport = class {
|
|
|
1641
612
|
async deliverPayment(url, init, paymentHeader) {
|
|
1642
613
|
assertSecureX402RetryTarget(url);
|
|
1643
614
|
const headers = new Headers(init?.headers);
|
|
1644
|
-
const send = x402PaymentHeaderNamesFor(paymentHeader);
|
|
1645
|
-
for (const name of X402_PAYMENT_HEADER_NAMES) {
|
|
615
|
+
const send = chunkCK4NLLMO_cjs.x402PaymentHeaderNamesFor(paymentHeader);
|
|
616
|
+
for (const name of chunkCK4NLLMO_cjs.X402_PAYMENT_HEADER_NAMES) {
|
|
1646
617
|
if (send.includes(name)) headers.set(name, paymentHeader);
|
|
1647
618
|
else headers.delete(name);
|
|
1648
619
|
}
|
|
1649
|
-
return this.fetch(url, { ...init, headers });
|
|
620
|
+
return this.fetch(url, withMcpPaymentMeta({ ...init, headers }, paymentHeader));
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* #3171: deliver the payment; if the merchant answers its unknown-session
|
|
624
|
+
* 404 WITH the settled-nothing recovery data, re-initialize once and resend
|
|
625
|
+
* the SAME header on the new session. The merchant's own guarantee (#1578:
|
|
626
|
+
* the session guard runs before its payment gate) is what makes the resend
|
|
627
|
+
* safe — a bare -32001, or any other 404, is returned to the caller
|
|
628
|
+
* untouched (body re-wrapped, since reading it consumed the stream). One
|
|
629
|
+
* recovery only: a second 404 is the answer.
|
|
630
|
+
*/
|
|
631
|
+
async deliverPaymentRecoveringSession(url, init, paymentHeader, reinitialize) {
|
|
632
|
+
const first = await this.deliverPayment(url, init, paymentHeader);
|
|
633
|
+
if (first.status !== 404) return first;
|
|
634
|
+
let text;
|
|
635
|
+
try {
|
|
636
|
+
text = await first.clone().text();
|
|
637
|
+
} catch {
|
|
638
|
+
return first;
|
|
639
|
+
}
|
|
640
|
+
if (!sessionNotFoundRecovery(text)) return first;
|
|
641
|
+
const sessionId = await reinitialize();
|
|
642
|
+
if (!sessionId) return first;
|
|
643
|
+
return this.deliverPayment(url, this.withSessionHeaders(init, sessionId), paymentHeader);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* #3118: read a native MCP payment-required tool result from a response
|
|
647
|
+
* WITHOUT consuming it — JSON or SSE framed. `undefined` for anything that
|
|
648
|
+
* is not an `isError: true` tool result carrying a valid `PaymentRequired`
|
|
649
|
+
* (structured content first, text fallback second), so an ordinary tool
|
|
650
|
+
* error, a successful result that merely resembles a challenge, or an
|
|
651
|
+
* unparseable body is never mistaken for a payment demand.
|
|
652
|
+
*/
|
|
653
|
+
async extractToolResultChallenge(response, init) {
|
|
654
|
+
const toolResult = await this.readToolResult(response, init);
|
|
655
|
+
return toolResult ? extractMcpPaymentRequired(toolResult) : void 0;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* #3118: the tool RESULT a response carries, read WITHOUT consuming it, or
|
|
659
|
+
* `undefined`. Only a JSON or SSE body is read at all (#3155 review S2):
|
|
660
|
+
* a non-402 answer used to be returned untouched, and buffering an
|
|
661
|
+
* arbitrary body — a streaming or binary paid resource — to look for a
|
|
662
|
+
* challenge would block the caller until the stream ended or the merchant
|
|
663
|
+
* timeout fired. A merchant that speaks JSON-RPC declares one of those two
|
|
664
|
+
* content types.
|
|
665
|
+
*/
|
|
666
|
+
async readToolResult(response, init) {
|
|
667
|
+
if (init !== void 0 && !isJsonRpcToolsCallBody(init.body)) return void 0;
|
|
668
|
+
const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
|
|
669
|
+
if (!contentType.includes("application/json") && !contentType.includes("text/event-stream")) return void 0;
|
|
670
|
+
return mcpToolResultOf(await this.readMessage(response));
|
|
1650
671
|
}
|
|
1651
672
|
async notifyInitialized(url, init, sessionId, wallet) {
|
|
1652
673
|
try {
|
|
@@ -1668,6 +689,106 @@ var McpMerchantTransport = class {
|
|
|
1668
689
|
}
|
|
1669
690
|
}
|
|
1670
691
|
};
|
|
692
|
+
function mcpToolResultOf(value) {
|
|
693
|
+
if (!isRecord(value)) return void 0;
|
|
694
|
+
if ("jsonrpc" in value) {
|
|
695
|
+
return isRecord(value.result) ? value.result : void 0;
|
|
696
|
+
}
|
|
697
|
+
if ("isError" in value || Array.isArray(value.content) || isRecord(value._meta)) return value;
|
|
698
|
+
return void 0;
|
|
699
|
+
}
|
|
700
|
+
function extractMcpPaymentRequired(toolResult) {
|
|
701
|
+
if (toolResult.isError !== true) return void 0;
|
|
702
|
+
if (isRecord(toolResult.structuredContent)) {
|
|
703
|
+
const parsed = chunkCK4NLLMO_cjs.normalizePaymentRequired(toolResult.structuredContent);
|
|
704
|
+
if (parsed) return parsed;
|
|
705
|
+
}
|
|
706
|
+
if (Array.isArray(toolResult.content)) {
|
|
707
|
+
for (const item of toolResult.content) {
|
|
708
|
+
if (!isRecord(item) || item.type !== "text" || typeof item.text !== "string") continue;
|
|
709
|
+
let candidate;
|
|
710
|
+
try {
|
|
711
|
+
candidate = JSON.parse(item.text);
|
|
712
|
+
} catch {
|
|
713
|
+
continue;
|
|
714
|
+
}
|
|
715
|
+
const parsed = chunkCK4NLLMO_cjs.normalizePaymentRequired(candidate);
|
|
716
|
+
if (parsed) return parsed;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
return void 0;
|
|
720
|
+
}
|
|
721
|
+
function mcpSettlementFromToolResult(toolResult) {
|
|
722
|
+
const meta = toolResult._meta;
|
|
723
|
+
if (!isRecord(meta)) return void 0;
|
|
724
|
+
const settlement = meta[MCP_X402_PAYMENT_RESPONSE_META_KEY];
|
|
725
|
+
if (!isRecord(settlement) || typeof settlement.success !== "boolean") return void 0;
|
|
726
|
+
return {
|
|
727
|
+
success: settlement.success,
|
|
728
|
+
...typeof settlement.transaction === "string" ? { transaction: settlement.transaction } : {},
|
|
729
|
+
...typeof settlement.network === "string" ? { network: settlement.network } : {},
|
|
730
|
+
...typeof settlement.payer === "string" ? { payer: settlement.payer } : {},
|
|
731
|
+
...typeof settlement.errorReason === "string" ? { errorReason: settlement.errorReason } : {}
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
function withMcpPaymentMeta(init, paymentHeader) {
|
|
735
|
+
const request = parseJsonRpcToolsCall(init.body);
|
|
736
|
+
if (!request) return init;
|
|
737
|
+
let envelope;
|
|
738
|
+
try {
|
|
739
|
+
envelope = chunkCK4NLLMO_cjs.decodeBase64Json(paymentHeader);
|
|
740
|
+
} catch {
|
|
741
|
+
return init;
|
|
742
|
+
}
|
|
743
|
+
if (!isRecord(envelope)) return init;
|
|
744
|
+
const params = request.params;
|
|
745
|
+
const existingMeta = isRecord(params._meta) ? params._meta : {};
|
|
746
|
+
return {
|
|
747
|
+
...init,
|
|
748
|
+
body: JSON.stringify({
|
|
749
|
+
...request,
|
|
750
|
+
params: { ...params, _meta: { ...existingMeta, [MCP_X402_PAYMENT_META_KEY]: envelope } }
|
|
751
|
+
})
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
function encodeMcpSettlementReceipt(settlement) {
|
|
755
|
+
return chunkCK4NLLMO_cjs.encodeBase64Json(settlement);
|
|
756
|
+
}
|
|
757
|
+
function parseJsonRpcToolsCall(body) {
|
|
758
|
+
if (typeof body !== "string") return void 0;
|
|
759
|
+
let request;
|
|
760
|
+
try {
|
|
761
|
+
request = JSON.parse(body);
|
|
762
|
+
} catch {
|
|
763
|
+
return void 0;
|
|
764
|
+
}
|
|
765
|
+
if (!isRecord(request) || request.method !== "tools/call" || !isRecord(request.params)) return void 0;
|
|
766
|
+
return request;
|
|
767
|
+
}
|
|
768
|
+
function isJsonRpcToolsCallBody(body) {
|
|
769
|
+
return parseJsonRpcToolsCall(body) !== void 0;
|
|
770
|
+
}
|
|
771
|
+
function sessionNotFoundRecovery(body) {
|
|
772
|
+
let parsed;
|
|
773
|
+
try {
|
|
774
|
+
parsed = JSON.parse(body);
|
|
775
|
+
} catch {
|
|
776
|
+
return void 0;
|
|
777
|
+
}
|
|
778
|
+
if (!isRecord(parsed) || !isRecord(parsed.error)) return void 0;
|
|
779
|
+
if (parsed.error.code !== -32001) return void 0;
|
|
780
|
+
const data = parsed.error.data;
|
|
781
|
+
if (!isRecord(data)) return void 0;
|
|
782
|
+
if (data.settled !== false || data.next_action !== SESSION_NOT_FOUND_NEXT_ACTION) return void 0;
|
|
783
|
+
return {
|
|
784
|
+
reason: typeof data.reason === "string" ? data.reason : "session_expired",
|
|
785
|
+
settled: false,
|
|
786
|
+
next_action: SESSION_NOT_FOUND_NEXT_ACTION
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
function isRecord(value) {
|
|
790
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
791
|
+
}
|
|
1671
792
|
async function captureMerchantResponse(response) {
|
|
1672
793
|
const merchant_body = await response.text().catch(() => "");
|
|
1673
794
|
return {
|
|
@@ -1755,9 +876,42 @@ function deriveReadiness(status, allowances) {
|
|
|
1755
876
|
return allowances.some((allowance) => safeBigInt(allowance.remainingAtomic) > 0n) ? "ready" : "needs_approval";
|
|
1756
877
|
}
|
|
1757
878
|
function formatRemainingDisplay(tokenAddress, tokenSymbol, remainingAtomic) {
|
|
1758
|
-
const token = resolveTokenFromAddress(tokenAddress);
|
|
879
|
+
const token = chunkCK4NLLMO_cjs.resolveTokenFromAddress(tokenAddress);
|
|
1759
880
|
return token ? `${formatAtomicAmount(safeBigInt(remainingAtomic), token.decimals)} ${tokenSymbol}` : `${remainingAtomic} ${tokenSymbol} (atomic; unknown decimals)`;
|
|
1760
881
|
}
|
|
882
|
+
function mapTaskBudget(raw) {
|
|
883
|
+
return {
|
|
884
|
+
id: raw.id,
|
|
885
|
+
agentId: raw.agent_id,
|
|
886
|
+
chainId: raw.chain_id,
|
|
887
|
+
tokenAddress: raw.token_address,
|
|
888
|
+
recipientAddress: raw.recipient_address,
|
|
889
|
+
parentDelegationHash: raw.parent_delegation_hash,
|
|
890
|
+
delegationHash: raw.delegation_hash,
|
|
891
|
+
label: raw.label,
|
|
892
|
+
maxAtomic: raw.max_atomic,
|
|
893
|
+
status: raw.status,
|
|
894
|
+
expiresAt: raw.expires_at,
|
|
895
|
+
isExpired: raw.is_expired,
|
|
896
|
+
createdAt: raw.created_at,
|
|
897
|
+
openedAt: raw.opened_at,
|
|
898
|
+
closedAt: raw.closed_at,
|
|
899
|
+
closeTxHash: raw.close_tx_hash
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
function summarizeTaskBudget(taskBudget) {
|
|
903
|
+
const token = chunkCK4NLLMO_cjs.resolveTokenFromAddress(taskBudget.tokenAddress);
|
|
904
|
+
const maxDisplay = token ? `${formatAtomicAmount(safeBigInt(taskBudget.maxAtomic), token.decimals)} ${token.symbol}` : `${taskBudget.maxAtomic} (atomic; unknown decimals)`;
|
|
905
|
+
return {
|
|
906
|
+
id: taskBudget.id,
|
|
907
|
+
label: taskBudget.label,
|
|
908
|
+
tokenAddress: taskBudget.tokenAddress,
|
|
909
|
+
maxAtomic: taskBudget.maxAtomic,
|
|
910
|
+
maxDisplay,
|
|
911
|
+
recipientAddress: taskBudget.recipientAddress,
|
|
912
|
+
expiresAt: taskBudget.expiresAt
|
|
913
|
+
};
|
|
914
|
+
}
|
|
1761
915
|
var AccountReads = class {
|
|
1762
916
|
transport;
|
|
1763
917
|
getPaymentStatus;
|
|
@@ -1777,7 +931,11 @@ var AccountReads = class {
|
|
|
1777
931
|
return request;
|
|
1778
932
|
}
|
|
1779
933
|
async getAgentSummary() {
|
|
1780
|
-
const [agent, allowanceSummary] = await Promise.all([
|
|
934
|
+
const [agent, allowanceSummary, taskBudgets] = await Promise.all([
|
|
935
|
+
this.getAgent(),
|
|
936
|
+
this.getAllowances(),
|
|
937
|
+
this.listOpenTaskBudgetsSummary()
|
|
938
|
+
]);
|
|
1781
939
|
const allowances = allowanceSummary.allowances.map((allowance) => {
|
|
1782
940
|
return {
|
|
1783
941
|
id: allowance.id,
|
|
@@ -1791,7 +949,30 @@ var AccountReads = class {
|
|
|
1791
949
|
};
|
|
1792
950
|
});
|
|
1793
951
|
const readiness = deriveReadiness(agent.status, allowances);
|
|
1794
|
-
return { ...agent, readiness, spend_authority_readiness: readiness, allowances };
|
|
952
|
+
return { ...agent, readiness, spend_authority_readiness: readiness, allowances, taskBudgets };
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* #3329: `GET /task-budgets?status=open`, mapped to the condensed summary
|
|
956
|
+
* row `getAgentSummary()` carries. Fails SOFT per the #3093 rule (default
|
|
957
|
+
* every array wire key to `[]` so an absent/malformed key degrades instead
|
|
958
|
+
* of taking the route down): a 404 (a backend that predates #3329's
|
|
959
|
+
* route), ANY other transport error, an undefined/null body, or a missing
|
|
960
|
+
* or non-array `task_budgets` key all return `[]` rather than throwing —
|
|
961
|
+
* `getAgentSummary`'s identity + readiness + allowances fields are what
|
|
962
|
+
* callers depend on, and this read must never be why the whole summary
|
|
963
|
+
* fails.
|
|
964
|
+
*/
|
|
965
|
+
async listOpenTaskBudgetsSummary() {
|
|
966
|
+
try {
|
|
967
|
+
const raw = await this.transport.get(
|
|
968
|
+
"/task-budgets?status=open"
|
|
969
|
+
);
|
|
970
|
+
const rows = raw?.task_budgets;
|
|
971
|
+
if (!Array.isArray(rows)) return [];
|
|
972
|
+
return rows.map((row) => summarizeTaskBudget(mapTaskBudget(row)));
|
|
973
|
+
} catch {
|
|
974
|
+
return [];
|
|
975
|
+
}
|
|
1795
976
|
}
|
|
1796
977
|
async getAllowances() {
|
|
1797
978
|
const raw = await this.transport.get("/machine-payments/allowances");
|
|
@@ -1859,7 +1040,7 @@ var AccountReads = class {
|
|
|
1859
1040
|
payment: payment2,
|
|
1860
1041
|
allowance: null,
|
|
1861
1042
|
warnings: [{
|
|
1862
|
-
code: AgentPaymentWarningCode.AllowanceCheckUnavailable,
|
|
1043
|
+
code: chunkS42QSWJY_cjs.AgentPaymentWarningCode.AllowanceCheckUnavailable,
|
|
1863
1044
|
message: `Could not read the post-purchase allowance/budget for payment ${paymentId} (${detail}). The payment itself succeeded \u2014 the on-chain policy remains the actual spend gate; this only affects the remaining-budget figure reported here.`
|
|
1864
1045
|
}]
|
|
1865
1046
|
});
|
|
@@ -1885,7 +1066,7 @@ var AccountReads = class {
|
|
|
1885
1066
|
(allowance) => allowance.tokenAddress.toLowerCase() === tokenAddress.toLowerCase()
|
|
1886
1067
|
);
|
|
1887
1068
|
if (!match) return unavailable("no allowance/budget row matches the settled token", payment);
|
|
1888
|
-
const token = resolveTokenFromAddress(match.tokenAddress);
|
|
1069
|
+
const token = chunkCK4NLLMO_cjs.resolveTokenFromAddress(match.tokenAddress);
|
|
1889
1070
|
const remainingDisplay = token ? `${formatAtomicAmount(safeBigInt(match.onchain.remaining), token.decimals)} ${match.tokenSymbol}` : void 0;
|
|
1890
1071
|
const rail = agentResult.value.executionRail;
|
|
1891
1072
|
return {
|
|
@@ -1960,7 +1141,7 @@ function isWaitTimeout(err) {
|
|
|
1960
1141
|
async function waitForSweepTx(tx) {
|
|
1961
1142
|
let receipt;
|
|
1962
1143
|
try {
|
|
1963
|
-
receipt = await tx.wait(1, DEFAULT_CONFIRMATION_TIMEOUT_MS);
|
|
1144
|
+
receipt = await tx.wait(1, chunkS42QSWJY_cjs.DEFAULT_CONFIRMATION_TIMEOUT_MS);
|
|
1964
1145
|
} catch (err) {
|
|
1965
1146
|
if (!isWaitTimeout(err)) throw err;
|
|
1966
1147
|
return { txHash: tx.hash, confirmation: "unconfirmed" };
|
|
@@ -1974,16 +1155,16 @@ var DelegateSweepApi = class {
|
|
|
1974
1155
|
}
|
|
1975
1156
|
options;
|
|
1976
1157
|
async sweepDelegate() {
|
|
1977
|
-
if (!this.options.delegateKey) throw new HavenSigningError("delegateKey is required for sweepDelegate.");
|
|
1158
|
+
if (!this.options.delegateKey) throw new chunkS42QSWJY_cjs.HavenSigningError("delegateKey is required for sweepDelegate.");
|
|
1978
1159
|
const agent = await this.options.getAgent();
|
|
1979
|
-
if (!agent.delegateAddress) throw new HavenApiError("Agent has no delegate address.", 422);
|
|
1160
|
+
if (!agent.delegateAddress) throw new chunkS42QSWJY_cjs.HavenApiError("Agent has no delegate address.", 422);
|
|
1980
1161
|
const rpcUrl = this.options.chainRpcs[agent.chainId];
|
|
1981
|
-
if (!rpcUrl) throw new HavenApiError(`chainRpcs[${agent.chainId}] must be configured to sweep the delegate wallet.`, 422);
|
|
1162
|
+
if (!rpcUrl) throw new chunkS42QSWJY_cjs.HavenApiError(`chainRpcs[${agent.chainId}] must be configured to sweep the delegate wallet.`, 422);
|
|
1982
1163
|
const provider = createJsonRpcProvider(rpcUrl);
|
|
1983
1164
|
const wallet = createWallet(this.options.delegateKey, provider);
|
|
1984
1165
|
const transfers = [];
|
|
1985
|
-
if (isSweepableChain(agent.chainId)) {
|
|
1986
|
-
const contract = createErc20Contract(sweepUsdcAddress(agent.chainId), ["function balanceOf(address) view returns (uint256)", "function transfer(address to, uint256 amount) returns (bool)"], wallet);
|
|
1166
|
+
if (chunkCK4NLLMO_cjs.isSweepableChain(agent.chainId)) {
|
|
1167
|
+
const contract = createErc20Contract(chunkCK4NLLMO_cjs.sweepUsdcAddress(agent.chainId), ["function balanceOf(address) view returns (uint256)", "function transfer(address to, uint256 amount) returns (bool)"], wallet);
|
|
1987
1168
|
const balance2 = await contract.balanceOf(agent.delegateAddress);
|
|
1988
1169
|
if (balance2 > 0n) {
|
|
1989
1170
|
const tx = await contract.transfer(agent.accountAddress, balance2);
|
|
@@ -2037,7 +1218,7 @@ function chainIdFromNetwork(network) {
|
|
|
2037
1218
|
function chainIdOrNull(network) {
|
|
2038
1219
|
return chainIdFromNetwork(network) ?? null;
|
|
2039
1220
|
}
|
|
2040
|
-
function
|
|
1221
|
+
function sameAddress(a, b) {
|
|
2041
1222
|
return Boolean(a && b && a.toLowerCase() === b.toLowerCase());
|
|
2042
1223
|
}
|
|
2043
1224
|
function decimalFromUsdcAtomic(value) {
|
|
@@ -2071,7 +1252,7 @@ function snapshotRequestBody(body) {
|
|
|
2071
1252
|
if (body == null) return void 0;
|
|
2072
1253
|
if (typeof body === "string") return body;
|
|
2073
1254
|
if (body instanceof URLSearchParams) return body.toString();
|
|
2074
|
-
throw new HavenApiError(
|
|
1255
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2075
1256
|
"Quote helpers can only capture resumable request bodies that are strings or URLSearchParams. For streams, blobs, or binary bodies, preserve the original request yourself and call the matching resume method with fresh init.",
|
|
2076
1257
|
400
|
|
2077
1258
|
);
|
|
@@ -2092,25 +1273,25 @@ function requestInitFromSnapshot(request) {
|
|
|
2092
1273
|
};
|
|
2093
1274
|
}
|
|
2094
1275
|
function noCompatiblePaymentOptionError(accepts) {
|
|
2095
|
-
const erc7710Only = selectErc7710PaymentOption(accepts) !== null;
|
|
1276
|
+
const erc7710Only = chunkCK4NLLMO_cjs.selectErc7710PaymentOption(accepts) !== null;
|
|
2096
1277
|
const unsupportedOnly = !erc7710Only && accepts.some(
|
|
2097
|
-
(opt) => opt !== null && typeof opt === "object" && !isErc7710Option(opt) && (x402AssetTransferMethod(opt) !== null || opt.extra?.paymentFlow !== void 0)
|
|
1278
|
+
(opt) => opt !== null && typeof opt === "object" && !chunkCK4NLLMO_cjs.isErc7710Option(opt) && (chunkCK4NLLMO_cjs.x402AssetTransferMethod(opt) !== null || opt.extra?.paymentFlow !== void 0)
|
|
2098
1279
|
);
|
|
2099
|
-
return new HavenApiError(
|
|
1280
|
+
return new chunkS42QSWJY_cjs.HavenApiError(
|
|
2100
1281
|
"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)." : unsupportedOnly ? " Every option this merchant advertises asks for a transfer method or payment flow Haven cannot construct (for example extra.assetTransferMethod: 'permit2', or an unrecognized extra.paymentFlow). No payment intent was created and no funds moved." : ""),
|
|
2101
1282
|
400
|
|
2102
1283
|
);
|
|
2103
1284
|
}
|
|
2104
1285
|
function buildX402Quote(paymentRequired, request, idempotencyKey, mcpTransport) {
|
|
2105
|
-
const standard = selectStandardPaymentOption(paymentRequired.accepts);
|
|
2106
|
-
const option = standard ?? selectErc7710PaymentOption(paymentRequired.accepts);
|
|
1286
|
+
const standard = chunkCK4NLLMO_cjs.selectStandardPaymentOption(paymentRequired.accepts);
|
|
1287
|
+
const option = standard ?? chunkCK4NLLMO_cjs.selectErc7710PaymentOption(paymentRequired.accepts);
|
|
2107
1288
|
if (!option) {
|
|
2108
1289
|
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
2109
1290
|
}
|
|
2110
|
-
const token = resolveTokenFromAddress(option.asset, option.network);
|
|
1291
|
+
const token = chunkCK4NLLMO_cjs.resolveTokenFromAddress(option.asset, option.network);
|
|
2111
1292
|
return {
|
|
2112
1293
|
rail: "x402",
|
|
2113
|
-
idempotencyKey: idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option),
|
|
1294
|
+
idempotencyKey: idempotencyKey ?? chunkCK4NLLMO_cjs.buildX402IdempotencyKey(paymentRequired, option),
|
|
2114
1295
|
paymentRequired,
|
|
2115
1296
|
accepted: option,
|
|
2116
1297
|
acceptedScheme: standard ? "standard" : "erc7710",
|
|
@@ -2124,8 +1305,8 @@ function buildX402Quote(paymentRequired, request, idempotencyKey, mcpTransport)
|
|
|
2124
1305
|
resourceUrlDiffersFromRequest: paymentRequired.resource.url !== request.url,
|
|
2125
1306
|
description: paymentRequired.resource.description ?? option.description ?? null,
|
|
2126
1307
|
mimeType: paymentRequired.resource.mimeType ?? option.mimeType ?? null,
|
|
2127
|
-
amountAtomic: x402AuthorizationAmount(option),
|
|
2128
|
-
amount: decimalFromUsdcAtomic(x402AuthorizationAmount(option)),
|
|
1308
|
+
amountAtomic: chunkCK4NLLMO_cjs.x402AuthorizationAmount(option),
|
|
1309
|
+
amount: decimalFromUsdcAtomic(chunkCK4NLLMO_cjs.x402AuthorizationAmount(option)),
|
|
2129
1310
|
token: token?.symbol ?? "USDC",
|
|
2130
1311
|
// #1351: null when the asset is unrecognised on this network — the
|
|
2131
1312
|
// `token` fallback above is a LABEL, not evidence of 6 decimals, and a
|
|
@@ -2164,7 +1345,7 @@ function buildX402Receipt(input) {
|
|
|
2164
1345
|
payTo: input.merchantTo ?? input.accepted.payTo
|
|
2165
1346
|
},
|
|
2166
1347
|
x402: {
|
|
2167
|
-
amount: x402AuthorizationAmount(input.accepted),
|
|
1348
|
+
amount: chunkCK4NLLMO_cjs.x402AuthorizationAmount(input.accepted),
|
|
2168
1349
|
token: input.token,
|
|
2169
1350
|
network: input.accepted.network,
|
|
2170
1351
|
asset: input.accepted.asset,
|
|
@@ -2173,7 +1354,7 @@ function buildX402Receipt(input) {
|
|
|
2173
1354
|
};
|
|
2174
1355
|
}
|
|
2175
1356
|
function buildX402ResumeState(input) {
|
|
2176
|
-
const token = resolveTokenFromAddress(input.accepted.asset, input.accepted.network);
|
|
1357
|
+
const token = chunkCK4NLLMO_cjs.resolveTokenFromAddress(input.accepted.asset, input.accepted.network);
|
|
2177
1358
|
return {
|
|
2178
1359
|
rail: "x402",
|
|
2179
1360
|
paymentId: input.paymentId,
|
|
@@ -2184,8 +1365,8 @@ function buildX402ResumeState(input) {
|
|
|
2184
1365
|
request: input.request,
|
|
2185
1366
|
resourceUrl: input.paymentRequired.resource.url,
|
|
2186
1367
|
description: input.paymentRequired.resource.description ?? input.accepted.description ?? null,
|
|
2187
|
-
amountAtomic: x402AuthorizationAmount(input.accepted),
|
|
2188
|
-
amount: decimalFromUsdcAtomic(x402AuthorizationAmount(input.accepted)),
|
|
1368
|
+
amountAtomic: chunkCK4NLLMO_cjs.x402AuthorizationAmount(input.accepted),
|
|
1369
|
+
amount: decimalFromUsdcAtomic(chunkCK4NLLMO_cjs.x402AuthorizationAmount(input.accepted)),
|
|
2189
1370
|
token: token?.symbol ?? "USDC",
|
|
2190
1371
|
asset: input.accepted.asset,
|
|
2191
1372
|
network: input.accepted.network,
|
|
@@ -2194,7 +1375,7 @@ function buildX402ResumeState(input) {
|
|
|
2194
1375
|
};
|
|
2195
1376
|
}
|
|
2196
1377
|
function attachX402ResumeState(err, paymentRequired, accepted, idempotencyKey, request) {
|
|
2197
|
-
if (!(err instanceof HavenPaymentStateError)) return;
|
|
1378
|
+
if (!(err instanceof chunkS42QSWJY_cjs.HavenPaymentStateError)) return;
|
|
2198
1379
|
if (err.state.rail !== "x402") return;
|
|
2199
1380
|
err.resumeState = buildX402ResumeState({
|
|
2200
1381
|
paymentId: err.state.paymentId,
|
|
@@ -2215,17 +1396,17 @@ function attachResumeState(err, input) {
|
|
|
2215
1396
|
}
|
|
2216
1397
|
function assertCanResumeX402(status, paymentRequired, option) {
|
|
2217
1398
|
if (status.rail !== "x402") {
|
|
2218
|
-
throw new HavenPaymentStateError(
|
|
1399
|
+
throw new chunkS42QSWJY_cjs.HavenPaymentStateError(
|
|
2219
1400
|
`Payment ${status.paymentId} is ${status.rail}, not x402.`,
|
|
2220
1401
|
409,
|
|
2221
1402
|
status
|
|
2222
1403
|
);
|
|
2223
1404
|
}
|
|
2224
|
-
if (status.nextAction !== AgentPaymentNextAction.RetryOriginalX402Request) {
|
|
2225
|
-
throw new HavenPaymentStateError(status.message, paymentStateStatusCode(status.status, 409), status);
|
|
1405
|
+
if (status.nextAction !== chunkS42QSWJY_cjs.AgentPaymentNextAction.RetryOriginalX402Request) {
|
|
1406
|
+
throw new chunkS42QSWJY_cjs.HavenPaymentStateError(status.message, paymentStateStatusCode(status.status, 409), status);
|
|
2226
1407
|
}
|
|
2227
1408
|
if (!status.txHash) {
|
|
2228
|
-
throw new HavenApiError(
|
|
1409
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2229
1410
|
`x402 payment ${status.paymentId} is ready to retry but has no Haven transaction hash.`,
|
|
2230
1411
|
502,
|
|
2231
1412
|
status,
|
|
@@ -2233,15 +1414,15 @@ function assertCanResumeX402(status, paymentRequired, option) {
|
|
|
2233
1414
|
);
|
|
2234
1415
|
}
|
|
2235
1416
|
if (status.resourceUrl && status.resourceUrl !== paymentRequired.resource.url) {
|
|
2236
|
-
throw new HavenApiError(
|
|
1417
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2237
1418
|
"x402 resume request does not match the approved resource URL.",
|
|
2238
1419
|
409,
|
|
2239
1420
|
{ status, paymentRequired },
|
|
2240
1421
|
status.paymentId
|
|
2241
1422
|
);
|
|
2242
1423
|
}
|
|
2243
|
-
if (status.merchantAddress && !
|
|
2244
|
-
throw new HavenApiError(
|
|
1424
|
+
if (status.merchantAddress && !sameAddress(status.merchantAddress, option.payTo)) {
|
|
1425
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2245
1426
|
"x402 resume request does not match the approved merchant.",
|
|
2246
1427
|
409,
|
|
2247
1428
|
{ status, selectedPayment: option },
|
|
@@ -2250,7 +1431,7 @@ function assertCanResumeX402(status, paymentRequired, option) {
|
|
|
2250
1431
|
}
|
|
2251
1432
|
const optionChainId = chainIdFromNetwork(option.network);
|
|
2252
1433
|
if (status.chainId && optionChainId && status.chainId !== optionChainId) {
|
|
2253
|
-
throw new HavenApiError(
|
|
1434
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2254
1435
|
"x402 resume request does not match the approved network.",
|
|
2255
1436
|
409,
|
|
2256
1437
|
{ status, selectedPayment: option },
|
|
@@ -2258,7 +1439,7 @@ function assertCanResumeX402(status, paymentRequired, option) {
|
|
|
2258
1439
|
);
|
|
2259
1440
|
}
|
|
2260
1441
|
if (status.token && status.token !== "USDC") {
|
|
2261
|
-
throw new HavenApiError(
|
|
1442
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2262
1443
|
"x402 resume request does not match the approved token.",
|
|
2263
1444
|
409,
|
|
2264
1445
|
{ status, selectedPayment: option },
|
|
@@ -2266,9 +1447,9 @@ function assertCanResumeX402(status, paymentRequired, option) {
|
|
|
2266
1447
|
);
|
|
2267
1448
|
}
|
|
2268
1449
|
const approvedAmount = status.amount ? normalizeDecimal(status.amount) : "";
|
|
2269
|
-
const requestedAmount = normalizeDecimal(decimalFromUsdcAtomic(x402AuthorizationAmount(option)));
|
|
1450
|
+
const requestedAmount = normalizeDecimal(decimalFromUsdcAtomic(chunkCK4NLLMO_cjs.x402AuthorizationAmount(option)));
|
|
2270
1451
|
if (approvedAmount && approvedAmount !== requestedAmount) {
|
|
2271
|
-
throw new HavenApiError(
|
|
1452
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2272
1453
|
"x402 resume request does not match the approved amount.",
|
|
2273
1454
|
409,
|
|
2274
1455
|
{ status, selectedPayment: option },
|
|
@@ -2321,12 +1502,12 @@ var X402FundingLeg = class {
|
|
|
2321
1502
|
}
|
|
2322
1503
|
}
|
|
2323
1504
|
// ── Authorization ────────────────────────────────────────────────
|
|
2324
|
-
async authorize(paymentRequired, option, idempotencyKey) {
|
|
1505
|
+
async authorize(paymentRequired, option, idempotencyKey, taskBudgetId) {
|
|
2325
1506
|
const raw = await this.post("/x402", {
|
|
2326
1507
|
url: paymentRequired.resource.url,
|
|
2327
1508
|
payTo: this.delegateAddress,
|
|
2328
1509
|
merchantPayTo: option.payTo,
|
|
2329
|
-
amount: x402AuthorizationAmount(option),
|
|
1510
|
+
amount: chunkCK4NLLMO_cjs.x402AuthorizationAmount(option),
|
|
2330
1511
|
asset: option.asset,
|
|
2331
1512
|
network: option.network,
|
|
2332
1513
|
description: paymentRequired.resource.description,
|
|
@@ -2334,20 +1515,23 @@ var X402FundingLeg = class {
|
|
|
2334
1515
|
// #1360: same explicit funding-leg declaration as createX402Intent —
|
|
2335
1516
|
// this local-key path derives payTo from the key (never stale), but the
|
|
2336
1517
|
// declaration keeps both writers of the 3009 shape loud-by-default.
|
|
2337
|
-
settlementScheme: "eip3009"
|
|
1518
|
+
settlementScheme: "eip3009",
|
|
1519
|
+
// #3329: `/x402` bodies are camelCase (`X402AuthorizeRequest`) — do not
|
|
1520
|
+
// switch this to `task_budget_id`, which is only the `POST /payments` key.
|
|
1521
|
+
...taskBudgetId ? { taskBudgetId } : {}
|
|
2338
1522
|
});
|
|
2339
1523
|
const state = paymentStateFromRaw("x402 payment", raw);
|
|
2340
|
-
const executedReplay = raw.success && raw.tx_hash ? "idempotency-collision" : state?.nextAction === AgentPaymentNextAction.RetryOriginalX402Request ? "approval-resume" : null;
|
|
1524
|
+
const executedReplay = raw.success && raw.tx_hash ? "idempotency-collision" : state?.nextAction === chunkS42QSWJY_cjs.AgentPaymentNextAction.RetryOriginalX402Request ? "approval-resume" : null;
|
|
2341
1525
|
if (executedReplay) {
|
|
2342
1526
|
const canFund = await this.delegateCanFund(
|
|
2343
1527
|
raw.chain_id ?? state?.chainId ?? chainIdFromNetwork(option.network),
|
|
2344
1528
|
option.asset,
|
|
2345
|
-
x402AuthorizationAmount(option)
|
|
1529
|
+
chunkCK4NLLMO_cjs.x402AuthorizationAmount(option)
|
|
2346
1530
|
);
|
|
2347
1531
|
const refuse = executedReplay === "idempotency-collision" ? canFund !== true : canFund === false;
|
|
2348
1532
|
if (refuse) {
|
|
2349
1533
|
const settledReceipt = state && executedReplay === "approval-resume" ? this.receiptFromStatus(paymentRequired, option, void 0, state) : this.receiptFromAuthorization(paymentRequired, option, void 0, raw);
|
|
2350
|
-
throw new X402AlreadySettledError(
|
|
1534
|
+
throw new chunkS42QSWJY_cjs.X402AlreadySettledError(
|
|
2351
1535
|
canFund === false ? "This x402 payment already settled \u2014 the delegate no longer holds the funds to authorize it again. To buy the same item a second time, pass a distinct `idempotencyKey`; the synthesised key intentionally collapses repeat calls for the same product within a 5-minute window so a retried request cannot pay twice." : "This x402 payment already settled, and whether the delegate can still fund a new authorization could not be verified (no `chainRpcs` entry for this chain). Refusing rather than issue an authorization that may be unfundable. To buy the same item a second time, pass a distinct `idempotencyKey`; to finish an interrupted payment, resume it by `paymentId`.",
|
|
2352
1536
|
settledReceipt,
|
|
2353
1537
|
canFund === false ? "settled" : "unverifiable"
|
|
@@ -2360,16 +1544,19 @@ var X402FundingLeg = class {
|
|
|
2360
1544
|
this.cacheReceipt(idempotencyKey, paymentHeader, receipt2);
|
|
2361
1545
|
return receipt2;
|
|
2362
1546
|
}
|
|
2363
|
-
if (state?.nextAction === AgentPaymentNextAction.RetryOriginalX402Request) {
|
|
1547
|
+
if (state?.nextAction === chunkS42QSWJY_cjs.AgentPaymentNextAction.RetryOriginalX402Request) {
|
|
2364
1548
|
const receipt2 = this.receiptFromStatus(paymentRequired, option, paymentHeader, state);
|
|
2365
1549
|
this.cacheReceipt(idempotencyKey, paymentHeader, receipt2);
|
|
2366
1550
|
return receipt2;
|
|
2367
1551
|
}
|
|
2368
1552
|
this.assertSignableAuthorizationState("x402 payment", raw);
|
|
2369
1553
|
if (!raw.sign_data?.hash) {
|
|
2370
|
-
throw new HavenApiError("No sign_hash returned from x402/authorize", 500, raw);
|
|
1554
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("No sign_hash returned from x402/authorize", 500, raw);
|
|
2371
1555
|
}
|
|
2372
|
-
const sig = await this.signForData(raw.sign_data
|
|
1556
|
+
const sig = await this.signForData(raw.sign_data, {
|
|
1557
|
+
asset: option.asset,
|
|
1558
|
+
amount: chunkCK4NLLMO_cjs.x402AuthorizationAmount(option)
|
|
1559
|
+
});
|
|
2373
1560
|
const execResult = await this.post(
|
|
2374
1561
|
`/payments/${raw.payment_id}/sign`,
|
|
2375
1562
|
{ signature: sig }
|
|
@@ -2388,25 +1575,25 @@ var X402FundingLeg = class {
|
|
|
2388
1575
|
// ── Header minting ───────────────────────────────────────────────
|
|
2389
1576
|
async createPaymentHeader(paymentRequired, option) {
|
|
2390
1577
|
if (!this.delegateKey) {
|
|
2391
|
-
throw new HavenSigningError("delegateKey is required to sign x402 payment headers.");
|
|
1578
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError("delegateKey is required to sign x402 payment headers.");
|
|
2392
1579
|
}
|
|
2393
1580
|
const account = accounts.privateKeyToAccount(this.delegateKey);
|
|
2394
|
-
const requirements = toStandardPaymentRequirements(paymentRequired, option);
|
|
1581
|
+
const requirements = chunkCK4NLLMO_cjs.toStandardPaymentRequirements(paymentRequired, option);
|
|
2395
1582
|
const header = await schemes.exact.evm.createPaymentHeader(
|
|
2396
1583
|
account,
|
|
2397
1584
|
paymentRequired.x402Version,
|
|
2398
1585
|
requirements
|
|
2399
1586
|
);
|
|
2400
1587
|
if (paymentRequired.x402Version < 2) return header;
|
|
2401
|
-
const payment = decodeBase64Json(header);
|
|
2402
|
-
return encodeBase64Json(x402V2PaymentEnvelope(paymentRequired, option, payment.payload));
|
|
1588
|
+
const payment = chunkCK4NLLMO_cjs.decodeBase64Json(header);
|
|
1589
|
+
return chunkCK4NLLMO_cjs.encodeBase64Json(chunkCK4NLLMO_cjs.x402V2PaymentEnvelope(paymentRequired, option, payment.payload));
|
|
2403
1590
|
}
|
|
2404
1591
|
// ── Receipt mapping ──────────────────────────────────────────────
|
|
2405
1592
|
receiptFromAuthorization(paymentRequired, option, paymentHeader, raw, execResult) {
|
|
2406
1593
|
const txHash = execResult?.tx_hash ?? raw.tx_hash ?? "";
|
|
2407
1594
|
const chainId = execResult?.chain_id ?? raw.chain_id ?? chainIdFromNetwork(option.network);
|
|
2408
1595
|
const token = execResult?.token ?? raw.token ?? "USDC";
|
|
2409
|
-
const amount = execResult?.amount ?? raw.amount ?? decimalFromUsdcAtomic(x402AuthorizationAmount(option));
|
|
1596
|
+
const amount = execResult?.amount ?? raw.amount ?? decimalFromUsdcAtomic(chunkCK4NLLMO_cjs.x402AuthorizationAmount(option));
|
|
2410
1597
|
const to = execResult?.to ?? raw.to ?? this.delegateAddress ?? "";
|
|
2411
1598
|
const explorerUrl = execResult?.explorer_url ?? raw.explorer_url ?? explorerUrlOrEmpty(chainId, txHash);
|
|
2412
1599
|
const merchantTo = execResult?.merchant_to ?? raw.merchant_to ?? option.payTo;
|
|
@@ -2428,7 +1615,7 @@ var X402FundingLeg = class {
|
|
|
2428
1615
|
}
|
|
2429
1616
|
receiptFromStatus(paymentRequired, option, paymentHeader, status) {
|
|
2430
1617
|
if (!status.txHash) {
|
|
2431
|
-
throw new HavenApiError(
|
|
1618
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2432
1619
|
`x402 payment ${status.paymentId} is ready to retry but has no Haven transaction hash.`,
|
|
2433
1620
|
502,
|
|
2434
1621
|
status,
|
|
@@ -2439,7 +1626,7 @@ var X402FundingLeg = class {
|
|
|
2439
1626
|
paymentId: status.paymentId,
|
|
2440
1627
|
txHash: status.txHash,
|
|
2441
1628
|
token: status.token || "USDC",
|
|
2442
|
-
amount: status.amount || decimalFromUsdcAtomic(x402AuthorizationAmount(option)),
|
|
1629
|
+
amount: status.amount || decimalFromUsdcAtomic(chunkCK4NLLMO_cjs.x402AuthorizationAmount(option)),
|
|
2443
1630
|
to: this.delegateAddress ?? "",
|
|
2444
1631
|
resourceUrl: paymentRequired.resource.url,
|
|
2445
1632
|
explorerUrl: explorerUrlOrEmpty(status.chainId, status.txHash),
|
|
@@ -2467,7 +1654,7 @@ var X402FundingLeg = class {
|
|
|
2467
1654
|
const provider = createJsonRpcProvider(rpcUrl);
|
|
2468
1655
|
const onChainReceipt = await provider.waitForTransaction(txHash, 1, timeoutMs);
|
|
2469
1656
|
if (!onChainReceipt || onChainReceipt.status !== 1) {
|
|
2470
|
-
throw new HavenApiError(
|
|
1657
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2471
1658
|
"Funding tx did not confirm on-chain within the timeout window.",
|
|
2472
1659
|
500,
|
|
2473
1660
|
{ txHash, chainId }
|
|
@@ -2516,7 +1703,7 @@ var X402FundingLeg = class {
|
|
|
2516
1703
|
};
|
|
2517
1704
|
function getPaymentHeaderValidBefore(paymentHeader) {
|
|
2518
1705
|
try {
|
|
2519
|
-
const payment = decodeBase64Json(
|
|
1706
|
+
const payment = chunkCK4NLLMO_cjs.decodeBase64Json(
|
|
2520
1707
|
paymentHeader
|
|
2521
1708
|
);
|
|
2522
1709
|
const payload = payment.payload;
|
|
@@ -2571,12 +1758,15 @@ var X402Erc7710 = class {
|
|
|
2571
1758
|
*/
|
|
2572
1759
|
async settle(paymentRequired, options = {}) {
|
|
2573
1760
|
if (!this.delegateKey) {
|
|
2574
|
-
throw new HavenSigningError(
|
|
1761
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
2575
1762
|
"delegateKey is required for x402 payments. Pass it in the HavenClient config."
|
|
2576
1763
|
);
|
|
2577
1764
|
}
|
|
2578
1765
|
const prepared = await this.prepare(paymentRequired, options);
|
|
2579
|
-
const signature = await this.signForData(
|
|
1766
|
+
const signature = await this.signForData(
|
|
1767
|
+
prepared.signData,
|
|
1768
|
+
settlementExpectationFromQuote(prepared.settlement)
|
|
1769
|
+
);
|
|
2580
1770
|
const paymentHeader = await this.submit(prepared.paymentId, signature);
|
|
2581
1771
|
return { ...prepared.settlement, paymentHeader };
|
|
2582
1772
|
}
|
|
@@ -2593,21 +1783,21 @@ var X402Erc7710 = class {
|
|
|
2593
1783
|
async prepare(paymentRequired, options = {}) {
|
|
2594
1784
|
const delegationRail = options.delegationRail ?? (await this.getAgent()).executionRail === "delegation";
|
|
2595
1785
|
if (!delegationRail) {
|
|
2596
|
-
throw new HavenApiError(
|
|
1786
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2597
1787
|
"erc7710 settlement requires a delegation-rail account; this one is not on it. Use authorizeX402() for the standard EIP-3009 path.",
|
|
2598
1788
|
400
|
|
2599
1789
|
);
|
|
2600
1790
|
}
|
|
2601
|
-
const selection = selectX402SettlementScheme(paymentRequired.accepts, { delegationRail });
|
|
1791
|
+
const selection = chunkCK4NLLMO_cjs.selectX402SettlementScheme(paymentRequired.accepts, { delegationRail });
|
|
2602
1792
|
if (!selection || selection.scheme !== "erc7710") {
|
|
2603
|
-
throw new HavenApiError(
|
|
1793
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2604
1794
|
"This merchant does not advertise an erc7710 settlement option (no accepts[] entry carries extra.assetTransferMethod: 'erc7710'). Use authorizeX402() for the standard EIP-3009 path.",
|
|
2605
1795
|
400
|
|
2606
1796
|
);
|
|
2607
1797
|
}
|
|
2608
1798
|
const option = selection.option;
|
|
2609
1799
|
const merchantPayTo = option.payTo;
|
|
2610
|
-
const amountAtomic = x402AuthorizationAmount(option);
|
|
1800
|
+
const amountAtomic = chunkCK4NLLMO_cjs.x402AuthorizationAmount(option);
|
|
2611
1801
|
const raw = await this.post("/x402", {
|
|
2612
1802
|
url: options.resourceUrl ?? paymentRequired.resource?.url,
|
|
2613
1803
|
// #2373: the full 402 challenge, persisted verbatim by the backend
|
|
@@ -2642,14 +1832,17 @@ var X402Erc7710 = class {
|
|
|
2642
1832
|
...selection.facilitatorAddresses ? { facilitatorAddresses: selection.facilitatorAddresses } : {},
|
|
2643
1833
|
// #1307/#1547: persisted so the settle leg can rehydrate the merchant
|
|
2644
1834
|
// call by payment_id on this scheme too, not only on the 3009 bridge.
|
|
2645
|
-
...options.mcpCallContext ? { mcpCallContext: options.mcpCallContext } : {}
|
|
1835
|
+
...options.mcpCallContext ? { mcpCallContext: options.mcpCallContext } : {},
|
|
1836
|
+
// #3329: `/x402` bodies are camelCase (`X402AuthorizeRequest`) — do not
|
|
1837
|
+
// switch this to `task_budget_id`, which is only the `POST /payments` key.
|
|
1838
|
+
...options.taskBudgetId ? { taskBudgetId: options.taskBudgetId } : {}
|
|
2646
1839
|
});
|
|
2647
1840
|
if (!raw.payment_id) {
|
|
2648
|
-
throw new HavenApiError("No payment_id returned from x402/authorize", 500, raw);
|
|
1841
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("No payment_id returned from x402/authorize", 500, raw);
|
|
2649
1842
|
}
|
|
2650
1843
|
const signData = raw.sign_data;
|
|
2651
1844
|
if (signData?.signature_scheme !== "eip712_delegation" || !signData.typed_data) {
|
|
2652
|
-
throw new HavenApiError(
|
|
1845
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2653
1846
|
`x402/authorize did not return an erc7710 settlement child (signature_scheme was ${JSON.stringify(signData?.signature_scheme)}). Refusing to sign a payload this path did not ask for.`,
|
|
2654
1847
|
500,
|
|
2655
1848
|
raw
|
|
@@ -2682,7 +1875,7 @@ var X402Erc7710 = class {
|
|
|
2682
1875
|
{ signature }
|
|
2683
1876
|
);
|
|
2684
1877
|
if (!settled.payment_header) {
|
|
2685
|
-
throw new HavenApiError(
|
|
1878
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2686
1879
|
"x402 settle returned no payment_header \u2014 the merchant cannot be retried.",
|
|
2687
1880
|
500,
|
|
2688
1881
|
settled
|
|
@@ -2691,6 +1884,21 @@ var X402Erc7710 = class {
|
|
|
2691
1884
|
return settled.payment_header;
|
|
2692
1885
|
}
|
|
2693
1886
|
};
|
|
1887
|
+
function settlementExpectationFromQuote(settlement) {
|
|
1888
|
+
const chainId = chunkS42QSWJY_cjs.chainIdForNetwork(settlement.network);
|
|
1889
|
+
if (chainId === void 0) {
|
|
1890
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
1891
|
+
`Refusing to sign the x402 settlement child: the merchant's network ${JSON.stringify(settlement.network)} is not one this SDK can verify a settlement child on.`
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
return {
|
|
1895
|
+
merchantTo: settlement.merchantPayTo,
|
|
1896
|
+
amount: settlement.amountAtomic,
|
|
1897
|
+
asset: settlement.asset,
|
|
1898
|
+
chainId,
|
|
1899
|
+
...settlement.facilitatorAddresses && settlement.facilitatorAddresses.length > 0 ? { redeemers: settlement.facilitatorAddresses } : {}
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
2694
1902
|
|
|
2695
1903
|
// src/tool-adapter.ts
|
|
2696
1904
|
function toolX402PaymentRequired(input) {
|
|
@@ -2729,7 +1937,7 @@ function x402ToolReceipt(receipt) {
|
|
|
2729
1937
|
};
|
|
2730
1938
|
}
|
|
2731
1939
|
function toolError(err) {
|
|
2732
|
-
if (err instanceof HavenPaymentStateError) {
|
|
1940
|
+
if (err instanceof chunkS42QSWJY_cjs.HavenPaymentStateError) {
|
|
2733
1941
|
return {
|
|
2734
1942
|
success: false,
|
|
2735
1943
|
payment_id: err.state.paymentId,
|
|
@@ -2774,7 +1982,7 @@ function toolError(err) {
|
|
|
2774
1982
|
error: err.message
|
|
2775
1983
|
};
|
|
2776
1984
|
}
|
|
2777
|
-
if (err instanceof HavenApiError) {
|
|
1985
|
+
if (err instanceof chunkS42QSWJY_cjs.HavenApiError) {
|
|
2778
1986
|
return {
|
|
2779
1987
|
success: false,
|
|
2780
1988
|
status_code: err.statusCode,
|
|
@@ -2811,17 +2019,22 @@ var MerchantCompletion = class {
|
|
|
2811
2019
|
}
|
|
2812
2020
|
async retryRequest(url, initialInit, paymentRequired, receipt) {
|
|
2813
2021
|
if (!receipt.accepted) {
|
|
2814
|
-
throw new HavenApiError("No accepted x402 option was recorded for payment retry", 500);
|
|
2022
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("No accepted x402 option was recorded for payment retry", 500);
|
|
2815
2023
|
}
|
|
2816
2024
|
if (!receipt.paymentHeader) {
|
|
2817
|
-
throw new HavenApiError("No x402 payment header was returned for payment retry", 500);
|
|
2025
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("No x402 payment header was returned for payment retry", 500);
|
|
2818
2026
|
}
|
|
2819
|
-
const retryResponse = await this.merchantTransport.
|
|
2027
|
+
const retryResponse = await this.merchantTransport.deliverPaymentRecoveringSession(
|
|
2820
2028
|
url,
|
|
2821
2029
|
initialInit,
|
|
2822
|
-
receipt.paymentHeader
|
|
2030
|
+
receipt.paymentHeader,
|
|
2031
|
+
() => this.merchantTransport.initialize(url, initialInit)
|
|
2823
2032
|
);
|
|
2824
|
-
|
|
2033
|
+
const toolResult = retryResponse.ok ? await this.merchantTransport.readToolResult(retryResponse) : void 0;
|
|
2034
|
+
const inBandChallenge = toolResult ? extractMcpPaymentRequired(toolResult) : void 0;
|
|
2035
|
+
const metaSettlement = toolResult ? mcpSettlementFromToolResult(toolResult) : void 0;
|
|
2036
|
+
const inBandRejection = inBandChallenge !== void 0 || metaSettlement?.success === false;
|
|
2037
|
+
if (!retryResponse.ok || inBandRejection) {
|
|
2825
2038
|
const merchant = await captureMerchantResponse(retryResponse);
|
|
2826
2039
|
await this.recordRetryRejected({
|
|
2827
2040
|
rail: "x402",
|
|
@@ -2834,9 +2047,9 @@ var MerchantCompletion = class {
|
|
|
2834
2047
|
delegate_to: receipt.to
|
|
2835
2048
|
}
|
|
2836
2049
|
});
|
|
2837
|
-
throw new HavenApiError(
|
|
2050
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2838
2051
|
"x402 retry failed after Haven funded the delegate wallet; reconciliation may be required.",
|
|
2839
|
-
merchant.merchant_status,
|
|
2052
|
+
inBandRejection ? X402_RETRY_REJECTED_STATUS : merchant.merchant_status,
|
|
2840
2053
|
{
|
|
2841
2054
|
marker: "x402_retry_rejected_after_funding",
|
|
2842
2055
|
payment_id: receipt.paymentId,
|
|
@@ -2848,7 +2061,10 @@ var MerchantCompletion = class {
|
|
|
2848
2061
|
}
|
|
2849
2062
|
);
|
|
2850
2063
|
}
|
|
2851
|
-
const
|
|
2064
|
+
const headerReceipt = retryResponse.headers.get("PAYMENT-RESPONSE");
|
|
2065
|
+
const protocolReceiptHeader = headerReceipt ?? (metaSettlement ? encodeMcpSettlementReceipt(metaSettlement) : void 0);
|
|
2066
|
+
const protocolReceiptHeaderName = headerReceipt ? "PAYMENT-RESPONSE" : metaSettlement ? `_meta.${MCP_X402_PAYMENT_RESPONSE_META_KEY}` : void 0;
|
|
2067
|
+
const merchantSettlement = parseMerchantSettlement(protocolReceiptHeader ?? null);
|
|
2852
2068
|
if (receipt.merchant && merchantSettlement.settlementTxHash) {
|
|
2853
2069
|
receipt.merchant.settlementTxHash = merchantSettlement.settlementTxHash;
|
|
2854
2070
|
receipt.merchant.settlementExplorerUrl = buildExplorerUrl(
|
|
@@ -2864,10 +2080,10 @@ var MerchantCompletion = class {
|
|
|
2864
2080
|
merchantStatus: retryResponse.status,
|
|
2865
2081
|
challengePayload: paymentRequired,
|
|
2866
2082
|
selectedPayment: receipt.accepted,
|
|
2867
|
-
paymentProofHeaderName: x402PaymentHeaderNamesSent(receipt.paymentHeader),
|
|
2083
|
+
paymentProofHeaderName: chunkCK4NLLMO_cjs.x402PaymentHeaderNamesSent(receipt.paymentHeader),
|
|
2868
2084
|
paymentProofHeader: receipt.paymentHeader,
|
|
2869
|
-
protocolReceiptHeaderName
|
|
2870
|
-
protocolReceiptHeader
|
|
2085
|
+
protocolReceiptHeaderName,
|
|
2086
|
+
protocolReceiptHeader
|
|
2871
2087
|
});
|
|
2872
2088
|
await this.reportMerchantReceipt(receipt.paymentId, retryResponse);
|
|
2873
2089
|
return retryResponse;
|
|
@@ -2905,18 +2121,18 @@ var MerchantCompletion = class {
|
|
|
2905
2121
|
async resolveCompletionContext(input) {
|
|
2906
2122
|
const status = await this.getPaymentStatus(input.paymentId);
|
|
2907
2123
|
if (status.rail !== "x402") {
|
|
2908
|
-
throw new HavenPaymentStateError(
|
|
2124
|
+
throw new chunkS42QSWJY_cjs.HavenPaymentStateError(
|
|
2909
2125
|
`Payment ${status.paymentId} is ${status.rail}, not x402.`,
|
|
2910
2126
|
409,
|
|
2911
2127
|
status
|
|
2912
2128
|
);
|
|
2913
2129
|
}
|
|
2914
|
-
const readyForMerchantCompletion = input.noFundingLeg ? status.kind === "payment_intent" && status.status === "submitted" : status.nextAction === AgentPaymentNextAction.RetryOriginalX402Request || status.kind === "payment_intent" && status.status === "confirmed" && status.phase === AgentPaymentPhase.PaymentConfirmed && status.nextAction === AgentPaymentNextAction.None;
|
|
2130
|
+
const readyForMerchantCompletion = input.noFundingLeg ? status.kind === "payment_intent" && status.status === "submitted" : status.nextAction === chunkS42QSWJY_cjs.AgentPaymentNextAction.RetryOriginalX402Request || status.kind === "payment_intent" && status.status === "confirmed" && status.phase === chunkS42QSWJY_cjs.AgentPaymentPhase.PaymentConfirmed && status.nextAction === chunkS42QSWJY_cjs.AgentPaymentNextAction.None;
|
|
2915
2131
|
if (!readyForMerchantCompletion) {
|
|
2916
|
-
throw new HavenPaymentStateError(status.message, paymentStateStatusCode(status.status, 409), status);
|
|
2132
|
+
throw new chunkS42QSWJY_cjs.HavenPaymentStateError(status.message, paymentStateStatusCode(status.status, 409), status);
|
|
2917
2133
|
}
|
|
2918
2134
|
if (!input.noFundingLeg && !status.txHash) {
|
|
2919
|
-
throw new HavenApiError(
|
|
2135
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2920
2136
|
`x402 payment ${status.paymentId} is ready for merchant completion but has no Haven transaction hash.`,
|
|
2921
2137
|
502,
|
|
2922
2138
|
status,
|
|
@@ -2925,7 +2141,7 @@ var MerchantCompletion = class {
|
|
|
2925
2141
|
}
|
|
2926
2142
|
const approvedResourceUrl = status.resourceUrl ?? status.x402?.resourceUrl ?? null;
|
|
2927
2143
|
if (approvedResourceUrl && approvedResourceUrl !== input.url) {
|
|
2928
|
-
throw new HavenApiError(
|
|
2144
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
2929
2145
|
"x402 merchant completion does not match the approved resource URL.",
|
|
2930
2146
|
409,
|
|
2931
2147
|
{ status, url: input.url },
|
|
@@ -3011,7 +2227,7 @@ var MerchantCompletion = class {
|
|
|
3011
2227
|
*/
|
|
3012
2228
|
async reportMerchantOutcome(input) {
|
|
3013
2229
|
if (!Number.isInteger(input.merchantStatus) || input.merchantStatus < 100 || input.merchantStatus > 599) {
|
|
3014
|
-
throw new HavenApiError(
|
|
2230
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
3015
2231
|
`merchant_status must be an integer HTTP status from 100 to 599 (received ${input.merchantStatus}).`,
|
|
3016
2232
|
400,
|
|
3017
2233
|
void 0,
|
|
@@ -3020,7 +2236,7 @@ var MerchantCompletion = class {
|
|
|
3020
2236
|
}
|
|
3021
2237
|
const looksAccepted = input.merchantStatus >= 200 && input.merchantStatus < 300;
|
|
3022
2238
|
if (looksAccepted !== (input.outcome === "accepted")) {
|
|
3023
|
-
throw new HavenApiError(
|
|
2239
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
3024
2240
|
`outcome "${input.outcome}" contradicts merchant_status ${input.merchantStatus}: report "accepted" only for a 2xx and "rejected" only for a non-2xx.`,
|
|
3025
2241
|
400,
|
|
3026
2242
|
void 0,
|
|
@@ -3029,14 +2245,14 @@ var MerchantCompletion = class {
|
|
|
3029
2245
|
}
|
|
3030
2246
|
const status = await this.getPaymentStatus(input.paymentId);
|
|
3031
2247
|
if (status.rail !== "x402") {
|
|
3032
|
-
throw new HavenPaymentStateError(
|
|
2248
|
+
throw new chunkS42QSWJY_cjs.HavenPaymentStateError(
|
|
3033
2249
|
`Payment ${status.paymentId} is ${status.rail}, not x402 \u2014 there is no merchant retry to report.`,
|
|
3034
2250
|
409,
|
|
3035
2251
|
status
|
|
3036
2252
|
);
|
|
3037
2253
|
}
|
|
3038
2254
|
if (status.status !== "confirmed" || !status.txHash) {
|
|
3039
|
-
throw new HavenPaymentStateError(
|
|
2255
|
+
throw new chunkS42QSWJY_cjs.HavenPaymentStateError(
|
|
3040
2256
|
`Payment ${status.paymentId} has no confirmed Haven funding transaction to anchor a merchant report to (status ${status.status}). ${status.message}`,
|
|
3041
2257
|
paymentStateStatusCode(status.status, 409),
|
|
3042
2258
|
status
|
|
@@ -3044,7 +2260,7 @@ var MerchantCompletion = class {
|
|
|
3044
2260
|
}
|
|
3045
2261
|
const resourceUrl = status.resourceUrl ?? status.x402?.resourceUrl ?? null;
|
|
3046
2262
|
if (!resourceUrl) {
|
|
3047
|
-
throw new HavenApiError(
|
|
2263
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
3048
2264
|
`Payment ${status.paymentId} has no recorded resource URL, so a merchant report cannot be stored.`,
|
|
3049
2265
|
409,
|
|
3050
2266
|
status,
|
|
@@ -3097,7 +2313,7 @@ var MerchantCompletion = class {
|
|
|
3097
2313
|
await this.post("/machine-payments/evidence", body);
|
|
3098
2314
|
return { outcome: "confirmed" };
|
|
3099
2315
|
} catch (err) {
|
|
3100
|
-
const statusCode = err instanceof HavenApiError ? err.statusCode : void 0;
|
|
2316
|
+
const statusCode = err instanceof chunkS42QSWJY_cjs.HavenApiError ? err.statusCode : void 0;
|
|
3101
2317
|
const retryable = statusCode === EVIDENCE_RETRYABLE_STATUS;
|
|
3102
2318
|
if (!retryable) {
|
|
3103
2319
|
return { outcome: "refused", statusCode: statusCode ?? 0 };
|
|
@@ -3134,7 +2350,7 @@ var MerchantCompletion = class {
|
|
|
3134
2350
|
*/
|
|
3135
2351
|
async reportSettlementEvidence(paymentId, settlementTxHash) {
|
|
3136
2352
|
if (isZeroSettlementTxHash(settlementTxHash)) {
|
|
3137
|
-
throw new HavenZeroSettlementHashError(paymentId);
|
|
2353
|
+
throw new chunkS42QSWJY_cjs.HavenZeroSettlementHashError(paymentId);
|
|
3138
2354
|
}
|
|
3139
2355
|
return this.reportEvidence({
|
|
3140
2356
|
paymentId,
|
|
@@ -3154,7 +2370,7 @@ function parseMerchantSettlement(header) {
|
|
|
3154
2370
|
}
|
|
3155
2371
|
function parseProtocolReceiptHeader(value) {
|
|
3156
2372
|
try {
|
|
3157
|
-
return decodeBase64Json(value);
|
|
2373
|
+
return chunkCK4NLLMO_cjs.decodeBase64Json(value);
|
|
3158
2374
|
} catch {
|
|
3159
2375
|
try {
|
|
3160
2376
|
return JSON.parse(value);
|
|
@@ -3171,7 +2387,7 @@ function x402TypedDataDigest(typedData) {
|
|
|
3171
2387
|
try {
|
|
3172
2388
|
return viem.hashTypedData(typedData);
|
|
3173
2389
|
} catch (err) {
|
|
3174
|
-
throw new HavenSigningError(
|
|
2390
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3175
2391
|
`The x402 funding intent carried a sign_data.typed_data that is not a valid EIP-712 payload (needs domain, types, primaryType, message), so its digest cannot be derived and no signer could accept it. Underlying error: ${err instanceof Error ? err.message : String(err)}`
|
|
3176
2392
|
);
|
|
3177
2393
|
}
|
|
@@ -3253,7 +2469,7 @@ var HavenClient = class {
|
|
|
3253
2469
|
});
|
|
3254
2470
|
this.x402Wallet = config.x402Wallet;
|
|
3255
2471
|
this.merchantTransport = new McpMerchantTransport({ merchantTimeout: config.merchantTimeout });
|
|
3256
|
-
this.confirmationTimeout = config.confirmationTimeout ?? DEFAULT_CONFIRMATION_TIMEOUT_MS;
|
|
2472
|
+
this.confirmationTimeout = config.confirmationTimeout ?? chunkS42QSWJY_cjs.DEFAULT_CONFIRMATION_TIMEOUT_MS;
|
|
3257
2473
|
this.pollingInterval = config.pollingInterval ?? DEFAULT_POLLING_INTERVAL;
|
|
3258
2474
|
this.chainRpcs = config.chainRpcs ?? {};
|
|
3259
2475
|
if (this.delegateKey) {
|
|
@@ -3265,7 +2481,7 @@ var HavenClient = class {
|
|
|
3265
2481
|
x402Wallet: this.x402Wallet,
|
|
3266
2482
|
chainRpcs: this.chainRpcs,
|
|
3267
2483
|
post: (path, body) => this.post(path, body),
|
|
3268
|
-
signForData: (signData) => this.signForData(signData),
|
|
2484
|
+
signForData: (signData, fundingExpectation) => this.signForData(signData, void 0, fundingExpectation),
|
|
3269
2485
|
assertSignableAuthorizationState: (label, raw) => this.throwIfNonSignableAuthorizationState(label, raw)
|
|
3270
2486
|
});
|
|
3271
2487
|
this.merchantCompletion = new MerchantCompletion({
|
|
@@ -3279,7 +2495,7 @@ var HavenClient = class {
|
|
|
3279
2495
|
this.erc7710 = new X402Erc7710({
|
|
3280
2496
|
delegateKey: this.delegateKey,
|
|
3281
2497
|
post: (path, body) => this.post(path, body),
|
|
3282
|
-
signForData: (signData) => this.signForData(signData),
|
|
2498
|
+
signForData: (signData, settlementExpectation) => this.signForData(signData, settlementExpectation),
|
|
3283
2499
|
getAgent: () => this.getAgent()
|
|
3284
2500
|
});
|
|
3285
2501
|
}
|
|
@@ -3301,23 +2517,33 @@ var HavenClient = class {
|
|
|
3301
2517
|
withRequestContext(headers, fn) {
|
|
3302
2518
|
return this.havenApi.withRequestContext(headers, fn);
|
|
3303
2519
|
}
|
|
2520
|
+
/**
|
|
2521
|
+
* The backend's newest `client_update` hint for this client (#3303): inside
|
|
2522
|
+
* a `withRequestContext` dispatch, the one that dispatch's own requests
|
|
2523
|
+
* received; outside one, the latest seen. Undefined when the client is
|
|
2524
|
+
* current or the backend predates #3303.
|
|
2525
|
+
*/
|
|
2526
|
+
clientUpdate() {
|
|
2527
|
+
return this.havenApi.clientUpdate();
|
|
2528
|
+
}
|
|
3304
2529
|
// ── High-Level API ───────────────────────────────────────────────
|
|
3305
2530
|
/**
|
|
3306
2531
|
* Send a payment in one call.
|
|
3307
2532
|
*
|
|
3308
|
-
* Creates the intent, signs
|
|
2533
|
+
* Creates the intent, signs its `sign_data` (a delegation-rail intent's
|
|
2534
|
+
* EIP-712 typed data, after the #3271 UserOp binding check), submits the signature,
|
|
3309
2535
|
* and polls until confirmed (or throws on failure/timeout).
|
|
3310
2536
|
*
|
|
3311
2537
|
* Requires `delegateKey` to be set in the client config.
|
|
3312
2538
|
*/
|
|
3313
2539
|
async pay(request) {
|
|
3314
2540
|
if (!this.delegateKey) {
|
|
3315
|
-
throw new HavenSigningError(
|
|
2541
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3316
2542
|
"Cannot use pay() without a delegateKey. Use createIntent() + submitSignature() for manual signing."
|
|
3317
2543
|
);
|
|
3318
2544
|
}
|
|
3319
2545
|
const intent = await this.createIntent(request);
|
|
3320
|
-
const signature = this.
|
|
2546
|
+
const signature = await this.signForData(intent.signData);
|
|
3321
2547
|
await this.submitSignature(intent.paymentId, signature);
|
|
3322
2548
|
return this.waitForConfirmation(intent.paymentId);
|
|
3323
2549
|
}
|
|
@@ -3332,7 +2558,8 @@ var HavenClient = class {
|
|
|
3332
2558
|
token: request.token,
|
|
3333
2559
|
amount: request.amount,
|
|
3334
2560
|
to: request.to,
|
|
3335
|
-
...request.idempotencyKey ? { idempotency_key: request.idempotencyKey } : {}
|
|
2561
|
+
...request.idempotencyKey ? { idempotency_key: request.idempotencyKey } : {},
|
|
2562
|
+
...request.taskBudgetId ? { task_budget_id: request.taskBudgetId } : {}
|
|
3336
2563
|
});
|
|
3337
2564
|
if (raw.status === "pending_approval") {
|
|
3338
2565
|
throwPaymentStateError("Payment", raw);
|
|
@@ -3361,15 +2588,15 @@ var HavenClient = class {
|
|
|
3361
2588
|
* on-chain allowance — there is nothing to sign until the user approves.
|
|
3362
2589
|
*/
|
|
3363
2590
|
async createX402Intent(paymentRequired, options = {}) {
|
|
3364
|
-
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
2591
|
+
const option = chunkCK4NLLMO_cjs.selectStandardPaymentOption(paymentRequired.accepts);
|
|
3365
2592
|
if (!option) {
|
|
3366
2593
|
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
3367
2594
|
}
|
|
3368
2595
|
const fundingTo = options.delegateAddress ?? (await this.getAgent()).delegateAddress;
|
|
3369
2596
|
if (!fundingTo) {
|
|
3370
|
-
throw new HavenApiError("Authenticated agent has no delegate address registered.", 502);
|
|
2597
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("Authenticated agent has no delegate address registered.", 502);
|
|
3371
2598
|
}
|
|
3372
|
-
const idempotencyKey = options.idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option);
|
|
2599
|
+
const idempotencyKey = options.idempotencyKey ?? chunkCK4NLLMO_cjs.buildX402IdempotencyKey(paymentRequired, option);
|
|
3373
2600
|
const raw = await this.post("/x402", {
|
|
3374
2601
|
url: paymentRequired.resource.url,
|
|
3375
2602
|
payTo: fundingTo,
|
|
@@ -3380,7 +2607,7 @@ var HavenClient = class {
|
|
|
3380
2607
|
// of a silent reroute to the erc7710 settlement branch (the #1358
|
|
3381
2608
|
// review's open-budget misroute). Legacy-rail backends ignore the field.
|
|
3382
2609
|
settlementScheme: "eip3009",
|
|
3383
|
-
amount: x402AuthorizationAmount(option),
|
|
2610
|
+
amount: chunkCK4NLLMO_cjs.x402AuthorizationAmount(option),
|
|
3384
2611
|
asset: option.asset,
|
|
3385
2612
|
network: option.network,
|
|
3386
2613
|
description: paymentRequired.resource.description,
|
|
@@ -3392,21 +2619,25 @@ var HavenClient = class {
|
|
|
3392
2619
|
// the agent passes only payment_id. Bounded: the backend rejects >64KB,
|
|
3393
2620
|
// so an oversized blob is omitted here (signer falls back to the
|
|
3394
2621
|
// caller-supplied copy) rather than failing the intent.
|
|
3395
|
-
...new TextEncoder().encode(JSON.stringify(paymentRequired)).length <= 65536 ? { paymentRequired } : {}
|
|
2622
|
+
...new TextEncoder().encode(JSON.stringify(paymentRequired)).length <= 65536 ? { paymentRequired } : {},
|
|
2623
|
+
// #3329: `/x402` bodies are camelCase (`X402AuthorizeRequest`), unlike
|
|
2624
|
+
// `POST /payments`'s snake_case `task_budget_id` above — the two
|
|
2625
|
+
// surfaces use different conventions, so this key is NOT `task_budget_id`.
|
|
2626
|
+
...options.taskBudgetId ? { taskBudgetId: options.taskBudgetId } : {}
|
|
3396
2627
|
});
|
|
3397
2628
|
if (raw.status !== "pending_signature") {
|
|
3398
2629
|
throwPaymentStateError("x402 payment", raw);
|
|
3399
2630
|
}
|
|
3400
2631
|
if (!raw.sign_data?.hash) {
|
|
3401
|
-
throw new HavenApiError("No sign_hash returned from x402/authorize", 500, raw);
|
|
2632
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("No sign_hash returned from x402/authorize", 500, raw);
|
|
3402
2633
|
}
|
|
3403
2634
|
if (raw.sign_data.signature_scheme !== void 0 && !raw.sign_data.typed_data) {
|
|
3404
|
-
throw new HavenSigningError(
|
|
2635
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3405
2636
|
`This account's x402 funding intent declares signature scheme '${raw.sign_data.signature_scheme}' but carried no typed_data to sign. Refusing to fall back to the bare hash \u2014 the account would reject that signature on-chain. This is a backend contract violation; report it rather than working around it.`
|
|
3406
2637
|
);
|
|
3407
2638
|
}
|
|
3408
2639
|
if (!raw.x402_expected_auth) {
|
|
3409
|
-
throw new HavenApiError("No x402 expected-context binding returned from x402/authorize", 500, raw);
|
|
2640
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("No x402 expected-context binding returned from x402/authorize", 500, raw);
|
|
3410
2641
|
}
|
|
3411
2642
|
return {
|
|
3412
2643
|
paymentId: raw.payment_id,
|
|
@@ -3417,7 +2648,7 @@ var HavenClient = class {
|
|
|
3417
2648
|
accepted: option,
|
|
3418
2649
|
resourceUrl: paymentRequired.resource.url,
|
|
3419
2650
|
merchantTo: raw.merchant_to ?? option.payTo,
|
|
3420
|
-
amountAtomic: x402AuthorizationAmount(option),
|
|
2651
|
+
amountAtomic: chunkCK4NLLMO_cjs.x402AuthorizationAmount(option),
|
|
3421
2652
|
asset: option.asset,
|
|
3422
2653
|
network: option.network,
|
|
3423
2654
|
expectedAuth: raw.x402_expected_auth,
|
|
@@ -3442,13 +2673,13 @@ var HavenClient = class {
|
|
|
3442
2673
|
*/
|
|
3443
2674
|
sign(hash) {
|
|
3444
2675
|
if (!this.delegateKey) {
|
|
3445
|
-
throw new HavenSigningError(
|
|
2676
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3446
2677
|
"Cannot sign without a delegateKey. Pass the private key in HavenClient config, or sign externally."
|
|
3447
2678
|
);
|
|
3448
2679
|
}
|
|
3449
2680
|
const signature = signHash(this.delegateKey, hash);
|
|
3450
2681
|
if (!verifySignature(hash, signature, this.delegateAddress)) {
|
|
3451
|
-
throw new HavenSigningError(
|
|
2682
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3452
2683
|
"Local signature verification failed \u2014 recovered address does not match delegate key."
|
|
3453
2684
|
);
|
|
3454
2685
|
}
|
|
@@ -3464,40 +2695,58 @@ var HavenClient = class {
|
|
|
3464
2695
|
* (#834) — the backend refuses those intents with HTTP 410 before any
|
|
3465
2696
|
* sign_data reaches a client, so encountering it here is a hard error too.
|
|
3466
2697
|
*/
|
|
3467
|
-
async signForData(signData) {
|
|
2698
|
+
async signForData(signData, settlementExpectation, fundingExpectation) {
|
|
3468
2699
|
if (!this.delegateKey) {
|
|
3469
|
-
throw new HavenSigningError(
|
|
2700
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3470
2701
|
"Cannot sign without a delegateKey. Pass the private key in HavenClient config, or sign externally."
|
|
3471
2702
|
);
|
|
3472
2703
|
}
|
|
3473
2704
|
const scheme = signData.signature_scheme;
|
|
3474
2705
|
if (scheme === "eip191_userop") {
|
|
3475
|
-
throw new HavenSigningError(
|
|
2706
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3476
2707
|
"The session rail is retired \u2014 'eip191_userop' intents can no longer be signed. Re-onboard the account on the delegation rail."
|
|
3477
2708
|
);
|
|
3478
2709
|
}
|
|
3479
2710
|
if (scheme === "eip712_userop") {
|
|
3480
2711
|
if (!signData.typed_data) {
|
|
3481
|
-
throw new HavenSigningError(
|
|
2712
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3482
2713
|
"sign_data.signature_scheme is eip712_userop but typed_data is missing \u2014 refusing to sign the bare hash (the account would reject it)."
|
|
3483
2714
|
);
|
|
3484
2715
|
}
|
|
2716
|
+
chunkS42QSWJY_cjs.assertUserOpTypedDataBinding(signData.typed_data, signData.hash);
|
|
2717
|
+
chunkCK4NLLMO_cjs.assertBoundDirectPaymentUserOp(
|
|
2718
|
+
signData.typed_data,
|
|
2719
|
+
this.delegateAddress
|
|
2720
|
+
);
|
|
2721
|
+
if (fundingExpectation) {
|
|
2722
|
+
chunkCK4NLLMO_cjs.assertFundingLegPaysDelegate(signData.typed_data, {
|
|
2723
|
+
delegateAddress: this.delegateAddress,
|
|
2724
|
+
asset: fundingExpectation.asset,
|
|
2725
|
+
amount: fundingExpectation.amount
|
|
2726
|
+
});
|
|
2727
|
+
}
|
|
3485
2728
|
return signUserOpTypedDataForDelegation(this.delegateKey, signData.typed_data);
|
|
3486
2729
|
}
|
|
3487
2730
|
if (scheme === "eip712_delegation") {
|
|
3488
2731
|
if (!signData.typed_data) {
|
|
3489
|
-
throw new HavenSigningError(
|
|
2732
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3490
2733
|
"sign_data.signature_scheme is eip712_delegation but typed_data is missing \u2014 refusing to sign the bare hash (the settlement would be rejected on redemption)."
|
|
3491
2734
|
);
|
|
3492
2735
|
}
|
|
2736
|
+
if (!settlementExpectation) {
|
|
2737
|
+
throw new chunkCK4NLLMO_cjs.HavenTypedDataRefusedError(
|
|
2738
|
+
"Refusing to sign an x402 settlement child without an independent expectation of what it must pay (the merchant's 402). Pay erc7710 merchants through settleX402Erc7710(), which supplies it."
|
|
2739
|
+
);
|
|
2740
|
+
}
|
|
2741
|
+
chunkCK4NLLMO_cjs.assertOwnSettlementChild(signData.typed_data, settlementExpectation, this.delegateAddress);
|
|
3493
2742
|
return signSettlementDelegationTypedData(this.delegateKey, signData.typed_data);
|
|
3494
2743
|
}
|
|
3495
2744
|
if (scheme === void 0) {
|
|
3496
|
-
throw new HavenSigningError(
|
|
2745
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3497
2746
|
"sign_data.signature_scheme is required \u2014 the legacy AllowanceModule rail that signed the bare hash is retired (#2850). Refusing to guess a signing scheme."
|
|
3498
2747
|
);
|
|
3499
2748
|
}
|
|
3500
|
-
throw new HavenSigningError(
|
|
2749
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3501
2750
|
`Unknown sign_data.signature_scheme '${scheme}' \u2014 refusing to guess a signing scheme. Update @haven_ai/sdk.`
|
|
3502
2751
|
);
|
|
3503
2752
|
}
|
|
@@ -3550,11 +2799,12 @@ var HavenClient = class {
|
|
|
3550
2799
|
return this.accountReads.getAgentSummary();
|
|
3551
2800
|
}
|
|
3552
2801
|
/**
|
|
3553
|
-
* Sweep stranded USDC and ETH from the delegate EOA back to the
|
|
2802
|
+
* Sweep stranded USDC and ETH from the delegate EOA back to the agent's Haven account.
|
|
3554
2803
|
*
|
|
3555
2804
|
* The delegate key held by this client signs and submits the transfer transactions
|
|
3556
2805
|
* directly — Haven's backend never handles the key or constructs signed txs
|
|
3557
|
-
* (CASP/MiCA Red Line #2). Funds always go to the
|
|
2806
|
+
* (CASP/MiCA Red Line #2). Funds always go to the Haven account linked to this agent
|
|
2807
|
+
* (`accountAddress` from `getAgent()`).
|
|
3558
2808
|
*
|
|
3559
2809
|
* Requires `chainRpcs` to be set for the agent's chain in `HavenClientConfig`.
|
|
3560
2810
|
*/
|
|
@@ -3680,7 +2930,7 @@ var HavenClient = class {
|
|
|
3680
2930
|
*/
|
|
3681
2931
|
async getPaymentStatusWithPostPurchaseAllowance(paymentId) {
|
|
3682
2932
|
const status = await this.getPaymentStatus(paymentId);
|
|
3683
|
-
if (status.rail === AgentPaymentRail.X402 && status.phase === AgentPaymentPhase.PaymentConfirmed) {
|
|
2933
|
+
if (status.rail === chunkS42QSWJY_cjs.AgentPaymentRail.X402 && status.phase === chunkS42QSWJY_cjs.AgentPaymentPhase.PaymentConfirmed) {
|
|
3684
2934
|
const { allowance, warnings } = await this.getPostPurchaseAllowanceSummary(paymentId);
|
|
3685
2935
|
return { ...status, allowance, ...warnings.length > 0 ? { warnings } : {} };
|
|
3686
2936
|
}
|
|
@@ -3766,6 +3016,96 @@ var HavenClient = class {
|
|
|
3766
3016
|
async getReceipt(paymentId) {
|
|
3767
3017
|
return this.accountReads.getReceipt(paymentId);
|
|
3768
3018
|
}
|
|
3019
|
+
// ── Task Budgets (#3329) ────────────────────────────────────────────
|
|
3020
|
+
/**
|
|
3021
|
+
* Open a task budget: a self-delegated, time-boxed slice of the agent's own
|
|
3022
|
+
* budget delegation. Returns the pending row plus the child delegation's
|
|
3023
|
+
* `sign_data` — sign it (via `signForData` / `haven_sign` with
|
|
3024
|
+
* `task_budget_id`) and pass the signature to `submitTaskBudget` to make it
|
|
3025
|
+
* OPEN. Nothing is on-chain until then.
|
|
3026
|
+
*/
|
|
3027
|
+
async openTaskBudget(request) {
|
|
3028
|
+
const raw = await this.post("/task-budgets", {
|
|
3029
|
+
...request.tokenAddress ? { token_address: request.tokenAddress } : {},
|
|
3030
|
+
max_amount_atomic: request.maxAmountAtomic,
|
|
3031
|
+
ttl_seconds: request.ttlSeconds,
|
|
3032
|
+
...request.recipientAddress ? { recipient_address: request.recipientAddress } : {},
|
|
3033
|
+
...request.label ? { label: request.label } : {}
|
|
3034
|
+
});
|
|
3035
|
+
return {
|
|
3036
|
+
taskBudget: mapTaskBudget(raw.task_budget),
|
|
3037
|
+
signData: raw.sign_data,
|
|
3038
|
+
nextAction: raw.next_action,
|
|
3039
|
+
instructions: raw.instructions
|
|
3040
|
+
};
|
|
3041
|
+
}
|
|
3042
|
+
/** Read one task budget by id. */
|
|
3043
|
+
async getTaskBudget(id) {
|
|
3044
|
+
const raw = await this.get(`/task-budgets/${encodeURIComponent(id)}`);
|
|
3045
|
+
return mapTaskBudget(raw.task_budget);
|
|
3046
|
+
}
|
|
3047
|
+
/** List this agent's task budgets — `status: 'open'` (default; unexpired only) or `'all'`. */
|
|
3048
|
+
async listTaskBudgets(options = {}) {
|
|
3049
|
+
const query = options.status ? `?status=${encodeURIComponent(options.status)}` : "";
|
|
3050
|
+
const raw = await this.get(`/task-budgets${query}`);
|
|
3051
|
+
return raw.task_budgets.map(mapTaskBudget);
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* The exact signing payload for a pending (purpose `open`) or closing
|
|
3055
|
+
* (purpose `close`) task budget — the `task_budget_id` counterpart of
|
|
3056
|
+
* `getResumeState` / the payment sign-context reads. `haven_sign` with
|
|
3057
|
+
* `task_budget_id` fetches this itself; call it directly only for manual
|
|
3058
|
+
* signing.
|
|
3059
|
+
*/
|
|
3060
|
+
async getTaskBudgetSignContext(id) {
|
|
3061
|
+
const raw = await this.get(`/task-budgets/${encodeURIComponent(id)}/sign-context`);
|
|
3062
|
+
if (raw.purpose === "close") {
|
|
3063
|
+
return {
|
|
3064
|
+
taskBudgetId: raw.task_budget_id,
|
|
3065
|
+
purpose: "close",
|
|
3066
|
+
taskSignContextVersion: raw.task_sign_context_version,
|
|
3067
|
+
typedData: raw.typed_data,
|
|
3068
|
+
userOperation: raw.user_operation,
|
|
3069
|
+
userOpHash: raw.user_op_hash,
|
|
3070
|
+
expected: raw.expected
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
return {
|
|
3074
|
+
taskBudgetId: raw.task_budget_id,
|
|
3075
|
+
purpose: "open",
|
|
3076
|
+
taskSignContextVersion: raw.task_sign_context_version,
|
|
3077
|
+
typedData: raw.typed_data,
|
|
3078
|
+
expected: raw.expected
|
|
3079
|
+
};
|
|
3080
|
+
}
|
|
3081
|
+
/** Submit a signature for a pending (open) or closing task budget. */
|
|
3082
|
+
async submitTaskBudget(id, signature) {
|
|
3083
|
+
const raw = await this.post(
|
|
3084
|
+
`/task-budgets/${encodeURIComponent(id)}/submit`,
|
|
3085
|
+
{ signature }
|
|
3086
|
+
);
|
|
3087
|
+
return {
|
|
3088
|
+
taskBudget: mapTaskBudget(raw.task_budget),
|
|
3089
|
+
status: raw.status,
|
|
3090
|
+
...raw.close_tx_hash ? { closeTxHash: raw.close_tx_hash } : {}
|
|
3091
|
+
};
|
|
3092
|
+
}
|
|
3093
|
+
/**
|
|
3094
|
+
* Close a task budget early. A `pending` or already-expired `open` budget
|
|
3095
|
+
* closes immediately (nothing was ever signed or is on-chain). A live
|
|
3096
|
+
* `open` budget returns `sign_data` for an on-chain `disableDelegation`
|
|
3097
|
+
* UserOp — sign it (`haven_sign` with `task_budget_id`) and call
|
|
3098
|
+
* `submitTaskBudget`.
|
|
3099
|
+
*/
|
|
3100
|
+
async closeTaskBudget(id) {
|
|
3101
|
+
const raw = await this.post(`/task-budgets/${encodeURIComponent(id)}/close`, {});
|
|
3102
|
+
return {
|
|
3103
|
+
taskBudget: mapTaskBudget(raw.task_budget),
|
|
3104
|
+
status: raw.status,
|
|
3105
|
+
...raw.sign_data ? { signData: raw.sign_data } : {},
|
|
3106
|
+
...raw.next_action ? { nextAction: raw.next_action } : {}
|
|
3107
|
+
};
|
|
3108
|
+
}
|
|
3769
3109
|
/**
|
|
3770
3110
|
* Rehydrate the x402 resume-state bundle for a payment id (#1328: the MPP
|
|
3771
3111
|
* resume-state variant retired along with the rest of the mpp_demo surface).
|
|
@@ -3788,7 +3128,7 @@ var HavenClient = class {
|
|
|
3788
3128
|
}
|
|
3789
3129
|
await sleep(this.pollingInterval);
|
|
3790
3130
|
}
|
|
3791
|
-
throw new HavenTimeoutError(paymentId);
|
|
3131
|
+
throw new chunkS42QSWJY_cjs.HavenTimeoutError(paymentId);
|
|
3792
3132
|
}
|
|
3793
3133
|
// ── x402 Protocol Support ────────────────────────────────────────
|
|
3794
3134
|
/**
|
|
@@ -3802,23 +3142,23 @@ var HavenClient = class {
|
|
|
3802
3142
|
*/
|
|
3803
3143
|
async authorizeX402(paymentRequired, options = {}) {
|
|
3804
3144
|
if (!this.delegateKey) {
|
|
3805
|
-
throw new HavenSigningError(
|
|
3145
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3806
3146
|
"delegateKey is required for x402 payments. Pass it in the HavenClient config."
|
|
3807
3147
|
);
|
|
3808
3148
|
}
|
|
3809
3149
|
if (!this.delegateAddress) {
|
|
3810
|
-
throw new HavenSigningError("delegateAddress could not be derived from delegateKey.");
|
|
3150
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError("delegateAddress could not be derived from delegateKey.");
|
|
3811
3151
|
}
|
|
3812
|
-
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
3152
|
+
const option = chunkCK4NLLMO_cjs.selectStandardPaymentOption(paymentRequired.accepts);
|
|
3813
3153
|
if (!option) {
|
|
3814
3154
|
throw noCompatiblePaymentOptionError(paymentRequired.accepts);
|
|
3815
3155
|
}
|
|
3816
|
-
const idempotencyKey = options.idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option);
|
|
3156
|
+
const idempotencyKey = options.idempotencyKey ?? chunkCK4NLLMO_cjs.buildX402IdempotencyKey(paymentRequired, option);
|
|
3817
3157
|
const cached = this.fundingLeg.cachedReceipt(idempotencyKey);
|
|
3818
3158
|
if (cached) return cached;
|
|
3819
3159
|
const inFlight = this.inFlightX402.get(idempotencyKey);
|
|
3820
3160
|
if (inFlight) return inFlight;
|
|
3821
|
-
const promise = this.fundingLeg.authorize(paymentRequired, option, idempotencyKey);
|
|
3161
|
+
const promise = this.fundingLeg.authorize(paymentRequired, option, idempotencyKey, options.taskBudgetId);
|
|
3822
3162
|
this.inFlightX402.set(idempotencyKey, promise);
|
|
3823
3163
|
try {
|
|
3824
3164
|
return await promise;
|
|
@@ -3842,22 +3182,27 @@ var HavenClient = class {
|
|
|
3842
3182
|
const request = snapshotX402Request(url, initialInit);
|
|
3843
3183
|
const response = await this.merchantTransport.fetch(url, initialInit);
|
|
3844
3184
|
if (response.status !== 402) {
|
|
3185
|
+
const toolResultChallenge = await this.merchantTransport.extractToolResultChallenge(response, initialInit);
|
|
3186
|
+
if (toolResultChallenge) {
|
|
3187
|
+
const mcpTransport2 = await this.merchantTransport.detect(url, toolResultChallenge, response);
|
|
3188
|
+
return buildX402Quote(toolResultChallenge, request, options.idempotencyKey, mcpTransport2);
|
|
3189
|
+
}
|
|
3845
3190
|
let body;
|
|
3846
3191
|
try {
|
|
3847
3192
|
body = await response.clone().json();
|
|
3848
3193
|
} catch {
|
|
3849
3194
|
body = void 0;
|
|
3850
3195
|
}
|
|
3851
|
-
throw new X402UnexpectedStatusError(
|
|
3196
|
+
throw new chunkS42QSWJY_cjs.X402UnexpectedStatusError(
|
|
3852
3197
|
`Expected an x402 quote response with HTTP 402, got HTTP ${response.status}.`,
|
|
3853
3198
|
response.status || 400,
|
|
3854
3199
|
body
|
|
3855
3200
|
);
|
|
3856
3201
|
}
|
|
3857
3202
|
if (response.headers.get("MACHINE-PAYMENT-CHALLENGE")) {
|
|
3858
|
-
throw new HavenApiError("quoteX402 only supports standard x402 Payment Required responses.", 400);
|
|
3203
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("quoteX402 only supports standard x402 Payment Required responses.", 400);
|
|
3859
3204
|
}
|
|
3860
|
-
const paymentRequired = await parsePaymentRequiredResponse(response);
|
|
3205
|
+
const paymentRequired = await chunkCK4NLLMO_cjs.parsePaymentRequiredResponse(response);
|
|
3861
3206
|
const mcpTransport = await this.merchantTransport.detect(url, paymentRequired, response);
|
|
3862
3207
|
return buildX402Quote(paymentRequired, request, options.idempotencyKey, mcpTransport);
|
|
3863
3208
|
}
|
|
@@ -3875,7 +3220,7 @@ var HavenClient = class {
|
|
|
3875
3220
|
const wallet = await this.merchantCompletion.resolveWalletForMerchantCall();
|
|
3876
3221
|
const sessionId = await this.merchantTransport.initialize(url, init, wallet);
|
|
3877
3222
|
if (!sessionId) {
|
|
3878
|
-
throw new HavenApiError(
|
|
3223
|
+
throw new chunkS42QSWJY_cjs.HavenApiError(
|
|
3879
3224
|
"The merchant did not establish an MCP session before the x402 quote. No payment was created.",
|
|
3880
3225
|
502,
|
|
3881
3226
|
{ mcpSessionNotEstablished: true }
|
|
@@ -3895,7 +3240,7 @@ var HavenClient = class {
|
|
|
3895
3240
|
async payX402Quote(quote, options = {}) {
|
|
3896
3241
|
const idempotencyKey = options.idempotencyKey ?? quote.idempotencyKey;
|
|
3897
3242
|
try {
|
|
3898
|
-
const receipt = await this.authorizeX402(quote.paymentRequired, { idempotencyKey });
|
|
3243
|
+
const receipt = await this.authorizeX402(quote.paymentRequired, { ...options, idempotencyKey });
|
|
3899
3244
|
return this.merchantCompletion.retryRequest(
|
|
3900
3245
|
quote.request.url,
|
|
3901
3246
|
requestInitFromSnapshot(quote.request),
|
|
@@ -3949,18 +3294,18 @@ var HavenClient = class {
|
|
|
3949
3294
|
}
|
|
3950
3295
|
async resumeAuthorizedX402(input) {
|
|
3951
3296
|
if (!this.delegateKey) {
|
|
3952
|
-
throw new HavenSigningError(
|
|
3297
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError(
|
|
3953
3298
|
"delegateKey is required for x402 payments. Pass it in the HavenClient config."
|
|
3954
3299
|
);
|
|
3955
3300
|
}
|
|
3956
3301
|
if (!this.delegateAddress) {
|
|
3957
|
-
throw new HavenSigningError("delegateAddress could not be derived from delegateKey.");
|
|
3302
|
+
throw new chunkS42QSWJY_cjs.HavenSigningError("delegateAddress could not be derived from delegateKey.");
|
|
3958
3303
|
}
|
|
3959
|
-
const option = selectStandardPaymentOption(input.paymentRequired.accepts);
|
|
3304
|
+
const option = chunkCK4NLLMO_cjs.selectStandardPaymentOption(input.paymentRequired.accepts);
|
|
3960
3305
|
if (!option) {
|
|
3961
3306
|
throw noCompatiblePaymentOptionError(input.paymentRequired.accepts);
|
|
3962
3307
|
}
|
|
3963
|
-
const idempotencyKey = input.idempotencyKey ?? buildX402IdempotencyKey(input.paymentRequired, option);
|
|
3308
|
+
const idempotencyKey = input.idempotencyKey ?? chunkCK4NLLMO_cjs.buildX402IdempotencyKey(input.paymentRequired, option);
|
|
3964
3309
|
const cached = this.fundingLeg.cachedReceipt(idempotencyKey);
|
|
3965
3310
|
if (cached) return cached;
|
|
3966
3311
|
const status = await this.getPaymentStatus(input.paymentId);
|
|
@@ -3968,10 +3313,10 @@ var HavenClient = class {
|
|
|
3968
3313
|
const canFund = await this.fundingLeg.delegateCanFund(
|
|
3969
3314
|
status.chainId ?? chainIdFromNetwork(option.network),
|
|
3970
3315
|
option.asset,
|
|
3971
|
-
x402AuthorizationAmount(option)
|
|
3316
|
+
chunkCK4NLLMO_cjs.x402AuthorizationAmount(option)
|
|
3972
3317
|
);
|
|
3973
3318
|
if (canFund === false) {
|
|
3974
|
-
throw new X402AlreadySettledError(
|
|
3319
|
+
throw new chunkS42QSWJY_cjs.X402AlreadySettledError(
|
|
3975
3320
|
`x402 payment ${status.paymentId} has already settled \u2014 the delegate no longer holds the funds to authorize it again, so there is nothing left to resume.`,
|
|
3976
3321
|
this.fundingLeg.receiptFromStatus(input.paymentRequired, option, void 0, status),
|
|
3977
3322
|
"settled"
|
|
@@ -3992,13 +3337,13 @@ var HavenClient = class {
|
|
|
3992
3337
|
const url = input.url ?? input.request?.url;
|
|
3993
3338
|
if (!paymentRequired) {
|
|
3994
3339
|
if (!url) {
|
|
3995
|
-
throw new HavenApiError("x402 resume requires the original URL or a captured request snapshot.", 400);
|
|
3340
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("x402 resume requires the original URL or a captured request snapshot.", 400);
|
|
3996
3341
|
}
|
|
3997
3342
|
const response = await this.merchantTransport.fetch(url, initialInit);
|
|
3998
3343
|
if (response.status !== 402) {
|
|
3999
|
-
throw new HavenApiError("Expected the original x402 request to return HTTP 402 before resuming.", 400);
|
|
3344
|
+
throw new chunkS42QSWJY_cjs.HavenApiError("Expected the original x402 request to return HTTP 402 before resuming.", 400);
|
|
4000
3345
|
}
|
|
4001
|
-
paymentRequired = await parsePaymentRequiredResponse(response);
|
|
3346
|
+
paymentRequired = await chunkCK4NLLMO_cjs.parsePaymentRequiredResponse(response);
|
|
4002
3347
|
}
|
|
4003
3348
|
const receipt = await this.resumeAuthorizedX402({
|
|
4004
3349
|
paymentId: input.paymentId,
|
|
@@ -4008,10 +3353,11 @@ var HavenClient = class {
|
|
|
4008
3353
|
return this.merchantCompletion.retryRequest(url ?? paymentRequired.resource.url, initialInit, paymentRequired, receipt);
|
|
4009
3354
|
}
|
|
4010
3355
|
/**
|
|
4011
|
-
* Fetch wrapper that automatically handles HTTP 402 responses
|
|
3356
|
+
* Fetch wrapper that automatically handles HTTP 402 responses — and, since
|
|
3357
|
+
* #3118, a native-MCP payment-required tool result answered under HTTP 200.
|
|
4012
3358
|
*
|
|
4013
|
-
* Works like the standard `fetch()` but intercepts 402 responses
|
|
4014
|
-
* pays via x402 through Haven, and retries the request.
|
|
3359
|
+
* Works like the standard `fetch()` but intercepts 402 responses (or that
|
|
3360
|
+
* tool-result challenge), pays via x402 through Haven, and retries the request.
|
|
4015
3361
|
*
|
|
4016
3362
|
* ```ts
|
|
4017
3363
|
* const response = await haven.fetch('https://paid-api.com/data')
|
|
@@ -4019,8 +3365,9 @@ var HavenClient = class {
|
|
|
4019
3365
|
* ```
|
|
4020
3366
|
*
|
|
4021
3367
|
* **MCP-over-x402 auto-handshake (issue #315):** when the endpoint is
|
|
4022
|
-
* MCP-shaped — the URL path ends in `/mcp`, or the 402 body
|
|
4023
|
-
*
|
|
3368
|
+
* MCP-shaped — the URL path ends in `/mcp`, or the 402 body (or, since
|
|
3369
|
+
* #3118, the tool-result challenge) carries a Coinbase Bazaar
|
|
3370
|
+
* `extensions.bazaar` block — the SDK runs the MCP
|
|
4024
3371
|
* `initialize` handshake, threads the resulting `mcp-session-id`,
|
|
4025
3372
|
* `Accept: application/json, text/event-stream`, and `x402-wallet` headers
|
|
4026
3373
|
* through every request, and collapses SSE responses to the JSON-RPC
|
|
@@ -4038,22 +3385,29 @@ var HavenClient = class {
|
|
|
4038
3385
|
let requestInit = withX402Wallet(init, x402PayerAddress(this.delegateAddress, this.x402Wallet));
|
|
4039
3386
|
if (mcpSessionId) requestInit = this.merchantTransport.withSessionHeaders(requestInit, mcpSessionId);
|
|
4040
3387
|
const response = await this.merchantTransport.fetch(url, requestInit);
|
|
4041
|
-
if (response.status !== 402) {
|
|
4042
|
-
return mcpSessionId ? this.merchantTransport.surfaceResult(response) : response;
|
|
4043
|
-
}
|
|
4044
3388
|
let paymentRequired;
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
3389
|
+
let nativeChallenge = false;
|
|
3390
|
+
if (response.status !== 402) {
|
|
3391
|
+
const toolResultChallenge = await this.merchantTransport.extractToolResultChallenge(response, requestInit);
|
|
3392
|
+
if (!toolResultChallenge) {
|
|
3393
|
+
return mcpSessionId ? this.merchantTransport.surfaceResult(response) : response;
|
|
3394
|
+
}
|
|
3395
|
+
paymentRequired = toolResultChallenge;
|
|
3396
|
+
nativeChallenge = true;
|
|
3397
|
+
} else {
|
|
3398
|
+
try {
|
|
3399
|
+
paymentRequired = await chunkCK4NLLMO_cjs.parsePaymentRequiredResponse(response);
|
|
3400
|
+
} catch {
|
|
3401
|
+
return response;
|
|
3402
|
+
}
|
|
4049
3403
|
}
|
|
4050
|
-
if (!mcpSessionId && await this.merchantTransport.hasBazaarExtension(response)) {
|
|
3404
|
+
if (!mcpSessionId && (paymentRequired.extensions?.bazaar != null || await this.merchantTransport.hasBazaarExtension(response))) {
|
|
4051
3405
|
mcpSessionId = await this.merchantTransport.initialize(url, init);
|
|
4052
3406
|
if (mcpSessionId) requestInit = this.merchantTransport.withSessionHeaders(requestInit, mcpSessionId);
|
|
4053
3407
|
}
|
|
4054
3408
|
const request = snapshotX402Request(url, requestInit);
|
|
4055
|
-
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
4056
|
-
const idempotencyKey = options.idempotencyKey ?? (option ? buildX402IdempotencyKey(paymentRequired, option) : void 0);
|
|
3409
|
+
const option = chunkCK4NLLMO_cjs.selectStandardPaymentOption(paymentRequired.accepts);
|
|
3410
|
+
const idempotencyKey = options.idempotencyKey ?? (option ? chunkCK4NLLMO_cjs.buildX402IdempotencyKey(paymentRequired, option) : void 0);
|
|
4057
3411
|
let receipt;
|
|
4058
3412
|
try {
|
|
4059
3413
|
receipt = await this.authorizeX402(paymentRequired, options);
|
|
@@ -4069,7 +3423,7 @@ var HavenClient = class {
|
|
|
4069
3423
|
throw err;
|
|
4070
3424
|
}
|
|
4071
3425
|
const retryResponse = await this.merchantCompletion.retryRequest(url, requestInit, paymentRequired, receipt);
|
|
4072
|
-
return mcpSessionId ? this.merchantTransport.surfaceResult(retryResponse) : retryResponse;
|
|
3426
|
+
return mcpSessionId || nativeChallenge ? this.merchantTransport.surfaceResult(retryResponse) : retryResponse;
|
|
4073
3427
|
}
|
|
4074
3428
|
/**
|
|
4075
3429
|
* Deliver an already-signed x402 payment header to the merchant and return
|
|
@@ -4090,7 +3444,7 @@ var HavenClient = class {
|
|
|
4090
3444
|
* collapses an SSE JSON-RPC response to its `result`.
|
|
4091
3445
|
*/
|
|
4092
3446
|
/**
|
|
4093
|
-
* Wait for a payment's
|
|
3447
|
+
* Wait for a payment's account→delegate funding tx to reach ≥1 on-chain
|
|
4094
3448
|
* confirmation. The hosted x402 completion path MUST call this after funding
|
|
4095
3449
|
* and before delivering the merchant payment header, so the merchant's
|
|
4096
3450
|
* balanceOf(delegate) / transferWithAuthorization verification sees the funded
|
|
@@ -4129,10 +3483,13 @@ var HavenClient = class {
|
|
|
4129
3483
|
}
|
|
4130
3484
|
let requestInit = withX402Wallet(input.init, x402Wallet) ?? {};
|
|
4131
3485
|
if (mcpSessionId) requestInit = this.merchantTransport.withSessionHeaders(requestInit, mcpSessionId);
|
|
4132
|
-
const response = await this.merchantTransport.
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
3486
|
+
const response = await this.merchantTransport.deliverPaymentRecoveringSession(
|
|
3487
|
+
input.url,
|
|
3488
|
+
requestInit,
|
|
3489
|
+
input.paymentHeader,
|
|
3490
|
+
() => this.merchantTransport.initialize(input.url, input.init, x402Wallet)
|
|
3491
|
+
);
|
|
3492
|
+
const surfaced = await this.merchantTransport.surfaceResult(response);
|
|
4136
3493
|
const text = await surfaced.text();
|
|
4137
3494
|
let body;
|
|
4138
3495
|
try {
|
|
@@ -4140,8 +3497,16 @@ var HavenClient = class {
|
|
|
4140
3497
|
} catch {
|
|
4141
3498
|
body = text;
|
|
4142
3499
|
}
|
|
3500
|
+
const toolResult = mcpToolResultOf(body);
|
|
3501
|
+
const inBandChallenge = toolResult ? extractMcpPaymentRequired(toolResult) : void 0;
|
|
3502
|
+
const metaSettlement = toolResult ? mcpSettlementFromToolResult(toolResult) : void 0;
|
|
3503
|
+
const headerReceipt = surfaced.headers.get("PAYMENT-RESPONSE") ?? void 0;
|
|
3504
|
+
const protocolReceiptHeaderName = headerReceipt ? "PAYMENT-RESPONSE" : metaSettlement ? `_meta.${MCP_X402_PAYMENT_RESPONSE_META_KEY}` : void 0;
|
|
3505
|
+
const protocolReceiptHeader = headerReceipt ?? (metaSettlement ? encodeMcpSettlementReceipt(metaSettlement) : void 0);
|
|
3506
|
+
const settlement = parseMerchantSettlement(protocolReceiptHeader ?? null);
|
|
3507
|
+
const merchantAccepted = surfaced.ok && inBandChallenge === void 0 && metaSettlement?.success !== false;
|
|
4143
3508
|
let evidenceOutcome;
|
|
4144
|
-
if (!
|
|
3509
|
+
if (!merchantAccepted) {
|
|
4145
3510
|
if (!input.noFundingLeg && fundingTxHash) {
|
|
4146
3511
|
await this.merchantCompletion.recordRetryRejected({
|
|
4147
3512
|
rail: "x402",
|
|
@@ -4169,9 +3534,9 @@ var HavenClient = class {
|
|
|
4169
3534
|
txHash: evidenceTxHash,
|
|
4170
3535
|
resourceUrl: evidenceContext.resourceUrl,
|
|
4171
3536
|
merchantStatus: surfaced.status,
|
|
4172
|
-
paymentProofHeaderName: x402PaymentHeaderNamesSent(input.paymentHeader),
|
|
3537
|
+
paymentProofHeaderName: chunkCK4NLLMO_cjs.x402PaymentHeaderNamesSent(input.paymentHeader),
|
|
4173
3538
|
paymentProofHeader: input.paymentHeader,
|
|
4174
|
-
protocolReceiptHeaderName
|
|
3539
|
+
protocolReceiptHeaderName,
|
|
4175
3540
|
protocolReceiptHeader
|
|
4176
3541
|
});
|
|
4177
3542
|
}
|
|
@@ -4179,9 +3544,10 @@ var HavenClient = class {
|
|
|
4179
3544
|
}
|
|
4180
3545
|
return {
|
|
4181
3546
|
status: surfaced.status,
|
|
4182
|
-
ok:
|
|
3547
|
+
ok: merchantAccepted,
|
|
4183
3548
|
body,
|
|
4184
|
-
|
|
3549
|
+
// #3155 review S3: a transaction beside a rejection is not a settlement.
|
|
3550
|
+
settlementTxHash: merchantAccepted ? settlement.settlementTxHash ?? void 0 : void 0,
|
|
4185
3551
|
evidenceOutcome
|
|
4186
3552
|
};
|
|
4187
3553
|
}
|
|
@@ -4371,12 +3737,12 @@ var toolDescriptions = {
|
|
|
4371
3737
|
payX402OneShot: {
|
|
4372
3738
|
summary: "Fetch an x402 paid HTTP resource in a single call. Handles the full probe -> pay -> retry round trip and returns the merchant response.",
|
|
4373
3739
|
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.",
|
|
4374
|
-
behavior: "Calls the URL, parses any HTTP 402 x402 challenge, signs the payment locally, then retries the original request with the signed payment header (sent under PAYMENT-SIGNATURE, plus the legacy X-PAYMENT on the EIP-3009 path only) 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.",
|
|
3740
|
+
behavior: "Calls the URL, parses any HTTP 402 x402 challenge (or, since #3118, a native-MCP payment-required tool result under HTTP 200), signs the payment locally, then retries the original request with the signed payment header (sent under PAYMENT-SIGNATURE, plus the legacy X-PAYMENT on the EIP-3009 path only) 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 with no payment-required tool result, returns it unchanged without contacting Haven.",
|
|
4375
3741
|
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_account_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."
|
|
4376
3742
|
},
|
|
4377
3743
|
resumeX402: {
|
|
4378
3744
|
summary: "Resume an x402 payment whose Haven-side authorization already succeeded but whose merchant retry did not complete.",
|
|
4379
|
-
behavior: "Accepts either resume_state or payment_id, validates the
|
|
3745
|
+
behavior: "Accepts either resume_state or payment_id, validates the x402 details against the authorized funding, and retries the merchant request with the signed payment header (PAYMENT-SIGNATURE, plus legacy X-PAYMENT on EIP-3009 only; also params._meta on an MCP tools/call body). No new Haven payment is created.",
|
|
4380
3746
|
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."
|
|
4381
3747
|
},
|
|
4382
3748
|
// #1328: quoteMpp / payMpp / resumeMpp (the mpp_demo challenge/quote/resume
|
|
@@ -4415,8 +3781,8 @@ var toolDescriptions = {
|
|
|
4415
3781
|
},
|
|
4416
3782
|
listReceipts: {
|
|
4417
3783
|
summary: "List machine-payment receipts, newest first, by page.",
|
|
4418
|
-
selectionGuidance: "
|
|
4419
|
-
behavior: "Page
|
|
3784
|
+
selectionGuidance: "This agent's payment evidence, not the wallet's transaction history (sweeps, funding legs, other agents); use the allowance tool instead for remaining allowance or what-can-I-spend questions.",
|
|
3785
|
+
behavior: "Page { receipts, total, hasMore, nextCursor }; hasMore: pass nextCursor as cursor. parties.treasuryAccount is Haven's authoritative payer. protocolReceiptPayload is the merchant's PAYMENT-RESPONSE relayed verbatim: merchant-controlled, unverified, not Haven's record; payer may differ from payerAddress. Proof header values omitted.",
|
|
4420
3786
|
nextActionGuidance: ""
|
|
4421
3787
|
},
|
|
4422
3788
|
verifyReceipt: {
|
|
@@ -4452,7 +3818,7 @@ var toolDescriptions = {
|
|
|
4452
3818
|
send: {
|
|
4453
3819
|
summary: "Send ETH or USDC directly from the agent's Haven wallet to a recipient address.",
|
|
4454
3820
|
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. Do NOT use to check whether funds are held before sending \u2014 use haven_check_funds.",
|
|
4455
|
-
behavior: "Sends the
|
|
3821
|
+
behavior: "Sends the 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 or any signing \u2014 never queued for a human to approve. The agent's signing key signs the account's typed data; a current signer refuses any that does not match the payment's hash (USEROP_BINDING_MISMATCH), an older signer signs it and the account rejects it on-chain. Haven never receives the key.",
|
|
4456
3822
|
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."
|
|
4457
3823
|
},
|
|
4458
3824
|
reportSettlementEvidence: {
|
|
@@ -4785,6 +4151,10 @@ Call \`haven_get_agent\`, one of the Haven MCP tools the connector wires into yo
|
|
|
4785
4151
|
|
|
4786
4152
|
Nothing here needs you to. Steps 1-3 are links: hand your user the full \`<host>/\u2026\` URL and ask them to say when it is done. Step 5 is a link only when your run reported one in \`approval.url\` \u2014 otherwise it is the tab they already have open, as above. Then poll \`haven_get_agent\` until it reads \`ready\`. Do not route around the sign-in wall \u2014 it makes the account theirs, not yours.
|
|
4787
4153
|
|
|
4154
|
+
## If something breaks
|
|
4155
|
+
|
|
4156
|
+
If a Haven result carries \`client_update\`, that client is out of date: update it \u2014 \`upgrade_command\` names the package and channel \u2014 then retry. \`required: true\` means payments are refused until you do. What changed: [/releases](/releases).
|
|
4157
|
+
|
|
4788
4158
|
## Vocabulary
|
|
4789
4159
|
|
|
4790
4160
|
| Term | What it is |
|
|
@@ -5119,103 +4489,6 @@ for that credential.
|
|
|
5119
4489
|
var SKILL_FOLDER_NAME = "haven-pay";
|
|
5120
4490
|
var HAVEN_SKILL_BODY_MD = HAVEN_SKILL_MD.replace(/^---\n[\s\S]*?\n---\n+/, "");
|
|
5121
4491
|
|
|
5122
|
-
// src/next-step.ts
|
|
5123
|
-
var NEXT_TOOL_SERVER_NAMES = {
|
|
5124
|
-
hosted: "haven",
|
|
5125
|
-
signer: "haven-signer"
|
|
5126
|
-
};
|
|
5127
|
-
var NEXT_TOOL_SERVER_ROLES = {
|
|
5128
|
-
haven: "hosted",
|
|
5129
|
-
"haven-signer": "signer"
|
|
5130
|
-
};
|
|
5131
|
-
function renderNextTool(role, name) {
|
|
5132
|
-
return `mcp__${NEXT_TOOL_SERVER_NAMES[role]}__${name}`;
|
|
5133
|
-
}
|
|
5134
|
-
function parseNextTool(literal) {
|
|
5135
|
-
const m = /^mcp__([a-z0-9-]+)__([a-z0-9_]+)$/.exec(literal);
|
|
5136
|
-
if (!m) return null;
|
|
5137
|
-
const role = NEXT_TOOL_SERVER_ROLES[m[1]];
|
|
5138
|
-
return { server: m[1], name: m[2], ...role ? { role } : {} };
|
|
5139
|
-
}
|
|
5140
|
-
var DEFAULT_NEXT_TOOL_BY_ACTION = {
|
|
5141
|
-
check_status_later: "haven_get_payment_status",
|
|
5142
|
-
sweep_stranded_funds: "haven_sweep_delegate"
|
|
5143
|
-
// `retry_original_x402_request` is NOT here: its only live emitter
|
|
5144
|
-
// (state-direct-recovery.ts, erc7710) names no tool on purpose — the retry
|
|
5145
|
-
// is the agent's own HTTP call — so a default would contradict the site.
|
|
5146
|
-
};
|
|
5147
|
-
function defaultNextToolFor(action) {
|
|
5148
|
-
return DEFAULT_NEXT_TOOL_BY_ACTION[action];
|
|
5149
|
-
}
|
|
5150
|
-
function createNextStepBuilder(targets) {
|
|
5151
|
-
return function nextStep(input) {
|
|
5152
|
-
const i = input;
|
|
5153
|
-
const base = {
|
|
5154
|
-
next_action: input.nextAction,
|
|
5155
|
-
safe_to_continue: input.safeToContinue,
|
|
5156
|
-
reason: input.reason
|
|
5157
|
-
};
|
|
5158
|
-
if (i.nextTool === null) {
|
|
5159
|
-
return { ...base, next_tool_omitted_reason: i.nextToolOmittedReason ?? "no next tool" };
|
|
5160
|
-
}
|
|
5161
|
-
const target = targets[i.nextTool];
|
|
5162
|
-
if (!target) {
|
|
5163
|
-
return { ...base, next_tool_omitted_reason: `${i.nextTool} is not a registered next-step target` };
|
|
5164
|
-
}
|
|
5165
|
-
const problem = target.validate(i.nextArguments);
|
|
5166
|
-
if (problem) {
|
|
5167
|
-
return { ...base, next_tool_omitted_reason: `next_arguments do not parse under ${i.nextTool}: ${problem}` };
|
|
5168
|
-
}
|
|
5169
|
-
return {
|
|
5170
|
-
...base,
|
|
5171
|
-
next_tool: renderNextTool(target.role, i.nextTool),
|
|
5172
|
-
next_tool_server: NEXT_TOOL_SERVER_NAMES[target.role],
|
|
5173
|
-
next_tool_name: i.nextTool,
|
|
5174
|
-
next_tool_server_role: target.role,
|
|
5175
|
-
next_arguments: i.nextArguments
|
|
5176
|
-
};
|
|
5177
|
-
};
|
|
5178
|
-
}
|
|
5179
|
-
|
|
5180
|
-
// src/node-version.ts
|
|
5181
|
-
var HAVEN_MINIMUM_NODE_VERSION = "22.0.0";
|
|
5182
|
-
function parseNodeVersion(value) {
|
|
5183
|
-
const match = value.trim().match(/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
5184
|
-
if (!match) return [0, 0, 0];
|
|
5185
|
-
return [Number(match[1] ?? 0), Number(match[2] ?? 0), Number(match[3] ?? 0)];
|
|
5186
|
-
}
|
|
5187
|
-
function compareNodeVersions(left, right) {
|
|
5188
|
-
const leftParts = parseNodeVersion(left);
|
|
5189
|
-
const rightParts = parseNodeVersion(right);
|
|
5190
|
-
for (let i = 0; i < 3; i += 1) {
|
|
5191
|
-
if (leftParts[i] !== rightParts[i]) return leftParts[i] > rightParts[i] ? 1 : -1;
|
|
5192
|
-
}
|
|
5193
|
-
return 0;
|
|
5194
|
-
}
|
|
5195
|
-
function isSupportedNodeVersion(nodeVersion = process.versions.node, minimumNodeVersion = HAVEN_MINIMUM_NODE_VERSION) {
|
|
5196
|
-
return compareNodeVersions(nodeVersion, minimumNodeVersion) >= 0;
|
|
5197
|
-
}
|
|
5198
|
-
function unsupportedNodeVersionMessage(options) {
|
|
5199
|
-
const nodeVersion = options.nodeVersion ?? process.versions.node;
|
|
5200
|
-
const minimum = options.minimumNodeVersion ?? HAVEN_MINIMUM_NODE_VERSION;
|
|
5201
|
-
const lines = [
|
|
5202
|
-
`${options.subject} requires Node.js >=${minimum}, but this is Node.js ${nodeVersion}.`,
|
|
5203
|
-
"",
|
|
5204
|
-
"Upgrade Node, then try again:",
|
|
5205
|
-
` nvm install ${major(minimum)} && nvm use ${major(minimum)} (nvm)`,
|
|
5206
|
-
` fnm install ${major(minimum)} && fnm use ${major(minimum)} (fnm)`,
|
|
5207
|
-
` volta install node@${major(minimum)} (volta)`,
|
|
5208
|
-
` or download Node ${major(minimum)} from https://nodejs.org`,
|
|
5209
|
-
"",
|
|
5210
|
-
"If you use a version manager, check that the agent runtime launching Haven picks up the same version \u2014 upgrading your shell does not always change what a desktop app spawns."
|
|
5211
|
-
];
|
|
5212
|
-
if (options.retryHint) lines.push("", options.retryHint);
|
|
5213
|
-
return lines.join("\n");
|
|
5214
|
-
}
|
|
5215
|
-
function major(version) {
|
|
5216
|
-
return String(parseNodeVersion(version)[0]);
|
|
5217
|
-
}
|
|
5218
|
-
|
|
5219
4492
|
// src/merchant-discovery.ts
|
|
5220
4493
|
var MERCHANT_DISCOVERY_PATHS = ["/.well-known/haven-demo-merchant", "/"];
|
|
5221
4494
|
var DISCOVERY_MAX_BYTES = 64 * 1024;
|
|
@@ -5260,6 +4533,458 @@ function sameUrl(a, b) {
|
|
|
5260
4533
|
}
|
|
5261
4534
|
}
|
|
5262
4535
|
|
|
4536
|
+
Object.defineProperty(exports, "DEFAULT_NEXT_TOOL_BY_ACTION", {
|
|
4537
|
+
enumerable: true,
|
|
4538
|
+
get: function () { return chunkCK4NLLMO_cjs.DEFAULT_NEXT_TOOL_BY_ACTION; }
|
|
4539
|
+
});
|
|
4540
|
+
Object.defineProperty(exports, "ERC7710_ASSET_TRANSFER_METHOD", {
|
|
4541
|
+
enumerable: true,
|
|
4542
|
+
get: function () { return chunkCK4NLLMO_cjs.ERC7710_ASSET_TRANSFER_METHOD; }
|
|
4543
|
+
});
|
|
4544
|
+
Object.defineProperty(exports, "HAVEN_CLIENT_HEADER", {
|
|
4545
|
+
enumerable: true,
|
|
4546
|
+
get: function () { return chunkCK4NLLMO_cjs.HAVEN_CLIENT_HEADER; }
|
|
4547
|
+
});
|
|
4548
|
+
Object.defineProperty(exports, "HAVEN_MINIMUM_NODE_VERSION", {
|
|
4549
|
+
enumerable: true,
|
|
4550
|
+
get: function () { return chunkCK4NLLMO_cjs.HAVEN_MINIMUM_NODE_VERSION; }
|
|
4551
|
+
});
|
|
4552
|
+
Object.defineProperty(exports, "HavenTypedDataRefusedError", {
|
|
4553
|
+
enumerable: true,
|
|
4554
|
+
get: function () { return chunkCK4NLLMO_cjs.HavenTypedDataRefusedError; }
|
|
4555
|
+
});
|
|
4556
|
+
Object.defineProperty(exports, "MAX_TASK_BUDGET_TTL_SECONDS", {
|
|
4557
|
+
enumerable: true,
|
|
4558
|
+
get: function () { return chunkCK4NLLMO_cjs.MAX_TASK_BUDGET_TTL_SECONDS; }
|
|
4559
|
+
});
|
|
4560
|
+
Object.defineProperty(exports, "NEXT_TOOL_SERVER_NAMES", {
|
|
4561
|
+
enumerable: true,
|
|
4562
|
+
get: function () { return chunkCK4NLLMO_cjs.NEXT_TOOL_SERVER_NAMES; }
|
|
4563
|
+
});
|
|
4564
|
+
Object.defineProperty(exports, "NEXT_TOOL_SERVER_ROLES", {
|
|
4565
|
+
enumerable: true,
|
|
4566
|
+
get: function () { return chunkCK4NLLMO_cjs.NEXT_TOOL_SERVER_ROLES; }
|
|
4567
|
+
});
|
|
4568
|
+
Object.defineProperty(exports, "SDK_CLIENT_IDENTITY", {
|
|
4569
|
+
enumerable: true,
|
|
4570
|
+
get: function () { return chunkCK4NLLMO_cjs.SDK_CLIENT_IDENTITY; }
|
|
4571
|
+
});
|
|
4572
|
+
Object.defineProperty(exports, "SDK_VERSION", {
|
|
4573
|
+
enumerable: true,
|
|
4574
|
+
get: function () { return chunkCK4NLLMO_cjs.SDK_VERSION; }
|
|
4575
|
+
});
|
|
4576
|
+
Object.defineProperty(exports, "SWEEP_BASE_CHAIN_ID", {
|
|
4577
|
+
enumerable: true,
|
|
4578
|
+
get: function () { return chunkCK4NLLMO_cjs.SWEEP_BASE_CHAIN_ID; }
|
|
4579
|
+
});
|
|
4580
|
+
Object.defineProperty(exports, "SWEEP_BASE_SEPOLIA_CHAIN_ID", {
|
|
4581
|
+
enumerable: true,
|
|
4582
|
+
get: function () { return chunkCK4NLLMO_cjs.SWEEP_BASE_SEPOLIA_CHAIN_ID; }
|
|
4583
|
+
});
|
|
4584
|
+
Object.defineProperty(exports, "SWEEP_BASE_SEPOLIA_USDC_ADDRESS", {
|
|
4585
|
+
enumerable: true,
|
|
4586
|
+
get: function () { return chunkCK4NLLMO_cjs.SWEEP_BASE_SEPOLIA_USDC_ADDRESS; }
|
|
4587
|
+
});
|
|
4588
|
+
Object.defineProperty(exports, "SWEEP_BASE_USDC_ADDRESS", {
|
|
4589
|
+
enumerable: true,
|
|
4590
|
+
get: function () { return chunkCK4NLLMO_cjs.SWEEP_BASE_USDC_ADDRESS; }
|
|
4591
|
+
});
|
|
4592
|
+
Object.defineProperty(exports, "TRANSFER_WITH_AUTHORIZATION_TYPES", {
|
|
4593
|
+
enumerable: true,
|
|
4594
|
+
get: function () { return chunkCK4NLLMO_cjs.TRANSFER_WITH_AUTHORIZATION_TYPES; }
|
|
4595
|
+
});
|
|
4596
|
+
Object.defineProperty(exports, "TYPED_DATA_NOT_ALLOWED", {
|
|
4597
|
+
enumerable: true,
|
|
4598
|
+
get: function () { return chunkCK4NLLMO_cjs.TYPED_DATA_NOT_ALLOWED; }
|
|
4599
|
+
});
|
|
4600
|
+
Object.defineProperty(exports, "X402PaymentHeaderValidationError", {
|
|
4601
|
+
enumerable: true,
|
|
4602
|
+
get: function () { return chunkCK4NLLMO_cjs.X402PaymentHeaderValidationError; }
|
|
4603
|
+
});
|
|
4604
|
+
Object.defineProperty(exports, "X402_LEGACY_PAYMENT_HEADER_NAME", {
|
|
4605
|
+
enumerable: true,
|
|
4606
|
+
get: function () { return chunkCK4NLLMO_cjs.X402_LEGACY_PAYMENT_HEADER_NAME; }
|
|
4607
|
+
});
|
|
4608
|
+
Object.defineProperty(exports, "X402_MAX_AUTHORIZATION_WINDOW_SECONDS", {
|
|
4609
|
+
enumerable: true,
|
|
4610
|
+
get: function () { return chunkCK4NLLMO_cjs.X402_MAX_AUTHORIZATION_WINDOW_SECONDS; }
|
|
4611
|
+
});
|
|
4612
|
+
Object.defineProperty(exports, "X402_PAYMENT_HEADER_NAME", {
|
|
4613
|
+
enumerable: true,
|
|
4614
|
+
get: function () { return chunkCK4NLLMO_cjs.X402_PAYMENT_HEADER_NAME; }
|
|
4615
|
+
});
|
|
4616
|
+
Object.defineProperty(exports, "X402_PAYMENT_HEADER_NAMES_SENT", {
|
|
4617
|
+
enumerable: true,
|
|
4618
|
+
get: function () { return chunkCK4NLLMO_cjs.X402_PAYMENT_HEADER_NAMES_SENT; }
|
|
4619
|
+
});
|
|
4620
|
+
Object.defineProperty(exports, "X402_PAYMENT_REQUIRED_HEADER_NAME", {
|
|
4621
|
+
enumerable: true,
|
|
4622
|
+
get: function () { return chunkCK4NLLMO_cjs.X402_PAYMENT_REQUIRED_HEADER_NAME; }
|
|
4623
|
+
});
|
|
4624
|
+
Object.defineProperty(exports, "X402_PAYMENT_RESPONSE_HEADER_NAME", {
|
|
4625
|
+
enumerable: true,
|
|
4626
|
+
get: function () { return chunkCK4NLLMO_cjs.X402_PAYMENT_RESPONSE_HEADER_NAME; }
|
|
4627
|
+
});
|
|
4628
|
+
Object.defineProperty(exports, "X402_SETTLEMENT_FORWARD_MARGIN_SECONDS", {
|
|
4629
|
+
enumerable: true,
|
|
4630
|
+
get: function () { return chunkCK4NLLMO_cjs.X402_SETTLEMENT_FORWARD_MARGIN_SECONDS; }
|
|
4631
|
+
});
|
|
4632
|
+
Object.defineProperty(exports, "assertBoundDirectPaymentUserOp", {
|
|
4633
|
+
enumerable: true,
|
|
4634
|
+
get: function () { return chunkCK4NLLMO_cjs.assertBoundDirectPaymentUserOp; }
|
|
4635
|
+
});
|
|
4636
|
+
Object.defineProperty(exports, "assertOwnTaskBudgetCloseUserOp", {
|
|
4637
|
+
enumerable: true,
|
|
4638
|
+
get: function () { return chunkCK4NLLMO_cjs.assertOwnTaskBudgetCloseUserOp; }
|
|
4639
|
+
});
|
|
4640
|
+
Object.defineProperty(exports, "assertOwnTaskChild", {
|
|
4641
|
+
enumerable: true,
|
|
4642
|
+
get: function () { return chunkCK4NLLMO_cjs.assertOwnTaskChild; }
|
|
4643
|
+
});
|
|
4644
|
+
Object.defineProperty(exports, "buildSweepAuthorizationMessage", {
|
|
4645
|
+
enumerable: true,
|
|
4646
|
+
get: function () { return chunkCK4NLLMO_cjs.buildSweepAuthorizationMessage; }
|
|
4647
|
+
});
|
|
4648
|
+
Object.defineProperty(exports, "buildSweepTypedData", {
|
|
4649
|
+
enumerable: true,
|
|
4650
|
+
get: function () { return chunkCK4NLLMO_cjs.buildSweepTypedData; }
|
|
4651
|
+
});
|
|
4652
|
+
Object.defineProperty(exports, "buildX402ExpectedMessage", {
|
|
4653
|
+
enumerable: true,
|
|
4654
|
+
get: function () { return chunkCK4NLLMO_cjs.buildX402ExpectedMessage; }
|
|
4655
|
+
});
|
|
4656
|
+
Object.defineProperty(exports, "compareNodeVersions", {
|
|
4657
|
+
enumerable: true,
|
|
4658
|
+
get: function () { return chunkCK4NLLMO_cjs.compareNodeVersions; }
|
|
4659
|
+
});
|
|
4660
|
+
Object.defineProperty(exports, "createNextStepBuilder", {
|
|
4661
|
+
enumerable: true,
|
|
4662
|
+
get: function () { return chunkCK4NLLMO_cjs.createNextStepBuilder; }
|
|
4663
|
+
});
|
|
4664
|
+
Object.defineProperty(exports, "decodeBase64Json", {
|
|
4665
|
+
enumerable: true,
|
|
4666
|
+
get: function () { return chunkCK4NLLMO_cjs.decodeBase64Json; }
|
|
4667
|
+
});
|
|
4668
|
+
Object.defineProperty(exports, "decodeBase64Utf8", {
|
|
4669
|
+
enumerable: true,
|
|
4670
|
+
get: function () { return chunkCK4NLLMO_cjs.decodeBase64Utf8; }
|
|
4671
|
+
});
|
|
4672
|
+
Object.defineProperty(exports, "defaultNextToolFor", {
|
|
4673
|
+
enumerable: true,
|
|
4674
|
+
get: function () { return chunkCK4NLLMO_cjs.defaultNextToolFor; }
|
|
4675
|
+
});
|
|
4676
|
+
Object.defineProperty(exports, "encodeBase64Json", {
|
|
4677
|
+
enumerable: true,
|
|
4678
|
+
get: function () { return chunkCK4NLLMO_cjs.encodeBase64Json; }
|
|
4679
|
+
});
|
|
4680
|
+
Object.defineProperty(exports, "encodeBase64Utf8", {
|
|
4681
|
+
enumerable: true,
|
|
4682
|
+
get: function () { return chunkCK4NLLMO_cjs.encodeBase64Utf8; }
|
|
4683
|
+
});
|
|
4684
|
+
Object.defineProperty(exports, "encodePaymentProof", {
|
|
4685
|
+
enumerable: true,
|
|
4686
|
+
get: function () { return chunkCK4NLLMO_cjs.encodePaymentProof; }
|
|
4687
|
+
});
|
|
4688
|
+
Object.defineProperty(exports, "hashDelegation", {
|
|
4689
|
+
enumerable: true,
|
|
4690
|
+
get: function () { return chunkCK4NLLMO_cjs.hashDelegation; }
|
|
4691
|
+
});
|
|
4692
|
+
Object.defineProperty(exports, "havenClientIdentity", {
|
|
4693
|
+
enumerable: true,
|
|
4694
|
+
get: function () { return chunkCK4NLLMO_cjs.havenClientIdentity; }
|
|
4695
|
+
});
|
|
4696
|
+
Object.defineProperty(exports, "isErc7710Option", {
|
|
4697
|
+
enumerable: true,
|
|
4698
|
+
get: function () { return chunkCK4NLLMO_cjs.isErc7710Option; }
|
|
4699
|
+
});
|
|
4700
|
+
Object.defineProperty(exports, "isSupportedNodeVersion", {
|
|
4701
|
+
enumerable: true,
|
|
4702
|
+
get: function () { return chunkCK4NLLMO_cjs.isSupportedNodeVersion; }
|
|
4703
|
+
});
|
|
4704
|
+
Object.defineProperty(exports, "isSweepableChain", {
|
|
4705
|
+
enumerable: true,
|
|
4706
|
+
get: function () { return chunkCK4NLLMO_cjs.isSweepableChain; }
|
|
4707
|
+
});
|
|
4708
|
+
Object.defineProperty(exports, "isTaskChildTypedData", {
|
|
4709
|
+
enumerable: true,
|
|
4710
|
+
get: function () { return chunkCK4NLLMO_cjs.isTaskChildTypedData; }
|
|
4711
|
+
});
|
|
4712
|
+
Object.defineProperty(exports, "normalizePaymentRequired", {
|
|
4713
|
+
enumerable: true,
|
|
4714
|
+
get: function () { return chunkCK4NLLMO_cjs.normalizePaymentRequired; }
|
|
4715
|
+
});
|
|
4716
|
+
Object.defineProperty(exports, "parseNextTool", {
|
|
4717
|
+
enumerable: true,
|
|
4718
|
+
get: function () { return chunkCK4NLLMO_cjs.parseNextTool; }
|
|
4719
|
+
});
|
|
4720
|
+
Object.defineProperty(exports, "parsePaymentRequired", {
|
|
4721
|
+
enumerable: true,
|
|
4722
|
+
get: function () { return chunkCK4NLLMO_cjs.parsePaymentRequired; }
|
|
4723
|
+
});
|
|
4724
|
+
Object.defineProperty(exports, "parsePaymentRequiredResponse", {
|
|
4725
|
+
enumerable: true,
|
|
4726
|
+
get: function () { return chunkCK4NLLMO_cjs.parsePaymentRequiredResponse; }
|
|
4727
|
+
});
|
|
4728
|
+
Object.defineProperty(exports, "readClientUpdate", {
|
|
4729
|
+
enumerable: true,
|
|
4730
|
+
get: function () { return chunkCK4NLLMO_cjs.readClientUpdate; }
|
|
4731
|
+
});
|
|
4732
|
+
Object.defineProperty(exports, "renderNextTool", {
|
|
4733
|
+
enumerable: true,
|
|
4734
|
+
get: function () { return chunkCK4NLLMO_cjs.renderNextTool; }
|
|
4735
|
+
});
|
|
4736
|
+
Object.defineProperty(exports, "resolveTokenFromAddress", {
|
|
4737
|
+
enumerable: true,
|
|
4738
|
+
get: function () { return chunkCK4NLLMO_cjs.resolveTokenFromAddress; }
|
|
4739
|
+
});
|
|
4740
|
+
Object.defineProperty(exports, "selectErc7710PaymentOption", {
|
|
4741
|
+
enumerable: true,
|
|
4742
|
+
get: function () { return chunkCK4NLLMO_cjs.selectErc7710PaymentOption; }
|
|
4743
|
+
});
|
|
4744
|
+
Object.defineProperty(exports, "selectPaymentOption", {
|
|
4745
|
+
enumerable: true,
|
|
4746
|
+
get: function () { return chunkCK4NLLMO_cjs.selectPaymentOption; }
|
|
4747
|
+
});
|
|
4748
|
+
Object.defineProperty(exports, "selectStandardPaymentOption", {
|
|
4749
|
+
enumerable: true,
|
|
4750
|
+
get: function () { return chunkCK4NLLMO_cjs.selectStandardPaymentOption; }
|
|
4751
|
+
});
|
|
4752
|
+
Object.defineProperty(exports, "selectX402SettlementScheme", {
|
|
4753
|
+
enumerable: true,
|
|
4754
|
+
get: function () { return chunkCK4NLLMO_cjs.selectX402SettlementScheme; }
|
|
4755
|
+
});
|
|
4756
|
+
Object.defineProperty(exports, "sweepUsdcAddress", {
|
|
4757
|
+
enumerable: true,
|
|
4758
|
+
get: function () { return chunkCK4NLLMO_cjs.sweepUsdcAddress; }
|
|
4759
|
+
});
|
|
4760
|
+
Object.defineProperty(exports, "sweepUsdcDomain", {
|
|
4761
|
+
enumerable: true,
|
|
4762
|
+
get: function () { return chunkCK4NLLMO_cjs.sweepUsdcDomain; }
|
|
4763
|
+
});
|
|
4764
|
+
Object.defineProperty(exports, "toStandardPaymentRequirements", {
|
|
4765
|
+
enumerable: true,
|
|
4766
|
+
get: function () { return chunkCK4NLLMO_cjs.toStandardPaymentRequirements; }
|
|
4767
|
+
});
|
|
4768
|
+
Object.defineProperty(exports, "unsupportedNodeVersionMessage", {
|
|
4769
|
+
enumerable: true,
|
|
4770
|
+
get: function () { return chunkCK4NLLMO_cjs.unsupportedNodeVersionMessage; }
|
|
4771
|
+
});
|
|
4772
|
+
Object.defineProperty(exports, "validateStandardX402PaymentHeader", {
|
|
4773
|
+
enumerable: true,
|
|
4774
|
+
get: function () { return chunkCK4NLLMO_cjs.validateStandardX402PaymentHeader; }
|
|
4775
|
+
});
|
|
4776
|
+
Object.defineProperty(exports, "x402AssetTransferMethod", {
|
|
4777
|
+
enumerable: true,
|
|
4778
|
+
get: function () { return chunkCK4NLLMO_cjs.x402AssetTransferMethod; }
|
|
4779
|
+
});
|
|
4780
|
+
Object.defineProperty(exports, "x402AuthorizationAmount", {
|
|
4781
|
+
enumerable: true,
|
|
4782
|
+
get: function () { return chunkCK4NLLMO_cjs.x402AuthorizationAmount; }
|
|
4783
|
+
});
|
|
4784
|
+
Object.defineProperty(exports, "x402FacilitatorAddresses", {
|
|
4785
|
+
enumerable: true,
|
|
4786
|
+
get: function () { return chunkCK4NLLMO_cjs.x402FacilitatorAddresses; }
|
|
4787
|
+
});
|
|
4788
|
+
Object.defineProperty(exports, "x402V2PaymentEnvelope", {
|
|
4789
|
+
enumerable: true,
|
|
4790
|
+
get: function () { return chunkCK4NLLMO_cjs.x402V2PaymentEnvelope; }
|
|
4791
|
+
});
|
|
4792
|
+
Object.defineProperty(exports, "AGENT_PAYMENT_FAILURE_CODE_VALUES", {
|
|
4793
|
+
enumerable: true,
|
|
4794
|
+
get: function () { return chunkS42QSWJY_cjs.AGENT_PAYMENT_FAILURE_CODE_VALUES; }
|
|
4795
|
+
});
|
|
4796
|
+
Object.defineProperty(exports, "AGENT_PAYMENT_NEXT_ACTION_VALUES", {
|
|
4797
|
+
enumerable: true,
|
|
4798
|
+
get: function () { return chunkS42QSWJY_cjs.AGENT_PAYMENT_NEXT_ACTION_VALUES; }
|
|
4799
|
+
});
|
|
4800
|
+
Object.defineProperty(exports, "AGENT_PAYMENT_PHASE_VALUES", {
|
|
4801
|
+
enumerable: true,
|
|
4802
|
+
get: function () { return chunkS42QSWJY_cjs.AGENT_PAYMENT_PHASE_VALUES; }
|
|
4803
|
+
});
|
|
4804
|
+
Object.defineProperty(exports, "AGENT_PAYMENT_RAIL_VALUES", {
|
|
4805
|
+
enumerable: true,
|
|
4806
|
+
get: function () { return chunkS42QSWJY_cjs.AGENT_PAYMENT_RAIL_VALUES; }
|
|
4807
|
+
});
|
|
4808
|
+
Object.defineProperty(exports, "AgentPaymentFailureCode", {
|
|
4809
|
+
enumerable: true,
|
|
4810
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentFailureCode; }
|
|
4811
|
+
});
|
|
4812
|
+
Object.defineProperty(exports, "AgentPaymentFailureCodeDescriptions", {
|
|
4813
|
+
enumerable: true,
|
|
4814
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentFailureCodeDescriptions; }
|
|
4815
|
+
});
|
|
4816
|
+
Object.defineProperty(exports, "AgentPaymentFailureCodeSchema", {
|
|
4817
|
+
enumerable: true,
|
|
4818
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentFailureCodeSchema; }
|
|
4819
|
+
});
|
|
4820
|
+
Object.defineProperty(exports, "AgentPaymentNextAction", {
|
|
4821
|
+
enumerable: true,
|
|
4822
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentNextAction; }
|
|
4823
|
+
});
|
|
4824
|
+
Object.defineProperty(exports, "AgentPaymentNextActionDescriptions", {
|
|
4825
|
+
enumerable: true,
|
|
4826
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentNextActionDescriptions; }
|
|
4827
|
+
});
|
|
4828
|
+
Object.defineProperty(exports, "AgentPaymentNextActionSchema", {
|
|
4829
|
+
enumerable: true,
|
|
4830
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentNextActionSchema; }
|
|
4831
|
+
});
|
|
4832
|
+
Object.defineProperty(exports, "AgentPaymentPhase", {
|
|
4833
|
+
enumerable: true,
|
|
4834
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentPhase; }
|
|
4835
|
+
});
|
|
4836
|
+
Object.defineProperty(exports, "AgentPaymentPhaseDescriptions", {
|
|
4837
|
+
enumerable: true,
|
|
4838
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentPhaseDescriptions; }
|
|
4839
|
+
});
|
|
4840
|
+
Object.defineProperty(exports, "AgentPaymentPhaseSchema", {
|
|
4841
|
+
enumerable: true,
|
|
4842
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentPhaseSchema; }
|
|
4843
|
+
});
|
|
4844
|
+
Object.defineProperty(exports, "AgentPaymentRail", {
|
|
4845
|
+
enumerable: true,
|
|
4846
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentRail; }
|
|
4847
|
+
});
|
|
4848
|
+
Object.defineProperty(exports, "AgentPaymentRailDescriptions", {
|
|
4849
|
+
enumerable: true,
|
|
4850
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentRailDescriptions; }
|
|
4851
|
+
});
|
|
4852
|
+
Object.defineProperty(exports, "AgentPaymentRailSchema", {
|
|
4853
|
+
enumerable: true,
|
|
4854
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentRailSchema; }
|
|
4855
|
+
});
|
|
4856
|
+
Object.defineProperty(exports, "AgentPaymentWarningCode", {
|
|
4857
|
+
enumerable: true,
|
|
4858
|
+
get: function () { return chunkS42QSWJY_cjs.AgentPaymentWarningCode; }
|
|
4859
|
+
});
|
|
4860
|
+
Object.defineProperty(exports, "CONNECTOR_PACKAGE_NAME", {
|
|
4861
|
+
enumerable: true,
|
|
4862
|
+
get: function () { return chunkS42QSWJY_cjs.CONNECTOR_PACKAGE_NAME; }
|
|
4863
|
+
});
|
|
4864
|
+
Object.defineProperty(exports, "DEFAULT_CONFIRMATION_TIMEOUT_MS", {
|
|
4865
|
+
enumerable: true,
|
|
4866
|
+
get: function () { return chunkS42QSWJY_cjs.DEFAULT_CONFIRMATION_TIMEOUT_MS; }
|
|
4867
|
+
});
|
|
4868
|
+
Object.defineProperty(exports, "DIRECT_SIGN_CONTEXT_VERSION", {
|
|
4869
|
+
enumerable: true,
|
|
4870
|
+
get: function () { return chunkS42QSWJY_cjs.DIRECT_SIGN_CONTEXT_VERSION; }
|
|
4871
|
+
});
|
|
4872
|
+
Object.defineProperty(exports, "ENTRY_POINT_V07", {
|
|
4873
|
+
enumerable: true,
|
|
4874
|
+
get: function () { return chunkS42QSWJY_cjs.ENTRY_POINT_V07; }
|
|
4875
|
+
});
|
|
4876
|
+
Object.defineProperty(exports, "HAVEN_CONNECTOR_CHANNEL", {
|
|
4877
|
+
enumerable: true,
|
|
4878
|
+
get: function () { return chunkS42QSWJY_cjs.HAVEN_CONNECTOR_CHANNEL; }
|
|
4879
|
+
});
|
|
4880
|
+
Object.defineProperty(exports, "HYBRID_DELEGATOR_DOMAIN_NAME", {
|
|
4881
|
+
enumerable: true,
|
|
4882
|
+
get: function () { return chunkS42QSWJY_cjs.HYBRID_DELEGATOR_DOMAIN_NAME; }
|
|
4883
|
+
});
|
|
4884
|
+
Object.defineProperty(exports, "HYBRID_DELEGATOR_DOMAIN_VERSION", {
|
|
4885
|
+
enumerable: true,
|
|
4886
|
+
get: function () { return chunkS42QSWJY_cjs.HYBRID_DELEGATOR_DOMAIN_VERSION; }
|
|
4887
|
+
});
|
|
4888
|
+
Object.defineProperty(exports, "HavenApiError", {
|
|
4889
|
+
enumerable: true,
|
|
4890
|
+
get: function () { return chunkS42QSWJY_cjs.HavenApiError; }
|
|
4891
|
+
});
|
|
4892
|
+
Object.defineProperty(exports, "HavenError", {
|
|
4893
|
+
enumerable: true,
|
|
4894
|
+
get: function () { return chunkS42QSWJY_cjs.HavenError; }
|
|
4895
|
+
});
|
|
4896
|
+
Object.defineProperty(exports, "HavenPaymentStateError", {
|
|
4897
|
+
enumerable: true,
|
|
4898
|
+
get: function () { return chunkS42QSWJY_cjs.HavenPaymentStateError; }
|
|
4899
|
+
});
|
|
4900
|
+
Object.defineProperty(exports, "HavenSigningError", {
|
|
4901
|
+
enumerable: true,
|
|
4902
|
+
get: function () { return chunkS42QSWJY_cjs.HavenSigningError; }
|
|
4903
|
+
});
|
|
4904
|
+
Object.defineProperty(exports, "HavenTimeoutError", {
|
|
4905
|
+
enumerable: true,
|
|
4906
|
+
get: function () { return chunkS42QSWJY_cjs.HavenTimeoutError; }
|
|
4907
|
+
});
|
|
4908
|
+
Object.defineProperty(exports, "HavenUnsupportedSignerVersionError", {
|
|
4909
|
+
enumerable: true,
|
|
4910
|
+
get: function () { return chunkS42QSWJY_cjs.HavenUnsupportedSignerVersionError; }
|
|
4911
|
+
});
|
|
4912
|
+
Object.defineProperty(exports, "HavenUserOpBindingError", {
|
|
4913
|
+
enumerable: true,
|
|
4914
|
+
get: function () { return chunkS42QSWJY_cjs.HavenUserOpBindingError; }
|
|
4915
|
+
});
|
|
4916
|
+
Object.defineProperty(exports, "HavenZeroSettlementHashError", {
|
|
4917
|
+
enumerable: true,
|
|
4918
|
+
get: function () { return chunkS42QSWJY_cjs.HavenZeroSettlementHashError; }
|
|
4919
|
+
});
|
|
4920
|
+
Object.defineProperty(exports, "MerchantTimeoutError", {
|
|
4921
|
+
enumerable: true,
|
|
4922
|
+
get: function () { return chunkS42QSWJY_cjs.MerchantTimeoutError; }
|
|
4923
|
+
});
|
|
4924
|
+
Object.defineProperty(exports, "PACKED_USER_OPERATION_FIELDS", {
|
|
4925
|
+
enumerable: true,
|
|
4926
|
+
get: function () { return chunkS42QSWJY_cjs.PACKED_USER_OPERATION_FIELDS; }
|
|
4927
|
+
});
|
|
4928
|
+
Object.defineProperty(exports, "ROOT_AUTHORITY", {
|
|
4929
|
+
enumerable: true,
|
|
4930
|
+
get: function () { return chunkS42QSWJY_cjs.ROOT_AUTHORITY; }
|
|
4931
|
+
});
|
|
4932
|
+
Object.defineProperty(exports, "SIGNER_UPDATE_FALLBACK", {
|
|
4933
|
+
enumerable: true,
|
|
4934
|
+
get: function () { return chunkS42QSWJY_cjs.SIGNER_UPDATE_FALLBACK; }
|
|
4935
|
+
});
|
|
4936
|
+
Object.defineProperty(exports, "SignerRefusalCode", {
|
|
4937
|
+
enumerable: true,
|
|
4938
|
+
get: function () { return chunkS42QSWJY_cjs.SignerRefusalCode; }
|
|
4939
|
+
});
|
|
4940
|
+
Object.defineProperty(exports, "X402AlreadySettledError", {
|
|
4941
|
+
enumerable: true,
|
|
4942
|
+
get: function () { return chunkS42QSWJY_cjs.X402AlreadySettledError; }
|
|
4943
|
+
});
|
|
4944
|
+
Object.defineProperty(exports, "X402UnexpectedStatusError", {
|
|
4945
|
+
enumerable: true,
|
|
4946
|
+
get: function () { return chunkS42QSWJY_cjs.X402UnexpectedStatusError; }
|
|
4947
|
+
});
|
|
4948
|
+
Object.defineProperty(exports, "assertUserOpTypedDataBinding", {
|
|
4949
|
+
enumerable: true,
|
|
4950
|
+
get: function () { return chunkS42QSWJY_cjs.assertUserOpTypedDataBinding; }
|
|
4951
|
+
});
|
|
4952
|
+
Object.defineProperty(exports, "connectorRerunCommand", {
|
|
4953
|
+
enumerable: true,
|
|
4954
|
+
get: function () { return chunkS42QSWJY_cjs.connectorRerunCommand; }
|
|
4955
|
+
});
|
|
4956
|
+
Object.defineProperty(exports, "connectorSpec", {
|
|
4957
|
+
enumerable: true,
|
|
4958
|
+
get: function () { return chunkS42QSWJY_cjs.connectorSpec; }
|
|
4959
|
+
});
|
|
4960
|
+
Object.defineProperty(exports, "deriveDelegateAccountAddress", {
|
|
4961
|
+
enumerable: true,
|
|
4962
|
+
get: function () { return chunkS42QSWJY_cjs.deriveDelegateAccountAddress; }
|
|
4963
|
+
});
|
|
4964
|
+
Object.defineProperty(exports, "isConnectorChannel", {
|
|
4965
|
+
enumerable: true,
|
|
4966
|
+
get: function () { return chunkS42QSWJY_cjs.isConnectorChannel; }
|
|
4967
|
+
});
|
|
4968
|
+
Object.defineProperty(exports, "isPackedUserOperationTypedData", {
|
|
4969
|
+
enumerable: true,
|
|
4970
|
+
get: function () { return chunkS42QSWJY_cjs.isPackedUserOperationTypedData; }
|
|
4971
|
+
});
|
|
4972
|
+
Object.defineProperty(exports, "packedUserOperationHash", {
|
|
4973
|
+
enumerable: true,
|
|
4974
|
+
get: function () { return chunkS42QSWJY_cjs.packedUserOperationHash; }
|
|
4975
|
+
});
|
|
4976
|
+
Object.defineProperty(exports, "resolveConnectorChannel", {
|
|
4977
|
+
enumerable: true,
|
|
4978
|
+
get: function () { return chunkS42QSWJY_cjs.resolveConnectorChannel; }
|
|
4979
|
+
});
|
|
4980
|
+
Object.defineProperty(exports, "signerUpdateFallback", {
|
|
4981
|
+
enumerable: true,
|
|
4982
|
+
get: function () { return chunkS42QSWJY_cjs.signerUpdateFallback; }
|
|
4983
|
+
});
|
|
4984
|
+
Object.defineProperty(exports, "verifySettlementChild", {
|
|
4985
|
+
enumerable: true,
|
|
4986
|
+
get: function () { return chunkS42QSWJY_cjs.verifySettlementChild; }
|
|
4987
|
+
});
|
|
5263
4988
|
exports.AGENT_APPROVAL_RELAY_JSON_SENTENCE = AGENT_APPROVAL_RELAY_JSON_SENTENCE;
|
|
5264
4989
|
exports.AGENT_APPROVAL_RELAY_PROSE_SENTENCE = AGENT_APPROVAL_RELAY_PROSE_SENTENCE;
|
|
5265
4990
|
exports.AGENT_COMMAND_MODIFICATION_SENTENCE = AGENT_COMMAND_MODIFICATION_SENTENCE;
|
|
@@ -5267,121 +4992,33 @@ exports.AGENT_JSON_MODE_SENTENCE = AGENT_JSON_MODE_SENTENCE;
|
|
|
5267
4992
|
exports.AGENT_LOCAL_KEY_SENTENCE = AGENT_LOCAL_KEY_SENTENCE;
|
|
5268
4993
|
exports.AGENT_NETWORK_ACCESS_SENTENCE = AGENT_NETWORK_ACCESS_SENTENCE;
|
|
5269
4994
|
exports.AGENT_ONBOARDING_PROMPT = AGENT_ONBOARDING_PROMPT;
|
|
5270
|
-
exports.AGENT_PAYMENT_FAILURE_CODE_VALUES = AGENT_PAYMENT_FAILURE_CODE_VALUES;
|
|
5271
|
-
exports.AGENT_PAYMENT_NEXT_ACTION_VALUES = AGENT_PAYMENT_NEXT_ACTION_VALUES;
|
|
5272
|
-
exports.AGENT_PAYMENT_PHASE_VALUES = AGENT_PAYMENT_PHASE_VALUES;
|
|
5273
|
-
exports.AGENT_PAYMENT_RAIL_VALUES = AGENT_PAYMENT_RAIL_VALUES;
|
|
5274
4995
|
exports.AGENT_README_SECTION_MD = AGENT_README_SECTION_MD;
|
|
5275
4996
|
exports.AGENT_SECRET_HYGIENE_SENTENCE = AGENT_SECRET_HYGIENE_SENTENCE;
|
|
5276
4997
|
exports.AGENT_WIRING_COLLISION_RELAY_SENTENCE = AGENT_WIRING_COLLISION_RELAY_SENTENCE;
|
|
5277
|
-
exports.AgentPaymentFailureCode = AgentPaymentFailureCode;
|
|
5278
|
-
exports.AgentPaymentFailureCodeDescriptions = AgentPaymentFailureCodeDescriptions;
|
|
5279
|
-
exports.AgentPaymentFailureCodeSchema = AgentPaymentFailureCodeSchema;
|
|
5280
|
-
exports.AgentPaymentNextAction = AgentPaymentNextAction;
|
|
5281
|
-
exports.AgentPaymentNextActionDescriptions = AgentPaymentNextActionDescriptions;
|
|
5282
|
-
exports.AgentPaymentNextActionSchema = AgentPaymentNextActionSchema;
|
|
5283
|
-
exports.AgentPaymentPhase = AgentPaymentPhase;
|
|
5284
|
-
exports.AgentPaymentPhaseDescriptions = AgentPaymentPhaseDescriptions;
|
|
5285
|
-
exports.AgentPaymentPhaseSchema = AgentPaymentPhaseSchema;
|
|
5286
|
-
exports.AgentPaymentRail = AgentPaymentRail;
|
|
5287
|
-
exports.AgentPaymentRailDescriptions = AgentPaymentRailDescriptions;
|
|
5288
|
-
exports.AgentPaymentRailSchema = AgentPaymentRailSchema;
|
|
5289
|
-
exports.AgentPaymentWarningCode = AgentPaymentWarningCode;
|
|
5290
|
-
exports.CONNECTOR_PACKAGE_NAME = CONNECTOR_PACKAGE_NAME;
|
|
5291
|
-
exports.DEFAULT_CONFIRMATION_TIMEOUT_MS = DEFAULT_CONFIRMATION_TIMEOUT_MS;
|
|
5292
|
-
exports.DEFAULT_NEXT_TOOL_BY_ACTION = DEFAULT_NEXT_TOOL_BY_ACTION;
|
|
5293
4998
|
exports.DISCOVERY_MAX_BYTES = DISCOVERY_MAX_BYTES;
|
|
5294
|
-
exports.ERC7710_ASSET_TRANSFER_METHOD = ERC7710_ASSET_TRANSFER_METHOD;
|
|
5295
4999
|
exports.HAVEN_AGENT_RUNBOOK_MD = HAVEN_AGENT_RUNBOOK_MD;
|
|
5296
|
-
exports.HAVEN_CONNECTOR_CHANNEL = HAVEN_CONNECTOR_CHANNEL;
|
|
5297
|
-
exports.HAVEN_MINIMUM_NODE_VERSION = HAVEN_MINIMUM_NODE_VERSION;
|
|
5298
5000
|
exports.HAVEN_SKILL_BODY_MD = HAVEN_SKILL_BODY_MD;
|
|
5299
5001
|
exports.HAVEN_SKILL_MD = HAVEN_SKILL_MD;
|
|
5300
|
-
exports.HavenApiError = HavenApiError;
|
|
5301
5002
|
exports.HavenClient = HavenClient;
|
|
5302
|
-
exports.HavenError = HavenError;
|
|
5303
5003
|
exports.HavenInsecureRetryTargetError = HavenInsecureRetryTargetError;
|
|
5304
|
-
exports.HavenPaymentStateError = HavenPaymentStateError;
|
|
5305
|
-
exports.HavenSigningError = HavenSigningError;
|
|
5306
|
-
exports.HavenTimeoutError = HavenTimeoutError;
|
|
5307
|
-
exports.HavenUnsupportedSignerVersionError = HavenUnsupportedSignerVersionError;
|
|
5308
|
-
exports.HavenZeroSettlementHashError = HavenZeroSettlementHashError;
|
|
5309
5004
|
exports.INSECURE_RETRY_TARGET_CODE = INSECURE_RETRY_TARGET_CODE;
|
|
5310
5005
|
exports.MERCHANT_DISCOVERY_PATHS = MERCHANT_DISCOVERY_PATHS;
|
|
5311
|
-
exports.MerchantTimeoutError = MerchantTimeoutError;
|
|
5312
|
-
exports.NEXT_TOOL_SERVER_NAMES = NEXT_TOOL_SERVER_NAMES;
|
|
5313
|
-
exports.NEXT_TOOL_SERVER_ROLES = NEXT_TOOL_SERVER_ROLES;
|
|
5314
5006
|
exports.RECEIPT_VERSION = RECEIPT_VERSION;
|
|
5315
|
-
exports.SIGNER_UPDATE_FALLBACK = SIGNER_UPDATE_FALLBACK;
|
|
5316
5007
|
exports.SKILL_FOLDER_NAME = SKILL_FOLDER_NAME;
|
|
5317
|
-
exports.SWEEP_BASE_CHAIN_ID = SWEEP_BASE_CHAIN_ID;
|
|
5318
|
-
exports.SWEEP_BASE_SEPOLIA_CHAIN_ID = SWEEP_BASE_SEPOLIA_CHAIN_ID;
|
|
5319
|
-
exports.SWEEP_BASE_SEPOLIA_USDC_ADDRESS = SWEEP_BASE_SEPOLIA_USDC_ADDRESS;
|
|
5320
|
-
exports.SWEEP_BASE_USDC_ADDRESS = SWEEP_BASE_USDC_ADDRESS;
|
|
5321
|
-
exports.SignerRefusalCode = SignerRefusalCode;
|
|
5322
|
-
exports.TRANSFER_WITH_AUTHORIZATION_TYPES = TRANSFER_WITH_AUTHORIZATION_TYPES;
|
|
5323
|
-
exports.X402AlreadySettledError = X402AlreadySettledError;
|
|
5324
|
-
exports.X402PaymentHeaderValidationError = X402PaymentHeaderValidationError;
|
|
5325
|
-
exports.X402UnexpectedStatusError = X402UnexpectedStatusError;
|
|
5326
|
-
exports.X402_LEGACY_PAYMENT_HEADER_NAME = X402_LEGACY_PAYMENT_HEADER_NAME;
|
|
5327
|
-
exports.X402_MAX_AUTHORIZATION_WINDOW_SECONDS = X402_MAX_AUTHORIZATION_WINDOW_SECONDS;
|
|
5328
|
-
exports.X402_PAYMENT_HEADER_NAME = X402_PAYMENT_HEADER_NAME;
|
|
5329
|
-
exports.X402_PAYMENT_HEADER_NAMES_SENT = X402_PAYMENT_HEADER_NAMES_SENT;
|
|
5330
|
-
exports.X402_PAYMENT_REQUIRED_HEADER_NAME = X402_PAYMENT_REQUIRED_HEADER_NAME;
|
|
5331
|
-
exports.X402_PAYMENT_RESPONSE_HEADER_NAME = X402_PAYMENT_RESPONSE_HEADER_NAME;
|
|
5332
|
-
exports.X402_SETTLEMENT_FORWARD_MARGIN_SECONDS = X402_SETTLEMENT_FORWARD_MARGIN_SECONDS;
|
|
5333
5008
|
exports.addressFromKey = addressFromKey;
|
|
5334
5009
|
exports.assertSecureX402RetryTarget = assertSecureX402RetryTarget;
|
|
5335
|
-
exports.buildSweepAuthorizationMessage = buildSweepAuthorizationMessage;
|
|
5336
|
-
exports.buildSweepTypedData = buildSweepTypedData;
|
|
5337
|
-
exports.buildX402ExpectedMessage = buildX402ExpectedMessage;
|
|
5338
|
-
exports.compareNodeVersions = compareNodeVersions;
|
|
5339
5010
|
exports.composeDescription = composeDescription;
|
|
5340
|
-
exports.connectorRerunCommand = connectorRerunCommand;
|
|
5341
|
-
exports.connectorSpec = connectorSpec;
|
|
5342
|
-
exports.createNextStepBuilder = createNextStepBuilder;
|
|
5343
|
-
exports.decodeBase64Json = decodeBase64Json;
|
|
5344
|
-
exports.decodeBase64Utf8 = decodeBase64Utf8;
|
|
5345
|
-
exports.defaultNextToolFor = defaultNextToolFor;
|
|
5346
5011
|
exports.discoverMerchantMcpUrl = discoverMerchantMcpUrl;
|
|
5347
|
-
exports.encodeBase64Json = encodeBase64Json;
|
|
5348
|
-
exports.encodeBase64Utf8 = encodeBase64Utf8;
|
|
5349
|
-
exports.encodePaymentProof = encodePaymentProof;
|
|
5350
5012
|
exports.havenTools = havenTools;
|
|
5351
|
-
exports.isConnectorChannel = isConnectorChannel;
|
|
5352
|
-
exports.isErc7710Option = isErc7710Option;
|
|
5353
5013
|
exports.isSecureX402RetryTarget = isSecureX402RetryTarget;
|
|
5354
|
-
exports.isSupportedNodeVersion = isSupportedNodeVersion;
|
|
5355
|
-
exports.isSweepableChain = isSweepableChain;
|
|
5356
5014
|
exports.isZeroSettlementTxHash = isZeroSettlementTxHash;
|
|
5357
|
-
exports.normalizePaymentRequired = normalizePaymentRequired;
|
|
5358
|
-
exports.parseNextTool = parseNextTool;
|
|
5359
|
-
exports.parsePaymentRequired = parsePaymentRequired;
|
|
5360
|
-
exports.parsePaymentRequiredResponse = parsePaymentRequiredResponse;
|
|
5361
5015
|
exports.readX402ReceiptPayer = readX402ReceiptPayer;
|
|
5362
|
-
exports.renderNextTool = renderNextTool;
|
|
5363
|
-
exports.resolveConnectorChannel = resolveConnectorChannel;
|
|
5364
|
-
exports.resolveTokenFromAddress = resolveTokenFromAddress;
|
|
5365
5016
|
exports.resolveX402RetryTarget = resolveX402RetryTarget;
|
|
5366
5017
|
exports.sameUrl = sameUrl;
|
|
5367
|
-
exports.selectErc7710PaymentOption = selectErc7710PaymentOption;
|
|
5368
|
-
exports.selectPaymentOption = selectPaymentOption;
|
|
5369
|
-
exports.selectStandardPaymentOption = selectStandardPaymentOption;
|
|
5370
|
-
exports.selectX402SettlementScheme = selectX402SettlementScheme;
|
|
5371
5018
|
exports.signHash = signHash;
|
|
5372
5019
|
exports.signUserOpTypedDataForDelegation = signUserOpTypedDataForDelegation;
|
|
5373
|
-
exports.signerUpdateFallback = signerUpdateFallback;
|
|
5374
|
-
exports.sweepUsdcAddress = sweepUsdcAddress;
|
|
5375
|
-
exports.sweepUsdcDomain = sweepUsdcDomain;
|
|
5376
|
-
exports.toStandardPaymentRequirements = toStandardPaymentRequirements;
|
|
5377
5020
|
exports.toolDescriptions = toolDescriptions;
|
|
5378
|
-
exports.unsupportedNodeVersionMessage = unsupportedNodeVersionMessage;
|
|
5379
|
-
exports.validateStandardX402PaymentHeader = validateStandardX402PaymentHeader;
|
|
5380
5021
|
exports.verifyPaymentReceipt = verifyPaymentReceipt;
|
|
5381
5022
|
exports.verifySignature = verifySignature;
|
|
5382
|
-
exports.x402AssetTransferMethod = x402AssetTransferMethod;
|
|
5383
|
-
exports.x402AuthorizationAmount = x402AuthorizationAmount;
|
|
5384
|
-
exports.x402FacilitatorAddresses = x402FacilitatorAddresses;
|
|
5385
|
-
exports.x402V2PaymentEnvelope = x402V2PaymentEnvelope;
|
|
5386
5023
|
//# sourceMappingURL=index.cjs.map
|
|
5387
5024
|
//# sourceMappingURL=index.cjs.map
|