@haven_ai/signer 0.2.0-alpha.0 → 0.3.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/dist/index.d.cts CHANGED
@@ -282,18 +282,8 @@ declare function signerInstructions(): string;
282
282
  interface SignerCredentials {
283
283
  delegateKey: string;
284
284
  agentId?: string;
285
- /**
286
- * The Haven account (smart account) the agent spends from — #2908, the
287
- * account-vocabulary name. Same value as `safeAddress`.
288
- */
285
+ /** The Haven account (smart account) the agent spends from. */
289
286
  accountAddress?: string;
290
- /**
291
- * @deprecated #2908 — same value as {@link SignerCredentials.accountAddress}.
292
- * Removed from this shape in the release after the one carrying #2908
293
- * (#2914). The credential-FILE keys it was read from are a different
294
- * matter — see `readAccountAddressField`.
295
- */
296
- safeAddress?: string;
297
287
  chainId?: number;
298
288
  network?: string;
299
289
  x402BindingSigner?: string;
@@ -305,11 +295,11 @@ interface RawCredentialFile {
305
295
  delegateKey?: unknown;
306
296
  agent_id?: unknown;
307
297
  agentId?: unknown;
308
- /** #2908: what `@haven_ai/connect` writes from this release on. */
298
+ /** What `@haven_ai/connect` writes. */
309
299
  account_address?: unknown;
310
- /** Pre-#2908 spelling — read PERMANENTLY, see `readAccountAddressField`. */
300
+ /** Pre-#2908 spelling — read PERMANENTLY (a credential file never rewrites itself), see `readAccountAddressField`. */
311
301
  safe_address?: unknown;
312
- /** Pre-#2908 spelling — read PERMANENTLY, see `readAccountAddressField`. */
302
+ /** Pre-#2908 spelling — read PERMANENTLY (a credential file never rewrites itself), see `readAccountAddressField`. */
313
303
  safeAddress?: unknown;
314
304
  chain_id?: unknown;
315
305
  chainId?: unknown;
@@ -346,11 +336,11 @@ declare function loadSignerCredentials(path?: string | undefined): Promise<Signe
346
336
  */
347
337
  declare function readAccountAddressField(raw: Pick<RawCredentialFile, 'account_address' | 'safe_address' | 'safeAddress'>): string | undefined;
348
338
  /**
349
- * The account address off the process environment, new name first:
350
- * `HAVEN_ACCOUNT_ADDRESS` (the survivor, decided on #2906) then the two
351
- * names the dashboard handoff emitted before #2908 — `HAVEN_WALLET_ADDRESS`
352
- * and `HAVEN_SAFE_ADDRESS`. Unlike the file fallbacks these two ARE
353
- * window-scoped: they are dropped at #2914, one release after this one.
339
+ * The account address off the process environment: `HAVEN_ACCOUNT_ADDRESS`
340
+ * (the survivor, decided on #2906). The two names the dashboard handoff
341
+ * emitted before #2908 — `HAVEN_WALLET_ADDRESS` and `HAVEN_SAFE_ADDRESS` —
342
+ * were window-scoped (unlike the credential-FILE fallbacks) and are retired
343
+ * as of #2914.
354
344
  */
355
345
  declare function readAccountAddressEnv(env: NodeJS.ProcessEnv): string | undefined;
356
346
  /**
@@ -368,12 +358,20 @@ interface SigningAuditEntry {
368
358
  tool: SignerToolName;
369
359
  payload_hash: string;
370
360
  delegate_address: string;
361
+ /**
362
+ * Serialized key kept as `safe_address` deliberately (#2914 review): this
363
+ * is a persisted JSONL field, and an audit log written by an earlier
364
+ * release never rewrites itself — renaming the key here would fork the
365
+ * format mid-file. `SigningAuditContext.accountAddress` (the in-memory
366
+ * field this is built from) carries the account-vocabulary name; only the
367
+ * on-disk spelling stays put.
368
+ */
371
369
  safe_address?: string;
372
370
  chain_id?: number;
373
371
  }
374
372
  interface SigningAuditContext {
375
373
  delegateAddress: string;
376
- safeAddress?: string;
374
+ accountAddress?: string;
377
375
  chainId?: number;
378
376
  auditPath?: string;
379
377
  }
@@ -420,9 +418,17 @@ interface ToolFailure {
420
418
  /**
421
419
  * #1309: precise recovery guidance as DATA, not just prose inside `message`
422
420
  * — the same text the hosted quote's advisory `signer_compatibility.fallback`
423
- * carries when the refusal is an out-of-date signer.
421
+ * carries when the refusal is an out-of-date signer. #3001 reuses this same
422
+ * field for every sign-context refusal (`'typed_data_b64'`).
424
423
  */
425
424
  fallback?: string;
425
+ /**
426
+ * #3001: present on `SIGN_CONTEXT_REFUSED` — the HTTP status the backend
427
+ * answered the `/x402/:id/sign-context` fetch with (404, 410, …).
428
+ */
429
+ http_status?: number;
430
+ /** #3001: the backend's own `error_code` on `SIGN_CONTEXT_REFUSED` (`expired`, `already_executed`, `not_signable`, `sign_context_unavailable`). */
431
+ backend_error_code?: string;
426
432
  }
427
433
  type ToolPayload<T = unknown> = ToolSuccess<T> | ToolFailure;
428
434
  interface ToolHandlerOptions {
@@ -443,7 +449,7 @@ declare function createToolHandlers(signer: EdgeSigner, options?: ToolHandlerOpt
443
449
 
444
450
  interface SignerConsentInput {
445
451
  delegateAddress: string;
446
- safeAddress?: string;
452
+ accountAddress?: string;
447
453
  agentId?: string;
448
454
  chainId?: number;
449
455
  network?: string;
@@ -468,7 +474,7 @@ declare function renderSignerConsentBlock(input: SignerConsentInput, hash: strin
468
474
  declare function ensureSignerConsent(input: SignerConsentInput, options?: SignerConsentOptions): Promise<SignerConsentDecision>;
469
475
 
470
476
  declare const SIGNER_NAME = "@haven_ai/signer";
471
- declare const SIGNER_VERSION = "0.2.0-alpha.0";
477
+ declare const SIGNER_VERSION = "0.3.0-alpha.0";
472
478
  interface SignerOptions {
473
479
  /** Path to a Haven credential JSON file (delegate_key is read from it). */
474
480
  credentialsPath?: string;
package/dist/index.d.ts CHANGED
@@ -282,18 +282,8 @@ declare function signerInstructions(): string;
282
282
  interface SignerCredentials {
283
283
  delegateKey: string;
284
284
  agentId?: string;
285
- /**
286
- * The Haven account (smart account) the agent spends from — #2908, the
287
- * account-vocabulary name. Same value as `safeAddress`.
288
- */
285
+ /** The Haven account (smart account) the agent spends from. */
289
286
  accountAddress?: string;
290
- /**
291
- * @deprecated #2908 — same value as {@link SignerCredentials.accountAddress}.
292
- * Removed from this shape in the release after the one carrying #2908
293
- * (#2914). The credential-FILE keys it was read from are a different
294
- * matter — see `readAccountAddressField`.
295
- */
296
- safeAddress?: string;
297
287
  chainId?: number;
298
288
  network?: string;
299
289
  x402BindingSigner?: string;
@@ -305,11 +295,11 @@ interface RawCredentialFile {
305
295
  delegateKey?: unknown;
306
296
  agent_id?: unknown;
307
297
  agentId?: unknown;
308
- /** #2908: what `@haven_ai/connect` writes from this release on. */
298
+ /** What `@haven_ai/connect` writes. */
309
299
  account_address?: unknown;
310
- /** Pre-#2908 spelling — read PERMANENTLY, see `readAccountAddressField`. */
300
+ /** Pre-#2908 spelling — read PERMANENTLY (a credential file never rewrites itself), see `readAccountAddressField`. */
311
301
  safe_address?: unknown;
312
- /** Pre-#2908 spelling — read PERMANENTLY, see `readAccountAddressField`. */
302
+ /** Pre-#2908 spelling — read PERMANENTLY (a credential file never rewrites itself), see `readAccountAddressField`. */
313
303
  safeAddress?: unknown;
314
304
  chain_id?: unknown;
315
305
  chainId?: unknown;
@@ -346,11 +336,11 @@ declare function loadSignerCredentials(path?: string | undefined): Promise<Signe
346
336
  */
347
337
  declare function readAccountAddressField(raw: Pick<RawCredentialFile, 'account_address' | 'safe_address' | 'safeAddress'>): string | undefined;
348
338
  /**
349
- * The account address off the process environment, new name first:
350
- * `HAVEN_ACCOUNT_ADDRESS` (the survivor, decided on #2906) then the two
351
- * names the dashboard handoff emitted before #2908 — `HAVEN_WALLET_ADDRESS`
352
- * and `HAVEN_SAFE_ADDRESS`. Unlike the file fallbacks these two ARE
353
- * window-scoped: they are dropped at #2914, one release after this one.
339
+ * The account address off the process environment: `HAVEN_ACCOUNT_ADDRESS`
340
+ * (the survivor, decided on #2906). The two names the dashboard handoff
341
+ * emitted before #2908 — `HAVEN_WALLET_ADDRESS` and `HAVEN_SAFE_ADDRESS` —
342
+ * were window-scoped (unlike the credential-FILE fallbacks) and are retired
343
+ * as of #2914.
354
344
  */
355
345
  declare function readAccountAddressEnv(env: NodeJS.ProcessEnv): string | undefined;
356
346
  /**
@@ -368,12 +358,20 @@ interface SigningAuditEntry {
368
358
  tool: SignerToolName;
369
359
  payload_hash: string;
370
360
  delegate_address: string;
361
+ /**
362
+ * Serialized key kept as `safe_address` deliberately (#2914 review): this
363
+ * is a persisted JSONL field, and an audit log written by an earlier
364
+ * release never rewrites itself — renaming the key here would fork the
365
+ * format mid-file. `SigningAuditContext.accountAddress` (the in-memory
366
+ * field this is built from) carries the account-vocabulary name; only the
367
+ * on-disk spelling stays put.
368
+ */
371
369
  safe_address?: string;
372
370
  chain_id?: number;
373
371
  }
374
372
  interface SigningAuditContext {
375
373
  delegateAddress: string;
376
- safeAddress?: string;
374
+ accountAddress?: string;
377
375
  chainId?: number;
378
376
  auditPath?: string;
379
377
  }
@@ -420,9 +418,17 @@ interface ToolFailure {
420
418
  /**
421
419
  * #1309: precise recovery guidance as DATA, not just prose inside `message`
422
420
  * — the same text the hosted quote's advisory `signer_compatibility.fallback`
423
- * carries when the refusal is an out-of-date signer.
421
+ * carries when the refusal is an out-of-date signer. #3001 reuses this same
422
+ * field for every sign-context refusal (`'typed_data_b64'`).
424
423
  */
425
424
  fallback?: string;
425
+ /**
426
+ * #3001: present on `SIGN_CONTEXT_REFUSED` — the HTTP status the backend
427
+ * answered the `/x402/:id/sign-context` fetch with (404, 410, …).
428
+ */
429
+ http_status?: number;
430
+ /** #3001: the backend's own `error_code` on `SIGN_CONTEXT_REFUSED` (`expired`, `already_executed`, `not_signable`, `sign_context_unavailable`). */
431
+ backend_error_code?: string;
426
432
  }
427
433
  type ToolPayload<T = unknown> = ToolSuccess<T> | ToolFailure;
428
434
  interface ToolHandlerOptions {
@@ -443,7 +449,7 @@ declare function createToolHandlers(signer: EdgeSigner, options?: ToolHandlerOpt
443
449
 
444
450
  interface SignerConsentInput {
445
451
  delegateAddress: string;
446
- safeAddress?: string;
452
+ accountAddress?: string;
447
453
  agentId?: string;
448
454
  chainId?: number;
449
455
  network?: string;
@@ -468,7 +474,7 @@ declare function renderSignerConsentBlock(input: SignerConsentInput, hash: strin
468
474
  declare function ensureSignerConsent(input: SignerConsentInput, options?: SignerConsentOptions): Promise<SignerConsentDecision>;
469
475
 
470
476
  declare const SIGNER_NAME = "@haven_ai/signer";
471
- declare const SIGNER_VERSION = "0.2.0-alpha.0";
477
+ declare const SIGNER_VERSION = "0.3.0-alpha.0";
472
478
  interface SignerOptions {
473
479
  /** Path to a Haven credential JSON file (delegate_key is read from it). */
474
480
  credentialsPath?: string;
package/dist/index.js CHANGED
@@ -506,7 +506,6 @@ async function loadSignerCredentials(path = process.env.HAVEN_CREDENTIALS) {
506
506
  delegateKey: envKey,
507
507
  agentId: stringField(process.env.HAVEN_AGENT_ID),
508
508
  accountAddress,
509
- safeAddress: accountAddress,
510
509
  chainId: chainIdField(process.env.HAVEN_CHAIN_ID, "HAVEN_CHAIN_ID"),
511
510
  network: stringField(process.env.HAVEN_NETWORK),
512
511
  x402BindingSigner: stringField(process.env.HAVEN_X402_BINDING_SIGNER)
@@ -541,7 +540,6 @@ async function loadFromFile(path) {
541
540
  delegateKey,
542
541
  agentId: stringField(raw.agent_id ?? raw.agentId),
543
542
  accountAddress,
544
- safeAddress: accountAddress,
545
543
  chainId: chainIdField(raw.chain_id ?? raw.chainId, "chain_id"),
546
544
  network: stringField(raw.network),
547
545
  x402BindingSigner: stringField(
@@ -554,7 +552,22 @@ function readAccountAddressField(raw) {
554
552
  return stringField(raw.account_address ?? raw.safe_address ?? raw.safeAddress);
555
553
  }
556
554
  function readAccountAddressEnv(env) {
557
- return stringField(env.HAVEN_ACCOUNT_ADDRESS ?? env.HAVEN_WALLET_ADDRESS ?? env.HAVEN_SAFE_ADDRESS);
555
+ const current = stringField(env.HAVEN_ACCOUNT_ADDRESS);
556
+ for (const name of ["HAVEN_WALLET_ADDRESS", "HAVEN_SAFE_ADDRESS"]) {
557
+ const retired = stringField(env[name]);
558
+ if (!retired) continue;
559
+ if (!current) {
560
+ throw new Error(
561
+ `${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.`
562
+ );
563
+ }
564
+ if (retired.toLowerCase() !== current.toLowerCase()) {
565
+ throw new Error(
566
+ `${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.`
567
+ );
568
+ }
569
+ }
570
+ return current;
558
571
  }
559
572
  function stringField(value) {
560
573
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -611,7 +624,7 @@ function createSigningAuditEntry(tool, payloadHash, context, now = /* @__PURE__
611
624
  payload_hash: payloadHash,
612
625
  delegate_address: context.delegateAddress
613
626
  };
614
- if (context.safeAddress) entry.safe_address = context.safeAddress;
627
+ if (context.accountAddress) entry.safe_address = context.accountAddress;
615
628
  if (typeof context.chainId === "number") entry.chain_id = context.chainId;
616
629
  return entry;
617
630
  }
@@ -627,6 +640,49 @@ function stableStringify(value) {
627
640
  const object = value;
628
641
  return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
629
642
  }
643
+ var HavenSignContextError = class extends HavenSigningError {
644
+ /**
645
+ * #3001 / #3010 review: the recovery path, when signing OTHER bytes is
646
+ * actually a remedy — a transport failure (timeout, unreachable) or a
647
+ * body this signer could not read. `typed_data_b64` is NOT in the default
648
+ * quote result since #1272: obtain it by re-running the SAME quote tool
649
+ * with the SAME idempotency_key plus `include_signing_payload: true`.
650
+ * Absent on a backend REFUSAL: an expired, executed or unsignable intent
651
+ * cannot be rescued by re-signing its bytes.
652
+ */
653
+ fallback;
654
+ /**
655
+ * #3001: `AgentPaymentNextAction` values the signer already emits — the
656
+ * version-mismatch refusal's `stop_and_tell_user` for the classes where
657
+ * retrying the same call cannot help, and `payment_window_expired` (with
658
+ * `retry_with_new_quote`) for the backend's 410 `expired`, exactly as the
659
+ * plain `HavenError` branch already does for that code.
660
+ */
661
+ next_action;
662
+ retry_with_new_quote;
663
+ /** Present only for `SIGN_CONTEXT_REFUSED` (the backend's HTTP status). */
664
+ http_status;
665
+ /** Present only for `SIGN_CONTEXT_REFUSED`: the backend's own `error_code`. */
666
+ backend_error_code;
667
+ constructor(message, code, refusal) {
668
+ super(message);
669
+ this.code = code;
670
+ this.name = "HavenSignContextError";
671
+ if (code === "SIGN_CONTEXT_REFUSED") {
672
+ this.http_status = refusal?.httpStatus;
673
+ this.backend_error_code = refusal?.errorCode;
674
+ if (refusal?.httpStatus === 410 || refusal?.errorCode === "expired") {
675
+ this.next_action = AgentPaymentNextAction.PaymentWindowExpired;
676
+ this.retry_with_new_quote = true;
677
+ } else {
678
+ this.next_action = AgentPaymentNextAction.StopAndTellUser;
679
+ }
680
+ } else {
681
+ this.fallback = "typed_data_b64";
682
+ this.next_action = AgentPaymentNextAction.StopAndTellUser;
683
+ }
684
+ }
685
+ };
630
686
  async function loadHavenIdentity(credentialsPath) {
631
687
  if (!credentialsPath) return null;
632
688
  try {
@@ -641,30 +697,50 @@ async function loadHavenIdentity(credentialsPath) {
641
697
  return null;
642
698
  }
643
699
  }
644
- async function fetchX402SignContext(identity, paymentId, fetchImpl = fetch) {
700
+ var SIGN_CONTEXT_TIMEOUT_MS = 15e3;
701
+ async function fetchX402SignContext(identity, paymentId, fetchImpl = fetch, timeoutMs = SIGN_CONTEXT_TIMEOUT_MS) {
645
702
  let response;
646
703
  try {
647
704
  response = await fetchImpl(
648
705
  `${identity.apiUrl}/x402/${encodeURIComponent(paymentId)}/sign-context`,
649
- { headers: { Authorization: `Bearer ${identity.apiKey}` } }
706
+ {
707
+ headers: { Authorization: `Bearer ${identity.apiKey}` },
708
+ signal: AbortSignal.timeout(timeoutMs)
709
+ }
650
710
  );
651
711
  } catch (err) {
652
- throw new HavenSigningError(
653
- `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.`
712
+ const timedOut = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
713
+ throw new HavenSignContextError(
714
+ 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.`,
715
+ timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE"
654
716
  );
655
717
  }
656
- const body = await response.json().catch(() => ({}));
718
+ let body;
719
+ try {
720
+ body = await response.json();
721
+ } catch (err) {
722
+ if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
723
+ throw new HavenSignContextError(
724
+ `Haven did not finish sending the signing context for ${paymentId} within ${timeoutMs} ms. Retry, or pass typed_data_b64 from the quote result instead.`,
725
+ "SIGN_CONTEXT_TIMEOUT"
726
+ );
727
+ }
728
+ body = {};
729
+ }
657
730
  if (!response.ok) {
658
731
  const detail = typeof body.error === "string" ? body.error : `HTTP ${response.status}`;
659
- throw new HavenSigningError(
660
- `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." : "")
732
+ throw new HavenSignContextError(
733
+ `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." : ""),
734
+ "SIGN_CONTEXT_REFUSED",
735
+ { httpStatus: response.status, errorCode: typeof body.error_code === "string" ? body.error_code : void 0 }
661
736
  );
662
737
  }
663
738
  const signData = body.sign_data;
664
739
  const x402Expected = body.x402_expected;
665
740
  if (!signData || typeof signData.hash !== "string" || !signData.typed_data || typeof signData.typed_data !== "object" || !x402Expected) {
666
- throw new HavenSigningError(
667
- "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."
741
+ throw new HavenSignContextError(
742
+ "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.",
743
+ "SIGN_CONTEXT_MALFORMED"
668
744
  );
669
745
  }
670
746
  const paymentRequired = body.payment_required;
@@ -1015,7 +1091,7 @@ function createToolHandlers(signer, options = {}) {
1015
1091
  authorization: args.authorization,
1016
1092
  expectedAuth: args.expected_auth,
1017
1093
  // Cross-check `to` against the Safe in the local credential when present.
1018
- expectedSafe: options.audit?.safeAddress
1094
+ expectedSafe: options.audit?.accountAddress
1019
1095
  });
1020
1096
  await auditSigning(
1021
1097
  "haven_sign_sweep_delegate",
@@ -1095,6 +1171,18 @@ function normalizeError(err) {
1095
1171
  next_action: AgentPaymentNextAction.StopAndTellUser
1096
1172
  };
1097
1173
  }
1174
+ if (err instanceof HavenSignContextError) {
1175
+ return {
1176
+ success: false,
1177
+ code: err.code,
1178
+ message: err.message,
1179
+ next_action: err.next_action,
1180
+ ...err.fallback !== void 0 ? { fallback: err.fallback } : {},
1181
+ ...err.retry_with_new_quote ? { retry_with_new_quote: true } : {},
1182
+ ...err.http_status !== void 0 ? { http_status: err.http_status } : {},
1183
+ ...err.backend_error_code !== void 0 ? { backend_error_code: err.backend_error_code } : {}
1184
+ };
1185
+ }
1098
1186
  if (err instanceof HavenSigningError) {
1099
1187
  return { success: false, code: err.code, message: err.message };
1100
1188
  }
@@ -1128,7 +1216,7 @@ var SIGNER_CONSENT_SURFACE_VERSION = 2;
1128
1216
  function computeSignerConsentHash(input) {
1129
1217
  const identity = [
1130
1218
  input.delegateAddress.toLowerCase(),
1131
- (input.safeAddress ?? "").toLowerCase(),
1219
+ (input.accountAddress ?? "").toLowerCase(),
1132
1220
  input.agentId ?? "",
1133
1221
  input.chainId ?? "",
1134
1222
  input.network ?? ""
@@ -1147,7 +1235,7 @@ function renderSignerConsentBlock(input, hash) {
1147
1235
  "",
1148
1236
  `Delegate address: ${input.delegateAddress}`
1149
1237
  ];
1150
- lines.push(`Haven wallet: ${input.safeAddress ?? "not provided to this signer"}`);
1238
+ lines.push(`Haven wallet: ${input.accountAddress ?? "not provided to this signer"}`);
1151
1239
  if (input.agentId) lines.push(`Agent ID: ${input.agentId}`);
1152
1240
  if (typeof input.chainId === "number") lines.push(`Chain ID: ${input.chainId}`);
1153
1241
  if (input.network) lines.push(`Network: ${input.network}`);
@@ -1241,7 +1329,7 @@ async function writeAckFile(path, hash) {
1241
1329
  );
1242
1330
  }
1243
1331
  var SIGNER_NAME = "@haven_ai/signer";
1244
- var SIGNER_VERSION = "0.2.0-alpha.0";
1332
+ var SIGNER_VERSION = "0.3.0-alpha.0";
1245
1333
  async function resolveEdgeSigner(options = {}) {
1246
1334
  const { signer } = await resolveSignerRuntime(options);
1247
1335
  return signer;
@@ -1280,7 +1368,7 @@ function buildSignerMcpServer(signer, options = {}) {
1280
1368
  audit: {
1281
1369
  auditPath: options.auditPath ?? defaultSigningAuditPath(credentialsPath),
1282
1370
  delegateAddress: signer.delegateAddress,
1283
- safeAddress: options.credentials?.accountAddress ?? options.credentials?.safeAddress,
1371
+ accountAddress: options.credentials?.accountAddress,
1284
1372
  chainId: options.credentials?.chainId
1285
1373
  },
1286
1374
  // #1263: the payment_id signing path — the ONLY network call this server
@@ -1330,7 +1418,7 @@ async function runSignerConsentGate(signer, credentials, options) {
1330
1418
  return ensureSignerConsent(
1331
1419
  {
1332
1420
  delegateAddress: signer.delegateAddress,
1333
- safeAddress: credentials?.accountAddress ?? credentials?.safeAddress,
1421
+ accountAddress: credentials?.accountAddress,
1334
1422
  agentId: credentials?.agentId,
1335
1423
  chainId: credentials?.chainId,
1336
1424
  network: credentials?.network,