@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/README.md
CHANGED
|
@@ -21,6 +21,17 @@ and managing the account from the shell with `@haven_ai/cli`.
|
|
|
21
21
|
npm install @haven_ai/sdk@alpha
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
The package has three entries. `@haven_ai/sdk` is the full client. `@haven_ai/sdk/edge`
|
|
25
|
+
(#3173) is the ethers-free subset the local signer imports — error classes, the
|
|
26
|
+
typed-next-step builder, the x402 message builders, viem-based key helpers, and
|
|
27
|
+
(#3283) the signing-surface guard: `assertBoundDirectPaymentUserOp`, the
|
|
28
|
+
redemption guard, `deriveDelegateAccountAddress` and `verifySettlementChild` —
|
|
29
|
+
and loads in about a third of the time; use it when you need those helpers
|
|
30
|
+
without the HTTP client. A class imported from either entry is the same class.
|
|
31
|
+
`@haven_ai/sdk/test-support` (#3283) holds test fixture builders shared by
|
|
32
|
+
Haven's own packages; it is not a signing API, nothing at runtime imports it,
|
|
33
|
+
and it carries no semver guarantee.
|
|
34
|
+
|
|
24
35
|
## Quick Start
|
|
25
36
|
|
|
26
37
|
```typescript
|
|
@@ -79,6 +90,7 @@ shows up in your Haven dashboard activity feed.
|
|
|
79
90
|
- The delegate key signs payment payloads locally. Haven's backend never receives it.
|
|
80
91
|
- The agent's on-chain budget delegation enforces the agent budget: budget, recipient and expiry are checked by audited caveat enforcers at redemption, not by an off-chain rules engine.
|
|
81
92
|
- `getAllowances()` / `get_allowances` is the right path for budget, remaining amount, reset period, or "what can I spend?" questions.
|
|
93
|
+
- `checkFunds()` / `haven_check_funds` answers the different question of whether the account actually holds funds behind the budget — as a sufficiency signal (`covered` true/false/null), never as a balance.
|
|
82
94
|
- If an API key is exposed or lost, rotate it from the Haven agent detail page. The new key is shown once and the old key stops working.
|
|
83
95
|
- If a delegate key is exposed or lost, a delegation-rail agent is **re-keyed** rather than replaced — same agent, new signing key, budget remainder carried. See [Replacing an agent's signing key](../../docs/product/agent-key-rotation.md).
|
|
84
96
|
|
|
@@ -105,8 +117,18 @@ const intent = await haven.createIntent({
|
|
|
105
117
|
to: '0xabc...',
|
|
106
118
|
})
|
|
107
119
|
|
|
108
|
-
// Step 2: Sign the
|
|
109
|
-
|
|
120
|
+
// Step 2: Sign externally. On the delegation rail (the only rail that pays)
|
|
121
|
+
// the account validates the EIP-712 typed data in intent.signData.typed_data,
|
|
122
|
+
// never the bare hash — a signature over signData.hash is rejected on-chain
|
|
123
|
+
// (AA24). Sign that typed data with your delegate key (viem signTypedData),
|
|
124
|
+
// after checking it with assertUserOpTypedDataBinding(typed_data, hash) AND
|
|
125
|
+
// assertBoundDirectPaymentUserOp(typed_data, yourDelegateAddress) — the
|
|
126
|
+
// first proves the typed data matches the hash, the second that it is your
|
|
127
|
+
// own account redeeming your budget delegation, not a self-call (#3283).
|
|
128
|
+
// There is no public HavenClient method for this step yet; pay() does both
|
|
129
|
+
// for you. HavenClient.sign(hash) and signUserOpTypedDataForDelegation are
|
|
130
|
+
// verbatim primitives: they check nothing.
|
|
131
|
+
const signature = await signTypedDataWithYourDelegateKey(intent.signData.typed_data)
|
|
110
132
|
|
|
111
133
|
// Step 3: Submit the signature
|
|
112
134
|
await haven.submitSignature(intent.paymentId, signature)
|
|
@@ -146,6 +168,23 @@ if (apiResponse.status === 402) {
|
|
|
146
168
|
}
|
|
147
169
|
```
|
|
148
170
|
|
|
171
|
+
**MCP merchants, both dialects (#3118).** A merchant may serve x402 over MCP
|
|
172
|
+
in Haven's HTTP layering (HTTP 402 with the `PAYMENT-REQUIRED` header or JSON
|
|
173
|
+
body, payment in `PAYMENT-SIGNATURE` / `X-PAYMENT`, settlement in
|
|
174
|
+
`PAYMENT-RESPONSE`) or in the official x402 MCP transport profile (a tool
|
|
175
|
+
result with `isError: true` and the `PaymentRequired` as `structuredContent`,
|
|
176
|
+
payment in `params._meta["x402/payment"]`, settlement in
|
|
177
|
+
`result._meta["x402/payment-response"]`). `fetch()`, `quoteX402()`,
|
|
178
|
+
`quoteMcpX402()` and `completeX402MerchantCall()` handle both: a payment-
|
|
179
|
+
required tool result quotes like a 402, the paid retry carries the header and
|
|
180
|
+
— for a `tools/call` body — the `_meta` object, and settlement is read from the
|
|
181
|
+
header first, the `_meta` second. An in-band refusal (an `isError` challenge on
|
|
182
|
+
the paid retry, or `success: false`) is a rejection even under HTTP 200. An
|
|
183
|
+
ordinary tool error, or a successful result that merely resembles a challenge,
|
|
184
|
+
is never paid for. The tool-result challenge is read only from a response
|
|
185
|
+
declaring `application/json` or `text/event-stream`; any other content type is
|
|
186
|
+
passed through untouched rather than buffered.
|
|
187
|
+
|
|
149
188
|
### Idempotency: what the key guarantees, and what it costs
|
|
150
189
|
|
|
151
190
|
**Omit `idempotencyKey` and the SDK synthesises one** from the merchant's
|
|
@@ -227,7 +266,7 @@ const data = await response.json()
|
|
|
227
266
|
|
|
228
267
|
Merchant-verified x402 retries use the official EIP-3009 `exact` scheme on Base USDC (`base` / `eip155:8453`). `haven.fetch()` sends the payment under `PAYMENT-SIGNATURE` (the x402 v2 name), and on the EIP-3009 bridge also under `X-PAYMENT` (v1), so a merchant on either version reads it. **On erc7710 it sends the v2 name ALONE**: that payload is always x402 v2, and its header carries a whole delegation chain, so duplicating it overflows the merchant's header limit and the request is refused with HTTP 431. If you build the retry yourself, follow the same rule. Haven's older tx-hash proof helper remains exported for Haven-native integrations; it is a different payload that happens to have shared the v2 name, and it is not what `haven.fetch()` sends.
|
|
229
268
|
|
|
230
|
-
For standard x402, the `x402-wallet` identity is the agent delegate wallet, because that is the wallet that signs and settles the merchant payment. Integrations that scope access by Haven wallet
|
|
269
|
+
For standard x402, the `x402-wallet` identity is the agent delegate wallet, because that is the wallet that signs and settles the merchant payment. Integrations that scope access by Haven wallet address should use a Haven-native flow instead of standard merchant x402.
|
|
231
270
|
|
|
232
271
|
## AI Agent Integration
|
|
233
272
|
|
|
@@ -561,6 +600,18 @@ original `tools/call`, setting BOTH `PAYMENT-SIGNATURE` (x402 v2) and `X-PAYMENT
|
|
|
561
600
|
user intent so fresh merchant quotes or sessions do not become duplicate Haven
|
|
562
601
|
payments.
|
|
563
602
|
|
|
603
|
+
If the merchant's session is gone by the time the paid retry arrives (it
|
|
604
|
+
expired, or the merchant restarted), a merchant that answers HTTP 404 with
|
|
605
|
+
JSON-RPC `-32001` **and** `error.data = { settled: false, next_action:
|
|
606
|
+
'reinitialize_then_retry_same_payment_header' }` is stating its own guarantee
|
|
607
|
+
that nothing was settled; since #3171 `fetch()`, `payX402Quote()`,
|
|
608
|
+
`resumeX402Payment()` and `completeX402MerchantCall()` act on exactly that
|
|
609
|
+
shape — re-initialize once and resend the SAME payment header on the new
|
|
610
|
+
session. A bare `-32001` without the data, any other 404, a failed
|
|
611
|
+
re-initialize, or a second 404 is returned to you unchanged and, after
|
|
612
|
+
funding, recorded as a rejection as before: the SDK never resends on an
|
|
613
|
+
inference, only on the merchant's stated guarantee.
|
|
614
|
+
|
|
564
615
|
See [`examples/mcp-x402-sse.ts`](./examples/mcp-x402-sse.ts) for a complete
|
|
565
616
|
MCP flow with initialize, `mcp-session-id`, JSON-RPC `tools/call`, quote
|
|
566
617
|
inspection, saved resume state, and final retry.
|