@haven_ai/sdk 0.1.22-alpha.0 → 0.1.23-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 +3 -1
- package/dist/index.cjs +107 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -5
- package/dist/index.d.ts +95 -5
- package/dist/index.js +107 -32
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -323,7 +323,9 @@ Hosted MCP and signer tools also return stable `code` values on recoverable x402
|
|
|
323
323
|
|
|
324
324
|
| `code` | Meaning | Agent recovery |
|
|
325
325
|
|--------|---------|----------------|
|
|
326
|
-
| `PRICE_EXCEEDS_MAX` | The merchant-authoritative x402 price is above the caller's
|
|
326
|
+
| `PRICE_EXCEEDS_MAX` | The merchant-authoritative x402 price is above the caller's spending cap. No funding transfer was created. | Tell the user the live price exceeded the cap and retry only after they confirm a higher one. |
|
|
327
|
+
| `AMBIGUOUS_MAX_AMOUNT` | Both `max_amount` (atomic units) and `max_amount_human` (whole tokens) were sent for one purchase. Nothing was contacted and nothing was spent. | Re-send with exactly one — `max_amount_human` for a cap the user stated in tokens, `max_amount` for an exact atomic figure. |
|
|
328
|
+
| `MAX_AMOUNT_UNCONVERTIBLE` | `max_amount_human` could not be converted against this quote's asset — its decimals are unknown to Haven, or the cap has more decimal places than the asset supports. Nothing was spent. | Round the cap to the asset's decimals, or re-send it as an exact atomic `max_amount`. |
|
|
327
329
|
| `PAYMENT_WINDOW_EXPIRED` | The funding/quote window closed before `haven_x402_sign_header`, `haven_submit`, or `haven_complete_mcp_tool` could finish. | Re-run `haven_pay_mcp_tool` with the same `idempotency_key`, then sign and complete the fresh quote. Payloads include `retry_with_new_quote: true`. |
|
|
328
330
|
| `MERCHANT_REJECTED_AFTER_FUNDING` | Haven's funding leg succeeded, but the merchant rejected the paid retry. | Stop retrying the merchant and call `haven_sweep_delegate` so the user can recover stranded delegate USDC. |
|
|
329
331
|
|
package/dist/index.cjs
CHANGED
|
@@ -104,7 +104,23 @@ var AgentPaymentFailureCode = {
|
|
|
104
104
|
* mechanical: re-send merchant_url, tool_name, arguments, and
|
|
105
105
|
* mcp_transport explicitly (the version-skew path).
|
|
106
106
|
*/
|
|
107
|
-
MerchantCallContextUnavailable: "MERCHANT_CALL_CONTEXT_UNAVAILABLE"
|
|
107
|
+
MerchantCallContextUnavailable: "MERCHANT_CALL_CONTEXT_UNAVAILABLE",
|
|
108
|
+
/**
|
|
109
|
+
* #1351: the caller supplied BOTH the atomic `max_amount` and the
|
|
110
|
+
* human-denominated `max_amount_human` cap for one purchase. Haven refuses
|
|
111
|
+
* to guess which the user meant — the two differ by a factor of 10^decimals,
|
|
112
|
+
* so picking wrong is exactly the silent-overspend this cap exists to
|
|
113
|
+
* prevent. Rejected before any merchant probe, funding intent, or signature.
|
|
114
|
+
*/
|
|
115
|
+
AmbiguousMaxAmount: "AMBIGUOUS_MAX_AMOUNT",
|
|
116
|
+
/**
|
|
117
|
+
* #1351: a human-denominated cap was supplied, but it cannot be converted to
|
|
118
|
+
* atomic units against THIS quote — either the quote's asset has no known
|
|
119
|
+
* decimals on its network, or the cap carries more fraction digits than the
|
|
120
|
+
* asset can represent (truncating it would silently change the user's cap).
|
|
121
|
+
* The fallback is the exact atomic `max_amount`.
|
|
122
|
+
*/
|
|
123
|
+
MaxAmountUnconvertible: "MAX_AMOUNT_UNCONVERTIBLE"
|
|
108
124
|
};
|
|
109
125
|
var AgentPaymentRail = {
|
|
110
126
|
/** Standard Haven payment from the user's Safe through an approved delegate allowance. */
|
|
@@ -159,7 +175,9 @@ var AgentPaymentFailureCodeDescriptions = {
|
|
|
159
175
|
[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.",
|
|
160
176
|
[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.",
|
|
161
177
|
[AgentPaymentFailureCode.MerchantUnresponsiveAfterFunding]: "The Haven funding leg succeeded, but the merchant did not answer the paid retry before the timeout. The merchant may still settle late \u2014 check haven_get_payment_status (and retry haven_complete_mcp_tool once) BEFORE sweeping; sweep only if no settlement appears.",
|
|
162
|
-
[AgentPaymentFailureCode.MerchantCallContextUnavailable]: "merchant_url/tool_name were omitted and no stored merchant call context is available for this payment_id. Re-send merchant_url, tool_name, arguments, and mcp_transport explicitly."
|
|
178
|
+
[AgentPaymentFailureCode.MerchantCallContextUnavailable]: "merchant_url/tool_name were omitted and no stored merchant call context is available for this payment_id. Re-send merchant_url, tool_name, arguments, and mcp_transport explicitly.",
|
|
179
|
+
[AgentPaymentFailureCode.AmbiguousMaxAmount]: "Both max_amount (atomic units) and max_amount_human (whole tokens) were supplied for one purchase. Nothing was contacted and nothing was spent. Re-send with exactly ONE: max_amount_human for a cap the user stated in tokens, max_amount for an exact atomic figure.",
|
|
180
|
+
[AgentPaymentFailureCode.MaxAmountUnconvertible]: "max_amount_human could not be converted to atomic units against this quote's asset \u2014 either its decimals are unknown to Haven or the cap has more decimal places than the asset supports. Nothing was spent. Round the cap, or re-send it as an exact atomic max_amount."
|
|
163
181
|
};
|
|
164
182
|
var AgentPaymentWarningCode = {
|
|
165
183
|
/** No max_amount cap was supplied — the live quoted price was accepted as-is. */
|
|
@@ -1094,8 +1112,7 @@ var HavenClient = class {
|
|
|
1094
1112
|
400
|
|
1095
1113
|
);
|
|
1096
1114
|
}
|
|
1097
|
-
const
|
|
1098
|
-
const fundingTo = agent.delegateAddress;
|
|
1115
|
+
const fundingTo = options.delegateAddress ?? (await this.getAgent()).delegateAddress;
|
|
1099
1116
|
if (!fundingTo) {
|
|
1100
1117
|
throw new HavenApiError("Authenticated agent has no delegate address registered.", 502);
|
|
1101
1118
|
}
|
|
@@ -1104,13 +1121,25 @@ var HavenClient = class {
|
|
|
1104
1121
|
url: paymentRequired.resource.url,
|
|
1105
1122
|
payTo: fundingTo,
|
|
1106
1123
|
merchantPayTo: option.payTo,
|
|
1124
|
+
// #1360: this path ALWAYS means the EIP-3009 funding leg (payTo is the
|
|
1125
|
+
// agent's own delegate EOA). Saying so explicitly turns a stale/rotated
|
|
1126
|
+
// delegate address into the backend's LOUD shape-mismatch 400 instead
|
|
1127
|
+
// of a silent reroute to the erc7710 settlement branch (the #1358
|
|
1128
|
+
// review's open-budget misroute). Legacy-rail backends ignore the field.
|
|
1129
|
+
settlementScheme: "eip3009",
|
|
1107
1130
|
amount: x402AuthorizationAmount(option),
|
|
1108
1131
|
asset: option.asset,
|
|
1109
1132
|
network: option.network,
|
|
1110
1133
|
description: paymentRequired.resource.description,
|
|
1111
1134
|
idempotencyKey,
|
|
1112
1135
|
// #1307: persisted so the settle leg can rehydrate it by payment_id.
|
|
1113
|
-
...options.mcpCallContext ? { mcpCallContext: options.mcpCallContext } : {}
|
|
1136
|
+
...options.mcpCallContext ? { mcpCallContext: options.mcpCallContext } : {},
|
|
1137
|
+
// #1355: persisted so the SIGN leg can rehydrate it by payment_id — the
|
|
1138
|
+
// local signer's context fetch then carries the 402 PaymentRequired and
|
|
1139
|
+
// the agent passes only payment_id. Bounded: the backend rejects >64KB,
|
|
1140
|
+
// so an oversized blob is omitted here (signer falls back to the
|
|
1141
|
+
// caller-supplied copy) rather than failing the intent.
|
|
1142
|
+
...new TextEncoder().encode(JSON.stringify(paymentRequired)).length <= 65536 ? { paymentRequired } : {}
|
|
1114
1143
|
});
|
|
1115
1144
|
if (raw.status !== "pending_signature") {
|
|
1116
1145
|
this.throwPaymentStateError("x402 payment", raw);
|
|
@@ -1242,6 +1271,17 @@ var HavenClient = class {
|
|
|
1242
1271
|
* Get the agent identity tied to this API key.
|
|
1243
1272
|
*/
|
|
1244
1273
|
async getAgent() {
|
|
1274
|
+
if (this.agentInFlight) return this.agentInFlight;
|
|
1275
|
+
const request = this.fetchAgent();
|
|
1276
|
+
this.agentInFlight = request;
|
|
1277
|
+
request.finally(() => {
|
|
1278
|
+
this.agentInFlight = null;
|
|
1279
|
+
}).catch(() => {
|
|
1280
|
+
});
|
|
1281
|
+
return request;
|
|
1282
|
+
}
|
|
1283
|
+
agentInFlight = null;
|
|
1284
|
+
async fetchAgent() {
|
|
1245
1285
|
const raw = await this.get("/machine-payments/agent");
|
|
1246
1286
|
return {
|
|
1247
1287
|
id: raw.id,
|
|
@@ -1440,6 +1480,7 @@ var HavenClient = class {
|
|
|
1440
1480
|
*/
|
|
1441
1481
|
async getPostPurchaseAllowanceSummary(paymentId) {
|
|
1442
1482
|
const unavailable = (detail) => ({
|
|
1483
|
+
payment: null,
|
|
1443
1484
|
allowance: null,
|
|
1444
1485
|
warnings: [
|
|
1445
1486
|
{
|
|
@@ -1448,27 +1489,38 @@ var HavenClient = class {
|
|
|
1448
1489
|
}
|
|
1449
1490
|
]
|
|
1450
1491
|
});
|
|
1492
|
+
const [statusResult, agentResult, allowanceResult] = await Promise.allSettled([
|
|
1493
|
+
this.getPaymentStatus(paymentId),
|
|
1494
|
+
this.getAgent(),
|
|
1495
|
+
this.getAllowances()
|
|
1496
|
+
]);
|
|
1497
|
+
if (statusResult.status === "rejected") {
|
|
1498
|
+
return unavailable(statusResult.reason instanceof Error ? statusResult.reason.message : String(statusResult.reason));
|
|
1499
|
+
}
|
|
1500
|
+
const status = statusResult.value;
|
|
1501
|
+
if (agentResult.status === "rejected") {
|
|
1502
|
+
return { ...unavailable(agentResult.reason instanceof Error ? agentResult.reason.message : String(agentResult.reason)), payment: status };
|
|
1503
|
+
}
|
|
1504
|
+
if (allowanceResult.status === "rejected") {
|
|
1505
|
+
return { ...unavailable(allowanceResult.reason instanceof Error ? allowanceResult.reason.message : String(allowanceResult.reason)), payment: status };
|
|
1506
|
+
}
|
|
1451
1507
|
try {
|
|
1452
|
-
const [status, agent, allowanceSummary] = await Promise.all([
|
|
1453
|
-
this.getPaymentStatus(paymentId),
|
|
1454
|
-
this.getAgent(),
|
|
1455
|
-
this.getAllowances()
|
|
1456
|
-
]);
|
|
1457
1508
|
const tokenAddress = status.asset ?? status.x402?.asset ?? null;
|
|
1458
1509
|
if (!tokenAddress) {
|
|
1459
|
-
return unavailable("the settled payment does not carry a resolvable token address");
|
|
1510
|
+
return { ...unavailable("the settled payment does not carry a resolvable token address"), payment: status };
|
|
1460
1511
|
}
|
|
1461
|
-
const rail =
|
|
1512
|
+
const rail = agentResult.value.executionRail;
|
|
1462
1513
|
const source = rail === "delegation" ? "active_delegations" : "allowance_module";
|
|
1463
|
-
const match =
|
|
1514
|
+
const match = allowanceResult.value.allowances.find(
|
|
1464
1515
|
(a) => a.tokenAddress.toLowerCase() === tokenAddress.toLowerCase()
|
|
1465
1516
|
);
|
|
1466
1517
|
if (!match) {
|
|
1467
|
-
return unavailable("no allowance/budget row matches the settled token");
|
|
1518
|
+
return { ...unavailable("no allowance/budget row matches the settled token"), payment: status };
|
|
1468
1519
|
}
|
|
1469
1520
|
const token = resolveTokenFromAddress(match.tokenAddress);
|
|
1470
1521
|
const remainingDisplay = token ? `${formatAtomicAmount(safeBigInt(match.onchain.remaining), token.decimals)} ${match.tokenSymbol}` : void 0;
|
|
1471
1522
|
return {
|
|
1523
|
+
payment: status,
|
|
1472
1524
|
allowance: {
|
|
1473
1525
|
rail,
|
|
1474
1526
|
remaining_atomic: match.onchain.remaining,
|
|
@@ -1516,6 +1568,7 @@ var HavenClient = class {
|
|
|
1516
1568
|
async discoverTools(options = {}) {
|
|
1517
1569
|
const params = new URLSearchParams();
|
|
1518
1570
|
if (options.category) params.set("category", options.category);
|
|
1571
|
+
if (options.search !== void 0) params.set("search", options.search);
|
|
1519
1572
|
if (options.rail) params.set("rail", options.rail);
|
|
1520
1573
|
const query = params.size > 0 ? `?${params.toString()}` : "";
|
|
1521
1574
|
const raw = await this.get(`/catalog${query}`);
|
|
@@ -1707,7 +1760,11 @@ var HavenClient = class {
|
|
|
1707
1760
|
asset: option.asset,
|
|
1708
1761
|
network: option.network,
|
|
1709
1762
|
description: paymentRequired.resource.description,
|
|
1710
|
-
idempotencyKey
|
|
1763
|
+
idempotencyKey,
|
|
1764
|
+
// #1360: same explicit funding-leg declaration as createX402Intent —
|
|
1765
|
+
// this local-key path derives payTo from the key (never stale), but the
|
|
1766
|
+
// declaration keeps both writers of the 3009 shape loud-by-default.
|
|
1767
|
+
settlementScheme: "eip3009"
|
|
1711
1768
|
});
|
|
1712
1769
|
if (raw.success && raw.tx_hash) {
|
|
1713
1770
|
const receipt2 = this.mapX402ReceiptFromAuthorization(paymentRequired, option, paymentHeader, raw);
|
|
@@ -2910,6 +2967,11 @@ var HavenClient = class {
|
|
|
2910
2967
|
amountAtomic: x402AuthorizationAmount(option),
|
|
2911
2968
|
amount: decimalFromUsdcAtomic(x402AuthorizationAmount(option)),
|
|
2912
2969
|
token: token?.symbol ?? "USDC",
|
|
2970
|
+
// #1351: null when the asset is unrecognised on this network — the
|
|
2971
|
+
// `token` fallback above is a LABEL, not evidence of 6 decimals, and a
|
|
2972
|
+
// human-denominated cap must fail closed rather than convert against a
|
|
2973
|
+
// guess. Same resolution as `token`, so the two never disagree.
|
|
2974
|
+
decimals: token?.decimals ?? null,
|
|
2913
2975
|
asset: option.asset,
|
|
2914
2976
|
network: option.network,
|
|
2915
2977
|
chainId: chainIdOrNull(option.network),
|
|
@@ -3524,8 +3586,8 @@ var toolDescriptions = {
|
|
|
3524
3586
|
discoverTools: {
|
|
3525
3587
|
summary: "Step 1 of a purchase: discover payable services from Haven's curated merchant catalog \u2014 names, prices, and which pay tool to use next.",
|
|
3526
3588
|
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.",
|
|
3527
|
-
behavior: "Use each entry's suggested_tool field first \u2014 it names the exact next call. Read-only lookup against Haven's curated catalog; entries are periodically re-verified against the live merchant and degraded entries are flagged. Returns name, description, price, rail, resource URL, tool_name, tool_arguments, and suggested_tool. 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.",
|
|
3528
|
-
nextActionGuidance:
|
|
3589
|
+
behavior: "Use each entry's suggested_tool field first \u2014 it names the exact next call. Read-only lookup against Haven's curated catalog; entries are periodically re-verified against the live merchant and degraded entries are flagged. Use category for a case-insensitive category filter (for example, VPN or vpn), or search for a product name, category, or description term. Returns name, description, price, rail, resource URL, tool_name, tool_arguments, and suggested_tool. 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.",
|
|
3590
|
+
nextActionGuidance: `Pick an entry and pay it with the tool named in suggested_tool, passing the entry's resource_url, tool_name, and tool_arguments for MCP merchants. Confirm the price from the live pay-tool result (not the catalog), and pass the user's cap as max_amount_human in whole tokens ("no more than 1 USDC" \u2192 max_amount_human: "1") \u2014 never convert it to atomic units by hand (#1351).`
|
|
3529
3591
|
},
|
|
3530
3592
|
sweep_delegate: {
|
|
3531
3593
|
summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating Safe.",
|
|
@@ -3837,10 +3899,13 @@ normal, not an error.
|
|
|
3837
3899
|
|
|
3838
3900
|
1. \`mcp__haven__haven_discover_tools\` to find a payable service and its
|
|
3839
3901
|
\`catalog_id\`.
|
|
3840
|
-
2. \`mcp__haven__haven_prepare_catalog_purchase\` with \`catalog_id\` and
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3902
|
+
2. \`mcp__haven__haven_prepare_catalog_purchase\` with \`catalog_id\` and a
|
|
3903
|
+
spending cap. A cap is REQUIRED on this tool and is best practice on every
|
|
3904
|
+
paid call below too \u2014 it caps what the LIVE merchant quote may charge,
|
|
3905
|
+
checked before any funding intent is created. Write it the way the user
|
|
3906
|
+
said it: \`max_amount_human\` is whole tokens, so "no more than 1 USDC" is
|
|
3907
|
+
\`max_amount_human: "1"\`. (\`max_amount\` is the atomic-unit form, where
|
|
3908
|
+
"1" means 0.000001 USDC \u2014 do not convert by hand, and never send both.)
|
|
3844
3909
|
3. Then FOLLOW THE RESPONSE'S GUIDANCE FIELDS: \`next_action\`, \`next_tool\`,
|
|
3845
3910
|
and \`next_arguments\` name the exact next call \u2014 act on those first; the
|
|
3846
3911
|
prose in this section is fallback and debugging detail. If the catalog
|
|
@@ -3848,9 +3913,11 @@ normal, not an error.
|
|
|
3848
3913
|
\`mcp__haven__haven_pay_mcp_tool\` (merchant URL, tool name, arguments) as
|
|
3849
3914
|
the manual fallback.
|
|
3850
3915
|
|
|
3851
|
-
**Signing:** \`mcp__haven-signer__haven_sign_x402\` with \`payment_id\`
|
|
3852
|
-
|
|
3853
|
-
itself, so never relay \`typed_data\` yourself.
|
|
3916
|
+
**Signing:** \`mcp__haven-signer__haven_sign_x402\` with \`payment_id\` ONLY \u2014
|
|
3917
|
+
the local signer fetches the exact signing bytes AND \`payment_required\`
|
|
3918
|
+
itself, so never relay \`typed_data\` or the 402 blob yourself. If the signer
|
|
3919
|
+
reports its fetched context carried no \`payment_required\` (older backend),
|
|
3920
|
+
re-call with \`payment_required\` added verbatim. Fallback for an older signer
|
|
3854
3921
|
or backend: re-run the quote/prepare tool with the SAME \`idempotency_key\`
|
|
3855
3922
|
plus \`include_signing_payload=true\`, then pass \`payload_hash\`,
|
|
3856
3923
|
\`x402_expected\` (the nested \`x402.expected\` object), and
|
|
@@ -3920,8 +3987,14 @@ present and surface \`message\` or \`error\` verbatim. Common cases:
|
|
|
3920
3987
|
- \`pending_approval\`: queued for the user's approval (see above).
|
|
3921
3988
|
- \`insufficient_funds\`: the Haven wallet doesn't hold enough of that token.
|
|
3922
3989
|
Suggest the user add funds in the Haven dashboard.
|
|
3923
|
-
- \`PRICE_EXCEEDS_MAX\`: the live merchant price exceeded your
|
|
3924
|
-
|
|
3990
|
+
- \`PRICE_EXCEEDS_MAX\`: the live merchant price exceeded your cap. No funds
|
|
3991
|
+
moved; ask the user before retrying with a higher one.
|
|
3992
|
+
- \`AMBIGUOUS_MAX_AMOUNT\`: you sent both \`max_amount\` and
|
|
3993
|
+
\`max_amount_human\`. Nothing was contacted or spent \u2014 re-send with exactly
|
|
3994
|
+
one (\`max_amount_human\` for a cap the user stated in tokens).
|
|
3995
|
+
- \`MAX_AMOUNT_UNCONVERTIBLE\`: \`max_amount_human\` does not fit this quote's
|
|
3996
|
+
asset \u2014 unknown decimals, or more decimal places than the asset supports.
|
|
3997
|
+
Round the cap, or send an exact atomic \`max_amount\`.
|
|
3925
3998
|
- \`PAYMENT_WINDOW_EXPIRED\`: re-run the quote/prepare tool with the same
|
|
3926
3999
|
\`idempotency_key\`, then sign the fresh payload.
|
|
3927
4000
|
- \`MERCHANT_REJECTED_AFTER_FUNDING\`: the merchant refused the paid retry.
|
|
@@ -3940,10 +4013,12 @@ present and surface \`message\` or \`error\` verbatim. Common cases:
|
|
|
3940
4013
|
## Reporting after a purchase
|
|
3941
4014
|
|
|
3942
4015
|
A settled \`mcp__haven__haven_settle_mcp_tool\` response carries
|
|
3943
|
-
\`agent_summary\` and the remaining post-purchase allowance
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
purchase
|
|
4016
|
+
\`agent_summary.purchase_summary\` and the remaining post-purchase allowance
|
|
4017
|
+
in \`allowance\` \u2014 report the product, Haven-derived payment/transaction
|
|
4018
|
+
fields, and what is left from those fields directly. \`result\` is optional
|
|
4019
|
+
raw merchant evidence; never use it to decide whether the purchase was paid.
|
|
4020
|
+
Do not call \`haven_get_agent\` or \`haven_get_allowances\` again just to
|
|
4021
|
+
report a purchase you already made.
|
|
3947
4022
|
|
|
3948
4023
|
## Revoke
|
|
3949
4024
|
|
|
@@ -3954,7 +4029,7 @@ for that credential.
|
|
|
3954
4029
|
var SKILL_FOLDER_NAME = "haven-pay";
|
|
3955
4030
|
|
|
3956
4031
|
// src/node-version.ts
|
|
3957
|
-
var HAVEN_MINIMUM_NODE_VERSION = "
|
|
4032
|
+
var HAVEN_MINIMUM_NODE_VERSION = "22.0.0";
|
|
3958
4033
|
function parseNodeVersion(value) {
|
|
3959
4034
|
const match = value.trim().match(/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
3960
4035
|
if (!match) return [0, 0, 0];
|
|
@@ -4203,6 +4278,7 @@ exports.parseMachinePaymentChallenge = parseMachinePaymentChallenge;
|
|
|
4203
4278
|
exports.parseMachinePaymentChallengeResponse = parseMachinePaymentChallengeResponse;
|
|
4204
4279
|
exports.parsePaymentRequired = parsePaymentRequired;
|
|
4205
4280
|
exports.parsePaymentRequiredResponse = parsePaymentRequiredResponse;
|
|
4281
|
+
exports.resolveTokenFromAddress = resolveTokenFromAddress;
|
|
4206
4282
|
exports.sameUrl = sameUrl;
|
|
4207
4283
|
exports.selectPaymentOption = selectPaymentOption;
|
|
4208
4284
|
exports.selectStandardPaymentOption = selectStandardPaymentOption;
|