@haven_ai/sdk 0.5.0-alpha.1 → 0.7.0-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 +24 -8
- package/dist/{base64-BUMXmruY.d.cts → base64-_seD1uw8.d.cts} +425 -18
- package/dist/{base64-BUMXmruY.d.ts → base64-_seD1uw8.d.ts} +425 -18
- package/dist/{chunk-JKUIE45B.cjs → chunk-3SVPI4LS.cjs} +130 -9
- package/dist/chunk-3SVPI4LS.cjs.map +1 -0
- package/dist/{chunk-QSSVOPWA.cjs → chunk-J6DQEBK2.cjs} +340 -17
- package/dist/chunk-J6DQEBK2.cjs.map +1 -0
- package/dist/{chunk-GLNG2GF7.js → chunk-NNIT7WAI.js} +127 -10
- package/dist/chunk-NNIT7WAI.js.map +1 -0
- package/dist/{chunk-KQ7JXKTV.js → chunk-R3RZJJWL.js} +321 -6
- package/dist/chunk-R3RZJJWL.js.map +1 -0
- package/dist/edge.cjs +296 -57
- package/dist/edge.cjs.map +1 -1
- package/dist/edge.d.cts +122 -5
- package/dist/edge.d.ts +122 -5
- package/dist/edge.js +204 -4
- package/dist/edge.js.map +1 -1
- package/dist/index.cjs +772 -350
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +162 -28
- package/dist/index.d.ts +162 -28
- package/dist/index.js +461 -80
- package/dist/index.js.map +1 -1
- package/dist/test-support.cjs +18 -18
- package/dist/test-support.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-GLNG2GF7.js.map +0 -1
- package/dist/chunk-JKUIE45B.cjs.map +0 -1
- package/dist/chunk-KQ7JXKTV.js.map +0 -1
- package/dist/chunk-QSSVOPWA.cjs.map +0 -1
|
@@ -28,6 +28,9 @@ function connectorRerunCommand(args, options) {
|
|
|
28
28
|
const command = `npx ${flags}${connectorSpec(channel)}`;
|
|
29
29
|
return args ? `${command} ${args}` : command;
|
|
30
30
|
}
|
|
31
|
+
function connectorUpgradeCommand(options) {
|
|
32
|
+
return connectorRerunCommand("--doctor", { channel: options?.channel, npxFlags: "-y" });
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
// src/types.ts
|
|
33
36
|
var DEFAULT_CONFIRMATION_TIMEOUT_MS = 9e4;
|
|
@@ -73,7 +76,21 @@ var AgentPaymentPhase = {
|
|
|
73
76
|
* agent should stop, tell the user, and wait for the sweep flow to reclaim
|
|
74
77
|
* the funds.
|
|
75
78
|
*/
|
|
76
|
-
FundedButUnsettled: "funded_but_unsettled"
|
|
79
|
+
FundedButUnsettled: "funded_but_unsettled",
|
|
80
|
+
/**
|
|
81
|
+
* #3420: TERMINAL — a `submitted` erc7710 x402 intent whose settlement
|
|
82
|
+
* window AND the sweep's last attribution chance have both passed with no
|
|
83
|
+
* verified evidence. The sweep's tick (120s) only ever confirms a
|
|
84
|
+
* transaction mined inside the payment's own settlement window (the child
|
|
85
|
+
* delegation's on-chain `timestamp` caveat, plus the verifier's 120s
|
|
86
|
+
* clock-skew allowance), so once authorize + window + skew is behind the
|
|
87
|
+
* payment, no poll — and no sweep tick — can ever change the answer.
|
|
88
|
+
* The paired `next_action` is `stop_and_tell_user`: tell the user the goods
|
|
89
|
+
* were delivered but Haven holds no verified settlement evidence; reporting
|
|
90
|
+
* a real settlement hash (`haven_report_settlement_evidence`) still works
|
|
91
|
+
* at any age.
|
|
92
|
+
*/
|
|
93
|
+
DeliveredUnverified: "delivered_unverified"
|
|
77
94
|
};
|
|
78
95
|
var AgentPaymentNextAction = {
|
|
79
96
|
/** Sign with the delegate key and submit the payment to Haven. */
|
|
@@ -221,7 +238,8 @@ var AgentPaymentPhaseDescriptions = {
|
|
|
221
238
|
[AgentPaymentPhase.Expired]: "The payment expired before completion.",
|
|
222
239
|
[AgentPaymentPhase.Failed]: "Haven could not complete the payment; the agent should stop and surface the failure.",
|
|
223
240
|
[AgentPaymentPhase.InsufficientFunds]: "Pre-flight check determined the delegate balance plus the remaining on-chain budget cannot cover the requested amount, so no payment was created. The account must be funded or the agent budget raised before retrying.",
|
|
224
|
-
[AgentPaymentPhase.FundedButUnsettled]: "Haven's funding leg confirmed on-chain but the merchant rejected the x402 retry. The delegate wallet may hold stranded funds. The agent should stop and wait for the wallet owner to sweep the stranded funds back to the account."
|
|
241
|
+
[AgentPaymentPhase.FundedButUnsettled]: "Haven's funding leg confirmed on-chain but the merchant rejected the x402 retry. The delegate wallet may hold stranded funds. The agent should stop and wait for the wallet owner to sweep the stranded funds back to the account.",
|
|
242
|
+
[AgentPaymentPhase.DeliveredUnverified]: "Terminal: the merchant delivered the goods and the settlement window plus the sweep's last attribution chance have both passed with no verified on-chain evidence. The payment can no longer resolve by polling. Tell the user the goods were delivered but Haven holds no verified settlement evidence for this payment."
|
|
225
243
|
};
|
|
226
244
|
var AgentPaymentNextActionDescriptions = {
|
|
227
245
|
[AgentPaymentNextAction.SignAndSubmitPayment]: "Sign with the delegate key and submit the payment to Haven.",
|
|
@@ -356,6 +374,24 @@ var MerchantTimeoutError = class extends HavenApiError {
|
|
|
356
374
|
this.name = "MerchantTimeoutError";
|
|
357
375
|
}
|
|
358
376
|
};
|
|
377
|
+
var X402Erc7710AlreadySettledError = class extends HavenError {
|
|
378
|
+
constructor(paymentId, txHash, body) {
|
|
379
|
+
super(
|
|
380
|
+
`Payment ${paymentId} already settled on-chain (tx ${txHash}). Nothing was signed and nothing new was charged.`,
|
|
381
|
+
"PAYMENT_ALREADY_SETTLED",
|
|
382
|
+
void 0,
|
|
383
|
+
paymentId
|
|
384
|
+
);
|
|
385
|
+
this.paymentId = paymentId;
|
|
386
|
+
this.txHash = txHash;
|
|
387
|
+
this.body = body;
|
|
388
|
+
this.name = "X402Erc7710AlreadySettledError";
|
|
389
|
+
}
|
|
390
|
+
paymentId;
|
|
391
|
+
txHash;
|
|
392
|
+
body;
|
|
393
|
+
x402ErrorCode = "payment_already_settled";
|
|
394
|
+
};
|
|
359
395
|
var X402UnexpectedStatusError = class extends HavenApiError {
|
|
360
396
|
x402ErrorCode = "unexpected_non_402_status";
|
|
361
397
|
/**
|
|
@@ -402,6 +438,19 @@ var HavenPaymentStateError = class extends HavenApiError {
|
|
|
402
438
|
return this.state.nextAction;
|
|
403
439
|
}
|
|
404
440
|
};
|
|
441
|
+
var X402TaskBudgetMismatchError = class extends HavenError {
|
|
442
|
+
constructor(message, idempotencyKey, entryTaskBudgetId, requestedTaskBudgetId) {
|
|
443
|
+
super(message, "X402_TASK_BUDGET_MISMATCH");
|
|
444
|
+
this.idempotencyKey = idempotencyKey;
|
|
445
|
+
this.entryTaskBudgetId = entryTaskBudgetId;
|
|
446
|
+
this.requestedTaskBudgetId = requestedTaskBudgetId;
|
|
447
|
+
this.name = "X402TaskBudgetMismatchError";
|
|
448
|
+
}
|
|
449
|
+
idempotencyKey;
|
|
450
|
+
entryTaskBudgetId;
|
|
451
|
+
requestedTaskBudgetId;
|
|
452
|
+
x402ErrorCode = "task_budget_mismatch";
|
|
453
|
+
};
|
|
405
454
|
var HavenSigningError = class extends HavenError {
|
|
406
455
|
constructor(message) {
|
|
407
456
|
super(message, "SIGNING_ERROR");
|
|
@@ -426,7 +475,7 @@ var SignerRefusalCode = {
|
|
|
426
475
|
UnsupportedSweepBindingVersion: "UNSUPPORTED_SWEEP_BINDING_VERSION"
|
|
427
476
|
};
|
|
428
477
|
function signerUpdateFallback(channel = HAVEN_CONNECTOR_CHANNEL) {
|
|
429
|
-
return `Update @haven_ai/signer
|
|
478
|
+
return `Update @haven_ai/signer: run \`${connectorUpgradeCommand({ channel })}\` and then the repair line it prints, which reinstalls the pinned MCP runtime, then retry the same signing call. Nothing was signed or spent \u2014 the quote or payment this version came from is unaffected and does not need to be re-quoted.`;
|
|
430
479
|
}
|
|
431
480
|
var SIGNER_UPDATE_FALLBACK = signerUpdateFallback();
|
|
432
481
|
var HavenUnsupportedSignerVersionError = class extends HavenError {
|
|
@@ -453,6 +502,7 @@ var HavenTimeoutError = class extends HavenError {
|
|
|
453
502
|
}
|
|
454
503
|
};
|
|
455
504
|
var DIRECT_SIGN_CONTEXT_VERSION = 1;
|
|
505
|
+
var TASK_SIGN_CONTEXT_VERSION = 1;
|
|
456
506
|
var EIP712_DOMAIN_FIELDS = [
|
|
457
507
|
{ name: "name", type: "string" },
|
|
458
508
|
{ name: "version", type: "string" },
|
|
@@ -595,7 +645,15 @@ var CAVEAT_ENFORCERS = {
|
|
|
595
645
|
var MAX_SETTLEMENT_WINDOW_SECONDS = 600;
|
|
596
646
|
function isSettlementChildTypedData(value) {
|
|
597
647
|
const td = value;
|
|
598
|
-
|
|
648
|
+
if (!td || td.primaryType !== "Delegation" || typeof td.domain?.verifyingContract !== "string" || !Array.isArray(td.message?.caveats)) {
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
const delegate = td.message?.delegate;
|
|
652
|
+
const delegator = td.message?.delegator;
|
|
653
|
+
if (typeof delegate === "string" && typeof delegator === "string" && delegate.toLowerCase() === delegator.toLowerCase()) {
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
656
|
+
return true;
|
|
599
657
|
}
|
|
600
658
|
function same(a, b) {
|
|
601
659
|
return !!a && !!b && a.toLowerCase() === b.toLowerCase();
|
|
@@ -659,6 +717,13 @@ function verifySettlementChild(typedData, expected, now = Date.now()) {
|
|
|
659
717
|
`Expected delegator ${expected.delegatorAccount}; the child names ${String(delegator)}.`
|
|
660
718
|
);
|
|
661
719
|
}
|
|
720
|
+
const delegate = typedData.message?.delegate;
|
|
721
|
+
if (typeof delegate === "string" && same(delegate, delegator)) {
|
|
722
|
+
refuse2(
|
|
723
|
+
"its delegate is the same account as its delegator (a self-delegation)",
|
|
724
|
+
"A settlement child is always redeemed by a facilitator or left open to any redeemer \u2014 never redeemable only by the account that granted it. This is the shape of a task-budget child, a different typed-data class Haven never signs through this path."
|
|
725
|
+
);
|
|
726
|
+
}
|
|
662
727
|
}
|
|
663
728
|
const caveats = typedData.message?.caveats ?? [];
|
|
664
729
|
if (caveats.length === 0) {
|
|
@@ -835,7 +900,7 @@ var REDEEM_DELEGATIONS_ABI = [
|
|
|
835
900
|
var SINGLE_DEFAULT_MODE = `0x${"00".repeat(32)}`;
|
|
836
901
|
function refuse3(detail) {
|
|
837
902
|
throw new HavenSigningError(
|
|
838
|
-
`Refusing to sign: this UserOperation's redeemDelegations call ${detail}. This signer only signs
|
|
903
|
+
`Refusing to sign: this UserOperation's redeemDelegations call ${detail}. This signer only signs one of three shapes: a single grant to the agent's own account, a self-delegated task-budget child redeemed under it (the two-link [task child, budget] chain), or a sub-budget grant redeemed under its parent's self-narrowing (the three-link [sub grant, parent child, budget] chain, #3330).`
|
|
839
904
|
);
|
|
840
905
|
}
|
|
841
906
|
function assertRedeemsOwnBudgetDelegation(redeemCalldata, ownAccount) {
|
|
@@ -879,8 +944,10 @@ function assertRedeemsOwnBudgetDelegation(redeemCalldata, ownAccount) {
|
|
|
879
944
|
"carries an EMPTY delegation chain \u2014 DelegationManager treats this as self-authorised and runs the paired execution as the account, with no caveat, budget or recipient pin"
|
|
880
945
|
);
|
|
881
946
|
}
|
|
882
|
-
if (delegations.length !== 1) {
|
|
883
|
-
refuse3(
|
|
947
|
+
if (delegations.length !== 1 && delegations.length !== 2 && delegations.length !== 3) {
|
|
948
|
+
refuse3(
|
|
949
|
+
`carries a ${delegations.length}-link delegation chain, not the single budget grant, the two-link [task child, budget] chain, or the three-link [sub grant, parent child, budget] chain Haven emits`
|
|
950
|
+
);
|
|
884
951
|
}
|
|
885
952
|
const reEncodedContext = viem.encodeAbiParameters(DELEGATION_ARRAY_PARAM, [delegations]);
|
|
886
953
|
if (reEncodedContext.toLowerCase() !== permissionContexts[0].toLowerCase()) {
|
|
@@ -892,6 +959,56 @@ function assertRedeemsOwnBudgetDelegation(redeemCalldata, ownAccount) {
|
|
|
892
959
|
`is redeemed for delegate ${leaf.delegate}, not this signer's own account (${ownAccount})`
|
|
893
960
|
);
|
|
894
961
|
}
|
|
962
|
+
if (delegations.length === 2) {
|
|
963
|
+
if (leaf.delegator.toLowerCase() !== ownAccount.toLowerCase()) {
|
|
964
|
+
refuse3(
|
|
965
|
+
`carries a two-link chain whose leaf is delegated by ${leaf.delegator}, not this signer's own account (${ownAccount}) \u2014 a task-budget child is always self-delegated`
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
const budget = delegations[1];
|
|
969
|
+
if (budget.delegate.toLowerCase() !== ownAccount.toLowerCase()) {
|
|
970
|
+
refuse3(
|
|
971
|
+
`carries a two-link chain whose second link delegates to ${budget.delegate}, not this signer's own account (${ownAccount})`
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
if (budget.delegator.toLowerCase() === ownAccount.toLowerCase()) {
|
|
975
|
+
refuse3(
|
|
976
|
+
"carries a two-link chain whose budget link is granted by this signer's OWN account \u2014 a real budget delegation always comes from elsewhere"
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
if (delegations.length === 3) {
|
|
982
|
+
if (leaf.delegator.toLowerCase() === ownAccount.toLowerCase()) {
|
|
983
|
+
refuse3(
|
|
984
|
+
"carries a three-link chain whose leaf is delegated by this signer's OWN account \u2014 a sub-budget grant always comes from the delegating agent, never from the sub-agent itself"
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
const parentChild = delegations[1];
|
|
988
|
+
const parentAccount = leaf.delegator;
|
|
989
|
+
if (parentChild.delegate.toLowerCase() !== parentAccount.toLowerCase()) {
|
|
990
|
+
refuse3(
|
|
991
|
+
`carries a three-link chain whose middle link delegates to ${parentChild.delegate}, not the delegating agent's account the leaf names as its delegator (${parentAccount})`
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
if (parentChild.delegator.toLowerCase() !== parentAccount.toLowerCase()) {
|
|
995
|
+
refuse3(
|
|
996
|
+
`carries a three-link chain whose middle link is delegated by ${parentChild.delegator}, not the delegating agent's own account (${parentAccount}) \u2014 the parent link is a self-delegated narrowing`
|
|
997
|
+
);
|
|
998
|
+
}
|
|
999
|
+
const budget = delegations[2];
|
|
1000
|
+
if (budget.delegate.toLowerCase() !== parentAccount.toLowerCase()) {
|
|
1001
|
+
refuse3(
|
|
1002
|
+
`carries a three-link chain whose budget link delegates to ${budget.delegate}, not the delegating agent's account (${parentAccount})`
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
if (budget.delegator.toLowerCase() === parentAccount.toLowerCase()) {
|
|
1006
|
+
refuse3(
|
|
1007
|
+
"carries a three-link chain whose budget link is granted by the delegating agent's OWN account \u2014 a real budget delegation always comes from elsewhere"
|
|
1008
|
+
);
|
|
1009
|
+
}
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
895
1012
|
const root = delegations[delegations.length - 1];
|
|
896
1013
|
if (root.delegator.toLowerCase() === ownAccount.toLowerCase()) {
|
|
897
1014
|
refuse3(
|
|
@@ -945,13 +1062,17 @@ exports.SIGNER_UPDATE_FALLBACK = SIGNER_UPDATE_FALLBACK;
|
|
|
945
1062
|
exports.SIMPLE_FACTORY_ADDRESS = SIMPLE_FACTORY_ADDRESS;
|
|
946
1063
|
exports.SINGLE_DEFAULT_MODE = SINGLE_DEFAULT_MODE;
|
|
947
1064
|
exports.SignerRefusalCode = SignerRefusalCode;
|
|
1065
|
+
exports.TASK_SIGN_CONTEXT_VERSION = TASK_SIGN_CONTEXT_VERSION;
|
|
948
1066
|
exports.X402AlreadySettledError = X402AlreadySettledError;
|
|
1067
|
+
exports.X402Erc7710AlreadySettledError = X402Erc7710AlreadySettledError;
|
|
1068
|
+
exports.X402TaskBudgetMismatchError = X402TaskBudgetMismatchError;
|
|
949
1069
|
exports.X402UnexpectedStatusError = X402UnexpectedStatusError;
|
|
950
1070
|
exports.assertRedeemsOwnBudgetDelegation = assertRedeemsOwnBudgetDelegation;
|
|
951
1071
|
exports.assertUserOpTypedDataBinding = assertUserOpTypedDataBinding;
|
|
952
1072
|
exports.chainIdForNetwork = chainIdForNetwork;
|
|
953
1073
|
exports.connectorRerunCommand = connectorRerunCommand;
|
|
954
1074
|
exports.connectorSpec = connectorSpec;
|
|
1075
|
+
exports.connectorUpgradeCommand = connectorUpgradeCommand;
|
|
955
1076
|
exports.deriveDelegateAccountAddress = deriveDelegateAccountAddress;
|
|
956
1077
|
exports.isConnectorChannel = isConnectorChannel;
|
|
957
1078
|
exports.isPackedUserOperationTypedData = isPackedUserOperationTypedData;
|
|
@@ -960,5 +1081,5 @@ exports.packedUserOperationHash = packedUserOperationHash;
|
|
|
960
1081
|
exports.resolveConnectorChannel = resolveConnectorChannel;
|
|
961
1082
|
exports.signerUpdateFallback = signerUpdateFallback;
|
|
962
1083
|
exports.verifySettlementChild = verifySettlementChild;
|
|
963
|
-
//# sourceMappingURL=chunk-
|
|
964
|
-
//# sourceMappingURL=chunk-
|
|
1084
|
+
//# sourceMappingURL=chunk-3SVPI4LS.cjs.map
|
|
1085
|
+
//# sourceMappingURL=chunk-3SVPI4LS.cjs.map
|