@haven_ai/sdk 0.6.0-alpha.0 → 0.8.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,13 +46,13 @@ const haven = new HavenClient({
46
46
 
47
47
  // One-liner payment — handles intent, signing, submission, and confirmation
48
48
  const result = await haven.pay({
49
- token: 'EURe',
49
+ token: 'USDC',
50
50
  amount: '5.00',
51
51
  to: '0xabc...',
52
52
  })
53
53
 
54
54
  console.log(result.txHash) // 0x...
55
- console.log(result.explorerUrl) // https://gnosisscan.io/tx/0x... (or basescan.org for Base)
55
+ console.log(result.explorerUrl) // https://basescan.org/tx/0x... (sepolia.basescan.org on Base Sepolia)
56
56
  ```
57
57
 
58
58
  ## Pay for an x402 resource
@@ -82,8 +82,8 @@ shows up in your Haven dashboard activity feed.
82
82
 
83
83
  | Network | CAIP-2 | Tokens |
84
84
  |---------|--------|--------|
85
- | Gnosis Chain | `eip155:100` | EURe, USDC.e, xDAI |
86
- | Base | `eip155:8453` | USDC, ETH |
85
+ | Base | `eip155:8453` | USDC |
86
+ | Base Sepolia (dev/QA) | `eip155:84532` | USDC |
87
87
 
88
88
  ## Credential Lifecycle
89
89
 
@@ -244,7 +244,12 @@ case where two purchases collided on a key you did not choose.
244
244
 
245
245
  This applies to the **EIP-3009 funding-leg** scheme, which routes money
246
246
  through the delegate EOA. **erc7710 direct settlement is unaffected**: it has
247
- no funding leg and no delegate balance to exhaust.
247
+ no funding leg and no delegate balance to exhaust. On erc7710, a key whose
248
+ payment to the same merchant for the same resource already settled makes
249
+ `prepareX402Erc7710()` throw `X402Erc7710AlreadySettledError` (`paymentId`,
250
+ `txHash`) instead of minting a settlement child. A key already used for a
251
+ payment to a different payee or resource is refused with a 409
252
+ `HavenApiError`; amount and MCP tool call are not compared (#3417).
248
253
 
249
254
  For agents that need to inspect the price before paying, use the quote-first
250
255
  path. `quoteX402()` probes the merchant and parses the HTTP 402 response, but it
@@ -285,7 +290,7 @@ const anthropic = new Anthropic()
285
290
  const response = await anthropic.messages.create({
286
291
  model: 'claude-opus-4-7',
287
292
  tools: havenTools.claude(), // or havenTools.openai() for OpenAI
288
- messages: [{ role: 'user', content: 'Pay 5 EURe to 0xabc for API access' }],
293
+ messages: [{ role: 'user', content: 'Pay 5 USDC to 0xabc for API access' }],
289
294
  })
290
295
 
291
296
  // Handle tool calls
@@ -420,6 +425,7 @@ x402 tool-window failures:
420
425
  | `rejected` | The payment was rejected and cannot proceed. | yes |
421
426
  | `expired` | Payment expired before completion. | yes |
422
427
  | `failed` | Haven could not complete the payment. | yes |
428
+ | `delivered_unverified` | **#3420: terminal.** The merchant delivered, but the settlement window and the sweep's last attribution chance have both passed with no verified on-chain evidence. Polling cannot change this; the only remedy is reporting a real settlement hash (`haven_report_settlement_evidence`). | yes |
423
429
 
424
430
  The merchant settlement leg of x402 (and the MPP retry) is the agent's own request to the merchant — it does not have a Haven `phase`. The payment is `funding_sent` until the agent retries with the payment header (`PAYMENT-SIGNATURE`, plus `X-PAYMENT` on this bridged path) (x402) or the MPP proof header; from Haven's perspective the payment becomes `executed` only after the agent successfully resumes.
425
431
 
@@ -430,10 +436,11 @@ The merchant settlement leg of x402 (and the MPP retry) is the agent's own reque
430
436
  | `sign_and_submit_payment` | Sign with the delegate key and submit the payment to Haven. |
431
437
  | `check_status_later` | Poll `getPaymentStatus(payment_id)` later. |
432
438
  | `none` | Stop polling; no more action is needed for this payment id. |
439
+ | `awaiting_settlement_evidence` | #2970/#3420: the erc7710 settlement window passed with no verified evidence. Poll `getPaymentStatus(payment_id)` once more shortly after the payment's expiry; if it still shows nothing (or already answers the terminal `delivered_unverified` phase), tell the user the goods were delivered but unverified. |
433
440
  | `wait_for_user_approval` | **No longer produced — nothing maps to it.** Retired with the Safe rail's approval queue; kept in the exported enum for wire compatibility. The SDK's own status mapping now answers `stop_and_tell_user` for the statuses that used to yield this. |
434
441
  | `wait_for_user_to_complete_payment` | **No longer produced — nothing maps to it.** Same retirement as above. |
435
442
  | `retry_original_x402_request` | Haven's funding leg confirmed but no merchant response was ever recorded — most often because the process crashed between the funding confirmation and the merchant retry (a 15-minute grace window applies before this fires; a client-reported merchant rejection instead yields `sweep_stranded_funds`). Call `resumeX402Payment()` with the preserved `resumeState`, or rehydrate it first with `getResumeState(payment_id)`. Do not start a new payment for the same purchase. |
436
- | `stop_and_tell_user` | Stop retrying and tell the user the payment failed or was rejected. |
443
+ | `stop_and_tell_user` | Stop retrying and tell the user what happened — the payment failed, was rejected, or (#3420) was delivered but its settlement can no longer be verified. |
437
444
  | `request_again_if_user_still_wants_it` | The request expired; ask again only if the user still wants the payment. |
438
445
  | `payment_window_expired` | The x402 funding/quote window expired. Re-quote the same paid MCP tool call with the same `idempotency_key`, then sign the fresh `payload_hash`. |
439
446
  | `sweep_stranded_funds` | A funding leg succeeded but the merchant/protocol leg did not settle. Stop retrying and use `haven_sweep_delegate` to recover stranded delegate funds. |
@@ -463,9 +470,11 @@ answers HTTP 410 at every agent-payment entry point.
463
470
  If an agent requests a payment outside that policy, Haven **declines it before
464
471
  any money moves** — during prepare, before anything is written and before the
465
472
  agent is asked to sign. `POST /payments` answers `403` when no active delegation
466
- authorizes that token and recipient, and `502` when the on-chain caveat check
467
- rejects the amount, recipient or expiry; the x402 authorize path answers `403
468
- delegation_budget_exceeded`. In every case the SDK raises `HavenApiError` and no
473
+ authorizes that token and recipient, `403 delegation_budget_exceeded` when the
474
+ remaining period budget cannot cover the amount (#3503; the x402 authorize path
475
+ answers the same), and `502` when the on-chain caveat check rejects a
476
+ redemption anyway (a recipient outside a pin or an expired grant already gets
477
+ the first `403`, since no active delegation matches). In every case the SDK raises `HavenApiError` and no
469
478
  `payment_id` exists to poll.
470
479
 
471
480
  Surface that to the user as a decline, not a wait: **nothing will arrive later.**
@@ -623,7 +632,7 @@ inspection, saved resume state, and final retry.
623
632
  import { HavenApiError, HavenPaymentStateError, HavenSigningError, HavenTimeoutError } from '@haven_ai/sdk'
624
633
 
625
634
  try {
626
- await haven.pay({ token: 'EURe', amount: '5.00', to: '0xabc...' })
635
+ await haven.pay({ token: 'USDC', amount: '5.00', to: '0xabc...' })
627
636
  } catch (err) {
628
637
  if (err instanceof HavenPaymentStateError) {
629
638
  console.log(err.paymentId, err.phase, err.nextAction)
@@ -640,11 +649,19 @@ try {
640
649
  }
641
650
  ```
642
651
 
643
- `X402AlreadySettledError` extends `HavenApiError` (status 409) and is the one
644
- error above that is **not** a failure to pay — it reports that the payment it
645
- describes *succeeded*, earlier. Handle it before the generic `HavenApiError`
646
- branch, and treat `err.receipt` as proof of purchase rather than retrying. See
647
- [Idempotency](#idempotency-what-the-key-guarantees-and-what-it-costs).
652
+ Two errors are **not** a failure to pay; each reports that the payment it
653
+ describes *succeeded*, earlier. Handle both before the generic branches, and
654
+ treat them as proof of purchase rather than retrying:
655
+
656
+ - `X402AlreadySettledError` extends `HavenApiError` (status 409; EIP-3009
657
+ path) and carries `err.receipt`.
658
+ - `X402Erc7710AlreadySettledError` extends `HavenError`, **not**
659
+ `HavenApiError` (no status; code `PAYMENT_ALREADY_SETTLED`; erc7710
660
+ `prepareX402Erc7710()`, and since #3423 `submitX402Erc7710()` on a repeated
661
+ settle), and carries `err.paymentId` and `err.txHash`. An
662
+ `instanceof HavenApiError` branch does not catch it.
663
+
664
+ See [Idempotency](#idempotency-what-the-key-guarantees-and-what-it-costs).
648
665
 
649
666
  ## License
650
667