@haven_ai/sdk 0.1.3 → 0.1.5

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/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { AsyncLocalStorage } from 'async_hooks';
1
2
  import { exact } from 'x402/schemes';
2
3
  import { privateKeyToAccount } from 'viem/accounts';
3
4
  import { ethers } from 'ethers';
@@ -6,6 +7,114 @@ import { createHash } from 'crypto';
6
7
  // src/client.ts
7
8
 
8
9
  // src/types.ts
10
+ var AgentPaymentPhase = {
11
+ /** The agent must sign and submit the prepared payment before Haven can relay it. */
12
+ AgentSignatureRequired: "agent_signature_required",
13
+ /** Haven has received the signed payment and the agent should poll for confirmation. */
14
+ PaymentSubmitted: "payment_submitted",
15
+ /** The direct payment is confirmed; the agent does not need to do more for this payment id. */
16
+ PaymentConfirmed: "payment_confirmed",
17
+ /** The payment needs wallet owner approval in Haven before it can continue. */
18
+ UserApprovalRequired: "user_approval_required",
19
+ /** The wallet owner approved the request and still needs to complete the funding payment. */
20
+ UserExecutionRequired: "user_execution_required",
21
+ /** The funding payment was proposed and is waiting for the remaining account approvals. */
22
+ WaitingForAdditionalApprovals: "waiting_for_additional_approvals",
23
+ /** The Haven funding leg was sent; the agent can continue the merchant/protocol leg. */
24
+ FundingSent: "funding_sent",
25
+ /** The wallet owner rejected the request; the agent should stop and tell the user. */
26
+ Rejected: "rejected",
27
+ /** The payment or approval request expired before completion. */
28
+ Expired: "expired",
29
+ /** Haven could not complete the payment; the agent should stop and surface the failure. */
30
+ Failed: "failed"
31
+ };
32
+ var AgentPaymentNextAction = {
33
+ /** Sign with the delegate key and submit the payment to Haven. */
34
+ SignAndSubmitPayment: "sign_and_submit_payment",
35
+ /** Poll getPaymentStatus later using this payment id. */
36
+ CheckStatusLater: "check_status_later",
37
+ /** No further agent action is required for this payment id. */
38
+ None: "none",
39
+ /** Wait for the wallet owner to approve or reject the request in Haven. */
40
+ WaitForUserApproval: "wait_for_user_approval",
41
+ /** Wait for the wallet owner to finish sending the approved funding payment. */
42
+ WaitForUserToCompletePayment: "wait_for_user_to_complete_payment",
43
+ /** Resume this payment id and retry the original x402 request with the merchant payment header. */
44
+ RetryOriginalX402Request: "retry_original_x402_request",
45
+ /** Stop retrying this payment and tell the user what happened. */
46
+ StopAndTellUser: "stop_and_tell_user",
47
+ /** Ask again only if the user still wants the payment after expiry. */
48
+ RequestAgainIfUserStillWantsIt: "request_again_if_user_still_wants_it"
49
+ };
50
+ var AgentPaymentRail = {
51
+ /** Standard Haven payment from the user's Safe through an approved delegate allowance. */
52
+ Direct: "direct",
53
+ /** x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg. */
54
+ X402: "x402",
55
+ /** Machine Payment Protocol family — categorical value used as a resume-state discriminator. */
56
+ Mpp: "mpp",
57
+ /** Haven internal MPP demo rail. Not for production traffic. */
58
+ MppDemo: "mpp_demo",
59
+ /** Crypto-settled MPP rail. */
60
+ MppCrypto: "mpp_crypto",
61
+ /** Stripe-deposit-backed MPP rail. */
62
+ StripeDeposit: "stripe_deposit",
63
+ /** Stripe Payment Token MPP rail. */
64
+ Spt: "spt"
65
+ };
66
+ var AGENT_PAYMENT_PHASE_VALUES = Object.values(AgentPaymentPhase);
67
+ var AGENT_PAYMENT_NEXT_ACTION_VALUES = Object.values(AgentPaymentNextAction);
68
+ var AGENT_PAYMENT_RAIL_VALUES = Object.values(AgentPaymentRail);
69
+ var AgentPaymentPhaseDescriptions = {
70
+ [AgentPaymentPhase.AgentSignatureRequired]: "The agent must sign and submit the prepared payment before Haven can relay it.",
71
+ [AgentPaymentPhase.PaymentSubmitted]: "Haven has received the signed payment and the agent should poll for confirmation.",
72
+ [AgentPaymentPhase.PaymentConfirmed]: "The direct payment is confirmed; the agent does not need to do more for this payment id.",
73
+ [AgentPaymentPhase.UserApprovalRequired]: "The payment needs wallet owner approval in Haven before it can continue.",
74
+ [AgentPaymentPhase.UserExecutionRequired]: "The wallet owner approved the request and still needs to complete the funding payment.",
75
+ [AgentPaymentPhase.WaitingForAdditionalApprovals]: "The funding payment was proposed and is waiting for the remaining account approvals.",
76
+ [AgentPaymentPhase.FundingSent]: "The Haven funding leg was sent; the agent can continue the merchant/protocol leg.",
77
+ [AgentPaymentPhase.Rejected]: "The wallet owner rejected the request; the agent should stop and tell the user.",
78
+ [AgentPaymentPhase.Expired]: "The payment or approval request expired before completion.",
79
+ [AgentPaymentPhase.Failed]: "Haven could not complete the payment; the agent should stop and surface the failure."
80
+ };
81
+ var AgentPaymentNextActionDescriptions = {
82
+ [AgentPaymentNextAction.SignAndSubmitPayment]: "Sign with the delegate key and submit the payment to Haven.",
83
+ [AgentPaymentNextAction.CheckStatusLater]: "Poll getPaymentStatus later using this payment id.",
84
+ [AgentPaymentNextAction.None]: "No further agent action is required for this payment id.",
85
+ [AgentPaymentNextAction.WaitForUserApproval]: "Wait for the wallet owner to approve or reject the request in Haven.",
86
+ [AgentPaymentNextAction.WaitForUserToCompletePayment]: "Wait for the wallet owner to finish sending the approved funding payment.",
87
+ [AgentPaymentNextAction.RetryOriginalX402Request]: "Resume this payment id and retry the original x402 request with the merchant payment header.",
88
+ [AgentPaymentNextAction.StopAndTellUser]: "Stop retrying this payment and tell the user what happened.",
89
+ [AgentPaymentNextAction.RequestAgainIfUserStillWantsIt]: "Ask again only if the user still wants the payment after expiry."
90
+ };
91
+ var AgentPaymentRailDescriptions = {
92
+ [AgentPaymentRail.Direct]: "Standard Haven payment from the user-controlled Safe through an approved delegate allowance.",
93
+ [AgentPaymentRail.X402]: "x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg.",
94
+ [AgentPaymentRail.Mpp]: "Categorical MPP rail value used as a resume-state discriminator. Response bodies carry a granular mpp_* value instead.",
95
+ [AgentPaymentRail.MppDemo]: "Haven internal MPP demo rail. Not for production traffic.",
96
+ [AgentPaymentRail.MppCrypto]: "Crypto-settled MPP rail.",
97
+ [AgentPaymentRail.StripeDeposit]: "Stripe-deposit-backed MPP rail.",
98
+ [AgentPaymentRail.Spt]: "Stripe Payment Token MPP rail."
99
+ };
100
+ var AgentPaymentPhaseSchema = {
101
+ type: "string",
102
+ enum: AGENT_PAYMENT_PHASE_VALUES,
103
+ description: "Stable Haven agent payment state phase.",
104
+ "x-enumDescriptions": AgentPaymentPhaseDescriptions
105
+ };
106
+ var AgentPaymentNextActionSchema = {
107
+ type: "string",
108
+ enum: AGENT_PAYMENT_NEXT_ACTION_VALUES,
109
+ description: "Stable next action an agent should take for a Haven payment state.",
110
+ "x-enumDescriptions": AgentPaymentNextActionDescriptions
111
+ };
112
+ var AgentPaymentRailSchema = {
113
+ type: "string",
114
+ enum: AGENT_PAYMENT_RAIL_VALUES,
115
+ description: "Stable rail identifier for Haven agent payment states.",
116
+ "x-enumDescriptions": AgentPaymentRailDescriptions
117
+ };
9
118
  var HavenError = class extends Error {
10
119
  constructor(message, code, statusCode, paymentId) {
11
120
  super(message);
@@ -33,6 +142,7 @@ var HavenPaymentStateError = class extends HavenApiError {
33
142
  this.name = "HavenPaymentStateError";
34
143
  }
35
144
  state;
145
+ resumeState;
36
146
  get status() {
37
147
  return this.state.status;
38
148
  }
@@ -160,6 +270,10 @@ var BASE_TOKENS = {
160
270
  "0x0000000000000000000000000000000000000000": { symbol: "ETH", decimals: 18 },
161
271
  "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913": { symbol: "USDC", decimals: 6 }
162
272
  };
273
+ var ALL_TOKENS = {
274
+ ...GNOSIS_TOKENS,
275
+ ...BASE_TOKENS
276
+ };
163
277
  var NETWORK_TOKENS = {
164
278
  "eip155:100": GNOSIS_TOKENS,
165
279
  "eip155:8453": BASE_TOKENS,
@@ -221,6 +335,23 @@ function selectStandardPaymentOption(accepts) {
221
335
  }
222
336
  return null;
223
337
  }
338
+ function x402AuthorizationAmount(option) {
339
+ return option.maxAmountRequired ?? option.amount;
340
+ }
341
+ function buildX402ExpectedMessage(context) {
342
+ return `Haven x402 expected context v1
343
+ ${stableStringify({
344
+ version: 1,
345
+ kind: "haven.x402.expected",
346
+ paymentId: context.paymentId,
347
+ payloadHash: context.payloadHash.toLowerCase(),
348
+ resourceUrl: context.resourceUrl,
349
+ merchantTo: context.merchantTo.toLowerCase(),
350
+ amount: context.amount,
351
+ asset: context.asset.toLowerCase(),
352
+ network: context.network
353
+ })}`;
354
+ }
224
355
  function toStandardPaymentRequirements(paymentRequired, option) {
225
356
  const network = STANDARD_X402_NETWORKS[option.network];
226
357
  if (!network) {
@@ -232,7 +363,7 @@ function toStandardPaymentRequirements(paymentRequired, option) {
232
363
  return {
233
364
  scheme: "exact",
234
365
  network,
235
- maxAmountRequired: option.maxAmountRequired ?? option.amount,
366
+ maxAmountRequired: x402AuthorizationAmount(option),
236
367
  resource: option.resource ?? paymentRequired.resource.url,
237
368
  description: option.description ?? paymentRequired.resource.description ?? "Haven x402 payment",
238
369
  mimeType: option.mimeType ?? paymentRequired.resource.mimeType ?? "application/octet-stream",
@@ -249,7 +380,7 @@ function buildX402IdempotencyKey(paymentRequired, option, now = Date.now()) {
249
380
  paymentRequired.resource.description ?? "",
250
381
  option.payTo.toLowerCase(),
251
382
  option.asset.toLowerCase(),
252
- option.amount,
383
+ x402AuthorizationAmount(option),
253
384
  option.network,
254
385
  bucket
255
386
  ].join("|");
@@ -271,6 +402,22 @@ function encodePaymentProof(receipt) {
271
402
  };
272
403
  return btoa(JSON.stringify(payload));
273
404
  }
405
+ function resolveTokenFromAddress(address, network) {
406
+ const lower = address.toLowerCase();
407
+ if (network && network in NETWORK_TOKENS) {
408
+ return NETWORK_TOKENS[network][lower] ?? null;
409
+ }
410
+ return ALL_TOKENS[lower] ?? null;
411
+ }
412
+ function stableStringify(value) {
413
+ if (value === null || typeof value !== "object") {
414
+ const primitive = JSON.stringify(value);
415
+ return primitive === void 0 ? "undefined" : primitive;
416
+ }
417
+ if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(",")}]`;
418
+ const object = value;
419
+ return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
420
+ }
274
421
  function decodeBase64Json2(value, label) {
275
422
  try {
276
423
  return JSON.parse(atob(value));
@@ -380,30 +527,33 @@ function chainIdFromNetwork(network) {
380
527
  const chainId = Number(network.slice("eip155:".length));
381
528
  return Number.isFinite(chainId) ? chainId : void 0;
382
529
  }
530
+ function chainIdOrNull(network) {
531
+ return chainIdFromNetwork(network) ?? null;
532
+ }
383
533
  function phaseForStatus(status) {
384
- if (status === "pending_signature") return "agent_signature_required";
385
- if (status === "submitted") return "payment_submitted";
386
- if (status === "confirmed") return "payment_confirmed";
387
- if (status === "pending" || status === "pending_approval") return "user_approval_required";
388
- if (status === "approved") return "user_execution_required";
389
- if (status === "proposed") return "waiting_for_additional_approvals";
390
- if (status === "executed") return "funding_sent";
391
- if (status === "rejected") return "rejected";
392
- if (status === "expired") return "expired";
393
- if (status === "failed") return "failed";
534
+ if (status === "pending_signature") return AgentPaymentPhase.AgentSignatureRequired;
535
+ if (status === "submitted") return AgentPaymentPhase.PaymentSubmitted;
536
+ if (status === "confirmed") return AgentPaymentPhase.PaymentConfirmed;
537
+ if (status === "pending" || status === "pending_approval") return AgentPaymentPhase.UserApprovalRequired;
538
+ if (status === "approved") return AgentPaymentPhase.UserExecutionRequired;
539
+ if (status === "proposed") return AgentPaymentPhase.WaitingForAdditionalApprovals;
540
+ if (status === "executed") return AgentPaymentPhase.FundingSent;
541
+ if (status === "rejected") return AgentPaymentPhase.Rejected;
542
+ if (status === "expired") return AgentPaymentPhase.Expired;
543
+ if (status === "failed") return AgentPaymentPhase.Failed;
394
544
  return null;
395
545
  }
396
546
  function nextActionForStatus(status) {
397
- if (status === "pending_signature") return "sign_and_submit_payment";
398
- if (status === "submitted") return "check_status_later";
399
- if (status === "confirmed") return "none";
400
- if (status === "pending" || status === "pending_approval") return "wait_for_user_approval";
401
- if (status === "approved") return "wait_for_user_to_complete_payment";
402
- if (status === "proposed") return "wait_for_user_approval";
403
- if (status === "executed") return "retry_original_x402_request";
404
- if (status === "rejected") return "stop_and_tell_user";
405
- if (status === "expired") return "request_again_if_user_still_wants_it";
406
- if (status === "failed") return "stop_and_tell_user";
547
+ if (status === "pending_signature") return AgentPaymentNextAction.SignAndSubmitPayment;
548
+ if (status === "submitted") return AgentPaymentNextAction.CheckStatusLater;
549
+ if (status === "confirmed") return AgentPaymentNextAction.None;
550
+ if (status === "pending" || status === "pending_approval") return AgentPaymentNextAction.WaitForUserApproval;
551
+ if (status === "approved") return AgentPaymentNextAction.WaitForUserToCompletePayment;
552
+ if (status === "proposed") return AgentPaymentNextAction.WaitForUserApproval;
553
+ if (status === "executed") return AgentPaymentNextAction.RetryOriginalX402Request;
554
+ if (status === "rejected") return AgentPaymentNextAction.StopAndTellUser;
555
+ if (status === "expired") return AgentPaymentNextAction.RequestAgainIfUserStillWantsIt;
556
+ if (status === "failed") return AgentPaymentNextAction.StopAndTellUser;
407
557
  return null;
408
558
  }
409
559
  function messageForState(label, status, paymentId, nextAction) {
@@ -424,6 +574,9 @@ function messageForState(label, status, paymentId, nextAction) {
424
574
  function sameAddress(a, b) {
425
575
  return Boolean(a && b && a.toLowerCase() === b.toLowerCase());
426
576
  }
577
+ function isMppRail(rail) {
578
+ return rail === "mpp" || Boolean(rail?.startsWith("mpp_"));
579
+ }
427
580
  function decimalFromUsdcAtomic(value) {
428
581
  const amount = BigInt(value);
429
582
  const whole = amount / 1000000n;
@@ -454,6 +607,19 @@ var HavenClient = class {
454
607
  inFlightX402 = /* @__PURE__ */ new Map();
455
608
  x402ReceiptCache = /* @__PURE__ */ new Map();
456
609
  inFlightMachinePayments = /* @__PURE__ */ new Map();
610
+ /**
611
+ * Setup-time headers configured via `HavenClientConfig.defaultHeaders`.
612
+ * Read-only after construction — use `withRequestContext` for per-call
613
+ * scoping so concurrent requests don't race on shared mutable state.
614
+ */
615
+ defaultHeaders;
616
+ /**
617
+ * Async-local store for per-request context (currently: extra headers).
618
+ * Each `withRequestContext` invocation produces an isolated store, so
619
+ * overlapping async work — like two MCP tool dispatches in flight at
620
+ * the same time — see their own headers without stepping on each other.
621
+ */
622
+ requestContext = new AsyncLocalStorage();
457
623
  /** Delegate address derived from the private key (if provided) */
458
624
  delegateAddress;
459
625
  constructor(config) {
@@ -464,10 +630,29 @@ var HavenClient = class {
464
630
  this.requestTimeout = config.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;
465
631
  this.confirmationTimeout = config.confirmationTimeout ?? DEFAULT_CONFIRMATION_TIMEOUT;
466
632
  this.pollingInterval = config.pollingInterval ?? DEFAULT_POLLING_INTERVAL;
633
+ this.defaultHeaders = { ...config.defaultHeaders ?? {} };
467
634
  if (this.delegateKey) {
468
635
  this.delegateAddress = addressFromKey(this.delegateKey);
469
636
  }
470
637
  }
638
+ /**
639
+ * Run `fn` with extra Haven-API headers scoped to the async work it
640
+ * performs. Used by the MCP server to tag every Haven API request that
641
+ * a single tool dispatch makes with `X-Haven-MCP-Tool: <name>` so the
642
+ * backend can write an audit-log row attributing the call.
643
+ *
644
+ * The headers are held in an `AsyncLocalStorage` so overlapping
645
+ * dispatches do not leak headers into each other's requests. The store
646
+ * inherits across `await` boundaries, so any Haven API call made while
647
+ * `fn` is awaiting will pick up the right headers.
648
+ *
649
+ * Has no effect on outbound merchant requests (x402 / MPP) — those
650
+ * never go through the internal `request<T>` path that reads the
651
+ * context.
652
+ */
653
+ withRequestContext(headers, fn) {
654
+ return this.requestContext.run({ headers: { ...headers } }, fn);
655
+ }
471
656
  // ── High-Level API ───────────────────────────────────────────────
472
657
  /**
473
658
  * Send a payment in one call.
@@ -510,6 +695,70 @@ var HavenClient = class {
510
695
  signData: raw.sign_data
511
696
  };
512
697
  }
698
+ /**
699
+ * Keyless x402 construct.
700
+ *
701
+ * The non-custodial half of an x402 payment: posts the funding request to
702
+ * `/x402` and returns the unsigned funding hash plus the data the caller
703
+ * needs to build and sign the EIP-3009 merchant header itself. Crucially it
704
+ * does **not** sign — neither the funding hash nor the merchant header — so
705
+ * it works without a `delegateKey`. Both delegate signatures happen on the
706
+ * machine that holds the key (the edge); the hosted MCP server relays only.
707
+ *
708
+ * Use this from the hosted, keyless server. The all-in-one `authorizeX402`
709
+ * remains for local clients that hold the key.
710
+ *
711
+ * Throws (via the shared payment-state path) when the amount exceeds the
712
+ * on-chain allowance — there is nothing to sign until the user approves.
713
+ */
714
+ async createX402Intent(paymentRequired, options = {}) {
715
+ const option = selectStandardPaymentOption(paymentRequired.accepts);
716
+ if (!option) {
717
+ throw new HavenApiError(
718
+ "No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
719
+ 400
720
+ );
721
+ }
722
+ const agent = await this.getAgent();
723
+ const fundingTo = agent.delegateAddress;
724
+ if (!fundingTo) {
725
+ throw new HavenApiError("Authenticated agent has no delegate address registered.", 502);
726
+ }
727
+ const idempotencyKey = options.idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option);
728
+ const raw = await this.post("/x402", {
729
+ url: paymentRequired.resource.url,
730
+ payTo: fundingTo,
731
+ merchantPayTo: option.payTo,
732
+ amount: x402AuthorizationAmount(option),
733
+ asset: option.asset,
734
+ network: option.network,
735
+ description: paymentRequired.resource.description,
736
+ idempotencyKey
737
+ });
738
+ if (raw.status !== "pending_signature") {
739
+ this.throwPaymentStateError("x402 payment", raw);
740
+ }
741
+ if (!raw.sign_data?.hash) {
742
+ throw new HavenApiError("No sign_hash returned from x402/authorize", 500, raw);
743
+ }
744
+ if (!raw.x402_expected_auth) {
745
+ throw new HavenApiError("No x402 expected-context binding returned from x402/authorize", 500, raw);
746
+ }
747
+ return {
748
+ paymentId: raw.payment_id,
749
+ status: "pending_signature",
750
+ expiresAt: raw.expires_at,
751
+ signData: raw.sign_data,
752
+ accepted: option,
753
+ resourceUrl: paymentRequired.resource.url,
754
+ merchantTo: raw.merchant_to ?? option.payTo,
755
+ amountAtomic: x402AuthorizationAmount(option),
756
+ asset: option.asset,
757
+ network: option.network,
758
+ expectedAuth: raw.x402_expected_auth,
759
+ fundingTo
760
+ };
761
+ }
513
762
  /**
514
763
  * Step 2: Sign a hash with the delegate key.
515
764
  *
@@ -562,6 +811,66 @@ var HavenClient = class {
562
811
  const raw = await this.get(`/machine-payments/${paymentId}/status`);
563
812
  return this.mapPaymentStatusResult(raw);
564
813
  }
814
+ /**
815
+ * Get the agent identity tied to this API key.
816
+ */
817
+ async getAgent() {
818
+ const raw = await this.get("/machine-payments/agent");
819
+ return {
820
+ id: raw.id,
821
+ name: raw.name,
822
+ status: raw.status,
823
+ safeAddress: raw.safe_address,
824
+ delegateAddress: raw.delegate_address,
825
+ chainId: raw.chain_id
826
+ };
827
+ }
828
+ /**
829
+ * Get configured and on-chain allowances for the authenticated agent.
830
+ */
831
+ async getAllowances() {
832
+ const raw = await this.get("/machine-payments/allowances");
833
+ return {
834
+ agentId: raw.agent_id,
835
+ safeAddress: raw.safe_address,
836
+ delegateAddress: raw.delegate_address,
837
+ chainId: raw.chain_id,
838
+ allowances: raw.allowances.map((allowance) => ({
839
+ id: allowance.id,
840
+ tokenAddress: allowance.token_address,
841
+ tokenSymbol: allowance.token_symbol,
842
+ configuredAmount: allowance.configured_amount,
843
+ resetPeriodMin: allowance.reset_period_min,
844
+ onchain: {
845
+ amount: allowance.onchain.amount,
846
+ spent: allowance.onchain.spent,
847
+ remaining: allowance.onchain.remaining,
848
+ effectiveSpent: allowance.onchain.effective_spent,
849
+ resetTimeMin: allowance.onchain.reset_time_min,
850
+ lastResetMin: allowance.onchain.last_reset_min,
851
+ nonce: allowance.onchain.nonce,
852
+ isResetPending: allowance.onchain.is_reset_pending
853
+ }
854
+ }))
855
+ };
856
+ }
857
+ /**
858
+ * List recent machine-payment receipts/evidence for bookkeeping.
859
+ */
860
+ async listReceipts(options = {}) {
861
+ const query = options.limit ? `?limit=${encodeURIComponent(String(options.limit))}` : "";
862
+ const raw = await this.get(`/machine-payments/receipts${query}`);
863
+ return raw.receipts.map((receipt) => this.mapPaymentReceipt(receipt));
864
+ }
865
+ /**
866
+ * Rehydrate the x402/MPP resume-state bundle for a payment id.
867
+ *
868
+ * The server returns stored protocol context only. The client still signs the
869
+ * merchant proof locally when resumeX402Payment() or resumeMppPayment() runs.
870
+ */
871
+ async getResumeState(paymentId) {
872
+ return this.get(`/payments/${paymentId}/resume_state`);
873
+ }
565
874
  /**
566
875
  * Poll until a payment reaches a terminal status (confirmed, failed, expired).
567
876
  */
@@ -611,17 +920,69 @@ var HavenClient = class {
611
920
  this.inFlightX402.set(idempotencyKey, promise);
612
921
  try {
613
922
  return await promise;
923
+ } catch (err) {
924
+ this.attachResumeState(err, {
925
+ rail: "x402",
926
+ paymentRequired,
927
+ accepted: option,
928
+ idempotencyKey
929
+ });
930
+ throw err;
614
931
  } finally {
615
932
  this.inFlightX402.delete(idempotencyKey);
616
933
  }
617
934
  }
935
+ /**
936
+ * Probe a paid endpoint and return its x402 quote without creating a Haven
937
+ * payment or approval request.
938
+ */
939
+ async quoteX402(url, init, options = {}) {
940
+ const initialInit = this.withX402Wallet(init, this.x402PayerAddress());
941
+ const request = this.snapshotX402Request(url, initialInit);
942
+ const response = await globalThis.fetch(url, initialInit);
943
+ if (response.status !== 402) {
944
+ throw new HavenApiError(
945
+ `Expected an x402 quote response with HTTP 402, got HTTP ${response.status}.`,
946
+ response.status || 400
947
+ );
948
+ }
949
+ if (response.headers.get("MACHINE-PAYMENT-CHALLENGE")) {
950
+ throw new HavenApiError("quoteX402 only supports standard x402 Payment Required responses.", 400);
951
+ }
952
+ const paymentRequired = await parsePaymentRequiredResponse(response);
953
+ return this.buildX402Quote(paymentRequired, request, options.idempotencyKey);
954
+ }
955
+ /**
956
+ * Pay a previously inspected x402 quote and retry the exact captured request.
957
+ */
958
+ async payX402Quote(quote, options = {}) {
959
+ const idempotencyKey = options.idempotencyKey ?? quote.idempotencyKey;
960
+ try {
961
+ const receipt = await this.authorizeX402(quote.paymentRequired, { idempotencyKey });
962
+ return this.retryX402Request(
963
+ quote.request.url,
964
+ this.requestInitFromSnapshot(quote.request),
965
+ quote.paymentRequired,
966
+ receipt
967
+ );
968
+ } catch (err) {
969
+ this.attachResumeState(err, {
970
+ rail: "x402",
971
+ paymentRequired: quote.paymentRequired,
972
+ accepted: quote.accepted,
973
+ idempotencyKey,
974
+ request: quote.request
975
+ });
976
+ throw err;
977
+ }
978
+ }
618
979
  async authorizeStandardX402(paymentRequired, option, idempotencyKey) {
619
980
  const paymentHeader = await this.createStandardX402Header(paymentRequired, option);
620
981
  const raw = await this.post("/x402", {
621
982
  url: paymentRequired.resource.url,
622
983
  payTo: this.delegateAddress,
623
984
  merchantPayTo: option.payTo,
624
- amount: option.amount,
985
+ amount: x402AuthorizationAmount(option),
625
986
  asset: option.asset,
626
987
  network: option.network,
627
988
  description: paymentRequired.resource.description,
@@ -633,7 +994,7 @@ var HavenClient = class {
633
994
  return receipt2;
634
995
  }
635
996
  const state = this.paymentStateFromRaw("x402 payment", raw);
636
- if (state?.nextAction === "retry_original_x402_request") {
997
+ if (state?.nextAction === AgentPaymentNextAction.RetryOriginalX402Request) {
637
998
  const receipt2 = this.mapX402ReceiptFromStatus(paymentRequired, option, paymentHeader, state);
638
999
  this.cacheX402Receipt(idempotencyKey, paymentHeader, receipt2);
639
1000
  return receipt2;
@@ -681,10 +1042,18 @@ var HavenClient = class {
681
1042
  return receipt;
682
1043
  }
683
1044
  async resumeX402Payment(input) {
684
- const initialInit = this.withX402Wallet(input.init, this.x402PayerAddress());
1045
+ const inputInit = "init" in input ? input.init : void 0;
1046
+ const initialInit = this.withX402Wallet(
1047
+ inputInit ?? (input.request ? this.requestInitFromSnapshot(input.request) : void 0),
1048
+ this.x402PayerAddress()
1049
+ );
685
1050
  let paymentRequired = input.paymentRequired;
1051
+ const url = input.url ?? input.request?.url;
686
1052
  if (!paymentRequired) {
687
- const response = await globalThis.fetch(input.url, initialInit);
1053
+ if (!url) {
1054
+ throw new HavenApiError("x402 resume requires the original URL or a captured request snapshot.", 400);
1055
+ }
1056
+ const response = await globalThis.fetch(url, initialInit);
688
1057
  if (response.status !== 402) {
689
1058
  throw new HavenApiError("Expected the original x402 request to return HTTP 402 before resuming.", 400);
690
1059
  }
@@ -695,7 +1064,7 @@ var HavenClient = class {
695
1064
  paymentRequired,
696
1065
  idempotencyKey: input.idempotencyKey
697
1066
  });
698
- return this.retryX402Request(input.url, initialInit, paymentRequired, receipt);
1067
+ return this.retryX402Request(url ?? paymentRequired.resource.url, initialInit, paymentRequired, receipt);
699
1068
  }
700
1069
  /**
701
1070
  * Fetch wrapper that automatically handles HTTP 402 responses.
@@ -731,9 +1100,69 @@ var HavenClient = class {
731
1100
  }
732
1101
  return this.fetchWithMachinePayment(url, initialInit, challenge);
733
1102
  }
734
- const receipt = await this.authorizeX402(paymentRequired, options);
1103
+ const request = this.snapshotX402Request(url, initialInit);
1104
+ const option = selectStandardPaymentOption(paymentRequired.accepts);
1105
+ const idempotencyKey = options.idempotencyKey ?? (option ? buildX402IdempotencyKey(paymentRequired, option) : void 0);
1106
+ let receipt;
1107
+ try {
1108
+ receipt = await this.authorizeX402(paymentRequired, options);
1109
+ } catch (err) {
1110
+ if (option && idempotencyKey) {
1111
+ this.attachResumeState(err, {
1112
+ rail: "x402",
1113
+ paymentRequired,
1114
+ accepted: option,
1115
+ idempotencyKey,
1116
+ request
1117
+ });
1118
+ }
1119
+ throw err;
1120
+ }
735
1121
  return this.retryX402Request(url, initialInit, paymentRequired, receipt);
736
1122
  }
1123
+ /**
1124
+ * Probe a paid MPP endpoint or inspect an existing challenge without creating
1125
+ * a Haven payment or approval request.
1126
+ */
1127
+ async quoteMpp(challengeOrUrl, init, options = {}) {
1128
+ if (typeof challengeOrUrl !== "string") {
1129
+ const request2 = this.snapshotX402Request(challengeOrUrl.resource, init);
1130
+ return this.buildMppQuote(challengeOrUrl, request2, options.idempotencyKey);
1131
+ }
1132
+ const request = this.snapshotX402Request(challengeOrUrl, init);
1133
+ const response = await globalThis.fetch(challengeOrUrl, init);
1134
+ if (response.status !== 402) {
1135
+ throw new HavenApiError(
1136
+ `Expected an MPP quote response with HTTP 402, got HTTP ${response.status}.`,
1137
+ response.status || 400
1138
+ );
1139
+ }
1140
+ const challenge = await parseMachinePaymentChallengeResponse(response);
1141
+ return this.buildMppQuote(challenge, request, options.idempotencyKey);
1142
+ }
1143
+ /**
1144
+ * Pay a previously inspected MPP quote and retry the exact captured request.
1145
+ */
1146
+ async payMppChallenge(quote, options = {}) {
1147
+ const idempotencyKey = options.idempotencyKey ?? quote.idempotencyKey;
1148
+ try {
1149
+ const receipt = await this.authorizeMachinePayment(quote.challenge, { idempotencyKey });
1150
+ return this.retryMppRequest(
1151
+ quote.request.url,
1152
+ this.requestInitFromSnapshot(quote.request),
1153
+ quote.challenge,
1154
+ receipt
1155
+ );
1156
+ } catch (err) {
1157
+ this.attachResumeState(err, {
1158
+ rail: "mpp",
1159
+ challenge: quote.challenge,
1160
+ idempotencyKey,
1161
+ request: quote.request
1162
+ });
1163
+ throw err;
1164
+ }
1165
+ }
737
1166
  async retryX402Request(url, initialInit, paymentRequired, receipt) {
738
1167
  if (!receipt.accepted) {
739
1168
  throw new HavenApiError("No accepted x402 option was recorded for payment retry", 500);
@@ -795,7 +1224,7 @@ var HavenClient = class {
795
1224
  });
796
1225
  return retryResponse;
797
1226
  }
798
- async authorizeMachinePayment(challenge) {
1227
+ async authorizeMachinePayment(challenge, options = {}) {
799
1228
  if (!this.delegateKey) {
800
1229
  throw new HavenSigningError(
801
1230
  "delegateKey is required for machine payments. Pass it in the HavenClient config."
@@ -804,13 +1233,20 @@ var HavenClient = class {
804
1233
  if (challenge.rail !== "mpp_demo") {
805
1234
  throw new HavenApiError(`Unsupported machine payment rail: ${challenge.rail}`, 400);
806
1235
  }
807
- const idempotencyKey = buildMachinePaymentIdempotencyKey(challenge);
1236
+ const idempotencyKey = options.idempotencyKey ?? buildMachinePaymentIdempotencyKey(challenge);
808
1237
  const inFlight = this.inFlightMachinePayments.get(idempotencyKey);
809
1238
  if (inFlight) return inFlight;
810
1239
  const promise = this.authorizeMppDemoPayment(challenge, idempotencyKey);
811
1240
  this.inFlightMachinePayments.set(idempotencyKey, promise);
812
1241
  try {
813
1242
  return await promise;
1243
+ } catch (err) {
1244
+ this.attachResumeState(err, {
1245
+ rail: "mpp",
1246
+ challenge,
1247
+ idempotencyKey
1248
+ });
1249
+ throw err;
814
1250
  } finally {
815
1251
  this.inFlightMachinePayments.delete(idempotencyKey);
816
1252
  }
@@ -837,8 +1273,56 @@ var HavenClient = class {
837
1273
  }
838
1274
  return this.mapMachinePaymentReceipt(challenge, raw, execResult.tx_hash, execResult);
839
1275
  }
1276
+ async resumeAuthorizedMpp(input) {
1277
+ if (!this.delegateKey) {
1278
+ throw new HavenSigningError(
1279
+ "delegateKey is required for machine payments. Pass it in the HavenClient config."
1280
+ );
1281
+ }
1282
+ const status = await this.getPaymentStatus(input.paymentId);
1283
+ this.assertCanResumeMpp(status, input.challenge);
1284
+ return this.mapMachinePaymentReceiptFromStatus(input.challenge, status);
1285
+ }
1286
+ async resumeMppPayment(input) {
1287
+ const inputInit = "init" in input ? input.init : void 0;
1288
+ const initialInit = inputInit ?? (input.request ? this.requestInitFromSnapshot(input.request) : void 0);
1289
+ let challenge = input.challenge;
1290
+ const url = input.url ?? input.request?.url;
1291
+ if (!challenge) {
1292
+ if (!url) {
1293
+ throw new HavenApiError("MPP resume requires the original URL or a captured request snapshot.", 400);
1294
+ }
1295
+ const response = await globalThis.fetch(url, initialInit);
1296
+ if (response.status !== 402) {
1297
+ throw new HavenApiError("Expected the original MPP request to return HTTP 402 before resuming.", 400);
1298
+ }
1299
+ challenge = await parseMachinePaymentChallengeResponse(response);
1300
+ }
1301
+ const receipt = await this.resumeAuthorizedMpp({
1302
+ paymentId: input.paymentId,
1303
+ challenge,
1304
+ idempotencyKey: input.idempotencyKey
1305
+ });
1306
+ return this.retryMppRequest(url ?? challenge.resource, initialInit, challenge, receipt);
1307
+ }
840
1308
  async fetchWithMachinePayment(url, initialInit, challenge) {
841
- const receipt = await this.authorizeMachinePayment(challenge);
1309
+ const request = this.snapshotX402Request(url, initialInit);
1310
+ const idempotencyKey = buildMachinePaymentIdempotencyKey(challenge);
1311
+ let receipt;
1312
+ try {
1313
+ receipt = await this.authorizeMachinePayment(challenge, { idempotencyKey });
1314
+ } catch (err) {
1315
+ this.attachResumeState(err, {
1316
+ rail: "mpp",
1317
+ challenge,
1318
+ idempotencyKey,
1319
+ request
1320
+ });
1321
+ throw err;
1322
+ }
1323
+ return this.retryMppRequest(url, initialInit, challenge, receipt);
1324
+ }
1325
+ async retryMppRequest(url, initialInit, challenge, receipt) {
842
1326
  const retryHeaders = new Headers(initialInit?.headers);
843
1327
  retryHeaders.set("MACHINE-PAYMENT-PROOF", receipt.proofHeader);
844
1328
  const retryResponse = await globalThis.fetch(url, {
@@ -890,7 +1374,7 @@ var HavenClient = class {
890
1374
  status
891
1375
  );
892
1376
  }
893
- if (status.nextAction !== "retry_original_x402_request") {
1377
+ if (status.nextAction !== AgentPaymentNextAction.RetryOriginalX402Request) {
894
1378
  throw new HavenPaymentStateError(status.message, PAYMENT_STATE_STATUS_CODES[status.status] ?? 409, status);
895
1379
  }
896
1380
  if (!status.txHash) {
@@ -935,7 +1419,7 @@ var HavenClient = class {
935
1419
  );
936
1420
  }
937
1421
  const approvedAmount = status.amount ? normalizeDecimal(status.amount) : "";
938
- const requestedAmount = normalizeDecimal(decimalFromUsdcAtomic(option.amount));
1422
+ const requestedAmount = normalizeDecimal(decimalFromUsdcAtomic(x402AuthorizationAmount(option)));
939
1423
  if (approvedAmount && approvedAmount !== requestedAmount) {
940
1424
  throw new HavenApiError(
941
1425
  "x402 resume request does not match the approved amount.",
@@ -945,11 +1429,73 @@ var HavenClient = class {
945
1429
  );
946
1430
  }
947
1431
  }
1432
+ assertCanResumeMpp(status, challenge) {
1433
+ if (!isMppRail(status.rail)) {
1434
+ throw new HavenPaymentStateError(
1435
+ `Payment ${status.paymentId} is ${status.rail}, not MPP.`,
1436
+ 409,
1437
+ status
1438
+ );
1439
+ }
1440
+ if (status.nextAction !== AgentPaymentNextAction.RetryOriginalX402Request) {
1441
+ throw new HavenPaymentStateError(status.message, PAYMENT_STATE_STATUS_CODES[status.status] ?? 409, status);
1442
+ }
1443
+ if (!status.txHash) {
1444
+ throw new HavenApiError(
1445
+ `MPP payment ${status.paymentId} is ready to retry but has no Haven transaction hash.`,
1446
+ 502,
1447
+ status,
1448
+ status.paymentId
1449
+ );
1450
+ }
1451
+ if (status.resourceUrl && status.resourceUrl !== challenge.resource) {
1452
+ throw new HavenApiError(
1453
+ "MPP resume request does not match the approved resource URL.",
1454
+ 409,
1455
+ { status, challenge },
1456
+ status.paymentId
1457
+ );
1458
+ }
1459
+ if (status.merchantAddress && !sameAddress(status.merchantAddress, challenge.recipient)) {
1460
+ throw new HavenApiError(
1461
+ "MPP resume request does not match the approved merchant.",
1462
+ 409,
1463
+ { status, challenge },
1464
+ status.paymentId
1465
+ );
1466
+ }
1467
+ if (status.chainId && status.chainId !== challenge.network.chainId) {
1468
+ throw new HavenApiError(
1469
+ "MPP resume request does not match the approved network.",
1470
+ 409,
1471
+ { status, challenge },
1472
+ status.paymentId
1473
+ );
1474
+ }
1475
+ if (status.token && status.token !== challenge.asset.symbol) {
1476
+ throw new HavenApiError(
1477
+ "MPP resume request does not match the approved token.",
1478
+ 409,
1479
+ { status, challenge },
1480
+ status.paymentId
1481
+ );
1482
+ }
1483
+ const approvedAmount = status.amount ? normalizeDecimal(status.amount) : "";
1484
+ const requestedAmount = normalizeDecimal(challenge.amount.display);
1485
+ if (approvedAmount && approvedAmount !== requestedAmount) {
1486
+ throw new HavenApiError(
1487
+ "MPP resume request does not match the approved amount.",
1488
+ 409,
1489
+ { status, challenge },
1490
+ status.paymentId
1491
+ );
1492
+ }
1493
+ }
948
1494
  mapX402ReceiptFromAuthorization(paymentRequired, option, paymentHeader, raw, execResult) {
949
1495
  const txHash = execResult?.tx_hash ?? raw.tx_hash ?? "";
950
1496
  const chainId = execResult?.chain_id ?? raw.chain_id ?? chainIdFromNetwork(option.network);
951
1497
  const token = execResult?.token ?? raw.token ?? "USDC";
952
- const amount = execResult?.amount ?? raw.amount ?? decimalFromUsdcAtomic(option.amount);
1498
+ const amount = execResult?.amount ?? raw.amount ?? decimalFromUsdcAtomic(x402AuthorizationAmount(option));
953
1499
  const to = execResult?.to ?? raw.to ?? this.delegateAddress ?? "";
954
1500
  const explorerUrl = execResult?.explorer_url ?? raw.explorer_url ?? explorerUrlOrEmpty(chainId, txHash);
955
1501
  const merchantTo = execResult?.merchant_to ?? raw.merchant_to ?? option.payTo;
@@ -982,7 +1528,7 @@ var HavenClient = class {
982
1528
  paymentId: status.paymentId,
983
1529
  txHash: status.txHash,
984
1530
  token: status.token || "USDC",
985
- amount: status.amount || decimalFromUsdcAtomic(option.amount),
1531
+ amount: status.amount || decimalFromUsdcAtomic(x402AuthorizationAmount(option)),
986
1532
  to: this.delegateAddress ?? "",
987
1533
  resourceUrl: paymentRequired.resource.url,
988
1534
  explorerUrl: explorerUrlOrEmpty(status.chainId, status.txHash),
@@ -1018,7 +1564,7 @@ var HavenClient = class {
1018
1564
  payTo: input.merchantTo ?? input.accepted.payTo
1019
1565
  },
1020
1566
  x402: {
1021
- amount: input.accepted.amount,
1567
+ amount: x402AuthorizationAmount(input.accepted),
1022
1568
  token: input.token,
1023
1569
  network: input.accepted.network,
1024
1570
  asset: input.accepted.asset,
@@ -1071,6 +1617,33 @@ var HavenClient = class {
1071
1617
  proofHeader: encodeMachinePaymentProof(receiptWithoutHeader)
1072
1618
  };
1073
1619
  }
1620
+ mapMachinePaymentReceiptFromStatus(challenge, status) {
1621
+ if (!status.txHash) {
1622
+ throw new HavenApiError(
1623
+ `MPP payment ${status.paymentId} is ready to retry but has no Haven transaction hash.`,
1624
+ 502,
1625
+ status,
1626
+ status.paymentId
1627
+ );
1628
+ }
1629
+ const receiptWithoutHeader = {
1630
+ success: true,
1631
+ rail: challenge.rail,
1632
+ paymentId: status.paymentId,
1633
+ challengeId: challenge.challengeId,
1634
+ txHash: status.txHash,
1635
+ token: status.token || challenge.asset.symbol,
1636
+ amount: status.amount || challenge.amount.display,
1637
+ to: status.merchantAddress ?? challenge.recipient,
1638
+ resourceUrl: status.resourceUrl ?? challenge.resource,
1639
+ explorerUrl: explorerUrlOrEmpty(status.chainId || challenge.network.chainId, status.txHash),
1640
+ chainId: status.chainId || challenge.network.chainId
1641
+ };
1642
+ return {
1643
+ ...receiptWithoutHeader,
1644
+ proofHeader: encodeMachinePaymentProof(receiptWithoutHeader)
1645
+ };
1646
+ }
1074
1647
  async recordMerchantRetryRejected(input) {
1075
1648
  try {
1076
1649
  await this.post("/machine-payments/reconciliation-events", {
@@ -1154,16 +1727,64 @@ var HavenClient = class {
1154
1727
  amount,
1155
1728
  token,
1156
1729
  resourceUrl: raw.resource_url ?? null,
1157
- merchantAddress: raw.merchant_to ?? null,
1730
+ merchantAddress: raw.merchant_address ?? raw.merchant_to ?? null,
1158
1731
  txHash: raw.tx_hash ?? null,
1159
1732
  expiresAt: raw.expires_at ?? "",
1160
1733
  chainId: raw.chain_id ?? 0,
1161
- message
1734
+ message,
1735
+ amountAtomic: raw.amount_atomic ?? raw.x402?.amount_atomic ?? raw.mpp?.amount_atomic ?? null,
1736
+ asset: raw.asset ?? raw.x402?.asset ?? raw.mpp?.asset ?? null,
1737
+ network: raw.network ?? raw.x402?.network ?? raw.mpp?.network ?? null,
1738
+ description: raw.description ?? raw.x402?.description ?? raw.mpp?.description ?? null,
1739
+ idempotencyKey: raw.idempotency_key ?? raw.x402?.idempotency_key ?? raw.mpp?.idempotency_key ?? null,
1740
+ x402: raw.x402 ? {
1741
+ amountAtomic: raw.x402.amount_atomic ?? raw.amount_atomic ?? null,
1742
+ asset: raw.x402.asset ?? raw.asset ?? null,
1743
+ network: raw.x402.network ?? raw.network ?? null,
1744
+ resourceUrl: raw.x402.resource_url ?? raw.resource_url ?? null,
1745
+ merchantAddress: raw.x402.merchant_address ?? raw.merchant_address ?? raw.merchant_to ?? null,
1746
+ description: raw.x402.description ?? raw.description ?? null,
1747
+ idempotencyKey: raw.x402.idempotency_key ?? raw.idempotency_key ?? null
1748
+ } : void 0,
1749
+ mpp: raw.mpp ? {
1750
+ amountAtomic: raw.mpp.amount_atomic ?? raw.amount_atomic ?? null,
1751
+ asset: raw.mpp.asset ?? raw.asset ?? null,
1752
+ network: raw.mpp.network ?? raw.network ?? null,
1753
+ resourceUrl: raw.mpp.resource_url ?? raw.resource_url ?? null,
1754
+ merchantAddress: raw.mpp.merchant_address ?? raw.merchant_address ?? raw.merchant_to ?? null,
1755
+ description: raw.mpp.description ?? raw.description ?? null,
1756
+ idempotencyKey: raw.mpp.idempotency_key ?? raw.idempotency_key ?? null,
1757
+ challengeId: raw.mpp.challenge_id ?? raw.challenge_id ?? null
1758
+ } : void 0
1162
1759
  };
1163
1760
  }
1164
1761
  x402PayerAddress() {
1165
1762
  return this.delegateAddress ?? this.x402Wallet;
1166
1763
  }
1764
+ snapshotX402Request(url, init) {
1765
+ return {
1766
+ url,
1767
+ method: init?.method ?? "GET",
1768
+ headers: Array.from(new Headers(init?.headers).entries()),
1769
+ body: this.snapshotRequestBody(init?.body)
1770
+ };
1771
+ }
1772
+ snapshotRequestBody(body) {
1773
+ if (body == null) return void 0;
1774
+ if (typeof body === "string") return body;
1775
+ if (body instanceof URLSearchParams) return body.toString();
1776
+ throw new HavenApiError(
1777
+ "Quote helpers can only capture resumable request bodies that are strings or URLSearchParams. For streams, blobs, or binary bodies, preserve the original request yourself and call the matching resume method with fresh init.",
1778
+ 400
1779
+ );
1780
+ }
1781
+ requestInitFromSnapshot(request) {
1782
+ return {
1783
+ method: request.method,
1784
+ headers: request.headers,
1785
+ body: request.body
1786
+ };
1787
+ }
1167
1788
  withX402Wallet(init, wallet = this.x402PayerAddress()) {
1168
1789
  if (!wallet) return init;
1169
1790
  const headers = new Headers(init?.headers);
@@ -1175,6 +1796,134 @@ var HavenClient = class {
1175
1796
  headers
1176
1797
  };
1177
1798
  }
1799
+ buildX402Quote(paymentRequired, request, idempotencyKey) {
1800
+ const option = selectStandardPaymentOption(paymentRequired.accepts);
1801
+ if (!option) {
1802
+ throw new HavenApiError(
1803
+ "No compatible payment option found in x402 requirements. Haven supports standard x402 exact payments on Base USDC.",
1804
+ 400
1805
+ );
1806
+ }
1807
+ const token = resolveTokenFromAddress(option.asset, option.network);
1808
+ return {
1809
+ rail: "x402",
1810
+ idempotencyKey: idempotencyKey ?? buildX402IdempotencyKey(paymentRequired, option),
1811
+ paymentRequired,
1812
+ accepted: option,
1813
+ request,
1814
+ resourceUrl: paymentRequired.resource.url,
1815
+ description: paymentRequired.resource.description ?? option.description ?? null,
1816
+ mimeType: paymentRequired.resource.mimeType ?? option.mimeType ?? null,
1817
+ amountAtomic: x402AuthorizationAmount(option),
1818
+ amount: decimalFromUsdcAtomic(x402AuthorizationAmount(option)),
1819
+ token: token?.symbol ?? "USDC",
1820
+ asset: option.asset,
1821
+ network: option.network,
1822
+ chainId: chainIdOrNull(option.network),
1823
+ merchantAddress: option.payTo,
1824
+ maxTimeoutSeconds: option.maxTimeoutSeconds
1825
+ };
1826
+ }
1827
+ buildX402ResumeState(input) {
1828
+ const token = resolveTokenFromAddress(input.accepted.asset, input.accepted.network);
1829
+ return {
1830
+ rail: "x402",
1831
+ paymentId: input.paymentId,
1832
+ idempotencyKey: input.idempotencyKey,
1833
+ paymentRequired: input.paymentRequired,
1834
+ accepted: input.accepted,
1835
+ url: input.request?.url ?? input.paymentRequired.resource.url,
1836
+ request: input.request,
1837
+ resourceUrl: input.paymentRequired.resource.url,
1838
+ description: input.paymentRequired.resource.description ?? input.accepted.description ?? null,
1839
+ amountAtomic: x402AuthorizationAmount(input.accepted),
1840
+ amount: decimalFromUsdcAtomic(x402AuthorizationAmount(input.accepted)),
1841
+ token: token?.symbol ?? "USDC",
1842
+ asset: input.accepted.asset,
1843
+ network: input.accepted.network,
1844
+ chainId: chainIdOrNull(input.accepted.network),
1845
+ merchantAddress: input.accepted.payTo
1846
+ };
1847
+ }
1848
+ buildMppQuote(challenge, request, idempotencyKey) {
1849
+ return {
1850
+ rail: "mpp",
1851
+ paymentRail: challenge.rail,
1852
+ idempotencyKey: idempotencyKey ?? buildMachinePaymentIdempotencyKey(challenge),
1853
+ challenge,
1854
+ request,
1855
+ resourceUrl: challenge.resource,
1856
+ description: challenge.description ?? null,
1857
+ amountAtomic: challenge.amount.atomic,
1858
+ amount: challenge.amount.display,
1859
+ token: challenge.asset.symbol,
1860
+ asset: challenge.asset.address,
1861
+ network: challenge.network.name,
1862
+ chainId: challenge.network.chainId,
1863
+ merchantAddress: challenge.recipient,
1864
+ expiresAt: challenge.expiresAt
1865
+ };
1866
+ }
1867
+ buildMppResumeState(input) {
1868
+ const quote = this.buildMppQuote(
1869
+ input.challenge,
1870
+ input.request ?? this.snapshotX402Request(input.challenge.resource),
1871
+ input.idempotencyKey
1872
+ );
1873
+ return {
1874
+ rail: "mpp",
1875
+ paymentRail: quote.paymentRail,
1876
+ paymentId: input.paymentId,
1877
+ idempotencyKey: quote.idempotencyKey,
1878
+ challenge: input.challenge,
1879
+ url: input.request?.url ?? input.challenge.resource,
1880
+ request: input.request,
1881
+ resourceUrl: quote.resourceUrl,
1882
+ description: quote.description,
1883
+ amountAtomic: quote.amountAtomic,
1884
+ amount: quote.amount,
1885
+ token: quote.token,
1886
+ asset: quote.asset,
1887
+ network: quote.network,
1888
+ chainId: quote.chainId,
1889
+ merchantAddress: quote.merchantAddress,
1890
+ expiresAt: quote.expiresAt
1891
+ };
1892
+ }
1893
+ attachResumeState(err, input) {
1894
+ if (input.rail === "x402") {
1895
+ this.attachX402ResumeState(
1896
+ err,
1897
+ input.paymentRequired,
1898
+ input.accepted,
1899
+ input.idempotencyKey,
1900
+ input.request
1901
+ );
1902
+ return;
1903
+ }
1904
+ this.attachMppResumeState(err, input.challenge, input.idempotencyKey, input.request);
1905
+ }
1906
+ attachX402ResumeState(err, paymentRequired, accepted, idempotencyKey, request) {
1907
+ if (!(err instanceof HavenPaymentStateError)) return;
1908
+ if (err.state.rail !== "x402") return;
1909
+ err.resumeState = this.buildX402ResumeState({
1910
+ paymentId: err.state.paymentId,
1911
+ paymentRequired,
1912
+ accepted,
1913
+ idempotencyKey,
1914
+ request
1915
+ });
1916
+ }
1917
+ attachMppResumeState(err, challenge, idempotencyKey, request) {
1918
+ if (!(err instanceof HavenPaymentStateError)) return;
1919
+ if (!isMppRail(err.state.rail)) return;
1920
+ err.resumeState = this.buildMppResumeState({
1921
+ paymentId: err.state.paymentId,
1922
+ challenge,
1923
+ idempotencyKey,
1924
+ request
1925
+ });
1926
+ }
1178
1927
  // ── Tool Execution (for agent frameworks) ────────────────────────
1179
1928
  /**
1180
1929
  * Execute a tool call by name and input.
@@ -1234,9 +1983,9 @@ var HavenClient = class {
1234
1983
  }
1235
1984
  }
1236
1985
  if (toolName === "authorize_machine_payment") {
1237
- const { challenge } = input;
1986
+ const { challenge, idempotencyKey } = input;
1238
1987
  try {
1239
- const receipt = await this.authorizeMachinePayment(challenge);
1988
+ const receipt = await this.authorizeMachinePayment(challenge, { idempotencyKey });
1240
1989
  return {
1241
1990
  success: true,
1242
1991
  payment_id: receipt.paymentId,
@@ -1271,11 +2020,21 @@ var HavenClient = class {
1271
2020
  amount: result.amount,
1272
2021
  resource_url: result.resourceUrl,
1273
2022
  merchant_address: result.merchantAddress,
2023
+ amount_atomic: result.amountAtomic,
2024
+ asset: result.asset,
2025
+ network: result.network,
2026
+ description: result.description,
2027
+ idempotency_key: result.idempotencyKey,
2028
+ x402: result.x402,
2029
+ mpp: result.mpp,
1274
2030
  expires_at: result.expiresAt,
1275
2031
  chain_id: result.chainId,
1276
2032
  message: result.message
1277
2033
  };
1278
2034
  }
2035
+ if (toolName === "get_allowances") {
2036
+ return { ...await this.getAllowances() };
2037
+ }
1279
2038
  throw new Error(`Unknown tool: ${toolName}`);
1280
2039
  }
1281
2040
  toolX402PaymentRequired(input) {
@@ -1328,6 +2087,31 @@ var HavenClient = class {
1328
2087
  amount: err.state.amount,
1329
2088
  resource_url: err.state.resourceUrl,
1330
2089
  merchant_address: err.state.merchantAddress,
2090
+ amount_atomic: err.state.amountAtomic,
2091
+ asset: err.state.asset,
2092
+ network: err.state.network,
2093
+ description: err.state.description,
2094
+ idempotency_key: err.state.idempotencyKey,
2095
+ x402: err.state.x402 ? {
2096
+ amount_atomic: err.state.x402.amountAtomic,
2097
+ asset: err.state.x402.asset,
2098
+ network: err.state.x402.network,
2099
+ resource_url: err.state.x402.resourceUrl,
2100
+ merchant_address: err.state.x402.merchantAddress,
2101
+ description: err.state.x402.description,
2102
+ idempotency_key: err.state.x402.idempotencyKey
2103
+ } : void 0,
2104
+ mpp: err.state.mpp ? {
2105
+ amount_atomic: err.state.mpp.amountAtomic,
2106
+ asset: err.state.mpp.asset,
2107
+ network: err.state.mpp.network,
2108
+ resource_url: err.state.mpp.resourceUrl,
2109
+ merchant_address: err.state.mpp.merchantAddress,
2110
+ description: err.state.mpp.description,
2111
+ idempotency_key: err.state.mpp.idempotencyKey,
2112
+ challenge_id: err.state.mpp.challengeId
2113
+ } : void 0,
2114
+ resume_state: err.resumeState,
1331
2115
  expires_at: err.state.expiresAt,
1332
2116
  chain_id: err.state.chainId,
1333
2117
  message: err.state.message,
@@ -1359,11 +2143,14 @@ var HavenClient = class {
1359
2143
  const controller = new AbortController();
1360
2144
  const timeout = setTimeout(() => controller.abort(), this.requestTimeout);
1361
2145
  try {
2146
+ const contextHeaders = this.requestContext.getStore()?.headers ?? {};
1362
2147
  const res = await fetch(url, {
1363
2148
  method,
1364
2149
  headers: {
1365
2150
  "Content-Type": "application/json",
1366
- "Authorization": `Bearer ${this.apiKey}`
2151
+ "Authorization": `Bearer ${this.apiKey}`,
2152
+ ...this.defaultHeaders,
2153
+ ...contextHeaders
1367
2154
  },
1368
2155
  body: body ? JSON.stringify(body) : void 0,
1369
2156
  signal: controller.signal
@@ -1420,7 +2207,50 @@ var HavenClient = class {
1420
2207
  txHash: raw.tx_hash,
1421
2208
  expiresAt: raw.expires_at,
1422
2209
  chainId: raw.chain_id,
1423
- message: raw.message
2210
+ message: raw.message,
2211
+ amountAtomic: raw.amount_atomic ?? raw.x402?.amount_atomic ?? null,
2212
+ asset: raw.asset ?? raw.x402?.asset ?? null,
2213
+ network: raw.network ?? raw.x402?.network ?? null,
2214
+ description: raw.description ?? raw.x402?.description ?? null,
2215
+ idempotencyKey: raw.idempotency_key ?? raw.x402?.idempotency_key ?? null,
2216
+ x402: raw.x402 ? {
2217
+ amountAtomic: raw.x402.amount_atomic ?? raw.amount_atomic ?? null,
2218
+ asset: raw.x402.asset ?? raw.asset ?? null,
2219
+ network: raw.x402.network ?? raw.network ?? null,
2220
+ resourceUrl: raw.x402.resource_url ?? raw.resource_url,
2221
+ merchantAddress: raw.x402.merchant_address ?? raw.merchant_address,
2222
+ description: raw.x402.description ?? raw.description ?? null,
2223
+ idempotencyKey: raw.x402.idempotency_key ?? raw.idempotency_key ?? null
2224
+ } : void 0
2225
+ };
2226
+ }
2227
+ mapPaymentReceipt(raw) {
2228
+ return {
2229
+ id: raw.id,
2230
+ paymentId: raw.payment_id,
2231
+ rail: raw.rail,
2232
+ proofStatus: raw.proof_status,
2233
+ txHash: raw.tx_hash,
2234
+ chainId: raw.chain_id,
2235
+ resourceUrl: raw.resource_url,
2236
+ merchantAddress: raw.merchant_address,
2237
+ payerAddress: raw.payer_address,
2238
+ settlementAddress: raw.settlement_address,
2239
+ tokenSymbol: raw.token_symbol,
2240
+ tokenAddress: raw.token_address,
2241
+ amountRaw: raw.amount_raw,
2242
+ amount: raw.amount_human,
2243
+ challengeId: raw.challenge_id,
2244
+ idempotencyKey: raw.idempotency_key,
2245
+ challengePayload: raw.challenge_payload,
2246
+ selectedPayment: raw.selected_payment,
2247
+ paymentProofHeaderName: raw.payment_proof_header_name,
2248
+ protocolReceiptHeaderName: raw.protocol_receipt_header_name,
2249
+ protocolReceiptPayload: raw.protocol_receipt_payload,
2250
+ merchantStatus: raw.merchant_status,
2251
+ confirmedAt: raw.confirmed_at,
2252
+ createdAt: raw.created_at,
2253
+ updatedAt: raw.updated_at
1424
2254
  };
1425
2255
  }
1426
2256
  };
@@ -1462,6 +2292,72 @@ async function responseSnippet(response) {
1462
2292
  }
1463
2293
  }
1464
2294
 
2295
+ // src/tool-descriptions.ts
2296
+ function composeDescription(d) {
2297
+ return [d.summary, d.selectionGuidance, d.behavior, d.nextActionGuidance].filter(Boolean).join(" ");
2298
+ }
2299
+ var toolDescriptions = {
2300
+ quoteX402: {
2301
+ summary: "Inspect an HTTP 402 x402 paid resource without creating a Haven payment, signature, approval, or on-chain transaction.",
2302
+ behavior: "Probes the merchant directly and parses the 402 response. Pure read-only client behavior \u2014 Haven is not contacted.",
2303
+ nextActionGuidance: ""
2304
+ },
2305
+ payX402: {
2306
+ summary: "Pay an inspected x402 quote. The delegate key signs locally; Haven only validates and relays signed, on-chain-constrained payment transactions.",
2307
+ selectionGuidance: "Do not use this for read-only allowance, budget, spend-limit, remaining-amount, reset-period, or what-can-I-spend questions; use the allowance lookup tool instead.",
2308
+ behavior: "Signs the EIP-3009 payment from the delegate wallet, asks Haven for a Safe AllowanceModule top-up if needed, and returns the merchant response or a pending-approval state.",
2309
+ nextActionGuidance: "If approval is needed, preserve the returned resume_state and wait for nextAction=retry_original_x402_request before resuming."
2310
+ },
2311
+ resumeX402: {
2312
+ summary: "Resume an x402 payment after the Haven wallet owner approved the funding step.",
2313
+ behavior: "Accepts either resume_state or payment_id, validates the original x402 details against the approved Haven funding, and retries the merchant request with the X-PAYMENT header. No new Haven approval is created.",
2314
+ nextActionGuidance: "Only use when get_payment_status returns nextAction=retry_original_x402_request; do not start a new merchant session."
2315
+ },
2316
+ quoteMpp: {
2317
+ summary: "Inspect a Haven MPP challenge or paid MPP URL without creating a Haven payment, signature, approval, or on-chain transaction.",
2318
+ behavior: "Parses an MPP challenge envelope and returns a typed quote with rail tag, amount, asset, and merchant context. Pure read-only \u2014 Haven is not contacted.",
2319
+ nextActionGuidance: ""
2320
+ },
2321
+ payMpp: {
2322
+ summary: "Pay an inspected MPP challenge. The delegate key signs locally; Haven only validates and relays signed, on-chain-constrained payment transactions.",
2323
+ selectionGuidance: "Do not use this for read-only allowance, budget, spend-limit, remaining-amount, reset-period, or what-can-I-spend questions; use the allowance lookup tool instead.",
2324
+ behavior: "Authorizes the payment through Haven within the on-chain allowance, signs the challenge proof, and returns the proof header for retrying the original paid resource.",
2325
+ nextActionGuidance: "If approval is needed, preserve resume_state or payment_id and wait for nextAction=retry_original_x402_request before resuming."
2326
+ },
2327
+ resumeMpp: {
2328
+ summary: "Resume an MPP payment after the Haven wallet owner approved the funding step.",
2329
+ behavior: "Accepts either resume_state or payment_id and retries the original paid resource with the MPP proof header. No new Haven approval is created.",
2330
+ nextActionGuidance: ""
2331
+ },
2332
+ getPaymentStatus: {
2333
+ summary: "Fetch structured Haven payment status, including phase and nextAction taxonomy for agent recovery.",
2334
+ behavior: "Accepts a payment intent or approval request id and returns the full state taxonomy (phase, nextAction, rail, amount, merchant, resource url, idempotency key, message).",
2335
+ nextActionGuidance: ""
2336
+ },
2337
+ getResumeState: {
2338
+ summary: "Rehydrate stored x402 or MPP resume_state by payment_id.",
2339
+ behavior: "Returns the context that the agent originally received in a pending-approval response, reconstructed from Haven's database. This is context only; signing still happens locally when a resume tool is called.",
2340
+ nextActionGuidance: ""
2341
+ },
2342
+ getAgent: {
2343
+ summary: "Return the authenticated agent identity, Haven wallet, delegate address, chain, and status.",
2344
+ behavior: "Read-only identity lookup. Useful for verifying which on-chain Safe and delegate the credential is bound to.",
2345
+ nextActionGuidance: ""
2346
+ },
2347
+ getAllowances: {
2348
+ summary: "Return configured and on-chain allowance state for the authenticated agent. On-chain allowance is the real spend gate.",
2349
+ 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.",
2350
+ behavior: "Reads the Safe AllowanceModule snapshot per token (allowance, spent, remaining, reset window). Configured amounts from Haven are returned alongside the on-chain truth.",
2351
+ nextActionGuidance: ""
2352
+ },
2353
+ listReceipts: {
2354
+ summary: "List recent machine-payment receipts and evidence for bookkeeping.",
2355
+ selectionGuidance: "Use this for transaction history, receipts, payment evidence, or bookkeeping; use the allowance tool instead for remaining allowance, budget, spend-limit, or what-can-I-spend questions.",
2356
+ behavior: "Returns the agent's recent machine-payment receipts ordered by recency. Proof header values are not returned.",
2357
+ nextActionGuidance: ""
2358
+ }
2359
+ };
2360
+
1465
2361
  // src/tools.ts
1466
2362
  var makePaymentSchema = {
1467
2363
  type: "object",
@@ -1495,6 +2391,11 @@ var getPaymentStatusSchema = {
1495
2391
  },
1496
2392
  required: ["payment_id"]
1497
2393
  };
2394
+ var getAllowancesSchema = {
2395
+ type: "object",
2396
+ properties: {},
2397
+ required: []
2398
+ };
1498
2399
  var authorizeX402Schema = {
1499
2400
  type: "object",
1500
2401
  properties: {
@@ -1577,11 +2478,12 @@ var authorizeMachinePaymentSchema = {
1577
2478
  },
1578
2479
  required: ["challenge"]
1579
2480
  };
1580
- var MAKE_PAYMENT_DESCRIPTION = "Request and sign a payment from the user-controlled Safe within approved on-chain limits. Haven authenticates the agent, validates the signed intent, and relays the Safe AllowanceModule transaction; it does not hold keys or control funds. Gnosis Chain tokens: EURe, USDC.e, xDAI. Base tokens: USDC, ETH.";
1581
- var GET_STATUS_DESCRIPTION = "Check the status of a previously initiated payment. Accepts payment intent IDs and approval request IDs. Returns the current status, phase, next_action, transaction hash if available, and payment details.";
1582
- var AUTHORIZE_X402_DESCRIPTION = "Authorize payment for an HTTP 402 (Payment Required) response. When a paid API returns x402 payment requirements, use this tool to sign with the agent-owned delegate key and request a policy-limited Safe AllowanceModule top-up when needed. Haven relays signed transactions only; the agent key authorizes payment and on-chain limits enforce spend. If this returns pending_approval, tell the user it is waiting in Haven, call get_payment_status later, and use resume_x402_payment only when next_action is retry_original_x402_request. Do not loop retries while approval is pending. Use the returned payment_header as the X-PAYMENT header on the retry request when doing a manual HTTP retry.";
1583
- var RESUME_X402_DESCRIPTION = "Resume an x402 payment after the user approved it in Haven. Use this only after get_payment_status returns next_action=retry_original_x402_request. It checks the approved payment, validates the original x402 details, and returns a merchant X-PAYMENT header without creating a new approval request.";
1584
- var AUTHORIZE_MACHINE_PAYMENT_DESCRIPTION = "Authorize a Haven machine-payment challenge, currently for the internal MPP demo rail. The agent signs the payment, Haven relays it within the on-chain allowance, and the tool returns a proof header for the retry request.";
2481
+ var MAKE_PAYMENT_DESCRIPTION = "Request and sign a payment from the user-controlled Safe within approved on-chain limits. For read-only allowance, budget, spend-limit, remaining-amount, or reset-period questions, use get_allowances instead of making a payment. Haven authenticates the agent, validates the signed intent, and relays the Safe AllowanceModule transaction; it does not hold keys or control funds. Gnosis Chain tokens: EURe, USDC.e, xDAI. Base tokens: USDC, ETH.";
2482
+ var GET_STATUS_DESCRIPTION = toolDescriptions.getPaymentStatus.summary + " Accepts payment intent IDs and approval request IDs. Returns the current status, phase, next_action, transaction hash if available, and payment details.";
2483
+ var GET_ALLOWANCES_DESCRIPTION = composeDescription(toolDescriptions.getAllowances);
2484
+ var AUTHORIZE_X402_DESCRIPTION = composeDescription(toolDescriptions.payX402) + " In this SDK tool set, the allowance lookup tool is get_allowances. When a paid API returns x402 payment requirements, use this tool to sign with the agent-owned delegate key and request a policy-limited Safe AllowanceModule top-up when needed. Haven relays signed transactions only; the agent key authorizes payment and on-chain limits enforce spend. If this returns pending_approval, tell the user it is waiting in Haven, preserve the original merchant/MCP session and x402 details, call get_payment_status later, and use resume_x402_payment only when next_action is retry_original_x402_request. Do not start a new merchant session or loop retries while approval is pending. Use the returned payment_header as the X-PAYMENT header on the retry request when doing a manual HTTP retry.";
2485
+ var RESUME_X402_DESCRIPTION = toolDescriptions.resumeX402.summary + " Use this only after get_payment_status returns next_action=retry_original_x402_request. It checks the approved payment, validates the original x402 details, and returns a merchant X-PAYMENT header without creating a new approval request or merchant session.";
2486
+ var AUTHORIZE_MACHINE_PAYMENT_DESCRIPTION = composeDescription(toolDescriptions.payMpp) + " In this SDK tool set, the allowance lookup tool is get_allowances. Currently scoped to the internal MPP demo rail. The agent signs the payment, Haven relays it within the on-chain allowance, and the tool returns a proof header for the retry request.";
1585
2487
  function claudeTools() {
1586
2488
  return [
1587
2489
  {
@@ -1594,6 +2496,11 @@ function claudeTools() {
1594
2496
  description: GET_STATUS_DESCRIPTION,
1595
2497
  input_schema: getPaymentStatusSchema
1596
2498
  },
2499
+ {
2500
+ name: "get_allowances",
2501
+ description: GET_ALLOWANCES_DESCRIPTION,
2502
+ input_schema: getAllowancesSchema
2503
+ },
1597
2504
  {
1598
2505
  name: "authorize_x402_payment",
1599
2506
  description: AUTHORIZE_X402_DESCRIPTION,
@@ -1629,6 +2536,14 @@ function openaiTools() {
1629
2536
  parameters: getPaymentStatusSchema
1630
2537
  }
1631
2538
  },
2539
+ {
2540
+ type: "function",
2541
+ function: {
2542
+ name: "get_allowances",
2543
+ description: GET_ALLOWANCES_DESCRIPTION,
2544
+ parameters: getAllowancesSchema
2545
+ }
2546
+ },
1632
2547
  {
1633
2548
  type: "function",
1634
2549
  function: {
@@ -1662,6 +2577,6 @@ var havenTools = {
1662
2577
  openai: openaiTools
1663
2578
  };
1664
2579
 
1665
- export { HavenApiError, HavenClient, HavenError, HavenPaymentStateError, HavenSigningError, HavenTimeoutError, addressFromKey, buildMachinePaymentIdempotencyKey, encodeMachinePaymentProof, encodePaymentProof, havenTools, parseMachinePaymentChallenge, parseMachinePaymentChallengeResponse, parsePaymentRequired, parsePaymentRequiredResponse, selectPaymentOption, signHash, verifySignature };
2580
+ export { AGENT_PAYMENT_NEXT_ACTION_VALUES, AGENT_PAYMENT_PHASE_VALUES, AGENT_PAYMENT_RAIL_VALUES, AgentPaymentNextAction, AgentPaymentNextActionDescriptions, AgentPaymentNextActionSchema, AgentPaymentPhase, AgentPaymentPhaseDescriptions, AgentPaymentPhaseSchema, AgentPaymentRail, AgentPaymentRailDescriptions, AgentPaymentRailSchema, HavenApiError, HavenClient, HavenError, HavenPaymentStateError, HavenSigningError, HavenTimeoutError, addressFromKey, buildMachinePaymentIdempotencyKey, buildX402ExpectedMessage, composeDescription, encodeMachinePaymentProof, encodePaymentProof, havenTools, parseMachinePaymentChallenge, parseMachinePaymentChallengeResponse, parsePaymentRequired, parsePaymentRequiredResponse, selectPaymentOption, selectStandardPaymentOption, signHash, toStandardPaymentRequirements, toolDescriptions, verifySignature, x402AuthorizationAmount };
1666
2581
  //# sourceMappingURL=index.js.map
1667
2582
  //# sourceMappingURL=index.js.map