@haven_ai/sdk 0.1.14-alpha.0 → 0.1.16-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 +18 -0
- package/dist/index.cjs +394 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +282 -16
- package/dist/index.d.ts +282 -16
- package/dist/index.js +384 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -63,6 +63,11 @@ var AgentPaymentNextAction = {
|
|
|
63
63
|
StopAndTellUser: "stop_and_tell_user",
|
|
64
64
|
/** Ask again only if the user still wants the payment after expiry. */
|
|
65
65
|
RequestAgainIfUserStillWantsIt: "request_again_if_user_still_wants_it",
|
|
66
|
+
/**
|
|
67
|
+
* The x402 funding/quote window expired. Re-quote the same logical merchant
|
|
68
|
+
* operation with the same idempotency key to stay double-charge-safe.
|
|
69
|
+
*/
|
|
70
|
+
PaymentWindowExpired: "payment_window_expired",
|
|
66
71
|
/**
|
|
67
72
|
* Stop and tell the user that the originating Safe needs to be funded or
|
|
68
73
|
* the agent's per-token allowance needs to be raised before the payment
|
|
@@ -76,6 +81,14 @@ var AgentPaymentNextAction = {
|
|
|
76
81
|
*/
|
|
77
82
|
SweepStrandedFunds: "sweep_stranded_funds"
|
|
78
83
|
};
|
|
84
|
+
var AgentPaymentFailureCode = {
|
|
85
|
+
/** A merchant-authoritative x402 price exceeds the caller's pre-funding max_amount cap. */
|
|
86
|
+
PriceExceedsMax: "PRICE_EXCEEDS_MAX",
|
|
87
|
+
/** The x402 funding/quote window expired before the signer or hosted settle step could finish. */
|
|
88
|
+
PaymentWindowExpired: "PAYMENT_WINDOW_EXPIRED",
|
|
89
|
+
/** The Haven funding leg succeeded, but the merchant rejected the paid retry. */
|
|
90
|
+
MerchantRejectedAfterFunding: "MERCHANT_REJECTED_AFTER_FUNDING"
|
|
91
|
+
};
|
|
79
92
|
var AgentPaymentRail = {
|
|
80
93
|
/** Standard Haven payment from the user's Safe through an approved delegate allowance. */
|
|
81
94
|
Direct: "direct",
|
|
@@ -94,6 +107,7 @@ var AgentPaymentRail = {
|
|
|
94
107
|
};
|
|
95
108
|
var AGENT_PAYMENT_PHASE_VALUES = Object.values(AgentPaymentPhase);
|
|
96
109
|
var AGENT_PAYMENT_NEXT_ACTION_VALUES = Object.values(AgentPaymentNextAction);
|
|
110
|
+
var AGENT_PAYMENT_FAILURE_CODE_VALUES = Object.values(AgentPaymentFailureCode);
|
|
97
111
|
var AGENT_PAYMENT_RAIL_VALUES = Object.values(AgentPaymentRail);
|
|
98
112
|
var AgentPaymentPhaseDescriptions = {
|
|
99
113
|
[AgentPaymentPhase.AgentSignatureRequired]: "The agent must sign and submit the prepared payment before Haven can relay it.",
|
|
@@ -118,9 +132,15 @@ var AgentPaymentNextActionDescriptions = {
|
|
|
118
132
|
[AgentPaymentNextAction.RetryOriginalX402Request]: "Resume this payment id and retry the original x402 request with the merchant payment header.",
|
|
119
133
|
[AgentPaymentNextAction.StopAndTellUser]: "Stop retrying this payment and tell the user what happened.",
|
|
120
134
|
[AgentPaymentNextAction.RequestAgainIfUserStillWantsIt]: "Ask again only if the user still wants the payment after expiry.",
|
|
135
|
+
[AgentPaymentNextAction.PaymentWindowExpired]: "The x402 funding/quote window expired. Re-quote with the same idempotency key before asking the signer to build a merchant payment header again.",
|
|
121
136
|
[AgentPaymentNextAction.FundSafeOrRaiseAllowance]: "Stop and tell the user that the originating Safe needs to be funded or the agent allowance raised before the payment can succeed.",
|
|
122
137
|
[AgentPaymentNextAction.SweepStrandedFunds]: "Tell the user that funds may be stranded in the delegate wallet and prompt them to initiate a sweep in Haven to return them to the originating Safe."
|
|
123
138
|
};
|
|
139
|
+
var AgentPaymentFailureCodeDescriptions = {
|
|
140
|
+
[AgentPaymentFailureCode.PriceExceedsMax]: "The merchant-authoritative x402 amount exceeds the caller's max_amount cap. No funding transfer was created; ask the user before retrying with a larger cap.",
|
|
141
|
+
[AgentPaymentFailureCode.PaymentWindowExpired]: "The x402 funding/quote window expired before the signer or hosted settle step could finish. Re-quote via haven_pay_mcp_tool with the same idempotency key to avoid duplicate funding.",
|
|
142
|
+
[AgentPaymentFailureCode.MerchantRejectedAfterFunding]: "The Haven funding leg succeeded, but the merchant rejected the paid retry. Stop retrying the merchant and reconcile stranded delegate funds with haven_sweep_delegate."
|
|
143
|
+
};
|
|
124
144
|
var AgentPaymentRailDescriptions = {
|
|
125
145
|
[AgentPaymentRail.Direct]: "Standard Haven payment from the user-controlled Safe through an approved delegate allowance.",
|
|
126
146
|
[AgentPaymentRail.X402]: "x402 HTTP 402 payment flow with a Haven funding leg and merchant retry leg.",
|
|
@@ -142,6 +162,12 @@ var AgentPaymentNextActionSchema = {
|
|
|
142
162
|
description: "Stable next action an agent should take for a Haven payment state.",
|
|
143
163
|
"x-enumDescriptions": AgentPaymentNextActionDescriptions
|
|
144
164
|
};
|
|
165
|
+
var AgentPaymentFailureCodeSchema = {
|
|
166
|
+
type: "string",
|
|
167
|
+
enum: AGENT_PAYMENT_FAILURE_CODE_VALUES,
|
|
168
|
+
description: "Stable machine-readable failure codes for Haven agent payment recovery paths.",
|
|
169
|
+
"x-enumDescriptions": AgentPaymentFailureCodeDescriptions
|
|
170
|
+
};
|
|
145
171
|
var AgentPaymentRailSchema = {
|
|
146
172
|
type: "string",
|
|
147
173
|
enum: AGENT_PAYMENT_RAIL_VALUES,
|
|
@@ -329,7 +355,8 @@ function normalizePaymentRequired(value) {
|
|
|
329
355
|
x402Version: candidate.x402Version,
|
|
330
356
|
resource,
|
|
331
357
|
accepts,
|
|
332
|
-
error: candidate.error
|
|
358
|
+
error: candidate.error,
|
|
359
|
+
...candidate.extensions && typeof candidate.extensions === "object" ? { extensions: candidate.extensions } : {}
|
|
333
360
|
};
|
|
334
361
|
}
|
|
335
362
|
var SUPPORTED_X402_NETWORKS = {
|
|
@@ -425,8 +452,7 @@ function x402AuthorizationAmount(option) {
|
|
|
425
452
|
return amount;
|
|
426
453
|
}
|
|
427
454
|
function buildX402ExpectedMessage(context) {
|
|
428
|
-
|
|
429
|
-
${stableStringify({
|
|
455
|
+
const payload = {
|
|
430
456
|
version: 1,
|
|
431
457
|
kind: "haven.x402.expected",
|
|
432
458
|
paymentId: context.paymentId,
|
|
@@ -436,7 +462,12 @@ ${stableStringify({
|
|
|
436
462
|
amount: context.amount,
|
|
437
463
|
asset: context.asset.toLowerCase(),
|
|
438
464
|
network: context.network
|
|
439
|
-
}
|
|
465
|
+
};
|
|
466
|
+
if (context.expiresAt) {
|
|
467
|
+
payload.expiresAt = context.expiresAt;
|
|
468
|
+
}
|
|
469
|
+
return `Haven x402 expected context v1
|
|
470
|
+
${stableStringify(payload)}`;
|
|
440
471
|
}
|
|
441
472
|
function toStandardPaymentRequirements(paymentRequired, option) {
|
|
442
473
|
const network = STANDARD_X402_NETWORKS[option.network];
|
|
@@ -500,6 +531,7 @@ function stableStringify(value) {
|
|
|
500
531
|
const primitive = JSON.stringify(value);
|
|
501
532
|
return primitive === void 0 ? "undefined" : primitive;
|
|
502
533
|
}
|
|
534
|
+
if (value instanceof Date) return JSON.stringify(value.toISOString());
|
|
503
535
|
if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
504
536
|
const object = value;
|
|
505
537
|
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
@@ -601,11 +633,24 @@ var DEFAULT_REQUEST_TIMEOUT = 3e4;
|
|
|
601
633
|
var DEFAULT_CONFIRMATION_TIMEOUT = 9e4;
|
|
602
634
|
var DEFAULT_POLLING_INTERVAL = 3e3;
|
|
603
635
|
function formatAtomicAmount(atomic, decimals) {
|
|
636
|
+
if (atomic < 0n) return "0.0";
|
|
604
637
|
const s = atomic.toString().padStart(decimals + 1, "0");
|
|
605
638
|
const intPart = s.slice(0, s.length - decimals) || "0";
|
|
606
639
|
const fracPart = s.slice(s.length - decimals).replace(/0+$/, "") || "0";
|
|
607
640
|
return `${intPart}.${fracPart}`;
|
|
608
641
|
}
|
|
642
|
+
function safeBigInt(value) {
|
|
643
|
+
try {
|
|
644
|
+
return BigInt(value);
|
|
645
|
+
} catch {
|
|
646
|
+
return 0n;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
function deriveReadiness(status, allowances) {
|
|
650
|
+
if (status !== "active") return "revoked";
|
|
651
|
+
const hasSpendable = allowances.some((a) => safeBigInt(a.remainingAtomic) > 0n);
|
|
652
|
+
return hasSpendable ? "ready" : "needs_approval";
|
|
653
|
+
}
|
|
609
654
|
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
610
655
|
var MCP_ACCEPT = "application/json, text/event-stream";
|
|
611
656
|
var MCP_CLIENT_INFO = { name: "haven-sdk", version: "1" };
|
|
@@ -892,6 +937,7 @@ var HavenClient = class {
|
|
|
892
937
|
}
|
|
893
938
|
return {
|
|
894
939
|
paymentId: raw.payment_id,
|
|
940
|
+
idempotencyKey,
|
|
895
941
|
status: "pending_signature",
|
|
896
942
|
expiresAt: raw.expires_at,
|
|
897
943
|
signData: raw.sign_data,
|
|
@@ -971,6 +1017,32 @@ var HavenClient = class {
|
|
|
971
1017
|
chainId: raw.chain_id
|
|
972
1018
|
};
|
|
973
1019
|
}
|
|
1020
|
+
/**
|
|
1021
|
+
* One-shot "am I ready?" bootstrap: identity + live spend authority + a
|
|
1022
|
+
* readiness signal, in a single call. Folds {@link getAgent} and
|
|
1023
|
+
* {@link getAllowances} together and derives a {@link HavenAgentReadiness}
|
|
1024
|
+
* so an agent can answer "who am I and can I pay right now" at session start
|
|
1025
|
+
* without two round trips and manual assembly.
|
|
1026
|
+
*/
|
|
1027
|
+
async getAgentSummary() {
|
|
1028
|
+
const [agent, allowanceSummary] = await Promise.all([
|
|
1029
|
+
this.getAgent(),
|
|
1030
|
+
this.getAllowances()
|
|
1031
|
+
]);
|
|
1032
|
+
const allowances = allowanceSummary.allowances.map((a) => {
|
|
1033
|
+
const token = resolveTokenFromAddress(a.tokenAddress);
|
|
1034
|
+
const remainingDisplay = token ? `${formatAtomicAmount(safeBigInt(a.onchain.remaining), token.decimals)} ${a.tokenSymbol}` : `${a.onchain.remaining} ${a.tokenSymbol} (atomic; unknown decimals)`;
|
|
1035
|
+
return {
|
|
1036
|
+
tokenSymbol: a.tokenSymbol,
|
|
1037
|
+
remainingAtomic: a.onchain.remaining,
|
|
1038
|
+
remainingDisplay,
|
|
1039
|
+
configuredAmount: a.configuredAmount,
|
|
1040
|
+
resetPeriodMin: a.resetPeriodMin,
|
|
1041
|
+
isResetPending: a.onchain.isResetPending
|
|
1042
|
+
};
|
|
1043
|
+
});
|
|
1044
|
+
return { ...agent, readiness: deriveReadiness(agent.status, allowances), allowances };
|
|
1045
|
+
}
|
|
974
1046
|
/**
|
|
975
1047
|
* Sweep stranded USDC and ETH from the delegate EOA back to the originating Safe.
|
|
976
1048
|
*
|
|
@@ -1043,6 +1115,30 @@ var HavenClient = class {
|
|
|
1043
1115
|
transfers
|
|
1044
1116
|
};
|
|
1045
1117
|
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Hosted (keyless) split-signer sweep — step 1 of 2.
|
|
1120
|
+
*
|
|
1121
|
+
* Asks the backend to build a gasless EIP-3009 sweep authorization for the
|
|
1122
|
+
* delegate's stranded USDC. Returns `nothing_stranded` when the delegate is
|
|
1123
|
+
* empty, otherwise an `authorization` + Haven `expected_auth` to hand to the
|
|
1124
|
+
* edge signer's `haven_sign_sweep_delegate`. No key is required on this client.
|
|
1125
|
+
*/
|
|
1126
|
+
async prepareSweep() {
|
|
1127
|
+
return this.post("/machine-payments/sweep/prepare", {});
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Hosted (keyless) split-signer sweep — step 2 of 2.
|
|
1131
|
+
*
|
|
1132
|
+
* Relays the delegate-signed authorization. The Haven relayer submits the
|
|
1133
|
+
* on-chain `transferWithAuthorization` and pays gas; this client never holds
|
|
1134
|
+
* the key.
|
|
1135
|
+
*/
|
|
1136
|
+
async submitSweep(authorization, signature) {
|
|
1137
|
+
return this.post("/machine-payments/sweep/submit", {
|
|
1138
|
+
authorization,
|
|
1139
|
+
signature
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1046
1142
|
/**
|
|
1047
1143
|
* Get configured and on-chain allowances for the authenticated agent.
|
|
1048
1144
|
*/
|
|
@@ -1198,7 +1294,8 @@ var HavenClient = class {
|
|
|
1198
1294
|
throw new HavenApiError("quoteX402 only supports standard x402 Payment Required responses.", 400);
|
|
1199
1295
|
}
|
|
1200
1296
|
const paymentRequired = await parsePaymentRequiredResponse(response);
|
|
1201
|
-
|
|
1297
|
+
const mcpTransport = await this.detectX402McpTransport(url, paymentRequired, response);
|
|
1298
|
+
return this.buildX402Quote(paymentRequired, request, options.idempotencyKey, mcpTransport);
|
|
1202
1299
|
}
|
|
1203
1300
|
/**
|
|
1204
1301
|
* Pay a previously inspected x402 quote and retry the exact captured request.
|
|
@@ -1403,12 +1500,11 @@ var HavenClient = class {
|
|
|
1403
1500
|
* a transport/HTTP error, a missing session id, or a JSON-RPC error in the
|
|
1404
1501
|
* handshake response — so the caller can fall back to plain x402.
|
|
1405
1502
|
*/
|
|
1406
|
-
async mcpInitialize(url, init) {
|
|
1503
|
+
async mcpInitialize(url, init, wallet = this.x402PayerAddress()) {
|
|
1407
1504
|
try {
|
|
1408
1505
|
const headers = new Headers(init?.headers);
|
|
1409
1506
|
headers.set("Content-Type", "application/json");
|
|
1410
1507
|
headers.set("Accept", MCP_ACCEPT);
|
|
1411
|
-
const wallet = this.x402PayerAddress();
|
|
1412
1508
|
if (wallet && !headers.has("x402-wallet")) headers.set("x402-wallet", wallet);
|
|
1413
1509
|
const response = await globalThis.fetch(url, {
|
|
1414
1510
|
method: "POST",
|
|
@@ -1429,7 +1525,7 @@ var HavenClient = class {
|
|
|
1429
1525
|
if (!sessionId) return void 0;
|
|
1430
1526
|
const message = await this.readMcpMessage(response);
|
|
1431
1527
|
if (message && "error" in message) return void 0;
|
|
1432
|
-
await this.mcpNotifyInitialized(url, init, sessionId);
|
|
1528
|
+
await this.mcpNotifyInitialized(url, init, sessionId, wallet);
|
|
1433
1529
|
return sessionId;
|
|
1434
1530
|
} catch {
|
|
1435
1531
|
return void 0;
|
|
@@ -1440,13 +1536,12 @@ var HavenClient = class {
|
|
|
1440
1536
|
* lifecycle handshake. Best-effort: the session is already established, so a
|
|
1441
1537
|
* failed notification must not abort the payment.
|
|
1442
1538
|
*/
|
|
1443
|
-
async mcpNotifyInitialized(url, init, sessionId) {
|
|
1539
|
+
async mcpNotifyInitialized(url, init, sessionId, wallet = this.x402PayerAddress()) {
|
|
1444
1540
|
try {
|
|
1445
1541
|
const headers = new Headers(init?.headers);
|
|
1446
1542
|
headers.set("Content-Type", "application/json");
|
|
1447
1543
|
headers.set("Accept", MCP_ACCEPT);
|
|
1448
1544
|
headers.set("mcp-session-id", sessionId);
|
|
1449
|
-
const wallet = this.x402PayerAddress();
|
|
1450
1545
|
if (wallet && !headers.has("x402-wallet")) headers.set("x402-wallet", wallet);
|
|
1451
1546
|
await globalThis.fetch(url, {
|
|
1452
1547
|
method: "POST",
|
|
@@ -1624,30 +1719,48 @@ var HavenClient = class {
|
|
|
1624
1719
|
* amount/merchant/nonce-bound EIP-3009 authorization the edge signer already
|
|
1625
1720
|
* produced — the hosted server cannot mint or reuse signing authority.
|
|
1626
1721
|
*
|
|
1627
|
-
* When the URL is MCP-shaped (`/mcp` path)
|
|
1722
|
+
* When the URL is MCP-shaped (`/mcp` path) or the quote-time transport context
|
|
1723
|
+
* says the merchant was Bazaar-discoverable, runs a fresh `initialize`
|
|
1628
1724
|
* handshake (the quote-time session is gone once funding confirms; the x402
|
|
1629
1725
|
* challenge is stateless w.r.t. the MCP session, so a fresh session is
|
|
1630
1726
|
* accepted), threads the session + wallet headers, sets `X-PAYMENT`, and
|
|
1631
1727
|
* collapses an SSE JSON-RPC response to its `result`.
|
|
1632
|
-
*
|
|
1633
|
-
* Limitation: detects MCP only by the `/mcp` path convention, not the
|
|
1634
|
-
* Coinbase Bazaar `extensions.bazaar` 402 signal that `fetch()` also honors.
|
|
1635
|
-
* A Bazaar-discoverable merchant on a non-`/mcp` URL would need the standard
|
|
1636
|
-
* `fetch()` path. All current MCP-tool merchants use the `/mcp` convention.
|
|
1637
1728
|
*/
|
|
1729
|
+
/**
|
|
1730
|
+
* Wait for a payment's Safe→delegate funding tx to reach ≥1 on-chain
|
|
1731
|
+
* confirmation. The hosted x402 completion path MUST call this after funding
|
|
1732
|
+
* and before delivering the X-PAYMENT header, so the merchant's
|
|
1733
|
+
* balanceOf(delegate) / transferWithAuthorization verification sees the funded
|
|
1734
|
+
* balance — otherwise it rejects with "Payment verification failed". The
|
|
1735
|
+
* SDK's local path already does this (see authorizeStandardX402); the hosted
|
|
1736
|
+
* split flow regressed when the 5→3 collapse removed the incidental
|
|
1737
|
+
* inter-call latency that used to mask it. No-op when the funding tx hash or
|
|
1738
|
+
* a chain RPC (chainRpcs[chainId]) is unavailable.
|
|
1739
|
+
*/
|
|
1740
|
+
async ensureFundingConfirmed(paymentId, fundingTxHash) {
|
|
1741
|
+
const status = await this.getPaymentStatus(paymentId);
|
|
1742
|
+
await this.waitForFundingTx(fundingTxHash ?? status.txHash ?? void 0, status.chainId);
|
|
1743
|
+
}
|
|
1638
1744
|
async completeX402MerchantCall(input) {
|
|
1745
|
+
const evidenceContext = await this.resolveX402MerchantCompletionContext({
|
|
1746
|
+
paymentId: input.paymentId,
|
|
1747
|
+
url: input.url
|
|
1748
|
+
});
|
|
1749
|
+
const shouldHandshakeMcp = isMcpUrl(input.url) || input.mcpTransport?.handshakeRequired === true;
|
|
1750
|
+
const x402Wallet = shouldHandshakeMcp ? await this.resolveX402WalletForMerchantCall() : this.x402PayerAddress();
|
|
1639
1751
|
let mcpSessionId;
|
|
1640
|
-
if (
|
|
1641
|
-
mcpSessionId = await this.mcpInitialize(input.url, input.init);
|
|
1752
|
+
if (shouldHandshakeMcp) {
|
|
1753
|
+
mcpSessionId = await this.mcpInitialize(input.url, input.init, x402Wallet);
|
|
1642
1754
|
}
|
|
1643
|
-
let requestInit = this.withX402Wallet(input.init,
|
|
1755
|
+
let requestInit = this.withX402Wallet(input.init, x402Wallet) ?? {};
|
|
1644
1756
|
if (mcpSessionId) requestInit = this.withMcpHeaders(requestInit, mcpSessionId);
|
|
1645
1757
|
const headers = new Headers(requestInit.headers);
|
|
1646
1758
|
headers.set("X-PAYMENT", input.paymentHeader);
|
|
1647
1759
|
requestInit = { ...requestInit, headers };
|
|
1648
1760
|
const response = await globalThis.fetch(input.url, requestInit);
|
|
1649
1761
|
const surfaced = mcpSessionId ? await this.surfaceMcpResult(response) : response;
|
|
1650
|
-
const
|
|
1762
|
+
const protocolReceiptHeader = surfaced.headers.get("PAYMENT-RESPONSE") ?? void 0;
|
|
1763
|
+
const settlement = parseMerchantSettlement(protocolReceiptHeader ?? null);
|
|
1651
1764
|
const text = await surfaced.text();
|
|
1652
1765
|
let body;
|
|
1653
1766
|
try {
|
|
@@ -1655,6 +1768,35 @@ var HavenClient = class {
|
|
|
1655
1768
|
} catch {
|
|
1656
1769
|
body = text;
|
|
1657
1770
|
}
|
|
1771
|
+
if (!surfaced.ok) {
|
|
1772
|
+
await this.recordMerchantRetryRejected({
|
|
1773
|
+
rail: "x402",
|
|
1774
|
+
paymentId: evidenceContext.paymentId,
|
|
1775
|
+
txHash: evidenceContext.txHash,
|
|
1776
|
+
resourceUrl: evidenceContext.resourceUrl,
|
|
1777
|
+
merchant: {
|
|
1778
|
+
merchant_status: surfaced.status,
|
|
1779
|
+
merchant_status_text: surfaced.statusText,
|
|
1780
|
+
merchant_headers: Object.fromEntries(surfaced.headers.entries()),
|
|
1781
|
+
merchant_body: text
|
|
1782
|
+
},
|
|
1783
|
+
details: {
|
|
1784
|
+
merchant_to: evidenceContext.merchantAddress
|
|
1785
|
+
}
|
|
1786
|
+
});
|
|
1787
|
+
} else {
|
|
1788
|
+
await this.reportMachinePaymentEvidence({
|
|
1789
|
+
paymentId: evidenceContext.paymentId,
|
|
1790
|
+
rail: "x402",
|
|
1791
|
+
txHash: evidenceContext.txHash,
|
|
1792
|
+
resourceUrl: evidenceContext.resourceUrl,
|
|
1793
|
+
merchantStatus: surfaced.status,
|
|
1794
|
+
paymentProofHeaderName: "X-PAYMENT",
|
|
1795
|
+
paymentProofHeader: input.paymentHeader,
|
|
1796
|
+
protocolReceiptHeaderName: protocolReceiptHeader ? "PAYMENT-RESPONSE" : void 0,
|
|
1797
|
+
protocolReceiptHeader
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1658
1800
|
return {
|
|
1659
1801
|
status: surfaced.status,
|
|
1660
1802
|
ok: surfaced.ok,
|
|
@@ -1662,6 +1804,53 @@ var HavenClient = class {
|
|
|
1662
1804
|
settlementTxHash: settlement.settlementTxHash ?? void 0
|
|
1663
1805
|
};
|
|
1664
1806
|
}
|
|
1807
|
+
async resolveX402MerchantCompletionContext(input) {
|
|
1808
|
+
const status = await this.getPaymentStatus(input.paymentId);
|
|
1809
|
+
if (status.rail !== "x402") {
|
|
1810
|
+
throw new HavenPaymentStateError(
|
|
1811
|
+
`Payment ${status.paymentId} is ${status.rail}, not x402.`,
|
|
1812
|
+
409,
|
|
1813
|
+
status
|
|
1814
|
+
);
|
|
1815
|
+
}
|
|
1816
|
+
const readyForMerchantCompletion = status.nextAction === AgentPaymentNextAction.RetryOriginalX402Request || status.kind === "payment_intent" && status.status === "confirmed" && status.phase === AgentPaymentPhase.PaymentConfirmed && status.nextAction === AgentPaymentNextAction.None;
|
|
1817
|
+
if (!readyForMerchantCompletion) {
|
|
1818
|
+
throw new HavenPaymentStateError(status.message, PAYMENT_STATE_STATUS_CODES[status.status] ?? 409, status);
|
|
1819
|
+
}
|
|
1820
|
+
if (!status.txHash) {
|
|
1821
|
+
throw new HavenApiError(
|
|
1822
|
+
`x402 payment ${status.paymentId} is ready for merchant completion but has no Haven transaction hash.`,
|
|
1823
|
+
502,
|
|
1824
|
+
status,
|
|
1825
|
+
status.paymentId
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
const approvedResourceUrl = status.resourceUrl ?? status.x402?.resourceUrl ?? null;
|
|
1829
|
+
if (approvedResourceUrl && approvedResourceUrl !== input.url) {
|
|
1830
|
+
throw new HavenApiError(
|
|
1831
|
+
"x402 merchant completion does not match the approved resource URL.",
|
|
1832
|
+
409,
|
|
1833
|
+
{ status, url: input.url },
|
|
1834
|
+
status.paymentId
|
|
1835
|
+
);
|
|
1836
|
+
}
|
|
1837
|
+
return {
|
|
1838
|
+
paymentId: status.paymentId,
|
|
1839
|
+
txHash: status.txHash,
|
|
1840
|
+
resourceUrl: approvedResourceUrl ?? input.url,
|
|
1841
|
+
merchantAddress: status.merchantAddress ?? status.x402?.merchantAddress ?? null
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
async resolveX402WalletForMerchantCall() {
|
|
1845
|
+
const localWallet = this.x402PayerAddress();
|
|
1846
|
+
if (localWallet) return localWallet;
|
|
1847
|
+
try {
|
|
1848
|
+
const agent = await this.getAgent();
|
|
1849
|
+
return agent.delegateAddress ?? void 0;
|
|
1850
|
+
} catch {
|
|
1851
|
+
return void 0;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1665
1854
|
async authorizeMachinePayment(challenge, options = {}) {
|
|
1666
1855
|
if (!this.delegateKey) {
|
|
1667
1856
|
throw new HavenSigningError(
|
|
@@ -2259,7 +2448,7 @@ var HavenClient = class {
|
|
|
2259
2448
|
headers
|
|
2260
2449
|
};
|
|
2261
2450
|
}
|
|
2262
|
-
buildX402Quote(paymentRequired, request, idempotencyKey) {
|
|
2451
|
+
buildX402Quote(paymentRequired, request, idempotencyKey, mcpTransport) {
|
|
2263
2452
|
const option = selectStandardPaymentOption(paymentRequired.accepts);
|
|
2264
2453
|
if (!option) {
|
|
2265
2454
|
throw new HavenApiError(
|
|
@@ -2274,6 +2463,7 @@ var HavenClient = class {
|
|
|
2274
2463
|
paymentRequired,
|
|
2275
2464
|
accepted: option,
|
|
2276
2465
|
request,
|
|
2466
|
+
...mcpTransport ? { mcpTransport } : {},
|
|
2277
2467
|
resourceUrl: paymentRequired.resource.url,
|
|
2278
2468
|
description: paymentRequired.resource.description ?? option.description ?? null,
|
|
2279
2469
|
mimeType: paymentRequired.resource.mimeType ?? option.mimeType ?? null,
|
|
@@ -2287,6 +2477,18 @@ var HavenClient = class {
|
|
|
2287
2477
|
maxTimeoutSeconds: option.maxTimeoutSeconds
|
|
2288
2478
|
};
|
|
2289
2479
|
}
|
|
2480
|
+
async detectX402McpTransport(url, paymentRequired, response) {
|
|
2481
|
+
if (isMcpUrl(url)) {
|
|
2482
|
+
return { handshakeRequired: true, source: "path" };
|
|
2483
|
+
}
|
|
2484
|
+
if (paymentRequired.extensions?.bazaar != null) {
|
|
2485
|
+
return { handshakeRequired: true, source: "bazaar" };
|
|
2486
|
+
}
|
|
2487
|
+
if (await responseHasBazaarExtension(response)) {
|
|
2488
|
+
return { handshakeRequired: true, source: "bazaar" };
|
|
2489
|
+
}
|
|
2490
|
+
return void 0;
|
|
2491
|
+
}
|
|
2290
2492
|
buildX402ResumeState(input) {
|
|
2291
2493
|
const token = resolveTokenFromAddress(input.accepted.asset, input.accepted.network);
|
|
2292
2494
|
return {
|
|
@@ -2814,8 +3016,9 @@ var toolDescriptions = {
|
|
|
2814
3016
|
nextActionGuidance: ""
|
|
2815
3017
|
},
|
|
2816
3018
|
getAgent: {
|
|
2817
|
-
summary: "Return the authenticated agent identity
|
|
2818
|
-
|
|
3019
|
+
summary: "Return the authenticated agent identity AND its live spend authority in one call: Haven wallet, delegate, chain, raw status, a readiness signal, and per-token remaining allowance (atomic + human-readable). The recommended first call in a new session to confirm who you are and whether you can pay right now.",
|
|
3020
|
+
selectionGuidance: "Use this as the one-shot orientation/bootstrap at the start of a session, or whenever you need to confirm identity together with whether the agent can spend right now. For a detailed per-token breakdown (configured vs spent vs reset window) use haven_get_allowances.",
|
|
3021
|
+
behavior: 'Reads identity plus the on-chain AllowanceModule snapshot in one shot. readiness is "ready" when at least one token has remaining on-chain allowance, "needs_approval" when the agent is active but has no remaining allowance to auto-spend (payments will be queued for the wallet owner to approve in Haven), and "revoked" when the credential is not active. allowances[] carries remainingAtomic and remainingDisplay per token. Identity fields (id, name, status, safeAddress, delegateAddress, chainId) are unchanged from before.',
|
|
2819
3022
|
nextActionGuidance: ""
|
|
2820
3023
|
},
|
|
2821
3024
|
getAllowances: {
|
|
@@ -2839,8 +3042,8 @@ var toolDescriptions = {
|
|
|
2839
3042
|
discoverTools: {
|
|
2840
3043
|
summary: "Discover payable services from Haven's curated merchant catalog \u2014 names, prices, and which pay tool to use.",
|
|
2841
3044
|
selectionGuidance: "Use this when the user asks what the agent can buy, pay for, or which paid services exist \u2014 or when you need a resource URL for a service the user described. Do NOT use for balance, budget, or spend-limit questions \u2014 use haven_get_allowances. Do NOT use to pay \u2014 each returned entry names the pay tool to use next.",
|
|
2842
|
-
behavior: "Read-only lookup against Haven's curated catalog. Entries are periodically re-verified against the live merchant; degraded entries are flagged. Returns name, description, price, rail, resource URL, and a suggested_tool field naming the exact Haven pay tool for that entry. Never creates a payment, signature, or approval.",
|
|
2843
|
-
nextActionGuidance: "Pick an entry
|
|
3045
|
+
behavior: "Read-only lookup against Haven's curated catalog. Entries are periodically re-verified against the live merchant; degraded entries are flagged. Returns name, description, price, rail, resource URL, and a suggested_tool field naming the exact Haven pay tool for that entry. The catalog price (price_display/price_atomic, marked price_is_indicative) is a last-verified hint, NOT authoritative \u2014 the real price comes from the merchant's live 402 at pay time. Never creates a payment, signature, or approval.",
|
|
3046
|
+
nextActionGuidance: "Pick an entry and pay it with the tool named in suggested_tool, passing the entry's resource_url (and tool_name for MCP merchants). Confirm the price from the live pay-tool result (not the catalog), and pass max_amount when the user has a cap."
|
|
2844
3047
|
},
|
|
2845
3048
|
sweep_delegate: {
|
|
2846
3049
|
summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating Safe.",
|
|
@@ -3107,18 +3310,37 @@ the Haven MCP tools. Every payment is checked against the agent's on-chain
|
|
|
3107
3310
|
budget before money moves; payments above the remaining budget wait for the
|
|
3108
3311
|
user's approval in Haven.
|
|
3109
3312
|
|
|
3313
|
+
Hosted tools run in the \`mcp__haven__\` namespace. Local signing tools run in
|
|
3314
|
+
the \`mcp__haven-signer__\` namespace and keep the delegate key on this machine.
|
|
3315
|
+
|
|
3110
3316
|
## When to use this skill
|
|
3111
3317
|
|
|
3112
3318
|
- The user asks to send money, pay someone, tip, donate, or transfer tokens.
|
|
3113
3319
|
- A request returns HTTP 402 (x402): use the Haven pay tools to settle it,
|
|
3114
3320
|
then retry the original request.
|
|
3115
3321
|
|
|
3116
|
-
## Identity and budget
|
|
3322
|
+
## Identity and budget
|
|
3323
|
+
|
|
3324
|
+
Do not guess the wallet address, network, or budget.
|
|
3117
3325
|
|
|
3118
|
-
|
|
3326
|
+
For instant orientation at the start of a session, read the non-secret
|
|
3327
|
+
\`agent.json\` the connector wrote to your Haven credential directory (typically
|
|
3328
|
+
\`~/.haven/agents/<agent-id>/agent.json\` \u2014 if you don't know the agent id, list
|
|
3329
|
+
\`~/.haven/agents/\` to find the folder). It
|
|
3330
|
+
holds your agent id, Haven wallet address, network, and *configured* per-token
|
|
3331
|
+
budget, and contains no keys \u2014 the fastest way to answer "who am I and what may
|
|
3332
|
+
I spend" with no round trip. If that file is absent (some setups don't write
|
|
3333
|
+
it), use the tools below instead.
|
|
3119
3334
|
|
|
3120
|
-
|
|
3121
|
-
|
|
3335
|
+
Before any payment, confirm the *live remaining* budget with the tools \u2014
|
|
3336
|
+
\`agent.json\` shows the configured budget, not what is left after recent
|
|
3337
|
+
spending:
|
|
3338
|
+
|
|
3339
|
+
- \`haven_get_agent\` \u2014 the recommended first call: identity (wallet, network)
|
|
3340
|
+
plus a readiness signal (\`ready\` / \`needs_approval\` / \`revoked\`) and live
|
|
3341
|
+
remaining per-token allowance, in one shot.
|
|
3342
|
+
- \`haven_get_allowances\` \u2014 detailed per-token breakdown (configured, spent,
|
|
3343
|
+
reset window) when you need more than the summary.
|
|
3122
3344
|
|
|
3123
3345
|
Budgets reset on a period the user chose. If a payment exceeds the remaining
|
|
3124
3346
|
budget it is queued for the user to approve in the Haven dashboard \u2014 this is
|
|
@@ -3132,13 +3354,33 @@ normal, not an error.
|
|
|
3132
3354
|
the local Haven signer; follow the tool results \u2014 they tell you the next
|
|
3133
3355
|
action at every step. Retry the original request only when the result says
|
|
3134
3356
|
\`retry_original_x402_request\`.
|
|
3135
|
-
- **Paid MCP tool call:** \`
|
|
3136
|
-
name, and arguments
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
\`
|
|
3141
|
-
|
|
3357
|
+
- **Paid MCP tool call:** \`mcp__haven__haven_pay_mcp_tool\` with the merchant
|
|
3358
|
+
URL, tool name, and arguments, then finish in two calls (fast path):
|
|
3359
|
+
\`mcp__haven-signer__haven_sign_x402\` on the local signer (pass
|
|
3360
|
+
\`payload_hash\`, \`x402_expected\` as the nested \`x402.expected\` object, and
|
|
3361
|
+
\`payment_required\`) returns \`{ signature, payment_header }\`; then
|
|
3362
|
+
\`mcp__haven__haven_settle_mcp_tool\` (pass \`payment_id\`, \`signature\`,
|
|
3363
|
+
\`payment_header\`, \`merchant_url\`, \`tool_name\`, \`arguments\`,
|
|
3364
|
+
\`mcp_transport\`) funds and settles in one step and returns the tool result.
|
|
3365
|
+
If it returns \`settled: false\`, funding is queued for the user's approval \u2014
|
|
3366
|
+
tell them and check status later, do not re-pay. Step-by-step alternative:
|
|
3367
|
+
\`mcp__haven-signer__haven_sign\` \u2192 \`mcp__haven__haven_submit\` \u2192
|
|
3368
|
+
\`mcp__haven-signer__haven_x402_sign_header\` \u2192
|
|
3369
|
+
\`mcp__haven__haven_complete_mcp_tool\`. Pass \`payment_required\`,
|
|
3370
|
+
\`arguments\`, and \`mcp_transport\` verbatim from the
|
|
3371
|
+
\`mcp__haven__haven_pay_mcp_tool\` result. The returned \`expires_at\` is the
|
|
3372
|
+
signing window; if a tool returns \`PAYMENT_WINDOW_EXPIRED\`, re-run
|
|
3373
|
+
\`mcp__haven__haven_pay_mcp_tool\` with the same
|
|
3374
|
+
\`idempotency_key\`. Do not call the merchant yourself \u2014 Haven completes the
|
|
3375
|
+
merchant leg for you.
|
|
3376
|
+
- **Prices:** show the user the live price from the pay-tool result, never a
|
|
3377
|
+
catalog price. \`haven_discover_tools\` prices are indicative
|
|
3378
|
+
(\`price_is_indicative\`) and can be stale. The pay-tool result's \`amount\` /
|
|
3379
|
+
\`amount_atomic\` is the amount Haven authorizes for the call \u2014 a ceiling the
|
|
3380
|
+
merchant settles at or below \u2014 so present it as the most the user will pay.
|
|
3381
|
+
Pass \`max_amount\` (atomic units) to \`haven_pay_mcp_tool\` /
|
|
3382
|
+
\`haven_pay_x402_quote\` to reject a quote whose authorized amount is above the
|
|
3383
|
+
user's cap, before any funds move.
|
|
3142
3384
|
- **Status:** \`haven_get_payment_status\` with a \`payment_id\` to check on
|
|
3143
3385
|
queued or in-flight payments. Do not poll in a tight loop.
|
|
3144
3386
|
|
|
@@ -3147,18 +3389,26 @@ normal, not an error.
|
|
|
3147
3389
|
- A result with \`pending_approval\` means the payment exceeded the remaining
|
|
3148
3390
|
budget and is waiting for the user in Haven. Tell the user, then check
|
|
3149
3391
|
status later.
|
|
3150
|
-
- Never ask the user for private keys
|
|
3151
|
-
|
|
3152
|
-
tell the user to re-run the Haven
|
|
3392
|
+
- Never ask the user for private keys. Signing happens only in the local Haven
|
|
3393
|
+
signer; the hosted Haven tools never receive the signing key. If a tool
|
|
3394
|
+
reports a missing or invalid credential, tell the user to re-run the Haven
|
|
3395
|
+
setup command.
|
|
3153
3396
|
|
|
3154
3397
|
## Failure handling
|
|
3155
3398
|
|
|
3156
|
-
Haven
|
|
3157
|
-
|
|
3399
|
+
Haven tool failures are shaped like \`{ success: false, code, message, ... }\`
|
|
3400
|
+
or older \`{ error, status, details? }\` responses. Branch on \`code\` when
|
|
3401
|
+
present and surface \`message\` or \`error\` verbatim. Common cases:
|
|
3158
3402
|
|
|
3159
3403
|
- \`pending_approval\`: queued for the user's approval (see above).
|
|
3160
3404
|
- \`insufficient_funds\`: the Haven wallet doesn't hold enough of that token.
|
|
3161
3405
|
Suggest the user add funds in the Haven dashboard.
|
|
3406
|
+
- \`PRICE_EXCEEDS_MAX\`: the live merchant price exceeded your \`max_amount\`.
|
|
3407
|
+
No funds moved; ask the user before retrying with a higher cap.
|
|
3408
|
+
- \`PAYMENT_WINDOW_EXPIRED\`: re-run \`mcp__haven__haven_pay_mcp_tool\` with the same
|
|
3409
|
+
\`idempotency_key\`, then sign the fresh \`payload_hash\`.
|
|
3410
|
+
- \`MERCHANT_REJECTED_AFTER_FUNDING\`: stop retrying the merchant and use
|
|
3411
|
+
\`mcp__haven__haven_sweep_delegate\` to recover stranded delegate funds.
|
|
3162
3412
|
- Budget exceeded: tell the user how much remains (from
|
|
3163
3413
|
\`haven_get_allowances\`) and that they can raise the budget in Haven.
|
|
3164
3414
|
|
|
@@ -3170,9 +3420,105 @@ for that credential.
|
|
|
3170
3420
|
`;
|
|
3171
3421
|
var SKILL_FOLDER_NAME = "haven-pay";
|
|
3172
3422
|
|
|
3423
|
+
// src/sweep.ts
|
|
3424
|
+
var SWEEP_BASE_CHAIN_ID = 8453;
|
|
3425
|
+
var SWEEP_BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
3426
|
+
var USDC_EIP712_DOMAIN_BY_CHAIN = {
|
|
3427
|
+
[SWEEP_BASE_CHAIN_ID]: {
|
|
3428
|
+
name: "USD Coin",
|
|
3429
|
+
version: "2",
|
|
3430
|
+
chainId: SWEEP_BASE_CHAIN_ID,
|
|
3431
|
+
verifyingContract: SWEEP_BASE_USDC_ADDRESS
|
|
3432
|
+
}
|
|
3433
|
+
};
|
|
3434
|
+
var USDC_ADDRESS_BY_CHAIN = {
|
|
3435
|
+
[SWEEP_BASE_CHAIN_ID]: SWEEP_BASE_USDC_ADDRESS
|
|
3436
|
+
};
|
|
3437
|
+
var TRANSFER_WITH_AUTHORIZATION_TYPES = {
|
|
3438
|
+
TransferWithAuthorization: [
|
|
3439
|
+
{ name: "from", type: "address" },
|
|
3440
|
+
{ name: "to", type: "address" },
|
|
3441
|
+
{ name: "value", type: "uint256" },
|
|
3442
|
+
{ name: "validAfter", type: "uint256" },
|
|
3443
|
+
{ name: "validBefore", type: "uint256" },
|
|
3444
|
+
{ name: "nonce", type: "bytes32" }
|
|
3445
|
+
]
|
|
3446
|
+
};
|
|
3447
|
+
function sweepUsdcAddress(chainId) {
|
|
3448
|
+
const address = USDC_ADDRESS_BY_CHAIN[chainId];
|
|
3449
|
+
if (!address) {
|
|
3450
|
+
throw new HavenSigningError(
|
|
3451
|
+
`Sweep is only supported on Base (chainId ${SWEEP_BASE_CHAIN_ID}). Got chainId ${chainId}.`
|
|
3452
|
+
);
|
|
3453
|
+
}
|
|
3454
|
+
return address;
|
|
3455
|
+
}
|
|
3456
|
+
function sweepUsdcDomain(chainId) {
|
|
3457
|
+
const domain = USDC_EIP712_DOMAIN_BY_CHAIN[chainId];
|
|
3458
|
+
if (!domain) {
|
|
3459
|
+
throw new HavenSigningError(
|
|
3460
|
+
`Sweep is only supported on Base (chainId ${SWEEP_BASE_CHAIN_ID}). Got chainId ${chainId}.`
|
|
3461
|
+
);
|
|
3462
|
+
}
|
|
3463
|
+
return domain;
|
|
3464
|
+
}
|
|
3465
|
+
function sameAddress2(a, b) {
|
|
3466
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
3467
|
+
}
|
|
3468
|
+
function buildSweepTypedData(auth) {
|
|
3469
|
+
const domain = sweepUsdcDomain(auth.chainId);
|
|
3470
|
+
const expectedToken = sweepUsdcAddress(auth.chainId);
|
|
3471
|
+
if (!sameAddress2(auth.token, expectedToken)) {
|
|
3472
|
+
throw new HavenSigningError(
|
|
3473
|
+
`Sweep token ${auth.token} is not the canonical USDC contract for chain ${auth.chainId}.`
|
|
3474
|
+
);
|
|
3475
|
+
}
|
|
3476
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(auth.nonce)) {
|
|
3477
|
+
throw new HavenSigningError("Sweep nonce must be a 0x-prefixed 32-byte hex string.");
|
|
3478
|
+
}
|
|
3479
|
+
return {
|
|
3480
|
+
domain,
|
|
3481
|
+
types: TRANSFER_WITH_AUTHORIZATION_TYPES,
|
|
3482
|
+
primaryType: "TransferWithAuthorization",
|
|
3483
|
+
message: {
|
|
3484
|
+
from: auth.from,
|
|
3485
|
+
to: auth.to,
|
|
3486
|
+
value: BigInt(auth.value),
|
|
3487
|
+
validAfter: BigInt(auth.validAfter),
|
|
3488
|
+
validBefore: BigInt(auth.validBefore),
|
|
3489
|
+
nonce: auth.nonce
|
|
3490
|
+
}
|
|
3491
|
+
};
|
|
3492
|
+
}
|
|
3493
|
+
function buildSweepAuthorizationMessage(auth) {
|
|
3494
|
+
return `Haven sweep authorization v1
|
|
3495
|
+
${stableStringify2({
|
|
3496
|
+
version: 1,
|
|
3497
|
+
kind: "haven.sweep.authorization",
|
|
3498
|
+
from: auth.from.toLowerCase(),
|
|
3499
|
+
to: auth.to.toLowerCase(),
|
|
3500
|
+
value: auth.value,
|
|
3501
|
+
validAfter: auth.validAfter,
|
|
3502
|
+
validBefore: auth.validBefore,
|
|
3503
|
+
nonce: auth.nonce.toLowerCase(),
|
|
3504
|
+
token: auth.token.toLowerCase(),
|
|
3505
|
+
chainId: auth.chainId
|
|
3506
|
+
})}`;
|
|
3507
|
+
}
|
|
3508
|
+
function stableStringify2(value) {
|
|
3509
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
3510
|
+
if (Array.isArray(value)) return `[${value.map((item) => stableStringify2(item)).join(",")}]`;
|
|
3511
|
+
const object = value;
|
|
3512
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(object[key])}`).join(",")}}`;
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3515
|
+
exports.AGENT_PAYMENT_FAILURE_CODE_VALUES = AGENT_PAYMENT_FAILURE_CODE_VALUES;
|
|
3173
3516
|
exports.AGENT_PAYMENT_NEXT_ACTION_VALUES = AGENT_PAYMENT_NEXT_ACTION_VALUES;
|
|
3174
3517
|
exports.AGENT_PAYMENT_PHASE_VALUES = AGENT_PAYMENT_PHASE_VALUES;
|
|
3175
3518
|
exports.AGENT_PAYMENT_RAIL_VALUES = AGENT_PAYMENT_RAIL_VALUES;
|
|
3519
|
+
exports.AgentPaymentFailureCode = AgentPaymentFailureCode;
|
|
3520
|
+
exports.AgentPaymentFailureCodeDescriptions = AgentPaymentFailureCodeDescriptions;
|
|
3521
|
+
exports.AgentPaymentFailureCodeSchema = AgentPaymentFailureCodeSchema;
|
|
3176
3522
|
exports.AgentPaymentNextAction = AgentPaymentNextAction;
|
|
3177
3523
|
exports.AgentPaymentNextActionDescriptions = AgentPaymentNextActionDescriptions;
|
|
3178
3524
|
exports.AgentPaymentNextActionSchema = AgentPaymentNextActionSchema;
|
|
@@ -3190,8 +3536,13 @@ exports.HavenPaymentStateError = HavenPaymentStateError;
|
|
|
3190
3536
|
exports.HavenSigningError = HavenSigningError;
|
|
3191
3537
|
exports.HavenTimeoutError = HavenTimeoutError;
|
|
3192
3538
|
exports.SKILL_FOLDER_NAME = SKILL_FOLDER_NAME;
|
|
3539
|
+
exports.SWEEP_BASE_CHAIN_ID = SWEEP_BASE_CHAIN_ID;
|
|
3540
|
+
exports.SWEEP_BASE_USDC_ADDRESS = SWEEP_BASE_USDC_ADDRESS;
|
|
3541
|
+
exports.TRANSFER_WITH_AUTHORIZATION_TYPES = TRANSFER_WITH_AUTHORIZATION_TYPES;
|
|
3193
3542
|
exports.addressFromKey = addressFromKey;
|
|
3194
3543
|
exports.buildMachinePaymentIdempotencyKey = buildMachinePaymentIdempotencyKey;
|
|
3544
|
+
exports.buildSweepAuthorizationMessage = buildSweepAuthorizationMessage;
|
|
3545
|
+
exports.buildSweepTypedData = buildSweepTypedData;
|
|
3195
3546
|
exports.buildX402ExpectedMessage = buildX402ExpectedMessage;
|
|
3196
3547
|
exports.composeDescription = composeDescription;
|
|
3197
3548
|
exports.decodeBase64Json = decodeBase64Json;
|
|
@@ -3208,6 +3559,8 @@ exports.parsePaymentRequiredResponse = parsePaymentRequiredResponse;
|
|
|
3208
3559
|
exports.selectPaymentOption = selectPaymentOption;
|
|
3209
3560
|
exports.selectStandardPaymentOption = selectStandardPaymentOption;
|
|
3210
3561
|
exports.signHash = signHash;
|
|
3562
|
+
exports.sweepUsdcAddress = sweepUsdcAddress;
|
|
3563
|
+
exports.sweepUsdcDomain = sweepUsdcDomain;
|
|
3211
3564
|
exports.toStandardPaymentRequirements = toStandardPaymentRequirements;
|
|
3212
3565
|
exports.toolDescriptions = toolDescriptions;
|
|
3213
3566
|
exports.verifySignature = verifySignature;
|