@haven_ai/sdk 0.1.23-alpha.2 → 0.1.24-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/dist/index.cjs +429 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +223 -4
- package/dist/index.d.ts +223 -4
- package/dist/index.js +421 -126
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
2
|
import { exact } from 'x402/schemes';
|
|
3
|
-
import { hashTypedData } from 'viem';
|
|
3
|
+
import { recoverTypedDataAddress, hashTypedData } from 'viem';
|
|
4
4
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
5
5
|
import { ethers } from 'ethers';
|
|
6
6
|
import { createHash } from 'crypto';
|
|
@@ -342,7 +342,7 @@ function signHash(privateKey, hash) {
|
|
|
342
342
|
);
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
|
-
async function
|
|
345
|
+
async function signTypedDataVerbatim(privateKey, typedData, label) {
|
|
346
346
|
try {
|
|
347
347
|
const wallet = new ethers.Wallet(privateKey);
|
|
348
348
|
const types = { ...typedData.types };
|
|
@@ -354,10 +354,16 @@ async function signUserOpTypedDataForDelegation(privateKey, typedData) {
|
|
|
354
354
|
);
|
|
355
355
|
} catch (err) {
|
|
356
356
|
throw new HavenSigningError(
|
|
357
|
-
`Failed to sign
|
|
357
|
+
`Failed to sign ${label}: ${err instanceof Error ? err.message : String(err)}`
|
|
358
358
|
);
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
|
+
async function signUserOpTypedDataForDelegation(privateKey, typedData) {
|
|
362
|
+
return signTypedDataVerbatim(privateKey, typedData, "delegation UserOperation");
|
|
363
|
+
}
|
|
364
|
+
async function signSettlementDelegationTypedData(privateKey, typedData) {
|
|
365
|
+
return signTypedDataVerbatim(privateKey, typedData, "x402 settlement delegation");
|
|
366
|
+
}
|
|
361
367
|
function addressFromKey(privateKey) {
|
|
362
368
|
try {
|
|
363
369
|
return new ethers.Wallet(privateKey).address;
|
|
@@ -435,12 +441,128 @@ function decodeBase64Json(value, label) {
|
|
|
435
441
|
}
|
|
436
442
|
}
|
|
437
443
|
|
|
444
|
+
// src/sweep.ts
|
|
445
|
+
var SWEEP_BASE_CHAIN_ID = 8453;
|
|
446
|
+
var SWEEP_BASE_SEPOLIA_CHAIN_ID = 84532;
|
|
447
|
+
var SWEEP_BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
448
|
+
var SWEEP_BASE_SEPOLIA_USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
|
|
449
|
+
var USDC_EIP712_DOMAIN_BY_CHAIN = {
|
|
450
|
+
[SWEEP_BASE_CHAIN_ID]: {
|
|
451
|
+
name: "USD Coin",
|
|
452
|
+
version: "2",
|
|
453
|
+
chainId: SWEEP_BASE_CHAIN_ID,
|
|
454
|
+
verifyingContract: SWEEP_BASE_USDC_ADDRESS
|
|
455
|
+
},
|
|
456
|
+
[SWEEP_BASE_SEPOLIA_CHAIN_ID]: {
|
|
457
|
+
name: "USDC",
|
|
458
|
+
version: "2",
|
|
459
|
+
chainId: SWEEP_BASE_SEPOLIA_CHAIN_ID,
|
|
460
|
+
verifyingContract: SWEEP_BASE_SEPOLIA_USDC_ADDRESS
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
var USDC_ADDRESS_BY_CHAIN = {
|
|
464
|
+
[SWEEP_BASE_CHAIN_ID]: SWEEP_BASE_USDC_ADDRESS,
|
|
465
|
+
[SWEEP_BASE_SEPOLIA_CHAIN_ID]: SWEEP_BASE_SEPOLIA_USDC_ADDRESS
|
|
466
|
+
};
|
|
467
|
+
var SWEEPABLE_CHAIN_IDS = Object.keys(USDC_ADDRESS_BY_CHAIN).map(Number);
|
|
468
|
+
function isSweepableChain(chainId) {
|
|
469
|
+
return chainId in USDC_ADDRESS_BY_CHAIN;
|
|
470
|
+
}
|
|
471
|
+
var TRANSFER_WITH_AUTHORIZATION_TYPES = {
|
|
472
|
+
TransferWithAuthorization: [
|
|
473
|
+
{ name: "from", type: "address" },
|
|
474
|
+
{ name: "to", type: "address" },
|
|
475
|
+
{ name: "value", type: "uint256" },
|
|
476
|
+
{ name: "validAfter", type: "uint256" },
|
|
477
|
+
{ name: "validBefore", type: "uint256" },
|
|
478
|
+
{ name: "nonce", type: "bytes32" }
|
|
479
|
+
]
|
|
480
|
+
};
|
|
481
|
+
function sweepUsdcAddress(chainId) {
|
|
482
|
+
const address = USDC_ADDRESS_BY_CHAIN[chainId];
|
|
483
|
+
if (!address) {
|
|
484
|
+
throw new HavenSigningError(
|
|
485
|
+
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
return address;
|
|
489
|
+
}
|
|
490
|
+
function sweepUsdcDomain(chainId) {
|
|
491
|
+
const domain = USDC_EIP712_DOMAIN_BY_CHAIN[chainId];
|
|
492
|
+
if (!domain) {
|
|
493
|
+
throw new HavenSigningError(
|
|
494
|
+
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
return domain;
|
|
498
|
+
}
|
|
499
|
+
function sameAddress(a, b) {
|
|
500
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
501
|
+
}
|
|
502
|
+
function buildSweepTypedData(auth) {
|
|
503
|
+
const domain = sweepUsdcDomain(auth.chainId);
|
|
504
|
+
const expectedToken = sweepUsdcAddress(auth.chainId);
|
|
505
|
+
if (!sameAddress(auth.token, expectedToken)) {
|
|
506
|
+
throw new HavenSigningError(
|
|
507
|
+
`Sweep token ${auth.token} is not the canonical USDC contract for chain ${auth.chainId}.`
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(auth.nonce)) {
|
|
511
|
+
throw new HavenSigningError("Sweep nonce must be a 0x-prefixed 32-byte hex string.");
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
domain,
|
|
515
|
+
types: TRANSFER_WITH_AUTHORIZATION_TYPES,
|
|
516
|
+
primaryType: "TransferWithAuthorization",
|
|
517
|
+
message: {
|
|
518
|
+
from: auth.from,
|
|
519
|
+
to: auth.to,
|
|
520
|
+
value: BigInt(auth.value),
|
|
521
|
+
validAfter: BigInt(auth.validAfter),
|
|
522
|
+
validBefore: BigInt(auth.validBefore),
|
|
523
|
+
nonce: auth.nonce
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
function buildSweepAuthorizationMessage(auth) {
|
|
528
|
+
return `Haven sweep authorization v1
|
|
529
|
+
${stableStringify({
|
|
530
|
+
version: 1,
|
|
531
|
+
kind: "haven.sweep.authorization",
|
|
532
|
+
from: auth.from.toLowerCase(),
|
|
533
|
+
to: auth.to.toLowerCase(),
|
|
534
|
+
value: auth.value,
|
|
535
|
+
validAfter: auth.validAfter,
|
|
536
|
+
validBefore: auth.validBefore,
|
|
537
|
+
nonce: auth.nonce.toLowerCase(),
|
|
538
|
+
token: auth.token.toLowerCase(),
|
|
539
|
+
chainId: auth.chainId
|
|
540
|
+
})}`;
|
|
541
|
+
}
|
|
542
|
+
function stableStringify(value) {
|
|
543
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
544
|
+
if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
545
|
+
const object = value;
|
|
546
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
547
|
+
}
|
|
548
|
+
|
|
438
549
|
// src/x402.ts
|
|
439
550
|
var BASE_USDC_ADDRESS = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
440
551
|
var BASE_SEPOLIA_USDC_ADDRESS = "0x036cbd53842c5426634e7929541ec2318f3dcf7e";
|
|
441
552
|
var STANDARD_X402_USDC_ADDRESSES = /* @__PURE__ */ new Set([BASE_USDC_ADDRESS, BASE_SEPOLIA_USDC_ADDRESS]);
|
|
442
553
|
var X402_IDEMPOTENCY_BUCKET_MS = 3e5;
|
|
443
554
|
var DECIMAL_ATOMIC_AMOUNT_RE = /^[0-9]+$/;
|
|
555
|
+
var X402_PAYMENT_HEADER_MAX_LENGTH = 65536;
|
|
556
|
+
var BASE64_RE = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
557
|
+
var ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
558
|
+
var SIGNATURE_RE = /^0x[0-9a-fA-F]{130}$/;
|
|
559
|
+
var NONCE_RE = /^0x[0-9a-fA-F]{64}$/;
|
|
560
|
+
var X402PaymentHeaderValidationError = class extends Error {
|
|
561
|
+
constructor() {
|
|
562
|
+
super("Invalid X-PAYMENT header.");
|
|
563
|
+
this.name = "X402PaymentHeaderValidationError";
|
|
564
|
+
}
|
|
565
|
+
};
|
|
444
566
|
function isPositiveDecimalAtomicAmount(value) {
|
|
445
567
|
return DECIMAL_ATOMIC_AMOUNT_RE.test(value) && BigInt(value) > 0n;
|
|
446
568
|
}
|
|
@@ -483,7 +605,7 @@ function normalizePaymentRequired(value) {
|
|
|
483
605
|
if (!candidate || typeof candidate !== "object" || typeof candidate.x402Version !== "number" || !Array.isArray(candidate.accepts)) {
|
|
484
606
|
return null;
|
|
485
607
|
}
|
|
486
|
-
const accepts = candidate.accepts.map((option) => normalizePaymentOption(option)).filter((option) => !!option);
|
|
608
|
+
const accepts = candidate.accepts.map((option) => normalizePaymentOption(option)).filter((option) => !!option && typeof option === "object");
|
|
487
609
|
if (accepts.length === 0) return null;
|
|
488
610
|
const first = accepts[0];
|
|
489
611
|
const resourceUrl = candidate.resource?.url ?? first.resource;
|
|
@@ -588,13 +710,52 @@ function selectPaymentOption(accepts) {
|
|
|
588
710
|
}
|
|
589
711
|
return null;
|
|
590
712
|
}
|
|
713
|
+
var ERC7710_ASSET_TRANSFER_METHOD = "erc7710";
|
|
714
|
+
function x402AssetTransferMethod(option) {
|
|
715
|
+
const raw = option.extra?.assetTransferMethod;
|
|
716
|
+
return typeof raw === "string" ? raw : null;
|
|
717
|
+
}
|
|
718
|
+
function isErc7710Option(option) {
|
|
719
|
+
return x402AssetTransferMethod(option) === ERC7710_ASSET_TRANSFER_METHOD;
|
|
720
|
+
}
|
|
721
|
+
function x402FacilitatorAddresses(option) {
|
|
722
|
+
const raw = option.extra?.facilitatorAddresses;
|
|
723
|
+
if (!Array.isArray(raw)) return null;
|
|
724
|
+
const addresses = raw.filter((a) => typeof a === "string" && ADDRESS_RE.test(a));
|
|
725
|
+
return addresses.length > 0 ? addresses : null;
|
|
726
|
+
}
|
|
727
|
+
function isPayableStandardOption(opt) {
|
|
728
|
+
return opt.scheme === "exact" && opt.network in STANDARD_X402_NETWORKS && STANDARD_X402_USDC_ADDRESSES.has(opt.asset.toLowerCase()) && isPositiveDecimalAtomicAmount(optionAuthorizationAmount(opt));
|
|
729
|
+
}
|
|
591
730
|
function selectStandardPaymentOption(accepts) {
|
|
592
731
|
if (!accepts || accepts.length === 0) return null;
|
|
593
732
|
for (const opt of accepts) {
|
|
594
|
-
if (opt
|
|
595
|
-
|
|
733
|
+
if (opt === null || typeof opt !== "object") continue;
|
|
734
|
+
if (!isErc7710Option(opt) && isPayableStandardOption(opt)) return opt;
|
|
735
|
+
}
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
function selectErc7710PaymentOption(accepts) {
|
|
739
|
+
if (!accepts || accepts.length === 0) return null;
|
|
740
|
+
for (const opt of accepts) {
|
|
741
|
+
if (opt === null || typeof opt !== "object") continue;
|
|
742
|
+
if (isErc7710Option(opt) && isPayableStandardOption(opt)) return opt;
|
|
743
|
+
}
|
|
744
|
+
return null;
|
|
745
|
+
}
|
|
746
|
+
function selectX402SettlementScheme(accepts, opts) {
|
|
747
|
+
if (opts.delegationRail) {
|
|
748
|
+
const preferred = selectErc7710PaymentOption(accepts);
|
|
749
|
+
if (preferred) {
|
|
750
|
+
return {
|
|
751
|
+
scheme: "erc7710",
|
|
752
|
+
option: preferred,
|
|
753
|
+
facilitatorAddresses: x402FacilitatorAddresses(preferred)
|
|
754
|
+
};
|
|
596
755
|
}
|
|
597
756
|
}
|
|
757
|
+
const fallback = selectStandardPaymentOption(accepts);
|
|
758
|
+
if (fallback) return { scheme: "eip3009", option: fallback, facilitatorAddresses: null };
|
|
598
759
|
return null;
|
|
599
760
|
}
|
|
600
761
|
function x402AuthorizationAmount(option) {
|
|
@@ -624,7 +785,7 @@ function buildX402ExpectedMessage(context) {
|
|
|
624
785
|
payload.typedDataHash = context.typedDataHash.toLowerCase();
|
|
625
786
|
}
|
|
626
787
|
return `Haven x402 expected context v${version}
|
|
627
|
-
${
|
|
788
|
+
${stableStringify2(payload)}`;
|
|
628
789
|
}
|
|
629
790
|
function toStandardPaymentRequirements(paymentRequired, option) {
|
|
630
791
|
const network = STANDARD_X402_NETWORKS[option.network];
|
|
@@ -655,6 +816,89 @@ function toStandardPaymentRequirements(paymentRequired, option) {
|
|
|
655
816
|
extra: option.extra
|
|
656
817
|
};
|
|
657
818
|
}
|
|
819
|
+
async function validateStandardX402PaymentHeader(paymentHeader, context) {
|
|
820
|
+
try {
|
|
821
|
+
if (typeof paymentHeader !== "string" || paymentHeader.length === 0 || paymentHeader.length > X402_PAYMENT_HEADER_MAX_LENGTH || paymentHeader.length % 4 !== 0 || !BASE64_RE.test(paymentHeader)) {
|
|
822
|
+
throw new Error("wire");
|
|
823
|
+
}
|
|
824
|
+
const decoded = decodeBase64Json(paymentHeader);
|
|
825
|
+
if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) throw new Error("shape");
|
|
826
|
+
const version = decoded.x402Version;
|
|
827
|
+
const payload = decoded.payload;
|
|
828
|
+
if (version !== 1 && version !== 2 || !payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
829
|
+
throw new Error("shape");
|
|
830
|
+
}
|
|
831
|
+
if (version === 1) {
|
|
832
|
+
if (!hasOnlyKeys(decoded, ["x402Version", "scheme", "network", "payload"])) throw new Error("shape");
|
|
833
|
+
if (decoded.scheme !== "exact" || decoded.network !== standardX402WireNetwork(context.network)) {
|
|
834
|
+
throw new Error("context");
|
|
835
|
+
}
|
|
836
|
+
} else {
|
|
837
|
+
if (!hasOnlyKeys(decoded, ["x402Version", "accepted", "payload"])) throw new Error("shape");
|
|
838
|
+
const accepted = selectStandardPaymentOption([decoded.accepted]);
|
|
839
|
+
if (!accepted || !matchesHeaderContext(accepted, context)) throw new Error("context");
|
|
840
|
+
}
|
|
841
|
+
const record = payload;
|
|
842
|
+
if (!hasOnlyKeys(record, ["signature", "authorization"])) throw new Error("shape");
|
|
843
|
+
if (typeof record.signature !== "string" || !SIGNATURE_RE.test(record.signature)) throw new Error("shape");
|
|
844
|
+
const authorization = record.authorization;
|
|
845
|
+
if (!authorization || typeof authorization !== "object" || Array.isArray(authorization)) throw new Error("shape");
|
|
846
|
+
const auth = authorization;
|
|
847
|
+
if (!hasOnlyKeys(auth, ["from", "to", "value", "validAfter", "validBefore", "nonce"])) throw new Error("shape");
|
|
848
|
+
if (typeof auth.from !== "string" || !ADDRESS_RE.test(auth.from) || typeof auth.to !== "string" || !ADDRESS_RE.test(auth.to) || typeof auth.value !== "string" || !isPositiveDecimalAtomicAmount(auth.value) || typeof auth.validAfter !== "string" || !DECIMAL_ATOMIC_AMOUNT_RE.test(auth.validAfter) || typeof auth.validBefore !== "string" || !DECIMAL_ATOMIC_AMOUNT_RE.test(auth.validBefore) || typeof auth.nonce !== "string" || !NONCE_RE.test(auth.nonce)) {
|
|
849
|
+
throw new Error("shape");
|
|
850
|
+
}
|
|
851
|
+
if (!sameAddress2(auth.from, context.payer) || !sameAddress2(auth.to, context.merchantTo) || auth.value !== context.amountAtomic) {
|
|
852
|
+
throw new Error("context");
|
|
853
|
+
}
|
|
854
|
+
const validAfter = BigInt(auth.validAfter);
|
|
855
|
+
const validBefore = BigInt(auth.validBefore);
|
|
856
|
+
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
857
|
+
if (validBefore <= now || validAfter > validBefore) throw new Error("expired");
|
|
858
|
+
const typedData = buildSweepTypedData({
|
|
859
|
+
from: auth.from,
|
|
860
|
+
to: auth.to,
|
|
861
|
+
value: auth.value,
|
|
862
|
+
validAfter: auth.validAfter,
|
|
863
|
+
validBefore: auth.validBefore,
|
|
864
|
+
nonce: auth.nonce,
|
|
865
|
+
token: context.asset,
|
|
866
|
+
chainId: context.chainId
|
|
867
|
+
});
|
|
868
|
+
const recovered = await recoverTypedDataAddress({
|
|
869
|
+
...typedData,
|
|
870
|
+
// `buildSweepTypedData` keeps the public domain framework-neutral;
|
|
871
|
+
// viem brands contract addresses at this crypto call boundary only.
|
|
872
|
+
domain: {
|
|
873
|
+
...typedData.domain,
|
|
874
|
+
verifyingContract: typedData.domain.verifyingContract
|
|
875
|
+
},
|
|
876
|
+
message: {
|
|
877
|
+
...typedData.message,
|
|
878
|
+
from: typedData.message.from,
|
|
879
|
+
to: typedData.message.to,
|
|
880
|
+
nonce: typedData.message.nonce
|
|
881
|
+
},
|
|
882
|
+
signature: record.signature
|
|
883
|
+
});
|
|
884
|
+
if (!sameAddress2(recovered, context.payer)) throw new Error("recovery");
|
|
885
|
+
} catch {
|
|
886
|
+
throw new X402PaymentHeaderValidationError();
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
function hasOnlyKeys(value, allowed) {
|
|
890
|
+
return Object.keys(value).every((key) => allowed.includes(key)) && allowed.every((key) => key in value);
|
|
891
|
+
}
|
|
892
|
+
function sameAddress2(left, right) {
|
|
893
|
+
return left.toLowerCase() === right.toLowerCase();
|
|
894
|
+
}
|
|
895
|
+
function standardX402WireNetwork(network) {
|
|
896
|
+
return STANDARD_X402_NETWORKS[network] ?? null;
|
|
897
|
+
}
|
|
898
|
+
function matchesHeaderContext(option, context) {
|
|
899
|
+
if (option.scheme !== "exact" || !sameAddress2(option.payTo, context.merchantTo) || !sameAddress2(option.asset, context.asset) || option.network !== context.network || x402AuthorizationAmount(option) !== context.amountAtomic) return false;
|
|
900
|
+
return option.resource === void 0 || option.resource === context.resourceUrl;
|
|
901
|
+
}
|
|
658
902
|
function buildX402IdempotencyKey(paymentRequired, option, now = Date.now()) {
|
|
659
903
|
const bucket = Math.floor(now / X402_IDEMPOTENCY_BUCKET_MS);
|
|
660
904
|
const material = [
|
|
@@ -691,15 +935,15 @@ function resolveTokenFromAddress(address, network) {
|
|
|
691
935
|
}
|
|
692
936
|
return ALL_TOKENS[lower] ?? null;
|
|
693
937
|
}
|
|
694
|
-
function
|
|
938
|
+
function stableStringify2(value) {
|
|
695
939
|
if (value === null || typeof value !== "object") {
|
|
696
940
|
const primitive = JSON.stringify(value);
|
|
697
941
|
return primitive === void 0 ? "undefined" : primitive;
|
|
698
942
|
}
|
|
699
943
|
if (value instanceof Date) return JSON.stringify(value.toISOString());
|
|
700
|
-
if (Array.isArray(value)) return `[${value.map((item) =>
|
|
944
|
+
if (Array.isArray(value)) return `[${value.map((item) => stableStringify2(item)).join(",")}]`;
|
|
701
945
|
const object = value;
|
|
702
|
-
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${
|
|
946
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(object[key])}`).join(",")}}`;
|
|
703
947
|
}
|
|
704
948
|
function createJsonRpcProvider(url) {
|
|
705
949
|
return new ethers.JsonRpcProvider(url);
|
|
@@ -770,6 +1014,7 @@ var PAYMENT_STATE_STATUS_CODES = {
|
|
|
770
1014
|
};
|
|
771
1015
|
function chainIdFromNetwork(network) {
|
|
772
1016
|
if (network === "base") return 8453;
|
|
1017
|
+
if (network === "base-sepolia") return 84532;
|
|
773
1018
|
if (!network?.startsWith("eip155:")) return void 0;
|
|
774
1019
|
const chainId = Number(network.slice("eip155:".length));
|
|
775
1020
|
return Number.isFinite(chainId) ? chainId : void 0;
|
|
@@ -818,7 +1063,7 @@ function messageForState(label, status, paymentId, nextAction) {
|
|
|
818
1063
|
}
|
|
819
1064
|
return `${label} is ${status}; next_action=${nextAction} (payment_id: ${paymentId}).`;
|
|
820
1065
|
}
|
|
821
|
-
function
|
|
1066
|
+
function sameAddress3(a, b) {
|
|
822
1067
|
return Boolean(a && b && a.toLowerCase() === b.toLowerCase());
|
|
823
1068
|
}
|
|
824
1069
|
function decimalFromUsdcAtomic(value) {
|
|
@@ -1155,6 +1400,14 @@ var HavenClient = class {
|
|
|
1155
1400
|
}
|
|
1156
1401
|
return signUserOpTypedDataForDelegation(this.delegateKey, signData.typed_data);
|
|
1157
1402
|
}
|
|
1403
|
+
if (scheme === "eip712_delegation") {
|
|
1404
|
+
if (!signData.typed_data) {
|
|
1405
|
+
throw new HavenSigningError(
|
|
1406
|
+
"sign_data.signature_scheme is eip712_delegation but typed_data is missing \u2014 refusing to sign the bare hash (the settlement would be rejected on redemption)."
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
return signSettlementDelegationTypedData(this.delegateKey, signData.typed_data);
|
|
1410
|
+
}
|
|
1158
1411
|
if (scheme === void 0) {
|
|
1159
1412
|
return signHash(this.delegateKey, signData.hash);
|
|
1160
1413
|
}
|
|
@@ -1725,6 +1978,140 @@ var HavenClient = class {
|
|
|
1725
1978
|
this.cacheX402Receipt(idempotencyKey, paymentHeader, receipt);
|
|
1726
1979
|
return receipt;
|
|
1727
1980
|
}
|
|
1981
|
+
/**
|
|
1982
|
+
* Pay a merchant through **erc7710 direct settlement** (#1454, epic #1450).
|
|
1983
|
+
*
|
|
1984
|
+
* The whole point of this path is what it does NOT do. There is no funding
|
|
1985
|
+
* leg: the merchant redeems a delegation chain and pulls from the treasury
|
|
1986
|
+
* directly, so the delegate EOA never holds the money, no sweep can strand
|
|
1987
|
+
* it, and the #713 reconciliation class does not apply. It is also why this
|
|
1988
|
+
* method is SMALLER than the 3009 path — the backend assembles the merchant
|
|
1989
|
+
* `X-PAYMENT` header in `assembleSettlementPayload`, so the SDK builds no
|
|
1990
|
+
* header locally.
|
|
1991
|
+
*
|
|
1992
|
+
* authorize (payTo = the MERCHANT) → sign the child → settle → header
|
|
1993
|
+
*
|
|
1994
|
+
* The caller then retries the merchant with that header. **Nothing has
|
|
1995
|
+
* settled when this returns** — that is why it does not return an
|
|
1996
|
+
* `X402Receipt`.
|
|
1997
|
+
*
|
|
1998
|
+
* Requires a delegation-rail account. The backend enforces that
|
|
1999
|
+
* (`validateGenericSchemeRail`), and so does this method, before building a
|
|
2000
|
+
* request the backend would only reject: an error a client can explain is
|
|
2001
|
+
* worth more than a 400 it has to decode.
|
|
2002
|
+
*
|
|
2003
|
+
* **MCP callers must pass `options.resourceUrl`.** An in-band MCP 402
|
|
2004
|
+
* challenge frequently carries no `resource` object at all, so
|
|
2005
|
+
* `paymentRequired.resource?.url` is undefined and the backend answers
|
|
2006
|
+
* "Valid url is required". The QA scenario this path was ported from falls
|
|
2007
|
+
* back to the request URL for exactly that reason — the SDK cannot, because
|
|
2008
|
+
* it never saw the request. Pass it.
|
|
2009
|
+
*/
|
|
2010
|
+
async settleX402Erc7710(paymentRequired, options = {}) {
|
|
2011
|
+
if (!this.delegateKey) {
|
|
2012
|
+
throw new HavenSigningError(
|
|
2013
|
+
"delegateKey is required for x402 payments. Pass it in the HavenClient config."
|
|
2014
|
+
);
|
|
2015
|
+
}
|
|
2016
|
+
const prepared = await this.prepareX402Erc7710(paymentRequired, options);
|
|
2017
|
+
const signature = await this.signForData(prepared.signData);
|
|
2018
|
+
const paymentHeader = await this.submitX402Erc7710(prepared.paymentId, signature);
|
|
2019
|
+
return { ...prepared.settlement, paymentHeader };
|
|
2020
|
+
}
|
|
2021
|
+
/**
|
|
2022
|
+
* The AUTHORIZE half of erc7710 settlement (#1456): select the scheme, build
|
|
2023
|
+
* the request, and return the child to be signed — without signing it.
|
|
2024
|
+
*
|
|
2025
|
+
* Split out because the hosted topology cannot use `settleX402Erc7710()`:
|
|
2026
|
+
* that method signs in-process with `delegateKey`, and hosted Haven does not
|
|
2027
|
+
* have one and must not. The hosted MCP server drives these two halves with
|
|
2028
|
+
* the LOCAL signer in between, so the key stays where it belongs and the
|
|
2029
|
+
* request shaping stays in one place rather than being reimplemented.
|
|
2030
|
+
*/
|
|
2031
|
+
async prepareX402Erc7710(paymentRequired, options = {}) {
|
|
2032
|
+
const delegationRail = options.delegationRail ?? (await this.getAgent()).executionRail === "delegation";
|
|
2033
|
+
if (!delegationRail) {
|
|
2034
|
+
throw new HavenApiError(
|
|
2035
|
+
"erc7710 settlement requires a delegation-rail account; this one is not on it. Use authorizeX402() for the standard EIP-3009 path.",
|
|
2036
|
+
400
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
2039
|
+
const selection = selectX402SettlementScheme(paymentRequired.accepts, { delegationRail });
|
|
2040
|
+
if (!selection || selection.scheme !== "erc7710") {
|
|
2041
|
+
throw new HavenApiError(
|
|
2042
|
+
"This merchant does not advertise an erc7710 settlement option (no accepts[] entry carries extra.assetTransferMethod: 'erc7710'). Use authorizeX402() for the standard EIP-3009 path.",
|
|
2043
|
+
400
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
const option = selection.option;
|
|
2047
|
+
const merchantPayTo = option.payTo;
|
|
2048
|
+
const amountAtomic = x402AuthorizationAmount(option);
|
|
2049
|
+
const raw = await this.post("/x402", {
|
|
2050
|
+
url: options.resourceUrl ?? paymentRequired.resource?.url,
|
|
2051
|
+
// payTo = the MERCHANT is what selects direct settlement server-side.
|
|
2052
|
+
// The explicit settlementScheme must AGREE with that shape (#1360) —
|
|
2053
|
+
// disagreement is a 400 by design, so that a stale delegate address
|
|
2054
|
+
// becomes a loud mismatch instead of a silent reroute to the 3009 leg.
|
|
2055
|
+
payTo: merchantPayTo,
|
|
2056
|
+
settlementScheme: "erc7710",
|
|
2057
|
+
amount: amountAtomic,
|
|
2058
|
+
asset: option.asset,
|
|
2059
|
+
network: option.network,
|
|
2060
|
+
// The v2 header echoes the accepted entry field-for-field, so the quoted
|
|
2061
|
+
// timeout must round-trip or the merchant rejects the echo (#1064).
|
|
2062
|
+
maxTimeoutSeconds: option.maxTimeoutSeconds,
|
|
2063
|
+
// #1058: forward the advertised facilitators verbatim — the child becomes
|
|
2064
|
+
// redeemable ONLY by them. `null` here means the merchant advertised none
|
|
2065
|
+
// (or an empty array, which the backend 400s on), so the field is OMITTED
|
|
2066
|
+
// rather than sent empty. See x402FacilitatorAddresses.
|
|
2067
|
+
...selection.facilitatorAddresses ? { facilitatorAddresses: selection.facilitatorAddresses } : {}
|
|
2068
|
+
});
|
|
2069
|
+
if (!raw.payment_id) {
|
|
2070
|
+
throw new HavenApiError("No payment_id returned from x402/authorize", 500, raw);
|
|
2071
|
+
}
|
|
2072
|
+
const signData = raw.sign_data;
|
|
2073
|
+
if (signData?.signature_scheme !== "eip712_delegation" || !signData.typed_data) {
|
|
2074
|
+
throw new HavenApiError(
|
|
2075
|
+
`x402/authorize did not return an erc7710 settlement child (signature_scheme was ${JSON.stringify(signData?.signature_scheme)}). Refusing to sign a payload this path did not ask for.`,
|
|
2076
|
+
500,
|
|
2077
|
+
raw
|
|
2078
|
+
);
|
|
2079
|
+
}
|
|
2080
|
+
return {
|
|
2081
|
+
paymentId: raw.payment_id,
|
|
2082
|
+
signData,
|
|
2083
|
+
settlement: {
|
|
2084
|
+
paymentId: raw.payment_id,
|
|
2085
|
+
merchantPayTo,
|
|
2086
|
+
amountAtomic,
|
|
2087
|
+
asset: option.asset,
|
|
2088
|
+
network: option.network,
|
|
2089
|
+
facilitatorAddresses: selection.facilitatorAddresses
|
|
2090
|
+
}
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
/**
|
|
2094
|
+
* The SETTLE half (#1456): exchange the signed child for the merchant header.
|
|
2095
|
+
*
|
|
2096
|
+
* The SDK builds no header on this path — the backend assembles the MetaMask
|
|
2097
|
+
* erc7710 payload in `assembleSettlementPayload`. Whoever produced the
|
|
2098
|
+
* signature (an in-process delegate key, or the local edge signer over the
|
|
2099
|
+
* hosted boundary) is irrelevant here.
|
|
2100
|
+
*/
|
|
2101
|
+
async submitX402Erc7710(paymentId, signature) {
|
|
2102
|
+
const settled = await this.post(
|
|
2103
|
+
`/x402/${paymentId}/settle`,
|
|
2104
|
+
{ signature }
|
|
2105
|
+
);
|
|
2106
|
+
if (!settled.payment_header) {
|
|
2107
|
+
throw new HavenApiError(
|
|
2108
|
+
"x402 settle returned no payment_header \u2014 the merchant cannot be retried.",
|
|
2109
|
+
500,
|
|
2110
|
+
settled
|
|
2111
|
+
);
|
|
2112
|
+
}
|
|
2113
|
+
return settled.payment_header;
|
|
2114
|
+
}
|
|
1728
2115
|
async resumeAuthorizedX402(input) {
|
|
1729
2116
|
if (!this.delegateKey) {
|
|
1730
2117
|
throw new HavenSigningError(
|
|
@@ -2255,7 +2642,7 @@ var HavenClient = class {
|
|
|
2255
2642
|
status.paymentId
|
|
2256
2643
|
);
|
|
2257
2644
|
}
|
|
2258
|
-
if (status.merchantAddress && !
|
|
2645
|
+
if (status.merchantAddress && !sameAddress3(status.merchantAddress, option.payTo)) {
|
|
2259
2646
|
throw new HavenApiError(
|
|
2260
2647
|
"x402 resume request does not match the approved merchant.",
|
|
2261
2648
|
409,
|
|
@@ -2950,6 +3337,7 @@ var HavenClient = class {
|
|
|
2950
3337
|
token: raw.token,
|
|
2951
3338
|
resourceUrl: raw.resource_url,
|
|
2952
3339
|
merchantAddress: raw.merchant_address,
|
|
3340
|
+
payerAddress: raw.payer_address ?? null,
|
|
2953
3341
|
txHash: raw.tx_hash,
|
|
2954
3342
|
expiresAt: raw.expires_at,
|
|
2955
3343
|
chainId: raw.chain_id,
|
|
@@ -3412,14 +3800,18 @@ normal, not an error.
|
|
|
3412
3800
|
|
|
3413
3801
|
1. \`mcp__haven__haven_discover_tools\` to find a payable service and its
|
|
3414
3802
|
\`catalog_id\`.
|
|
3415
|
-
2.
|
|
3803
|
+
2. If the user needs the live price before authorizing a cap, call
|
|
3804
|
+
\`mcp__haven__haven_quote_catalog_purchase\` with \`catalog_id\`. It is
|
|
3805
|
+
read-only and informational only: it never reserves a price or creates a
|
|
3806
|
+
payment. Tell the user its \`amount\` / \`amount_atomic\`, then choose a cap.
|
|
3807
|
+
3. \`mcp__haven__haven_prepare_catalog_purchase\` with \`catalog_id\` and a
|
|
3416
3808
|
spending cap. A cap is REQUIRED on this tool and is best practice on every
|
|
3417
3809
|
paid call below too \u2014 it caps what the LIVE merchant quote may charge,
|
|
3418
3810
|
checked before any funding intent is created. Write it the way the user
|
|
3419
3811
|
said it: \`max_amount_human\` is whole tokens, so "no more than 1 USDC" is
|
|
3420
3812
|
\`max_amount_human: "1"\`. (\`max_amount\` is the atomic-unit form, where
|
|
3421
3813
|
"1" means 0.000001 USDC \u2014 do not convert by hand, and never send both.)
|
|
3422
|
-
|
|
3814
|
+
4. Then FOLLOW THE RESPONSE'S GUIDANCE FIELDS: \`next_action\`, \`next_tool\`,
|
|
3423
3815
|
and \`next_arguments\` name the exact next call \u2014 act on those first; the
|
|
3424
3816
|
prose in this section is fallback and debugging detail. If the catalog
|
|
3425
3817
|
entry is missing or degraded, the response instead names
|
|
@@ -3447,7 +3839,12 @@ do not re-pay.
|
|
|
3447
3839
|
|
|
3448
3840
|
Step-by-step alternative (also key-safe; for an older signer or backend, or
|
|
3449
3841
|
when you already have a merchant URL and tool name instead of a
|
|
3450
|
-
\`catalog_id\`):
|
|
3842
|
+
\`catalog_id\`): if the user needs the live price before choosing a cap, first
|
|
3843
|
+
call \`mcp__haven__haven_quote_mcp_tool\` with that merchant URL, tool name,
|
|
3844
|
+
and arguments. It is informational only; then call
|
|
3845
|
+
\`mcp__haven__haven_pay_mcp_tool\` with the same inputs and the explicit cap.
|
|
3846
|
+
The paid call always obtains a fresh quote before it creates any intent. Then
|
|
3847
|
+
continue \`mcp__haven__haven_pay_mcp_tool\` \u2192
|
|
3451
3848
|
\`mcp__haven-signer__haven_sign\` \u2192 \`mcp__haven__haven_submit\` \u2192
|
|
3452
3849
|
\`mcp__haven-signer__haven_x402_sign_header\` \u2192
|
|
3453
3850
|
\`mcp__haven__haven_complete_mcp_tool\`. Pass \`payment_required\`,
|
|
@@ -3469,11 +3866,13 @@ when the result says \`retry_original_x402_request\`.
|
|
|
3469
3866
|
\`arguments\` field (for example
|
|
3470
3867
|
\`tool_arguments: { "tier": "50gb" }\` -> \`arguments: { "tier": "50gb" }\`).
|
|
3471
3868
|
|
|
3472
|
-
**Prices:** show the user the live price from the pay-tool
|
|
3473
|
-
catalog price. \`haven_discover_tools\` prices are indicative
|
|
3474
|
-
(\`price_is_indicative\`) and can be stale.
|
|
3475
|
-
|
|
3476
|
-
|
|
3869
|
+
**Prices:** show the user the live price from a read-only quote or the pay-tool
|
|
3870
|
+
result, never a catalog price. \`haven_discover_tools\` prices are indicative
|
|
3871
|
+
(\`price_is_indicative\`) and can be stale. A read-only quote is informational
|
|
3872
|
+
only and does not reserve a price; the later paid call re-quotes and enforces
|
|
3873
|
+
the cap. The pay-tool result's \`amount\` / \`amount_atomic\` is the amount
|
|
3874
|
+
Haven authorizes for that call \u2014 a ceiling the merchant settles at or below \u2014
|
|
3875
|
+
so present it as the most the user will pay.
|
|
3477
3876
|
|
|
3478
3877
|
**Status:** \`mcp__haven__haven_get_payment_status\` with a \`payment_id\` to
|
|
3479
3878
|
check on queued or in-flight payments. Do not poll in a tight loop.
|
|
@@ -3540,6 +3939,7 @@ the agent in the Haven dashboard under Agents. New requests stop immediately
|
|
|
3540
3939
|
for that credential.
|
|
3541
3940
|
`;
|
|
3542
3941
|
var SKILL_FOLDER_NAME = "haven-pay";
|
|
3942
|
+
var HAVEN_SKILL_BODY_MD = HAVEN_SKILL_MD.replace(/^---\n[\s\S]*?\n---\n+/, "");
|
|
3543
3943
|
|
|
3544
3944
|
// src/node-version.ts
|
|
3545
3945
|
var HAVEN_MINIMUM_NODE_VERSION = "22.0.0";
|
|
@@ -3580,111 +3980,6 @@ function major(version) {
|
|
|
3580
3980
|
return String(parseNodeVersion(version)[0]);
|
|
3581
3981
|
}
|
|
3582
3982
|
|
|
3583
|
-
// src/sweep.ts
|
|
3584
|
-
var SWEEP_BASE_CHAIN_ID = 8453;
|
|
3585
|
-
var SWEEP_BASE_SEPOLIA_CHAIN_ID = 84532;
|
|
3586
|
-
var SWEEP_BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
3587
|
-
var SWEEP_BASE_SEPOLIA_USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
|
|
3588
|
-
var USDC_EIP712_DOMAIN_BY_CHAIN = {
|
|
3589
|
-
[SWEEP_BASE_CHAIN_ID]: {
|
|
3590
|
-
name: "USD Coin",
|
|
3591
|
-
version: "2",
|
|
3592
|
-
chainId: SWEEP_BASE_CHAIN_ID,
|
|
3593
|
-
verifyingContract: SWEEP_BASE_USDC_ADDRESS
|
|
3594
|
-
},
|
|
3595
|
-
[SWEEP_BASE_SEPOLIA_CHAIN_ID]: {
|
|
3596
|
-
name: "USDC",
|
|
3597
|
-
version: "2",
|
|
3598
|
-
chainId: SWEEP_BASE_SEPOLIA_CHAIN_ID,
|
|
3599
|
-
verifyingContract: SWEEP_BASE_SEPOLIA_USDC_ADDRESS
|
|
3600
|
-
}
|
|
3601
|
-
};
|
|
3602
|
-
var USDC_ADDRESS_BY_CHAIN = {
|
|
3603
|
-
[SWEEP_BASE_CHAIN_ID]: SWEEP_BASE_USDC_ADDRESS,
|
|
3604
|
-
[SWEEP_BASE_SEPOLIA_CHAIN_ID]: SWEEP_BASE_SEPOLIA_USDC_ADDRESS
|
|
3605
|
-
};
|
|
3606
|
-
var SWEEPABLE_CHAIN_IDS = Object.keys(USDC_ADDRESS_BY_CHAIN).map(Number);
|
|
3607
|
-
function isSweepableChain(chainId) {
|
|
3608
|
-
return chainId in USDC_ADDRESS_BY_CHAIN;
|
|
3609
|
-
}
|
|
3610
|
-
var TRANSFER_WITH_AUTHORIZATION_TYPES = {
|
|
3611
|
-
TransferWithAuthorization: [
|
|
3612
|
-
{ name: "from", type: "address" },
|
|
3613
|
-
{ name: "to", type: "address" },
|
|
3614
|
-
{ name: "value", type: "uint256" },
|
|
3615
|
-
{ name: "validAfter", type: "uint256" },
|
|
3616
|
-
{ name: "validBefore", type: "uint256" },
|
|
3617
|
-
{ name: "nonce", type: "bytes32" }
|
|
3618
|
-
]
|
|
3619
|
-
};
|
|
3620
|
-
function sweepUsdcAddress(chainId) {
|
|
3621
|
-
const address = USDC_ADDRESS_BY_CHAIN[chainId];
|
|
3622
|
-
if (!address) {
|
|
3623
|
-
throw new HavenSigningError(
|
|
3624
|
-
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
3625
|
-
);
|
|
3626
|
-
}
|
|
3627
|
-
return address;
|
|
3628
|
-
}
|
|
3629
|
-
function sweepUsdcDomain(chainId) {
|
|
3630
|
-
const domain = USDC_EIP712_DOMAIN_BY_CHAIN[chainId];
|
|
3631
|
-
if (!domain) {
|
|
3632
|
-
throw new HavenSigningError(
|
|
3633
|
-
`Sweep is not supported on chain ${chainId}. Supported: ${SWEEPABLE_CHAIN_IDS.join(", ")}.`
|
|
3634
|
-
);
|
|
3635
|
-
}
|
|
3636
|
-
return domain;
|
|
3637
|
-
}
|
|
3638
|
-
function sameAddress2(a, b) {
|
|
3639
|
-
return a.toLowerCase() === b.toLowerCase();
|
|
3640
|
-
}
|
|
3641
|
-
function buildSweepTypedData(auth) {
|
|
3642
|
-
const domain = sweepUsdcDomain(auth.chainId);
|
|
3643
|
-
const expectedToken = sweepUsdcAddress(auth.chainId);
|
|
3644
|
-
if (!sameAddress2(auth.token, expectedToken)) {
|
|
3645
|
-
throw new HavenSigningError(
|
|
3646
|
-
`Sweep token ${auth.token} is not the canonical USDC contract for chain ${auth.chainId}.`
|
|
3647
|
-
);
|
|
3648
|
-
}
|
|
3649
|
-
if (!/^0x[0-9a-fA-F]{64}$/.test(auth.nonce)) {
|
|
3650
|
-
throw new HavenSigningError("Sweep nonce must be a 0x-prefixed 32-byte hex string.");
|
|
3651
|
-
}
|
|
3652
|
-
return {
|
|
3653
|
-
domain,
|
|
3654
|
-
types: TRANSFER_WITH_AUTHORIZATION_TYPES,
|
|
3655
|
-
primaryType: "TransferWithAuthorization",
|
|
3656
|
-
message: {
|
|
3657
|
-
from: auth.from,
|
|
3658
|
-
to: auth.to,
|
|
3659
|
-
value: BigInt(auth.value),
|
|
3660
|
-
validAfter: BigInt(auth.validAfter),
|
|
3661
|
-
validBefore: BigInt(auth.validBefore),
|
|
3662
|
-
nonce: auth.nonce
|
|
3663
|
-
}
|
|
3664
|
-
};
|
|
3665
|
-
}
|
|
3666
|
-
function buildSweepAuthorizationMessage(auth) {
|
|
3667
|
-
return `Haven sweep authorization v1
|
|
3668
|
-
${stableStringify2({
|
|
3669
|
-
version: 1,
|
|
3670
|
-
kind: "haven.sweep.authorization",
|
|
3671
|
-
from: auth.from.toLowerCase(),
|
|
3672
|
-
to: auth.to.toLowerCase(),
|
|
3673
|
-
value: auth.value,
|
|
3674
|
-
validAfter: auth.validAfter,
|
|
3675
|
-
validBefore: auth.validBefore,
|
|
3676
|
-
nonce: auth.nonce.toLowerCase(),
|
|
3677
|
-
token: auth.token.toLowerCase(),
|
|
3678
|
-
chainId: auth.chainId
|
|
3679
|
-
})}`;
|
|
3680
|
-
}
|
|
3681
|
-
function stableStringify2(value) {
|
|
3682
|
-
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
3683
|
-
if (Array.isArray(value)) return `[${value.map((item) => stableStringify2(item)).join(",")}]`;
|
|
3684
|
-
const object = value;
|
|
3685
|
-
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(object[key])}`).join(",")}}`;
|
|
3686
|
-
}
|
|
3687
|
-
|
|
3688
3983
|
// src/merchant-discovery.ts
|
|
3689
3984
|
var MERCHANT_DISCOVERY_PATHS = ["/.well-known/haven-demo-merchant", "/"];
|
|
3690
3985
|
var DISCOVERY_MAX_BYTES = 64 * 1024;
|
|
@@ -3729,6 +4024,6 @@ function sameUrl(a, b) {
|
|
|
3729
4024
|
}
|
|
3730
4025
|
}
|
|
3731
4026
|
|
|
3732
|
-
export { AGENT_PAYMENT_FAILURE_CODE_VALUES, AGENT_PAYMENT_NEXT_ACTION_VALUES, AGENT_PAYMENT_PHASE_VALUES, AGENT_PAYMENT_RAIL_VALUES, AgentPaymentFailureCode, AgentPaymentFailureCodeDescriptions, AgentPaymentFailureCodeSchema, AgentPaymentNextAction, AgentPaymentNextActionDescriptions, AgentPaymentNextActionSchema, AgentPaymentPhase, AgentPaymentPhaseDescriptions, AgentPaymentPhaseSchema, AgentPaymentRail, AgentPaymentRailDescriptions, AgentPaymentRailSchema, AgentPaymentWarningCode, DISCOVERY_MAX_BYTES, HAVEN_MINIMUM_NODE_VERSION, HAVEN_SKILL_MD, HavenApiError, HavenClient, HavenError, HavenPaymentStateError, HavenSigningError, HavenTimeoutError, HavenUnsupportedSignerVersionError, MERCHANT_DISCOVERY_PATHS, MerchantTimeoutError, RECEIPT_VERSION, SIGNER_UPDATE_FALLBACK, SKILL_FOLDER_NAME, SWEEP_BASE_CHAIN_ID, SWEEP_BASE_SEPOLIA_CHAIN_ID, SWEEP_BASE_SEPOLIA_USDC_ADDRESS, SWEEP_BASE_USDC_ADDRESS, SignerRefusalCode, TRANSFER_WITH_AUTHORIZATION_TYPES, X402UnexpectedStatusError, X402_MAX_AUTHORIZATION_WINDOW_SECONDS, X402_SETTLEMENT_FORWARD_MARGIN_SECONDS, addressFromKey, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, compareNodeVersions, composeDescription, decodeBase64Json, decodeBase64Utf8, discoverMerchantMcpUrl, encodeBase64Json, encodeBase64Utf8, encodePaymentProof, havenTools, isSupportedNodeVersion, isSweepableChain, parsePaymentRequired, parsePaymentRequiredResponse, resolveTokenFromAddress, sameUrl, selectPaymentOption, selectStandardPaymentOption, signHash, signUserOpTypedDataForDelegation, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, toolDescriptions, unsupportedNodeVersionMessage, verifyPaymentReceipt, verifySignature, x402AuthorizationAmount };
|
|
4027
|
+
export { AGENT_PAYMENT_FAILURE_CODE_VALUES, AGENT_PAYMENT_NEXT_ACTION_VALUES, AGENT_PAYMENT_PHASE_VALUES, AGENT_PAYMENT_RAIL_VALUES, AgentPaymentFailureCode, AgentPaymentFailureCodeDescriptions, AgentPaymentFailureCodeSchema, AgentPaymentNextAction, AgentPaymentNextActionDescriptions, AgentPaymentNextActionSchema, AgentPaymentPhase, AgentPaymentPhaseDescriptions, AgentPaymentPhaseSchema, AgentPaymentRail, AgentPaymentRailDescriptions, AgentPaymentRailSchema, AgentPaymentWarningCode, DISCOVERY_MAX_BYTES, ERC7710_ASSET_TRANSFER_METHOD, HAVEN_MINIMUM_NODE_VERSION, HAVEN_SKILL_BODY_MD, HAVEN_SKILL_MD, HavenApiError, HavenClient, HavenError, HavenPaymentStateError, HavenSigningError, HavenTimeoutError, HavenUnsupportedSignerVersionError, MERCHANT_DISCOVERY_PATHS, MerchantTimeoutError, RECEIPT_VERSION, SIGNER_UPDATE_FALLBACK, SKILL_FOLDER_NAME, SWEEP_BASE_CHAIN_ID, SWEEP_BASE_SEPOLIA_CHAIN_ID, SWEEP_BASE_SEPOLIA_USDC_ADDRESS, SWEEP_BASE_USDC_ADDRESS, SignerRefusalCode, TRANSFER_WITH_AUTHORIZATION_TYPES, X402PaymentHeaderValidationError, X402UnexpectedStatusError, X402_MAX_AUTHORIZATION_WINDOW_SECONDS, X402_SETTLEMENT_FORWARD_MARGIN_SECONDS, addressFromKey, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, compareNodeVersions, composeDescription, decodeBase64Json, decodeBase64Utf8, discoverMerchantMcpUrl, encodeBase64Json, encodeBase64Utf8, encodePaymentProof, havenTools, isErc7710Option, isSupportedNodeVersion, isSweepableChain, normalizePaymentRequired, parsePaymentRequired, parsePaymentRequiredResponse, resolveTokenFromAddress, sameUrl, selectErc7710PaymentOption, selectPaymentOption, selectStandardPaymentOption, selectX402SettlementScheme, signHash, signUserOpTypedDataForDelegation, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, toolDescriptions, unsupportedNodeVersionMessage, validateStandardX402PaymentHeader, verifyPaymentReceipt, verifySignature, x402AssetTransferMethod, x402AuthorizationAmount, x402FacilitatorAddresses };
|
|
3733
4028
|
//# sourceMappingURL=index.js.map
|
|
3734
4029
|
//# sourceMappingURL=index.js.map
|