@owney/sdk 0.7.27-beta.2 → 0.7.27-beta.3

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.cjs CHANGED
@@ -1,8 +1,18 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res, err) => function __init() {
9
+ if (err) throw err[0];
10
+ try {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ } catch (e) {
13
+ throw err = [e], e;
14
+ }
15
+ };
6
16
  var __export = (target, all) => {
7
17
  for (var name in all)
8
18
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -15,153 +25,76 @@ var __copyProps = (to, from, except, desc) => {
15
25
  }
16
26
  return to;
17
27
  };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
18
36
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
37
 
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- AgentChainIncompatibleError: () => AgentChainIncompatibleError,
24
- AgentNotFoundError: () => AgentNotFoundError,
25
- InvalidHistoryCursorError: () => InvalidHistoryCursorError,
26
- NotConnectedError: () => NotConnectedError,
27
- OwneyError: () => OwneyError,
28
- OwneySDK: () => OwneySDK,
29
- YieldseekerAgent: () => YieldseekerAgent,
30
- clearWithdrawSwap: () => clearWithdrawSwap,
31
- createOwneySIWX: () => createOwneySIWX,
32
- listPendingDeposits: () => listPendingDeposits,
33
- listPendingSwaps: () => listOrders,
34
- listWithdrawSwaps: () => listWithdrawSwaps,
35
- saveWithdrawSwap: () => saveWithdrawSwap,
36
- setOwneyDebug: () => setOwneyDebug,
37
- subscribeWithdrawSwaps: () => subscribeWithdrawSwaps,
38
- updateWithdrawSwap: () => updateWithdrawSwap
39
- });
40
- module.exports = __toCommonJS(index_exports);
41
-
42
38
  // src/errors.ts
43
- var OwneyError = class extends Error {
44
- code;
45
- details;
46
- agentId;
47
- constructor(code, message, details, agentId) {
48
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
49
- super(`${prefix} ${message}`);
50
- this.name = "OwneyError";
51
- this.code = code;
52
- this.details = details;
53
- this.agentId = agentId;
54
- }
55
- };
56
- var AgentNotFoundError = class extends OwneyError {
57
- constructor(agentId, available) {
58
- super(
59
- "AGENT_NOT_FOUND",
60
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
61
- { agentId, available },
62
- agentId
63
- );
64
- this.name = "AgentNotFoundError";
65
- }
66
- };
67
- var NotConnectedError = class extends OwneyError {
68
- constructor() {
69
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
70
- this.name = "NotConnectedError";
71
- }
72
- };
73
- var AgentChainIncompatibleError = class extends OwneyError {
74
- incompatibleAgents;
75
- connectedChainId;
76
- constructor(incompatibleAgents, connectedChainId) {
77
- const details = incompatibleAgents.map(
78
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
79
- ).join("; ");
80
- super(
81
- "AGENT_CHAIN_INCOMPATIBLE",
82
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
83
- { incompatibleAgents, connectedChainId }
84
- );
85
- this.name = "AgentChainIncompatibleError";
86
- this.incompatibleAgents = incompatibleAgents;
87
- this.connectedChainId = connectedChainId;
88
- }
89
- };
90
-
91
- // src/lib/swap/swap.observation.ts
92
- var active = /* @__PURE__ */ new Set();
93
- var isOrderObserved = (key2) => active.has(key2);
94
- async function observeOrder(key2, run) {
95
- const busy = () => new OwneyError(
96
- "SWAP_REQUEST_FAILED",
97
- "This order is already being observed.",
98
- { orderHash: key2, watchActive: true, settlementUnconfirmed: true }
99
- );
100
- if (active.has(key2)) throw busy();
101
- active.add(key2);
102
- try {
103
- if (typeof navigator !== "undefined" && navigator.locks)
104
- return await navigator.locks.request(`owney.swap.observe:${key2}`, { ifAvailable: true }, (lock) => {
105
- if (!lock) throw busy();
106
- return run();
107
- });
108
- return await run();
109
- } finally {
110
- active.delete(key2);
111
- }
112
- }
113
-
114
- // src/lib/swap/swap.deadline.ts
115
- async function bounded(work, timeoutMs, error) {
116
- if (timeoutMs <= 0) throw error();
117
- let timer;
118
- try {
119
- return await Promise.race([
120
- Promise.resolve().then(work),
121
- new Promise((_, reject) => {
122
- timer = setTimeout(() => reject(error()), timeoutMs);
123
- })
124
- ]);
125
- } finally {
126
- clearTimeout(timer);
39
+ var OwneyError, AgentNotFoundError, NotConnectedError, AgentChainIncompatibleError;
40
+ var init_errors = __esm({
41
+ "src/errors.ts"() {
42
+ "use strict";
43
+ OwneyError = class extends Error {
44
+ code;
45
+ details;
46
+ agentId;
47
+ constructor(code, message, details, agentId) {
48
+ const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
49
+ super(`${prefix} ${message}`);
50
+ this.name = "OwneyError";
51
+ this.code = code;
52
+ this.details = details;
53
+ this.agentId = agentId;
54
+ }
55
+ };
56
+ AgentNotFoundError = class extends OwneyError {
57
+ constructor(agentId, available) {
58
+ super(
59
+ "AGENT_NOT_FOUND",
60
+ `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
61
+ { agentId, available },
62
+ agentId
63
+ );
64
+ this.name = "AgentNotFoundError";
65
+ }
66
+ };
67
+ NotConnectedError = class extends OwneyError {
68
+ constructor() {
69
+ super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
70
+ this.name = "NotConnectedError";
71
+ }
72
+ };
73
+ AgentChainIncompatibleError = class extends OwneyError {
74
+ incompatibleAgents;
75
+ connectedChainId;
76
+ constructor(incompatibleAgents, connectedChainId) {
77
+ const details = incompatibleAgents.map(
78
+ ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
79
+ ).join("; ");
80
+ super(
81
+ "AGENT_CHAIN_INCOMPATIBLE",
82
+ `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
83
+ { incompatibleAgents, connectedChainId }
84
+ );
85
+ this.name = "AgentChainIncompatibleError";
86
+ this.incompatibleAgents = incompatibleAgents;
87
+ this.connectedChainId = connectedChainId;
88
+ }
89
+ };
127
90
  }
128
- }
129
- async function mapConcurrent(items, run, concurrency = 3) {
130
- const results = new Array(items.length);
131
- let next = 0;
132
- await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, async () => {
133
- for (; ; ) {
134
- const index = next++;
135
- if (index >= items.length) return;
136
- results[index] = await run(items[index]);
137
- }
138
- }));
139
- return results;
140
- }
91
+ });
141
92
 
142
93
  // src/lib/permit2-batch.ts
143
- var import_viem = require("viem");
144
- var BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
145
- var BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
146
- var ARBITRUM_USDC_ADDRESS = "0xaf88d065e77c8cc2239327c5edb3a432268e5831";
147
94
  function supportsSponsoredErc2612(chainId, token) {
148
95
  const expected = chainId === 8453 ? BASE_USDC_ADDRESS : chainId === 42161 ? ARBITRUM_USDC_ADDRESS : void 0;
149
96
  return expected !== void 0 && token.toLowerCase() === expected.toLowerCase();
150
97
  }
