@haven_ai/sdk 0.0.0-dev.202609291912.efd0772 → 0.0.0-dev.202609291949.4e52d4b

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-5I6LGPWZ.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-5I6LGPWZ.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 {
@@ -783,7 +785,7 @@ function stableStringify2(value) {
783
785
  }
784
786
 
785
787
  // src/client-identity.ts
786
- var SDK_VERSION = "0.0.0-dev.202609291912.efd0772";
788
+ var SDK_VERSION = "0.0.0-dev.202609291949.4e52d4b";
787
789
  var HAVEN_CLIENT_HEADER = "X-Haven-Client";
788
790
  function havenClientIdentity(pkg, version) {
789
791
  return `${pkg}/${version}`;
@@ -805,6 +807,177 @@ function readClientUpdate(value) {
805
807
  notes_url: typeof v.notes_url === "string" ? v.notes_url : null
806
808
  };
807
809
  }
810
+ var HALF_N = BigInt("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0");
811
+ function hexBytes(value, bytes, what) {
812
+ if (!/^0x[0-9a-fA-F]+$/.test(value) || value.length !== 2 + bytes * 2) {
813
+ throw new Error(`${what} must be a 0x-prefixed ${bytes}-byte hex string`);
814
+ }
815
+ return value.slice(2);
816
+ }
817
+ function addressFromKey(privateKey) {
818
+ try {
819
+ return privateKeyToAddress(`0x${hexBytes(privateKey, 32, "private key")}`);
820
+ } catch (err) {
821
+ throw new HavenSigningError(
822
+ `Invalid private key: ${err instanceof Error ? err.message : String(err)}`
823
+ );
824
+ }
825
+ }
826
+ function signHash(privateKey, hash) {
827
+ try {
828
+ const { r, s, recovery } = secp256k1.sign(hexBytes(hash, 32, "hash"), hexBytes(privateKey, 32, "private key"), { lowS: true });
829
+ return serializeSignature({
830
+ r: `0x${r.toString(16).padStart(64, "0")}`,
831
+ s: `0x${s.toString(16).padStart(64, "0")}`,
832
+ yParity: recovery
833
+ });
834
+ } catch (err) {
835
+ throw new HavenSigningError(
836
+ `Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`
837
+ );
838
+ }
839
+ }
840
+ function verifySignature(hash, signature, expectedAddress) {
841
+ try {
842
+ const sig = hexBytes(signature, 65, "signature");
843
+ const hashHex = hexBytes(hash, 32, "hash");
844
+ if (BigInt(`0x${sig.slice(64, 128)}`) > HALF_N) return false;
845
+ const yParityOrV = Number.parseInt(sig.slice(128), 16);
846
+ const recoveryBit = yParityOrV === 0 || yParityOrV === 27 ? 0 : yParityOrV === 1 || yParityOrV === 28 ? 1 : -1;
847
+ if (recoveryBit < 0) return false;
848
+ const publicKey = secp256k1.Signature.fromCompact(sig.slice(0, 128)).addRecoveryBit(recoveryBit).recoverPublicKey(hashHex).toHex(false);
849
+ const recovered = publicKeyToAddress(`0x${publicKey}`);
850
+ return recovered.toLowerCase() === expectedAddress.toLowerCase();
851
+ } catch {
852
+ return false;
853
+ }
854
+ }
855
+ var TAX_DECLARATION_DOMAIN = { name: "x402 Tax Declaration", version: "1" };
856
+ var TAX_DECLARATION_PRIMARY_TYPE = "TaxDeclaration";
857
+ var TAX_DECLARATION_TYPES = {
858
+ TaxDeclaration: [
859
+ { name: "version", type: "string" },
860
+ { name: "jurisdiction", type: "string" },
861
+ { name: "taxableStatus", type: "string" },
862
+ { name: "taxId", type: "string" },
863
+ { name: "validUntil", type: "uint256" },
864
+ { name: "principalId", type: "string" },
865
+ { name: "principalAttributionHash", type: "string" }
866
+ ]
867
+ };
868
+ var X_TAX_DECLARATION_HEADER = "X-Tax-Declaration";
869
+ function validateContent(content) {
870
+ if (typeof content !== "object" || content === null || Array.isArray(content)) {
871
+ throw new HavenSigningError("Tax declaration content must be an object.");
872
+ }
873
+ const record = content;
874
+ for (const field of ["principalId", "principalAttributionHash"]) {
875
+ if (record[field] !== void 0) {
876
+ throw new TaxDeclarationRefusedError(
877
+ `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.`
878
+ );
879
+ }
880
+ }
881
+ const allowed = /* @__PURE__ */ new Set(["version", "jurisdiction", "taxableStatus", "taxId", "validUntil"]);
882
+ for (const key of Object.keys(record)) {
883
+ if (!allowed.has(key)) {
884
+ throw new TaxDeclarationRefusedError(
885
+ `Tax declaration content carries an unknown field '${key}'; the signed shape is built locally from the \xA72.1 fields only.`
886
+ );
887
+ }
888
+ }
889
+ const strings = ["version", "jurisdiction", "taxableStatus", "taxId"];
890
+ for (const key of strings) {
891
+ if (typeof record[key] !== "string" || record[key].length === 0) {
892
+ throw new TaxDeclarationRefusedError(
893
+ `Tax declaration content field '${key}' must be a non-empty string.`
894
+ );
895
+ }
896
+ }
897
+ if (typeof record.validUntil !== "number" || !Number.isInteger(record.validUntil) || record.validUntil <= 0) {
898
+ throw new TaxDeclarationRefusedError(
899
+ "Tax declaration content field 'validUntil' must be a positive integer (milliseconds)."
900
+ );
901
+ }
902
+ return {
903
+ version: record.version,
904
+ jurisdiction: record.jurisdiction,
905
+ taxableStatus: record.taxableStatus,
906
+ taxId: record.taxId,
907
+ validUntil: record.validUntil
908
+ };
909
+ }
910
+ function jcsCanonicalBytes(value) {
911
+ const keys = Object.keys(value).sort();
912
+ const members = keys.map((key) => `${JSON.stringify(key)}:${JSON.stringify(value[key])}`);
913
+ return `{${members.join(",")}}`;
914
+ }
915
+ function principalAttributionHash(principalId) {
916
+ const canonical = jcsCanonicalBytes({ principalId });
917
+ const hex2 = createHash("sha256").update(canonical, "utf8").digest("hex");
918
+ return `sha-256:${hex2}`;
919
+ }
920
+ function taxPrincipalId(network, delegateAddress) {
921
+ if (network.startsWith("eip155:")) {
922
+ return `did:pkh:${network}:${delegateAddress}`;
923
+ }
924
+ const chainId = chainIdForNetwork(network);
925
+ if (chainId === void 0) {
926
+ throw new TaxDeclarationRefusedError(
927
+ `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.`
928
+ );
929
+ }
930
+ return `did:pkh:eip155:${chainId}:${delegateAddress}`;
931
+ }
932
+ function buildSignedTaxDeclaration(input) {
933
+ const content = validateContent(input.content);
934
+ const principalId = taxPrincipalId(input.network, addressFromKeyForTax(input.delegateKey));
935
+ const attributionHash = principalAttributionHash(principalId);
936
+ const declaration = { ...content, principalId, principalAttributionHash: attributionHash };
937
+ const message = { ...declaration, validUntil: BigInt(declaration.validUntil) };
938
+ const digest = hashTypedData({
939
+ domain: TAX_DECLARATION_DOMAIN,
940
+ types: TAX_DECLARATION_TYPES,
941
+ primaryType: TAX_DECLARATION_PRIMARY_TYPE,
942
+ message
943
+ });
944
+ const signature = signHash(input.delegateKey, digest);
945
+ return { declaration, signature };
946
+ }
947
+ function verifyTaxDeclarationSignature(declaration, signature, expectedAddress) {
948
+ const message = { ...declaration, validUntil: BigInt(declaration.validUntil) };
949
+ const digest = hashTypedData({
950
+ domain: TAX_DECLARATION_DOMAIN,
951
+ types: TAX_DECLARATION_TYPES,
952
+ primaryType: TAX_DECLARATION_PRIMARY_TYPE,
953
+ message
954
+ });
955
+ return verifySignature(digest, signature, expectedAddress);
956
+ }
957
+ function encodeTaxDeclarationHeader(result) {
958
+ const json = JSON.stringify({ ...result.declaration, signature: result.signature });
959
+ return base64Url(json);
960
+ }
961
+ function base64Url(value) {
962
+ const standard = typeof Buffer !== "undefined" ? Buffer.from(value, "utf8").toString("base64") : btoa(String.fromCharCode(...new TextEncoder().encode(value)));
963
+ return standard.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
964
+ }
965
+ function addressFromKeyForTax(delegateKey) {
966
+ try {
967
+ return addressFromKey(delegateKey);
968
+ } catch (err) {
969
+ throw new HavenSigningError(
970
+ `Invalid delegate key for tax declaration signing: ${err instanceof Error ? err.message : String(err)}`
971
+ );
972
+ }
973
+ }
974
+ var TaxDeclarationRefusedError = class extends HavenSigningError {
975
+ code = "TAX_DECLARATION_REFUSED";
976
+ constructor(message) {
977
+ super(message);
978
+ this.name = "TaxDeclarationRefusedError";
979
+ }
980
+ };
808
981
 
809
982
  // src/next-step.ts
810
983
  var NEXT_TOOL_SERVER_NAMES = {
@@ -1212,6 +1385,6 @@ function hashDelegation(delegation) {
1212
1385
  return keccak256(encoded);
1213
1386
  }
1214
1387
 
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-6JQT7HNR.js.map
1217
- //# sourceMappingURL=chunk-6JQT7HNR.js.map
1388
+ 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 };
1389
+ //# sourceMappingURL=chunk-S35ZUPXQ.js.map
1390
+ //# sourceMappingURL=chunk-S35ZUPXQ.js.map