@haven_ai/sdk 0.6.0-alpha.0 → 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/dist/edge.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkCK4NLLMO_cjs = require('./chunk-CK4NLLMO.cjs');
4
- var chunkS42QSWJY_cjs = require('./chunk-S42QSWJY.cjs');
3
+ var chunkJ6DQEBK2_cjs = require('./chunk-J6DQEBK2.cjs');
4
+ var chunk3SVPI4LS_cjs = require('./chunk-3SVPI4LS.cjs');
5
5
  var secp256k1 = require('@noble/curves/secp256k1');
6
6
  var accounts = require('viem/accounts');
7
7
  var viem = require('viem');
@@ -17,7 +17,7 @@ function addressFromKey(privateKey) {
17
17
  try {
18
18
  return accounts.privateKeyToAddress(`0x${hexBytes(privateKey, 32, "private key")}`);
19
19
  } catch (err) {
20
- throw new chunkS42QSWJY_cjs.HavenSigningError(
20
+ throw new chunk3SVPI4LS_cjs.HavenSigningError(
21
21
  `Invalid private key: ${err instanceof Error ? err.message : String(err)}`
22
22
  );
23
23
  }
@@ -31,7 +31,7 @@ function signHash(privateKey, hash) {
31
31
  yParity: recovery
32
32
  });
33
33
  } catch (err) {
34
- throw new chunkS42QSWJY_cjs.HavenSigningError(
34
+ throw new chunk3SVPI4LS_cjs.HavenSigningError(
35
35
  `Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`
36
36
  );
37
37
  }
@@ -52,247 +52,458 @@ function verifySignature(hash, signature, expectedAddress) {
52
52
  }
53
53
  }
54
54
 