151
- var ERC2612_PERMIT_TYPES = {
152
- Permit: [
153
- { name: "owner", type: "address" },
154
- { name: "spender", type: "address" },
155
- { name: "value", type: "uint256" },
156
- { name: "nonce", type: "uint256" },
157
- { name: "deadline", type: "uint256" }
158
- ]
159
- };
160
- var ERC2612_READ_ABI = (0, import_viem.parseAbi)([
161
- "function name() view returns (string)",
162
- "function version() view returns (string)",
163
- "function nonces(address owner) view returns (uint256)"
164
- ]);
165
98
  function erc2612TypedData(input) {
166
99
  return {
167
100
  domain: {
@@ -181,27 +114,6 @@ function erc2612TypedData(input) {
181
114
  }
182
115
  };
183
116
  }
184
- var PERMIT_BATCH_TYPES = {
185
- PermitBatchWitnessTransferFrom: [
186
- { name: "permitted", type: "TokenPermissions[]" },
187
- { name: "spender", type: "address" },
188
- { name: "nonce", type: "uint256" },
189
- { name: "deadline", type: "uint256" },
190
- { name: "witness", type: "Deposit" }
191
- ],
192
- Deposit: [{ name: "recipients", type: "address[]" }],
193
- TokenPermissions: [
194
- { name: "token", type: "address" },
195
- { name: "amount", type: "uint256" }
196
- ]
197
- };
198
- var PERMIT2_BATCH_ABI = (0, import_viem.parseAbi)([
199
- "struct TokenPermissions { address token; uint256 amount; }",
200
- "struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
201
- "struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
202
- "function permitWitnessTransferFrom(PermitBatchTransferFrom permit,SignatureTransferDetails[] transferDetails,address owner,bytes32 witness,string witnessTypeString,bytes signature)",
203
- "function nonceBitmap(address owner,uint256 wordPos) view returns (uint256)"
204
- ]);
205
117
  function batchPermit(b) {
206
118
  return {
207
119
  permitted: b.transfers.map((t) => ({
@@ -228,7 +140,6 @@ function batchTypedData(b, spender) {
228
140
  }
229
141
  };
230
142
  }
231
- var BATCH_WITNESS_TYPE = "Deposit witness)Deposit(address[] recipients)TokenPermissions(address token,uint256 amount)";
232
143
  function batchWitness(b) {
233
144
  return (0, import_viem.hashStruct)({
234
145
  types: PERMIT_BATCH_TYPES,
@@ -246,9 +157,451 @@ function batchArgs(b) {
246
157
  b.signature
247
158
  ];
248
159
  }
160
+ var import_viem, BATCH_PERMIT2_ADDRESS, BASE_USDC_ADDRESS, ARBITRUM_USDC_ADDRESS, ERC2612_PERMIT_TYPES, ERC2612_READ_ABI, PERMIT_BATCH_TYPES, PERMIT2_BATCH_ABI, BATCH_WITNESS_TYPE;
161
+ var init_permit2_batch = __esm({
162
+ "src/lib/permit2-batch.ts"() {
163
+ "use strict";
164
+ import_viem = require("viem");
165
+ BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
166
+ BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
167
+ ARBITRUM_USDC_ADDRESS = "0xaf88d065e77c8cc2239327c5edb3a432268e5831";
168
+ ERC2612_PERMIT_TYPES = {
169
+ Permit: [
170
+ { name: "owner", type: "address" },
171
+ { name: "spender", type: "address" },
172
+ { name: "value", type: "uint256" },
173
+ { name: "nonce", type: "uint256" },
174
+ { name: "deadline", type: "uint256" }
175
+ ]
176
+ };
177
+ ERC2612_READ_ABI = (0, import_viem.parseAbi)([
178
+ "function name() view returns (string)",
179
+ "function version() view returns (string)",
180
+ "function nonces(address owner) view returns (uint256)"
181
+ ]);
182
+ PERMIT_BATCH_TYPES = {
183
+ PermitBatchWitnessTransferFrom: [
184
+ { name: "permitted", type: "TokenPermissions[]" },
185
+ { name: "spender", type: "address" },
186
+ { name: "nonce", type: "uint256" },
187
+ { name: "deadline", type: "uint256" },
188
+ { name: "witness", type: "Deposit" }
189
+ ],
190
+ Deposit: [{ name: "recipients", type: "address[]" }],
191
+ TokenPermissions: [
192
+ { name: "token", type: "address" },
193
+ { name: "amount", type: "uint256" }
194
+ ]
195
+ };
196
+ PERMIT2_BATCH_ABI = (0, import_viem.parseAbi)([
197
+ "struct TokenPermissions { address token; uint256 amount; }",
198
+ "struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
199
+ "struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
200
+ "function permitWitnessTransferFrom(PermitBatchTransferFrom permit,SignatureTransferDetails[] transferDetails,address owner,bytes32 witness,string witnessTypeString,bytes signature)",
201
+ "function nonceBitmap(address owner,uint256 wordPos) view returns (uint256)"
202
+ ]);
203
+ BATCH_WITNESS_TYPE = "Deposit witness)Deposit(address[] recipients)TokenPermissions(address token,uint256 amount)";
204
+ }
205
+ });
206
+
207
+ // src/lib/token-batch-family.ts
208
+ var token_batch_family_exports = {};
209
+ __export(token_batch_family_exports, {
210
+ finishTokenBatchFamily: () => finishTokenBatchFamily,
211
+ loadTokenBatchFamily: () => loadTokenBatchFamily,
212
+ saveTokenBatchAttempt: () => saveTokenBatchAttempt,
213
+ tokenBatchAuthorizationId: () => tokenBatchAuthorizationId,
214
+ tokenBatchCall: () => tokenBatchCall,
215
+ tokenBatchClear: () => tokenBatchClear,
216
+ tokenBatchKey: () => tokenBatchKey,
217
+ tokenBatchRead: () => tokenBatchRead,
218
+ tokenBatchStoredBody: () => tokenBatchStoredBody,
219
+ tokenBatchWrite: () => tokenBatchWrite,
220
+ validateTokenBatchAttempt: () => validateTokenBatchAttempt
221
+ });
222
+ function tokenBatchRead(key2) {
223
+ const raw2 = typeof window === "undefined" ? memory.get(key2) : window.localStorage.getItem(key2) ?? void 0;
224
+ return raw2 && settled.get(key2) === raw2 ? void 0 : raw2;
225
+ }
226
+ function tokenBatchWrite(key2, value) {
227
+ if (typeof window === "undefined") memory.set(key2, value);
228
+ else window.localStorage.setItem(key2, value);
229
+ settled.delete(key2);
230
+ if (tokenBatchRead(key2) !== value)
231
+ throw pending("Deposit recovery data could not be saved.");
232
+ }
233
+ function tokenBatchClear(key2, expected) {
234
+ if (tokenBatchRead(key2) !== expected) return;
235
+ try {
236
+ if (typeof window === "undefined") memory.delete(key2);
237
+ else window.localStorage.removeItem(key2);
238
+ } catch {
239
+ settled.set(key2, expected);
240
+ }
241
+ }
242
+ function keys() {
243
+ if (typeof window === "undefined") return [...memory.keys()];
244
+ const storage8 = window.localStorage;
245
+ return Array.from(
246
+ { length: storage8.length },
247
+ (_, i) => storage8.key(i)
248
+ ).filter((key2) => key2 !== null);
249
+ }
250
+ function pending(message = "The saved deposit could not be verified. Its existing transactions remain pending.") {
251
+ return new OwneyError("DEPOSIT_IN_PROGRESS", message, {
252
+ sponsorPending: true,
253
+ notSubmitted: false,
254
+ safeToFallback: false
255
+ });
256
+ }
257
+ function tokenBatchCall(body, phase) {
258
+ if (phase === "deposit")
259
+ return {
260
+ to: BATCH_PERMIT2_ADDRESS,
261
+ data: (0, import_viem2.encodeFunctionData)({
262
+ abi: PERMIT2_BATCH_ABI,
263
+ functionName: "permitWitnessTransferFrom",
264
+ args: batchArgs(body)
265
+ })
266
+ };
267
+ const p = body.erc2612Permit;
268
+ let v = Number((0, import_viem2.sliceHex)(p.signature, 64));
269
+ if (v < 27) v += 27;
270
+ return {
271
+ to: body.token,
272
+ data: (0, import_viem2.encodeFunctionData)({
273
+ abi: approvalAbi,
274
+ functionName: "permit",
275
+ args: [
276
+ body.from,
277
+ BATCH_PERMIT2_ADDRESS,
278
+ BigInt(p.value),
279
+ BigInt(p.deadline),
280
+ v,
281
+ (0, import_viem2.sliceHex)(p.signature, 0, 32),
282
+ (0, import_viem2.sliceHex)(p.signature, 32, 64)
283
+ ]
284
+ })
285
+ };
286
+ }
287
+ async function validateBody(scope, body, relayer) {
288
+ if (!body || body.chainId !== scope.chainId || !(0, import_viem2.isAddressEqual)(body.from, scope.owner) || !(0, import_viem2.isAddressEqual)(body.token, scope.token) || !uint(body.nonce) || !uint(body.deadline) || BigInt(body.deadline) === 0n || !Array.isArray(body.transfers) || !body.transfers.length || body.transfers.length > 16 || body.transfers.some(
289
+ (t) => !(0, import_viem2.isAddress)(t.to) || !uint(t.amount) || BigInt(t.amount) === 0n
290
+ ) || new Set(body.transfers.map((t) => t.to.toLowerCase())).size !== body.transfers.length)
291
+ throw pending();
292
+ if (!(0, import_viem2.isAddressEqual)(
293
+ await (0, import_viem2.recoverTypedDataAddress)({
294
+ ...batchTypedData(body, relayer),
295
+ signature: body.signature
296
+ }),
297
+ body.from
298
+ ))
299
+ throw pending();
300
+ const p = body.erc2612Permit;
301
+ if (p) {
302
+ if (!supportsSponsoredErc2612(body.chainId, body.token) || !uint(p.nonce) || !uint(p.deadline) || !uint(p.value) || BigInt(p.value) !== (1n << 256n) - 1n || p.deadline !== body.deadline || typeof p.tokenName !== "string" || typeof p.tokenVersion !== "string")
303
+ throw pending();
304
+ if (!(0, import_viem2.isAddressEqual)(
305
+ await (0, import_viem2.recoverTypedDataAddress)({
306
+ ...erc2612TypedData({
307
+ chainId: body.chainId,
308
+ token: body.token,
309
+ owner: body.from,
310
+ permit: p
311
+ }),
312
+ signature: p.signature
313
+ }),
314
+ body.from
315
+ ))
316
+ throw pending();
317
+ }
318
+ }
319
+ async function validateTokenBatchAttempt(scope, body, attempt, expectedRelayer) {
320
+ if (!attempt || !["approval", "deposit"].includes(attempt.phase) || !hashPattern.test(attempt.hash) || !uint(attempt.nonce) || !Number.isFinite(attempt.preparedAt) || typeof attempt.submissionAttempted !== "boolean" || attempt.predecessorHash !== void 0 && !hashPattern.test(attempt.predecessorHash))
321
+ throw pending();
322
+ if (typeof attempt.serializedTransaction !== "string" || !/^0x(?:[\da-f]{2}){1,32768}$/i.test(attempt.serializedTransaction))
323
+ throw pending();
324
+ const serialized = attempt.serializedTransaction;
325
+ if (!same((0, import_viem2.keccak256)(serialized), attempt.hash)) throw pending();
326
+ const tx = (0, import_viem2.parseTransaction)(serialized), relayer = await (0, import_viem2.recoverTransactionAddress)({
327
+ serializedTransaction: serialized
328
+ });
329
+ if (expectedRelayer && !(0, import_viem2.isAddressEqual)(relayer, expectedRelayer))
330
+ throw pending();
331
+ await validateBody(scope, body, relayer);
332
+ const call = tokenBatchCall(body, attempt.phase);
333
+ if (tx.chainId !== body.chainId || !tx.to || !(0, import_viem2.isAddressEqual)(tx.to, call.to) || (tx.value ?? 0n) !== 0n || tx.data !== call.data || !Number.isSafeInteger(tx.nonce) || String(tx.nonce) !== attempt.nonce)
334
+ throw pending();
335
+ return relayer;
336
+ }
337
+ function terminalOf(value, attempts) {
338
+ if (!value || !["confirmed", "failed", "expired"].includes(value.kind) || !uint(value.blockNumber))
339
+ return;
340
+ if (value.kind === "confirmed" && (!value.txHash || !attempts.some(
341
+ (a) => a.phase === "deposit" && same(a.hash, value.txHash)
342
+ )))
343
+ return;
344
+ if (value.txHash !== void 0 && !hashPattern.test(value.txHash)) return;
345
+ return {
346
+ kind: value.kind,
347
+ blockNumber: value.blockNumber,
348
+ ...value.txHash ? { txHash: value.txHash } : {}
349
+ };
350
+ }
351
+ async function validateFamily(scope, raw2) {
352
+ if (!raw2 || raw2.version !== 1 || !Array.isArray(raw2.attempts) || !raw2.attempts.length || !raw2.current || !(0, import_viem2.isAddress)(raw2.relayer) || !hashPattern.test(raw2.authorizationId))
353
+ throw pending();
354
+ if (!same(tokenBatchAuthorizationId(raw2.body, raw2.relayer), raw2.authorizationId))
355
+ throw pending();
356
+ const seen = /* @__PURE__ */ new Map();
357
+ const roots = /* @__PURE__ */ new Set();
358
+ for (const a of raw2.attempts) {
359
+ await validateTokenBatchAttempt(scope, raw2.body, a, raw2.relayer);
360
+ if (seen.has(a.hash.toLowerCase())) throw pending();
361
+ if (a.predecessorHash) {
362
+ const predecessor = seen.get(a.predecessorHash.toLowerCase());
363
+ if (!predecessor || predecessor.phase !== a.phase || BigInt(a.nonce) <= BigInt(predecessor.nonce))
364
+ throw pending();
365
+ } else {
366
+ if (roots.has(a.phase)) throw pending();
367
+ roots.add(a.phase);
368
+ }
369
+ seen.set(a.hash.toLowerCase(), a);
370
+ }
371
+ for (const phase of ["approval", "deposit"]) {
372
+ const current = raw2.current[phase];
373
+ if (current && !raw2.attempts.some((a) => a.phase === phase && same(a.hash, current)))
374
+ throw pending();
375
+ if (raw2.attempts.some((a) => a.phase === phase) && !current)
376
+ throw pending();
377
+ }
378
+ return {
379
+ ...raw2,
380
+ body: tokenBatchStoredBody(raw2.body),
381
+ terminal: terminalOf(raw2.terminal, raw2.attempts)
382
+ };
383
+ }
384
+ async function importBody(scope, body) {
385
+ const attempts = [];
386
+ let relayer;
387
+ for (const phase of ["approval", "deposit"]) {
388
+ const bytes = phase === "approval" ? body.serializedPermitTransaction : body.serializedTransaction;
389
+ if (!bytes) continue;
390
+ const a = {
391
+ phase,
392
+ hash: (0, import_viem2.keccak256)(bytes),
393
+ serializedTransaction: bytes,
394
+ nonce: String((0, import_viem2.parseTransaction)(bytes).nonce),
395
+ preparedAt: 0,
396
+ submissionAttempted: true
397
+ };
398
+ relayer = await validateTokenBatchAttempt(scope, body, a, relayer);
399
+ attempts.push(a);
400
+ }
401
+ if (!relayer) return;
402
+ return {
403
+ version: 1,
404
+ authorizationId: tokenBatchAuthorizationId(body, relayer),
405
+ relayer,
406
+ body: tokenBatchStoredBody(body),
407
+ attempts,
408
+ current: Object.fromEntries(attempts.map((a) => [a.phase, a.hash]))
409
+ };
410
+ }
411
+ function merge(base7, incoming) {
412
+ if (!same(base7.authorizationId, incoming.authorizationId)) throw pending();
413
+ const attempts = base7.attempts.map((a) => ({ ...a }));
414
+ for (const a of incoming.attempts) {
415
+ const existing = attempts.find((x) => same(x.hash, a.hash));
416
+ if (existing) existing.submissionAttempted ||= a.submissionAttempted;
417
+ else attempts.push(a);
418
+ }
419
+ return { ...base7, attempts };
420
+ }
421
+ async function loadTokenBatchFamily(scope, expectedHash, allowMissing = false) {
422
+ try {
423
+ const key2 = tokenBatchKey(scope), records = /* @__PURE__ */ new Map();
424
+ for (const k of keys().filter((k2) => k2.startsWith(`${key2}:family:`))) {
425
+ const raw2 = tokenBatchRead(k);
426
+ if (!raw2) continue;
427
+ const family = await validateFamily(scope, JSON.parse(raw2));
428
+ if (k !== `${key2}:family:${family.authorizationId}`) throw pending();
429
+ records.set(family.authorizationId, family);
430
+ }
431
+ let projectedId;
432
+ const projection = tokenBatchRead(key2);
433
+ if (projection) {
434
+ const imported = await importBody(scope, JSON.parse(projection));
435
+ if (imported) {
436
+ projectedId = imported.authorizationId;
437
+ const stored = records.get(projectedId);
438
+ if (stored)
439
+ for (const attempt of imported.attempts) {
440
+ const known = stored.attempts.find(
441
+ (a) => same(a.hash, attempt.hash)
442
+ );
443
+ if (known) attempt.submissionAttempted = known.submissionAttempted;
444
+ }
445
+ records.set(
446
+ projectedId,
447
+ stored ? await validateFamily(scope, merge(stored, imported)) : imported
448
+ );
449
+ }
450
+ }
451
+ if (expectedHash) {
452
+ let found = [...records.values()].filter(
453
+ (f) => f.attempts.some((a) => same(a.hash, expectedHash))
454
+ );
455
+ if (!found.length) {
456
+ const archive = tokenBatchRead(
457
+ `${key2}:expired:${expectedHash.toLowerCase()}`
458
+ );
459
+ if (archive) {
460
+ const f = await importBody(scope, JSON.parse(archive));
461
+ if (f?.attempts.some((a) => same(a.hash, expectedHash))) found = [f];
462
+ }
463
+ }
464
+ if (!found.length && allowMissing) return;
465
+ if (found.length !== 1) throw pending();
466
+ return found[0];
467
+ }
468
+ const active2 = [...records.values()].filter(
469
+ (f) => !f.terminal || f.authorizationId === projectedId
470
+ );
471
+ if (active2.length > 1) throw pending();
472
+ return active2[0];
473
+ } catch (error) {
474
+ if (error instanceof OwneyError) throw error;
475
+ throw pending();
476
+ }
477
+ }
478
+ async function saveTokenBatchAttempt(scope, body, attempt, assertCurrent = () => {
479
+ }) {
480
+ try {
481
+ const relayer = await validateTokenBatchAttempt(scope, body, attempt), id = tokenBatchAuthorizationId(body, relayer), key2 = tokenBatchKey(scope), sidecar = `${key2}:family:${id}`;
482
+ const prior = await loadTokenBatchFamily(scope);
483
+ if (prior && prior.authorizationId !== id) throw pending();
484
+ let family = prior ?? {
485
+ version: 1,
486
+ authorizationId: id,
487
+ relayer,
488
+ body: tokenBatchStoredBody(body),
489
+ attempts: [],
490
+ current: {}
491
+ };
492
+ const saved = tokenBatchRead(sidecar);
493
+ if (saved)
494
+ family = merge(await validateFamily(scope, JSON.parse(saved)), family);
495
+ const sameAttempt = family.attempts.find((a) => same(a.hash, attempt.hash));
496
+ if (sameAttempt)
497
+ sameAttempt.submissionAttempted ||= attempt.submissionAttempted;
498
+ else family.attempts.push({ ...attempt });
499
+ family.current[attempt.phase] = attempt.hash;
500
+ family.body = { ...tokenBatchStoredBody(body) };
501
+ for (const phase of ["approval", "deposit"]) {
502
+ const current = family.attempts.find(
503
+ (a) => a.hash === family.current[phase]
504
+ );
505
+ if (current)
506
+ family.body[phase === "deposit" ? "serializedTransaction" : "serializedPermitTransaction"] = current.serializedTransaction;
507
+ }
508
+ family = await validateFamily(scope, family);
509
+ if (tokenBatchRead(sidecar) !== saved)
510
+ throw pending(
511
+ "Deposit recovery data changed. Retry the existing deposit."
512
+ );
513
+ assertCurrent();
514
+ tokenBatchWrite(sidecar, JSON.stringify(family));
515
+ assertCurrent();
516
+ tokenBatchWrite(key2, JSON.stringify(family.body));
517
+ return family;
518
+ } catch (error) {
519
+ if (error instanceof OwneyError) throw error;
520
+ throw pending(
521
+ "Deposit recovery data could not be saved. The earlier transaction remains tracked."
522
+ );
523
+ }
524
+ }
525
+ function finishTokenBatchFamily(scope, family, terminal) {
526
+ const key2 = tokenBatchKey(scope), sidecar = `${key2}:family:${family.authorizationId}`;
527
+ try {
528
+ const saved = tokenBatchRead(sidecar), current = saved ? JSON.parse(saved) : family;
529
+ if (current.authorizationId !== family.authorizationId) return;
530
+ if (terminal.kind !== "confirmed" && current.attempts.some(
531
+ (a) => !family.attempts.some((known) => same(known.hash, a.hash))
532
+ ))
533
+ return;
534
+ const evidence = terminalOf(terminal, current.attempts);
535
+ if (!evidence) return;
536
+ tokenBatchWrite(
537
+ sidecar,
538
+ JSON.stringify({ ...current, terminal: evidence })
539
+ );
540
+ const projected = tokenBatchRead(key2);
541
+ if (projected && tokenBatchAuthorizationId(JSON.parse(projected), family.relayer) === family.authorizationId)
542
+ tokenBatchClear(key2, projected);
543
+ } catch {
544
+ }
545
+ }
546
+ var import_viem2, memory, settled, hashPattern, uint, same, tokenBatchKey, tokenBatchAuthorizationId, tokenBatchStoredBody, approvalAbi;
547
+ var init_token_batch_family = __esm({
548
+ "src/lib/token-batch-family.ts"() {
549
+ "use strict";
550
+ import_viem2 = require("viem");
551
+ init_errors();
552
+ init_permit2_batch();
553
+ memory = /* @__PURE__ */ new Map();
554
+ settled = /* @__PURE__ */ new Map();
555
+ hashPattern = /^0x[\da-f]{64}$/i;
556
+ uint = (value) => typeof value === "string" && /^\d{1,78}$/.test(value) && BigInt(value) < 1n << 256n;
557
+ same = (a, b) => a.toLowerCase() === b.toLowerCase();
558
+ tokenBatchKey = (s) => `owney.token-batch.v1:${(0, import_viem2.keccak256)((0, import_viem2.toBytes)(s.apiKey))}:${s.baseUrl ?? "default"}:${s.chainId}:${s.owner.toLowerCase()}:${s.token.toLowerCase()}`;
559
+ tokenBatchAuthorizationId = (body, relayer) => (0, import_viem2.keccak256)(
560
+ (0, import_viem2.encodeAbiParameters)(
561
+ [{ type: "address" }, { type: "bytes32" }],
562
+ [body.from, (0, import_viem2.hashTypedData)(batchTypedData(body, relayer))]
563
+ )
564
+ );
565
+ tokenBatchStoredBody = (body) => ({
566
+ ...body,
567
+ transfers: body.transfers.map(({ to, amount }) => ({ to, amount }))
568
+ });
569
+ approvalAbi = (0, import_viem2.parseAbi)([
570
+ "function permit(address owner,address spender,uint256 value,uint256 deadline,uint8 v,bytes32 r,bytes32 s)"
571
+ ]);
572
+ }
573
+ });
574
+
575
+ // src/index.ts
576
+ var index_exports = {};
577
+ __export(index_exports, {
578
+ AgentChainIncompatibleError: () => AgentChainIncompatibleError,
579
+ AgentNotFoundError: () => AgentNotFoundError,
580
+ InvalidHistoryCursorError: () => InvalidHistoryCursorError,
581
+ NotConnectedError: () => NotConnectedError,
582
+ OwneyError: () => OwneyError,
583
+ OwneySDK: () => OwneySDK,
584
+ YieldseekerAgent: () => YieldseekerAgent,
585
+ clearWithdrawSwap: () => clearWithdrawSwap,
586
+ createOwneySIWX: () => createOwneySIWX,
587
+ listPendingDeposits: () => listPendingDeposits,
588
+ listPendingSwaps: () => listOrders,
589
+ listWithdrawSwaps: () => listWithdrawSwaps,
590
+ saveWithdrawSwap: () => saveWithdrawSwap,
591
+ setOwneyDebug: () => setOwneyDebug,
592
+ subscribeWithdrawSwaps: () => subscribeWithdrawSwaps,
593
+ updateWithdrawSwap: () => updateWithdrawSwap
594
+ });
595
+ module.exports = __toCommonJS(index_exports);
596
+
597
+ // src/client.ts
598
+ init_token_batch_family();
599
+
600
+ // src/lib/token-batch-observer.ts
601
+ init_permit2_batch();
249
602
 
250
603
  // src/lib/funding-evidence.ts
251
- var import_viem2 = require("viem");
604
+ var import_viem3 = require("viem");
252
605
  var import_account_abstraction = require("viem/account-abstraction");
253
606
  function notifyFunding(callback, evidence) {
254
607
  try {
@@ -257,9 +610,9 @@ function notifyFunding(callback, evidence) {
257
610
  } catch {
258
611
  }
259
612
  }
260
- var fullWithdrawalAbi = (0, import_viem2.parseAbi)(["function withdrawAllAssetToUser(address recipient, address asset)"]);
261
- var withdrawalEventAbi = (0, import_viem2.parseAbi)(["event WithdrewTokenToUser(address indexed owner, address indexed recipient, address indexed token, uint256 amount)"]);
262
- var accountExecutionAbi = (0, import_viem2.parseAbi)([
613
+ var fullWithdrawalAbi = (0, import_viem3.parseAbi)(["function withdrawAllAssetToUser(address recipient, address asset)"]);
614
+ var withdrawalEventAbi = (0, import_viem3.parseAbi)(["event WithdrewTokenToUser(address indexed owner, address indexed recipient, address indexed token, uint256 amount)"]);
615
+ var accountExecutionAbi = (0, import_viem3.parseAbi)([
263
616
  "function execute(address target,uint256 value,bytes data)",
264
617
  "function executeBatch((address target,uint256 value,bytes data)[] calls)"
265
618
  ]);
@@ -269,7 +622,7 @@ function yieldseekerExecution(receipt, evidence) {
269
622
  const operationEvents = receipt.logs.flatMap((log) => {
270
623
  if (![entryPoint06, entryPoint07].includes(log.address.toLowerCase())) return [];
271
624
  try {
272
- const event = (0, import_viem2.decodeEventLog)({ abi: import_account_abstraction.entryPoint06Abi, data: log.data, topics: log.topics });
625
+ const event = (0, import_viem3.decodeEventLog)({ abi: import_account_abstraction.entryPoint06Abi, data: log.data, topics: log.topics });
273
626
  return event.eventName === "UserOperationEvent" ? [{ ...event.args, logIndex: log.logIndex }] : [];
274
627
  } catch {
275
628
  return [];
@@ -292,7 +645,7 @@ function isFullYieldseekerWithdrawal(transaction, evidence, tokenAddress, receip
292
645
  if (evidence.agentId !== "yieldseeker" || transaction.chainId !== evidence.chainId || transaction.hash.toLowerCase() !== evidence.txHash?.toLowerCase() || !evidence.agentWallet) return false;
293
646
  const matchesFullCall = (data) => {
294
647
  try {
295
- const decoded = (0, import_viem2.decodeFunctionData)({ abi: fullWithdrawalAbi, data });
648
+ const decoded = (0, import_viem3.decodeFunctionData)({ abi: fullWithdrawalAbi, data });
296
649
  return decoded.args[0].toLowerCase() === evidence.walletAddress.toLowerCase() && decoded.args[1].toLowerCase() === tokenAddress.toLowerCase();
297
650
  } catch {
298
651
  return false;
@@ -303,7 +656,7 @@ function isFullYieldseekerWithdrawal(transaction, evidence, tokenAddress, receip
303
656
  const address = transaction.to?.toLowerCase();
304
657
  if (address !== entryPoint06 && address !== entryPoint07) return false;
305
658
  const version = address === entryPoint06 ? "0.6" : "0.7";
306
- const decoded = (0, import_viem2.decodeFunctionData)({ abi: version === "0.6" ? import_account_abstraction.entryPoint06Abi : import_account_abstraction.entryPoint07Abi, data: transaction.input });
659
+ const decoded = (0, import_viem3.decodeFunctionData)({ abi: version === "0.6" ? import_account_abstraction.entryPoint06Abi : import_account_abstraction.entryPoint07Abi, data: transaction.input });
307
660
  if (decoded.functionName !== "handleOps") return false;
308
661
  const operations = decoded.args[0].filter((operation2) => [evidence.agentWallet.toLowerCase(), evidence.walletAddress.toLowerCase()].includes(operation2.sender.toLowerCase()));
309
662
  if (operations.length !== 1) return false;
@@ -319,14 +672,14 @@ function isFullYieldseekerWithdrawal(transaction, evidence, tokenAddress, receip
319
672
  if (!receipt?.logs.some((log) => {
320
673
  if (log.address.toLowerCase() !== address) return false;
321
674
  try {
322
- const event = (0, import_viem2.decodeEventLog)({ abi: import_account_abstraction.entryPoint06Abi, data: log.data, topics: log.topics });
675
+ const event = (0, import_viem3.decodeEventLog)({ abi: import_account_abstraction.entryPoint06Abi, data: log.data, topics: log.topics });
323
676
  return event.eventName === "UserOperationEvent" && event.args.userOpHash.toLowerCase() === hash2.toLowerCase() && event.args.sender.toLowerCase() === operation.sender.toLowerCase() && event.args.success;
324
677
  } catch {
325
678
  return false;
326
679
  }
327
680
  })) return false;
328
681
  if (operation.sender.toLowerCase() === evidence.agentWallet.toLowerCase()) return matchesFullCall(operation.callData);
329
- const execution = (0, import_viem2.decodeFunctionData)({ abi: accountExecutionAbi, data: operation.callData });
682
+ const execution = (0, import_viem3.decodeFunctionData)({ abi: accountExecutionAbi, data: operation.callData });
330
683
  const calls = execution.functionName === "execute" ? [{ target: execution.args[0], value: execution.args[1], data: execution.args[2] }] : execution.args[0];
331
684
  return calls.length === 1 && calls[0].value === 0n && calls[0].target.toLowerCase() === evidence.agentWallet.toLowerCase() && matchesFullCall(calls[0].data);
332
685
  } catch {
@@ -369,7 +722,7 @@ function inspectFundingReceipt(receipt, evidence, tokenAddress, direction, optio
369
722
  if (seen.has(log.logIndex)) continue;
370
723
  seen.add(log.logIndex);
371
724
  try {
372
- const event = (0, import_viem2.decodeEventLog)({ abi: import_viem2.erc20Abi, data: log.data, topics: log.topics });
725
+ const event = (0, import_viem3.decodeEventLog)({ abi: import_viem3.erc20Abi, data: log.data, topics: log.topics });
373
726
  if (event.eventName !== "Transfer") continue;
374
727
  const { from, to, value } = event.args;
375
728
  if (direction === "withdraw" && value === 0n && from.toLowerCase() === agent && to.toLowerCase() === owner)
@@ -393,7 +746,7 @@ function inspectFundingReceipt(receipt, evidence, tokenAddress, direction, optio
393
746
  const emptyPayout = direction === "withdraw" && evidence.agentId === "yieldseeker" && amount === 0n && zeroTransferLogs.length > 0 && execution.logs.some((log) => {
394
747
  if (log.address.toLowerCase() !== agent) return false;
395
748
  try {
396
- const { args } = (0, import_viem2.decodeEventLog)({ abi: withdrawalEventAbi, data: log.data, topics: log.topics });
749
+ const { args } = (0, import_viem3.decodeEventLog)({ abi: withdrawalEventAbi, data: log.data, topics: log.topics });
397
750
  return args.owner.toLowerCase() === owner && args.recipient.toLowerCase() === owner && args.token.toLowerCase() === tokenAddress.toLowerCase() && args.amount === 0n;
398
751
  } catch {
399
752
  return false;
@@ -425,6 +778,218 @@ function inspectFundingReceipt(receipt, evidence, tokenAddress, direction, optio
425
778
  };
426
779
  }
427
780
 
781
+ // src/lib/token-batch-observer.ts
782
+ init_token_batch_family();
783
+ var cursors = /* @__PURE__ */ new Map();
784
+ async function observeTokenBatchFamily(input) {
785
+ let expired = false, timer;
786
+ const assertCurrent = () => {
787
+ if (expired || Date.now() >= input.deadlineAt)
788
+ throw Error("observation ended");
789
+ input.assertCurrent();
790
+ };
791
+ const run = async () => {
792
+ assertCurrent();
793
+ const { scope, pub } = input;
794
+ const family = await loadTokenBatchFamily(
795
+ scope,
796
+ input.family.attempts[0].hash
797
+ );
798
+ assertCurrent();
799
+ if (!family || family.authorizationId !== input.family.authorizationId)
800
+ return { status: "unresolved" };
801
+ const attempts = family.attempts.filter((a) => a.phase === "deposit");
802
+ const key2 = `${tokenBatchKey(scope)}:${family.authorizationId}`;
803
+ const start = (cursors.get(key2) ?? 0) % Math.max(1, attempts.length);
804
+ const ordered = [...attempts.slice(start), ...attempts.slice(0, start)];
805
+ const reverted = [];
806
+ for (let index = 0; index < ordered.length; index += 3) {
807
+ assertCurrent();
808
+ const group = ordered.slice(index, index + 3);
809
+ cursors.set(key2, (start + index + group.length) % attempts.length);
810
+ const observations = await Promise.all(
811
+ group.map(async (attempt) => {
812
+ try {
813
+ await validateTokenBatchAttempt(
814
+ scope,
815
+ family.body,
816
+ attempt,
817
+ family.relayer
818
+ );
819
+ assertCurrent();
820
+ const receipt = await pub.getTransactionReceipt({
821
+ hash: attempt.hash
822
+ });
823
+ assertCurrent();
824
+ if (receipt.transactionHash?.toLowerCase() !== attempt.hash.toLowerCase() || typeof receipt.blockNumber !== "bigint" || !receipt.blockHash)
825
+ return;
826
+ if (receipt.status === "reverted")
827
+ return { kind: "reverted", receipt };
828
+ if (receipt.status !== "success" || receipt.from?.toLowerCase() !== family.relayer.toLowerCase() || receipt.to?.toLowerCase() !== BATCH_PERMIT2_ADDRESS.toLowerCase())
829
+ return;
830
+ const exact = family.body.transfers.every(
831
+ (t) => inspectFundingReceipt(
832
+ receipt,
833
+ {
834
+ agentId: "yieldseeker",
835
+ chainId: family.body.chainId,
836
+ token: "USDC",
837
+ walletAddress: family.body.from,
838
+ agentWallet: t.to,
839
+ intendedAmount: t.amount,
840
+ txHash: attempt.hash,
841
+ transfer: "pending",
842
+ registration: "pending",
843
+ delivery: "not-applicable"
844
+ },
845
+ family.body.token,
846
+ "deposit",
847
+ { requireAmountMatch: true }
848
+ ).transfer === "confirmed"
849
+ );
850
+ return exact ? { kind: "confirmed", receipt } : void 0;
851
+ } catch {
852
+ return;
853
+ }
854
+ })
855
+ );
856
+ assertCurrent();
857
+ const winner = observations.find((o) => o?.kind === "confirmed");
858
+ if (winner) {
859
+ const latest2 = await loadTokenBatchFamily(
860
+ scope,
861
+ winner.receipt.transactionHash
862
+ );
863
+ assertCurrent();
864
+ if (!latest2) return { status: "unresolved" };
865
+ finishTokenBatchFamily(scope, latest2, {
866
+ kind: "confirmed",
867
+ txHash: winner.receipt.transactionHash,
868
+ blockNumber: winner.receipt.blockNumber.toString()
869
+ });
870
+ return {
871
+ status: "confirmed",
872
+ txHash: winner.receipt.transactionHash,
873
+ receipt: winner.receipt
874
+ };
875
+ }
876
+ for (const o of observations)
877
+ if (o?.kind === "reverted") reverted.push(o.receipt);
878
+ }
879
+ const latest = await loadTokenBatchFamily(scope, family.attempts[0].hash);
880
+ assertCurrent();
881
+ if (!latest) return { status: "unresolved" };
882
+ if (attempts.length > 0 && reverted.length === latest.attempts.filter((a) => a.phase === "deposit").length) {
883
+ const block2 = reverted.reduce(
884
+ (n, r) => r.blockNumber > n ? r.blockNumber : n,
885
+ 0n
886
+ );
887
+ finishTokenBatchFamily(scope, latest, {
888
+ kind: "failed",
889
+ blockNumber: block2.toString()
890
+ });
891
+ return { status: "failed", receipts: reverted };
892
+ }
893
+ const block = await pub.getBlock({ blockTag: "finalized" });
894
+ assertCurrent();
895
+ if (typeof block.number !== "bigint" || !block.hash || typeof block.timestamp !== "bigint" || block.timestamp <= BigInt(family.body.deadline))
896
+ return { status: "unresolved" };
897
+ const nonce = BigInt(family.body.nonce);
898
+ const bitmap = await pub.readContract({
899
+ address: BATCH_PERMIT2_ADDRESS,
900
+ abi: PERMIT2_BATCH_ABI,
901
+ functionName: "nonceBitmap",
902
+ args: [family.body.from, nonce >> 8n],
903
+ blockNumber: block.number
904
+ });
905
+ assertCurrent();
906
+ if (typeof bitmap !== "bigint" || bitmap < 0n || bitmap >= 1n << 256n || (bitmap & 1n << (nonce & 255n)) !== 0n)
907
+ return { status: "unresolved" };
908
+ if ((await pub.getBlock({ blockNumber: block.number })).hash !== block.hash)
909
+ return { status: "unresolved" };
910
+ assertCurrent();
911
+ finishTokenBatchFamily(scope, latest, {
912
+ kind: "expired",
913
+ blockNumber: block.number.toString()
914
+ });
915
+ return { status: "expired", blockNumber: block.number };
916
+ };
917
+ try {
918
+ return await Promise.race([
919
+ run(),
920
+ new Promise((resolve) => {
921
+ timer = setTimeout(
922
+ () => {
923
+ expired = true;
924
+ resolve({ status: "unresolved" });
925
+ },
926
+ Math.max(0, input.deadlineAt - Date.now())
927
+ );
928
+ })
929
+ ]);
930
+ } catch {
931
+ return { status: "unresolved" };
932
+ } finally {
933
+ expired = true;
934
+ if (timer) clearTimeout(timer);
935
+ }
936
+ }
937
+
938
+ // src/lib/swap/swap.observation.ts
939
+ init_errors();
940
+ var active = /* @__PURE__ */ new Set();
941
+ var isOrderObserved = (key2) => active.has(key2);
942
+ async function observeOrder(key2, run) {
943
+ const busy = () => new OwneyError(
944
+ "SWAP_REQUEST_FAILED",
945
+ "This order is already being observed.",
946
+ { orderHash: key2, watchActive: true, settlementUnconfirmed: true }
947
+ );
948
+ if (active.has(key2)) throw busy();
949
+ active.add(key2);
950
+ try {
951
+ if (typeof navigator !== "undefined" && navigator.locks)
952
+ return await navigator.locks.request(`owney.swap.observe:${key2}`, { ifAvailable: true }, (lock) => {
953
+ if (!lock) throw busy();
954
+ return run();
955
+ });
956
+ return await run();
957
+ } finally {
958
+ active.delete(key2);
959
+ }
960
+ }
961
+
962
+ // src/lib/swap/swap.deadline.ts
963
+ async function bounded(work, timeoutMs, error) {
964
+ if (timeoutMs <= 0) throw error();
965
+ let timer;
966
+ try {
967
+ return await Promise.race([
968
+ Promise.resolve().then(work),
969
+ new Promise((_, reject) => {
970
+ timer = setTimeout(() => reject(error()), timeoutMs);
971
+ })
972
+ ]);
973
+ } finally {
974
+ clearTimeout(timer);
975
+ }
976
+ }
977
+ async function mapConcurrent(items, run, concurrency = 3) {
978
+ const results = new Array(items.length);
979
+ let next = 0;
980
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, async () => {
981
+ for (; ; ) {
982
+ const index = next++;
983
+ if (index >= items.length) return;
984
+ results[index] = await run(items[index]);
985
+ }
986
+ }));
987
+ return results;
988
+ }
989
+
990
+ // src/client.ts
991
+ init_permit2_batch();
992
+
428
993
  // src/lib/helpers/funding-amount.ts
429
994
  function isFundingAmount(value, allowZero = false) {
430
995
  if (typeof value !== "string" || !/^\d{1,78}$/.test(value)) return false;
@@ -452,10 +1017,14 @@ function registerDepositBatch(callback, transfer) {
452
1017
  batchCallbacks.set(callback, transfer);
453
1018
  }
454
1019
 
1020
+ // src/lib/sponsored-deposit.ts
1021
+ init_errors();
1022
+
455
1023
  // src/lib/transfer-auth.ts
456
- var import_viem3 = require("viem");
1024
+ var import_viem4 = require("viem");
457
1025
 
458
1026
  // src/lib/sponsor-client.ts
1027
+ init_errors();
459
1028
  var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
460
1029
  async function postPaymasterIntent(input) {
461
1030
  const base7 = input.baseUrl ?? ROUTING_API_BASE_URL;
@@ -539,6 +1108,7 @@ async function postSponsorBatchTransfer(input) {
539
1108
  `${input.baseUrl ?? ROUTING_API_BASE_URL}/api/v1/sponsor/permit2-batch`,
540
1109
  {
541
1110
  method: "POST",
1111
+ ...input.signal ? { signal: input.signal } : {},
542
1112
  headers: {
543
1113
  "content-type": "application/json",
544
1114
  "x-owney-api-key": input.apiKey
@@ -567,9 +1137,48 @@ async function postSponsorBatchTransfer(input) {
567
1137
  }
568
1138
  return parsed.data;
569
1139
  }
1140
+ async function postSponsorBatchRecovery(input) {
1141
+ const failure = () => new OwneyError("SPONSOR_REQUEST_FAILED", "Deposit recovery is unavailable. The existing transaction remains tracked.", { safeToFallback: false });
1142
+ try {
1143
+ input.signal?.throwIfAborted();
1144
+ const response = await fetch(`${input.baseUrl ?? ROUTING_API_BASE_URL}/api/v1/sponsor/permit2-batch/recover`, { method: "POST", headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey }, body: JSON.stringify(input.body), signal: input.signal });
1145
+ input.signal?.throwIfAborted();
1146
+ if (response.status === 404) return;
1147
+ const payload = await response.json();
1148
+ input.signal?.throwIfAborted();
1149
+ if (!response.ok || payload?.success !== true) throw failure();
1150
+ const value = payload.data;
1151
+ const { isAddress: isAddress6, keccak256: keccak2565, parseTransaction: parseTransaction4, recoverTransactionAddress: recoverTransactionAddress2 } = await import("viem");
1152
+ const { validateTokenBatchAttempt: validateTokenBatchAttempt2 } = await Promise.resolve().then(() => (init_token_batch_family(), token_batch_family_exports));
1153
+ const phase = input.body.phase;
1154
+ const original = phase === "approval" ? input.body.serializedPermitTransaction : input.body.serializedTransaction;
1155
+ if (!original) throw failure();
1156
+ const hash2 = keccak2565(original), relayer = await recoverTransactionAddress2({ serializedTransaction: original });
1157
+ const validHash = (v) => typeof v === "string" && /^0x[\da-f]{64}$/i.test(v);
1158
+ if (!value || value.protocol !== 1 || value.phase !== phase || !validHash(value.txHash) || !isAddress6(value.relayer) || value.relayer.toLowerCase() !== relayer.toLowerCase()) throw failure();
1159
+ if (value.status !== "prepared" && value.txHash.toLowerCase() !== hash2.toLowerCase()) throw failure();
1160
+ if (value.status === "unresolved") {
1161
+ if (!["nonce-not-consumed", "authorization-used", "authorization-expired", "state-unavailable", "preparation-rejected", "relayer-changed"].includes(value.reason)) throw failure();
1162
+ } else {
1163
+ if (!("blockNumber" in value) || typeof value.blockNumber !== "string" || !/^\d{1,78}$/.test(value.blockNumber) || BigInt(value.blockNumber) >= 1n << 256n || !validHash(value.blockHash)) throw failure();
1164
+ if (value.status === "prepared") {
1165
+ if (value.predecessorHash?.toLowerCase() !== hash2.toLowerCase()) throw failure();
1166
+ const tx = parseTransaction4(value.serializedTransaction), old = parseTransaction4(original);
1167
+ if (!Number.isSafeInteger(tx.nonce) || tx.nonce <= old.nonce) throw failure();
1168
+ await validateTokenBatchAttempt2({ apiKey: input.apiKey, baseUrl: input.baseUrl, chainId: input.body.chainId, owner: input.body.from, token: input.body.token }, input.body, { phase, hash: value.txHash, serializedTransaction: value.serializedTransaction, nonce: String(tx.nonce), predecessorHash: hash2, preparedAt: Date.now(), submissionAttempted: false }, relayer);
1169
+ } else if (value.status === "included") {
1170
+ if (value.outcome !== "success" && value.outcome !== "reverted") throw failure();
1171
+ } else if (value.status !== "approval-satisfied" || phase !== "approval") throw failure();
1172
+ }
1173
+ input.signal?.throwIfAborted();
1174
+ return value;
1175
+ } catch {
1176
+ throw failure();
1177
+ }
1178
+ }
570
1179
 
571
1180
  // src/lib/permit2.ts
572
- var import_viem4 = require("viem");
1181
+ var import_viem5 = require("viem");
573
1182
  var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
574
1183
  var MAX_UINT256 = 2n ** 256n - 1n;
575
1184
  function permit2ApprovalAmount(requiredAmount) {
@@ -610,7 +1219,7 @@ var ERC20_ALLOWANCE_ABI = [
610
1219
  function randomPermit2Nonce() {
611
1220
  const bytes = new Uint8Array(32);
612
1221
  globalThis.crypto.getRandomValues(bytes);
613
- return BigInt((0, import_viem4.bytesToHex)(bytes));
1222
+ return BigInt((0, import_viem5.bytesToHex)(bytes));
614
1223
  }
615
1224
  async function readPermit2Allowance(publicClient, token, owner, blockNumber) {
616
1225
  return publicClient.readContract({
@@ -631,6 +1240,7 @@ async function readErc20Balance(publicClient, token, owner) {
631
1240
  }
632
1241
 
633
1242
  // src/lib/chain-guard.ts
1243
+ init_errors();
634
1244
  var CHAIN_NAMES = {
635
1245
  1: "Ethereum",
636
1246
  8453: "Base",
@@ -704,6 +1314,9 @@ function makeVerificationAwareDepositCallback(implementation) {
704
1314
  return callback;
705
1315
  }
706
1316
 
1317
+ // src/lib/agent-reads.ts
1318
+ init_errors();
1319
+
707
1320
  // src/lib/rate-limit.ts
708
1321
  function rateLimitDelay(error, now = Date.now()) {
709
1322
  const seen = /* @__PURE__ */ new Set();
@@ -1005,15 +1618,15 @@ function positionsEmpty(entries, chainId, token) {
1005
1618
  function hasEmptyWithdrawalSnapshot(raw2, chainId, token) {
1006
1619
  const snapshot = snapshotPortfolio(raw2);
1007
1620
  if (!snapshot) return false;
1008
- const pending = snapshot.portfolio.pendingAsyncWithdrawals;
1009
- if (pending !== void 0 && (!Array.isArray(pending) || pending.length > 0)) return false;
1621
+ const pending2 = snapshot.portfolio.pendingAsyncWithdrawals;
1622
+ if (pending2 !== void 0 && (!Array.isArray(pending2) || pending2.length > 0)) return false;
1010
1623
  return chainBalancesMatch(snapshot.chains, chainId, token, (balance) => zero(balance.balance)) && positionsEmpty(snapshot.entries, chainId, token);
1011
1624
  }
1012
1625
  function hasIdleOnlyWithdrawalSnapshot(raw2, chainId, token, decimals, idle) {
1013
1626
  const snapshot = snapshotPortfolio(raw2);
1014
1627
  if (!snapshot) return false;
1015
- const pending = snapshot.portfolio.pendingAsyncWithdrawals;
1016
- if (pending !== void 0 && (!Array.isArray(pending) || pending.some((value) => record(value)?.status !== "CLAIMED"))) return false;
1628
+ const pending2 = snapshot.portfolio.pendingAsyncWithdrawals;
1629
+ if (pending2 !== void 0 && (!Array.isArray(pending2) || pending2.some((value) => record(value)?.status !== "CLAIMED"))) return false;
1017
1630
  return chainBalancesMatch(snapshot.chains, chainId, token, (balance) => {
1018
1631
  const amount = units(balance.balance);
1019
1632
  return amount !== void 0 && amount <= idle && (balance.decimals === void 0 || balance.decimals === decimals);
@@ -1021,7 +1634,8 @@ function hasIdleOnlyWithdrawalSnapshot(raw2, chainId, token, decimals, idle) {
1021
1634
  }
1022
1635
 
1023
1636
  // src/agents/zyfai/zyfai.deposit.ts
1024
- var import_viem5 = require("viem");
1637
+ var import_viem6 = require("viem");
1638
+ init_errors();
1025
1639
 
1026
1640
  // src/types/config.ts
1027
1641
  var P_SUPPORTED_CHAINS = {
@@ -1075,16 +1689,16 @@ async function submitZyfaiDeposit({ sdk, state, chain: chain2, amount, asset, sm
1075
1689
  const owner = state.walletAddress;
1076
1690
  const provider = state.provider;
1077
1691
  const token = SupportedAssets.find((value) => value.chainId === chain2.id && value.symbol === asset);
1078
- if (!token || !(0, import_viem5.isAddress)(owner) || !(0, import_viem5.isAddress)(smartWallet) || !/^\d+$/.test(amount) || BigInt(amount) <= 0n)
1692
+ if (!token || !(0, import_viem6.isAddress)(owner) || !(0, import_viem6.isAddress)(smartWallet) || !/^\d+$/.test(amount) || BigInt(amount) <= 0n)
1079
1693
  throw new OwneyError("AGENT_INVALID_RESPONSE", "Invalid Zyfai deposit transfer.", { chainId: chain2.id, asset }, "zyfai");
1080
1694
  assertCurrent();
1081
1695
  const prepared = await sdk.prepareEnterPosition({ userAddress: owner, chainId: chain2.id, amount, asset, strategy: "aggressive" });
1082
1696
  assertCurrent();
1083
- const expectedData = (0, import_viem5.encodeFunctionData)({ abi: import_viem5.erc20Abi, functionName: "transfer", args: [smartWallet, BigInt(amount)] });
1697
+ const expectedData = (0, import_viem6.encodeFunctionData)({ abi: import_viem6.erc20Abi, functionName: "transfer", args: [smartWallet, BigInt(amount)] });
1084
1698
  const transfer = prepared?.transfer;
1085
1699
  if (!transfer || transfer.safeAddress?.toLowerCase() !== smartWallet.toLowerCase() || transfer.tokenAddress?.toLowerCase() !== token.address.toLowerCase() || transfer.to?.toLowerCase() !== token.address.toLowerCase() || transfer.data?.toLowerCase() !== expectedData.toLowerCase() || transfer.value !== "0")
1086
1700
  throw new OwneyError("AGENT_INVALID_RESPONSE", "Zyfai prepared a different deposit transfer.", { chainId: chain2.id, asset }, "zyfai");
1087
- const wallet = (0, import_viem5.createWalletClient)({ account: owner, chain: chain2, transport: (0, import_viem5.custom)({
1701
+ const wallet = (0, import_viem6.createWalletClient)({ account: owner, chain: chain2, transport: (0, import_viem6.custom)({
1088
1702
  request: async (args) => {
1089
1703
  assertCurrent();
1090
1704
  if (args.method === "eth_sendTransaction") {
@@ -1106,7 +1720,7 @@ async function submitZyfaiDeposit({ sdk, state, chain: chain2, amount, asset, sm
1106
1720
 
1107
1721
  // src/agents/zyfai/zyfai.agent.ts
1108
1722
  var import_sdk = require("@zyfai/sdk");
1109
- var import_viem8 = require("viem");
1723
+ var import_viem9 = require("viem");
1110
1724
  var import_chains = require("viem/chains");
1111
1725
 
1112
1726
  // src/lib/debug.ts
@@ -1127,6 +1741,7 @@ function debugLog(scope, message, data) {
1127
1741
  }
1128
1742
 
1129
1743
  // src/lib/utils.ts
1744
+ init_errors();
1130
1745
  var isValidChainId = (chainId) => {
1131
1746
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
1132
1747
  throw new OwneyError(
@@ -1162,8 +1777,8 @@ function matchesAsset(symbol2, asset) {
1162
1777
  }
1163
1778
 
1164
1779
  // src/agents/zyfai/zyfai.mapper.ts
1165
- var import_viem6 = require("viem");
1166
- var exactHexAmount = (raw2, decimals) => (0, import_viem6.formatUnits)(BigInt(/^0x/i.test(raw2) ? raw2 : `0x${raw2}`), decimals);
1780
+ var import_viem7 = require("viem");
1781
+ var exactHexAmount = (raw2, decimals) => (0, import_viem7.formatUnits)(BigInt(/^0x/i.test(raw2) ? raw2 : `0x${raw2}`), decimals);
1167
1782
  var DECIMALS_BY_SYMBOL = {
1168
1783
  usdc: 6,
1169
1784
  weth: 18,
@@ -1202,7 +1817,7 @@ function resolveChainId(chain2) {
1202
1817
  }
1203
1818
  function mapPendingAllocations(raw2) {
1204
1819
  if (!Array.isArray(raw2)) return void 0;
1205
- const pending = [];
1820
+ const pending2 = [];
1206
1821
  for (const entry of raw2) {
1207
1822
  if (typeof entry !== "object" || entry === null) continue;
1208
1823
  const e = entry;
@@ -1216,7 +1831,7 @@ function mapPendingAllocations(raw2) {
1216
1831
  } catch {
1217
1832
  continue;
1218
1833
  }
1219
- pending.push({
1834
+ pending2.push({
1220
1835
  chainId: e.chainId,
1221
1836
  asset: e.tokenSymbol,
1222
1837
  amount,
@@ -1224,7 +1839,7 @@ function mapPendingAllocations(raw2) {
1224
1839
  ...typeof e.updatedAt === "string" && e.updatedAt !== "" ? { since: e.updatedAt } : {}
1225
1840
  });
1226
1841
  }
1227
- return pending.length > 0 ? pending : void 0;
1842
+ return pending2.length > 0 ? pending2 : void 0;
1228
1843
  }
1229
1844
  function mapBalances(raw2, _chainId, smartWallet) {
1230
1845
  const portfolio = raw2.portfolio;
@@ -1262,7 +1877,7 @@ function mapBalances(raw2, _chainId, smartWallet) {
1262
1877
  // legacy `amount` fallback is hex. Runtime
1263
1878
  // getBalances payloads often carry one (e.g. 18 for WETH) — prefer that
1264
1879
  // when present, otherwise fall back to the per-symbol lookup.
1265
- amount: p.underlyingAmountWithFee ?? p.underlyingAmount ? (0, import_viem6.formatUnits)(
1880
+ amount: p.underlyingAmountWithFee ?? p.underlyingAmount ? (0, import_viem7.formatUnits)(
1266
1881
  BigInt(p.underlyingAmountWithFee ?? p.underlyingAmount ?? "0"),
1267
1882
  tokenDecimals(
1268
1883
  p.token_symbol,
@@ -1664,6 +2279,9 @@ function decodeHistoryCursor(token) {
1664
2279
  return parsed;
1665
2280
  }
1666
2281
 
2282
+ // src/agents/zyfai/zyfai.agent.ts
2283
+ init_errors();
2284
+
1667
2285
  // src/agents/zyfai/zyfai.auth-cache.ts
1668
2286
  var KEY_PREFIX = "owney.zyfai.session";
1669
2287
  var storage = () => {
@@ -1926,7 +2544,8 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
1926
2544
  }
1927
2545
 
1928
2546
  // src/lib/paid-rpc.ts
1929
- var import_viem7 = require("viem");
2547
+ var import_viem8 = require("viem");
2548
+ init_errors();
1930
2549
  var PAID_RPC_RETRY_COUNT = 3;
1931
2550
  var PAID_RPC_RETRY_DELAY_MS = 1e3;
1932
2551
  function configuredRpcProxyBaseUrl(baseUrl) {
@@ -1962,9 +2581,9 @@ function createPaidRpcClient(chain2, rpcUrls) {
1962
2581
  rpcUrls,
1963
2582
  chain2.id
1964
2583
  );
1965
- return (0, import_viem7.createPublicClient)({
2584
+ return (0, import_viem8.createPublicClient)({
1966
2585
  chain: chain2,
1967
- transport: (0, import_viem7.http)(url, {
2586
+ transport: (0, import_viem8.http)(url, {
1968
2587
  retryCount: PAID_RPC_RETRY_COUNT,
1969
2588
  retryDelay: PAID_RPC_RETRY_DELAY_MS
1970
2589
  })
@@ -2061,7 +2680,7 @@ async function withPaidRpcDiagnostics(operation, chainId, rpcMethod, agentId) {
2061
2680
  }
2062
2681
 
2063
2682
  // src/agents/zyfai/zyfai.agent.ts
2064
- var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem8.parseAbi)([
2683
+ var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem9.parseAbi)([
2065
2684
  "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)"
2066
2685
  ]);
2067
2686
  var WETH_ADDRESS_BY_CHAIN = {
@@ -2079,7 +2698,7 @@ function belowMinimumCeiling(rejection, token, decimals) {
2079
2698
  const ceiling = (display) => {
2080
2699
  const places = display.split(".")[1]?.length ?? 0;
2081
2700
  if (places >= decimals) return void 0;
2082
- return (0, import_viem8.parseUnits)(display, decimals) + 5n * 10n ** BigInt(decimals - places - 1);
2701
+ return (0, import_viem9.parseUnits)(display, decimals) + 5n * 10n ** BigInt(decimals - places - 1);
2083
2702
  };
2084
2703
  const idle = ceiling(rejection.idle);
2085
2704
  const minimum = ceiling(rejection.minimum);
@@ -2131,6 +2750,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2131
2750
  connectedAddress = null;
2132
2751
  connectedChainId = null;
2133
2752
  smartWalletCache = /* @__PURE__ */ new Map();
2753
+ smartWalletReads = /* @__PURE__ */ new Map();
2134
2754
  /**
2135
2755
  * `${eoa}:${chainId}` keys we have already tried createSessionKey for. Guards
2136
2756
  * against re-running it on every activation/deposit when Zyfai's
@@ -2148,6 +2768,9 @@ var ZyfaiAgent = class _ZyfaiAgent {
2148
2768
  fundingHistoryCache = /* @__PURE__ */ new Map();
2149
2769
  earningsReads = /* @__PURE__ */ new Map();
2150
2770
  earningsRefreshes = /* @__PURE__ */ new Map();
2771
+ // Recalculation is wallet-wide across assets/chains. Bound attempts locally,
2772
+ // including failures; a negative result must not trigger a POST every poll.
2773
+ earningsCalculationAttempts = /* @__PURE__ */ new Map();
2151
2774
  earningsSnapshot = null;
2152
2775
  earningsGeneration = 0;
2153
2776
  balanceSnapshots = /* @__PURE__ */ new WeakMap();
@@ -2239,7 +2862,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2239
2862
  }, asset.address, entry.action === "Withdraw" ? "withdraw" : "deposit");
2240
2863
  if (evidence.transfer === "confirmed" && evidence.confirmedAmount) {
2241
2864
  Object.assign(tx, {
2242
- amount: (0, import_viem8.formatUnits)(BigInt(evidence.confirmedAmount), asset.decimals),
2865
+ amount: (0, import_viem9.formatUnits)(BigInt(evidence.confirmedAmount), asset.decimals),
2243
2866
  amountRaw: evidence.confirmedAmount,
2244
2867
  blockNumber: evidence.blockNumber,
2245
2868
  logIndexes: evidence.logIndexes,
@@ -2323,9 +2946,11 @@ var ZyfaiAgent = class _ZyfaiAgent {
2323
2946
  this.sdkHasConnected = true;
2324
2947
  const executionSdk = this.sdk;
2325
2948
  const generation = ++this.connectionGeneration;
2949
+ this.smartWalletCache.clear();
2950
+ this.smartWalletReads.clear();
2326
2951
  this.connectedAddress = null;
2327
2952
  this.connectedChainId = null;
2328
- const pending = (async () => {
2953
+ const pending2 = (async () => {
2329
2954
  const address = await this.connectAccountWithRetry(
2330
2955
  state.provider,
2331
2956
  validChainId,
@@ -2336,12 +2961,12 @@ var ZyfaiAgent = class _ZyfaiAgent {
2336
2961
  this.connectedAddress = address;
2337
2962
  this.connectedChainId = validChainId;
2338
2963
  })();
2339
- this.connectAuthPromise = pending;
2964
+ this.connectAuthPromise = pending2;
2340
2965
  this.connectAuthScope = scope;
2341
2966
  try {
2342
- await pending;
2967
+ await pending2;
2343
2968
  } finally {
2344
- if (this.connectAuthPromise === pending) {
2969
+ if (this.connectAuthPromise === pending2) {
2345
2970
  this.connectAuthPromise = null;
2346
2971
  this.connectAuthScope = null;
2347
2972
  }
@@ -2434,18 +3059,29 @@ var ZyfaiAgent = class _ZyfaiAgent {
2434
3059
  await this.connectAuth(state, chainId);
2435
3060
  const validChainId = isValidChainId(chainId);
2436
3061
  const ownerAddress = this.getAddress();
2437
- const cacheKey = `${ownerAddress}_${validChainId}`;
2438
- let smartWallet = this.smartWalletCache.get(cacheKey);
2439
- if (!smartWallet) {
2440
- const { address } = await this.sdk.getSmartWalletAddress(
2441
- ownerAddress,
2442
- validChainId
2443
- );
2444
- smartWallet = address;
2445
- this.smartWalletCache.set(cacheKey, smartWallet);
2446
- }
3062
+ const smartWallet = await this.readSmartWallet(ownerAddress, validChainId);
2447
3063
  return { smartWallet, chainId: validChainId };
2448
3064
  }
3065
+ /** Read-only resolution shared with recovery; never enters authentication. */
3066
+ readSmartWallet(owner, chainId) {
3067
+ const key2 = `${owner.toLowerCase()}_${chainId}`;
3068
+ const cached = this.smartWalletCache.get(key2);
3069
+ if (cached) return Promise.resolve(cached);
3070
+ const existing = this.smartWalletReads.get(key2);
3071
+ if (existing) return existing;
3072
+ const generation = this.connectionGeneration;
3073
+ const executionSdk = this.sdk;
3074
+ const pending2 = Promise.resolve().then(() => executionSdk.getSmartWalletAddress(owner, chainId)).then(({ address }) => {
3075
+ if (generation !== this.connectionGeneration || executionSdk !== this.sdk)
3076
+ throw new OwneyError("NOT_CONNECTED", "Wallet changed while resolving Zyfai.", void 0, this.id);
3077
+ this.smartWalletCache.set(key2, address);
3078
+ return address;
3079
+ }).finally(() => {
3080
+ if (this.smartWalletReads.get(key2) === pending2) this.smartWalletReads.delete(key2);
3081
+ });
3082
+ this.smartWalletReads.set(key2, pending2);
3083
+ return pending2;
3084
+ }
2449
3085
  // --- IAgent: Connection lifecycle ---
2450
3086
  async disconnect() {
2451
3087
  const executionSdk = this.sdk;
@@ -2453,6 +3089,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2453
3089
  this.earningsGeneration++;
2454
3090
  this.earningsReads.clear();
2455
3091
  this.earningsRefreshes.clear();
3092
+ this.earningsCalculationAttempts.clear();
2456
3093
  this.earningsSnapshot = null;
2457
3094
  if (this.connectedAddress && this.connectedChainId !== null) {
2458
3095
  clearSession(this.connectedAddress, this.connectedChainId);
@@ -2462,6 +3099,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
2462
3099
  this.connectAuthPromise = null;
2463
3100
  this.connectAuthScope = null;
2464
3101
  this.smartWalletCache.clear();
3102
+ this.smartWalletReads.clear();
2465
3103
  this.sdk = this.createSdk();
2466
3104
  this.sdkHasConnected = false;
2467
3105
  await executionSdk.disconnectAccount();
@@ -3068,7 +3706,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
3068
3706
  this.sdk.getPortfolio(owner).catch(() => void 0)
3069
3707
  ]);
3070
3708
  assertScope();
3071
- if (!(0, import_viem8.isAddress)(wallet.address) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase())
3709
+ if (!(0, import_viem9.isAddress)(wallet.address) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase())
3072
3710
  throw new OwneyError(
3073
3711
  "AGENT_AUTH_FAILED",
3074
3712
  "Could not verify Zyfai's withdrawal wallet.",
@@ -3082,7 +3720,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
3082
3720
  if (!empty && ceiling === void 0) return;
3083
3721
  const idle = await this.getPublicClient(chainId).readContract({
3084
3722
  address: asset.address,
3085
- abi: import_viem8.erc20Abi,
3723
+ abi: import_viem9.erc20Abi,
3086
3724
  functionName: "balanceOf",
3087
3725
  args: [wallet.address]
3088
3726
  }).catch(() => void 0);
@@ -3307,7 +3945,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
3307
3945
  }
3308
3946
  // --- IAgent: Portfolio reads ---
3309
3947
  async getFundingWallet(state, chainId) {
3310
- return (await this.sdk.getSmartWalletAddress(state.walletAddress, isValidChainId(chainId))).address;
3948
+ return this.readSmartWallet(state.walletAddress, isValidChainId(chainId));
3311
3949
  }
3312
3950
  /** A positive deployed Safe balance is a conservative planning floor. Zero
3313
3951
  * requires both the mapped Safe's exact idle balance and a fresh complete
@@ -3340,13 +3978,13 @@ var ZyfaiAgent = class _ZyfaiAgent {
3340
3978
  this.sdk.getSmartWalletByEOA(owner)
3341
3979
  ]);
3342
3980
  assertScope();
3343
- if (!(0, import_viem8.isAddress)(wallet.address) || wallet.isDeployed !== false && (wallet.isDeployed !== true || wallet.isOwner !== true) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase()) throw unavailable();
3981
+ if (!(0, import_viem9.isAddress)(wallet.address) || wallet.isDeployed !== false && (wallet.isDeployed !== true || wallet.isOwner !== true) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase()) throw unavailable();
3344
3982
  const client = this.getPublicClient(validChainId);
3345
3983
  const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
3346
3984
  assertScope();
3347
3985
  const idle = await client.readContract({
3348
3986
  address: asset.address,
3349
- abi: import_viem8.erc20Abi,
3987
+ abi: import_viem9.erc20Abi,
3350
3988
  functionName: "balanceOf",
3351
3989
  args: [wallet.address],
3352
3990
  blockNumber
@@ -3403,7 +4041,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
3403
4041
  if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
3404
4042
  const idle = await client.readContract({
3405
4043
  address: asset.address,
3406
- abi: import_viem8.erc20Abi,
4044
+ abi: import_viem9.erc20Abi,
3407
4045
  functionName: "balanceOf",
3408
4046
  args: [balance.smartWallet],
3409
4047
  blockNumber
@@ -3422,17 +4060,22 @@ var ZyfaiAgent = class _ZyfaiAgent {
3422
4060
  const existing = this.earningsReads.get(key2);
3423
4061
  if (existing) return existing;
3424
4062
  const generation = this.earningsGeneration;
3425
- const pending = Promise.resolve().then(() => this.sdk.getOnchainEarnings(smartWallet)).then((raw2) => {
3426
- if (generation === this.earningsGeneration) {
4063
+ const executionSdk = this.sdk;
4064
+ const pending2 = Promise.resolve().then(() => {
4065
+ if (generation !== this.earningsGeneration || executionSdk !== this.sdk)
4066
+ throw new OwneyError("NOT_CONNECTED", "Wallet changed while reading Zyfai earnings.", void 0, this.id);
4067
+ return executionSdk.getOnchainEarnings(smartWallet);
4068
+ }).then((raw2) => {
4069
+ if (generation === this.earningsGeneration && executionSdk === this.sdk) {
3427
4070
  this.earningsSnapshot = { key: key2, raw: raw2, at: Date.now() };
3428
4071
  }
3429
4072
  return raw2;
3430
4073
  }).finally(() => {
3431
- if (this.earningsReads.get(key2) === pending)
4074
+ if (this.earningsReads.get(key2) === pending2)
3432
4075
  this.earningsReads.delete(key2);
3433
4076
  });
3434
- this.earningsReads.set(key2, pending);
3435
- return pending;
4077
+ this.earningsReads.set(key2, pending2);
4078
+ return pending2;
3436
4079
  }
3437
4080
  async getEarnings(state, chainId) {
3438
4081
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
@@ -3443,27 +4086,44 @@ var ZyfaiAgent = class _ZyfaiAgent {
3443
4086
  return mapEarnings(raw2, smartWallet);
3444
4087
  }
3445
4088
  async refreshEarnings(state, chainId) {
4089
+ const generation = this.earningsGeneration;
4090
+ await this.connectAuth(state, chainId);
4091
+ const executionSdk = this.sdk;
4092
+ const connectionGeneration = this.connectionGeneration;
4093
+ const assertCurrent = () => {
4094
+ if (generation !== this.earningsGeneration || connectionGeneration !== this.connectionGeneration || executionSdk !== this.sdk)
4095
+ throw new OwneyError("NOT_CONNECTED", "Wallet changed while refreshing Zyfai earnings.", void 0, this.id);
4096
+ };
4097
+ assertCurrent();
3446
4098
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
4099
+ assertCurrent();
3447
4100
  const key2 = this.earningsKey(state, chainId, smartWallet);
3448
4101
  const existing = this.earningsRefreshes.get(key2);
3449
4102
  if (existing) return existing;
3450
- const generation = this.earningsGeneration;
3451
- const pending = (async () => {
4103
+ const pending2 = (async () => {
3452
4104
  const recent = this.earningsSnapshot;
3453
4105
  const current = recent?.key === key2 && Date.now() - recent.at < 5e3 ? recent.raw : await this.readEarnings(key2, smartWallet);
3454
4106
  const lastCheck = current.data.lastCheckTimestamp ? Date.parse(current.data.lastCheckTimestamp) : Number.NaN;
3455
- const isFresh = Number.isFinite(lastCheck) && Date.now() - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
3456
- const earnings = isFresh ? current : await this.sdk.calculateOnchainEarnings(smartWallet);
3457
- if (!isFresh && generation === this.earningsGeneration) {
3458
- this.earningsSnapshot = { key: key2, raw: earnings, at: Date.now() };
3459
- }
4107
+ const mapped = mapEarnings(current, smartWallet);
4108
+ assertCurrent();
4109
+ const now = Date.now();
4110
+ const isFresh = Number.isFinite(lastCheck) && lastCheck <= now && now - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
4111
+ const negative = mapped.lifetimeEarnings < 0 || mapped.tokens.some((token) => Number(token.amount) < 0);
4112
+ const calculationKey = JSON.stringify([state.walletAddress?.toLowerCase(), smartWallet.toLowerCase()]);
4113
+ const attemptedAt = this.earningsCalculationAttempts.get(calculationKey);
4114
+ const canCalculate = attemptedAt === void 0 || now - attemptedAt >= EARNINGS_REFRESH_COOLDOWN_MS;
4115
+ if (isFresh && !negative || !canCalculate) return mapped;
4116
+ this.earningsCalculationAttempts.set(calculationKey, now);
4117
+ const earnings = await executionSdk.calculateOnchainEarnings(smartWallet);
4118
+ assertCurrent();
4119
+ this.earningsSnapshot = { key: key2, raw: earnings, at: Date.now() };
3460
4120
  return mapEarnings(earnings, smartWallet);
3461
4121
  })().finally(() => {
3462
- if (this.earningsRefreshes.get(key2) === pending)
4122
+ if (this.earningsRefreshes.get(key2) === pending2)
3463
4123
  this.earningsRefreshes.delete(key2);
3464
4124
  });
3465
- this.earningsRefreshes.set(key2, pending);
3466
- return pending;
4125
+ this.earningsRefreshes.set(key2, pending2);
4126
+ return pending2;
3467
4127
  }
3468
4128
  async getAccountApy(state, chainId, days, tokenSymbol) {
3469
4129
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
@@ -3608,12 +4268,13 @@ var ZyfaiAgent = class _ZyfaiAgent {
3608
4268
  };
3609
4269
 
3610
4270
  // src/agents/yieldseeker/yieldseeker.agent.ts
3611
- var import_viem14 = require("viem");
4271
+ var import_viem16 = require("viem");
3612
4272
  var import_chains4 = require("viem/chains");
4273
+ init_errors();
3613
4274
 
3614
4275
  // src/agents/yieldseeker/yieldseeker.auth.ts
3615
4276
  var import_siwe = require("siwe");
3616
- var import_viem9 = require("viem");
4277
+ var import_viem10 = require("viem");
3617
4278
  var import_chains2 = require("viem/chains");
3618
4279
 
3619
4280
  // src/agents/yieldseeker/yieldseeker.auth-cache.ts
@@ -3728,7 +4389,7 @@ function createYieldseekerSiweMessage(address, chainId, dependencies = {}) {
3728
4389
  return new import_siwe.SiweMessage({
3729
4390
  scheme: url.protocol.slice(0, -1),
3730
4391
  domain: url.host,
3731
- address: (0, import_viem9.getAddress)(address),
4392
+ address: (0, import_viem10.getAddress)(address),
3732
4393
  uri: url.origin,
3733
4394
  version: "1",
3734
4395
  chainId,
@@ -3828,15 +4489,15 @@ var YieldseekerAuth = class {
3828
4489
  clearYieldseekerSession(state.walletAddress, chainId);
3829
4490
  }
3830
4491
  async sign(state, chainId) {
3831
- const account = (0, import_viem9.getAddress)(state.walletAddress);
3832
- const publicClient = (0, import_viem9.createPublicClient)({
4492
+ const account = (0, import_viem10.getAddress)(state.walletAddress);
4493
+ const publicClient = (0, import_viem10.createPublicClient)({
3833
4494
  chain: import_chains2.base,
3834
- transport: (0, import_viem9.custom)(state.provider)
4495
+ transport: (0, import_viem10.custom)(state.provider)
3835
4496
  });
3836
- const walletClient = (0, import_viem9.createWalletClient)({
4497
+ const walletClient = (0, import_viem10.createWalletClient)({
3837
4498
  account,
3838
4499
  chain: import_chains2.base,
3839
- transport: (0, import_viem9.custom)(state.provider)
4500
+ transport: (0, import_viem10.custom)(state.provider)
3840
4501
  });
3841
4502
  await ensureWalletOnChain(
3842
4503
  publicClient,
@@ -4003,7 +4664,8 @@ var YieldseekerApiClient = class {
4003
4664
  };
4004
4665
 
4005
4666
  // src/agents/yieldseeker/yieldseeker.mapper.ts
4006
- var import_viem10 = require("viem");
4667
+ var import_viem11 = require("viem");
4668
+ init_errors();
4007
4669
 
4008
4670
  // src/lib/helpers/snapshot-apy.ts
4009
4671
  var DAY_MS = 864e5;
@@ -4070,7 +4732,7 @@ function raw(value, endpoint) {
4070
4732
  return BigInt(value);
4071
4733
  }
4072
4734
  function decimal(value, decimals, endpoint) {
4073
- return (0, import_viem10.formatUnits)(raw(value, endpoint), decimals);
4735
+ return (0, import_viem11.formatUnits)(raw(value, endpoint), decimals);
4074
4736
  }
4075
4737
  function balanceRaw(value, endpoint) {
4076
4738
  const amount = raw(value, endpoint);
@@ -4078,10 +4740,10 @@ function balanceRaw(value, endpoint) {
4078
4740
  return amount;
4079
4741
  }
4080
4742
  function balanceDecimal(value, decimals, endpoint) {
4081
- return (0, import_viem10.formatUnits)(balanceRaw(value, endpoint), decimals);
4743
+ return (0, import_viem11.formatUnits)(balanceRaw(value, endpoint), decimals);
4082
4744
  }
4083
4745
  function usd(rawAmount2, decimals, price) {
4084
- return Number((0, import_viem10.formatUnits)(rawAmount2, decimals)) * price;
4746
+ return Number((0, import_viem11.formatUnits)(rawAmount2, decimals)) * price;
4085
4747
  }
4086
4748
  function percent(value) {
4087
4749
  const result = Number(value);
@@ -4107,7 +4769,7 @@ function assetAddressValue(record2, address) {
4107
4769
  }
4108
4770
  function position(value, asset, baseAssetDecimals) {
4109
4771
  const option = value?.vaultOption;
4110
- if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0, import_viem10.isAddress)(option.address)) {
4772
+ if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0, import_viem11.isAddress)(option.address)) {
4111
4773
  return invalid("vault positions", "missing vault metadata");
4112
4774
  }
4113
4775
  return {
@@ -4200,7 +4862,7 @@ function mapYieldseekerEarnings(contexts) {
4200
4862
  chain: "BASE",
4201
4863
  chainId: 8453,
4202
4864
  asset: context.asset,
4203
- amount: (0, import_viem10.formatUnits)(amount, context.snapshot.baseAssetDecimals)
4865
+ amount: (0, import_viem11.formatUnits)(amount, context.snapshot.baseAssetDecimals)
4204
4866
  });
4205
4867
  lifetimeEarnings += usd(
4206
4868
  amount,
@@ -4356,7 +5018,7 @@ function allocationLegs(value, context, requireAmount) {
4356
5018
  const symbol2 = typeof leg.assetSymbol === "string" ? leg.assetSymbol.toUpperCase() : "";
4357
5019
  if ((requireAmount || symbol2) && symbol2 !== context.asset && !(context.asset === "WETH" && symbol2 === "ETH"))
4358
5020
  return void 0;
4359
- if (typeof leg.vaultAddress !== "string" || !(0, import_viem10.isAddress)(leg.vaultAddress)) return void 0;
5021
+ if (typeof leg.vaultAddress !== "string" || !(0, import_viem11.isAddress)(leg.vaultAddress)) return void 0;
4360
5022
  const rawAmount2 = typeof leg.rawAmount === "string" && /^\d+$/.test(leg.rawAmount) ? BigInt(leg.rawAmount) : typeof leg.rawAmount === "number" && Number.isSafeInteger(leg.rawAmount) ? BigInt(leg.rawAmount) : void 0;
4361
5023
  if (requireAmount && (rawAmount2 === void 0 || rawAmount2 <= 0n)) return void 0;
4362
5024
  const vault = leg.vaultAddress.toLowerCase();
@@ -4383,7 +5045,7 @@ function allocationEntry(action, context) {
4383
5045
  protocol: leg.protocol,
4384
5046
  pool: leg.pool,
4385
5047
  tokenSymbol: context.asset,
4386
- amount: (0, import_viem10.formatUnits)(leg.rawAmount, decimals)
5048
+ amount: (0, import_viem11.formatUnits)(leg.rawAmount, decimals)
4387
5049
  }));
4388
5050
  const amountRaw = deposits.reduce((total, leg) => total + leg.rawAmount, 0n);
4389
5051
  const rebalance = withdrawals.length > 0;
@@ -4405,7 +5067,7 @@ function allocationEntry(action, context) {
4405
5067
  toProtocol: leg.protocol,
4406
5068
  ...leg.pool ? { toPool: leg.pool } : {},
4407
5069
  tokenSymbol: context.asset,
4408
- amount: (0, import_viem10.formatUnits)(leg.rawAmount, decimals),
5070
+ amount: (0, import_viem11.formatUnits)(leg.rawAmount, decimals),
4409
5071
  status: "success"
4410
5072
  })) : [],
4411
5073
  transactions: [{
@@ -4415,7 +5077,7 @@ function allocationEntry(action, context) {
4415
5077
  tokenSymbol: context.asset,
4416
5078
  agentWallet: context.wallet.walletAddress,
4417
5079
  amountRaw: String(amountRaw),
4418
- amount: (0, import_viem10.formatUnits)(amountRaw, decimals)
5080
+ amount: (0, import_viem11.formatUnits)(amountRaw, decimals)
4419
5081
  }]
4420
5082
  };
4421
5083
  }
@@ -4547,7 +5209,7 @@ function mapYieldseekerHistory(contexts, options) {
4547
5209
  const known = new Set(target.logIndexes ?? []);
4548
5210
  if (tx.logIndexes?.some((index) => !known.has(index))) {
4549
5211
  target.amountRaw = String(BigInt(target.amountRaw ?? "0") + BigInt(tx.amountRaw));
4550
- target.amount = (0, import_viem10.formatUnits)(
5212
+ target.amount = (0, import_viem11.formatUnits)(
4551
5213
  BigInt(target.amountRaw),
4552
5214
  YIELDSEEKER_ASSET_METADATA[target.tokenSymbol].decimals
4553
5215
  );
@@ -4628,7 +5290,7 @@ function mapYieldseekerAgentApy(options, days) {
4628
5290
  }
4629
5291
 
4630
5292
  // src/lib/remaining-vault-balance.ts
4631
- var import_viem11 = require("viem");
5293
+ var import_viem12 = require("viem");
4632
5294
  async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber) {
4633
5295
  const addresses = [...new Set(vaults.map((value) => value.toLowerCase()))];
4634
5296
  if (addresses.length > 64) return void 0;
@@ -4639,8 +5301,8 @@ async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber)
4639
5301
  blockNumber,
4640
5302
  allowFailure: true,
4641
5303
  contracts: batch.map((address) => ({
4642
- address: (0, import_viem11.getAddress)(address),
4643
- abi: import_viem11.erc20Abi,
5304
+ address: (0, import_viem12.getAddress)(address),
5305
+ abi: import_viem12.erc20Abi,
4644
5306
  functionName: "balanceOf",
4645
5307
  args: [wallet]
4646
5308
  }))
@@ -4650,15 +5312,15 @@ async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber)
4650
5312
  for (let index = 0; index < batch.length; index++) {
4651
5313
  const result = balances[index];
4652
5314
  if (result?.status !== "success" || typeof result.result !== "bigint" || result.result < 0n) return void 0;
4653
- if (result.result > 0n) funded.push({ address: (0, import_viem11.getAddress)(batch[index]), shares: result.result });
5315
+ if (result.result > 0n) funded.push({ address: (0, import_viem12.getAddress)(batch[index]), shares: result.result });
4654
5316
  }
4655
5317
  if (!funded.length) return 0n;
4656
5318
  const valuations = await client.multicall({
4657
5319
  blockNumber,
4658
5320
  allowFailure: true,
4659
5321
  contracts: funded.flatMap(({ address, shares }) => [
4660
- { address, abi: import_viem11.erc4626Abi, functionName: "asset" },
4661
- { address, abi: import_viem11.erc4626Abi, functionName: "convertToAssets", args: [shares] }
5322
+ { address, abi: import_viem12.erc4626Abi, functionName: "asset" },
5323
+ { address, abi: import_viem12.erc4626Abi, functionName: "convertToAssets", args: [shares] }
4662
5324
  ])
4663
5325
  });
4664
5326
  if (valuations.length !== funded.length * 2) return void 0;
@@ -4674,12 +5336,12 @@ async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber)
4674
5336
  }
4675
5337
 
4676
5338
  // src/agents/yieldseeker/yieldseeker.wallet-version.ts
4677
- var import_viem12 = require("viem");
5339
+ var import_viem13 = require("viem");
4678
5340
  var YIELDSEEKER_FACTORY = "0x9c7410a0faCAC60850C46eE5b58B518daec95130";
4679
5341
  var YIELDSEEKER_V1_IMPLEMENTATION = "0x32403455357589523435dB18b414057D7cE05051";
4680
5342
  var YIELDSEEKER_V2_IMPLEMENTATION = "0x613Db9c924ADB7A7A90c11b02Cce20c913E3Fe50";
4681
5343
  var ERC1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
4682
- var walletAbi = (0, import_viem12.parseAbi)([
5344
+ var walletAbi = (0, import_viem13.parseAbi)([
4683
5345
  "function owner() view returns (address)",
4684
5346
  "function ownerAgentIndex() view returns (uint256)",
4685
5347
  "function baseAsset() view returns (address)",
@@ -4687,7 +5349,7 @@ var walletAbi = (0, import_viem12.parseAbi)([
4687
5349
  "function upgradeToLatest()",
4688
5350
  "event Upgraded(address indexed implementation)"
4689
5351
  ]);
4690
- var factoryAbi = (0, import_viem12.parseAbi)([
5352
+ var factoryAbi = (0, import_viem13.parseAbi)([
4691
5353
  "function userWallets(address owner, uint256 index) view returns (address)",
4692
5354
  "function agentWalletImplementation() view returns (address)"
4693
5355
  ]);
@@ -4695,9 +5357,9 @@ function yieldseekerOwnerPath(code) {
4695
5357
  return !code || code === "0x" || /^0xef0100[0-9a-f]{40}$/i.test(code) ? "eoa" : "smart";
4696
5358
  }
4697
5359
  async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNumber) {
4698
- const agentWallet = (0, import_viem12.getAddress)(wallet);
4699
- const expectedOwner = (0, import_viem12.getAddress)(owner);
4700
- const expectedAsset = (0, import_viem12.getAddress)(asset);
5360
+ const agentWallet = (0, import_viem13.getAddress)(wallet);
5361
+ const expectedOwner = (0, import_viem13.getAddress)(owner);
5362
+ const expectedAsset = (0, import_viem13.getAddress)(asset);
4701
5363
  const [code, ownerCode, slot, actualOwner, index, actualAsset, actualFactory, latest] = await Promise.all([
4702
5364
  client.getBytecode({ address: agentWallet, blockNumber }),
4703
5365
  client.getBytecode({ address: expectedOwner, blockNumber }),
@@ -4711,7 +5373,7 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
4711
5373
  if (!code || code === "0x" || !slot || /^0x0+$/.test(slot)) {
4712
5374
  throw new Error("Yieldseeker wallet is not a deployed ERC1967 proxy");
4713
5375
  }
4714
- const implementation = (0, import_viem12.getAddress)(`0x${slot.slice(-40)}`);
5376
+ const implementation = (0, import_viem13.getAddress)(`0x${slot.slice(-40)}`);
4715
5377
  const mapped = await client.readContract({
4716
5378
  address: YIELDSEEKER_FACTORY,
4717
5379
  abi: factoryAbi,
@@ -4719,8 +5381,8 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
4719
5381
  args: [expectedOwner, index],
4720
5382
  blockNumber
4721
5383
  });
4722
- const verified = (0, import_viem12.isAddressEqual)(actualOwner, expectedOwner) && (0, import_viem12.isAddressEqual)(actualAsset, expectedAsset) && (0, import_viem12.isAddressEqual)(actualFactory, YIELDSEEKER_FACTORY) && (0, import_viem12.isAddressEqual)(mapped, agentWallet);
4723
- const version = !verified ? "unknown" : (0, import_viem12.isAddressEqual)(implementation, YIELDSEEKER_V2_IMPLEMENTATION) ? "v2" : (0, import_viem12.isAddressEqual)(implementation, YIELDSEEKER_V1_IMPLEMENTATION) ? "v1" : "unknown";
5384
+ const verified = (0, import_viem13.isAddressEqual)(actualOwner, expectedOwner) && (0, import_viem13.isAddressEqual)(actualAsset, expectedAsset) && (0, import_viem13.isAddressEqual)(actualFactory, YIELDSEEKER_FACTORY) && (0, import_viem13.isAddressEqual)(mapped, agentWallet);
5385
+ const version = !verified ? "unknown" : (0, import_viem13.isAddressEqual)(implementation, YIELDSEEKER_V2_IMPLEMENTATION) ? "v2" : (0, import_viem13.isAddressEqual)(implementation, YIELDSEEKER_V1_IMPLEMENTATION) ? "v1" : "unknown";
4724
5386
  return {
4725
5387
  agentWallet,
4726
5388
  owner: actualOwner,
@@ -4729,16 +5391,17 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
4729
5391
  implementation,
4730
5392
  version,
4731
5393
  verified,
4732
- upgradeAvailable: version === "v1" && (0, import_viem12.isAddressEqual)(latest, YIELDSEEKER_V2_IMPLEMENTATION)
5394
+ upgradeAvailable: version === "v1" && (0, import_viem13.isAddressEqual)(latest, YIELDSEEKER_V2_IMPLEMENTATION)
4733
5395
  };
4734
5396
  }
4735
5397
  var YIELDSEEKER_UPGRADE_ABI = walletAbi;
4736
5398
 
4737
5399
  // src/agents/yieldseeker/yieldseeker.sponsored-withdraw.ts
4738
- var import_viem13 = require("viem");
5400
+ var import_viem14 = require("viem");
4739
5401
  var import_account_abstraction2 = require("viem/account-abstraction");
4740
5402
  var import_accounts = require("viem/accounts");
4741
5403
  var import_chains3 = require("viem/chains");
5404
+ init_errors();
4742
5405
  var ENTRY_POINT_V06 = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
4743
5406
  var USER_OP_FEE_HEADROOM = 2n;
4744
5407
  var OBSERVATION_WINDOW_MS = 6e4;
@@ -4822,7 +5485,7 @@ function rpcDiagnostics(data) {
4822
5485
  details.revertName = data.revertName;
4823
5486
  if (typeof data?.aaCode === "string" && /^AA[0-9]{2}$/.test(data.aaCode)) details.aaCode = data.aaCode;
4824
5487
  if (typeof data?.panicCode === "string" && /^0x[0-9a-fA-F]{1,2}$/.test(data.panicCode)) {
4825
- const panicCode = (0, import_viem13.toHex)(BigInt(data.panicCode));
5488
+ const panicCode = (0, import_viem14.toHex)(BigInt(data.panicCode));
4826
5489
  if (["0x0", "0x1", "0x11", "0x12", "0x21", "0x22", "0x31", "0x32", "0x41", "0x51"].includes(panicCode))
4827
5490
  details.panicCode = panicCode;
4828
5491
  }
@@ -4863,9 +5526,9 @@ function savePending(onPending, evidence, beforeSubmission = false) {
4863
5526
  );
4864
5527
  }
4865
5528
  }
4866
- async function checkpoint(callback, pending) {
5529
+ async function checkpoint(callback, pending2) {
4867
5530
  try {
4868
- await callback?.(pending);
5531
+ await callback?.(pending2);
4869
5532
  } catch {
4870
5533
  throw sponsorError(
4871
5534
  "Withdrawal status cannot be saved before submission.",
@@ -5042,14 +5705,14 @@ async function submitEoa(input) {
5042
5705
  throw sponsorError("Base did not return EIP-1559 gas fees.", true);
5043
5706
  let operation = {
5044
5707
  sender: input.agentWallet,
5045
- nonce: (0, import_viem13.toHex)(nonce),
5708
+ nonce: (0, import_viem14.toHex)(nonce),
5046
5709
  initCode: "0x",
5047
5710
  callData: input.callData,
5048
- callGasLimit: (0, import_viem13.toHex)(3e5),
5049
- verificationGasLimit: (0, import_viem13.toHex)(3e5),
5050
- preVerificationGas: (0, import_viem13.toHex)(6e4),
5051
- maxFeePerGas: (0, import_viem13.toHex)(fees.maxFeePerGas * USER_OP_FEE_HEADROOM),
5052
- maxPriorityFeePerGas: (0, import_viem13.toHex)(fees.maxPriorityFeePerGas),
5711
+ callGasLimit: (0, import_viem14.toHex)(3e5),
5712
+ verificationGasLimit: (0, import_viem14.toHex)(3e5),
5713
+ preVerificationGas: (0, import_viem14.toHex)(6e4),
5714
+ maxFeePerGas: (0, import_viem14.toHex)(fees.maxFeePerGas * USER_OP_FEE_HEADROOM),
5715
+ maxPriorityFeePerGas: (0, import_viem14.toHex)(fees.maxPriorityFeePerGas),
5053
5716
  paymasterAndData: "0x",
5054
5717
  signature: "0x"
5055
5718
  };
@@ -5057,7 +5720,7 @@ async function submitEoa(input) {
5057
5720
  const stub = await rpc(
5058
5721
  input.rpcUrl,
5059
5722
  "pm_getPaymasterStubData",
5060
- [operation, ENTRY_POINT_V06, (0, import_viem13.toHex)(8453), {}],
5723
+ [operation, ENTRY_POINT_V06, (0, import_viem14.toHex)(8453), {}],
5061
5724
  "prepare"
5062
5725
  );
5063
5726
  if (!stub.paymasterAndData?.startsWith("0x"))
@@ -5072,7 +5735,7 @@ async function submitEoa(input) {
5072
5735
  const final = await rpc(
5073
5736
  input.rpcUrl,
5074
5737
  "pm_getPaymasterData",
5075
- [operation, ENTRY_POINT_V06, (0, import_viem13.toHex)(8453), {}],
5738
+ [operation, ENTRY_POINT_V06, (0, import_viem14.toHex)(8453), {}],
5076
5739
  "prepare"
5077
5740
  );
5078
5741
  if (!final.paymasterAndData?.startsWith("0x"))
@@ -5082,10 +5745,10 @@ async function submitEoa(input) {
5082
5745
  const userOpHash = operationHash(operation);
5083
5746
  await assertOwnerSession(input.state, input.owner);
5084
5747
  assertIntentFresh(input.expiresAt);
5085
- const wallet = (0, import_viem13.createWalletClient)({
5748
+ const wallet = (0, import_viem14.createWalletClient)({
5086
5749
  account: input.owner,
5087
5750
  chain: import_chains3.base,
5088
- transport: (0, import_viem13.custom)(input.state.provider)
5751
+ transport: (0, import_viem14.custom)(input.state.provider)
5089
5752
  });
5090
5753
  input.assertCurrent?.();
5091
5754
  const signature = await wallet.signMessage({ message: { raw: userOpHash } });
@@ -5166,13 +5829,13 @@ async function submitSmart(input) {
5166
5829
  } catch {
5167
5830
  throw sponsorError("This account cannot check paymaster support on Base.", true);
5168
5831
  }
5169
- const supportsPaymaster = capabilities?.[(0, import_viem13.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
5832
+ const supportsPaymaster = capabilities?.[(0, import_viem14.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
5170
5833
  if (supportsPaymaster !== true)
5171
5834
  throw sponsorError("This account cannot use a paymaster on Base.", true);
5172
5835
  await assertOwnerSession(input.state, input.owner);
5173
5836
  let sent;
5174
5837
  assertIntentFresh(input.expiresAt);
5175
- const requestedId = (0, import_viem13.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
5838
+ const requestedId = (0, import_viem14.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
5176
5839
  savePending(input.onPending, { callsId: requestedId }, true);
5177
5840
  input.assertCurrent?.();
5178
5841
  await checkpoint(input.onBeforeSubmission, { callsId: requestedId });
@@ -5183,7 +5846,7 @@ async function submitSmart(input) {
5183
5846
  params: [{
5184
5847
  version: "2.0.0",
5185
5848
  from: input.owner,
5186
- chainId: (0, import_viem13.toHex)(8453),
5849
+ chainId: (0, import_viem14.toHex)(8453),
5187
5850
  id: requestedId,
5188
5851
  atomicRequired: false,
5189
5852
  calls: [{ to: input.agentWallet, value: "0x0", data: input.callData }],
@@ -5258,7 +5921,7 @@ async function submitSmart(input) {
5258
5921
  );
5259
5922
  }
5260
5923
  async function submitYieldseekerSponsoredWithdrawal(input) {
5261
- const owner = (0, import_viem13.getAddress)(input.state.walletAddress);
5924
+ const owner = (0, import_viem14.getAddress)(input.state.walletAddress);
5262
5925
  const { intent, rpcUrl } = await requestIntent({
5263
5926
  apiKey: input.apiKey,
5264
5927
  routingApiBaseUrl: input.routingApiBaseUrl,
@@ -5277,7 +5940,7 @@ async function submitYieldseekerSponsoredWithdrawal(input) {
5277
5940
  return intent.ownerPath === "eoa" ? submitEoa(args) : submitSmart(args);
5278
5941
  }
5279
5942
  async function submitYieldseekerSponsoredUpgrade(input) {
5280
- const owner = (0, import_viem13.getAddress)(input.state.walletAddress);
5943
+ const owner = (0, import_viem14.getAddress)(input.state.walletAddress);
5281
5944
  const { intent, rpcUrl } = await requestIntent({
5282
5945
  apiKey: input.apiKey,
5283
5946
  routingApiBaseUrl: input.routingApiBaseUrl,
@@ -5297,6 +5960,57 @@ async function submitYieldseekerSponsoredUpgrade(input) {
5297
5960
  return submitSmart({ ...input, owner, rpcUrl, expiresAt: intent.expiresAt });
5298
5961
  }
5299
5962
 
5963
+ // src/agents/yieldseeker/yieldseeker.vault-reads.ts
5964
+ var import_viem15 = require("viem");
5965
+ var nativeAbi = (0, import_viem15.parseAbi)([
5966
+ "function underlying() view returns (address)",
5967
+ "function baseToken() view returns (address)",
5968
+ "function UNDERLYING_ASSET_ADDRESS() view returns (address)",
5969
+ "function balanceOfUnderlying(address owner) returns (uint256)"
5970
+ ]);
5971
+ function nativeYieldseekerProtocol(option) {
5972
+ switch (option.provider?.toLowerCase()) {
5973
+ case "moonwell":
5974
+ return "moonwell";
5975
+ case "compound":
5976
+ return "compound";
5977
+ case "aave":
5978
+ return "aave";
5979
+ default:
5980
+ return void 0;
5981
+ }
5982
+ }
5983
+ function yieldseekerUnderlyingCall(option) {
5984
+ const address = (0, import_viem15.getAddress)(option.address);
5985
+ switch (nativeYieldseekerProtocol(option)) {
5986
+ case "moonwell":
5987
+ return { address, abi: nativeAbi, functionName: "underlying" };
5988
+ case "compound":
5989
+ return { address, abi: nativeAbi, functionName: "baseToken" };
5990
+ case "aave":
5991
+ return { address, abi: nativeAbi, functionName: "UNDERLYING_ASSET_ADDRESS" };
5992
+ default:
5993
+ return { address, abi: import_viem15.erc4626Abi, functionName: "asset" };
5994
+ }
5995
+ }
5996
+ async function readNativeYieldseekerAssets(client, option, wallet, balance, blockNumber) {
5997
+ if (nativeYieldseekerProtocol(option) !== "moonwell") {
5998
+ return balance;
5999
+ }
6000
+ try {
6001
+ const { data } = await client.call({
6002
+ to: (0, import_viem15.getAddress)(option.address),
6003
+ blockNumber,
6004
+ data: (0, import_viem15.encodeFunctionData)({ abi: nativeAbi, functionName: "balanceOfUnderlying", args: [(0, import_viem15.getAddress)(wallet)] })
6005
+ });
6006
+ if (!data) return void 0;
6007
+ const assets = (0, import_viem15.decodeFunctionResult)({ abi: nativeAbi, functionName: "balanceOfUnderlying", data });
6008
+ return assets > 0n ? assets : void 0;
6009
+ } catch {
6010
+ return void 0;
6011
+ }
6012
+ }
6013
+
5300
6014
  // src/agents/yieldseeker/yieldseeker.agent.ts
5301
6015
  var OWNEY_AGENT_NAME = "owney";
5302
6016
  var OWNEY_AGENT_RULE_PRESET = "explorative";
@@ -5306,7 +6020,8 @@ var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
5306
6020
  var YIELDSEEKER_VAULT_OPTIONS_CACHE_MS = 6e4;
5307
6021
  var YIELDSEEKER_AGENT_LIST_CACHE_MS = 12e4;
5308
6022
  var YIELDSEEKER_PORTFOLIO_CACHE_MS = 12e4;
5309
- var YIELDSEEKER_SETTLEMENT_CACHE_MS = 5e3;
6023
+ var YIELDSEEKER_SETTLEMENT_BACKOFF_MS = [5e3, 1e4, 2e4, 4e4, 6e4];
6024
+ var YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS = 10 * 6e4;
5310
6025
  var YIELDSEEKER_SETTLEMENT_ACTIVITY_CACHE_MS = 15e3;
5311
6026
  var YIELDSEEKER_READ_FAILURE_COOLDOWN_MS = 6e4;
5312
6027
  var YIELDSEEKER_SETTLEMENT_WINDOW_MS = 5 * 6e4;
@@ -5393,6 +6108,7 @@ var YieldseekerAgent = class {
5393
6108
  receiptClient;
5394
6109
  // A client preparation hint only; the routing API still checks live identity.
5395
6110
  withdrawalVersionCache = /* @__PURE__ */ new Map();
6111
+ pendingWalletStatus = /* @__PURE__ */ new Map();
5396
6112
  pendingUpgrades = /* @__PURE__ */ new Map();
5397
6113
  transactionExecutor;
5398
6114
  unwindReceiptWaiter;
@@ -5409,6 +6125,7 @@ var YieldseekerAgent = class {
5409
6125
  liquidityVersions = /* @__PURE__ */ new Map();
5410
6126
  snapshotFailures = /* @__PURE__ */ new Map();
5411
6127
  standardReadFailures = /* @__PURE__ */ new Map();
6128
+ endpointReadFailures = /* @__PURE__ */ new Map();
5412
6129
  reconcileUntil = /* @__PURE__ */ new Map();
5413
6130
  allocationRefresh = /* @__PURE__ */ new Set();
5414
6131
  activityRefreshUntil = /* @__PURE__ */ new Map();
@@ -5416,6 +6133,8 @@ var YieldseekerAgent = class {
5416
6133
  // settlement; keep slow reconciliation after the fast window expires.
5417
6134
  snapshotMovements = /* @__PURE__ */ new Map();
5418
6135
  movementEpochs = /* @__PURE__ */ new Map();
6136
+ // Forced checks issued by the current movement's settlement schedule.
6137
+ settlementChecks = /* @__PURE__ */ new Map();
5419
6138
  vaultOptions = /* @__PURE__ */ new Map();
5420
6139
  pendingVaultOptions = /* @__PURE__ */ new Map();
5421
6140
  constructor(owneyApiKey, options = {}) {
@@ -5439,19 +6158,31 @@ var YieldseekerAgent = class {
5439
6158
  async getWalletStatus(state, chainId, asset, useCachedV2 = false) {
5440
6159
  this.assertChain(chainId);
5441
6160
  this.assertAsset(asset);
6161
+ const generation = this.readGeneration;
5442
6162
  const context = await this.findAgent(state, chainId, asset);
6163
+ this.assertSession(generation, chainId, asset);
5443
6164
  if (!context) return null;
5444
6165
  const key2 = `${chainId}:${state.walletAddress.toLowerCase()}:${context.wallet.walletAddress.toLowerCase()}:${asset}`;
5445
6166
  const cached = this.withdrawalVersionCache.get(key2);
5446
6167
  if (useCachedV2 && cached && Date.now() - cached.at < 15 * 6e4) return { ...cached.status };
5447
- const status = await readYieldseekerWalletStatus(
6168
+ const existing = this.pendingWalletStatus.get(key2);
6169
+ if (existing) return { ...await existing };
6170
+ const pending2 = readYieldseekerWalletStatus(
5448
6171
  this.getReceiptClient(),
5449
- (0, import_viem14.getAddress)(context.wallet.walletAddress),
5450
- (0, import_viem14.getAddress)(state.walletAddress),
6172
+ (0, import_viem16.getAddress)(context.wallet.walletAddress),
6173
+ (0, import_viem16.getAddress)(state.walletAddress),
5451
6174
  YIELDSEEKER_ASSET_METADATA[asset].address
5452
- );
5453
- this.rememberWalletStatus(key2, status);
5454
- return status;
6175
+ ).then((status) => {
6176
+ this.assertSession(generation, chainId, asset);
6177
+ if (this.pendingWalletStatus.get(key2) !== pending2)
6178
+ throw new OwneyError("AGENT_API_ERROR", "Yieldseeker wallet verification changed. Please retry.", void 0, this.id);
6179
+ this.rememberWalletStatus(key2, status);
6180
+ return status;
6181
+ }).finally(() => {
6182
+ if (this.pendingWalletStatus.get(key2) === pending2) this.pendingWalletStatus.delete(key2);
6183
+ });
6184
+ this.pendingWalletStatus.set(key2, pending2);
6185
+ return { ...await pending2 };
5455
6186
  }
5456
6187
  rememberWalletStatus(key2, status) {
5457
6188
  if (status.verified && status.version === "v2") {
@@ -5477,12 +6208,13 @@ var YieldseekerAgent = class {
5477
6208
  const pendingKey2 = `owney.yieldseeker.upgrade:${before.owner.toLowerCase()}:${before.agentWallet.toLowerCase()}`;
5478
6209
  const confirmUpgrade = async (hash2, receipt2) => {
5479
6210
  this.withdrawalVersionCache.delete(versionKey);
5480
- const upgradeTopic = (0, import_viem14.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
6211
+ this.pendingWalletStatus.delete(versionKey);
6212
+ const upgradeTopic = (0, import_viem16.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
5481
6213
  const lastUpgrade = receipt2?.logs.filter((log) => log.address.toLowerCase() === before.agentWallet.toLowerCase() && log.topics[0] === upgradeTopic).at(-1);
5482
6214
  const expectedUpgrade = (() => {
5483
6215
  if (!lastUpgrade || lastUpgrade.removed) return false;
5484
6216
  try {
5485
- const event = (0, import_viem14.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
6217
+ const event = (0, import_viem16.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
5486
6218
  return event.args.implementation.toLowerCase() === YIELDSEEKER_V2_IMPLEMENTATION.toLowerCase();
5487
6219
  } catch {
5488
6220
  return false;
@@ -5620,7 +6352,7 @@ var YieldseekerAgent = class {
5620
6352
  { version: before.version },
5621
6353
  this.id
5622
6354
  );
5623
- const data = (0, import_viem14.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
6355
+ const data = (0, import_viem16.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
5624
6356
  let txHash;
5625
6357
  let receipt;
5626
6358
  if (gasMode === "sponsored") {
@@ -5646,9 +6378,9 @@ var YieldseekerAgent = class {
5646
6378
  agentWallet: before.agentWallet,
5647
6379
  asset: YIELDSEEKER_ASSET_METADATA[asset].address,
5648
6380
  callData: data,
5649
- onPending: (pending) => {
6381
+ onPending: (pending2) => {
5650
6382
  const current = this.pendingUpgrades.has(pendingKey2) ? this.pendingUpgrades.get(pendingKey2) : JSON.parse(storage8.getItem(pendingKey2) ?? "null");
5651
- const next = { startedAt: Date.now(), ...current, ...pending };
6383
+ const next = { startedAt: Date.now(), ...current, ...pending2 };
5652
6384
  storage8.setItem(pendingKey2, JSON.stringify(next));
5653
6385
  this.pendingUpgrades.delete(pendingKey2);
5654
6386
  }
@@ -5663,18 +6395,18 @@ var YieldseekerAgent = class {
5663
6395
  let submittedHash;
5664
6396
  try {
5665
6397
  txHash = await this.submitTransaction(state, chainId, {
5666
- from: (0, import_viem14.getAddress)(state.walletAddress),
6398
+ from: (0, import_viem16.getAddress)(state.walletAddress),
5667
6399
  to: before.agentWallet,
5668
6400
  data,
5669
6401
  value: "0",
5670
6402
  chainId
5671
6403
  }, (hash2) => {
5672
6404
  submittedHash = hash2;
5673
- const pending = { txHash: hash2 };
5674
- this.pendingUpgrades.set(pendingKey2, pending);
6405
+ const pending2 = { txHash: hash2 };
6406
+ this.pendingUpgrades.set(pendingKey2, pending2);
5675
6407
  try {
5676
6408
  if (storage8) {
5677
- storage8.setItem(pendingKey2, JSON.stringify(pending));
6409
+ storage8.setItem(pendingKey2, JSON.stringify(pending2));
5678
6410
  this.pendingUpgrades.delete(pendingKey2);
5679
6411
  }
5680
6412
  } catch {
@@ -5697,6 +6429,7 @@ var YieldseekerAgent = class {
5697
6429
  }
5698
6430
  async disconnect() {
5699
6431
  this.withdrawalVersionCache.clear();
6432
+ this.pendingWalletStatus.clear();
5700
6433
  this.readGeneration += 1;
5701
6434
  this.auth.clear();
5702
6435
  for (const key2 of this.users.keys()) {
@@ -5714,11 +6447,13 @@ var YieldseekerAgent = class {
5714
6447
  this.liquidityVersions.clear();
5715
6448
  this.snapshotFailures.clear();
5716
6449
  this.standardReadFailures.clear();
6450
+ this.endpointReadFailures.clear();
5717
6451
  this.reconcileUntil.clear();
5718
6452
  this.allocationRefresh.clear();
5719
6453
  this.activityRefreshUntil.clear();
5720
6454
  this.snapshotMovements.clear();
5721
6455
  this.movementEpochs.clear();
6456
+ this.settlementChecks.clear();
5722
6457
  }
5723
6458
  async activateAgent(state, chainId, asset) {
5724
6459
  this.assertChain(chainId);
@@ -5771,12 +6506,12 @@ var YieldseekerAgent = class {
5771
6506
  } else {
5772
6507
  try {
5773
6508
  txHash = await this.submitTransaction(state, chainId, {
5774
- from: (0, import_viem14.getAddress)(state.walletAddress),
6509
+ from: (0, import_viem16.getAddress)(state.walletAddress),
5775
6510
  to: YIELDSEEKER_ASSET_METADATA[asset].address,
5776
- data: (0, import_viem14.encodeFunctionData)({
5777
- abi: import_viem14.erc20Abi,
6511
+ data: (0, import_viem16.encodeFunctionData)({
6512
+ abi: import_viem16.erc20Abi,
5778
6513
  functionName: "transfer",
5779
- args: [(0, import_viem14.getAddress)(context.wallet.walletAddress), BigInt(amount)]
6514
+ args: [(0, import_viem16.getAddress)(context.wallet.walletAddress), BigInt(amount)]
5780
6515
  }),
5781
6516
  value: "0",
5782
6517
  chainId
@@ -5839,7 +6574,10 @@ var YieldseekerAgent = class {
5839
6574
  ownerTransferAttempted = true;
5840
6575
  }, gasMode, onBeforeSubmission, assertOperation);
5841
6576
  } catch (error) {
5842
- if (error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED") this.withdrawalVersionCache.clear();
6577
+ if (error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED") {
6578
+ this.withdrawalVersionCache.clear();
6579
+ this.pendingWalletStatus.clear();
6580
+ }
5843
6581
  if (!ownerTransferAttempted || error?.code === 4001 || error instanceof OwneyError && (error.code === "AGENT_TRANSACTION_REVERTED" || error.details?.ownerTransferNotExecuted === true || error.code === "SPONSOR_REQUEST_FAILED" && (error.details?.safeToFallback === true || error.details?.executionFailed === true)))
5844
6582
  notifyFunding(onProgress, {
5845
6583
  ...evidence,
@@ -5922,7 +6660,7 @@ var YieldseekerAgent = class {
5922
6660
  );
5923
6661
  const positionsRead = this.readWithdrawalPositions(state, chainId, context);
5924
6662
  const metadata = YIELDSEEKER_ASSET_METADATA[asset];
5925
- const agentWallet = (0, import_viem14.getAddress)(context.wallet.walletAddress);
6663
+ const agentWallet = (0, import_viem16.getAddress)(context.wallet.walletAddress);
5926
6664
  const readOwnerFunds = async (blockNumber) => {
5927
6665
  const feeTracker = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5928
6666
  address: agentWallet,
@@ -5931,18 +6669,18 @@ var YieldseekerAgent = class {
5931
6669
  blockNumber
5932
6670
  }), chainId, "eth_call", this.id);
5933
6671
  this.assertSession(generation, chainId, asset);
5934
- if (!(0, import_viem14.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
6672
+ if (!(0, import_viem16.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
5935
6673
  throw this.invalidResponse("wallet fee tracker");
5936
6674
  const [idle2, fees] = await Promise.all([
5937
6675
  withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5938
6676
  address: metadata.address,
5939
- abi: import_viem14.erc20Abi,
6677
+ abi: import_viem16.erc20Abi,
5940
6678
  functionName: "balanceOf",
5941
6679
  args: [agentWallet],
5942
6680
  blockNumber
5943
6681
  }), chainId, "eth_call", this.id),
5944
6682
  withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
5945
- address: (0, import_viem14.getAddress)(feeTracker),
6683
+ address: (0, import_viem16.getAddress)(feeTracker),
5946
6684
  abi: YIELDSEEKER_FEE_TRACKER_ABI,
5947
6685
  functionName: "getFeesOwed",
5948
6686
  args: [agentWallet],
@@ -5984,21 +6722,35 @@ var YieldseekerAgent = class {
5984
6722
  let active2 = true;
5985
6723
  const checks = this.readVaultShares(values.map((position2) => position2.vaultOption), agentWallet, blockNumber).catch(() => []);
5986
6724
  const reads = values.map(async (position2, index) => {
5987
- const address = (0, import_viem14.getAddress)(position2.vaultOption.address);
6725
+ const address = (0, import_viem16.getAddress)(position2.vaultOption.address);
5988
6726
  try {
5989
6727
  const group = (await checks).slice(index * 2, index * 2 + 2);
5990
6728
  if (!active2 || group.length !== 2 || group.some((value) => value.status !== "success")) return null;
5991
6729
  this.assertSession(generation, chainId, asset);
5992
6730
  const [underlying, shares] = group.map((value) => value.result);
5993
- if (typeof underlying !== "string" || !(0, import_viem14.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n) return null;
6731
+ if (typeof underlying !== "string" || !(0, import_viem16.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n) return null;
5994
6732
  const verified = { ...position2, assetsRaw: shares.toString(), withdrawableAssetsRaw: "0" };
6733
+ if (shares > 0n && nativeYieldseekerProtocol(position2.vaultOption)) {
6734
+ const value = await readNativeYieldseekerAssets(
6735
+ this.getReceiptClient(),
6736
+ position2.vaultOption,
6737
+ agentWallet,
6738
+ shares,
6739
+ blockNumber
6740
+ );
6741
+ if (!active2 || value === void 0) return null;
6742
+ this.assertSession(generation, chainId, asset);
6743
+ verified.withdrawableAssetsRaw = value.toString();
6744
+ verifiedPositions.push(verified);
6745
+ return verified;
6746
+ }
5995
6747
  if (shares > 0n) {
5996
6748
  let positiveValue = false;
5997
6749
  const valuations = await Promise.all(["convertToAssets", "previewRedeem"].map(async (functionName) => {
5998
6750
  try {
5999
6751
  const value = await this.getReceiptClient().readContract({
6000
6752
  address,
6001
- abi: import_viem14.erc4626Abi,
6753
+ abi: import_viem16.erc4626Abi,
6002
6754
  functionName,
6003
6755
  args: [shares],
6004
6756
  blockNumber
@@ -6239,7 +6991,7 @@ var YieldseekerAgent = class {
6239
6991
  delta: maxSettlementBasis.delta - payout,
6240
6992
  expectedNetDeposits: maxSettlementBasis.expectedNetDeposits - payout
6241
6993
  } : this.snapshotMovement(state, chainId, context, -payout);
6242
- const account = (0, import_viem14.getAddress)(state.walletAddress);
6994
+ const account = (0, import_viem16.getAddress)(state.walletAddress);
6243
6995
  let receipt;
6244
6996
  const base7 = { agentId: this.id, chainId, token: asset, walletAddress: state.walletAddress, agentWallet: context.wallet.walletAddress, intendedAmount: amount ?? "MAX", transfer: "pending", registration: "not-applicable", delivery: "pending" };
6245
6997
  if (amount === void 0) base7.maxCompletion = {
@@ -6250,11 +7002,11 @@ var YieldseekerAgent = class {
6250
7002
  };
6251
7003
  if (base7.maxCompletion) notifyFunding(onProgress, base7);
6252
7004
  let submissionEvidence = base7;
6253
- const data = amount === void 0 ? (0, import_viem14.encodeFunctionData)({
7005
+ const data = amount === void 0 ? (0, import_viem16.encodeFunctionData)({
6254
7006
  abi: YIELDSEEKER_AGENT_WALLET_ABI,
6255
7007
  functionName: "withdrawAllAssetToUser",
6256
7008
  args: [account, metadata.address]
6257
- }) : (0, import_viem14.encodeFunctionData)({
7009
+ }) : (0, import_viem16.encodeFunctionData)({
6258
7010
  abi: YIELDSEEKER_AGENT_WALLET_ABI,
6259
7011
  functionName: "withdrawAssetToUser",
6260
7012
  args: [account, metadata.address, payout]
@@ -6271,16 +7023,16 @@ var YieldseekerAgent = class {
6271
7023
  refreshYieldseekerSignature: (rejected) => this.auth.refreshToken(state, chainId, rejected),
6272
7024
  userId: context.user.userId,
6273
7025
  agentId: context.agent.agentId,
6274
- agentWallet: (0, import_viem14.getAddress)(context.wallet.walletAddress),
7026
+ agentWallet: (0, import_viem16.getAddress)(context.wallet.walletAddress),
6275
7027
  asset: metadata.address,
6276
7028
  callData: data,
6277
- onPending: (pending) => {
6278
- submissionEvidence = { ...submissionEvidence, ...pending };
7029
+ onPending: (pending2) => {
7030
+ submissionEvidence = { ...submissionEvidence, ...pending2 };
6279
7031
  notifyFunding(onProgress, submissionEvidence);
6280
7032
  },
6281
- onBeforeSubmission: async (pending) => {
7033
+ onBeforeSubmission: async (pending2) => {
6282
7034
  assertOperation?.();
6283
- await onBeforeSubmission?.({ ...base7, ...pending });
7035
+ await onBeforeSubmission?.({ ...base7, ...pending2 });
6284
7036
  onOwnerTransferAttempted?.();
6285
7037
  }
6286
7038
  });
@@ -6293,7 +7045,7 @@ var YieldseekerAgent = class {
6293
7045
  chainId,
6294
7046
  {
6295
7047
  from: account,
6296
- to: (0, import_viem14.getAddress)(context.wallet.walletAddress),
7048
+ to: (0, import_viem16.getAddress)(context.wallet.walletAddress),
6297
7049
  data,
6298
7050
  value: "0",
6299
7051
  chainId
@@ -6423,7 +7175,7 @@ var YieldseekerAgent = class {
6423
7175
  async verifyWithdrawalCompletion(state, evidence) {
6424
7176
  const unknown = (reason2) => ({ status: "unavailable", reason: reason2 });
6425
7177
  const proof = evidence.maxCompletion;
6426
- if (evidence.agentId !== this.id || evidence.walletAddress.toLowerCase() !== state.walletAddress.toLowerCase() || evidence.chainId !== 8453 || !proof || !evidence.agentWallet || !(0, import_viem14.isAddress)(evidence.agentWallet) || !evidence.blockNumber || !/^\d+$/.test(evidence.blockNumber) || evidence.transfer !== "confirmed" || evidence.delivery !== "confirmed" || !this.isTransactionHash(evidence.txHash)) return unknown("PAYOUT_PROOF_UNAVAILABLE");
7178
+ if (evidence.agentId !== this.id || evidence.walletAddress.toLowerCase() !== state.walletAddress.toLowerCase() || evidence.chainId !== 8453 || !proof || !evidence.agentWallet || !(0, import_viem16.isAddress)(evidence.agentWallet) || !evidence.blockNumber || !/^\d+$/.test(evidence.blockNumber) || evidence.transfer !== "confirmed" || evidence.delivery !== "confirmed" || !this.isTransactionHash(evidence.txHash)) return unknown("PAYOUT_PROOF_UNAVAILABLE");
6427
7179
  this.assertAsset(evidence.token);
6428
7180
  const asset = evidence.token;
6429
7181
  const metadata = YIELDSEEKER_ASSET_METADATA[asset];
@@ -6438,28 +7190,35 @@ var YieldseekerAgent = class {
6438
7190
  );
6439
7191
  if (!Array.isArray(response?.vaultPositions)) return unknown("CATALOG_INVALID");
6440
7192
  const positions = this.validateWithdrawalPositions(response.vaultPositions, evidence.chainId, asset);
6441
- const vaults = new Set([...proof.vaults, ...positions.map((p) => p.vaultOption.address)].map((a) => a.toLowerCase()));
6442
- if (!proof.inventoryComplete) {
6443
- const catalog = await this.loadVaultOptions(asset);
6444
- const eligible = catalog.filter((o) => o.chainId === evidence.chainId && o.assetAddress?.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem14.isAddress)(o.address));
6445
- if (!eligible.length) return unknown("INVENTORY_INCOMPLETE");
6446
- eligible.forEach((o) => vaults.add(o.address.toLowerCase()));
7193
+ const vaults = new Map(proof.vaults.map((address) => [address.toLowerCase(), { address }]));
7194
+ positions.forEach((p) => vaults.set(p.vaultOption.address.toLowerCase(), p.vaultOption));
7195
+ const needsInventory = !proof.inventoryComplete;
7196
+ if (needsInventory || [...vaults.values()].some((option) => !option.provider)) {
7197
+ const catalog = await this.loadVaultOptions(asset).catch(() => []);
7198
+ const eligible = catalog.filter((o) => o.chainId === evidence.chainId && o.assetAddress?.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem16.isAddress)(o.address));
7199
+ if (needsInventory && !eligible.length) return unknown("INVENTORY_INCOMPLETE");
7200
+ for (const option of eligible) {
7201
+ const key2 = option.address.toLowerCase();
7202
+ if (needsInventory || vaults.has(key2)) vaults.set(key2, option);
7203
+ }
6447
7204
  }
6448
- if (vaults.size > YIELDSEEKER_WITHDRAWAL_CANDIDATE_LIMIT || [...vaults].some((a) => !(0, import_viem14.isAddress)(a)))
7205
+ if (vaults.size > YIELDSEEKER_WITHDRAWAL_CANDIDATE_LIMIT || [...vaults.keys()].some((a) => !(0, import_viem16.isAddress)(a)))
6449
7206
  return unknown("INVENTORY_INVALID");
6450
7207
  reason = "VAULT_PROOF_UNAVAILABLE";
6451
7208
  const blockNumber = BigInt(evidence.blockNumber);
6452
- const addresses = [...vaults];
6453
- const shares = await this.readVaultShares(addresses.map((address) => ({ address })), evidence.agentWallet, blockNumber);
7209
+ const options = [...vaults.values()];
7210
+ const addresses = options.map((option) => option.address);
7211
+ const shares = await this.readVaultShares(options, evidence.agentWallet, blockNumber);
6454
7212
  const checks = await Promise.all(addresses.map(async (address, i) => {
6455
7213
  const group = shares.slice(i * 2, i * 2 + 2);
6456
7214
  if (group.length !== 2 || group.some((r) => r.status !== "success")) return "unavailable";
6457
7215
  const [underlying, value] = group.map((r) => r.result);
6458
7216
  if (typeof underlying !== "string" || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof value !== "bigint" || value < 0n) return "unavailable";
6459
7217
  if (value === 0n) return "complete";
7218
+ if (nativeYieldseekerProtocol(options[i])) return "remaining";
6460
7219
  const amounts = await Promise.allSettled(["convertToAssets", "previewRedeem"].map((functionName) => this.getReceiptClient().readContract({
6461
- address: (0, import_viem14.getAddress)(address),
6462
- abi: import_viem14.erc4626Abi,
7220
+ address: (0, import_viem16.getAddress)(address),
7221
+ abi: import_viem16.erc4626Abi,
6463
7222
  functionName,
6464
7223
  args: [value],
6465
7224
  blockNumber
@@ -6479,16 +7238,16 @@ var YieldseekerAgent = class {
6479
7238
  }
6480
7239
  }
6481
7240
  async readVaultShares(options, wallet, blockNumber) {
6482
- const owner = (0, import_viem14.getAddress)(wallet);
7241
+ const owner = (0, import_viem16.getAddress)(wallet);
6483
7242
  const batches = Array.from({ length: Math.ceil(options.length / YIELDSEEKER_VAULTS_PER_RPC_BATCH) }, (_, index) => options.slice(index * YIELDSEEKER_VAULTS_PER_RPC_BATCH, (index + 1) * YIELDSEEKER_VAULTS_PER_RPC_BATCH));
6484
7243
  const results = await Promise.all(batches.map((batch) => this.getReceiptClient().multicall({
6485
7244
  blockNumber,
6486
7245
  allowFailure: true,
6487
7246
  contracts: batch.flatMap((option) => {
6488
- const address = (0, import_viem14.getAddress)(option.address);
7247
+ const address = (0, import_viem16.getAddress)(option.address);
6489
7248
  return [
6490
- { address, abi: import_viem14.erc4626Abi, functionName: "asset" },
6491
- { address, abi: import_viem14.erc20Abi, functionName: "balanceOf", args: [owner] }
7249
+ yieldseekerUnderlyingCall(option),
7250
+ { address, abi: import_viem16.erc20Abi, functionName: "balanceOf", args: [owner] }
6492
7251
  ];
6493
7252
  })
6494
7253
  })));
@@ -6499,7 +7258,7 @@ var YieldseekerAgent = class {
6499
7258
  const seen = /* @__PURE__ */ new Set();
6500
7259
  for (const value of values) {
6501
7260
  const option = value?.vaultOption;
6502
- if (!option || typeof option.address !== "string" || !(0, import_viem14.isAddress)(option.address) || seen.has(option.address.toLowerCase()) || option.chainId !== void 0 && option.chainId !== chainId || option.assetAddress !== void 0 && (typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== underlying) || typeof value.assetsRaw !== "string" || !/^\d+$/.test(value.assetsRaw) || typeof value.withdrawableAssetsRaw !== "string" || !/^\d+$/.test(value.withdrawableAssetsRaw))
7261
+ if (!option || typeof option.address !== "string" || !(0, import_viem16.isAddress)(option.address) || seen.has(option.address.toLowerCase()) || option.chainId !== void 0 && option.chainId !== chainId || option.assetAddress !== void 0 && (typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== underlying) || typeof value.assetsRaw !== "string" || !/^\d+$/.test(value.assetsRaw) || typeof value.withdrawableAssetsRaw !== "string" || !/^\d+$/.test(value.withdrawableAssetsRaw))
6503
7262
  throw this.invalidResponse("vault positions");
6504
7263
  seen.add(option.address.toLowerCase());
6505
7264
  }
@@ -6512,7 +7271,7 @@ var YieldseekerAgent = class {
6512
7271
  const historic = this.readCache.get(`historic:${key2}`)?.value?.position;
6513
7272
  const receivedAssets = new Set((historic?.movements ?? []).filter((movement) => movement.chainId === chainId && movement.agentWalletId === context.wallet.agentWalletId && movement.toAddress?.toLowerCase() === context.wallet.walletAddress.toLowerCase()).filter((movement) => typeof movement.assetAddress === "string").map((movement) => movement.assetAddress.toLowerCase()));
6514
7273
  for (const option of this.vaultOptions.get(context.asset)?.value ?? []) {
6515
- if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0, import_viem14.isAddress)(option.address) || !receivedAssets.has(option.address.toLowerCase()) || hints.has(option.address.toLowerCase())) continue;
7274
+ if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0, import_viem16.isAddress)(option.address) || !receivedAssets.has(option.address.toLowerCase()) || hints.has(option.address.toLowerCase())) continue;
6516
7275
  hints.set(option.address.toLowerCase(), {
6517
7276
  vaultOption: option,
6518
7277
  assetsRaw: "0",
@@ -6566,7 +7325,7 @@ var YieldseekerAgent = class {
6566
7325
  const read2 = async () => {
6567
7326
  const client = this.getReceiptClient();
6568
7327
  const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
6569
- const wallet = (0, import_viem14.getAddress)(context.wallet.walletAddress);
7328
+ const wallet = (0, import_viem16.getAddress)(context.wallet.walletAddress);
6570
7329
  assertReadCurrent();
6571
7330
  if (typeof blockNumber !== "bigint") throw unavailable();
6572
7331
  const indexedPositions = this.validateWithdrawalPositions(positions ?? [], chainId, context.asset);
@@ -6579,7 +7338,7 @@ var YieldseekerAgent = class {
6579
7338
  const [idle, feeTracker] = await Promise.all([
6580
7339
  client.readContract({
6581
7340
  address: metadata.address,
6582
- abi: import_viem14.erc20Abi,
7341
+ abi: import_viem16.erc20Abi,
6583
7342
  functionName: "balanceOf",
6584
7343
  args: [wallet],
6585
7344
  blockNumber
@@ -6591,10 +7350,10 @@ var YieldseekerAgent = class {
6591
7350
  blockNumber
6592
7351
  })
6593
7352
  ]);
6594
- if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem14.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
7353
+ if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem16.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
6595
7354
  assertReadCurrent();
6596
7355
  const fees = await client.readContract({
6597
- address: (0, import_viem14.getAddress)(feeTracker),
7356
+ address: (0, import_viem16.getAddress)(feeTracker),
6598
7357
  abi: YIELDSEEKER_FEE_TRACKER_ABI,
6599
7358
  functionName: "getFeesOwed",
6600
7359
  args: [wallet],
@@ -6646,7 +7405,7 @@ var YieldseekerAgent = class {
6646
7405
  const group = results.slice(index * 2, index * 2 + 2);
6647
7406
  if (group.length !== 2 || group.some((value2) => value2.status !== "success")) return false;
6648
7407
  const [underlying, shares] = group.map((value2) => value2.result);
6649
- if (typeof underlying !== "string" || !(0, import_viem14.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n) return false;
7408
+ if (typeof underlying !== "string" || !(0, import_viem16.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n) return false;
6650
7409
  if (shares > 0n) known.add(option.address.toLowerCase());
6651
7410
  const position2 = {
6652
7411
  vaultOption: option,
@@ -6660,11 +7419,21 @@ var YieldseekerAgent = class {
6660
7419
  verified.push(position2);
6661
7420
  knownProof = proof(false);
6662
7421
  if (shares === 0n) return true;
7422
+ if (nativeYieldseekerProtocol(option)) {
7423
+ const value2 = await readNativeYieldseekerAssets(client, option, wallet, shares, blockNumber);
7424
+ assertReadCurrent();
7425
+ if (value2 === void 0) return false;
7426
+ position2.withdrawableAssetsRaw = value2.toString();
7427
+ position2.withdrawableAssetsBase = value2.toString();
7428
+ deployed += value2;
7429
+ knownProof = proof(false);
7430
+ return true;
7431
+ }
6663
7432
  let preview;
6664
7433
  try {
6665
7434
  const value2 = await client.readContract({
6666
- address: (0, import_viem14.getAddress)(option.address),
6667
- abi: import_viem14.erc4626Abi,
7435
+ address: (0, import_viem16.getAddress)(option.address),
7436
+ abi: import_viem16.erc4626Abi,
6668
7437
  functionName: "previewRedeem",
6669
7438
  args: [shares],
6670
7439
  blockNumber
@@ -6677,8 +7446,8 @@ var YieldseekerAgent = class {
6677
7446
  if (value === void 0 || value === 0n) {
6678
7447
  try {
6679
7448
  const converted = await client.readContract({
6680
- address: (0, import_viem14.getAddress)(option.address),
6681
- abi: import_viem14.erc4626Abi,
7449
+ address: (0, import_viem16.getAddress)(option.address),
7450
+ abi: import_viem16.erc4626Abi,
6682
7451
  functionName: "convertToAssets",
6683
7452
  args: [shares],
6684
7453
  blockNumber
@@ -6718,7 +7487,7 @@ var YieldseekerAgent = class {
6718
7487
  assertReadCurrent();
6719
7488
  const eligible = /* @__PURE__ */ new Map();
6720
7489
  for (const option of catalog ?? []) {
6721
- if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem14.isAddress)(option.address))
7490
+ if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem16.isAddress)(option.address))
6722
7491
  eligible.set(option.address.toLowerCase(), option);
6723
7492
  }
6724
7493
  const extra = [...eligible].filter(([address]) => !candidates.has(address)).map(([, option]) => option);
@@ -6769,7 +7538,7 @@ var YieldseekerAgent = class {
6769
7538
  const key2 = this.contextKey(state, evidence.chainId, evidence.token);
6770
7539
  const generation = this.readGeneration, version = this.portfolioVersion(key2);
6771
7540
  if (read2.readVersion !== version) return void 0;
6772
- const wallet = (0, import_viem14.getAddress)(context.wallet.walletAddress);
7541
+ const wallet = (0, import_viem16.getAddress)(context.wallet.walletAddress);
6773
7542
  const asset = YIELDSEEKER_ASSET_METADATA[evidence.token];
6774
7543
  const client = this.getReceiptClient();
6775
7544
  const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
@@ -6777,10 +7546,10 @@ var YieldseekerAgent = class {
6777
7546
  const vaults = [...this.balanceVaults.get(key2) ?? []];
6778
7547
  const [invested, idle, tracker] = await Promise.all([
6779
7548
  remainingVaultBalance(client, wallet, asset.address, vaults, blockNumber),
6780
- client.readContract({ address: asset.address, abi: import_viem14.erc20Abi, functionName: "balanceOf", args: [wallet], blockNumber }),
7549
+ client.readContract({ address: asset.address, abi: import_viem16.erc20Abi, functionName: "balanceOf", args: [wallet], blockNumber }),
6781
7550
  client.readContract({ address: wallet, abi: YIELDSEEKER_AGENT_WALLET_ABI, functionName: "feeTracker", blockNumber })
6782
7551
  ]);
6783
- if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !(0, import_viem14.isAddress)(tracker) || /^0x0{40}$/i.test(tracker)) return void 0;
7552
+ if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !(0, import_viem16.isAddress)(tracker) || /^0x0{40}$/i.test(tracker)) return void 0;
6784
7553
  const fees = await client.readContract({
6785
7554
  address: tracker,
6786
7555
  abi: YIELDSEEKER_FEE_TRACKER_ABI,
@@ -6793,7 +7562,7 @@ var YieldseekerAgent = class {
6793
7562
  const total = idle + invested > fees ? idle + invested - fees : 0n;
6794
7563
  const displayed = balance.assetBalances?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
6795
7564
  if (!displayed || !evidence.confirmedAmount || !/^\d+$/.test(evidence.confirmedAmount)) return void 0;
6796
- const amount = (0, import_viem14.parseUnits)(displayed.amount, asset.decimals);
7565
+ const amount = (0, import_viem16.parseUnits)(displayed.amount, asset.decimals);
6797
7566
  if (amount < 0n) return void 0;
6798
7567
  const displayUnit = evidence.token === "USDC" ? 5000n : 500000000000n;
6799
7568
  const movementUnit = BigInt(evidence.confirmedAmount) / 1000n;
@@ -6810,16 +7579,18 @@ var YieldseekerAgent = class {
6810
7579
  if (failure && failure.retryAt > Date.now()) this.snapshotFailures.set(key2, failure);
6811
7580
  this.allocationRefresh.add(key2);
6812
7581
  }
6813
- invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS) {
7582
+ invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() + YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS) {
6814
7583
  this.assertAsset(asset);
6815
7584
  const key2 = this.contextKey(state, chainId, asset);
6816
7585
  const failure = this.snapshotFailures.get(key2);
6817
7586
  this.advancePortfolioVersion(key2);
6818
7587
  if (failure && failure.retryAt > Date.now()) this.snapshotFailures.set(key2, failure);
6819
7588
  if (!this.snapshotMovements.has(key2)) this.snapshotMovements.set(key2, null);
6820
- const until = Math.min(refreshUntil, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
7589
+ const until = Math.min(refreshUntil, Date.now() + YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS);
7590
+ const activityUntil = Math.min(refreshUntil, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
7591
+ if (until > Date.now()) this.beginSettlement(key2, false);
6821
7592
  this.reconcileUntil.set(key2, Math.max(this.reconcileUntil.get(key2) ?? 0, until));
6822
- this.activityRefreshUntil.set(key2, Math.max(this.activityRefreshUntil.get(key2) ?? 0, until));
7593
+ this.activityRefreshUntil.set(key2, Math.max(this.activityRefreshUntil.get(key2) ?? 0, activityUntil));
6823
7594
  }
6824
7595
  endFundingBalanceRefresh(state, chainId, asset, read2) {
6825
7596
  this.assertChain(chainId);
@@ -6848,9 +7619,9 @@ var YieldseekerAgent = class {
6848
7619
  if (!context) return void 0;
6849
7620
  const idle = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
6850
7621
  address: YIELDSEEKER_ASSET_METADATA[asset].address,
6851
- abi: import_viem14.erc20Abi,
7622
+ abi: import_viem16.erc20Abi,
6852
7623
  functionName: "balanceOf",
6853
- args: [(0, import_viem14.getAddress)(context.wallet.walletAddress)]
7624
+ args: [(0, import_viem16.getAddress)(context.wallet.walletAddress)]
6854
7625
  }), chainId, "eth_call", this.id);
6855
7626
  this.assertSession(generation, chainId, asset);
6856
7627
  if (typeof idle !== "bigint" || idle < 0n) throw this.invalidResponse("wallet deposit balance");
@@ -6897,7 +7668,7 @@ var YieldseekerAgent = class {
6897
7668
  );
6898
7669
  const vaultAddresses = new Set(
6899
7670
  catalog.flat().filter(
6900
- (vaultOption) => vaultOption.chainId === chainId && (0, import_viem14.isAddress)(vaultOption.address)
7671
+ (vaultOption) => vaultOption.chainId === chainId && (0, import_viem16.isAddress)(vaultOption.address)
6901
7672
  ).map((vaultOption) => vaultOption.address.toLowerCase())
6902
7673
  );
6903
7674
  return mapYieldseekerHistory(contexts, {
@@ -6931,8 +7702,8 @@ var YieldseekerAgent = class {
6931
7702
  async loadVaultOptions(asset) {
6932
7703
  const cached = this.vaultOptions.get(asset);
6933
7704
  if (cached && cached.expiresAt > Date.now()) return cached.value;
6934
- const pending = this.pendingVaultOptions.get(asset);
6935
- if (pending) return pending;
7705
+ const pending2 = this.pendingVaultOptions.get(asset);
7706
+ if (pending2) return pending2;
6936
7707
  const metadata = YIELDSEEKER_ASSET_METADATA[asset];
6937
7708
  const request2 = this.api.request(
6938
7709
  `/chains/8453/assets/${metadata.address}/vault-options`
@@ -6970,8 +7741,8 @@ var YieldseekerAgent = class {
6970
7741
  if (cached && cached.expiresAt > Date.now()) {
6971
7742
  return Promise.resolve(cached.value);
6972
7743
  }
6973
- const pending = this.pendingReads.get(key2);
6974
- if (pending) return pending;
7744
+ const pending2 = this.pendingReads.get(key2);
7745
+ if (pending2) return pending2;
6975
7746
  const generation = this.readGeneration;
6976
7747
  const requestedAt = Date.now();
6977
7748
  const request2 = Promise.resolve().then(read2).then((value) => {
@@ -7017,8 +7788,8 @@ var YieldseekerAgent = class {
7017
7788
  const key2 = this.contextKey(state, chainId, asset);
7018
7789
  const cached = this.agentContexts.get(key2);
7019
7790
  if (cached?.agent.agentId === agent.agentId) return cached;
7020
- const pending = this.pendingWalletContexts.get(key2);
7021
- if (pending) return pending;
7791
+ const pending2 = this.pendingWalletContexts.get(key2);
7792
+ if (pending2) return pending2;
7022
7793
  const generation = this.readGeneration;
7023
7794
  const request2 = this.walletRequest(
7024
7795
  state,
@@ -7026,7 +7797,7 @@ var YieldseekerAgent = class {
7026
7797
  `/users/${user.userId}/agents/${agent.agentId}/wallet`
7027
7798
  ).then((walletResponse) => {
7028
7799
  this.assertSession(generation, chainId, asset);
7029
- if (!walletResponse?.agentWallet || !(0, import_viem14.isAddress)(walletResponse.agentWallet.walletAddress)) {
7800
+ if (!walletResponse?.agentWallet || !(0, import_viem16.isAddress)(walletResponse.agentWallet.walletAddress)) {
7030
7801
  throw this.invalidResponse("agent wallet");
7031
7802
  }
7032
7803
  const context = {
@@ -7056,7 +7827,7 @@ var YieldseekerAgent = class {
7056
7827
  this.users.set(key2, persisted);
7057
7828
  return persisted;
7058
7829
  }
7059
- const walletAddress = (0, import_viem14.getAddress)(state.walletAddress);
7830
+ const walletAddress = (0, import_viem16.getAddress)(state.walletAddress);
7060
7831
  const generation = this.readGeneration;
7061
7832
  let user = null;
7062
7833
  try {
@@ -7118,8 +7889,8 @@ var YieldseekerAgent = class {
7118
7889
  const key2 = this.contextKey(state, chainId, asset);
7119
7890
  const cached = this.agentContexts.get(key2);
7120
7891
  if (cached) return cached;
7121
- const pending = this.pendingAgents.get(key2);
7122
- if (pending) return pending;
7892
+ const pending2 = this.pendingAgents.get(key2);
7893
+ if (pending2) return pending2;
7123
7894
  const generation = this.readGeneration;
7124
7895
  const request2 = this.resolveAgent(state, chainId, asset, true).then(
7125
7896
  async (context) => {
@@ -7229,8 +8000,21 @@ var YieldseekerAgent = class {
7229
8000
  portfolioVersion(contextKey) {
7230
8001
  return this.portfolioVersions.get(contextKey) ?? 0;
7231
8002
  }
8003
+ /** Snapshot cache lifetime: the settlement backoff while a movement is being
8004
+ * checked, otherwise the routine non-forced cadence. */
7232
8005
  portfolioCacheMs(contextKey) {
7233
- return (this.reconcileUntil.get(contextKey) ?? 0) > Date.now() ? YIELDSEEKER_SETTLEMENT_CACHE_MS : YIELDSEEKER_PORTFOLIO_CACHE_MS;
8006
+ if ((this.reconcileUntil.get(contextKey) ?? 0) <= Date.now()) return YIELDSEEKER_PORTFOLIO_CACHE_MS;
8007
+ const checks = this.settlementChecks.get(contextKey) ?? 0;
8008
+ return YIELDSEEKER_SETTLEMENT_BACKOFF_MS[Math.min(checks, YIELDSEEKER_SETTLEMENT_BACKOFF_MS.length - 1)];
8009
+ }
8010
+ /** A pending movement inside its ten-minute window forces snapshots. */
8011
+ settling(contextKey) {
8012
+ return this.snapshotMovements.has(contextKey) && (this.reconcileUntil.get(contextKey) ?? 0) > Date.now();
8013
+ }
8014
+ /** Start a new forced-check schedule, or keep the active one. */
8015
+ beginSettlement(contextKey, restart) {
8016
+ if (!restart && (this.reconcileUntil.get(contextKey) ?? 0) > Date.now()) return;
8017
+ this.settlementChecks.set(contextKey, 0);
7234
8018
  }
7235
8019
  snapshotMovement(state, chainId, context, delta) {
7236
8020
  const key2 = this.contextKey(state, chainId, context.asset);
@@ -7256,13 +8040,15 @@ var YieldseekerAgent = class {
7256
8040
  expectedNetDeposits: BigInt(snapshot.netDepositsBase) + delta
7257
8041
  };
7258
8042
  }
7259
- advancePortfolioVersion(contextKey, { snapshotOnly = false } = {}) {
8043
+ advancePortfolioVersion(contextKey, { snapshotOnly = false, keepPositions = false } = {}) {
7260
8044
  const version = this.portfolioVersion(contextKey) + 1;
7261
8045
  this.portfolioVersions.set(contextKey, version);
7262
8046
  if (!snapshotOnly) this.liquidityVersions.set(contextKey, version);
7263
8047
  this.snapshotFailures.delete(contextKey);
7264
- for (const kind of ["snapshot", "positions", "historic", "actions"]) {
8048
+ const kinds = !snapshotOnly ? ["snapshot", "positions", "historic", "actions"] : keepPositions ? ["snapshot"] : ["snapshot", "positions"];
8049
+ for (const kind of kinds) {
7265
8050
  const key2 = `${kind}:${contextKey}`;
8051
+ if (snapshotOnly && kind === "positions" && this.pendingReads.has(key2)) continue;
7266
8052
  this.readCache.delete(key2);
7267
8053
  this.pendingReads.delete(key2);
7268
8054
  }
@@ -7307,7 +8093,7 @@ var YieldseekerAgent = class {
7307
8093
  if ((!cached || cached.expiresAt <= Date.now()) && !this.pendingReads.has(key2)) {
7308
8094
  const failure = this.snapshotFailures.get(contextKey);
7309
8095
  if (failure && failure.retryAt > Date.now()) throw failure.error;
7310
- this.advancePortfolioVersion(contextKey, { snapshotOnly: true });
8096
+ this.advancePortfolioVersion(contextKey, { snapshotOnly: true, keepPositions: this.settling(contextKey) });
7311
8097
  }
7312
8098
  const version = this.portfolioVersion(contextKey);
7313
8099
  const generation = this.readGeneration;
@@ -7315,6 +8101,8 @@ var YieldseekerAgent = class {
7315
8101
  version,
7316
8102
  read: this.cachedRead(key2, this.portfolioCacheMs(contextKey), () => {
7317
8103
  const allocationChanged = this.allocationRefresh.delete(contextKey);
8104
+ const settling = this.settling(contextKey);
8105
+ if (settling) this.settlementChecks.set(contextKey, (this.settlementChecks.get(contextKey) ?? 0) + 1);
7318
8106
  return this.requestPortfolioSnapshot(
7319
8107
  state,
7320
8108
  chainId,
@@ -7322,7 +8110,7 @@ var YieldseekerAgent = class {
7322
8110
  contextKey,
7323
8111
  version,
7324
8112
  generation,
7325
- allocationChanged || this.snapshotMovements.has(contextKey) && (this.reconcileUntil.get(contextKey) ?? 0) > Date.now()
8113
+ allocationChanged || settling
7326
8114
  );
7327
8115
  })
7328
8116
  };
@@ -7392,7 +8180,7 @@ var YieldseekerAgent = class {
7392
8180
  const [positions, historic, actions] = await Promise.all([
7393
8181
  options.includePositions === false ? Promise.resolve({ vaultPositions: [] }) : this.cachedRead(
7394
8182
  `positions:${contextKey}`,
7395
- this.portfolioCacheMs(contextKey),
8183
+ YIELDSEEKER_PORTFOLIO_CACHE_MS,
7396
8184
  async () => {
7397
8185
  const response = await this.walletRequest(
7398
8186
  state,
@@ -7439,7 +8227,7 @@ var YieldseekerAgent = class {
7439
8227
  this.agentPath(context, "deploy"),
7440
8228
  { method: "POST", body: {} }
7441
8229
  );
7442
- if (!deployed?.agentWallet || !(0, import_viem14.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
8230
+ if (!deployed?.agentWallet || !(0, import_viem16.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
7443
8231
  throw this.invalidResponse("agent deployment", {
7444
8232
  reason: "Deploy did not return the expected Agent Wallet."
7445
8233
  });
@@ -7448,7 +8236,8 @@ var YieldseekerAgent = class {
7448
8236
  }
7449
8237
  async refreshSnapshotAfterMovement(state, chainId, context, movement, settlement) {
7450
8238
  const contextKey = this.contextKey(state, chainId, context.asset);
7451
- this.reconcileUntil.set(contextKey, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
8239
+ this.beginSettlement(contextKey, true);
8240
+ this.reconcileUntil.set(contextKey, Date.now() + YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS);
7452
8241
  this.activityRefreshUntil.set(contextKey, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
7453
8242
  const epoch = this.movementEpochs.get(contextKey) ?? 0;
7454
8243
  this.snapshotMovements.set(contextKey, settlement?.epoch === epoch ? settlement : null);
@@ -7456,9 +8245,11 @@ var YieldseekerAgent = class {
7456
8245
  const version = this.advancePortfolioVersion(contextKey);
7457
8246
  const generation = this.readGeneration;
7458
8247
  try {
8248
+ const ttl = this.portfolioCacheMs(contextKey);
8249
+ this.settlementChecks.set(contextKey, 1);
7459
8250
  await this.cachedRead(
7460
8251
  `snapshot:${contextKey}`,
7461
- YIELDSEEKER_SETTLEMENT_CACHE_MS,
8252
+ ttl,
7462
8253
  () => this.requestPortfolioSnapshot(state, chainId, context, contextKey, version, generation, true)
7463
8254
  );
7464
8255
  } catch (error) {
@@ -7474,10 +8265,14 @@ var YieldseekerAgent = class {
7474
8265
  async walletRequest(state, chainId, path, options = {}) {
7475
8266
  const read2 = (options.method ?? "GET") === "GET";
7476
8267
  const userKey = this.userKey(state, chainId);
8268
+ const endpointKey = `${userKey}:${path}`;
7477
8269
  if (read2) {
7478
8270
  const failure = this.standardReadFailures.get(userKey);
7479
8271
  if (failure && failure.retryAt > Date.now()) throw failure.error;
7480
8272
  if (failure) this.standardReadFailures.delete(userKey);
8273
+ const endpointFailure = this.endpointReadFailures.get(endpointKey);
8274
+ if (endpointFailure && endpointFailure.retryAt > Date.now()) throw endpointFailure.error;
8275
+ if (endpointFailure) this.endpointReadFailures.delete(endpointKey);
7481
8276
  }
7482
8277
  const generation = this.readGeneration;
7483
8278
  try {
@@ -7491,6 +8286,12 @@ var YieldseekerAgent = class {
7491
8286
  error: mapped
7492
8287
  });
7493
8288
  }
8289
+ if (read2 && this.readGeneration === generation && error instanceof YieldseekerApiError && (error.status === 0 || error.status === 408 || error.status >= 500 && error.status < 600)) {
8290
+ this.endpointReadFailures.set(endpointKey, {
8291
+ retryAt: Date.now() + YIELDSEEKER_READ_FAILURE_COOLDOWN_MS,
8292
+ error: mapped
8293
+ });
8294
+ }
7494
8295
  throw mapped;
7495
8296
  }
7496
8297
  }
@@ -7548,18 +8349,18 @@ var YieldseekerAgent = class {
7548
8349
  return hash3;
7549
8350
  }
7550
8351
  this.assertTransaction(transaction, state, chainId);
7551
- const account = (0, import_viem14.getAddress)(state.walletAddress);
7552
- const walletClient = (0, import_viem14.createWalletClient)({
8352
+ const account = (0, import_viem16.getAddress)(state.walletAddress);
8353
+ const walletClient = (0, import_viem16.createWalletClient)({
7553
8354
  account,
7554
8355
  chain: import_chains4.base,
7555
- transport: onBeforeSubmission ? (0, import_viem14.custom)({ request: async (args) => {
8356
+ transport: onBeforeSubmission ? (0, import_viem16.custom)({ request: async (args) => {
7556
8357
  if (args.method === "eth_sendTransaction") await onBeforeSubmission();
7557
8358
  return state.provider.request(args);
7558
- } }, { retryCount: 0 }) : (0, import_viem14.custom)(state.provider)
8359
+ } }, { retryCount: 0 }) : (0, import_viem16.custom)(state.provider)
7559
8360
  });
7560
- const walletChainClient = (0, import_viem14.createPublicClient)({
8361
+ const walletChainClient = (0, import_viem16.createPublicClient)({
7561
8362
  chain: import_chains4.base,
7562
- transport: (0, import_viem14.custom)(state.provider)
8363
+ transport: (0, import_viem16.custom)(state.provider)
7563
8364
  });
7564
8365
  await ensureWalletOnChain(
7565
8366
  walletChainClient,
@@ -7569,7 +8370,7 @@ var YieldseekerAgent = class {
7569
8370
  const hash2 = await walletClient.sendTransaction({
7570
8371
  account,
7571
8372
  chain: import_chains4.base,
7572
- to: (0, import_viem14.getAddress)(transaction.to),
8373
+ to: (0, import_viem16.getAddress)(transaction.to),
7573
8374
  data: transaction.data,
7574
8375
  value: BigInt(transaction.value)
7575
8376
  });
@@ -7673,12 +8474,12 @@ var YieldseekerAgent = class {
7673
8474
  return receipt;
7674
8475
  }
7675
8476
  assertTransaction(transaction, state, chainId) {
7676
- if (!transaction || typeof transaction.from !== "string" || !(0, import_viem14.isAddress)(transaction.from) || typeof transaction.to !== "string" || !(0, import_viem14.isAddress)(transaction.to) || typeof transaction.data !== "string" || !/^0x[a-fA-F0-9]*$/.test(transaction.data) || typeof transaction.value !== "string" || !/^[0-9]+$/.test(transaction.value) || transaction.chainId !== chainId || (0, import_viem14.getAddress)(transaction.from) !== (0, import_viem14.getAddress)(state.walletAddress)) {
8477
+ if (!transaction || typeof transaction.from !== "string" || !(0, import_viem16.isAddress)(transaction.from) || typeof transaction.to !== "string" || !(0, import_viem16.isAddress)(transaction.to) || typeof transaction.data !== "string" || !/^0x[a-fA-F0-9]*$/.test(transaction.data) || typeof transaction.value !== "string" || !/^[0-9]+$/.test(transaction.value) || transaction.chainId !== chainId || (0, import_viem16.getAddress)(transaction.from) !== (0, import_viem16.getAddress)(state.walletAddress)) {
7677
8478
  throw this.invalidResponse("transaction");
7678
8479
  }
7679
8480
  }
7680
8481
  assertAgent(agent) {
7681
- if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem14.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
8482
+ if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem16.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
7682
8483
  throw this.invalidResponse("agent");
7683
8484
  }
7684
8485
  }
@@ -7734,6 +8535,7 @@ var YieldseekerAgent = class {
7734
8535
  };
7735
8536
 
7736
8537
  // src/lib/routing-api.ts
8538
+ init_errors();
7737
8539
  var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
7738
8540
  var getRoutingApiBaseUrl = (override) => override ?? ROUTING_API_BASE_URL2;
7739
8541
  async function fetchOrgAgentConfig(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
@@ -7798,7 +8600,11 @@ async function fetchAgentKeys(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
7798
8600
  return json.data;
7799
8601
  }
7800
8602
 
8603
+ // src/client.ts
8604
+ init_errors();
8605
+
7801
8606
  // src/lib/swap/swap-api.ts
8607
+ init_errors();
7802
8608
  async function request(baseUrl, apiKey, path, init) {
7803
8609
  const url = `${baseUrl}/api/v1/swap${path}`;
7804
8610
  const controller = new AbortController();
@@ -7975,7 +8781,7 @@ function createSwapApi(baseUrl, apiKey) {
7975
8781
  }
7976
8782
 
7977
8783
  // src/lib/swap/swap.rpc.ts
7978
- var import_viem15 = require("viem");
8784
+ var import_viem17 = require("viem");
7979
8785
  var DEFAULT_RPC_URLS = {
7980
8786
  // NOT cloudflare-eth.com, which used to lead this list. It answers
7981
8787
  // eth_chainId happily, errors on eth_blockNumber, and — the part that
@@ -8015,16 +8821,17 @@ var DEFAULT_RPC_URLS = {
8015
8821
  };
8016
8822
  function swapReadTransport(chainId, overrides) {
8017
8823
  const override = overrides?.[chainId];
8018
- if (override) return (0, import_viem15.http)(override);
8824
+ if (override) return (0, import_viem17.http)(override);
8019
8825
  const urls = DEFAULT_RPC_URLS[chainId];
8020
- if (!urls || urls.length === 0) return (0, import_viem15.http)();
8021
- return (0, import_viem15.fallback)(urls.map((url) => (0, import_viem15.http)(url)));
8826
+ if (!urls || urls.length === 0) return (0, import_viem17.http)();
8827
+ return (0, import_viem17.fallback)(urls.map((url) => (0, import_viem17.http)(url)));
8022
8828
  }
8023
8829
  function receiptTimeoutMs(chainId) {
8024
8830
  return chainId === 1 ? 6e5 : 18e4;
8025
8831
  }
8026
8832
 
8027
8833
  // src/lib/swap/swap.wrap.ts
8834
+ init_errors();
8028
8835
  var WRAP_SELECTOR = "0xd0e30db0";
8029
8836
  var FALLBACK_WRAP_GAS = 50000n;
8030
8837
  var APPROVE_GAS = 60000n;
@@ -8128,7 +8935,11 @@ function swapChain(chainId) {
8128
8935
  return CHAINS[chainId];
8129
8936
  }
8130
8937
 
8938
+ // src/lib/swap/swap.executor.ts
8939
+ init_errors();
8940
+
8131
8941
  // src/lib/swap/swap.arrival.ts
8942
+ init_errors();
8132
8943
  var DEFAULT_TIMEOUT_MS = 18e4;
8133
8944
  var DEFAULT_POLL_MS = 4e3;
8134
8945
  var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -8183,7 +8994,7 @@ async function awaitBalanceIncrease(options) {
8183
8994
  }
8184
8995
 
8185
8996
  // src/lib/swap/swap.secrets.ts
8186
- var import_viem16 = require("viem");
8997
+ var import_viem18 = require("viem");
8187
8998
  var SECRET_BYTES = 32;
8188
8999
  function randomBytes(length) {
8189
9000
  const bytes = new Uint8Array(length);
@@ -8205,13 +9016,16 @@ function mintSecrets(count) {
8205
9016
  const secrets = [];
8206
9017
  const secretHashes = [];
8207
9018
  for (let i = 0; i < count; i++) {
8208
- const secret = (0, import_viem16.toHex)(randomBytes(SECRET_BYTES));
9019
+ const secret = (0, import_viem18.toHex)(randomBytes(SECRET_BYTES));
8209
9020
  secrets.push(secret);
8210
- secretHashes.push((0, import_viem16.keccak256)(secret));
9021
+ secretHashes.push((0, import_viem18.keccak256)(secret));
8211
9022
  }
8212
9023
  return { secrets, secretHashes };
8213
9024
  }
8214
9025
 
9026
+ // src/lib/swap/swap.order-runner.ts
9027
+ init_errors();
9028
+
8215
9029
  // src/lib/swap/swap.types.ts
8216
9030
  var SWAP_TERMINAL_STATUSES = [
8217
9031
  "executed",
@@ -8322,6 +9136,7 @@ function runFusionOrder(deps, options) {
8322
9136
  }
8323
9137
 
8324
9138
  // src/lib/swap/swap.same-chain-runner.ts
9139
+ init_errors();
8325
9140
  var DEFAULT_POLL_MS3 = 5e3;
8326
9141
  var MAX_BACKOFF_MS2 = 3e4;
8327
9142
  var backoffFor2 = (failures, base7) => Math.min(base7 * 2 ** Math.min(failures, 5), MAX_BACKOFF_MS2);
@@ -8440,12 +9255,12 @@ function listOrders(_now = Date.now()) {
8440
9255
  if (!store) return [];
8441
9256
  const out = [];
8442
9257
  try {
8443
- const keys = [];
9258
+ const keys2 = [];
8444
9259
  for (let i = 0; i < store.length; i++) {
8445
9260
  const key2 = store.key(i);
8446
- if (key2?.startsWith(`${KEY_PREFIX4}.`)) keys.push(key2);
9261
+ if (key2?.startsWith(`${KEY_PREFIX4}.`)) keys2.push(key2);
8447
9262
  }
8448
- for (const key2 of keys) {
9263
+ for (const key2 of keys2) {
8449
9264
  const raw2 = store.getItem(key2);
8450
9265
  if (!raw2) continue;
8451
9266
  try {
@@ -8832,6 +9647,7 @@ function submissionUnknown(error, orderHash) {
8832
9647
  }
8833
9648
 
8834
9649
  // src/lib/swap/swap.withdrawal-settlement.ts
9650
+ init_errors();
8835
9651
  var rawAmount = (value) => typeof value === "string" && /^\d+$/.test(value) ? BigInt(value) : void 0;
8836
9652
  var hash = (value) => typeof value === "string" && /^0x[\da-f]{64}$/i.test(value);
8837
9653
  var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -8880,7 +9696,7 @@ async function awaitWithdrawalPayouts(options) {
8880
9696
  const candidates = /* @__PURE__ */ new Map();
8881
9697
  const toDate = (/* @__PURE__ */ new Date()).toISOString();
8882
9698
  const fromDate = new Date(options.submittedAt - 5e3).toISOString();
8883
- const cursors = /* @__PURE__ */ new Set();
9699
+ const cursors2 = /* @__PURE__ */ new Set();
8884
9700
  let cursor;
8885
9701
  for (let pageNumber = 0; pageNumber < 10; pageNumber++) {
8886
9702
  assertActive();
@@ -8906,8 +9722,8 @@ async function awaitWithdrawalPayouts(options) {
8906
9722
  const confirmed = inspected.flatMap((value) => value.status === "fulfilled" && value.value.transfer === "confirmed" && value.value.delivery === "confirmed" && (rawAmount(value.value.blockNumber) ?? 0n) > options.baselineBlock ? [value.value] : []);
8907
9723
  return confirmed.length === 1 ? confirmed[0] : void 0;
8908
9724
  }
8909
- if (!page.nextCursor || cursors.has(page.nextCursor)) return;
8910
- cursors.add(page.nextCursor);
9725
+ if (!page.nextCursor || cursors2.has(page.nextCursor)) return;
9726
+ cursors2.add(page.nextCursor);
8911
9727
  cursor = page.nextCursor;
8912
9728
  }
8913
9729
  };
@@ -9052,8 +9868,8 @@ function verifiedFee(payout) {
9052
9868
  }
9053
9869
 
9054
9870
  // src/lib/swap/swap.permit.ts
9055
- var import_viem17 = require("viem");
9056
- var PERMIT_ABI = (0, import_viem17.parseAbi)([
9871
+ var import_viem19 = require("viem");
9872
+ var PERMIT_ABI = (0, import_viem19.parseAbi)([
9057
9873
  "function nonces(address owner) view returns (uint256)",
9058
9874
  "function name() view returns (string)",
9059
9875
  "function version() view returns (string)",
@@ -9080,7 +9896,7 @@ async function tryRead(read2) {
9080
9896
  function matchDomain(name, versions, chainId, token, onChainSeparator) {
9081
9897
  for (const version of versions) {
9082
9898
  const domain = { name, version, chainId, verifyingContract: token };
9083
- if ((0, import_viem17.domainSeparator)({ domain }) === onChainSeparator) return domain;
9899
+ if ((0, import_viem19.domainSeparator)({ domain }) === onChainSeparator) return domain;
9084
9900
  }
9085
9901
  return null;
9086
9902
  }
@@ -9133,9 +9949,9 @@ async function buildErc2612Permit(reads, input) {
9133
9949
  primaryType: "Permit",
9134
9950
  message: { owner, spender, value, nonce, deadline }
9135
9951
  });
9136
- const { r, s, v, yParity } = (0, import_viem17.parseSignature)(signature);
9952
+ const { r, s, v, yParity } = (0, import_viem19.parseSignature)(signature);
9137
9953
  const recoveryV = v ?? BigInt(yParity + 27);
9138
- return (0, import_viem17.encodeAbiParameters)(
9954
+ return (0, import_viem19.encodeAbiParameters)(
9139
9955
  [
9140
9956
  { type: "address" },
9141
9957
  { type: "address" },
@@ -9226,12 +10042,12 @@ function listWithdrawSwaps(now = Date.now(), includeDismissed = false) {
9226
10042
  if (!store) return [];
9227
10043
  const out = [];
9228
10044
  try {
9229
- const keys = [];
10045
+ const keys2 = [];
9230
10046
  for (let i = 0; i < store.length; i++) {
9231
10047
  const key2 = store.key(i);
9232
- if (key2?.startsWith(`${KEY_PREFIX5}.`)) keys.push(key2);
10048
+ if (key2?.startsWith(`${KEY_PREFIX5}.`)) keys2.push(key2);
9233
10049
  }
9234
- for (const key2 of keys) {
10050
+ for (const key2 of keys2) {
9235
10051
  const raw2 = store.getItem(key2);
9236
10052
  if (!raw2) continue;
9237
10053
  try {
@@ -9291,12 +10107,12 @@ function listPendingDeposits(now = Date.now()) {
9291
10107
  if (!store) return [];
9292
10108
  const out = [];
9293
10109
  try {
9294
- const keys = [];
10110
+ const keys2 = [];
9295
10111
  for (let i = 0; i < store.length; i++) {
9296
10112
  const key2 = store.key(i);
9297
- if (key2?.startsWith(`${KEY_PREFIX6}.`)) keys.push(key2);
10113
+ if (key2?.startsWith(`${KEY_PREFIX6}.`)) keys2.push(key2);
9298
10114
  }
9299
- for (const key2 of keys) {
10115
+ for (const key2 of keys2) {
9300
10116
  const raw2 = store.getItem(key2);
9301
10117
  if (!raw2) continue;
9302
10118
  try {
@@ -9317,6 +10133,7 @@ function listPendingDeposits(now = Date.now()) {
9317
10133
  }
9318
10134
 
9319
10135
  // src/lib/health-report.ts
10136
+ init_errors();
9320
10137
  var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
9321
10138
  async function reportAgentFailure(apiKey, agentType, errorCode, baseUrl = ROUTING_API_BASE_URL3) {
9322
10139
  try {
@@ -9350,7 +10167,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
9350
10167
  }
9351
10168
 
9352
10169
  // src/lib/helpers/withdraw-helper.ts
9353
- var import_viem18 = require("viem");
10170
+ var import_viem20 = require("viem");
9354
10171
  function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
9355
10172
  return agents.map((agent) => {
9356
10173
  let invalidBalance = false;
@@ -9360,7 +10177,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
9360
10177
  return 0n;
9361
10178
  }
9362
10179
  const [whole, fraction] = value.split(".");
9363
- return raw2 ? BigInt(value) : (0, import_viem18.parseUnits)(fraction === void 0 ? whole : `${whole}.${fraction.slice(0, decimals)}`, decimals);
10180
+ return raw2 ? BigInt(value) : (0, import_viem20.parseUnits)(fraction === void 0 ? whole : `${whole}.${fraction.slice(0, decimals)}`, decimals);
9364
10181
  };
9365
10182
  const agentBalance = aggregated[agent.id];
9366
10183
  const tokenBalance = agentBalance?.tokens.find(
@@ -9569,7 +10386,7 @@ function aggregateDailyEarnings(series, tokenSymbol) {
9569
10386
  }
9570
10387
  return [...byAsset.entries()].map(([asset, components]) => {
9571
10388
  const dates = [...new Set(components.flatMap((points2) => points2.map((point) => point.date)))].sort();
9572
- const cursors = components.map((points2) => ({
10389
+ const cursors2 = components.map((points2) => ({
9573
10390
  index: 0,
9574
10391
  // Providers can have different lifetime/window offsets and start dates.
9575
10392
  // Remove each opening reading before combining their earned amounts.
@@ -9579,7 +10396,7 @@ function aggregateDailyEarnings(series, tokenSymbol) {
9579
10396
  const points = dates.map((date) => {
9580
10397
  let amount = 0;
9581
10398
  components.forEach((component, index) => {
9582
- const cursor = cursors[index];
10399
+ const cursor = cursors2[index];
9583
10400
  while (cursor.index < component.length && component[cursor.index].date <= date) {
9584
10401
  cursor.current = component[cursor.index++].amount;
9585
10402
  }
@@ -9592,13 +10409,314 @@ function aggregateDailyEarnings(series, tokenSymbol) {
9592
10409
  }
9593
10410
 
9594
10411
  // src/client.ts
9595
- var import_viem21 = require("viem");
10412
+ var import_viem24 = require("viem");
9596
10413
  var import_chains6 = require("viem/chains");
9597
10414
 
10415
+ // src/lib/sponsored-token-deposit.ts
10416
+ init_errors();
10417
+
10418
+ // src/lib/token-batch-execution.ts
10419
+ var import_viem21 = require("viem");
10420
+ init_errors();
10421
+ init_token_batch_family();
10422
+ async function executeTokenBatch(input, initial) {
10423
+ let body = initial, family, ended = false;
10424
+ const deadlineAt = Date.now() + 9e4, controller = new AbortController();
10425
+ let timer;
10426
+ const pending2 = () => new OwneyError(
10427
+ "DEPOSIT_IN_PROGRESS",
10428
+ "Deposit is awaiting confirmation. Its transaction is still being checked.",
10429
+ {
10430
+ sponsorPending: true,
10431
+ phase: body.serializedTransaction ? "deposit" : "approval",
10432
+ txHash: body.serializedTransaction ? (0, import_viem21.keccak256)(body.serializedTransaction) : body.serializedPermitTransaction ? (0, import_viem21.keccak256)(body.serializedPermitTransaction) : void 0,
10433
+ notSubmitted: false,
10434
+ safeToFallback: false
10435
+ }
10436
+ );
10437
+ const assertCurrent = () => {
10438
+ if (ended || Date.now() >= deadlineAt) throw pending2();
10439
+ input.assertCurrent?.();
10440
+ };
10441
+ const timeout = new Promise((_, reject) => {
10442
+ timer = setTimeout(() => {
10443
+ ended = true;
10444
+ controller.abort();
10445
+ reject(pending2());
10446
+ }, 9e4);
10447
+ });
10448
+ const bounded2 = async (work) => {
10449
+ const value = await Promise.race([work, timeout]);
10450
+ assertCurrent();
10451
+ return value;
10452
+ };
10453
+ const post = () => bounded2(
10454
+ postSponsorBatchTransfer({
10455
+ apiKey: input.apiKey,
10456
+ baseUrl: input.baseUrl,
10457
+ body,
10458
+ signal: controller.signal
10459
+ })
10460
+ );
10461
+ const replacements = { approval: 0, deposit: 0 };
10462
+ const unavailable = /* @__PURE__ */ new Set();
10463
+ const observedApprovals = /* @__PURE__ */ new Set();
10464
+ const checkpointed = /* @__PURE__ */ new Set();
10465
+ const accounted = /* @__PURE__ */ new Set();
10466
+ const remember = async (phase, bytes, hash2, predecessorHash) => {
10467
+ assertCurrent();
10468
+ if ((0, import_viem21.keccak256)(bytes) !== hash2) throw pending2();
10469
+ const tx = (0, import_viem21.parseTransaction)(bytes);
10470
+ const next = {
10471
+ ...body,
10472
+ [phase === "deposit" ? "serializedTransaction" : "serializedPermitTransaction"]: bytes
10473
+ };
10474
+ family = await bounded2(
10475
+ saveTokenBatchAttempt(
10476
+ input,
10477
+ next,
10478
+ {
10479
+ phase,
10480
+ hash: hash2,
10481
+ serializedTransaction: bytes,
10482
+ nonce: String(tx.nonce),
10483
+ predecessorHash,
10484
+ preparedAt: Date.now(),
10485
+ submissionAttempted: false
10486
+ },
10487
+ assertCurrent
10488
+ )
10489
+ );
10490
+ body = { ...family.body, transfers: initial.transfers };
10491
+ };
10492
+ const reference = (hash2) => family ? {
10493
+ authorizationId: family.authorizationId,
10494
+ predecessorTxHash: family.attempts.find((a) => a.hash === hash2)?.predecessorHash
10495
+ } : void 0;
10496
+ const markSubmission = async (phase) => {
10497
+ const hash2 = phase === "deposit" ? family?.current.deposit : family?.current.approval;
10498
+ if (!family || !hash2) throw pending2();
10499
+ if (phase === "deposit" && !checkpointed.has(hash2)) {
10500
+ try {
10501
+ await bounded2(
10502
+ Promise.resolve(input.onBeforeSubmission?.(hash2, reference(hash2)))
10503
+ );
10504
+ } catch (error) {
10505
+ if (error instanceof OwneyError && error.code === "DEPOSIT_CHECKPOINT_FAILED")
10506
+ throw new OwneyError(error.code, error.message, {
10507
+ ...error.details,
10508
+ notSubmitted: !family.attempts.some(
10509
+ (a) => a.phase === "deposit" && a.submissionAttempted
10510
+ ),
10511
+ safeToFallback: false
10512
+ });
10513
+ throw error;
10514
+ }
10515
+ checkpointed.add(hash2);
10516
+ }
10517
+ assertCurrent();
10518
+ const attempt = family.attempts.find((a) => a.hash === hash2);
10519
+ family = await bounded2(
10520
+ saveTokenBatchAttempt(
10521
+ input,
10522
+ body,
10523
+ { ...attempt, submissionAttempted: true },
10524
+ assertCurrent
10525
+ )
10526
+ );
10527
+ assertCurrent();
10528
+ if (phase === "deposit")
10529
+ try {
10530
+ input.onSubmitted?.(hash2, reference(hash2));
10531
+ } catch {
10532
+ }
10533
+ assertCurrent();
10534
+ };
10535
+ const observe = async () => {
10536
+ if (!family) return;
10537
+ const observation = await bounded2(
10538
+ observeTokenBatchFamily({
10539
+ scope: input,
10540
+ family,
10541
+ pub: input.pub,
10542
+ deadlineAt,
10543
+ assertCurrent
10544
+ })
10545
+ );
10546
+ if (observation.status === "confirmed") {
10547
+ const winning = family.attempts.find(
10548
+ (a) => a.hash === observation.txHash
10549
+ );
10550
+ if (!accounted.has(observation.txHash)) {
10551
+ const accounting = new AbortController();
10552
+ const accountingTimer = setTimeout(() => accounting.abort(), 8e3);
10553
+ void postSponsorBatchTransfer({
10554
+ apiKey: input.apiKey,
10555
+ baseUrl: input.baseUrl,
10556
+ body: {
10557
+ ...body,
10558
+ serializedTransaction: winning.serializedTransaction
10559
+ },
10560
+ signal: accounting.signal
10561
+ }).catch(() => {
10562
+ }).finally(() => clearTimeout(accountingTimer));
10563
+ }
10564
+ return observation.txHash;
10565
+ }
10566
+ if (observation.status === "failed" || observation.status === "expired")
10567
+ throw new OwneyError(
10568
+ "SPONSOR_REQUEST_FAILED",
10569
+ observation.status === "expired" ? "The deposit authorization expired without transferring funds. Start a new deposit." : "Sponsored deposit transactions reverted. Please retry.",
10570
+ { notSubmitted: true, safeToFallback: false }
10571
+ );
10572
+ };
10573
+ try {
10574
+ assertCurrent();
10575
+ family = await bounded2(
10576
+ loadTokenBatchFamily(
10577
+ input,
10578
+ initial.serializedTransaction ? (0, import_viem21.keccak256)(initial.serializedTransaction) : initial.serializedPermitTransaction ? (0, import_viem21.keccak256)(initial.serializedPermitTransaction) : void 0
10579
+ )
10580
+ );
10581
+ if (family) body = { ...family.body, transfers: initial.transfers };
10582
+ else
10583
+ tokenBatchWrite(
10584
+ tokenBatchKey(input),
10585
+ JSON.stringify(tokenBatchStoredBody(body))
10586
+ );
10587
+ if (family) {
10588
+ const winner = await observe();
10589
+ if (winner) return winner;
10590
+ }
10591
+ if (family)
10592
+ for (const attempt of family.attempts)
10593
+ family = await bounded2(
10594
+ saveTokenBatchAttempt(input, body, attempt, assertCurrent)
10595
+ );
10596
+ let needsPost = true;
10597
+ while (true) {
10598
+ assertCurrent();
10599
+ const winner = await observe();
10600
+ if (winner) return winner;
10601
+ if (needsPost) {
10602
+ needsPost = false;
10603
+ const signedPhase = body.serializedTransaction ? "deposit" : body.serializedPermitTransaction ? "approval" : void 0;
10604
+ if (signedPhase) await markSubmission(signedPhase);
10605
+ let result;
10606
+ try {
10607
+ result = await post();
10608
+ } catch (error) {
10609
+ assertCurrent();
10610
+ if (!family) {
10611
+ tokenBatchClear(
10612
+ tokenBatchKey(input),
10613
+ JSON.stringify(tokenBatchStoredBody(body))
10614
+ );
10615
+ throw error;
10616
+ }
10617
+ }
10618
+ if (result?.serializedPermitTransaction && !body.serializedPermitTransaction) {
10619
+ if (!result.permitTxHash) throw pending2();
10620
+ await remember(
10621
+ "approval",
10622
+ result.serializedPermitTransaction,
10623
+ result.permitTxHash
10624
+ );
10625
+ needsPost = true;
10626
+ continue;
10627
+ }
10628
+ if (result?.serializedTransaction && !body.serializedTransaction) {
10629
+ await remember(
10630
+ "deposit",
10631
+ result.serializedTransaction,
10632
+ result.txHash
10633
+ );
10634
+ needsPost = true;
10635
+ continue;
10636
+ }
10637
+ if (result && !result.status && !result.serializedTransaction && !result.serializedPermitTransaction && family?.current.deposit === result.txHash)
10638
+ accounted.add(result.txHash);
10639
+ const winner2 = await observe();
10640
+ if (winner2) return winner2;
10641
+ }
10642
+ const phase = body.serializedTransaction ? "deposit" : "approval";
10643
+ const current = family?.current[phase];
10644
+ if (!current) throw pending2();
10645
+ if (phase === "approval" && !observedApprovals.has(current)) {
10646
+ const receipt = await bounded2(
10647
+ input.pub.getTransactionReceipt({ hash: current }).catch(() => void 0)
10648
+ );
10649
+ if (receipt?.status === "success" && receipt.transactionHash?.toLowerCase() === current.toLowerCase() && receipt.from?.toLowerCase() === family.relayer.toLowerCase() && receipt.to?.toLowerCase() === body.token.toLowerCase()) {
10650
+ observedApprovals.add(current);
10651
+ needsPost = true;
10652
+ continue;
10653
+ }
10654
+ }
10655
+ if (replacements[phase] < 2 && !unavailable.has(phase)) {
10656
+ let recovered;
10657
+ try {
10658
+ recovered = await bounded2(
10659
+ postSponsorBatchRecovery({
10660
+ apiKey: input.apiKey,
10661
+ baseUrl: input.baseUrl,
10662
+ body: { ...body, phase },
10663
+ signal: controller.signal
10664
+ })
10665
+ );
10666
+ } catch {
10667
+ assertCurrent();
10668
+ }
10669
+ assertCurrent();
10670
+ if (!recovered) unavailable.add(phase);
10671
+ else if (recovered.status === "prepared") {
10672
+ if (recovered.predecessorHash !== current) throw pending2();
10673
+ await remember(
10674
+ phase,
10675
+ recovered.serializedTransaction,
10676
+ recovered.txHash,
10677
+ current
10678
+ );
10679
+ replacements[phase]++;
10680
+ needsPost = true;
10681
+ continue;
10682
+ } else if (phase === "approval" && (recovered.status === "approval-satisfied" || recovered.status === "included" && recovered.outcome === "success")) {
10683
+ needsPost = true;
10684
+ } else if (recovered.status === "included" && recovered.outcome === "reverted") {
10685
+ if (phase === "approval" && !family.attempts.some((a) => a.phase === "deposit") && family.attempts.filter((a) => a.phase === "approval").length === 1) {
10686
+ finishTokenBatchFamily(input, family, {
10687
+ kind: "failed",
10688
+ blockNumber: recovered.blockNumber
10689
+ });
10690
+ throw new OwneyError(
10691
+ "SPONSOR_REQUEST_FAILED",
10692
+ "Sponsored approval reverted. Please retry.",
10693
+ { notSubmitted: true, safeToFallback: false }
10694
+ );
10695
+ }
10696
+ unavailable.add(phase);
10697
+ }
10698
+ }
10699
+ await bounded2(
10700
+ new Promise(
10701
+ (resolve) => setTimeout(
10702
+ resolve,
10703
+ Math.min(2e3, Math.max(0, deadlineAt - Date.now()))
10704
+ )
10705
+ )
10706
+ );
10707
+ }
10708
+ } finally {
10709
+ ended = true;
10710
+ if (timer) clearTimeout(timer);
10711
+ controller.abort();
10712
+ }
10713
+ }
10714
+
9598
10715
  // src/lib/sponsored-token-batch.ts
9599
- var import_viem19 = require("viem");
9600
- var memory = /* @__PURE__ */ new Map();
9601
- var settledRecords = /* @__PURE__ */ new Map();
10716
+ init_token_batch_family();
10717
+ var import_viem22 = require("viem");
10718
+ init_errors();
10719
+ init_permit2_batch();
9602
10720
  var expiredRecords = /* @__PURE__ */ new Map();
9603
10721
  var inflight = /* @__PURE__ */ new Map();
9604
10722
  var planOf = (transfers) => JSON.stringify(
@@ -9607,18 +10725,7 @@ var planOf = (transfers) => JSON.stringify(
9607
10725
  amount: BigInt(t.amount).toString()
9608
10726
  }))
9609
10727
  );
9610
- var pendingKey = (i) => `owney.token-batch.v1:${(0, import_viem19.keccak256)((0, import_viem19.toBytes)(i.apiKey))}:${i.baseUrl ?? "default"}:${i.chainId}:${i.owner.toLowerCase()}:${i.token.toLowerCase()}`;
9611
- function pendingTokenBatch(i) {
9612
- try {
9613
- const saved = read(pendingKey(i));
9614
- if (!saved) return;
9615
- const body = JSON.parse(saved);
9616
- if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem19.isAddressEqual)(body.from, i.owner) || !(0, import_viem19.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
9617
- return { txHash: (0, import_viem19.keccak256)(body.serializedTransaction), transfers: body.transfers.map(({ to, amount }) => ({ to, amount })) };
9618
- } catch {
9619
- return;
9620
- }
9621
- }
10728
+ var pendingKey = (i) => `owney.token-batch.v1:${(0, import_viem22.keccak256)((0, import_viem22.toBytes)(i.apiKey))}:${i.baseUrl ?? "default"}:${i.chainId}:${i.owner.toLowerCase()}:${i.token.toLowerCase()}`;
9622
10729
  async function releaseExpiredTokenBatch(i) {
9623
10730
  const key2 = pendingKey(i);
9624
10731
  let timer;
@@ -9627,18 +10734,18 @@ async function releaseExpiredTokenBatch(i) {
9627
10734
  let active2 = read(key2);
9628
10735
  if (active2 && i.expectedTxHash) {
9629
10736
  const current = JSON.parse(active2);
9630
- if (!current.serializedTransaction || (0, import_viem19.keccak256)(current.serializedTransaction).toLowerCase() !== i.expectedTxHash.toLowerCase())
10737
+ if (!current.serializedTransaction || (0, import_viem22.keccak256)(current.serializedTransaction).toLowerCase() !== i.expectedTxHash.toLowerCase())
9631
10738
  active2 = void 0;
9632
10739
  }
9633
10740
  const archiveKey = i.expectedTxHash ? `${key2}:expired:${i.expectedTxHash.toLowerCase()}` : void 0;
9634
10741
  const saved = active2 ?? (archiveKey && (expiredRecords.get(archiveKey) ?? (typeof window === "undefined" ? void 0 : window.localStorage.getItem(archiveKey))));
9635
10742
  if (!saved) return;
9636
10743
  const body = JSON.parse(saved);
9637
- if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem19.isAddressEqual)(body.from, i.owner) || !(0, import_viem19.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
9638
- const txHash = (0, import_viem19.keccak256)(body.serializedTransaction);
10744
+ if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem22.isAddressEqual)(body.from, i.owner) || !(0, import_viem22.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
10745
+ const txHash = (0, import_viem22.keccak256)(body.serializedTransaction);
9639
10746
  if (i.expectedTxHash && txHash.toLowerCase() !== i.expectedTxHash.toLowerCase()) return;
9640
- const transaction = (0, import_viem19.parseTransaction)(body.serializedTransaction);
9641
- if (transaction.chainId !== i.chainId || !transaction.to || !(0, import_viem19.isAddressEqual)(transaction.to, BATCH_PERMIT2_ADDRESS) || (transaction.value ?? 0n) !== 0n || transaction.data !== (0, import_viem19.encodeFunctionData)({
10747
+ const transaction = (0, import_viem22.parseTransaction)(body.serializedTransaction);
10748
+ if (transaction.chainId !== i.chainId || !transaction.to || !(0, import_viem22.isAddressEqual)(transaction.to, BATCH_PERMIT2_ADDRESS) || (transaction.value ?? 0n) !== 0n || transaction.data !== (0, import_viem22.encodeFunctionData)({
9642
10749
  abi: PERMIT2_BATCH_ABI,
9643
10750
  functionName: "permitWitnessTransferFrom",
9644
10751
  args: batchArgs(body)
@@ -9667,8 +10774,7 @@ async function releaseExpiredTokenBatch(i) {
9667
10774
  }
9668
10775
  } catch {
9669
10776
  }
9670
- if (!persisted) settledRecords.set(key2, saved);
9671
- else clear(key2, body);
10777
+ if (persisted) clear(key2, body);
9672
10778
  }
9673
10779
  return { txHash, transfers: body.transfers.map(({ to, amount }) => ({ to, amount })), blockNumber: block.number };
9674
10780
  };
@@ -9686,37 +10792,17 @@ async function releaseExpiredTokenBatch(i) {
9686
10792
  if (timer) clearTimeout(timer);
9687
10793
  }
9688
10794
  }
9689
- function read(key2) {
9690
- const value = typeof window === "undefined" ? memory.get(key2) : window.localStorage.getItem(key2);
9691
- return value && settledRecords.get(key2) === value ? void 0 : value;
9692
- }
9693
- function storedBody(body) {
9694
- return JSON.stringify({
9695
- ...body,
9696
- transfers: body.transfers.map(({ to, amount }) => ({ to, amount }))
9697
- });
9698
- }
9699
- function save(key2, body) {
9700
- const value = storedBody(body);
9701
- if (typeof window === "undefined") memory.set(key2, value);
9702
- else window.localStorage.setItem(key2, value);
9703
- settledRecords.delete(key2);
9704
- }
10795
+ var read = tokenBatchRead;
10796
+ var storedBody = (body) => JSON.stringify(tokenBatchStoredBody(body));
9705
10797
  function clear(key2, body) {
9706
- try {
9707
- if (typeof window === "undefined") memory.delete(key2);
9708
- else window.localStorage.removeItem(key2);
9709
- settledRecords.delete(key2);
9710
- } catch {
9711
- settledRecords.set(key2, storedBody(body));
9712
- }
10798
+ tokenBatchClear(key2, storedBody(body));
9713
10799
  }
9714
10800
  function sponsorTokenBatch(i) {
9715
10801
  const key2 = pendingKey(i);
9716
10802
  const plan = planOf(i.transfers);
9717
10803
  const active2 = inflight.get(key2);
9718
10804
  if (active2) {
9719
- if (active2.plan !== plan || i.resumeTxHash && pendingTokenBatch(i)?.txHash !== i.resumeTxHash)
10805
+ if (active2.plan !== plan)
9720
10806
  return Promise.reject(
9721
10807
  new Error(
9722
10808
  "A token deposit is already in progress. Wait for its result before depositing again."
@@ -9733,136 +10819,13 @@ async function execute(i, key2, plan) {
9733
10819
  (t) => BigInt(t.amount) <= 0n || BigInt(t.amount) >= 1n << 256n
9734
10820
  ) || new Set(i.transfers.map((t) => t.to.toLowerCase())).size !== i.transfers.length)
9735
10821
  throw new Error("Invalid token deposit shares.");
9736
- const send = async (initial) => {
9737
- let body = initial;
9738
- save(key2, body);
9739
- const rejectedPreparation = (error) => !body.serializedTransaction && error instanceof OwneyError && typeof error.details?.statusCode === "number" && error.details.statusCode >= 400 && error.details.statusCode < 500 && ![408, 429].includes(error.details.statusCode);
9740
- try {
9741
- const post = () => postSponsorBatchTransfer({ apiKey: i.apiKey, baseUrl: i.baseUrl, body });
9742
- const pendingError = (phase, txHash) => new OwneyError(
9743
- "DEPOSIT_IN_PROGRESS",
9744
- phase === "approval" ? "Deposit approval is awaiting confirmation. Retry the same amount to continue it." : "Deposit is awaiting confirmation. Its transaction is still being checked.",
9745
- { sponsorPending: true, phase, txHash, safeToFallback: false }
9746
- );
9747
- const assertReceipt = (receipt, phase) => {
9748
- if (receipt.status !== "success") throw new OwneyError(
9749
- "SPONSOR_REQUEST_FAILED",
9750
- `Sponsored ${phase} transaction reverted. Please retry.`,
9751
- { notSubmitted: true, safeToFallback: false }
9752
- );
9753
- };
9754
- const waitForConfirmation = async (phase, hash3) => {
9755
- let receipt;
9756
- try {
9757
- receipt = await i.pub.waitForTransactionReceipt({ hash: hash3, confirmations: 1, timeout: 9e4, checkReplacement: false });
9758
- } catch {
9759
- receipt = await i.pub.getTransactionReceipt({ hash: hash3 }).catch(() => void 0);
9760
- }
9761
- if (!receipt) throw pendingError(phase, hash3);
9762
- assertReceipt(receipt, phase);
9763
- };
9764
- const postSigned = async (phase, hash3) => {
9765
- try {
9766
- return await post();
9767
- } catch (error) {
9768
- if (rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true) throw error;
9769
- await waitForConfirmation(phase, hash3);
9770
- return void 0;
9771
- }
9772
- };
9773
- if (body.erc2612Permit && !body.serializedPermitTransaction) {
9774
- const preparedPermit = await postSponsorBatchTransfer({
9775
- apiKey: i.apiKey,
9776
- baseUrl: i.baseUrl,
9777
- body
9778
- });
9779
- if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0, import_viem19.keccak256)(preparedPermit.serializedPermitTransaction) !== preparedPermit.permitTxHash)
9780
- throw new Error(
9781
- "Sponsorship API did not return a valid prepared permit transaction."
9782
- );
9783
- body = {
9784
- ...body,
9785
- serializedPermitTransaction: preparedPermit.serializedPermitTransaction
9786
- };
9787
- save(key2, body);
9788
- }
9789
- if (!body.serializedTransaction) {
9790
- const permitHash = body.serializedPermitTransaction ? (0, import_viem19.keccak256)(body.serializedPermitTransaction) : void 0;
9791
- let prepared = permitHash ? await postSigned("approval", permitHash) : await post();
9792
- if (prepared?.status === "pending") {
9793
- if (!permitHash || prepared.phase !== "approval" || prepared.txHash !== permitHash)
9794
- throw new Error("Sponsorship approval does not match the pending transaction.");
9795
- await waitForConfirmation("approval", permitHash);
9796
- prepared = void 0;
9797
- }
9798
- if (!prepared) prepared = await post();
9799
- if (prepared.status === "pending" && permitHash && prepared.phase === "approval" && prepared.txHash === permitHash)
9800
- throw pendingError("approval", permitHash);
9801
- if (!prepared.serializedTransaction || (0, import_viem19.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
9802
- throw new Error(
9803
- "Sponsorship API did not return a valid prepared transaction."
9804
- );
9805
- body = {
9806
- ...body,
9807
- serializedTransaction: prepared.serializedTransaction
9808
- };
9809
- save(key2, body);
9810
- }
9811
- await i.onBeforeSubmission?.((0, import_viem19.keccak256)(body.serializedTransaction));
9812
- try {
9813
- i.onSubmitted?.((0, import_viem19.keccak256)(body.serializedTransaction));
9814
- } catch {
9815
- }
9816
- const hash2 = (0, import_viem19.keccak256)(body.serializedTransaction);
9817
- const existing = await i.pub.getTransactionReceipt({ hash: hash2 }).catch(() => void 0);
9818
- if (existing) {
9819
- assertReceipt(existing, "deposit");
9820
- void post().catch(() => void 0);
9821
- clear(key2, body);
9822
- return hash2;
9823
- }
9824
- let result = await postSigned("deposit", hash2);
9825
- if (result?.status === "pending" && result.phase === "approval" && body.serializedPermitTransaction && result.txHash === (0, import_viem19.keccak256)(body.serializedPermitTransaction)) {
9826
- await waitForConfirmation("approval", result.txHash);
9827
- result = await postSigned("deposit", hash2);
9828
- if (result?.status === "pending" && result.phase === "approval" && result.txHash === (0, import_viem19.keccak256)(body.serializedPermitTransaction)) throw pendingError("approval", result.txHash);
9829
- }
9830
- if (result) {
9831
- if (result.txHash !== hash2 || result.status === "pending" && result.phase !== "deposit")
9832
- throw new Error("Sponsorship receipt does not match the pending transaction.");
9833
- if (result.status === "pending") await waitForConfirmation("deposit", hash2);
9834
- }
9835
- if (!result || result.status === "pending") void post().catch(() => void 0);
9836
- clear(key2, body);
9837
- return hash2;
9838
- } catch (error) {
9839
- if (initial.serializedTransaction && error instanceof OwneyError && error.code === "DEPOSIT_CHECKPOINT_FAILED") {
9840
- throw new OwneyError(
9841
- error.code,
9842
- "Could not save recovery of the existing deposit.",
9843
- { ...error.details, notSubmitted: false, safeToFallback: false }
9844
- );
9845
- }
9846
- if (!body.serializedTransaction && !body.serializedPermitTransaction || rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true)
9847
- clear(key2, body);
9848
- throw error;
9849
- }
9850
- };
9851
- const saved = read(key2);
9852
- if (i.resumeTxHash && pendingTokenBatch(i)?.txHash !== i.resumeTxHash)
9853
- throw new OwneyError("DEPOSIT_IN_PROGRESS", "The saved deposit changed. Check its status before depositing again.");
10822
+ const send = (body) => executeTokenBatch(i, body);
10823
+ const family = await loadTokenBatchFamily(i, i.resumeTxHash);
10824
+ const saved = family ? JSON.stringify(family.body) : read(key2);
9854
10825
  if (saved) {
9855
10826
  const previous = JSON.parse(saved);
9856
- if (previous.chainId !== i.chainId || !(0, import_viem19.isAddressEqual)(previous.from, i.owner) || !(0, import_viem19.isAddressEqual)(previous.token, i.token) || planOf(previous.transfers) !== plan)
9857
- throw new Error(
9858
- "Retry the previous token deposit and agent split first to reconcile its status."
9859
- );
9860
- if (await releaseExpiredTokenBatch({ ...i, expectedTxHash: previous.serializedTransaction ? (0, import_viem19.keccak256)(previous.serializedTransaction) : void 0 }))
9861
- throw new OwneyError(
9862
- "SPONSOR_REQUEST_FAILED",
9863
- "The deposit authorization expired without transferring funds. Start a new deposit.",
9864
- { notSubmitted: true, safeToFallback: false }
9865
- );
10827
+ if (previous.chainId !== i.chainId || !(0, import_viem22.isAddressEqual)(previous.from, i.owner) || !(0, import_viem22.isAddressEqual)(previous.token, i.token) || planOf(previous.transfers) !== plan)
10828
+ throw new OwneyError("DEPOSIT_IN_PROGRESS", "Retry the previous token deposit and agent split first to reconcile its status.");
9866
10829
  i.onApproved?.();
9867
10830
  return send({ ...previous, transfers: i.transfers });
9868
10831
  }
@@ -9968,8 +10931,9 @@ function makeSponsoredTokenCallback(deps) {
9968
10931
  pub,
9969
10932
  wallet,
9970
10933
  onApproved: deps.onApproved,
9971
- onSubmitted: (hash2) => deps.onSubmitted?.(hash2, transfers),
9972
- onBeforeSubmission: (hash2) => deps.onBeforeSubmission?.(hash2, transfers),
10934
+ onSubmitted: (hash2, reference) => deps.onSubmitted?.(hash2, transfers, reference),
10935
+ onBeforeSubmission: (hash2, reference) => deps.onBeforeSubmission?.(hash2, transfers, reference),
10936
+ assertCurrent: deps.assertCurrent,
9973
10937
  resumeTxHash: deps.resumeTxHash
9974
10938
  });
9975
10939
  };
@@ -9981,6 +10945,7 @@ function makeSponsoredTokenCallback(deps) {
9981
10945
  }
9982
10946
 
9983
10947
  // src/lib/agent-deposit-batch.ts
10948
+ init_errors();
9984
10949
  function deferred() {
9985
10950
  let resolve, reject;
9986
10951
  const promise = new Promise((yes, no) => {
@@ -10028,10 +10993,10 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
10028
10993
  }
10029
10994
  const txHash = await transfer(chainId, transfers);
10030
10995
  funding.resolve(txHash);
10031
- const settled = await Promise.allSettled(tasks);
10996
+ const settled2 = await Promise.allSettled(tasks);
10032
10997
  const agentResults = {};
10033
10998
  const failures = [];
10034
- for (const [index, result] of settled.entries()) {
10999
+ for (const [index, result] of settled2.entries()) {
10035
11000
  if (result.status === "fulfilled")
10036
11001
  agentResults[legs[index].id] = result.value;
10037
11002
  else failures.push(legs[index].id);
@@ -10056,7 +11021,8 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
10056
11021
  }
10057
11022
 
10058
11023
  // src/lib/sponsored-calls-deposit.ts
10059
- var import_viem20 = require("viem");
11024
+ var import_viem23 = require("viem");
11025
+ init_errors();
10060
11026
  var DEFAULT_POLL_INTERVAL_MS = 1500;
10061
11027
  var DEFAULT_MAX_POLLS = 30;
10062
11028
  async function paymasterSupported(provider, owner, chainId) {
@@ -10064,7 +11030,7 @@ async function paymasterSupported(provider, owner, chainId) {
10064
11030
  method: "wallet_getCapabilities",
10065
11031
  params: [owner]
10066
11032
  });
10067
- const forChain = caps?.[(0, import_viem20.toHex)(chainId)] ?? caps?.[String(chainId)];
11033
+ const forChain = caps?.[(0, import_viem23.toHex)(chainId)] ?? caps?.[String(chainId)];
10068
11034
  return Boolean(forChain?.paymasterService?.supported);
10069
11035
  }
10070
11036
  function makeSponsoredCallsCallback(deps) {
@@ -10101,8 +11067,8 @@ function makeSponsoredCallsCallback(deps) {
10101
11067
  const calls = transfers.map((transfer) => ({
10102
11068
  to: token,
10103
11069
  value: "0x0",
10104
- data: (0, import_viem20.encodeFunctionData)({
10105
- abi: import_viem20.erc20Abi,
11070
+ data: (0, import_viem23.encodeFunctionData)({
11071
+ abi: import_viem23.erc20Abi,
10106
11072
  functionName: "transfer",
10107
11073
  args: [transfer.to, BigInt(transfer.amount)]
10108
11074
  })
@@ -10134,7 +11100,7 @@ function makeSponsoredCallsCallback(deps) {
10134
11100
  url.searchParams.append("owneyIntent", intent);
10135
11101
  paymasterUrl = url.toString();
10136
11102
  }
10137
- const requestedId = (0, import_viem20.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
11103
+ const requestedId = (0, import_viem23.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
10138
11104
  const progress = (id, transfer) => {
10139
11105
  try {
10140
11106
  deps.onCallsProgress?.(id, transfers, transfer);
@@ -10152,7 +11118,7 @@ function makeSponsoredCallsCallback(deps) {
10152
11118
  version: "2.0.0",
10153
11119
  id: requestedId,
10154
11120
  from: deps.ownerAddress,
10155
- chainId: (0, import_viem20.toHex)(chainId),
11121
+ chainId: (0, import_viem23.toHex)(chainId),
10156
11122
  atomicRequired: transfers.length > 1,
10157
11123
  calls,
10158
11124
  capabilities: {
@@ -10306,6 +11272,7 @@ var OwneySDK = class {
10306
11272
  paymasterServiceUrl;
10307
11273
  cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
10308
11274
  agentReads = new AgentReads();
11275
+ depositFamilyReads = /* @__PURE__ */ new Map();
10309
11276
  recoveredFundingReads = /* @__PURE__ */ new Set();
10310
11277
  fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
10311
11278
  activationChecks = /* @__PURE__ */ new Map();
@@ -10384,17 +11351,17 @@ var OwneySDK = class {
10384
11351
  }
10385
11352
  disconnectAgents() {
10386
11353
  if (this.disconnectingAgents) return this.disconnectingAgents;
10387
- const pending = Promise.allSettled([...this.agents.values()].map(async (agent) => agent.disconnect())).then((results) => {
11354
+ const pending2 = Promise.allSettled([...this.agents.values()].map(async (agent) => agent.disconnect())).then((results) => {
10388
11355
  const failure = results.find((result) => result.status === "rejected");
10389
11356
  if (failure?.status === "rejected") throw failure.reason;
10390
11357
  });
10391
- this.disconnectingAgents = pending;
10392
- void pending.then(() => {
10393
- if (this.disconnectingAgents === pending) this.disconnectingAgents = null;
11358
+ this.disconnectingAgents = pending2;
11359
+ void pending2.then(() => {
11360
+ if (this.disconnectingAgents === pending2) this.disconnectingAgents = null;
10394
11361
  }, () => {
10395
- if (this.disconnectingAgents === pending) this.disconnectingAgents = null;
11362
+ if (this.disconnectingAgents === pending2) this.disconnectingAgents = null;
10396
11363
  });
10397
- return pending;
11364
+ return pending2;
10398
11365
  }
10399
11366
  isAgentDisabled(agentId) {
10400
11367
  return this.disabledAgents.has(agentId);
@@ -10441,11 +11408,13 @@ var OwneySDK = class {
10441
11408
  return createPaidRpcClient(VIEM_CHAIN2[chainId], this.rpcUrls);
10442
11409
  }
10443
11410
  /** Builds the default USDC batch callback for the connected wallet. */
10444
- getDefaultSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission) {
10445
- if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && this.cachedSponsoredCallback)
11411
+ getDefaultSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission, assertSubmissionCurrent) {
11412
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent && this.cachedSponsoredCallback)
10446
11413
  return this.cachedSponsoredCallback;
10447
11414
  const provider = this.requireConnectedProvider();
10448
- const owner = this.state.walletAddress;
11415
+ const connection = this.requireState();
11416
+ const owner = connection.walletAddress;
11417
+ const connectedChain = connection.chainId;
10449
11418
  const callback = makeSponsoredTokenCallback({
10450
11419
  apiKey: this.apiKey,
10451
11420
  baseUrl: this.routingApiBaseUrl,
@@ -10454,22 +11423,26 @@ var OwneySDK = class {
10454
11423
  onSubmitted,
10455
11424
  onBeforeSubmission,
10456
11425
  resumeTxHash,
11426
+ assertCurrent: () => {
11427
+ assertSubmissionCurrent?.();
11428
+ if (!this.state || this.state !== connection || this.state.chainId !== connectedChain || this.state.provider !== provider || this.state.walletAddress.toLowerCase() !== owner.toLowerCase()) throw new OwneyError("NOT_CONNECTED", "Wallet changed before deposit submission.");
11429
+ },
10457
11430
  tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
10458
11431
  // Casts work around viem's chain-narrowed Client vs the generic
10459
11432
  // PublicClient/WalletClient param types — structurally identical at
10460
11433
  // runtime, but the two share a name TS treats as unrelated.
10461
11434
  getPublicClient: (cid) => this.getPaidRpcClient(cid),
10462
- getWalletChainClient: (cid) => (0, import_viem21.createPublicClient)({
11435
+ getWalletChainClient: (cid) => (0, import_viem24.createPublicClient)({
10463
11436
  chain: VIEM_CHAIN2[cid],
10464
- transport: (0, import_viem21.custom)(provider)
11437
+ transport: (0, import_viem24.custom)(provider)
10465
11438
  }),
10466
- getWalletClient: (cid) => (0, import_viem21.createWalletClient)({
11439
+ getWalletClient: (cid) => (0, import_viem24.createWalletClient)({
10467
11440
  account: owner,
10468
11441
  chain: VIEM_CHAIN2[cid],
10469
- transport: (0, import_viem21.custom)(provider)
11442
+ transport: (0, import_viem24.custom)(provider)
10470
11443
  })
10471
11444
  });
10472
- if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission) this.cachedSponsoredCallback = callback;
11445
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent) this.cachedSponsoredCallback = callback;
10473
11446
  return callback;
10474
11447
  }
10475
11448
  /** Builds the wallet-native sponsored calls callback for compatible paymasters. */
@@ -10498,11 +11471,13 @@ var OwneySDK = class {
10498
11471
  * Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
10499
11472
  * single-use batch authorization instead of an EIP-3009 authorization.
10500
11473
  */
10501
- getDefaultWethSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission) {
10502
- if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && this.cachedWethSponsoredCallback)
11474
+ getDefaultWethSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission, assertSubmissionCurrent) {
11475
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent && this.cachedWethSponsoredCallback)
10503
11476
  return this.cachedWethSponsoredCallback;
10504
11477
  const provider = this.requireConnectedProvider();
10505
- const owner = this.state.walletAddress;
11478
+ const connection = this.requireState();
11479
+ const owner = connection.walletAddress;
11480
+ const connectedChain = connection.chainId;
10506
11481
  const callback = makeSponsoredTokenCallback({
10507
11482
  apiKey: this.apiKey,
10508
11483
  baseUrl: this.routingApiBaseUrl,
@@ -10511,22 +11486,26 @@ var OwneySDK = class {
10511
11486
  onSubmitted,
10512
11487
  onBeforeSubmission,
10513
11488
  resumeTxHash,
11489
+ assertCurrent: () => {
11490
+ assertSubmissionCurrent?.();
11491
+ if (!this.state || this.state !== connection || this.state.chainId !== connectedChain || this.state.provider !== provider || this.state.walletAddress.toLowerCase() !== owner.toLowerCase()) throw new OwneyError("NOT_CONNECTED", "Wallet changed before deposit submission.");
11492
+ },
10514
11493
  tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
10515
11494
  // Casts work around viem's chain-narrowed Client vs the generic
10516
11495
  // PublicClient/WalletClient param types — structurally identical at
10517
11496
  // runtime, but the two share a name TS treats as unrelated.
10518
11497
  getPublicClient: (cid) => this.getPaidRpcClient(cid),
10519
- getWalletChainClient: (cid) => (0, import_viem21.createPublicClient)({
11498
+ getWalletChainClient: (cid) => (0, import_viem24.createPublicClient)({
10520
11499
  chain: VIEM_CHAIN2[cid],
10521
- transport: (0, import_viem21.custom)(provider)
11500
+ transport: (0, import_viem24.custom)(provider)
10522
11501
  }),
10523
- getWalletClient: (cid) => (0, import_viem21.createWalletClient)({
11502
+ getWalletClient: (cid) => (0, import_viem24.createWalletClient)({
10524
11503
  account: owner,
10525
11504
  chain: VIEM_CHAIN2[cid],
10526
- transport: (0, import_viem21.custom)(provider)
11505
+ transport: (0, import_viem24.custom)(provider)
10527
11506
  })
10528
11507
  });
10529
- if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission) this.cachedWethSponsoredCallback = callback;
11508
+ if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent) this.cachedWethSponsoredCallback = callback;
10530
11509
  return callback;
10531
11510
  }
10532
11511
  getAgent(agentId) {
@@ -10850,10 +11829,10 @@ var OwneySDK = class {
10850
11829
  }
10851
11830
  notifyFunding(options.onProgress, evidence);
10852
11831
  } : void 0;
10853
- const onSubmitted = onProgress ? (hash2, destinations) => {
11832
+ const onSubmitted = onProgress ? (hash2, destinations, depositAuthorization) => {
10854
11833
  for (const destination of destinations) {
10855
11834
  const evidence = prepared.get(destination.to.toLowerCase());
10856
- if (evidence) notifyFunding(onProgress, { ...evidence, txHash: hash2, transfer: "pending" });
11835
+ if (evidence) notifyFunding(onProgress, { ...evidence, txHash: hash2, ...depositAuthorization ? { depositAuthorization } : {}, transfer: "pending" });
10857
11836
  }
10858
11837
  } : void 0;
10859
11838
  const onCallsProgress = onProgress ? (callsId, destinations, transfer) => {
@@ -10895,7 +11874,7 @@ var OwneySDK = class {
10895
11874
  });
10896
11875
  await checkpoint2(evidence);
10897
11876
  } : void 0;
10898
- const checkpointHash = checkpointDestinations ? (hash2, destinations) => checkpointDestinations(destinations, { txHash: hash2 }) : void 0;
11877
+ const checkpointHash = checkpointDestinations ? (hash2, destinations, depositAuthorization) => checkpointDestinations(destinations, { txHash: hash2, depositAuthorization }) : void 0;
10899
11878
  const checkpointCalls = checkpointDestinations ? (id, destinations) => checkpointDestinations(destinations, { callsId: id }) : void 0;
10900
11879
  const checkpointPaid = checkpoint2 ? (evidence) => checkpoint2([evidence]) : void 0;
10901
11880
  const customCallback = depositCallback && checkpointDestinations ? makeVerificationAwareDepositCallback(async (to, cid, value, verification) => {
@@ -10905,19 +11884,20 @@ var OwneySDK = class {
10905
11884
  }) : depositCallback;
10906
11885
  if (options.resumeTxHash && (depositCallback || this.paymasterServiceUrl || !/^0x[\da-f]{64}$/i.test(options.resumeTxHash)))
10907
11886
  throw new OwneyError("DEPOSIT_IN_PROGRESS", "This deposit cannot resume the saved relayer transaction.");
10908
- const effectiveCallback = customCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress, checkpointCalls) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash) : this.getDefaultSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash));
11887
+ const effectiveCallback = customCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress, checkpointCalls) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash, options.assertSubmissionCurrent) : this.getDefaultSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash, options.assertSubmissionCurrent));
10909
11888
  try {
10910
11889
  if (options.resumeTxHash) {
10911
11890
  const token = SupportedAssets.find((value) => value.chainId === chainId && value.symbol === asset);
10912
- const pending = token && pendingTokenBatch({
11891
+ const family = token && await loadTokenBatchFamily({
10913
11892
  apiKey: this.apiKey,
10914
11893
  baseUrl: this.routingApiBaseUrl,
10915
11894
  owner: state.walletAddress,
10916
11895
  chainId,
10917
11896
  token: token.address
10918
- });
11897
+ }, options.resumeTxHash);
11898
+ const pending2 = family && { transfers: family.body.transfers };
10919
11899
  const invalid2 = () => new OwneyError("DEPOSIT_IN_PROGRESS", "The saved deposit does not match this request. Check its status before depositing again.");
10920
- if (!pending || pending.txHash.toLowerCase() !== options.resumeTxHash.toLowerCase() || pending.transfers.some((transfer) => !/^\d+$/.test(transfer.amount) || BigInt(transfer.amount) <= 0n) || pending.transfers.reduce((sum, transfer) => sum + BigInt(transfer.amount), 0n) !== BigInt(amount)) throw invalid2();
11900
+ if (!pending2 || pending2.transfers.some((transfer) => !/^\d+$/.test(transfer.amount) || BigInt(transfer.amount) <= 0n) || pending2.transfers.reduce((sum, transfer) => sum + BigInt(transfer.amount), 0n) !== BigInt(amount)) throw invalid2();
10921
11901
  const candidates = agentId ? [this.getAgent(agentId)] : this.getEligibleAgents(chainId, asset);
10922
11902
  const wallets = await Promise.all(candidates.map(async (agent) => {
10923
11903
  this.validateAssetSupport(agent, chainId, asset);
@@ -10927,7 +11907,7 @@ var OwneySDK = class {
10927
11907
  if (this.state !== state || this.state.chainId !== chainId)
10928
11908
  throw new OwneyError("NOT_CONNECTED", "Wallet changed while recovering the deposit.");
10929
11909
  const usedAgents = /* @__PURE__ */ new Set();
10930
- const legs = pending.transfers.map((transfer) => {
11910
+ const legs = pending2.transfers.map((transfer) => {
10931
11911
  const matches = wallets.filter((value) => value.wallet?.toLowerCase() === transfer.to.toLowerCase());
10932
11912
  if (matches.length !== 1 || usedAgents.has(matches[0].agent.id)) throw invalid2();
10933
11913
  const { agent } = matches[0];
@@ -11376,8 +12356,46 @@ var OwneySDK = class {
11376
12356
  if (!token) throw new OwneyError("CHAIN_UNSUPPORTED", "Unsupported funding asset.");
11377
12357
  const rpc2 = this.getPaidRpcClient(chainId);
11378
12358
  let receipt;
12359
+ if (direction === "deposit" && !evidence.callsId && !evidence.userOpHash) {
12360
+ const scope = {
12361
+ apiKey: this.apiKey,
12362
+ baseUrl: this.routingApiBaseUrl,
12363
+ owner: state.walletAddress,
12364
+ chainId,
12365
+ token: token.address
12366
+ };
12367
+ const family = await loadTokenBatchFamily(scope, evidence.txHash, !evidence.depositAuthorization);
12368
+ assertCurrent();
12369
+ if (family) {
12370
+ if (evidence.depositAuthorization && evidence.depositAuthorization.authorizationId !== family.authorizationId || !family.body.transfers.some((t) => t.to.toLowerCase() === agentWallet.toLowerCase() && t.amount === evidence.intendedAmount))
12371
+ throw new OwneyError("DEPOSIT_IN_PROGRESS", "Deposit evidence does not match its signed authorization.");
12372
+ const familyKey = `${tokenBatchKey(scope)}:${family.authorizationId}`;
12373
+ let reading = this.depositFamilyReads.get(familyKey);
12374
+ if (!reading) {
12375
+ reading = observeTokenBatchFamily({ scope, family, pub: rpc2, deadlineAt: Date.now() + 8e3, assertCurrent }).finally(() => this.depositFamilyReads.delete(familyKey));
12376
+ this.depositFamilyReads.set(familyKey, reading);
12377
+ }
12378
+ const result = await reading;
12379
+ assertCurrent();
12380
+ evidence = { ...evidence, depositAuthorization: { authorizationId: family.authorizationId } };
12381
+ if (result.status === "confirmed") {
12382
+ receipt = result.receipt;
12383
+ evidence = { ...evidence, txHash: result.txHash };
12384
+ } else if (result.status === "expired" || result.status === "failed")
12385
+ return {
12386
+ ...evidence,
12387
+ agentWallet,
12388
+ transfer: "failed",
12389
+ delivery: "not-applicable",
12390
+ registration: "not-applicable",
12391
+ confirmedAmount: "0",
12392
+ blockNumber: (result.status === "expired" ? result.blockNumber : result.receipts.reduce((n, r) => r.blockNumber > n ? r.blockNumber : n, 0n)).toString()
12393
+ };
12394
+ else return { ...evidence, agentWallet, transfer: "unknown", delivery: "not-applicable" };
12395
+ }
12396
+ }
11379
12397
  try {
11380
- receipt = await rpc2.getTransactionReceipt({ hash: evidence.txHash });
12398
+ receipt ??= await rpc2.getTransactionReceipt({ hash: evidence.txHash });
11381
12399
  } catch (error) {
11382
12400
  if (direction === "deposit") {
11383
12401
  const expired = await releaseExpiredTokenBatch({
@@ -11497,29 +12515,65 @@ var OwneySDK = class {
11497
12515
  /** Whether a foreground deposit can resume the same signed batch, never a
11498
12516
  * fresh authorization. The batch rail independently rechecks the exact plan. */
11499
12517
  async canResumePendingDeposit(evidences, amount) {
11500
- if (this.paymasterServiceUrl || !evidences.length || !/^\d+$/.test(amount)) return false;
11501
- const first = evidences[0];
11502
- const { state, chainId, assertCurrent } = this.captureReadScope(first.chainId);
11503
- const token = SupportedAssets.find((value) => value.chainId === chainId && value.symbol === first.token);
11504
- if (!token) return false;
11505
- const pending = pendingTokenBatch({
11506
- apiKey: this.apiKey,
11507
- baseUrl: this.routingApiBaseUrl,
11508
- owner: state.walletAddress,
11509
- chainId,
11510
- token: token.address
11511
- });
11512
- if (!pending || pending.transfers.length !== evidences.length || pending.transfers.reduce((sum, transfer) => sum + BigInt(transfer.amount), 0n).toString() !== amount) return false;
11513
- const destinations = /* @__PURE__ */ new Set();
11514
- for (const evidence of evidences) {
11515
- if (evidence.chainId !== chainId || evidence.token !== first.token || evidence.walletAddress.toLowerCase() !== state.walletAddress.toLowerCase() || evidence.callsId || evidence.userOpHash || evidence.txHash?.toLowerCase() !== pending.txHash.toLowerCase()) return false;
11516
- const agent = this.getAgent(evidence.agentId);
11517
- const wallet = agent.getFundingWallet ? await agent.getFundingWallet(state, chainId, evidence.token) : (await agent.getUserProfile(state, chainId)).smartWallet;
11518
- if (!wallet || destinations.has(wallet.toLowerCase()) || !pending.transfers.some((transfer) => transfer.to.toLowerCase() === wallet.toLowerCase() && transfer.amount === evidence.intendedAmount)) return false;
11519
- destinations.add(wallet.toLowerCase());
12518
+ try {
12519
+ if (this.paymasterServiceUrl || !evidences.length || !/^\d+$/.test(amount)) return false;
12520
+ const first = evidences[0];
12521
+ if (!first.txHash) return false;
12522
+ const { state, chainId, assertCurrent } = this.captureReadScope(first.chainId);
12523
+ const token = SupportedAssets.find((value) => value.chainId === chainId && value.symbol === first.token);
12524
+ if (!token) return false;
12525
+ const family = await loadTokenBatchFamily({
12526
+ apiKey: this.apiKey,
12527
+ baseUrl: this.routingApiBaseUrl,
12528
+ owner: state.walletAddress,
12529
+ chainId,
12530
+ token: token.address
12531
+ }, first.txHash);
12532
+ const transfers = family?.body.transfers;
12533
+ if (!family || !transfers || transfers.length !== evidences.length || transfers.reduce((n, t) => n + BigInt(t.amount), 0n).toString() !== amount) return false;
12534
+ const destinations = /* @__PURE__ */ new Set();
12535
+ for (const e of evidences) {
12536
+ if (e.chainId !== chainId || e.token !== first.token || e.walletAddress.toLowerCase() !== state.walletAddress.toLowerCase() || e.callsId || e.userOpHash || !family.attempts.some((a) => a.phase === "deposit" && a.hash.toLowerCase() === e.txHash?.toLowerCase()) || e.depositAuthorization && e.depositAuthorization.authorizationId !== family.authorizationId) return false;
12537
+ const agent = this.getAgent(e.agentId);
12538
+ const wallet = agent.getFundingWallet ? await agent.getFundingWallet(state, chainId, e.token) : (await agent.getUserProfile(state, chainId)).smartWallet;
12539
+ assertCurrent();
12540
+ if (!wallet || destinations.has(wallet.toLowerCase()) || e.agentWallet && e.agentWallet.toLowerCase() !== wallet.toLowerCase() || !transfers.some((t) => t.to.toLowerCase() === wallet.toLowerCase() && t.amount === e.intendedAmount)) return false;
12541
+ destinations.add(wallet.toLowerCase());
12542
+ }
12543
+ assertCurrent();
12544
+ return true;
12545
+ } catch {
12546
+ return false;
12547
+ }
12548
+ }
12549
+ /** Validate signed journal membership, never just a caller-supplied family ID. */
12550
+ async validateDepositReplacement(previous, next) {
12551
+ try {
12552
+ if (!previous.length || previous.length !== next.length || previous.some((e) => e.transfer === "confirmed" || !/^\d+$/.test(e.intendedAmount))) return;
12553
+ const amount = previous.reduce((sum, e) => sum + BigInt(e.intendedAmount), 0n).toString();
12554
+ if (!await this.canResumePendingDeposit(previous, amount) || !await this.canResumePendingDeposit(next, amount)) return;
12555
+ const { state, chainId, assertCurrent } = this.captureReadScope(previous[0].chainId);
12556
+ const token = SupportedAssets.find((t) => t.chainId === chainId && t.symbol === previous[0].token);
12557
+ const family = await loadTokenBatchFamily({
12558
+ apiKey: this.apiKey,
12559
+ baseUrl: this.routingApiBaseUrl,
12560
+ owner: state.walletAddress,
12561
+ chainId,
12562
+ token: token.address
12563
+ }, previous[0].txHash);
12564
+ assertCurrent();
12565
+ if (!family || family.terminal) return;
12566
+ const predecessorTxHash = previous[0].txHash, replacementTxHash = next[0].txHash;
12567
+ const replacement = family.attempts.find((a) => a.phase === "deposit" && a.hash.toLowerCase() === replacementTxHash.toLowerCase());
12568
+ if (!replacement || replacement.predecessorHash?.toLowerCase() !== predecessorTxHash.toLowerCase()) return;
12569
+ for (const p of previous) {
12570
+ const matches = next.filter((n2) => n2.agentId === p.agentId), n = matches[0];
12571
+ if (matches.length !== 1 || p.txHash?.toLowerCase() !== predecessorTxHash.toLowerCase() || n.txHash?.toLowerCase() !== replacementTxHash.toLowerCase() || p.intendedAmount !== n.intendedAmount || p.agentWallet?.toLowerCase() !== n.agentWallet?.toLowerCase() || n.depositAuthorization?.authorizationId !== family.authorizationId || n.depositAuthorization.predecessorTxHash?.toLowerCase() !== predecessorTxHash.toLowerCase()) return;
12572
+ }
12573
+ return { authorizationId: family.authorizationId, predecessorTxHash, replacementTxHash };
12574
+ } catch {
12575
+ return;
11520
12576
  }
11521
- assertCurrent();
11522
- return true;
11523
12577
  }
11524
12578
  /** Optional post-payout display proof; receipt verification and the provider
11525
12579
  * adapter must agree before attaching it to this exact balance object. */
@@ -11549,13 +12603,13 @@ var OwneySDK = class {
11549
12603
  metadata
11550
12604
  ] };
11551
12605
  };
11552
- const pending = Promise.race([read2(), new Promise((resolve) => {
12606
+ const pending2 = Promise.race([read2(), new Promise((resolve) => {
11553
12607
  timer = setTimeout(() => resolve(balance), 2e3);
11554
12608
  })]).catch(() => balance).finally(() => {
11555
12609
  if (timer) clearTimeout(timer);
11556
12610
  });
11557
- checks.set(key2, pending);
11558
- const result = await pending;
12611
+ checks.set(key2, pending2);
12612
+ const result = await pending2;
11559
12613
  assertCurrent();
11560
12614
  return result;
11561
12615
  }
@@ -11647,11 +12701,11 @@ var OwneySDK = class {
11647
12701
  );
11648
12702
  }
11649
12703
  await ensureWalletOnChain(
11650
- (0, import_viem21.createPublicClient)({ chain: chain2, transport: (0, import_viem21.custom)(provider) }),
11651
- (0, import_viem21.createWalletClient)({
12704
+ (0, import_viem24.createPublicClient)({ chain: chain2, transport: (0, import_viem24.custom)(provider) }),
12705
+ (0, import_viem24.createWalletClient)({
11652
12706
  account: state.walletAddress,
11653
12707
  chain: chain2,
11654
- transport: (0, import_viem21.custom)(provider)
12708
+ transport: (0, import_viem24.custom)(provider)
11655
12709
  }),
11656
12710
  chainId
11657
12711
  );
@@ -11671,19 +12725,22 @@ var OwneySDK = class {
11671
12725
  * quote's source token. A quote naming ETH would have all of them reading
11672
12726
  * the wrong asset.
11673
12727
  */
11674
- async wrapNativeSource(quote, walletAddress, onStage, direction) {
12728
+ async wrapNativeSource(quote, walletAddress, onStage, direction, assertCurrent) {
11675
12729
  const wrapper = requireWrapper(quote);
11676
12730
  const chainId = quote.src.chainId;
11677
12731
  const chain2 = swapChain(chainId);
11678
12732
  const provider = this.requireConnectedProvider();
11679
- const publicClient = (0, import_viem21.createPublicClient)({
12733
+ const publicClient = (0, import_viem24.createPublicClient)({
11680
12734
  chain: chain2,
11681
12735
  transport: swapReadTransport(chainId, this.zyfaiRpcUrls)
11682
12736
  });
11683
- const wallet = (0, import_viem21.createWalletClient)({
12737
+ const wallet = (0, import_viem24.createWalletClient)({
11684
12738
  account: walletAddress,
11685
12739
  chain: chain2,
11686
- transport: (0, import_viem21.custom)(provider)
12740
+ transport: (0, import_viem24.custom)({ request: (args) => {
12741
+ assertCurrent?.();
12742
+ return provider.request(args);
12743
+ } })
11687
12744
  });
11688
12745
  onStage?.("wrapping");
11689
12746
  const { wrapped } = await wrapNative(
@@ -11704,6 +12761,7 @@ var OwneySDK = class {
11704
12761
  return fees.maxFeePerGas ?? publicClient.getGasPrice();
11705
12762
  },
11706
12763
  sendTransaction: async (tx, onSubmitted) => {
12764
+ assertCurrent?.();
11707
12765
  const hash2 = await wallet.sendTransaction({
11708
12766
  to: tx.to,
11709
12767
  data: tx.data,
@@ -11790,22 +12848,22 @@ var OwneySDK = class {
11790
12848
  };
11791
12849
  const srcChain = swapChain(quote.src.chainId);
11792
12850
  const dstChain = swapChain(quote.dst.chainId);
11793
- const wallet = (0, import_viem21.createWalletClient)({
12851
+ const wallet = (0, import_viem24.createWalletClient)({
11794
12852
  account: state.walletAddress,
11795
12853
  chain: srcChain,
11796
12854
  // viem can await chain/account preparation before dispatching a wallet
11797
12855
  // request. Recheck at the transport boundary so an expired attempt or
11798
12856
  // replaced session cannot send after that internal await completes.
11799
- transport: (0, import_viem21.custom)({ request: (args) => {
12857
+ transport: (0, import_viem24.custom)({ request: (args) => {
11800
12858
  assertWallet();
11801
12859
  return provider.request(args);
11802
12860
  } }, { retryCount: 0 })
11803
12861
  });
11804
- const srcPublic = (0, import_viem21.createPublicClient)({
12862
+ const srcPublic = (0, import_viem24.createPublicClient)({
11805
12863
  chain: srcChain,
11806
12864
  transport: swapReadTransport(quote.src.chainId, this.zyfaiRpcUrls)
11807
12865
  });
11808
- const dstPublic = (0, import_viem21.createPublicClient)({
12866
+ const dstPublic = (0, import_viem24.createPublicClient)({
11809
12867
  chain: dstChain,
11810
12868
  transport: swapReadTransport(quote.dst.chainId, this.zyfaiRpcUrls)
11811
12869
  });
@@ -11822,7 +12880,7 @@ var OwneySDK = class {
11822
12880
  }
11823
12881
  return dstPublic.readContract({
11824
12882
  address: dst,
11825
- abi: import_viem21.erc20Abi,
12883
+ abi: import_viem24.erc20Abi,
11826
12884
  functionName: "balanceOf",
11827
12885
  args: [state.walletAddress]
11828
12886
  });
@@ -11964,9 +13022,9 @@ var OwneySDK = class {
11964
13022
  async readTokenBalance(chainId, token) {
11965
13023
  const state = this.requireState();
11966
13024
  return readErc20Balance(
11967
- (0, import_viem21.createPublicClient)({
13025
+ (0, import_viem24.createPublicClient)({
11968
13026
  chain: swapChain(chainId),
11969
- transport: (0, import_viem21.custom)(this.requireConnectedProvider())
13027
+ transport: (0, import_viem24.custom)(this.requireConnectedProvider())
11970
13028
  }),
11971
13029
  token,
11972
13030
  state.walletAddress
@@ -11976,9 +13034,9 @@ var OwneySDK = class {
11976
13034
  async readTokenPermit2Allowance(chainId, token) {
11977
13035
  const state = this.requireState();
11978
13036
  return readPermit2Allowance(
11979
- (0, import_viem21.createPublicClient)({
13037
+ (0, import_viem24.createPublicClient)({
11980
13038
  chain: swapChain(chainId),
11981
- transport: (0, import_viem21.custom)(this.requireConnectedProvider())
13039
+ transport: (0, import_viem24.custom)(this.requireConnectedProvider())
11982
13040
  }),
11983
13041
  token,
11984
13042
  state.walletAddress
@@ -11991,13 +13049,19 @@ var OwneySDK = class {
11991
13049
  * Native Base/Arbitrum USDC uses sponsored ERC-2612; configured paymaster
11992
13050
  * wallet calls also cover approval without spending the received tokens.
11993
13051
  */
11994
- async settleSwapDepositAmount(chainId, token, symbol2, received) {
13052
+ async settleSwapDepositAmount(chainId, token, symbol2, received, assertCurrent) {
11995
13053
  if (symbol2 !== "WETH" && symbol2 !== "USDC" || this.paymasterServiceUrl || supportsSponsoredErc2612(chainId, token)) {
11996
13054
  return received.toString();
11997
13055
  }
11998
13056
  const allowance = await this.readTokenPermit2Allowance(chainId, token);
13057
+ assertCurrent?.();
11999
13058
  if (allowance < received) {
12000
- await this.approvePermit2(symbol2, received, chainId);
13059
+ await this.approvePermit2(
13060
+ symbol2,
13061
+ received,
13062
+ chainId,
13063
+ ...assertCurrent ? [assertCurrent] : []
13064
+ );
12001
13065
  }
12002
13066
  const balance = await this.readTokenBalance(chainId, token);
12003
13067
  return (balance < received ? balance : received).toString();
@@ -12005,9 +13069,9 @@ var OwneySDK = class {
12005
13069
  async walletSeesBalance(chainId, token, amount) {
12006
13070
  const provider = this.requireConnectedProvider();
12007
13071
  const state = this.requireState();
12008
- const pub = (0, import_viem21.createPublicClient)({
13072
+ const pub = (0, import_viem24.createPublicClient)({
12009
13073
  chain: swapChain(chainId),
12010
- transport: (0, import_viem21.custom)(provider)
13074
+ transport: (0, import_viem24.custom)(provider)
12011
13075
  });
12012
13076
  const { arrived } = await awaitBalanceIncrease({
12013
13077
  readBalance: () => pub.readContract({
@@ -12028,7 +13092,7 @@ var OwneySDK = class {
12028
13092
  * so the deposit half of `swapAndDeposit` can be exercised on its own.
12029
13093
  */
12030
13094
  runSwap(quote, options) {
12031
- return executeSwap(this.buildSwapDeps(quote), { quote, ...options });
13095
+ return executeSwap(this.buildSwapDeps(quote, options.assertCurrent), { quote, ...options });
12032
13096
  }
12033
13097
  /**
12034
13098
  * The half of the swap deps that only ever talks to the routing API.
@@ -12130,7 +13194,7 @@ var OwneySDK = class {
12130
13194
  async resumePendingSwaps(options = {}) {
12131
13195
  await mapConcurrent(listWithdrawSwaps(Date.now(), true).filter((record2) => record2.txHash && record2.status === "unknown" && (!options.orderHash || options.orderHash === record2.orderHash)), async (record2) => {
12132
13196
  try {
12133
- const rpc2 = (0, import_viem21.createPublicClient)({ chain: swapChain(record2.srcChainId), transport: swapReadTransport(record2.srcChainId, this.zyfaiRpcUrls) });
13197
+ const rpc2 = (0, import_viem24.createPublicClient)({ chain: swapChain(record2.srcChainId), transport: swapReadTransport(record2.srcChainId, this.zyfaiRpcUrls) });
12134
13198
  const receipt = await bounded(
12135
13199
  () => rpc2.getTransactionReceipt({ hash: record2.txHash }),
12136
13200
  8e3,
@@ -12140,10 +13204,10 @@ var OwneySDK = class {
12140
13204
  } catch {
12141
13205
  }
12142
13206
  });
12143
- const pending = listOrders().filter((order) => !isOrderObserved(order.orderHash) && (!options.orderHash || order.orderHash === options.orderHash));
13207
+ const pending2 = listOrders().filter((order) => !isOrderObserved(order.orderHash) && (!options.orderHash || order.orderHash === options.orderHash));
12144
13208
  const runner = this.swapRunnerDeps();
12145
13209
  const sameChain = this.resumeSameChainSwaps(options);
12146
- const results = await mapConcurrent(pending, async (order) => {
13210
+ const results = await mapConcurrent(pending2, async (order) => {
12147
13211
  try {
12148
13212
  await runFusionOrder(runner, {
12149
13213
  orderHash: order.orderHash,
@@ -12316,45 +13380,69 @@ var OwneySDK = class {
12316
13380
  */
12317
13381
  async swapAndDeposit(options) {
12318
13382
  const state = this.requireState();
13383
+ options.assertCurrent?.();
13384
+ if (options.agentId) {
13385
+ this.validateAssetSupport(
13386
+ this.getAgent(options.agentId),
13387
+ options.to.chainId,
13388
+ options.to.symbol
13389
+ );
13390
+ }
12319
13391
  const api = this.swapApi();
12320
13392
  const quoted = await api.quote({
12321
13393
  from: options.from,
12322
13394
  to: options.to,
12323
13395
  walletAddress: state.walletAddress
12324
13396
  });
13397
+ options.assertCurrent?.();
12325
13398
  const quote = quoted.requiresOnchainOrder ? await this.wrapNativeSource(
12326
13399
  quoted,
12327
13400
  state.walletAddress,
12328
- options.onSwapProgress
13401
+ options.onSwapProgress,
13402
+ void 0,
13403
+ options.assertCurrent
12329
13404
  ) : quoted;
13405
+ options.assertCurrent?.();
12330
13406
  await this.ensureSwapChain(quote.src.chainId);
13407
+ options.assertCurrent?.();
12331
13408
  const swap = await this.runSwap(quote, {
12332
13409
  walletAddress: state.walletAddress,
13410
+ ...options.assertCurrent ? { assertCurrent: options.assertCurrent } : {},
12333
13411
  ...options.slippage === void 0 ? {} : { slippage: options.slippage },
12334
13412
  ...options.onSwapProgress ? { onStage: options.onSwapProgress } : {}
12335
13413
  });
12336
13414
  options.onSwapProgress?.("depositing");
12337
13415
  try {
13416
+ options.assertCurrent?.();
12338
13417
  await this.ensureSwapChain(quote.dst.chainId);
13418
+ options.assertCurrent?.();
12339
13419
  await this.walletSeesBalance(
12340
13420
  quote.dst.chainId,
12341
13421
  quote.dst.address,
12342
13422
  BigInt(swap.received)
12343
13423
  );
13424
+ options.assertCurrent?.();
12344
13425
  const amount = await this.settleSwapDepositAmount(
12345
13426
  quote.dst.chainId,
12346
13427
  quote.dst.address,
12347
13428
  options.to.symbol,
12348
- BigInt(swap.received)
13429
+ BigInt(swap.received),
13430
+ options.assertCurrent
12349
13431
  );
13432
+ options.assertCurrent?.();
13433
+ await options.onBeforeDeposit?.();
13434
+ options.assertCurrent?.();
12350
13435
  const deposit = await this.deposit({
12351
13436
  amount,
12352
13437
  asset: options.to.symbol,
12353
- ...options.agentId ? { agentId: options.agentId } : {}
13438
+ ...options.agentId ? { agentId: options.agentId } : {},
13439
+ ...options.onDepositProgress ? { onProgress: options.onDepositProgress } : {},
13440
+ ...options.onBeforeDepositSubmission ? { onBeforeSubmission: options.onBeforeDepositSubmission } : {},
13441
+ ...options.assertCurrent ? { assertSubmissionCurrent: options.assertCurrent } : {}
12354
13442
  });
12355
13443
  return { swap, deposit, deposited: amount };
12356
13444
  } catch (error) {
12357
- const pending = {
13445
+ const pending2 = {
12358
13446
  id: `${quote.dst.chainId}-${options.to.symbol}-${Date.now()}`,
12359
13447
  received: swap.received,
12360
13448
  symbol: options.to.symbol,
@@ -12362,12 +13450,12 @@ var OwneySDK = class {
12362
13450
  ...options.agentId ? { agentId: options.agentId } : {},
12363
13451
  createdAt: Date.now()
12364
13452
  };
12365
- savePendingDeposit(pending);
13453
+ savePendingDeposit(pending2);
12366
13454
  throw new OwneyError(
12367
13455
  "SWAP_DEPOSIT_PENDING",
12368
13456
  `The swap went through and your ${options.to.symbol} is in your wallet, but adding it to the agent didn't complete. Nothing needs swapping again.`,
12369
13457
  {
12370
- ...pending,
13458
+ ...pending2,
12371
13459
  cause: error instanceof Error ? error.message : String(error),
12372
13460
  ...error instanceof OwneyError ? { causeCode: error.code } : {}
12373
13461
  }
@@ -12390,7 +13478,7 @@ var OwneySDK = class {
12390
13478
  "Some withdrawal results remain unknown. Check Activity and balances before continuing.",
12391
13479
  { reason: "WITHDRAWAL_RESULTS_UNAVAILABLE", swapSubmitted: false }
12392
13480
  );
12393
- const rpc2 = (0, import_viem21.createPublicClient)({
13481
+ const rpc2 = (0, import_viem24.createPublicClient)({
12394
13482
  chain: VIEM_CHAIN2[record2.srcChainId],
12395
13483
  transport: swapReadTransport(record2.srcChainId, this.zyfaiRpcUrls)
12396
13484
  });
@@ -12423,7 +13511,7 @@ var OwneySDK = class {
12423
13511
  baselineBlock: BigInt(recovery.baselineBlock),
12424
13512
  timeoutMs: 3e4,
12425
13513
  assertCurrent: assertRecoveryCurrent,
12426
- readBalance: () => rpc2.readContract({ address: asset.address, abi: import_viem21.erc20Abi, functionName: "balanceOf", args: [state.walletAddress] }),
13514
+ readBalance: () => rpc2.readContract({ address: asset.address, abi: import_viem24.erc20Abi, functionName: "balanceOf", args: [state.walletAddress] }),
12427
13515
  inspect: (value, fromHistory) => this.inspectFunding(value, "withdraw", { requireAmountMatch: fromHistory, refreshBalance: false }),
12428
13516
  resolve: (value) => this.resolveSponsoredWithdrawalEvidence(value, { submittedAt: recovery.submittedAt }),
12429
13517
  history: (value, fromDate, filters) => this.getFundingHistory(value, fromDate, filters),
@@ -12527,13 +13615,13 @@ var OwneySDK = class {
12527
13615
  );
12528
13616
  }
12529
13617
  const srcChain = VIEM_CHAIN2[options.from.chainId];
12530
- const srcPublic = (0, import_viem21.createPublicClient)({
13618
+ const srcPublic = (0, import_viem24.createPublicClient)({
12531
13619
  chain: srcChain,
12532
13620
  transport: swapReadTransport(options.from.chainId, this.zyfaiRpcUrls)
12533
13621
  });
12534
13622
  const readWalletBalance = () => srcPublic.readContract({
12535
13623
  address: asset.address,
12536
- abi: import_viem21.erc20Abi,
13624
+ abi: import_viem24.erc20Abi,
12537
13625
  functionName: "balanceOf",
12538
13626
  args: [state.walletAddress]
12539
13627
  });
@@ -12554,7 +13642,7 @@ var OwneySDK = class {
12554
13642
  });
12555
13643
  options.onSwapProgress?.("withdrawing");
12556
13644
  const submittedAt = saved?.recovery?.submittedAt ?? Date.now();
12557
- const requested = saved ? saved.recovery.requested === void 0 ? void 0 : BigInt(saved.recovery.requested) : options.amount === void 0 ? void 0 : (0, import_viem21.parseUnits)(options.amount, asset.decimals);
13645
+ const requested = saved ? saved.recovery.requested === void 0 ? void 0 : BigInt(saved.recovery.requested) : options.amount === void 0 ? void 0 : (0, import_viem24.parseUnits)(options.amount, asset.decimals);
12558
13646
  confirmationDeadline = Date.now() + (options.arrivalTimeoutMs ?? 18e4);
12559
13647
  const attemptId = saved?.recovery?.attemptId ?? `withdraw-${globalThis.crypto.randomUUID()}`;
12560
13648
  record2 = saved ?? {
@@ -12879,12 +13967,12 @@ var OwneySDK = class {
12879
13967
  const submissionEvidence = /* @__PURE__ */ new Map();
12880
13968
  const pendingSubmissions = () => Object.fromEntries([...submissionEvidence].filter(([id, evidence]) => evidence.agentId === id && evidence.chainId === chainId && evidence.token === token && evidence.walletAddress.toLowerCase() === state.walletAddress.toLowerCase() && evidence.transfer !== "failed" && evidence.delivery !== "failed" && (evidence.transfer === "unknown" || evidence.txHash || evidence.userOpHash || evidence.callsId)));
12881
13969
  const throwUnconfirmed = (agentErrors2) => {
12882
- const pending = pendingSubmissions();
12883
- if (Object.keys(pending).length)
13970
+ const pending2 = pendingSubmissions();
13971
+ if (Object.keys(pending2).length)
12884
13972
  throw new OwneyError(
12885
13973
  "WITHDRAW_UNCONFIRMED",
12886
13974
  "The withdrawal was submitted, but its outcome could not be confirmed yet.",
12887
- { asset, amount, agentErrors: agentErrors2, agentFailures, pendingSubmissions: pending }
13975
+ { asset, amount, agentErrors: agentErrors2, agentFailures, pendingSubmissions: pending2 }
12888
13976
  );
12889
13977
  };
12890
13978
  const submit = async (agent, requested2) => {
@@ -13045,7 +14133,7 @@ var OwneySDK = class {
13045
14133
  if (this.isUserRejectedWithdrawal(originalFailure)) throw originalFailure;
13046
14134
  if (entry.balance !== 0n && entry.agent.id !== "yieldseeker") {
13047
14135
  const total = aggregated.agentBalances[entry.agent.id]?.assetBalances?.find((value) => value.chainId === chainId && value.asset.toUpperCase() === token);
13048
- if (!total || (0, import_viem21.parseUnits)(total.amount, assetInfo.decimals) <= entry.balance) return;
14136
+ if (!total || (0, import_viem24.parseUnits)(total.amount, assetInfo.decimals) <= entry.balance) return;
13049
14137
  }
13050
14138
  try {
13051
14139
  const otherAvailable = indexedAvailable - entry.balance;
@@ -13337,15 +14425,15 @@ var OwneySDK = class {
13337
14425
  return this.aggregateEarnings([...this.getActiveAgents().entries()], refreshAgent);
13338
14426
  }
13339
14427
  async aggregateEarnings(entries, read2) {
13340
- const settled = await Promise.allSettled(entries.map(([, agent]) => read2(agent)));
14428
+ const settled2 = await Promise.allSettled(entries.map(([, agent]) => read2(agent)));
13341
14429
  const agentEarnings = {};
13342
14430
  const agentErrors = {};
13343
14431
  const agentRetryAt = {};
13344
14432
  const failures = [];
13345
14433
  let totalEarnings = 0;
13346
- for (let i = 0; i < settled.length; i++) {
14434
+ for (let i = 0; i < settled2.length; i++) {
13347
14435
  const [id] = entries[i];
13348
- const result = settled[i];
14436
+ const result = settled2[i];
13349
14437
  if (result.status === "fulfilled") {
13350
14438
  agentEarnings[id] = result.value;
13351
14439
  totalEarnings += Number(result.value.lifetimeEarnings);
@@ -13414,7 +14502,7 @@ var OwneySDK = class {
13414
14502
  const entries = [...this.getActiveAgents().entries()].filter(
13415
14503
  ([, agent]) => agent.getDailyEarnings
13416
14504
  );
13417
- const settled = await Promise.allSettled(
14505
+ const settled2 = await Promise.allSettled(
13418
14506
  entries.map(
13419
14507
  ([, agent]) => this.readAgent(
13420
14508
  agent,
@@ -13424,9 +14512,9 @@ var OwneySDK = class {
13424
14512
  )
13425
14513
  )
13426
14514
  );
13427
- const series = settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
14515
+ const series = settled2.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
13428
14516
  if (entries.length && !series.length) {
13429
- const failure = settled.find((result) => result.status === "rejected");
14517
+ const failure = settled2.find((result) => result.status === "rejected");
13430
14518
  if (failure?.status === "rejected") throw failure.reason;
13431
14519
  }
13432
14520
  return {
@@ -13649,12 +14737,12 @@ var OwneySDK = class {
13649
14737
  ]);
13650
14738
  const existing = this.activationChecks.get(key2);
13651
14739
  if (existing) return existing;
13652
- const pending = Promise.resolve().then(() => agent.ensureAutoSelectProtocols(state, chainId, asset)).finally(() => {
13653
- if (this.activationChecks.get(key2) === pending)
14740
+ const pending2 = Promise.resolve().then(() => agent.ensureAutoSelectProtocols(state, chainId, asset)).finally(() => {
14741
+ if (this.activationChecks.get(key2) === pending2)
13654
14742
  this.activationChecks.delete(key2);
13655
14743
  });
13656
- this.activationChecks.set(key2, pending);
13657
- return pending;
14744
+ this.activationChecks.set(key2, pending2);
14745
+ return pending2;
13658
14746
  }
13659
14747
  /**
13660
14748
  * User-paid approval of Permit2 on the selected token for the active chain.
@@ -13667,7 +14755,7 @@ var OwneySDK = class {
13667
14755
  * @param expectedChainId Chain captured by the deposit that requested approval.
13668
14756
  * @returns the approval transaction hash.
13669
14757
  */
13670
- async approvePermit2(asset = "WETH", requiredAmount = 0n, expectedChainId) {
14758
+ async approvePermit2(asset = "WETH", requiredAmount = 0n, expectedChainId, assertCurrent) {
13671
14759
  const state = this.requireState();
13672
14760
  const chainId = expectedChainId ?? this.requireChainId();
13673
14761
  this.getEligibleAgents(chainId, asset, { excludeDisabled: true });
@@ -13679,18 +14767,22 @@ var OwneySDK = class {
13679
14767
  );
13680
14768
  }
13681
14769
  const provider = this.requireConnectedProvider();
13682
- const walletChainClient = (0, import_viem21.createPublicClient)({
14770
+ const walletChainClient = (0, import_viem24.createPublicClient)({
13683
14771
  chain: VIEM_CHAIN2[chainId],
13684
- transport: (0, import_viem21.custom)(provider)
14772
+ transport: (0, import_viem24.custom)(provider)
13685
14773
  });
13686
14774
  const publicClient = this.getPaidRpcClient(chainId);
13687
14775
  const approvalAmount = permit2ApprovalAmount(requiredAmount);
13688
- const wallet = (0, import_viem21.createWalletClient)({
14776
+ const wallet = (0, import_viem24.createWalletClient)({
13689
14777
  account: state.walletAddress,
13690
14778
  chain: VIEM_CHAIN2[chainId],
13691
- transport: (0, import_viem21.custom)(provider)
14779
+ transport: (0, import_viem24.custom)({ request: (args) => {
14780
+ assertCurrent?.();
14781
+ return provider.request(args);
14782
+ } })
13692
14783
  });
13693
14784
  await ensureWalletOnChain(walletChainClient, wallet, chainId);
14785
+ assertCurrent?.();
13694
14786
  const hash2 = await wallet.writeContract({
13695
14787
  address: token,
13696
14788
  abi: ERC20_ALLOWANCE_ABI,
@@ -13829,10 +14921,10 @@ var OwneySDK = class {
13829
14921
  const agentErrors = {};
13830
14922
  const agentFailures = [];
13831
14923
  for (let i = 0; i < balanceResults.length; i++) {
13832
- const settled = balanceResults[i];
14924
+ const settled2 = balanceResults[i];
13833
14925
  const [aid] = entries[i];
13834
- if (settled.status === "fulfilled") {
13835
- const [id, positions] = settled.value;
14926
+ if (settled2.status === "fulfilled") {
14927
+ const [id, positions] = settled2.value;
13836
14928
  const per = computeAllocationApy(positions);
13837
14929
  agentApy[id] = {
13838
14930
  totalApy: per.totalApy,
@@ -13841,7 +14933,7 @@ var OwneySDK = class {
13841
14933
  allPositions.push(...positions);
13842
14934
  successCount += 1;
13843
14935
  } else {
13844
- const reason = settled.reason;
14936
+ const reason = settled2.reason;
13845
14937
  agentFailures.push(reason);
13846
14938
  agentErrors[aid] = reason instanceof Error ? reason.message : String(reason);
13847
14939
  console.error(`getAllocationApy agent "${aid}" failed:`, reason);
@@ -13863,8 +14955,11 @@ var OwneySDK = class {
13863
14955
  }
13864
14956
  };
13865
14957
 
14958
+ // src/index.ts
14959
+ init_errors();
14960
+
13866
14961
  // src/agents/zyfai/zyfai.siwx.ts
13867
- var import_viem22 = require("viem");
14962
+ var import_viem25 = require("viem");
13868
14963
  var import_siwe2 = require("siwe");
13869
14964
  var import_sdk2 = require("@zyfai/sdk");
13870
14965
 
@@ -13991,7 +15086,7 @@ function buildSIWXConfig(deps) {
13991
15086
  issuedAt,
13992
15087
  toString() {
13993
15088
  return new import_siwe2.SiweMessage({
13994
- address: (0, import_viem22.getAddress)(accountAddress),
15089
+ address: (0, import_viem25.getAddress)(accountAddress),
13995
15090
  chainId: numericChainId(chainId),
13996
15091
  domain,
13997
15092
  uri,