@haven_ai/sdk 0.7.0-alpha.0 → 0.8.1-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.
@@ -1,6 +1,8 @@
1
- import { HavenSigningError, deriveDelegateAccountAddress, DELEGATION_MANAGER, assertRedeemsOwnBudgetDelegation, verifySettlementChild, REDEEM_DELEGATIONS_ABI, ROOT_AUTHORITY, CAVEAT_ENFORCERS, DELEGATION_TUPLE_COMPONENTS } from './chunk-NNIT7WAI.js';
2
- import { decodeFunctionData, encodeFunctionData, encodePacked, recoverTypedDataAddress, encodeAbiParameters, keccak256 } from 'viem';
1
+ import { HavenSigningError, deriveDelegateAccountAddress, DELEGATION_MANAGER, assertRedeemsOwnBudgetDelegation, verifySettlementChild, REDEEM_DELEGATIONS_ABI, chainIdForNetwork, ROOT_AUTHORITY, CAVEAT_ENFORCERS, DELEGATION_TUPLE_COMPONENTS } from './chunk-H4APV67M.js';
2
+ import { decodeFunctionData, encodeFunctionData, encodePacked, recoverTypedDataAddress, serializeSignature, hashTypedData, encodeAbiParameters, keccak256 } from 'viem';
3
3
  import { createHash } from 'crypto';
4
+ import { secp256k1 } from '@noble/curves/secp256k1';
5
+ import { privateKeyToAddress, publicKeyToAddress } from 'viem/accounts';
4
6
 
5
7
  var TYPED_DATA_NOT_ALLOWED = "TYPED_DATA_NOT_ALLOWED";
6
8
  var HavenTypedDataRefusedError = class extends HavenSigningError {
@@ -394,7 +396,6 @@ function normalizePaymentRequired(value) {
394
396
  };
395
397
  }