55
+ // src/sub-budget-guards.ts
56
+ var ERC20_PERIOD_TRANSFER_ENFORCER = "0x474e3Ae7E169e940607cC624Da8A15Eb120139aB";
57
+ var DELEGATION_DOMAIN_NAME = "DelegationManager";
58
+ var DELEGATION_DOMAIN_VERSION = "1";
59
+ var EXPECTED_DELEGATION_TYPES = {
60
+ Caveat: [
61
+ { name: "enforcer", type: "address" },
62
+ { name: "terms", type: "bytes" }
63
+ ],
64
+ Delegation: [
65
+ { name: "delegate", type: "address" },
66
+ { name: "delegator", type: "address" },
67
+ { name: "authority", type: "bytes32" },
68
+ { name: "caveats", type: "Caveat[]" },
69
+ { name: "salt", type: "uint256" }
70
+ ]
71
+ };
72
+ function same(a, b) {
73
+ return !!a && !!b && a.toLowerCase() === b.toLowerCase();
74
+ }
75
+ function sliceTerms(terms, start, end) {
76
+ const body = terms.startsWith("0x") ? terms.slice(2).toLowerCase() : terms.toLowerCase();
77
+ return end === void 0 ? body.slice(start * 2) : body.slice(start * 2, end * 2);
78
+ }
79
+ function findCaveat(caveats, enforcer) {
80
+ return caveats.find((c) => same(c.enforcer, enforcer));
81
+ }
82
+ function hashSubBudgetDelegation(delegation) {
83
+ return chunkJ6DQEBK2_cjs.hashDelegation(delegation);
84
+ }
85
+ function refuseSubBudgetChild(what, detail) {
86
+ throw new chunkJ6DQEBK2_cjs.HavenTypedDataRefusedError(
87
+ `Refusing to sign the sub-budget child: ${what}. ${detail} This signature opens a slice of the delegating agent budget for another agent, so it is verified locally against the expectation Haven declared, rather than trusted.`
88
+ );
89
+ }
90
+ function assertOwnSubBudgetChild(typedData, expected, delegateAddress, now = Date.now()) {
91
+ const td = typedData;
92
+ if (td?.primaryType !== "Delegation") {
93
+ refuseSubBudgetChild("it is not a Delegation payload", `primaryType was '${String(td?.primaryType)}'.`);
94
+ }
95
+ if (!same(td.domain?.verifyingContract, chunk3SVPI4LS_cjs.DELEGATION_MANAGER)) {
96
+ refuseSubBudgetChild(
97
+ "the EIP-712 domain names an unknown DelegationManager",
98
+ `Expected ${chunk3SVPI4LS_cjs.DELEGATION_MANAGER}, got ${td.domain?.verifyingContract}.`
99
+ );
100
+ }
101
+ if (td.domain?.name !== DELEGATION_DOMAIN_NAME || td.domain?.version !== DELEGATION_DOMAIN_VERSION) {
102
+ refuseSubBudgetChild(
103
+ "the EIP-712 domain name/version does not match the pinned DelegationManager domain",
104
+ `Expected name '${DELEGATION_DOMAIN_NAME}' version '${DELEGATION_DOMAIN_VERSION}'; got name '${String(td.domain?.name)}' version '${String(td.domain?.version)}'.`
105
+ );
106
+ }
107
+ if (JSON.stringify(td.types?.Caveat) !== JSON.stringify(EXPECTED_DELEGATION_TYPES.Caveat) || JSON.stringify(td.types?.Delegation) !== JSON.stringify(EXPECTED_DELEGATION_TYPES.Delegation)) {
108
+ refuseSubBudgetChild(
109
+ "its EIP-712 type definitions do not match the pinned Delegation/Caveat shape",
110
+ "A renamed, reordered, or additional field on Delegation or Caveat could change what the caveats below mean without changing this check's field-by-field comparisons."
111
+ );
112
+ }
113
+ const domainChain = Number(td.domain?.chainId);
114
+ if (!Number.isFinite(domainChain) || !chunkJ6DQEBK2_cjs.DIRECT_PAYMENT_CHAIN_IDS.has(domainChain)) {
115
+ refuseSubBudgetChild(
116
+ "it is scoped to a chain the delegation rail has no pinned contracts for",
117
+ `Chains with pinned contracts: ${[...chunkJ6DQEBK2_cjs.DIRECT_PAYMENT_CHAIN_IDS].join(", ")}; the child says ${String(td.domain?.chainId)}.`
118
+ );
119
+ }
120
+ if (domainChain !== expected.chainId) {
121
+ refuseSubBudgetChild(
122
+ "it is scoped to the wrong chain",
123
+ `Expected chain ${expected.chainId}; the child says ${td.domain?.chainId}.`
124
+ );
125
+ }
126
+ const ownAccount = chunk3SVPI4LS_cjs.deriveDelegateAccountAddress(delegateAddress);
127
+ const delegator = td.message?.delegator;
128
+ if (typeof delegator !== "string" || !same(delegator, ownAccount)) {
129
+ refuseSubBudgetChild(
130
+ "it is not delegated by this agent's own account",
131
+ `Expected delegator ${ownAccount}; the child names ${String(delegator)}.`
132
+ );
133
+ }
134
+ if (!same(delegator, expected.delegateAccount)) {
135
+ refuseSubBudgetChild(
136
+ "its delegator does not match the account Haven declared",
137
+ `Expected ${expected.delegateAccount}; the child names ${String(delegator)}.`
138
+ );
139
+ }
140
+ const delegate = td.message?.delegate;
141
+ if (typeof delegate !== "string" || !same(delegate, expected.childDelegateAccount)) {
142
+ refuseSubBudgetChild(
143
+ "its delegate does not match the declared child delegate",
144
+ `Expected ${expected.childDelegateAccount}; the child names ${String(delegate)}.`
145
+ );
146
+ }
147
+ const authority = td.message?.authority;
148
+ if (typeof authority !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(authority)) {
149
+ refuseSubBudgetChild("its authority is not a 32-byte delegation hash", `Got ${String(authority)}.`);
150
+ }
151
+ if (authority.toLowerCase() === chunk3SVPI4LS_cjs.ROOT_AUTHORITY) {
152
+ refuseSubBudgetChild(
153
+ "it is a ROOT delegation, not a re-delegation of the delegating agent budget",
154
+ "A sub-budget always chains under the delegating agent budget delegation."
155
+ );
156
+ }
157
+ if (!same(authority, expected.parentDelegationHash)) {
158
+ refuseSubBudgetChild(
159
+ "it chains under a different parent delegation",
160
+ `Expected authority ${expected.parentDelegationHash}; the child says ${authority}.`
161
+ );
162
+ }
163
+ const caveats = td.message?.caveats ?? [];
164
+ if (findCaveat(caveats, chunk3SVPI4LS_cjs.CAVEAT_ENFORCERS.erc20TransferAmount)) {
165
+ refuseSubBudgetChild(
166
+ "it carries a hard-cap transfer-amount caveat (the task-budget shape)",
167
+ "A sub-budget is period-scoped: its amount caveat must be an ERC20PeriodTransferEnforcer caveat slicing the parent period meter, never a lifetime cap."
168
+ );
169
+ }
170
+ const period = findCaveat(caveats, ERC20_PERIOD_TRANSFER_ENFORCER);
171
+ if (!period) {
172
+ refuseSubBudgetChild(
173
+ "it has no ERC-20 period-transfer caveat",
174
+ "Without it the child is not bounded to a per-period amount."
175
+ );
176
+ }
177
+ const token = `0x${sliceTerms(period.terms, 0, 20)}`;
178
+ if (!same(token, expected.tokenAddress)) {
179
+ refuseSubBudgetChild("it spends a different token", `Expected ${expected.tokenAddress}, child pins ${token}.`);
180
+ }
181
+ const periodAmount = BigInt(`0x${sliceTerms(period.terms, 20, 52)}`);
182
+ if (periodAmount !== BigInt(expected.periodAmountAtomic)) {
183
+ refuseSubBudgetChild(
184
+ "the period amount does not match",
185
+ `Expected ${expected.periodAmountAtomic}; the child allows ${periodAmount.toString()}.`
186
+ );
187
+ }
188
+ const periodDuration = Number(BigInt(`0x${sliceTerms(period.terms, 52, 84)}`));
189
+ if (periodDuration !== expected.periodDurationSeconds) {
190
+ refuseSubBudgetChild(
191
+ "its period duration does not match the parent window Haven declared",
192
+ `Expected ${expected.periodDurationSeconds}s; the child says ${periodDuration}s. A sub-budget is a slice of the parent period meter \u2014 same window, smaller amount \u2014 never a different clock.`
193
+ );
194
+ }
195
+ const startDate = Number(BigInt(`0x${sliceTerms(period.terms, 84, 116)}`));
196
+ if (startDate !== expected.startDate) {
197
+ refuseSubBudgetChild(
198
+ "its period start does not match the parent anchor Haven declared",
199
+ `Expected ${expected.startDate}; the child says ${startDate}.`
200
+ );
201
+ }
202
+ const timestamp = findCaveat(caveats, chunk3SVPI4LS_cjs.CAVEAT_ENFORCERS.timestamp);
203
+ if (!timestamp) {
204
+ refuseSubBudgetChild("it never expires", "A sub-budget child without a timestamp caveat is open-ended.");
205
+ }
206
+ const beforeThreshold = Number(BigInt(`0x${sliceTerms(timestamp.terms, 16, 32)}`));
207
+ const nowSec = Math.floor(now / 1e3);
208
+ if (beforeThreshold <= nowSec) {
209
+ refuseSubBudgetChild("it has already expired", `Expiry ${beforeThreshold} is not in the future.`);
210
+ }
211
+ if (beforeThreshold !== expected.expiresAt) {
212
+ refuseSubBudgetChild(
213
+ "its expiry does not match what Haven declared",
214
+ `Expected ${expected.expiresAt}; the child says ${beforeThreshold}.`
215
+ );
216
+ }
217
+ const calldata = findCaveat(caveats, chunk3SVPI4LS_cjs.CAVEAT_ENFORCERS.allowedCalldata);
218
+ if (expected.recipientAddress) {
219
+ if (!calldata) {
220
+ refuseSubBudgetChild(
221
+ "it has no recipient pin",
222
+ "The sub-budget was issued with a pinned recipient, so the child must carry one."
223
+ );
224
+ }
225
+ const startIndex = BigInt(`0x${sliceTerms(calldata.terms, 0, 32)}`);
226
+ if (startIndex !== 4n) {
227
+ refuseSubBudgetChild(
228
+ "the recipient pin points at the wrong calldata offset",
229
+ `Expected offset 4, got ${startIndex.toString()}.`
230
+ );
231
+ }
232
+ const paddedRecipient = sliceTerms(calldata.terms, 32, 64);
233
+ if (paddedRecipient.slice(0, 24) !== "0".repeat(24)) {
234
+ refuseSubBudgetChild("the pinned recipient is not a plain address", "Its 32-byte word is not a padded address.");
235
+ }
236
+ const recipient = `0x${paddedRecipient.slice(24)}`;
237
+ if (!same(recipient, expected.recipientAddress)) {
238
+ refuseSubBudgetChild(
239
+ "it pins a different recipient than Haven declared",
240
+ `Expected ${expected.recipientAddress}; the child pins ${recipient}.`
241
+ );
242
+ }
243
+ } else if (calldata) {
244
+ refuseSubBudgetChild(
245
+ "it pins a recipient the sub-budget was not issued with",
246
+ "This sub-budget is open (no recipient pin); the child must not add one."
247
+ );
248
+ }
249
+ }
250
+ function assertOwnSubBudgetCloseUserOp(typedData, expected, delegateAddress) {
251
+ chunkJ6DQEBK2_cjs.assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress);
252
+ }
253
+
55
254
  Object.defineProperty(exports, "CAVEAT_TYPEHASH", {
56
255
  enumerable: true,
57
- get: function () { return chunkCK4NLLMO_cjs.CAVEAT_TYPEHASH; }
256
+ get: function () { return chunkJ6DQEBK2_cjs.CAVEAT_TYPEHASH; }
58
257
  });
59
258
  Object.defineProperty(exports, "DELEGATION_TYPEHASH", {
60
259
  enumerable: true,
61
- get: function () { return chunkCK4NLLMO_cjs.DELEGATION_TYPEHASH; }
260
+ get: function () { return chunkJ6DQEBK2_cjs.DELEGATION_TYPEHASH; }
62
261
  });
63
262
  Object.defineProperty(exports, "DIRECT_PAYMENT_CHAIN_IDS", {
64
263
  enumerable: true,
65
- get: function () { return chunkCK4NLLMO_cjs.DIRECT_PAYMENT_CHAIN_IDS; }
264
+ get: function () { return chunkJ6DQEBK2_cjs.DIRECT_PAYMENT_CHAIN_IDS; }
66
265
  });
67
266
  Object.defineProperty(exports, "EXECUTE_ABI", {
68
267
  enumerable: true,
69
- get: function () { return chunkCK4NLLMO_cjs.EXECUTE_ABI; }
268
+ get: function () { return chunkJ6DQEBK2_cjs.EXECUTE_ABI; }
70
269
  });
