@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.
- package/dist/{base64-DyOPH887.d.cts → base64-VVxgYQAD.d.cts} +1 -1
- package/dist/{base64-DyOPH887.d.ts → base64-VVxgYQAD.d.ts} +1 -1
- package/dist/{chunk-MJ2IMB5H.cjs → chunk-J6SS36ZD.cjs} +189 -3
- package/dist/chunk-J6SS36ZD.cjs.map +1 -0
- package/dist/{chunk-6JQT7HNR.js → chunk-S35ZUPXQ.js} +179 -6
- package/dist/chunk-S35ZUPXQ.js.map +1 -0
- package/dist/edge.cjs +88 -88
- package/dist/edge.cjs.map +1 -1
- package/dist/edge.d.cts +172 -3
- package/dist/edge.d.ts +172 -3
- package/dist/edge.js +4 -53
- package/dist/edge.js.map +1 -1
- package/dist/index.cjs +220 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +97 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6JQT7HNR.js.map +0 -1
- package/dist/chunk-MJ2IMB5H.cjs.map +0 -1
|
@@ -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.
|
|
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-
|
|
1217
|
-
//# sourceMappingURL=chunk-
|
|
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
|