@owney/sdk 0.7.16-beta.5 → 0.7.16-beta.6

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.js CHANGED
@@ -1,3 +1,30 @@
1
+ import {
2
+ debugLog,
3
+ fetchAgentKeys,
4
+ fetchOrgAgentConfig,
5
+ setOwneyDebug
6
+ } from "./chunk-QA7JUSDB.js";
7
+ import {
8
+ buildTransferWithAuthorizationTypedData,
9
+ randomAuthNonce,
10
+ readTokenMeta
11
+ } from "./chunk-5LU2SHO7.js";
12
+ import {
13
+ ERC20_ALLOWANCE_ABI,
14
+ MAX_UINT256,
15
+ PERMIT2_ADDRESS,
16
+ buildPermitTransferFromTypedData,
17
+ randomPermit2Nonce,
18
+ readErc20Balance,
19
+ readPermit2Allowance
20
+ } from "./chunk-DBRXNDSB.js";
21
+ import {
22
+ AgentChainIncompatibleError,
23
+ AgentNotFoundError,
24
+ NotConnectedError,
25
+ OwneyError
26
+ } from "./chunk-GMNQBWUB.js";
27
+
1
28
  // src/agents/zyfai/zyfai.agent.ts
2
29
  import { SMART_SESSIONS_VALIDATOR, ZyfaiSDK } from "@zyfai/sdk";
3
30
  import { createPublicClient, http, parseAbi } from "viem";
@@ -50,55 +77,6 @@ var SupportedAssets = [
50
77
  }
51
78
  ];
52
79
 
53
- // src/errors.ts
54
- var OwneyError = class extends Error {
55
- code;
56
- details;
57
- agentId;
58
- constructor(code, message, details, agentId) {
59
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
60
- super(`${prefix} ${message}`);
61
- this.name = "OwneyError";
62
- this.code = code;
63
- this.details = details;
64
- this.agentId = agentId;
65
- }
66
- };
67
- var AgentNotFoundError = class extends OwneyError {
68
- constructor(agentId, available) {
69
- super(
70
- "AGENT_NOT_FOUND",
71
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
72
- { agentId, available },
73
- agentId
74
- );
75
- this.name = "AgentNotFoundError";
76
- }
77
- };
78
- var NotConnectedError = class extends OwneyError {
79
- constructor() {
80
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
81
- this.name = "NotConnectedError";
82
- }
83
- };
84
- var AgentChainIncompatibleError = class extends OwneyError {
85
- incompatibleAgents;
86
- connectedChainId;
87
- constructor(incompatibleAgents, connectedChainId) {
88
- const details = incompatibleAgents.map(
89
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
90
- ).join("; ");
91
- super(
92
- "AGENT_CHAIN_INCOMPATIBLE",
93
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
94
- { incompatibleAgents, connectedChainId }
95
- );
96
- this.name = "AgentChainIncompatibleError";
97
- this.incompatibleAgents = incompatibleAgents;
98
- this.connectedChainId = connectedChainId;
99
- }
100
- };
101
-
102
80
  // src/lib/utils.ts
103
81
  var isValidChainId = (chainId) => {
104
82
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
@@ -110,6 +88,12 @@ var isValidChainId = (chainId) => {
110
88
  }
111
89
  return chainId;
112
90
  };
