@haven_ai/sdk 0.11.0-alpha.0 → 0.13.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 +37 -4
- package/dist/{base64-D4VZhgUg.d.ts → base64-C3mJNLYR.d.cts} +10 -2
- package/dist/{base64-DR4Gl8cD.d.cts → base64-CxzIc3KH.d.ts} +10 -2
- package/dist/{chunk-IKQIIMM6.cjs → chunk-4Z7PKLFD.cjs} +38 -37
- package/dist/chunk-4Z7PKLFD.cjs.map +1 -0
- package/dist/{chunk-34YJQFCM.js → chunk-CK6VRIPR.js} +3 -3
- package/dist/chunk-CK6VRIPR.js.map +1 -0
- package/dist/{chunk-ZDJ55LR7.js → chunk-CXQ42FOA.js} +7 -6
- package/dist/chunk-CXQ42FOA.js.map +1 -0
- package/dist/{chunk-MZKLAHBK.cjs → chunk-LZHCIK7L.cjs} +56 -4
- package/dist/chunk-LZHCIK7L.cjs.map +1 -0
- package/dist/{chunk-I7SL4A6X.js → chunk-MI7LVP56.js} +55 -5
- package/dist/chunk-MI7LVP56.js.map +1 -0
- package/dist/{chunk-DXBAN4SN.cjs → chunk-Z5MTKU6O.cjs} +4 -4
- package/dist/chunk-Z5MTKU6O.cjs.map +1 -0
- package/dist/edge.cjs +93 -93
- package/dist/edge.d.cts +11 -8
- package/dist/edge.d.ts +11 -8
- package/dist/edge.js +4 -4
- package/dist/index.cjs +456 -356
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -15
- package/dist/index.d.ts +26 -15
- package/dist/index.js +140 -48
- package/dist/index.js.map +1 -1
- package/dist/{receipt-CbD8L0WL.d.ts → receipt-CTOPh2fm.d.ts} +5 -4
- package/dist/{receipt-_bWCELEH.d.cts → receipt-DwRqGjGb.d.cts} +5 -4
- package/dist/test-support.cjs +58 -21
- package/dist/test-support.cjs.map +1 -1
- package/dist/test-support.d.cts +47 -3
- package/dist/test-support.d.ts +47 -3
- package/dist/test-support.js +37 -3
- package/dist/test-support.js.map +1 -1
- package/dist/{types-DKmvjXK6.d.cts → types-3vUBmumz.d.cts} +163 -2
- package/dist/{types-DKmvjXK6.d.ts → types-3vUBmumz.d.ts} +163 -2
- package/package.json +2 -2
- package/dist/chunk-34YJQFCM.js.map +0 -1
- package/dist/chunk-DXBAN4SN.cjs.map +0 -1
- package/dist/chunk-I7SL4A6X.js.map +0 -1
- package/dist/chunk-IKQIIMM6.cjs.map +0 -1
- package/dist/chunk-MZKLAHBK.cjs.map +0 -1
- package/dist/chunk-ZDJ55LR7.js.map +0 -1
package/README.md
CHANGED
|
@@ -273,7 +273,7 @@ const response = await haven.payX402Quote(quote)
|
|
|
273
273
|
const data = await response.json()
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
-
Merchant-verified x402 retries use the
|
|
276
|
+
Merchant-verified x402 retries use the x402 `exact` scheme on Base USDC (`base` / `eip155:8453`, or Base Sepolia `eip155:84532`): the EIP-3009 `authorization` payload on the bridge, or a delegation when the merchant's entry carries `extra.assetTransferMethod: 'erc7710'`. `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: `x402RetryHeadersFor(paymentHeader)` returns exactly those headers (#3727). 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.
|
|
277
277
|
|
|
278
278
|
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.
|
|
279
279
|
|
|
@@ -412,6 +412,9 @@ x402 tool-window failures:
|
|
|
412
412
|
expired funding/quote window → PAYMENT_WINDOW_EXPIRED → re-quote with same idempotency_key
|
|
413
413
|
merchant rejection after funding → MERCHANT_REJECTED_AFTER_FUNDING → haven_sweep_delegate (eip3009 only; erc7710: nothing to sweep, follow the message)
|
|
414
414
|
merchant timeout after funding → MERCHANT_UNRESPONSIVE_AFTER_FUNDING → check_status_later; eip3009: retry once, then haven_sweep_delegate; erc7710: no retry, check status after the window, re-quote only if unsettled
|
|
415
|
+
funding confirmation unreadable (eip3009, hosted) → FUNDING_CONFIRMATION_UNKNOWN → check_status_later; merchant not called; once funding shows confirmed, complete ONCE (#4470)
|
|
416
|
+
funding transaction reverted (eip3009, hosted) → FUNDING_REVERTED → stop_and_tell_user; nothing reached the delegate (#4470)
|
|
417
|
+
no answer to a submit (hosted haven_submit, and haven_settle_mcp_tool's erc7710 settle) → NO_ANSWER_OUTCOME_UNKNOWN → check_status_later; never re-submit, never a new payment (#4470)
|
|
415
418
|
```
|
|
416
419
|
|
|
417
420
|
### `phase` reference
|
|
@@ -428,6 +431,8 @@ x402 tool-window failures:
|
|
|
428
431
|
| `rejected` | The payment was rejected and cannot proceed. | yes |
|
|
429
432
|
| `expired` | Payment expired before completion. | yes |
|
|
430
433
|
| `failed` | Haven could not complete the payment. | yes |
|
|
434
|
+
| `insufficient_funds` | Carried by the `delegation_budget_exceeded` refusal — `403` at prepare, or `502` when the budget ran out by the time the payment was signed — with `nextAction: fund_account_or_raise_allowance`. The budget must be raised, or the period reset, before a new payment can succeed. | yes |
|
|
435
|
+
| `funded_but_unsettled` | The EIP-3009 bridge's funding leg confirmed, but the merchant leg has not settled: either the merchant rejected the retry (`nextAction: sweep_stranded_funds`) or no merchant response was ever recorded (`nextAction: retry_original_x402_request`). Follow `nextAction`. | no |
|
|
431
436
|
| `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 |
|
|
432
437
|
|
|
433
438
|
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.
|
|
@@ -445,6 +450,8 @@ The merchant settlement leg of x402 (and the MPP retry) is the agent's own reque
|
|
|
445
450
|
| `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. |
|
|
446
451
|
| `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. |
|
|
447
452
|
| `request_again_if_user_still_wants_it` | The request expired; ask again only if the user still wants the payment. |
|
|
453
|
+
| `retry_with_explicit_context` | #1307: retry the same tool call, passing `merchant_url`, `tool_name`, `arguments` and `mcp_transport` explicitly — the server had no stored context to rehydrate for this payment id. |
|
|
454
|
+
| `fund_account_or_raise_allowance` | Stop and tell the user the agent's budget must be raised (or its period reset) before a new payment can succeed; it rides on the `delegation_budget_exceeded` refusal. An approval will not fix it. |
|
|
448
455
|
| `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`. |
|
|
449
456
|
| `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. |
|
|
450
457
|
|
|
@@ -471,8 +478,10 @@ queue**: the queue-and-approve path belonged to the retired Safe rail, which now
|
|
|
471
478
|
answers HTTP 410 at every agent-payment entry point.
|
|
472
479
|
|
|
473
480
|
If an agent requests a payment outside that policy, Haven **declines it before
|
|
474
|
-
any money moves** — during prepare, before
|
|
475
|
-
agent is asked to sign.
|
|
481
|
+
any money moves** — during prepare, before any payment intent is created and
|
|
482
|
+
before the agent is asked to sign. The one row written is the refusal itself,
|
|
483
|
+
in the `payment_refusals` ledger (#2945, migration 086; written through the
|
|
484
|
+
`refuse()` choke point since #3053). `POST /payments` answers `403` when no active delegation
|
|
476
485
|
authorizes that token and recipient, `403 delegation_budget_exceeded` when the
|
|
477
486
|
remaining period budget cannot cover the amount (#3503; the x402 authorize path
|
|
478
487
|
answers the same), and `502` when the on-chain caveat check rejects a
|
|
@@ -609,7 +618,9 @@ For MCP/SSE x402 tools, keep the same MCP session and JSON-RPC payload where the
|
|
|
609
618
|
merchant requires it: initialize, retain `mcp-session-id`, send the original
|
|
610
619
|
`tools/call`, parse the 402 challenge, wait for the funding leg to confirm if
|
|
611
620
|
the payment is bridged, then resume with the same `payment_id` and retry the
|
|
612
|
-
original `tools/call
|
|
621
|
+
original `tools/call` with the headers `x402RetryHeadersFor(paymentHeader)`
|
|
622
|
+
returns — `PAYMENT-SIGNATURE` (x402 v2), plus `X-PAYMENT` (v1) only on the
|
|
623
|
+
EIP-3009 bridge; erc7710 sends the v2 name alone. Use a stable `idempotencyKey` for the
|
|
613
624
|
user intent so fresh merchant quotes or sessions do not become duplicate Haven
|
|
614
625
|
payments.
|
|
615
626
|
|
|
@@ -666,6 +677,28 @@ treat them as proof of purchase rather than retrying:
|
|
|
666
677
|
|
|
667
678
|
See [Idempotency](#idempotency-what-the-key-guarantees-and-what-it-costs).
|
|
668
679
|
|
|
680
|
+
**Why a `HavenApiError` happened is `err.failureCause`, not only its status
|
|
681
|
+
(#4470).** The status alone misleads in two ways, so two causes are marked
|
|
682
|
+
where the SDK creates the error, and every other error leaves the field
|
|
683
|
+
`undefined`:
|
|
684
|
+
|
|
685
|
+
- `{ kind: 'no_answer', method }` — the transport got no usable answer: the
|
|
686
|
+
request timed out (`statusCode` 408), `fetch` threw, or the body was not
|
|
687
|
+
JSON (`statusCode` 0; a gateway's HTML 502 arrives this way). Whether the
|
|
688
|
+
call took effect is unknown. A `GET` may be retried; a `POST` should not
|
|
689
|
+
be — read the payment's status first. A server that answers 408 with a
|
|
690
|
+
JSON body is an answer and carries no cause.
|
|
691
|
+
- `{ kind: 'deterministic' }` — the SDK refused an answer it cannot use (a
|
|
692
|
+
missing field, the wrong shape). A retry gets the same answer, whatever the
|
|
693
|
+
5xx status says. Built with `HavenApiError.deterministic(...)`.
|
|
694
|
+
|
|
695
|
+
The funding wait before a merchant retry has two typed outcomes, both
|
|
696
|
+
`HavenApiError` subclasses: `FundingConfirmationUnknownError` (status 504;
|
|
697
|
+
the confirmation could not be read in time, so funding may have moved — check
|
|
698
|
+
the payment's status) and `FundingRevertedError` (status 502; the funding
|
|
699
|
+
transaction reverted, nothing reached the delegate). Each carries `txHash`,
|
|
700
|
+
`chainId` and a `fundingErrorCode`.
|
|
701
|
+
|
|
669
702
|
## License
|
|
670
703
|
|
|
671
704
|
MIT
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Q as AgentNextStep, Z as AgentPaymentNextAction,
|
|
1
|
+
import { Q as AgentNextStep, Z as AgentPaymentNextAction, aP as X402PaymentOption, aO as X402ExpectedContext, X as X402PaymentRequired, I as HavenError, aq as HavenSigningError } from './types-3vUBmumz.cjs';
|
|
2
2
|
import { PaymentRequirements } from 'x402/types';
|
|
3
3
|
import { Hex, Address } from 'viem';
|
|
4
4
|
|
|
@@ -200,7 +200,7 @@ declare function buildSweepAuthorizationMessage(auth: SweepAuthorization): strin
|
|
|
200
200
|
* This SDK's own version. Owned by `scripts/release-bump.mjs`, which rewrites
|
|
201
201
|
* it with the package version on every release — never hand-edit it.
|
|
202
202
|
*/
|
|
203
|
-
declare const SDK_VERSION = "0.
|
|
203
|
+
declare const SDK_VERSION = "0.13.0-alpha.0";
|
|
204
204
|
/** The request header every published Haven client sends. */
|
|
205
205
|
declare const HAVEN_CLIENT_HEADER = "X-Haven-Client";
|
|
206
206
|
/** `<package>/<version>` — the value of {@link HAVEN_CLIENT_HEADER}. */
|
|
@@ -269,6 +269,14 @@ declare function parseNextTool(literal: string): {
|
|
|
269
269
|
interface NextStepTarget<TArgs> {
|
|
270
270
|
role: NextToolServerRole;
|
|
271
271
|
validate: (input: unknown) => string | null;
|
|
272
|
+
/**
|
|
273
|
+
* #4449: the bare tool name to render, when the target-map key is not it.
|
|
274
|
+
* One hosted tool that takes several argument shapes is declared once per
|
|
275
|
+
* shape under `<tool>#<variant>` keys (the signer's `haven_submit#payment`
|
|
276
|
+
* beside `#task_budget` / `#sub_budget`): the key selects the shape, this
|
|
277
|
+
* names the tool. Absent → the key IS the name, which is every other target.
|
|
278
|
+
*/
|
|
279
|
+
name?: string;
|
|
272
280
|
/** Phantom carrier for the argument type; never read at runtime. */
|
|
273
281
|
readonly _args?: TArgs;
|
|
274
282
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Q as AgentNextStep, Z as AgentPaymentNextAction,
|
|
1
|
+
import { Q as AgentNextStep, Z as AgentPaymentNextAction, aP as X402PaymentOption, aO as X402ExpectedContext, X as X402PaymentRequired, I as HavenError, aq as HavenSigningError } from './types-3vUBmumz.js';
|
|
2
2
|
import { PaymentRequirements } from 'x402/types';
|
|
3
3
|
import { Hex, Address } from 'viem';
|
|
4
4
|
|
|
@@ -200,7 +200,7 @@ declare function buildSweepAuthorizationMessage(auth: SweepAuthorization): strin
|
|
|
200
200
|
* This SDK's own version. Owned by `scripts/release-bump.mjs`, which rewrites
|
|
201
201
|
* it with the package version on every release — never hand-edit it.
|
|
202
202
|
*/
|
|
203
|
-
declare const SDK_VERSION = "0.
|
|
203
|
+
declare const SDK_VERSION = "0.13.0-alpha.0";
|
|
204
204
|
/** The request header every published Haven client sends. */
|
|
205
205
|
declare const HAVEN_CLIENT_HEADER = "X-Haven-Client";
|
|
206
206
|
/** `<package>/<version>` — the value of {@link HAVEN_CLIENT_HEADER}. */
|
|
@@ -269,6 +269,14 @@ declare function parseNextTool(literal: string): {
|
|
|
269
269
|
interface NextStepTarget<TArgs> {
|
|
270
270
|
role: NextToolServerRole;
|
|
271
271
|
validate: (input: unknown) => string | null;
|
|
272
|
+
/**
|
|
273
|
+
* #4449: the bare tool name to render, when the target-map key is not it.
|
|
274
|
+
* One hosted tool that takes several argument shapes is declared once per
|
|
275
|
+
* shape under `<tool>#<variant>` keys (the signer's `haven_submit#payment`
|
|
276
|
+
* beside `#task_budget` / `#sub_budget`): the key selects the shape, this
|
|
277
|
+
* names the tool. Absent → the key IS the name, which is every other target.
|
|
278
|
+
*/
|
|
279
|
+
name?: string;
|
|
272
280
|
/** Phantom carrier for the argument type; never read at runtime. */
|
|
273
281
|
readonly _args?: TArgs;
|
|
274
282
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkLZHCIK7L_cjs = require('./chunk-LZHCIK7L.cjs');
|
|
4
4
|
var viem = require('viem');
|
|
5
5
|
var crypto = require('crypto');
|
|
6
6
|
var secp256k1 = require('@noble/curves/secp256k1');
|
|
7
7
|
var accounts = require('viem/accounts');
|
|
8
8
|
|
|
9
9
|
var TYPED_DATA_NOT_ALLOWED = "TYPED_DATA_NOT_ALLOWED";
|
|
10
|
-
var HavenTypedDataRefusedError = class extends
|
|
10
|
+
var HavenTypedDataRefusedError = class extends chunkLZHCIK7L_cjs.HavenSigningError {
|
|
11
11
|
constructor(message) {
|
|
12
12
|
super(message);
|
|
13
13
|
this.code = TYPED_DATA_NOT_ALLOWED;
|
|
@@ -48,7 +48,7 @@ function assertBoundDirectPaymentUserOp(typedData, delegateAddress) {
|
|
|
48
48
|
`This signer only signs direct payments on chains the delegation rail has pinned contracts for (${[...DIRECT_PAYMENT_CHAIN_IDS].join(", ")}); this typed data names chain ${String(domain.chainId)}. Refusing.`
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
|
-
const ownAccount =
|
|
51
|
+
const ownAccount = chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress);
|
|
52
52
|
const sender = typeof message.sender === "string" ? message.sender : "";
|
|
53
53
|
if (sender.toLowerCase() !== ownAccount.toLowerCase()) {
|
|
54
54
|
throw new HavenTypedDataRefusedError(
|
|
@@ -78,9 +78,9 @@ function assertBoundDirectPaymentUserOp(typedData, delegateAddress) {
|
|
|
78
78
|
"This UserOperation's execute() call does not re-encode to the exact callData bytes (trailing or non-canonical bytes). Refusing."
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
|
-
if (decoded.target.toLowerCase() !==
|
|
81
|
+
if (decoded.target.toLowerCase() !== chunkLZHCIK7L_cjs.DELEGATION_MANAGER.toLowerCase()) {
|
|
82
82
|
throw new HavenTypedDataRefusedError(
|
|
83
|
-
`This UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${
|
|
83
|
+
`This UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${chunkLZHCIK7L_cjs.DELEGATION_MANAGER}). A direct payment only ever redeems the agent's own budget delegation \u2014 refusing what looks like a self-call (e.g. transferOwnership, updateSigners, upgradeToAndCall) or a call to an unrelated contract.`
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
86
|
if (decoded.value !== 0n) {
|
|
@@ -89,20 +89,20 @@ function assertBoundDirectPaymentUserOp(typedData, delegateAddress) {
|
|
|
89
89
|
);
|
|
90
90
|
}
|
|
91
91
|
try {
|
|
92
|
-
|
|
92
|
+
chunkLZHCIK7L_cjs.assertRedeemsOwnBudgetDelegation(decoded.callData, ownAccount);
|
|
93
93
|
} catch (err) {
|
|
94
94
|
throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
function assertOwnSettlementChild(typedData, expectation, delegateAddress) {
|
|
98
98
|
try {
|
|
99
|
-
|
|
99
|
+
chunkLZHCIK7L_cjs.verifySettlementChild(typedData, {
|
|
100
100
|
...expectation,
|
|
101
|
-
delegatorAccount:
|
|
101
|
+
delegatorAccount: chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress)
|
|
102
102
|
});
|
|
103
103
|
} catch (err) {
|
|
104
104
|
if (err instanceof HavenTypedDataRefusedError) throw err;
|
|
105
|
-
if (err instanceof
|
|
105
|
+
if (err instanceof chunkLZHCIK7L_cjs.HavenSigningError) throw new HavenTypedDataRefusedError(err.message);
|
|
106
106
|
throw new HavenTypedDataRefusedError(
|
|
107
107
|
`Refusing to sign the x402 settlement child: it is malformed (${err instanceof Error ? err.message : String(err)}).`
|
|
108
108
|
);
|
|
@@ -131,7 +131,7 @@ function assertFundingLegPaysDelegate(typedData, expected) {
|
|
|
131
131
|
try {
|
|
132
132
|
const { args: executeArgs } = viem.decodeFunctionData({ abi: EXECUTE_ABI, data: message.callData });
|
|
133
133
|
const inner = executeArgs[0].callData;
|
|
134
|
-
const { args } = viem.decodeFunctionData({ abi:
|
|
134
|
+
const { args } = viem.decodeFunctionData({ abi: chunkLZHCIK7L_cjs.REDEEM_DELEGATIONS_ABI, data: inner });
|
|
135
135
|
const executions = args[2];
|
|
136
136
|
executionCallData = executions[0];
|
|
137
137
|
} catch {
|
|
@@ -250,7 +250,7 @@ var TRANSFER_WITH_AUTHORIZATION_TYPES = {
|
|
|
250
250
|
function sweepUsdcAddress(chainId) {
|
|
251
251
|
const address = USDC_ADDRESS_BY_CHAIN[chainId];
|
|
252
252
|
if (!address) {
|
|
253
|
-
throw new
|
|
253
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError(
|
|
254
254
|
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
255
255
|
);
|
|
256
256
|
}
|
|
@@ -259,7 +259,7 @@ function sweepUsdcAddress(chainId) {
|
|
|
259
259
|
function sweepUsdcDomain(chainId) {
|
|
260
260
|
const domain = USDC_EIP712_DOMAIN_BY_CHAIN[chainId];
|
|
261
261
|
if (!domain) {
|
|
262
|
-
throw new
|
|
262
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError(
|
|
263
263
|
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
264
264
|
);
|
|
265
265
|
}
|
|
@@ -272,12 +272,12 @@ function buildSweepTypedData(auth) {
|
|
|
272
272
|
const domain = sweepUsdcDomain(auth.chainId);
|
|
273
273
|
const expectedToken = sweepUsdcAddress(auth.chainId);
|
|
274
274
|
if (!sameAddress(auth.token, expectedToken)) {
|
|
275
|
-
throw new
|
|
275
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError(
|
|
276
276
|
`Sweep token ${auth.token} is not the canonical USDC contract for chain ${auth.chainId}.`
|
|
277
277
|
);
|
|
278
278
|
}
|
|
279
279
|
if (!/^0x[0-9a-fA-F]{64}$/.test(auth.nonce)) {
|
|
280
|
-
throw new
|
|
280
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError("Sweep nonce must be a 0x-prefixed 32-byte hex string.");
|
|
281
281
|
}
|
|
282
282
|
return {
|
|
283
283
|
domain,
|
|
@@ -782,7 +782,7 @@ function stableStringify2(value) {
|
|
|
782
782
|
}
|
|
783
783
|
|
|
784
784
|
// src/client-identity.ts
|
|
785
|
-
var SDK_VERSION = "0.
|
|
785
|
+
var SDK_VERSION = "0.13.0-alpha.0";
|
|
786
786
|
var HAVEN_CLIENT_HEADER = "X-Haven-Client";
|
|
787
787
|
function havenClientIdentity(pkg, version) {
|
|
788
788
|
return `${pkg}/${version}`;
|
|
@@ -815,7 +815,7 @@ function addressFromKey(privateKey) {
|
|
|
815
815
|
try {
|
|
816
816
|
return accounts.privateKeyToAddress(`0x${hexBytes(privateKey, 32, "private key")}`);
|
|
817
817
|
} catch (err) {
|
|
818
|
-
throw new
|
|
818
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError(
|
|
819
819
|
`Invalid private key: ${err instanceof Error ? err.message : String(err)}`
|
|
820
820
|
);
|
|
821
821
|
}
|
|
@@ -829,7 +829,7 @@ function signHash(privateKey, hash) {
|
|
|
829
829
|
yParity: recovery
|
|
830
830
|
});
|
|
831
831
|
} catch (err) {
|
|
832
|
-
throw new
|
|
832
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError(
|
|
833
833
|
`Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`
|
|
834
834
|
);
|
|
835
835
|
}
|
|
@@ -865,7 +865,7 @@ var TAX_DECLARATION_TYPES = {
|
|
|
865
865
|
var X_TAX_DECLARATION_HEADER = "X-Tax-Declaration";
|
|
866
866
|
function validateContent(content) {
|
|
867
867
|
if (typeof content !== "object" || content === null || Array.isArray(content)) {
|
|
868
|
-
throw new
|
|
868
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError("Tax declaration content must be an object.");
|
|
869
869
|
}
|
|
870
870
|
const record = content;
|
|
871
871
|
for (const field of ["principalId", "principalAttributionHash"]) {
|
|
@@ -918,7 +918,7 @@ function taxPrincipalId(network, delegateAddress) {
|
|
|
918
918
|
if (network.startsWith("eip155:")) {
|
|
919
919
|
return `did:pkh:${network}:${delegateAddress}`;
|
|
920
920
|
}
|
|
921
|
-
const chainId =
|
|
921
|
+
const chainId = chunkLZHCIK7L_cjs.chainIdForNetwork(network);
|
|
922
922
|
if (chainId === void 0) {
|
|
923
923
|
throw new TaxDeclarationRefusedError(
|
|
924
924
|
`The accepted payment option's network '${network}' is not a CAIP-2 eip155 chain this SDK can name; refusing to build a tax principal without the settlement network.`
|
|
@@ -963,12 +963,12 @@ function addressFromKeyForTax(delegateKey) {
|
|
|
963
963
|
try {
|
|
964
964
|
return addressFromKey(delegateKey);
|
|
965
965
|
} catch (err) {
|
|
966
|
-
throw new
|
|
966
|
+
throw new chunkLZHCIK7L_cjs.HavenSigningError(
|
|
967
967
|
`Invalid delegate key for tax declaration signing: ${err instanceof Error ? err.message : String(err)}`
|
|
968
968
|
);
|
|
969
969
|
}
|
|
970
970
|
}
|
|
971
|
-
var TaxDeclarationRefusedError = class extends
|
|
971
|
+
var TaxDeclarationRefusedError = class extends chunkLZHCIK7L_cjs.HavenSigningError {
|
|
972
972
|
code = "TAX_DECLARATION_REFUSED";
|
|
973
973
|
constructor(message) {
|
|
974
974
|
super(message);
|
|
@@ -1027,11 +1027,12 @@ function createNextStepBuilder(targets) {
|
|
|
1027
1027
|
if (problem) {
|
|
1028
1028
|
return { ...base, next_tool_omitted_reason: `next_arguments do not parse under ${i.nextTool}: ${problem}` };
|
|
1029
1029
|
}
|
|
1030
|
+
const name = target.name ?? i.nextTool;
|
|
1030
1031
|
return {
|
|
1031
1032
|
...base,
|
|
1032
|
-
next_tool: renderNextTool(target.role,
|
|
1033
|
+
next_tool: renderNextTool(target.role, name),
|
|
1033
1034
|
next_tool_server: NEXT_TOOL_SERVER_NAMES[target.role],
|
|
1034
|
-
next_tool_name:
|
|
1035
|
+
next_tool_name: name,
|
|
1035
1036
|
next_tool_server_role: target.role,
|
|
1036
1037
|
next_arguments: i.nextArguments
|
|
1037
1038
|
};
|
|
@@ -1124,10 +1125,10 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
|
|
|
1124
1125
|
if (td?.primaryType !== "Delegation") {
|
|
1125
1126
|
refuseTaskChild("it is not a Delegation payload", `primaryType was '${String(td?.primaryType)}'.`);
|
|
1126
1127
|
}
|
|
1127
|
-
if (!same(td.domain?.verifyingContract,
|
|
1128
|
+
if (!same(td.domain?.verifyingContract, chunkLZHCIK7L_cjs.DELEGATION_MANAGER)) {
|
|
1128
1129
|
refuseTaskChild(
|
|
1129
1130
|
"the EIP-712 domain names an unknown DelegationManager",
|
|
1130
|
-
`Expected ${
|
|
1131
|
+
`Expected ${chunkLZHCIK7L_cjs.DELEGATION_MANAGER}, got ${td.domain?.verifyingContract}.`
|
|
1131
1132
|
);
|
|
1132
1133
|
}
|
|
1133
1134
|
if (td.domain?.name !== DELEGATION_DOMAIN_NAME || td.domain?.version !== DELEGATION_DOMAIN_VERSION) {
|
|
@@ -1155,7 +1156,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
|
|
|
1155
1156
|
`Expected chain ${expected.chainId}; the child says ${td.domain?.chainId}.`
|
|
1156
1157
|
);
|
|
1157
1158
|
}
|
|
1158
|
-
const ownAccount =
|
|
1159
|
+
const ownAccount = chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress);
|
|
1159
1160
|
const delegator = td.message?.delegator;
|
|
1160
1161
|
if (typeof delegator !== "string" || !same(delegator, ownAccount)) {
|
|
1161
1162
|
refuseTaskChild(
|
|
@@ -1174,7 +1175,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
|
|
|
1174
1175
|
if (typeof authority !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(authority)) {
|
|
1175
1176
|
refuseTaskChild("its authority is not a 32-byte delegation hash", `Got ${String(authority)}.`);
|
|
1176
1177
|
}
|
|
1177
|
-
if (authority.toLowerCase() ===
|
|
1178
|
+
if (authority.toLowerCase() === chunkLZHCIK7L_cjs.ROOT_AUTHORITY) {
|
|
1178
1179
|
refuseTaskChild(
|
|
1179
1180
|
"it is a ROOT delegation, not a re-delegation of the agent budget",
|
|
1180
1181
|
"A task budget always chains under the agent budget delegation."
|
|
@@ -1187,7 +1188,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
|
|
|
1187
1188
|
);
|
|
1188
1189
|
}
|
|
1189
1190
|
const caveats = td.message?.caveats ?? [];
|
|
1190
|
-
const transfer = findCaveat(caveats,
|
|
1191
|
+
const transfer = findCaveat(caveats, chunkLZHCIK7L_cjs.CAVEAT_ENFORCERS.erc20TransferAmount);
|
|
1191
1192
|
if (!transfer) {
|
|
1192
1193
|
refuseTaskChild(
|
|
1193
1194
|
"it has no ERC-20 transfer-amount caveat",
|
|
@@ -1205,7 +1206,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
|
|
|
1205
1206
|
`Expected ${expected.maxAmountAtomic}; the child allows ${amount.toString()}.`
|
|
1206
1207
|
);
|
|
1207
1208
|
}
|
|
1208
|
-
const timestamp = findCaveat(caveats,
|
|
1209
|
+
const timestamp = findCaveat(caveats, chunkLZHCIK7L_cjs.CAVEAT_ENFORCERS.timestamp);
|
|
1209
1210
|
if (!timestamp) {
|
|
1210
1211
|
refuseTaskChild("it never expires", "A task-budget child without a timestamp caveat is open-ended.");
|
|
1211
1212
|
}
|
|
@@ -1226,7 +1227,7 @@ function assertOwnTaskChild(typedData, expected, delegateAddress, now = Date.now
|
|
|
1226
1227
|
`Expected ${expected.expiresAt}; the child says ${beforeThreshold}.`
|
|
1227
1228
|
);
|
|
1228
1229
|
}
|
|
1229
|
-
const calldata = findCaveat(caveats,
|
|
1230
|
+
const calldata = findCaveat(caveats, chunkLZHCIK7L_cjs.CAVEAT_ENFORCERS.allowedCalldata);
|
|
1230
1231
|
if (expected.recipientAddress) {
|
|
1231
1232
|
if (!calldata) {
|
|
1232
1233
|
refuseTaskChild(
|
|
@@ -1263,7 +1264,7 @@ var DISABLE_DELEGATION_ABI = [
|
|
|
1263
1264
|
{
|
|
1264
1265
|
type: "function",
|
|
1265
1266
|
name: "disableDelegation",
|
|
1266
|
-
inputs: [{ name: "delegation", type: "tuple", components:
|
|
1267
|
+
inputs: [{ name: "delegation", type: "tuple", components: chunkLZHCIK7L_cjs.DELEGATION_TUPLE_COMPONENTS }],
|
|
1267
1268
|
outputs: [],
|
|
1268
1269
|
stateMutability: "nonpayable"
|
|
1269
1270
|
}
|
|
@@ -1282,7 +1283,7 @@ function assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress) {
|
|
|
1282
1283
|
`This signer only signs a task-budget close on chains the delegation rail has pinned contracts for (${[...DIRECT_PAYMENT_CHAIN_IDS].join(", ")}); this typed data names chain ${String(domain.chainId)}. Refusing.`
|
|
1283
1284
|
);
|
|
1284
1285
|
}
|
|
1285
|
-
const ownAccount =
|
|
1286
|
+
const ownAccount = chunkLZHCIK7L_cjs.deriveDelegateAccountAddress(delegateAddress);
|
|
1286
1287
|
const sender = typeof message.sender === "string" ? message.sender : "";
|
|
1287
1288
|
if (sender.toLowerCase() !== ownAccount.toLowerCase()) {
|
|
1288
1289
|
throw new HavenTypedDataRefusedError(
|
|
@@ -1305,9 +1306,9 @@ function assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress) {
|
|
|
1305
1306
|
"This close UserOperation's execute() call does not re-encode to the exact callData bytes (trailing or non-canonical bytes). Refusing."
|
|
1306
1307
|
);
|
|
1307
1308
|
}
|
|
1308
|
-
if (decoded.target.toLowerCase() !==
|
|
1309
|
+
if (decoded.target.toLowerCase() !== chunkLZHCIK7L_cjs.DELEGATION_MANAGER.toLowerCase()) {
|
|
1309
1310
|
throw new HavenTypedDataRefusedError(
|
|
1310
|
-
`This close UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${
|
|
1311
|
+
`This close UserOperation's execute() calls ${decoded.target}, not the DelegationManager (${chunkLZHCIK7L_cjs.DELEGATION_MANAGER}). Refusing what looks like a self-call or a call to an unrelated contract.`
|
|
1311
1312
|
);
|
|
1312
1313
|
}
|
|
1313
1314
|
if (decoded.value !== 0n) {
|
|
@@ -1344,7 +1345,7 @@ function assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress) {
|
|
|
1344
1345
|
`This close UserOperation disables a delegation granted to ${delegation.delegate}, not this signer's own account (${ownAccount}) \u2014 a task-budget child is always self-delegated. Refusing.`
|
|
1345
1346
|
);
|
|
1346
1347
|
}
|
|
1347
|
-
if (delegation.authority.toLowerCase() ===
|
|
1348
|
+
if (delegation.authority.toLowerCase() === chunkLZHCIK7L_cjs.ROOT_AUTHORITY) {
|
|
1348
1349
|
throw new HavenTypedDataRefusedError(
|
|
1349
1350
|
"This close UserOperation disables a ROOT delegation, not a re-delegation of the agent budget. A task-budget child always chains under the agent budget delegation. Refusing."
|
|
1350
1351
|
);
|
|
@@ -1477,5 +1478,5 @@ exports.x402PaymentHeaderNamesFor = x402PaymentHeaderNamesFor;
|
|
|
1477
1478
|
exports.x402PaymentHeaderNamesSent = x402PaymentHeaderNamesSent;
|
|
1478
1479
|
exports.x402RetryHeadersFor = x402RetryHeadersFor;
|
|
1479
1480
|
exports.x402V2PaymentEnvelope = x402V2PaymentEnvelope;
|
|
1480
|
-
//# sourceMappingURL=chunk-
|
|
1481
|
-
//# sourceMappingURL=chunk-
|
|
1481
|
+
//# sourceMappingURL=chunk-4Z7PKLFD.cjs.map
|
|
1482
|
+
//# sourceMappingURL=chunk-4Z7PKLFD.cjs.map
|