71
270
  Object.defineProperty(exports, "HAVEN_CLIENT_HEADER", {
72
271
  enumerable: true,
73
- get: function () { return chunkCK4NLLMO_cjs.HAVEN_CLIENT_HEADER; }
272
+ get: function () { return chunkJ6DQEBK2_cjs.HAVEN_CLIENT_HEADER; }
74
273
  });
75
274
  Object.defineProperty(exports, "HAVEN_MINIMUM_NODE_VERSION", {
76
275
  enumerable: true,
77
- get: function () { return chunkCK4NLLMO_cjs.HAVEN_MINIMUM_NODE_VERSION; }
276
+ get: function () { return chunkJ6DQEBK2_cjs.HAVEN_MINIMUM_NODE_VERSION; }
78
277
  });
79
278
  Object.defineProperty(exports, "HavenTypedDataRefusedError", {
80
279
  enumerable: true,
81
- get: function () { return chunkCK4NLLMO_cjs.HavenTypedDataRefusedError; }
280
+ get: function () { return chunkJ6DQEBK2_cjs.HavenTypedDataRefusedError; }
82
281
  });
83
282
  Object.defineProperty(exports, "MAX_TASK_BUDGET_TTL_SECONDS", {
84
283
  enumerable: true,
85
- get: function () { return chunkCK4NLLMO_cjs.MAX_TASK_BUDGET_TTL_SECONDS; }
284
+ get: function () { return chunkJ6DQEBK2_cjs.MAX_TASK_BUDGET_TTL_SECONDS; }
86
285
  });
87
286
  Object.defineProperty(exports, "TYPED_DATA_NOT_ALLOWED", {
88
287
  enumerable: true,
89
- get: function () { return chunkCK4NLLMO_cjs.TYPED_DATA_NOT_ALLOWED; }
288
+ get: function () { return chunkJ6DQEBK2_cjs.TYPED_DATA_NOT_ALLOWED; }
90
289
  });
91
290
  Object.defineProperty(exports, "assertBoundDirectPaymentUserOp", {
92
291
  enumerable: true,
93
- get: function () { return chunkCK4NLLMO_cjs.assertBoundDirectPaymentUserOp; }
292
+ get: function () { return chunkJ6DQEBK2_cjs.assertBoundDirectPaymentUserOp; }
94
293
  });
95
294
  Object.defineProperty(exports, "assertFundingLegPaysDelegate", {
96
295
  enumerable: true,
97
- get: function () { return chunkCK4NLLMO_cjs.assertFundingLegPaysDelegate; }
296
+ get: function () { return chunkJ6DQEBK2_cjs.assertFundingLegPaysDelegate; }
98
297
  });
99
298
  Object.defineProperty(exports, "assertOwnSettlementChild", {
100
299
  enumerable: true,
101
- get: function () { return chunkCK4NLLMO_cjs.assertOwnSettlementChild; }
300
+ get: function () { return chunkJ6DQEBK2_cjs.assertOwnSettlementChild; }
102
301
  });
103
302
  Object.defineProperty(exports, "assertOwnTaskBudgetCloseUserOp", {
104
303
  enumerable: true,
105
- get: function () { return chunkCK4NLLMO_cjs.assertOwnTaskBudgetCloseUserOp; }
304
+ get: function () { return chunkJ6DQEBK2_cjs.assertOwnTaskBudgetCloseUserOp; }
106
305
  });
107
306
  Object.defineProperty(exports, "assertOwnTaskChild", {
108
307
  enumerable: true,
109
- get: function () { return chunkCK4NLLMO_cjs.assertOwnTaskChild; }
308
+ get: function () { return chunkJ6DQEBK2_cjs.assertOwnTaskChild; }
110
309
  });
111
310
  Object.defineProperty(exports, "buildSweepAuthorizationMessage", {
112
311
  enumerable: true,
113
- get: function () { return chunkCK4NLLMO_cjs.buildSweepAuthorizationMessage; }
312
+ get: function () { return chunkJ6DQEBK2_cjs.buildSweepAuthorizationMessage; }
114
313
  });
115
314
  Object.defineProperty(exports, "buildSweepTypedData", {
116
315
  enumerable: true,
117
- get: function () { return chunkCK4NLLMO_cjs.buildSweepTypedData; }
316
+ get: function () { return chunkJ6DQEBK2_cjs.buildSweepTypedData; }
118
317
  });
119
318
  Object.defineProperty(exports, "buildX402ExpectedMessage", {
120
319
  enumerable: true,
121
- get: function () { return chunkCK4NLLMO_cjs.buildX402ExpectedMessage; }
320
+ get: function () { return chunkJ6DQEBK2_cjs.buildX402ExpectedMessage; }
122
321
  });
123
322
  Object.defineProperty(exports, "createNextStepBuilder", {
124
323
  enumerable: true,
125
- get: function () { return chunkCK4NLLMO_cjs.createNextStepBuilder; }
324
+ get: function () { return chunkJ6DQEBK2_cjs.createNextStepBuilder; }
126
325
  });
127
326
  Object.defineProperty(exports, "decodeBase64Json", {
128
327
  enumerable: true,
129
- get: function () { return chunkCK4NLLMO_cjs.decodeBase64Json; }
328
+ get: function () { return chunkJ6DQEBK2_cjs.decodeBase64Json; }
130
329
  });
131
330
  Object.defineProperty(exports, "encodeBase64Json", {
132
331
  enumerable: true,
133
- get: function () { return chunkCK4NLLMO_cjs.encodeBase64Json; }
332
+ get: function () { return chunkJ6DQEBK2_cjs.encodeBase64Json; }
134
333
  });
135
334
  Object.defineProperty(exports, "hashDelegation", {
136
335
  enumerable: true,
137
- get: function () { return chunkCK4NLLMO_cjs.hashDelegation; }
336
+ get: function () { return chunkJ6DQEBK2_cjs.hashDelegation; }
138
337
  });
139
338
  Object.defineProperty(exports, "havenClientIdentity", {
140
339
  enumerable: true,
141
- get: function () { return chunkCK4NLLMO_cjs.havenClientIdentity; }
340
+ get: function () { return chunkJ6DQEBK2_cjs.havenClientIdentity; }
142
341
  });
143
342
  Object.defineProperty(exports, "isSupportedNodeVersion", {
144
343
  enumerable: true,
145
- get: function () { return chunkCK4NLLMO_cjs.isSupportedNodeVersion; }
344
+ get: function () { return chunkJ6DQEBK2_cjs.isSupportedNodeVersion; }
146
345
  });
147
346
  Object.defineProperty(exports, "isTaskChildTypedData", {
148
347
  enumerable: true,
149
- get: function () { return chunkCK4NLLMO_cjs.isTaskChildTypedData; }
348
+ get: function () { return chunkJ6DQEBK2_cjs.isTaskChildTypedData; }
150
349
  });
151
350
  Object.defineProperty(exports, "readClientUpdate", {
152
351
  enumerable: true,
153
- get: function () { return chunkCK4NLLMO_cjs.readClientUpdate; }
352
+ get: function () { return chunkJ6DQEBK2_cjs.readClientUpdate; }
154
353
  });
155
354
  Object.defineProperty(exports, "selectStandardPaymentOption", {
156
355
  enumerable: true,
157
- get: function () { return chunkCK4NLLMO_cjs.selectStandardPaymentOption; }
356
+ get: function () { return chunkJ6DQEBK2_cjs.selectStandardPaymentOption; }
158
357
  });
159
358
  Object.defineProperty(exports, "toStandardPaymentRequirements", {
160
359
  enumerable: true,
161
- get: function () { return chunkCK4NLLMO_cjs.toStandardPaymentRequirements; }
360
+ get: function () { return chunkJ6DQEBK2_cjs.toStandardPaymentRequirements; }
162
361
  });
