@haven_ai/sdk 0.1.0 → 0.1.2
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 +83 -11
- package/dist/index.cjs +809 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +136 -5
- package/dist/index.d.ts +136 -5
- package/dist/index.js +804 -55
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @haven_ai/sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for [Haven](https://github.com/d-hinders/Haven) — agent wallet infrastructure for the autonomous economy.
|
|
3
|
+
TypeScript SDK for [Haven](https://github.com/d-hinders/Haven-AI) — agent wallet infrastructure for the autonomous economy.
|
|
4
4
|
|
|
5
|
-
Haven
|
|
5
|
+
Haven lets AI agents request and sign payments within strict, user-approved on-chain guardrails. This SDK makes it straightforward to integrate Haven payment requests into any agent without giving Haven custody of user or agent keys.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -32,6 +32,35 @@ console.log(result.txHash) // 0x...
|
|
|
32
32
|
console.log(result.explorerUrl) // https://gnosisscan.io/tx/0x... (or basescan.org for Base)
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
## Try it live — zero setup
|
|
36
|
+
|
|
37
|
+
Haven hosts a demo endpoint you can hit immediately after creating an agent:
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { HavenClient } from '@haven_ai/sdk'
|
|
41
|
+
|
|
42
|
+
const haven = new HavenClient({
|
|
43
|
+
apiKey: process.env.HAVEN_API_KEY!, // from Haven dashboard
|
|
44
|
+
delegateKey: process.env.DELEGATE_KEY!, // agent's delegate private key
|
|
45
|
+
baseUrl: 'https://havenbackend-production-8a00.up.railway.app', // hosted Haven, or your self-hosted URL
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// haven.fetch handles 402 → pay → retry automatically
|
|
49
|
+
const response = await haven.fetch(
|
|
50
|
+
'https://havenbackend-production-8a00.up.railway.app/demo/x402/data',
|
|
51
|
+
)
|
|
52
|
+
const data = await response.json()
|
|
53
|
+
|
|
54
|
+
console.log(data.message) // "You paid! Here's your demo data."
|
|
55
|
+
console.log(data.fact) // a fun fact about the agent economy
|
|
56
|
+
console.log(data.explorerUrl) // link to the on-chain payment tx
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Tell your agent:
|
|
60
|
+
> "Use Haven to fetch `https://havenbackend-production-8a00.up.railway.app/demo/x402/data` and show me what came back."
|
|
61
|
+
|
|
62
|
+
The agent will pay a tiny amount (~0.01 EURe on Gnosis Chain), receive the demo payload, and you'll see the payment in your Haven dashboard activity feed — no local server or extra config required.
|
|
63
|
+
|
|
35
64
|
## Supported Networks & Tokens
|
|
36
65
|
|
|
37
66
|
| Network | CAIP-2 | Tokens |
|
|
@@ -63,7 +92,9 @@ const result = await haven.waitForConfirmation(intent.paymentId)
|
|
|
63
92
|
|
|
64
93
|
## x402 Protocol Support
|
|
65
94
|
|
|
66
|
-
|
|
95
|
+
Production merchant acceptance, facilitator, settlement, fiat, or acquiring functionality needs separate product and legal review under the repo's [CASP / MiCA guardrails](../../docs/regulatory/casp-risk-guardrails.md). The hosted x402 endpoint is an internal technical demo, not a merchant settlement product.
|
|
96
|
+
|
|
97
|
+
Haven natively supports the [x402](https://x402.org) payment protocol. When an API returns HTTP 402, the SDK evaluates the challenge against the agent's approved limits, uses the configured delegate key for the required signature, and retries automatically:
|
|
67
98
|
|
|
68
99
|
```typescript
|
|
69
100
|
// Automatic — fetch() intercepts 402, pays, and retries
|
|
@@ -71,17 +102,20 @@ const response = await haven.fetch('https://paid-api.example.com/data')
|
|
|
71
102
|
const data = await response.json()
|
|
72
103
|
|
|
73
104
|
// Manual — parse and authorize the 402 yourself
|
|
74
|
-
import {
|
|
105
|
+
import { parsePaymentRequiredResponse } from '@haven_ai/sdk'
|
|
75
106
|
|
|
76
107
|
const apiResponse = await fetch('https://paid-api.example.com/data')
|
|
77
108
|
if (apiResponse.status === 402) {
|
|
78
|
-
const paymentRequired =
|
|
109
|
+
const paymentRequired = await parsePaymentRequiredResponse(apiResponse)
|
|
79
110
|
const receipt = await haven.authorizeX402(paymentRequired)
|
|
111
|
+
// Retry with { 'X-PAYMENT': receipt.paymentHeader }
|
|
80
112
|
console.log(receipt.explorerUrl)
|
|
81
113
|
}
|
|
82
114
|
```
|
|
83
115
|
|
|
84
|
-
|
|
116
|
+
Merchant-verified x402 retries use the official EIP-3009 `exact` scheme on Base USDC (`base` / `eip155:8453`) and send the payment as `X-PAYMENT`. Haven's older tx-hash proof helper remains exported for Haven-native integrations, but `haven.fetch()` does not send `PAYMENT-SIGNATURE`.
|
|
117
|
+
|
|
118
|
+
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/Safe address should use a Haven-native flow instead of standard merchant x402.
|
|
85
119
|
|
|
86
120
|
## AI Agent Integration
|
|
87
121
|
|
|
@@ -97,7 +131,7 @@ const haven = new HavenClient({ apiKey, delegateKey })
|
|
|
97
131
|
const anthropic = new Anthropic()
|
|
98
132
|
|
|
99
133
|
const response = await anthropic.messages.create({
|
|
100
|
-
model: 'claude-opus-4-
|
|
134
|
+
model: 'claude-opus-4-7',
|
|
101
135
|
tools: havenTools.claude(), // or havenTools.openai() for OpenAI
|
|
102
136
|
messages: [{ role: 'user', content: 'Pay 5 EURe to 0xabc for API access' }],
|
|
103
137
|
})
|
|
@@ -115,9 +149,9 @@ for (const block of response.content) {
|
|
|
115
149
|
|
|
116
150
|
| Tool | Description |
|
|
117
151
|
|------|-------------|
|
|
118
|
-
| `make_payment` |
|
|
119
|
-
| `get_payment_status` | Check the status of a
|
|
120
|
-
| `authorize_x402_payment` |
|
|
152
|
+
| `make_payment` | Request and sign a payment from the user-controlled Safe within approved limits |
|
|
153
|
+
| `get_payment_status` | Check the status of a payment intent or approval request |
|
|
154
|
+
| `authorize_x402_payment` | Authorize a policy-limited x402 payment and return a payment header for an HTTP 402 resource |
|
|
121
155
|
|
|
122
156
|
## Configuration
|
|
123
157
|
|
|
@@ -126,20 +160,58 @@ const haven = new HavenClient({
|
|
|
126
160
|
apiKey: 'sk_agent_xxx', // required — Haven agent API key
|
|
127
161
|
delegateKey: '0x...', // optional — enables .pay() and .sign()
|
|
128
162
|
baseUrl: 'http://localhost:3001', // default
|
|
163
|
+
x402Wallet: '0x...', // optional fallback when no delegate key is configured
|
|
129
164
|
requestTimeout: 30000, // per-request timeout (ms)
|
|
130
165
|
confirmationTimeout: 90000, // polling timeout (ms)
|
|
131
166
|
pollingInterval: 3000, // polling interval (ms)
|
|
132
167
|
})
|
|
133
168
|
```
|
|
134
169
|
|
|
170
|
+
## Payments above the on-chain allowance
|
|
171
|
+
|
|
172
|
+
Haven's policy lives on the Safe AllowanceModule (token, amount, reset period).
|
|
173
|
+
If an agent requests a payment above the remaining allowance, Haven does **not**
|
|
174
|
+
reject it — it returns HTTP 202 with `status: 'pending_approval'`, a
|
|
175
|
+
`payment_id`, `phase`, and `next_action`, then queues it for the wallet owner
|
|
176
|
+
to approve in the dashboard.
|
|
177
|
+
|
|
178
|
+
Surface that to the user: the payment isn't dead, it's waiting for a human to
|
|
179
|
+
sign off. Check `getPaymentStatus(payment_id)` or the `get_payment_status`
|
|
180
|
+
tool later instead of retrying in a tight loop.
|
|
181
|
+
|
|
182
|
+
For x402, the manual approval path has two steps. First, the user approves the
|
|
183
|
+
funding movement from the Haven wallet to the agent's delegate wallet. Once
|
|
184
|
+
Haven reports `next_action: 'retry_original_x402_request'`, retry the original
|
|
185
|
+
paid API request so the SDK can attach the merchant x402 payment header. Do not
|
|
186
|
+
rewrite the SDK while waiting for approval.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
try {
|
|
190
|
+
await haven.pay({ token: 'USDC', amount: '500', to: '0xabc...' })
|
|
191
|
+
} catch (err) {
|
|
192
|
+
if (err instanceof HavenPaymentStateError && err.nextAction === 'wait_for_user_approval') {
|
|
193
|
+
console.log(err.paymentId, err.phase, err.nextAction)
|
|
194
|
+
console.log('Queued for owner approval — visible in the Haven dashboard.')
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const status = await haven.getPaymentStatus('approval-or-payment-id')
|
|
199
|
+
if (status.nextAction === 'retry_original_x402_request') {
|
|
200
|
+
// Retry the original paid API request.
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
135
204
|
## Error Handling
|
|
136
205
|
|
|
137
206
|
```typescript
|
|
138
|
-
import { HavenApiError, HavenSigningError, HavenTimeoutError } from '@haven_ai/sdk'
|
|
207
|
+
import { HavenApiError, HavenPaymentStateError, HavenSigningError, HavenTimeoutError } from '@haven_ai/sdk'
|
|
139
208
|
|
|
140
209
|
try {
|
|
141
210
|
await haven.pay({ token: 'EURe', amount: '5.00', to: '0xabc...' })
|
|
142
211
|
} catch (err) {
|
|
212
|
+
if (err instanceof HavenPaymentStateError) {
|
|
213
|
+
console.log(err.paymentId, err.phase, err.nextAction)
|
|
214
|
+
}
|
|
143
215
|
if (err instanceof HavenApiError) {
|
|
144
216
|
console.log(err.statusCode, err.message) // API returned an error
|
|
145
217
|
}
|