91
+ function isSameAsset(tokenSymbol, asset) {
92
+ const token = tokenSymbol.toLowerCase();
93
+ const target = asset.toLowerCase();
94
+ if (token === target) return true;
95
+ return target === "weth" && token === "eth" || target === "eth" && token === "weth";
96
+ }
113
97
  function hexToDecimal(hex, decimals = 6) {
114
98
  const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
115
99
  const parsed = BigInt(normalized);
@@ -147,18 +131,18 @@ function tokenDecimals(symbol, explicit) {
147
131
  return explicit;
148
132
  return DECIMALS_BY_SYMBOL[(symbol ?? "").toLowerCase()] ?? 6;
149
133
  }
150
- function mapDeposit(raw2) {
134
+ function mapDeposit(raw) {
151
135
  return {
152
- txHash: raw2.txHash,
153
- smartWallet: raw2.smartWallet,
154
- amount: raw2.amount
136
+ txHash: raw.txHash,
137
+ smartWallet: raw.smartWallet,
138
+ amount: raw.amount
155
139
  };
156
140
  }
157
- function mapWithdraw(raw2) {
141
+ function mapWithdraw(raw) {
158
142
  return {
159
- txHash: raw2.txHash,
160
- type: raw2.type,
161
- amount: raw2.amount
143
+ txHash: raw.txHash,
144
+ type: raw.type,
145
+ amount: raw.amount
162
146
  };
163
147
  }
164
148
  var CHAIN_ID_TO_NAME = {
@@ -177,10 +161,10 @@ function resolveChainId(chain) {
177
161
  if (Number.isFinite(asNum) && asNum > 0) return asNum;
178
162
  return NAME_TO_CHAIN_ID[chain.trim().toLowerCase()] ?? NaN;
179
163
  }
180
- function mapPendingAllocations(raw2) {
181
- if (!Array.isArray(raw2)) return void 0;
164
+ function mapPendingAllocations(raw) {
165
+ if (!Array.isArray(raw)) return void 0;
182
166
  const pending = [];
183
- for (const entry of raw2) {
167
+ for (const entry of raw) {
184
168
  if (typeof entry !== "object" || entry === null) continue;
185
169
  const e = entry;
186
170
  if (typeof e.chainId !== "number" || !Number.isFinite(e.chainId)) continue;
@@ -203,8 +187,8 @@ function mapPendingAllocations(raw2) {
203
187
  }
204
188
  return pending.length > 0 ? pending : void 0;
205
189
  }
206
- function mapBalances(raw2, _chainId, smartWallet) {
207
- const portfolio = raw2.portfolio;
190
+ function mapBalances(raw, _chainId, smartWallet) {
191
+ const portfolio = raw.portfolio;
208
192
  const portfolioByChain = portfolio.portfolioByChain ?? {};
209
193
  let totalBalance = 0;
210
194
  const tokens = [];
@@ -249,7 +233,7 @@ function mapBalances(raw2, _chainId, smartWallet) {
249
233
  )
250
234
  )
251
235
  ),
252
- apy: p.pool_apy,
236
+ apy: netApy(p.pool_apy_withFee, p.pool_apy, "pool_apy_withFee"),
253
237
  tvl: p.pool_tvl,
254
238
  // PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
255
239
  // structural read keeps it undefined today and auto-populates later.
@@ -273,8 +257,8 @@ function sumTokenValues(tokens) {
273
257
  function sumTokenEarnings(tokens) {
274
258
  return Object.values(tokens).reduce((sum, val) => sum + Number(val), 0);
275
259
  }
276
- function mapEarnings(raw2, smartWallet) {
277
- const totalEarningsByChain = raw2.data.totalEarningsByChainWithFee ?? raw2.data.totalEarningsByChain ?? {};
260
+ function mapEarnings(raw, smartWallet) {
261
+ const totalEarningsByChain = raw.data.totalEarningsByChainWithFee ?? raw.data.totalEarningsByChain ?? {};
278
262
  const tokens = [];
279
263
  for (const [chainIdKey, tokensBySymbol] of Object.entries(
280
264
  totalEarningsByChain
@@ -293,15 +277,15 @@ function mapEarnings(raw2, smartWallet) {
293
277
  return {
294
278
  smartWallet,
295
279
  lifetimeEarnings: sumTokenEarnings(
296
- raw2.data.totalEarningsByTokenWithFee ?? raw2.data.totalEarningsByToken
280
+ raw.data.totalEarningsByTokenWithFee ?? raw.data.totalEarningsByToken
297
281
  ),
298
282
  tokens
299
283
  };
300
284
  }
301
- function mapWeightedApyByChain(raw2) {
302
- if (!raw2) return void 0;
285
+ function mapWeightedApyByChain(raw) {
286
+ if (!raw) return void 0;
303
287
  const out = {};
304
- for (const [chainKey, tokenApy] of Object.entries(raw2)) {
288
+ for (const [chainKey, tokenApy] of Object.entries(raw)) {
305
289
  const chainId = Number(chainKey);
306
290
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) continue;
307
291
  const perAsset = {};
@@ -314,6 +298,19 @@ function mapWeightedApyByChain(raw2) {
314
298
  }
315
299
  return Object.keys(out).length > 0 ? out : void 0;
316
300
  }
301
+ var warnedGrossApyFallbacks = /* @__PURE__ */ new Set();
302
+ function netApy(net, gross, field) {
303
+ if (net !== void 0 && net !== null) return net;
304
+ if (gross === void 0 || gross === null) return void 0;
305
+ if (!warnedGrossApyFallbacks.has(field)) {
306
+ warnedGrossApyFallbacks.add(field);
307
+ console.warn(
308
+ `[owney] @zyfai/sdk omitted "${field}"; falling back to the gross APY, which does not deduct Zyfai's performance fee and so reads high.`
309
+ );
310
+ }
311
+ debugLog("zyfai:apy", `gross fallback for ${field}`, { gross });
312
+ return gross;
313
+ }
317
314
  function rawPoolApyForChain(entry, chainId, tokenSymbol) {
318
315
  let weightedSum = 0;
319
316
  let totalBalance = 0;
@@ -321,21 +318,22 @@ function rawPoolApyForChain(entry, chainId, tokenSymbol) {
321
318
  if (p.chainId !== chainId) continue;
322
319
  if (tokenSymbol && p.tokenSymbol !== tokenSymbol) continue;
323
320
  const balance = p.balance ?? 0;
324
- if (balance <= 0 || typeof p.apy !== "number") continue;
325
- weightedSum += p.apy * balance;
321
+ const apy = netApy(p.apy_withFee, p.apy, "apy_withFee");
322
+ if (balance <= 0 || typeof apy !== "number") continue;
323
+ weightedSum += apy * balance;
326
324
  totalBalance += balance;
327
325
  }
328
326
  return totalBalance > 0 ? weightedSum / totalBalance : null;
329
327
  }
330
- function mapApyHistory(raw2, chainId, tokenSymbol) {
331
- const history = Object.entries(raw2.history ?? {}).map(([date, entry]) => ({
328
+ function mapApyHistory(raw, chainId, tokenSymbol) {
329
+ const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({
332
330
  date,
333
331
  apy: rawPoolApyForChain(entry, chainId, tokenSymbol)
334
332
  })).filter((p) => p.apy !== null).sort((a, b) => a.date.localeCompare(b.date));
335
333
  return {
336
- walletAddress: raw2.walletAddress,
337
- weightedApyAfterFee: raw2.weightedApyAfterFee ? sumTokenValues(raw2.weightedApyAfterFee) : void 0,
338
- apyByChainAndAsset: mapWeightedApyByChain(raw2.weightedApyAfterFeeByChain),
334
+ walletAddress: raw.walletAddress,
335
+ weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0,
336
+ apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain),
339
337
  history
340
338
  };
341
339
  }
@@ -370,8 +368,12 @@ function mapEntries(rawEntries, chainId) {
370
368
  const matched = positions.find(
371
369
  (p) => p.protocol_name ? rawLog.newOpportunity.includes(`${p.protocol_name} (${p.pool})`) : false
372
370
  );
373
- oldApy = Number(rawLog.oldApy);
374
- newApy = Number(rawLog.newApy);
371
+ oldApy = Number(
372
+ netApy(rawLog.oldApy_withFee, rawLog.oldApy, "oldApy_withFee")
373
+ );
374
+ newApy = Number(
375
+ netApy(rawLog.newApy_withFee, rawLog.newApy, "newApy_withFee")
376
+ );
375
377
  const from = splitOpportunity(rawLog.oldOpportunity);
376
378
  const to = splitOpportunity(rawLog.newOpportunity);
377
379
  rebalanceLog = [
@@ -427,23 +429,23 @@ function mapEntries(rawEntries, chainId) {
427
429
  };
428
430
  });
429
431
  }
430
- function mapUserProfile(raw2, userAddress) {
432
+ function mapUserProfile(raw, userAddress) {
431
433
  return {
432
434
  address: userAddress,
433
- smartWallet: raw2.smartWallet || "",
434
- chains: raw2.chains || [],
435
- strategy: raw2.strategy,
436
- hasActiveSessionKey: raw2.hasActiveSessionKey || false,
437
- protocols: raw2.protocols || [],
438
- splitting: raw2.splitting,
439
- minSplits: raw2.minSplits
435
+ smartWallet: raw.smartWallet || "",
436
+ chains: raw.chains || [],
437
+ strategy: raw.strategy,
438
+ hasActiveSessionKey: raw.hasActiveSessionKey || false,
439
+ protocols: raw.protocols || [],
440
+ splitting: raw.splitting,
441
+ minSplits: raw.minSplits
440
442
  };
441
443
  }
442
- function mapApyByStrategy(raw2) {
444
+ function mapApyByStrategy(raw) {
443
445
  const apyPerAsset = {};
444
446
  let apySum = 0;
445
447
  let apyCount = 0;
446
- for (const entry of raw2.data) {
448
+ for (const entry of raw.data) {
447
449
  const supported = SupportedAssets.find(
448
450
  (asset) => asset.chainId === entry.chain_id && asset.symbol === entry.token_symbol
449
451
  );
@@ -451,7 +453,11 @@ function mapApyByStrategy(raw2) {
451
453
  const chainKey = supported.chainId;
452
454
  const symbolKey = supported.symbol;
453
455
  const bucket = apyPerAsset[chainKey] ?? {};
454
- const apy = entry.average_apy_with_fee ?? entry.average_apy;
456
+ const apy = netApy(
457
+ entry.average_apy_withFee,
458
+ entry.average_apy,
459
+ "average_apy_withFee"
460
+ ) ?? entry.average_apy;
455
461
  bucket[symbolKey] = apy;
456
462
  apyPerAsset[chainKey] = bucket;
457
463
  apySum += apy;
@@ -610,15 +616,15 @@ var readSession = (address, _chainId) => {
610
616
  if (typeof window === "undefined") return null;
611
617
  const key2 = buildKey(address);
612
618
  const store = storage();
613
- let raw2 = null;
619
+ let raw = null;
614
620
  try {
615
- raw2 = store?.getItem(key2) ?? null;
621
+ raw = store?.getItem(key2) ?? null;
616
622
  } catch {
617
- raw2 = null;
623
+ raw = null;
618
624
  }
619
- if (raw2) {
625
+ if (raw) {
620
626
  try {
621
- const parsed = JSON.parse(raw2);
627
+ const parsed = JSON.parse(raw);
622
628
  if (isFreshSession(parsed)) return parsed;
623
629
  } catch {
624
630
  }
@@ -786,8 +792,8 @@ function buildChainsByProtocol(protocols, dashboardChainIds) {
786
792
  }
787
793
  return result;
788
794
  }
789
- function flattenAvailablePools(raw2) {
790
- const byChain = raw2 ?? {};
795
+ function flattenAvailablePools(raw) {
796
+ const byChain = raw ?? {};
791
797
  const names = [];
792
798
  for (const byToken of Object.values(byChain ?? {})) {
793
799
  for (const entry of Object.values(byToken ?? {})) {
@@ -811,23 +817,6 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
811
817
  return !protocolListsEqual(current.protocols, desiredProtocols);
812
818
  }
813
819
 
814
- // src/lib/debug.ts
815
- var configuredDebug = false;
816
- function setOwneyDebug(enabled) {
817
- configuredDebug = enabled;
818
- }
819
- function isOwneyDebug() {
820
- return globalThis.__OWNEY_DEBUG__ === true || configuredDebug;
821
- }
822
- function debugLog(scope, message, data) {
823
- if (!isOwneyDebug()) return;
824
- if (data === void 0) {
825
- console.log(`[${scope}] ${message}`);
826
- } else {
827
- console.log(`[${scope}] ${message}`, data);
828
- }
829
- }
830
-
831
820
  // src/agents/zyfai/zyfai.agent.ts
832
821
  var ERC7579_IS_MODULE_INSTALLED_ABI = parseAbi([
833
822
  "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)"
@@ -1298,8 +1287,8 @@ var ZyfaiAgent = class _ZyfaiAgent {
1298
1287
  const poolResults = await Promise.all(
1299
1288
  universe.map(async (protocol) => {
1300
1289
  try {
1301
- const raw2 = await this.sdk.getAvailablePools(protocol.id, strategy);
1302
- return [protocol.id, flattenAvailablePools(raw2)];
1290
+ const raw = await this.sdk.getAvailablePools(protocol.id, strategy);
1291
+ return [protocol.id, flattenAvailablePools(raw)];
1303
1292
  } catch (error) {
1304
1293
  console.warn(
1305
1294
  `[zyfai] applyPoolPolicy: getAvailablePools(${protocol.id}) failed, skipping this protocol (non-fatal):`,
@@ -1338,6 +1327,37 @@ var ZyfaiAgent = class _ZyfaiAgent {
1338
1327
  );
1339
1328
  }
1340
1329
  }
1330
+ /**
1331
+ * Records the deposit with Zyfai, retrying transient failures.
1332
+ *
1333
+ * This runs AFTER the transfer has already landed on-chain, so it must never
1334
+ * fail the deposit — the funds moved. But it is also the ONLY source of the
1335
+ * "Top up wallet" entry the history is built from: Zyfai auto-deploys the
1336
+ * balance it detects either way, so when this call is lost the user's deposit
1337
+ * never appears in Activity (an earlier withdrawal stays the newest row) and
1338
+ * nothing ever backfills it. Retry, then log loudly enough to be recoverable.
1339
+ */
1340
+ async logDepositWithRetry(chainId, txHash, amount, tokenAddress) {
1341
+ const ATTEMPTS = 3;
1342
+ const RETRY_DELAY_MS = 1e3;
1343
+ for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
1344
+ try {
1345
+ await (tokenAddress ? this.sdk.logDeposit(chainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(chainId, txHash, amount));
1346
+ return;
1347
+ } catch (logError) {
1348
+ if (attempt === ATTEMPTS) {
1349
+ console.error(
1350
+ "[owney-sdk] Deposit landed on-chain but logDeposit failed \u2014 it will be missing from Zyfai history:",
1351
+ { txHash, chainId, amount, tokenAddress, error: logError }
1352
+ );
1353
+ return;
1354
+ }
1355
+ await new Promise(
1356
+ (resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt)
1357
+ );
1358
+ }
1359
+ }
1360
+ }
1341
1361
  /**
1342
1362
  * True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
1343
1363
  * to this EOA — the "new wallet" kind that is predeployed on the chains it
@@ -1365,14 +1385,14 @@ var ZyfaiAgent = class _ZyfaiAgent {
1365
1385
  async readWalletState(ownerAddress) {
1366
1386
  try {
1367
1387
  const { portfolio } = await this.sdk.getPositions(ownerAddress);
1368
- const raw2 = portfolio;
1388
+ const raw = portfolio;
1369
1389
  debugLog("zyfai:onboard", "wallet state from getPositions", {
1370
- predeployed: raw2?.predeployed,
1371
- hasActiveSessionKey: raw2?.hasActiveSessionKey
1390
+ predeployed: raw?.predeployed,
1391
+ hasActiveSessionKey: raw?.hasActiveSessionKey
1372
1392
  });
1373
1393
  return {
1374
- predeployed: raw2?.predeployed,
1375
- hasActiveSessionKey: raw2?.hasActiveSessionKey
1394
+ predeployed: raw?.predeployed,
1395
+ hasActiveSessionKey: raw?.hasActiveSessionKey
1376
1396
  };
1377
1397
  } catch (error) {
1378
1398
  console.warn(
@@ -1641,25 +1661,23 @@ var ZyfaiAgent = class _ZyfaiAgent {
1641
1661
  );
1642
1662
  const txHash = await depositCallback(smartWallet, validChainId, amount);
1643
1663
  const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
1644
- try {
1645
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1646
- } catch (logError) {
1647
- console.warn(
1648
- "[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
1649
- logError
1650
- );
1651
- }
1664
+ await this.logDepositWithRetry(
1665
+ validChainId,
1666
+ txHash,
1667
+ amount,
1668
+ tokenAddress
1669
+ );
1652
1670
  return { txHash, smartWallet, amount };
1653
1671
  }
1654
1672
  await this.ensureWalletDeployed(this.getAddress(), validChainId);
1655
- const raw2 = await this.sdk.depositFunds(
1673
+ const raw = await this.sdk.depositFunds(
1656
1674
  this.getAddress(),
1657
1675
  validChainId,
1658
1676
  amount,
1659
1677
  asset,
1660
1678
  "aggressive"
1661
1679
  );
1662
- return mapDeposit(raw2);
1680
+ return mapDeposit(raw);
1663
1681
  } catch (error) {
1664
1682
  throw error;
1665
1683
  }
@@ -1668,32 +1686,32 @@ var ZyfaiAgent = class _ZyfaiAgent {
1668
1686
  async withdraw(state, chainId, token, amount) {
1669
1687
  const validChainId = isValidChainId(chainId);
1670
1688
  await this.ensureConnected(state, validChainId);
1671
- const raw2 = await this.sdk.withdrawFunds(
1689
+ const raw = await this.sdk.withdrawFunds(
1672
1690
  this.getAddress(),
1673
1691
  validChainId,
1674
1692
  amount,
1675
1693
  token
1676
1694
  );
1677
- if (!raw2.success) {
1695
+ if (!raw.success) {
1678
1696
  throw new OwneyError(
1679
1697
  "WITHDRAW_FAILED",
1680
- raw2.message || "Zyfai withdraw failed.",
1681
- { chainId: validChainId, token, amount, response: raw2 },
1698
+ raw.message || "Zyfai withdraw failed.",
1699
+ { chainId: validChainId, token, amount, response: raw },
1682
1700
  this.id
1683
1701
  );
1684
1702
  }
1685
- return mapWithdraw(raw2);
1703
+ return mapWithdraw(raw);
1686
1704
  }
1687
1705
  // --- IAgent: Portfolio reads ---
1688
1706
  async getBalances(state, chainId) {
1689
1707
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
1690
- const raw2 = await this.sdk.getPortfolio(this.getAddress());
1691
- return mapBalances(raw2, validChainId, smartWallet);
1708
+ const raw = await this.sdk.getPortfolio(this.getAddress());
1709
+ return mapBalances(raw, validChainId, smartWallet);
1692
1710
  }
1693
1711
  async getEarnings(state, chainId) {
1694
1712
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1695
- const raw2 = await this.sdk.getOnchainEarnings(smartWallet);
1696
- return mapEarnings(raw2, smartWallet);
1713
+ const raw = await this.sdk.getOnchainEarnings(smartWallet);
1714
+ return mapEarnings(raw, smartWallet);
1697
1715
  }
1698
1716
  async refreshEarnings(state, chainId) {
1699
1717
  if (this.earningsRefreshInFlight) return this.earningsRefreshInFlight;
@@ -1713,8 +1731,8 @@ var ZyfaiAgent = class _ZyfaiAgent {
1713
1731
  }
1714
1732
  async getAccountApy(state, chainId, days, tokenSymbol) {
1715
1733
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1716
- const raw2 = await this.sdk.getDailyApyHistory(smartWallet, days);
1717
- return mapApyHistory(raw2, chainId, tokenSymbol);
1734
+ const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
1735
+ return mapApyHistory(raw, chainId, tokenSymbol);
1718
1736
  }
1719
1737
  /**
1720
1738
  * Owney speaks asset symbols ("USDC" / "WETH"); Zyfai's history endpoint
@@ -1749,7 +1767,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
1749
1767
  const matched = [];
1750
1768
  let backendExhausted = false;
1751
1769
  for (let i = 0; i < MAX_BACKEND_CALLS && matched.length < limit; i++) {
1752
- const raw2 = await this.sdk.getHistory(smartWallet, validChainId, {
1770
+ const raw = await this.sdk.getHistory(smartWallet, validChainId, {
1753
1771
  limit: backendPageSize,
1754
1772
  offset,
1755
1773
  fromDate: options?.fromDate,
@@ -1760,13 +1778,13 @@ var ZyfaiAgent = class _ZyfaiAgent {
1760
1778
  // asset's rows and handing back a page that filters to nothing.
1761
1779
  assetType
1762
1780
  });
1763
- raw2.data.forEach((entry, idx) => {
1781
+ raw.data.forEach((entry, idx) => {
1764
1782
  if (entry.chainId === validChainId) {
1765
1783
  matched.push({ entry, rawIdx: offset + idx });
1766
1784
  }
1767
1785
  });
1768
- offset += raw2.data.length;
1769
- if (raw2.data.length < backendPageSize) {
1786
+ offset += raw.data.length;
1787
+ if (raw.data.length < backendPageSize) {
1770
1788
  backendExhausted = true;
1771
1789
  break;
1772
1790
  }
@@ -1788,18 +1806,18 @@ var ZyfaiAgent = class _ZyfaiAgent {
1788
1806
  }
1789
1807
  async getUserProfile(state, chainId) {
1790
1808
  await this.connectAuth(state, chainId);
1791
- const raw2 = await this.sdk.getUserDetails();
1809
+ const raw = await this.sdk.getUserDetails();
1792
1810
  debugLog("zyfai:profile", "getUserProfile \u2014 Zyfai reports", {
1793
1811
  asset: "USDC (default \u2014 no asset passed)",
1794
- splitting: raw2.splitting,
1795
- minSplits: raw2.minSplits,
1796
- strategy: raw2.strategy,
1797
- chains: raw2.chains,
1798
- protocolCount: raw2.protocols?.length,
1799
- hasActiveSessionKey: raw2.hasActiveSessionKey,
1800
- smartWallet: raw2.smartWallet
1812
+ splitting: raw.splitting,
1813
+ minSplits: raw.minSplits,
1814
+ strategy: raw.strategy,
1815
+ chains: raw.chains,
1816
+ protocolCount: raw.protocols?.length,
1817
+ hasActiveSessionKey: raw.hasActiveSessionKey,
1818
+ smartWallet: raw.smartWallet
1801
1819
  });
1802
- return mapUserProfile(raw2, this.connectedAddress);
1820
+ return mapUserProfile(raw, this.connectedAddress);
1803
1821
  }
1804
1822
  async ensureAutoSelectProtocols(state, chainId, asset) {
1805
1823
  await this.connectAuth(state, chainId);
@@ -1818,151 +1836,184 @@ var ZyfaiAgent = class _ZyfaiAgent {
1818
1836
  }
1819
1837
  // --- IAgent: Discovery (no wallet required) ---
1820
1838
  async getAgentApy(days, options) {
1821
- const raw2 = await this.sdk.getAPYPerStrategy(
1839
+ const raw = await this.sdk.getAPYPerStrategy(
1822
1840
  false,
1823
1841
  DayFilterMapping[days],
1824
1842
  "aggressive",
1825
1843
  options?.chainId,
1826
1844
  options?.tokenSymbol
1827
1845
  );
1828
- return mapApyByStrategy(raw2);
1846
+ return mapApyByStrategy(raw);
1829
1847
  }
1830
1848
  };
1831
1849
 
1832
- // src/agents/yieldseeker/yieldseeker.agent.ts
1833
- import {
1834
- createPublicClient as createPublicClient3,
1835
- createWalletClient as createWalletClient2,
1836
- custom as custom2,
1837
- encodeFunctionData,
1838
- erc20Abi,
1839
- getAddress as getAddress2,
1840
- isAddress as isAddress2
1841
- } from "viem";
1842
- import { base as base3 } from "viem/chains";
1843
-
1844
- // src/lib/chain-guard.ts
1845
- var CHAIN_NAMES = {
1846
- 1: "Ethereum",
1847
- 8453: "Base",
1848
- 42161: "Arbitrum"
1849
- };
1850
- function chainName(chainId) {
1851
- return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
1852
- }
1853
- async function ensureWalletOnChain(pub, wallet, expected) {
1854
- const actual = await pub.getChainId();
1855
- if (actual === expected) return;
1850
+ // src/lib/health-report.ts
1851
+ var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
1852
+ async function reportAgentFailure(apiKey, agentType, errorCode, baseUrl = ROUTING_API_BASE_URL) {
1856
1853
  try {
1857
- await wallet.switchChain({ id: expected });
1858
- } catch (error) {
1859
- throw new OwneyError(
1860
- "CHAIN_MISMATCH",
1861
- `Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
1862
- {
1863
- expectedChainId: expected,
1864
- actualChainId: actual,
1865
- cause: error instanceof Error ? error.message : String(error)
1866
- }
1854
+ await fetch(`${baseUrl}/api/v1/agent/health-report`, {
1855
+ method: "POST",
1856
+ headers: {
1857
+ "Content-Type": "application/json",
1858
+ "x-owney-api-key": apiKey
1859
+ },
1860
+ body: JSON.stringify({
1861
+ agent_type: agentType,
1862
+ error_code: errorCode,
1863
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1864
+ })
1865
+ });
1866
+ } catch (err) {
1867
+ console.warn(
1868
+ `[owney-sdk] health-report failed for agent "${agentType}":`,
1869
+ err instanceof Error ? err.message : err
1867
1870
  );
1868
1871
  }
1869
- const after = await pub.getChainId();
1870
- if (after !== expected) {
1871
- throw new OwneyError(
1872
- "CHAIN_MISMATCH",
1873
- `Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
1874
- { expectedChainId: expected, actualChainId: after }
1875
- );
1872
+ }
1873
+ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
1874
+ try {
1875
+ return await fn();
1876
+ } catch (err) {
1877
+ const errorCode = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
1878
+ void reportAgentFailure(apiKey, agentType, errorCode, baseUrl);
1879
+ throw err;
1876
1880
  }
1877
1881
  }
1878
1882
 
1879
- // src/lib/transfer-auth.ts
1880
- import { bytesToHex } from "viem";
1881
- var ERC20_META_ABI = [
1882
- { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
1883
- { type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
1884
- ];
1885
- function buildTransferWithAuthorizationTypedData(input) {
1886
- return {
1887
- domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
1888
- types: {
1889
- TransferWithAuthorization: [
1890
- { name: "from", type: "address" },
1891
- { name: "to", type: "address" },
1892
- { name: "value", type: "uint256" },
1893
- { name: "validAfter", type: "uint256" },
1894
- { name: "validBefore", type: "uint256" },
1895
- { name: "nonce", type: "bytes32" }
1896
- ]
1897
- },
1898
- primaryType: "TransferWithAuthorization",
1899
- message: input.message
1900
- };
1883
+ // src/lib/helpers/withdraw-helper.ts
1884
+ import { parseUnits } from "viem";
1885
+ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
1886
+ return agents.map((agent) => {
1887
+ const agentBalance = aggregated[agent.id];
1888
+ const tokenBalance = agentBalance?.tokens.find(
1889
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
1890
+ );
1891
+ if (!tokenBalance) return { agent, balance: 0n };
1892
+ return { agent, balance: parseUnits(tokenBalance.amount, decimals) };
1893
+ });
1901
1894
  }
1902
- async function readTokenMeta(publicClient, token) {
1903
- const [tokenName, tokenVersion] = await Promise.all([
1904
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
1905
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
1906
- ]);
1907
- return { tokenName, tokenVersion };
1895
+ function planProportionalShares(balances, requested, totalAvailable) {
1896
+ const plans = balances.map(({ agent, balance }) => ({
1897
+ agent,
1898
+ balance,
1899
+ planned: totalAvailable > 0n ? balance * requested / totalAvailable : 0n
1900
+ }));
1901
+ const assigned = plans.reduce((s, p) => s + p.planned, 0n);
1902
+ let remainder = requested - assigned;
1903
+ const byHeadroom = [...plans].sort((a, b) => {
1904
+ const diff = b.balance - b.planned - (a.balance - a.planned);
1905
+ return diff > 0n ? 1 : diff < 0n ? -1 : 0;
1906
+ });
1907
+ for (const p of byHeadroom) {
1908
+ if (remainder === 0n) break;
1909
+ const headroom = p.balance - p.planned;
1910
+ if (headroom <= 0n) continue;
1911
+ const take = headroom < remainder ? headroom : remainder;
1912
+ p.planned += take;
1913
+ remainder -= take;
1914
+ }
1915
+ return plans;
1908
1916
  }
1909
- function randomAuthNonce() {
1910
- const bytes = new Uint8Array(32);
1911
- globalThis.crypto.getRandomValues(bytes);
1912
- return bytesToHex(bytes);
1917
+ function planDisabledDrain(disabled, requested) {
1918
+ const sorted = [...disabled].filter((d) => d.balance > 0n).sort((a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0);
1919
+ const plans = [];
1920
+ let remaining = requested;
1921
+ for (const { agent, balance } of sorted) {
1922
+ if (remaining === 0n) {
1923
+ plans.push({ agent, balance, planned: 0n });
1924
+ continue;
1925
+ }
1926
+ const take = balance < remaining ? balance : remaining;
1927
+ plans.push({ agent, balance, planned: take });
1928
+ remaining -= take;
1929
+ }
1930
+ return { plans, remaining };
1913
1931
  }
1914
-
1915
- // src/lib/sponsor-client.ts
1916
- var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
1917
- async function postPaymasterIntent(input) {
1918
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
1919
- let res;
1920
- try {
1921
- res = await fetch(`${base5}/api/v1/sponsor/paymaster-intent`, {
1922
- method: "POST",
1923
- headers: {
1924
- "content-type": "application/json",
1925
- "x-owney-api-key": input.apiKey,
1926
- Authorization: `Signature ${input.yieldseekerSignature}`
1927
- },
1928
- body: JSON.stringify(input.body)
1929
- });
1930
- } catch (networkError) {
1931
- throw new OwneyError(
1932
- "SPONSOR_REQUEST_FAILED",
1933
- `Paymaster intent network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
1934
- { cause: String(networkError), safeToFallback: true }
1935
- );
1932
+ function redistributeShare(plans, fromIndex, amount, candidatePool) {
1933
+ const pool = candidatePool ?? plans.slice(fromIndex + 1);
1934
+ const candidates = pool.filter((c) => c.balance - c.planned > 0n);
1935
+ const totalHeadroom = candidates.reduce(
1936
+ (s, c) => s + (c.balance - c.planned),
1937
+ 0n
1938
+ );
1939
+ if (totalHeadroom === 0n) return;
1940
+ let distributed = 0n;
1941
+ for (const c of candidates) {
1942
+ const headroom = c.balance - c.planned;
1943
+ const proportional = headroom * amount / totalHeadroom;
1944
+ const give = proportional > headroom ? headroom : proportional;
1945
+ c.planned += give;
1946
+ distributed += give;
1936
1947
  }
1937
- const text = await res.text();
1938
- let parsed = null;
1939
- try {
1940
- parsed = JSON.parse(text);
1941
- } catch {
1948
+ let leftover = amount - distributed;
1949
+ for (const c of candidates) {
1950
+ if (leftover === 0n) break;
1951
+ const headroom = c.balance - c.planned;
1952
+ if (headroom <= 0n) continue;
1953
+ const take = headroom < leftover ? headroom : leftover;
1954
+ c.planned += take;
1955
+ leftover -= take;
1942
1956
  }
1943
- if (!res.ok || !parsed?.success || typeof parsed.data?.intent !== "string" || typeof parsed.data.expiresAt !== "number") {
1944
- throw new OwneyError(
1945
- "SPONSOR_REQUEST_FAILED",
1946
- `Paymaster intent API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
1947
- {
1948
- statusCode: res.status,
1949
- responseBody: text.slice(0, 500),
1950
- safeToFallback: true
1957
+ }
1958
+ function sumWithdrawnAmount(results) {
1959
+ return Object.values(results).reduce((sum, r) => sum + BigInt(r.amount), 0n);
1960
+ }
1961
+
1962
+ // src/lib/helpers/account-apy-helper.ts
1963
+ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
1964
+ const sums = {};
1965
+ const weights = {};
1966
+ for (const id of Object.keys(agentApys)) {
1967
+ const cells = agentApys[id].apyByChainAndAsset;
1968
+ const balance = agentBalances[id] ?? 0;
1969
+ if (!cells || balance <= 0) continue;
1970
+ for (const [chainKey, perAsset] of Object.entries(cells)) {
1971
+ if (!perAsset) continue;
1972
+ const chainId = Number(chainKey);
1973
+ for (const [asset, apyValue] of Object.entries(perAsset)) {
1974
+ const apy = Number(apyValue ?? 0);
1975
+ if (apy === 0) continue;
1976
+ sums[chainId] ??= {};
1977
+ weights[chainId] ??= {};
1978
+ sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
1979
+ weights[chainId][asset] = (weights[chainId][asset] ?? 0) + balance;
1951
1980
  }
1952
- );
1981
+ }
1953
1982
  }
1954
- return parsed.data;
1983
+ const out = {};
1984
+ for (const chainKey of Object.keys(sums)) {
1985
+ const chainId = Number(chainKey);
1986
+ const perAssetOut = {};
1987
+ for (const asset of Object.keys(sums[chainId])) {
1988
+ const w = weights[chainId][asset];
1989
+ if (w > 0) perAssetOut[asset] = sums[chainId][asset] / w;
1990
+ }
1991
+ if (Object.keys(perAssetOut).length > 0) {
1992
+ out[chainId] = perAssetOut;
1993
+ }
1994
+ }
1995
+ return out;
1955
1996
  }
1997
+
1998
+ // src/client.ts
1999
+ import {
2000
+ createPublicClient as createPublicClient2,
2001
+ createWalletClient,
2002
+ custom
2003
+ } from "viem";
2004
+ import { base as base2, arbitrum as arbitrum2, mainnet as mainnet2 } from "viem/chains";
2005
+
2006
+ // src/lib/sponsor-client.ts
2007
+ var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
1956
2008
  async function postSponsorTransferAuth(input) {
1957
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
2009
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL2;
1958
2010
  let res;
1959
2011
  try {
1960
- res = await fetch(`${base5}/api/v1/sponsor/erc20-transfer-auth`, {
2012
+ res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
1961
2013
  method: "POST",
1962
2014
  headers: {
1963
2015
  "content-type": "application/json",
1964
- "x-owney-api-key": input.apiKey,
1965
- ...input.yieldseekerSignature ? { Authorization: `Signature ${input.yieldseekerSignature}` } : {}
2016
+ "x-owney-api-key": input.apiKey
1966
2017
  },
1967
2018
  body: JSON.stringify(input.body)
1968
2019
  });
@@ -1995,15 +2046,14 @@ async function postSponsorTransferAuth(input) {
1995
2046
  return parsed.data;
1996
2047
  }
1997
2048
  async function postSponsorPermit2Transfer(input) {
1998
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
2049
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL2;
1999
2050
  let res;
2000
2051
  try {
2001
- res = await fetch(`${base5}/api/v1/sponsor/permit2-transfer`, {
2052
+ res = await fetch(`${base3}/api/v1/sponsor/permit2-transfer`, {
2002
2053
  method: "POST",
2003
2054
  headers: {
2004
2055
  "content-type": "application/json",
2005
- "x-owney-api-key": input.apiKey,
2006
- ...input.yieldseekerSignature ? { Authorization: `Signature ${input.yieldseekerSignature}` } : {}
2056
+ "x-owney-api-key": input.apiKey
2007
2057
  },
2008
2058
  body: JSON.stringify(input.body)
2009
2059
  });
@@ -2034,11 +2084,11 @@ async function postSponsorPermit2Transfer(input) {
2034
2084
  return parsed.data;
2035
2085
  }
2036
2086
  async function getSponsorRelayerAddress(input) {
2037
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
2087
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL2;
2038
2088
  let res;
2039
2089
  try {
2040
2090
  res = await fetch(
2041
- `${base5}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
2091
+ `${base3}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
2042
2092
  {
2043
2093
  headers: { "x-owney-api-key": input.apiKey }
2044
2094
  }
@@ -2070,2015 +2120,204 @@ async function getSponsorRelayerAddress(input) {
2070
2120
  return parsed.data.relayer;
2071
2121
  }
2072
2122
 
2073
- // src/lib/permit2.ts
2074
- import { bytesToHex as bytesToHex2 } from "viem";
2075
- var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
2076
- var MAX_UINT256 = 2n ** 256n - 1n;
2077
- var ERC20_ALLOWANCE_ABI = [
2078
- {
2079
- type: "function",
2080
- name: "allowance",
2081
- stateMutability: "view",
2082
- inputs: [
2083
- { name: "owner", type: "address" },
2084
- { name: "spender", type: "address" }
2085
- ],
2086
- outputs: [{ name: "", type: "uint256" }]
2087
- },
2088
- {
2089
- type: "function",
2090
- name: "approve",
2091
- stateMutability: "nonpayable",
2092
- inputs: [
2093
- { name: "spender", type: "address" },
2094
- { name: "amount", type: "uint256" }
2095
- ],
2096
- outputs: [{ name: "", type: "bool" }]
2097
- },
2098
- {
2099
- type: "function",
2100
- name: "balanceOf",
2101
- stateMutability: "view",
2102
- inputs: [{ name: "account", type: "address" }],
2103
- outputs: [{ name: "", type: "uint256" }]
2104
- }
2105
- ];
2106
- function buildPermitTransferFromTypedData(input) {
2107
- return {
2108
- domain: {
2109
- name: "Permit2",
2110
- chainId: input.chainId,
2111
- verifyingContract: PERMIT2_ADDRESS
2112
- },
2113
- types: {
2114
- PermitTransferFrom: [
2115
- { name: "permitted", type: "TokenPermissions" },
2116
- { name: "spender", type: "address" },
2117
- { name: "nonce", type: "uint256" },
2118
- { name: "deadline", type: "uint256" }
2119
- ],
2120
- TokenPermissions: [
2121
- { name: "token", type: "address" },
2122
- { name: "amount", type: "uint256" }
2123
- ]
2124
- },
2125
- primaryType: "PermitTransferFrom",
2126
- message: input.message
2127
- };
2128
- }
2129
- function randomPermit2Nonce() {
2130
- const bytes = new Uint8Array(32);
2131
- globalThis.crypto.getRandomValues(bytes);
2132
- return BigInt(bytesToHex2(bytes));
2133
- }
2134
- async function readPermit2Allowance(publicClient, token, owner) {
2135
- return publicClient.readContract({
2136
- address: token,
2137
- abi: ERC20_ALLOWANCE_ABI,
2138
- functionName: "allowance",
2139
- args: [owner, PERMIT2_ADDRESS]
2140
- });
2141
- }
2142
- async function readErc20Balance(publicClient, token, owner) {
2143
- return publicClient.readContract({
2144
- address: token,
2145
- abi: ERC20_ALLOWANCE_ABI,
2146
- functionName: "balanceOf",
2147
- args: [owner]
2148
- });
2149
- }
2150
-
2151
- // src/lib/sponsored-deposit.ts
2152
- var AUTH_WINDOW_SECONDS = 15 * 60;
2153
- var verificationSetter = /* @__PURE__ */ Symbol("owney.depositVerificationSetter");
2154
- function provideDepositVerificationContext(callback, context) {
2155
- callback[verificationSetter]?.(context);
2156
- }
2157
- function makeVerificationAwareDepositCallback(implementation) {
2158
- let nextVerification;
2159
- const callback = async (smartWallet, chainId, amount) => {
2160
- const verification = nextVerification;
2161
- nextVerification = void 0;
2162
- return implementation(smartWallet, chainId, amount, verification);
2163
- };
2164
- Object.defineProperty(callback, verificationSetter, {
2165
- value: (context) => {
2166
- nextVerification = context;
2167
- }
2168
- });
2169
- return callback;
2170
- }
2171
- function makeSponsoredDepositCallback(deps) {
2172
- const post = deps.httpPost ?? postSponsorTransferAuth;
2173
- return makeVerificationAwareDepositCallback(
2174
- async (smartWallet, chainId, amount, verification) => {
2175
- const cid = chainId;
2176
- const token = deps.tokenAddressByChain[cid];
2177
- if (!token) {
2178
- throw new OwneyError(
2179
- "CHAIN_UNSUPPORTED",
2180
- `No sponsored token configured for chain ${chainId}`
2181
- );
2182
- }
2183
- const pub = deps.getPublicClient(cid);
2184
- const wallet = deps.getWalletClient(cid);
2185
- await ensureWalletOnChain(pub, wallet, cid);
2186
- try {
2187
- const balance = await readErc20Balance(pub, token, deps.ownerAddress);
2188
- if (balance < BigInt(amount)) {
2189
- throw new OwneyError(
2190
- "DEPOSIT_INSUFFICIENT_BALANCE",
2191
- "Insufficient balance for this deposit.",
2192
- { token, chainId: cid, balance: balance.toString(), amount }
2193
- );
2194
- }
2195
- } catch (err) {
2196
- if (err instanceof OwneyError) throw err;
2197
- console.warn(
2198
- "[owney-sdk] Deposit balance pre-check failed (non-fatal):",
2199
- err instanceof Error ? err.message : String(err)
2200
- );
2201
- }
2202
- const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
2203
- const validAfter = 0n;
2204
- const validBefore = BigInt(
2205
- Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
2206
- );
2207
- const nonce = randomAuthNonce();
2208
- const typedData = buildTransferWithAuthorizationTypedData({
2209
- token,
2210
- chainId: cid,
2211
- tokenName,
2212
- tokenVersion,
2213
- message: {
2214
- from: deps.ownerAddress,
2215
- to: smartWallet,
2216
- value: BigInt(amount),
2217
- validAfter,
2218
- validBefore,
2219
- nonce
2220
- }
2221
- });
2222
- const authSignature = await wallet.signTypedData({
2223
- account: deps.ownerAddress,
2224
- ...typedData
2225
- });
2226
- deps.onApproved?.();
2227
- const result = await post({
2228
- baseUrl: deps.baseUrl,
2229
- apiKey: deps.apiKey,
2230
- ...verification?.agentId === "yieldseeker" ? { yieldseekerSignature: verification.signature } : {},
2231
- body: {
2232
- chainId: cid,
2233
- token,
2234
- from: deps.ownerAddress,
2235
- to: smartWallet,
2236
- value: amount,
2237
- validAfter: validAfter.toString(),
2238
- validBefore: validBefore.toString(),
2239
- nonce,
2240
- authSignature,
2241
- tokenName,
2242
- tokenVersion,
2243
- ...verification?.agentId === "yieldseeker" ? {
2244
- yieldseekerUserId: verification.userId,
2245
- yieldseekerAgentId: verification.yieldseekerAgentId
2246
- } : {}
2247
- }
2248
- });
2249
- return result.txHash;
2250
- }
2251
- );
2252
- }
2253
-
2254
- // src/agents/yieldseeker/yieldseeker.auth.ts
2255
- import { SiweMessage, generateNonce } from "siwe";
2256
- import {
2257
- createPublicClient as createPublicClient2,
2258
- createWalletClient,
2259
- custom,
2260
- getAddress
2261
- } from "viem";
2262
- import { base as base2 } from "viem/chains";
2263
-
2264
- // src/agents/yieldseeker/yieldseeker.auth-cache.ts
2265
- var KEY_PREFIX2 = "owney.yieldseeker.session.v4";
2266
- var INVALIDATED_KEY_PREFIXES = [
2267
- "owney.yieldseeker.session",
2268
- "owney.yieldseeker.session.v3"
2269
- ];
2270
- var storage2 = () => {
2271
- if (typeof window === "undefined") return null;
2272
- try {
2273
- return window.localStorage;
2274
- } catch {
2275
- return null;
2276
- }
2277
- };
2278
- var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2279
- var invalidatedKeys = (address, chainId) => INVALIDATED_KEY_PREFIXES.map(
2280
- (prefix) => `${prefix}:${address.toLowerCase()}:${chainId}`
2281
- );
2282
- var clearInvalidatedSessions = (store, address, chainId) => {
2283
- for (const key2 of invalidatedKeys(address, chainId)) {
2284
- memorySessions2.delete(key2);
2285
- try {
2286
- store?.removeItem(key2);
2287
- } catch {
2288
- }
2289
- }
2290
- };
2291
- var memorySessions2 = /* @__PURE__ */ new Map();
2292
- var isValidSession = (session) => {
2293
- if (!session?.token) return false;
2294
- try {
2295
- const parsed = JSON.parse(atob(session.token));
2296
- return typeof parsed.message === "string" && typeof parsed.signature === "string" && parsed.signature.startsWith("0x");
2297
- } catch {
2298
- return false;
2299
- }
2300
- };
2301
- var readYieldseekerSession = (address, chainId) => {
2302
- if (typeof window === "undefined") return null;
2303
- const key2 = buildKey2(address, chainId);
2304
- const store = storage2();
2305
- clearInvalidatedSessions(store, address, chainId);
2306
- let raw2 = null;
2307
- try {
2308
- raw2 = store?.getItem(key2) ?? null;
2309
- } catch {
2310
- raw2 = null;
2311
- }
2312
- if (raw2) {
2313
- try {
2314
- const parsed = JSON.parse(raw2);
2315
- if (isValidSession(parsed)) return parsed.token;
2316
- } catch {
2317
- }
2318
- memorySessions2.delete(key2);
2319
- try {
2320
- store?.removeItem(key2);
2321
- } catch {
2322
- }
2323
- return null;
2324
- }
2325
- const cached = memorySessions2.get(key2);
2326
- if (isValidSession(cached)) return cached.token;
2327
- if (cached) memorySessions2.delete(key2);
2328
- return null;
2329
- };
2330
- var writeYieldseekerSession = (address, chainId, token) => {
2331
- if (typeof window === "undefined") return;
2332
- const session = { token };
2333
- if (!isValidSession(session)) return;
2334
- const key2 = buildKey2(address, chainId);
2335
- memorySessions2.set(key2, session);
2336
- const store = storage2();
2337
- try {
2338
- store?.setItem(key2, JSON.stringify(session));
2339
- } catch {
2340
- }
2341
- };
2342
- var clearYieldseekerSession = (address, chainId) => {
2343
- const key2 = buildKey2(address, chainId);
2344
- memorySessions2.delete(key2);
2345
- const store = storage2();
2346
- clearInvalidatedSessions(store, address, chainId);
2347
- try {
2348
- store?.removeItem(key2);
2349
- } catch {
2350
- }
2351
- };
2352
-
2353
- // src/agents/yieldseeker/yieldseeker.auth.ts
2354
- function createYieldseekerSiweMessage(address, chainId, dependencies = {}) {
2355
- return new SiweMessage({
2356
- domain: "yieldseeker.xyz",
2357
- address: getAddress(address),
2358
- uri: "https://yieldseeker.xyz",
2359
- version: "1",
2360
- chainId,
2361
- nonce: (dependencies.nonce ?? generateNonce)(),
2362
- issuedAt: (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString()
2363
- }).prepareMessage();
2364
- }
2365
- function encodeYieldseekerAuthToken(token) {
2366
- const bytes = new TextEncoder().encode(JSON.stringify(token));
2367
- let binary = "";
2368
- for (const byte of bytes) binary += String.fromCharCode(byte);
2369
- return btoa(binary);
2370
- }
2371
- var YieldseekerAuth = class {
2372
- constructor(dependencies = {}) {
2373
- this.dependencies = dependencies;
2374
- }
2375
- dependencies;
2376
- tokens = /* @__PURE__ */ new Map();
2377
- pending = /* @__PURE__ */ new Map();
2378
- scopes = /* @__PURE__ */ new Map();
2379
- key(state, chainId) {
2380
- return `${state.walletAddress.toLowerCase()}:${chainId}`;
2381
- }
2382
- async getToken(state, chainId) {
2383
- const key2 = this.key(state, chainId);
2384
- const scope = { address: state.walletAddress, chainId };
2385
- this.scopes.set(key2, scope);
2386
- const cached = this.tokens.get(key2);
2387
- if (cached) return cached;
2388
- const persisted = readYieldseekerSession(scope.address, scope.chainId);
2389
- if (persisted) {
2390
- this.tokens.set(key2, persisted);
2391
- return persisted;
2392
- }
2393
- const inFlight = this.pending.get(key2);
2394
- if (inFlight) return inFlight;
2395
- const request = this.sign(state, chainId).then((token) => {
2396
- this.tokens.set(key2, token);
2397
- writeYieldseekerSession(scope.address, scope.chainId, token);
2398
- return token;
2399
- });
2400
- this.pending.set(key2, request);
2401
- try {
2402
- return await request;
2403
- } finally {
2404
- this.pending.delete(key2);
2405
- }
2406
- }
2407
- clear(state, chainId) {
2408
- if (!state || chainId === void 0) {
2409
- for (const scope of this.scopes.values()) {
2410
- clearYieldseekerSession(scope.address, scope.chainId);
2411
- }
2412
- this.tokens.clear();
2413
- this.pending.clear();
2414
- this.scopes.clear();
2415
- return;
2416
- }
2417
- const key2 = this.key(state, chainId);
2418
- this.tokens.delete(key2);
2419
- this.pending.delete(key2);
2420
- this.scopes.delete(key2);
2421
- clearYieldseekerSession(state.walletAddress, chainId);
2422
- }
2423
- async sign(state, chainId) {
2424
- const account = getAddress(state.walletAddress);
2425
- const publicClient = createPublicClient2({
2426
- chain: base2,
2427
- transport: custom(state.provider)
2428
- });
2429
- const walletClient = createWalletClient({
2430
- account,
2431
- chain: base2,
2432
- transport: custom(state.provider)
2433
- });
2434
- await ensureWalletOnChain(
2435
- publicClient,
2436
- walletClient,
2437
- 8453
2438
- );
2439
- const message = createYieldseekerSiweMessage(
2440
- account,
2441
- chainId,
2442
- this.dependencies
2443
- );
2444
- const signature = await walletClient.signMessage({ account, message });
2445
- return encodeYieldseekerAuthToken({ message, signature });
2446
- }
2447
- };
2448
-
2449
- // src/agents/yieldseeker/yieldseeker.identity-cache.ts
2450
- var KEY_PREFIX3 = "owney.yieldseeker.identity.v1";
2451
- var YIELDSEEKER_IDENTITY_TTL_MS = 24 * 60 * 60 * 1e3;
2452
- var memoryIdentities = /* @__PURE__ */ new Map();
2453
- var storage3 = () => {
2454
- if (typeof window === "undefined") return null;
2455
- try {
2456
- return window.localStorage;
2457
- } catch {
2458
- return null;
2459
- }
2460
- };
2461
- var keyFor = (walletAddress, chainId) => `${KEY_PREFIX3}:${walletAddress.toLowerCase()}:${chainId}`;
2462
- function valid(value, walletAddress, chainId, now) {
2463
- return Boolean(
2464
- value && typeof value.userId === "string" && /^[a-zA-Z0-9_-]{1,128}$/.test(value.userId) && value.walletAddress.toLowerCase() === walletAddress.toLowerCase() && value.chainId === chainId && Number.isSafeInteger(value.expiresAt) && value.expiresAt > now
2465
- );
2466
- }
2467
- function readYieldseekerIdentity(walletAddress, chainId, now = Date.now()) {
2468
- if (typeof window === "undefined") return null;
2469
- const key2 = keyFor(walletAddress, chainId);
2470
- const store = storage3();
2471
- let parsed = null;
2472
- try {
2473
- const raw2 = store?.getItem(key2);
2474
- parsed = raw2 ? JSON.parse(raw2) : null;
2475
- } catch {
2476
- parsed = null;
2477
- }
2478
- const candidate = parsed ?? memoryIdentities.get(key2);
2479
- if (valid(candidate, walletAddress, chainId, now)) {
2480
- memoryIdentities.set(key2, candidate);
2481
- return { userId: candidate.userId };
2482
- }
2483
- memoryIdentities.delete(key2);
2484
- try {
2485
- store?.removeItem(key2);
2486
- } catch {
2487
- }
2488
- return null;
2489
- }
2490
- function writeYieldseekerIdentity(walletAddress, chainId, userId, now = Date.now()) {
2491
- if (typeof window === "undefined") return;
2492
- const identity = {
2493
- userId,
2494
- walletAddress,
2495
- chainId,
2496
- expiresAt: now + YIELDSEEKER_IDENTITY_TTL_MS
2497
- };
2498
- if (!valid(identity, walletAddress, chainId, now)) return;
2499
- const key2 = keyFor(walletAddress, chainId);
2500
- memoryIdentities.set(key2, identity);
2501
- try {
2502
- storage3()?.setItem(key2, JSON.stringify(identity));
2503
- } catch {
2504
- }
2505
- }
2506
- function clearYieldseekerIdentity(walletAddress, chainId) {
2507
- const key2 = keyFor(walletAddress, chainId);
2508
- memoryIdentities.delete(key2);
2509
- try {
2510
- storage3()?.removeItem(key2);
2511
- } catch {
2512
- }
2513
- }
2514
-
2515
- // src/agents/yieldseeker/yieldseeker.client.ts
2516
- var DEFAULT_ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
2517
- function getYieldseekerProxyBaseUrl(routingApiBaseUrl = DEFAULT_ROUTING_API_BASE_URL) {
2518
- return `${routingApiBaseUrl.replace(/\/$/, "")}/api/v1/agent/yieldseeker`;
2519
- }
2520
- var YIELDSEEKER_API_BASE_URL = getYieldseekerProxyBaseUrl();
2521
- var YieldseekerApiError = class extends Error {
2522
- constructor(status, providerCode, responseFields) {
2523
- super(`Yieldseeker request failed (${status}): ${providerCode}`);
2524
- this.status = status;
2525
- this.providerCode = providerCode;
2526
- this.responseFields = responseFields;
2527
- this.name = "YieldseekerApiError";
2528
- }
2529
- status;
2530
- providerCode;
2531
- responseFields;
2532
- get isAuthenticationError() {
2533
- return this.status === 401 || this.status === 403;
2534
- }
2535
- };
2536
- function providerError(body, fallback) {
2537
- if (!body || typeof body !== "object") return { code: fallback };
2538
- const record = body;
2539
- return {
2540
- code: typeof record.message === "string" ? record.message : fallback,
2541
- fields: record.fields && typeof record.fields === "object" ? record.fields : void 0
2542
- };
2543
- }
2544
- var YieldseekerApiClient = class {
2545
- constructor(owneyApiKey, baseUrl = YIELDSEEKER_API_BASE_URL, fetchFn = fetch) {
2546
- this.owneyApiKey = owneyApiKey;
2547
- this.baseUrl = baseUrl;
2548
- this.fetchFn = fetchFn;
2549
- }
2550
- owneyApiKey;
2551
- baseUrl;
2552
- fetchFn;
2553
- async request(path, options = {}) {
2554
- const controller = new AbortController();
2555
- const timer = setTimeout(
2556
- () => controller.abort(),
2557
- options.timeoutMs ?? 15e3
2558
- );
2559
- try {
2560
- const response = await this.fetchFn(`${this.baseUrl}${path}`, {
2561
- method: options.method ?? "GET",
2562
- headers: {
2563
- "Content-Type": "application/json",
2564
- "x-owney-api-key": this.owneyApiKey,
2565
- ...options.signature ? { Authorization: `Signature ${options.signature}` } : {}
2566
- },
2567
- body: options.body ? JSON.stringify(options.body) : void 0,
2568
- signal: controller.signal
2569
- });
2570
- const payload = await response.json().catch(() => null);
2571
- if (!response.ok) {
2572
- const error = providerError(payload, `HTTP_${response.status}`);
2573
- throw new YieldseekerApiError(
2574
- response.status,
2575
- error.code,
2576
- error.fields
2577
- );
2578
- }
2579
- if (payload && typeof payload === "object" && payload.success === true && "data" in payload) {
2580
- return payload.data;
2581
- }
2582
- return payload;
2583
- } catch (error) {
2584
- if (error instanceof YieldseekerApiError) throw error;
2585
- if (error instanceof DOMException && error.name === "AbortError") {
2586
- throw new YieldseekerApiError(408, "REQUEST_TIMEOUT");
2587
- }
2588
- throw new YieldseekerApiError(0, "NETWORK_ERROR", {
2589
- cause: error instanceof Error ? error.message : String(error)
2590
- });
2591
- } finally {
2592
- clearTimeout(timer);
2593
- }
2594
- }
2595
- };
2596
-
2597
- // src/agents/yieldseeker/yieldseeker.mapper.ts
2598
- import { formatUnits, isAddress } from "viem";
2599
-
2600
- // src/agents/yieldseeker/yieldseeker.types.ts
2601
- var YIELDSEEKER_ASSET_METADATA = {
2602
- USDC: {
2603
- address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
2604
- decimals: 6
2605
- },
2606
- WETH: {
2607
- address: "0x4200000000000000000000000000000000000006",
2608
- decimals: 18
2609
- }
2610
- };
2611
-
2612
- // src/agents/yieldseeker/yieldseeker.mapper.ts
2613
- function invalid(endpoint, detail) {
2614
- throw new OwneyError(
2615
- "AGENT_INVALID_RESPONSE",
2616
- `Yieldseeker returned an invalid ${endpoint} response: ${detail}.`,
2617
- { endpoint, detail },
2618
- "yieldseeker"
2619
- );
2620
- }
2621
- function raw(value, endpoint) {
2622
- if (typeof value !== "string" || !/^-?[0-9]+$/.test(value)) {
2623
- return invalid(endpoint, "expected a base-10 integer string");
2624
- }
2625
- return BigInt(value);
2626
- }
2627
- function decimal(value, decimals, endpoint) {
2628
- return formatUnits(raw(value, endpoint), decimals);
2629
- }
2630
- function usd(rawAmount, decimals, price) {
2631
- return Number(formatUnits(rawAmount, decimals)) * price;
2632
- }
2633
- function percent(value) {
2634
- const result = Number(value);
2635
- return Number.isFinite(result) ? result * 100 : 0;
2636
- }
2637
- var YIELDSEEKER_POSITIVE_YIELD_FEE_RATE = 0.1;
2638
- function publicApyAfterYieldseekerFee(value) {
2639
- const grossPercent = percent(value);
2640
- if (grossPercent <= 0) return grossPercent;
2641
- const netPercent = grossPercent * (1 - YIELDSEEKER_POSITIVE_YIELD_FEE_RATE);
2642
- return Math.round(netPercent * 1e12) / 1e12;
2643
- }
2644
- function riskAdjustedApyForDays(option, days) {
2645
- if (days === "7D") return option.riskAdjustedApy7dAverage;
2646
- if (days === "30D") return option.riskAdjustedApy30dAverage;
2647
- return (option.riskAdjustedApy7dAverage + option.riskAdjustedApy30dAverage) / 2;
2648
- }
2649
- function assetAddressValue(record, address) {
2650
- const entry = Object.entries(record).find(
2651
- ([key2]) => key2.toLowerCase() === address.toLowerCase()
2652
- );
2653
- return entry?.[1] ?? "0";
2654
- }
2655
- function position(value, asset, baseAssetDecimals) {
2656
- const option = value?.yieldOption;
2657
- if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !isAddress(option.address)) {
2658
- return invalid("yield positions", "missing vault metadata");
2659
- }
2660
- return {
2661
- chain: "BASE",
2662
- protocol: option.provider,
2663
- protocolId: option.address,
2664
- pool: option.name,
2665
- asset,
2666
- // `assetsRaw` is the ERC-4626 vault-share quantity, whose decimals can
2667
- // differ from the underlying asset. Yieldseeker already converts it to
2668
- // underlying base-asset units in `assetsBase`; pair that value with the
2669
- // snapshot's corresponding `baseAssetDecimals` for display. Keep the raw
2670
- // share quantity separately because withdraw-from-position expects it.
2671
- amount: decimal(
2672
- value.assetsBase,
2673
- baseAssetDecimals,
2674
- "yield positions"
2675
- ),
2676
- amountRaw: String(value.assetsRaw),
2677
- apy: percent(option.riskAdjustedApy),
2678
- tvl: Number(option.totalDepositsUsd),
2679
- liquidity: Number(option.withdrawableDepositsUsd)
2680
- };
2681
- }
2682
- function mapYieldseekerBalances(contexts) {
2683
- const tokens = [];
2684
- const positions = [];
2685
- let totalUsd = 0;
2686
- for (const context of contexts) {
2687
- const metadata = YIELDSEEKER_ASSET_METADATA[context.asset];
2688
- const idle = assetAddressValue(
2689
- context.snapshot.tokenBalances,
2690
- metadata.address
2691
- );
2692
- tokens.push({
2693
- chain: "BASE",
2694
- chainId: 8453,
2695
- asset: context.asset,
2696
- amount: decimal(idle, metadata.decimals, "snapshot")
2697
- });
2698
- positions.push(
2699
- ...context.positions.map(
2700
- (entry) => position(
2701
- entry,
2702
- context.asset,
2703
- context.snapshot.baseAssetDecimals
2704
- )
2705
- )
2706
- );
2707
- totalUsd += usd(
2708
- raw(context.snapshot.totalValueBase, "snapshot"),
2709
- context.snapshot.baseAssetDecimals,
2710
- context.snapshot.baseAssetPriceUsd
2711
- );
2712
- }
2713
- return {
2714
- ...contexts.length === 1 ? { smartWallet: contexts[0].wallet.walletAddress } : {},
2715
- totalBalance: String(totalUsd),
2716
- totalBalanceAsset: "usdc",
2717
- tokens,
2718
- positions
2719
- };
2720
- }
2721
- function mapYieldseekerEarnings(contexts) {
2722
- const tokens = [];
2723
- let lifetimeEarnings = 0;
2724
- for (const context of contexts) {
2725
- const amount = raw(context.snapshot.cumulativeYieldBase, "snapshot");
2726
- tokens.push({
2727
- chain: "BASE",
2728
- chainId: 8453,
2729
- asset: context.asset,
2730
- amount: formatUnits(amount, context.snapshot.baseAssetDecimals)
2731
- });
2732
- lifetimeEarnings += usd(
2733
- amount,
2734
- context.snapshot.baseAssetDecimals,
2735
- context.snapshot.baseAssetPriceUsd
2736
- );
2737
- }
2738
- return {
2739
- smartWallet: contexts[0]?.wallet.walletAddress ?? "0x0000000000000000000000000000000000000000",
2740
- lifetimeEarnings,
2741
- tokens
2742
- };
2743
- }
2744
- function apyForDays(snapshot, days) {
2745
- if (days === "7D") return percent(snapshot.apy7d);
2746
- if (days === "30D") return percent(snapshot.apy30d);
2747
- return percent((snapshot.apy7d + snapshot.apy30d) / 2);
2748
- }
2749
- function dailyApy(point) {
2750
- const total = raw(point.totalValueBase, "historic position");
2751
- const earned = raw(point.dailyYieldBase, "historic position");
2752
- const principal = total - earned;
2753
- if (principal <= 0n || earned === 0n) return 0;
2754
- return Number(earned) / Number(principal) * 365 * 100;
2755
- }
2756
- function aggregateHistory(contexts, dayCount) {
2757
- const byDate = /* @__PURE__ */ new Map();
2758
- for (const context of contexts) {
2759
- const points = context.historic?.dailyYieldSnapshots ?? [];
2760
- for (const point of points.slice(-dayCount)) {
2761
- const valueUsd = usd(
2762
- raw(point.totalValueBase, "historic position"),
2763
- point.baseAssetDecimals,
2764
- point.baseAssetPriceUsd
2765
- );
2766
- const current = byDate.get(point.date) ?? { weighted: 0, valueUsd: 0 };
2767
- current.weighted += dailyApy(point) * valueUsd;
2768
- current.valueUsd += valueUsd;
2769
- byDate.set(point.date, current);
2770
- }
2771
- }
2772
- return [...byDate.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([date, value]) => ({
2773
- date,
2774
- apy: value.valueUsd > 0 ? value.weighted / value.valueUsd : 0
2775
- }));
2776
- }
2777
- function mapYieldseekerApy(walletAddress, contexts, days) {
2778
- let weighted = 0;
2779
- let totalUsd = 0;
2780
- const byAsset = {};
2781
- for (const context of contexts) {
2782
- const valueUsd = usd(
2783
- raw(context.snapshot.totalValueBase, "snapshot"),
2784
- context.snapshot.baseAssetDecimals,
2785
- context.snapshot.baseAssetPriceUsd
2786
- );
2787
- const apy = apyForDays(context.snapshot, days);
2788
- weighted += apy * valueUsd;
2789
- totalUsd += valueUsd;
2790
- byAsset[context.asset] = apy;
2791
- }
2792
- const dayCount = Number(days.slice(0, -1));
2793
- return {
2794
- walletAddress,
2795
- weightedApyAfterFee: totalUsd > 0 ? weighted / totalUsd : 0,
2796
- apyByChainAndAsset: { 8453: byAsset },
2797
- history: aggregateHistory(contexts, dayCount)
2798
- };
2799
- }
2800
- function actionType(value) {
2801
- const normalized = value.toLowerCase();
2802
- if (normalized.includes("deposit")) return "Deposit";
2803
- if (normalized.includes("withdraw")) return "Withdraw";
2804
- if (normalized.includes("yield") || normalized.includes("earn"))
2805
- return "Earned";
2806
- return "Rebalance";
2807
- }
2808
- function transactionHashes(details) {
2809
- if (!details) return [];
2810
- const values = [
2811
- details.transactionHash,
2812
- details.txHash,
2813
- ...Array.isArray(details.transactionHashes) ? details.transactionHashes : [],
2814
- ...Array.isArray(details.txHashes) ? details.txHashes : []
2815
- ];
2816
- return values.filter(
2817
- (value) => typeof value === "string" && /^0x[a-fA-F0-9]{64}$/.test(value)
2818
- ).filter((value, index, all) => all.indexOf(value) === index);
2819
- }
2820
- function actionEntry(action) {
2821
- if (action.actionType.toLowerCase().includes("withdraw")) return void 0;
2822
- return {
2823
- agent: "yieldseeker",
2824
- action: actionType(action.actionType),
2825
- date: action.createdDate,
2826
- oldApy: null,
2827
- newApy: null,
2828
- transactions: [
2829
- {
2830
- txHashes: transactionHashes(action.details),
2831
- chainId: 8453
2832
- }
2833
- ],
2834
- rebalanceLog: []
2835
- };
2836
- }
2837
- function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddresses) {
2838
- const from = movement.fromAddress.toLowerCase();
2839
- const to = movement.toAddress.toLowerCase();
2840
- const owner = ownerAddress.toLowerCase();
2841
- const agentWallet = wallet.walletAddress.toLowerCase();
2842
- const baseAsset = agent.assetAddress.toLowerCase();
2843
- if (movement.chainId !== agent.chainId || movement.assetAddress.toLowerCase() !== baseAsset) {
2844
- return void 0;
2845
- }
2846
- let action;
2847
- if (from === owner && to === agentWallet) {
2848
- action = "Top up";
2849
- } else if (from === agentWallet && to === owner) {
2850
- action = "Withdraw";
2851
- } else if (from === agentWallet && vaultAddresses.has(to)) {
2852
- action = "Deposit";
2853
- }
2854
- if (!action) return void 0;
2855
- return {
2856
- agent: "yieldseeker",
2857
- action,
2858
- date: movement.blockDate,
2859
- oldApy: null,
2860
- newApy: null,
2861
- transactions: [
2862
- {
2863
- txHashes: [movement.transactionHash],
2864
- chainId: agent.chainId,
2865
- tokenSymbol: asset,
2866
- amount: decimal(
2867
- movement.assetAmount,
2868
- YIELDSEEKER_ASSET_METADATA[asset].decimals,
2869
- "historic position"
2870
- )
2871
- }
2872
- ],
2873
- rebalanceLog: []
2874
- };
2875
- }
2876
- function mapYieldseekerHistory(contexts, options) {
2877
- const entries = contexts.flatMap((context) => {
2878
- const vaultAddresses = new Set(
2879
- context.positions.map(
2880
- (position2) => position2.yieldOption.address.toLowerCase()
2881
- )
2882
- );
2883
- return [
2884
- ...(context.historic?.movements ?? []).map(
2885
- (movement) => movementEntry(
2886
- movement,
2887
- context.wallet,
2888
- context.agent,
2889
- context.asset,
2890
- options.ownerAddress,
2891
- vaultAddresses
2892
- )
2893
- ),
2894
- ...(context.actions ?? []).map(actionEntry)
2895
- ].filter((entry) => entry !== void 0);
2896
- });
2897
- const filtered = entries.filter(
2898
- (entry) => (!options.fromDate || entry.date >= options.fromDate) && (!options.toDate || entry.date <= options.toDate)
2899
- ).filter((entry, index, all) => {
2900
- const transactionHash = entry.transactions[0]?.txHashes[0];
2901
- if (!transactionHash) return true;
2902
- return all.findIndex(
2903
- (candidate) => candidate.action === entry.action && candidate.transactions[0]?.txHashes[0] === transactionHash
2904
- ) === index;
2905
- }).sort((left, right) => right.date.localeCompare(left.date));
2906
- return {
2907
- data: filtered.slice(0, options.limit),
2908
- // v1 returns the whole action/movement collection and defines no cursor.
2909
- // Report a terminal page so callers never loop over the same prefix.
2910
- hasMore: false
2911
- };
2912
- }
2913
- function mapYieldseekerProfile(address, contexts) {
2914
- const protocols = /* @__PURE__ */ new Set();
2915
- for (const context of contexts) {
2916
- for (const current of context.positions) {
2917
- if (current.yieldOption?.provider) {
2918
- protocols.add(String(current.yieldOption.provider));
2919
- }
2920
- }
2921
- }
2922
- return {
2923
- address,
2924
- smartWallet: contexts[0]?.wallet.walletAddress ?? "0x0000000000000000000000000000000000000000",
2925
- chains: contexts.length > 0 ? [8453] : [],
2926
- hasActiveSessionKey: contexts.some(
2927
- (context) => context.wallet.initializedDate != null
2928
- ),
2929
- protocols: [...protocols]
2930
- };
2931
- }
2932
- function mapYieldseekerAgentApy(options, days) {
2933
- const perAsset = {};
2934
- const all = [];
2935
- for (const entry of options) {
2936
- const apys = entry.yieldOptions.map(
2937
- (option) => publicApyAfterYieldseekerFee(riskAdjustedApyForDays(option, days))
2938
- ).filter(Number.isFinite);
2939
- if (apys.length === 0) continue;
2940
- const average = apys.reduce((sum, value) => sum + value, 0) / apys.length;
2941
- perAsset[entry.asset] = average;
2942
- all.push(average);
2943
- }
2944
- return {
2945
- averageApy: all.length > 0 ? all.reduce((sum, value) => sum + value, 0) / all.length : 0,
2946
- detailedApys: { apyPerAsset: { 8453: perAsset } }
2947
- };
2948
- }
2949
-
2950
- // src/agents/yieldseeker/yieldseeker.agent.ts
2951
- var OWNEY_AGENT_NAME = "owney";
2952
- var YIELDSEEKER_USERNAME_PREFIX = "owney_";
2953
- var YIELDSEEKER_USERNAME_RANDOM_LENGTH = 14;
2954
- var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
2955
- function generateYieldseekerUsername() {
2956
- const suffix = globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, YIELDSEEKER_USERNAME_RANDOM_LENGTH).toLowerCase();
2957
- return `${YIELDSEEKER_USERNAME_PREFIX}${suffix}`;
2958
- }
2959
- function isUsernameConflict(error) {
2960
- if (!(error instanceof YieldseekerApiError)) return false;
2961
- const code = error.providerCode.toUpperCase();
2962
- return code.includes("USERNAME") && (code.includes("TAKEN") || code.includes("EXIST") || code.includes("UNAVAILABLE") || code.includes("IN_USE"));
2963
- }
2964
- var YIELDSEEKER_AGENT_WALLET_ABI = [
2965
- {
2966
- type: "function",
2967
- name: "withdrawAssetToUser",
2968
- stateMutability: "nonpayable",
2969
- inputs: [
2970
- { name: "recipient", type: "address" },
2971
- { name: "asset", type: "address" },
2972
- { name: "amount", type: "uint256" }
2973
- ],
2974
- outputs: []
2975
- },
2976
- {
2977
- type: "function",
2978
- name: "withdrawAllAssetToUser",
2979
- stateMutability: "nonpayable",
2980
- inputs: [
2981
- { name: "recipient", type: "address" },
2982
- { name: "asset", type: "address" }
2983
- ],
2984
- outputs: []
2985
- }
2986
- ];
2987
- function query(params) {
2988
- const search = new URLSearchParams();
2989
- for (const [key2, value] of Object.entries(params)) {
2990
- if (value !== void 0) search.set(key2, String(value));
2991
- }
2992
- const encoded = search.toString();
2993
- return encoded ? `?${encoded}` : "";
2994
- }
2995
- var YieldseekerAgent = class {
2996
- id = "yieldseeker";
2997
- balanceComposition = "tokens-plus-positions";
2998
- supportedChainIds = [8453];
2999
- supportedAssets = [
3000
- {
3001
- chainId: 8453,
3002
- chain: "BASE",
3003
- assets: [
3004
- { symbol: "USDC", minDepositAmount: "10000000" },
3005
- { symbol: "WETH", minDepositAmount: "1" }
3006
- ]
3007
- }
3008
- ];
3009
- api;
3010
- auth;
3011
- transactionExecutor;
3012
- unwindReceiptWaiter;
3013
- agentContexts = /* @__PURE__ */ new Map();
3014
- users = /* @__PURE__ */ new Map();
3015
- pendingAgents = /* @__PURE__ */ new Map();
3016
- constructor(owneyApiKey, options = {}) {
3017
- this.api = new YieldseekerApiClient(
3018
- owneyApiKey,
3019
- options.baseUrl ?? getYieldseekerProxyBaseUrl(),
3020
- options.fetchFn
3021
- );
3022
- this.auth = new YieldseekerAuth(options.auth);
3023
- this.transactionExecutor = options.transactionExecutor;
3024
- this.unwindReceiptWaiter = options.unwindReceiptWaiter;
3025
- }
3026
- async disconnect() {
3027
- this.auth.clear();
3028
- for (const key2 of this.users.keys()) {
3029
- const [walletAddress, chainId] = key2.split(":");
3030
- clearYieldseekerIdentity(walletAddress, Number(chainId));
3031
- }
3032
- this.users.clear();
3033
- this.agentContexts.clear();
3034
- this.pendingAgents.clear();
3035
- }
3036
- async activateAgent(state, chainId, asset) {
3037
- this.assertChain(chainId);
3038
- const targetAsset = asset ?? "USDC";
3039
- this.assertAsset(targetAsset);
3040
- await this.ensureAgent(state, chainId, targetAsset);
3041
- }
3042
- async deposit(state, chainId, amount, asset, depositCallback) {
3043
- this.assertChain(chainId);
3044
- this.assertAsset(asset);
3045
- if (BigInt(amount) <= 0n) {
3046
- throw new OwneyError(
3047
- "DEPOSIT_AMOUNT_BELOW_MINIMUM",
3048
- "Yieldseeker deposits must be greater than zero.",
3049
- { amount, minDepositAmount: "1" },
3050
- this.id
3051
- );
3052
- }
3053
- const context = await this.ensureAgent(state, chainId, asset);
3054
- let txHash;
3055
- try {
3056
- if (depositCallback) {
3057
- provideDepositVerificationContext(depositCallback, {
3058
- agentId: "yieldseeker",
3059
- signature: await this.auth.getToken(state, chainId),
3060
- userId: context.user.userId,
3061
- yieldseekerAgentId: context.agent.agentId
3062
- });
3063
- txHash = await depositCallback(
3064
- context.wallet.walletAddress,
3065
- chainId,
3066
- amount
3067
- );
3068
- await this.waitForReceipt(state, chainId, txHash);
3069
- } else {
3070
- txHash = await this.submitTransaction(state, chainId, {
3071
- from: getAddress2(state.walletAddress),
3072
- to: YIELDSEEKER_ASSET_METADATA[asset].address,
3073
- data: encodeFunctionData({
3074
- abi: erc20Abi,
3075
- functionName: "transfer",
3076
- args: [getAddress2(context.wallet.walletAddress), BigInt(amount)]
3077
- }),
3078
- value: "0",
3079
- chainId
3080
- });
3081
- }
3082
- await this.deployAfterFunding(state, chainId, context);
3083
- } finally {
3084
- await this.refreshSnapshotAfterMovement(
3085
- state,
3086
- chainId,
3087
- context,
3088
- "deposit"
3089
- );
3090
- }
3091
- return {
3092
- txHash,
3093
- smartWallet: context.wallet.walletAddress,
3094
- amount
3095
- };
3096
- }
3097
- async withdraw(state, chainId, asset, amount) {
3098
- this.assertChain(chainId);
3099
- this.assertAsset(asset);
3100
- if (amount !== void 0 && BigInt(amount) <= 0n) {
3101
- throw new OwneyError(
3102
- "WITHDRAW_FAILED",
3103
- "Yieldseeker withdrawals must be greater than zero.",
3104
- { amount },
3105
- this.id
3106
- );
3107
- }
3108
- const context = await this.findAgent(state, chainId, asset);
3109
- if (!context) {
3110
- throw new OwneyError(
3111
- "WITHDRAW_INSUFFICIENT_BALANCE",
3112
- `No Yieldseeker ${asset} agent exists for this wallet.`,
3113
- { asset, available: "0" },
3114
- this.id
3115
- );
3116
- }
3117
- try {
3118
- const portfolio = await this.loadPortfolioContext(
3119
- state,
3120
- chainId,
3121
- context
3122
- );
3123
- const metadata = YIELDSEEKER_ASSET_METADATA[asset];
3124
- const idleEntry = Object.entries(portfolio.snapshot.tokenBalances).find(
3125
- ([address]) => address.toLowerCase() === metadata.address.toLowerCase()
3126
- );
3127
- const idle = BigInt(idleEntry?.[1] ?? "0");
3128
- const deployed = portfolio.positions.reduce(
3129
- (total, position2) => total + BigInt(position2.withdrawableAssetsRaw),
3130
- 0n
3131
- );
3132
- const totalAvailable = idle + deployed;
3133
- const requested = amount === void 0 ? totalAvailable : BigInt(amount);
3134
- if (requested > totalAvailable) {
3135
- throw new OwneyError(
3136
- "WITHDRAW_INSUFFICIENT_BALANCE",
3137
- `Requested withdrawal "${requested}" exceeds available Yieldseeker balance "${totalAvailable}" for asset "${asset}".`,
3138
- {
3139
- asset,
3140
- requested: requested.toString(),
3141
- available: totalAvailable.toString()
3142
- },
3143
- this.id
3144
- );
3145
- }
3146
- let remaining = requested > idle ? requested - idle : 0n;
3147
- for (const position2 of portfolio.positions) {
3148
- if (remaining === 0n) break;
3149
- const available = BigInt(position2.withdrawableAssetsRaw);
3150
- if (available <= 0n) continue;
3151
- const assetsRaw = available < remaining ? available : remaining;
3152
- const response = await this.walletRequest(
3153
- state,
3154
- chainId,
3155
- this.agentPath(context, "withdraw-from-position"),
3156
- {
3157
- method: "POST",
3158
- body: {
3159
- chainId,
3160
- vaultAddress: position2.yieldOption.address,
3161
- assetsRaw: assetsRaw.toString()
3162
- }
3163
- }
3164
- );
3165
- if (!this.isTransactionHash(response?.transactionHash)) {
3166
- throw this.invalidResponse("position withdrawal");
3167
- }
3168
- await this.waitForReceipt(state, chainId, response.transactionHash);
3169
- remaining -= assetsRaw;
3170
- }
3171
- if (remaining > 0n) {
3172
- throw this.invalidResponse("yield positions", {
3173
- reason: "Withdrawable positions could not cover the request.",
3174
- remaining: remaining.toString()
3175
- });
3176
- }
3177
- const account = getAddress2(state.walletAddress);
3178
- const txHash = await this.submitTransaction(state, chainId, {
3179
- from: account,
3180
- to: getAddress2(context.wallet.walletAddress),
3181
- data: amount === void 0 ? encodeFunctionData({
3182
- abi: YIELDSEEKER_AGENT_WALLET_ABI,
3183
- functionName: "withdrawAllAssetToUser",
3184
- args: [account, metadata.address]
3185
- }) : encodeFunctionData({
3186
- abi: YIELDSEEKER_AGENT_WALLET_ABI,
3187
- functionName: "withdrawAssetToUser",
3188
- args: [account, metadata.address, requested]
3189
- }),
3190
- value: "0",
3191
- chainId
3192
- });
3193
- return {
3194
- txHash,
3195
- type: amount === void 0 ? "full" : "partial",
3196
- amount: requested.toString()
3197
- };
3198
- } finally {
3199
- await this.refreshSnapshotAfterMovement(
3200
- state,
3201
- chainId,
3202
- context,
3203
- "withdrawal"
3204
- );
3205
- }
3206
- }
3207
- async getBalances(state, chainId) {
3208
- this.assertChain(chainId);
3209
- return mapYieldseekerBalances(await this.loadPortfolio(state, chainId, {}));
3210
- }
3211
- async getEarnings(state, chainId) {
3212
- this.assertChain(chainId);
3213
- return mapYieldseekerEarnings(await this.loadPortfolio(state, chainId, {}));
3214
- }
3215
- async getAccountApy(state, chainId, days, tokenSymbol) {
3216
- this.assertChain(chainId);
3217
- const asset = tokenSymbol?.toUpperCase();
3218
- if (asset !== void 0) this.assertAsset(asset);
3219
- const contexts = await this.loadPortfolio(state, chainId, {
3220
- ...asset ? { asset } : {},
3221
- historic: true
3222
- });
3223
- return mapYieldseekerApy(state.walletAddress, contexts, days);
3224
- }
3225
- async getHistory(state, chainId, options) {
3226
- this.assertChain(chainId);
3227
- const asset = options?.tokenSymbol?.toUpperCase();
3228
- if (asset !== void 0) this.assertAsset(asset);
3229
- const contexts = await this.loadPortfolio(state, chainId, {
3230
- ...asset ? { asset } : {},
3231
- historic: true,
3232
- actions: true
3233
- });
3234
- return mapYieldseekerHistory(contexts, {
3235
- limit: options?.limit ?? 10,
3236
- ownerAddress: state.walletAddress,
3237
- ...options?.fromDate ? { fromDate: options.fromDate } : {},
3238
- ...options?.toDate ? { toDate: options.toDate } : {}
3239
- });
3240
- }
3241
- async getUserProfile(state, chainId) {
3242
- this.assertChain(chainId);
3243
- return mapYieldseekerProfile(
3244
- state.walletAddress,
3245
- await this.loadPortfolio(state, chainId, {})
3246
- );
3247
- }
3248
- async getAgentApy(days, options) {
3249
- this.assertOptionalChain(options?.chainId);
3250
- const requested = options?.tokenSymbol?.toUpperCase();
3251
- if (requested !== void 0) this.assertAsset(requested);
3252
- const assets = requested ? [requested] : ["USDC", "WETH"];
3253
- const values = await Promise.all(
3254
- assets.map(async (asset) => {
3255
- const metadata = YIELDSEEKER_ASSET_METADATA[asset];
3256
- const response = await this.api.request(
3257
- `/chains/8453/assets/${metadata.address}/yield-options`
3258
- );
3259
- if (!Array.isArray(response?.yieldOptions)) {
3260
- throw this.invalidResponse("yield options");
3261
- }
3262
- return { asset, yieldOptions: response.yieldOptions };
3263
- })
3264
- );
3265
- return mapYieldseekerAgentApy(values, days);
3266
- }
3267
- userKey(state, chainId) {
3268
- return `${state.walletAddress.toLowerCase()}:${chainId}`;
3269
- }
3270
- contextKey(state, chainId, asset) {
3271
- return `${this.userKey(state, chainId)}:${asset}`;
3272
- }
3273
- async resolveUser(state, chainId) {
3274
- const key2 = this.userKey(state, chainId);
3275
- const inMemory = this.users.get(key2);
3276
- if (inMemory) return inMemory;
3277
- const persisted = readYieldseekerIdentity(state.walletAddress, chainId);
3278
- if (persisted) {
3279
- this.users.set(key2, persisted);
3280
- return persisted;
3281
- }
3282
- const walletAddress = getAddress2(state.walletAddress);
3283
- let user = null;
3284
- try {
3285
- const login = await this.providerRequest(
3286
- state,
3287
- chainId,
3288
- "/users/login-with-wallet",
3289
- { method: "POST", body: { walletAddress } }
3290
- );
3291
- user = login?.user ?? null;
3292
- if (!user) {
3293
- throw this.invalidResponse("wallet login", {
3294
- reason: "A successful login returned no user."
3295
- });
3296
- }
3297
- } catch (error) {
3298
- if (!(error instanceof YieldseekerApiError) || error.providerCode !== "NO_USER") {
3299
- if (error instanceof OwneyError) throw error;
3300
- throw this.mapApiError(error);
3301
- }
3302
- let created;
3303
- for (let attempt = 0; attempt < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS; attempt += 1) {
3304
- try {
3305
- created = await this.providerRequest(
3306
- state,
3307
- chainId,
3308
- "/users",
3309
- {
3310
- method: "POST",
3311
- body: {
3312
- walletAddress,
3313
- username: generateYieldseekerUsername()
3314
- }
3315
- }
3316
- );
3317
- break;
3318
- } catch (createError) {
3319
- const canRetry = isUsernameConflict(createError) && attempt + 1 < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS;
3320
- if (canRetry) continue;
3321
- throw this.mapApiError(createError);
3322
- }
3323
- }
3324
- user = created?.user ?? null;
3325
- }
3326
- if (!user || !/^[a-zA-Z0-9_-]{1,128}$/.test(user.userId)) {
3327
- throw this.invalidResponse("wallet identity");
3328
- }
3329
- const resolved = { userId: user.userId };
3330
- this.users.set(key2, resolved);
3331
- writeYieldseekerIdentity(state.walletAddress, chainId, resolved.userId);
3332
- return resolved;
3333
- }
3334
- forgetUser(state, chainId) {
3335
- this.users.delete(this.userKey(state, chainId));
3336
- clearYieldseekerIdentity(state.walletAddress, chainId);
3337
- }
3338
- async ensureAgent(state, chainId, asset) {
3339
- const key2 = this.contextKey(state, chainId, asset);
3340
- const cached = this.agentContexts.get(key2);
3341
- if (cached) return cached;
3342
- const pending = this.pendingAgents.get(key2);
3343
- if (pending) return pending;
3344
- const request = this.resolveAgent(state, chainId, asset, true).then(
3345
- (context) => {
3346
- if (!context) throw this.invalidResponse("agent creation");
3347
- this.agentContexts.set(key2, context);
3348
- return context;
3349
- }
3350
- );
3351
- this.pendingAgents.set(key2, request);
3352
- try {
3353
- return await request;
3354
- } finally {
3355
- this.pendingAgents.delete(key2);
3356
- }
3357
- }
3358
- async findAgent(state, chainId, asset) {
3359
- const key2 = this.contextKey(state, chainId, asset);
3360
- const cached = this.agentContexts.get(key2);
3361
- if (cached) return cached;
3362
- const context = await this.resolveAgent(state, chainId, asset, false);
3363
- if (context) this.agentContexts.set(key2, context);
3364
- return context;
3365
- }
3366
- async resolveAgent(state, chainId, asset, createIfMissing) {
3367
- const user = await this.resolveUser(state, chainId);
3368
- const response = await this.walletRequest(
3369
- state,
3370
- chainId,
3371
- `/users/${user.userId}/agents`
3372
- );
3373
- if (!Array.isArray(response?.agents)) {
3374
- throw this.invalidResponse("agent list");
3375
- }
3376
- const metadata = YIELDSEEKER_ASSET_METADATA[asset];
3377
- let agent = response.agents.find(
3378
- (candidate) => this.isOwneyAgent(candidate) && candidate.chainId === chainId && candidate.type === "vault" && candidate.assetAddress.toLowerCase() === metadata.address.toLowerCase()
3379
- );
3380
- if (!agent && createIfMissing) {
3381
- const created = await this.walletRequest(
3382
- state,
3383
- chainId,
3384
- `/users/${user.userId}/agents`,
3385
- {
3386
- method: "POST",
3387
- body: {
3388
- name: OWNEY_AGENT_NAME,
3389
- emoji: "\u{1F989}",
3390
- chainId,
3391
- assetAddress: metadata.address,
3392
- type: "vault",
3393
- rulePreset: null
3394
- }
3395
- }
3396
- );
3397
- agent = created?.agent;
3398
- }
3399
- if (!agent) return null;
3400
- this.assertAgent(agent);
3401
- const walletResponse = await this.walletRequest(
3402
- state,
3403
- chainId,
3404
- `/users/${user.userId}/agents/${agent.agentId}/wallet`
3405
- );
3406
- if (!walletResponse?.agentWallet || !isAddress2(walletResponse.agentWallet.walletAddress)) {
3407
- throw this.invalidResponse("agent wallet");
3408
- }
3409
- return { user, agent, wallet: walletResponse.agentWallet, asset };
3410
- }
3411
- async loadPortfolio(state, chainId, options) {
3412
- const user = await this.resolveUser(state, chainId);
3413
- const response = await this.walletRequest(
3414
- state,
3415
- chainId,
3416
- `/users/${user.userId}/agents`
3417
- );
3418
- if (!Array.isArray(response?.agents)) {
3419
- throw this.invalidResponse("agent list");
3420
- }
3421
- const contexts = [];
3422
- for (const agent of response.agents) {
3423
- const asset = this.assetForAgent(agent);
3424
- if (!this.isOwneyAgent(agent) || !asset || agent.chainId !== chainId || agent.type !== "vault" || options.asset && options.asset !== asset) {
3425
- continue;
3426
- }
3427
- this.assertAgent(agent);
3428
- const walletResponse = await this.walletRequest(
3429
- state,
3430
- chainId,
3431
- `/users/${user.userId}/agents/${agent.agentId}/wallet`
3432
- );
3433
- if (!walletResponse?.agentWallet || !isAddress2(walletResponse.agentWallet.walletAddress)) {
3434
- throw this.invalidResponse("agent wallet");
3435
- }
3436
- const context = {
3437
- user,
3438
- agent,
3439
- wallet: walletResponse.agentWallet,
3440
- asset
3441
- };
3442
- this.agentContexts.set(this.contextKey(state, chainId, asset), context);
3443
- contexts.push(context);
3444
- }
3445
- return Promise.all(
3446
- contexts.map(
3447
- (context) => this.loadPortfolioContext(state, chainId, context, options)
3448
- )
3449
- );
3450
- }
3451
- async loadPortfolioContext(state, chainId, context, options = {}) {
3452
- const [snapshot, positions, historic, actions] = await Promise.all([
3453
- this.walletRequest(
3454
- state,
3455
- chainId,
3456
- `${this.agentPath(context, "snapshot")}${query({
3457
- shouldOnlyUseRecentValue: true,
3458
- shouldAllowStaleOnError: true
3459
- })}`
3460
- ),
3461
- this.walletRequest(
3462
- state,
3463
- chainId,
3464
- this.agentPath(context, "yield-positions")
3465
- ),
3466
- options.historic ? this.walletRequest(
3467
- state,
3468
- chainId,
3469
- this.agentPath(context, "wallet/historic-position")
3470
- ) : Promise.resolve(void 0),
3471
- options.actions ? this.walletRequest(
3472
- state,
3473
- chainId,
3474
- this.agentPath(context, "actions")
3475
- ) : Promise.resolve(void 0)
3476
- ]);
3477
- if (!snapshot?.agentSnapshot) {
3478
- throw this.invalidResponse("agent snapshot");
3479
- }
3480
- if (!Array.isArray(positions?.yieldPositions)) {
3481
- throw this.invalidResponse("yield positions");
3482
- }
3483
- return {
3484
- ...context,
3485
- snapshot: snapshot.agentSnapshot,
3486
- positions: positions.yieldPositions,
3487
- ...historic?.position ? { historic: historic.position } : {},
3488
- ...actions?.actions ? { actions: actions.actions } : {}
3489
- };
3490
- }
3491
- async deployAfterFunding(state, chainId, context) {
3492
- if (context.wallet.initializedDate != null) return;
3493
- try {
3494
- const deployed = await this.walletRequest(
3495
- state,
3496
- chainId,
3497
- this.agentPath(context, "deploy"),
3498
- { method: "POST", body: {} }
3499
- );
3500
- if (deployed?.agentWallet) {
3501
- context.wallet = deployed.agentWallet;
3502
- }
3503
- } catch (error) {
3504
- console.warn(
3505
- "[owney-sdk] Yieldseeker deposit is funded but not deployable yet:",
3506
- error
3507
- );
3508
- }
3509
- }
3510
- async refreshSnapshotAfterMovement(state, chainId, context, movement) {
3511
- try {
3512
- const response = await this.walletRequest(
3513
- state,
3514
- chainId,
3515
- `${this.agentPath(context, "snapshot")}${query({
3516
- shouldForceRefresh: true
3517
- })}`
3518
- );
3519
- if (!response?.agentSnapshot) {
3520
- throw this.invalidResponse("agent snapshot refresh");
3521
- }
3522
- } catch (error) {
3523
- console.warn(
3524
- `[owney-sdk] Yieldseeker ${movement} snapshot refresh failed:`,
3525
- error
3526
- );
3527
- }
3528
- }
3529
- agentPath(context, suffix) {
3530
- return `/users/${context.user.userId}/agents/${context.agent.agentId}/${suffix}`;
3531
- }
3532
- async walletRequest(state, chainId, path, options = {}) {
3533
- try {
3534
- return await this.providerRequest(state, chainId, path, options);
3535
- } catch (error) {
3536
- throw this.mapApiError(error);
3537
- }
3538
- }
3539
- async providerRequest(state, chainId, path, options = {}) {
3540
- this.assertChain(chainId);
3541
- const request = (signature2) => this.api.request(path, {
3542
- ...options,
3543
- signature: signature2
3544
- });
3545
- let signature = await this.auth.getToken(state, chainId);
3546
- try {
3547
- return await request(signature);
3548
- } catch (error) {
3549
- if (!(error instanceof YieldseekerApiError)) throw error;
3550
- if (error.providerCode === "NO_USER") throw error;
3551
- if (!error.isAuthenticationError) throw error;
3552
- this.auth.clear(state, chainId);
3553
- signature = await this.auth.getToken(state, chainId);
3554
- try {
3555
- return await request(signature);
3556
- } catch (retryError) {
3557
- if (retryError instanceof YieldseekerApiError && retryError.isAuthenticationError) {
3558
- this.forgetUser(state, chainId);
3559
- }
3560
- throw retryError;
3561
- }
3562
- }
3563
- }
3564
- mapApiError(error) {
3565
- if (!(error instanceof YieldseekerApiError)) {
3566
- return new OwneyError(
3567
- "AGENT_API_ERROR",
3568
- "Yieldseeker request failed.",
3569
- { cause: error instanceof Error ? error.message : String(error) },
3570
- this.id
3571
- );
3572
- }
3573
- const code = error.isAuthenticationError ? "AGENT_AUTH_FAILED" : error.providerCode === "REQUEST_TIMEOUT" ? "AGENT_TIMEOUT" : "AGENT_API_ERROR";
3574
- return new OwneyError(
3575
- code,
3576
- `Yieldseeker request failed: ${error.providerCode}.`,
3577
- {
3578
- statusCode: error.status,
3579
- providerCode: error.providerCode,
3580
- ...error.responseFields ? { fields: error.responseFields } : {}
3581
- },
3582
- this.id
3583
- );
3584
- }
3585
- async submitTransaction(state, chainId, transaction) {
3586
- if (this.transactionExecutor) {
3587
- return this.transactionExecutor(state, chainId, transaction);
3588
- }
3589
- this.assertTransaction(transaction, state, chainId);
3590
- const account = getAddress2(state.walletAddress);
3591
- const walletClient = createWalletClient2({
3592
- account,
3593
- chain: base3,
3594
- transport: custom2(state.provider)
3595
- });
3596
- const publicClient = createPublicClient3({
3597
- chain: base3,
3598
- transport: custom2(state.provider)
3599
- });
3600
- await ensureWalletOnChain(
3601
- publicClient,
3602
- walletClient,
3603
- 8453
3604
- );
3605
- const hash = await walletClient.sendTransaction({
3606
- account,
3607
- chain: base3,
3608
- to: getAddress2(transaction.to),
3609
- data: transaction.data,
3610
- value: BigInt(transaction.value)
3611
- });
3612
- const receipt = await publicClient.waitForTransactionReceipt({
3613
- hash,
3614
- confirmations: 1
3615
- });
3616
- if (receipt.status !== "success") {
3617
- throw new OwneyError(
3618
- "AGENT_TRANSACTION_REVERTED",
3619
- `Yieldseeker transaction reverted (${hash}).`,
3620
- { transactionHash: hash },
3621
- this.id
3622
- );
3623
- }
3624
- return hash;
3625
- }
3626
- async waitForReceipt(state, chainId, transactionHash) {
3627
- if (this.unwindReceiptWaiter) {
3628
- await this.unwindReceiptWaiter(state, chainId, transactionHash);
3629
- return;
3630
- }
3631
- const publicClient = createPublicClient3({
3632
- chain: base3,
3633
- transport: custom2(state.provider)
3634
- });
3635
- const receipt = await publicClient.waitForTransactionReceipt({
3636
- hash: transactionHash,
3637
- confirmations: 1
3638
- });
3639
- if (receipt.status !== "success") {
3640
- throw new OwneyError(
3641
- "AGENT_TRANSACTION_REVERTED",
3642
- `Yieldseeker transaction reverted (${transactionHash}).`,
3643
- { transactionHash },
3644
- this.id
3645
- );
3646
- }
3647
- }
3648
- assertTransaction(transaction, state, chainId) {
3649
- if (!transaction || typeof transaction.from !== "string" || !isAddress2(transaction.from) || typeof transaction.to !== "string" || !isAddress2(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 || getAddress2(transaction.from) !== getAddress2(state.walletAddress)) {
3650
- throw this.invalidResponse("transaction");
3651
- }
3652
- }
3653
- assertAgent(agent) {
3654
- if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !isAddress2(agent.assetAddress) || agent.chainId !== 8453) {
3655
- throw this.invalidResponse("agent");
3656
- }
3657
- }
3658
- isOwneyAgent(agent) {
3659
- return typeof agent.name === "string" && agent.name.trim().toLowerCase() === OWNEY_AGENT_NAME;
3660
- }
3661
- assetForAgent(agent) {
3662
- for (const asset of ["USDC", "WETH"]) {
3663
- if (agent.assetAddress.toLowerCase() === YIELDSEEKER_ASSET_METADATA[asset].address.toLowerCase()) {
3664
- return asset;
3665
- }
3666
- }
3667
- return null;
3668
- }
3669
- isTransactionHash(value) {
3670
- return typeof value === "string" && /^0x[a-fA-F0-9]{64}$/.test(value);
3671
- }
3672
- assertChain(chainId) {
3673
- if (chainId !== 8453) {
3674
- throw new OwneyError(
3675
- "CHAIN_UNSUPPORTED",
3676
- `Yieldseeker does not support chain ${chainId}.`,
3677
- { chainId, supportedChainIds: [8453] },
3678
- this.id
3679
- );
3680
- }
3681
- }
3682
- assertOptionalChain(chainId) {
3683
- if (chainId !== void 0) this.assertChain(chainId);
3684
- }
3685
- assertAsset(asset) {
3686
- if (asset !== "USDC" && asset !== "WETH") {
3687
- throw new OwneyError(
3688
- "ASSET_UNSUPPORTED",
3689
- `Yieldseeker does not support asset ${asset} in the Owney rollout.`,
3690
- {
3691
- asset,
3692
- supportedAssets: ["USDC", "WETH"],
3693
- providerAlsoAdvertises: ["cbBTC"]
3694
- },
3695
- this.id
3696
- );
3697
- }
3698
- }
3699
- invalidResponse(operation, details = {}) {
3700
- return new OwneyError(
3701
- "AGENT_INVALID_RESPONSE",
3702
- `Yieldseeker returned an invalid ${operation} response.`,
3703
- details,
3704
- this.id
3705
- );
3706
- }
2123
+ // src/lib/chain-guard.ts
2124
+ var CHAIN_NAMES = {
2125
+ 1: "Ethereum",
2126
+ 8453: "Base",
2127
+ 42161: "Arbitrum"
3707
2128
  };
3708
-
3709
- // src/lib/routing-api.ts
3710
- var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
3711
- async function fetchOrgAgentConfig(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
3712
- const url = `${baseUrl}/api/v1/agent/org-config`;
3713
- try {
3714
- const res = await fetch(url, {
3715
- method: "GET",
3716
- headers: {
3717
- "Content-Type": "application/json",
3718
- "x-owney-api-key": `${apiKey}`
3719
- }
3720
- });
3721
- if (!res.ok) {
3722
- if (res.status !== 404) {
3723
- console.warn(
3724
- `[owney-sdk] Could not read org agent config (${res.status}); leaving user profiles unchanged.`
3725
- );
3726
- }
3727
- return null;
3728
- }
3729
- const json = await res.json();
3730
- const policy = json.success ? json.data ?? null : null;
3731
- debugLog(
3732
- "owney-sdk",
3733
- policy ? "org agent config: loaded" : "org agent config: none set by this partner \u2014 user profiles will be left as they are",
3734
- policy ?? void 0
3735
- );
3736
- return policy;
3737
- } catch (error) {
3738
- console.warn(
3739
- "[owney-sdk] Could not read org agent config (non-fatal):",
3740
- error instanceof Error ? error.message : String(error)
3741
- );
3742
- return null;
3743
- }
3744
- }
3745
- async function fetchAgentKeys(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
3746
- const url = `${baseUrl}/api/v1/agent/keys`;
3747
- const res = await fetch(url, {
3748
- method: "GET",
3749
- headers: {
3750
- "Content-Type": "application/json",
3751
- "x-owney-api-key": `${apiKey}`
3752
- }
3753
- });
3754
- if (!res.ok) {
3755
- const text = await res.text().catch(() => "");
3756
- throw new OwneyError(
3757
- "API_ROUTING_ERROR",
3758
- `Routing API error ${res.status}: ${text}`,
3759
- { statusCode: res.status, responseBody: text }
3760
- );
3761
- }
3762
- const json = await res.json();
3763
- if (!json.success) {
3764
- throw new OwneyError(
3765
- "API_ROUTING_FAILED",
3766
- `Routing API request failed: ${json.message}`,
3767
- { message: json.message }
3768
- );
3769
- }
3770
- return json.data;
3771
- }
3772
-
3773
- // src/lib/health-report.ts
3774
- var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
3775
- async function reportAgentFailure(apiKey, agentType, errorCode, baseUrl = ROUTING_API_BASE_URL3) {
3776
- try {
3777
- await fetch(`${baseUrl}/api/v1/agent/health-report`, {
3778
- method: "POST",
3779
- headers: {
3780
- "Content-Type": "application/json",
3781
- "x-owney-api-key": apiKey
3782
- },
3783
- body: JSON.stringify({
3784
- agent_type: agentType,
3785
- error_code: errorCode,
3786
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
3787
- })
3788
- });
3789
- } catch (err) {
3790
- console.warn(
3791
- `[owney-sdk] health-report failed for agent "${agentType}":`,
3792
- err instanceof Error ? err.message : err
3793
- );
3794
- }
3795
- }
3796
- async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
3797
- try {
3798
- return await fn();
3799
- } catch (err) {
3800
- const errorCode = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
3801
- void reportAgentFailure(apiKey, agentType, errorCode, baseUrl);
3802
- throw err;
3803
- }
3804
- }
3805
-
3806
- // src/lib/helpers/withdraw-helper.ts
3807
- import { parseUnits } from "viem";
3808
- function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
3809
- const target = asset.toUpperCase();
3810
- return agents.map((agent) => {
3811
- const agentBalance = aggregated[agent.id];
3812
- const tokenBalance = agentBalance?.tokens.find(
3813
- (t) => t.chainId === chainId && t.asset.toUpperCase() === target
3814
- );
3815
- let balance = tokenBalance ? parseUnits(tokenBalance.amount, decimals) : 0n;
3816
- if (agent.balanceComposition === "tokens-plus-positions") {
3817
- const chainNameById = {
3818
- 1: "ETHEREUM",
3819
- 8453: "BASE",
3820
- 42161: "ARBITRUM"
3821
- };
3822
- const targetChain = chainNameById[chainId];
3823
- for (const position2 of agentBalance?.positions ?? []) {
3824
- const positionChain = position2.chain.trim().toUpperCase();
3825
- const matchesChain = positionChain === String(chainId) || targetChain !== void 0 && positionChain === targetChain;
3826
- if (!matchesChain || position2.asset.toUpperCase() !== target) continue;
3827
- if (position2.amountRaw !== void 0) {
3828
- try {
3829
- balance += BigInt(position2.amountRaw);
3830
- continue;
3831
- } catch {
3832
- }
3833
- }
3834
- balance += parseUnits(position2.amount, decimals);
3835
- }
3836
- }
3837
- return { agent, balance };
3838
- });
3839
- }
3840
- function planProportionalShares(balances, requested, totalAvailable) {
3841
- const plans = balances.map(({ agent, balance }) => ({
3842
- agent,
3843
- balance,
3844
- planned: totalAvailable > 0n ? balance * requested / totalAvailable : 0n
3845
- }));
3846
- const assigned = plans.reduce((s, p) => s + p.planned, 0n);
3847
- let remainder = requested - assigned;
3848
- const byHeadroom = [...plans].sort((a, b) => {
3849
- const diff = b.balance - b.planned - (a.balance - a.planned);
3850
- return diff > 0n ? 1 : diff < 0n ? -1 : 0;
3851
- });
3852
- for (const p of byHeadroom) {
3853
- if (remainder === 0n) break;
3854
- const headroom = p.balance - p.planned;
3855
- if (headroom <= 0n) continue;
3856
- const take = headroom < remainder ? headroom : remainder;
3857
- p.planned += take;
3858
- remainder -= take;
3859
- }
3860
- return plans;
3861
- }
3862
- function planDisabledDrain(disabled, requested) {
3863
- const sorted = [...disabled].filter((d) => d.balance > 0n).sort(
3864
- (a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0
3865
- );
3866
- const plans = [];
3867
- let remaining = requested;
3868
- for (const { agent, balance } of sorted) {
3869
- if (remaining === 0n) {
3870
- plans.push({ agent, balance, planned: 0n });
3871
- continue;
3872
- }
3873
- const take = balance < remaining ? balance : remaining;
3874
- plans.push({ agent, balance, planned: take });
3875
- remaining -= take;
3876
- }
3877
- return { plans, remaining };
2129
+ function chainName(chainId) {
2130
+ return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
3878
2131
  }
3879
- function redistributeShare(plans, fromIndex, amount, candidatePool) {
3880
- const pool = candidatePool ?? plans.slice(fromIndex + 1);
3881
- const candidates = pool.filter((c) => c.balance - c.planned > 0n);
3882
- const totalHeadroom = candidates.reduce(
3883
- (s, c) => s + (c.balance - c.planned),
3884
- 0n
3885
- );
3886
- if (totalHeadroom === 0n) return;
3887
- let distributed = 0n;
3888
- for (const c of candidates) {
3889
- const headroom = c.balance - c.planned;
3890
- const proportional = headroom * amount / totalHeadroom;
3891
- const give = proportional > headroom ? headroom : proportional;
3892
- c.planned += give;
3893
- distributed += give;
2132
+ async function ensureWalletOnChain(pub, wallet, expected) {
2133
+ const actual = await pub.getChainId();
2134
+ if (actual === expected) return;
2135
+ try {
2136
+ await wallet.switchChain({ id: expected });
2137
+ } catch (error) {
2138
+ throw new OwneyError(
2139
+ "CHAIN_MISMATCH",
2140
+ `Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
2141
+ {
2142
+ expectedChainId: expected,
2143
+ actualChainId: actual,
2144
+ cause: error instanceof Error ? error.message : String(error)
2145
+ }
2146
+ );
3894
2147
  }
3895
- let leftover = amount - distributed;
3896
- for (const c of candidates) {
3897
- if (leftover === 0n) break;
3898
- const headroom = c.balance - c.planned;
3899
- if (headroom <= 0n) continue;
3900
- const take = headroom < leftover ? headroom : leftover;
3901
- c.planned += take;
3902
- leftover -= take;
2148
+ const after = await pub.getChainId();
2149
+ if (after !== expected) {
2150
+ throw new OwneyError(
2151
+ "CHAIN_MISMATCH",
2152
+ `Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
2153
+ { expectedChainId: expected, actualChainId: after }
2154
+ );
3903
2155
  }
3904
2156
  }
3905
- function sumWithdrawnAmount(results) {
3906
- return Object.values(results).reduce((sum, r) => sum + BigInt(r.amount), 0n);
3907
- }
3908
2157
 
3909
- // src/lib/helpers/account-apy-helper.ts
3910
- function balanceForApyScope(balance, chainId, tokenSymbol) {
3911
- if (!tokenSymbol) {
3912
- const total = Number(balance.totalBalance);
3913
- return Number.isFinite(total) && total > 0 ? total : 0;
3914
- }
3915
- const normalizedToken = tokenSymbol.toUpperCase();
3916
- return balance.tokens.reduce((total, token) => {
3917
- if (Number(token.chainId) !== chainId || String(token.asset).toUpperCase() !== normalizedToken) {
3918
- return total;
3919
- }
3920
- const amount = Number(token.amount);
3921
- return Number.isFinite(amount) && amount > 0 ? total + amount : total;
3922
- }, 0);
3923
- }
3924
- function aggregateApyHistory(agentApys, agentBalances) {
3925
- const byDate = /* @__PURE__ */ new Map();
3926
- for (const [id, accountApy] of Object.entries(agentApys)) {
3927
- const balance = agentBalances[id] ?? 0;
3928
- if (!Number.isFinite(balance) || balance <= 0) continue;
3929
- for (const point of accountApy.history ?? []) {
3930
- const apy = Number(point.apy);
3931
- if (!point.date || !Number.isFinite(apy)) continue;
3932
- const current = byDate.get(point.date) ?? { weightedSum: 0, weight: 0 };
3933
- current.weightedSum += apy * balance;
3934
- current.weight += balance;
3935
- byDate.set(point.date, current);
2158
+ // src/lib/sponsored-deposit.ts
2159
+ var AUTH_WINDOW_SECONDS = 15 * 60;
2160
+ function makeSponsoredDepositCallback(deps) {
2161
+ const post = deps.httpPost ?? postSponsorTransferAuth;
2162
+ return async (smartWallet, chainId, amount) => {
2163
+ const cid = chainId;
2164
+ const token = deps.tokenAddressByChain[cid];
2165
+ if (!token) {
2166
+ throw new OwneyError(
2167
+ "CHAIN_UNSUPPORTED",
2168
+ `No sponsored token configured for chain ${chainId}`
2169
+ );
3936
2170
  }
3937
- }
3938
- return [...byDate.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([date, value]) => ({
3939
- date,
3940
- apy: value.weightedSum / value.weight
3941
- }));
3942
- }
3943
- function aggregateApyByChainAndAsset(agentApys, agentBalances) {
3944
- const sums = {};
3945
- const weights = {};
3946
- for (const id of Object.keys(agentApys)) {
3947
- const cells = agentApys[id].apyByChainAndAsset;
3948
- const balance = agentBalances[id] ?? 0;
3949
- if (!cells || balance <= 0) continue;
3950
- for (const [chainKey, perAsset] of Object.entries(cells)) {
3951
- if (!perAsset) continue;
3952
- const chainId = Number(chainKey);
3953
- for (const [asset, apyValue] of Object.entries(perAsset)) {
3954
- const apy = Number(apyValue ?? 0);
3955
- if (apy === 0) continue;
3956
- sums[chainId] ??= {};
3957
- weights[chainId] ??= {};
3958
- sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
3959
- weights[chainId][asset] = (weights[chainId][asset] ?? 0) + balance;
2171
+ const pub = deps.getPublicClient(cid);
2172
+ const wallet = deps.getWalletClient(cid);
2173
+ await ensureWalletOnChain(pub, wallet, cid);
2174
+ try {
2175
+ const balance = await readErc20Balance(pub, token, deps.ownerAddress);
2176
+ if (balance < BigInt(amount)) {
2177
+ throw new OwneyError(
2178
+ "DEPOSIT_INSUFFICIENT_BALANCE",
2179
+ "Insufficient balance for this deposit.",
2180
+ { token, chainId: cid, balance: balance.toString(), amount }
2181
+ );
3960
2182
  }
3961
- }
3962
- }
3963
- const out = {};
3964
- for (const chainKey of Object.keys(sums)) {
3965
- const chainId = Number(chainKey);
3966
- const perAssetOut = {};
3967
- for (const asset of Object.keys(sums[chainId])) {
3968
- const w = weights[chainId][asset];
3969
- if (w > 0) perAssetOut[asset] = sums[chainId][asset] / w;
3970
- }
3971
- if (Object.keys(perAssetOut).length > 0) {
3972
- out[chainId] = perAssetOut;
3973
- }
3974
- }
3975
- return out;
2183
+ } catch (err) {
2184
+ if (err instanceof OwneyError) throw err;
2185
+ console.warn(
2186
+ "[owney-sdk] Deposit balance pre-check failed (non-fatal):",
2187
+ err instanceof Error ? err.message : String(err)
2188
+ );
2189
+ }
2190
+ const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
2191
+ const validAfter = 0n;
2192
+ const validBefore = BigInt(
2193
+ Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
2194
+ );
2195
+ const nonce = randomAuthNonce();
2196
+ const typedData = buildTransferWithAuthorizationTypedData({
2197
+ token,
2198
+ chainId: cid,
2199
+ tokenName,
2200
+ tokenVersion,
2201
+ message: {
2202
+ from: deps.ownerAddress,
2203
+ to: smartWallet,
2204
+ value: BigInt(amount),
2205
+ validAfter,
2206
+ validBefore,
2207
+ nonce
2208
+ }
2209
+ });
2210
+ const authSignature = await wallet.signTypedData({
2211
+ account: deps.ownerAddress,
2212
+ ...typedData
2213
+ });
2214
+ deps.onApproved?.();
2215
+ const result = await post({
2216
+ baseUrl: deps.baseUrl,
2217
+ apiKey: deps.apiKey,
2218
+ body: {
2219
+ chainId: cid,
2220
+ token,
2221
+ from: deps.ownerAddress,
2222
+ to: smartWallet,
2223
+ value: amount,
2224
+ validAfter: validAfter.toString(),
2225
+ validBefore: validBefore.toString(),
2226
+ nonce,
2227
+ authSignature,
2228
+ tokenName,
2229
+ tokenVersion
2230
+ }
2231
+ });
2232
+ return result.txHash;
2233
+ };
3976
2234
  }
3977
2235
 
3978
- // src/client.ts
3979
- import {
3980
- createPublicClient as createPublicClient4,
3981
- createWalletClient as createWalletClient3,
3982
- custom as custom3
3983
- } from "viem";
3984
- import { base as base4, arbitrum as arbitrum2, mainnet as mainnet2 } from "viem/chains";
3985
-
3986
2236
  // src/lib/sponsored-weth-deposit.ts
3987
2237
  var PERMIT_WINDOW_SECONDS = 15 * 60;
3988
2238
  function makeSponsoredWethCallback(deps) {
3989
2239
  const get = deps.httpGet ?? getSponsorRelayerAddress;
3990
2240
  const post = deps.httpPost ?? postSponsorPermit2Transfer;
3991
- return makeVerificationAwareDepositCallback(
3992
- async (smartWallet, chainId, amount, verification) => {
3993
- const cid = chainId;
3994
- const token = deps.tokenAddressByChain[cid];
3995
- if (!token) {
3996
- throw new OwneyError(
3997
- "CHAIN_UNSUPPORTED",
3998
- `No sponsored WETH configured for chain ${chainId}`
3999
- );
4000
- }
4001
- const amountWei = BigInt(amount);
4002
- const pub = deps.getPublicClient(cid);
4003
- const wallet = deps.getWalletClient(cid);
4004
- await ensureWalletOnChain(pub, wallet, cid);
4005
- try {
4006
- const balance = await readErc20Balance(pub, token, deps.ownerAddress);
4007
- if (balance < amountWei) {
4008
- throw new OwneyError(
4009
- "DEPOSIT_INSUFFICIENT_BALANCE",
4010
- "Insufficient WETH balance for this deposit.",
4011
- { token, chainId: cid, balance: balance.toString(), amount }
4012
- );
4013
- }
4014
- } catch (err) {
4015
- if (err instanceof OwneyError) throw err;
4016
- console.warn(
4017
- "[owney-sdk] WETH balance pre-check failed (non-fatal):",
4018
- err instanceof Error ? err.message : String(err)
4019
- );
4020
- }
4021
- const allowance = await readPermit2Allowance(
4022
- pub,
4023
- token,
4024
- deps.ownerAddress
2241
+ return async (smartWallet, chainId, amount) => {
2242
+ const cid = chainId;
2243
+ const token = deps.tokenAddressByChain[cid];
2244
+ if (!token) {
2245
+ throw new OwneyError(
2246
+ "CHAIN_UNSUPPORTED",
2247
+ `No sponsored WETH configured for chain ${chainId}`
4025
2248
  );
4026
- if (allowance < amountWei) {
2249
+ }
2250
+ const amountWei = BigInt(amount);
2251
+ const pub = deps.getPublicClient(cid);
2252
+ const wallet = deps.getWalletClient(cid);
2253
+ await ensureWalletOnChain(pub, wallet, cid);
2254
+ try {
2255
+ const balance = await readErc20Balance(pub, token, deps.ownerAddress);
2256
+ if (balance < amountWei) {
4027
2257
  throw new OwneyError(
4028
- "PERMIT2_APPROVAL_REQUIRED",
4029
- "WETH gasless deposits need a one-time Permit2 approval; call approvePermit2() first",
4030
- { token, chainId: cid, allowance: allowance.toString(), amount }
2258
+ "DEPOSIT_INSUFFICIENT_BALANCE",
2259
+ "Insufficient WETH balance for this deposit.",
2260
+ { token, chainId: cid, balance: balance.toString(), amount }
4031
2261
  );
4032
2262
  }
4033
- const relayer = await get({
4034
- baseUrl: deps.baseUrl,
4035
- apiKey: deps.apiKey,
4036
- chainId: cid
4037
- });
4038
- const nonce = randomPermit2Nonce();
4039
- const deadline = BigInt(
4040
- Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
2263
+ } catch (err) {
2264
+ if (err instanceof OwneyError) throw err;
2265
+ console.warn(
2266
+ "[owney-sdk] WETH balance pre-check failed (non-fatal):",
2267
+ err instanceof Error ? err.message : String(err)
4041
2268
  );
4042
- const typedData = buildPermitTransferFromTypedData({
4043
- chainId: cid,
4044
- message: {
4045
- permitted: { token, amount: amountWei },
4046
- spender: relayer,
4047
- nonce,
4048
- deadline
4049
- }
4050
- });
4051
- const signature = await wallet.signTypedData({
4052
- account: deps.ownerAddress,
4053
- ...typedData
4054
- });
4055
- deps.onApproved?.();
4056
- const result = await post({
4057
- baseUrl: deps.baseUrl,
4058
- apiKey: deps.apiKey,
4059
- ...verification?.agentId === "yieldseeker" ? { yieldseekerSignature: verification.signature } : {},
4060
- body: {
4061
- chainId: cid,
4062
- token,
4063
- from: deps.ownerAddress,
4064
- to: smartWallet,
4065
- amount,
4066
- nonce: nonce.toString(),
4067
- deadline: deadline.toString(),
4068
- signature,
4069
- ...verification?.agentId === "yieldseeker" ? {
4070
- yieldseekerUserId: verification.userId,
4071
- yieldseekerAgentId: verification.yieldseekerAgentId
4072
- } : {}
4073
- }
4074
- });
4075
- return result.txHash;
4076
2269
  }
4077
- );
2270
+ const allowance = await readPermit2Allowance(pub, token, deps.ownerAddress);
2271
+ if (allowance < amountWei) {
2272
+ throw new OwneyError(
2273
+ "PERMIT2_APPROVAL_REQUIRED",
2274
+ "WETH gasless deposits need a one-time Permit2 approval; call approvePermit2() first",
2275
+ { token, chainId: cid, allowance: allowance.toString(), amount }
2276
+ );
2277
+ }
2278
+ const relayer = await get({
2279
+ baseUrl: deps.baseUrl,
2280
+ apiKey: deps.apiKey,
2281
+ chainId: cid
2282
+ });
2283
+ const nonce = randomPermit2Nonce();
2284
+ const deadline = BigInt(
2285
+ Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
2286
+ );
2287
+ const typedData = buildPermitTransferFromTypedData({
2288
+ chainId: cid,
2289
+ message: {
2290
+ permitted: { token, amount: amountWei },
2291
+ spender: relayer,
2292
+ nonce,
2293
+ deadline
2294
+ }
2295
+ });
2296
+ const signature = await wallet.signTypedData({
2297
+ account: deps.ownerAddress,
2298
+ ...typedData
2299
+ });
2300
+ deps.onApproved?.();
2301
+ const result = await post({
2302
+ baseUrl: deps.baseUrl,
2303
+ apiKey: deps.apiKey,
2304
+ body: {
2305
+ chainId: cid,
2306
+ token,
2307
+ from: deps.ownerAddress,
2308
+ to: smartWallet,
2309
+ amount,
2310
+ nonce: nonce.toString(),
2311
+ deadline: deadline.toString(),
2312
+ signature
2313
+ }
2314
+ });
2315
+ return result.txHash;
2316
+ };
4078
2317
  }
4079
2318
 
4080
2319
  // src/lib/sponsored-calls-deposit.ts
4081
- import { encodeFunctionData as encodeFunctionData2, erc20Abi as erc20Abi2, toHex } from "viem";
2320
+ import { encodeFunctionData, erc20Abi, toHex } from "viem";
4082
2321
  var DEFAULT_POLL_INTERVAL_MS = 1500;
4083
2322
  var DEFAULT_MAX_POLLS = 30;
4084
2323
  async function paymasterSupported(provider, owner, chainId) {
@@ -4104,7 +2343,7 @@ function makeSponsoredCallsCallback(deps) {
4104
2343
  }
4105
2344
  return new URL(configured, origin).toString();
4106
2345
  };
4107
- return makeVerificationAwareDepositCallback(async (smartWallet, chainId, amount, verification) => {
2346
+ return async (smartWallet, chainId, amount) => {
4108
2347
  const cid = chainId;
4109
2348
  const token = deps.tokenAddressByChain[cid];
4110
2349
  if (!token) {
@@ -4120,37 +2359,11 @@ function makeSponsoredCallsCallback(deps) {
4120
2359
  { chainId }
4121
2360
  );
4122
2361
  }
4123
- const data = encodeFunctionData2({
4124
- abi: erc20Abi2,
2362
+ const data = encodeFunctionData({
2363
+ abi: erc20Abi,
4125
2364
  functionName: "transfer",
4126
2365
  args: [smartWallet, BigInt(amount)]
4127
2366
  });
4128
- let paymasterUrl = absolutePaymasterUrl();
4129
- if (verification?.agentId === "yieldseeker") {
4130
- if (chainId !== 8453) {
4131
- throw new OwneyError(
4132
- "CHAIN_UNSUPPORTED",
4133
- `Yieldseeker Base Account sponsorship is not available on chain ${chainId}.`
4134
- );
4135
- }
4136
- const { intent } = await postPaymasterIntent({
4137
- baseUrl: deps.routingApiBaseUrl,
4138
- apiKey: deps.apiKey,
4139
- yieldseekerSignature: verification.signature,
4140
- body: {
4141
- chainId,
4142
- token,
4143
- from: deps.ownerAddress,
4144
- to: smartWallet,
4145
- amount,
4146
- yieldseekerUserId: verification.userId,
4147
- yieldseekerAgentId: verification.yieldseekerAgentId
4148
- }
4149
- });
4150
- const url = new URL(paymasterUrl);
4151
- url.searchParams.set("owneyIntent", intent);
4152
- paymasterUrl = url.toString();
4153
- }
4154
2367
  const sendResult = await deps.provider.request({
4155
2368
  method: "wallet_sendCalls",
4156
2369
  params: [
@@ -4161,7 +2374,7 @@ function makeSponsoredCallsCallback(deps) {
4161
2374
  atomicRequired: false,
4162
2375
  calls: [{ to: token, value: "0x0", data }],
4163
2376
  capabilities: {
4164
- paymasterService: { url: paymasterUrl }
2377
+ paymasterService: { url: absolutePaymasterUrl() }
4165
2378
  }
4166
2379
  }
4167
2380
  ]
@@ -4191,7 +2404,7 @@ function makeSponsoredCallsCallback(deps) {
4191
2404
  `No receipt for calls ${callsId} after ${maxPolls} polls; the deposit may still settle.`,
4192
2405
  { chainId, callsId }
4193
2406
  );
4194
- });
2407
+ };
4195
2408
  }
4196
2409
 
4197
2410
  // src/client.ts
@@ -4221,10 +2434,11 @@ var SPONSORED_USDC_BY_CHAIN = {
4221
2434
  1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
4222
2435
  };
4223
2436
  var VIEM_CHAIN2 = {
4224
- 8453: base4,
2437
+ 8453: base2,
4225
2438
  42161: arbitrum2,
4226
2439
  1: mainnet2
4227
2440
  };
2441
+ var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai"];
4228
2442
  var SPONSORED_WETH_BY_CHAIN = {
4229
2443
  8453: "0x4200000000000000000000000000000000000006",
4230
2444
  42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -4251,9 +2465,9 @@ var OwneySDK = class {
4251
2465
  orgAgentConfig;
4252
2466
  orgAgentConfigPromise = null;
4253
2467
  zyfaiRpcUrls;
4254
- yieldseekerApiBaseUrl;
4255
2468
  routingApiBaseUrl;
4256
2469
  referralSource;
2470
+ surfliquidApiBaseUrl;
4257
2471
  cachedSponsoredCallback = null;
4258
2472
  cachedWethSponsoredCallback = null;
4259
2473
  paymasterServiceUrl;
@@ -4263,10 +2477,10 @@ var OwneySDK = class {
4263
2477
  this.apiKey = config.apiKey;
4264
2478
  if (config.debug) setOwneyDebug(true);
4265
2479
  this.zyfaiRpcUrls = config.zyfaiRpcUrls;
4266
- this.yieldseekerApiBaseUrl = config.yieldseekerApiBaseUrl;
4267
2480
  this.routingApiBaseUrl = config.routingApiBaseUrl;
4268
2481
  this.paymasterServiceUrl = config.paymasterServiceUrl;
4269
2482
  this.referralSource = config.referralSource;
2483
+ this.surfliquidApiBaseUrl = config.surfliquidApiBaseUrl;
4270
2484
  }
4271
2485
  /**
4272
2486
  * Establish connection state for all subsequent SDK calls.
@@ -4366,14 +2580,14 @@ var OwneySDK = class {
4366
2580
  // Casts work around viem's chain-narrowed Client vs the generic
4367
2581
  // PublicClient/WalletClient param types — structurally identical at
4368
2582
  // runtime, but the two share a name TS treats as unrelated.
4369
- getPublicClient: (cid) => createPublicClient4({
2583
+ getPublicClient: (cid) => createPublicClient2({
4370
2584
  chain: VIEM_CHAIN2[cid],
4371
- transport: custom3(provider)
2585
+ transport: custom(provider)
4372
2586
  }),
4373
- getWalletClient: (cid) => createWalletClient3({
2587
+ getWalletClient: (cid) => createWalletClient({
4374
2588
  account: owner,
4375
2589
  chain: VIEM_CHAIN2[cid],
4376
- transport: custom3(provider)
2590
+ transport: custom(provider)
4377
2591
  })
4378
2592
  });
4379
2593
  if (!onApproved) this.cachedSponsoredCallback = callback;
@@ -4390,8 +2604,6 @@ var OwneySDK = class {
4390
2604
  if (!onApproved && cached) return cached;
4391
2605
  const provider = this.requireConnectedProvider();
4392
2606
  const callback = makeSponsoredCallsCallback({
4393
- apiKey: this.apiKey,
4394
- routingApiBaseUrl: this.routingApiBaseUrl,
4395
2607
  provider,
4396
2608
  ownerAddress: this.state.walletAddress,
4397
2609
  paymasterServiceUrl: this.paymasterServiceUrl,
@@ -4421,14 +2633,14 @@ var OwneySDK = class {
4421
2633
  // Casts work around viem's chain-narrowed Client vs the generic
4422
2634
  // PublicClient/WalletClient param types — structurally identical at
4423
2635
  // runtime, but the two share a name TS treats as unrelated.
4424
- getPublicClient: (cid) => createPublicClient4({
2636
+ getPublicClient: (cid) => createPublicClient2({
4425
2637
  chain: VIEM_CHAIN2[cid],
4426
- transport: custom3(provider)
2638
+ transport: custom(provider)
4427
2639
  }),
4428
- getWalletClient: (cid) => createWalletClient3({
2640
+ getWalletClient: (cid) => createWalletClient({
4429
2641
  account: owner,
4430
2642
  chain: VIEM_CHAIN2[cid],
4431
- transport: custom3(provider)
2643
+ transport: custom(provider)
4432
2644
  })
4433
2645
  });
4434
2646
  if (!onApproved) this.cachedWethSponsoredCallback = callback;
@@ -4459,10 +2671,12 @@ var OwneySDK = class {
4459
2671
  this.orgAgentConfigPromise = fetchOrgAgentConfig(
4460
2672
  this.apiKey,
4461
2673
  this.routingApiBaseUrl
4462
- ).then((config) => {
4463
- this.orgAgentConfig = config;
4464
- return config;
4465
- });
2674
+ ).then(
2675
+ (config) => {
2676
+ this.orgAgentConfig = config;
2677
+ return config;
2678
+ }
2679
+ );
4466
2680
  }
4467
2681
  return this.orgAgentConfigPromise;
4468
2682
  }
@@ -4502,15 +2716,8 @@ var OwneySDK = class {
4502
2716
  this.routingApiBaseUrl
4503
2717
  );
4504
2718
  this.disabledAgents.clear();
4505
- for (const {
4506
- key: key2,
4507
- agent_type,
4508
- is_enabled,
4509
- is_configured
4510
- } of agentKeys) {
4511
- const configured = is_configured ?? Boolean(key2);
4512
- if (!configured) continue;
4513
- const agent = this.createAgent(agent_type, key2);
2719
+ for (const { key: key2, agent_type, project_name, is_enabled } of agentKeys) {
2720
+ const agent = await this.createAgent(agent_type, key2, project_name);
4514
2721
  if (!agent) continue;
4515
2722
  this.agents.set(agent_type, agent);
4516
2723
  if (is_enabled === false) {
@@ -4531,49 +2738,26 @@ var OwneySDK = class {
4531
2738
  this.initializingAgentsPromise = null;
4532
2739
  }
4533
2740
  }
4534
- createAgent(agentId, key2) {
2741
+ async createAgent(agentId, key2, projectName) {
4535
2742
  if (agentId === "zyfai") {
4536
- if (!key2) return null;
4537
2743
  return new ZyfaiAgent(key2, this.zyfaiRpcUrls, this.referralSource);
4538
2744
  }
4539
- if (agentId === "yieldseeker") {
4540
- return new YieldseekerAgent(this.apiKey, {
4541
- baseUrl: this.yieldseekerApiBaseUrl ?? getYieldseekerProxyBaseUrl(this.routingApiBaseUrl)
2745
+ if (agentId === "surfliquid") {
2746
+ if (!projectName) return null;
2747
+ const { SurfLiquidAgent } = await import("./surfliquid.agent-5CWKYMRL.js");
2748
+ return new SurfLiquidAgent({
2749
+ projectName,
2750
+ appId: key2,
2751
+ // Same-origin proxy override — SurfLiquid auth is an httpOnly cookie,
2752
+ // which WebKit (iOS) discards when it is third-party. See
2753
+ // OwneySDKConfig.surfliquidApiBaseUrl.
2754
+ apiBaseUrl: this.surfliquidApiBaseUrl,
2755
+ apiKey: this.apiKey,
2756
+ routingApiBaseUrl: this.routingApiBaseUrl
4542
2757
  });
4543
2758
  }
4544
2759
  return null;
4545
2760
  }
4546
- /**
4547
- * Discover the agents actually returned by routing for this organization.
4548
- * Consumers should use this instead of hardcoding a global agent roster.
4549
- */
4550
- async getAvailableAgents(options = {}) {
4551
- await this.ensureAgentsInitialized();
4552
- const { chainId, asset, includeDisabled = false } = options;
4553
- const available = [];
4554
- for (const [id, agent] of this.agents) {
4555
- const isEnabled = !this.isAgentDisabled(id);
4556
- if (!includeDisabled && !isEnabled) continue;
4557
- if (chainId !== void 0 && !agent.supportedChainIds.includes(chainId)) {
4558
- continue;
4559
- }
4560
- if (asset !== void 0) {
4561
- const supportsAsset = agent.supportedAssets.some(
4562
- (entry) => (chainId === void 0 || entry.chainId === chainId) && entry.assets.some((candidate) => candidate.symbol === asset)
4563
- );
4564
- if (!supportsAsset) {
4565
- continue;
4566
- }
4567
- }
4568
- available.push({
4569
- id,
4570
- isEnabled,
4571
- supportedChainIds: agent.supportedChainIds,
4572
- supportedAssets: agent.supportedAssets
4573
- });
4574
- }
4575
- return available;
4576
- }
4577
2761
  // --- Account lifecycle ---
4578
2762
  /**
4579
2763
  * Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
@@ -4585,7 +2769,7 @@ var OwneySDK = class {
4585
2769
  * If provided, ALL specified agents must support the chainId or the call
4586
2770
  * throws before activating any agent.
4587
2771
  */
4588
- async activateAgent(chainId, agentId, asset) {
2772
+ async activateAgent(chainId, agentId) {
4589
2773
  const state = this.requireState();
4590
2774
  await this.ensureAgentsInitialized();
4591
2775
  if (agentId !== void 0) {
@@ -4621,7 +2805,9 @@ var OwneySDK = class {
4621
2805
  this.activeAgents.add(id);
4622
2806
  }
4623
2807
  state.chainId = chainId;
4624
- await this.activateAgentsInTurn(agents, state, chainId, asset);
2808
+ this.activateAgentsInTurn(agents, state, chainId).catch((error) => {
2809
+ console.error("activateAgent background init failed:", error);
2810
+ });
4625
2811
  return;
4626
2812
  }
4627
2813
  const compatible = [...this.agents.values()].filter(
@@ -4642,7 +2828,11 @@ var OwneySDK = class {
4642
2828
  const enabledCompatible = compatible.filter(
4643
2829
  (agent) => !this.isAgentDisabled(agent.id)
4644
2830
  );
4645
- await this.activateAgentsInTurn(enabledCompatible, state, chainId, asset);
2831
+ this.activateAgentsInTurn(enabledCompatible, state, chainId).catch(
2832
+ (error) => {
2833
+ console.error("activateAgent background init failed:", error);
2834
+ }
2835
+ );
4646
2836
  }
4647
2837
  /**
4648
2838
  * Activate agents ONE AT A TIME, each followed by its org policy.
@@ -4658,25 +2848,17 @@ var OwneySDK = class {
4658
2848
  * at a time anyway.
4659
2849
  *
4660
2850
  * Every agent is attempted even if an earlier one fails, so one declined
4661
- * signature can't deny the remaining agents their turn. Once all agents have
4662
- * had a chance, a partial failure identifies the agents that still need a
4663
- * retry; if none activated, the original provider error is preserved.
2851
+ * signature can't deny the remaining agents their turn. The first failure is
2852
+ * rethrown (matching the previous `Promise.all` rejection) once all agents
2853
+ * have had a chance to activate.
4664
2854
  */
4665
- async activateAgentsInTurn(agents, state, chainId, asset) {
2855
+ async activateAgentsInTurn(agents, state, chainId) {
4666
2856
  let firstError = null;
4667
- const activatedAgentIds = [];
4668
- const failedAgents = [];
4669
2857
  for (const agent of agents) {
4670
2858
  try {
4671
- await agent.activateAgent(state, chainId, asset);
2859
+ await agent.activateAgent(state, chainId);
4672
2860
  await this.applyOrgPolicyTo(agent, state, chainId);
4673
- activatedAgentIds.push(agent.id);
4674
2861
  } catch (error) {
4675
- failedAgents.push({
4676
- agentId: agent.id,
4677
- code: error instanceof OwneyError ? error.code : void 0,
4678
- message: error instanceof Error ? error.message : String(error)
4679
- });
4680
2862
  if (firstError === null) {
4681
2863
  firstError = error;
4682
2864
  } else {
@@ -4684,19 +2866,10 @@ var OwneySDK = class {
4684
2866
  }
4685
2867
  }
4686
2868
  }
4687
- if (firstError === null) return;
4688
- if (activatedAgentIds.length === 0) throw firstError;
4689
- const failedAgentIds = failedAgents.map(({ agentId }) => agentId);
4690
- const activeNames = activatedAgentIds.map(this.formatAgentName).join(", ");
4691
- const remainingNames = failedAgentIds.map(this.formatAgentName).join(", ");
4692
- throw new OwneyError(
4693
- "AGENT_ACTIVATION_PARTIAL_FAILURE",
4694
- `${activeNames} activated, but ${remainingNames} still needs activation. Try again and approve the remaining wallet request.`,
4695
- { activatedAgentIds, failedAgentIds, failures: failedAgents }
4696
- );
2869
+ if (firstError !== null) throw firstError;
4697
2870
  }
4698
2871
  /**
4699
- * Deposit funds into a specific agent, or distribute across all agents if agentId is omitted.
2872
+ * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
4700
2873
  * Validates that the asset is supported and amount meets minimums for the target agent(s).
4701
2874
  * @param options - Deposit parameters
4702
2875
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
@@ -4704,8 +2877,7 @@ var OwneySDK = class {
4704
2877
  * @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
4705
2878
  * When agentId is omitted, this callback is invoked once per eligible agent with that agent's
4706
2879
  * split amount and smart wallet address — expect multiple wallet prompts.
4707
- * @param options.agentId - Optional. Target agent. Omit to fund all eligible agents. Deposits
4708
- * are equal once every agent is funded; first/recovery deposits also honor each agent's floor.
2880
+ * @param options.agentId - Optional. Target agent. Omit to split equally across all agents.
4709
2881
  * @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
4710
2882
  */
4711
2883
  async deposit(options) {
@@ -4757,50 +2929,37 @@ var OwneySDK = class {
4757
2929
  exempt
4758
2930
  );
4759
2931
  if (agentAmounts.length === 0) {
4760
- const agentsRequiringActivation = eligibleAgents.filter(
4761
- (agent) => !exempt.has(agent.id)
4762
- );
4763
- const perAgentMinimum = agentsRequiringActivation.reduce(
4764
- (highest, agent) => {
4765
- const minimum = this.getMinDepositAmount(agent, chainId, asset);
4766
- return minimum > highest ? minimum : highest;
4767
- },
4768
- 0n
4769
- );
4770
- const minimumRequired = perAgentMinimum * BigInt(agentsRequiringActivation.length);
4771
2932
  throw new OwneyError(
4772
2933
  "DEPOSIT_AMOUNT_BELOW_MINIMUM",
4773
- `Amount "${amount}" cannot activate every eligible agent. The combined minimum is "${minimumRequired.toString()}" for ${asset}.`,
4774
- {
4775
- amount,
4776
- asset,
4777
- chainId,
4778
- minDepositAmount: minimumRequired.toString(),
4779
- perAgentDepositAmount: perAgentMinimum.toString(),
4780
- agentMinimums: agentsRequiringActivation.map((agent) => ({
4781
- agentId: agent.id,
4782
- minDepositAmount: this.getMinDepositAmount(
4783
- agent,
4784
- chainId,
4785
- asset
4786
- ).toString()
4787
- }))
4788
- }
2934
+ `Amount "${amount}" cannot satisfy minimum deposit requirements for any eligible agent.`,
2935
+ { amount }
4789
2936
  );
4790
2937
  }
4791
2938
  const agentResults = {};
2939
+ const agentErrors = {};
4792
2940
  for (const { agent, amount: agentAmount } of agentAmounts) {
4793
- agentResults[agent.id] = await this.depositWithFallback(
4794
- agent,
4795
- state,
4796
- chainId,
4797
- agentAmount,
4798
- asset,
4799
- effectiveCallback,
4800
- depositCallback
2941
+ try {
2942
+ agentResults[agent.id] = await this.depositWithFallback(
2943
+ agent,
2944
+ state,
2945
+ chainId,
2946
+ agentAmount,
2947
+ asset,
2948
+ effectiveCallback,
2949
+ depositCallback
2950
+ );
2951
+ } catch (error) {
2952
+ agentErrors[agent.id] = error instanceof Error ? error.message : String(error);
2953
+ }
2954
+ }
2955
+ if (Object.keys(agentResults).length === 0) {
2956
+ throw new OwneyError(
2957
+ "DEPOSIT_ALL_FAILED",
2958
+ `All ${agentAmounts.length} agent deposit(s) failed.`,
2959
+ { agentErrors }
4801
2960
  );
4802
2961
  }
4803
- return { agentResults };
2962
+ return Object.keys(agentErrors).length > 0 ? { agentResults, agentErrors } : { agentResults };
4804
2963
  }
4805
2964
  /**
4806
2965
  * Invokes `agent.deposit` with the resolved sponsored callback, composing
@@ -4871,55 +3030,25 @@ var OwneySDK = class {
4871
3030
  }
4872
3031
  splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
4873
3032
  if (agents.length === 0) return [];
4874
- const agentsRequiringActivation = agents.filter(
4875
- (agent) => !exempt.has(agent.id)
4876
- );
4877
- if (agentsRequiringActivation.length === agents.length) {
4878
- const highestMinimum2 = agents.reduce(
4879
- (highest, agent) => {
4880
- const minimum = this.getMinDepositAmount(agent, chainId, asset);
4881
- return minimum > highest ? minimum : highest;
4882
- },
4883
- 0n
4884
- );
4885
- const minimumRequired2 = highestMinimum2 * BigInt(agents.length);
4886
- if (totalAmount < minimumRequired2) return [];
4887
- }
4888
3033
  const perAgent = totalAmount / BigInt(agents.length);
4889
3034
  const remainder = totalAmount % BigInt(agents.length);
4890
3035
  const splits = agents.map((agent, i) => ({
4891
3036
  agent,
4892
3037
  amount: i === agents.length - 1 ? perAgent + remainder : perAgent
4893
3038
  }));
4894
- const valid2 = splits.filter(
3039
+ const valid = splits.filter(
4895
3040
  (s) => exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset)
4896
3041
  );
4897
- if (valid2.length === agents.length) {
3042
+ if (valid.length === agents.length) {
4898
3043
  return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
4899
3044
  }
4900
- const targets = agentsRequiringActivation.length > 0 ? agentsRequiringActivation : valid2.map((s) => s.agent);
4901
- const highestMinimum = targets.reduce(
4902
- (highest, agent) => {
4903
- const minimum = this.getMinDepositAmount(agent, chainId, asset);
4904
- return minimum > highest ? minimum : highest;
4905
- },
4906
- 0n
3045
+ return this.splitDepositAmount(
3046
+ totalAmount,
3047
+ valid.map((s) => s.agent),
3048
+ chainId,
3049
+ asset,
3050
+ exempt
4907
3051
  );
4908
- const minimumRequired = highestMinimum * BigInt(targets.length);
4909
- if (totalAmount < minimumRequired) return [];
4910
- const targetShare = totalAmount / BigInt(targets.length);
4911
- const targetRemainder = totalAmount % BigInt(targets.length);
4912
- return targets.map((agent, index) => ({
4913
- agent,
4914
- amount: String(
4915
- targetShare + (index === targets.length - 1 ? targetRemainder : 0n)
4916
- )
4917
- }));
4918
- }
4919
- formatAgentName(agentId) {
4920
- if (agentId === "zyfai") return "Zyfai";
4921
- if (agentId === "yieldseeker") return "Yieldseeker";
4922
- return agentId;
4923
3052
  }
4924
3053
  async validateMinDepositAmount(agent, state, chainId, asset, amount) {
4925
3054
  const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
@@ -4947,24 +3076,10 @@ var OwneySDK = class {
4947
3076
  async hasExistingBalance(agent, state, chainId, asset) {
4948
3077
  try {
4949
3078
  const balance = await agent.getBalances(state, chainId);
4950
- const target = asset.toLowerCase();
4951
3079
  const token = balance.tokens.find(
4952
- (t) => t.chainId === chainId && t.asset.toLowerCase() === target
3080
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
4953
3081
  );
4954
- const chainNameById = {
4955
- 1: "ETHEREUM",
4956
- 8453: "BASE",
4957
- 42161: "ARBITRUM"
4958
- };
4959
- const targetChainName = chainNameById[chainId];
4960
- const position2 = (balance.positions ?? []).find(
4961
- (p) => {
4962
- const positionChain = p.chain.trim().toUpperCase();
4963
- const matchesChain = positionChain === String(chainId) || targetChainName !== void 0 && positionChain === targetChainName;
4964
- return matchesChain && p.asset.toLowerCase() === target && Number(p.amount) > 0;
4965
- }
4966
- );
4967
- return !!token && Number(token.amount) > 0 || !!position2;
3082
+ return !!token && Number(token.amount) > 0;
4968
3083
  } catch {
4969
3084
  return false;
4970
3085
  }
@@ -5001,6 +3116,34 @@ var OwneySDK = class {
5001
3116
  }
5002
3117
  return eligible;
5003
3118
  }
3119
+ /**
3120
+ * Agent ids the routing API provisioned for this org that support the given
3121
+ * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
3122
+ * surfliquid first). Returns `[]` when the org has no compatible agent — never
3123
+ * throws on an empty org. Loads agent keys on first call (apiKey only, no
3124
+ * wallet), so the UI can resolve which agent to use before the user connects.
3125
+ *
3126
+ * This is the source of truth for agent availability: an agent appears here
3127
+ * iff the routing API returned its key. No per-app feature flags.
3128
+ */
3129
+ async getEligibleAgentIds(chainId, asset) {
3130
+ try {
3131
+ await this.ensureAgentsInitialized();
3132
+ } catch (error) {
3133
+ if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
3134
+ return [];
3135
+ }
3136
+ throw error;
3137
+ }
3138
+ return [...this.agents.values()].filter((agent) => {
3139
+ const chainAssets = agent.supportedAssets.find(
3140
+ (sa) => sa.chainId === chainId
3141
+ );
3142
+ return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
3143
+ }).map((agent) => agent.id).sort(
3144
+ (a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
3145
+ );
3146
+ }
5004
3147
  // --- Fund operations ---
5005
3148
  /**
5006
3149
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
@@ -5037,9 +3180,17 @@ var OwneySDK = class {
5037
3180
  }
5038
3181
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
5039
3182
  if (!amount) {
3183
+ const aggregated2 = await this.getBalances();
3184
+ const funded = projectAgentBalancesForAsset(
3185
+ eligibleAgents,
3186
+ aggregated2.agentBalances,
3187
+ chainId,
3188
+ asset,
3189
+ assetInfo.decimals
3190
+ ).filter((b) => b.balance > 0n);
5040
3191
  const results2 = {};
5041
3192
  const agentErrors2 = {};
5042
- for (const agent of eligibleAgents) {
3193
+ for (const { agent } of funded) {
5043
3194
  try {
5044
3195
  results2[agent.id] = await agent.withdraw(state, chainId, token);
5045
3196
  } catch (err) {
@@ -5061,17 +3212,14 @@ var OwneySDK = class {
5061
3212
  { asset, agentErrors: agentErrors2 }
5062
3213
  );
5063
3214
  }
3215
+ const totalWithdrawn = funded.filter(({ agent }) => results2[agent.id] !== void 0).reduce((sum, { balance }) => sum + balance, 0n);
5064
3216
  return {
5065
3217
  agentResult: results2,
5066
- totalWithdrawn: sumWithdrawnAmount(results2).toString()
3218
+ totalWithdrawn: totalWithdrawn.toString()
5067
3219
  };
5068
3220
  }
5069
3221
  const requested = BigInt(amount);
5070
3222
  const aggregated = await this.getBalances();
5071
- const unavailableAgents = eligibleAgents.filter(
5072
- (agent) => !(agent.id in aggregated.agentBalances)
5073
- );
5074
- const unavailableAgentIds = unavailableAgents.map((agent) => agent.id);
5075
3223
  const balances = projectAgentBalancesForAsset(
5076
3224
  eligibleAgents,
5077
3225
  aggregated.agentBalances,
@@ -5080,18 +3228,7 @@ var OwneySDK = class {
5080
3228
  assetInfo.decimals
5081
3229
  );
5082
3230
  const totalAvailable = balances.reduce((sum, x) => sum + x.balance, 0n);
5083
- if (totalAvailable === 0n && unavailableAgents.length > 0) {
5084
- throw new OwneyError(
5085
- "WITHDRAW_BALANCE_UNAVAILABLE",
5086
- `Cannot safely plan the withdrawal because balance data is unavailable for: ${unavailableAgentIds.join(", ")}.`,
5087
- {
5088
- asset,
5089
- unavailableAgents: unavailableAgentIds,
5090
- agentErrors: aggregated.agentErrors
5091
- }
5092
- );
5093
- }
5094
- if (totalAvailable < requested && unavailableAgents.length === 0) {
3231
+ if (totalAvailable < requested) {
5095
3232
  throw new OwneyError(
5096
3233
  "WITHDRAW_INSUFFICIENT_BALANCE",
5097
3234
  `Requested withdrawal "${amount}" exceeds available balance "${totalAvailable.toString()}" for asset "${asset}".`,
@@ -5102,7 +3239,6 @@ var OwneySDK = class {
5102
3239
  }
5103
3240
  );
5104
3241
  }
5105
- const plannedTarget = totalAvailable < requested ? totalAvailable : requested;
5106
3242
  const disabledBalances = balances.filter(
5107
3243
  (b) => this.isAgentDisabled(b.agent.id)
5108
3244
  );
@@ -5111,7 +3247,7 @@ var OwneySDK = class {
5111
3247
  );
5112
3248
  const { plans: disabledPlans, remaining: afterDrain } = planDisabledDrain(
5113
3249
  disabledBalances,
5114
- plannedTarget
3250
+ requested
5115
3251
  );
5116
3252
  const enabledTotal = enabledBalances.reduce((s, b) => s + b.balance, 0n);
5117
3253
  const enabledPlans = afterDrain > 0n ? planProportionalShares(enabledBalances, afterDrain, enabledTotal) : enabledBalances.map(({ agent, balance }) => ({
@@ -5121,9 +3257,7 @@ var OwneySDK = class {
5121
3257
  }));
5122
3258
  const plans = [...disabledPlans, ...enabledPlans];
5123
3259
  const results = {};
5124
- const agentErrors = {
5125
- ...aggregated.agentErrors ?? {}
5126
- };
3260
+ const agentErrors = {};
5127
3261
  for (let i = 0; i < plans.length; i++) {
5128
3262
  const p = plans[i];
5129
3263
  if (p.planned === 0n) continue;
@@ -5170,8 +3304,7 @@ var OwneySDK = class {
5170
3304
  requested: amount,
5171
3305
  withdrawn: withdrawn.toString(),
5172
3306
  partialResults: results,
5173
- agentErrors,
5174
- ...unavailableAgentIds.length > 0 ? { unavailableAgents: unavailableAgentIds } : {}
3307
+ agentErrors
5175
3308
  }
5176
3309
  );
5177
3310
  }
@@ -5187,12 +3320,8 @@ var OwneySDK = class {
5187
3320
  const state = this.requireState();
5188
3321
  const chainId = this.requireChainId();
5189
3322
  if (agentId) {
5190
- const agent = this.getAgent(agentId);
5191
- const result = await agent.getBalances(state, chainId);
5192
- return {
5193
- ...result,
5194
- balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
5195
- };
3323
+ const result = await this.getAgent(agentId).getBalances(state, chainId);
3324
+ return result;
5196
3325
  }
5197
3326
  let totalBalance = 0;
5198
3327
  const results = {};
@@ -5200,13 +3329,7 @@ var OwneySDK = class {
5200
3329
  const balanceResults = await Promise.allSettled(
5201
3330
  entries.map(async ([id, agent]) => {
5202
3331
  const b = await agent.getBalances(state, chainId);
5203
- return [
5204
- id,
5205
- {
5206
- ...b,
5207
- balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
5208
- }
5209
- ];
3332
+ return [id, b];
5210
3333
  })
5211
3334
  );
5212
3335
  let successCount = 0;
@@ -5222,12 +3345,7 @@ var OwneySDK = class {
5222
3345
  continue;
5223
3346
  }
5224
3347
  const reason = settledResult.reason;
5225
- const message = reason instanceof Error ? reason.message : String(reason);
5226
- agentErrors[agentId2] = message;
5227
- console.error(
5228
- `[owney-sdk] Balance fetch failed for agent "${agentId2}":`,
5229
- reason
5230
- );
3348
+ agentErrors[agentId2] = reason instanceof Error ? reason.message : String(reason);
5231
3349
  }
5232
3350
  if (successCount === 0) {
5233
3351
  throw new OwneyError(
@@ -5239,8 +3357,7 @@ var OwneySDK = class {
5239
3357
  return {
5240
3358
  totalBalance: String(totalBalance),
5241
3359
  totalBalanceAsset: "usdc",
5242
- agentBalances: results,
5243
- ...Object.keys(agentErrors).length > 0 ? { agentErrors } : {}
3360
+ agentBalances: results
5244
3361
  };
5245
3362
  }
5246
3363
  /**
@@ -5334,10 +3451,7 @@ var OwneySDK = class {
5334
3451
  Promise.all(
5335
3452
  entries.map(async ([id, agent]) => {
5336
3453
  const b = await agent.getBalances(state, chainId);
5337
- return [
5338
- id,
5339
- balanceForApyScope(b, chainId, tokenSymbol)
5340
- ];
3454
+ return [id, Number(b.totalBalance)];
5341
3455
  })
5342
3456
  )
5343
3457
  ]);
@@ -5365,12 +3479,10 @@ var OwneySDK = class {
5365
3479
  }
5366
3480
  }
5367
3481
  const apyByChainAndAsset = aggregateApyByChainAndAsset(results, balances);
5368
- const history = aggregateApyHistory(results, balances);
5369
3482
  return {
5370
3483
  totalApy: String(totalApy),
5371
3484
  agentApy: results,
5372
- apyByChainAndAsset,
5373
- history
3485
+ apyByChainAndAsset
5374
3486
  };
5375
3487
  }
5376
3488
  /**
@@ -5500,10 +3612,10 @@ var OwneySDK = class {
5500
3612
  );
5501
3613
  }
5502
3614
  const provider = this.requireConnectedProvider();
5503
- const wallet = createWalletClient3({
3615
+ const wallet = createWalletClient({
5504
3616
  account: state.walletAddress,
5505
3617
  chain: VIEM_CHAIN2[chainId],
5506
- transport: custom3(provider)
3618
+ transport: custom(provider)
5507
3619
  });
5508
3620
  const hash = await wallet.writeContract({
5509
3621
  address: token,
@@ -5513,9 +3625,9 @@ var OwneySDK = class {
5513
3625
  account: state.walletAddress,
5514
3626
  chain: VIEM_CHAIN2[chainId]
5515
3627
  });
5516
- const publicClient = createPublicClient4({
3628
+ const publicClient = createPublicClient2({
5517
3629
  chain: VIEM_CHAIN2[chainId],
5518
- transport: custom3(provider)
3630
+ transport: custom(provider)
5519
3631
  });
5520
3632
  const receipt = await publicClient.waitForTransactionReceipt({
5521
3633
  hash,
@@ -5551,9 +3663,7 @@ var OwneySDK = class {
5551
3663
  return this.getAgent(agentId).getAgentApy(days, agentOptions);
5552
3664
  }
5553
3665
  const results = {};
5554
- const agentEntries = [...this.agents.entries()].filter(
5555
- ([id]) => !this.isAgentDisabled(id)
5556
- );
3666
+ const agentEntries = [...this.agents.entries()];
5557
3667
  const apyResults = await Promise.all(
5558
3668
  agentEntries.map(async ([id, agent]) => {
5559
3669
  const apy = await agent.getAgentApy(days, agentOptions);
@@ -5626,13 +3736,13 @@ var OwneySDK = class {
5626
3736
  };
5627
3737
 
5628
3738
  // src/agents/zyfai/zyfai.siwx.ts
5629
- import { getAddress as getAddress3 } from "viem";
5630
- import { SiweMessage as SiweMessage2 } from "siwe";
3739
+ import { getAddress } from "viem";
3740
+ import { SiweMessage } from "siwe";
5631
3741
  import { ZyfaiSDK as ZyfaiSDK2 } from "@zyfai/sdk";
5632
3742
 
5633
3743
  // src/agents/zyfai/zyfai.siwx-cache.ts
5634
- var KEY_PREFIX4 = "owney.siwx.session";
5635
- var storage4 = () => {
3744
+ var KEY_PREFIX2 = "owney.siwx.session";
3745
+ var storage2 = () => {
5636
3746
  if (typeof window === "undefined") return null;
5637
3747
  try {
5638
3748
  return window.localStorage;
@@ -5640,8 +3750,8 @@ var storage4 = () => {
5640
3750
  return null;
5641
3751
  }
5642
3752
  };
5643
- var buildKey3 = (address) => `${KEY_PREFIX4}:${address.toLowerCase()}`;
5644
- var legacyKeyPrefix2 = (address) => `${KEY_PREFIX4}:${address.toLowerCase()}:`;
3753
+ var buildKey2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}`;
3754
+ var legacyKeyPrefix2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}:`;
5645
3755
  var memorySiwxSessions = /* @__PURE__ */ new Map();
5646
3756
  var readLegacySiwxSession = (store, address) => {
5647
3757
  if (!store) return null;
@@ -5672,17 +3782,17 @@ var readLegacySiwxSession = (store, address) => {
5672
3782
  };
5673
3783
  var readSiwxSession = (address, chainId) => {
5674
3784
  if (typeof window === "undefined") return null;
5675
- const key2 = buildKey3(address);
5676
- const store = storage4();
5677
- let raw2 = null;
3785
+ const key2 = buildKey2(address);
3786
+ const store = storage2();
3787
+ let raw = null;
5678
3788
  try {
5679
- raw2 = store?.getItem(key2) ?? null;
3789
+ raw = store?.getItem(key2) ?? null;
5680
3790
  } catch {
5681
- raw2 = null;
3791
+ raw = null;
5682
3792
  }
5683
- if (raw2) {
3793
+ if (raw) {
5684
3794
  try {
5685
- return JSON.parse(raw2);
3795
+ return JSON.parse(raw);
5686
3796
  } catch {
5687
3797
  memorySiwxSessions.delete(key2);
5688
3798
  try {
@@ -5701,18 +3811,18 @@ var readSiwxSession = (address, chainId) => {
5701
3811
  };
5702
3812
  var writeSiwxSession = (address, _chainId, session) => {
5703
3813
  if (typeof window === "undefined") return;
5704
- const key2 = buildKey3(address);
3814
+ const key2 = buildKey2(address);
5705
3815
  memorySiwxSessions.set(key2, session);
5706
- const store = storage4();
3816
+ const store = storage2();
5707
3817
  try {
5708
3818
  store?.setItem(key2, JSON.stringify(session));
5709
3819
  } catch {
5710
3820
  }
5711
3821
  };
5712
3822
  var clearSiwxSession = (address, _chainId) => {
5713
- const key2 = buildKey3(address);
3823
+ const key2 = buildKey2(address);
5714
3824
  memorySiwxSessions.delete(key2);
5715
- const store = storage4();
3825
+ const store = storage2();
5716
3826
  try {
5717
3827
  store?.removeItem(key2);
5718
3828
  } catch {
@@ -5752,8 +3862,8 @@ function buildSIWXConfig(deps) {
5752
3862
  statement: STATEMENT,
5753
3863
  issuedAt,
5754
3864
  toString() {
5755
- return new SiweMessage2({
5756
- address: getAddress3(accountAddress),
3865
+ return new SiweMessage({
3866
+ address: getAddress(accountAddress),
5757
3867
  chainId: numericChainId(chainId),
5758
3868
  domain,
5759
3869
  uri,
@@ -5795,7 +3905,7 @@ function buildSIWXConfig(deps) {
5795
3905
  const persistSession = async (session) => {
5796
3906
  const address = session.data.accountAddress;
5797
3907
  const id = numericChainId(session.data.chainId);
5798
- const message = new SiweMessage2(session.message);
3908
+ const message = new SiweMessage(session.message);
5799
3909
  const login = await post("/auth/login", {
5800
3910
  message,
5801
3911
  signature: session.signature,
@@ -5843,7 +3953,6 @@ export {
5843
3953
  NotConnectedError,
5844
3954
  OwneyError,
5845
3955
  OwneySDK,
5846
- YieldseekerAgent,
5847
3956
  createOwneySIWX,
5848
3957
  setOwneyDebug
5849
3958
  };