163
362
  Object.defineProperty(exports, "unsupportedNodeVersionMessage", {
164
363
  enumerable: true,
165
- get: function () { return chunkCK4NLLMO_cjs.unsupportedNodeVersionMessage; }
364
+ get: function () { return chunkJ6DQEBK2_cjs.unsupportedNodeVersionMessage; }
166
365
  });
167
366
  Object.defineProperty(exports, "x402AuthorizationAmount", {
168
367
  enumerable: true,
169
- get: function () { return chunkCK4NLLMO_cjs.x402AuthorizationAmount; }
368
+ get: function () { return chunkJ6DQEBK2_cjs.x402AuthorizationAmount; }
170
369
  });
171
370
  Object.defineProperty(exports, "x402V2PaymentEnvelope", {
172
371
  enumerable: true,
173
- get: function () { return chunkCK4NLLMO_cjs.x402V2PaymentEnvelope; }
372
+ get: function () { return chunkJ6DQEBK2_cjs.x402V2PaymentEnvelope; }
174
373
  });
175
374
  Object.defineProperty(exports, "AgentPaymentFailureCode", {
176
375
  enumerable: true,
177
- get: function () { return chunkS42QSWJY_cjs.AgentPaymentFailureCode; }
376
+ get: function () { return chunk3SVPI4LS_cjs.AgentPaymentFailureCode; }
178
377
  });
179
378
  Object.defineProperty(exports, "AgentPaymentNextAction", {
180
379
  enumerable: true,
181
- get: function () { return chunkS42QSWJY_cjs.AgentPaymentNextAction; }
380
+ get: function () { return chunk3SVPI4LS_cjs.AgentPaymentNextAction; }
182
381
  });
183
382
  Object.defineProperty(exports, "CAVEAT_ENFORCERS", {
184
383
  enumerable: true,
185
- get: function () { return chunkS42QSWJY_cjs.CAVEAT_ENFORCERS; }
384
+ get: function () { return chunk3SVPI4LS_cjs.CAVEAT_ENFORCERS; }
186
385
  });
187
386
  Object.defineProperty(exports, "DELEGATION_MANAGER", {
188
387
  enumerable: true,
189
- get: function () { return chunkS42QSWJY_cjs.DELEGATION_MANAGER; }
388
+ get: function () { return chunk3SVPI4LS_cjs.DELEGATION_MANAGER; }
190
389
  });
191
390
  Object.defineProperty(exports, "DELEGATION_TUPLE_COMPONENTS", {
192
391
  enumerable: true,
193
- get: function () { return chunkS42QSWJY_cjs.DELEGATION_TUPLE_COMPONENTS; }
392
+ get: function () { return chunk3SVPI4LS_cjs.DELEGATION_TUPLE_COMPONENTS; }
194
393
  });
195
394
  Object.defineProperty(exports, "DIRECT_SIGN_CONTEXT_VERSION", {
196
395
  enumerable: true,
197
- get: function () { return chunkS42QSWJY_cjs.DIRECT_SIGN_CONTEXT_VERSION; }
396
+ get: function () { return chunk3SVPI4LS_cjs.DIRECT_SIGN_CONTEXT_VERSION; }
198
397
  });
199
398
  Object.defineProperty(exports, "ENTRY_POINT_V07", {
200
399
  enumerable: true,
201
- get: function () { return chunkS42QSWJY_cjs.ENTRY_POINT_V07; }
400
+ get: function () { return chunk3SVPI4LS_cjs.ENTRY_POINT_V07; }
202
401
  });
203
402
  Object.defineProperty(exports, "HAVEN_CONNECTOR_CHANNEL", {
204
403
  enumerable: true,
205
- get: function () { return chunkS42QSWJY_cjs.HAVEN_CONNECTOR_CHANNEL; }
404
+ get: function () { return chunk3SVPI4LS_cjs.HAVEN_CONNECTOR_CHANNEL; }
206
405
  });
207
406
  Object.defineProperty(exports, "HYBRID_DELEGATOR_IMPLEMENTATION", {
208
407
  enumerable: true,
209
- get: function () { return chunkS42QSWJY_cjs.HYBRID_DELEGATOR_IMPLEMENTATION; }
408
+ get: function () { return chunk3SVPI4LS_cjs.HYBRID_DELEGATOR_IMPLEMENTATION; }
210
409
  });
211
410
  Object.defineProperty(exports, "HavenApiError", {
212
411
  enumerable: true,
213
- get: function () { return chunkS42QSWJY_cjs.HavenApiError; }
412
+ get: function () { return chunk3SVPI4LS_cjs.HavenApiError; }
214
413
  });
215
414
  Object.defineProperty(exports, "HavenError", {
216
415
  enumerable: true,
217
- get: function () { return chunkS42QSWJY_cjs.HavenError; }
416
+ get: function () { return chunk3SVPI4LS_cjs.HavenError; }
218
417
  });
219
418
  Object.defineProperty(exports, "HavenSigningError", {
220
419
  enumerable: true,
221
- get: function () { return chunkS42QSWJY_cjs.HavenSigningError; }
420
+ get: function () { return chunk3SVPI4LS_cjs.HavenSigningError; }
222
421
  });
223
422
  Object.defineProperty(exports, "HavenUnsupportedSignerVersionError", {
224
423
  enumerable: true,
225
- get: function () { return chunkS42QSWJY_cjs.HavenUnsupportedSignerVersionError; }
424
+ get: function () { return chunk3SVPI4LS_cjs.HavenUnsupportedSignerVersionError; }
226
425
  });
227
426
  Object.defineProperty(exports, "HavenUserOpBindingError", {
228
427
  enumerable: true,
229
- get: function () { return chunkS42QSWJY_cjs.HavenUserOpBindingError; }
428
+ get: function () { return chunk3SVPI4LS_cjs.HavenUserOpBindingError; }
230
429
  });
231
430
  Object.defineProperty(exports, "MAX_SETTLEMENT_WINDOW_SECONDS", {
232
431
  enumerable: true,
233
- get: function () { return chunkS42QSWJY_cjs.MAX_SETTLEMENT_WINDOW_SECONDS; }
432
+ get: function () { return chunk3SVPI4LS_cjs.MAX_SETTLEMENT_WINDOW_SECONDS; }
234
433
  });
235
434
  Object.defineProperty(exports, "REDEEM_DELEGATIONS_ABI", {
236
435
  enumerable: true,
237
- get: function () { return chunkS42QSWJY_cjs.REDEEM_DELEGATIONS_ABI; }
436
+ get: function () { return chunk3SVPI4LS_cjs.REDEEM_DELEGATIONS_ABI; }
238
437
  });
239
438
  Object.defineProperty(exports, "ROOT_AUTHORITY", {
240
439
  enumerable: true,
241
- get: function () { return chunkS42QSWJY_cjs.ROOT_AUTHORITY; }
440
+ get: function () { return chunk3SVPI4LS_cjs.ROOT_AUTHORITY; }
242
441
  });
243
442
  Object.defineProperty(exports, "SIGNER_UPDATE_FALLBACK", {
244
443
  enumerable: true,
245
- get: function () { return chunkS42QSWJY_cjs.SIGNER_UPDATE_FALLBACK; }
444
+ get: function () { return chunk3SVPI4LS_cjs.SIGNER_UPDATE_FALLBACK; }
246
445
  });