396
398
  var SUPPORTED_X402_NETWORKS = {
397
- "eip155:100": "Gnosis Chain",
398
399
  "eip155:8453": "Base",
399
400
  "base": "Base",
400
401
  "eip155:84532": "Base Sepolia",
@@ -406,11 +407,6 @@ var STANDARD_X402_NETWORKS = {
406
407
  "eip155:84532": "base-sepolia",
407
408
  "base-sepolia": "base-sepolia"
408
409
  };
409
- var GNOSIS_TOKENS = {
410
- "0x0000000000000000000000000000000000000000": { symbol: "xDAI", decimals: 18 },
411
- "0xcb444e90d8198415266c6a2724b7900fb12fc56e": { symbol: "EURe", decimals: 18 },
412
- "0x2a22f9c3b484c3629090feed35f17ff8f88f76f0": { symbol: "USDC.e", decimals: 6 }
413
- };
414
410
  var BASE_TOKENS = {
415
411
  "0x0000000000000000000000000000000000000000": { symbol: "ETH", decimals: 18 },
416
412
  "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913": { symbol: "USDC", decimals: 6 }
@@ -420,12 +416,10 @@ var BASE_SEPOLIA_TOKENS = {
420
416
  "0x036cbd53842c5426634e7929541ec2318f3dcf7e": { symbol: "USDC", decimals: 6 }
421
417
  };
422
418
  var ALL_TOKENS = {
423
- ...GNOSIS_TOKENS,
424
419
  ...BASE_TOKENS,
425
420
  ...BASE_SEPOLIA_TOKENS
426
421
  };
427
422
  var NETWORK_TOKENS = {
428
- "eip155:100": GNOSIS_TOKENS,
429
423
  "eip155:8453": BASE_TOKENS,
430
424
  "base": BASE_TOKENS,
431
425
  "eip155:84532": BASE_SEPOLIA_TOKENS,
@@ -760,9 +754,7 @@ function encodePaymentProof(receipt) {
760
754
  }
761
755
  function resolveTokenFromAddress(address, network) {
762
756
  const lower = address.toLowerCase();
763
- if (network && network in NETWORK_TOKENS) {
764
- return NETWORK_TOKENS[network][lower] ?? null;
765
- }
757
+ if (network) return NETWORK_TOKENS[network]?.[lower] ?? null;
766
758
  return ALL_TOKENS[lower] ?? null;
767
759
  }
768
760
  function resolveTokenBySymbol(chainId, symbol) {
@@ -783,7 +775,7 @@ function stableStringify2(value) {
783
775
  }
784
776
 
785
777
  // src/client-identity.ts
786
- var SDK_VERSION = "0.7.0-alpha.0";
778
+ var SDK_VERSION = "0.8.1-alpha.0";
787
779
  var HAVEN_CLIENT_HEADER = "X-Haven-Client";
788
780
  function havenClientIdentity(pkg, version) {
789
781
  return `${pkg}/${version}`;
@@ -805,6 +797,177 @@ function readClientUpdate(value) {
805
797
  notes_url: typeof v.notes_url === "string" ? v.notes_url : null
806
798
  };
807
799
  }
800
+ var HALF_N = BigInt("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0");
801
+ function hexBytes(value, bytes, what) {
802
+ if (!/^0x[0-9a-fA-F]+$/.test(value) || value.length !== 2 + bytes * 2) {
803
+ throw new Error(`${what} must be a 0x-prefixed ${bytes}-byte hex string`);
804
+ }
805
+ return value.slice(2);
806
+ }
807
+ function addressFromKey(privateKey) {
808
+ try {
809
+ return privateKeyToAddress(`0x${hexBytes(privateKey, 32, "private key")}`);
810
+ } catch (err) {
811
+ throw new HavenSigningError(
812
+ `Invalid private key: ${err instanceof Error ? err.message : String(err)}`
813
+ );
814
+ }
815
+ }
816
+ function signHash(privateKey, hash) {
817
+ try {
818
+ const { r, s, recovery } = secp256k1.sign(hexBytes(hash, 32, "hash"), hexBytes(privateKey, 32, "private key"), { lowS: true });
819
+ return serializeSignature({
820
+ r: `0x${r.toString(16).padStart(64, "0")}`,
821
+ s: `0x${s.toString(16).padStart(64, "0")}`,
822
+ yParity: recovery
823
+ });
824
+ } catch (err) {
825
+ throw new HavenSigningError(
826
+ `Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`
827
+ );
828
+ }
829
+ }
830
+ function verifySignature(hash, signature, expectedAddress) {
831
+ try {
832
+ const sig = hexBytes(signature, 65, "signature");
833
+ const hashHex = hexBytes(hash, 32, "hash");
834
+ if (BigInt(`0x${sig.slice(64, 128)}`) > HALF_N) return false;
835
+ const yParityOrV = Number.parseInt(sig.slice(128), 16);
836
+ const recoveryBit = yParityOrV === 0 || yParityOrV === 27 ? 0 : yParityOrV === 1 || yParityOrV === 28 ? 1 : -1;
837
+ if (recoveryBit < 0) return false;
838
+ const publicKey = secp256k1.Signature.fromCompact(sig.slice(0, 128)).addRecoveryBit(recoveryBit).recoverPublicKey(hashHex).toHex(false);
839
+ const recovered = publicKeyToAddress(`0x${publicKey}`);
840
+ return recovered.toLowerCase() === expectedAddress.toLowerCase();
841
+ } catch {
842
+ return false;
843
+ }
844
+ }
845
+ var TAX_DECLARATION_DOMAIN = { name: "x402 Tax Declaration", version: "1" };
846
+ var TAX_DECLARATION_PRIMARY_TYPE = "TaxDeclaration";
847
+ var TAX_DECLARATION_TYPES = {
848
+ TaxDeclaration: [
849
+ { name: "version", type: "string" },
850
+ { name: "jurisdiction", type: "string" },
851
+ { name: "taxableStatus", type: "string" },
852
+ { name: "taxId", type: "string" },
853
+ { name: "validUntil", type: "uint256" },
854
+ { name: "principalId", type: "string" },
855
+ { name: "principalAttributionHash", type: "string" }
856
+ ]
857
+ };
858
+ var X_TAX_DECLARATION_HEADER = "X-Tax-Declaration";
859
+ function validateContent(content) {
860
+ if (typeof content !== "object" || content === null || Array.isArray(content)) {
861
+ throw new HavenSigningError("Tax declaration content must be an object.");
862
+ }
863
+ const record = content;
864
+ for (const field of ["principalId", "principalAttributionHash"]) {
865
+ if (record[field] !== void 0) {
866
+ throw new TaxDeclarationRefusedError(
867
+ `Tax declaration content arrives with ${field} already set; that field is computed locally from the delegate key and the accepted payment option, never accepted from Haven.`
868
+ );
869
+ }
870
+ }
871
+ const allowed = /* @__PURE__ */ new Set(["version", "jurisdiction", "taxableStatus", "taxId", "validUntil"]);
872
+ for (const key of Object.keys(record)) {
873
+ if (!allowed.has(key)) {
874
+ throw new TaxDeclarationRefusedError(
875
+ `Tax declaration content carries an unknown field '${key}'; the signed shape is built locally from the \xA72.1 fields only.`
876
+ );
877
+ }
878
+ }
879
+ const strings = ["version", "jurisdiction", "taxableStatus", "taxId"];
880
+ for (const key of strings) {
881
+ if (typeof record[key] !== "string" || record[key].length === 0) {
882
+ throw new TaxDeclarationRefusedError(
883
+ `Tax declaration content field '${key}' must be a non-empty string.`
884
+ );
885
+ }
886
+ }
887
+ if (typeof record.validUntil !== "number" || !Number.isInteger(record.validUntil) || record.validUntil <= 0) {
888
+ throw new TaxDeclarationRefusedError(
889
+ "Tax declaration content field 'validUntil' must be a positive integer (milliseconds)."
890
+ );
891
+ }
892
+ return {
893
+ version: record.version,
894
+ jurisdiction: record.jurisdiction,
895
+ taxableStatus: record.taxableStatus,
896
+ taxId: record.taxId,
897
+ validUntil: record.validUntil
898
+ };
899
+ }
900
+ function jcsCanonicalBytes(value) {
901
+ const keys = Object.keys(value).sort();
902
+ const members = keys.map((key) => `${JSON.stringify(key)}:${JSON.stringify(value[key])}`);
903
+ return `{${members.join(",")}}`;
904
+ }
905
+ function principalAttributionHash(principalId) {
906
+ const canonical = jcsCanonicalBytes({ principalId });
907
+ const hex2 = createHash("sha256").update(canonical, "utf8").digest("hex");
908
+ return `sha-256:${hex2}`;
909
+ }
910
+ function taxPrincipalId(network, delegateAddress) {
911
+ if (network.startsWith("eip155:")) {
912
+ return `did:pkh:${network}:${delegateAddress}`;
913
+ }
914
+ const chainId = chainIdForNetwork(network);
915
+ if (chainId === void 0) {
916
+ throw new TaxDeclarationRefusedError(
917
+ `The accepted payment option's network '${network}' is not a CAIP-2 eip155 chain this SDK can name; refusing to build a tax principal without the settlement network.`
918
+ );
919
+ }
920
+ return `did:pkh:eip155:${chainId}:${delegateAddress}`;
921
+ }
922
+ function buildSignedTaxDeclaration(input) {
923
+ const content = validateContent(input.content);
924
+ const principalId = taxPrincipalId(input.network, addressFromKeyForTax(input.delegateKey));
925
+ const attributionHash = principalAttributionHash(principalId);
926
+ const declaration = { ...content, principalId, principalAttributionHash: attributionHash };
927
+ const message = { ...declaration, validUntil: BigInt(declaration.validUntil) };
928
+ const digest = hashTypedData({
929
+ domain: TAX_DECLARATION_DOMAIN,
930
+ types: TAX_DECLARATION_TYPES,
931
+ primaryType: TAX_DECLARATION_PRIMARY_TYPE,
932
+ message
933
+ });
934
+ const signature = signHash(input.delegateKey, digest);
935
+ return { declaration, signature };
936
+ }
937
+ function verifyTaxDeclarationSignature(declaration, signature, expectedAddress) {
938
+ const message = { ...declaration, validUntil: BigInt(declaration.validUntil) };
939
+ const digest = hashTypedData({
940
+ domain: TAX_DECLARATION_DOMAIN,
941
+ types: TAX_DECLARATION_TYPES,
942
+ primaryType: TAX_DECLARATION_PRIMARY_TYPE,
943
+ message
944
+ });
945
+ return verifySignature(digest, signature, expectedAddress);
946
+ }
947
+ function encodeTaxDeclarationHeader(result) {
948
+ const json = JSON.stringify({ ...result.declaration, signature: result.signature });
949
+ return base64Url(json);
950
+ }
951
+ function base64Url(value) {
952
+ const standard = typeof Buffer !== "undefined" ? Buffer.from(value, "utf8").toString("base64") : btoa(String.fromCharCode(...new TextEncoder().encode(value)));
953
+ return standard.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
954
+ }
955
+ function addressFromKeyForTax(delegateKey) {
956
+ try {
957
+ return addressFromKey(delegateKey);
958
+ } catch (err) {
959
+ throw new HavenSigningError(
960
+ `Invalid delegate key for tax declaration signing: ${err instanceof Error ? err.message : String(err)}`
961
+ );
962
+ }
963
+ }
964
+ var TaxDeclarationRefusedError = class extends HavenSigningError {
965
+ code = "TAX_DECLARATION_REFUSED";
966
+ constructor(message) {
967
+ super(message);
968
+ this.name = "TaxDeclarationRefusedError";
969
+ }
970
+ };
808
971
 
809
972
  // src/next-step.ts
810
973
  var NEXT_TOOL_SERVER_NAMES = {
@@ -1212,6 +1375,6 @@ function hashDelegation(delegation) {
1212
1375
  return keccak256(encoded);
1213
1376
  }
1214
1377
 
1215
- export { CAVEAT_TYPEHASH, DEFAULT_NEXT_TOOL_BY_ACTION, DELEGATION_TYPEHASH, DIRECT_PAYMENT_CHAIN_IDS, ERC7710_ASSET_TRANSFER_METHOD, EXECUTE_ABI, HAVEN_CLIENT_HEADER, HAVEN_MINIMUM_NODE_VERSION, HavenTypedDataRefusedError, MAX_TASK_BUDGET_TTL_SECONDS, NEXT_TOOL_SERVER_NAMES, NEXT_TOOL_SERVER_ROLES, SDK_CLIENT_IDENTITY, SDK_VERSION, SWEEP_BASE_CHAIN_ID, SWEEP_BASE_SEPOLIA_CHAIN_ID, SWEEP_BASE_SEPOLIA_USDC_ADDRESS, SWEEP_BASE_USDC_ADDRESS, TRANSFER_WITH_AUTHORIZATION_TYPES, TYPED_DATA_NOT_ALLOWED, X402PaymentHeaderValidationError, X402_LEGACY_PAYMENT_HEADER_NAME, X402_MAX_AUTHORIZATION_WINDOW_SECONDS, X402_PAYMENT_HEADER_NAME, X402_PAYMENT_HEADER_NAMES, X402_PAYMENT_HEADER_NAMES_SENT, X402_PAYMENT_REQUIRED_HEADER_NAME, X402_PAYMENT_RESPONSE_HEADER_NAME, X402_SETTLEMENT_FORWARD_MARGIN_SECONDS, assertBoundDirectPaymentUserOp, assertFundingLegPaysDelegate, assertOwnSettlementChild, assertOwnTaskBudgetCloseUserOp, assertOwnTaskChild, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, buildX402IdempotencyKey, compareNodeVersions, createNextStepBuilder, decodeBase64Json, decodeBase64Utf8, defaultNextToolFor, encodeBase64Json, encodeBase64Utf8, encodePaymentProof, hashDelegation, havenClientIdentity, isErc7710Option, isSupportedNodeVersion, isSweepableChain, isTaskChildTypedData, normalizePaymentRequired, parseNextTool, parsePaymentRequired, parsePaymentRequiredResponse, readClientUpdate, renderNextTool, resolveTokenBySymbol, resolveTokenFromAddress, selectErc7710PaymentOption, selectPaymentOption, selectStandardPaymentOption, selectX402SettlementScheme, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, unsupportedNodeVersionMessage, validateStandardX402PaymentHeader, x402AssetTransferMethod, x402AuthorizationAmount, x402FacilitatorAddresses, x402PaymentHeaderNamesFor, x402PaymentHeaderNamesSent, x402V2PaymentEnvelope };
1216
- //# sourceMappingURL=chunk-R3RZJJWL.js.map
1217
- //# sourceMappingURL=chunk-R3RZJJWL.js.map
1378
+ export { CAVEAT_TYPEHASH, DEFAULT_NEXT_TOOL_BY_ACTION, DELEGATION_TYPEHASH, DIRECT_PAYMENT_CHAIN_IDS, ERC7710_ASSET_TRANSFER_METHOD, EXECUTE_ABI, HAVEN_CLIENT_HEADER, HAVEN_MINIMUM_NODE_VERSION, HavenTypedDataRefusedError, MAX_TASK_BUDGET_TTL_SECONDS, NEXT_TOOL_SERVER_NAMES, NEXT_TOOL_SERVER_ROLES, SDK_CLIENT_IDENTITY, SDK_VERSION, SWEEP_BASE_CHAIN_ID, SWEEP_BASE_SEPOLIA_CHAIN_ID, SWEEP_BASE_SEPOLIA_USDC_ADDRESS, SWEEP_BASE_USDC_ADDRESS, TAX_DECLARATION_DOMAIN, TAX_DECLARATION_PRIMARY_TYPE, TAX_DECLARATION_TYPES, TRANSFER_WITH_AUTHORIZATION_TYPES, TYPED_DATA_NOT_ALLOWED, TaxDeclarationRefusedError, X402PaymentHeaderValidationError, X402_LEGACY_PAYMENT_HEADER_NAME, X402_MAX_AUTHORIZATION_WINDOW_SECONDS, X402_PAYMENT_HEADER_NAME, X402_PAYMENT_HEADER_NAMES, X402_PAYMENT_HEADER_NAMES_SENT, X402_PAYMENT_REQUIRED_HEADER_NAME, X402_PAYMENT_RESPONSE_HEADER_NAME, X402_SETTLEMENT_FORWARD_MARGIN_SECONDS, X_TAX_DECLARATION_HEADER, addressFromKey, assertBoundDirectPaymentUserOp, assertFundingLegPaysDelegate, assertOwnSettlementChild, assertOwnTaskBudgetCloseUserOp, assertOwnTaskChild, buildSignedTaxDeclaration, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, buildX402IdempotencyKey, compareNodeVersions, createNextStepBuilder, decodeBase64Json, decodeBase64Utf8, defaultNextToolFor, encodeBase64Json, encodeBase64Utf8, encodePaymentProof, encodeTaxDeclarationHeader, hashDelegation, havenClientIdentity, isErc7710Option, isSupportedNodeVersion, isSweepableChain, isTaskChildTypedData, normalizePaymentRequired, parseNextTool, parsePaymentRequired, parsePaymentRequiredResponse, principalAttributionHash, readClientUpdate, renderNextTool, resolveTokenBySymbol, resolveTokenFromAddress, selectErc7710PaymentOption, selectPaymentOption, selectStandardPaymentOption, selectX402SettlementScheme, signHash, sweepUsdcAddress, sweepUsdcDomain, taxPrincipalId, toStandardPaymentRequirements, unsupportedNodeVersionMessage, validateStandardX402PaymentHeader, verifySignature, verifyTaxDeclarationSignature, x402AssetTransferMethod, x402AuthorizationAmount, x402FacilitatorAddresses, x402PaymentHeaderNamesFor, x402PaymentHeaderNamesSent, x402V2PaymentEnvelope };
1379
+ //# sourceMappingURL=chunk-WDA3IGJP.js.map
1380
+ //# sourceMappingURL=chunk-WDA3IGJP.js.map