@haven_ai/signer 0.5.0-alpha.1 → 0.6.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 +5 -3
- package/dist/cli.cjs +217 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +218 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +217 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +218 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -251,6 +251,13 @@ interface SignerCompatibility {
|
|
|
251
251
|
* never a second literal.
|
|
252
252
|
*/
|
|
253
253
|
direct_sign_context_versions: number[];
|
|
254
|
+
/**
|
|
255
|
+
* #3329: `task_sign_context_version`s this signer will fetch and verify
|
|
256
|
+
* from `GET /task-budgets/:id/sign-context` — derived from
|
|
257
|
+
* `SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS`, never a second literal, same
|
|
258
|
+
* discipline as `direct_sign_context_versions`.
|
|
259
|
+
*/
|
|
260
|
+
task_sign_context_versions: number[];
|
|
254
261
|
}
|
|
255
262
|
/** The supported sets this signer enforces, as a plain serialisable object. */
|
|
256
263
|
declare function signerCompatibility(): SignerCompatibility;
|
|
@@ -604,6 +611,7 @@ declare const toolSchemas: {
|
|
|
604
611
|
}>>;
|
|
605
612
|
readonly typed_data: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
606
613
|
readonly typed_data_b64: z$1.ZodOptional<z$1.ZodString>;
|
|
614
|
+
readonly task_budget_id: z$1.ZodOptional<z$1.ZodString>;
|
|
607
615
|
};
|
|
608
616
|
readonly haven_x402_sign_header: {
|
|
609
617
|
readonly payment_required: z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>;
|
|
@@ -776,7 +784,7 @@ declare function renderSignerConsentBlock(input: SignerConsentInput, hash: strin
|
|
|
776
784
|
declare function ensureSignerConsent(input: SignerConsentInput, options?: SignerConsentOptions): Promise<SignerConsentDecision>;
|
|
777
785
|
|
|
778
786
|
declare const SIGNER_NAME = "@haven_ai/signer";
|
|
779
|
-
declare const SIGNER_VERSION = "0.
|
|
787
|
+
declare const SIGNER_VERSION = "0.6.0-alpha.0";
|
|
780
788
|
interface SignerOptions {
|
|
781
789
|
/** Path to a Haven credential JSON file (delegate_key is read from it). */
|
|
782
790
|
credentialsPath?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -251,6 +251,13 @@ interface SignerCompatibility {
|
|
|
251
251
|
* never a second literal.
|
|
252
252
|
*/
|
|
253
253
|
direct_sign_context_versions: number[];
|
|
254
|
+
/**
|
|
255
|
+
* #3329: `task_sign_context_version`s this signer will fetch and verify
|
|
256
|
+
* from `GET /task-budgets/:id/sign-context` — derived from
|
|
257
|
+
* `SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS`, never a second literal, same
|
|
258
|
+
* discipline as `direct_sign_context_versions`.
|
|
259
|
+
*/
|
|
260
|
+
task_sign_context_versions: number[];
|
|
254
261
|
}
|
|
255
262
|
/** The supported sets this signer enforces, as a plain serialisable object. */
|
|
256
263
|
declare function signerCompatibility(): SignerCompatibility;
|
|
@@ -604,6 +611,7 @@ declare const toolSchemas: {
|
|
|
604
611
|
}>>;
|
|
605
612
|
readonly typed_data: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
606
613
|
readonly typed_data_b64: z$1.ZodOptional<z$1.ZodString>;
|
|
614
|
+
readonly task_budget_id: z$1.ZodOptional<z$1.ZodString>;
|
|
607
615
|
};
|
|
608
616
|
readonly haven_x402_sign_header: {
|
|
609
617
|
readonly payment_required: z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>;
|
|
@@ -776,7 +784,7 @@ declare function renderSignerConsentBlock(input: SignerConsentInput, hash: strin
|
|
|
776
784
|
declare function ensureSignerConsent(input: SignerConsentInput, options?: SignerConsentOptions): Promise<SignerConsentDecision>;
|
|
777
785
|
|
|
778
786
|
declare const SIGNER_NAME = "@haven_ai/signer";
|
|
779
|
-
declare const SIGNER_VERSION = "0.
|
|
787
|
+
declare const SIGNER_VERSION = "0.6.0-alpha.0";
|
|
780
788
|
interface SignerOptions {
|
|
781
789
|
/** Path to a Haven credential JSON file (delegate_key is read from it). */
|
|
782
790
|
credentialsPath?: string;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID, createHash } from 'crypto';
|
|
2
2
|
import { recoverTypedDataAddress, hashTypedData, hashMessage } from 'viem';
|
|
3
3
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
|
-
import { createNextStepBuilder, addressFromKey, HavenSigningError, buildSweepTypedData, selectStandardPaymentOption, HavenApiError, toStandardPaymentRequirements, decodeBase64Json, encodeBase64Json, x402V2PaymentEnvelope, isSettlementChildTypedData, chainIdForNetwork, assertOwnSettlementChild, isPackedUserOperationTypedData, assertUserOpTypedDataBinding, assertBoundDirectPaymentUserOp, assertFundingLegPaysDelegate, HavenTypedDataRefusedError, buildSweepAuthorizationMessage, verifySignature, x402AuthorizationAmount, SignerRefusalCode, connectorRerunCommand, SIGNER_UPDATE_FALLBACK, HavenUnsupportedSignerVersionError, buildX402ExpectedMessage, DIRECT_SIGN_CONTEXT_VERSION, AgentPaymentNextAction, HavenError, AgentPaymentFailureCode, havenClientIdentity, isSupportedNodeVersion, unsupportedNodeVersionMessage, HavenUserOpBindingError, readClientUpdate, HAVEN_CLIENT_HEADER } from '@haven_ai/sdk/edge';
|
|
4
|
+
import { createNextStepBuilder, addressFromKey, HavenSigningError, buildSweepTypedData, selectStandardPaymentOption, HavenApiError, toStandardPaymentRequirements, decodeBase64Json, encodeBase64Json, x402V2PaymentEnvelope, isSettlementChildTypedData, chainIdForNetwork, assertOwnSettlementChild, isPackedUserOperationTypedData, assertUserOpTypedDataBinding, assertBoundDirectPaymentUserOp, assertFundingLegPaysDelegate, HavenTypedDataRefusedError, buildSweepAuthorizationMessage, verifySignature, x402AuthorizationAmount, SignerRefusalCode, connectorRerunCommand, SIGNER_UPDATE_FALLBACK, HavenUnsupportedSignerVersionError, buildX402ExpectedMessage, DIRECT_SIGN_CONTEXT_VERSION, AgentPaymentNextAction, HavenError, AgentPaymentFailureCode, havenClientIdentity, isSupportedNodeVersion, unsupportedNodeVersionMessage, HavenUserOpBindingError, assertOwnTaskChild, assertOwnTaskBudgetCloseUserOp, readClientUpdate, HAVEN_CLIENT_HEADER } from '@haven_ai/sdk/edge';
|
|
5
5
|
export { deriveDelegateAccountAddress } from '@haven_ai/sdk/edge';
|
|
6
6
|
import { stat, lstat, chmod, readFile, mkdir, rename, appendFile, writeFile } from 'fs/promises';
|
|
7
7
|
import { resolve, dirname, join } from 'path';
|
|
@@ -475,6 +475,13 @@ var HavenSignContextError = class extends HavenSigningError {
|
|
|
475
475
|
nextTool: null,
|
|
476
476
|
nextToolOmittedReason: "re-run the hosted quote tool you called with the same idempotency_key; which one depends on the flow"
|
|
477
477
|
});
|
|
478
|
+
} else if (flow === "task") {
|
|
479
|
+
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
480
|
+
step = signerRefusalStep({
|
|
481
|
+
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
482
|
+
nextTool: null,
|
|
483
|
+
nextToolOmittedReason: `re-check this task budget's status (id ${paymentId}) with the hosted Haven server before retrying`
|
|
484
|
+
});
|
|
478
485
|
} else {
|
|
479
486
|
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
480
487
|
step = signerRefusalStep({
|
|
@@ -483,6 +490,13 @@ var HavenSignContextError = class extends HavenSigningError {
|
|
|
483
490
|
nextArguments: { payment_id: paymentId }
|
|
484
491
|
});
|
|
485
492
|
}
|
|
493
|
+
} else if (flow === "task") {
|
|
494
|
+
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
495
|
+
step = signerRefusalStep({
|
|
496
|
+
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
497
|
+
nextTool: null,
|
|
498
|
+
nextToolOmittedReason: "retry the same haven_sign call with the same task_budget_id"
|
|
499
|
+
});
|
|
486
500
|
} else {
|
|
487
501
|
this.fallback = "typed_data_b64";
|
|
488
502
|
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
@@ -651,6 +665,116 @@ async function fetchDirectSignContext(identity, paymentId, fetchImpl = fetch, ti
|
|
|
651
665
|
clientUpdate: readClientUpdate(body.client_update)
|
|
652
666
|
};
|
|
653
667
|
}
|
|
668
|
+
var SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS = [1];
|
|
669
|
+
async function fetchTaskBudgetSignContext(identity, taskBudgetId, fetchImpl = fetch, timeoutMs = SIGN_CONTEXT_TIMEOUT_MS, clientIdentity) {
|
|
670
|
+
let response;
|
|
671
|
+
try {
|
|
672
|
+
response = await fetchImpl(
|
|
673
|
+
`${identity.apiUrl}/task-budgets/${encodeURIComponent(taskBudgetId)}/sign-context`,
|
|
674
|
+
{
|
|
675
|
+
headers: signContextHeaders(identity, clientIdentity),
|
|
676
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
677
|
+
}
|
|
678
|
+
);
|
|
679
|
+
} catch (err) {
|
|
680
|
+
const timedOut = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
|
|
681
|
+
throw new HavenSignContextError(
|
|
682
|
+
timedOut ? `Haven did not answer the task-budget signing-context fetch for ${taskBudgetId} within ${timeoutMs} ms. Retry.` : `Could not reach Haven to fetch the task-budget signing context for ${taskBudgetId}: ${err instanceof Error ? err.message : String(err)}.`,
|
|
683
|
+
timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE",
|
|
684
|
+
void 0,
|
|
685
|
+
taskBudgetId,
|
|
686
|
+
"task"
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
let body;
|
|
690
|
+
try {
|
|
691
|
+
body = await response.json();
|
|
692
|
+
} catch (err) {
|
|
693
|
+
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
694
|
+
throw new HavenSignContextError(
|
|
695
|
+
`Haven did not finish sending the task-budget signing context for ${taskBudgetId} within ${timeoutMs} ms. Retry.`,
|
|
696
|
+
"SIGN_CONTEXT_TIMEOUT",
|
|
697
|
+
void 0,
|
|
698
|
+
taskBudgetId,
|
|
699
|
+
"task"
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
body = {};
|
|
703
|
+
}
|
|
704
|
+
if (!response.ok) {
|
|
705
|
+
const detail = typeof body.error === "string" ? body.error : `HTTP ${response.status}`;
|
|
706
|
+
throw new HavenSignContextError(
|
|
707
|
+
`Haven refused the task-budget signing-context fetch for ${taskBudgetId}: ${detail}`,
|
|
708
|
+
"SIGN_CONTEXT_REFUSED",
|
|
709
|
+
refusalOf(response.status, body),
|
|
710
|
+
taskBudgetId,
|
|
711
|
+
"task"
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
const purpose = body.purpose;
|
|
715
|
+
const typedData = body.typed_data;
|
|
716
|
+
const version = body.task_sign_context_version;
|
|
717
|
+
const expected = body.expected;
|
|
718
|
+
const malformed = (detail) => {
|
|
719
|
+
throw new HavenSignContextError(
|
|
720
|
+
`The Haven task-budget sign-context response for ${taskBudgetId} is malformed: ${detail}.`,
|
|
721
|
+
"SIGN_CONTEXT_MALFORMED",
|
|
722
|
+
void 0,
|
|
723
|
+
taskBudgetId,
|
|
724
|
+
"task"
|
|
725
|
+
);
|
|
726
|
+
};
|
|
727
|
+
if (typeof version !== "number" || !SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS.includes(version)) {
|
|
728
|
+
throw new HavenSignContextError(
|
|
729
|
+
`The Haven task-budget sign-context response is version ${String(version)}, which this signer does not support (supported: ${SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS.join(", ")}). Update @haven_ai/signer.`,
|
|
730
|
+
"SIGN_CONTEXT_MALFORMED",
|
|
731
|
+
void 0,
|
|
732
|
+
taskBudgetId,
|
|
733
|
+
"task"
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
if (!typedData || typeof typedData !== "object") return malformed("missing typed_data");
|
|
737
|
+
if (!expected || typeof expected !== "object") return malformed("missing expected");
|
|
738
|
+
const e = expected;
|
|
739
|
+
if (purpose === "open") {
|
|
740
|
+
if (typeof e.delegate_account !== "string" || typeof e.chain_id !== "number" || typeof e.token_address !== "string" || typeof e.max_amount_atomic !== "string" || e.recipient_address !== null && typeof e.recipient_address !== "string" || typeof e.expires_at !== "number" || typeof e.parent_delegation_hash !== "string") {
|
|
741
|
+
return malformed("expected is missing a required field for purpose open");
|
|
742
|
+
}
|
|
743
|
+
return {
|
|
744
|
+
purpose: "open",
|
|
745
|
+
taskBudgetId: String(body.task_budget_id ?? taskBudgetId),
|
|
746
|
+
typedData,
|
|
747
|
+
expected: {
|
|
748
|
+
delegateAccount: e.delegate_account,
|
|
749
|
+
chainId: e.chain_id,
|
|
750
|
+
tokenAddress: e.token_address,
|
|
751
|
+
maxAmountAtomic: e.max_amount_atomic,
|
|
752
|
+
recipientAddress: e.recipient_address ?? null,
|
|
753
|
+
expiresAt: e.expires_at,
|
|
754
|
+
parentDelegationHash: e.parent_delegation_hash
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
if (purpose === "close") {
|
|
759
|
+
const userOpHash = body.user_op_hash;
|
|
760
|
+
if (typeof userOpHash !== "string") return malformed("missing user_op_hash for purpose close");
|
|
761
|
+
if (typeof e.delegate_account !== "string" || typeof e.chain_id !== "number" || typeof e.delegation_hash !== "string") {
|
|
762
|
+
return malformed("expected is missing a required field for purpose close");
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
purpose: "close",
|
|
766
|
+
taskBudgetId: String(body.task_budget_id ?? taskBudgetId),
|
|
767
|
+
typedData,
|
|
768
|
+
userOpHash,
|
|
769
|
+
expected: {
|
|
770
|
+
delegateAccount: e.delegate_account,
|
|
771
|
+
chainId: e.chain_id,
|
|
772
|
+
delegationHash: e.delegation_hash
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
return malformed(`unknown purpose '${String(purpose)}'`);
|
|
777
|
+
}
|
|
654
778
|
|
|
655
779
|
// src/capabilities.ts
|
|
656
780
|
var SIGNER_CAPABILITY_KEY = "haven/signer-compatibility";
|
|
@@ -658,7 +782,8 @@ function signerCompatibility() {
|
|
|
658
782
|
return {
|
|
659
783
|
x402_expected_context_versions: [...SUPPORTED_X402_EXPECTED_VERSIONS],
|
|
660
784
|
sweep_binding_versions: [...SUPPORTED_SWEEP_BINDING_VERSIONS],
|
|
661
|
-
direct_sign_context_versions: [...SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS]
|
|
785
|
+
direct_sign_context_versions: [...SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS],
|
|
786
|
+
task_sign_context_versions: [...SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS]
|
|
662
787
|
};
|
|
663
788
|
}
|
|
664
789
|
function signerCapabilityAdvertisement() {
|
|
@@ -677,6 +802,7 @@ function signerInstructions() {
|
|
|
677
802
|
`- x402 expected-context versions supported: ${compatibility.x402_expected_context_versions.join(", ")}`,
|
|
678
803
|
`- sweep authorization binding versions supported: ${compatibility.sweep_binding_versions.join(", ")}`,
|
|
679
804
|
`- direct-payment (haven_send / haven_pay) sign-context versions supported: ${compatibility.direct_sign_context_versions.join(", ")} \u2014 pass payment_id alone to haven_sign; this signer fetches the exact bytes`,
|
|
805
|
+
`- task-budget sign-context versions supported: ${compatibility.task_sign_context_versions.join(", ")} \u2014 pass task_budget_id alone to haven_sign; this signer fetches the exact bytes`,
|
|
680
806
|
"",
|
|
681
807
|
"Haven quote and prepare results report the expected-context version they will emit",
|
|
682
808
|
"(signer_compatibility.x402_expected_context_version). If that version is not in the list",
|
|
@@ -1029,7 +1155,14 @@ var toolSchemas = {
|
|
|
1029
1155
|
// Bounded: a realistic redemption payload is ~10KB encoded; 256KB is
|
|
1030
1156
|
// generous headroom while keeping the offline signer from materializing
|
|
1031
1157
|
// arbitrarily large caller input.
|
|
1032
|
-
typed_data_b64: z$1.string().min(1).max(262144).optional()
|
|
1158
|
+
typed_data_b64: z$1.string().min(1).max(262144).optional(),
|
|
1159
|
+
// #3329: sign a task budget's own child delegation (purpose `open`) or
|
|
1160
|
+
// its early-close UserOp (purpose `close`) — the signer fetches the
|
|
1161
|
+
// exact typed data and expectation itself, exactly like payment_id.
|
|
1162
|
+
// Mutually exclusive with payment_id / payload_hash (checked in the
|
|
1163
|
+
// handler, since Zod's object-level refine on a raw shape used by
|
|
1164
|
+
// several call sites is not the shape this schema is composed as).
|
|
1165
|
+
task_budget_id: z$1.string().min(1).optional()
|
|
1033
1166
|
},
|
|
1034
1167
|
haven_x402_sign_header: {
|
|
1035
1168
|
// The parsed HTTP 402 PaymentRequired from the merchant. Typed as an object
|
|
@@ -1079,7 +1212,11 @@ var SIGN_DESCRIPTION = [
|
|
|
1079
1212
|
"intent against a Haven-signed context \u2014 never an arbitrary typed_data payload, however it is shaped.",
|
|
1080
1213
|
"Next: call mcp__haven__haven_submit with signature, then pass x402_binding",
|
|
1081
1214
|
"to mcp__haven-signer__haven_x402_sign_header. A bare payload_hash with no payment_id, typed_data",
|
|
1082
|
-
"or x402_expected is REFUSED (BARE_HASH_REFUSED): a hash carries nothing this signer can verify."
|
|
1215
|
+
"or x402_expected is REFUSED (BARE_HASH_REFUSED): a hash carries nothing this signer can verify.",
|
|
1216
|
+
"TASK BUDGETS (#3329): pass task_budget_id ALONE \u2014 mutually exclusive with payment_id and",
|
|
1217
|
+
"payload_hash \u2014 to sign a task budget\u2019s own child delegation (opening it) or its early-close",
|
|
1218
|
+
"UserOp; this signer fetches the exact typed data itself. Result then carries next_tool_name",
|
|
1219
|
+
"(haven_submit) and next_arguments { task_budget_id, signature } instead of x402_binding."
|
|
1083
1220
|
].join(" ");
|
|
1084
1221
|
var X402_SIGN_HEADER_DESCRIPTION = [
|
|
1085
1222
|
"Build and sign the EIP-3009 merchant payment header for the merchant leg of an x402 payment.",
|
|
@@ -1243,9 +1380,84 @@ function createToolHandlers(signer, options = {}) {
|
|
|
1243
1380
|
throw err;
|
|
1244
1381
|
}
|
|
1245
1382
|
}
|
|
1383
|
+
async function signTaskBudget(taskBudgetId) {
|
|
1384
|
+
const identity = await options.signContext?.loadIdentity() ?? null;
|
|
1385
|
+
if (!identity) {
|
|
1386
|
+
throw new HavenSigningError(
|
|
1387
|
+
`task_budget_id signing needs the agent identity (identity.json next to the signer credentials), which this signer could not load. Re-run \`${connectorRerunCommand()}\` to restore it.`
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
const ctx = await fetchTaskBudgetSignContext(
|
|
1391
|
+
identity,
|
|
1392
|
+
taskBudgetId,
|
|
1393
|
+
options.signContext?.fetchImpl,
|
|
1394
|
+
void 0,
|
|
1395
|
+
options.signContext?.clientIdentity
|
|
1396
|
+
);
|
|
1397
|
+
let signature;
|
|
1398
|
+
if (ctx.purpose === "open") {
|
|
1399
|
+
try {
|
|
1400
|
+
assertOwnTaskChild(
|
|
1401
|
+
ctx.typedData,
|
|
1402
|
+
{
|
|
1403
|
+
chainId: ctx.expected.chainId,
|
|
1404
|
+
tokenAddress: ctx.expected.tokenAddress,
|
|
1405
|
+
maxAmountAtomic: ctx.expected.maxAmountAtomic,
|
|
1406
|
+
recipientAddress: ctx.expected.recipientAddress,
|
|
1407
|
+
expiresAt: ctx.expected.expiresAt,
|
|
1408
|
+
parentDelegationHash: ctx.expected.parentDelegationHash
|
|
1409
|
+
},
|
|
1410
|
+
signer.delegateAddress
|
|
1411
|
+
);
|
|
1412
|
+
} catch (err) {
|
|
1413
|
+
if (err instanceof HavenTypedDataRefusedError) throw err;
|
|
1414
|
+
throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
|
|
1415
|
+
}
|
|
1416
|
+
signature = await signer.signDelegationTypedData(ctx.typedData);
|
|
1417
|
+
} else {
|
|
1418
|
+
try {
|
|
1419
|
+
assertUserOpTypedDataBinding(ctx.typedData, ctx.userOpHash);
|
|
1420
|
+
} catch (err) {
|
|
1421
|
+
if (err instanceof HavenUserOpBindingError) throw new HavenUserOpBindingRefusedError(err.message);
|
|
1422
|
+
throw err;
|
|
1423
|
+
}
|
|
1424
|
+
try {
|
|
1425
|
+
assertOwnTaskBudgetCloseUserOp(
|
|
1426
|
+
ctx.typedData,
|
|
1427
|
+
{ delegationHash: ctx.expected.delegationHash },
|
|
1428
|
+
signer.delegateAddress
|
|
1429
|
+
);
|
|
1430
|
+
} catch (err) {
|
|
1431
|
+
if (err instanceof HavenTypedDataRefusedError) throw err;
|
|
1432
|
+
throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
|
|
1433
|
+
}
|
|
1434
|
+
signature = await signer.signDelegationTypedData(ctx.typedData);
|
|
1435
|
+
}
|
|
1436
|
+
await auditSigning("haven_sign", hashTypedData(ctx.typedData));
|
|
1437
|
+
return {
|
|
1438
|
+
signature,
|
|
1439
|
+
task_budget_id: ctx.taskBudgetId,
|
|
1440
|
+
purpose: ctx.purpose,
|
|
1441
|
+
next_tool_name: "haven_submit",
|
|
1442
|
+
next_tool_server_role: "hosted",
|
|
1443
|
+
next_arguments: { task_budget_id: ctx.taskBudgetId, signature }
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1246
1446
|
return {
|
|
1247
1447
|
haven_sign: async (input) => runTool(async () => {
|
|
1248
1448
|
const args = parse("haven_sign", coerceX402Expected(input));
|
|
1449
|
+
if (args.task_budget_id) {
|
|
1450
|
+
if (args.payment_id || args.payload_hash) {
|
|
1451
|
+
throw new z$1.ZodError([
|
|
1452
|
+
{
|
|
1453
|
+
code: z$1.ZodIssueCode.custom,
|
|
1454
|
+
path: ["task_budget_id"],
|
|
1455
|
+
message: "task_budget_id is mutually exclusive with payment_id / payload_hash \u2014 pass exactly one."
|
|
1456
|
+
}
|
|
1457
|
+
]);
|
|
1458
|
+
}
|
|
1459
|
+
return signTaskBudget(args.task_budget_id);
|
|
1460
|
+
}
|
|
1249
1461
|
const resolved = await resolveSignContext(args, { allowDirectFallback: true });
|
|
1250
1462
|
const typedData = resolved?.ctx.typedData ?? resolveTypedData(args);
|
|
1251
1463
|
const payloadHash = resolved?.ctx.payloadHash ?? args.payload_hash;
|
|
@@ -1516,7 +1728,7 @@ function normalizeError(err) {
|
|
|
1516
1728
|
|
|
1517
1729
|
// src/consent.ts
|
|
1518
1730
|
var toolSummaries = {
|
|
1519
|
-
haven_sign: "signs
|
|
1731
|
+
haven_sign: "signs a Haven-prepared payment, task-budget open, or task-budget close (a UserOp from your own account whose only call redeems a delegation made to it, directly or through a self-delegated task-budget child, or an x402 funding intent against a Haven-signed context)",
|
|
1520
1732
|
haven_x402_sign_header: "builds and signs the EIP-3009 merchant payment header for an x402 payment",
|
|
1521
1733
|
haven_sign_x402: "the two above in one call: funding payload + merchant header",
|
|
1522
1734
|
haven_sign_sweep_delegate: "signs a Haven-prepared gasless sweep of stranded funds back to your own account"
|
|
@@ -1646,7 +1858,7 @@ async function writeAckFile(path, hash) {
|
|
|
1646
1858
|
);
|
|
1647
1859
|
}
|
|
1648
1860
|
var SIGNER_NAME = "@haven_ai/signer";
|
|
1649
|
-
var SIGNER_VERSION = "0.
|
|
1861
|
+
var SIGNER_VERSION = "0.6.0-alpha.0";
|
|
1650
1862
|
async function resolveEdgeSigner(options = {}) {
|
|
1651
1863
|
const { signer } = await resolveSignerRuntime(options);
|
|
1652
1864
|
return signer;
|