247
446
  Object.defineProperty(exports, "SIMPLE_FACTORY_ADDRESS", {
248
447
  enumerable: true,
249
- get: function () { return chunkS42QSWJY_cjs.SIMPLE_FACTORY_ADDRESS; }
448
+ get: function () { return chunk3SVPI4LS_cjs.SIMPLE_FACTORY_ADDRESS; }
250
449
  });
251
450
  Object.defineProperty(exports, "SINGLE_DEFAULT_MODE", {
252
451
  enumerable: true,
253
- get: function () { return chunkS42QSWJY_cjs.SINGLE_DEFAULT_MODE; }
452
+ get: function () { return chunk3SVPI4LS_cjs.SINGLE_DEFAULT_MODE; }
254
453
  });
255
454
  Object.defineProperty(exports, "SignerRefusalCode", {
256
455
  enumerable: true,
257
- get: function () { return chunkS42QSWJY_cjs.SignerRefusalCode; }
456
+ get: function () { return chunk3SVPI4LS_cjs.SignerRefusalCode; }
457
+ });
458
+ Object.defineProperty(exports, "TASK_SIGN_CONTEXT_VERSION", {
459
+ enumerable: true,
460
+ get: function () { return chunk3SVPI4LS_cjs.TASK_SIGN_CONTEXT_VERSION; }
258
461
  });
259
462
  Object.defineProperty(exports, "assertRedeemsOwnBudgetDelegation", {
260
463
  enumerable: true,
261
- get: function () { return chunkS42QSWJY_cjs.assertRedeemsOwnBudgetDelegation; }
464
+ get: function () { return chunk3SVPI4LS_cjs.assertRedeemsOwnBudgetDelegation; }
262
465
  });
263
466
  Object.defineProperty(exports, "assertUserOpTypedDataBinding", {
264
467
  enumerable: true,
265
- get: function () { return chunkS42QSWJY_cjs.assertUserOpTypedDataBinding; }
468
+ get: function () { return chunk3SVPI4LS_cjs.assertUserOpTypedDataBinding; }
266
469
  });
267
470
  Object.defineProperty(exports, "chainIdForNetwork", {
268
471
  enumerable: true,
269
- get: function () { return chunkS42QSWJY_cjs.chainIdForNetwork; }
472
+ get: function () { return chunk3SVPI4LS_cjs.chainIdForNetwork; }
270
473
  });
271
474
  Object.defineProperty(exports, "connectorRerunCommand", {
272
475
  enumerable: true,
273
- get: function () { return chunkS42QSWJY_cjs.connectorRerunCommand; }
476
+ get: function () { return chunk3SVPI4LS_cjs.connectorRerunCommand; }
477
+ });
478
+ Object.defineProperty(exports, "connectorUpgradeCommand", {
479
+ enumerable: true,
480
+ get: function () { return chunk3SVPI4LS_cjs.connectorUpgradeCommand; }
274
481
  });
275
482
  Object.defineProperty(exports, "deriveDelegateAccountAddress", {
276
483
  enumerable: true,
277
- get: function () { return chunkS42QSWJY_cjs.deriveDelegateAccountAddress; }
484
+ get: function () { return chunk3SVPI4LS_cjs.deriveDelegateAccountAddress; }
278
485
  });
279
486
  Object.defineProperty(exports, "isPackedUserOperationTypedData", {
280
487
  enumerable: true,
281
- get: function () { return chunkS42QSWJY_cjs.isPackedUserOperationTypedData; }
488
+ get: function () { return chunk3SVPI4LS_cjs.isPackedUserOperationTypedData; }
282
489
  });
283
490
  Object.defineProperty(exports, "isSettlementChildTypedData", {
284
491
  enumerable: true,
285
- get: function () { return chunkS42QSWJY_cjs.isSettlementChildTypedData; }
492
+ get: function () { return chunk3SVPI4LS_cjs.isSettlementChildTypedData; }
286
493
  });
287
494
  Object.defineProperty(exports, "packedUserOperationHash", {
288
495
  enumerable: true,
289
- get: function () { return chunkS42QSWJY_cjs.packedUserOperationHash; }
496
+ get: function () { return chunk3SVPI4LS_cjs.packedUserOperationHash; }
290
497
  });
291
498
  Object.defineProperty(exports, "verifySettlementChild", {
292
499
  enumerable: true,
293
- get: function () { return chunkS42QSWJY_cjs.verifySettlementChild; }
500
+ get: function () { return chunk3SVPI4LS_cjs.verifySettlementChild; }
294
501
  });
502
+ exports.ERC20_PERIOD_TRANSFER_ENFORCER = ERC20_PERIOD_TRANSFER_ENFORCER;
295
503
  exports.addressFromKey = addressFromKey;
504
+ exports.assertOwnSubBudgetChild = assertOwnSubBudgetChild;
505
+ exports.assertOwnSubBudgetCloseUserOp = assertOwnSubBudgetCloseUserOp;
506
+ exports.hashSubBudgetDelegation = hashSubBudgetDelegation;
296
507
  exports.signHash = signHash;
297
508
  exports.verifySignature = verifySignature;
298
509
  //# sourceMappingURL=edge.cjs.map
