@owney/sdk 0.6.5 → 0.6.6-beta.1

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
@@ -3,6 +3,9 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
6
9
  var __export = (target, all) => {
7
10
  for (var name in all)
8
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -17,9 +20,486 @@ var __copyProps = (to, from, except, desc) => {
17
20
  };
18
21
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
22
 
23
+ // src/errors.ts
24
+ var OwneyError, AgentNotFoundError, NotConnectedError, AgentChainIncompatibleError;
25
+ var init_errors = __esm({
26
+ "src/errors.ts"() {
27
+ "use strict";
28
+ OwneyError = class extends Error {
29
+ code;
30
+ details;
31
+ agentId;
32
+ constructor(code, message, details, agentId) {
33
+ const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
34
+ super(`${prefix} ${message}`);
35
+ this.name = "OwneyError";
36
+ this.code = code;
37
+ this.details = details;
38
+ this.agentId = agentId;
39
+ }
40
+ };
41
+ AgentNotFoundError = class extends OwneyError {
42
+ constructor(agentId, available) {
43
+ super(
44
+ "AGENT_NOT_FOUND",
45
+ `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
46
+ { agentId, available },
47
+ agentId
48
+ );
49
+ this.name = "AgentNotFoundError";
50
+ }
51
+ };
52
+ NotConnectedError = class extends OwneyError {
53
+ constructor() {
54
+ super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
55
+ this.name = "NotConnectedError";
56
+ }
57
+ };
58
+ AgentChainIncompatibleError = class extends OwneyError {
59
+ incompatibleAgents;
60
+ connectedChainId;
61
+ constructor(incompatibleAgents, connectedChainId) {
62
+ const details = incompatibleAgents.map(
63
+ ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
64
+ ).join("; ");
65
+ super(
66
+ "AGENT_CHAIN_INCOMPATIBLE",
67
+ `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
68
+ { incompatibleAgents, connectedChainId }
69
+ );
70
+ this.name = "AgentChainIncompatibleError";
71
+ this.incompatibleAgents = incompatibleAgents;
72
+ this.connectedChainId = connectedChainId;
73
+ }
74
+ };
75
+ }
76
+ });
77
+
78
+ // src/agents/surfliquid/surfliquid.constants.ts
79
+ var SURFLIQUID_CHAIN_ID, SURFLIQUID_CHAIN_NAME, SURFLIQUID_USDC_ADDRESS, SURFLIQUID_USDC_DECIMALS, SURFLIQUID_MIN_DEPOSIT, SURFLIQUID_SUPPORTED_ASSETS, SURFLIQUID_ACTION_MAP;
80
+ var init_surfliquid_constants = __esm({
81
+ "src/agents/surfliquid/surfliquid.constants.ts"() {
82
+ "use strict";
83
+ SURFLIQUID_CHAIN_ID = 8453;
84
+ SURFLIQUID_CHAIN_NAME = "BASE";
85
+ SURFLIQUID_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
86
+ SURFLIQUID_USDC_DECIMALS = 6;
87
+ SURFLIQUID_MIN_DEPOSIT = "0";
88
+ SURFLIQUID_SUPPORTED_ASSETS = [
89
+ {
90
+ chainId: SURFLIQUID_CHAIN_ID,
91
+ chain: SURFLIQUID_CHAIN_NAME,
92
+ assets: [{ symbol: "USDC", minDepositAmount: SURFLIQUID_MIN_DEPOSIT }]
93
+ }
94
+ ];
95
+ SURFLIQUID_ACTION_MAP = {
96
+ // INITIAL_DEPOSIT is the user's real first deposit, so surface it like any
97
+ // other funding ("Top up"). The mini-app intentionally hides the "Deposit"
98
+ // action (it marks Zyfai's smart-account-creation event), which would
99
+ // otherwise drop a SurfLiquid user's only history row.
100
+ INITIAL_DEPOSIT: "Top up",
101
+ DEPOSIT: "Top up",
102
+ USER_DEPOSIT: "Top up",
103
+ WITHDRAWAL: "Withdraw",
104
+ USER_WITHDRAWAL: "Withdraw",
105
+ REBALANCE: "Rebalance",
106
+ REBALANCE_COMPLETED: "Rebalance",
107
+ CROSS_CHAIN_REBALANCE: "Rebalance",
108
+ MERKL_CLAIM: "Earned"
109
+ };
110
+ }
111
+ });
112
+
113
+ // src/agents/surfliquid/surfliquid.mapper.ts
114
+ function mapMessage(message) {
115
+ const action = SURFLIQUID_ACTION_MAP[message.transactionType];
116
+ if (!action)
117
+ return null;
118
+ return {
119
+ agent: "surfliquid",
120
+ action,
121
+ date: message.timestamp,
122
+ oldApy: message.apyBefore != null ? String(message.apyBefore) : null,
123
+ newApy: message.apyAfter != null ? String(message.apyAfter) : null,
124
+ transactions: [
125
+ {
126
+ txHashes: [message.txHash],
127
+ chainId: message.chainId,
128
+ tokenSymbol: message.token ?? void 0,
129
+ amount: message.amount != null ? String(message.amount) : void 0
130
+ }
131
+ ],
132
+ rebalanceLog: []
133
+ };
134
+ }
135
+ function mapHistory(result, _chainId) {
136
+ const data = result.messages.map(mapMessage).filter((entry) => entry !== null);
137
+ const hasMore = result.page < result.pages;
138
+ return {
139
+ data,
140
+ hasMore,
141
+ nextCursor: hasMore ? String(result.page + 1) : void 0
142
+ };
143
+ }
144
+ function mapBalances2(vault, chainId, morphoStats) {
145
+ const assets = (vault.assets ?? []).filter(
146
+ (asset) => asset.assetSymbol === "USDC" && asset.chainId === chainId
147
+ );
148
+ const tokens = assets.map((asset) => ({
149
+ chain: SURFLIQUID_CHAIN_NAME,
150
+ chainId: SURFLIQUID_CHAIN_ID,
151
+ asset: "USDC",
152
+ amount: String(asset.currentValueUSD)
153
+ }));
154
+ const positions = assets.map((asset) => {
155
+ const stats = morphoStats?.get(asset.morphoVaultAddress?.toLowerCase() ?? "");
156
+ return {
157
+ chain: SURFLIQUID_CHAIN_NAME,
158
+ protocol: "Morpho",
159
+ // The specific MetaMorpho vault (e.g. "Gauntlet USDC Frontier"), read from
160
+ // Morpho — renders as "Morpho <vault>" alongside zyfai's vault detail.
161
+ pool: stats?.name ?? void 0,
162
+ asset: "USDC",
163
+ amount: String(asset.currentValueUSD),
164
+ apy: asset.currentAPY,
165
+ // TVL + liquidity come straight from Morpho (SurfLiquid's API omits them).
166
+ tvl: stats?.tvlUsd,
167
+ liquidity: stats?.liquidityUsd
168
+ };
169
+ });
170
+ const total = assets.reduce(
171
+ (sum, asset) => sum + asset.currentValueUSD,
172
+ 0
173
+ );
174
+ return {
175
+ smartWallet: vault.userVaultAddress ?? void 0,
176
+ totalBalance: String(total),
177
+ totalBalanceAsset: "usdc",
178
+ tokens,
179
+ positions
180
+ };
181
+ }
182
+ function mapAccountApy(vault, days) {
183
+ const breakdown = vault.apyBreakdown;
184
+ const windowed = breakdown ? breakdown[APY_WINDOW_KEY[days]] : void 0;
185
+ const apy = windowed != null ? windowed : breakdown?.currentAPY ?? 0;
186
+ return {
187
+ walletAddress: vault.walletAddress ?? "",
188
+ weightedApyAfterFee: apy,
189
+ apyByChainAndAsset: { [SURFLIQUID_CHAIN_ID]: { USDC: apy } },
190
+ // Parity with Sail: SurfLiquid's core-sdk exposes no daily net-APY series.
191
+ history: []
192
+ };
193
+ }
194
+ function mapEarnings2(vault, vaultAddress) {
195
+ return {
196
+ smartWallet: vaultAddress,
197
+ lifetimeEarnings: vault.earned?.totalEarningsUSD ?? 0,
198
+ tokens: []
199
+ };
200
+ }
201
+ function mapUserProfile2(vault, address) {
202
+ return {
203
+ address,
204
+ smartWallet: vault.userVaultAddress ?? "",
205
+ chains: [SURFLIQUID_CHAIN_ID],
206
+ // SurfLiquid uses cookie-based session auth — no session-key concept.
207
+ hasActiveSessionKey: false,
208
+ protocols: ["SurfLiquid"]
209
+ };
210
+ }
211
+ var APY_WINDOW_KEY;
212
+ var init_surfliquid_mapper = __esm({
213
+ "src/agents/surfliquid/surfliquid.mapper.ts"() {
214
+ "use strict";
215
+ init_surfliquid_constants();
216
+ APY_WINDOW_KEY = {
217
+ "7D": "apy7d",
218
+ "14D": "apy14d",
219
+ "30D": "apy30d"
220
+ };
221
+ }
222
+ });
223
+
224
+ // src/agents/surfliquid/surfliquid.wallet-adapter.ts
225
+ var import_core_sdk, OwneyWalletAdapter;
226
+ var init_surfliquid_wallet_adapter = __esm({
227
+ "src/agents/surfliquid/surfliquid.wallet-adapter.ts"() {
228
+ "use strict";
229
+ import_core_sdk = require("@surf_liquid/core-sdk");
230
+ OwneyWalletAdapter = class extends import_core_sdk.BaseWalletAdapter {
231
+ constructor(eip1193Provider) {
232
+ super();
233
+ this.eip1193Provider = eip1193Provider;
234
+ }
235
+ name = "owney";
236
+ get installed() {
237
+ return true;
238
+ }
239
+ resolveProvider() {
240
+ return this.eip1193Provider;
241
+ }
242
+ };
243
+ }
244
+ });
245
+
246
+ // src/agents/surfliquid/surfliquid.morpho.ts
247
+ async function fetchMorphoVaultStats(vaultAddress, chainId) {
248
+ try {
249
+ const res = await fetch(MORPHO_API_URL, {
250
+ method: "POST",
251
+ headers: { "Content-Type": "application/json" },
252
+ body: JSON.stringify({
253
+ query: VAULT_STATS_QUERY,
254
+ variables: { address: vaultAddress, chainId }
255
+ })
256
+ });
257
+ if (!res.ok)
258
+ return null;
259
+ const json = await res.json();
260
+ if (json.errors)
261
+ return null;
262
+ const vault = json.data?.vaultByAddress;
263
+ const tvlUsd = vault?.state?.totalAssetsUsd;
264
+ const liquidityUsd = vault?.liquidity?.usd;
265
+ if (typeof tvlUsd !== "number" || typeof liquidityUsd !== "number") {
266
+ return null;
267
+ }
268
+ const name = typeof vault?.name === "string" ? vault.name : null;
269
+ return { name, tvlUsd, liquidityUsd };
270
+ } catch (error) {
271
+ console.warn("surfliquid: Morpho vault stats fetch failed", {
272
+ vaultAddress,
273
+ chainId,
274
+ error
275
+ });
276
+ return null;
277
+ }
278
+ }
279
+ async function fetchMorphoStatsByVault(vaultAddresses, chainId) {
280
+ const unique = [...new Set(vaultAddresses.map((a) => a.toLowerCase()))];
281
+ const entries = await Promise.all(
282
+ unique.map(
283
+ async (address) => [address, await fetchMorphoVaultStats(address, chainId)]
284
+ )
285
+ );
286
+ const byVault = /* @__PURE__ */ new Map();
287
+ for (const [address, stats] of entries) {
288
+ if (stats)
289
+ byVault.set(address, stats);
290
+ }
291
+ return byVault;
292
+ }
293
+ var MORPHO_API_URL, VAULT_STATS_QUERY;
294
+ var init_surfliquid_morpho = __esm({
295
+ "src/agents/surfliquid/surfliquid.morpho.ts"() {
296
+ "use strict";
297
+ MORPHO_API_URL = "https://api.morpho.org/graphql";
298
+ VAULT_STATS_QUERY = `
299
+ query VaultStats($address: String!, $chainId: Int!) {
300
+ vaultByAddress(address: $address, chainId: $chainId) {
301
+ name
302
+ state { totalAssetsUsd }
303
+ liquidity { usd }
304
+ }
305
+ }
306
+ `;
307
+ }
308
+ });
309
+
310
+ // src/agents/surfliquid/surfliquid.agent.ts
311
+ var surfliquid_agent_exports = {};
312
+ __export(surfliquid_agent_exports, {
313
+ SurfLiquidAgent: () => SurfLiquidAgent
314
+ });
315
+ var import_core_sdk2, import_viem4, APY_WINDOW_KEY2, SurfLiquidAgent;
316
+ var init_surfliquid_agent = __esm({
317
+ "src/agents/surfliquid/surfliquid.agent.ts"() {
318
+ "use strict";
319
+ import_core_sdk2 = require("@surf_liquid/core-sdk");
320
+ import_viem4 = require("viem");
321
+ init_errors();
322
+ init_surfliquid_constants();
323
+ init_surfliquid_mapper();
324
+ init_surfliquid_wallet_adapter();
325
+ init_surfliquid_morpho();
326
+ APY_WINDOW_KEY2 = {
327
+ "7D": "apy7d",
328
+ "14D": "apy14d",
329
+ "30D": "apy30d"
330
+ };
331
+ SurfLiquidAgent = class {
332
+ constructor(config) {
333
+ this.config = config;
334
+ }
335
+ id = "surfliquid";
336
+ supportedChainIds = [SURFLIQUID_CHAIN_ID];
337
+ supportedAssets = SURFLIQUID_SUPPORTED_ASSETS;
338
+ surf = null;
339
+ connectedAddress = null;
340
+ // In-flight connect+auth, shared by concurrent callers to dedupe SIWE.
341
+ connectPromise = null;
342
+ ensureSurf() {
343
+ if (this.surf)
344
+ return this.surf;
345
+ this.surf = import_core_sdk2.SurfClient.create({
346
+ projectName: this.config.projectName,
347
+ appId: this.config.appId,
348
+ environment: "mainnet",
349
+ chainId: SURFLIQUID_CHAIN_ID,
350
+ apiBaseUrl: this.config.apiBaseUrl,
351
+ rpcUrl: this.config.rpcUrl,
352
+ // Let the SDK auto-approve USDC to the vault before depositing.
353
+ autoApprove: true
354
+ });
355
+ return this.surf;
356
+ }
357
+ /**
358
+ * Connects + authenticates the SurfClient against owney's provider. Skips the
359
+ * SIWE prompt when already authenticated for this wallet (cookie session).
360
+ */
361
+ async connect(state) {
362
+ const surf = this.ensureSurf();
363
+ const sameWallet = this.connectedAddress?.toLowerCase() === state.walletAddress.toLowerCase();
364
+ if (sameWallet && surf.getAuthState().authenticated) {
365
+ return surf;
366
+ }
367
+ if (this.connectPromise)
368
+ return this.connectPromise;
369
+ this.connectPromise = (async () => {
370
+ surf.registerWalletAdapter(
371
+ "owney",
372
+ new OwneyWalletAdapter(state.provider)
373
+ );
374
+ await surf.connectWallet("owney");
375
+ await surf.authenticate();
376
+ this.connectedAddress = state.walletAddress;
377
+ return surf;
378
+ })();
379
+ try {
380
+ return await this.connectPromise;
381
+ } finally {
382
+ this.connectPromise = null;
383
+ }
384
+ }
385
+ /**
386
+ * Returns the user's vault address, deploying one on first use. SurfLiquid's
387
+ * deposit requires the vault to exist, so this must run before depositing.
388
+ * Existing vault → returned as-is; otherwise `deployVault()` is sent
389
+ * (user-pays) and the freshly deployed address is returned.
390
+ */
391
+ async resolveVaultAddress(surf, owner) {
392
+ const vault = await surf.getVault(owner).catch(() => null);
393
+ if (vault?.exists && vault.userVaultAddress) {
394
+ return vault.userVaultAddress;
395
+ }
396
+ const { vaultAddress } = await surf.deployVault();
397
+ return vaultAddress;
398
+ }
399
+ // --- IAgent: lifecycle ---
400
+ async disconnect() {
401
+ if (this.surf) {
402
+ await this.surf.disconnectWallet();
403
+ }
404
+ this.connectedAddress = null;
405
+ }
406
+ async activateAgent(state) {
407
+ await this.connect(state);
408
+ }
409
+ // --- IAgent: funds (user-pays; depositCallback intentionally ignored) ---
410
+ async deposit(state, _chainId, amount, _depositCallback) {
411
+ const surf = await this.connect(state);
412
+ const human = (0, import_viem4.formatUnits)(BigInt(amount), SURFLIQUID_USDC_DECIMALS);
413
+ const smartWallet = await this.resolveVaultAddress(
414
+ surf,
415
+ state.walletAddress
416
+ );
417
+ const tx = await surf.deposit({
418
+ asset: SURFLIQUID_USDC_ADDRESS,
419
+ amount: human
420
+ });
421
+ await tx.wait();
422
+ return { txHash: tx.hash, smartWallet, amount };
423
+ }
424
+ async withdraw(state, _chainId, _token, amount) {
425
+ const surf = await this.connect(state);
426
+ const human = amount != null ? (0, import_viem4.formatUnits)(BigInt(amount), SURFLIQUID_USDC_DECIMALS) : void 0;
427
+ try {
428
+ const tx = await surf.withdraw({
429
+ asset: SURFLIQUID_USDC_ADDRESS,
430
+ amount: human
431
+ });
432
+ await tx.wait();
433
+ return {
434
+ txHash: tx.hash,
435
+ type: amount != null ? "partial" : "full",
436
+ amount: amount ?? "0"
437
+ };
438
+ } catch (error) {
439
+ throw new OwneyError(
440
+ "WITHDRAW_FAILED",
441
+ error instanceof Error ? error.message : "SurfLiquid withdraw failed.",
442
+ { chainId: SURFLIQUID_CHAIN_ID, amount },
443
+ this.id
444
+ );
445
+ }
446
+ }
447
+ // --- IAgent: portfolio reads ---
448
+ async getBalances(state, chainId) {
449
+ const surf = await this.connect(state);
450
+ const vault = await surf.getVault(state.walletAddress);
451
+ const morphoVaultAddresses = (vault.assets ?? []).filter((asset) => asset.assetSymbol === "USDC" && asset.chainId === chainId).map((asset) => asset.morphoVaultAddress).filter((address) => Boolean(address));
452
+ const morphoStats = await fetchMorphoStatsByVault(
453
+ morphoVaultAddresses,
454
+ chainId
455
+ );
456
+ return mapBalances2(vault, chainId, morphoStats);
457
+ }
458
+ async getEarnings(state) {
459
+ const surf = await this.connect(state);
460
+ const vault = await surf.getVault(state.walletAddress);
461
+ return mapEarnings2(vault, vault.userVaultAddress ?? state.walletAddress);
462
+ }
463
+ async getAccountApy(state, _chainId, days) {
464
+ const surf = await this.connect(state);
465
+ const vault = await surf.getVault(state.walletAddress);
466
+ return mapAccountApy(vault, days);
467
+ }
468
+ async getHistory(state, chainId, options) {
469
+ const surf = await this.connect(state);
470
+ const page = options?.cursor ? Number(options.cursor) : 1;
471
+ const limit = options?.limit ?? 10;
472
+ const result = await surf.getAgentMessages(
473
+ state.walletAddress,
474
+ page,
475
+ limit,
476
+ options?.fromDate,
477
+ options?.toDate
478
+ );
479
+ return mapHistory(result, chainId);
480
+ }
481
+ async getUserProfile(state) {
482
+ const surf = await this.connect(state);
483
+ const vault = await surf.getVault(state.walletAddress);
484
+ return mapUserProfile2(vault, state.walletAddress);
485
+ }
486
+ // --- IAgent: discovery (no wallet) ---
487
+ async getAgentApy(days, _options) {
488
+ const surf = this.ensureSurf();
489
+ const assets = await surf.getSupportedAssets(SURFLIQUID_CHAIN_ID);
490
+ const usdc = assets.find((asset) => asset.assetSymbol === "USDC");
491
+ if (!usdc)
492
+ return { averageApy: 0 };
493
+ const windowed = usdc[APY_WINDOW_KEY2[days]];
494
+ return { averageApy: windowed != null ? windowed : usdc.currentAPY };
495
+ }
496
+ };
497
+ }
498
+ });
499
+
20
500
  // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
501
+ var src_exports = {};
502
+ __export(src_exports, {
23
503
  AgentChainIncompatibleError: () => AgentChainIncompatibleError,
24
504
  AgentNotFoundError: () => AgentNotFoundError,
25
505
  InvalidHistoryCursorError: () => InvalidHistoryCursorError,
@@ -28,7 +508,7 @@ __export(index_exports, {
28
508
  OwneySDK: () => OwneySDK,
29
509
  createOwneySIWX: () => createOwneySIWX
30
510
  });
31
- module.exports = __toCommonJS(index_exports);
511
+ module.exports = __toCommonJS(src_exports);
32
512
 
33
513
  // src/agents/zyfai/zyfai.agent.ts
34
514
  var import_sdk = require("@zyfai/sdk");
@@ -37,10 +517,10 @@ var import_chains = require("viem/chains");
37
517
 
38
518
  // src/types/config.ts
39
519
  var P_SUPPORTED_CHAINS = {
40
- chainIds: [8453, 42161, 1],
41
- chains: ["BASE", "ARBITRUM", "ETHEREUM"]
520
+ chainIds: [8453, 42161],
521
+ chains: ["BASE", "ARBITRUM"]
42
522
  };
43
- var SUPPORTED_TOKENS = ["USDC", "USDT", "WETH"];
523
+ var SUPPORTED_TOKENS = ["USDC", "USDT"];
44
524
  var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
45
525
  var SUPPORTED_CHAINS = P_SUPPORTED_CHAINS.chains;
46
526
  var SupportedAssets = [
@@ -61,83 +541,11 @@ var SupportedAssets = [
61
541
  symbol: "USDT",
62
542
  chainId: 42161,
63
543
  decimals: 6
64
- },
65
- {
66
- address: `0x4200000000000000000000000000000000000006`,
67
- symbol: "WETH",
68
- chainId: 8453,
69
- decimals: 18
70
- },
71
- {
72
- address: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`,
73
- symbol: "WETH",
74
- chainId: 42161,
75
- decimals: 18
76
- },
77
- {
78
- address: `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`,
79
- symbol: "USDC",
80
- chainId: 1,
81
- decimals: 6
82
- },
83
- {
84
- address: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`,
85
- symbol: "WETH",
86
- chainId: 1,
87
- decimals: 18
88
544
  }
89
545
  ];
90
546
 
91
- // src/errors.ts
92
- var OwneyError = class extends Error {
93
- code;
94
- details;
95
- agentId;
96
- constructor(code, message, details, agentId) {
97
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
98
- super(`${prefix} ${message}`);
99
- this.name = "OwneyError";
100
- this.code = code;
101
- this.details = details;
102
- this.agentId = agentId;
103
- }
104
- };
105
- var AgentNotFoundError = class extends OwneyError {
106
- constructor(agentId, available) {
107
- super(
108
- "AGENT_NOT_FOUND",
109
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
110
- { agentId, available },
111
- agentId
112
- );
113
- this.name = "AgentNotFoundError";
114
- }
115
- };
116
- var NotConnectedError = class extends OwneyError {
117
- constructor() {
118
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
119
- this.name = "NotConnectedError";
120
- }
121
- };
122
- var AgentChainIncompatibleError = class extends OwneyError {
123
- incompatibleAgents;
124
- connectedChainId;
125
- constructor(incompatibleAgents, connectedChainId) {
126
- const details = incompatibleAgents.map(
127
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
128
- ).join("; ");
129
- super(
130
- "AGENT_CHAIN_INCOMPATIBLE",
131
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
132
- { incompatibleAgents, connectedChainId }
133
- );
134
- this.name = "AgentChainIncompatibleError";
135
- this.incompatibleAgents = incompatibleAgents;
136
- this.connectedChainId = connectedChainId;
137
- }
138
- };
139
-
140
547
  // src/lib/utils.ts
548
+ init_errors();
141
549
  var isValidChainId = (chainId) => {
142
550
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
143
551
  throw new OwneyError(
@@ -151,7 +559,8 @@ var isValidChainId = (chainId) => {
151
559
  function hexToDecimal(hex, decimals = 6) {
152
560
  const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
153
561
  const parsed = BigInt(normalized);
154
- if (decimals <= 0) return Number(parsed);
562
+ if (decimals <= 0)
563
+ return Number(parsed);
155
564
  const divisor = BigInt(10 ** decimals);
156
565
  const whole = parsed / divisor;
157
566
  const remainder = parsed % divisor;
@@ -164,20 +573,6 @@ var DayFilterMapping = {
164
573
  };
165
574
 
166
575
  // src/agents/zyfai/zyfai.mapper.ts
167
- var DECIMALS_BY_SYMBOL = {
168
- usdc: 6,
169
- usdt: 6,
170
- weth: 18,
171
- eth: 18,
172
- cbeth: 18,
173
- wbtc: 8,
174
- cbbtc: 8
175
- };
176
- function tokenDecimals(symbol, explicit) {
177
- if (typeof explicit === "number" && Number.isFinite(explicit))
178
- return explicit;
179
- return DECIMALS_BY_SYMBOL[(symbol ?? "").toLowerCase()] ?? 6;
180
- }
181
576
  function mapDeposit(raw) {
182
577
  return {
183
578
  txHash: raw.txHash,
@@ -194,8 +589,7 @@ function mapWithdraw(raw) {
194
589
  }
195
590
  var CHAIN_ID_TO_NAME = {
196
591
  8453: "BASE",
197
- 42161: "ARBITRUM",
198
- 1: "ETHEREUM"
592
+ 42161: "ARBITRUM"
199
593
  };
200
594
  var NAME_TO_CHAIN_ID = Object.entries(
201
595
  CHAIN_ID_TO_NAME
@@ -205,52 +599,54 @@ var NAME_TO_CHAIN_ID = Object.entries(
205
599
  }, {});
206
600
  function resolveChainId(chain) {
207
601
  const asNum = Number(chain);
208
- if (Number.isFinite(asNum) && asNum > 0) return asNum;
602
+ if (Number.isFinite(asNum) && asNum > 0)
603
+ return asNum;
209
604
  return NAME_TO_CHAIN_ID[chain.trim().toLowerCase()] ?? NaN;
210
605
  }
211
606
  function mapBalances(raw, _chainId, smartWallet) {
212
607
  const portfolio = raw.portfolio;
213
608
  const portfolioByChain = portfolio.portfolioByChain ?? {};
609
+ const rawPositions = portfolio.positions ?? [];
610
+ const detailByKey = /* @__PURE__ */ new Map();
611
+ for (const p of rawPositions) {
612
+ const cid = resolveChainId(p.chain ?? "");
613
+ const symbol = (p.token_symbol ?? "").toUpperCase();
614
+ if (Number.isFinite(cid) && symbol)
615
+ detailByKey.set(`${cid}:${symbol}`, p);
616
+ }
214
617
  let totalBalance = 0;
215
618
  const tokens = [];
619
+ const positions = [];
216
620
  for (const [chainIdKey, tokensBySymbol] of Object.entries(portfolioByChain)) {
217
621
  const positionChainId = Number(chainIdKey);
622
+ const chainName = CHAIN_ID_TO_NAME[positionChainId] ?? "BASE";
218
623
  for (const [symbol, { balance, decimals }] of Object.entries(
219
624
  tokensBySymbol ?? {}
220
625
  )) {
221
626
  const amount = hexToDecimal(balance || "0", decimals);
222
627
  totalBalance += amount;
223
628
  tokens.push({
224
- chain: CHAIN_ID_TO_NAME[positionChainId] ?? "BASE",
629
+ chain: chainName,
225
630
  chainId: positionChainId,
226
631
  asset: symbol,
227
632
  amount: String(amount)
228
633
  });
634
+ const detail = detailByKey.get(`${positionChainId}:${symbol.toUpperCase()}`);
635
+ positions.push({
636
+ chain: chainName,
637
+ protocol: detail?.protocol_name ?? detail?.protocol_id ?? "",
638
+ protocolId: detail?.protocol_id,
639
+ pool: detail?.pool,
640
+ asset: symbol,
641
+ amount: String(amount),
642
+ apy: detail?.pool_apy,
643
+ tvl: detail?.pool_tvl,
644
+ // PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
645
+ // structural read keeps it undefined today and auto-populates later.
646
+ liquidity: detail?.liquidity
647
+ });
229
648
  }
230
649
  }
231
- const positions = (portfolio.positions ?? []).map((p) => ({
232
- chain: p.chain ?? "",
233
- protocol: p.protocol_name ?? p.protocol_id ?? "",
234
- protocolId: p.protocol_id,
235
- pool: p.pool,
236
- asset: p.token_symbol ?? "",
237
- // Position amount is hex-encoded base units (like the token balances
238
- // above). `PositionSlot` doesn't type a `decimals` field, but runtime
239
- // getBalances payloads often carry one (e.g. 18 for WETH) — prefer that
240
- // when present, otherwise fall back to the per-symbol lookup so
241
- // non-6-decimal assets like WETH don't render 1e12 too large.
242
- amount: String(
243
- hexToDecimal(
244
- p.amount || "0",
245
- tokenDecimals(p.token_symbol, p.decimals)
246
- )
247
- ),
248
- apy: p.pool_apy,
249
- tvl: p.pool_tvl,
250
- // PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
251
- // structural read keeps it undefined today and auto-populates later.
252
- liquidity: p.liquidity
253
- }));
254
650
  return {
255
651
  smartWallet,
256
652
  totalBalance: String(totalBalance),
@@ -289,39 +685,41 @@ function mapEarnings(raw, smartWallet) {
289
685
  };
290
686
  }
291
687
  function mapWeightedApyByChain(raw) {
292
- if (!raw) return void 0;
688
+ if (!raw)
689
+ return void 0;
293
690
  const out = {};
294
691
  for (const [chainKey, tokenApy] of Object.entries(raw)) {
295
692
  const chainId = Number(chainKey);
296
- if (!SUPPORTED_CHAIN_IDS.includes(chainId)) continue;
693
+ if (!SUPPORTED_CHAIN_IDS.includes(chainId))
694
+ continue;
297
695
  const perAsset = {};
298
696
  for (const [symbol, apy] of Object.entries(tokenApy)) {
299
697
  const token = symbol;
300
- if (!SUPPORTED_TOKENS.includes(token)) continue;
698
+ if (!SUPPORTED_TOKENS.includes(token))
699
+ continue;
301
700
  perAsset[token] = apy;
302
701
  }
303
- if (Object.keys(perAsset).length > 0) out[chainId] = perAsset;
702
+ if (Object.keys(perAsset).length > 0)
703
+ out[chainId] = perAsset;
304
704
  }
305
705
  return Object.keys(out).length > 0 ? out : void 0;
306
706
  }
307
- function rawPoolApyForChain(entry, chainId, tokenSymbol) {
707
+ function rawPoolApyForChain(entry, chainId) {
308
708
  let weightedSum = 0;
309
709
  let totalBalance = 0;
310
710
  for (const p of entry.positions ?? []) {
311
- if (p.chainId !== chainId) continue;
312
- if (tokenSymbol && p.tokenSymbol !== tokenSymbol) continue;
711
+ if (p.chainId !== chainId)
712
+ continue;
313
713
  const balance = p.balance ?? 0;
314
- if (balance <= 0 || typeof p.apy !== "number") continue;
714
+ if (balance <= 0 || typeof p.apy !== "number")
715
+ continue;
315
716
  weightedSum += p.apy * balance;
316
717
  totalBalance += balance;
317
718
  }
318
719
  return totalBalance > 0 ? weightedSum / totalBalance : null;
319
720
  }
320
- function mapApyHistory(raw, chainId, tokenSymbol) {
321
- const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({
322
- date,
323
- apy: rawPoolApyForChain(entry, chainId, tokenSymbol)
324
- })).filter((p) => p.apy !== null).sort((a, b) => a.date.localeCompare(b.date));
721
+ function mapApyHistory(raw, chainId) {
722
+ const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({ date, apy: rawPoolApyForChain(entry, chainId) })).filter((p) => p.apy !== null).sort((a, b) => a.date.localeCompare(b.date));
325
723
  return {
326
724
  walletAddress: raw.walletAddress,
327
725
  weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0,
@@ -344,7 +742,6 @@ function mapEntries(rawEntries, chainId) {
344
742
  "Withdraw from protocol": "Withdraw",
345
743
  Rebalance: "Rebalance"
346
744
  };
347
- void chainId;
348
745
  return rawEntries.map((entry) => {
349
746
  const rawLog = entry.rebalanceLog;
350
747
  const positions = entry.positions ?? [];
@@ -366,15 +763,7 @@ function mapEntries(rawEntries, chainId) {
366
763
  fromPool: from.pool,
367
764
  toPool: to.pool,
368
765
  tokenSymbol: matched?.token_symbol ?? "",
369
- amount: matched ? String(
370
- hexToDecimal(
371
- matched.amount || "0x",
372
- tokenDecimals(
373
- matched.token_symbol,
374
- matched.decimals
375
- )
376
- )
377
- ) : "",
766
+ amount: matched ? String(hexToDecimal(matched.amount || "0x")) : "",
378
767
  status: "success"
379
768
  }
380
769
  ];
@@ -393,12 +782,7 @@ function mapEntries(rawEntries, chainId) {
393
782
  txHashes: entry.transactionHash ? [entry.transactionHash] : [],
394
783
  chainId: entry.chainId,
395
784
  tokenSymbol: entry?.positions?.[0]?.token_symbol,
396
- amount: hasAmount ? String(
397
- hexToDecimal(
398
- rawAmount,
399
- tokenDecimals(entry?.positions?.[0]?.token_symbol)
400
- )
401
- ) : void 0
785
+ amount: hasAmount ? String(hexToDecimal(rawAmount)) : void 0
402
786
  }
403
787
  ],
404
788
  rebalanceLog
@@ -423,7 +807,8 @@ function mapApyByStrategy(raw) {
423
807
  const supported = SupportedAssets.find(
424
808
  (asset) => asset.chainId === entry.chain_id && asset.symbol === entry.token_symbol
425
809
  );
426
- if (!supported) continue;
810
+ if (!supported)
811
+ continue;
427
812
  const chainKey = supported.chainId;
428
813
  const symbolKey = supported.symbol;
429
814
  const bucket = apyPerAsset[chainKey] ?? {};
@@ -453,8 +838,10 @@ function computeAllocationApy(positions) {
453
838
  totalValue += value;
454
839
  const chainId = resolveChainId(p.chain);
455
840
  const token = p.asset;
456
- if (!SUPPORTED_CHAIN_IDS.includes(chainId)) continue;
457
- if (!SUPPORTED_TOKENS.includes(token)) continue;
841
+ if (!SUPPORTED_CHAIN_IDS.includes(chainId))
842
+ continue;
843
+ if (!SUPPORTED_TOKENS.includes(token))
844
+ continue;
458
845
  const perAsset = buckets[chainId] ?? {};
459
846
  const cell = perAsset[token] ?? { weightedSum: 0, value: 0 };
460
847
  cell.weightedSum += apy * value;
@@ -471,7 +858,8 @@ function computeAllocationApy(positions) {
471
858
  out[token] = cell.weightedSum / cell.value;
472
859
  }
473
860
  }
474
- if (Object.keys(out).length > 0) apyByChainAndAsset[chainId] = out;
861
+ if (Object.keys(out).length > 0)
862
+ apyByChainAndAsset[chainId] = out;
475
863
  }
476
864
  const totalApy = totalValue > 0 ? String(weightedSum / totalValue) : "0";
477
865
  return { totalApy, apyByChainAndAsset };
@@ -488,14 +876,19 @@ function extractWithdrawnAmount(logs, recipient, token, decimals) {
488
876
  let total = 0n;
489
877
  let matched = false;
490
878
  for (const log of logs) {
491
- if (log.address.toLowerCase() !== wantToken) continue;
492
- if ((log.topics[0] ?? "").toLowerCase() !== TRANSFER_TOPIC) continue;
493
- if (topicToAddress(log.topics[2]) !== wantRecipient) continue;
494
- if (!log.data || log.data === "0x") continue;
879
+ if (log.address.toLowerCase() !== wantToken)
880
+ continue;
881
+ if ((log.topics[0] ?? "").toLowerCase() !== TRANSFER_TOPIC)
882
+ continue;
883
+ if (topicToAddress(log.topics[2]) !== wantRecipient)
884
+ continue;
885
+ if (!log.data || log.data === "0x")
886
+ continue;
495
887
  total += BigInt(log.data);
496
888
  matched = true;
497
889
  }
498
- if (!matched) return void 0;
890
+ if (!matched)
891
+ return void 0;
499
892
  return String(hexToDecimal(`0x${total.toString(16)}`, decimals));
500
893
  }
501
894
 
@@ -511,7 +904,8 @@ function encodeHistoryCursor(payload) {
511
904
  return Buffer.from(JSON.stringify(payload), "utf8").toString("base64");
512
905
  }
513
906
  function decodeHistoryCursor(token) {
514
- if (!token) throw new InvalidHistoryCursorError("Cursor is empty.");
907
+ if (!token)
908
+ throw new InvalidHistoryCursorError("Cursor is empty.");
515
909
  let parsed;
516
910
  try {
517
911
  const json = Buffer.from(token, "base64").toString("utf8");
@@ -525,10 +919,14 @@ function decodeHistoryCursor(token) {
525
919
  return parsed;
526
920
  }
527
921
 
922
+ // src/agents/zyfai/zyfai.agent.ts
923
+ init_errors();
924
+
528
925
  // src/agents/zyfai/zyfai.auth-cache.ts
529
926
  var KEY_PREFIX = "owney.zyfai.session";
530
927
  var storage = () => {
531
- if (typeof window === "undefined") return null;
928
+ if (typeof window === "undefined")
929
+ return null;
532
930
  try {
533
931
  return window.localStorage;
534
932
  } catch {
@@ -538,13 +936,15 @@ var storage = () => {
538
936
  var buildKey = (address, chainId) => `${KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
539
937
  var isJwtExpired = (token) => {
540
938
  const parts = token.split(".");
541
- if (parts.length !== 3) return false;
939
+ if (parts.length !== 3)
940
+ return false;
542
941
  try {
543
942
  const payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
544
943
  const padded = payload + "=".repeat((4 - payload.length % 4) % 4);
545
944
  const decoded = typeof atob === "function" ? atob(padded) : Buffer.from(padded, "base64").toString("utf8");
546
945
  const claims = JSON.parse(decoded);
547
- if (typeof claims.exp !== "number") return false;
946
+ if (typeof claims.exp !== "number")
947
+ return false;
548
948
  return Date.now() / 1e3 >= claims.exp - 30;
549
949
  } catch {
550
950
  return false;
@@ -552,9 +952,11 @@ var isJwtExpired = (token) => {
552
952
  };
553
953
  var readSession = (address, chainId) => {
554
954
  const store = storage();
555
- if (!store) return null;
955
+ if (!store)
956
+ return null;
556
957
  const raw = store.getItem(buildKey(address, chainId));
557
- if (!raw) return null;
958
+ if (!raw)
959
+ return null;
558
960
  try {
559
961
  const parsed = JSON.parse(raw);
560
962
  if (!parsed.token || isJwtExpired(parsed.token)) {
@@ -569,7 +971,8 @@ var readSession = (address, chainId) => {
569
971
  };
570
972
  var writeSession = (address, chainId, session) => {
571
973
  const store = storage();
572
- if (!store) return;
974
+ if (!store)
975
+ return;
573
976
  try {
574
977
  store.setItem(buildKey(address, chainId), JSON.stringify(session));
575
978
  } catch {
@@ -577,67 +980,33 @@ var writeSession = (address, chainId, session) => {
577
980
  };
578
981
  var clearSession = (address, chainId) => {
579
982
  const store = storage();
580
- if (!store) return;
983
+ if (!store)
984
+ return;
581
985
  try {
582
986
  store.removeItem(buildKey(address, chainId));
583
987
  } catch {
584
988
  }
585
989
  };
586
990
 
587
- // src/agents/zyfai/autoSelect.ts
588
- function buildAutoSelectUpdate(current, asset) {
589
- if (current.autoSelectProtocols === true) return null;
590
- return {
591
- asset,
592
- autoSelectProtocols: true,
593
- ...current.chains ? { chains: current.chains } : {}
594
- };
595
- }
596
-
597
991
  // src/agents/zyfai/zyfai.agent.ts
598
992
  var DEFAULT_ZYFAI_RPC_URLS = {
599
993
  8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
600
- 42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
601
- 1: "https://eth-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
994
+ 42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
602
995
  };
603
- var WETH_ADDRESS_BY_CHAIN = {
604
- 8453: "0x4200000000000000000000000000000000000006",
605
- 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
606
- 1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
607
- };
608
- var VIEM_CHAIN = { 8453: import_chains.base, 42161: import_chains.arbitrum, 1: import_chains.mainnet };
996
+ var VIEM_CHAIN = { 8453: import_chains.base, 42161: import_chains.arbitrum };
609
997
  var ZyfaiAgent = class {
610
998
  id = "zyfai";
611
- supportedChainIds = [8453, 42161, 1];
999
+ supportedChainIds = [8453, 42161];
612
1000
  supportedAssets = [
613
1001
  {
614
1002
  chainId: 8453,
615
1003
  chain: "BASE",
616
- assets: [
617
- { symbol: "USDC", minDepositAmount: "1500000" },
618
- { symbol: "WETH", minDepositAmount: "500000000000000" }
619
- ]
1004
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
620
1005
  },
621
1006
  {
622
1007
  chainId: 42161,
623
1008
  chain: "ARBITRUM",
624
- assets: [
625
- { symbol: "USDC", minDepositAmount: "1500000" },
626
- { symbol: "WETH", minDepositAmount: "500000000000000" }
627
- ]
628
- },
629
- {
630
- chainId: 1,
631
- chain: "ETHEREUM",
632
- // Zyfai enforces per-asset minimum portfolios on Ethereum mainnet, keyed
633
- // by MIN_PORTFOLIO_BALANCE[1] in @zyfai/sdk (mainnet gas only pays off on
634
- // large positions). USDC: 10,000 (10_000 * 1e6). WETH: 5 (5 * 1e18).
635
- // NOTE: the @zyfai/sdk README claims WETH has no minimum — that's stale;
636
- // the shipped code enforces 5 WETH, so match it or deposits reject on-chain.
637
- assets: [
638
- { symbol: "USDC", minDepositAmount: "10000000000" },
639
- { symbol: "WETH", minDepositAmount: "5000000000000000000" }
640
- ]
1009
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
641
1010
  }
642
1011
  ];
643
1012
  sdk;
@@ -661,7 +1030,8 @@ var ZyfaiAgent = class {
661
1030
  }
662
1031
  getPublicClient(chainId) {
663
1032
  const cached = this.publicClients.get(chainId);
664
- if (cached) return cached;
1033
+ if (cached)
1034
+ return cached;
665
1035
  const client = (0, import_viem.createPublicClient)({
666
1036
  chain: VIEM_CHAIN[chainId],
667
1037
  transport: (0, import_viem.http)(this.rpcUrls[chainId])
@@ -671,43 +1041,33 @@ var ZyfaiAgent = class {
671
1041
  }
672
1042
  /**
673
1043
  * Fills in the true withdrawn amount for `Withdraw` entries by decoding the
674
- * on-chain `Transfer` that lands in the user's wallet. The Zyfai history
1044
+ * USDC `Transfer` that lands in the user's wallet on-chain. The Zyfai history
675
1045
  * payload only reports the *remaining* position for a partial withdraw (see
676
1046
  * the note in `mapEntries`), so without this the UI shows the leftover
677
1047
  * balance instead of the amount withdrawn.
678
1048
  *
679
- * The withdrawn asset varies per entry (USDC or WETH), so it's resolved
680
- * from `tx.tokenSymbol` (set by `mapEntries` from the entry's own
681
- * position) rather than assumed to always be USDC. Zyfai sometimes
682
- * denominates WETH as lowercase "eth" — that's normalized to WETH.
683
- * Entries with no symbol (older payload shapes) fall back to USDC to
684
- * preserve prior behavior.
685
- *
686
1049
  * Mutates `entries` in place. Runs all lookups concurrently and is tolerant
687
1050
  * of RPC failures: an entry whose amount can't be resolved keeps
688
1051
  * `amount: undefined`, which consumers render as a hidden/retryable row
689
1052
  * rather than a wrong number.
690
1053
  */
691
1054
  async resolveWithdrawnAmounts(entries, chainId, recipient) {
1055
+ const asset = SupportedAssets.find(
1056
+ (a) => a.chainId === chainId && a.symbol === "USDC"
1057
+ );
1058
+ if (!asset)
1059
+ return;
692
1060
  const withdrawals = entries.filter(
693
1061
  (e) => e.action === "Withdraw" && e.transactions[0]?.txHashes[0]
694
1062
  );
695
- if (withdrawals.length === 0) return;
1063
+ if (withdrawals.length === 0)
1064
+ return;
696
1065
  const client = this.getPublicClient(chainId);
697
1066
  await Promise.all(
698
1067
  withdrawals.map(async (entry) => {
699
1068
  const tx = entry.transactions[0];
700
1069
  const txHash = tx.txHashes[0];
701
- const rawSymbol = tx.tokenSymbol;
702
- const normalizedSymbol = rawSymbol ? rawSymbol.toLowerCase() === "eth" ? "WETH" : rawSymbol.toUpperCase() : "USDC";
703
- const asset = SupportedAssets.find(
704
- (a) => a.chainId === chainId && a.symbol === normalizedSymbol
705
- ) ?? SupportedAssets.find(
706
- (a) => a.chainId === chainId && a.symbol === "USDC"
707
- );
708
- if (!asset) return;
709
- const cacheKey = `${txHash}:${asset.address}`;
710
- const cached = this.withdrawAmountCache.get(cacheKey);
1070
+ const cached = this.withdrawAmountCache.get(txHash);
711
1071
  if (cached !== void 0) {
712
1072
  tx.amount = cached;
713
1073
  return;
@@ -723,7 +1083,7 @@ var ZyfaiAgent = class {
723
1083
  asset.decimals
724
1084
  );
725
1085
  if (amount !== void 0) {
726
- this.withdrawAmountCache.set(cacheKey, amount);
1086
+ this.withdrawAmountCache.set(txHash, amount);
727
1087
  tx.amount = amount;
728
1088
  }
729
1089
  } catch {
@@ -742,11 +1102,13 @@ var ZyfaiAgent = class {
742
1102
  * for some apps and the patch only matters in the browser anyway.
743
1103
  */
744
1104
  installAuthCache() {
745
- if (typeof window === "undefined") return;
1105
+ if (typeof window === "undefined")
1106
+ return;
746
1107
  const internals = this.sdk;
747
1108
  const original = internals.authenticateUser.bind(internals);
748
1109
  internals.authenticateUser = async () => {
749
- if (internals.authenticatedUserId !== null) return;
1110
+ if (internals.authenticatedUserId !== null)
1111
+ return;
750
1112
  const address = internals.walletClient?.account?.address;
751
1113
  const chainId = internals.currentChainId;
752
1114
  if (address && chainId) {
@@ -821,10 +1183,12 @@ var ZyfaiAgent = class {
821
1183
  return await this.sdk.connectAccount(provider, chainId);
822
1184
  } catch (error) {
823
1185
  const message = error instanceof Error ? error.message : String(error);
824
- if (!message.toLowerCase().includes("unauthorized")) throw error;
1186
+ if (!message.toLowerCase().includes("unauthorized"))
1187
+ throw error;
825
1188
  const internals = this.sdk;
826
1189
  const address = internals.walletClient?.account?.address;
827
- if (address) clearSession(address, chainId);
1190
+ if (address)
1191
+ clearSession(address, chainId);
828
1192
  return await this.sdk.connectAccount(provider, chainId);
829
1193
  }
830
1194
  }
@@ -837,22 +1201,6 @@ var ZyfaiAgent = class {
837
1201
  this.smartWalletCache.set(`${address}_${validChainId}`, wallet.address);
838
1202
  if (!wallet.isDeployed) {
839
1203
  await this.sdk.deploySafe(address, validChainId, "aggressive", true);
840
- try {
841
- if (validChainId === 42161) {
842
- await this.sdk.updateUserProfile({
843
- asset: "WETH",
844
- chains: [validChainId],
845
- protocols: ["c24a33fa-4a87-4376-b756-93bd3957d3ea"],
846
- // AAVE protocol ID
847
- autoSelectProtocols: false
848
- });
849
- }
850
- } catch (err) {
851
- console.warn(
852
- "Failed to configure AAVE protocol after Safe deployment:",
853
- err instanceof Error ? err.message : String(err)
854
- );
855
- }
856
1204
  }
857
1205
  const user = await this.sdk.getUserDetails();
858
1206
  if (!user.hasActiveSessionKey) {
@@ -894,7 +1242,7 @@ var ZyfaiAgent = class {
894
1242
  throw error;
895
1243
  }
896
1244
  }
897
- async deposit(state, chainId, amount, asset, depositCallback) {
1245
+ async deposit(state, chainId, amount, depositCallback) {
898
1246
  try {
899
1247
  await this.connectFull(state, chainId);
900
1248
  const validChainId = isValidChainId(chainId);
@@ -908,15 +1256,13 @@ var ZyfaiAgent = class {
908
1256
  validChainId,
909
1257
  amount
910
1258
  );
911
- const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
912
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1259
+ await this.sdk.logDeposit(validChainId, txHash, amount);
913
1260
  return { txHash, smartWallet: wallet.address, amount };
914
1261
  }
915
1262
  const raw = await this.sdk.depositFunds(
916
1263
  this.getAddress(),
917
1264
  validChainId,
918
- amount,
919
- asset
1265
+ amount
920
1266
  );
921
1267
  return mapDeposit(raw);
922
1268
  } catch (error) {
@@ -954,10 +1300,10 @@ var ZyfaiAgent = class {
954
1300
  const raw = await this.sdk.getOnchainEarnings(smartWallet);
955
1301
  return mapEarnings(raw, smartWallet);
956
1302
  }
957
- async getAccountApy(state, chainId, days, tokenSymbol) {
1303
+ async getAccountApy(state, chainId, days) {
958
1304
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
959
1305
  const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
960
- return mapApyHistory(raw, chainId, tokenSymbol);
1306
+ return mapApyHistory(raw, chainId);
961
1307
  }
962
1308
  async getHistory(state, chainId, options) {
963
1309
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
@@ -1012,20 +1358,6 @@ var ZyfaiAgent = class {
1012
1358
  }
1013
1359
  return mapUserProfile(raw, this.connectedAddress);
1014
1360
  }
1015
- async ensureAutoSelectProtocols(state, chainId, asset) {
1016
- await this.connectAuth(state, chainId);
1017
- const current = await this.sdk.getUserDetails(asset);
1018
- const update = buildAutoSelectUpdate(
1019
- {
1020
- autoSelectProtocols: current.autoSelectProtocols,
1021
- chains: current.chains
1022
- },
1023
- asset
1024
- );
1025
- if (!update) return false;
1026
- await this.sdk.updateUserProfile(update);
1027
- return true;
1028
- }
1029
1361
  // --- IAgent: Discovery (no wallet required) ---
1030
1362
  async getAgentApy(days, options) {
1031
1363
  const raw = await this.sdk.getAPYPerStrategy(
@@ -1039,7 +1371,11 @@ var ZyfaiAgent = class {
1039
1371
  }
1040
1372
  };
1041
1373
 
1374
+ // src/client.ts
1375
+ init_errors();
1376
+
1042
1377
  // src/lib/routing-api.ts
1378
+ init_errors();
1043
1379
  var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
1044
1380
  async function fetchAgentKeys(apiKey) {
1045
1381
  const url = `${ROUTING_API_BASE_URL}/api/v1/agent/keys`;
@@ -1070,6 +1406,7 @@ async function fetchAgentKeys(apiKey) {
1070
1406
  }
1071
1407
 
1072
1408
  // src/lib/health-report.ts
1409
+ init_errors();
1073
1410
  var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
1074
1411
  async function reportAgentFailure(apiKey, agentType, errorCode) {
1075
1412
  try {
@@ -1111,7 +1448,8 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
1111
1448
  const tokenBalance = agentBalance?.tokens.find(
1112
1449
  (t) => t.chainId === chainId && t.asset.toUpperCase() === target
1113
1450
  );
1114
- if (!tokenBalance) return { agent, balance: 0n };
1451
+ if (!tokenBalance)
1452
+ return { agent, balance: 0n };
1115
1453
  return { agent, balance: (0, import_viem2.parseUnits)(tokenBalance.amount, decimals) };
1116
1454
  });
1117
1455
  }
@@ -1128,9 +1466,11 @@ function planProportionalShares(balances, requested, totalAvailable) {
1128
1466
  return diff > 0n ? 1 : diff < 0n ? -1 : 0;
1129
1467
  });
1130
1468
  for (const p of byHeadroom) {
1131
- if (remainder === 0n) break;
1469
+ if (remainder === 0n)
1470
+ break;
1132
1471
  const headroom = p.balance - p.planned;
1133
- if (headroom <= 0n) continue;
1472
+ if (headroom <= 0n)
1473
+ continue;
1134
1474
  const take = headroom < remainder ? headroom : remainder;
1135
1475
  p.planned += take;
1136
1476
  remainder -= take;
@@ -1159,7 +1499,8 @@ function redistributeShare(plans, fromIndex, amount, candidatePool) {
1159
1499
  (s, c) => s + (c.balance - c.planned),
1160
1500
  0n
1161
1501
  );
1162
- if (totalHeadroom === 0n) return;
1502
+ if (totalHeadroom === 0n)
1503
+ return;
1163
1504
  let distributed = 0n;
1164
1505
  for (const c of candidates) {
1165
1506
  const headroom = c.balance - c.planned;
@@ -1170,9 +1511,11 @@ function redistributeShare(plans, fromIndex, amount, candidatePool) {
1170
1511
  }
1171
1512
  let leftover = amount - distributed;
1172
1513
  for (const c of candidates) {
1173
- if (leftover === 0n) break;
1514
+ if (leftover === 0n)
1515
+ break;
1174
1516
  const headroom = c.balance - c.planned;
1175
- if (headroom <= 0n) continue;
1517
+ if (headroom <= 0n)
1518
+ continue;
1176
1519
  const take = headroom < leftover ? headroom : leftover;
1177
1520
  c.planned += take;
1178
1521
  leftover -= take;
@@ -1189,13 +1532,16 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
1189
1532
  for (const id of Object.keys(agentApys)) {
1190
1533
  const cells = agentApys[id].apyByChainAndAsset;
1191
1534
  const balance = agentBalances[id] ?? 0;
1192
- if (!cells || balance <= 0) continue;
1535
+ if (!cells || balance <= 0)
1536
+ continue;
1193
1537
  for (const [chainKey, perAsset] of Object.entries(cells)) {
1194
- if (!perAsset) continue;
1538
+ if (!perAsset)
1539
+ continue;
1195
1540
  const chainId = Number(chainKey);
1196
1541
  for (const [asset, apyValue] of Object.entries(perAsset)) {
1197
1542
  const apy = Number(apyValue ?? 0);
1198
- if (apy === 0) continue;
1543
+ if (apy === 0)
1544
+ continue;
1199
1545
  sums[chainId] ??= {};
1200
1546
  weights[chainId] ??= {};
1201
1547
  sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
@@ -1209,7 +1555,8 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
1209
1555
  const perAssetOut = {};
1210
1556
  for (const asset of Object.keys(sums[chainId])) {
1211
1557
  const w = weights[chainId][asset];
1212
- if (w > 0) perAssetOut[asset] = sums[chainId][asset] / w;
1558
+ if (w > 0)
1559
+ perAssetOut[asset] = sums[chainId][asset] / w;
1213
1560
  }
1214
1561
  if (Object.keys(perAssetOut).length > 0) {
1215
1562
  out[chainId] = perAssetOut;
@@ -1222,6 +1569,9 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
1222
1569
  var import_viem5 = require("viem");
1223
1570
  var import_chains2 = require("viem/chains");
1224
1571
 
1572
+ // src/lib/sponsored-deposit.ts
1573
+ init_errors();
1574
+
1225
1575
  // src/lib/transfer-auth.ts
1226
1576
  var import_viem3 = require("viem");
1227
1577
  var ERC20_META_ABI = [
@@ -1259,6 +1609,7 @@ function randomAuthNonce() {
1259
1609
  }
1260
1610
 
1261
1611
  // src/lib/sponsor-client.ts
1612
+ init_errors();
1262
1613
  var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
1263
1614
  async function postSponsorTransferAuth(input) {
1264
1615
  const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
@@ -1266,10 +1617,7 @@ async function postSponsorTransferAuth(input) {
1266
1617
  try {
1267
1618
  res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
1268
1619
  method: "POST",
1269
- headers: {
1270
- "content-type": "application/json",
1271
- "x-owney-api-key": input.apiKey
1272
- },
1620
+ headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey },
1273
1621
  body: JSON.stringify(input.body)
1274
1622
  });
1275
1623
  } catch (networkError) {
@@ -1289,91 +1637,11 @@ async function postSponsorTransferAuth(input) {
1289
1637
  throw new OwneyError(
1290
1638
  "SPONSOR_REQUEST_FAILED",
1291
1639
  `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
1292
- {
1293
- statusCode: res.status,
1294
- responseBody: text.slice(0, 500),
1295
- // 503 SPONSOR_UNAVAILABLE = relayer out of gas; the tx was rejected
1296
- // before broadcast, so it is safe to fall back to a user-paid deposit.
1297
- safeToFallback: res.status === 503
1298
- }
1640
+ { statusCode: res.status, responseBody: text.slice(0, 500) }
1299
1641
  );
1300
1642
  }
1301
1643
  return parsed.data;
1302
1644
  }
1303
- async function postSponsorPermit2Transfer(input) {
1304
- const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
1305
- let res;
1306
- try {
1307
- res = await fetch(`${base3}/api/v1/sponsor/permit2-transfer`, {
1308
- method: "POST",
1309
- headers: {
1310
- "content-type": "application/json",
1311
- "x-owney-api-key": input.apiKey
1312
- },
1313
- body: JSON.stringify(input.body)
1314
- });
1315
- } catch (networkError) {
1316
- throw new OwneyError(
1317
- "SPONSOR_REQUEST_FAILED",
1318
- `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
1319
- { cause: String(networkError), safeToFallback: false }
1320
- );
1321
- }
1322
- const text = await res.text();
1323
- let parsed = null;
1324
- try {
1325
- parsed = JSON.parse(text);
1326
- } catch {
1327
- }
1328
- if (!res.ok || !parsed?.success || !parsed.data) {
1329
- throw new OwneyError(
1330
- "SPONSOR_REQUEST_FAILED",
1331
- `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
1332
- {
1333
- statusCode: res.status,
1334
- responseBody: text.slice(0, 500),
1335
- safeToFallback: res.status >= 400 && res.status < 500 || res.status === 503
1336
- }
1337
- );
1338
- }
1339
- return parsed.data;
1340
- }
1341
- async function getSponsorRelayerAddress(input) {
1342
- const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
1343
- let res;
1344
- try {
1345
- res = await fetch(
1346
- `${base3}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
1347
- {
1348
- headers: { "x-owney-api-key": input.apiKey }
1349
- }
1350
- );
1351
- } catch (networkError) {
1352
- throw new OwneyError(
1353
- "SPONSOR_REQUEST_FAILED",
1354
- `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
1355
- { cause: String(networkError), safeToFallback: true }
1356
- );
1357
- }
1358
- const text = await res.text();
1359
- let parsed = null;
1360
- try {
1361
- parsed = JSON.parse(text);
1362
- } catch {
1363
- }
1364
- if (!res.ok || !parsed?.success || !parsed.data?.relayer) {
1365
- throw new OwneyError(
1366
- "SPONSOR_REQUEST_FAILED",
1367
- `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
1368
- {
1369
- statusCode: res.status,
1370
- responseBody: text.slice(0, 500),
1371
- safeToFallback: true
1372
- }
1373
- );
1374
- }
1375
- return parsed.data.relayer;
1376
- }
1377
1645
 
1378
1646
  // src/lib/sponsored-deposit.ts
1379
1647
  var AUTH_WINDOW_SECONDS = 15 * 60;
@@ -1425,114 +1693,6 @@ function makeSponsoredDepositCallback(deps) {
1425
1693
  };
1426
1694
  }
1427
1695
 
1428
- // src/lib/permit2.ts
1429
- var import_viem4 = require("viem");
1430
- var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
1431
- var MAX_UINT256 = 2n ** 256n - 1n;
1432
- var ERC20_ALLOWANCE_ABI = [
1433
- {
1434
- type: "function",
1435
- name: "allowance",
1436
- stateMutability: "view",
1437
- inputs: [{ name: "owner", type: "address" }, { name: "spender", type: "address" }],
1438
- outputs: [{ name: "", type: "uint256" }]
1439
- },
1440
- {
1441
- type: "function",
1442
- name: "approve",
1443
- stateMutability: "nonpayable",
1444
- inputs: [{ name: "spender", type: "address" }, { name: "amount", type: "uint256" }],
1445
- outputs: [{ name: "", type: "bool" }]
1446
- }
1447
- ];
1448
- function buildPermitTransferFromTypedData(input) {
1449
- return {
1450
- domain: { name: "Permit2", chainId: input.chainId, verifyingContract: PERMIT2_ADDRESS },
1451
- types: {
1452
- PermitTransferFrom: [
1453
- { name: "permitted", type: "TokenPermissions" },
1454
- { name: "spender", type: "address" },
1455
- { name: "nonce", type: "uint256" },
1456
- { name: "deadline", type: "uint256" }
1457
- ],
1458
- TokenPermissions: [
1459
- { name: "token", type: "address" },
1460
- { name: "amount", type: "uint256" }
1461
- ]
1462
- },
1463
- primaryType: "PermitTransferFrom",
1464
- message: input.message
1465
- };
1466
- }
1467
- function randomPermit2Nonce() {
1468
- const bytes = new Uint8Array(32);
1469
- globalThis.crypto.getRandomValues(bytes);
1470
- return BigInt((0, import_viem4.bytesToHex)(bytes));
1471
- }
1472
- async function readPermit2Allowance(publicClient, token, owner) {
1473
- return publicClient.readContract({
1474
- address: token,
1475
- abi: ERC20_ALLOWANCE_ABI,
1476
- functionName: "allowance",
1477
- args: [owner, PERMIT2_ADDRESS]
1478
- });
1479
- }
1480
-
1481
- // src/lib/sponsored-weth-deposit.ts
1482
- var PERMIT_WINDOW_SECONDS = 15 * 60;
1483
- function makeSponsoredWethCallback(deps) {
1484
- const get = deps.httpGet ?? getSponsorRelayerAddress;
1485
- const post = deps.httpPost ?? postSponsorPermit2Transfer;
1486
- return async (smartWallet, chainId, amount) => {
1487
- const cid = chainId;
1488
- const token = deps.tokenAddressByChain[cid];
1489
- if (!token) {
1490
- throw new OwneyError("CHAIN_UNSUPPORTED", `No sponsored WETH configured for chain ${chainId}`);
1491
- }
1492
- const amountWei = BigInt(amount);
1493
- const pub = deps.getPublicClient(cid);
1494
- const allowance = await readPermit2Allowance(pub, token, deps.ownerAddress);
1495
- if (allowance < amountWei) {
1496
- throw new OwneyError(
1497
- "PERMIT2_APPROVAL_REQUIRED",
1498
- "WETH gasless deposits need a one-time Permit2 approval; call approvePermit2() first",
1499
- { token, chainId: cid, allowance: allowance.toString(), amount }
1500
- );
1501
- }
1502
- const relayer = await get({ baseUrl: deps.baseUrl, apiKey: deps.apiKey, chainId: cid });
1503
- const nonce = randomPermit2Nonce();
1504
- const deadline = BigInt(Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS);
1505
- const typedData = buildPermitTransferFromTypedData({
1506
- chainId: cid,
1507
- message: {
1508
- permitted: { token, amount: amountWei },
1509
- spender: relayer,
1510
- nonce,
1511
- deadline
1512
- }
1513
- });
1514
- const wallet = deps.getWalletClient(cid);
1515
- const signature = await wallet.signTypedData(
1516
- { account: deps.ownerAddress, ...typedData }
1517
- );
1518
- const result = await post({
1519
- baseUrl: deps.baseUrl,
1520
- apiKey: deps.apiKey,
1521
- body: {
1522
- chainId: cid,
1523
- token,
1524
- from: deps.ownerAddress,
1525
- to: smartWallet,
1526
- amount,
1527
- nonce: nonce.toString(),
1528
- deadline: deadline.toString(),
1529
- signature
1530
- }
1531
- });
1532
- return result.txHash;
1533
- };
1534
- }
1535
-
1536
1696
  // src/client.ts
1537
1697
  function encodeMultiAgentCursor(map) {
1538
1698
  return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
@@ -1556,22 +1716,13 @@ function decodeMultiAgentCursor(token) {
1556
1716
  }
1557
1717
  var SPONSORED_USDC_BY_CHAIN = {
1558
1718
  8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
1559
- 42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
1560
- 1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
1719
+ 42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
1561
1720
  };
1562
1721
  var VIEM_CHAIN2 = {
1563
1722
  8453: import_chains2.base,
1564
- 42161: import_chains2.arbitrum,
1565
- 1: import_chains2.mainnet
1566
- };
1567
- var SPONSORED_WETH_BY_CHAIN = {
1568
- 8453: "0x4200000000000000000000000000000000000006",
1569
- 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
1570
- 1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
1723
+ 42161: import_chains2.arbitrum
1571
1724
  };
1572
- function shouldFallbackToUserPaid(error, asset, appCallback) {
1573
- return (asset === "WETH" || asset === "USDC") && appCallback === void 0 && error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED" && error.details?.safeToFallback === true;
1574
- }
1725
+ var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai", "sail"];
1575
1726
  var OwneySDK = class {
1576
1727
  agents = /* @__PURE__ */ new Map();
1577
1728
  activeAgents = /* @__PURE__ */ new Set();
@@ -1584,14 +1735,11 @@ var OwneySDK = class {
1584
1735
  state = null;
1585
1736
  apiKey;
1586
1737
  zyfaiRpcUrls;
1587
- routingApiBaseUrl;
1588
1738
  cachedSponsoredCallback = null;
1589
- cachedWethSponsoredCallback = null;
1590
1739
  initializingAgentsPromise = null;
1591
1740
  constructor(config) {
1592
1741
  this.apiKey = config.apiKey;
1593
1742
  this.zyfaiRpcUrls = config.zyfaiRpcUrls;
1594
- this.routingApiBaseUrl = config.routingApiBaseUrl;
1595
1743
  }
1596
1744
  /**
1597
1745
  * Establish connection state for all subsequent SDK calls.
@@ -1612,7 +1760,6 @@ var OwneySDK = class {
1612
1760
  }
1613
1761
  this.state = { provider, walletAddress, chainId: null };
1614
1762
  this.cachedSponsoredCallback = null;
1615
- this.cachedWethSponsoredCallback = null;
1616
1763
  }
1617
1764
  /**
1618
1765
  * Disconnect from all agents and clear connection state.
@@ -1626,7 +1773,6 @@ var OwneySDK = class {
1626
1773
  this.disabledAgents.clear();
1627
1774
  this.state = null;
1628
1775
  this.cachedSponsoredCallback = null;
1629
- this.cachedWethSponsoredCallback = null;
1630
1776
  }
1631
1777
  isAgentDisabled(agentId) {
1632
1778
  return this.disabledAgents.has(agentId);
@@ -1646,7 +1792,8 @@ var OwneySDK = class {
1646
1792
  return this.state?.chainId ?? null;
1647
1793
  }
1648
1794
  requireState() {
1649
- if (!this.state) throw new NotConnectedError();
1795
+ if (!this.state)
1796
+ throw new NotConnectedError();
1650
1797
  return this.state;
1651
1798
  }
1652
1799
  requireChainId() {
@@ -1676,12 +1823,12 @@ var OwneySDK = class {
1676
1823
  * `TransferWithAuthorization`, then POSTs to the sponsor API.
1677
1824
  */
1678
1825
  getDefaultSponsoredCallback() {
1679
- if (this.cachedSponsoredCallback) return this.cachedSponsoredCallback;
1826
+ if (this.cachedSponsoredCallback)
1827
+ return this.cachedSponsoredCallback;
1680
1828
  const provider = this.requireConnectedProvider();
1681
1829
  const owner = this.state.walletAddress;
1682
1830
  this.cachedSponsoredCallback = makeSponsoredDepositCallback({
1683
1831
  apiKey: this.apiKey,
1684
- baseUrl: this.routingApiBaseUrl,
1685
1832
  ownerAddress: owner,
1686
1833
  tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
1687
1834
  // Casts work around viem's chain-narrowed Client vs the generic
@@ -1699,37 +1846,6 @@ var OwneySDK = class {
1699
1846
  });
1700
1847
  return this.cachedSponsoredCallback;
1701
1848
  }
1702
- /**
1703
- * Lazily builds (and caches) the default Permit2 sponsored WETH deposit
1704
- * callback used when the caller omits `depositCallback` for a WETH
1705
- * deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
1706
- * `PermitTransferFrom` instead of an EIP-3009 authorization.
1707
- */
1708
- getDefaultWethSponsoredCallback() {
1709
- if (this.cachedWethSponsoredCallback)
1710
- return this.cachedWethSponsoredCallback;
1711
- const provider = this.requireConnectedProvider();
1712
- const owner = this.state.walletAddress;
1713
- this.cachedWethSponsoredCallback = makeSponsoredWethCallback({
1714
- apiKey: this.apiKey,
1715
- baseUrl: this.routingApiBaseUrl,
1716
- ownerAddress: owner,
1717
- tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
1718
- // Casts work around viem's chain-narrowed Client vs the generic
1719
- // PublicClient/WalletClient param types — structurally identical at
1720
- // runtime, but the two share a name TS treats as unrelated.
1721
- getPublicClient: (cid) => (0, import_viem5.createPublicClient)({
1722
- chain: VIEM_CHAIN2[cid],
1723
- transport: (0, import_viem5.custom)(provider)
1724
- }),
1725
- getWalletClient: (cid) => (0, import_viem5.createWalletClient)({
1726
- account: owner,
1727
- chain: VIEM_CHAIN2[cid],
1728
- transport: (0, import_viem5.custom)(provider)
1729
- })
1730
- });
1731
- return this.cachedWethSponsoredCallback;
1732
- }
1733
1849
  getAgent(agentId) {
1734
1850
  const agent = this.agents.get(agentId);
1735
1851
  if (!agent) {
@@ -1741,19 +1857,22 @@ var OwneySDK = class {
1741
1857
  const active = /* @__PURE__ */ new Map();
1742
1858
  for (const id of this.activeAgents) {
1743
1859
  const agent = this.agents.get(id);
1744
- if (agent) active.set(id, agent);
1860
+ if (agent)
1861
+ active.set(id, agent);
1745
1862
  }
1746
1863
  return active;
1747
1864
  }
1748
1865
  async ensureAgentsInitialized() {
1749
- if (this.agents.size > 0) return;
1866
+ if (this.agents.size > 0)
1867
+ return;
1750
1868
  if (!this.initializingAgentsPromise) {
1751
1869
  this.initializingAgentsPromise = (async () => {
1752
1870
  const agentKeys = await fetchAgentKeys(this.apiKey);
1753
1871
  this.disabledAgents.clear();
1754
- for (const { key, agent_type, is_enabled } of agentKeys) {
1755
- const agent = this.createAgent(agent_type, key);
1756
- if (!agent) continue;
1872
+ for (const { key, agent_type, project_name, is_enabled } of agentKeys) {
1873
+ const agent = await this.createAgent(agent_type, key, project_name);
1874
+ if (!agent)
1875
+ continue;
1757
1876
  this.agents.set(agent_type, agent);
1758
1877
  if (is_enabled === false) {
1759
1878
  this.disabledAgents.add(agent_type);
@@ -1773,10 +1892,16 @@ var OwneySDK = class {
1773
1892
  this.initializingAgentsPromise = null;
1774
1893
  }
1775
1894
  }
1776
- createAgent(agentId, key) {
1895
+ async createAgent(agentId, key, projectName) {
1777
1896
  if (agentId === "zyfai") {
1778
1897
  return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1779
1898
  }
1899
+ if (agentId === "surfliquid") {
1900
+ if (!projectName)
1901
+ return null;
1902
+ const { SurfLiquidAgent: SurfLiquidAgent2 } = await Promise.resolve().then(() => (init_surfliquid_agent(), surfliquid_agent_exports));
1903
+ return new SurfLiquidAgent2({ projectName, appId: key });
1904
+ }
1780
1905
  return null;
1781
1906
  }
1782
1907
  // --- Account lifecycle ---
@@ -1880,7 +2005,7 @@ var OwneySDK = class {
1880
2005
  }
1881
2006
  const state = this.requireState();
1882
2007
  const chainId = this.requireChainId();
1883
- const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback() : this.getDefaultSponsoredCallback());
2008
+ const effectiveCallback = depositCallback ?? this.getDefaultSponsoredCallback();
1884
2009
  if (agentId) {
1885
2010
  if (this.isAgentDisabled(agentId)) {
1886
2011
  throw new OwneyError(
@@ -1892,14 +2017,10 @@ var OwneySDK = class {
1892
2017
  const agent = this.getAgent(agentId);
1893
2018
  this.validateAssetSupport(agent, chainId, asset);
1894
2019
  await this.validateMinDepositAmount(agent, state, chainId, asset, amount);
1895
- return this.depositWithFallback(
1896
- agent,
1897
- state,
1898
- chainId,
1899
- amount,
1900
- asset,
1901
- effectiveCallback,
1902
- depositCallback
2020
+ return withFailureReporting(
2021
+ this.apiKey,
2022
+ agent.id,
2023
+ () => agent.deposit(state, chainId, amount, effectiveCallback)
1903
2024
  );
1904
2025
  }
1905
2026
  const totalAmount = BigInt(amount);
@@ -1929,77 +2050,26 @@ var OwneySDK = class {
1929
2050
  );
1930
2051
  }
1931
2052
  const agentResults = {};
2053
+ const agentErrors = {};
1932
2054
  for (const { agent, amount: agentAmount } of agentAmounts) {
1933
- agentResults[agent.id] = await this.depositWithFallback(
1934
- agent,
1935
- state,
1936
- chainId,
1937
- agentAmount,
1938
- asset,
1939
- effectiveCallback,
1940
- depositCallback
1941
- );
1942
- }
1943
- return { agentResults };
1944
- }
1945
- /**
1946
- * Invokes `agent.deposit` with the resolved sponsored callback, composing
1947
- * two independent auto-recovery mechanisms:
1948
- *
1949
- * 1. Missing Permit2 allowance: when the app did not supply its own
1950
- * callback and the attempt fails with `PERMIT2_APPROVAL_REQUIRED` on a
1951
- * WETH deposit, this is the wallet's first gasless WETH deposit. We send
1952
- * the one-time (user-paid) Permit2 approval via `approvePermit2()` and
1953
- * retry the SAME sponsored attempt once. Bounded to one approval attempt
1954
- * per call so a wallet/agent that keeps reporting the allowance as
1955
- * missing can't loop forever. If `approvePermit2()` itself throws (e.g.
1956
- * the user rejects the wallet prompt), that error propagates as-is —
1957
- * the user said no to a transaction, so we must not turn around and ask
1958
- * them to pay for a different one via the fallback below.
1959
- * 2. `shouldFallbackToUserPaid`: the SDK's own WETH sponsor path failed at
1960
- * the infrastructure layer in a provably safe-to-retry way, so we warn
1961
- * and retry once with `undefined`, falling through to a user-paid
1962
- * native deposit. This still applies after a successful Permit2
1963
- * approval retry (the retried sponsored attempt can itself hit a safe
1964
- * sponsor failure).
1965
- *
1966
- * Any other error — an app-supplied callback's own failure in particular —
1967
- * propagates unchanged. Scoped per agent invocation so one agent's failure
1968
- * doesn't force a retry of sibling agents in a multi-agent split.
1969
- */
1970
- async depositWithFallback(agent, state, chainId, amount, asset, effectiveCallback, appCallback) {
1971
- const attempt = (callback) => withFailureReporting(
1972
- this.apiKey,
1973
- agent.id,
1974
- () => agent.deposit(
1975
- state,
1976
- chainId,
1977
- amount,
1978
- asset,
1979
- callback
1980
- )
1981
- );
1982
- let approvalAttempted = false;
1983
- for (; ; ) {
1984
2055
  try {
1985
- return await attempt(effectiveCallback);
1986
- } catch (error) {
1987
- if (!approvalAttempted && appCallback === void 0 && asset === "WETH" && error instanceof OwneyError && error.code === "PERMIT2_APPROVAL_REQUIRED") {
1988
- approvalAttempted = true;
1989
- console.warn(
1990
- "[owney-sdk] First WETH deposit: sending one-time Permit2 approval..."
1991
- );
1992
- await this.approvePermit2();
1993
- continue;
1994
- }
1995
- if (!shouldFallbackToUserPaid(error, asset, appCallback)) throw error;
1996
- console.warn(
1997
- `[owney-sdk] ${asset} sponsorship unavailable, falling back to user-paid deposit:`,
1998
- error
2056
+ agentResults[agent.id] = await withFailureReporting(
2057
+ this.apiKey,
2058
+ agent.id,
2059
+ () => agent.deposit(state, chainId, agentAmount, effectiveCallback)
1999
2060
  );
2000
- return attempt(void 0);
2061
+ } catch (error) {
2062
+ agentErrors[agent.id] = error instanceof Error ? error.message : String(error);
2001
2063
  }
2002
2064
  }
2065
+ if (Object.keys(agentResults).length === 0) {
2066
+ throw new OwneyError(
2067
+ "DEPOSIT_ALL_FAILED",
2068
+ `All ${agentAmounts.length} agent deposit(s) failed.`,
2069
+ { agentErrors }
2070
+ );
2071
+ }
2072
+ return Object.keys(agentErrors).length > 0 ? { agentResults, agentErrors } : { agentResults };
2003
2073
  }
2004
2074
  getMinDepositAmount(agent, chainId, asset) {
2005
2075
  const chainAssets = agent.supportedAssets.find(
@@ -2009,7 +2079,8 @@ var OwneySDK = class {
2009
2079
  return BigInt(assetEntry?.minDepositAmount ?? "0");
2010
2080
  }
2011
2081
  splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
2012
- if (agents.length === 0) return [];
2082
+ if (agents.length === 0)
2083
+ return [];
2013
2084
  const perAgent = totalAmount / BigInt(agents.length);
2014
2085
  const remainder = totalAmount % BigInt(agents.length);
2015
2086
  const splits = agents.map((agent, i) => ({
@@ -2033,8 +2104,10 @@ var OwneySDK = class {
2033
2104
  async validateMinDepositAmount(agent, state, chainId, asset, amount) {
2034
2105
  const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
2035
2106
  const parsedAmount = BigInt(amount);
2036
- if (parsedAmount >= minDepositAmount) return;
2037
- if (await this.hasExistingBalance(agent, state, chainId, asset)) return;
2107
+ if (parsedAmount >= minDepositAmount)
2108
+ return;
2109
+ if (await this.hasExistingBalance(agent, state, chainId, asset))
2110
+ return;
2038
2111
  throw new OwneyError(
2039
2112
  "DEPOSIT_AMOUNT_BELOW_MINIMUM",
2040
2113
  `Amount "${amount}" is below the required minimum deposit "${minDepositAmount.toString()}" for agent "${agent.id}" on chain ${chainId} for asset "${asset}".`,
@@ -2097,6 +2170,34 @@ var OwneySDK = class {
2097
2170
  }
2098
2171
  return eligible;
2099
2172
  }
2173
+ /**
2174
+ * Agent ids the routing API provisioned for this org that support the given
2175
+ * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
2176
+ * surfliquid first). Returns `[]` when the org has no compatible agent — never
2177
+ * throws on an empty org. Loads agent keys on first call (apiKey only, no
2178
+ * wallet), so the UI can resolve which agent to use before the user connects.
2179
+ *
2180
+ * This is the source of truth for agent availability: an agent appears here
2181
+ * iff the routing API returned its key. No per-app feature flags.
2182
+ */
2183
+ async getEligibleAgentIds(chainId, asset) {
2184
+ try {
2185
+ await this.ensureAgentsInitialized();
2186
+ } catch (error) {
2187
+ if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
2188
+ return [];
2189
+ }
2190
+ throw error;
2191
+ }
2192
+ return [...this.agents.values()].filter((agent) => {
2193
+ const chainAssets = agent.supportedAssets.find(
2194
+ (sa) => sa.chainId === chainId
2195
+ );
2196
+ return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
2197
+ }).map((agent) => agent.id).sort(
2198
+ (a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
2199
+ );
2200
+ }
2100
2201
  // --- Fund operations ---
2101
2202
  /**
2102
2203
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
@@ -2132,9 +2233,17 @@ var OwneySDK = class {
2132
2233
  }
2133
2234
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
2134
2235
  if (!amount) {
2236
+ const aggregated2 = await this.getBalances();
2237
+ const funded = projectAgentBalancesForAsset(
2238
+ eligibleAgents,
2239
+ aggregated2.agentBalances,
2240
+ chainId,
2241
+ asset,
2242
+ assetInfo.decimals
2243
+ ).filter((b) => b.balance > 0n);
2135
2244
  const results2 = {};
2136
2245
  const agentErrors2 = {};
2137
- for (const agent of eligibleAgents) {
2246
+ for (const { agent } of funded) {
2138
2247
  try {
2139
2248
  results2[agent.id] = await agent.withdraw(state, chainId, token);
2140
2249
  } catch (err) {
@@ -2151,9 +2260,10 @@ var OwneySDK = class {
2151
2260
  { asset, agentErrors: agentErrors2 }
2152
2261
  );
2153
2262
  }
2263
+ const totalWithdrawn = funded.filter(({ agent }) => results2[agent.id] !== void 0).reduce((sum, { balance }) => sum + balance, 0n);
2154
2264
  return {
2155
2265
  agentResult: results2,
2156
- totalWithdrawn: sumWithdrawnAmount(results2).toString()
2266
+ totalWithdrawn: totalWithdrawn.toString()
2157
2267
  };
2158
2268
  }
2159
2269
  const requested = BigInt(amount);
@@ -2198,7 +2308,8 @@ var OwneySDK = class {
2198
2308
  const agentErrors = {};
2199
2309
  for (let i = 0; i < plans.length; i++) {
2200
2310
  const p = plans[i];
2201
- if (p.planned === 0n) continue;
2311
+ if (p.planned === 0n)
2312
+ continue;
2202
2313
  try {
2203
2314
  results[p.agent.id] = await p.agent.withdraw(
2204
2315
  state,
@@ -2332,30 +2443,19 @@ var OwneySDK = class {
2332
2443
  */
2333
2444
  async getAccountApy({
2334
2445
  agentId,
2335
- days,
2336
- tokenSymbol
2446
+ days
2337
2447
  }) {
2338
2448
  const state = this.requireState();
2339
2449
  const chainId = this.requireChainId();
2340
2450
  if (agentId) {
2341
- return this.getAgent(agentId).getAccountApy(
2342
- state,
2343
- chainId,
2344
- days,
2345
- tokenSymbol
2346
- );
2451
+ return this.getAgent(agentId).getAccountApy(state, chainId, days);
2347
2452
  }
2348
2453
  const activeAgents = this.getActiveAgents();
2349
2454
  const entries = [...activeAgents.entries()];
2350
2455
  const [apyResults, balanceResults] = await Promise.all([
2351
2456
  Promise.all(
2352
2457
  entries.map(async ([id, agent]) => {
2353
- const apy = await agent.getAccountApy(
2354
- state,
2355
- chainId,
2356
- days,
2357
- tokenSymbol
2358
- );
2458
+ const apy = await agent.getAccountApy(state, chainId, days);
2359
2459
  return [id, apy];
2360
2460
  })
2361
2461
  ),
@@ -2378,13 +2478,15 @@ var OwneySDK = class {
2378
2478
  let relevantBalance = 0;
2379
2479
  for (const id of Object.keys(results)) {
2380
2480
  const agentApy = Number(results[id].weightedApyAfterFee ?? 0);
2381
- if (agentApy === 0) continue;
2481
+ if (agentApy === 0)
2482
+ continue;
2382
2483
  relevantBalance += balances[id];
2383
2484
  }
2384
2485
  if (relevantBalance > 0) {
2385
2486
  for (const id of Object.keys(results)) {
2386
2487
  const agentApy = Number(results[id].weightedApyAfterFee ?? 0);
2387
- if (agentApy === 0) continue;
2488
+ if (agentApy === 0)
2489
+ continue;
2388
2490
  const weight = balances[id] / relevantBalance;
2389
2491
  totalApy += agentApy * weight;
2390
2492
  }
@@ -2439,7 +2541,8 @@ var OwneySDK = class {
2439
2541
  const nextCursorMap = {};
2440
2542
  let hasMore = false;
2441
2543
  for (const { agentId: id, page } of perAgent) {
2442
- if (!page) continue;
2544
+ if (!page)
2545
+ continue;
2443
2546
  merged.push(...page.data);
2444
2547
  if (page.hasMore && page.nextCursor) {
2445
2548
  nextCursorMap[id] = page.nextCursor;
@@ -2448,12 +2551,16 @@ var OwneySDK = class {
2448
2551
  }
2449
2552
  merged.sort((a, b) => {
2450
2553
  const dateDiff = new Date(b.date).getTime() - new Date(a.date).getTime();
2451
- if (dateDiff !== 0) return dateDiff;
2452
- if (a.agent !== b.agent) return a.agent < b.agent ? -1 : 1;
2554
+ if (dateDiff !== 0)
2555
+ return dateDiff;
2556
+ if (a.agent !== b.agent)
2557
+ return a.agent < b.agent ? -1 : 1;
2453
2558
  const aTx = a.transactions?.[0]?.txHashes?.[0] ?? "";
2454
2559
  const bTx = b.transactions?.[0]?.txHashes?.[0] ?? "";
2455
- if (aTx !== bTx) return aTx < bTx ? -1 : 1;
2456
- if (a.action !== b.action) return a.action < b.action ? -1 : 1;
2560
+ if (aTx !== bTx)
2561
+ return aTx < bTx ? -1 : 1;
2562
+ if (a.action !== b.action)
2563
+ return a.action < b.action ? -1 : 1;
2457
2564
  return 0;
2458
2565
  });
2459
2566
  return {
@@ -2488,67 +2595,6 @@ var OwneySDK = class {
2488
2595
  agentUserProfile: results
2489
2596
  };
2490
2597
  }
2491
- /**
2492
- * Ensure the given asset uses backend protocol auto-selection for the active
2493
- * chain's account. No-op (returns false) for agents that don't support it.
2494
- * @param asset - "USDC" or "WETH".
2495
- * @param agentId - Agent to target. Defaults to "zyfai".
2496
- * @returns whether a profile write occurred.
2497
- */
2498
- async ensureAutoSelectProtocols(asset, agentId = "zyfai") {
2499
- const state = this.requireState();
2500
- const chainId = this.requireChainId();
2501
- const agent = this.getAgent(agentId);
2502
- if (typeof agent.ensureAutoSelectProtocols !== "function") return false;
2503
- return agent.ensureAutoSelectProtocols(state, chainId, asset);
2504
- }
2505
- /**
2506
- * One-time, user-paid approval of Permit2 on the sponsored WETH token for
2507
- * the active chain. Required once per wallet per chain before gasless WETH
2508
- * deposits; afterwards deposit() is signature-only. Resolves only after the
2509
- * approval transaction is mined (1 confirmation), so a subsequent deposit()
2510
- * will see the new allowance; throws if the transaction reverted.
2511
- * @returns the approval transaction hash.
2512
- */
2513
- async approvePermit2(asset = "WETH") {
2514
- void asset;
2515
- const state = this.requireState();
2516
- const chainId = this.requireChainId();
2517
- this.validateAssetSupport(this.getAgent("zyfai"), chainId, "WETH");
2518
- const token = SPONSORED_WETH_BY_CHAIN[chainId];
2519
- if (!token) {
2520
- throw new OwneyError(
2521
- "CHAIN_UNSUPPORTED",
2522
- `No sponsored WETH on chain ${chainId}`
2523
- );
2524
- }
2525
- const provider = this.requireConnectedProvider();
2526
- const wallet = (0, import_viem5.createWalletClient)({
2527
- account: state.walletAddress,
2528
- chain: VIEM_CHAIN2[chainId],
2529
- transport: (0, import_viem5.custom)(provider)
2530
- });
2531
- const hash = await wallet.writeContract({
2532
- address: token,
2533
- abi: ERC20_ALLOWANCE_ABI,
2534
- functionName: "approve",
2535
- args: [PERMIT2_ADDRESS, MAX_UINT256],
2536
- account: state.walletAddress,
2537
- chain: VIEM_CHAIN2[chainId]
2538
- });
2539
- const publicClient = (0, import_viem5.createPublicClient)({
2540
- chain: VIEM_CHAIN2[chainId],
2541
- transport: (0, import_viem5.custom)(provider)
2542
- });
2543
- const receipt = await publicClient.waitForTransactionReceipt({
2544
- hash,
2545
- confirmations: 1
2546
- });
2547
- if (receipt.status !== "success") {
2548
- throw new Error(`Permit2 approval reverted (tx ${hash})`);
2549
- }
2550
- return hash;
2551
- }
2552
2598
  // --- Discovery (no wallet required) ---
2553
2599
  /**
2554
2600
  * Get the agent's average APY performance over a time period. Does not require a wallet connection.
@@ -2646,6 +2692,9 @@ var OwneySDK = class {
2646
2692
  }
2647
2693
  };
2648
2694
 
2695
+ // src/index.ts
2696
+ init_errors();
2697
+
2649
2698
  // src/agents/zyfai/zyfai.siwx.ts
2650
2699
  var import_viem6 = require("viem");
2651
2700
  var import_siwe = require("siwe");
@@ -2654,7 +2703,8 @@ var import_sdk2 = require("@zyfai/sdk");
2654
2703
  // src/agents/zyfai/zyfai.siwx-cache.ts
2655
2704
  var KEY_PREFIX2 = "owney.siwx.session";
2656
2705
  var storage2 = () => {
2657
- if (typeof window === "undefined") return null;
2706
+ if (typeof window === "undefined")
2707
+ return null;
2658
2708
  try {
2659
2709
  return window.localStorage;
2660
2710
  } catch {
@@ -2664,9 +2714,11 @@ var storage2 = () => {
2664
2714
  var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2665
2715
  var readSiwxSession = (address, chainId) => {
2666
2716
  const store = storage2();
2667
- if (!store) return null;
2717
+ if (!store)
2718
+ return null;
2668
2719
  const raw = store.getItem(buildKey2(address, chainId));
2669
- if (!raw) return null;
2720
+ if (!raw)
2721
+ return null;
2670
2722
  try {
2671
2723
  return JSON.parse(raw);
2672
2724
  } catch {
@@ -2676,7 +2728,8 @@ var readSiwxSession = (address, chainId) => {
2676
2728
  };
2677
2729
  var writeSiwxSession = (address, chainId, session) => {
2678
2730
  const store = storage2();
2679
- if (!store) return;
2731
+ if (!store)
2732
+ return;
2680
2733
  try {
2681
2734
  store.setItem(buildKey2(address, chainId), JSON.stringify(session));
2682
2735
  } catch {
@@ -2684,7 +2737,8 @@ var writeSiwxSession = (address, chainId, session) => {
2684
2737
  };
2685
2738
  var clearSiwxSession = (address, chainId) => {
2686
2739
  const store = storage2();
2687
- if (!store) return;
2740
+ if (!store)
2741
+ return;
2688
2742
  try {
2689
2743
  store.removeItem(buildKey2(address, chainId));
2690
2744
  } catch {
@@ -2747,10 +2801,12 @@ function buildSIWXConfig(deps) {
2747
2801
  const jwt = readSession(address, id);
2748
2802
  const stored = readSiwxSession(address, id);
2749
2803
  if (!jwt) {
2750
- if (stored) clearSiwxSession(address, id);
2804
+ if (stored)
2805
+ clearSiwxSession(address, id);
2751
2806
  return [];
2752
2807
  }
2753
- if (!stored) return [];
2808
+ if (!stored)
2809
+ return [];
2754
2810
  const session = {
2755
2811
  // `stored.data.chainId` is a plain string in the cache (kept AppKit-free);
2756
2812
  // it always holds a valid CaipNetworkId here, so narrow at the boundary.