@haven_ai/signer 0.2.1-alpha.0 → 0.4.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 +12 -5
- package/dist/cli.cjs +130 -19
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +176 -65
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +131 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +244 -24
- package/dist/index.d.ts +244 -24
- package/dist/index.js +177 -66
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -180,15 +180,17 @@ what a payload means; they re-derive it.
|
|
|
180
180
|
allowed — top-level caveats are AND-ed during redemption, so an unrecognised
|
|
181
181
|
one can only add a constraint.
|
|
182
182
|
- **A binding version it does not understand.** The refusal is machine-readable
|
|
183
|
-
— `code`, `supported_versions`, `received_version`, `fallback
|
|
184
|
-
updating the signer as the fix.
|
|
183
|
+
— `code`, `supported_versions`, `received_version`, `fallback`, and (#3103)
|
|
184
|
+
`next_tool_omitted_reason` — and names updating the signer as the fix.
|
|
185
185
|
- **A sweep that does not move funds out of this delegate's own key** — the
|
|
186
186
|
`from` check is unconditional. The **destination** check is not, and this is
|
|
187
187
|
the one asymmetry in this list: the signer compares the sweep's `to` against
|
|
188
188
|
the account address **only when the local credential records one**
|
|
189
189
|
(`account_address`, or the pre-#2908 `safe_address` / `safeAddress`, which
|
|
190
|
-
are read permanently; from the environment, `HAVEN_ACCOUNT_ADDRESS
|
|
191
|
-
|
|
190
|
+
are read permanently; from the environment, `HAVEN_ACCOUNT_ADDRESS` only —
|
|
191
|
+
`HAVEN_WALLET_ADDRESS` and `HAVEN_SAFE_ADDRESS` were removed by #2914, so a
|
|
192
|
+
machine still configured through either records no account address and lands
|
|
193
|
+
in exactly the degraded case this paragraph describes). Run with
|
|
192
194
|
`HAVEN_DELEGATE_KEY` alone — or with a credential
|
|
193
195
|
whose account address is absent — and there is no local value to compare
|
|
194
196
|
against, so the destination is authenticated by Haven's binding signature and
|
|
@@ -204,7 +206,12 @@ signing payload from Haven (`GET /x402/:id/sign-context`, see
|
|
|
204
206
|
still holds everywhere it did before, but structured like the version-mismatch
|
|
205
207
|
refusal below rather than prose alone: `code`, `next_action`, and — per
|
|
206
208
|
refusal class — `fallback`, `retry_with_new_quote`, `http_status`,
|
|
207
|
-
`backend_error_code`.
|
|
209
|
+
`backend_error_code`. Since #3103 each also carries a typed next step: the
|
|
210
|
+
`SIGN_CONTEXT_REFUSED` (other) row names the hosted status read
|
|
211
|
+
(`next_tool_server_role: hosted`, `next_tool_name: haven_get_payment_status`,
|
|
212
|
+
`next_arguments: { payment_id }` — resolve the role against your own server
|
|
213
|
+
names); every other row carries `next_tool_omitted_reason` with the exact
|
|
214
|
+
remedy. `message` is unchanged.
|
|
208
215
|
|
|
209
216
|
| `code` | When | `next_action` | `fallback` | extra |
|
|
210
217
|
|---|---|---|---|---|
|
package/dist/cli.cjs
CHANGED
|
@@ -12,6 +12,7 @@ var viem = require('viem');
|
|
|
12
12
|
var accounts = require('viem/accounts');
|
|
13
13
|
var schemes = require('x402/schemes');
|
|
14
14
|
var v3 = require('zod/v3');
|
|
15
|
+
var zod = require('zod');
|
|
15
16
|
|
|
16
17
|
function defaultSigningAuditPath(credentialsPath) {
|
|
17
18
|
if (credentialsPath) return path.resolve(`${credentialsPath}.signer-audit.jsonl`);
|
|
@@ -30,7 +31,7 @@ function createSigningAuditEntry(tool, payloadHash, context, now = /* @__PURE__
|
|
|
30
31
|
payload_hash: payloadHash,
|
|
31
32
|
delegate_address: context.delegateAddress
|
|
32
33
|
};
|
|
33
|
-
if (context.
|
|
34
|
+
if (context.accountAddress) entry.safe_address = context.accountAddress;
|
|
34
35
|
if (typeof context.chainId === "number") entry.chain_id = context.chainId;
|
|
35
36
|
return entry;
|
|
36
37
|
}
|
|
@@ -531,9 +532,44 @@ function signerInstructions() {
|
|
|
531
532
|
"",
|
|
532
533
|
"A version-mismatch refusal from haven_sign / haven_sign_x402 / haven_sign_sweep_delegate is",
|
|
533
534
|
"machine-readable, not just prose: it carries code, supported_versions, received_version, and",
|
|
534
|
-
"fallback fields alongside the message, so you can branch on it directly."
|
|
535
|
+
"fallback fields alongside the message, so you can branch on it directly. Every signer",
|
|
536
|
+
"refusal also carries the next-step family: next_tool_name + next_tool_server_role when a",
|
|
537
|
+
"hosted tool follows (resolve the role against your own server names), else",
|
|
538
|
+
"next_tool_omitted_reason saying why not."
|
|
535
539
|
].join("\n");
|
|
536
540
|
}
|
|
541
|
+
var SIGNER_HOSTED_HANDOFF_SHAPES = {
|
|
542
|
+
haven_get_payment_status: { payment_id: zod.z.string().min(1) }
|
|
543
|
+
};
|
|
544
|
+
function target(shape) {
|
|
545
|
+
const schema = zod.z.object(shape).strict();
|
|
546
|
+
return {
|
|
547
|
+
role: "hosted",
|
|
548
|
+
validate: (input) => {
|
|
549
|
+
const r = schema.safeParse(input ?? {});
|
|
550
|
+
return r.success ? null : r.error.errors.map((e) => `${e.path.join(".") || "(root)"}: ${e.message}`).join("; ");
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
var SIGNER_NEXT_STEP_TARGETS = {
|
|
555
|
+
haven_get_payment_status: target(SIGNER_HOSTED_HANDOFF_SHAPES.haven_get_payment_status)
|
|
556
|
+
};
|
|
557
|
+
var nextStep = sdk.createNextStepBuilder(SIGNER_NEXT_STEP_TARGETS);
|
|
558
|
+
function signerRefusalStep(input) {
|
|
559
|
+
return nextStep({ ...input, safeToContinue: false, reason: "" });
|
|
560
|
+
}
|
|
561
|
+
function nextStepWireFields(step) {
|
|
562
|
+
return {
|
|
563
|
+
...step.next_tool ? { next_tool: step.next_tool } : {},
|
|
564
|
+
...step.next_tool_server ? { next_tool_server: step.next_tool_server } : {},
|
|
565
|
+
...step.next_tool_name ? { next_tool_name: step.next_tool_name } : {},
|
|
566
|
+
...step.next_tool_server_role ? { next_tool_server_role: step.next_tool_server_role } : {},
|
|
567
|
+
...step.next_arguments ? { next_arguments: step.next_arguments } : {},
|
|
568
|
+
...step.next_tool_omitted_reason ? { next_tool_omitted_reason: step.next_tool_omitted_reason } : {}
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// src/sign-context.ts
|
|
537
573
|
var HavenSignContextError = class extends sdk.HavenSigningError {
|
|
538
574
|
/**
|
|
539
575
|
* #3001 / #3010 review: the recovery path, when signing OTHER bytes is
|
|
@@ -553,28 +589,63 @@ var HavenSignContextError = class extends sdk.HavenSigningError {
|
|
|
553
589
|
* plain `HavenError` branch already does for that code.
|
|
554
590
|
*/
|
|
555
591
|
next_action;
|
|
592
|
+
/**
|
|
593
|
+
* #3103 (epic #3105, decisions 1 and 3): the typed next step beside the
|
|
594
|
+
* action. A refusal Haven made (`SIGN_CONTEXT_REFUSED`, not expired) names
|
|
595
|
+
* the hosted status read with the payment id; a transport failure or a
|
|
596
|
+
* malformed body names no tool — the remedy is re-running the SAME quote
|
|
597
|
+
* tool with `include_signing_payload: true` — and an expired window names
|
|
598
|
+
* none either (which quote tool depends on the flow). Never null: a step
|
|
599
|
+
* with no tool carries `next_tool_omitted_reason`. Additive: the class is
|
|
600
|
+
* not exported from the package index — the published surface is the
|
|
601
|
+
* `ToolFailure` envelope `tools.ts` builds from these fields — and every
|
|
602
|
+
* constructor call site is in this file.
|
|
603
|
+
*/
|
|
604
|
+
next_tool;
|
|
605
|
+
next_tool_server;
|
|
606
|
+
next_tool_name;
|
|
607
|
+
next_tool_server_role;
|
|
608
|
+
next_arguments;
|
|
609
|
+
next_tool_omitted_reason;
|
|
556
610
|
retry_with_new_quote;
|
|
557
611
|
/** Present only for `SIGN_CONTEXT_REFUSED` (the backend's HTTP status). */
|
|
558
612
|
http_status;
|
|
559
613
|
/** Present only for `SIGN_CONTEXT_REFUSED`: the backend's own `error_code`. */
|
|
560
614
|
backend_error_code;
|
|
561
|
-
constructor(message, code, refusal) {
|
|
615
|
+
constructor(message, code, refusal, paymentId) {
|
|
562
616
|
super(message);
|
|
563
617
|
this.code = code;
|
|
564
618
|
this.name = "HavenSignContextError";
|
|
619
|
+
let step;
|
|
565
620
|
if (code === "SIGN_CONTEXT_REFUSED") {
|
|
566
621
|
this.http_status = refusal?.httpStatus;
|
|
567
622
|
this.backend_error_code = refusal?.errorCode;
|
|
568
623
|
if (refusal?.httpStatus === 410 || refusal?.errorCode === "expired") {
|
|
569
624
|
this.next_action = sdk.AgentPaymentNextAction.PaymentWindowExpired;
|
|
570
625
|
this.retry_with_new_quote = true;
|
|
626
|
+
step = signerRefusalStep({
|
|
627
|
+
nextAction: sdk.AgentPaymentNextAction.PaymentWindowExpired,
|
|
628
|
+
nextTool: null,
|
|
629
|
+
nextToolOmittedReason: "re-run the hosted quote tool you called with the same idempotency_key; which one depends on the flow"
|
|
630
|
+
});
|
|
571
631
|
} else {
|
|
572
632
|
this.next_action = sdk.AgentPaymentNextAction.StopAndTellUser;
|
|
633
|
+
step = signerRefusalStep({
|
|
634
|
+
nextAction: sdk.AgentPaymentNextAction.StopAndTellUser,
|
|
635
|
+
nextTool: "haven_get_payment_status",
|
|
636
|
+
nextArguments: { payment_id: paymentId }
|
|
637
|
+
});
|
|
573
638
|
}
|
|
574
639
|
} else {
|
|
575
640
|
this.fallback = "typed_data_b64";
|
|
576
641
|
this.next_action = sdk.AgentPaymentNextAction.StopAndTellUser;
|
|
642
|
+
step = signerRefusalStep({
|
|
643
|
+
nextAction: sdk.AgentPaymentNextAction.StopAndTellUser,
|
|
644
|
+
nextTool: null,
|
|
645
|
+
nextToolOmittedReason: "re-run the SAME hosted quote tool with the same idempotency_key and include_signing_payload: true, then pass its typed_data_b64 to this signer"
|
|
646
|
+
});
|
|
577
647
|
}
|
|
648
|
+
Object.assign(this, nextStepWireFields(step));
|
|
578
649
|
}
|
|
579
650
|
};
|
|
580
651
|
async function loadHavenIdentity(credentialsPath) {
|
|
@@ -606,7 +677,9 @@ async function fetchX402SignContext(identity, paymentId, fetchImpl = fetch, time
|
|
|
606
677
|
const timedOut = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
|
|
607
678
|
throw new HavenSignContextError(
|
|
608
679
|
timedOut ? `Haven did not answer the signing-context fetch for ${paymentId} within ${timeoutMs} ms. Retry, or pass typed_data_b64 from the quote result instead.` : `Could not reach Haven to fetch the signing context for ${paymentId}: ${err instanceof Error ? err.message : String(err)}. Retry, or pass typed_data_b64 from the quote result instead.`,
|
|
609
|
-
timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE"
|
|
680
|
+
timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE",
|
|
681
|
+
void 0,
|
|
682
|
+
paymentId
|
|
610
683
|
);
|
|
611
684
|
}
|
|
612
685
|
let body;
|
|
@@ -616,7 +689,9 @@ async function fetchX402SignContext(identity, paymentId, fetchImpl = fetch, time
|
|
|
616
689
|
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
617
690
|
throw new HavenSignContextError(
|
|
618
691
|
`Haven did not finish sending the signing context for ${paymentId} within ${timeoutMs} ms. Retry, or pass typed_data_b64 from the quote result instead.`,
|
|
619
|
-
"SIGN_CONTEXT_TIMEOUT"
|
|
692
|
+
"SIGN_CONTEXT_TIMEOUT",
|
|
693
|
+
void 0,
|
|
694
|
+
paymentId
|
|
620
695
|
);
|
|
621
696
|
}
|
|
622
697
|
body = {};
|
|
@@ -626,7 +701,8 @@ async function fetchX402SignContext(identity, paymentId, fetchImpl = fetch, time
|
|
|
626
701
|
throw new HavenSignContextError(
|
|
627
702
|
`Haven refused the signing-context fetch for ${paymentId}: ${detail}` + (response.status === 404 ? " \u2014 check the payment_id came from this agent\u2019s own quote." : response.status === 410 ? " Re-run the quote with the same idempotency key, then sign the fresh payment_id." : ""),
|
|
628
703
|
"SIGN_CONTEXT_REFUSED",
|
|
629
|
-
{ httpStatus: response.status, errorCode: typeof body.error_code === "string" ? body.error_code : void 0 }
|
|
704
|
+
{ httpStatus: response.status, errorCode: typeof body.error_code === "string" ? body.error_code : void 0 },
|
|
705
|
+
paymentId
|
|
630
706
|
);
|
|
631
707
|
}
|
|
632
708
|
const signData = body.sign_data;
|
|
@@ -634,7 +710,9 @@ async function fetchX402SignContext(identity, paymentId, fetchImpl = fetch, time
|
|
|
634
710
|
if (!signData || typeof signData.hash !== "string" || !signData.typed_data || typeof signData.typed_data !== "object" || !x402Expected) {
|
|
635
711
|
throw new HavenSignContextError(
|
|
636
712
|
"The Haven sign-context response is missing sign_data.typed_data or x402_expected \u2014 the backend may predate #1263. Pass typed_data_b64 from the quote result instead.",
|
|
637
|
-
"SIGN_CONTEXT_MALFORMED"
|
|
713
|
+
"SIGN_CONTEXT_MALFORMED",
|
|
714
|
+
void 0,
|
|
715
|
+
paymentId
|
|
638
716
|
);
|
|
639
717
|
}
|
|
640
718
|
const paymentRequired = body.payment_required;
|
|
@@ -758,6 +836,7 @@ var toolSchemas = {
|
|
|
758
836
|
// #1255: see haven_sign.typed_data_b64 — the copy-through-safe form.
|
|
759
837
|
typed_data_b64: v3.z.string().min(1).max(262144).optional()
|
|
760
838
|
}
|
|
839
|
+
// #3101: keys survive on the type (see the hosted server's contracts.ts).
|
|
761
840
|
};
|
|
762
841
|
var SIGN_DESCRIPTION = [
|
|
763
842
|
"Sign an unsigned Haven payment hash with the local delegate key. The delegate key never leaves",
|
|
@@ -985,7 +1064,7 @@ function createToolHandlers(signer, options = {}) {
|
|
|
985
1064
|
authorization: args.authorization,
|
|
986
1065
|
expectedAuth: args.expected_auth,
|
|
987
1066
|
// Cross-check `to` against the Safe in the local credential when present.
|
|
988
|
-
expectedSafe: options.audit?.
|
|
1067
|
+
expectedSafe: options.audit?.accountAddress
|
|
989
1068
|
});
|
|
990
1069
|
await auditSigning(
|
|
991
1070
|
"haven_sign_sweep_delegate",
|
|
@@ -1062,7 +1141,13 @@ function normalizeError(err) {
|
|
|
1062
1141
|
supported_versions: [...err.supportedVersions],
|
|
1063
1142
|
received_version: err.receivedVersion,
|
|
1064
1143
|
fallback: err.fallback,
|
|
1065
|
-
next_action: sdk.AgentPaymentNextAction.StopAndTellUser
|
|
1144
|
+
next_action: sdk.AgentPaymentNextAction.StopAndTellUser,
|
|
1145
|
+
// #3103: no tool can fix a version skew from inside the call.
|
|
1146
|
+
...nextStepWireFields(signerRefusalStep({
|
|
1147
|
+
nextAction: sdk.AgentPaymentNextAction.StopAndTellUser,
|
|
1148
|
+
nextTool: null,
|
|
1149
|
+
nextToolOmittedReason: "update @haven_ai/signer by re-running the connector, then repeat the same call"
|
|
1150
|
+
}))
|
|
1066
1151
|
};
|
|
1067
1152
|
}
|
|
1068
1153
|
if (err instanceof HavenSignContextError) {
|
|
@@ -1074,7 +1159,14 @@ function normalizeError(err) {
|
|
|
1074
1159
|
...err.fallback !== void 0 ? { fallback: err.fallback } : {},
|
|
1075
1160
|
...err.retry_with_new_quote ? { retry_with_new_quote: true } : {},
|
|
1076
1161
|
...err.http_status !== void 0 ? { http_status: err.http_status } : {},
|
|
1077
|
-
...err.backend_error_code !== void 0 ? { backend_error_code: err.backend_error_code } : {}
|
|
1162
|
+
...err.backend_error_code !== void 0 ? { backend_error_code: err.backend_error_code } : {},
|
|
1163
|
+
// #3103: the typed step the error decided beside its action.
|
|
1164
|
+
...err.next_tool ? { next_tool: err.next_tool } : {},
|
|
1165
|
+
...err.next_tool_server ? { next_tool_server: err.next_tool_server } : {},
|
|
1166
|
+
...err.next_tool_name ? { next_tool_name: err.next_tool_name } : {},
|
|
1167
|
+
...err.next_tool_server_role ? { next_tool_server_role: err.next_tool_server_role } : {},
|
|
1168
|
+
...err.next_arguments ? { next_arguments: err.next_arguments } : {},
|
|
1169
|
+
...err.next_tool_omitted_reason ? { next_tool_omitted_reason: err.next_tool_omitted_reason } : {}
|
|
1078
1170
|
};
|
|
1079
1171
|
}
|
|
1080
1172
|
if (err instanceof sdk.HavenSigningError) {
|
|
@@ -1093,7 +1185,13 @@ function normalizeError(err) {
|
|
|
1093
1185
|
...err.code === sdk.AgentPaymentFailureCode.PaymentWindowExpired ? {
|
|
1094
1186
|
next_action: sdk.AgentPaymentNextAction.PaymentWindowExpired,
|
|
1095
1187
|
retry_with_new_quote: true,
|
|
1096
|
-
suggested_tool: "haven_pay_mcp_tool"
|
|
1188
|
+
suggested_tool: "haven_pay_mcp_tool",
|
|
1189
|
+
// #3103: same omission as the hosted window-expired helper.
|
|
1190
|
+
...nextStepWireFields(signerRefusalStep({
|
|
1191
|
+
nextAction: sdk.AgentPaymentNextAction.PaymentWindowExpired,
|
|
1192
|
+
nextTool: null,
|
|
1193
|
+
nextToolOmittedReason: "re-run the hosted quote tool you called with the same idempotency_key; which one depends on the flow (suggested_tool names the MCP one)"
|
|
1194
|
+
}))
|
|
1097
1195
|
} : {}
|
|
1098
1196
|
};
|
|
1099
1197
|
}
|
|
@@ -1110,7 +1208,7 @@ var SIGNER_CONSENT_SURFACE_VERSION = 2;
|
|
|
1110
1208
|
function computeSignerConsentHash(input) {
|
|
1111
1209
|
const identity = [
|
|
1112
1210
|
input.delegateAddress.toLowerCase(),
|
|
1113
|
-
(input.
|
|
1211
|
+
(input.accountAddress ?? "").toLowerCase(),
|
|
1114
1212
|
input.agentId ?? "",
|
|
1115
1213
|
input.chainId ?? "",
|
|
1116
1214
|
input.network ?? ""
|
|
@@ -1129,7 +1227,7 @@ function renderSignerConsentBlock(input, hash) {
|
|
|
1129
1227
|
"",
|
|
1130
1228
|
`Delegate address: ${input.delegateAddress}`
|
|
1131
1229
|
];
|
|
1132
|
-
lines.push(`Haven wallet: ${input.
|
|
1230
|
+
lines.push(`Haven wallet: ${input.accountAddress ?? "not provided to this signer"}`);
|
|
1133
1231
|
if (input.agentId) lines.push(`Agent ID: ${input.agentId}`);
|
|
1134
1232
|
if (typeof input.chainId === "number") lines.push(`Chain ID: ${input.chainId}`);
|
|
1135
1233
|
if (input.network) lines.push(`Network: ${input.network}`);
|
|
@@ -1231,7 +1329,6 @@ async function loadSignerCredentials(path = process.env.HAVEN_CREDENTIALS) {
|
|
|
1231
1329
|
delegateKey: envKey,
|
|
1232
1330
|
agentId: stringField(process.env.HAVEN_AGENT_ID),
|
|
1233
1331
|
accountAddress,
|
|
1234
|
-
safeAddress: accountAddress,
|
|
1235
1332
|
chainId: chainIdField(process.env.HAVEN_CHAIN_ID, "HAVEN_CHAIN_ID"),
|
|
1236
1333
|
network: stringField(process.env.HAVEN_NETWORK),
|
|
1237
1334
|
x402BindingSigner: stringField(process.env.HAVEN_X402_BINDING_SIGNER)
|
|
@@ -1266,7 +1363,6 @@ async function loadFromFile(path) {
|
|
|
1266
1363
|
delegateKey,
|
|
1267
1364
|
agentId: stringField(raw.agent_id ?? raw.agentId),
|
|
1268
1365
|
accountAddress,
|
|
1269
|
-
safeAddress: accountAddress,
|
|
1270
1366
|
chainId: chainIdField(raw.chain_id ?? raw.chainId, "chain_id"),
|
|
1271
1367
|
network: stringField(raw.network),
|
|
1272
1368
|
x402BindingSigner: stringField(
|
|
@@ -1279,7 +1375,22 @@ function readAccountAddressField(raw) {
|
|
|
1279
1375
|
return stringField(raw.account_address ?? raw.safe_address ?? raw.safeAddress);
|
|
1280
1376
|
}
|
|
1281
1377
|
function readAccountAddressEnv(env) {
|
|
1282
|
-
|
|
1378
|
+
const current = stringField(env.HAVEN_ACCOUNT_ADDRESS);
|
|
1379
|
+
for (const name of ["HAVEN_WALLET_ADDRESS", "HAVEN_SAFE_ADDRESS"]) {
|
|
1380
|
+
const retired = stringField(env[name]);
|
|
1381
|
+
if (!retired) continue;
|
|
1382
|
+
if (!current) {
|
|
1383
|
+
throw new Error(
|
|
1384
|
+
`${name} is retired (#2906) \u2014 Haven accounts are addressed as accounts, not Safes. Set HAVEN_ACCOUNT_ADDRESS to the same value. Refusing rather than ignoring it, because an unset account address silently skips the sweep-destination check.`
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
if (retired.toLowerCase() !== current.toLowerCase()) {
|
|
1388
|
+
throw new Error(
|
|
1389
|
+
`${name} and HAVEN_ACCOUNT_ADDRESS were both set to different addresses. Remove the retired name, or make them match \u2014 picking one silently would hide the mismatch.`
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
return current;
|
|
1283
1394
|
}
|
|
1284
1395
|
function stringField(value) {
|
|
1285
1396
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
@@ -1322,7 +1433,7 @@ async function warnIfCredentialFilePermissive(path, log = (message) => process.s
|
|
|
1322
1433
|
|
|
1323
1434
|
// src/server.ts
|
|
1324
1435
|
var SIGNER_NAME = "@haven_ai/signer";
|
|
1325
|
-
var SIGNER_VERSION = "0.
|
|
1436
|
+
var SIGNER_VERSION = "0.4.0-alpha.0";
|
|
1326
1437
|
async function resolveSignerRuntime(options = {}) {
|
|
1327
1438
|
assertSupportedNodeVersion(options.nodeVersion);
|
|
1328
1439
|
if (options.delegateKey) {
|
|
@@ -1357,7 +1468,7 @@ function buildSignerMcpServer(signer, options = {}) {
|
|
|
1357
1468
|
audit: {
|
|
1358
1469
|
auditPath: options.auditPath ?? defaultSigningAuditPath(credentialsPath),
|
|
1359
1470
|
delegateAddress: signer.delegateAddress,
|
|
1360
|
-
|
|
1471
|
+
accountAddress: options.credentials?.accountAddress,
|
|
1361
1472
|
chainId: options.credentials?.chainId
|
|
1362
1473
|
},
|
|
1363
1474
|
// #1263: the payment_id signing path — the ONLY network call this server
|
|
@@ -1407,7 +1518,7 @@ async function runSignerConsentGate(signer, credentials, options) {
|
|
|
1407
1518
|
return ensureSignerConsent(
|
|
1408
1519
|
{
|
|
1409
1520
|
delegateAddress: signer.delegateAddress,
|
|
1410
|
-
|
|
1521
|
+
accountAddress: credentials?.accountAddress,
|
|
1411
1522
|
agentId: credentials?.agentId,
|
|
1412
1523
|
chainId: credentials?.chainId,
|
|
1413
1524
|
network: credentials?.network,
|