package/dist/edge.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/edge-signing.ts"],"names":["privateKeyToAddress","HavenSigningError","secp256k1","serializeSignature","publicKeyToAddress"],"mappings":"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","file":"edge.cjs","sourcesContent":["import { secp256k1 } from '@noble/curves/secp256k1'\nimport { privateKeyToAddress, publicKeyToAddress } from 'viem/accounts'\nimport { serializeSignature, type Hex } from 'viem'\nimport { HavenSigningError } from './types.js'\n\n/**\n * #3173: the three key helpers the edge signer needs, without ethers.\n *\n * `./signer.ts` implements the same three on ethers, and the SDK barrel pulls\n * ethers in for them (and for `provider.ts` / `receipt.ts`). The edge signer\n * already ships viem, and viem signs with `@noble/curves` underneath — these\n * use the same curve library directly, synchronously (viem's own `sign` is\n * async), so `@haven_ai/sdk/edge` stays ethers-free and a signer session stops\n * paying for module init it never uses. Byte-equivalence with the ethers forms\n * is pinned in `edge-signing.test.ts`: same address, same 65-byte `r‖s‖v`\n * serialisation with low-s and v = 27/28, same recovery verdicts, and the same\n * refusals (high-s twin, wrong lengths) — with three stated strict-direction\n * exceptions, see `hexBytes`. Raw ECDSA over the hash — never the EIP-191\n * prefixed digest.\n */\n\n/** secp256k1 order / 2 — a signature with s above this is the malleable twin ethers rejects. */\nconst HALF_N = BigInt('0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0')\n\n/**\n * Stricter than ethers, never looser: the lowercase `0x` prefix and the exact\n * byte length are required. Ethers accepts an uppercase `0X` prefix on a\n * signature and the 64-byte EIP-2098 compact form, and is inconsistent on a\n * private key (`Wallet` accepts unprefixed and refuses `0X`; `SigningKey` does\n * the reverse); every such form is refused here — the divergences are pinned\n * in `edge-signing.test.ts` with ethers control assertions, and every\n * well-formed input is byte-equivalent.\n */\nfunction hexBytes(value: string, bytes: number, what: string): string {\n if (!/^0x[0-9a-fA-F]+$/.test(value) || value.length !== 2 + bytes * 2) {\n throw new Error(`${what} must be a 0x-prefixed ${bytes}-byte hex string`)\n }\n return value.slice(2)\n}\n\nexport function addressFromKey(privateKey: string): string {\n try {\n // Same gate as signHash: a key that derives an address must also sign.\n return privateKeyToAddress(`0x${hexBytes(privateKey, 32, 'private key')}`)\n } catch (err) {\n throw new HavenSigningError(\n `Invalid private key: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\nexport function signHash(privateKey: string, hash: string): string {\n try {\n const { r, s, recovery } = secp256k1.sign(hexBytes(hash, 32, 'hash'), hexBytes(privateKey, 32, 'private key'), { lowS: true })\n // viem serialises the trailing byte from yParity (0/1 → 27/28), the same\n // `v` ethers' `Signature.serialized` writes.\n return serializeSignature({\n r: `0x${r.toString(16).padStart(64, '0')}`,\n s: `0x${s.toString(16).padStart(64, '0')}`,\n yParity: recovery,\n })\n } catch (err) {\n throw new HavenSigningError(\n `Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\nexport function verifySignature(hash: string, signature: string, expectedAddress: string): boolean {\n try {\n const sig = hexBytes(signature, 65, 'signature')\n const hashHex = hexBytes(hash, 32, 'hash')\n // Reject the high-s malleable twin, as ethers does — one signature per message.\n if (BigInt(`0x${sig.slice(64, 128)}`) > HALF_N) return false\n const yParityOrV = Number.parseInt(sig.slice(128), 16)\n const recoveryBit = yParityOrV === 0 || yParityOrV === 27 ? 0 : yParityOrV === 1 || yParityOrV === 28 ? 1 : -1\n if (recoveryBit < 0) return false\n const publicKey = secp256k1.Signature.fromCompact(sig.slice(0, 128))\n .addRecoveryBit(recoveryBit)\n .recoverPublicKey(hashHex)\n .toHex(false)\n const recovered = publicKeyToAddress(`0x${publicKey}`)\n return recovered.toLowerCase() === expectedAddress.toLowerCase()\n } catch {\n return false\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/edge-signing.ts","../src/sub-budget-guards.ts"],"names":["privateKeyToAddress","HavenSigningError","secp256k1","serializeSignature","publicKeyToAddress","hashDelegation","HavenTypedDataRefusedError","DELEGATION_MANAGER","DIRECT_PAYMENT_CHAIN_IDS","deriveDelegateAccountAddress","ROOT_AUTHORITY","CAVEAT_ENFORCERS","assertOwnTaskBudgetCloseUserOp"],"mappings":"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","file":"edge.cjs","sourcesContent":["import { secp256k1 } from '@noble/curves/secp256k1'\nimport { privateKeyToAddress, publicKeyToAddress } from 'viem/accounts'\nimport { serializeSignature, type Hex } from 'viem'\nimport { HavenSigningError } from './types.js'\n\n/**\n * #3173: the three key helpers the edge signer needs, without ethers.\n *\n * `./signer.ts` implements the same three on ethers, and the SDK barrel pulls\n * ethers in for them (and for `provider.ts` / `receipt.ts`). The edge signer\n * already ships viem, and viem signs with `@noble/curves` underneath — these\n * use the same curve library directly, synchronously (viem's own `sign` is\n * async), so `@haven_ai/sdk/edge` stays ethers-free and a signer session stops\n * paying for module init it never uses. Byte-equivalence with the ethers forms\n * is pinned in `edge-signing.test.ts`: same address, same 65-byte `r‖s‖v`\n * serialisation with low-s and v = 27/28, same recovery verdicts, and the same\n * refusals (high-s twin, wrong lengths) — with three stated strict-direction\n * exceptions, see `hexBytes`. Raw ECDSA over the hash — never the EIP-191\n * prefixed digest.\n */\n\n/** secp256k1 order / 2 — a signature with s above this is the malleable twin ethers rejects. */\nconst HALF_N = BigInt('0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0')\n\n/**\n * Stricter than ethers, never looser: the lowercase `0x` prefix and the exact\n * byte length are required. Ethers accepts an uppercase `0X` prefix on a\n * signature and the 64-byte EIP-2098 compact form, and is inconsistent on a\n * private key (`Wallet` accepts unprefixed and refuses `0X`; `SigningKey` does\n * the reverse); every such form is refused here — the divergences are pinned\n * in `edge-signing.test.ts` with ethers control assertions, and every\n * well-formed input is byte-equivalent.\n */\nfunction hexBytes(value: string, bytes: number, what: string): string {\n if (!/^0x[0-9a-fA-F]+$/.test(value) || value.length !== 2 + bytes * 2) {\n throw new Error(`${what} must be a 0x-prefixed ${bytes}-byte hex string`)\n }\n return value.slice(2)\n}\n\nexport function addressFromKey(privateKey: string): string {\n try {\n // Same gate as signHash: a key that derives an address must also sign.\n return privateKeyToAddress(`0x${hexBytes(privateKey, 32, 'private key')}`)\n } catch (err) {\n throw new HavenSigningError(\n `Invalid private key: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\nexport function signHash(privateKey: string, hash: string): string {\n try {\n const { r, s, recovery } = secp256k1.sign(hexBytes(hash, 32, 'hash'), hexBytes(privateKey, 32, 'private key'), { lowS: true })\n // viem serialises the trailing byte from yParity (0/1 → 27/28), the same\n // `v` ethers' `Signature.serialized` writes.\n return serializeSignature({\n r: `0x${r.toString(16).padStart(64, '0')}`,\n s: `0x${s.toString(16).padStart(64, '0')}`,\n yParity: recovery,\n })\n } catch (err) {\n throw new HavenSigningError(\n `Failed to sign hash: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\nexport function verifySignature(hash: string, signature: string, expectedAddress: string): boolean {\n try {\n const sig = hexBytes(signature, 65, 'signature')\n const hashHex = hexBytes(hash, 32, 'hash')\n // Reject the high-s malleable twin, as ethers does — one signature per message.\n if (BigInt(`0x${sig.slice(64, 128)}`) > HALF_N) return false\n const yParityOrV = Number.parseInt(sig.slice(128), 16)\n const recoveryBit = yParityOrV === 0 || yParityOrV === 27 ? 0 : yParityOrV === 1 || yParityOrV === 28 ? 1 : -1\n if (recoveryBit < 0) return false\n const publicKey = secp256k1.Signature.fromCompact(sig.slice(0, 128))\n .addRecoveryBit(recoveryBit)\n .recoverPublicKey(hashHex)\n .toHex(false)\n const recovered = publicKeyToAddress(`0x${publicKey}`)\n return recovered.toLowerCase() === expectedAddress.toLowerCase()\n } catch {\n return false\n }\n}\n","/**\n * Sub-budget child guards (#3330) — the SDK-side local verification the\n * signer runs before its delegate key signs a sub-budget child, mirroring\n * `task-budget-guards.ts`'s `assertOwnTaskChild` for the two-row sub-budget\n * tree. ONE verifier covers BOTH rows, because the same signer (the\n * delegating agent A's own key) signs both:\n *\n * - A's PARENT-CHILD row: `delegate === delegator === A's own account`\n * (self-delegated, the task-child shape class).\n * - B's GRANT row: `delegator === A's own account`, `delegate === B's\n * delegate account` (a real grant to another account).\n *\n * What makes a sub-budget child a sub-budget child (vs a task budget's\n * hard-cap child) is the AMOUNT caveat: an `ERC20PeriodTransferEnforcer`\n * caveat whose terms are `abi.encode(address token, uint256 periodAmount,\n * uint256 periodDuration, uint256 startDate)` — the period-scoped slice of\n * the parent's own period meter, with the parent's periodDuration and\n * startDate reused verbatim. A hard-cap `ERC20TransferAmountEnforcer` caveat\n * is refused: that would be a task budget, which this channel must never\n * sign (two different products, two different sign-context endpoints).\n *\n * Authority, timestamp and recipient-pin checks are byte-for-byte the\n * task-child discipline: authority must equal the declared parent hash and\n * never be ROOT; expiry must be in the future and equal the declared one; a\n * pinned recipient must match exactly, and an unpinned budget must not grow\n * one. Enforcers are the pinned constants from `settlement-child.ts` (no kit\n * dependency) — same reasoning as that file's header documents.\n */\n\nimport { type Address, type Hex } from 'viem'\nimport { HavenTypedDataRefusedError, DIRECT_PAYMENT_CHAIN_IDS } from './direct-payment-guard.js'\nimport { DELEGATION_MANAGER, ROOT_AUTHORITY, CAVEAT_ENFORCERS } from './settlement-child.js'\nimport { deriveDelegateAccountAddress } from './delegate-account.js'\nimport {\n DELEGATION_TYPEHASH,\n CAVEAT_TYPEHASH,\n hashDelegation,\n type DelegationForHashing,\n} from './task-budget-guards.js'\n\n/** The pinned `ERC20PeriodTransferEnforcer` (bytecode-identical on Base + Base Sepolia). */\nexport const ERC20_PERIOD_TRANSFER_ENFORCER = '0x474e3Ae7E169e940607cC624Da8A15Eb120139aB'\n\n/** The pinned `Delegation` EIP-712 domain (cross-checked by task-budget-guards' pin test). */\nconst DELEGATION_DOMAIN_NAME = 'DelegationManager'\nconst DELEGATION_DOMAIN_VERSION = '1'\n\n/** The pinned `types` shape, byte-identical to `task-budget-guards.ts`'s. */\nconst EXPECTED_DELEGATION_TYPES = {\n Caveat: [\n { name: 'enforcer', type: 'address' },\n { name: 'terms', type: 'bytes' },\n ],\n Delegation: [\n { name: 'delegate', type: 'address' },\n { name: 'delegator', type: 'address' },\n { name: 'authority', type: 'bytes32' },\n { name: 'caveats', type: 'Caveat[]' },\n { name: 'salt', type: 'uint256' },\n ],\n} as const\n\nexport interface SubBudgetChildTypedData {\n domain: { name?: string; version?: string; chainId?: number | string; verifyingContract?: string }\n types: Record<string, unknown>\n primaryType: string\n message: Record<string, unknown>\n}\n\nfunction same(a: string | undefined, b: string | undefined): boolean {\n return !!a && !!b && a.toLowerCase() === b.toLowerCase()\n}\n\n/** Byte slice [start, end) of a `0x…` string, as lowercase hex without prefix. */\nfunction sliceTerms(terms: string, start: number, end?: number): string {\n const body = terms.startsWith('0x') ? terms.slice(2).toLowerCase() : terms.toLowerCase()\n return end === undefined ? body.slice(start * 2) : body.slice(start * 2, end * 2)\n}\n\nfunction findCaveat(caveats: Array<{ enforcer: string; terms: string }>, enforcer: string) {\n return caveats.find((c) => same(c.enforcer, enforcer))\n}\n\n/** The struct hash of a sub-budget child — the redemption chain's link value. */\nexport function hashSubBudgetDelegation(delegation: DelegationForHashing): Hex {\n return hashDelegation(delegation)\n}\n\n// The kit's own struct hashes, re-exported verbatim from task-budget-guards'\n// pinned literals so a caller can name them from this module too.\nexport { DELEGATION_TYPEHASH, CAVEAT_TYPEHASH }\n\nexport interface SubBudgetChildExpectation {\n chainId: number\n tokenAddress: string\n /** Per-period amount in atomic units — the child's periodAmount. */\n periodAmountAtomic: string\n /** The PARENT's period duration (seconds), reused verbatim in the caveat. */\n periodDurationSeconds: number\n /** The PARENT's period anchor, reused verbatim in the caveat. */\n startDate: number\n recipientAddress: string | null\n /** unix seconds — the `TimestampEnforcer`'s `beforeThreshold`. */\n expiresAt: number\n /** The hash of the row's parent delegation (`parent_delegation_hash`). */\n parentDelegationHash: string\n /**\n * A's own derived delegate account — the child's `delegator` on BOTH rows.\n */\n delegateAccount: string\n /**\n * The row's own `delegate`: A's account again for the parent-child row,\n * B's delegate account for the grant row. Served in the sign-context's\n * `expected` (read from the stored child JSON, not trusted caller input).\n */\n childDelegateAccount: string\n}\n\nfunction refuseSubBudgetChild(what: string, detail: string): never {\n throw new HavenTypedDataRefusedError(\n `Refusing to sign the sub-budget child: ${what}. ${detail} ` +\n 'This signature opens a slice of the delegating agent budget for another agent, so it is ' +\n 'verified locally against the expectation Haven declared, rather than trusted.',\n )\n}\n\n/**\n * Verify a sub-budget child delegation is EXACTLY what\n * `GET /sub-budgets/:id/sign-context` (purpose `open`) declared, that its\n * `delegator` is this signer's own account, and that its `delegate` is the\n * declared child delegate. Throws `HavenTypedDataRefusedError` (never\n * returns) on any disagreement.\n */\nexport function assertOwnSubBudgetChild(\n typedData: unknown,\n expected: SubBudgetChildExpectation,\n delegateAddress: string,\n now: number = Date.now(),\n): void {\n const td = typedData as SubBudgetChildTypedData\n if (td?.primaryType !== 'Delegation') {\n refuseSubBudgetChild('it is not a Delegation payload', `primaryType was '${String(td?.primaryType)}'.`)\n }\n if (!same(td.domain?.verifyingContract, DELEGATION_MANAGER)) {\n refuseSubBudgetChild(\n 'the EIP-712 domain names an unknown DelegationManager',\n `Expected ${DELEGATION_MANAGER}, got ${td.domain?.verifyingContract}.`,\n )\n }\n if (td.domain?.name !== DELEGATION_DOMAIN_NAME || td.domain?.version !== DELEGATION_DOMAIN_VERSION) {\n refuseSubBudgetChild(\n 'the EIP-712 domain name/version does not match the pinned DelegationManager domain',\n `Expected name '${DELEGATION_DOMAIN_NAME}' version '${DELEGATION_DOMAIN_VERSION}'; got name ` +\n `'${String(td.domain?.name)}' version '${String(td.domain?.version)}'.`,\n )\n }\n if (\n JSON.stringify(td.types?.Caveat) !== JSON.stringify(EXPECTED_DELEGATION_TYPES.Caveat) ||\n JSON.stringify(td.types?.Delegation) !== JSON.stringify(EXPECTED_DELEGATION_TYPES.Delegation)\n ) {\n refuseSubBudgetChild(\n 'its EIP-712 type definitions do not match the pinned Delegation/Caveat shape',\n 'A renamed, reordered, or additional field on Delegation or Caveat could change what the ' +\n 'caveats below mean without changing this check\\'s field-by-field comparisons.',\n )\n }\n const domainChain = Number(td.domain?.chainId)\n if (!Number.isFinite(domainChain) || !DIRECT_PAYMENT_CHAIN_IDS.has(domainChain)) {\n refuseSubBudgetChild(\n 'it is scoped to a chain the delegation rail has no pinned contracts for',\n `Chains with pinned contracts: ${[...DIRECT_PAYMENT_CHAIN_IDS].join(', ')}; the child says ${String(td.domain?.chainId)}.`,\n )\n }\n if (domainChain !== expected.chainId) {\n refuseSubBudgetChild(\n 'it is scoped to the wrong chain',\n `Expected chain ${expected.chainId}; the child says ${td.domain?.chainId}.`,\n )\n }\n\n const ownAccount = deriveDelegateAccountAddress(delegateAddress as Address)\n const delegator = td.message?.delegator\n if (typeof delegator !== 'string' || !same(delegator, ownAccount)) {\n refuseSubBudgetChild(\n \"it is not delegated by this agent's own account\",\n `Expected delegator ${ownAccount}; the child names ${String(delegator)}.`,\n )\n }\n if (!same(delegator, expected.delegateAccount)) {\n refuseSubBudgetChild(\n 'its delegator does not match the account Haven declared',\n `Expected ${expected.delegateAccount}; the child names ${String(delegator)}.`,\n )\n }\n const delegate = td.message?.delegate\n if (typeof delegate !== 'string' || !same(delegate, expected.childDelegateAccount)) {\n refuseSubBudgetChild(\n 'its delegate does not match the declared child delegate',\n `Expected ${expected.childDelegateAccount}; the child names ${String(delegate)}.`,\n )\n }\n\n const authority = td.message?.authority\n if (typeof authority !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(authority)) {\n refuseSubBudgetChild('its authority is not a 32-byte delegation hash', `Got ${String(authority)}.`)\n }\n if (authority.toLowerCase() === ROOT_AUTHORITY) {\n refuseSubBudgetChild(\n 'it is a ROOT delegation, not a re-delegation of the delegating agent budget',\n 'A sub-budget always chains under the delegating agent budget delegation.',\n )\n }\n if (!same(authority, expected.parentDelegationHash)) {\n refuseSubBudgetChild(\n 'it chains under a different parent delegation',\n `Expected authority ${expected.parentDelegationHash}; the child says ${authority}.`,\n )\n }\n\n const caveats = (td.message?.caveats as Array<{ enforcer: string; terms: string }> | undefined) ?? []\n\n // The PERIOD caveat is what makes this a sub-budget — a hard-cap\n // `ERC20TransferAmountEnforcer` caveat is the task-budget shape and is\n // refused on this channel.\n if (findCaveat(caveats, CAVEAT_ENFORCERS.erc20TransferAmount)) {\n refuseSubBudgetChild(\n 'it carries a hard-cap transfer-amount caveat (the task-budget shape)',\n 'A sub-budget is period-scoped: its amount caveat must be an ERC20PeriodTransferEnforcer ' +\n 'caveat slicing the parent period meter, never a lifetime cap.',\n )\n }\n const period = findCaveat(caveats, ERC20_PERIOD_TRANSFER_ENFORCER)\n if (!period) {\n refuseSubBudgetChild(\n 'it has no ERC-20 period-transfer caveat',\n 'Without it the child is not bounded to a per-period amount.',\n )\n }\n // terms = abi.encodePacked(address token, uint256 periodAmount,\n // uint256 periodDuration, uint256 startDate) — the kit's TIGHT packing\n // (20 + 32×3 = 116 bytes, verified against `createDelegation`'s own\n // output), the same layout `task-budget-guards.ts` decodes for the\n // ERC20TransferAmountEnforcer. NOT head/tail-padded words: the address\n // occupies bytes [0,20) and the amount starts at byte 20.\n const token = `0x${sliceTerms(period.terms, 0, 20)}`\n if (!same(token, expected.tokenAddress)) {\n refuseSubBudgetChild('it spends a different token', `Expected ${expected.tokenAddress}, child pins ${token}.`)\n }\n const periodAmount = BigInt(`0x${sliceTerms(period.terms, 20, 52)}`)\n if (periodAmount !== BigInt(expected.periodAmountAtomic)) {\n refuseSubBudgetChild(\n 'the period amount does not match',\n `Expected ${expected.periodAmountAtomic}; the child allows ${periodAmount.toString()}.`,\n )\n }\n const periodDuration = Number(BigInt(`0x${sliceTerms(period.terms, 52, 84)}`))\n if (periodDuration !== expected.periodDurationSeconds) {\n refuseSubBudgetChild(\n 'its period duration does not match the parent window Haven declared',\n `Expected ${expected.periodDurationSeconds}s; the child says ${periodDuration}s. A sub-budget is a ` +\n 'slice of the parent period meter — same window, smaller amount — never a different clock.',\n )\n }\n const startDate = Number(BigInt(`0x${sliceTerms(period.terms, 84, 116)}`))\n if (startDate !== expected.startDate) {\n refuseSubBudgetChild(\n 'its period start does not match the parent anchor Haven declared',\n `Expected ${expected.startDate}; the child says ${startDate}.`,\n )\n }\n\n const timestamp = findCaveat(caveats, CAVEAT_ENFORCERS.timestamp)\n if (!timestamp) {\n refuseSubBudgetChild('it never expires', 'A sub-budget child without a timestamp caveat is open-ended.')\n }\n const beforeThreshold = Number(BigInt(`0x${sliceTerms(timestamp.terms, 16, 32)}`))\n const nowSec = Math.floor(now / 1000)\n if (beforeThreshold <= nowSec) {\n refuseSubBudgetChild('it has already expired', `Expiry ${beforeThreshold} is not in the future.`)\n }\n if (beforeThreshold !== expected.expiresAt) {\n refuseSubBudgetChild(\n 'its expiry does not match what Haven declared',\n `Expected ${expected.expiresAt}; the child says ${beforeThreshold}.`,\n )\n }\n\n const calldata = findCaveat(caveats, CAVEAT_ENFORCERS.allowedCalldata)\n if (expected.recipientAddress) {\n if (!calldata) {\n refuseSubBudgetChild(\n 'it has no recipient pin',\n 'The sub-budget was issued with a pinned recipient, so the child must carry one.',\n )\n }\n const startIndex = BigInt(`0x${sliceTerms(calldata.terms, 0, 32)}`)\n if (startIndex !== 4n) {\n refuseSubBudgetChild(\n 'the recipient pin points at the wrong calldata offset',\n `Expected offset 4, got ${startIndex.toString()}.`,\n )\n }\n const paddedRecipient = sliceTerms(calldata.terms, 32, 64)\n if (paddedRecipient.slice(0, 24) !== '0'.repeat(24)) {\n refuseSubBudgetChild('the pinned recipient is not a plain address', 'Its 32-byte word is not a padded address.')\n }\n const recipient = `0x${paddedRecipient.slice(24)}`\n if (!same(recipient, expected.recipientAddress)) {\n refuseSubBudgetChild(\n 'it pins a different recipient than Haven declared',\n `Expected ${expected.recipientAddress}; the child pins ${recipient}.`,\n )\n }\n } else if (calldata) {\n refuseSubBudgetChild(\n 'it pins a recipient the sub-budget was not issued with',\n 'This sub-budget is open (no recipient pin); the child must not add one.',\n )\n }\n}\n\n/** Close UserOp verification — byte-for-byte the task-budget discipline. */\nexport function assertOwnSubBudgetCloseUserOp(\n typedData: Record<string, unknown>,\n expected: { delegationHash: string },\n delegateAddress: string,\n): void {\n // The close UserOp shape is identical to the task budget's: a\n // disableDelegation(child) call from the agent's own delegate account.\n // Reuse the task-budget verifier — the only expectation that differs is\n // the delegation hash, which is an input here either way. Static import,\n // not lazy: these modules share no init-time cycle.\n assertOwnTaskBudgetCloseUserOp(typedData, expected, delegateAddress)\n}\n\n// The close-UserOp verifier is imported for the re-export above.\nimport { assertOwnTaskBudgetCloseUserOp } from './task-budget-guards.js'\n"]}