@haven_ai/signer 0.1.13-alpha.0 → 0.1.15-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/cli.cjs +220 -24
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +222 -26
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +220 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -3
- package/dist/index.d.ts +28 -3
- package/dist/index.js +222 -26
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -46,6 +46,22 @@ function stableStringify(value) {
|
|
|
46
46
|
const object = value;
|
|
47
47
|
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
48
48
|
}
|
|
49
|
+
var sweepAuthorizationSchema = v3.z.object({
|
|
50
|
+
from: v3.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "from must be a 0x address"),
|
|
51
|
+
to: v3.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "to must be a 0x address"),
|
|
52
|
+
value: v3.z.string().regex(/^[0-9]+$/, "value must be a decimal atomic amount"),
|
|
53
|
+
validAfter: v3.z.string().regex(/^[0-9]+$/, "validAfter must be a decimal unix time"),
|
|
54
|
+
validBefore: v3.z.string().regex(/^[0-9]+$/, "validBefore must be a decimal unix time"),
|
|
55
|
+
nonce: v3.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "nonce must be a 0x-prefixed 32-byte hex string"),
|
|
56
|
+
token: v3.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "token must be a 0x address"),
|
|
57
|
+
chainId: v3.z.number().int().positive()
|
|
58
|
+
});
|
|
59
|
+
var sweepExpectedAuthSchema = v3.z.object({
|
|
60
|
+
version: v3.z.literal(1),
|
|
61
|
+
message: v3.z.string().min(1),
|
|
62
|
+
signature: v3.z.string().regex(/^0x[0-9a-fA-F]+$/, "signature must be a 0x-prefixed hex string"),
|
|
63
|
+
signer: v3.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "signer must be a 0x address")
|
|
64
|
+
});
|
|
49
65
|
var x402ExpectedSchema = v3.z.object({
|
|
50
66
|
payment_id: v3.z.string().min(1),
|
|
51
67
|
payload_hash: v3.z.string().regex(/^0x[0-9a-fA-F]+$/, "payload_hash must be a 0x-prefixed hex string"),
|
|
@@ -54,6 +70,7 @@ var x402ExpectedSchema = v3.z.object({
|
|
|
54
70
|
amount: v3.z.string().min(1),
|
|
55
71
|
asset: v3.z.string().min(1),
|
|
56
72
|
network: v3.z.string().min(1),
|
|
73
|
+
expires_at: v3.z.string().min(1).optional(),
|
|
57
74
|
auth: v3.z.object({
|
|
58
75
|
version: v3.z.literal(1),
|
|
59
76
|
message: v3.z.string().min(1),
|
|
@@ -62,57 +79,102 @@ var x402ExpectedSchema = v3.z.object({
|
|
|
62
79
|
})
|
|
63
80
|
});
|
|
64
81
|
var toolSchemas = {
|
|
82
|
+
haven_sign_sweep_delegate: {
|
|
83
|
+
// The authorization fields prepared by Haven's POST /sweep/prepare. Passed
|
|
84
|
+
// through verbatim from the hosted haven_sweep_delegate tool — the signer
|
|
85
|
+
// re-derives the binding message from these exact values.
|
|
86
|
+
authorization: sweepAuthorizationSchema,
|
|
87
|
+
// Haven's signature over the authorization context (the binding).
|
|
88
|
+
expected_auth: sweepExpectedAuthSchema
|
|
89
|
+
},
|
|
65
90
|
haven_sign: {
|
|
66
|
-
// The unsigned hash from haven_pay /
|
|
91
|
+
// The unsigned hash from haven_pay / haven_pay_x402_quote (payload_hash).
|
|
67
92
|
payload_hash: v3.z.string().regex(/^0x[0-9a-fA-F]+$/, "payload_hash must be a 0x-prefixed hex string"),
|
|
68
|
-
// Pass x402.expected from hosted
|
|
93
|
+
// Pass x402.expected from hosted haven_pay_x402_quote when this hash funds
|
|
69
94
|
// a standard x402 merchant retry. The signer records it locally and returns
|
|
70
95
|
// an opaque x402_binding for the later header-signing step.
|
|
71
96
|
x402_expected: x402ExpectedSchema.optional()
|
|
72
97
|
},
|
|
73
98
|
haven_x402_sign_header: {
|
|
74
|
-
// The parsed HTTP 402 PaymentRequired from the merchant.
|
|
75
|
-
|
|
99
|
+
// The parsed HTTP 402 PaymentRequired from the merchant. Typed as an object
|
|
100
|
+
// (not z.unknown(), which becomes empty JSON Schema `{}`) so MCP clients
|
|
101
|
+
// embed it as JSON rather than serialising the object to a string.
|
|
102
|
+
payment_required: v3.z.record(v3.z.string(), v3.z.unknown()),
|
|
76
103
|
// Opaque binding returned by haven_sign when x402_expected was supplied.
|
|
77
104
|
x402_binding: v3.z.string().min(1)
|
|
105
|
+
},
|
|
106
|
+
haven_sign_x402: {
|
|
107
|
+
// One-shot x402 signing: funding hash + merchant header in one local call.
|
|
108
|
+
payload_hash: v3.z.string().regex(/^0x[0-9a-fA-F]+$/, "payload_hash must be a 0x-prefixed hex string"),
|
|
109
|
+
x402_expected: x402ExpectedSchema,
|
|
110
|
+
payment_required: v3.z.record(v3.z.string(), v3.z.unknown())
|
|
78
111
|
}
|
|
79
112
|
};
|
|
80
113
|
var SIGN_DESCRIPTION = [
|
|
81
114
|
"Sign an unsigned Haven payment hash with the local delegate key. The delegate key never leaves",
|
|
82
115
|
"this process. Pass the payload_hash returned by haven_pay or haven_pay_x402_quote.",
|
|
83
116
|
"For x402, also pass x402_expected from haven_pay_x402_quote; the signer records it locally",
|
|
84
|
-
"and returns { signature, x402_binding }.
|
|
85
|
-
"
|
|
86
|
-
"
|
|
117
|
+
"and returns { signature, x402_binding }. x402_expected includes expires_at; sign before that",
|
|
118
|
+
"window closes. Next: call mcp__haven__haven_submit with signature, then pass x402_binding",
|
|
119
|
+
"to mcp__haven-signer__haven_x402_sign_header. For plain SafeTransfer payments, just pass payload_hash and",
|
|
120
|
+
"relay the returned signature via mcp__haven__haven_submit."
|
|
87
121
|
].join(" ");
|
|
88
122
|
var X402_SIGN_HEADER_DESCRIPTION = [
|
|
89
123
|
"Build and sign the EIP-3009 X-PAYMENT header for the merchant leg of an x402 payment.",
|
|
90
124
|
"The delegate key stays local \u2014 only the signed header crosses any boundary.",
|
|
91
125
|
"Pass the payment_required from the original merchant 402 response and the x402_binding",
|
|
92
126
|
"returned by haven_sign. The signer validates the merchant, amount, resource, asset, and",
|
|
93
|
-
"network against the recorded funding context before signing,
|
|
127
|
+
"network against the recorded funding context before signing, checks expires_at when present,",
|
|
128
|
+
"and rejects mismatches or expired payment windows.",
|
|
94
129
|
"Returns { payment_header, accepted }. Set X-PAYMENT: <payment_header> on your retry to the",
|
|
95
130
|
"merchant. Only call after haven_submit has confirmed the funding step (nextAction=none or",
|
|
96
|
-
"the funding tx has a confirmed status)."
|
|
131
|
+
"the funding tx has a confirmed status). Next for paid MCP tools: call mcp__haven__haven_complete_mcp_tool."
|
|
132
|
+
].join(" ");
|
|
133
|
+
var SIGN_X402_DESCRIPTION = [
|
|
134
|
+
"One-shot x402 signing for the fast 3-call flow: sign the funding hash AND build the EIP-3009",
|
|
135
|
+
"X-PAYMENT header in a single local call (equivalent to haven_sign followed by",
|
|
136
|
+
"haven_x402_sign_header). The delegate key never leaves this process. From the haven_pay_mcp_tool",
|
|
137
|
+
"result pass payload_hash, x402_expected (the nested x402.expected object, not a top-level field),",
|
|
138
|
+
"and payment_required (verbatim). Returns",
|
|
139
|
+
"{ signature, x402_binding, payment_header, accepted }; hand signature + payment_header to",
|
|
140
|
+
"mcp__haven__haven_settle_mcp_tool to fund and settle in one hosted call. The header is built now (before",
|
|
141
|
+
"funding confirms), so its short validity window starts here \u2014 call mcp__haven__haven_settle_mcp_tool promptly,",
|
|
142
|
+
"and re-run mcp__haven__haven_pay_mcp_tool with the same idempotency_key if a tool returns PAYMENT_WINDOW_EXPIRED.",
|
|
143
|
+
"Next: call mcp__haven__haven_settle_mcp_tool."
|
|
144
|
+
].join(" ");
|
|
145
|
+
var SIGN_SWEEP_DELEGATE_DESCRIPTION = [
|
|
146
|
+
"Sign a Haven-prepared gasless USDC sweep that recovers stranded funds from the delegate",
|
|
147
|
+
"wallet back to your Haven wallet. The delegate key never leaves this process and this tool",
|
|
148
|
+
"never broadcasts \u2014 it returns only an EIP-3009 signature that Haven's relayer submits and",
|
|
149
|
+
"pays gas for. Pass the authorization and expected_auth returned by the hosted",
|
|
150
|
+
"haven_sweep_delegate tool. The signer verifies Haven authored the authorization and that it",
|
|
151
|
+
"pays out to your own Safe before signing, then returns { signature } to hand back to",
|
|
152
|
+
"mcp__haven__haven_sweep_delegate to complete recovery."
|
|
97
153
|
].join(" ");
|
|
98
154
|
var toolDescriptions = {
|
|
99
155
|
haven_sign: SIGN_DESCRIPTION,
|
|
100
|
-
haven_x402_sign_header: X402_SIGN_HEADER_DESCRIPTION
|
|
156
|
+
haven_x402_sign_header: X402_SIGN_HEADER_DESCRIPTION,
|
|
157
|
+
haven_sign_x402: SIGN_X402_DESCRIPTION,
|
|
158
|
+
haven_sign_sweep_delegate: SIGN_SWEEP_DELEGATE_DESCRIPTION
|
|
101
159
|
};
|
|
160
|
+
function toExpectedX402(raw) {
|
|
161
|
+
return {
|
|
162
|
+
paymentId: raw.payment_id,
|
|
163
|
+
payloadHash: raw.payload_hash,
|
|
164
|
+
resourceUrl: raw.resource_url,
|
|
165
|
+
merchantTo: raw.merchant_to,
|
|
166
|
+
amount: raw.amount,
|
|
167
|
+
asset: raw.asset,
|
|
168
|
+
network: raw.network,
|
|
169
|
+
expiresAt: raw.expires_at,
|
|
170
|
+
auth: raw.auth
|
|
171
|
+
};
|
|
172
|
+
}
|
|
102
173
|
function createToolHandlers(signer, options = {}) {
|
|
103
174
|
return {
|
|
104
175
|
haven_sign: async (input) => runTool(async () => {
|
|
105
176
|
const args = parse("haven_sign", input);
|
|
106
|
-
const x402Expected = args.x402_expected ?
|
|
107
|
-
paymentId: args.x402_expected.payment_id,
|
|
108
|
-
payloadHash: args.x402_expected.payload_hash,
|
|
109
|
-
resourceUrl: args.x402_expected.resource_url,
|
|
110
|
-
merchantTo: args.x402_expected.merchant_to,
|
|
111
|
-
amount: args.x402_expected.amount,
|
|
112
|
-
asset: args.x402_expected.asset,
|
|
113
|
-
network: args.x402_expected.network,
|
|
114
|
-
auth: args.x402_expected.auth
|
|
115
|
-
} : null;
|
|
177
|
+
const x402Expected = args.x402_expected ? toExpectedX402(args.x402_expected) : null;
|
|
116
178
|
const result = x402Expected ? signer.signX402FundingHash(args.payload_hash, x402Expected) : null;
|
|
117
179
|
if (!result) {
|
|
118
180
|
const signature = signer.signPaymentHash(args.payload_hash);
|
|
@@ -123,7 +185,7 @@ function createToolHandlers(signer, options = {}) {
|
|
|
123
185
|
return { signature: result.signature, x402_binding: result.x402Binding };
|
|
124
186
|
}),
|
|
125
187
|
haven_x402_sign_header: async (input) => runTool(async () => {
|
|
126
|
-
const args = parse("haven_x402_sign_header", input);
|
|
188
|
+
const args = parse("haven_x402_sign_header", coercePaymentRequired(input));
|
|
127
189
|
const result = await signer.buildX402PaymentHeader(
|
|
128
190
|
args.payment_required,
|
|
129
191
|
args.x402_binding
|
|
@@ -133,6 +195,36 @@ function createToolHandlers(signer, options = {}) {
|
|
|
133
195
|
hashPayloadForAudit(args.payment_required)
|
|
134
196
|
);
|
|
135
197
|
return { payment_header: result.paymentHeader, accepted: result.accepted };
|
|
198
|
+
}),
|
|
199
|
+
haven_sign_x402: async (input) => runTool(async () => {
|
|
200
|
+
const args = parse("haven_sign_x402", coercePaymentRequired(input));
|
|
201
|
+
const funding = signer.signX402FundingHash(args.payload_hash, toExpectedX402(args.x402_expected));
|
|
202
|
+
const header = await signer.buildX402PaymentHeader(
|
|
203
|
+
args.payment_required,
|
|
204
|
+
funding.x402Binding
|
|
205
|
+
);
|
|
206
|
+
await auditSigning("haven_sign_x402", args.payload_hash);
|
|
207
|
+
await auditSigning("haven_sign_x402", hashPayloadForAudit(args.payment_required));
|
|
208
|
+
return {
|
|
209
|
+
signature: funding.signature,
|
|
210
|
+
x402_binding: funding.x402Binding,
|
|
211
|
+
payment_header: header.paymentHeader,
|
|
212
|
+
accepted: header.accepted
|
|
213
|
+
};
|
|
214
|
+
}),
|
|
215
|
+
haven_sign_sweep_delegate: async (input) => runTool(async () => {
|
|
216
|
+
const args = parse("haven_sign_sweep_delegate", input);
|
|
217
|
+
const result = await signer.signSweepAuthorization({
|
|
218
|
+
authorization: args.authorization,
|
|
219
|
+
expectedAuth: args.expected_auth,
|
|
220
|
+
// Cross-check `to` against the Safe in the local credential when present.
|
|
221
|
+
expectedSafe: options.audit?.safeAddress
|
|
222
|
+
});
|
|
223
|
+
await auditSigning(
|
|
224
|
+
"haven_sign_sweep_delegate",
|
|
225
|
+
hashPayloadForAudit(args.authorization)
|
|
226
|
+
);
|
|
227
|
+
return { signature: result.signature };
|
|
136
228
|
})
|
|
137
229
|
};
|
|
138
230
|
async function auditSigning(tool, payloadHash) {
|
|
@@ -150,6 +242,16 @@ function createToolHandlers(signer, options = {}) {
|
|
|
150
242
|
function parse(name, input) {
|
|
151
243
|
return v3.z.object(toolSchemas[name]).parse(input ?? {});
|
|
152
244
|
}
|
|
245
|
+
function coercePaymentRequired(input) {
|
|
246
|
+
if (!input || typeof input !== "object") return input;
|
|
247
|
+
const record = input;
|
|
248
|
+
if (typeof record.payment_required !== "string") return input;
|
|
249
|
+
try {
|
|
250
|
+
return { ...record, payment_required: JSON.parse(record.payment_required) };
|
|
251
|
+
} catch {
|
|
252
|
+
return input;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
153
255
|
async function runTool(fn) {
|
|
154
256
|
try {
|
|
155
257
|
return { success: true, data: await fn() };
|
|
@@ -173,7 +275,18 @@ function normalizeError(err) {
|
|
|
173
275
|
return { success: false, code: err.code, message: err.message, statusCode: err.statusCode };
|
|
174
276
|
}
|
|
175
277
|
if (err instanceof sdk.HavenError) {
|
|
176
|
-
return {
|
|
278
|
+
return {
|
|
279
|
+
success: false,
|
|
280
|
+
code: err.code,
|
|
281
|
+
message: err.message,
|
|
282
|
+
statusCode: err.statusCode,
|
|
283
|
+
paymentId: err.paymentId,
|
|
284
|
+
...err.code === sdk.AgentPaymentFailureCode.PaymentWindowExpired ? {
|
|
285
|
+
next_action: sdk.AgentPaymentNextAction.PaymentWindowExpired,
|
|
286
|
+
retry_with_new_quote: true,
|
|
287
|
+
suggested_tool: "haven_pay_mcp_tool"
|
|
288
|
+
} : {}
|
|
289
|
+
};
|
|
177
290
|
}
|
|
178
291
|
return {
|
|
179
292
|
success: false,
|
|
@@ -333,6 +446,12 @@ function createEdgeSigner(delegateKey, options = {}) {
|
|
|
333
446
|
"x402 funding binding is required before signing a merchant header. Sign the hosted funding hash with x402_expected first."
|
|
334
447
|
);
|
|
335
448
|
}
|
|
449
|
+
try {
|
|
450
|
+
assertX402PaymentWindowOpen(expected);
|
|
451
|
+
} catch (err) {
|
|
452
|
+
x402Bindings.delete(x402Binding);
|
|
453
|
+
throw err;
|
|
454
|
+
}
|
|
336
455
|
const option = sdk.selectStandardPaymentOption(paymentRequired.accepts);
|
|
337
456
|
if (!option) {
|
|
338
457
|
throw new sdk.HavenApiError(
|
|
@@ -363,9 +482,70 @@ function createEdgeSigner(delegateKey, options = {}) {
|
|
|
363
482
|
} finally {
|
|
364
483
|
x402Bindings.delete(x402Binding);
|
|
365
484
|
}
|
|
485
|
+
},
|
|
486
|
+
async signSweepAuthorization({
|
|
487
|
+
authorization,
|
|
488
|
+
expectedAuth,
|
|
489
|
+
expectedSafe
|
|
490
|
+
}) {
|
|
491
|
+
assertSweepBinding(authorization, expectedAuth, options.x402BindingSigner);
|
|
492
|
+
if (!sameAddress(authorization.from, delegateAddress)) {
|
|
493
|
+
throw new sdk.HavenSigningError(
|
|
494
|
+
"Sweep authorization `from` does not match this delegate address."
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (expectedSafe && !sameAddress(authorization.to, expectedSafe)) {
|
|
498
|
+
throw new sdk.HavenSigningError(
|
|
499
|
+
"Sweep authorization `to` does not match the Safe in the local credential."
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
const typedData = sdk.buildSweepTypedData(authorization);
|
|
503
|
+
const viemTypedData = {
|
|
504
|
+
domain: {
|
|
505
|
+
...typedData.domain,
|
|
506
|
+
verifyingContract: typedData.domain.verifyingContract
|
|
507
|
+
},
|
|
508
|
+
types: typedData.types,
|
|
509
|
+
primaryType: typedData.primaryType,
|
|
510
|
+
message: {
|
|
511
|
+
...typedData.message,
|
|
512
|
+
from: typedData.message.from,
|
|
513
|
+
to: typedData.message.to,
|
|
514
|
+
nonce: typedData.message.nonce
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
const account = accounts.privateKeyToAccount(delegateKey);
|
|
518
|
+
const signature = await account.signTypedData(viemTypedData);
|
|
519
|
+
const recovered = await viem.recoverTypedDataAddress({ ...viemTypedData, signature });
|
|
520
|
+
if (!sameAddress(recovered, delegateAddress)) {
|
|
521
|
+
throw new sdk.HavenSigningError(
|
|
522
|
+
"Local sweep signature verification failed \u2014 recovered address does not match the delegate key."
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
return { signature };
|
|
366
526
|
}
|
|
367
527
|
};
|
|
368
528
|
}
|
|
529
|
+
function assertSweepBinding(authorization, expectedAuth, trustedSigner) {
|
|
530
|
+
if (!expectedAuth || typeof expectedAuth !== "object") {
|
|
531
|
+
throw new sdk.HavenSigningError("Sweep authorization binding is required before signing.");
|
|
532
|
+
}
|
|
533
|
+
if (!trustedSigner) {
|
|
534
|
+
throw new sdk.HavenSigningError(
|
|
535
|
+
"Sweep binding verifier is not configured. Set HAVEN_X402_BINDING_SIGNER before signing sweep authorizations."
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
const message = sdk.buildSweepAuthorizationMessage(authorization);
|
|
539
|
+
if (expectedAuth.version !== 1 || expectedAuth.message !== message) {
|
|
540
|
+
throw new sdk.HavenSigningError("Sweep authorization binding does not match the authorization being signed.");
|
|
541
|
+
}
|
|
542
|
+
if (!sameAddress(expectedAuth.signer, trustedSigner)) {
|
|
543
|
+
throw new sdk.HavenSigningError("Sweep authorization binding was not signed by the configured Haven signer.");
|
|
544
|
+
}
|
|
545
|
+
if (!sdk.verifySignature(viem.hashMessage(message), expectedAuth.signature, trustedSigner)) {
|
|
546
|
+
throw new sdk.HavenSigningError("Sweep authorization binding signature could not be verified.");
|
|
547
|
+
}
|
|
548
|
+
}
|
|
369
549
|
function assertX402MatchesExpected(paymentRequired, option, expected) {
|
|
370
550
|
assertExpectedShape(expected);
|
|
371
551
|
const headerResource = option.resource ?? paymentRequired.resource.url;
|
|
@@ -407,7 +587,8 @@ function assertExpectedBinding(payloadHash, expected, trustedSigner) {
|
|
|
407
587
|
merchantTo: expected.merchantTo,
|
|
408
588
|
amount: expected.amount,
|
|
409
589
|
asset: expected.asset,
|
|
410
|
-
network: expected.network
|
|
590
|
+
network: expected.network,
|
|
591
|
+
expiresAt: expected.expiresAt
|
|
411
592
|
});
|
|
412
593
|
if (expected.auth?.version !== 1 || expected.auth.message !== message) {
|
|
413
594
|
throw new sdk.HavenSigningError("x402 expected context authentication message is invalid.");
|
|
@@ -419,6 +600,21 @@ function assertExpectedBinding(payloadHash, expected, trustedSigner) {
|
|
|
419
600
|
throw new sdk.HavenSigningError("x402 expected context signature could not be verified.");
|
|
420
601
|
}
|
|
421
602
|
}
|
|
603
|
+
function assertX402PaymentWindowOpen(expected) {
|
|
604
|
+
if (!expected.expiresAt) return;
|
|
605
|
+
const expiresAtMs = Date.parse(expected.expiresAt);
|
|
606
|
+
if (Number.isNaN(expiresAtMs)) {
|
|
607
|
+
throw new sdk.HavenSigningError("x402 expected context expiresAt is not a valid ISO timestamp.");
|
|
608
|
+
}
|
|
609
|
+
if (expiresAtMs <= Date.now()) {
|
|
610
|
+
throw new sdk.HavenError(
|
|
611
|
+
"The x402 payment window expired before the merchant header could be signed. Re-quote with haven_pay_mcp_tool using the same idempotency_key before trying again.",
|
|
612
|
+
sdk.AgentPaymentFailureCode.PaymentWindowExpired,
|
|
613
|
+
410,
|
|
614
|
+
expected.paymentId
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
422
618
|
function sameAddress(a, b) {
|
|
423
619
|
return a.toLowerCase() === b.toLowerCase();
|
|
424
620
|
}
|
|
@@ -512,7 +708,7 @@ async function warnIfCredentialFilePermissive(path, log = (message) => process.s
|
|
|
512
708
|
|
|
513
709
|
// src/server.ts
|
|
514
710
|
var SIGNER_NAME = "@haven_ai/signer";
|
|
515
|
-
var SIGNER_VERSION = "0.1.
|
|
711
|
+
var SIGNER_VERSION = "0.1.15-alpha.0";
|
|
516
712
|
async function resolveSignerRuntime(options = {}) {
|
|
517
713
|
if (options.delegateKey) {
|
|
518
714
|
return {
|