@haven_ai/sdk 0.3.0-alpha.0 → 0.5.0-alpha.1
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-BUMXmruY.d.cts +2731 -0
- package/dist/base64-BUMXmruY.d.ts +2731 -0
- package/dist/chunk-GLNG2GF7.js +903 -0
- package/dist/chunk-GLNG2GF7.js.map +1 -0
- package/dist/chunk-JKUIE45B.cjs +964 -0
- package/dist/chunk-JKUIE45B.cjs.map +1 -0
- package/dist/chunk-KQ7JXKTV.js +902 -0
- package/dist/chunk-KQ7JXKTV.js.map +1 -0
- package/dist/chunk-QSSVOPWA.cjs +970 -0
- package/dist/chunk-QSSVOPWA.cjs.map +1 -0
- package/dist/edge.cjs +271 -0
- package/dist/edge.cjs.map +1 -0
- package/dist/edge.d.cts +105 -0
- package/dist/edge.d.ts +105 -0
- package/dist/edge.js +56 -0
- package/dist/edge.js.map +1 -0
- package/dist/index.cjs +1100 -1391
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -2091
- package/dist/index.d.ts +145 -2091
- package/dist/index.js +518 -1163
- 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 +24 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,1406 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
apiKey: string;
|
|
6
|
-
/** Agent's delegate EOA private key. If provided, the SDK handles signing automatically. */
|
|
7
|
-
delegateKey?: string;
|
|
8
|
-
/** Haven API base URL (default: http://localhost:3001) */
|
|
9
|
-
baseUrl?: string;
|
|
10
|
-
/** Optional wallet identity to send as the x402-wallet header. */
|
|
11
|
-
x402Wallet?: string;
|
|
12
|
-
/** Timeout in ms for individual HTTP requests (default: 30000) */
|
|
13
|
-
requestTimeout?: number;
|
|
14
|
-
/** Timeout (ms) for MERCHANT-facing requests — x402/MPP probes, MCP
|
|
15
|
-
* handshakes, paid retries. Separate from requestTimeout (Haven API):
|
|
16
|
-
* merchants may settle on-chain synchronously, so the default is
|
|
17
|
-
* deliberately generous. #1300. */
|
|
18
|
-
merchantTimeout?: number;
|
|
19
|
-
/** Timeout in ms when polling for tx confirmation (default: 90000) */
|
|
20
|
-
confirmationTimeout?: number;
|
|
21
|
-
/** Polling interval in ms when waiting for confirmation (default: 3000) */
|
|
22
|
-
pollingInterval?: number;
|
|
23
|
-
/**
|
|
24
|
-
* Extra headers to attach to every request to the Haven API.
|
|
25
|
-
*
|
|
26
|
-
* Used by the MCP server to tag requests with `X-Haven-MCP-Tool: <name>`
|
|
27
|
-
* so the backend can record an audit-log entry per tool invocation. Has
|
|
28
|
-
* no effect on outbound merchant requests (x402 / MPP) — those are
|
|
29
|
-
* standard HTTP and never carry Haven-internal headers.
|
|
30
|
-
*/
|
|
31
|
-
defaultHeaders?: Record<string, string>;
|
|
32
|
-
/**
|
|
33
|
-
* JSON-RPC RPC URLs keyed by EIP-155 chain ID.
|
|
34
|
-
*
|
|
35
|
-
* When provided for a chain, the SDK waits for ≥1 on-chain confirmation of
|
|
36
|
-
* the AllowanceModule funding tx before retrying the merchant. This prevents
|
|
37
|
-
* the race where the merchant's `balanceOf(delegate)` call runs before the
|
|
38
|
-
* funding block has propagated to the merchant's RPC node.
|
|
39
|
-
*
|
|
40
|
-
* Without this option the SDK proceeds as soon as Haven's backend confirms
|
|
41
|
-
* submission (backward-compatible default). Set it to a reliable RPC
|
|
42
|
-
* endpoint (e.g. Alchemy / Infura) for production usage.
|
|
43
|
-
*
|
|
44
|
-
* @example { 8453: 'https://mainnet.base.org' }
|
|
45
|
-
*/
|
|
46
|
-
chainRpcs?: Record<number, string>;
|
|
47
|
-
}
|
|
48
|
-
interface PaymentRequest {
|
|
49
|
-
/** Token symbol: "EURe", "USDC.e", or "xDAI" */
|
|
50
|
-
token: string;
|
|
51
|
-
/** Amount as a decimal string, e.g. "5.00" */
|
|
52
|
-
amount: string;
|
|
53
|
-
/** Recipient Ethereum address (0x...) */
|
|
54
|
-
to: string;
|
|
55
|
-
/**
|
|
56
|
-
* Optional dedupe key (#1207): a retried request with the same key returns
|
|
57
|
-
* the FIRST request's result instead of minting a second transfer or a
|
|
58
|
-
* second approval. Same contract as /machine-payments/send. Max 128 chars.
|
|
59
|
-
*/
|
|
60
|
-
idempotencyKey?: string;
|
|
61
|
-
}
|
|
62
|
-
interface SignData {
|
|
63
|
-
/** The hash to sign (keccak256, 0x-prefixed) */
|
|
64
|
-
hash: string;
|
|
65
|
-
/**
|
|
66
|
-
* Delegation rail: 'eip712_userop' (funding redemption) or
|
|
67
|
-
* 'eip712_delegation' (erc7710 settlement child). The backend spec makes it
|
|
68
|
-
* required; the legacy AllowanceModule reading — absent = raw ECDSA over
|
|
69
|
-
* `hash` — is retired (#2850), and the SDK client refuses an absent scheme.
|
|
70
|
-
* The session rail's 'eip191_userop' is retired (#834).
|
|
71
|
-
*
|
|
72
|
-
* When present, `hash` is NOT what gets signed — `typed_data` is (#1138).
|
|
73
|
-
*/
|
|
74
|
-
signature_scheme?: 'eip712_userop' | 'eip712_delegation';
|
|
75
|
-
/**
|
|
76
|
-
* EIP-712 payload the account validates, signed VERBATIM (#829). Present
|
|
77
|
-
* whenever `signature_scheme` is — never reconstruct it from `components`.
|
|
78
|
-
*/
|
|
79
|
-
typed_data?: {
|
|
80
|
-
domain: Record<string, unknown>;
|
|
81
|
-
types: Record<string, unknown>;
|
|
82
|
-
primaryType: string;
|
|
83
|
-
message: Record<string, unknown>;
|
|
84
|
-
};
|
|
85
|
-
/** Breakdown of values that were hashed — useful for debugging */
|
|
86
|
-
components: {
|
|
87
|
-
/**
|
|
88
|
-
* The PAYER account (the user's smart account). Not to be confused with
|
|
89
|
-
* `account`, which on the funding shapes holds the DELEGATE account
|
|
90
|
-
* address.
|
|
91
|
-
*/
|
|
92
|
-
payer_account?: string;
|
|
93
|
-
token: string;
|
|
94
|
-
to: string;
|
|
95
|
-
amount: string;
|
|
96
|
-
payment_token: string;
|
|
97
|
-
payment: string;
|
|
98
|
-
nonce: number;
|
|
99
|
-
};
|
|
100
|
-
/** Human-readable signing instructions */
|
|
101
|
-
instructions: string;
|
|
102
|
-
}
|
|
103
|
-
interface PaymentIntent {
|
|
104
|
-
/** Unique payment ID */
|
|
105
|
-
paymentId: string;
|
|
106
|
-
/** Current status */
|
|
107
|
-
status: 'pending_signature';
|
|
108
|
-
/** ISO 8601 expiry timestamp */
|
|
109
|
-
expiresAt: string;
|
|
110
|
-
/** Data needed to sign the payment */
|
|
111
|
-
signData: SignData;
|
|
112
|
-
}
|
|
113
|
-
type PaymentStatus = 'pending_signature' | 'submitted' | 'confirmed' | 'pending_approval' | 'approved' | 'proposed' | 'executed' | 'rejected' | 'expired' | 'failed';
|
|
114
|
-
interface PaymentResult {
|
|
115
|
-
/** Unique payment ID */
|
|
116
|
-
paymentId: string;
|
|
117
|
-
/** Final status */
|
|
118
|
-
status: PaymentStatus;
|
|
119
|
-
/** Token that was sent */
|
|
120
|
-
token: string;
|
|
121
|
-
/** Amount that was sent (human-readable) */
|
|
122
|
-
amount: string;
|
|
123
|
-
/** Recipient address */
|
|
124
|
-
to: string;
|
|
125
|
-
/** On-chain transaction hash (present when confirmed) */
|
|
126
|
-
txHash: string | null;
|
|
127
|
-
/** Error message (present when failed) */
|
|
128
|
-
errorMessage: string | null;
|
|
129
|
-
/** Block explorer URL for the transaction (chain-dependent) */
|
|
130
|
-
explorerUrl: string | null;
|
|
131
|
-
/** ISO 8601 timestamps */
|
|
132
|
-
createdAt: string;
|
|
133
|
-
signedAt: string | null;
|
|
134
|
-
submittedAt: string | null;
|
|
135
|
-
confirmedAt: string | null;
|
|
136
|
-
expiresAt: string;
|
|
137
|
-
/**
|
|
138
|
-
* Platform fee surfaced on the result so it's never silently collected. Dark
|
|
139
|
-
* today (`amount` "0", `applied` false); always present so it's visible the
|
|
140
|
-
* moment fees go live.
|
|
141
|
-
*/
|
|
142
|
-
fee?: PaymentFee | null;
|
|
143
|
-
}
|
|
144
|
-
/** The Haven platform fee applied to a payment (#386). */
|
|
145
|
-
interface PaymentFee {
|
|
146
|
-
/** Human-readable fee amount ("0" while the fee module is dark). */
|
|
147
|
-
amount: string;
|
|
148
|
-
/** Token the fee is denominated in. */
|
|
149
|
-
token: string;
|
|
150
|
-
/** Fee as basis points of gross (0 while dark). */
|
|
151
|
-
basisPoints: number;
|
|
152
|
-
/** True when a non-zero fee was actually applied. */
|
|
153
|
-
applied: boolean;
|
|
154
|
-
}
|
|
155
|
-
/** Payment requirements from an HTTP 402 response (x402 protocol). */
|
|
156
|
-
interface X402PaymentRequired {
|
|
157
|
-
x402Version: number;
|
|
158
|
-
resource: {
|
|
159
|
-
url: string;
|
|
160
|
-
description?: string;
|
|
161
|
-
mimeType?: string;
|
|
162
|
-
[key: string]: unknown;
|
|
163
|
-
};
|
|
164
|
-
accepts: X402PaymentOption[];
|
|
165
|
-
error?: string;
|
|
166
|
-
extensions?: Record<string, unknown>;
|
|
167
|
-
}
|
|
168
|
-
/** A single payment option from x402 PaymentRequired. */
|
|
169
|
-
interface X402PaymentOption {
|
|
170
|
-
scheme: string;
|
|
171
|
-
network: string;
|
|
172
|
-
amount: string;
|
|
173
|
-
maxAmountRequired?: string;
|
|
174
|
-
resource?: string;
|
|
175
|
-
description?: string;
|
|
176
|
-
mimeType?: string;
|
|
177
|
-
asset: string;
|
|
178
|
-
payTo: string;
|
|
179
|
-
maxTimeoutSeconds: number;
|
|
180
|
-
/**
|
|
181
|
-
* Merchant-supplied scheme metadata. Two keys are load-bearing for Haven
|
|
182
|
-
* (#1453), both from MetaMask's erc7710 x402 shape:
|
|
183
|
-
*
|
|
184
|
-
* assetTransferMethod — 'erc7710' marks this entry as settleable by
|
|
185
|
-
* redeeming a delegation chain. Absent/other means
|
|
186
|
-
* the standard EIP-3009 authorization.
|
|
187
|
-
* facilitatorAddresses — who may redeem it, pinned into the settlement
|
|
188
|
-
* child's redeemer caveat (#1058).
|
|
189
|
-
*
|
|
190
|
-
* Left as an open record on purpose: the field is the merchant's, and
|
|
191
|
-
* narrowing it to Haven's two keys would silently drop everything else a
|
|
192
|
-
* merchant sends. Read it through `x402AssetTransferMethod` /
|
|
193
|
-
* `x402FacilitatorAddresses` rather than indexing it raw.
|
|
194
|
-
*/
|
|
195
|
-
extra?: Record<string, unknown>;
|
|
196
|
-
}
|
|
197
|
-
/** Receipt returned after a successful x402 payment. */
|
|
198
|
-
interface X402Receipt {
|
|
199
|
-
success: boolean;
|
|
200
|
-
paymentId: string;
|
|
201
|
-
txHash: string;
|
|
202
|
-
token: string;
|
|
203
|
-
amount: string;
|
|
204
|
-
to: string;
|
|
205
|
-
resourceUrl: string;
|
|
206
|
-
explorerUrl: string;
|
|
207
|
-
accepted?: X402PaymentOption;
|
|
208
|
-
paymentHeader?: string;
|
|
209
|
-
merchantTo?: string | null;
|
|
210
|
-
payer?: string;
|
|
211
|
-
chainId?: number;
|
|
212
|
-
haven?: {
|
|
213
|
-
paymentId: string;
|
|
214
|
-
fundingTxHash: string;
|
|
215
|
-
fundingExplorerUrl: string;
|
|
216
|
-
};
|
|
217
|
-
merchant?: {
|
|
218
|
-
payTo: string | null;
|
|
219
|
-
settlementTxHash?: string | null;
|
|
220
|
-
settlementExplorerUrl?: string | null;
|
|
221
|
-
};
|
|
222
|
-
x402?: {
|
|
223
|
-
amount: string;
|
|
224
|
-
token: string;
|
|
225
|
-
network: string;
|
|
226
|
-
asset: string;
|
|
227
|
-
resource: string;
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
interface X402AuthorizationOptions {
|
|
231
|
-
/** Stable caller-supplied key for this user intent. Prevents duplicate approvals across fresh 402 quotes. */
|
|
232
|
-
idempotencyKey?: string;
|
|
233
|
-
/**
|
|
234
|
-
* #1307: the merchant MCP-tool call context this quote was made against
|
|
235
|
-
* (merchant_url, tool_name, arguments, mcp_transport). Persisted on the
|
|
236
|
-
* intent so `getX402MerchantCallContext` can rehydrate it by payment_id at
|
|
237
|
-
* settle/complete time instead of the caller re-threading it. Optional —
|
|
238
|
-
* omit for a non-MCP-tool x402 merchant (plain HTTP resource).
|
|
239
|
-
*/
|
|
240
|
-
mcpCallContext?: X402McpCallContext;
|
|
241
|
-
/**
|
|
242
|
-
* #1348: the agent's delegate address, when the caller already resolved it
|
|
243
|
-
* from `getAgent()` in this same flow — skips `createX402Intent`'s internal
|
|
244
|
-
* agent fetch (one full round trip on every guided purchase). Staleness
|
|
245
|
-
* caveat (#1358 review): the backend derives the funding shape by comparing
|
|
246
|
-
* `payTo` to the CURRENT delegate address, so a value made stale by a
|
|
247
|
-
* delegate rotation mid-flow is not always a clean failure — a pinned-budget
|
|
248
|
-
* agent gets a 403, but an open-budget delegation agent would route to the
|
|
249
|
-
* settlement shape with the stale address. The window is one tool call
|
|
250
|
-
* (previously sub-millisecond, now the merchant-quote duration), never
|
|
251
|
-
* externally suppliable; server-truth hardening is tracked in #1360. Only
|
|
252
|
-
* pass an address fetched in THIS flow; omit to keep the self-contained
|
|
253
|
-
* fetch.
|
|
254
|
-
*/
|
|
255
|
-
delegateAddress?: string;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Keyless x402 construct result.
|
|
259
|
-
*
|
|
260
|
-
* Returned by `createX402Intent` — the non-custodial half of an x402 payment.
|
|
261
|
-
* It carries the unsigned funding hash (`signData.hash`, Safe → delegate EOA)
|
|
262
|
-
* plus everything the *edge* needs to build and sign the EIP-3009 merchant
|
|
263
|
-
* header itself. The construct path never signs; both delegate signatures
|
|
264
|
-
* (funding hash + merchant header) happen on the machine that holds the key.
|
|
265
|
-
*/
|
|
266
|
-
interface X402Intent {
|
|
267
|
-
/** Haven payment id for the funding transfer. */
|
|
268
|
-
paymentId: string;
|
|
269
|
-
/** Stable key used to create or refresh this x402 funding intent. */
|
|
270
|
-
idempotencyKey: string;
|
|
271
|
-
status: 'pending_signature';
|
|
272
|
-
/** ISO 8601 expiry of the funding intent, if returned. */
|
|
273
|
-
expiresAt?: string;
|
|
274
|
-
/** The unsigned funding hash to sign with the delegate key (Safe → delegate EOA). */
|
|
275
|
-
signData: SignData;
|
|
276
|
-
/** The selected x402 option — the edge needs this to build the EIP-3009 header. */
|
|
277
|
-
accepted: X402PaymentOption;
|
|
278
|
-
/** Resource URL the 402 came from. */
|
|
279
|
-
resourceUrl: string;
|
|
280
|
-
/** Merchant payTo address (the final recipient of the EIP-3009 transfer). */
|
|
281
|
-
merchantTo: string;
|
|
282
|
-
/** Atomic amount the edge signer must authorize in the merchant header. */
|
|
283
|
-
amountAtomic: string;
|
|
284
|
-
/** Token contract the merchant header must pay. */
|
|
285
|
-
asset: string;
|
|
286
|
-
/** x402 network the merchant header must use. */
|
|
287
|
-
network: string;
|
|
288
|
-
/** Haven-authenticated binding over the x402 expected context. */
|
|
289
|
-
expectedAuth: X402ExpectedAuth;
|
|
290
|
-
/**
|
|
291
|
-
* #1690: the payer identity Haven bound into the expected context (v3),
|
|
292
|
-
* relayed VERBATIM to the signer's wire shape. Absent until the backend
|
|
293
|
-
* flips X402_EMIT_PAYER_CONTEXT.
|
|
294
|
-
*/
|
|
295
|
-
payerDelegate?: string;
|
|
296
|
-
payerAgentId?: string;
|
|
297
|
-
/**
|
|
298
|
-
* EIP-712 digest of `signData.typed_data`, present on the delegation rail
|
|
299
|
-
* (#1138). The edge signer needs it to reconstruct the v2 expected-context
|
|
300
|
-
* message that Haven signed.
|
|
301
|
-
*/
|
|
302
|
-
expectedTypedDataHash?: string;
|
|
303
|
-
/** Delegate EOA the funding transfer tops up (the x402 payer). */
|
|
304
|
-
fundingTo: string;
|
|
305
|
-
}
|
|
306
|
-
interface X402ExpectedContext {
|
|
307
|
-
paymentId: string;
|
|
308
|
-
payloadHash: string;
|
|
309
|
-
resourceUrl: string;
|
|
310
|
-
merchantTo: string;
|
|
311
|
-
amount: string;
|
|
312
|
-
asset: string;
|
|
313
|
-
network: string;
|
|
314
|
-
/** Optional ISO expiry for the funding/quote window. When present, it is bound into the Haven-authenticated context. */
|
|
315
|
-
expiresAt?: string;
|
|
316
|
-
/**
|
|
317
|
-
* EIP-712 digest of the typed data the account actually validates
|
|
318
|
-
* (delegation rail, #1138). Present ⇒ the context is **version 2** and the
|
|
319
|
-
* signer must sign that typed data, never `payloadHash`.
|
|
320
|
-
*
|
|
321
|
-
* On the delegation rail `payloadHash` is the bare ERC-4337 UserOp hash,
|
|
322
|
-
* which is NOT what the account validates — binding it alone would leave the
|
|
323
|
-
* edge signer unable to verify the payload it is being asked to sign. Binding
|
|
324
|
-
* this digest makes Haven's declaration cover the real payload.
|
|
325
|
-
*/
|
|
326
|
-
typedDataHash?: string;
|
|
327
|
-
/**
|
|
328
|
-
* The DELEGATE ADDRESS this quote was created for (#1690). Present ⇒ the
|
|
329
|
-
* context is **version 3** and the signer refuses to sign when this is not
|
|
330
|
-
* its own delegate — the guard that turns "quote as agent A, sign as agent
|
|
331
|
-
* B" from an on-chain revert three layers later into a named refusal.
|
|
332
|
-
* Inside the Haven-signed message on purpose: outside it, it is forgeable.
|
|
333
|
-
*/
|
|
334
|
-
payerDelegate?: string;
|
|
335
|
-
/** The paying agent's id, for the refusal message's diagnosis (#1690). */
|
|
336
|
-
payerAgentId?: string;
|
|
337
|
-
}
|
|
338
|
-
interface X402ExpectedAuth {
|
|
339
|
-
/**
|
|
340
|
-
* 1 = hash-only (legacy rail). 2 = carries `typedDataHash` (delegation rail,
|
|
341
|
-
* #1138).
|
|
342
|
-
*
|
|
343
|
-
* Deliberately `number`, not a literal union (#1143). This is an **inbound**
|
|
344
|
-
* value: a signer parses a context Haven produced, and a signer older than the
|
|
345
|
-
* backend will legitimately receive a version it does not know. A closed union
|
|
346
|
-
* makes that state unrepresentable, which pushed the rejection down to the
|
|
347
|
-
* schema boundary and produced a raw validation error naming neither the cause
|
|
348
|
-
* nor the fix. The supported set lives in the signer
|
|
349
|
-
* (`SUPPORTED_X402_EXPECTED_VERSIONS`), which fails closed on anything outside
|
|
350
|
-
* it with an actionable message.
|
|
351
|
-
*/
|
|
352
|
-
version: number;
|
|
353
|
-
message: string;
|
|
354
|
-
signature: string;
|
|
355
|
-
signer: string;
|
|
356
|
-
}
|
|
357
|
-
/** Serializable HTTP request state for retrying the same x402 merchant request. */
|
|
358
|
-
interface X402RequestSnapshot {
|
|
359
|
-
url: string;
|
|
360
|
-
method: string;
|
|
361
|
-
headers: [string, string][];
|
|
362
|
-
body?: string;
|
|
363
|
-
}
|
|
364
|
-
interface X402McpTransport {
|
|
365
|
-
handshakeRequired: boolean;
|
|
366
|
-
source: 'path' | 'bazaar';
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* #1307: the merchant MCP-tool call an x402 quote was made against — carried
|
|
370
|
-
* through `createX402Intent`'s options so Haven can persist it for the
|
|
371
|
-
* settle-leg rehydration handoff (`getX402MerchantCallContext`). Convenience
|
|
372
|
-
* metadata for retrying the merchant's OWN JSON-RPC call, never payment
|
|
373
|
-
* authority.
|
|
374
|
-
*/
|
|
375
|
-
interface X402McpCallContext {
|
|
376
|
-
merchantUrl: string;
|
|
377
|
-
toolName: string;
|
|
378
|
-
arguments?: Record<string, unknown>;
|
|
379
|
-
mcpTransport?: X402McpTransport;
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* Response shape of `getX402MerchantCallContext` — the stored merchant call
|
|
383
|
-
* context for a payment_id, rehydrated instead of re-threaded (#1307).
|
|
384
|
-
*/
|
|
385
|
-
interface X402MerchantCallContext {
|
|
386
|
-
paymentId: string;
|
|
387
|
-
merchantUrl: string;
|
|
388
|
-
toolName: string;
|
|
389
|
-
arguments: Record<string, unknown>;
|
|
390
|
-
mcpTransport?: X402McpTransport;
|
|
391
|
-
}
|
|
392
|
-
/** Quote parsed from an HTTP 402 response without creating a Haven payment. */
|
|
393
|
-
interface X402Quote {
|
|
394
|
-
rail: 'x402';
|
|
395
|
-
idempotencyKey: string;
|
|
396
|
-
paymentRequired: X402PaymentRequired;
|
|
397
|
-
accepted: X402PaymentOption;
|
|
398
|
-
/**
|
|
399
|
-
* #2054: which selector produced `accepted`, and therefore which entry every
|
|
400
|
-
* amount on this quote describes. `'standard'` is the untagged,
|
|
401
|
-
* EIP-3009-settleable entry; `'erc7710'` means the merchant advertises NO
|
|
402
|
-
* standard entry, so the quote describes its erc7710 one — settleable only
|
|
403
|
-
* from a delegation-rail account, a fact the quote layer cannot see (the
|
|
404
|
-
* rail is a property of the ACCOUNT, not of the 402). This field is
|
|
405
|
-
* descriptive: the actual settlement scheme is still chosen later, with the
|
|
406
|
-
* rail in hand, by `selectX402SettlementScheme`.
|
|
407
|
-
*/
|
|
408
|
-
acceptedScheme: 'standard' | 'erc7710';
|
|
409
|
-
request: X402RequestSnapshot;
|
|
410
|
-
mcpTransport?: X402McpTransport;
|
|
411
|
-
resourceUrl: string;
|
|
412
|
-
description: string | null;
|
|
413
|
-
mimeType: string | null;
|
|
414
|
-
amountAtomic: string;
|
|
415
|
-
amount: string;
|
|
416
|
-
token: string;
|
|
417
|
-
/**
|
|
418
|
-
* #1351: decimals for `asset` on `network`, resolved from the SAME
|
|
419
|
-
* address→token binding that produced `token` — the quote's own authority on
|
|
420
|
-
* how many atomic units one human unit is. `null` when the merchant's asset
|
|
421
|
-
* is not a token Haven recognises on that network, in which case `token` is
|
|
422
|
-
* an unverified fallback label and NO human→atomic conversion is safe.
|
|
423
|
-
* Consumers converting a human-denominated figure (a user-intent spending
|
|
424
|
-
* cap) MUST fail closed on `null` rather than assume 6.
|
|
425
|
-
*/
|
|
426
|
-
decimals: number | null;
|
|
427
|
-
asset: string;
|
|
428
|
-
network: string;
|
|
429
|
-
chainId: number | null;
|
|
430
|
-
merchantAddress: string;
|
|
431
|
-
maxTimeoutSeconds: number;
|
|
432
|
-
}
|
|
433
|
-
/** State bundle an agent can persist while waiting for manual x402 approval. */
|
|
434
|
-
interface X402ResumeState {
|
|
435
|
-
rail: 'x402';
|
|
436
|
-
paymentId: string;
|
|
437
|
-
idempotencyKey: string;
|
|
438
|
-
paymentRequired: X402PaymentRequired;
|
|
439
|
-
accepted: X402PaymentOption;
|
|
440
|
-
url: string;
|
|
441
|
-
request?: X402RequestSnapshot;
|
|
442
|
-
resourceUrl: string;
|
|
443
|
-
description: string | null;
|
|
444
|
-
amountAtomic: string;
|
|
445
|
-
amount: string;
|
|
446
|
-
token: string;
|
|
447
|
-
asset: string;
|
|
448
|
-
network: string;
|
|
449
|
-
chainId: number | null;
|
|
450
|
-
merchantAddress: string;
|
|
451
|
-
}
|
|
452
|
-
type PaymentResumeState = X402ResumeState;
|
|
453
|
-
interface ResumeAuthorizedX402Input extends X402AuthorizationOptions {
|
|
454
|
-
/** Payment or approval request ID returned by authorizeX402 / haven.fetch. */
|
|
455
|
-
paymentId: string;
|
|
456
|
-
/** Original or freshly parsed x402 requirements for the merchant retry. */
|
|
457
|
-
paymentRequired: X402PaymentRequired;
|
|
458
|
-
}
|
|
459
|
-
interface ResumeX402PaymentInput extends X402AuthorizationOptions {
|
|
460
|
-
/** Payment or approval request ID returned by authorizeX402 / haven.fetch. */
|
|
461
|
-
paymentId: string;
|
|
462
|
-
/** Original paid URL. If paymentRequired is omitted, Haven will call it once to re-read the 402 challenge. */
|
|
463
|
-
url: string;
|
|
464
|
-
/** Original fetch options. Reused for the 402 probe and final merchant retry. */
|
|
465
|
-
init?: RequestInit;
|
|
466
|
-
/** Serializable original request captured by quoteX402() / pending approval errors. */
|
|
467
|
-
request?: X402RequestSnapshot;
|
|
468
|
-
/** Original or freshly parsed x402 requirements. Supplying this avoids an extra merchant 402 probe. */
|
|
469
|
-
paymentRequired?: X402PaymentRequired;
|
|
470
|
-
}
|
|
471
|
-
type MachinePaymentRail = 'x402' | 'mpp_demo' | 'mpp_crypto' | 'stripe_deposit' | 'spt';
|
|
472
|
-
interface HavenAgent {
|
|
473
|
-
id: string;
|
|
474
|
-
name: string;
|
|
475
|
-
status: string;
|
|
476
|
-
/** The agent's Haven account (smart account) address. */
|
|
477
|
-
accountAddress: string;
|
|
478
|
-
delegateAddress: string;
|
|
479
|
-
chainId: number;
|
|
480
|
-
/**
|
|
481
|
-
* Which on-chain policy primitive gates this agent's spend (#1306): the
|
|
482
|
-
* legacy Safe AllowanceModule (retired — no account can enter it since
|
|
483
|
-
* #1984, and it cannot spend since #1986) or the delegation
|
|
484
|
-
* rail's active budget delegations (#1090). Read-only reporting — the
|
|
485
|
-
* on-chain state is the actual gate either way, this only says which
|
|
486
|
-
* mechanism a caller should read/derive from.
|
|
487
|
-
*/
|
|
488
|
-
executionRail: 'legacy' | 'delegation';
|
|
489
|
-
}
|
|
490
|
-
interface HavenAllowance {
|
|
491
|
-
id: string;
|
|
492
|
-
tokenAddress: string;
|
|
493
|
-
tokenSymbol: string;
|
|
494
|
-
configuredAmount: string;
|
|
495
|
-
resetPeriodMin: number;
|
|
496
|
-
onchain: {
|
|
497
|
-
amount: string;
|
|
498
|
-
spent: string;
|
|
499
|
-
remaining: string;
|
|
500
|
-
effectiveSpent: string;
|
|
501
|
-
resetTimeMin: number;
|
|
502
|
-
lastResetMin: number;
|
|
503
|
-
nonce: number;
|
|
504
|
-
isResetPending: boolean;
|
|
505
|
-
/**
|
|
506
|
-
* Delegation rail only (#1319, provenance for #1145's fallback): true
|
|
507
|
-
* when `remaining` came from a live on-chain enforcer read, false when
|
|
508
|
-
* the read failed and `remaining` is the fallback full configured
|
|
509
|
-
* budget. Undefined on the legacy AllowanceModule rail, which has no
|
|
510
|
-
* fallback concept. Reporting only — the on-chain policy remains the
|
|
511
|
-
* actual spend gate either way.
|
|
512
|
-
*/
|
|
513
|
-
remainingIsFromChain?: boolean;
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
interface HavenAllowanceSummary {
|
|
517
|
-
agentId: string;
|
|
518
|
-
accountAddress: string;
|
|
519
|
-
delegateAddress: string;
|
|
520
|
-
chainId: number;
|
|
521
|
-
allowances: HavenAllowance[];
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Post-purchase allowance/budget summary attached to a settled x402 payment
|
|
525
|
-
* (#1310). Read-only reporting — the on-chain policy remains the actual
|
|
526
|
-
* spend gate either way, this only says what is left after the purchase.
|
|
527
|
-
*
|
|
528
|
-
* Deliberately the SAME rail-labeled field spelling as #1306's
|
|
529
|
-
* catalog-purchase preflight `allowance` block (never a new spelling),
|
|
530
|
-
* minus the preflight-only `sufficient` field: post-purchase reporting
|
|
531
|
-
* answers "what is left", not "was this purchase covered". Read through the
|
|
532
|
-
* exact same source as {@link HavenAllowanceSummary} / `haven_get_allowances`
|
|
533
|
-
* (`GET /machine-payments/allowances`; delegation-rail values are the #1090
|
|
534
|
-
* `deriveDelegationBudgets`-backed enforcer read, never `agent_allowances`),
|
|
535
|
-
* so this can never disagree with `haven_get_allowances` for the same
|
|
536
|
-
* fixture.
|
|
537
|
-
*/
|
|
538
|
-
interface PostPurchaseAllowanceSummary {
|
|
539
|
-
/** Which on-chain policy primitive gates this agent's spend (#1306 labeling). */
|
|
540
|
-
rail: 'legacy' | 'delegation';
|
|
541
|
-
/** Remaining atomic units, read through the same source as {@link HavenAllowance.onchain.remaining}. */
|
|
542
|
-
remaining_atomic: string;
|
|
543
|
-
/** Human-readable remaining, e.g. "4.96 USDC". Omitted when the token's decimals are unknown. */
|
|
544
|
-
remaining_display?: string;
|
|
545
|
-
token_symbol?: string;
|
|
546
|
-
token_address?: string;
|
|
547
|
-
/** Minutes — mirrors {@link HavenAllowance.resetPeriodMin} / the delegation's period. */
|
|
548
|
-
reset_period?: number;
|
|
549
|
-
source: 'allowance_module' | 'active_delegations';
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Affirmative spend-readiness for the authenticated agent, derived from the raw
|
|
553
|
-
* agent status plus the remaining spend authority the backend reports per rail
|
|
554
|
-
* (the on-chain AllowanceModule on the legacy rail; the active budget
|
|
555
|
-
* delegation on the delegation rail — #1135):
|
|
556
|
-
* - `ready` — active and at least one token has remaining spend authority.
|
|
557
|
-
* - `needs_approval`— active but no remaining spend authority to auto-spend.
|
|
558
|
-
* The over-budget outcome differs by rail: on the legacy
|
|
559
|
-
* AllowanceModule rail the payment is queued for the wallet
|
|
560
|
-
* owner to approve in Haven; on the delegation rail there is
|
|
561
|
-
* NO approval queue — an over-budget redemption reverts
|
|
562
|
-
* on-chain, so the owner must grant or raise the budget in
|
|
563
|
-
* Haven before the agent can pay.
|
|
564
|
-
* - `revoked` — the agent's status is not `active`; nothing auto-executes.
|
|
565
|
-
*
|
|
566
|
-
* Note: a hard-paused/disabled credential is rejected by the API before this
|
|
567
|
-
* call returns, so it surfaces as an API error rather than `revoked`. `revoked`
|
|
568
|
-
* is reached when the request authenticates but the agent status is non-active.
|
|
569
|
-
*
|
|
570
|
-
* Wallet token balance is intentionally NOT folded in here: the on-chain
|
|
571
|
-
* remaining allowance is the gate Haven enforces, and insufficient wallet
|
|
572
|
-
* funding surfaces at pay time as INSUFFICIENT_FUNDS.
|
|
573
|
-
*/
|
|
574
|
-
type HavenAgentReadiness = 'ready' | 'needs_approval' | 'revoked';
|
|
575
|
-
/** Compact, agent-facing per-token spend authority for the bootstrap summary. */
|
|
576
|
-
interface HavenAgentAllowanceSummary {
|
|
577
|
-
tokenSymbol: string;
|
|
578
|
-
/** Live on-chain remaining allowance in atomic units. */
|
|
579
|
-
remainingAtomic: string;
|
|
580
|
-
/** Human-readable remaining, e.g. "4.96 USDC". */
|
|
581
|
-
remainingDisplay: string;
|
|
582
|
-
/** Configured allowance amount (atomic) the owner granted. */
|
|
583
|
-
configuredAmount: string;
|
|
584
|
-
resetPeriodMin: number;
|
|
585
|
-
isResetPending: boolean;
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* One-shot "am I ready?" bootstrap: identity + live spend authority + a
|
|
589
|
-
* readiness signal, so an agent can answer "who am I and can I pay right now"
|
|
590
|
-
* from a single call at session start. Superset of {@link HavenAgent}.
|
|
591
|
-
*/
|
|
592
|
-
interface HavenAgentSummary extends HavenAgent {
|
|
593
|
-
/**
|
|
594
|
-
* @deprecated Use {@link HavenAgentSummary.spend_authority_readiness} —
|
|
595
|
-
* same value, honest name. This signal covers hosted identity + on-chain
|
|
596
|
-
* spend authority ONLY; it says nothing about the LOCAL signer, which the
|
|
597
|
-
* hosted side cannot see (verify via a signer tool or connect --doctor).
|
|
598
|
-
* Kept as an alias; removal earliest after the next release train (#1590).
|
|
599
|
-
*/
|
|
600
|
-
readiness: HavenAgentReadiness;
|
|
601
|
-
/**
|
|
602
|
-
* Spend-authority readiness: hosted identity + on-chain remaining spend
|
|
603
|
-
* authority. Deliberately named for what it covers — the LOCAL signer's
|
|
604
|
-
* availability is NOT included and must be verified separately (a signer
|
|
605
|
-
* tool call, or the connector's `--doctor`, whose exact command this build
|
|
606
|
-
* renders from `HAVEN_CONNECTOR_CHANNEL` — see `connector-channel.ts`).
|
|
607
|
-
*/
|
|
608
|
-
spend_authority_readiness: HavenAgentReadiness;
|
|
609
|
-
allowances: HavenAgentAllowanceSummary[];
|
|
610
|
-
}
|
|
611
|
-
/**
|
|
612
|
-
* #2960 — one party vocabulary for "who paid" a Haven payment, additive
|
|
613
|
-
* alongside every existing lone `payer*`/`*Address` field (same discipline
|
|
614
|
-
* as the #2907 `safe`/`account` dual-emit, except these four are DISTINCT
|
|
615
|
-
* addresses, not same-value twins of one old field).
|
|
616
|
-
*/
|
|
617
|
-
interface PaymentParties {
|
|
618
|
-
treasuryAccount: string | null;
|
|
619
|
-
delegate: string | null;
|
|
620
|
-
delegateAccount: string | null;
|
|
621
|
-
merchant: string | null;
|
|
622
|
-
}
|
|
623
|
-
/** @internal wire shape of {@link PaymentParties}. */
|
|
624
|
-
interface RawPaymentParties {
|
|
625
|
-
treasury_account: string | null;
|
|
626
|
-
delegate: string | null;
|
|
627
|
-
delegate_account: string | null;
|
|
628
|
-
merchant: string | null;
|
|
629
|
-
}
|
|
630
|
-
interface HavenPaymentReceipt {
|
|
631
|
-
id: string;
|
|
632
|
-
paymentId: string;
|
|
633
|
-
paymentIntentId?: string | null;
|
|
634
|
-
approvalRequestId?: string | null;
|
|
635
|
-
rail: string;
|
|
636
|
-
proofStatus: string;
|
|
637
|
-
/**
|
|
638
|
-
* @deprecated (#2998) meaning depends on the settlement scheme — the
|
|
639
|
-
* account → delegate funding transaction on eip3009, the (only) settlement
|
|
640
|
-
* transaction on erc7710. Prefer {@link fundingTxHash} / {@link settlementTxHash}, which
|
|
641
|
-
* name which is which.
|
|
642
|
-
*/
|
|
643
|
-
txHash: string;
|
|
644
|
-
/** The account → delegate funding transaction, relayed by Haven (#2998); null on erc7710 (no funding leg) and on retired mpp-rail rows. */
|
|
645
|
-
fundingTxHash: string | null;
|
|
646
|
-
/**
|
|
647
|
-
* The delegate → merchant settlement transaction (#2998). Trust level differs
|
|
648
|
-
* by scheme: on erc7710 it is `txHash` itself and Haven VERIFIED it on-chain
|
|
649
|
-
* before the receipt existed; on eip3009 it is the merchant's claim as relayed
|
|
650
|
-
* (PAYMENT-RESPONSE), NOT verified on-chain by Haven — cite it as such.
|
|
651
|
-
*/
|
|
652
|
-
settlementTxHash: string | null;
|
|
653
|
-
chainId: number;
|
|
654
|
-
resourceUrl: string;
|
|
655
|
-
merchantAddress: string | null;
|
|
656
|
-
payerAddress: string;
|
|
657
|
-
/** #2960: additive alongside `payerAddress` above (`parties.treasury_account` only). */
|
|
658
|
-
parties?: PaymentParties;
|
|
659
|
-
settlementAddress: string;
|
|
660
|
-
tokenSymbol: string;
|
|
661
|
-
tokenAddress: string;
|
|
662
|
-
amountRaw: string;
|
|
663
|
-
amount: string;
|
|
664
|
-
challengeId: string | null;
|
|
665
|
-
idempotencyKey: string | null;
|
|
666
|
-
challengePayload?: Record<string, unknown> | null;
|
|
667
|
-
selectedPayment?: Record<string, unknown> | null;
|
|
668
|
-
paymentProofHeaderName: string | null;
|
|
669
|
-
protocolReceiptHeaderName: string | null;
|
|
670
|
-
protocolReceiptPayload?: Record<string, unknown> | null;
|
|
671
|
-
merchantStatus: number | null;
|
|
672
|
-
confirmedAt: string | null;
|
|
673
|
-
createdAt: string;
|
|
674
|
-
updatedAt: string;
|
|
675
|
-
}
|
|
676
|
-
/**
|
|
677
|
-
* How long this SDK waits for an on-chain confirmation before it stops
|
|
678
|
-
* waiting (#1756).
|
|
679
|
-
*
|
|
680
|
-
* Lives here rather than in `client.ts` so the payment-confirmation poller
|
|
681
|
-
* and the delegate sweep share ONE number instead of forking it. The SDK's
|
|
682
|
-
* other chain waits are already bounded (`waitForFundingTx` at 30 s), so a
|
|
683
|
-
* fourth independently chosen literal is exactly the drift this constant
|
|
684
|
-
* exists to prevent.
|
|
685
|
-
*/
|
|
686
|
-
declare const DEFAULT_CONFIRMATION_TIMEOUT_MS = 90000;
|
|
687
|
-
/**
|
|
688
|
-
* Whether a sweep transfer was observed to confirm (#1756).
|
|
689
|
-
*
|
|
690
|
-
* The distinction is the point: `unconfirmed` means the transfer was
|
|
691
|
-
* BROADCAST and may still land, which is neither success nor failure. It must
|
|
692
|
-
* never be collapsed into either — reporting a still-pending transaction as
|
|
693
|
-
* done, or as failed, are the same defect in opposite directions.
|
|
694
|
-
*/
|
|
695
|
-
type SweepConfirmation =
|
|
696
|
-
/** A receipt was observed. The funds are in the Safe. */
|
|
697
|
-
'confirmed'
|
|
698
|
-
/**
|
|
699
|
-
* Broadcast, but no receipt within `DEFAULT_CONFIRMATION_TIMEOUT_MS` (or the
|
|
700
|
-
* node returned no receipt). The transaction is still in the mempool and may
|
|
701
|
-
* mine at any time. `txHash` is the broadcast hash — check it on the
|
|
702
|
-
* explorer before re-running the sweep, and expect a re-run to find nothing
|
|
703
|
-
* stranded if it has since landed.
|
|
704
|
-
*/
|
|
705
|
-
| 'unconfirmed';
|
|
706
|
-
/** One transferred asset in a delegate sweep. */
|
|
707
|
-
interface SweepEntry {
|
|
708
|
-
/** 'USDC' or 'ETH' */
|
|
709
|
-
asset: string;
|
|
710
|
-
/** Human-readable amount swept (e.g. "0.12") */
|
|
711
|
-
amount: string;
|
|
712
|
-
/** Atomic amount swept */
|
|
713
|
-
amountAtomic: string;
|
|
714
|
-
/**
|
|
715
|
-
* Transaction hash of the sweep transfer.
|
|
716
|
-
*
|
|
717
|
-
* The RECEIPT hash when `confirmation` is `confirmed`; the BROADCAST hash
|
|
718
|
-
* when it is `unconfirmed` — which is the whole reason the sweep returns
|
|
719
|
-
* instead of throwing on a deadline, since this hash is the only thing that
|
|
720
|
-
* lets a user recover the transfer by hand (#1756).
|
|
721
|
-
*/
|
|
722
|
-
txHash: string;
|
|
723
|
-
/** Block explorer URL for the tx */
|
|
724
|
-
explorerUrl: string;
|
|
725
|
-
/**
|
|
726
|
-
* Did this transfer confirm on-chain within the deadline? (#1756)
|
|
727
|
-
*
|
|
728
|
-
* `unconfirmed` entries have MOVED NOTHING YET and may still move. Do not
|
|
729
|
-
* report a sweep as complete without checking this on every entry.
|
|
730
|
-
*/
|
|
731
|
-
confirmation: SweepConfirmation;
|
|
732
|
-
}
|
|
733
|
-
/** Result of a `sweepDelegate()` call. */
|
|
734
|
-
interface SweepResult {
|
|
735
|
-
/** Address funds were swept FROM */
|
|
736
|
-
fromAddress: string;
|
|
737
|
-
/** Address funds were swept TO (always the originating Safe) */
|
|
738
|
-
toAddress: string;
|
|
739
|
-
/** Chain the sweep occurred on */
|
|
740
|
-
chainId: number;
|
|
741
|
-
/** One entry per transferred asset. Empty when nothing was stranded. */
|
|
742
|
-
transfers: SweepEntry[];
|
|
743
|
-
/**
|
|
744
|
-
* True when ANY entry is `unconfirmed` — i.e. the sweep broadcast something
|
|
745
|
-
* it could not confirm within the deadline (#1756).
|
|
746
|
-
*
|
|
747
|
-
* Derived from `transfers`, and present anyway because the consumer most
|
|
748
|
-
* likely to misread this result is an LLM reading the JSON of the
|
|
749
|
-
* `haven_sweep_delegate` tool, which will otherwise see a populated
|
|
750
|
-
* `transfers` array and report the money as recovered.
|
|
751
|
-
*/
|
|
752
|
-
unconfirmed: boolean;
|
|
753
|
-
}
|
|
754
|
-
type PaymentStateKind = 'payment_intent' | 'approval_request';
|
|
755
|
-
interface AgentPaymentEnumSchema {
|
|
756
|
-
type: 'string';
|
|
757
|
-
enum: readonly string[];
|
|
758
|
-
description: string;
|
|
759
|
-
'x-enumDescriptions': Record<string, string>;
|
|
760
|
-
}
|
|
761
|
-
declare const AgentPaymentPhase: {
|
|
762
|
-
/** The agent must sign and submit the prepared payment before Haven can relay it. */
|
|
763
|
-
readonly AgentSignatureRequired: "agent_signature_required";
|
|
764
|
-
/** Haven has received the signed payment and the agent should poll for confirmation. */
|
|
765
|
-
readonly PaymentSubmitted: "payment_submitted";
|
|
766
|
-
/** The direct payment is confirmed; the agent does not need to do more for this payment id. */
|
|
767
|
-
readonly PaymentConfirmed: "payment_confirmed";
|
|
768
|
-
/**
|
|
769
|
-
* #2115: RETIRED wire value — no live rail produces it. It described the
|
|
770
|
-
* Safe rail's approval queue, which no longer exists. Kept so a stored value
|
|
771
|
-
* still typechecks; see `AgentPaymentPhaseDescriptions` below for the
|
|
772
|
-
* agent-visible wording, which this comment used to contradict.
|
|
773
|
-
*/
|
|
774
|
-
readonly UserApprovalRequired: "user_approval_required";
|
|
775
|
-
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
776
|
-
readonly UserExecutionRequired: "user_execution_required";
|
|
777
|
-
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user. */
|
|
778
|
-
readonly WaitingForAdditionalApprovals: "waiting_for_additional_approvals";
|
|
779
|
-
/** The Haven funding leg was sent; the agent can continue the merchant/protocol leg. */
|
|
780
|
-
readonly FundingSent: "funding_sent";
|
|
781
|
-
/** The payment was rejected and cannot proceed; the agent should stop and tell the user. */
|
|
782
|
-
readonly Rejected: "rejected";
|
|
783
|
-
/** The payment expired before completion. */
|
|
784
|
-
readonly Expired: "expired";
|
|
785
|
-
/** Haven could not complete the payment; the agent should stop and surface the failure. */
|
|
786
|
-
readonly Failed: "failed";
|
|
787
|
-
/**
|
|
788
|
-
* Pre-flight check determined the delegate's existing balance plus the
|
|
789
|
-
* remaining on-chain budget cannot cover the requested amount, so no
|
|
790
|
-
* payment intent was created. The account must be funded or the agent's
|
|
791
|
-
* budget raised before retrying — #2115: the old wording contrasted this
|
|
792
|
-
* with `UserApprovalRequired` as if that were a live alternative, and named
|
|
793
|
-
* the retired rail's Safe and per-token allowance as the fix.
|
|
794
|
-
*/
|
|
795
|
-
readonly InsufficientFunds: "insufficient_funds";
|
|
796
|
-
/**
|
|
797
|
-
* Haven's funding leg (account → delegate, the #946 EIP-3009 bridge)
|
|
798
|
-
* confirmed on-chain, but the merchant rejected the x402 retry. The delegate
|
|
799
|
-
* wallet may hold stranded USDC that was never settled to the merchant. The
|
|
800
|
-
* agent should stop, tell the user, and wait for the sweep flow to reclaim
|
|
801
|
-
* the funds.
|
|
802
|
-
*/
|
|
803
|
-
readonly FundedButUnsettled: "funded_but_unsettled";
|
|
804
|
-
};
|
|
805
|
-
type AgentPaymentPhase = (typeof AgentPaymentPhase)[keyof typeof AgentPaymentPhase];
|
|
806
|
-
declare const AgentPaymentNextAction: {
|
|
807
|
-
/** Sign with the delegate key and submit the payment to Haven. */
|
|
808
|
-
readonly SignAndSubmitPayment: "sign_and_submit_payment";
|
|
809
|
-
/** Poll getPaymentStatus later using this payment id. */
|
|
810
|
-
readonly CheckStatusLater: "check_status_later";
|
|
811
|
-
/** No further agent action is required for this payment id. */
|
|
812
|
-
readonly None: "none";
|
|
813
|
-
/**
|
|
814
|
-
* #2115: RETIRED wire value — no live rail produces it and nothing maps to
|
|
815
|
-
* it. Stop and tell the user rather than polling; no approval will arrive.
|
|
816
|
-
*/
|
|
817
|
-
readonly WaitForUserApproval: "wait_for_user_approval";
|
|
818
|
-
/** #2115: RETIRED wire value — no live rail produces it. Stop and tell the user rather than polling. */
|
|
819
|
-
readonly WaitForUserToCompletePayment: "wait_for_user_to_complete_payment";
|
|
820
|
-
/** Resume this payment id and retry the original x402 request with the merchant payment header. */
|
|
821
|
-
readonly RetryOriginalX402Request: "retry_original_x402_request";
|
|
822
|
-
/** Stop retrying this payment and tell the user what happened. */
|
|
823
|
-
readonly StopAndTellUser: "stop_and_tell_user";
|
|
824
|
-
/** Ask again only if the user still wants the payment after expiry. */
|
|
825
|
-
readonly RequestAgainIfUserStillWantsIt: "request_again_if_user_still_wants_it";
|
|
826
|
-
/** #1307: retry the SAME tool call, supplying the explicit context fields the server could not rehydrate. */
|
|
827
|
-
readonly RetryWithExplicitContext: "retry_with_explicit_context";
|
|
828
|
-
/**
|
|
829
|
-
* The x402 funding/quote window expired. Re-quote the same logical merchant
|
|
830
|
-
* operation with the same idempotency key to stay double-charge-safe.
|
|
831
|
-
*/
|
|
832
|
-
readonly PaymentWindowExpired: "payment_window_expired";
|
|
833
|
-
/**
|
|
834
|
-
* Stop and tell the user that the originating account needs to be funded or
|
|
835
|
-
* the agent's per-token allowance needs to be raised before the payment
|
|
836
|
-
* can succeed. A user approval will not fix this state on its own.
|
|
837
|
-
*
|
|
838
|
-
* #2914: the account-vocabulary spelling, and the only one — the
|
|
839
|
-
* pre-#2907 `fund_safe_or_raise_allowance` wire value (and the
|
|
840
|
-
* `AgentPaymentNextActionAccountAlias` seam #2908 added to bridge it) are
|
|
841
|
-
* retired along with the rest of the #2908 compatibility window.
|
|
842
|
-
*/
|
|
843
|
-
readonly FundAccountOrRaiseAllowance: "fund_account_or_raise_allowance";
|
|
844
|
-
/**
|
|
845
|
-
* The delegate wallet may hold funds that were sent from the Safe but never
|
|
846
|
-
* settled to the merchant. The wallet owner should initiate a sweep to
|
|
847
|
-
* return those funds to the originating Safe.
|
|
848
|
-
*/
|
|
849
|
-
readonly SweepStrandedFunds: "sweep_stranded_funds";
|
|
850
|
-
/**
|
|
851
|
-
* #2970: a `submitted` erc7710 x402 intent whose settlement window has
|
|
852
|
-
* passed with no on-chain settlement evidence Haven could verify. Distinct
|
|
853
|
-
* from {@link CheckStatusLater}, which this REPLACES once the window is
|
|
854
|
-
* past — but it is not futile: Haven's settlement sweep (120s tick) scans
|
|
855
|
-
* each candidate over its own window plus a 120s clock-skew allowance, so
|
|
856
|
-
* it can still attribute the settlement for a short while after this value
|
|
857
|
-
* first appears. Poll {@link CheckStatusLater}'s tool
|
|
858
|
-
* (`haven_get_payment_status`) once more, roughly two minutes later; if it
|
|
859
|
-
* still shows no evidence, tell the user the goods were delivered but
|
|
860
|
-
* Haven holds no verified settlement evidence for this payment. If the
|
|
861
|
-
* agent holds the merchant's real settlement transaction hash (from
|
|
862
|
-
* `PAYMENT-RESPONSE`'s `transaction` field, or a prior settle/complete
|
|
863
|
-
* result's `settlement_tx_hash`), report it with the hosted
|
|
864
|
-
* `haven_report_settlement_evidence` tool instead of waiting —
|
|
865
|
-
* `haven_report_x402_outcome` takes no hash and refuses a non-`confirmed`
|
|
866
|
-
* intent.
|
|
867
|
-
*/
|
|
868
|
-
readonly AwaitingSettlementEvidence: "awaiting_settlement_evidence";
|
|
869
|
-
};
|
|
870
|
-
type AgentPaymentNextAction = (typeof AgentPaymentNextAction)[keyof typeof AgentPaymentNextAction];
|
|
871
|
-
declare const AgentPaymentFailureCode: {
|
|
872
|
-
/** A merchant-authoritative x402 price exceeds the caller's pre-funding max_amount cap. */
|
|
873
|
-
readonly PriceExceedsMax: "PRICE_EXCEEDS_MAX";
|
|
874
|
-
/** The x402 funding/quote window expired before the signer or hosted settle step could finish. */
|
|
875
|
-
readonly PaymentWindowExpired: "PAYMENT_WINDOW_EXPIRED";
|
|
876
|
-
/** The merchant rejected the paid retry. On eip3009 the funding leg had succeeded (sweep);
|
|
877
|
-
* on erc7710 there is no funding leg — nothing to sweep, follow the message (#2983). */
|
|
878
|
-
readonly MerchantRejectedAfterFunding: "MERCHANT_REJECTED_AFTER_FUNDING";
|
|
879
|
-
/** #1300 review: funding is on-chain but the merchant never ANSWERED the
|
|
880
|
-
* paid retry within the timeout. NOT proof of rejection — the merchant
|
|
881
|
-
* may still settle late, so the guidance is verify-then-act. On eip3009
|
|
882
|
-
* the funding leg had succeeded (verify-then-sweep); on erc7710 there is
|
|
883
|
-
* no funding leg — nothing to sweep, follow the message (#3000). */
|
|
884
|
-
readonly MerchantUnresponsiveAfterFunding: "MERCHANT_UNRESPONSIVE_AFTER_FUNDING";
|
|
885
|
-
/**
|
|
886
|
-
* #1307: the caller omitted merchant_url/tool_name (asking Haven to
|
|
887
|
-
* rehydrate the stored MCP merchant-call context by payment_id), but no
|
|
888
|
-
* usable context was stored for this intent — either it was never an
|
|
889
|
-
* MCP-tool quote, or the stored context is incomplete. The fallback is
|
|
890
|
-
* mechanical: re-send merchant_url, tool_name, arguments, and
|
|
891
|
-
* mcp_transport explicitly (the version-skew path).
|
|
892
|
-
*/
|
|
893
|
-
readonly MerchantCallContextUnavailable: "MERCHANT_CALL_CONTEXT_UNAVAILABLE";
|
|
894
|
-
/**
|
|
895
|
-
* #1351: the caller supplied BOTH the atomic `max_amount` and the
|
|
896
|
-
* human-denominated `max_amount_human` cap for one purchase. Haven refuses
|
|
897
|
-
* to guess which the user meant — the two differ by a factor of 10^decimals,
|
|
898
|
-
* so picking wrong is exactly the silent-overspend this cap exists to
|
|
899
|
-
* prevent. Rejected before any merchant probe, funding intent, or signature.
|
|
900
|
-
*/
|
|
901
|
-
readonly AmbiguousMaxAmount: "AMBIGUOUS_MAX_AMOUNT";
|
|
902
|
-
/**
|
|
903
|
-
* #1351: a human-denominated cap was supplied, but it cannot be converted to
|
|
904
|
-
* atomic units against THIS quote — either the quote's asset has no known
|
|
905
|
-
* decimals on its network, or the cap carries more fraction digits than the
|
|
906
|
-
* asset can represent (truncating it would silently change the user's cap).
|
|
907
|
-
* The fallback is the exact atomic `max_amount`.
|
|
908
|
-
*/
|
|
909
|
-
readonly MaxAmountUnconvertible: "MAX_AMOUNT_UNCONVERTIBLE";
|
|
910
|
-
/**
|
|
911
|
-
* #2979: the merchant answered a `tools/call` probe with its own
|
|
912
|
-
* machine-readable "cannot settle right now" refusal (HTTP 503,
|
|
913
|
-
* `{ error: 'merchant_not_ready', reason_code, ... }`) instead of a 402
|
|
914
|
-
* challenge — e.g. its settlement wallet is out of gas. No 402 was ever
|
|
915
|
-
* issued and no payment was created; this is honest and (per
|
|
916
|
-
* `retry_after_s`, when present) usually transient, unlike a permanent
|
|
917
|
-
* endpoint miss.
|
|
918
|
-
*/
|
|
919
|
-
readonly MerchantNotReady: "MERCHANT_NOT_READY";
|
|
920
|
-
};
|
|
921
|
-
type AgentPaymentFailureCode = (typeof AgentPaymentFailureCode)[keyof typeof AgentPaymentFailureCode];
|
|
922
|
-
/**
|
|
923
|
-
* Stable rail identifier carried on Haven agent payment responses and resume
|
|
924
|
-
* state.
|
|
925
|
-
*
|
|
926
|
-
* Two layers of vocabulary share this enum because both reach the wire:
|
|
927
|
-
*
|
|
928
|
-
* - **Categorical rails** identify the rail family and are used as the
|
|
929
|
-
* `PaymentResumeState` discriminator: `direct`, `x402` (`mpp` remains a
|
|
930
|
-
* valid categorical VALUE on historical status reads, but #1328 retired
|
|
931
|
-
* the `MppResumeState` variant that used to carry it — the mpp_demo
|
|
932
|
-
* client resume flow no longer exists).
|
|
933
|
-
* - **Granular rails** identify the specific protocol the backend persists
|
|
934
|
-
* and returns on response bodies: `mpp_demo`, `mpp_crypto`,
|
|
935
|
-
* `stripe_deposit`, `spt`. `x402` doubles as both categorical and
|
|
936
|
-
* granular.
|
|
937
|
-
*
|
|
938
|
-
* Consumers reading the top-level `rail` field on a payment status response
|
|
939
|
-
* should treat any `mpp*` value as the MPP family — this still applies to
|
|
940
|
-
* historical `mpp_demo` rows, which remain readable.
|
|
941
|
-
*/
|
|
942
|
-
declare const AgentPaymentRail: {
|
|
943
|
-
/** Standard Haven payment from the user's Safe through an approved delegate allowance. */
|
|
944
|
-
readonly Direct: "direct";
|
|
945
|
-
/** x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg. */
|
|
946
|
-
readonly X402: "x402";
|
|
947
|
-
/** Machine Payment Protocol family — categorical value used as a resume-state discriminator. */
|
|
948
|
-
readonly Mpp: "mpp";
|
|
949
|
-
/** Haven internal MPP demo rail. Not for production traffic. */
|
|
950
|
-
readonly MppDemo: "mpp_demo";
|
|
951
|
-
/** Crypto-settled MPP rail. */
|
|
952
|
-
readonly MppCrypto: "mpp_crypto";
|
|
953
|
-
/** Stripe-deposit-backed MPP rail. */
|
|
954
|
-
readonly StripeDeposit: "stripe_deposit";
|
|
955
|
-
/** Stripe Payment Token MPP rail. */
|
|
956
|
-
readonly Spt: "spt";
|
|
957
|
-
};
|
|
958
|
-
type AgentPaymentRail = (typeof AgentPaymentRail)[keyof typeof AgentPaymentRail];
|
|
959
|
-
type PaymentPhase = AgentPaymentPhase;
|
|
960
|
-
type PaymentNextAction = AgentPaymentNextAction;
|
|
961
|
-
declare const AGENT_PAYMENT_PHASE_VALUES: ("rejected" | "expired" | "failed" | "agent_signature_required" | "payment_submitted" | "payment_confirmed" | "user_approval_required" | "user_execution_required" | "waiting_for_additional_approvals" | "funding_sent" | "insufficient_funds" | "funded_but_unsettled")[];
|
|
962
|
-
declare const AGENT_PAYMENT_NEXT_ACTION_VALUES: ("sign_and_submit_payment" | "check_status_later" | "none" | "wait_for_user_approval" | "wait_for_user_to_complete_payment" | "retry_original_x402_request" | "stop_and_tell_user" | "request_again_if_user_still_wants_it" | "retry_with_explicit_context" | "payment_window_expired" | "fund_account_or_raise_allowance" | "sweep_stranded_funds" | "awaiting_settlement_evidence")[];
|
|
963
|
-
declare const AGENT_PAYMENT_FAILURE_CODE_VALUES: ("PRICE_EXCEEDS_MAX" | "PAYMENT_WINDOW_EXPIRED" | "MERCHANT_REJECTED_AFTER_FUNDING" | "MERCHANT_UNRESPONSIVE_AFTER_FUNDING" | "MERCHANT_CALL_CONTEXT_UNAVAILABLE" | "AMBIGUOUS_MAX_AMOUNT" | "MAX_AMOUNT_UNCONVERTIBLE" | "MERCHANT_NOT_READY")[];
|
|
964
|
-
declare const AGENT_PAYMENT_RAIL_VALUES: ("x402" | "mpp_demo" | "mpp_crypto" | "stripe_deposit" | "spt" | "direct" | "mpp")[];
|
|
965
|
-
declare const AgentPaymentPhaseDescriptions: Record<AgentPaymentPhase, string>;
|
|
966
|
-
declare const AgentPaymentNextActionDescriptions: Record<AgentPaymentNextAction, string>;
|
|
967
|
-
declare const AgentPaymentFailureCodeDescriptions: Record<AgentPaymentFailureCode, string>;
|
|
968
|
-
/**
|
|
969
|
-
* #1308: machine-readable warning codes carried in the `warnings` array on
|
|
970
|
-
* x402 MCP tool responses. Warnings are ADVISORY — they never replace a
|
|
971
|
-
* refusal, and existing failure codes stay authoritative for errors. The
|
|
972
|
-
* legacy `cap_warning` string field is kept for compatibility; the structured
|
|
973
|
-
* entry carries the same message under MISSING_MAX_AMOUNT.
|
|
974
|
-
*/
|
|
975
|
-
declare const AgentPaymentWarningCode: {
|
|
976
|
-
/** No max_amount cap was supplied — the live quoted price was accepted as-is. */
|
|
977
|
-
readonly MissingMaxAmount: "MISSING_MAX_AMOUNT";
|
|
978
|
-
/** The signing window closes soon; sign promptly or re-quote with the same idempotency key. */
|
|
979
|
-
readonly QuoteExpiresSoon: "QUOTE_EXPIRES_SOON";
|
|
980
|
-
/** The merchant URL was resolved via discovery — pass the RESOLVED url forward. */
|
|
981
|
-
readonly MerchantUrlDiscovered: "MERCHANT_URL_DISCOVERED";
|
|
982
|
-
/**
|
|
983
|
-
* #1306: the catalog's last-verified price_atomic differs from the LIVE
|
|
984
|
-
* merchant quote for a guided catalog purchase. The catalog price is only
|
|
985
|
-
* ever indicative; the live quote in the same response is authoritative.
|
|
986
|
-
*/
|
|
987
|
-
readonly CatalogPriceDiffers: "CATALOG_PRICE_DIFFERS";
|
|
988
|
-
/**
|
|
989
|
-
* #1306: the rail-aware allowance/budget pre-check could not be read (RPC
|
|
990
|
-
* failure, etc). `sufficient` is reported as null rather than a fabricated
|
|
991
|
-
* true/false — the on-chain policy remains the actual gate either way.
|
|
992
|
-
*/
|
|
993
|
-
readonly AllowanceCheckUnavailable: "ALLOWANCE_CHECK_UNAVAILABLE";
|
|
994
|
-
/**
|
|
995
|
-
* #1319: the delegation-rail read itself SUCCEEDED, but the remaining
|
|
996
|
-
* figure it returned is the #1145 fallback (the full configured budget)
|
|
997
|
-
* rather than a live ERC20PeriodTransferEnforcer read — `sufficient` is a
|
|
998
|
-
* real true/false, just computed from an optimistic number. Distinct from
|
|
999
|
-
* {@link AgentPaymentWarningCode.AllowanceCheckUnavailable}, which fires
|
|
1000
|
-
* when the read failed outright and `sufficient` degrades to null. The
|
|
1001
|
-
* on-chain policy re-checks at redemption either way; this only says the
|
|
1002
|
-
* guidance shown here may be optimistic.
|
|
1003
|
-
*/
|
|
1004
|
-
readonly AllowanceReadOptimistic: "ALLOWANCE_READ_OPTIMISTIC";
|
|
1005
|
-
/**
|
|
1006
|
-
* #2991: the quote tools' `expected_settlement_scheme` prediction of what
|
|
1007
|
-
* `haven_prepare_catalog_purchase` / `haven_pay_mcp_tool` will actually
|
|
1008
|
-
* select could not be computed — the agent's execution rail could not be
|
|
1009
|
-
* read from Haven, so `expected_settlement_scheme` is `null` rather than a
|
|
1010
|
-
* guess. `accepted_scheme` (the merchant's offer) is unaffected.
|
|
1011
|
-
*/
|
|
1012
|
-
readonly X402SchemeUnknown: "X402_SCHEME_UNKNOWN";
|
|
1013
|
-
/**
|
|
1014
|
-
* #2968: the merchant answered 200 and handed over goods, but Haven holds NO
|
|
1015
|
-
* on-chain evidence that the payment moved. `settled: false` beside this code
|
|
1016
|
-
* is not a failure — it is the absence of proof, and the two must travel
|
|
1017
|
-
* together so an agent can tell "the user has the goods" apart from "the
|
|
1018
|
-
* money moved". Carries the intent's `expires_at`: after that instant the
|
|
1019
|
-
* settlement can no longer land at all.
|
|
1020
|
-
*/
|
|
1021
|
-
readonly SettlementUnconfirmed: "SETTLEMENT_UNCONFIRMED";
|
|
1022
|
-
};
|
|
1023
|
-
type AgentPaymentWarningCode = (typeof AgentPaymentWarningCode)[keyof typeof AgentPaymentWarningCode];
|
|
1024
|
-
interface AgentPaymentWarning {
|
|
1025
|
-
code: AgentPaymentWarningCode;
|
|
1026
|
-
message: string;
|
|
1027
|
-
}
|
|
1028
|
-
/**
|
|
1029
|
-
* #1308: the structured next-step contract on x402 MCP tool responses. It
|
|
1030
|
-
* EXTENDS the existing taxonomy — `next_action` values come from
|
|
1031
|
-
* AgentPaymentNextAction, never a parallel vocabulary. `next_arguments`
|
|
1032
|
-
* carries the small, literally-usable arguments; bulky pass-through fields
|
|
1033
|
-
* (payment_required) are named in `reason` and taken from the SAME response.
|
|
1034
|
-
*/
|
|
1035
|
-
interface AgentNextStep {
|
|
1036
|
-
/** From `AgentPaymentNextAction`. */
|
|
1037
|
-
next_action: AgentPaymentNextAction;
|
|
1038
|
-
/**
|
|
1039
|
-
* Claude-family namespaced tool name for the next call
|
|
1040
|
-
* (`mcp__<server>__<tool>`), when one exists.
|
|
1041
|
-
*
|
|
1042
|
-
* **Namespaced with the DEFAULT server names**, which is the most the hosted
|
|
1043
|
-
* server can know: local server names are the client's own config and never
|
|
1044
|
-
* reach Haven. Two runtimes are already not the default — Codex names servers
|
|
1045
|
-
* by config key (`haven`, `haven_signer`), and a connector run with
|
|
1046
|
-
* `--name <slug>` wires `haven-<slug>` / `haven-signer-<slug>` (#1694). On
|
|
1047
|
-
* either, this field and `next_tool_server` name a server the client does not
|
|
1048
|
-
* have. Prefer {@link AgentNextStep.next_tool_server_role} plus
|
|
1049
|
-
* {@link AgentNextStep.next_tool_name} whenever your servers are not the
|
|
1050
|
-
* default pair; see #2550.
|
|
1051
|
-
*/
|
|
1052
|
-
next_tool?: string;
|
|
1053
|
-
/**
|
|
1054
|
-
* The server half of `next_tool`, unprefixed — `haven` or `haven-signer`.
|
|
1055
|
-
* Carries the same default-name caveat as `next_tool` (#1588, #2550).
|
|
1056
|
-
*/
|
|
1057
|
-
next_tool_server?: string;
|
|
1058
|
-
/** The bare tool name, callable on whichever server plays the role below. */
|
|
1059
|
-
next_tool_name?: string;
|
|
1060
|
-
/**
|
|
1061
|
-
* Which of the CLIENT'S OWN servers to call (#2550). Runtime-neutral, and
|
|
1062
|
-
* the field to resolve against when your server names are not the defaults —
|
|
1063
|
-
* it names a role rather than a name the hosted server had to guess.
|
|
1064
|
-
*/
|
|
1065
|
-
next_tool_server_role?: 'hosted' | 'signer';
|
|
1066
|
-
/** Small literal arguments for next_tool. Bulky fields are referenced by reason. */
|
|
1067
|
-
next_arguments?: Record<string, unknown>;
|
|
1068
|
-
/** False when the agent should stop and involve the user before continuing. */
|
|
1069
|
-
safe_to_continue: boolean;
|
|
1070
|
-
reason: string;
|
|
1071
|
-
}
|
|
1072
|
-
/**
|
|
1073
|
-
* #1349: compact, Haven-generated reporting evidence for a completed x402
|
|
1074
|
-
* merchant purchase. `status`, money fields, merchant endpoint/address, and
|
|
1075
|
-
* funding transaction come from Haven payment state; `product` and
|
|
1076
|
-
* `invoice_id` are optional merchant-supplied display metadata. The raw
|
|
1077
|
-
* merchant result remains separate evidence and MUST NOT be used to infer
|
|
1078
|
-
* settlement status.
|
|
1079
|
-
*/
|
|
1080
|
-
interface AgentPurchaseSummary {
|
|
1081
|
-
/** Set only after Haven has completed the funding and merchant-settlement flow. */
|
|
1082
|
-
status: 'settled';
|
|
1083
|
-
product: string | null;
|
|
1084
|
-
amount: string | null;
|
|
1085
|
-
amount_atomic: string | null;
|
|
1086
|
-
asset: string | null;
|
|
1087
|
-
network: string | null;
|
|
1088
|
-
merchant: {
|
|
1089
|
-
address: string | null;
|
|
1090
|
-
resource_url: string | null;
|
|
1091
|
-
};
|
|
1092
|
-
/** Merchant-supplied identifier, or null when the merchant did not supply one. */
|
|
1093
|
-
invoice_id: string | null;
|
|
1094
|
-
funding_tx_hash: string | null;
|
|
1095
|
-
/** Optional merchant receipt reference parsed from PAYMENT-RESPONSE; not Haven settlement proof. */
|
|
1096
|
-
settlement_tx_hash: string | null;
|
|
1097
|
-
/** Same read-only allowance block returned at the top level, or null when unavailable. */
|
|
1098
|
-
allowance: PostPurchaseAllowanceSummary | null;
|
|
1099
|
-
}
|
|
1100
|
-
/** #1308: compact reporting summary — what the agent tells the user. */
|
|
1101
|
-
interface AgentPaymentSummary {
|
|
1102
|
-
payment_id: string;
|
|
1103
|
-
status: string;
|
|
1104
|
-
amount?: string;
|
|
1105
|
-
amount_atomic?: string;
|
|
1106
|
-
token?: string;
|
|
1107
|
-
network?: string;
|
|
1108
|
-
expires_at?: string;
|
|
1109
|
-
product?: string;
|
|
1110
|
-
/**
|
|
1111
|
-
* Default reporting contract for a successful `haven_settle_mcp_tool` call.
|
|
1112
|
-
* The merchant's raw `result` remains available separately as advanced
|
|
1113
|
-
* evidence; do not parse it to determine whether a payment settled.
|
|
1114
|
-
*/
|
|
1115
|
-
purchase_summary?: AgentPurchaseSummary;
|
|
1116
|
-
}
|
|
1117
|
-
declare const AgentPaymentRailDescriptions: Record<AgentPaymentRail, string>;
|
|
1118
|
-
declare const AgentPaymentPhaseSchema: AgentPaymentEnumSchema;
|
|
1119
|
-
declare const AgentPaymentNextActionSchema: AgentPaymentEnumSchema;
|
|
1120
|
-
declare const AgentPaymentFailureCodeSchema: AgentPaymentEnumSchema;
|
|
1121
|
-
declare const AgentPaymentRailSchema: AgentPaymentEnumSchema;
|
|
1122
|
-
interface PaymentStatusResult {
|
|
1123
|
-
paymentId: string;
|
|
1124
|
-
kind: PaymentStateKind;
|
|
1125
|
-
rail: string;
|
|
1126
|
-
status: PaymentStatus | string;
|
|
1127
|
-
phase: PaymentPhase;
|
|
1128
|
-
nextAction: PaymentNextAction;
|
|
1129
|
-
amount: string;
|
|
1130
|
-
token: string;
|
|
1131
|
-
resourceUrl: string | null;
|
|
1132
|
-
merchantAddress: string | null;
|
|
1133
|
-
/** Delegate EOA captured on the payment intent when it was created. */
|
|
1134
|
-
payerAddress?: string | null;
|
|
1135
|
-
/** #2960: additive alongside `payerAddress` above (`parties.delegate` only). */
|
|
1136
|
-
parties?: PaymentParties;
|
|
1137
|
-
txHash: string | null;
|
|
1138
|
-
expiresAt: string;
|
|
1139
|
-
chainId: number;
|
|
1140
|
-
message: string;
|
|
1141
|
-
/** Platform fee surfaced so it's never silently collected (#386). */
|
|
1142
|
-
fee?: PaymentFee | null;
|
|
1143
|
-
amountAtomic?: string | null;
|
|
1144
|
-
asset?: string | null;
|
|
1145
|
-
network?: string | null;
|
|
1146
|
-
description?: string | null;
|
|
1147
|
-
idempotencyKey?: string | null;
|
|
1148
|
-
x402?: {
|
|
1149
|
-
amountAtomic: string | null;
|
|
1150
|
-
asset: string | null;
|
|
1151
|
-
network: string | null;
|
|
1152
|
-
resourceUrl: string | null;
|
|
1153
|
-
merchantAddress: string | null;
|
|
1154
|
-
description: string | null;
|
|
1155
|
-
idempotencyKey: string | null;
|
|
1156
|
-
};
|
|
1157
|
-
mpp?: {
|
|
1158
|
-
amountAtomic: string | null;
|
|
1159
|
-
asset: string | null;
|
|
1160
|
-
network: string | null;
|
|
1161
|
-
resourceUrl: string | null;
|
|
1162
|
-
merchantAddress: string | null;
|
|
1163
|
-
description: string | null;
|
|
1164
|
-
idempotencyKey: string | null;
|
|
1165
|
-
challengeId: string | null;
|
|
1166
|
-
};
|
|
1167
|
-
}
|
|
1168
|
-
/**
|
|
1169
|
-
* Result of an erc7710 direct settlement (#1454).
|
|
1170
|
-
*
|
|
1171
|
-
* Deliberately NOT an `X402Receipt`. A 3009 receipt describes a completed
|
|
1172
|
-
* two-leg payment — funding tx included — whereas here nothing has settled yet
|
|
1173
|
-
* when this returns: the merchant redeems the delegation chain when the caller
|
|
1174
|
-
* retries with the header. Reusing the receipt type would let a caller read
|
|
1175
|
-
* `txHash` as "paid" on a payment that has not moved a cent.
|
|
1176
|
-
*/
|
|
1177
|
-
interface X402Erc7710Settlement {
|
|
1178
|
-
paymentId: string;
|
|
1179
|
-
/**
|
|
1180
|
-
* Pass verbatim as the `PAYMENT-SIGNATURE` header on the merchant retry —
|
|
1181
|
-
* that name ALONE. erc7710 is always x402 v2, and this header carries the
|
|
1182
|
-
* delegation chain, so also sending the legacy `X-PAYMENT` overflows the
|
|
1183
|
-
* merchant's header limit (HTTP 431, #2341).
|
|
1184
|
-
*/
|
|
1185
|
-
paymentHeader: string;
|
|
1186
|
-
/** The merchant address the child delegation is pinned to. */
|
|
1187
|
-
merchantPayTo: string;
|
|
1188
|
-
amountAtomic: string;
|
|
1189
|
-
asset: string;
|
|
1190
|
-
network: string;
|
|
1191
|
-
/** Facilitators the child is redeemable by, when the merchant advertised any. */
|
|
1192
|
-
facilitatorAddresses: string[] | null;
|
|
1193
|
-
}
|
|
1194
|
-
/** @internal */
|
|
1195
|
-
/** One payable service in Haven's merchant catalog (epic #1717). */
|
|
1196
|
-
interface HavenCatalogEntry {
|
|
1197
|
-
id: string;
|
|
1198
|
-
name: string;
|
|
1199
|
-
description: string;
|
|
1200
|
-
category: string;
|
|
1201
|
-
resourceUrl: string;
|
|
1202
|
-
rail: 'x402' | 'mpp';
|
|
1203
|
-
protocol: 'http' | 'mcp';
|
|
1204
|
-
toolName: string | null;
|
|
1205
|
-
toolArguments: Record<string, unknown> | null;
|
|
1206
|
-
priceDisplay: string | null;
|
|
1207
|
-
priceAtomic: string | null;
|
|
1208
|
-
asset: string | null;
|
|
1209
|
-
network: string | null;
|
|
1210
|
-
status: 'active' | 'degraded' | 'delisted';
|
|
1211
|
-
verifiedAt: string | null;
|
|
1212
|
-
/**
|
|
1213
|
-
* Where the entry came from. `operator` = curated in migrations/scripts
|
|
1214
|
-
* (the operator vouches for the listing; the catalog refresh probe still
|
|
1215
|
-
* checks the endpoint, see `verifiedPayable`). `ingestion` = submitted
|
|
1216
|
-
* through the Verified Payable Directory and passed domain-ownership proof
|
|
1217
|
-
* plus the read-only quote probe.
|
|
1218
|
-
*/
|
|
1219
|
-
source: 'operator' | 'ingestion';
|
|
1220
|
-
/** True only for `ingestion` entries — the one ownership claim. See the epic's trust claim (never merchant honesty or quality). */
|
|
1221
|
-
domainVerified: boolean;
|
|
1222
|
-
/**
|
|
1223
|
-
* True when Haven watched this endpoint answer a live quote (#2978): the
|
|
1224
|
-
* directory probe for `ingestion` rows, the periodic catalog refresh probe
|
|
1225
|
-
* for `operator` rows (`status === 'active'` with `verifiedAt` set). False
|
|
1226
|
-
* for a degraded row of either source. `discoverTools({ verified:
|
|
1227
|
-
* 'verified' })` filters on this field, not on `source`.
|
|
1228
|
-
*/
|
|
1229
|
-
verifiedPayable: boolean;
|
|
1230
|
-
}
|
|
1231
|
-
/** @internal */
|
|
1232
|
-
/** Wire shape of POST /catalog/submit (#1717, #1716). */
|
|
1233
|
-
interface CatalogSubmissionAccepted {
|
|
1234
|
-
id: string;
|
|
1235
|
-
verify_token: string;
|
|
1236
|
-
status: 'submitted' | 'ownership_verified' | 'verified_payable';
|
|
1237
|
-
}
|
|
1238
|
-
/** @internal Client-facing submission handle. */
|
|
1239
|
-
interface HavenCatalogSubmission {
|
|
1240
|
-
id: string;
|
|
1241
|
-
verifyToken: string;
|
|
1242
|
-
status: 'submitted' | 'ownership_verified' | 'verified_payable';
|
|
1243
|
-
}
|
|
1244
|
-
declare class HavenError extends Error {
|
|
1245
|
-
readonly code: string;
|
|
1246
|
-
readonly statusCode?: number | undefined;
|
|
1247
|
-
readonly paymentId?: string | undefined;
|
|
1248
|
-
constructor(message: string, code: string, statusCode?: number | undefined, paymentId?: string | undefined);
|
|
1249
|
-
}
|
|
1250
|
-
declare class HavenApiError extends HavenError {
|
|
1251
|
-
readonly body?: unknown | undefined;
|
|
1252
|
-
constructor(message: string, statusCode: number, body?: unknown | undefined, paymentId?: string);
|
|
1253
|
-
}
|
|
1254
|
-
/**
|
|
1255
|
-
* #1300: quoteX402 hit a URL that answered something other than 402 — the
|
|
1256
|
-
* typed form of "this is not the x402 endpoint". Exists so consumers (the
|
|
1257
|
-
* hosted MCP's #1271 discovery trigger) can key on a class instead of
|
|
1258
|
-
* message text.
|
|
1259
|
-
*/
|
|
1260
|
-
/**
|
|
1261
|
-
* #1300: a merchant-facing fetch hit the client-side merchantTimeout. Typed
|
|
1262
|
-
* so consumers can distinguish "merchant never answered" from a real HTTP
|
|
1263
|
-
* error response — the funded-retry path routes this to verify-then-sweep
|
|
1264
|
-
* guidance instead of a bare 504.
|
|
1265
|
-
*/
|
|
1266
|
-
declare class MerchantTimeoutError extends HavenApiError {
|
|
1267
|
-
readonly merchantErrorCode: "merchant_timeout";
|
|
1268
|
-
constructor(message: string);
|
|
1269
|
-
}
|
|
1270
|
-
declare class X402UnexpectedStatusError extends HavenApiError {
|
|
1271
|
-
readonly x402ErrorCode: "unexpected_non_402_status";
|
|
1272
|
-
/**
|
|
1273
|
-
* #2979: `body` is the merchant's own JSON, when the non-402 response
|
|
1274
|
-
* carried one — e.g. the demo merchant's `/mcp` readiness gate answers
|
|
1275
|
-
* `503 { error: 'merchant_not_ready', reason_code, ... }`. Optional and
|
|
1276
|
-
* best-effort: a non-JSON or unreadable body leaves this `undefined`, same
|
|
1277
|
-
* as before this field existed. Consumers key on it (not on the message
|
|
1278
|
-
* string) to distinguish an honest, machine-readable merchant refusal from
|
|
1279
|
-
* a genuine "this is not the x402 endpoint" miss, which otherwise look
|
|
1280
|
-
* identical — both are just "some non-402 status".
|
|
1281
|
-
*/
|
|
1282
|
-
constructor(message: string, statusCode: number, body?: unknown);
|
|
1283
|
-
}
|
|
1284
|
-
/**
|
|
1285
|
-
* #1521: the idempotency key resolved to a payment that has already settled,
|
|
1286
|
-
* and the delegate can no longer fund a fresh authorization for it.
|
|
1287
|
-
*
|
|
1288
|
-
* This is the typed form of "you already bought this". It exists because the
|
|
1289
|
-
* alternative was indefensible: the SDK used to mint a new EIP-3009
|
|
1290
|
-
* authorization against the spent delegate and hand it back paired with the
|
|
1291
|
-
* ORIGINAL payment's `txHash`, so the caller learned what had happened only
|
|
1292
|
-
* from a merchant-side balance error that reads identically to a broken
|
|
1293
|
-
* payment rail.
|
|
1294
|
-
*
|
|
1295
|
-
* `receipt` is the ORIGINAL payment — a real receipt for real settled funds,
|
|
1296
|
-
* deliberately carrying no `paymentHeader`, because any header minted here
|
|
1297
|
-
* would be exactly the unfundable artifact this error replaces.
|
|
1298
|
-
*/
|
|
1299
|
-
declare class X402AlreadySettledError extends HavenApiError {
|
|
1300
|
-
readonly receipt: X402Receipt;
|
|
1301
|
-
/**
|
|
1302
|
-
* `settled` — the delegate was checked on-chain and cannot fund a fresh
|
|
1303
|
-
* authorization, so this payment demonstrably completed.
|
|
1304
|
-
* `unverifiable` — no `chainRpcs` entry for the chain, so fundability
|
|
1305
|
-
* could not be established either way. Same refusal, weaker claim; say
|
|
1306
|
-
* which, rather than assert what was not checked.
|
|
1307
|
-
*/
|
|
1308
|
-
readonly basis: 'settled' | 'unverifiable';
|
|
1309
|
-
readonly x402ErrorCode: "already_settled";
|
|
1310
|
-
constructor(message: string, receipt: X402Receipt,
|
|
1311
|
-
/**
|
|
1312
|
-
* `settled` — the delegate was checked on-chain and cannot fund a fresh
|
|
1313
|
-
* authorization, so this payment demonstrably completed.
|
|
1314
|
-
* `unverifiable` — no `chainRpcs` entry for the chain, so fundability
|
|
1315
|
-
* could not be established either way. Same refusal, weaker claim; say
|
|
1316
|
-
* which, rather than assert what was not checked.
|
|
1317
|
-
*/
|
|
1318
|
-
basis: 'settled' | 'unverifiable');
|
|
1319
|
-
}
|
|
1320
|
-
declare class HavenPaymentStateError extends HavenApiError {
|
|
1321
|
-
readonly state: PaymentStatusResult;
|
|
1322
|
-
resumeState?: X402ResumeState;
|
|
1323
|
-
constructor(message: string, statusCode: number, state: PaymentStatusResult, body?: unknown);
|
|
1324
|
-
get status(): string;
|
|
1325
|
-
get phase(): PaymentPhase;
|
|
1326
|
-
get nextAction(): PaymentNextAction;
|
|
1327
|
-
}
|
|
1328
|
-
declare class HavenSigningError extends HavenError {
|
|
1329
|
-
constructor(message: string);
|
|
1330
|
-
}
|
|
1331
|
-
/**
|
|
1332
|
-
* #2972: `MerchantCompletion.reportSettlementEvidence` /
|
|
1333
|
-
* `HavenClient.reportSettlementEvidence` refuse a `0x00…00` settlement hash
|
|
1334
|
-
* BEFORE any network call — see `isZeroSettlementTxHash`. That marker is
|
|
1335
|
-
* never a real transaction (the demo merchant's own "delivered, not settled"
|
|
1336
|
-
* value), so posting it to `POST /machine-payments/evidence` could only ever
|
|
1337
|
-
* come back refused, at the cost of a real round trip. A typed error rather
|
|
1338
|
-
* than a `HavenApiError`-shaped 400: no request was ever attempted, so there
|
|
1339
|
-
* is no HTTP status or response body to carry.
|
|
1340
|
-
*/
|
|
1341
|
-
declare class HavenZeroSettlementHashError extends HavenError {
|
|
1342
|
-
constructor(paymentId: string);
|
|
1343
|
-
}
|
|
1344
|
-
/**
|
|
1345
|
-
* Refusal codes the local signer returns when it does not recognise the
|
|
1346
|
-
* VERSION of a Haven-signed binding it was asked to sign (#1309). Distinct
|
|
1347
|
-
* from `AgentPaymentFailureCode`: these describe a **signer capability**
|
|
1348
|
-
* problem (this install cannot evaluate what Haven sent), not a payment-domain
|
|
1349
|
-
* outcome, and they never reach the backend's REST/OpenAPI surface — only the
|
|
1350
|
-
* local signer's own MCP tool responses (`haven_sign` / `haven_sign_x402` /
|
|
1351
|
-
* `haven_sign_sweep_delegate`). That is also why this pair does not go through
|
|
1352
|
-
* the `AgentPaymentFailureCode` four-gate (sdk → backend mirror → spec →
|
|
1353
|
-
* api-types): there is no backend mirror to keep in sync with.
|
|
1354
|
-
*/
|
|
1355
|
-
declare const SignerRefusalCode: {
|
|
1356
|
-
/** `SUPPORTED_X402_EXPECTED_VERSIONS` in `@haven_ai/signer` does not include the received version. */
|
|
1357
|
-
readonly UnsupportedExpectedContextVersion: "UNSUPPORTED_EXPECTED_CONTEXT_VERSION";
|
|
1358
|
-
/** `SUPPORTED_SWEEP_BINDING_VERSIONS` in `@haven_ai/signer` does not include the received version. */
|
|
1359
|
-
readonly UnsupportedSweepBindingVersion: "UNSUPPORTED_SWEEP_BINDING_VERSION";
|
|
1360
|
-
};
|
|
1361
|
-
type SignerRefusalCode = (typeof SignerRefusalCode)[keyof typeof SignerRefusalCode];
|
|
1362
|
-
/**
|
|
1363
|
-
* Canonical recovery guidance for a stale local signer (#1309) — the ONE
|
|
1364
|
-
* string both the signer's structured refusal (`fallback` field, carried by
|
|
1365
|
-
* `HavenUnsupportedSignerVersionError`) and the hosted quote's advisory
|
|
1366
|
-
* `signer_compatibility.fallback` (#1155) render, so an agent that meets
|
|
1367
|
-
* either surface is told the identical fix. A second hand-maintained copy of
|
|
1368
|
-
* this sentence is exactly how the two surfaces could start disagreeing about
|
|
1369
|
-
* what to do.
|
|
1370
|
-
*/
|
|
1371
|
-
declare function signerUpdateFallback(channel?: string): string;
|
|
1372
|
-
/**
|
|
1373
|
-
* The same sentence rendered for THIS build's channel (#2423). Every existing
|
|
1374
|
-
* consumer keeps importing this constant and keeps getting a string; the only
|
|
1375
|
-
* thing that moved is that `alpha` is no longer typed into it.
|
|
1376
|
-
*
|
|
1377
|
-
* The hosted MCP server is the one caller that does NOT use this constant: it
|
|
1378
|
-
* is deployed rather than published, so it renders `signerUpdateFallback()`
|
|
1379
|
-
* with the channel its own environment names.
|
|
1380
|
-
*/
|
|
1381
|
-
declare const SIGNER_UPDATE_FALLBACK: string;
|
|
1382
|
-
/**
|
|
1383
|
-
* Thrown by the local signer when a Haven-signed binding (x402 expected
|
|
1384
|
-
* context or sweep authorization) carries a version outside what this signer
|
|
1385
|
-
* install enforces (#1143, structured as #1309). Machine-readable: `code`,
|
|
1386
|
-
* `supportedVersions`, and `receivedVersion` are DERIVED from the signer's own
|
|
1387
|
-
* `SUPPORTED_X402_EXPECTED_VERSIONS` / `SUPPORTED_SWEEP_BINDING_VERSIONS`
|
|
1388
|
-
* constants at the throw site, never a second literal — see
|
|
1389
|
-
* `assertSupportedBindingVersion` in `@haven_ai/signer`.
|
|
1390
|
-
*
|
|
1391
|
-
* This narrows HOW the refusal is reported. It does not weaken it: nothing is
|
|
1392
|
-
* signed either way, and the version stays inside the Haven-signed binding
|
|
1393
|
-
* message (callers must not "fix" a mismatch by rewriting it).
|
|
1394
|
-
*/
|
|
1395
|
-
declare class HavenUnsupportedSignerVersionError extends HavenError {
|
|
1396
|
-
readonly supportedVersions: readonly number[];
|
|
1397
|
-
readonly receivedVersion: number;
|
|
1398
|
-
readonly fallback: string;
|
|
1399
|
-
constructor(message: string, code: SignerRefusalCode, supportedVersions: readonly number[], receivedVersion: number, fallback: string);
|
|
1400
|
-
}
|
|
1401
|
-
declare class HavenTimeoutError extends HavenError {
|
|
1402
|
-
constructor(paymentId: string);
|
|
1403
|
-
}
|
|
1
|
+
import { R as RawPaymentParties, H as HavenClientConfig, a as HavenClientUpdate, P as PaymentRequest, b as PaymentResult, c as PaymentIntent, X as X402PaymentRequired, d as X402AuthorizationOptions, e as X402Intent, f as PaymentStatusResult, g as HavenAgent, h as HavenAgentSummary, S as SweepResult, i as SweepPrepareResponse, j as SweepAuthorization, k as SweepSubmitResponse, l as HavenAllowanceSummary, m as HavenBalanceCoverage, n as PostPurchaseAllowanceSummary, A as AgentPaymentWarning, o as HavenCatalogEntry, p as HavenCatalogSubmission, q as HavenPaymentReceipt, r as HavenPaymentReceiptsPage, s as PaymentResumeState, t as X402Receipt, u as X402Quote, v as X402Erc7710Settlement, w as X402McpCallContext, x as SignData, y as ResumeAuthorizedX402Input, z as ResumeX402PaymentInput, B as X402ResumeState, C as X402McpTransport, D as X402MerchantCallContext, E as HavenError } from './base64-BUMXmruY.js';
|
|
2
|
+
export { F as AGENT_PAYMENT_FAILURE_CODE_VALUES, G as AGENT_PAYMENT_NEXT_ACTION_VALUES, I as AGENT_PAYMENT_PHASE_VALUES, J as AGENT_PAYMENT_RAIL_VALUES, K as AgentNextStep, L as AgentPaymentEnumSchema, M as AgentPaymentFailureCode, N as AgentPaymentFailureCodeDescriptions, O as AgentPaymentFailureCodeSchema, Q as AgentPaymentNextAction, T as AgentPaymentNextActionDescriptions, U as AgentPaymentNextActionSchema, V as AgentPaymentPhase, W as AgentPaymentPhaseDescriptions, Y as AgentPaymentPhaseSchema, Z as AgentPaymentRail, _ as AgentPaymentRailDescriptions, $ as AgentPaymentRailSchema, a0 as AgentPaymentSummary, a1 as AgentPaymentWarningCode, a2 as AgentPurchaseSummary, a3 as CONNECTOR_PACKAGE_NAME, a4 as CatalogSubmissionAccepted, a5 as DEFAULT_CONFIRMATION_TIMEOUT_MS, a6 as DEFAULT_NEXT_TOOL_BY_ACTION, a7 as DIRECT_SIGN_CONTEXT_VERSION, a8 as ENTRY_POINT_V07, a9 as ERC7710_ASSET_TRANSFER_METHOD, aa as HAVEN_CLIENT_HEADER, ab as HAVEN_CONNECTOR_CHANNEL, ac as HAVEN_MINIMUM_NODE_VERSION, ad as HYBRID_DELEGATOR_DOMAIN_NAME, ae as HYBRID_DELEGATOR_DOMAIN_VERSION, af as HavenAgentAllowanceSummary, ag as HavenAgentReadiness, ah as HavenAllowance, ai as HavenApiError, aj as HavenCatalogMerchant, ak as HavenListScope, al as HavenPaymentStateError, am as HavenSigningError, an as HavenTimeoutError, ao as HavenTypedDataRefusedError, ap as HavenUnsupportedSignerVersionError, aq as HavenUserOpBindingError, ar as HavenZeroSettlementHashError, as as MachinePaymentRail, at as MerchantTimeoutError, au as NEXT_TOOL_SERVER_NAMES, av as NEXT_TOOL_SERVER_ROLES, aw as NextStep, ax as NextStepArguments, ay as NextStepHandoff, az as NextStepInput, aA as NextStepTarget, aB as NextStepTargets, aC as NextToolServerRole, aD as PACKED_USER_OPERATION_FIELDS, aE as PaymentFee, aF as PaymentNextAction, aG as PaymentPhase, aH as PaymentStatus, aI as ROOT_AUTHORITY, aJ as SDK_CLIENT_IDENTITY, aK as SDK_VERSION, aL as SIGNER_UPDATE_FALLBACK, aM as SWEEP_BASE_CHAIN_ID, aN as SWEEP_BASE_SEPOLIA_CHAIN_ID, aO as SWEEP_BASE_SEPOLIA_USDC_ADDRESS, aP as SWEEP_BASE_USDC_ADDRESS, aQ as SettlementChildExpectation, aR as SignerRefusalCode, aS as SweepConfirmation, aT as SweepEip712Domain, aU as SweepEntry, aV as SweepExpectedAuth, aW as SweepPreparation, aX as SweepSubmitResult, aY as SweepTypedData, aZ as TRANSFER_WITH_AUTHORIZATION_TYPES, a_ as TYPED_DATA_NOT_ALLOWED, a$ as UnsupportedNodeVersionMessageOptions, b0 as X402AlreadySettledError, b1 as X402ExpectedAuth, b2 as X402ExpectedContext, b3 as X402PaymentHeaderContext, b4 as X402PaymentHeaderValidationError, b5 as X402PaymentOption, b6 as X402RequestSnapshot, b7 as X402SchemeSelection, b8 as X402UnexpectedStatusError, b9 as X402_LEGACY_PAYMENT_HEADER_NAME, ba as X402_MAX_AUTHORIZATION_WINDOW_SECONDS, bb as X402_PAYMENT_HEADER_NAME, bc as X402_PAYMENT_HEADER_NAMES_SENT, bd as X402_PAYMENT_REQUIRED_HEADER_NAME, be as X402_PAYMENT_RESPONSE_HEADER_NAME, bf as X402_SETTLEMENT_FORWARD_MARGIN_SECONDS, bg as assertBoundDirectPaymentUserOp, bh as assertUserOpTypedDataBinding, bi as buildSweepAuthorizationMessage, bj as buildSweepTypedData, bk as buildX402ExpectedMessage, bl as compareNodeVersions, bm as connectorRerunCommand, bn as connectorSpec, bo as createNextStepBuilder, bp as decodeBase64Json, bq as decodeBase64Utf8, br as defaultNextToolFor, bs as deriveDelegateAccountAddress, bt as encodeBase64Json, bu as encodeBase64Utf8, bv as encodePaymentProof, bw as havenClientIdentity, bx as isConnectorChannel, by as isErc7710Option, bz as isPackedUserOperationTypedData, bA as isSupportedNodeVersion, bB as isSweepableChain, bC as normalizePaymentRequired, bD as packedUserOperationHash, bE as parseNextTool, bF as parsePaymentRequired, bG as parsePaymentRequiredResponse, bH as readClientUpdate, bI as renderNextTool, bJ as resolveConnectorChannel, bK as resolveTokenFromAddress, bL as selectErc7710PaymentOption, bM as selectPaymentOption, bN as selectStandardPaymentOption, bO as selectX402SettlementScheme, bP as signerUpdateFallback, bQ as sweepUsdcAddress, bR as sweepUsdcDomain, bS as toStandardPaymentRequirements, bT as unsupportedNodeVersionMessage, bU as validateStandardX402PaymentHeader, bV as verifySettlementChild, bW as x402AssetTransferMethod, bX as x402AuthorizationAmount, bY as x402FacilitatorAddresses, bZ as x402V2PaymentEnvelope } from './base64-BUMXmruY.js';
|
|
3
|
+
import 'x402/types';
|
|
4
|
+
import 'viem';
|
|
1404
5
|
|
|
1405
6
|
/**
|
|
1406
7
|
* Verifiable payment receipts.
|
|
@@ -1464,186 +65,6 @@ type ReceiptVerification = {
|
|
|
1464
65
|
*/
|
|
1465
66
|
declare function verifyPaymentReceipt(receipt: PaymentReceipt, recover?: (hash: string, signature: string) => string): ReceiptVerification;
|
|
1466
67
|
|
|
1467
|
-
/**
|
|
1468
|
-
* Gasless delegate-sweep primitives — the single source of truth shared by the
|
|
1469
|
-
* edge signer (which signs) and the Haven backend (which relays).
|
|
1470
|
-
*
|
|
1471
|
-
* A stranded delegate EOA holds USDC but no ETH, so a raw ERC-20 transfer can't
|
|
1472
|
-
* pay for its own gas. Instead the delegate signs an *off-chain* EIP-3009
|
|
1473
|
-
* `TransferWithAuthorization` and the Haven relayer submits it on-chain and pays
|
|
1474
|
-
* gas. The relayer is only a gas payer: it holds no allowance and is never a
|
|
1475
|
-
* spender, so a relayer compromise cannot move user funds.
|
|
1476
|
-
*
|
|
1477
|
-
* Framework-neutral on purpose: `buildSweepTypedData` returns a plain
|
|
1478
|
-
* `{ domain, types, primaryType, message }` that both viem
|
|
1479
|
-
* (`signTypedData`/`recoverTypedDataAddress`) and ethers v6
|
|
1480
|
-
* (`signTypedData`/`verifyTypedData`) accept, so the signer (viem) and backend
|
|
1481
|
-
* (ethers) stay in lockstep without sharing a crypto library.
|
|
1482
|
-
*/
|
|
1483
|
-
/** Base mainnet. The only chain Haven sweeps today. */
|
|
1484
|
-
declare const SWEEP_BASE_CHAIN_ID = 8453;
|
|
1485
|
-
/** Base Sepolia testnet — used by the dev environment / QA harness. */
|
|
1486
|
-
declare const SWEEP_BASE_SEPOLIA_CHAIN_ID = 84532;
|
|
1487
|
-
/** Canonical Circle USDC on Base (FiatTokenV2_2). */
|
|
1488
|
-
declare const SWEEP_BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
1489
|
-
/** Circle's canonical Base Sepolia testnet USDC. */
|
|
1490
|
-
declare const SWEEP_BASE_SEPOLIA_USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
|
|
1491
|
-
/** True when the gasless sweep supports a chain (its USDC domain + address are known). */
|
|
1492
|
-
declare function isSweepableChain(chainId: number): boolean;
|
|
1493
|
-
/** EIP-712 `TransferWithAuthorization` struct, per EIP-3009. */
|
|
1494
|
-
declare const TRANSFER_WITH_AUTHORIZATION_TYPES: {
|
|
1495
|
-
readonly TransferWithAuthorization: readonly [{
|
|
1496
|
-
readonly name: "from";
|
|
1497
|
-
readonly type: "address";
|
|
1498
|
-
}, {
|
|
1499
|
-
readonly name: "to";
|
|
1500
|
-
readonly type: "address";
|
|
1501
|
-
}, {
|
|
1502
|
-
readonly name: "value";
|
|
1503
|
-
readonly type: "uint256";
|
|
1504
|
-
}, {
|
|
1505
|
-
readonly name: "validAfter";
|
|
1506
|
-
readonly type: "uint256";
|
|
1507
|
-
}, {
|
|
1508
|
-
readonly name: "validBefore";
|
|
1509
|
-
readonly type: "uint256";
|
|
1510
|
-
}, {
|
|
1511
|
-
readonly name: "nonce";
|
|
1512
|
-
readonly type: "bytes32";
|
|
1513
|
-
}];
|
|
1514
|
-
};
|
|
1515
|
-
interface SweepEip712Domain {
|
|
1516
|
-
name: string;
|
|
1517
|
-
version: string;
|
|
1518
|
-
chainId: number;
|
|
1519
|
-
verifyingContract: string;
|
|
1520
|
-
}
|
|
1521
|
-
/**
|
|
1522
|
-
* A fully-specified EIP-3009 authorization. All amounts/times are decimal
|
|
1523
|
-
* strings (JSON-safe) and `nonce` is a 0x-prefixed 32-byte hex value. `token`
|
|
1524
|
-
* and `chainId` are carried explicitly so the signer can assert they are
|
|
1525
|
-
* canonical before signing.
|
|
1526
|
-
*/
|
|
1527
|
-
interface SweepAuthorization {
|
|
1528
|
-
/** Delegate EOA the funds are swept FROM. */
|
|
1529
|
-
from: string;
|
|
1530
|
-
/** Originating Safe the funds are swept TO. */
|
|
1531
|
-
to: string;
|
|
1532
|
-
/** Atomic USDC amount (decimal string). */
|
|
1533
|
-
value: string;
|
|
1534
|
-
/** Unix seconds the authorization becomes valid (decimal string, usually "0"). */
|
|
1535
|
-
validAfter: string;
|
|
1536
|
-
/** Unix seconds the authorization expires (decimal string). */
|
|
1537
|
-
validBefore: string;
|
|
1538
|
-
/** Random 0x-prefixed 32-byte hex nonce. */
|
|
1539
|
-
nonce: string;
|
|
1540
|
-
/** USDC contract address. */
|
|
1541
|
-
token: string;
|
|
1542
|
-
/** Chain id (8453 today). */
|
|
1543
|
-
chainId: number;
|
|
1544
|
-
}
|
|
1545
|
-
/**
|
|
1546
|
-
* Haven's signature over the sweep authorization context, signed with the same
|
|
1547
|
-
* binding key the x402 expected-context uses. Lets the edge signer verify the
|
|
1548
|
-
* authorization actually came from Haven (and wasn't crafted by a compromised
|
|
1549
|
-
* hosted server pointing `to` at an attacker) before it signs.
|
|
1550
|
-
*/
|
|
1551
|
-
interface SweepExpectedAuth {
|
|
1552
|
-
/**
|
|
1553
|
-
* Currently always 1. Typed as `number` for the same reason as
|
|
1554
|
-
* `X402ExpectedAuth.version` (#1143): it is inbound, so a stale signer must be
|
|
1555
|
-
* able to *receive* an unknown version in order to report it. The signer's
|
|
1556
|
-
* `SUPPORTED_SWEEP_BINDING_VERSIONS` is the authority on what it will sign.
|
|
1557
|
-
*/
|
|
1558
|
-
version: number;
|
|
1559
|
-
message: string;
|
|
1560
|
-
signature: string;
|
|
1561
|
-
signer: string;
|
|
1562
|
-
}
|
|
1563
|
-
/** What `POST /machine-payments/sweep/prepare` returns when funds are stranded. */
|
|
1564
|
-
interface SweepPreparation {
|
|
1565
|
-
authorization: SweepAuthorization;
|
|
1566
|
-
expectedAuth: SweepExpectedAuth;
|
|
1567
|
-
}
|
|
1568
|
-
/** Wire response from `POST /machine-payments/sweep/prepare` (snake_case). */
|
|
1569
|
-
interface SweepPrepareResponse {
|
|
1570
|
-
/** Present and true when the delegate holds nothing to recover. */
|
|
1571
|
-
nothing_stranded?: boolean;
|
|
1572
|
-
/**
|
|
1573
|
-
* Present and true when the stranded balance is below the sweep floor (#700):
|
|
1574
|
-
* it is left on the delegate as dust rather than recovered, because the gas to
|
|
1575
|
-
* sweep it would exceed its value. `min_usdc` carries the configured floor. No
|
|
1576
|
-
* `authorization` is built.
|
|
1577
|
-
*/
|
|
1578
|
-
below_min?: boolean;
|
|
1579
|
-
min_usdc?: string;
|
|
1580
|
-
/** The authorization to sign — absent when nothing is stranded or below the floor. */
|
|
1581
|
-
authorization?: SweepAuthorization;
|
|
1582
|
-
/** Haven's binding over the authorization — absent when nothing is stranded. */
|
|
1583
|
-
expected_auth?: SweepExpectedAuth;
|
|
1584
|
-
asset?: string;
|
|
1585
|
-
amount?: string;
|
|
1586
|
-
amount_atomic?: string;
|
|
1587
|
-
chain_id: number;
|
|
1588
|
-
sign_instructions?: string;
|
|
1589
|
-
message?: string;
|
|
1590
|
-
}
|
|
1591
|
-
/** Wire response from `POST /machine-payments/sweep/submit` (snake_case). */
|
|
1592
|
-
interface SweepSubmitResponse {
|
|
1593
|
-
tx_hash: string;
|
|
1594
|
-
asset: string;
|
|
1595
|
-
amount: string;
|
|
1596
|
-
amount_atomic: string;
|
|
1597
|
-
from_address: string;
|
|
1598
|
-
to_address: string;
|
|
1599
|
-
chain_id: number;
|
|
1600
|
-
explorer_url: string;
|
|
1601
|
-
idempotent_replay?: boolean;
|
|
1602
|
-
}
|
|
1603
|
-
/** Result of a submitted gasless sweep. */
|
|
1604
|
-
interface SweepSubmitResult {
|
|
1605
|
-
txHash: string;
|
|
1606
|
-
amount: string;
|
|
1607
|
-
amountAtomic: string;
|
|
1608
|
-
asset: string;
|
|
1609
|
-
fromAddress: string;
|
|
1610
|
-
toAddress: string;
|
|
1611
|
-
chainId: number;
|
|
1612
|
-
explorerUrl: string;
|
|
1613
|
-
}
|
|
1614
|
-
interface SweepTypedData {
|
|
1615
|
-
domain: SweepEip712Domain;
|
|
1616
|
-
types: typeof TRANSFER_WITH_AUTHORIZATION_TYPES;
|
|
1617
|
-
primaryType: 'TransferWithAuthorization';
|
|
1618
|
-
message: {
|
|
1619
|
-
from: string;
|
|
1620
|
-
to: string;
|
|
1621
|
-
value: bigint;
|
|
1622
|
-
validAfter: bigint;
|
|
1623
|
-
validBefore: bigint;
|
|
1624
|
-
nonce: string;
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1627
|
-
/** Resolve the canonical USDC contract for a sweepable chain, or throw. */
|
|
1628
|
-
declare function sweepUsdcAddress(chainId: number): string;
|
|
1629
|
-
/** Resolve the USDC EIP-712 domain for a sweepable chain, or throw. */
|
|
1630
|
-
declare function sweepUsdcDomain(chainId: number): SweepEip712Domain;
|
|
1631
|
-
/**
|
|
1632
|
-
* Build the EIP-712 typed data for an authorization, validating that the token
|
|
1633
|
-
* and chain are canonical (the domain's `verifyingContract` must match the
|
|
1634
|
-
* authorization's `token`). Returns bigint-valued fields so both viem and
|
|
1635
|
-
* ethers v6 sign/recover identically.
|
|
1636
|
-
*/
|
|
1637
|
-
declare function buildSweepTypedData(auth: SweepAuthorization): SweepTypedData;
|
|
1638
|
-
/**
|
|
1639
|
-
* Canonical, deterministic string the backend signs and the signer re-derives
|
|
1640
|
-
* for the authorization binding. The `Haven sweep authorization v1` namespace
|
|
1641
|
-
* (and `kind`) is distinct from the x402 expected-context namespace so an x402
|
|
1642
|
-
* binding can never be replayed as a sweep authorization even though they share
|
|
1643
|
-
* a signing key.
|
|
1644
|
-
*/
|
|
1645
|
-
declare function buildSweepAuthorizationMessage(auth: SweepAuthorization): string;
|
|
1646
|
-
|
|
1647
68
|
/**
|
|
1648
69
|
* Merchant delivery and the evidence trail behind it (#1620, epic #1613).
|
|
1649
70
|
*
|
|
@@ -1757,10 +178,18 @@ declare class HavenClient {
|
|
|
1757
178
|
* context.
|
|
1758
179
|
*/
|
|
1759
180
|
withRequestContext<T>(headers: Record<string, string>, fn: () => Promise<T>): Promise<T>;
|
|
181
|
+
/**
|
|
182
|
+
* The backend's newest `client_update` hint for this client (#3303): inside
|
|
183
|
+
* a `withRequestContext` dispatch, the one that dispatch's own requests
|
|
184
|
+
* received; outside one, the latest seen. Undefined when the client is
|
|
185
|
+
* current or the backend predates #3303.
|
|
186
|
+
*/
|
|
187
|
+
clientUpdate(): HavenClientUpdate | undefined;
|
|
1760
188
|
/**
|
|
1761
189
|
* Send a payment in one call.
|
|
1762
190
|
*
|
|
1763
|
-
* Creates the intent, signs
|
|
191
|
+
* Creates the intent, signs its `sign_data` (a delegation-rail intent's
|
|
192
|
+
* EIP-712 typed data, after the #3271 UserOp binding check), submits the signature,
|
|
1764
193
|
* and polls until confirmed (or throws on failure/timeout).
|
|
1765
194
|
*
|
|
1766
195
|
* Requires `delegateKey` to be set in the client config.
|
|
@@ -1840,11 +269,12 @@ declare class HavenClient {
|
|
|
1840
269
|
*/
|
|
1841
270
|
getAgentSummary(): Promise<HavenAgentSummary>;
|
|
1842
271
|
/**
|
|
1843
|
-
* Sweep stranded USDC and ETH from the delegate EOA back to the
|
|
272
|
+
* Sweep stranded USDC and ETH from the delegate EOA back to the agent's Haven account.
|
|
1844
273
|
*
|
|
1845
274
|
* The delegate key held by this client signs and submits the transfer transactions
|
|
1846
275
|
* directly — Haven's backend never handles the key or constructs signed txs
|
|
1847
|
-
* (CASP/MiCA Red Line #2). Funds always go to the
|
|
276
|
+
* (CASP/MiCA Red Line #2). Funds always go to the Haven account linked to this agent
|
|
277
|
+
* (`accountAddress` from `getAgent()`).
|
|
1848
278
|
*
|
|
1849
279
|
* Requires `chainRpcs` to be set for the agent's chain in `HavenClientConfig`.
|
|
1850
280
|
*/
|
|
@@ -1870,6 +300,52 @@ declare class HavenClient {
|
|
|
1870
300
|
* Get configured and on-chain allowances for the authenticated agent.
|
|
1871
301
|
*/
|
|
1872
302
|
getAllowances(): Promise<HavenAllowanceSummary>;
|
|
303
|
+
/**
|
|
304
|
+
* #3126 — is the checked amount of the token actually HELD on the
|
|
305
|
+
* agent's own account?
|
|
306
|
+
*
|
|
307
|
+
* This is the companion to {@link getAllowances}, not a variant of it:
|
|
308
|
+
* allowances answer what the agent is PERMITTED to spend this period;
|
|
309
|
+
* this answers whether the account HOLDS funds behind that permission,
|
|
310
|
+
* as a sufficiency signal — `covered: true | false | null` — never as a
|
|
311
|
+
* balance. `covered: null` means the chain read failed: treat it as
|
|
312
|
+
* unverifiable, not as absence (`coverageError` says why). The account's
|
|
313
|
+
* balance itself is deliberately not returned.
|
|
314
|
+
*/
|
|
315
|
+
checkFunds(input: {
|
|
316
|
+
token: string;
|
|
317
|
+
amountAtomic: string;
|
|
318
|
+
}): Promise<HavenBalanceCoverage>;
|
|
319
|
+
/**
|
|
320
|
+
* `POST /machine-payments/budget-precheck` (#3054): ask Haven to decide —
|
|
321
|
+
* server-side — whether `amountAtomic` of `token` fits the agent's
|
|
322
|
+
* remaining delegation budget, the same compare the guided prepare used to
|
|
323
|
+
* run locally over its allowances read.
|
|
324
|
+
*
|
|
325
|
+
* On insufficiency Haven refuses (403, `delegation_budget_exceeded`) and
|
|
326
|
+
* the refusal reaches the `payment_refusals` ledger with
|
|
327
|
+
* `source: 'hosted_prepare'` — the point of the endpoint. This method
|
|
328
|
+
* surfaces that decision as a thrown {@link HavenApiError}; it does NOT
|
|
329
|
+
* swallow it, because swallowing would turn a decided refusal into the
|
|
330
|
+
* degrade-to-warning path and the ledger row would still land while the
|
|
331
|
+
* purchase proceeded.
|
|
332
|
+
*
|
|
333
|
+
* camelCase body like the route family; the response mirrors the wire
|
|
334
|
+
* (`sufficient`, `remaining_atomic`). `resourceUrl` is the merchant
|
|
335
|
+
* resource being bought — the ledger dedupe window's discriminating
|
|
336
|
+
* column — never this request's own URL.
|
|
337
|
+
*/
|
|
338
|
+
precheckBudget(input: {
|
|
339
|
+
chainId?: number;
|
|
340
|
+
token: string;
|
|
341
|
+
amountAtomic: string;
|
|
342
|
+
merchantTo?: string;
|
|
343
|
+
resourceUrl?: string;
|
|
344
|
+
}): Promise<{
|
|
345
|
+
sufficient: boolean;
|
|
346
|
+
remaining_atomic: string;
|
|
347
|
+
remaining_is_from_chain?: boolean;
|
|
348
|
+
}>;
|
|
1873
349
|
/**
|
|
1874
350
|
* Post-purchase allowance/budget summary for a settled payment (#1310).
|
|
1875
351
|
*
|
|
@@ -1996,6 +472,11 @@ declare class HavenClient {
|
|
|
1996
472
|
listReceipts(options?: {
|
|
1997
473
|
limit?: number;
|
|
1998
474
|
}): Promise<HavenPaymentReceipt[]>;
|
|
475
|
+
/** #3128: one page of receipts with `total`, `hasMore` and `nextCursor`. */
|
|
476
|
+
listReceiptsPage(options?: {
|
|
477
|
+
limit?: number;
|
|
478
|
+
cursor?: string;
|
|
479
|
+
}): Promise<HavenPaymentReceiptsPage>;
|
|
1999
480
|
/**
|
|
2000
481
|
* Fetch the verifiable receipt bundle for a settled payment and verify it
|
|
2001
482
|
* locally. The server's own verification is ignored — the receipt is verified
|
|
@@ -2107,10 +588,11 @@ declare class HavenClient {
|
|
|
2107
588
|
resumeAuthorizedX402(input: ResumeAuthorizedX402Input): Promise<X402Receipt>;
|
|
2108
589
|
resumeX402Payment(input: ResumeX402PaymentInput | X402ResumeState): Promise<Response>;
|
|
2109
590
|
/**
|
|
2110
|
-
* Fetch wrapper that automatically handles HTTP 402 responses
|
|
591
|
+
* Fetch wrapper that automatically handles HTTP 402 responses — and, since
|
|
592
|
+
* #3118, a native-MCP payment-required tool result answered under HTTP 200.
|
|
2111
593
|
*
|
|
2112
|
-
* Works like the standard `fetch()` but intercepts 402 responses
|
|
2113
|
-
* pays via x402 through Haven, and retries the request.
|
|
594
|
+
* Works like the standard `fetch()` but intercepts 402 responses (or that
|
|
595
|
+
* tool-result challenge), pays via x402 through Haven, and retries the request.
|
|
2114
596
|
*
|
|
2115
597
|
* ```ts
|
|
2116
598
|
* const response = await haven.fetch('https://paid-api.com/data')
|
|
@@ -2118,8 +600,9 @@ declare class HavenClient {
|
|
|
2118
600
|
* ```
|
|
2119
601
|
*
|
|
2120
602
|
* **MCP-over-x402 auto-handshake (issue #315):** when the endpoint is
|
|
2121
|
-
* MCP-shaped — the URL path ends in `/mcp`, or the 402 body
|
|
2122
|
-
*
|
|
603
|
+
* MCP-shaped — the URL path ends in `/mcp`, or the 402 body (or, since
|
|
604
|
+
* #3118, the tool-result challenge) carries a Coinbase Bazaar
|
|
605
|
+
* `extensions.bazaar` block — the SDK runs the MCP
|
|
2123
606
|
* `initialize` handshake, threads the resulting `mcp-session-id`,
|
|
2124
607
|
* `Accept: application/json, text/event-stream`, and `x402-wallet` headers
|
|
2125
608
|
* through every request, and collapses SSE responses to the JSON-RPC
|
|
@@ -2149,7 +632,7 @@ declare class HavenClient {
|
|
|
2149
632
|
* collapses an SSE JSON-RPC response to its `result`.
|
|
2150
633
|
*/
|
|
2151
634
|
/**
|
|
2152
|
-
* Wait for a payment's
|
|
635
|
+
* Wait for a payment's account→delegate funding tx to reach ≥1 on-chain
|
|
2153
636
|
* confirmation. The hosted x402 completion path MUST call this after funding
|
|
2154
637
|
* and before delivering the merchant payment header, so the merchant's
|
|
2155
638
|
* balanceOf(delegate) / transferWithAuthorization verification sees the funded
|
|
@@ -2323,7 +806,7 @@ declare const havenTools: {
|
|
|
2323
806
|
/**
|
|
2324
807
|
* Sign a hash using raw ECDSA (no Ethereum message prefix).
|
|
2325
808
|
*
|
|
2326
|
-
* This matches what Safe's
|
|
809
|
+
* This matches what the retired Safe AllowanceModule rail's `checkSignature` expected —
|
|
2327
810
|
* a direct ecrecover over the hash, NOT the "\x19Ethereum Signed Message" variant.
|
|
2328
811
|
*
|
|
2329
812
|
* Uses ethers.SigningKey.sign() instead of wallet.signMessage() to avoid the prefix.
|
|
@@ -2405,12 +888,12 @@ declare const toolDescriptions: {
|
|
|
2405
888
|
readonly payX402OneShot: {
|
|
2406
889
|
readonly summary: "Fetch an x402 paid HTTP resource in a single call. Handles the full probe -> pay -> retry round trip and returns the merchant response.";
|
|
2407
890
|
readonly 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.";
|
|
2408
|
-
readonly 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.";
|
|
891
|
+
readonly 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.";
|
|
2409
892
|
readonly nextActionGuidance: string;
|
|
2410
893
|
};
|
|
2411
894
|
readonly resumeX402: {
|
|
2412
895
|
readonly summary: "Resume an x402 payment whose Haven-side authorization already succeeded but whose merchant retry did not complete.";
|
|
2413
|
-
readonly behavior: "Accepts either resume_state or payment_id, validates the
|
|
896
|
+
readonly 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.";
|
|
2414
897
|
readonly nextActionGuidance: string;
|
|
2415
898
|
};
|
|
2416
899
|
readonly getPaymentStatus: {
|
|
@@ -2424,21 +907,27 @@ declare const toolDescriptions: {
|
|
|
2424
907
|
readonly nextActionGuidance: "";
|
|
2425
908
|
};
|
|
2426
909
|
readonly getAgent: {
|
|
2427
|
-
readonly summary: "Return the authenticated agent identity AND its live spend authority in one call: Haven wallet, delegate, chain, raw status, spend_authority_readiness,
|
|
2428
|
-
readonly selectionGuidance: "Use this as the
|
|
2429
|
-
readonly behavior: "Reads identity plus the live spend-authority snapshot
|
|
910
|
+
readonly summary: "Return the authenticated agent identity AND its live spend authority in one call: Haven wallet, delegate, chain, raw status, spend_authority_readiness, per-token remaining allowance (atomic + human-readable). The recommended first call in a new session.";
|
|
911
|
+
readonly selectionGuidance: "Use this as the session bootstrap, or to confirm identity together with whether the agent can spend right now. For per-token detail (configured vs spent vs reset window) use haven_get_allowances.";
|
|
912
|
+
readonly behavior: "Reads identity plus the live spend-authority snapshot — the active on-chain budget delegation. spend_authority_readiness (readiness is a deprecated alias, same value) is \"ready\" when at least one token has remaining spend authority, \"needs_approval\" when the agent is active but has none, and \"revoked\" when the credential is not active. It covers hosted identity + on-chain spend authority ONLY — the hosted server cannot see the LOCAL signer, so \"ready\" does not mean the signer can start; verify the signer with a signer tool call or connect --doctor. An over-budget payment is declined before any money moves; there is no approval queue — ask the owner to grant or raise the budget in Haven. allowances[] carries id, tokenAddress, remainingAtomic, remainingDisplay per token. Identity fields: id, name, status, accountAddress, delegateAddress, chainId.";
|
|
2430
913
|
readonly nextActionGuidance: "";
|
|
2431
914
|
};
|
|
2432
915
|
readonly getAllowances: {
|
|
2433
916
|
readonly summary: "Return configured and on-chain allowance state for the authenticated agent. On-chain allowance is the real spend gate.";
|
|
2434
|
-
readonly selectionGuidance: "Use this when the user asks about allowance, budget, spend limit, remaining amount, remaining allowance, remaining budget, daily limit, reset period, what can I spend, or what the agent can still spend.";
|
|
2435
|
-
readonly behavior: "Returns the per-token spend authority for the account: the active budget delegation (remaining = the period budget, which re-arms natively at the period boundary). An over-budget payment is declined before any money moves; nothing queues. Configured amounts from Haven are returned alongside.";
|
|
917
|
+
readonly selectionGuidance: "Use this when the user asks about allowance, budget, spend limit, remaining amount, remaining allowance, remaining budget, daily limit, reset period, what can I spend, or what the agent can still spend. For whether the account actually HOLDS funds behind the budget use haven_check_funds.";
|
|
918
|
+
readonly behavior: "Returns the per-token spend authority for the account: the active budget delegation (remaining = the period budget, which re-arms natively at the period boundary), each with id, onchain.remaining, remainingDisplay. An over-budget payment is declined before any money moves; nothing queues. Configured amounts from Haven are returned alongside.";
|
|
2436
919
|
readonly nextActionGuidance: "";
|
|
2437
920
|
};
|
|
921
|
+
readonly checkFunds: {
|
|
922
|
+
readonly summary: "Check whether the agent's account actually holds at least the given amount of a token — funds held, not spend permitted.";
|
|
923
|
+
readonly selectionGuidance: "Use this before attempting a payment when it matters whether the money is really there: allowance answers say what you are PERMITTED to spend, never whether the account HOLDS it. For allowance, budget, spend-limit, remaining-budget, reset-period, or what-can-I-spend questions use the allowance lookup tool instead.";
|
|
924
|
+
readonly behavior: "Returns covered: true (the account holds at least the checked amount), false (a live chain read reports less — the budget is backed by an empty account; stop and tell the user funds are missing), or null (the chain read failed — unverifiable, never treat it as absence; coverageError says why). The account balance itself is deliberately not returned: this is a sufficiency signal, not a balance read. budget_remaining_atomic is the permitted figure from the allowance lookup (the SDK spells it budgetRemainingAtomic), named so it can never be confused with holdings.";
|
|
925
|
+
readonly nextActionGuidance: "On covered=false, do not attempt the payment — tell the user the account is short and let them fund it; on covered=null, retry the check shortly or proceed knowing the payment may fail on-chain.";
|
|
926
|
+
};
|
|
2438
927
|
readonly listReceipts: {
|
|
2439
|
-
readonly summary: "List
|
|
2440
|
-
readonly selectionGuidance: "
|
|
2441
|
-
readonly behavior: "
|
|
928
|
+
readonly summary: "List machine-payment receipts, newest first, by page.";
|
|
929
|
+
readonly 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.";
|
|
930
|
+
readonly 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.";
|
|
2442
931
|
readonly nextActionGuidance: "";
|
|
2443
932
|
};
|
|
2444
933
|
readonly verifyReceipt: {
|
|
@@ -2454,10 +943,10 @@ declare const toolDescriptions: {
|
|
|
2454
943
|
readonly nextActionGuidance: string;
|
|
2455
944
|
};
|
|
2456
945
|
readonly discoverTools: {
|
|
2457
|
-
readonly summary: "Step 1 of a purchase: discover payable services from Haven's curated merchant catalog — names, prices,
|
|
946
|
+
readonly summary: "Step 1 of a purchase: discover payable services from Haven's curated merchant catalog — names, prices, the next call.";
|
|
2458
947
|
readonly selectionGuidance: string;
|
|
2459
948
|
readonly behavior: string;
|
|
2460
|
-
readonly nextActionGuidance: "
|
|
949
|
+
readonly nextActionGuidance: "Call suggested_tool with suggested_arguments VERBATIM (no hint: read suggested_tool_omitted_reason). Confirm the price from the live quote or pay result, not the catalog; if the next tool takes a cap, pass the user's cap as max_amount_human in whole tokens (\"no more than 1 USDC\" → max_amount_human: \"1\"), never atomic units by hand.";
|
|
2461
950
|
};
|
|
2462
951
|
readonly submitCatalogEntry: {
|
|
2463
952
|
readonly summary: "Submit a merchant's payable (x402/MCP) endpoint to Haven's Verified Payable Directory for verification and listing.";
|
|
@@ -2527,7 +1016,7 @@ type SharedToolKey = keyof typeof toolDescriptions;
|
|
|
2527
1016
|
* live sibling constant not pulled in here; if it ever is, this applies to it
|
|
2528
1017
|
* too (design review, #2537).
|
|
2529
1018
|
*/
|
|
2530
|
-
declare const HAVEN_SKILL_MD = "---\nname: haven-pay\ndescription: Pay for things from the user's Haven wallet within their agent rules, and set Haven up when it is not yet connected. Use when the user asks to send, pay, tip, or transfer crypto; when a request hits an HTTP 402 (x402) paywall; or when they ask to create a Haven account, create an agent, or connect one.\n---\n\n# Haven: pay from a Haven wallet\n\nThis skill lets the agent make payments from the user's Haven wallet through\nthe Haven MCP tools. Every payment is checked against the agent's on-chain\nbudget before money moves; a payment above the remaining budget is declined \u2014\nnothing is paid past the rules the user set.\n\nHosted tools run in the `mcp__haven__` namespace. Local signing tools run in\nthe `mcp__haven-signer__` namespace and keep the delegate key on this machine.\nThat namespacing is Claude-family; other runtimes name the servers by their\nown config keys (Codex: `haven`, `haven_signer`). Tool results carry the\nexact next step (`next_action`, `next_tool`, `next_arguments`, plus the\nruntime-neutral `next_tool_server` + `next_tool_name` \u2014 the bare tool name\non that logical server, whatever your runtime calls it).\nFollow those fields first; the prose below is fallback and orientation, not\nthe source of truth.\n\n## When to use this skill\n\n- The user asks to send money, pay someone, tip, donate, or transfer tokens.\n- A request returns HTTP 402 (x402): use the Haven pay tools to settle it,\n then retry the original request.\n\n## Onboarding and setup\n\nYou are in this mode when there is no Haven agent credential on this machine,\nor when your user asks you to create a Haven account, create an agent, or\nconnect one \u2014 for themselves or for someone else.\n\n**None of the tools below creates authority.** They spend a budget a human\nalready signed. There is no tool here that opens an account, mints a\ncredential, or approves a budget, so reaching for one of them to \"set Haven\nup\" cannot work; the steps are the ones in this section instead.\n\nStart by reading `/for-agents.md` on the Haven host \u2014 the origin of the\n`api_url` in your `agent.json` if you have one, otherwise the host your user\nnames. It is the full runbook: six steps, which four are your user's, and what\nto say at each hand-off.\n\nTwo of those steps you can do yourself, from the shell with `@haven_ai/cli`\n(installs the `haven` command):\n\n- `haven login` \u2014 a device-code browser flow. It prints a code and a link\n for your user to approve, so you never see or ask for their password. What\n the session can reach is an allow-list, not your user's full authority: it\n creates and manages agents and reads the account, and it cannot approve a\n budget, rotate a key, change a signer or move money \u2014 those are your user's.\n- `haven agents connect` with `--name`, `--budget`, `--token` and\n `--period` \u2014 creates a connection setup and prints two things: the\n connector command the backend built, and the approval link to give your user.\n Add `--run` to execute that command here as a child process.\n- `haven wallets funding` \u2014 prints the paste-ready funding instruction: what\n to send, to which address, on which chain. Read the chain from there rather\n than assuming one. `--wait` polls until the account counts as funded.\n\n**Four steps are your user's, and each one needs a human:** create the account\nand its passkey, fund the wallet, approve every agent's budget, and rotate a\ncredential. You can compose the funding message for them with\n`haven wallets funding`, but you cannot send the money \u2014 that transfer is\ntheirs, from a wallet you have no access to.\n\nRunning the connector command is the step that wires this machine to the new\nagent \u2014 the command `haven agents connect` printed, or the one your user\npasted you from the dashboard. Three rules bind you while you do it, quoted\nunchanged from the setup prompt your user is also holding so the two copies\ncannot drift into contradicting each other. They are written in your user's\nvoice, so read them accordingly: \"me\" and \"I\" below are your user, never\nHaven, and \"the command above\" is that connector command, not anything printed\nin this file. The first rule outranks anything else you were about to do next:\n\n- When a --json outcome reports approval.required: true, your first action must be to relay the approval instruction to me in your own reply \u2014 if the outcome carries approval.url, give me that link; otherwise tell me to return to Haven and approve this agent's budget \u2014 before verifying the connection, restarting anything, or any other step. Never build that link yourself: relay the one the outcome gave you or none at all. Any restart the outcome asks for is a separate instruction to give me afterwards, once the approval is done.\n- Only two changes to the command above are permitted, and no others: appending --json, and \u2014 only if the connector refuses because it could not determine the agent runtime \u2014 re-running it once with --runtime <name> added, naming the harness you are running in, using one of the values that refusal lists. Never invent a runtime name and never change anything else.\n- If the connector refuses with wiring_collision, this machine is already wired to a different agent: relay that refusal to me with the superseded_agent_ids and suggested_name it carries, and let me choose whether to replace the existing wiring or add this agent alongside it. Never pick for me by adding --replace or --name yourself.\n\nDo not print private keys, API keys, credential file contents, or config secrets in chat or logs.\n\n## Identity and budget\n\nDo not guess the wallet address, network, or budget.\n\nFor instant orientation at the start of a session, read the non-secret\n`agent.json` the connector wrote to your Haven credential directory (typically\n`~/.haven/agents/<agent-id>/agent.json` \u2014 if you don't know the agent id, list\n`~/.haven/agents/` to find the folder). It\nholds your agent id, Haven wallet address, network, and *configured* per-token\nbudget, and contains no keys \u2014 the fastest way to answer \"who am I and what may\nI spend\" with no round trip. If that file is absent (some setups don't write\nit), use the tools below instead.\n\nBefore any payment, confirm the *live remaining* budget with the tools \u2014\n`agent.json` shows the configured budget, not what is left after recent\nspending:\n\n- `mcp__haven__haven_get_agent` \u2014 the recommended first call: identity\n (wallet, network) plus `spend_authority_readiness` (`ready` / `needs_approval` /\n `revoked`) and live remaining per-token allowance, in one shot. That signal\n covers hosted identity and on-chain spend authority only \u2014 it cannot see the\n local signer; the signer is verified by calling any signer tool.\n- `mcp__haven__haven_get_allowances` \u2014 detailed per-token breakdown\n (configured, spent, reset window) when you need more than the summary.\n\nBudgets reset on a period the user chose. If a payment exceeds the remaining\nbudget it is declined before any money moves \u2014 tell the user; they can raise\nthe budget in the Haven dashboard, or wait for the period reset.\n\n## Paying\n\n**Catalog purchases \u2014 the primary path for MCP merchants:**\n\n1. `mcp__haven__haven_discover_tools` to find a payable service and its\n `catalog_id`.\n2. If the user needs the live price before authorizing a cap, call\n `mcp__haven__haven_quote_catalog_purchase` with `catalog_id`. It is\n read-only and informational only: it never reserves a price or creates a\n payment. Tell the user its `amount` / `amount_atomic`, then choose a cap.\n3. `mcp__haven__haven_prepare_catalog_purchase` with `catalog_id` and a\n spending cap. A cap is REQUIRED on this tool and is best practice on every\n paid call below too \u2014 it caps what the LIVE merchant quote may charge,\n checked before any funding intent is created. Write it the way the user\n said it: `max_amount_human` is whole tokens, so \"no more than 1 USDC\" is\n `max_amount_human: \"1\"`. (`max_amount` is the atomic-unit form, where\n \"1\" means 0.000001 USDC \u2014 do not convert by hand, and never send both.)\n4. Then FOLLOW THE RESPONSE'S GUIDANCE FIELDS: `next_action`, `next_tool`,\n and `next_arguments` name the exact next call \u2014 act on those first; the\n prose in this section is fallback and debugging detail. If the catalog\n entry is missing or degraded, the response instead names\n `mcp__haven__haven_pay_mcp_tool` (merchant URL, tool name, arguments) as\n the manual fallback.\n\n**Signing:** `mcp__haven-signer__haven_sign_x402` with `payment_id` ONLY \u2014\nthe local signer fetches the exact signing bytes AND `payment_required`\nitself, so never relay `typed_data` or the 402 blob yourself. If the signer\nreports its fetched context carried no `payment_required` (older backend),\nre-call with `payment_required` added verbatim. Fallback for an older signer\nor backend: re-run the quote/prepare tool with the SAME `idempotency_key`\nplus `include_signing_payload=true`, then pass `payload_hash`,\n`x402_expected` (the nested `x402.expected` object), and\n`typed_data`/`typed_data_b64` through unchanged.\n\n**Settle:** `mcp__haven__haven_settle_mcp_tool` with `payment_id`,\n`signature`, and `payment_header` ONLY \u2014 Haven rehydrates the merchant call\ncontext (`merchant_url`, `tool_name`, `arguments`, `mcp_transport`)\nserver-side from `payment_id`. Pass those four fields explicitly only as a\nversion-skew fallback when Haven has no stored context for the id \u2014 both or\nnone together, never just one. If the settle result carries `settled: false`,\nfunding has not confirmed \u2014 follow the result's guidance fields and check\nstatus later, do not re-pay.\n\nStep-by-step alternative (also key-safe; for an older signer or backend, or\nwhen you already have a merchant URL and tool name instead of a\n`catalog_id`): if the user needs the live price before choosing a cap, first\ncall `mcp__haven__haven_quote_mcp_tool` with that merchant URL, tool name,\nand arguments. It is informational only; then call\n`mcp__haven__haven_pay_mcp_tool` with the same inputs and the explicit cap.\nThe paid call always obtains a fresh quote before it creates any intent. Then\ncontinue `mcp__haven__haven_pay_mcp_tool` \u2192\n`mcp__haven-signer__haven_sign` \u2192 `mcp__haven__haven_submit` \u2192\n`mcp__haven-signer__haven_x402_sign_header` \u2192\n`mcp__haven__haven_complete_mcp_tool`. Call that last step with\n`payment_id` and the signer's `payment_header` ONLY. It does not take\n`payment_required`: Haven rehydrates the merchant call context\n(`merchant_url`, `tool_name`, `arguments`, `mcp_transport`) and the\n402 server-side from `payment_id`, exactly as at settle. Pass that context\nexplicitly only as a version-skew fallback when Haven has no stored context\nfor the id \u2014 `merchant_url` and `tool_name` both or none together, never\njust one.\nThe returned `expires_at` is the signing window; if a tool returns\n`PAYMENT_WINDOW_EXPIRED`, re-run the same quote/prepare tool with the same\n`idempotency_key`. Do not call the merchant yourself \u2014 Haven completes the\nmerchant leg for you.\n\n**Direct transfer / non-MCP paywall:** `mcp__haven__haven_pay` with\n`to`, `amount`, and `token` for a plain transfer. For an arbitrary,\nnon-MCP x402 paywall: `mcp__haven__haven_quote_x402` to get a quote, then\n`mcp__haven__haven_pay_x402_quote` \u2014 follow the result's guidance fields\nfirst and sign in the local Haven signer. On THIS path Haven does not talk to\nthe merchant: `mcp__haven-signer__haven_sign_x402` returns both\n`signature` and `payment_header`; relay `signature` with\n`mcp__haven__haven_submit`, then retry the paywalled URL yourself with\n`payment_header`. Do not pass that call's `x402_binding` to\n`mcp__haven-signer__haven_x402_sign_header` \u2014 the one-shot already spent it\nbuilding the header, so the call can only refuse. Then tell Haven what the\nmerchant answered: `mcp__haven__haven_report_x402_outcome` with the\n`payment_id`, `outcome` (`\"accepted\"` for a 2xx, else `\"rejected\"`)\nand the `merchant_status` you got. Because Haven never contacted that\nmerchant, this is the only way it can learn the purchase failed \u2014 without it a\nfailed purchase reads as complete for fifteen minutes. (The SDK's own\n`haven_pay_x402` tool does perform the merchant retry itself; that tool is\nnot part of the hosted MCP surface.) If the process\ncrashes after payment, a later `mcp__haven__haven_get_payment_status` call\nmay report `nextAction: 'retry_original_x402_request'` \u2014 only then call\n`mcp__haven__haven_resume_x402_payment` with the preserved resume state or\npayment id, instead of paying again.\n\n**Catalog tool arguments:** when `haven_discover_tools` returns\n`tool_arguments`, pass that object unchanged as the pay tool's\n`arguments` field (for example\n`tool_arguments: { \"tier\": \"50gb\" }` -> `arguments: { \"tier\": \"50gb\" }`).\n\n**Prices:** show the user the live price from a read-only quote or the pay-tool\nresult, never a catalog price. `haven_discover_tools` prices are indicative\n(`price_is_indicative`) and can be stale. A read-only quote is informational\nonly and does not reserve a price; the later paid call re-quotes and enforces\nthe cap. The pay-tool result's `amount` / `amount_atomic` is the merchant's\nown quoted price for that call \u2014 a ceiling the merchant settles at or below \u2014\nso present it as the most the user will pay. It is a price, not an approval:\nthe payment goes through only if it also fits the cap you set and the on-chain\nbudget the user signed, which is enforced on-chain rather than by Haven.\n\n**Status:** `mcp__haven__haven_get_payment_status` with a `payment_id` to\ncheck on in-flight payments. Do not poll in a tight loop.\n\n## Declines and stop signals\n\n- A payment outside the agent's rules \u2014 above the remaining budget, wrong\n recipient, or expired budget \u2014 is declined before any money moves. Nothing\n is queued; tell the user, who can raise the budget in Haven.\n- `safe_to_continue: false` on a guidance block is a stop signal in\n machine-readable form: stop and involve the user before calling anything\n else for this payment.\n- Never ask the user for private keys. Signing happens only in the local Haven\n signer; the hosted Haven tools never receive the signing key. If a tool\n reports a missing or invalid credential, tell the user to re-run the Haven\n connector command.\n\n## Failure handling\n\nHaven tool failures are shaped like `{ success: false, code, message, ... }`\nor older `{ error, status, details? }` responses. Branch on `code` when\npresent and surface `message` or `error` verbatim. Common cases:\n\n- `insufficient_funds`: the Haven wallet doesn't hold enough of that token.\n Suggest the user add funds in the Haven dashboard.\n- `PRICE_EXCEEDS_MAX`: the live merchant price exceeded your cap. No funds\n moved; ask the user before retrying with a higher one.\n- `AMBIGUOUS_MAX_AMOUNT`: you sent both `max_amount` and\n `max_amount_human`. Nothing was contacted or spent \u2014 re-send with exactly\n one (`max_amount_human` for a cap the user stated in tokens).\n- `MAX_AMOUNT_UNCONVERTIBLE`: `max_amount_human` does not fit this quote's\n asset \u2014 unknown decimals, or more decimal places than the asset supports.\n Round the cap, or send an exact atomic `max_amount`.\n- `PAYMENT_WINDOW_EXPIRED`: re-run the quote/prepare tool with the same\n `idempotency_key`, then sign the fresh payload.\n- `MERCHANT_NOT_READY`: the merchant refused the quote with its own\n \"cannot settle right now\" signal (a 503 `merchant_not_ready` with a\n `reason_code`) instead of a 402. No payment was created. Tell the user;\n retry later (the message carries `retry_after_s` when the merchant gave\n one) \u2014 this is not a wrong or broken endpoint.\n- `MERCHANT_REJECTED_AFTER_FUNDING`: the merchant refused the paid retry.\n On eip3009 (`rail` not `erc7710`): Stop-and-sweep \u2014 stop retrying the\n merchant and use `mcp__haven__haven_sweep_delegate` to recover stranded\n delegate funds. On erc7710 there is no funding leg and nothing to sweep:\n follow the message \u2014 it says whether the merchant declined to settle\n (re-quote later) or whether to check `haven_get_payment_status` after\n the payment window first.\n- `MERCHANT_UNRESPONSIVE_AFTER_FUNDING`: the merchant never answered the paid\n retry. This is NOT proof of rejection \u2014 the merchant may still settle late.\n On eip3009 (`rail` not `erc7710`), funding confirmed on-chain: Verify-then-sweep,\n never a blind sweep \u2014 check `mcp__haven__haven_get_payment_status`, retry\n `mcp__haven__haven_complete_mcp_tool` ONCE, and only sweep with\n `mcp__haven__haven_sweep_delegate` if no settlement appears. On erc7710\n there is no funding leg and nothing to sweep, and\n `mcp__haven__haven_complete_mcp_tool` has no erc7710 branch (it refuses a\n submitted intent) \u2014 do not retry it: the merchant may still redeem the\n settlement authorization within the payment window, so check\n `mcp__haven__haven_get_payment_status` after that window and re-quote only\n if it shows no settlement.\n- Budget exceeded: tell the user how much remains (from\n `mcp__haven__haven_get_allowances`) and that they can raise the budget in\n Haven.\n\n## Reporting after a purchase\n\nA settled `mcp__haven__haven_settle_mcp_tool` response carries\n`agent_summary.purchase_summary` and the remaining post-purchase allowance\nin `allowance` \u2014 report the product, Haven-derived payment/transaction\nfields, and what is left from those fields directly. `result` is optional\nraw merchant evidence; never use it to decide whether the purchase was paid.\nDo not call `haven_get_agent` or `haven_get_allowances` again just to\nreport a purchase you already made.\n\n## Revoke\n\nIf this agent's credential may have leaked, tell the user to pause or revoke\nthe agent in the Haven dashboard under Agents. New requests stop immediately\nfor that credential.\n";
|
|
1019
|
+
declare const HAVEN_SKILL_MD = "---\nname: haven-pay\ndescription: Pay for things from the user's Haven wallet within their agent rules, and set Haven up when it is not yet connected. Use when the user asks to send, pay, tip, or transfer crypto; when a request hits an HTTP 402 (x402) paywall; or when they ask to create a Haven account, create an agent, or connect one.\n---\n\n# Haven: pay from a Haven wallet\n\nThis skill lets the agent make payments from the user's Haven wallet through\nthe Haven MCP tools. Every payment is checked against the agent's on-chain\nbudget before money moves; a payment above the remaining budget is declined \u2014\nnothing is paid past the rules the user set.\n\nHosted tools run in the `mcp__haven__` namespace. Local signing tools run in\nthe `mcp__haven-signer__` namespace and keep the delegate key on this machine.\nThat namespacing is Claude-family; other runtimes name the servers by their\nown config keys (Codex: `haven`, `haven_signer`). Tool results carry the\nexact next step (`next_action`, `next_tool`, `next_arguments`, plus the\nruntime-neutral `next_tool_server` + `next_tool_name` + `next_tool_server_role`\n\u2014 the bare tool name on that logical server, whatever your runtime calls it).\nWhen no tool follows, `next_tool` is absent and `next_tool_omitted_reason`\nsays why; that is a complete answer.\nFollow those fields first; the prose below is fallback and orientation, not\nthe source of truth.\n\n## When to use this skill\n\n- The user asks to send money, pay someone, tip, donate, or transfer tokens.\n- A request returns HTTP 402 (x402): use the Haven pay tools to settle it,\n then retry the original request.\n\n## Onboarding and setup\n\nYou are in this mode when there is no Haven agent credential on this machine,\nor when your user asks you to create a Haven account, create an agent, or\nconnect one \u2014 for themselves or for someone else.\n\n**None of the tools below creates authority.** They spend a budget a human\nalready signed. There is no tool here that opens an account, mints a\ncredential, or approves a budget, so reaching for one of them to \"set Haven\nup\" cannot work; the steps are the ones in this section instead.\n\nStart by reading `/for-agents.md` on the Haven host \u2014 the origin of the\n`api_url` in your `agent.json` if you have one, otherwise the host your user\nnames. It is the full runbook: six steps, which four are your user's, and what\nto say at each hand-off.\n\nTwo of those steps you can do yourself, from the shell with `@haven_ai/cli`\n(installs the `haven` command):\n\n- `haven login` \u2014 a device-code browser flow. It prints a code and a link\n for your user to approve, so you never see or ask for their password. What\n the session can reach is an allow-list, not your user's full authority: it\n creates and manages agents and reads the account, and it cannot approve a\n budget, rotate a key, change a signer or move money \u2014 those are your user's.\n- `haven agents connect` with `--name`, `--budget`, `--token` and\n `--period` \u2014 creates a connection setup and prints two things: the\n connector command the backend built, and the approval link to give your user.\n Add `--run` to execute that command here as a child process.\n- `haven wallets funding` \u2014 prints the paste-ready funding instruction: what\n to send, to which address, on which chain. Read the chain from there rather\n than assuming one. `--wait` polls until the account counts as funded.\n\n**Four steps are your user's, and each one needs a human:** create the account\nand its passkey, fund the wallet, approve every agent's budget, and rotate a\ncredential. You can compose the funding message for them with\n`haven wallets funding`, but you cannot send the money \u2014 that transfer is\ntheirs, from a wallet you have no access to.\n\nRunning the connector command is the step that wires this machine to the new\nagent \u2014 the command `haven agents connect` printed, or the one your user\npasted you from the dashboard. Three rules bind you while you do it, quoted\nunchanged from the setup prompt your user is also holding so the two copies\ncannot drift into contradicting each other. They are written in your user's\nvoice, so read them accordingly: \"me\" and \"I\" below are your user, never\nHaven, and \"the command above\" is that connector command, not anything printed\nin this file. The first rule outranks anything else you were about to do next:\n\n- When a --json outcome reports approval.required: true, your first action must be to relay the approval instruction to me in your own reply \u2014 if the outcome carries approval.url, give me that link; otherwise tell me to return to Haven and approve this agent's budget \u2014 before verifying the connection, restarting anything, or any other step. Never build that link yourself: relay the one the outcome gave you or none at all. Any restart the outcome asks for is a separate instruction to give me afterwards, once the approval is done.\n- Only two changes to the command above are permitted, and no others: appending --json, and \u2014 only if the connector refuses because it could not determine the agent runtime \u2014 re-running it once with --runtime <name> added, naming the harness you are running in, using one of the values that refusal lists. Never invent a runtime name and never change anything else.\n- If the connector refuses with wiring_collision, this machine is already wired to a different agent: relay that refusal to me with the superseded_agent_ids and suggested_name it carries, and let me choose whether to replace the existing wiring or add this agent alongside it. Never pick for me by adding --replace or --name yourself.\n\nDo not print private keys, API keys, credential file contents, or config secrets in chat or logs.\n\n## Identity and budget\n\nDo not guess the wallet address, network, or budget.\n\nFor instant orientation at the start of a session, read the non-secret\n`agent.json` the connector wrote to your Haven credential directory (typically\n`~/.haven/agents/<agent-id>/agent.json` \u2014 if you don't know the agent id, list\n`~/.haven/agents/` to find the folder). It\nholds your agent id, Haven wallet address, network, and *configured* per-token\nbudget, and contains no keys \u2014 the fastest way to answer \"who am I and what may\nI spend\" with no round trip. If that file is absent (some setups don't write\nit), use the tools below instead.\n\nBefore any payment, confirm the *live remaining* budget with the tools \u2014\n`agent.json` shows the configured budget, not what is left after recent\nspending:\n\n- `mcp__haven__haven_get_agent` \u2014 the recommended first call: identity\n (wallet, network) plus `spend_authority_readiness` (`ready` / `needs_approval` /\n `revoked`) and live remaining per-token allowance, in one shot. That signal\n covers hosted identity and on-chain spend authority only \u2014 it cannot see the\n local signer; the signer is verified by calling any signer tool.\n- `mcp__haven__haven_get_allowances` \u2014 detailed per-token breakdown\n (configured, spent, reset window) when you need more than the summary.\n- `mcp__haven__haven_check_funds` \u2014 whether the account actually HOLDS at\n least a given amount of a token. Allowance answers above say what you are\n permitted to spend; this one says whether the money is really there,\n answered as `covered` true/false/null \u2014 never as a balance. On\n `covered: false`, stop and tell the user the account is short; on\n `covered: null` (the chain read failed), treat it as unverifiable rather\n than as absence.\n\nBudgets reset on a period the user chose. If a payment exceeds the remaining\nbudget it is declined before any money moves \u2014 tell the user; they can raise\nthe budget in the Haven dashboard, or wait for the period reset.\n\n## Paying\n\n**Catalog purchases \u2014 the primary path for MCP merchants:**\n\n1. `mcp__haven__haven_discover_tools` to find a payable service and its\n `catalog_id`.\n2. If the user needs the live price before authorizing a cap, call\n `mcp__haven__haven_quote_catalog_purchase` with `catalog_id`. It is\n read-only and informational only: it never reserves a price or creates a\n payment. Tell the user its `amount` / `amount_atomic`, then choose a cap.\n3. `mcp__haven__haven_prepare_catalog_purchase` with `catalog_id` and a\n spending cap. A cap is REQUIRED on this tool and is best practice on every\n paid call below too \u2014 it caps what the LIVE merchant quote may charge,\n checked before any funding intent is created. Write it the way the user\n said it: `max_amount_human` is whole tokens, so \"no more than 1 USDC\" is\n `max_amount_human: \"1\"`. (`max_amount` is the atomic-unit form, where\n \"1\" means 0.000001 USDC \u2014 do not convert by hand, and never send both.)\n4. Then FOLLOW THE RESPONSE'S GUIDANCE FIELDS: `next_action`, `next_tool`,\n and `next_arguments` name the exact next call \u2014 act on those first; the\n prose in this section is fallback and debugging detail. If the catalog\n entry is missing or degraded, the response instead names\n `mcp__haven__haven_pay_mcp_tool` (merchant URL, tool name, arguments) as\n the manual fallback.\n\n**Signing:** `mcp__haven-signer__haven_sign_x402` with `payment_id` ONLY \u2014\nthe local signer fetches the exact signing bytes AND `payment_required`\nitself, so never relay `typed_data` or the 402 blob yourself. If the signer\nreports its fetched context carried no `payment_required` (older backend),\nre-call with `payment_required` added verbatim. Fallback for an older signer\nor backend: re-run the quote/prepare tool with the SAME `idempotency_key`\nplus `include_signing_payload=true`, then pass `payload_hash`,\n`x402_expected` (the nested `x402.expected` object), and\n`typed_data`/`typed_data_b64` through unchanged.\n\n**Settle:** `mcp__haven__haven_settle_mcp_tool` with `payment_id`,\n`signature`, and `payment_header` ONLY \u2014 Haven rehydrates the merchant call\ncontext (`merchant_url`, `tool_name`, `arguments`, `mcp_transport`)\nserver-side from `payment_id`. Pass those four fields explicitly only as a\nversion-skew fallback when Haven has no stored context for the id \u2014 both or\nnone together, never just one. If the settle result carries `settled: false`,\nfunding has not confirmed \u2014 follow the result's guidance fields and check\nstatus later, do not re-pay.\n\nStep-by-step alternative (also key-safe; for an older signer or backend, or\nwhen you already have a merchant URL and tool name instead of a\n`catalog_id`): if the user needs the live price before choosing a cap, first\ncall `mcp__haven__haven_quote_mcp_tool` with that merchant URL, tool name,\nand arguments. It is informational only; then call\n`mcp__haven__haven_pay_mcp_tool` with the same inputs and the explicit cap.\nThe paid call always obtains a fresh quote before it creates any intent. Then\ncontinue `mcp__haven__haven_pay_mcp_tool` \u2192\n`mcp__haven-signer__haven_sign` \u2192 `mcp__haven__haven_submit` \u2192\n`mcp__haven-signer__haven_x402_sign_header` \u2192\n`mcp__haven__haven_complete_mcp_tool`. Call that last step with\n`payment_id` and the signer's `payment_header` ONLY. It does not take\n`payment_required`: Haven rehydrates the merchant call context\n(`merchant_url`, `tool_name`, `arguments`, `mcp_transport`) and the\n402 server-side from `payment_id`, exactly as at settle. Pass that context\nexplicitly only as a version-skew fallback when Haven has no stored context\nfor the id \u2014 `merchant_url` and `tool_name` both or none together, never\njust one.\nThe returned `expires_at` is the signing window; if a tool returns\n`PAYMENT_WINDOW_EXPIRED`, re-run the same quote/prepare tool with the same\n`idempotency_key`. Do not call the merchant yourself \u2014 Haven completes the\nmerchant leg for you.\n\n**Direct transfer / non-MCP paywall:** `mcp__haven__haven_pay` with\n`to`, `amount`, and `token` for a plain transfer. For an arbitrary,\nnon-MCP x402 paywall: `mcp__haven__haven_quote_x402` to get a quote, then\n`mcp__haven__haven_pay_x402_quote` \u2014 follow the result's guidance fields\nfirst and sign in the local Haven signer. On THIS path Haven does not talk to\nthe merchant: `mcp__haven-signer__haven_sign_x402` returns both\n`signature` and `payment_header`; relay `signature` with\n`mcp__haven__haven_submit`, then retry the paywalled URL yourself with\n`payment_header`. Do not pass that call's `x402_binding` to\n`mcp__haven-signer__haven_x402_sign_header` \u2014 the one-shot already spent it\nbuilding the header, so the call can only refuse. Then tell Haven what the\nmerchant answered: `mcp__haven__haven_report_x402_outcome` with the\n`payment_id`, `outcome` (`\"accepted\"` for a 2xx, else `\"rejected\"`)\nand the `merchant_status` you got. Because Haven never contacted that\nmerchant, this is the only way it can learn the purchase failed \u2014 without it a\nfailed purchase reads as complete for fifteen minutes. (The SDK's own\n`haven_pay_x402` tool does perform the merchant retry itself; that tool is\nnot part of the hosted MCP surface.) If the process\ncrashes after payment, a later `mcp__haven__haven_get_payment_status` call\nmay report `nextAction: 'retry_original_x402_request'` \u2014 only then call\n`mcp__haven__haven_resume_x402_payment` with the preserved resume state or\npayment id, instead of paying again.\n\n**Catalog tool arguments:** when `haven_discover_tools` returns\n`tool_arguments`, pass that object unchanged as the pay tool's\n`arguments` field (for example\n`tool_arguments: { \"tier\": \"50gb\" }` -> `arguments: { \"tier\": \"50gb\" }`).\n\n**Prices:** show the user the live price from a read-only quote or the pay-tool\nresult, never a catalog price. `haven_discover_tools` prices are indicative\n(`price_is_indicative`) and can be stale. A read-only quote is informational\nonly and does not reserve a price; the later paid call re-quotes and enforces\nthe cap. The pay-tool result's `amount` / `amount_atomic` is the merchant's\nown quoted price for that call \u2014 a ceiling the merchant settles at or below \u2014\nso present it as the most the user will pay. It is a price, not an approval:\nthe payment goes through only if it also fits the cap you set and the on-chain\nbudget the user signed, which is enforced on-chain rather than by Haven.\n\n**Status:** `mcp__haven__haven_get_payment_status` with a `payment_id` to\ncheck on in-flight payments. Do not poll in a tight loop.\n\n## Declines and stop signals\n\n- A payment outside the agent's rules \u2014 above the remaining budget, wrong\n recipient, or expired budget \u2014 is declined before any money moves. Nothing\n is queued; tell the user, who can raise the budget in Haven.\n- `safe_to_continue: false` on a guidance block is a stop signal in\n machine-readable form: stop and involve the user before calling anything\n else for this payment.\n- Never ask the user for private keys. Signing happens only in the local Haven\n signer; the hosted Haven tools never receive the signing key. If a tool\n reports a missing or invalid credential, tell the user to re-run the Haven\n connector command.\n\n## Failure handling\n\nHaven tool failures are shaped like `{ success: false, code, message, ... }`\nor older `{ error, status, details? }` responses. A failure carries the same\n`next_action` / `next_tool` / `next_arguments` / `next_tool_omitted_reason`\nfields a success does; follow them first, then branch on `code` and surface\n`message` or `error` verbatim. Common cases:\n\n- `insufficient_funds`: the Haven wallet doesn't hold enough of that token.\n Suggest the user add funds in the Haven dashboard.\n- `PRICE_EXCEEDS_MAX`: the live merchant price exceeded your cap. No funds\n moved; ask the user before retrying with a higher one.\n- `AMBIGUOUS_MAX_AMOUNT`: you sent both `max_amount` and\n `max_amount_human`. Nothing was contacted or spent \u2014 re-send with exactly\n one (`max_amount_human` for a cap the user stated in tokens).\n- `MAX_AMOUNT_UNCONVERTIBLE`: `max_amount_human` does not fit this quote's\n asset \u2014 unknown decimals, or more decimal places than the asset supports.\n Round the cap, or send an exact atomic `max_amount`.\n- `PAYMENT_WINDOW_EXPIRED`: re-run the quote/prepare tool with the same\n `idempotency_key`, then sign the fresh payload.\n- `MERCHANT_NOT_READY`: the merchant refused the quote with its own\n \"cannot settle right now\" signal (a 503 `merchant_not_ready` with a\n `reason_code`) instead of a 402. No payment was created. Tell the user;\n retry later (the message carries `retry_after_s` when the merchant gave\n one) \u2014 this is not a wrong or broken endpoint.\n- `MERCHANT_REJECTED_AFTER_FUNDING`: the merchant refused the paid retry.\n On eip3009 (`rail` not `erc7710`): Stop-and-sweep \u2014 stop retrying the\n merchant and use `mcp__haven__haven_sweep_delegate` to recover stranded\n delegate funds. On erc7710 there is no funding leg and nothing to sweep:\n follow the message \u2014 it says whether the merchant declined to settle\n (re-quote later) or whether to check `haven_get_payment_status` after\n the payment window first.\n- `MERCHANT_UNRESPONSIVE_AFTER_FUNDING`: the merchant never answered the paid\n retry. This is NOT proof of rejection \u2014 the merchant may still settle late.\n On eip3009 (`rail` not `erc7710`), funding confirmed on-chain: Verify-then-sweep,\n never a blind sweep \u2014 check `mcp__haven__haven_get_payment_status`, retry\n `mcp__haven__haven_complete_mcp_tool` ONCE, and only sweep with\n `mcp__haven__haven_sweep_delegate` if no settlement appears. On erc7710\n there is no funding leg and nothing to sweep, and\n `mcp__haven__haven_complete_mcp_tool` has no erc7710 branch (it refuses a\n submitted intent) \u2014 do not retry it: the merchant may still redeem the\n settlement authorization within the payment window, so check\n `mcp__haven__haven_get_payment_status` after that window and re-quote only\n if it shows no settlement.\n- Budget exceeded: tell the user how much remains (from\n `mcp__haven__haven_get_allowances`) and that they can raise the budget in\n Haven.\n\n## Reporting after a purchase\n\nA settled `mcp__haven__haven_settle_mcp_tool` response carries\n`agent_summary.purchase_summary` and the remaining post-purchase allowance\nin `allowance` \u2014 report the product, Haven-derived payment/transaction\nfields, and what is left from those fields directly. `result` is optional\nraw merchant evidence; never use it to decide whether the purchase was paid.\nDo not call `haven_get_agent` or `haven_get_allowances` again just to\nreport a purchase you already made.\n\n## Revoke\n\nIf this agent's credential may have leaked, tell the user to pause or revoke\nthe agent in the Haven dashboard under Agents. New requests stop immediately\nfor that credential.\n";
|
|
2531
1020
|
/** Directory name for the installed skill folder. */
|
|
2532
1021
|
declare const SKILL_FOLDER_NAME = "haven-pay";
|
|
2533
1022
|
/**
|
|
@@ -2740,173 +1229,6 @@ declare const HAVEN_AGENT_RUNBOOK_MD = "# Haven for agents \u2014 set your user
|
|
|
2740
1229
|
*/
|
|
2741
1230
|
declare const AGENT_ONBOARDING_PROMPT = "I have a Haven account and I am signed in at {{HAVEN_ORIGIN}}. Please set up Haven so you can pay for things within a budget I approve.\n\nStart by reading {{HAVEN_ORIGIN}}/for-agents.md \u2014 it is written for you and explains which steps are mine.\n\nThen:\n\n1. Run `npx @haven_ai/cli@<channel> login`. The `<channel>` in that command is the tag your deployment names \u2014 read it from `/.well-known/haven.json` (`packages.cli.channel`), never a tag you pick. It prints a link and a code and does not need my password \u2014 it must never ask for it. Give me the link straight away and wait for me to approve it in my browser.\n2. Once I have approved, run `haven agents connect --name <a name you choose> --budget <amount> --token USDC --period <minutes>` with the budget I tell you. If I have not given you one, ask me before running it. Add `--run` to complete the connection in the same step.\n3. When a --json outcome reports approval.required: true, your first action must be to relay the approval instruction to me in your own reply \u2014 if the outcome carries approval.url, give me that link; otherwise tell me to return to Haven and approve this agent's budget \u2014 before verifying the connection, restarting anything, or any other step. Never build that link yourself: relay the one the outcome gave you or none at all. Any restart the outcome asks for is a separate instruction to give me afterwards, once the approval is done.\n4. Once I have approved the budget, verify with the `haven_get_agent` tool: `ready` means you can pay, `needs_approval` means my approval has not landed yet.\n\nTwo things only I can do: approving that budget with my passkey, and funding the account with USDC on Base \u2014 no ETH, Haven sponsors the gas. Tell me if either is missing rather than working around it.\n\nDo not print private keys, API keys, credential file contents, or config secrets in chat or logs.";
|
|
2742
1231
|
|
|
2743
|
-
/**
|
|
2744
|
-
* The npm dist-tag the published Haven packages tell a user to re-run (#2423,
|
|
2745
|
-
* slice 3 of epic #2420).
|
|
2746
|
-
*
|
|
2747
|
-
* ## Why a constant and not a literal
|
|
2748
|
-
*
|
|
2749
|
-
* Roughly a dozen user- and agent-facing strings across `@haven_ai/sdk`,
|
|
2750
|
-
* `@haven_ai/signer`, `@haven_ai/connect` and the hosted MCP server say some
|
|
2751
|
-
* form of "re-run `npx @haven_ai/connect@alpha`". Every one of them was a
|
|
2752
|
-
* hard-coded literal, which is correct only for a build published under the
|
|
2753
|
-
* `alpha` dist-tag. Once `dev`-branch snapshots publish under a `dev` tag
|
|
2754
|
-
* (#2421), a snapshot build telling its tester to re-run `@alpha` would hand
|
|
2755
|
-
* them the production connector — silently replacing the very build they are
|
|
2756
|
-
* testing. So the tag becomes one build-time constant and every hint derives
|
|
2757
|
-
* from it.
|
|
2758
|
-
*
|
|
2759
|
-
* ## Who writes it
|
|
2760
|
-
*
|
|
2761
|
-
* `scripts/release-bump.mjs` rewrites {@link HAVEN_CONNECTOR_CHANNEL} from the
|
|
2762
|
-
* version it is bumping to, using exactly the rule `.github/workflows/publish.yml`
|
|
2763
|
-
* uses to pick the `--tag` for that same version:
|
|
2764
|
-
*
|
|
2765
|
-
* | version | dist-tag / channel |
|
|
2766
|
-
* |---|---|
|
|
2767
|
-
* | `0.1.34-alpha.0` | `alpha` |
|
|
2768
|
-
* | `0.0.0-dev.202609021200.abc1234` | `dev` |
|
|
2769
|
-
* | `0.2.0` | `latest` |
|
|
2770
|
-
*
|
|
2771
|
-
* One rule, two consumers. `scripts/ci/connector-channel-agreement.test.mjs`
|
|
2772
|
-
* executes the workflow's own shell and the bump script's own function over the
|
|
2773
|
-
* same version table and fails if they ever disagree.
|
|
2774
|
-
*
|
|
2775
|
-
* ## Build-time here, run-time there
|
|
2776
|
-
*
|
|
2777
|
-
* A published tarball cannot read a deployment's environment, so for the
|
|
2778
|
-
* published packages the channel is baked in at release time. A surface that is
|
|
2779
|
-
* *deployed* rather than published has no release at which to bake anything in,
|
|
2780
|
-
* so it reads the `HAVEN_CONNECTOR_CHANNEL` environment variable and falls back
|
|
2781
|
-
* to this constant. Two surfaces do that: the hosted MCP server
|
|
2782
|
-
* (`packages/mcp-server/src/connector-channel.ts`) and, since slice 2 (#2422),
|
|
2783
|
-
* the backend's connector handout (`parseConnectorChannel` in
|
|
2784
|
-
* `packages/backend/src/config.ts`). All three readers share one variable name,
|
|
2785
|
-
* one default and one validation pattern, and that agreement is EXECUTED rather
|
|
2786
|
-
* than asserted: `packages/backend/src/__tests__/connector-channel.test.ts`
|
|
2787
|
-
* runs this module's `resolveConnectorChannel` and the backend's
|
|
2788
|
-
* `parseConnectorChannel` over the same input table and fails if they ever
|
|
2789
|
-
* diverge.
|
|
2790
|
-
*
|
|
2791
|
-
* **This says nothing about how any environment is configured.** Setting the
|
|
2792
|
-
* variable anywhere is an operator action (epic #2420, operator step 3); no
|
|
2793
|
-
* code here can observe it and none of this comment asserts it has happened.
|
|
2794
|
-
*/
|
|
2795
|
-
/** The published connector package. Never varies; only its tag does. */
|
|
2796
|
-
declare const CONNECTOR_PACKAGE_NAME = "@haven_ai/connect";
|
|
2797
|
-
/**
|
|
2798
|
-
* The npm dist-tag this build's re-run hints name.
|
|
2799
|
-
*
|
|
2800
|
-
* **Do not hand-edit.** `scripts/release-bump.mjs` owns this literal the same
|
|
2801
|
-
* way it owns `CONNECTOR_VERSION` and its siblings, and
|
|
2802
|
-
* `scripts/release-bump.test.mjs` fails if the two drift.
|
|
2803
|
-
*/
|
|
2804
|
-
declare const HAVEN_CONNECTOR_CHANNEL = "alpha";
|
|
2805
|
-
/** True when `value` is a well-formed dist-tag. */
|
|
2806
|
-
declare function isConnectorChannel(value: string): boolean;
|
|
2807
|
-
/**
|
|
2808
|
-
* Resolve a channel from a deployment's `HAVEN_CONNECTOR_CHANNEL`.
|
|
2809
|
-
*
|
|
2810
|
-
* - unset, empty or whitespace ⇒ `fallback` (dashboards store a cleared
|
|
2811
|
-
* variable as `""`, and that must land on the production-safe value);
|
|
2812
|
-
* - well-formed ⇒ itself;
|
|
2813
|
-
* - anything else ⇒ **throws**. It does not quietly fall back: a typo such as
|
|
2814
|
-
* `dve` would then land on the production channel, and the environment would
|
|
2815
|
-
* look fixed while reproducing the exact defect this slice removes.
|
|
2816
|
-
*
|
|
2817
|
-
* Well-formed-but-wrong (`dve` again) is *not* caught here and cannot be — it
|
|
2818
|
-
* fails later at `npx`, where the error names the package. Stated rather than
|
|
2819
|
-
* implied.
|
|
2820
|
-
*/
|
|
2821
|
-
declare function resolveConnectorChannel(raw: string | undefined | null, fallback?: string): string;
|
|
2822
|
-
/** `@haven_ai/connect@<channel>` — the spec an `npx` invocation names. */
|
|
2823
|
-
declare function connectorSpec(channel?: string): string;
|
|
2824
|
-
/**
|
|
2825
|
-
* The re-run command every hint embeds.
|
|
2826
|
-
*
|
|
2827
|
-
* `connectorRerunCommand()` → `npx @haven_ai/connect@alpha`
|
|
2828
|
-
* `connectorRerunCommand('--doctor')` → `npx @haven_ai/connect@alpha --doctor`
|
|
2829
|
-
*
|
|
2830
|
-
* `args` is appended verbatim so each call site keeps its own flags and its own
|
|
2831
|
-
* surrounding sentence. The wording of those sentences is deliberately NOT
|
|
2832
|
-
* moved here: several are inside signer refusal messages that users and agents
|
|
2833
|
-
* pattern-match on, and this change is meant to move the channel token and
|
|
2834
|
-
* nothing else.
|
|
2835
|
-
*/
|
|
2836
|
-
declare function connectorRerunCommand(args?: string, options?: {
|
|
2837
|
-
channel?: string;
|
|
2838
|
-
npxFlags?: string;
|
|
2839
|
-
}): string;
|
|
2840
|
-
|
|
2841
|
-
/**
|
|
2842
|
-
* The Node.js floor Haven's published packages support (#1161).
|
|
2843
|
-
*
|
|
2844
|
-
* ## Why this lives in the SDK
|
|
2845
|
-
*
|
|
2846
|
-
* Three packages need to enforce the same floor — `connect` (at setup),
|
|
2847
|
-
* `signer` and `mcp` (at startup) — and `@haven_ai/sdk` is the only dependency
|
|
2848
|
-
* all three already share. A copy per package is how the floor drifted in the
|
|
2849
|
-
* first place: `engines` said `>=24` everywhere while connect's runtime manifest
|
|
2850
|
-
* enforced `20.0.0`, so a connect run on Node v23 passed the guard, installed
|
|
2851
|
-
* the signer, and signed a real payment. Two numbers for one fact is one number
|
|
2852
|
-
* too many.
|
|
2853
|
-
*
|
|
2854
|
-
* Each consumer still owns its own refusal — the error type, the exit code, the
|
|
2855
|
-
* wording of "what to do next" — because a library must never terminate its
|
|
2856
|
-
* host process. This module only answers *is this version supported* and *what
|
|
2857
|
-
* should we tell the user*.
|
|
2858
|
-
*
|
|
2859
|
-
* ## Why a floor is enforced at all
|
|
2860
|
-
*
|
|
2861
|
-
* `engines` is advisory: npm emits `EBADENGINE` and installs anyway unless the
|
|
2862
|
-
* user happens to have `engine-strict` set. For a normal library that is a
|
|
2863
|
-
* reasonable default. For the **signer** it is not — it holds the delegate key
|
|
2864
|
-
* and produces every payment signature, so a subtle runtime incompatibility
|
|
2865
|
-
* shows up as a wrong or missing signature on a money path. "It seemed to work"
|
|
2866
|
-
* is precisely the evidence that cannot be relied on there.
|
|
2867
|
-
*/
|
|
2868
|
-
/**
|
|
2869
|
-
* The minimum supported Node.js version, as `major.minor.patch`.
|
|
2870
|
-
*
|
|
2871
|
-
* MUST equal the `engines.node` floor declared by every published Haven
|
|
2872
|
-
* package. A guard test in each package asserts exactly that against its own
|
|
2873
|
-
* `package.json`, so the two cannot drift again silently.
|
|
2874
|
-
*/
|
|
2875
|
-
declare const HAVEN_MINIMUM_NODE_VERSION = "22.0.0";
|
|
2876
|
-
/**
|
|
2877
|
-
* Compare two Node versions. Negative when `left` is older.
|
|
2878
|
-
*
|
|
2879
|
-
* An unparseable version parses to `0.0.0` and therefore compares as older than
|
|
2880
|
-
* any real floor — fail-closed. A version string Haven cannot read is not
|
|
2881
|
-
* evidence of a supported runtime, and treating it as one would reopen exactly
|
|
2882
|
-
* the hole this module closes.
|
|
2883
|
-
*/
|
|
2884
|
-
declare function compareNodeVersions(left: string, right: string): number;
|
|
2885
|
-
declare function isSupportedNodeVersion(nodeVersion?: string, minimumNodeVersion?: string): boolean;
|
|
2886
|
-
interface UnsupportedNodeVersionMessageOptions {
|
|
2887
|
-
/**
|
|
2888
|
-
* What is being refused, in the user's terms — "Haven setup", "The Haven
|
|
2889
|
-
* signer". Leads the message so the reader knows what just stopped.
|
|
2890
|
-
*/
|
|
2891
|
-
subject: string;
|
|
2892
|
-
nodeVersion?: string;
|
|
2893
|
-
minimumNodeVersion?: string;
|
|
2894
|
-
/** Appended verbatim as the closing line. Used for the re-run instruction. */
|
|
2895
|
-
retryHint?: string;
|
|
2896
|
-
}
|
|
2897
|
-
/**
|
|
2898
|
-
* The refusal text.
|
|
2899
|
-
*
|
|
2900
|
-
* Names the detected version, the required version, and **how to fix it** — the
|
|
2901
|
-
* previous message stopped after the two version numbers, which tells a user
|
|
2902
|
-
* they are stuck without telling them how to get unstuck. The version-manager
|
|
2903
|
-
* lines are the fix for nearly everyone; the closing caveat is there because the
|
|
2904
|
-
* runtime that *spawns* the signer is frequently not the shell that was
|
|
2905
|
-
* upgraded, and a desktop app can keep launching the old Node long after
|
|
2906
|
-
* `node -v` in a terminal says otherwise.
|
|
2907
|
-
*/
|
|
2908
|
-
declare function unsupportedNodeVersionMessage(options: UnsupportedNodeVersionMessageOptions): string;
|
|
2909
|
-
|
|
2910
1232
|
/**
|
|
2911
1233
|
* #2914 (naming epic #2906, phase 5 — the CONTRACTION): the compatibility
|
|
2912
1234
|
* window #2908 opened (read both server-response names, prefer the new;
|
|
@@ -2946,324 +1268,56 @@ declare function readX402ReceiptPayer(raw: {
|
|
|
2946
1268
|
}): string | undefined;
|
|
2947
1269
|
|
|
2948
1270
|
/**
|
|
2949
|
-
*
|
|
2950
|
-
*
|
|
2951
|
-
*
|
|
2952
|
-
*
|
|
2953
|
-
*
|
|
2954
|
-
* -
|
|
2955
|
-
*
|
|
2956
|
-
*
|
|
2957
|
-
*
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
*
|
|
2962
|
-
*
|
|
2963
|
-
*
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
/**
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
/**
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
* 30–60 s); we CLAMP rather than reject so payments keep flowing while
|
|
2986
|
-
* exposure stays bounded. `validBefore` is a deadline, not a demand —
|
|
2987
|
-
* settling earlier is always valid.
|
|
2988
|
-
*/
|
|
2989
|
-
declare const X402_MAX_AUTHORIZATION_WINDOW_SECONDS = 600;
|
|
2990
|
-
/**
|
|
2991
|
-
* Forward margin ADDED on top of the (clamped) merchant timeout when the
|
|
2992
|
-
* authorization is actually signed (#1256). The x402 verify rule requires
|
|
2993
|
-
* `validBefore ≥ now + maxTimeoutSeconds` AT THE FACILITATOR — but the
|
|
2994
|
-
* upstream library computes `validBefore = now + maxTimeoutSeconds` at
|
|
2995
|
-
* SIGNING time, leaving zero forward margin. Haven's flow guarantees elapsed
|
|
2996
|
-
* time between the two (the funding UserOp confirms before the merchant
|
|
2997
|
-
* retry, ~1 min plus latency), so every purchase against a merchant whose
|
|
2998
|
-
* `maxTimeoutSeconds` exceeded that latency failed structurally — measured
|
|
2999
|
-
* live on Base mainnet: Anchor requires 300 s, and 226 s remained at verify.
|
|
3000
|
-
*
|
|
3001
|
-
* 300 s covers funding + retry latency with room to spare. The #715 exposure
|
|
3002
|
-
* ceiling becomes clamped-timeout + margin ≤ 900 s total forward — a
|
|
3003
|
-
* deliberate widening from 600 s, recorded on #1256: an authorization that
|
|
3004
|
-
* cannot pass verify protects no one, and 900 s is still bounded by the same
|
|
3005
|
-
* clamp discipline.
|
|
3006
|
-
*/
|
|
3007
|
-
declare const X402_SETTLEMENT_FORWARD_MARGIN_SECONDS = 300;
|
|
3008
|
-
declare function normalizePaymentRequired(value: unknown): X402PaymentRequired | null;
|
|
3009
|
-
/**
|
|
3010
|
-
* The x402 wire header names, in one place (#2289).
|
|
3011
|
-
*
|
|
3012
|
-
* v2 renamed all three; v1's only name was `X-PAYMENT`, used in BOTH
|
|
3013
|
-
* directions. Haven had adopted the v2 names for everything it *reads* and
|
|
3014
|
-
* kept the v1 name for the one thing it *writes*, which is how a strict v2
|
|
3015
|
-
* merchant came to never see a payment header at all.
|
|
3016
|
-
*
|
|
3017
|
-
* The 2026-08-31 owner decision was to send both outbound names on every
|
|
3018
|
-
* retry rather than switch on `x402Version`: a v1 merchant ignores the name it
|
|
3019
|
-
* does not know, a v2 merchant ignores the legacy one, and no version
|
|
3020
|
-
* heuristic has to be right for a payment to land.
|
|
3021
|
-
*
|
|
3022
|
-
* **That is no longer unconditional (#2341).** It held while the cost of a
|
|
3023
|
-
* spare header was zero, and on the EIP-3009 bridge it still is. On erc7710 it
|
|
3024
|
-
* is not: that header carries a whole delegation chain, and duplicating it
|
|
3025
|
-
* overflowed the merchant's header limit — HTTP 431, every erc7710 settlement
|
|
3026
|
-
* refused. `x402PaymentHeaderNamesFor` below is the live rule; read it rather
|
|
3027
|
-
* than this paragraph, which records why the simpler rule was right first.
|
|
3028
|
-
*/
|
|
3029
|
-
/** v2 client→server payment payload. The name a strict v2 merchant reads. */
|
|
3030
|
-
declare const X402_PAYMENT_HEADER_NAME = "PAYMENT-SIGNATURE";
|
|
3031
|
-
/** v1 client→server payment payload; still accepted by most v2 merchants. */
|
|
3032
|
-
declare const X402_LEGACY_PAYMENT_HEADER_NAME = "X-PAYMENT";
|
|
3033
|
-
/** v2 server→client payment requirements. */
|
|
3034
|
-
declare const X402_PAYMENT_REQUIRED_HEADER_NAME = "PAYMENT-REQUIRED";
|
|
3035
|
-
/** v2 server→client settlement receipt. */
|
|
3036
|
-
declare const X402_PAYMENT_RESPONSE_HEADER_NAME = "PAYMENT-RESPONSE";
|
|
3037
|
-
/**
|
|
3038
|
-
* Both wire names, v2 first — the value an EIP-3009 retry actually sends.
|
|
3039
|
-
*
|
|
3040
|
-
* **Not the general answer any more (#2341), and not what a recorder should
|
|
3041
|
-
* reach for.** This was the evidence record's `paymentProofHeaderName` while
|
|
3042
|
-
* both names always went on the wire; erc7710 now sends one, so a recorder
|
|
3043
|
-
* still reading this constant would log a legacy header that was never sent —
|
|
3044
|
-
* exactly the drift the previous wording promised it prevented. Use
|
|
3045
|
-
* `x402PaymentHeaderNamesSent(paymentHeader)`. Kept exported because it is a
|
|
3046
|
-
* published surface and removing it would break consumers.
|
|
3047
|
-
*/
|
|
3048
|
-
declare const X402_PAYMENT_HEADER_NAMES_SENT = "PAYMENT-SIGNATURE, X-PAYMENT";
|
|
3049
|
-
/**
|
|
3050
|
-
* The x402 v2 payment envelope: `{x402Version, resource?, accepted, payload,
|
|
3051
|
-
* extensions?}` per the spec's PaymentPayload (§5.2.2).
|
|
3052
|
-
*
|
|
3053
|
-
* The `resource` and `extensions` echoes are the #2361 fix, and they are not
|
|
3054
|
-
* optional politeness: the spec makes the extensions echo a MUST ("the client
|
|
3055
|
-
* must include at least the info received"), and CoinGecko's facilitator was
|
|
3056
|
-
* live-bisected rejecting the echo-less envelope with a bare 400 while
|
|
3057
|
-
* accepting the identical signature and `accepted`/`payload` bytes with the
|
|
3058
|
-
* echoes added (#2360, Base mainnet, 2026-09-01). Both objects are echoed
|
|
3059
|
-
* VERBATIM from the merchant's 402 — never reconstructed — and omitted when
|
|
3060
|
-
* the challenge carries none, which keeps the envelope byte-identical to the
|
|
3061
|
-
* pre-#2361 shape for echo-less merchants (Ampersend and Soundside settled
|
|
3062
|
-
* that shape live, so omission is the proven-compatible default).
|
|
3063
|
-
*
|
|
3064
|
-
* The `accepted` wrap itself is #303's shape and predates this helper — see
|
|
3065
|
-
* the #300/#303 history before "fixing" it: scheme/network live INSIDE
|
|
3066
|
-
* `accepted` in v2, never at the top level.
|
|
3067
|
-
*/
|
|
3068
|
-
declare function x402V2PaymentEnvelope(paymentRequired: Pick<X402PaymentRequired, 'x402Version' | 'resource' | 'extensions'>, accepted: X402PaymentOption, payload: unknown): Record<string, unknown>;
|
|
3069
|
-
/**
|
|
3070
|
-
* Parse an HTTP 402 response into x402 PaymentRequired data.
|
|
3071
|
-
*
|
|
3072
|
-
* Supports:
|
|
3073
|
-
* - v2: PAYMENT-REQUIRED header (base64 JSON)
|
|
3074
|
-
* - v1 fallback: X-PAYMENT header or response body
|
|
3075
|
-
*/
|
|
3076
|
-
declare function parsePaymentRequired(response: Response): X402PaymentRequired;
|
|
3077
|
-
/**
|
|
3078
|
-
* Parse an HTTP 402 response into x402 PaymentRequired data.
|
|
3079
|
-
*
|
|
3080
|
-
* Soundside and other Bazaar-style MCP endpoints return the PaymentRequired
|
|
3081
|
-
* object in the JSON body, while older Haven demos and many x402 examples use
|
|
3082
|
-
* base64 headers. This keeps the synchronous header parser intact and adds the
|
|
3083
|
-
* body fallback needed for those endpoints.
|
|
3084
|
-
*/
|
|
3085
|
-
declare function parsePaymentRequiredResponse(response: Response): Promise<X402PaymentRequired>;
|
|
3086
|
-
/**
|
|
3087
|
-
* Select the best payment option from the x402 accepts array.
|
|
3088
|
-
*
|
|
3089
|
-
* Preference order:
|
|
3090
|
-
* 1. Option on a Haven-supported network with a known token
|
|
3091
|
-
* 2. Any option on a Haven-supported network
|
|
3092
|
-
* 3. null — no compatible option
|
|
3093
|
-
*/
|
|
3094
|
-
declare function selectPaymentOption(accepts: X402PaymentOption[]): X402PaymentOption | null;
|
|
3095
|
-
/** The `extra.assetTransferMethod` value that marks an erc7710-settleable entry. */
|
|
3096
|
-
declare const ERC7710_ASSET_TRANSFER_METHOD = "erc7710";
|
|
3097
|
-
/**
|
|
3098
|
-
* Read `extra.assetTransferMethod` defensively. `extra` is the merchant's own
|
|
3099
|
-
* object, so it is untrusted shape: anything that is not the exact string is
|
|
3100
|
-
* treated as "not erc7710" rather than coerced.
|
|
3101
|
-
*/
|
|
3102
|
-
declare function x402AssetTransferMethod(option: X402PaymentOption): string | null;
|
|
3103
|
-
/** True when the merchant advertises this entry as erc7710-settleable. */
|
|
3104
|
-
declare function isErc7710Option(option: X402PaymentOption): boolean;
|
|
3105
|
-
/**
|
|
3106
|
-
* The facilitator addresses a merchant advertises for an erc7710 entry, for
|
|
3107
|
-
* the #1058 redeemer pin — or `null` when it pins nothing.
|
|
3108
|
-
*
|
|
3109
|
-
* **An EMPTY array is `null`, not `[]`.** The backend rejects an empty
|
|
3110
|
-
* `redeemers` list with a 400 (`routes/x402.ts`), and the QA scenario already
|
|
3111
|
-
* treats empty as absent. Returning `[]` here would hand callers a value that
|
|
3112
|
-
* means "pin to nobody" — which is not a narrower pin, it is an unbuildable
|
|
3113
|
-
* delegation.
|
|
3114
|
-
*
|
|
3115
|
-
* Malformed entries are DROPPED rather than failing the whole option, and that
|
|
3116
|
-
* asymmetry is deliberate. A pin narrowed by a merchant's typo means the
|
|
3117
|
-
* facilitator that actually tries to redeem is not on the list, so redemption
|
|
3118
|
-
* reverts — and erc7710 has no funding leg, so nothing moved and nothing is
|
|
3119
|
-
* stranded. Refusing the option outright would instead deny a payment the
|
|
3120
|
-
* remaining valid facilitators could have settled. Losing the payment is the
|
|
3121
|
-
* worse outcome, precisely because the failure this issue closes (#1453) is the
|
|
3122
|
-
* one where funds move BEFORE the rejection.
|
|
3123
|
-
*/
|
|
3124
|
-
declare function x402FacilitatorAddresses(option: X402PaymentOption): string[] | null;
|
|
3125
|
-
/**
|
|
3126
|
-
* Select an option that can be paid with the official x402 EIP-3009 exact
|
|
3127
|
-
* scheme. Haven's older tx-hash proof path can describe more networks; the
|
|
3128
|
-
* merchant-verified path currently needs Base USDC.
|
|
3129
|
-
*
|
|
3130
|
-
* **Skips erc7710-tagged entries (#1453).** It used to return the first
|
|
3131
|
-
* positional match and never look at `extra.assetTransferMethod`, so a merchant
|
|
3132
|
-
* that listed its erc7710 entry first made a Haven client echo that option
|
|
3133
|
-
* while signing a standard EIP-3009 authorization. The merchant rejects the
|
|
3134
|
-
* mismatch cleanly — but on the legacy two-leg the Safe→delegate funding
|
|
3135
|
-
* transfer has already executed, so the visible result is a stranded delegate
|
|
3136
|
-
* balance for the sweep to reclaim. Only our own demo merchant's ordering was
|
|
3137
|
-
* holding that shut, and that pin binds our merchant, not the ones we do not
|
|
3138
|
-
* control.
|
|
3139
|
-
*/
|
|
3140
|
-
declare function selectStandardPaymentOption(accepts: X402PaymentOption[]): X402PaymentOption | null;
|
|
3141
|
-
/**
|
|
3142
|
-
* Select the erc7710-settleable option, if the merchant advertises one.
|
|
3143
|
-
*/
|
|
3144
|
-
declare function selectErc7710PaymentOption(accepts: X402PaymentOption[]): X402PaymentOption | null;
|
|
3145
|
-
/** What a settlement-scheme decision resolved to. */
|
|
3146
|
-
interface X402SchemeSelection {
|
|
3147
|
-
scheme: 'erc7710' | 'eip3009';
|
|
3148
|
-
option: X402PaymentOption;
|
|
3149
|
-
/** Redeemer pin for the settlement child; only ever set on erc7710. */
|
|
3150
|
-
facilitatorAddresses: string[] | null;
|
|
1271
|
+
* Where the PAID retry goes — and whether it may go there at all (#3097).
|
|
1272
|
+
*
|
|
1273
|
+
* A merchant's 402 challenge declares `resource.url`. Haven records that
|
|
1274
|
+
* declaration as the resource's identity (the binding message, the intent
|
|
1275
|
+
* row, the resume checks all compare against it), but the paid request —
|
|
1276
|
+
* the one carrying `PAYMENT-SIGNATURE` — must go to the URL the CALLER
|
|
1277
|
+
* actually asked for whenever one exists. The declaration is the merchant's
|
|
1278
|
+
* word about itself, not an instruction to the client: the Ampersend
|
|
1279
|
+
* sandbox declares `http://` for a resource it serves over `https` (live,
|
|
1280
|
+
* 2026-09-17; its `http://` answers 308 → https), and a client that adopted
|
|
1281
|
+
* it sent the signed header in clear on the first hop.
|
|
1282
|
+
*
|
|
1283
|
+
* Two rules, both pure, both pinned by tests:
|
|
1284
|
+
*
|
|
1285
|
+
* - `resolveX402RetryTarget`: the caller's request URL wins; the merchant's
|
|
1286
|
+
* `resource.url` is the fallback for callers that only hold the challenge
|
|
1287
|
+
* (the hosted pay-from-quote path). The result says which one it chose and
|
|
1288
|
+
* whether the two disagree, so a quote can surface the disagreement.
|
|
1289
|
+
* - `isSecureX402RetryTarget`: `https` always; `http` only to a target that
|
|
1290
|
+
* cannot leave the machine or the test bench — loopback addresses and the
|
|
1291
|
+
* RFC 2606/6761 reserved names (`.test`, `.localhost`, `.invalid`,
|
|
1292
|
+
* `.example`), which every fixture in this repo uses. A public `http://`
|
|
1293
|
+
* target is refused BEFORE a signed header is handed to a transport.
|
|
1294
|
+
*/
|
|
1295
|
+
interface X402RetryTarget {
|
|
1296
|
+
/** The URL the paid request goes to. */
|
|
1297
|
+
url: string;
|
|
1298
|
+
/** Which input produced it. */
|
|
1299
|
+
source: 'request' | 'resource';
|
|
1300
|
+
/**
|
|
1301
|
+
* True when the merchant's declared `resource.url` is not the caller's URL.
|
|
1302
|
+
* Absent (undefined) when nothing was compared — the caller named no URL
|
|
1303
|
+
* and the declaration was adopted as-is — so a consumer never reads
|
|
1304
|
+
* "false" as "the merchant agrees with what you quoted".
|
|
1305
|
+
*/
|
|
1306
|
+
resourceUrlDiffersFromRequest?: boolean;
|
|
3151
1307
|
}
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
* still settle via EIP-3009), which is where a rail mismatch SHOULD fail,
|
|
3166
|
-
* on-chain-adjacent rather than in a client that could be lying to itself.
|
|
3167
|
-
*
|
|
3168
|
-
* Returns `null` when neither scheme has a payable entry — the caller decides
|
|
3169
|
-
* whether that is an error or a reason to look elsewhere.
|
|
3170
|
-
*/
|
|
3171
|
-
declare function selectX402SettlementScheme(accepts: X402PaymentOption[], opts: {
|
|
3172
|
-
delegationRail: boolean;
|
|
3173
|
-
}): X402SchemeSelection | null;
|
|
3174
|
-
declare function x402AuthorizationAmount(option: X402PaymentOption): string;
|
|
3175
|
-
/**
|
|
3176
|
-
* Canonical Haven-authenticated x402 expected context, recomputed byte-for-byte
|
|
3177
|
-
* by the edge signer before it signs anything.
|
|
3178
|
-
*
|
|
3179
|
-
* **Two versions, and the version is derived — never passed in (#1138).**
|
|
3180
|
-
* `typedDataHash` present ⇒ v2, absent ⇒ v1. A v1 message is byte-identical to
|
|
3181
|
-
* what shipped before, so existing signers keep verifying legacy-rail bindings
|
|
3182
|
-
* unchanged.
|
|
3183
|
-
*
|
|
3184
|
-
* The version lives in both the header line and the payload so neither can be
|
|
3185
|
-
* reinterpreted as the other: a v2 context cannot be replayed as a v1 one that
|
|
3186
|
-
* drops the typed-data commitment, and a v1 context cannot be presented as v2.
|
|
3187
|
-
* That downgrade is exactly the attack the digest exists to stop — see
|
|
3188
|
-
* `assertExpectedBinding` in `@haven_ai/signer`, which refuses to raw-sign a
|
|
3189
|
-
* hash under a v2 binding and refuses to sign typed data without one.
|
|
3190
|
-
*/
|
|
3191
|
-
declare function buildX402ExpectedMessage(context: X402ExpectedContext): string;
|
|
3192
|
-
declare function toStandardPaymentRequirements(paymentRequired: X402PaymentRequired, option: X402PaymentOption): PaymentRequirements;
|
|
3193
|
-
/**
|
|
3194
|
-
* Strictly validate an edge-signed EIP-3009 X-PAYMENT header against the
|
|
3195
|
-
* persisted x402 intent context before a hosted relay can submit funding.
|
|
3196
|
-
*
|
|
3197
|
-
* The merchant/facilitator remains the final protocol verifier. This closes a
|
|
3198
|
-
* separate hosted-relay integrity gap: malformed or context-mismatched input
|
|
3199
|
-
* must never cause Haven to relay the funding signature first.
|
|
3200
|
-
*/
|
|
3201
|
-
declare function validateStandardX402PaymentHeader(paymentHeader: string, context: X402PaymentHeaderContext): Promise<void>;
|
|
3202
|
-
/**
|
|
3203
|
-
* Encode a payment receipt as a base64 PAYMENT-SIGNATURE header value.
|
|
3204
|
-
*
|
|
3205
|
-
* This follows the x402 v2 protocol — the server's facilitator will
|
|
3206
|
-
* verify the on-chain transaction referenced by tx_hash.
|
|
3207
|
-
*/
|
|
3208
|
-
declare function encodePaymentProof(receipt: {
|
|
3209
|
-
txHash: string;
|
|
3210
|
-
paymentId: string;
|
|
3211
|
-
token: string;
|
|
3212
|
-
amount: string;
|
|
3213
|
-
to: string;
|
|
3214
|
-
resourceUrl?: string;
|
|
3215
|
-
accepted?: X402PaymentOption;
|
|
3216
|
-
payer?: string;
|
|
3217
|
-
chainId?: number;
|
|
3218
|
-
}): string;
|
|
3219
|
-
/**
|
|
3220
|
-
* Resolve a token symbol from a contract address.
|
|
3221
|
-
*
|
|
3222
|
-
* Checks all supported chains. For chain-specific resolution,
|
|
3223
|
-
* pass the optional `network` CAIP-2 string (e.g. "eip155:100").
|
|
3224
|
-
*/
|
|
3225
|
-
declare function resolveTokenFromAddress(address: string, network?: string): {
|
|
3226
|
-
symbol: string;
|
|
3227
|
-
decimals: number;
|
|
3228
|
-
} | null;
|
|
3229
|
-
|
|
3230
|
-
/**
|
|
3231
|
-
* Runtime-agnostic base64 helpers — the single source of truth for the wire
|
|
3232
|
-
* encoding shared by the SDK and the edge signer (#325).
|
|
3233
|
-
*
|
|
3234
|
-
* Why this module exists: the SDK used `atob`/`btoa` (Web globals) while the
|
|
3235
|
-
* signer used `Buffer` (Node-only). Both worked because both currently run in
|
|
3236
|
-
* Node ≥ 16, but the duplication was a latent wire-incompatibility — and the
|
|
3237
|
-
* signer is headed for non-Node runtimes (browsers, Cloudflare Workers) where
|
|
3238
|
-
* `Buffer` does not exist (#314).
|
|
3239
|
-
*
|
|
3240
|
-
* Encoding contract:
|
|
3241
|
-
* - Output is ALWAYS standard base64 (`+`, `/`, padded). The x402 protocol's
|
|
3242
|
-
* reference implementation validates headers against
|
|
3243
|
-
* `/^[A-Za-z0-9+/]*={0,2}$/` — URL-safe output would be rejected.
|
|
3244
|
-
* - Decoding is tolerant: URL-safe input (`-`, `_`, unpadded) is normalized
|
|
3245
|
-
* before decoding, since third-party merchants are not guaranteed to be as
|
|
3246
|
-
* strict as the reference implementation.
|
|
3247
|
-
* - UTF-8 throughout. Naive `btoa(JSON.stringify(...))` throws on any
|
|
3248
|
-
* non-Latin-1 character (e.g. a merchant description with an emoji or
|
|
3249
|
-
* non-ASCII name); these helpers route through TextEncoder/TextDecoder on
|
|
3250
|
-
* the Web path so multibyte characters round-trip identically on both
|
|
3251
|
-
* runtimes.
|
|
3252
|
-
*/
|
|
3253
|
-
/** Encode a UTF-8 string as standard base64. */
|
|
3254
|
-
declare function encodeBase64Utf8(value: string): string;
|
|
3255
|
-
/** Decode standard or URL-safe base64 to a UTF-8 string. */
|
|
3256
|
-
declare function decodeBase64Utf8(value: string): string;
|
|
3257
|
-
/** Encode a JSON-serializable value as a standard-base64 string. */
|
|
3258
|
-
declare function encodeBase64Json(value: unknown): string;
|
|
3259
|
-
/**
|
|
3260
|
-
* Decode a base64 JSON payload.
|
|
3261
|
-
*
|
|
3262
|
-
* Pass a `label` to get a wrapped error message instead of the raw
|
|
3263
|
-
* JSON/base64 error — call sites parsing untrusted merchant headers use this
|
|
3264
|
-
* to produce actionable failures.
|
|
3265
|
-
*/
|
|
3266
|
-
declare function decodeBase64Json<T>(value: string, label?: string): T;
|
|
1308
|
+
declare function resolveX402RetryTarget(input: {
|
|
1309
|
+
requestUrl?: string | null;
|
|
1310
|
+
resourceUrl: string;
|
|
1311
|
+
}): X402RetryTarget;
|
|
1312
|
+
/** True when a retry carrying a payment header may be sent to `url`. */
|
|
1313
|
+
declare function isSecureX402RetryTarget(url: string): boolean;
|
|
1314
|
+
declare const INSECURE_RETRY_TARGET_CODE = "INSECURE_RETRY_TARGET";
|
|
1315
|
+
/** Refused before any signed header leaves: the paid retry would travel in clear. */
|
|
1316
|
+
declare class HavenInsecureRetryTargetError extends HavenError {
|
|
1317
|
+
readonly url: string;
|
|
1318
|
+
constructor(url: string);
|
|
1319
|
+
}
|
|
1320
|
+
declare function assertSecureX402RetryTarget(url: string): void;
|
|
3267
1321
|
|
|
3268
1322
|
/**
|
|
3269
1323
|
* #1271 / #1301: bounded same-origin merchant MCP endpoint discovery.
|
|
@@ -3293,4 +1347,4 @@ declare function discoverMerchantMcpUrl(inputUrl: string): Promise<string | null
|
|
|
3293
1347
|
/** Trailing-slash/percent-case echoes compare equal; unparseable never does. */
|
|
3294
1348
|
declare function sameUrl(a: string, b: string): boolean;
|
|
3295
1349
|
|
|
3296
|
-
export { AGENT_APPROVAL_RELAY_JSON_SENTENCE, AGENT_APPROVAL_RELAY_PROSE_SENTENCE, AGENT_COMMAND_MODIFICATION_SENTENCE, AGENT_JSON_MODE_SENTENCE, AGENT_LOCAL_KEY_SENTENCE, AGENT_NETWORK_ACCESS_SENTENCE, AGENT_ONBOARDING_PROMPT,
|
|
1350
|
+
export { AGENT_APPROVAL_RELAY_JSON_SENTENCE, AGENT_APPROVAL_RELAY_PROSE_SENTENCE, AGENT_COMMAND_MODIFICATION_SENTENCE, AGENT_JSON_MODE_SENTENCE, AGENT_LOCAL_KEY_SENTENCE, AGENT_NETWORK_ACCESS_SENTENCE, AGENT_ONBOARDING_PROMPT, AGENT_README_SECTION_MD, AGENT_SECRET_HYGIENE_SENTENCE, AGENT_WIRING_COLLISION_RELAY_SENTENCE, AgentPaymentWarning, type ClaudeTool, DISCOVERY_MAX_BYTES, type EvidenceReportOutcome, HAVEN_AGENT_RUNBOOK_MD, HAVEN_SKILL_BODY_MD, HAVEN_SKILL_MD, HavenAgent, HavenAgentSummary, HavenAllowanceSummary, HavenBalanceCoverage, HavenCatalogEntry, HavenCatalogSubmission, HavenClient, HavenClientConfig, HavenClientUpdate, HavenError, HavenInsecureRetryTargetError, HavenPaymentReceipt, HavenPaymentReceiptsPage, INSECURE_RETRY_TARGET_CODE, MERCHANT_DISCOVERY_PATHS, type OpenAITool, PaymentIntent, type PaymentReceipt, PaymentRequest, PaymentResult, PaymentResumeState, PaymentStatusResult, PostPurchaseAllowanceSummary, RECEIPT_VERSION, type ReceiptVerification, ResumeAuthorizedX402Input, ResumeX402PaymentInput, SKILL_FOLDER_NAME, type SharedToolKey, SignData, SweepAuthorization, SweepPrepareResponse, SweepResult, SweepSubmitResponse, type ToolDescription, X402AuthorizationOptions, X402Erc7710Settlement, X402Intent, X402McpCallContext, X402McpTransport, X402MerchantCallContext, type X402MerchantOutcome, type X402MerchantOutcomeReport, X402PaymentRequired, X402Quote, X402Receipt, X402ResumeState, type X402RetryTarget, addressFromKey, assertSecureX402RetryTarget, composeDescription, discoverMerchantMcpUrl, havenTools, isSecureX402RetryTarget, isZeroSettlementTxHash, readX402ReceiptPayer, resolveX402RetryTarget, sameUrl, signHash, signUserOpTypedDataForDelegation, toolDescriptions, verifyPaymentReceipt, verifySignature };
|