@owney/sdk 0.7.21-beta.2 → 0.7.22-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,51 +1,18 @@
1
- // src/errors.ts
2
- var OwneyError = class extends Error {
3
- code;
4
- details;
5
- agentId;
6
- constructor(code, message, details, agentId) {
7
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
8
- super(`${prefix} ${message}`);
9
- this.name = "OwneyError";
10
- this.code = code;
11
- this.details = details;
12
- this.agentId = agentId;
13
- }
14
- };
15
- var AgentNotFoundError = class extends OwneyError {
16
- constructor(agentId, available) {
17
- super(
18
- "AGENT_NOT_FOUND",
19
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
20
- { agentId, available },
21
- agentId
22
- );
23
- this.name = "AgentNotFoundError";
24
- }
25
- };
26
- var NotConnectedError = class extends OwneyError {
27
- constructor() {
28
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
29
- this.name = "NotConnectedError";
30
- }
31
- };
32
- var AgentChainIncompatibleError = class extends OwneyError {
33
- incompatibleAgents;
34
- connectedChainId;
35
- constructor(incompatibleAgents, connectedChainId) {
36
- const details = incompatibleAgents.map(
37
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
38
- ).join("; ");
39
- super(
40
- "AGENT_CHAIN_INCOMPATIBLE",
41
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
42
- { incompatibleAgents, connectedChainId }
43
- );
44
- this.name = "AgentChainIncompatibleError";
45
- this.incompatibleAgents = incompatibleAgents;
46
- this.connectedChainId = connectedChainId;
47
- }
48
- };
1
+ import {
2
+ AgentChainIncompatibleError,
3
+ AgentNotFoundError,
4
+ NotConnectedError,
5
+ OwneyError,
6
+ debugLog,
7
+ fetchAgentKeys,
8
+ fetchOrgAgentConfig,
9
+ setOwneyDebug
10
+ } from "./chunk-XBDJWZXY.js";
11
+ import {
12
+ buildTransferWithAuthorizationTypedData,
13
+ randomAuthNonce,
14
+ readTokenMeta
15
+ } from "./chunk-5LU2SHO7.js";
49
16
 
50
17
  // src/lib/rate-limit.ts
51
18
  function rateLimitDelay(error, now = Date.now()) {
@@ -212,23 +179,6 @@ var SupportedAssets = [
212
179
  }
213
180
  ];
214
181
 
215
- // src/lib/debug.ts
216
- var configuredDebug = false;
217
- function setOwneyDebug(enabled) {
218
- configuredDebug = enabled;
219
- }
220
- function isOwneyDebug() {
221
- return globalThis.__OWNEY_DEBUG__ === true || configuredDebug;
222
- }
223
- function debugLog(scope, message, data) {
224
- if (!isOwneyDebug()) return;
225
- if (data === void 0) {
226
- console.log(`[${scope}] ${message}`);
227
- } else {
228
- console.log(`[${scope}] ${message}`, data);
229
- }
230
- }
231
-
232
182
  // src/lib/utils.ts
233
183
  var isValidChainId = (chainId) => {
234
184
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
@@ -240,6 +190,12 @@ var isValidChainId = (chainId) => {
240
190
  }
241
191
  return chainId;
242
192
  };
193
+ function isSameAsset(tokenSymbol, asset) {
194
+ const token = tokenSymbol.toLowerCase();
195
+ const target = asset.toLowerCase();
196
+ if (token === target) return true;
197
+ return target === "weth" && token === "eth" || target === "eth" && token === "weth";
198
+ }
243
199
  function hexToDecimal(hex, decimals = 6) {
244
200
  const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
245
201
  const parsed = BigInt(normalized);
@@ -277,18 +233,18 @@ function tokenDecimals(symbol, explicit) {
277
233
  return explicit;
278
234
  return DECIMALS_BY_SYMBOL[(symbol ?? "").toLowerCase()] ?? 6;
279
235
  }
280
- function mapDeposit(raw2) {
236
+ function mapDeposit(raw) {
281
237
  return {
282
- txHash: raw2.txHash,
283
- smartWallet: raw2.smartWallet,
284
- amount: raw2.amount
238
+ txHash: raw.txHash,
239
+ smartWallet: raw.smartWallet,
240
+ amount: raw.amount
285
241
  };
286
242
  }
287
- function mapWithdraw(raw2) {
243
+ function mapWithdraw(raw) {
288
244
  return {
289
- txHash: raw2.txHash,
290
- type: raw2.type,
291
- amount: raw2.amount
245
+ txHash: raw.txHash,
246
+ type: raw.type,
247
+ amount: raw.amount
292
248
  };
293
249
  }
294
250
  var CHAIN_ID_TO_NAME = {
@@ -307,10 +263,10 @@ function resolveChainId(chain) {
307
263
  if (Number.isFinite(asNum) && asNum > 0) return asNum;
308
264
  return NAME_TO_CHAIN_ID[chain.trim().toLowerCase()] ?? NaN;
309
265
  }
310
- function mapPendingAllocations(raw2) {
311
- if (!Array.isArray(raw2)) return void 0;
266
+ function mapPendingAllocations(raw) {
267
+ if (!Array.isArray(raw)) return void 0;
312
268
  const pending = [];
313
- for (const entry of raw2) {
269
+ for (const entry of raw) {
314
270
  if (typeof entry !== "object" || entry === null) continue;
315
271
  const e = entry;
316
272
  if (typeof e.chainId !== "number" || !Number.isFinite(e.chainId)) continue;
@@ -333,8 +289,8 @@ function mapPendingAllocations(raw2) {
333
289
  }
334
290
  return pending.length > 0 ? pending : void 0;
335
291
  }
336
- function mapBalances(raw2, _chainId, smartWallet) {
337
- const portfolio = raw2.portfolio;
292
+ function mapBalances(raw, _chainId, smartWallet) {
293
+ const portfolio = raw.portfolio;
338
294
  const portfolioByChain = portfolio.portfolioByChain ?? {};
339
295
  let totalBalance = 0;
340
296
  const tokens = [];
@@ -403,8 +359,8 @@ function sumTokenValues(tokens) {
403
359
  function sumTokenEarnings(tokens) {
404
360
  return Object.values(tokens).reduce((sum, val) => sum + Number(val), 0);
405
361
  }
406
- function mapEarnings(raw2, smartWallet) {
407
- const totalEarningsByChain = raw2.data.totalEarningsByChainWithFee ?? raw2.data.totalEarningsByChain ?? {};
362
+ function mapEarnings(raw, smartWallet) {
363
+ const totalEarningsByChain = raw.data.totalEarningsByChainWithFee ?? raw.data.totalEarningsByChain ?? {};
408
364
  const tokens = [];
409
365
  for (const [chainIdKey, tokensBySymbol] of Object.entries(
410
366
  totalEarningsByChain
@@ -423,15 +379,15 @@ function mapEarnings(raw2, smartWallet) {
423
379
  return {
424
380
  smartWallet,
425
381
  lifetimeEarnings: sumTokenEarnings(
426
- raw2.data.totalEarningsByTokenWithFee ?? raw2.data.totalEarningsByToken
382
+ raw.data.totalEarningsByTokenWithFee ?? raw.data.totalEarningsByToken
427
383
  ),
428
384
  tokens
429
385
  };
430
386
  }
431
- function mapWeightedApyByChain(raw2) {
432
- if (!raw2) return void 0;
387
+ function mapWeightedApyByChain(raw) {
388
+ if (!raw) return void 0;
433
389
  const out = {};
434
- for (const [chainKey, tokenApy] of Object.entries(raw2)) {
390
+ for (const [chainKey, tokenApy] of Object.entries(raw)) {
435
391
  const chainId = Number(chainKey);
436
392
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) continue;
437
393
  const perAsset = {};
@@ -471,8 +427,8 @@ function rawPoolApyForChain(entry, chainId, tokenSymbol) {
471
427
  }
472
428
  return totalBalance > 0 ? weightedSum / totalBalance : null;
473
429
  }
474
- function mapApyHistory(raw2, chainId, tokenSymbol) {
475
- const history = Object.entries(raw2.history ?? {}).map(([date, entry]) => ({
430
+ function mapApyHistory(raw, chainId, tokenSymbol) {
431
+ const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({
476
432
  date,
477
433
  apy: rawPoolApyForChain(entry, chainId, tokenSymbol),
478
434
  // Provider position balances are treated as decimal amounts of the
@@ -488,9 +444,9 @@ function mapApyHistory(raw2, chainId, tokenSymbol) {
488
444
  } : {}
489
445
  })).filter((p) => p.apy !== null).sort((a, b) => a.date.localeCompare(b.date));
490
446
  return {
491
- walletAddress: raw2.walletAddress,
492
- weightedApyAfterFee: raw2.weightedApyAfterFee ? sumTokenValues(raw2.weightedApyAfterFee) : void 0,
493
- apyByChainAndAsset: mapWeightedApyByChain(raw2.weightedApyAfterFeeByChain),
447
+ walletAddress: raw.walletAddress,
448
+ weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0,
449
+ apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain),
494
450
  history
495
451
  };
496
452
  }
@@ -586,23 +542,23 @@ function mapEntries(rawEntries, chainId) {
586
542
  };
587
543
  });
588
544
  }
589
- function mapUserProfile(raw2, userAddress) {
545
+ function mapUserProfile(raw, userAddress) {
590
546
  return {
591
547
  address: userAddress,
592
- smartWallet: raw2.smartWallet || "",
593
- chains: raw2.chains || [],
594
- strategy: raw2.strategy,
595
- hasActiveSessionKey: raw2.hasActiveSessionKey || false,
596
- protocols: raw2.protocols || [],
597
- splitting: raw2.splitting,
598
- minSplits: raw2.minSplits
548
+ smartWallet: raw.smartWallet || "",
549
+ chains: raw.chains || [],
550
+ strategy: raw.strategy,
551
+ hasActiveSessionKey: raw.hasActiveSessionKey || false,
552
+ protocols: raw.protocols || [],
553
+ splitting: raw.splitting,
554
+ minSplits: raw.minSplits
599
555
  };
600
556
  }
601
- function mapApyByStrategy(raw2) {
557
+ function mapApyByStrategy(raw) {
602
558
  const apyPerAsset = {};
603
559
  let apySum = 0;
604
560
  let apyCount = 0;
605
- for (const entry of raw2.data) {
561
+ for (const entry of raw.data) {
606
562
  const supported = SupportedAssets.find(
607
563
  (asset) => asset.chainId === entry.chain_id && asset.symbol === entry.token_symbol
608
564
  );
@@ -773,15 +729,15 @@ var readSession = (address, _chainId) => {
773
729
  if (typeof window === "undefined") return null;
774
730
  const key2 = buildKey(address);
775
731
  const store = storage();
776
- let raw2 = null;
732
+ let raw = null;
777
733
  try {
778
- raw2 = store?.getItem(key2) ?? null;
734
+ raw = store?.getItem(key2) ?? null;
779
735
  } catch {
780
- raw2 = null;
736
+ raw = null;
781
737
  }
782
- if (raw2) {
738
+ if (raw) {
783
739
  try {
784
- const parsed = JSON.parse(raw2);
740
+ const parsed = JSON.parse(raw);
785
741
  if (isFreshSession(parsed)) return parsed;
786
742
  } catch {
787
743
  }
@@ -949,8 +905,8 @@ function buildChainsByProtocol(protocols, dashboardChainIds) {
949
905
  }
950
906
  return result;
951
907
  }
952
- function flattenAvailablePools(raw2) {
953
- const byChain = raw2 ?? {};
908
+ function flattenAvailablePools(raw) {
909
+ const byChain = raw ?? {};
954
910
  const names = [];
955
911
  for (const byToken of Object.values(byChain ?? {})) {
956
912
  for (const entry of Object.values(byToken ?? {})) {
@@ -1453,8 +1409,8 @@ var ZyfaiAgent = class _ZyfaiAgent {
1453
1409
  const poolResults = await Promise.all(
1454
1410
  universe.map(async (protocol) => {
1455
1411
  try {
1456
- const raw2 = await this.sdk.getAvailablePools(protocol.id, strategy);
1457
- return [protocol.id, flattenAvailablePools(raw2)];
1412
+ const raw = await this.sdk.getAvailablePools(protocol.id, strategy);
1413
+ return [protocol.id, flattenAvailablePools(raw)];
1458
1414
  } catch (error) {
1459
1415
  console.warn(
1460
1416
  `[zyfai] applyPoolPolicy: getAvailablePools(${protocol.id}) failed, skipping this protocol (non-fatal):`,
@@ -1493,6 +1449,37 @@ var ZyfaiAgent = class _ZyfaiAgent {
1493
1449
  );
1494
1450
  }
1495
1451
  }
1452
+ /**
1453
+ * Records the deposit with Zyfai, retrying transient failures.
1454
+ *
1455
+ * This runs AFTER the transfer has already landed on-chain, so it must never
1456
+ * fail the deposit — the funds moved. But it is also the ONLY source of the
1457
+ * "Top up wallet" entry the history is built from: Zyfai auto-deploys the
1458
+ * balance it detects either way, so when this call is lost the user's deposit
1459
+ * never appears in Activity (an earlier withdrawal stays the newest row) and
1460
+ * nothing ever backfills it. Retry, then log loudly enough to be recoverable.
1461
+ */
1462
+ async logDepositWithRetry(chainId, txHash, amount, tokenAddress) {
1463
+ const ATTEMPTS = 3;
1464
+ const RETRY_DELAY_MS = 1e3;
1465
+ for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
1466
+ try {
1467
+ await (tokenAddress ? this.sdk.logDeposit(chainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(chainId, txHash, amount));
1468
+ return;
1469
+ } catch (logError) {
1470
+ if (attempt === ATTEMPTS) {
1471
+ console.error(
1472
+ "[owney-sdk] Deposit landed on-chain but logDeposit failed \u2014 it will be missing from Zyfai history:",
1473
+ { txHash, chainId, amount, tokenAddress, error: logError }
1474
+ );
1475
+ return;
1476
+ }
1477
+ await new Promise(
1478
+ (resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt)
1479
+ );
1480
+ }
1481
+ }
1482
+ }
1496
1483
  /**
1497
1484
  * True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
1498
1485
  * to this EOA — the "new wallet" kind that is predeployed on the chains it
@@ -1520,14 +1507,14 @@ var ZyfaiAgent = class _ZyfaiAgent {
1520
1507
  async readWalletState(ownerAddress) {
1521
1508
  try {
1522
1509
  const { portfolio } = await this.sdk.getPositions(ownerAddress);
1523
- const raw2 = portfolio;
1510
+ const raw = portfolio;
1524
1511
  debugLog("zyfai:onboard", "wallet state from getPositions", {
1525
- predeployed: raw2?.predeployed,
1526
- hasActiveSessionKey: raw2?.hasActiveSessionKey
1512
+ predeployed: raw?.predeployed,
1513
+ hasActiveSessionKey: raw?.hasActiveSessionKey
1527
1514
  });
1528
1515
  return {
1529
- predeployed: raw2?.predeployed,
1530
- hasActiveSessionKey: raw2?.hasActiveSessionKey
1516
+ predeployed: raw?.predeployed,
1517
+ hasActiveSessionKey: raw?.hasActiveSessionKey
1531
1518
  };
1532
1519
  } catch (error) {
1533
1520
  console.warn(
@@ -1802,25 +1789,23 @@ var ZyfaiAgent = class _ZyfaiAgent {
1802
1789
  );
1803
1790
  const txHash = await depositCallback(smartWallet, validChainId, amount);
1804
1791
  const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
1805
- try {
1806
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1807
- } catch (logError) {
1808
- console.warn(
1809
- "[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
1810
- logError
1811
- );
1812
- }
1792
+ await this.logDepositWithRetry(
1793
+ validChainId,
1794
+ txHash,
1795
+ amount,
1796
+ tokenAddress
1797
+ );
1813
1798
  return { txHash, smartWallet, amount };
1814
1799
  }
1815
1800
  await this.ensureWalletDeployed(this.getAddress(), validChainId);
1816
- const raw2 = await this.sdk.depositFunds(
1801
+ const raw = await this.sdk.depositFunds(
1817
1802
  this.getAddress(),
1818
1803
  validChainId,
1819
1804
  amount,
1820
1805
  asset,
1821
1806
  "aggressive"
1822
1807
  );
1823
- return mapDeposit(raw2);
1808
+ return mapDeposit(raw);
1824
1809
  } catch (error) {
1825
1810
  throw error;
1826
1811
  }
@@ -1829,27 +1814,27 @@ var ZyfaiAgent = class _ZyfaiAgent {
1829
1814
  async withdraw(state, chainId, token, amount) {
1830
1815
  const validChainId = isValidChainId(chainId);
1831
1816
  await this.ensureConnected(state, validChainId);
1832
- const raw2 = await this.sdk.withdrawFunds(
1817
+ const raw = await this.sdk.withdrawFunds(
1833
1818
  this.getAddress(),
1834
1819
  validChainId,
1835
1820
  amount,
1836
1821
  token
1837
1822
  );
1838
- if (!raw2.success) {
1823
+ if (!raw.success) {
1839
1824
  throw new OwneyError(
1840
1825
  "WITHDRAW_FAILED",
1841
- raw2.message || "Zyfai withdraw failed.",
1842
- { chainId: validChainId, token, amount, response: raw2 },
1826
+ raw.message || "Zyfai withdraw failed.",
1827
+ { chainId: validChainId, token, amount, response: raw },
1843
1828
  this.id
1844
1829
  );
1845
1830
  }
1846
- return mapWithdraw(raw2);
1831
+ return mapWithdraw(raw);
1847
1832
  }
1848
1833
  // --- IAgent: Portfolio reads ---
1849
1834
  async getBalances(state, chainId) {
1850
1835
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
1851
- const raw2 = await this.sdk.getPortfolio(this.getAddress());
1852
- return mapBalances(raw2, validChainId, smartWallet);
1836
+ const raw = await this.sdk.getPortfolio(this.getAddress());
1837
+ return mapBalances(raw, validChainId, smartWallet);
1853
1838
  }
1854
1839
  earningsKey(state, chainId, smartWallet) {
1855
1840
  return JSON.stringify([
@@ -1862,11 +1847,11 @@ var ZyfaiAgent = class _ZyfaiAgent {
1862
1847
  const existing = this.earningsReads.get(key2);
1863
1848
  if (existing) return existing;
1864
1849
  const generation = this.earningsGeneration;
1865
- const pending = Promise.resolve().then(() => this.sdk.getOnchainEarnings(smartWallet)).then((raw2) => {
1850
+ const pending = Promise.resolve().then(() => this.sdk.getOnchainEarnings(smartWallet)).then((raw) => {
1866
1851
  if (generation === this.earningsGeneration) {
1867
- this.earningsSnapshot = { key: key2, raw: raw2, at: Date.now() };
1852
+ this.earningsSnapshot = { key: key2, raw, at: Date.now() };
1868
1853
  }
1869
- return raw2;
1854
+ return raw;
1870
1855
  }).finally(() => {
1871
1856
  if (this.earningsReads.get(key2) === pending)
1872
1857
  this.earningsReads.delete(key2);
@@ -1876,11 +1861,11 @@ var ZyfaiAgent = class _ZyfaiAgent {
1876
1861
  }
1877
1862
  async getEarnings(state, chainId) {
1878
1863
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1879
- const raw2 = await this.readEarnings(
1864
+ const raw = await this.readEarnings(
1880
1865
  this.earningsKey(state, chainId, smartWallet),
1881
1866
  smartWallet
1882
1867
  );
1883
- return mapEarnings(raw2, smartWallet);
1868
+ return mapEarnings(raw, smartWallet);
1884
1869
  }
1885
1870
  async refreshEarnings(state, chainId) {
1886
1871
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
@@ -1907,8 +1892,8 @@ var ZyfaiAgent = class _ZyfaiAgent {
1907
1892
  }
1908
1893
  async getAccountApy(state, chainId, days, tokenSymbol) {
1909
1894
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1910
- const raw2 = await this.sdk.getDailyApyHistory(smartWallet, days);
1911
- return mapApyHistory(raw2, chainId, tokenSymbol);
1895
+ const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
1896
+ return mapApyHistory(raw, chainId, tokenSymbol);
1912
1897
  }
1913
1898
  /**
1914
1899
  * Owney speaks asset symbols ("USDC" / "WETH"); Zyfai's history endpoint
@@ -1943,7 +1928,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
1943
1928
  const matched = [];
1944
1929
  let backendExhausted = false;
1945
1930
  for (let i = 0; i < MAX_BACKEND_CALLS && matched.length < limit; i++) {
1946
- const raw2 = await this.sdk.getHistory(smartWallet, validChainId, {
1931
+ const raw = await this.sdk.getHistory(smartWallet, validChainId, {
1947
1932
  limit: backendPageSize,
1948
1933
  offset,
1949
1934
  fromDate: options?.fromDate,
@@ -1954,13 +1939,13 @@ var ZyfaiAgent = class _ZyfaiAgent {
1954
1939
  // asset's rows and handing back a page that filters to nothing.
1955
1940
  assetType
1956
1941
  });
1957
- raw2.data.forEach((entry, idx) => {
1942
+ raw.data.forEach((entry, idx) => {
1958
1943
  if (entry.chainId === validChainId) {
1959
1944
  matched.push({ entry, rawIdx: offset + idx });
1960
1945
  }
1961
1946
  });
1962
- offset += raw2.data.length;
1963
- if (raw2.data.length < backendPageSize) {
1947
+ offset += raw.data.length;
1948
+ if (raw.data.length < backendPageSize) {
1964
1949
  backendExhausted = true;
1965
1950
  break;
1966
1951
  }
@@ -1982,18 +1967,18 @@ var ZyfaiAgent = class _ZyfaiAgent {
1982
1967
  }
1983
1968
  async getUserProfile(state, chainId) {
1984
1969
  await this.connectAuth(state, chainId);
1985
- const raw2 = await this.sdk.getUserDetails();
1970
+ const raw = await this.sdk.getUserDetails();
1986
1971
  debugLog("zyfai:profile", "getUserProfile \u2014 Zyfai reports", {
1987
1972
  asset: "USDC (default \u2014 no asset passed)",
1988
- splitting: raw2.splitting,
1989
- minSplits: raw2.minSplits,
1990
- strategy: raw2.strategy,
1991
- chains: raw2.chains,
1992
- protocolCount: raw2.protocols?.length,
1993
- hasActiveSessionKey: raw2.hasActiveSessionKey,
1994
- smartWallet: raw2.smartWallet
1973
+ splitting: raw.splitting,
1974
+ minSplits: raw.minSplits,
1975
+ strategy: raw.strategy,
1976
+ chains: raw.chains,
1977
+ protocolCount: raw.protocols?.length,
1978
+ hasActiveSessionKey: raw.hasActiveSessionKey,
1979
+ smartWallet: raw.smartWallet
1995
1980
  });
1996
- return mapUserProfile(raw2, this.connectedAddress);
1981
+ return mapUserProfile(raw, this.connectedAddress);
1997
1982
  }
1998
1983
  async ensureAutoSelectProtocols(state, chainId, asset) {
1999
1984
  await this.connectAuth(state, chainId);
@@ -2012,210 +1997,282 @@ var ZyfaiAgent = class _ZyfaiAgent {
2012
1997
  }
2013
1998
  // --- IAgent: Discovery (no wallet required) ---
2014
1999
  async getAgentApy(days, options) {
2015
- const raw2 = await this.sdk.getAPYPerStrategy(
2000
+ const raw = await this.sdk.getAPYPerStrategy(
2016
2001
  false,
2017
2002
  DayFilterMapping[days],
2018
2003
  "aggressive",
2019
2004
  options?.chainId,
2020
2005
  options?.tokenSymbol
2021
2006
  );
2022
- return mapApyByStrategy(raw2);
2007
+ return mapApyByStrategy(raw);
2023
2008
  }
2024
2009
  };
2025
2010
 
2026
- // src/agents/yieldseeker/yieldseeker.agent.ts
2027
- import {
2028
- createPublicClient as createPublicClient3,
2029
- createWalletClient as createWalletClient2,
2030
- custom as custom2,
2031
- encodeFunctionData,
2032
- erc20Abi,
2033
- getAddress as getAddress2,
2034
- isAddress as isAddress2
2035
- } from "viem";
2036
- import { base as base3 } from "viem/chains";
2037
-
2038
- // src/lib/chain-guard.ts
2039
- var CHAIN_NAMES = {
2040
- 1: "Ethereum",
2041
- 8453: "Base",
2042
- 42161: "Arbitrum"
2043
- };
2044
- function chainName(chainId) {
2045
- return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
2046
- }
2047
- async function ensureWalletOnChain(pub, wallet, expected) {
2048
- const actual = await pub.getChainId();
2049
- if (actual === expected) return;
2050
- try {
2051
- await wallet.switchChain({ id: expected });
2052
- } catch (error) {
2053
- throw new OwneyError(
2054
- "CHAIN_MISMATCH",
2055
- `Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
2056
- {
2057
- expectedChainId: expected,
2058
- actualChainId: actual,
2059
- cause: error instanceof Error ? error.message : String(error)
2060
- }
2061
- );
2062
- }
2063
- const after = await pub.getChainId();
2064
- if (after !== expected) {
2065
- throw new OwneyError(
2066
- "CHAIN_MISMATCH",
2067
- `Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
2068
- { expectedChainId: expected, actualChainId: after }
2069
- );
2070
- }
2071
- }
2072
-
2073
- // src/lib/transfer-auth.ts
2074
- import { bytesToHex } from "viem";
2075
- var ERC20_META_ABI = [
2076
- { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
2077
- { type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
2078
- ];
2079
- function buildTransferWithAuthorizationTypedData(input) {
2080
- return {
2081
- domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
2082
- types: {
2083
- TransferWithAuthorization: [
2084
- { name: "from", type: "address" },
2085
- { name: "to", type: "address" },
2086
- { name: "value", type: "uint256" },
2087
- { name: "validAfter", type: "uint256" },
2088
- { name: "validBefore", type: "uint256" },
2089
- { name: "nonce", type: "bytes32" }
2090
- ]
2091
- },
2092
- primaryType: "TransferWithAuthorization",
2093
- message: input.message
2094
- };
2095
- }
2096
- async function readTokenMeta(publicClient, token) {
2097
- const [tokenName, tokenVersion] = await Promise.all([
2098
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
2099
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
2100
- ]);
2101
- return { tokenName, tokenVersion };
2102
- }
2103
- function randomAuthNonce() {
2104
- const bytes = new Uint8Array(32);
2105
- globalThis.crypto.getRandomValues(bytes);
2106
- return bytesToHex(bytes);
2107
- }
2108
-
2109
- // src/lib/sponsor-client.ts
2011
+ // src/lib/health-report.ts
2110
2012
  var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
2111
- async function postPaymasterIntent(input) {
2112
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
2113
- let res;
2013
+ async function reportAgentFailure(apiKey, agentType, errorCode, baseUrl = ROUTING_API_BASE_URL) {
2114
2014
  try {
2115
- res = await fetch(`${base5}/api/v1/sponsor/paymaster-intent`, {
2015
+ await fetch(`${baseUrl}/api/v1/agent/health-report`, {
2116
2016
  method: "POST",
2117
2017
  headers: {
2118
- "content-type": "application/json",
2119
- "x-owney-api-key": input.apiKey,
2120
- Authorization: `Signature ${input.yieldseekerSignature}`
2018
+ "Content-Type": "application/json",
2019
+ "x-owney-api-key": apiKey
2121
2020
  },
2122
- body: JSON.stringify(input.body)
2021
+ body: JSON.stringify({
2022
+ agent_type: agentType,
2023
+ error_code: errorCode,
2024
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2025
+ })
2123
2026
  });
2124
- } catch (networkError) {
2125
- throw new OwneyError(
2126
- "SPONSOR_REQUEST_FAILED",
2127
- `Paymaster intent network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
2128
- { cause: String(networkError), safeToFallback: true }
2027
+ } catch (err) {
2028
+ console.warn(
2029
+ `[owney-sdk] health-report failed for agent "${agentType}":`,
2030
+ err instanceof Error ? err.message : err
2129
2031
  );
2130
2032
  }
2131
- const text = await res.text();
2132
- let parsed = null;
2033
+ }
2034
+ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
2133
2035
  try {
2134
- parsed = JSON.parse(text);
2135
- } catch {
2136
- }
2137
- if (!res.ok || !parsed?.success || typeof parsed.data?.intent !== "string" || typeof parsed.data.expiresAt !== "number") {
2138
- throw new OwneyError(
2139
- "SPONSOR_REQUEST_FAILED",
2140
- `Paymaster intent API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
2141
- {
2142
- statusCode: res.status,
2143
- responseBody: text.slice(0, 500),
2144
- safeToFallback: true
2145
- }
2146
- );
2036
+ return await fn();
2037
+ } catch (err) {
2038
+ const errorCode = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
2039
+ void reportAgentFailure(apiKey, agentType, errorCode, baseUrl);
2040
+ throw err;
2147
2041
  }
2148
- return parsed.data;
2149
2042
  }
2150
- async function postSponsorTransferAuth(input) {
2151
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
2152
- let res;
2153
- try {
2154
- res = await fetch(`${base5}/api/v1/sponsor/erc20-transfer-auth`, {
2155
- method: "POST",
2156
- headers: {
2157
- "content-type": "application/json",
2158
- "x-owney-api-key": input.apiKey,
2159
- ...input.yieldseekerSignature ? { Authorization: `Signature ${input.yieldseekerSignature}` } : {}
2160
- },
2161
- body: JSON.stringify(input.body)
2162
- });
2163
- } catch (networkError) {
2164
- throw new OwneyError(
2165
- "SPONSOR_REQUEST_FAILED",
2166
- `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
2167
- { cause: String(networkError) }
2043
+
2044
+ // src/lib/helpers/withdraw-helper.ts
2045
+ import { parseUnits } from "viem";
2046
+ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
2047
+ return agents.map((agent) => {
2048
+ const agentBalance = aggregated[agent.id];
2049
+ const tokenBalance = agentBalance?.tokens.find(
2050
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
2168
2051
  );
2052
+ if (!tokenBalance) return { agent, balance: 0n };
2053
+ return { agent, balance: parseUnits(tokenBalance.amount, decimals) };
2054
+ });
2055
+ }
2056
+ function planProportionalShares(balances, requested, totalAvailable) {
2057
+ const plans = balances.map(({ agent, balance }) => ({
2058
+ agent,
2059
+ balance,
2060
+ planned: totalAvailable > 0n ? balance * requested / totalAvailable : 0n
2061
+ }));
2062
+ const assigned = plans.reduce((s, p) => s + p.planned, 0n);
2063
+ let remainder = requested - assigned;
2064
+ const byHeadroom = [...plans].sort((a, b) => {
2065
+ const diff = b.balance - b.planned - (a.balance - a.planned);
2066
+ return diff > 0n ? 1 : diff < 0n ? -1 : 0;
2067
+ });
2068
+ for (const p of byHeadroom) {
2069
+ if (remainder === 0n) break;
2070
+ const headroom = p.balance - p.planned;
2071
+ if (headroom <= 0n) continue;
2072
+ const take = headroom < remainder ? headroom : remainder;
2073
+ p.planned += take;
2074
+ remainder -= take;
2169
2075
  }
2170
- const text = await res.text();
2171
- let parsed = null;
2172
- try {
2173
- parsed = JSON.parse(text);
2174
- } catch {
2175
- }
2176
- if (!res.ok || !parsed?.success || !parsed.data) {
2177
- throw new OwneyError(
2178
- "SPONSOR_REQUEST_FAILED",
2179
- `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
2180
- {
2181
- statusCode: res.status,
2182
- responseBody: text.slice(0, 500),
2183
- // 503 SPONSOR_UNAVAILABLE = relayer out of gas; the tx was rejected
2184
- // before broadcast, so it is safe to fall back to a user-paid deposit.
2185
- safeToFallback: res.status === 503
2186
- }
2187
- );
2076
+ return plans;
2077
+ }
2078
+ function planDisabledDrain(disabled, requested) {
2079
+ const sorted = [...disabled].filter((d) => d.balance > 0n).sort((a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0);
2080
+ const plans = [];
2081
+ let remaining = requested;
2082
+ for (const { agent, balance } of sorted) {
2083
+ if (remaining === 0n) {
2084
+ plans.push({ agent, balance, planned: 0n });
2085
+ continue;
2086
+ }
2087
+ const take = balance < remaining ? balance : remaining;
2088
+ plans.push({ agent, balance, planned: take });
2089
+ remaining -= take;
2188
2090
  }
2189
- return parsed.data;
2091
+ return { plans, remaining };
2190
2092
  }
2191
- async function postSponsorPermit2Transfer(input) {
2192
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
2193
- let res;
2194
- try {
2195
- res = await fetch(`${base5}/api/v1/sponsor/permit2-transfer`, {
2196
- method: "POST",
2197
- headers: {
2198
- "content-type": "application/json",
2199
- "x-owney-api-key": input.apiKey,
2200
- ...input.yieldseekerSignature ? { Authorization: `Signature ${input.yieldseekerSignature}` } : {}
2201
- },
2202
- body: JSON.stringify(input.body)
2203
- });
2204
- } catch (networkError) {
2205
- throw new OwneyError(
2206
- "SPONSOR_REQUEST_FAILED",
2207
- `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
2208
- { cause: String(networkError), safeToFallback: false }
2209
- );
2093
+ function redistributeShare(plans, fromIndex, amount, candidatePool) {
2094
+ const pool = candidatePool ?? plans.slice(fromIndex + 1);
2095
+ const candidates = pool.filter((c) => c.balance - c.planned > 0n);
2096
+ const totalHeadroom = candidates.reduce(
2097
+ (s, c) => s + (c.balance - c.planned),
2098
+ 0n
2099
+ );
2100
+ if (totalHeadroom === 0n) return;
2101
+ let distributed = 0n;
2102
+ for (const c of candidates) {
2103
+ const headroom = c.balance - c.planned;
2104
+ const proportional = headroom * amount / totalHeadroom;
2105
+ const give = proportional > headroom ? headroom : proportional;
2106
+ c.planned += give;
2107
+ distributed += give;
2210
2108
  }
2211
- const text = await res.text();
2212
- let parsed = null;
2213
- try {
2214
- parsed = JSON.parse(text);
2215
- } catch {
2109
+ let leftover = amount - distributed;
2110
+ for (const c of candidates) {
2111
+ if (leftover === 0n) break;
2112
+ const headroom = c.balance - c.planned;
2113
+ if (headroom <= 0n) continue;
2114
+ const take = headroom < leftover ? headroom : leftover;
2115
+ c.planned += take;
2116
+ leftover -= take;
2216
2117
  }
2217
- if (!res.ok || !parsed?.success || !parsed.data) {
2218
- throw new OwneyError(
2118
+ }
2119
+ function sumWithdrawnAmount(results) {
2120
+ return Object.values(results).reduce((sum, r) => sum + BigInt(r.amount), 0n);
2121
+ }
2122
+
2123
+ // src/lib/helpers/account-apy-helper.ts
2124
+ function balanceForApyScope(balance, chainId, tokenSymbol) {
2125
+ if (!tokenSymbol) {
2126
+ const total = Number(balance.totalBalance);
2127
+ return Number.isFinite(total) && total > 0 ? total : 0;
2128
+ }
2129
+ const normalizedToken = tokenSymbol.toUpperCase();
2130
+ return balance.tokens.reduce((total, token) => {
2131
+ if (Number(token.chainId) !== chainId || String(token.asset).toUpperCase() !== normalizedToken) {
2132
+ return total;
2133
+ }
2134
+ const amount = Number(token.amount);
2135
+ return Number.isFinite(amount) && amount > 0 ? total + amount : total;
2136
+ }, 0);
2137
+ }
2138
+ function aggregateApyHistory(agentApys) {
2139
+ const byDate = /* @__PURE__ */ new Map();
2140
+ for (const accountApy of Object.values(agentApys)) {
2141
+ const seen = /* @__PURE__ */ new Set();
2142
+ for (const point of accountApy.history ?? []) {
2143
+ if (!point.date || seen.has(point.date) || !Number.isFinite(point.apy)) continue;
2144
+ seen.add(point.date);
2145
+ const points = byDate.get(point.date) ?? [];
2146
+ points.push(point);
2147
+ byDate.set(point.date, points);
2148
+ }
2149
+ }
2150
+ return [...byDate.entries()].sort(([left], [right]) => left.localeCompare(right)).flatMap(([date, points]) => {
2151
+ if (points.length === 1 && !points[0].historicalBalance) {
2152
+ return [{ date, apy: points[0].apy }];
2153
+ }
2154
+ const unit = points[0].historicalBalance?.unit;
2155
+ if (!unit || points.some(
2156
+ ({ historicalBalance: balance }) => !balance || balance.unit !== unit || !Number.isFinite(balance.amount) || balance.amount < 0
2157
+ )) return [];
2158
+ const total = points.reduce((sum, p) => sum + p.historicalBalance.amount, 0);
2159
+ if (total <= 0 || !Number.isFinite(total)) return [];
2160
+ const apy = points.reduce((sum, p) => sum + p.apy * (p.historicalBalance.amount / total), 0);
2161
+ return Number.isFinite(apy) ? [{ date, apy }] : [];
2162
+ });
2163
+ }
2164
+ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
2165
+ const sums = {};
2166
+ const weights = {};
2167
+ for (const id of Object.keys(agentApys)) {
2168
+ const cells = agentApys[id].apyByChainAndAsset;
2169
+ const balance = agentBalances[id] ?? 0;
2170
+ if (!cells || balance <= 0) continue;
2171
+ for (const [chainKey, perAsset] of Object.entries(cells)) {
2172
+ if (!perAsset) continue;
2173
+ const chainId = Number(chainKey);
2174
+ for (const [asset, apyValue] of Object.entries(perAsset)) {
2175
+ const apy = Number(apyValue ?? 0);
2176
+ if (apy === 0) continue;
2177
+ sums[chainId] ??= {};
2178
+ weights[chainId] ??= {};
2179
+ sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
2180
+ weights[chainId][asset] = (weights[chainId][asset] ?? 0) + balance;
2181
+ }
2182
+ }
2183
+ }
2184
+ const out = {};
2185
+ for (const chainKey of Object.keys(sums)) {
2186
+ const chainId = Number(chainKey);
2187
+ const perAssetOut = {};
2188
+ for (const asset of Object.keys(sums[chainId])) {
2189
+ const w = weights[chainId][asset];
2190
+ if (w > 0) perAssetOut[asset] = sums[chainId][asset] / w;
2191
+ }
2192
+ if (Object.keys(perAssetOut).length > 0) {
2193
+ out[chainId] = perAssetOut;
2194
+ }
2195
+ }
2196
+ return out;
2197
+ }
2198
+
2199
+ // src/client.ts
2200
+ import {
2201
+ createPublicClient as createPublicClient2,
2202
+ createWalletClient,
2203
+ custom
2204
+ } from "viem";
2205
+ import { base as base2, arbitrum as arbitrum2, mainnet as mainnet2 } from "viem/chains";
2206
+
2207
+ // src/lib/sponsor-client.ts
2208
+ var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
2209
+ async function postSponsorTransferAuth(input) {
2210
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL2;
2211
+ let res;
2212
+ try {
2213
+ res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
2214
+ method: "POST",
2215
+ headers: {
2216
+ "content-type": "application/json",
2217
+ "x-owney-api-key": input.apiKey
2218
+ },
2219
+ body: JSON.stringify(input.body)
2220
+ });
2221
+ } catch (networkError) {
2222
+ throw new OwneyError(
2223
+ "SPONSOR_REQUEST_FAILED",
2224
+ `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
2225
+ { cause: String(networkError) }
2226
+ );
2227
+ }
2228
+ const text = await res.text();
2229
+ let parsed = null;
2230
+ try {
2231
+ parsed = JSON.parse(text);
2232
+ } catch {
2233
+ }
2234
+ if (!res.ok || !parsed?.success || !parsed.data) {
2235
+ throw new OwneyError(
2236
+ "SPONSOR_REQUEST_FAILED",
2237
+ `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
2238
+ {
2239
+ statusCode: res.status,
2240
+ responseBody: text.slice(0, 500),
2241
+ // 503 SPONSOR_UNAVAILABLE = relayer out of gas; the tx was rejected
2242
+ // before broadcast, so it is safe to fall back to a user-paid deposit.
2243
+ safeToFallback: res.status === 503
2244
+ }
2245
+ );
2246
+ }
2247
+ return parsed.data;
2248
+ }
2249
+ async function postSponsorPermit2Transfer(input) {
2250
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL2;
2251
+ let res;
2252
+ try {
2253
+ res = await fetch(`${base3}/api/v1/sponsor/permit2-transfer`, {
2254
+ method: "POST",
2255
+ headers: {
2256
+ "content-type": "application/json",
2257
+ "x-owney-api-key": input.apiKey
2258
+ },
2259
+ body: JSON.stringify(input.body)
2260
+ });
2261
+ } catch (networkError) {
2262
+ throw new OwneyError(
2263
+ "SPONSOR_REQUEST_FAILED",
2264
+ `Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
2265
+ { cause: String(networkError), safeToFallback: false }
2266
+ );
2267
+ }
2268
+ const text = await res.text();
2269
+ let parsed = null;
2270
+ try {
2271
+ parsed = JSON.parse(text);
2272
+ } catch {
2273
+ }
2274
+ if (!res.ok || !parsed?.success || !parsed.data) {
2275
+ throw new OwneyError(
2219
2276
  "SPONSOR_REQUEST_FAILED",
2220
2277
  `Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
2221
2278
  {
@@ -2228,11 +2285,11 @@ async function postSponsorPermit2Transfer(input) {
2228
2285
  return parsed.data;
2229
2286
  }
2230
2287
  async function getSponsorRelayerAddress(input) {
2231
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL;
2288
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL2;
2232
2289
  let res;
2233
2290
  try {
2234
2291
  res = await fetch(
2235
- `${base5}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
2292
+ `${base3}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
2236
2293
  {
2237
2294
  headers: { "x-owney-api-key": input.apiKey }
2238
2295
  }
@@ -2265,7 +2322,7 @@ async function getSponsorRelayerAddress(input) {
2265
2322
  }
2266
2323
 
2267
2324
  // src/lib/permit2.ts
2268
- import { bytesToHex as bytesToHex2 } from "viem";
2325
+ import { bytesToHex } from "viem";
2269
2326
  var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
2270
2327
  var MAX_UINT256 = 2n ** 256n - 1n;
2271
2328
  var ERC20_ALLOWANCE_ABI = [
@@ -2322,2052 +2379,224 @@ function buildPermitTransferFromTypedData(input) {
2322
2379
  }
2323
2380
  function randomPermit2Nonce() {
2324
2381
  const bytes = new Uint8Array(32);
2325
- globalThis.crypto.getRandomValues(bytes);
2326
- return BigInt(bytesToHex2(bytes));
2327
- }
2328
- async function readPermit2Allowance(publicClient, token, owner) {
2329
- return publicClient.readContract({
2330
- address: token,
2331
- abi: ERC20_ALLOWANCE_ABI,
2332
- functionName: "allowance",
2333
- args: [owner, PERMIT2_ADDRESS]
2334
- });
2335
- }
2336
- async function readErc20Balance(publicClient, token, owner) {
2337
- return publicClient.readContract({
2338
- address: token,
2339
- abi: ERC20_ALLOWANCE_ABI,
2340
- functionName: "balanceOf",
2341
- args: [owner]
2342
- });
2343
- }
2344
-
2345
- // src/lib/sponsored-deposit.ts
2346
- var AUTH_WINDOW_SECONDS = 15 * 60;
2347
- var verificationSetter = /* @__PURE__ */ Symbol("owney.depositVerificationSetter");
2348
- function provideDepositVerificationContext(callback, context) {
2349
- callback[verificationSetter]?.(context);
2350
- }
2351
- function makeVerificationAwareDepositCallback(implementation) {
2352
- let nextVerification;
2353
- const callback = async (smartWallet, chainId, amount) => {
2354
- const verification = nextVerification;
2355
- nextVerification = void 0;
2356
- return implementation(smartWallet, chainId, amount, verification);
2357
- };
2358
- Object.defineProperty(callback, verificationSetter, {
2359
- value: (context) => {
2360
- nextVerification = context;
2361
- }
2362
- });
2363
- return callback;
2364
- }
2365
- function makeSponsoredDepositCallback(deps) {
2366
- const post = deps.httpPost ?? postSponsorTransferAuth;
2367
- return makeVerificationAwareDepositCallback(
2368
- async (smartWallet, chainId, amount, verification) => {
2369
- const cid = chainId;
2370
- const token = deps.tokenAddressByChain[cid];
2371
- if (!token) {
2372
- throw new OwneyError(
2373
- "CHAIN_UNSUPPORTED",
2374
- `No sponsored token configured for chain ${chainId}`
2375
- );
2376
- }
2377
- const pub = deps.getPublicClient(cid);
2378
- const wallet = deps.getWalletClient(cid);
2379
- await ensureWalletOnChain(pub, wallet, cid);
2380
- try {
2381
- const balance = await readErc20Balance(pub, token, deps.ownerAddress);
2382
- if (balance < BigInt(amount)) {
2383
- throw new OwneyError(
2384
- "DEPOSIT_INSUFFICIENT_BALANCE",
2385
- "Insufficient balance for this deposit.",
2386
- { token, chainId: cid, balance: balance.toString(), amount }
2387
- );
2388
- }
2389
- } catch (err) {
2390
- if (err instanceof OwneyError) throw err;
2391
- console.warn(
2392
- "[owney-sdk] Deposit balance pre-check failed (non-fatal):",
2393
- err instanceof Error ? err.message : String(err)
2394
- );
2395
- }
2396
- const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
2397
- const validAfter = 0n;
2398
- const validBefore = BigInt(
2399
- Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
2400
- );
2401
- const nonce = randomAuthNonce();
2402
- const typedData = buildTransferWithAuthorizationTypedData({
2403
- token,
2404
- chainId: cid,
2405
- tokenName,
2406
- tokenVersion,
2407
- message: {
2408
- from: deps.ownerAddress,
2409
- to: smartWallet,
2410
- value: BigInt(amount),
2411
- validAfter,
2412
- validBefore,
2413
- nonce
2414
- }
2415
- });
2416
- const authSignature = await wallet.signTypedData({
2417
- account: deps.ownerAddress,
2418
- ...typedData
2419
- });
2420
- deps.onApproved?.();
2421
- const result = await post({
2422
- baseUrl: deps.baseUrl,
2423
- apiKey: deps.apiKey,
2424
- ...verification?.agentId === "yieldseeker" ? { yieldseekerSignature: verification.signature } : {},
2425
- body: {
2426
- chainId: cid,
2427
- token,
2428
- from: deps.ownerAddress,
2429
- to: smartWallet,
2430
- value: amount,
2431
- validAfter: validAfter.toString(),
2432
- validBefore: validBefore.toString(),
2433
- nonce,
2434
- authSignature,
2435
- tokenName,
2436
- tokenVersion,
2437
- ...verification?.agentId === "yieldseeker" ? {
2438
- yieldseekerUserId: verification.userId,
2439
- yieldseekerAgentId: verification.yieldseekerAgentId
2440
- } : {}
2441
- }
2442
- });
2443
- return result.txHash;
2444
- }
2445
- );
2446
- }
2447
-
2448
- // src/agents/yieldseeker/yieldseeker.auth.ts
2449
- import { SiweMessage, generateNonce } from "siwe";
2450
- import {
2451
- createPublicClient as createPublicClient2,
2452
- createWalletClient,
2453
- custom,
2454
- getAddress
2455
- } from "viem";
2456
- import { base as base2 } from "viem/chains";
2457
-
2458
- // src/agents/yieldseeker/yieldseeker.auth-cache.ts
2459
- var KEY_PREFIX2 = "owney.yieldseeker.session.v5";
2460
- var INVALIDATED_KEY_PREFIXES = [
2461
- "owney.yieldseeker.session",
2462
- "owney.yieldseeker.session.v3",
2463
- "owney.yieldseeker.session.v4"
2464
- ];
2465
- var storage2 = () => {
2466
- if (typeof window === "undefined") return null;
2467
- try {
2468
- return window.localStorage;
2469
- } catch {
2470
- return null;
2471
- }
2472
- };
2473
- var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2474
- var invalidatedKeys = (address, chainId) => INVALIDATED_KEY_PREFIXES.map(
2475
- (prefix) => `${prefix}:${address.toLowerCase()}:${chainId}`
2476
- );
2477
- var clearInvalidatedSessions = (store, address, chainId) => {
2478
- for (const key2 of invalidatedKeys(address, chainId)) {
2479
- memorySessions2.delete(key2);
2480
- try {
2481
- store?.removeItem(key2);
2482
- } catch {
2483
- }
2484
- }
2485
- };
2486
- var memorySessions2 = /* @__PURE__ */ new Map();
2487
- var isValidSession = (session) => {
2488
- if (!session?.token) return false;
2489
- try {
2490
- const parsed = JSON.parse(atob(session.token));
2491
- return typeof parsed.message === "string" && typeof parsed.signature === "string" && parsed.signature.startsWith("0x");
2492
- } catch {
2493
- return false;
2494
- }
2495
- };
2496
- var readYieldseekerSession = (address, chainId) => {
2497
- if (typeof window === "undefined") return null;
2498
- const key2 = buildKey2(address, chainId);
2499
- const store = storage2();
2500
- clearInvalidatedSessions(store, address, chainId);
2501
- let raw2 = null;
2502
- try {
2503
- raw2 = store?.getItem(key2) ?? null;
2504
- } catch {
2505
- raw2 = null;
2506
- }
2507
- if (raw2) {
2508
- try {
2509
- const parsed = JSON.parse(raw2);
2510
- if (isValidSession(parsed)) return parsed.token;
2511
- } catch {
2512
- }
2513
- memorySessions2.delete(key2);
2514
- try {
2515
- store?.removeItem(key2);
2516
- } catch {
2517
- }
2518
- return null;
2519
- }
2520
- const cached = memorySessions2.get(key2);
2521
- if (isValidSession(cached)) return cached.token;
2522
- if (cached) memorySessions2.delete(key2);
2523
- return null;
2524
- };
2525
- var writeYieldseekerSession = (address, chainId, token) => {
2526
- if (typeof window === "undefined") return;
2527
- const session = { token };
2528
- if (!isValidSession(session)) return;
2529
- const key2 = buildKey2(address, chainId);
2530
- memorySessions2.set(key2, session);
2531
- const store = storage2();
2532
- try {
2533
- store?.setItem(key2, JSON.stringify(session));
2534
- } catch {
2535
- }
2536
- };
2537
- var clearYieldseekerSession = (address, chainId) => {
2538
- const key2 = buildKey2(address, chainId);
2539
- memorySessions2.delete(key2);
2540
- const store = storage2();
2541
- clearInvalidatedSessions(store, address, chainId);
2542
- try {
2543
- store?.removeItem(key2);
2544
- } catch {
2545
- }
2546
- };
2547
-
2548
- // src/agents/yieldseeker/yieldseeker.auth.ts
2549
- function resolveSiweOrigin(override) {
2550
- const origin = override?.trim() || (typeof window !== "undefined" ? window.location?.origin : void 0);
2551
- if (!origin || origin === "null") {
2552
- throw new Error("Yieldseeker sign-in requires the requesting app's browser origin.");
2553
- }
2554
- const url = new URL(origin);
2555
- if (url.protocol !== "https:" && url.protocol !== "http:") {
2556
- throw new Error("Yieldseeker sign-in requires an HTTP or HTTPS app origin.");
2557
- }
2558
- if (url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
2559
- throw new Error("Yieldseeker SIWE override must be an origin without credentials, path, query, or fragment.");
2560
- }
2561
- return url;
2562
- }
2563
- function createYieldseekerSiweMessage(address, chainId, dependencies = {}) {
2564
- const url = resolveSiweOrigin(dependencies.origin);
2565
- return new SiweMessage({
2566
- scheme: url.protocol.slice(0, -1),
2567
- domain: url.host,
2568
- address: getAddress(address),
2569
- uri: url.origin,
2570
- version: "1",
2571
- chainId,
2572
- nonce: (dependencies.nonce ?? generateNonce)(),
2573
- issuedAt: (dependencies.now ?? (() => /* @__PURE__ */ new Date()))().toISOString()
2574
- }).prepareMessage();
2575
- }
2576
- function encodeYieldseekerAuthToken(token) {
2577
- const bytes = new TextEncoder().encode(JSON.stringify(token));
2578
- let binary = "";
2579
- for (const byte of bytes) binary += String.fromCharCode(byte);
2580
- return btoa(binary);
2581
- }
2582
- var YieldseekerAuth = class {
2583
- constructor(dependencies = {}) {
2584
- this.dependencies = dependencies;
2585
- }
2586
- dependencies;
2587
- tokens = /* @__PURE__ */ new Map();
2588
- pending = /* @__PURE__ */ new Map();
2589
- scopes = /* @__PURE__ */ new Map();
2590
- key(state, chainId) {
2591
- return `${state.walletAddress.toLowerCase()}:${chainId}:${resolveSiweOrigin(this.dependencies.origin).origin}`;
2592
- }
2593
- async getToken(state, chainId) {
2594
- const key2 = this.key(state, chainId);
2595
- const scope = { address: state.walletAddress, chainId };
2596
- this.scopes.set(key2, scope);
2597
- const cached = this.tokens.get(key2);
2598
- if (cached) return cached;
2599
- const persisted = readYieldseekerSession(scope.address, scope.chainId);
2600
- if (persisted && this.matchesOrigin(persisted)) {
2601
- this.tokens.set(key2, persisted);
2602
- return persisted;
2603
- }
2604
- if (persisted) clearYieldseekerSession(scope.address, scope.chainId);
2605
- const inFlight = this.pending.get(key2);
2606
- if (inFlight) return inFlight;
2607
- const request = this.sign(state, chainId).then((token) => {
2608
- this.tokens.set(key2, token);
2609
- writeYieldseekerSession(scope.address, scope.chainId, token);
2610
- return token;
2611
- });
2612
- this.pending.set(key2, request);
2613
- try {
2614
- return await request;
2615
- } finally {
2616
- this.pending.delete(key2);
2617
- }
2618
- }
2619
- matchesOrigin(token) {
2620
- try {
2621
- const message = new SiweMessage(JSON.parse(atob(token)).message);
2622
- const url = resolveSiweOrigin(this.dependencies.origin);
2623
- return message.domain === url.host && message.uri === url.origin && message.scheme === url.protocol.slice(0, -1);
2624
- } catch {
2625
- return false;
2626
- }
2627
- }
2628
- clear(state, chainId) {
2629
- if (!state || chainId === void 0) {
2630
- for (const scope of this.scopes.values()) {
2631
- clearYieldseekerSession(scope.address, scope.chainId);
2632
- }
2633
- this.tokens.clear();
2634
- this.pending.clear();
2635
- this.scopes.clear();
2636
- return;
2637
- }
2638
- const key2 = this.key(state, chainId);
2639
- this.tokens.delete(key2);
2640
- this.pending.delete(key2);
2641
- this.scopes.delete(key2);
2642
- clearYieldseekerSession(state.walletAddress, chainId);
2643
- }
2644
- async sign(state, chainId) {
2645
- const account = getAddress(state.walletAddress);
2646
- const publicClient = createPublicClient2({
2647
- chain: base2,
2648
- transport: custom(state.provider)
2649
- });
2650
- const walletClient = createWalletClient({
2651
- account,
2652
- chain: base2,
2653
- transport: custom(state.provider)
2654
- });
2655
- await ensureWalletOnChain(
2656
- publicClient,
2657
- walletClient,
2658
- 8453
2659
- );
2660
- const message = createYieldseekerSiweMessage(
2661
- account,
2662
- chainId,
2663
- this.dependencies
2664
- );
2665
- const signature = await walletClient.signMessage({ account, message });
2666
- return encodeYieldseekerAuthToken({ message, signature });
2667
- }
2668
- };
2669
-
2670
- // src/agents/yieldseeker/yieldseeker.identity-cache.ts
2671
- var KEY_PREFIX3 = "owney.yieldseeker.identity.v1";
2672
- var YIELDSEEKER_IDENTITY_TTL_MS = 24 * 60 * 60 * 1e3;
2673
- var memoryIdentities = /* @__PURE__ */ new Map();
2674
- var storage3 = () => {
2675
- if (typeof window === "undefined") return null;
2676
- try {
2677
- return window.localStorage;
2678
- } catch {
2679
- return null;
2680
- }
2681
- };
2682
- var keyFor = (walletAddress, chainId) => `${KEY_PREFIX3}:${walletAddress.toLowerCase()}:${chainId}`;
2683
- function valid(value, walletAddress, chainId, now) {
2684
- return Boolean(
2685
- 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
2686
- );
2687
- }
2688
- function readYieldseekerIdentity(walletAddress, chainId, now = Date.now()) {
2689
- if (typeof window === "undefined") return null;
2690
- const key2 = keyFor(walletAddress, chainId);
2691
- const store = storage3();
2692
- let parsed = null;
2693
- try {
2694
- const raw2 = store?.getItem(key2);
2695
- parsed = raw2 ? JSON.parse(raw2) : null;
2696
- } catch {
2697
- parsed = null;
2698
- }
2699
- const candidate = parsed ?? memoryIdentities.get(key2);
2700
- if (valid(candidate, walletAddress, chainId, now)) {
2701
- memoryIdentities.set(key2, candidate);
2702
- return { userId: candidate.userId };
2703
- }
2704
- memoryIdentities.delete(key2);
2705
- try {
2706
- store?.removeItem(key2);
2707
- } catch {
2708
- }
2709
- return null;
2710
- }
2711
- function writeYieldseekerIdentity(walletAddress, chainId, userId, now = Date.now()) {
2712
- if (typeof window === "undefined") return;
2713
- const identity = {
2714
- userId,
2715
- walletAddress,
2716
- chainId,
2717
- expiresAt: now + YIELDSEEKER_IDENTITY_TTL_MS
2718
- };
2719
- if (!valid(identity, walletAddress, chainId, now)) return;
2720
- const key2 = keyFor(walletAddress, chainId);
2721
- memoryIdentities.set(key2, identity);
2722
- try {
2723
- storage3()?.setItem(key2, JSON.stringify(identity));
2724
- } catch {
2725
- }
2726
- }
2727
- function clearYieldseekerIdentity(walletAddress, chainId) {
2728
- const key2 = keyFor(walletAddress, chainId);
2729
- memoryIdentities.delete(key2);
2730
- try {
2731
- storage3()?.removeItem(key2);
2732
- } catch {
2733
- }
2734
- }
2735
-
2736
- // src/agents/yieldseeker/yieldseeker.client.ts
2737
- var DEFAULT_ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
2738
- function getYieldseekerProxyBaseUrl(routingApiBaseUrl = DEFAULT_ROUTING_API_BASE_URL) {
2739
- return `${routingApiBaseUrl.replace(/\/$/, "")}/api/v1/agent/yieldseeker`;
2740
- }
2741
- var YIELDSEEKER_API_BASE_URL = getYieldseekerProxyBaseUrl();
2742
- var YieldseekerApiError = class extends Error {
2743
- constructor(status, providerCode, responseFields) {
2744
- super(`Yieldseeker request failed (${status}): ${providerCode}`);
2745
- this.status = status;
2746
- this.providerCode = providerCode;
2747
- this.responseFields = responseFields;
2748
- this.name = "YieldseekerApiError";
2749
- }
2750
- status;
2751
- providerCode;
2752
- responseFields;
2753
- get isAuthenticationError() {
2754
- return this.status === 401 || this.status === 403;
2755
- }
2756
- };
2757
- function providerError(body, fallback) {
2758
- if (!body || typeof body !== "object") return { code: fallback };
2759
- const record = body;
2760
- return {
2761
- code: typeof record.message === "string" ? record.message : fallback,
2762
- fields: record.fields && typeof record.fields === "object" ? record.fields : void 0
2763
- };
2764
- }
2765
- var YieldseekerApiClient = class {
2766
- constructor(owneyApiKey, baseUrl = YIELDSEEKER_API_BASE_URL, fetchFn = fetch) {
2767
- this.owneyApiKey = owneyApiKey;
2768
- this.baseUrl = baseUrl;
2769
- this.fetchFn = fetchFn;
2770
- }
2771
- owneyApiKey;
2772
- baseUrl;
2773
- fetchFn;
2774
- async request(path, options = {}) {
2775
- const controller = new AbortController();
2776
- const timer = setTimeout(
2777
- () => controller.abort(),
2778
- options.timeoutMs ?? 15e3
2779
- );
2780
- try {
2781
- const response = await this.fetchFn(`${this.baseUrl}${path}`, {
2782
- method: options.method ?? "GET",
2783
- headers: {
2784
- "Content-Type": "application/json",
2785
- "x-owney-api-key": this.owneyApiKey,
2786
- ...options.signature ? { Authorization: `Signature ${options.signature}` } : {}
2787
- },
2788
- body: options.body ? JSON.stringify(options.body) : void 0,
2789
- signal: controller.signal
2790
- });
2791
- const payload = await response.json().catch(() => null);
2792
- if (!response.ok) {
2793
- const error = providerError(payload, `HTTP_${response.status}`);
2794
- throw new YieldseekerApiError(
2795
- response.status,
2796
- error.code,
2797
- error.fields
2798
- );
2799
- }
2800
- if (payload && typeof payload === "object" && payload.success === true && "data" in payload) {
2801
- return payload.data;
2802
- }
2803
- return payload;
2804
- } catch (error) {
2805
- if (error instanceof YieldseekerApiError) throw error;
2806
- if (error instanceof DOMException && error.name === "AbortError") {
2807
- throw new YieldseekerApiError(408, "REQUEST_TIMEOUT");
2808
- }
2809
- throw new YieldseekerApiError(0, "NETWORK_ERROR", {
2810
- cause: error instanceof Error ? error.message : String(error)
2811
- });
2812
- } finally {
2813
- clearTimeout(timer);
2814
- }
2815
- }
2816
- };
2817
-
2818
- // src/agents/yieldseeker/yieldseeker.mapper.ts
2819
- import { formatUnits, isAddress } from "viem";
2820
-
2821
- // src/lib/helpers/snapshot-apy.ts
2822
- var DAY_MS = 864e5;
2823
- function snapshotTime(date) {
2824
- if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) return void 0;
2825
- const time = Date.parse(date);
2826
- return Number.isFinite(time) && new Date(time).toISOString().slice(0, 10) === date ? time : void 0;
2827
- }
2828
- function returnFactor(value) {
2829
- if (typeof value !== "number" && typeof value !== "string") return void 0;
2830
- if (typeof value === "string" && value.trim() === "") return void 0;
2831
- const factor = Number(value);
2832
- return Number.isFinite(factor) && factor >= 0 ? factor : void 0;
2833
- }
2834
- function calculateSnapshotApy(snapshots, lookbackDays, now = Date.now()) {
2835
- if (!Number.isFinite(lookbackDays) || lookbackDays <= 0 || !Number.isFinite(now)) {
2836
- return void 0;
2837
- }
2838
- const points = snapshots.flatMap((snapshot) => {
2839
- const time = snapshotTime(snapshot.date);
2840
- return time !== void 0 && time <= now ? [{ snapshot, time }] : [];
2841
- }).sort((a, b) => a.time - b.time);
2842
- const end = points.at(-1);
2843
- if (!end) return void 0;
2844
- const cutoff = end.time - lookbackDays * DAY_MS;
2845
- const start = points.find((point) => point.time >= cutoff);
2846
- const actualDays = (end.time - start.time) / DAY_MS;
2847
- if (actualDays <= 0) return void 0;
2848
- const startFactor = returnFactor(start.snapshot.cumulativeReturnFactor);
2849
- const endFactor = returnFactor(end.snapshot.cumulativeReturnFactor);
2850
- if (startFactor === void 0 || startFactor === 0 || endFactor === void 0) {
2851
- return void 0;
2852
- }
2853
- const periodReturn = endFactor / startFactor - 1;
2854
- const apy = Math.pow(1 + periodReturn, 365 / actualDays) - 1;
2855
- return Number.isFinite(apy) ? apy : void 0;
2856
- }
2857
-
2858
- // src/agents/yieldseeker/yieldseeker.types.ts
2859
- var YIELDSEEKER_ASSET_METADATA = {
2860
- USDC: {
2861
- address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
2862
- decimals: 6
2863
- },
2864
- WETH: {
2865
- address: "0x4200000000000000000000000000000000000006",
2866
- decimals: 18
2867
- }
2868
- };
2869
-
2870
- // src/agents/yieldseeker/yieldseeker.mapper.ts
2871
- function invalid(endpoint, detail) {
2872
- throw new OwneyError(
2873
- "AGENT_INVALID_RESPONSE",
2874
- `Yieldseeker returned an invalid ${endpoint} response: ${detail}.`,
2875
- { endpoint, detail },
2876
- "yieldseeker"
2877
- );
2878
- }
2879
- function raw(value, endpoint) {
2880
- if (typeof value !== "string" || !/^-?[0-9]+$/.test(value)) {
2881
- return invalid(endpoint, "expected a base-10 integer string");
2882
- }
2883
- return BigInt(value);
2884
- }
2885
- function decimal(value, decimals, endpoint) {
2886
- return formatUnits(raw(value, endpoint), decimals);
2887
- }
2888
- function usd(rawAmount, decimals, price) {
2889
- return Number(formatUnits(rawAmount, decimals)) * price;
2890
- }
2891
- function percent(value) {
2892
- const result = Number(value);
2893
- return Number.isFinite(result) ? result * 100 : 0;
2894
- }
2895
- var YIELDSEEKER_POSITIVE_YIELD_FEE_RATE = 0.1;
2896
- function publicApyAfterYieldseekerFee(value) {
2897
- const grossPercent = percent(value);
2898
- if (grossPercent <= 0) return grossPercent;
2899
- const netPercent = grossPercent * (1 - YIELDSEEKER_POSITIVE_YIELD_FEE_RATE);
2900
- return Math.round(netPercent * 1e12) / 1e12;
2901
- }
2902
- function riskAdjustedApyForDays(option, days) {
2903
- if (days === "7D") return option.riskAdjustedApy7dAverage;
2904
- if (days === "30D") return option.riskAdjustedApy30dAverage;
2905
- return (option.riskAdjustedApy7dAverage + option.riskAdjustedApy30dAverage) / 2;
2906
- }
2907
- function assetAddressValue(record, address) {
2908
- const entry = Object.entries(record).find(
2909
- ([key2]) => key2.toLowerCase() === address.toLowerCase()
2910
- );
2911
- return entry?.[1] ?? "0";
2912
- }
2913
- function position(value, asset, baseAssetDecimals) {
2914
- const option = value?.yieldOption;
2915
- if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !isAddress(option.address)) {
2916
- return invalid("yield positions", "missing vault metadata");
2917
- }
2918
- return {
2919
- chain: "BASE",
2920
- protocol: option.provider,
2921
- protocolId: option.address,
2922
- pool: option.name,
2923
- asset,
2924
- // `assetsRaw` is the ERC-4626 vault-share quantity, whose decimals can
2925
- // differ from the underlying asset. Yieldseeker already converts it to
2926
- // underlying base-asset units in `assetsBase`; pair that value with the
2927
- // snapshot's corresponding `baseAssetDecimals` for display. Keep the raw
2928
- // share quantity separately because withdraw-from-position expects it.
2929
- amount: decimal(
2930
- value.assetsBase,
2931
- baseAssetDecimals,
2932
- "yield positions"
2933
- ),
2934
- amountRaw: String(value.assetsRaw),
2935
- apy: percent(option.riskAdjustedApy),
2936
- tvl: Number(option.totalDepositsUsd),
2937
- liquidity: Number(option.withdrawableDepositsUsd)
2938
- };
2939
- }
2940
- function mapYieldseekerBalances(contexts) {
2941
- const tokens = [];
2942
- const assetBalances = [];
2943
- const positions = [];
2944
- let totalUsd = 0;
2945
- for (const context of contexts) {
2946
- const metadata = YIELDSEEKER_ASSET_METADATA[context.asset];
2947
- assetBalances.push({
2948
- chain: "BASE",
2949
- chainId: 8453,
2950
- asset: context.asset,
2951
- amount: decimal(context.snapshot.totalValueBase, context.snapshot.baseAssetDecimals, "snapshot")
2952
- });
2953
- const idle = assetAddressValue(
2954
- context.snapshot.tokenBalances,
2955
- metadata.address
2956
- );
2957
- tokens.push({
2958
- chain: "BASE",
2959
- chainId: 8453,
2960
- asset: context.asset,
2961
- amount: decimal(idle, metadata.decimals, "snapshot")
2962
- });
2963
- positions.push(
2964
- ...context.positions.map(
2965
- (entry) => position(
2966
- entry,
2967
- context.asset,
2968
- context.snapshot.baseAssetDecimals
2969
- )
2970
- )
2971
- );
2972
- totalUsd += usd(
2973
- raw(context.snapshot.totalValueBase, "snapshot"),
2974
- context.snapshot.baseAssetDecimals,
2975
- context.snapshot.baseAssetPriceUsd
2976
- );
2977
- }
2978
- return {
2979
- ...contexts.length === 1 ? { smartWallet: contexts[0].wallet.walletAddress } : {},
2980
- totalBalance: String(totalUsd),
2981
- totalBalanceAsset: "usdc",
2982
- assetBalances,
2983
- tokens,
2984
- positions
2985
- };
2986
- }
2987
- function mapYieldseekerEarnings(contexts) {
2988
- const tokens = [];
2989
- let lifetimeEarnings = 0;
2990
- for (const context of contexts) {
2991
- const amount = raw(context.snapshot.cumulativeYieldBase, "snapshot");
2992
- tokens.push({
2993
- chain: "BASE",
2994
- chainId: 8453,
2995
- asset: context.asset,
2996
- amount: formatUnits(amount, context.snapshot.baseAssetDecimals)
2997
- });
2998
- lifetimeEarnings += usd(
2999
- amount,
3000
- context.snapshot.baseAssetDecimals,
3001
- context.snapshot.baseAssetPriceUsd
3002
- );
3003
- }
3004
- return {
3005
- smartWallet: contexts[0]?.wallet.walletAddress ?? "0x0000000000000000000000000000000000000000",
3006
- lifetimeEarnings,
3007
- tokens
3008
- };
3009
- }
3010
- function apyForDays(context, days, now) {
3011
- if (days === "7D") return percent(context.snapshot.apy7d);
3012
- if (days === "30D") return percent(context.snapshot.apy30d);
3013
- const apy = calculateSnapshotApy(context.historic?.dailyYieldSnapshots ?? [], 14, now);
3014
- const apyPercent = apy === void 0 ? void 0 : apy * 100;
3015
- return apyPercent !== void 0 && Number.isFinite(apyPercent) ? apyPercent : void 0;
3016
- }
3017
- function dailyApy(point) {
3018
- const total = raw(point.totalValueBase, "historic position");
3019
- const earned = raw(point.dailyYieldBase, "historic position");
3020
- const principal = total - earned;
3021
- if (principal <= 0n || earned === 0n) return 0;
3022
- return Number(earned) / Number(principal) * 365 * 100;
3023
- }
3024
- function aggregateHistory(contexts, dayCount, now) {
3025
- const today = new Date(now).toISOString().slice(0, 10);
3026
- const cutoff = new Date(Date.parse(today) - (dayCount - 1) * 864e5).toISOString().slice(0, 10);
3027
- const assets = new Set(contexts.map((context) => context.asset.toUpperCase()));
3028
- const unit = assets.size === 1 ? [...assets][0] : "USD";
3029
- const byDate = /* @__PURE__ */ new Map();
3030
- for (const context of contexts) {
3031
- const points = context.historic?.dailyYieldSnapshots ?? [];
3032
- for (const point of points) {
3033
- if (!/^\d{4}-\d{2}-\d{2}$/.test(point.date) || !Number.isFinite(Date.parse(point.date)) || point.date < cutoff || point.date > today) continue;
3034
- const tokens = Number(decimal(point.totalValueBase, point.baseAssetDecimals, "historic position"));
3035
- const amount = assets.size === 1 ? tokens : tokens * point.baseAssetPriceUsd;
3036
- if (!Number.isFinite(amount) || amount < 0) {
3037
- invalid("historic position", "expected a finite non-negative balance");
3038
- }
3039
- const current = byDate.get(point.date) ?? { weighted: 0, amount: 0 };
3040
- current.weighted += dailyApy(point) * amount;
3041
- current.amount += amount;
3042
- byDate.set(point.date, current);
3043
- }
3044
- }
3045
- return [...byDate.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([date, value]) => ({
3046
- date,
3047
- apy: value.amount > 0 ? value.weighted / value.amount : 0,
3048
- historicalBalance: { amount: value.amount, unit }
3049
- }));
3050
- }
3051
- function mapYieldseekerApy(walletAddress, contexts, days, now = Date.now()) {
3052
- let weighted = 0;
3053
- let totalUsd = 0;
3054
- const byAsset = {};
3055
- for (const context of contexts) {
3056
- const valueUsd = usd(
3057
- raw(context.snapshot.totalValueBase, "snapshot"),
3058
- context.snapshot.baseAssetDecimals,
3059
- context.snapshot.baseAssetPriceUsd
3060
- );
3061
- const apy = apyForDays(context, days, now);
3062
- if (apy === void 0) continue;
3063
- weighted += apy * valueUsd;
3064
- totalUsd += valueUsd;
3065
- byAsset[context.asset] = apy;
3066
- }
3067
- const dayCount = Number(days.slice(0, -1));
3068
- return {
3069
- walletAddress,
3070
- ...days !== "14D" || Object.keys(byAsset).length > 0 ? { weightedApyAfterFee: totalUsd > 0 ? weighted / totalUsd : 0 } : {},
3071
- apyByChainAndAsset: { 8453: byAsset },
3072
- history: aggregateHistory(contexts, dayCount, now)
3073
- };
3074
- }
3075
- function actionType(value) {
3076
- const normalized = value.toLowerCase();
3077
- if (normalized.includes("deposit")) return "Deposit";
3078
- if (normalized.includes("withdraw")) return "Withdraw";
3079
- if (normalized.includes("yield") || normalized.includes("earn"))
3080
- return "Earned";
3081
- return "Rebalance";
3082
- }
3083
- function transactionHashes(details) {
3084
- if (!details) return [];
3085
- const values = [
3086
- details.transactionHash,
3087
- details.txHash,
3088
- ...Array.isArray(details.transactionHashes) ? details.transactionHashes : [],
3089
- ...Array.isArray(details.txHashes) ? details.txHashes : []
3090
- ];
3091
- return values.filter(
3092
- (value) => typeof value === "string" && /^0x[a-fA-F0-9]{64}$/.test(value)
3093
- ).filter((value, index, all) => all.indexOf(value) === index);
3094
- }
3095
- function actionEntry(action) {
3096
- if (action.actionType.toLowerCase().includes("withdraw")) return void 0;
3097
- return {
3098
- agent: "yieldseeker",
3099
- action: actionType(action.actionType),
3100
- date: action.createdDate,
3101
- oldApy: null,
3102
- newApy: null,
3103
- transactions: [
3104
- {
3105
- txHashes: transactionHashes(action.details),
3106
- chainId: 8453
3107
- }
3108
- ],
3109
- rebalanceLog: []
3110
- };
3111
- }
3112
- function movementEntry(movement, wallet, agent, asset, ownerAddress, vaultAddresses) {
3113
- const from = movement.fromAddress.toLowerCase();
3114
- const to = movement.toAddress.toLowerCase();
3115
- const owner = ownerAddress.toLowerCase();
3116
- const agentWallet = wallet.walletAddress.toLowerCase();
3117
- const baseAsset = agent.assetAddress.toLowerCase();
3118
- if (movement.chainId !== agent.chainId || movement.assetAddress.toLowerCase() !== baseAsset) {
3119
- return void 0;
3120
- }
3121
- let action;
3122
- if (from === owner && to === agentWallet) {
3123
- action = "Top up";
3124
- } else if (from === agentWallet && to === owner) {
3125
- action = "Withdraw";
3126
- } else if (from === agentWallet && vaultAddresses.has(to)) {
3127
- action = "Deposit";
3128
- }
3129
- if (!action) return void 0;
3130
- return {
3131
- agent: "yieldseeker",
3132
- action,
3133
- date: movement.blockDate,
3134
- oldApy: null,
3135
- newApy: null,
3136
- transactions: [
3137
- {
3138
- txHashes: [movement.transactionHash],
3139
- chainId: agent.chainId,
3140
- tokenSymbol: asset,
3141
- amount: decimal(
3142
- movement.assetAmount,
3143
- YIELDSEEKER_ASSET_METADATA[asset].decimals,
3144
- "historic position"
3145
- )
3146
- }
3147
- ],
3148
- rebalanceLog: []
3149
- };
3150
- }
3151
- function mapYieldseekerHistory(contexts, options) {
3152
- const entries = contexts.flatMap((context) => {
3153
- const vaultAddresses = new Set(
3154
- context.positions.map(
3155
- (position2) => position2.yieldOption.address.toLowerCase()
3156
- )
3157
- );
3158
- return [
3159
- ...(context.historic?.movements ?? []).map(
3160
- (movement) => movementEntry(
3161
- movement,
3162
- context.wallet,
3163
- context.agent,
3164
- context.asset,
3165
- options.ownerAddress,
3166
- vaultAddresses
3167
- )
3168
- ),
3169
- ...(context.actions ?? []).map(actionEntry)
3170
- ].filter((entry) => entry !== void 0);
3171
- });
3172
- const filtered = entries.filter(
3173
- (entry) => (!options.fromDate || entry.date >= options.fromDate) && (!options.toDate || entry.date <= options.toDate)
3174
- ).filter((entry, index, all) => {
3175
- const transactionHash = entry.transactions[0]?.txHashes[0];
3176
- if (!transactionHash) return true;
3177
- return all.findIndex(
3178
- (candidate) => candidate.action === entry.action && candidate.transactions[0]?.txHashes[0] === transactionHash
3179
- ) === index;
3180
- }).sort((left, right) => right.date.localeCompare(left.date));
3181
- return {
3182
- data: filtered.slice(0, options.limit),
3183
- // v1 returns the whole action/movement collection and defines no cursor.
3184
- // Report a terminal page so callers never loop over the same prefix.
3185
- hasMore: false
3186
- };
3187
- }
3188
- function mapYieldseekerProfile(address, contexts) {
3189
- const protocols = /* @__PURE__ */ new Set();
3190
- for (const context of contexts) {
3191
- for (const current of context.positions) {
3192
- if (current.yieldOption?.provider) {
3193
- protocols.add(String(current.yieldOption.provider));
3194
- }
3195
- }
3196
- }
3197
- return {
3198
- address,
3199
- smartWallet: contexts[0]?.wallet.walletAddress ?? "0x0000000000000000000000000000000000000000",
3200
- chains: contexts.length > 0 ? [8453] : [],
3201
- hasActiveSessionKey: contexts.some(
3202
- (context) => context.wallet.initializedDate != null
3203
- ),
3204
- protocols: [...protocols]
3205
- };
3206
- }
3207
- function mapYieldseekerAgentApy(options, days) {
3208
- const perAsset = {};
3209
- const all = [];
3210
- for (const entry of options) {
3211
- const apys = entry.yieldOptions.map(
3212
- (option) => publicApyAfterYieldseekerFee(riskAdjustedApyForDays(option, days))
3213
- ).filter(Number.isFinite);
3214
- if (apys.length === 0) continue;
3215
- const average = apys.reduce((sum, value) => sum + value, 0) / apys.length;
3216
- perAsset[entry.asset] = average;
3217
- all.push(average);
3218
- }
3219
- return {
3220
- averageApy: all.length > 0 ? all.reduce((sum, value) => sum + value, 0) / all.length : 0,
3221
- detailedApys: { apyPerAsset: { 8453: perAsset } }
3222
- };
3223
- }
3224
-
3225
- // src/agents/yieldseeker/yieldseeker.agent.ts
3226
- var OWNEY_AGENT_NAME = "owney";
3227
- var YIELDSEEKER_USERNAME_PREFIX = "owney_";
3228
- var YIELDSEEKER_USERNAME_RANDOM_LENGTH = 14;
3229
- var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
3230
- function generateYieldseekerUsername() {
3231
- const suffix = globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, YIELDSEEKER_USERNAME_RANDOM_LENGTH).toLowerCase();
3232
- return `${YIELDSEEKER_USERNAME_PREFIX}${suffix}`;
3233
- }
3234
- function isUsernameConflict(error) {
3235
- if (!(error instanceof YieldseekerApiError)) return false;
3236
- const code = error.providerCode.toUpperCase();
3237
- return code.includes("USERNAME") && (code.includes("TAKEN") || code.includes("EXIST") || code.includes("UNAVAILABLE") || code.includes("IN_USE"));
3238
- }
3239
- var YIELDSEEKER_AGENT_WALLET_ABI = [
3240
- {
3241
- type: "function",
3242
- name: "withdrawAssetToUser",
3243
- stateMutability: "nonpayable",
3244
- inputs: [
3245
- { name: "recipient", type: "address" },
3246
- { name: "asset", type: "address" },
3247
- { name: "amount", type: "uint256" }
3248
- ],
3249
- outputs: []
3250
- },
3251
- {
3252
- type: "function",
3253
- name: "withdrawAllAssetToUser",
3254
- stateMutability: "nonpayable",
3255
- inputs: [
3256
- { name: "recipient", type: "address" },
3257
- { name: "asset", type: "address" }
3258
- ],
3259
- outputs: []
3260
- }
3261
- ];
3262
- function query(params) {
3263
- const search = new URLSearchParams();
3264
- for (const [key2, value] of Object.entries(params)) {
3265
- if (value !== void 0) search.set(key2, String(value));
3266
- }
3267
- const encoded = search.toString();
3268
- return encoded ? `?${encoded}` : "";
3269
- }
3270
- var YieldseekerAgent = class {
3271
- id = "yieldseeker";
3272
- balanceComposition = "tokens-plus-positions";
3273
- supportedChainIds = [8453];
3274
- supportedAssets = [
3275
- {
3276
- chainId: 8453,
3277
- chain: "BASE",
3278
- assets: [
3279
- { symbol: "USDC", minDepositAmount: "10000000" },
3280
- { symbol: "WETH", minDepositAmount: "1" }
3281
- ]
3282
- }
3283
- ];
3284
- api;
3285
- auth;
3286
- transactionExecutor;
3287
- unwindReceiptWaiter;
3288
- agentContexts = /* @__PURE__ */ new Map();
3289
- users = /* @__PURE__ */ new Map();
3290
- pendingAgents = /* @__PURE__ */ new Map();
3291
- constructor(owneyApiKey, options = {}) {
3292
- this.api = new YieldseekerApiClient(
3293
- owneyApiKey,
3294
- options.baseUrl ?? getYieldseekerProxyBaseUrl(),
3295
- options.fetchFn
3296
- );
3297
- this.auth = new YieldseekerAuth(options.auth);
3298
- this.transactionExecutor = options.transactionExecutor;
3299
- this.unwindReceiptWaiter = options.unwindReceiptWaiter;
3300
- }
3301
- async disconnect() {
3302
- this.auth.clear();
3303
- for (const key2 of this.users.keys()) {
3304
- const [walletAddress, chainId] = key2.split(":");
3305
- clearYieldseekerIdentity(walletAddress, Number(chainId));
3306
- }
3307
- this.users.clear();
3308
- this.agentContexts.clear();
3309
- this.pendingAgents.clear();
3310
- }
3311
- async activateAgent(state, chainId, asset) {
3312
- this.assertChain(chainId);
3313
- const targetAsset = asset ?? "USDC";
3314
- this.assertAsset(targetAsset);
3315
- await this.ensureAgent(state, chainId, targetAsset);
3316
- }
3317
- async deposit(state, chainId, amount, asset, depositCallback) {
3318
- this.assertChain(chainId);
3319
- this.assertAsset(asset);
3320
- if (BigInt(amount) <= 0n) {
3321
- throw new OwneyError(
3322
- "DEPOSIT_AMOUNT_BELOW_MINIMUM",
3323
- "Yieldseeker deposits must be greater than zero.",
3324
- { amount, minDepositAmount: "1" },
3325
- this.id
3326
- );
3327
- }
3328
- const context = await this.ensureAgent(state, chainId, asset);
3329
- let txHash;
3330
- try {
3331
- if (depositCallback) {
3332
- provideDepositVerificationContext(depositCallback, {
3333
- agentId: "yieldseeker",
3334
- signature: await this.auth.getToken(state, chainId),
3335
- userId: context.user.userId,
3336
- yieldseekerAgentId: context.agent.agentId
3337
- });
3338
- txHash = await depositCallback(
3339
- context.wallet.walletAddress,
3340
- chainId,
3341
- amount
3342
- );
3343
- await this.waitForReceipt(state, chainId, txHash);
3344
- } else {
3345
- txHash = await this.submitTransaction(state, chainId, {
3346
- from: getAddress2(state.walletAddress),
3347
- to: YIELDSEEKER_ASSET_METADATA[asset].address,
3348
- data: encodeFunctionData({
3349
- abi: erc20Abi,
3350
- functionName: "transfer",
3351
- args: [getAddress2(context.wallet.walletAddress), BigInt(amount)]
3352
- }),
3353
- value: "0",
3354
- chainId
3355
- });
3356
- }
3357
- await this.deployAfterFunding(state, chainId, context);
3358
- } finally {
3359
- await this.refreshSnapshotAfterMovement(
3360
- state,
3361
- chainId,
3362
- context,
3363
- "deposit"
3364
- );
3365
- }
3366
- return {
3367
- txHash,
3368
- smartWallet: context.wallet.walletAddress,
3369
- amount
3370
- };
3371
- }
3372
- async withdraw(state, chainId, asset, amount) {
3373
- this.assertChain(chainId);
3374
- this.assertAsset(asset);
3375
- if (amount !== void 0 && BigInt(amount) <= 0n) {
3376
- throw new OwneyError(
3377
- "WITHDRAW_FAILED",
3378
- "Yieldseeker withdrawals must be greater than zero.",
3379
- { amount },
3380
- this.id
3381
- );
3382
- }
3383
- const context = await this.findAgent(state, chainId, asset);
3384
- if (!context) {
3385
- throw new OwneyError(
3386
- "WITHDRAW_INSUFFICIENT_BALANCE",
3387
- `No Yieldseeker ${asset} agent exists for this wallet.`,
3388
- { asset, available: "0" },
3389
- this.id
3390
- );
3391
- }
3392
- try {
3393
- const portfolio = await this.loadPortfolioContext(
3394
- state,
3395
- chainId,
3396
- context
3397
- );
3398
- const metadata = YIELDSEEKER_ASSET_METADATA[asset];
3399
- const idleEntry = Object.entries(portfolio.snapshot.tokenBalances).find(
3400
- ([address]) => address.toLowerCase() === metadata.address.toLowerCase()
3401
- );
3402
- const idle = BigInt(idleEntry?.[1] ?? "0");
3403
- const deployed = portfolio.positions.reduce(
3404
- (total, position2) => total + BigInt(position2.withdrawableAssetsRaw),
3405
- 0n
3406
- );
3407
- const totalAvailable = idle + deployed;
3408
- const requested = amount === void 0 ? totalAvailable : BigInt(amount);
3409
- if (requested > totalAvailable) {
3410
- throw new OwneyError(
3411
- "WITHDRAW_INSUFFICIENT_BALANCE",
3412
- `Requested withdrawal "${requested}" exceeds available Yieldseeker balance "${totalAvailable}" for asset "${asset}".`,
3413
- {
3414
- asset,
3415
- requested: requested.toString(),
3416
- available: totalAvailable.toString()
3417
- },
3418
- this.id
3419
- );
3420
- }
3421
- let remaining = requested > idle ? requested - idle : 0n;
3422
- for (const position2 of portfolio.positions) {
3423
- if (remaining === 0n) break;
3424
- const available = BigInt(position2.withdrawableAssetsRaw);
3425
- if (available <= 0n) continue;
3426
- const assetsRaw = available < remaining ? available : remaining;
3427
- const response = await this.walletRequest(
3428
- state,
3429
- chainId,
3430
- this.agentPath(context, "withdraw-from-position"),
3431
- {
3432
- method: "POST",
3433
- body: {
3434
- chainId,
3435
- vaultAddress: position2.yieldOption.address,
3436
- assetsRaw: assetsRaw.toString()
3437
- }
3438
- }
3439
- );
3440
- if (!this.isTransactionHash(response?.transactionHash)) {
3441
- throw this.invalidResponse("position withdrawal");
3442
- }
3443
- await this.waitForReceipt(state, chainId, response.transactionHash);
3444
- remaining -= assetsRaw;
3445
- }
3446
- if (remaining > 0n) {
3447
- throw this.invalidResponse("yield positions", {
3448
- reason: "Withdrawable positions could not cover the request.",
3449
- remaining: remaining.toString()
3450
- });
3451
- }
3452
- const account = getAddress2(state.walletAddress);
3453
- const txHash = await this.submitTransaction(state, chainId, {
3454
- from: account,
3455
- to: getAddress2(context.wallet.walletAddress),
3456
- data: amount === void 0 ? encodeFunctionData({
3457
- abi: YIELDSEEKER_AGENT_WALLET_ABI,
3458
- functionName: "withdrawAllAssetToUser",
3459
- args: [account, metadata.address]
3460
- }) : encodeFunctionData({
3461
- abi: YIELDSEEKER_AGENT_WALLET_ABI,
3462
- functionName: "withdrawAssetToUser",
3463
- args: [account, metadata.address, requested]
3464
- }),
3465
- value: "0",
3466
- chainId
3467
- });
3468
- return {
3469
- txHash,
3470
- type: amount === void 0 ? "full" : "partial",
3471
- amount: requested.toString()
3472
- };
3473
- } finally {
3474
- await this.refreshSnapshotAfterMovement(
3475
- state,
3476
- chainId,
3477
- context,
3478
- "withdrawal"
3479
- );
3480
- }
3481
- }
3482
- async getBalances(state, chainId) {
3483
- this.assertChain(chainId);
3484
- return mapYieldseekerBalances(await this.loadPortfolio(state, chainId, {}));
3485
- }
3486
- async getEarnings(state, chainId) {
3487
- this.assertChain(chainId);
3488
- return mapYieldseekerEarnings(await this.loadPortfolio(state, chainId, {}));
3489
- }
3490
- async getAccountApy(state, chainId, days, tokenSymbol) {
3491
- this.assertChain(chainId);
3492
- const asset = tokenSymbol?.toUpperCase();
3493
- if (asset !== void 0) this.assertAsset(asset);
3494
- const contexts = await this.loadPortfolio(state, chainId, {
3495
- ...asset ? { asset } : {},
3496
- historic: true
3497
- });
3498
- return mapYieldseekerApy(state.walletAddress, contexts, days);
3499
- }
3500
- async getHistory(state, chainId, options) {
3501
- this.assertChain(chainId);
3502
- const asset = options?.tokenSymbol?.toUpperCase();
3503
- if (asset !== void 0) this.assertAsset(asset);
3504
- const contexts = await this.loadPortfolio(state, chainId, {
3505
- ...asset ? { asset } : {},
3506
- historic: true,
3507
- actions: true
3508
- });
3509
- return mapYieldseekerHistory(contexts, {
3510
- limit: options?.limit ?? 10,
3511
- ownerAddress: state.walletAddress,
3512
- ...options?.fromDate ? { fromDate: options.fromDate } : {},
3513
- ...options?.toDate ? { toDate: options.toDate } : {}
3514
- });
3515
- }
3516
- async getUserProfile(state, chainId) {
3517
- this.assertChain(chainId);
3518
- return mapYieldseekerProfile(
3519
- state.walletAddress,
3520
- await this.loadPortfolio(state, chainId, {})
3521
- );
3522
- }
3523
- async getAgentApy(days, options) {
3524
- this.assertOptionalChain(options?.chainId);
3525
- const requested = options?.tokenSymbol?.toUpperCase();
3526
- if (requested !== void 0) this.assertAsset(requested);
3527
- const assets = requested ? [requested] : ["USDC", "WETH"];
3528
- const values = await Promise.all(
3529
- assets.map(async (asset) => {
3530
- const metadata = YIELDSEEKER_ASSET_METADATA[asset];
3531
- const response = await this.api.request(
3532
- `/chains/8453/assets/${metadata.address}/yield-options`
3533
- );
3534
- if (!Array.isArray(response?.yieldOptions)) {
3535
- throw this.invalidResponse("yield options");
3536
- }
3537
- return { asset, yieldOptions: response.yieldOptions };
3538
- })
3539
- );
3540
- return mapYieldseekerAgentApy(values, days);
3541
- }
3542
- userKey(state, chainId) {
3543
- return `${state.walletAddress.toLowerCase()}:${chainId}`;
3544
- }
3545
- contextKey(state, chainId, asset) {
3546
- return `${this.userKey(state, chainId)}:${asset}`;
3547
- }
3548
- async resolveUser(state, chainId) {
3549
- const key2 = this.userKey(state, chainId);
3550
- const inMemory = this.users.get(key2);
3551
- if (inMemory) return inMemory;
3552
- const persisted = readYieldseekerIdentity(state.walletAddress, chainId);
3553
- if (persisted) {
3554
- this.users.set(key2, persisted);
3555
- return persisted;
3556
- }
3557
- const walletAddress = getAddress2(state.walletAddress);
3558
- let user = null;
3559
- try {
3560
- const login = await this.providerRequest(
3561
- state,
3562
- chainId,
3563
- "/users/login-with-wallet",
3564
- { method: "POST", body: { walletAddress } }
3565
- );
3566
- user = login?.user ?? null;
3567
- if (!user) {
3568
- throw this.invalidResponse("wallet login", {
3569
- reason: "A successful login returned no user."
3570
- });
3571
- }
3572
- } catch (error) {
3573
- if (!(error instanceof YieldseekerApiError) || error.providerCode !== "NO_USER") {
3574
- if (error instanceof OwneyError) throw error;
3575
- throw this.mapApiError(error);
3576
- }
3577
- let created;
3578
- for (let attempt = 0; attempt < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS; attempt += 1) {
3579
- try {
3580
- created = await this.providerRequest(
3581
- state,
3582
- chainId,
3583
- "/users",
3584
- {
3585
- method: "POST",
3586
- body: {
3587
- walletAddress,
3588
- username: generateYieldseekerUsername()
3589
- }
3590
- }
3591
- );
3592
- break;
3593
- } catch (createError) {
3594
- const canRetry = isUsernameConflict(createError) && attempt + 1 < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS;
3595
- if (canRetry) continue;
3596
- throw this.mapApiError(createError);
3597
- }
3598
- }
3599
- user = created?.user ?? null;
3600
- }
3601
- if (!user || !/^[a-zA-Z0-9_-]{1,128}$/.test(user.userId)) {
3602
- throw this.invalidResponse("wallet identity");
3603
- }
3604
- const resolved = { userId: user.userId };
3605
- this.users.set(key2, resolved);
3606
- writeYieldseekerIdentity(state.walletAddress, chainId, resolved.userId);
3607
- return resolved;
3608
- }
3609
- forgetUser(state, chainId) {
3610
- this.users.delete(this.userKey(state, chainId));
3611
- clearYieldseekerIdentity(state.walletAddress, chainId);
3612
- }
3613
- async ensureAgent(state, chainId, asset) {
3614
- const key2 = this.contextKey(state, chainId, asset);
3615
- const cached = this.agentContexts.get(key2);
3616
- if (cached) return cached;
3617
- const pending = this.pendingAgents.get(key2);
3618
- if (pending) return pending;
3619
- const request = this.resolveAgent(state, chainId, asset, true).then(
3620
- (context) => {
3621
- if (!context) throw this.invalidResponse("agent creation");
3622
- this.agentContexts.set(key2, context);
3623
- return context;
3624
- }
3625
- );
3626
- this.pendingAgents.set(key2, request);
3627
- try {
3628
- return await request;
3629
- } finally {
3630
- this.pendingAgents.delete(key2);
3631
- }
3632
- }
3633
- async findAgent(state, chainId, asset) {
3634
- const key2 = this.contextKey(state, chainId, asset);
3635
- const cached = this.agentContexts.get(key2);
3636
- if (cached) return cached;
3637
- const context = await this.resolveAgent(state, chainId, asset, false);
3638
- if (context) this.agentContexts.set(key2, context);
3639
- return context;
3640
- }
3641
- async resolveAgent(state, chainId, asset, createIfMissing) {
3642
- const user = await this.resolveUser(state, chainId);
3643
- const response = await this.walletRequest(
3644
- state,
3645
- chainId,
3646
- `/users/${user.userId}/agents`
3647
- );
3648
- if (!Array.isArray(response?.agents)) {
3649
- throw this.invalidResponse("agent list");
3650
- }
3651
- const metadata = YIELDSEEKER_ASSET_METADATA[asset];
3652
- let agent = response.agents.find(
3653
- (candidate) => this.isOwneyAgent(candidate) && candidate.chainId === chainId && candidate.type === "vault" && candidate.assetAddress.toLowerCase() === metadata.address.toLowerCase()
3654
- );
3655
- if (!agent && createIfMissing) {
3656
- const created = await this.walletRequest(
3657
- state,
3658
- chainId,
3659
- `/users/${user.userId}/agents`,
3660
- {
3661
- method: "POST",
3662
- body: {
3663
- name: OWNEY_AGENT_NAME,
3664
- emoji: "\u{1F989}",
3665
- chainId,
3666
- assetAddress: metadata.address,
3667
- type: "vault",
3668
- rulePreset: null
3669
- }
3670
- }
3671
- );
3672
- agent = created?.agent;
3673
- }
3674
- if (!agent) return null;
3675
- this.assertAgent(agent);
3676
- const walletResponse = await this.walletRequest(
3677
- state,
3678
- chainId,
3679
- `/users/${user.userId}/agents/${agent.agentId}/wallet`
3680
- );
3681
- if (!walletResponse?.agentWallet || !isAddress2(walletResponse.agentWallet.walletAddress)) {
3682
- throw this.invalidResponse("agent wallet");
3683
- }
3684
- return { user, agent, wallet: walletResponse.agentWallet, asset };
3685
- }
3686
- async loadPortfolio(state, chainId, options) {
3687
- const user = await this.resolveUser(state, chainId);
3688
- const response = await this.walletRequest(
3689
- state,
3690
- chainId,
3691
- `/users/${user.userId}/agents`
3692
- );
3693
- if (!Array.isArray(response?.agents)) {
3694
- throw this.invalidResponse("agent list");
3695
- }
3696
- const contexts = [];
3697
- for (const agent of response.agents) {
3698
- const asset = this.assetForAgent(agent);
3699
- if (!this.isOwneyAgent(agent) || !asset || agent.chainId !== chainId || agent.type !== "vault" || options.asset && options.asset !== asset) {
3700
- continue;
3701
- }
3702
- this.assertAgent(agent);
3703
- const walletResponse = await this.walletRequest(
3704
- state,
3705
- chainId,
3706
- `/users/${user.userId}/agents/${agent.agentId}/wallet`
3707
- );
3708
- if (!walletResponse?.agentWallet || !isAddress2(walletResponse.agentWallet.walletAddress)) {
3709
- throw this.invalidResponse("agent wallet");
3710
- }
3711
- const context = {
3712
- user,
3713
- agent,
3714
- wallet: walletResponse.agentWallet,
3715
- asset
3716
- };
3717
- this.agentContexts.set(this.contextKey(state, chainId, asset), context);
3718
- contexts.push(context);
3719
- }
3720
- return Promise.all(
3721
- contexts.map(
3722
- (context) => this.loadPortfolioContext(state, chainId, context, options)
3723
- )
3724
- );
3725
- }
3726
- async loadPortfolioContext(state, chainId, context, options = {}) {
3727
- const [snapshot, positions, historic, actions] = await Promise.all([
3728
- this.walletRequest(
3729
- state,
3730
- chainId,
3731
- `${this.agentPath(context, "snapshot")}${query({
3732
- shouldOnlyUseRecentValue: true,
3733
- shouldAllowStaleOnError: true
3734
- })}`
3735
- ),
3736
- this.walletRequest(
3737
- state,
3738
- chainId,
3739
- this.agentPath(context, "yield-positions")
3740
- ),
3741
- options.historic ? this.walletRequest(
3742
- state,
3743
- chainId,
3744
- this.agentPath(context, "wallet/historic-position")
3745
- ) : Promise.resolve(void 0),
3746
- options.actions ? this.walletRequest(
3747
- state,
3748
- chainId,
3749
- this.agentPath(context, "actions")
3750
- ) : Promise.resolve(void 0)
3751
- ]);
3752
- if (!snapshot?.agentSnapshot) {
3753
- throw this.invalidResponse("agent snapshot");
3754
- }
3755
- if (!Array.isArray(positions?.yieldPositions)) {
3756
- throw this.invalidResponse("yield positions");
3757
- }
3758
- return {
3759
- ...context,
3760
- snapshot: snapshot.agentSnapshot,
3761
- positions: positions.yieldPositions,
3762
- ...historic?.position ? { historic: historic.position } : {},
3763
- ...actions?.actions ? { actions: actions.actions } : {}
3764
- };
3765
- }
3766
- async deployAfterFunding(state, chainId, context) {
3767
- if (context.wallet.initializedDate != null) return;
3768
- try {
3769
- const deployed = await this.walletRequest(
3770
- state,
3771
- chainId,
3772
- this.agentPath(context, "deploy"),
3773
- { method: "POST", body: {} }
3774
- );
3775
- if (deployed?.agentWallet) {
3776
- context.wallet = deployed.agentWallet;
3777
- }
3778
- } catch (error) {
3779
- console.warn(
3780
- "[owney-sdk] Yieldseeker deposit is funded but not deployable yet:",
3781
- error
3782
- );
3783
- }
3784
- }
3785
- async refreshSnapshotAfterMovement(state, chainId, context, movement) {
3786
- try {
3787
- const response = await this.walletRequest(
3788
- state,
3789
- chainId,
3790
- `${this.agentPath(context, "snapshot")}${query({
3791
- shouldForceRefresh: true
3792
- })}`
3793
- );
3794
- if (!response?.agentSnapshot) {
3795
- throw this.invalidResponse("agent snapshot refresh");
3796
- }
3797
- } catch (error) {
3798
- console.warn(
3799
- `[owney-sdk] Yieldseeker ${movement} snapshot refresh failed:`,
3800
- error
3801
- );
3802
- }
3803
- }
3804
- agentPath(context, suffix) {
3805
- return `/users/${context.user.userId}/agents/${context.agent.agentId}/${suffix}`;
3806
- }
3807
- async walletRequest(state, chainId, path, options = {}) {
3808
- try {
3809
- return await this.providerRequest(state, chainId, path, options);
3810
- } catch (error) {
3811
- throw this.mapApiError(error);
3812
- }
3813
- }
3814
- async providerRequest(state, chainId, path, options = {}) {
3815
- this.assertChain(chainId);
3816
- const request = (signature2) => this.api.request(path, {
3817
- ...options,
3818
- signature: signature2
3819
- });
3820
- let signature = await this.auth.getToken(state, chainId);
3821
- try {
3822
- return await request(signature);
3823
- } catch (error) {
3824
- if (!(error instanceof YieldseekerApiError)) throw error;
3825
- if (error.providerCode === "NO_USER") throw error;
3826
- if (!error.isAuthenticationError) throw error;
3827
- this.auth.clear(state, chainId);
3828
- signature = await this.auth.getToken(state, chainId);
3829
- try {
3830
- return await request(signature);
3831
- } catch (retryError) {
3832
- if (retryError instanceof YieldseekerApiError && retryError.isAuthenticationError) {
3833
- this.forgetUser(state, chainId);
3834
- }
3835
- throw retryError;
3836
- }
3837
- }
3838
- }
3839
- mapApiError(error) {
3840
- if (!(error instanceof YieldseekerApiError)) {
3841
- return new OwneyError(
3842
- "AGENT_API_ERROR",
3843
- "Yieldseeker request failed.",
3844
- { cause: error instanceof Error ? error.message : String(error) },
3845
- this.id
3846
- );
3847
- }
3848
- const code = error.isAuthenticationError ? "AGENT_AUTH_FAILED" : error.providerCode === "REQUEST_TIMEOUT" ? "AGENT_TIMEOUT" : "AGENT_API_ERROR";
3849
- return new OwneyError(
3850
- code,
3851
- `Yieldseeker request failed: ${error.providerCode}.`,
3852
- {
3853
- statusCode: error.status,
3854
- providerCode: error.providerCode,
3855
- ...error.responseFields ? { fields: error.responseFields } : {}
3856
- },
3857
- this.id
3858
- );
3859
- }
3860
- async submitTransaction(state, chainId, transaction) {
3861
- if (this.transactionExecutor) {
3862
- return this.transactionExecutor(state, chainId, transaction);
3863
- }
3864
- this.assertTransaction(transaction, state, chainId);
3865
- const account = getAddress2(state.walletAddress);
3866
- const walletClient = createWalletClient2({
3867
- account,
3868
- chain: base3,
3869
- transport: custom2(state.provider)
3870
- });
3871
- const publicClient = createPublicClient3({
3872
- chain: base3,
3873
- transport: custom2(state.provider)
3874
- });
3875
- await ensureWalletOnChain(
3876
- publicClient,
3877
- walletClient,
3878
- 8453
3879
- );
3880
- const hash = await walletClient.sendTransaction({
3881
- account,
3882
- chain: base3,
3883
- to: getAddress2(transaction.to),
3884
- data: transaction.data,
3885
- value: BigInt(transaction.value)
3886
- });
3887
- const receipt = await publicClient.waitForTransactionReceipt({
3888
- hash,
3889
- confirmations: 1
3890
- });
3891
- if (receipt.status !== "success") {
3892
- throw new OwneyError(
3893
- "AGENT_TRANSACTION_REVERTED",
3894
- `Yieldseeker transaction reverted (${hash}).`,
3895
- { transactionHash: hash },
3896
- this.id
3897
- );
3898
- }
3899
- return hash;
3900
- }
3901
- async waitForReceipt(state, chainId, transactionHash) {
3902
- if (this.unwindReceiptWaiter) {
3903
- await this.unwindReceiptWaiter(state, chainId, transactionHash);
3904
- return;
3905
- }
3906
- const publicClient = createPublicClient3({
3907
- chain: base3,
3908
- transport: custom2(state.provider)
3909
- });
3910
- const receipt = await publicClient.waitForTransactionReceipt({
3911
- hash: transactionHash,
3912
- confirmations: 1
3913
- });
3914
- if (receipt.status !== "success") {
3915
- throw new OwneyError(
3916
- "AGENT_TRANSACTION_REVERTED",
3917
- `Yieldseeker transaction reverted (${transactionHash}).`,
3918
- { transactionHash },
3919
- this.id
3920
- );
3921
- }
3922
- }
3923
- assertTransaction(transaction, state, chainId) {
3924
- 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)) {
3925
- throw this.invalidResponse("transaction");
3926
- }
3927
- }
3928
- assertAgent(agent) {
3929
- if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !isAddress2(agent.assetAddress) || agent.chainId !== 8453) {
3930
- throw this.invalidResponse("agent");
3931
- }
3932
- }
3933
- isOwneyAgent(agent) {
3934
- return typeof agent.name === "string" && agent.name.trim().toLowerCase() === OWNEY_AGENT_NAME;
3935
- }
3936
- assetForAgent(agent) {
3937
- for (const asset of ["USDC", "WETH"]) {
3938
- if (agent.assetAddress.toLowerCase() === YIELDSEEKER_ASSET_METADATA[asset].address.toLowerCase()) {
3939
- return asset;
3940
- }
3941
- }
3942
- return null;
3943
- }
3944
- isTransactionHash(value) {
3945
- return typeof value === "string" && /^0x[a-fA-F0-9]{64}$/.test(value);
3946
- }
3947
- assertChain(chainId) {
3948
- if (chainId !== 8453) {
3949
- throw new OwneyError(
3950
- "CHAIN_UNSUPPORTED",
3951
- `Yieldseeker does not support chain ${chainId}.`,
3952
- { chainId, supportedChainIds: [8453] },
3953
- this.id
3954
- );
3955
- }
3956
- }
3957
- assertOptionalChain(chainId) {
3958
- if (chainId !== void 0) this.assertChain(chainId);
3959
- }
3960
- assertAsset(asset) {
3961
- if (asset !== "USDC" && asset !== "WETH") {
3962
- throw new OwneyError(
3963
- "ASSET_UNSUPPORTED",
3964
- `Yieldseeker does not support asset ${asset} in the Owney rollout.`,
3965
- {
3966
- asset,
3967
- supportedAssets: ["USDC", "WETH"],
3968
- providerAlsoAdvertises: ["cbBTC"]
3969
- },
3970
- this.id
3971
- );
3972
- }
3973
- }
3974
- invalidResponse(operation, details = {}) {
3975
- return new OwneyError(
3976
- "AGENT_INVALID_RESPONSE",
3977
- `Yieldseeker returned an invalid ${operation} response.`,
3978
- details,
3979
- this.id
3980
- );
3981
- }
3982
- };
3983
-
3984
- // src/lib/routing-api.ts
3985
- var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
3986
- async function fetchOrgAgentConfig(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
3987
- const url = `${baseUrl}/api/v1/agent/org-config`;
3988
- try {
3989
- const res = await fetch(url, {
3990
- method: "GET",
3991
- headers: {
3992
- "Content-Type": "application/json",
3993
- "x-owney-api-key": `${apiKey}`
3994
- }
3995
- });
3996
- if (!res.ok) {
3997
- if (res.status !== 404) {
3998
- console.warn(
3999
- `[owney-sdk] Could not read org agent config (${res.status}); leaving user profiles unchanged.`
4000
- );
4001
- }
4002
- return null;
4003
- }
4004
- const json = await res.json();
4005
- const policy = json.success ? json.data ?? null : null;
4006
- debugLog(
4007
- "owney-sdk",
4008
- policy ? "org agent config: loaded" : "org agent config: none set by this partner \u2014 user profiles will be left as they are",
4009
- policy ?? void 0
4010
- );
4011
- return policy;
4012
- } catch (error) {
4013
- console.warn(
4014
- "[owney-sdk] Could not read org agent config (non-fatal):",
4015
- error instanceof Error ? error.message : String(error)
4016
- );
4017
- return null;
4018
- }
4019
- }
4020
- async function fetchAgentKeys(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
4021
- const url = `${baseUrl}/api/v1/agent/keys`;
4022
- const res = await fetch(url, {
4023
- method: "GET",
4024
- headers: {
4025
- "Content-Type": "application/json",
4026
- "x-owney-api-key": `${apiKey}`
4027
- }
4028
- });
4029
- if (!res.ok) {
4030
- const text = await res.text().catch(() => "");
4031
- throw new OwneyError(
4032
- "API_ROUTING_ERROR",
4033
- `Routing API error ${res.status}: ${text}`,
4034
- { statusCode: res.status, responseBody: text }
4035
- );
4036
- }
4037
- const json = await res.json();
4038
- if (!json.success) {
4039
- throw new OwneyError(
4040
- "API_ROUTING_FAILED",
4041
- `Routing API request failed: ${json.message}`,
4042
- { message: json.message }
4043
- );
4044
- }
4045
- return json.data;
4046
- }
4047
-
4048
- // src/lib/health-report.ts
4049
- var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
4050
- async function reportAgentFailure(apiKey, agentType, errorCode, baseUrl = ROUTING_API_BASE_URL3) {
4051
- try {
4052
- await fetch(`${baseUrl}/api/v1/agent/health-report`, {
4053
- method: "POST",
4054
- headers: {
4055
- "Content-Type": "application/json",
4056
- "x-owney-api-key": apiKey
4057
- },
4058
- body: JSON.stringify({
4059
- agent_type: agentType,
4060
- error_code: errorCode,
4061
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4062
- })
4063
- });
4064
- } catch (err) {
4065
- console.warn(
4066
- `[owney-sdk] health-report failed for agent "${agentType}":`,
4067
- err instanceof Error ? err.message : err
4068
- );
4069
- }
4070
- }
4071
- async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
4072
- try {
4073
- return await fn();
4074
- } catch (err) {
4075
- const errorCode = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
4076
- void reportAgentFailure(apiKey, agentType, errorCode, baseUrl);
4077
- throw err;
4078
- }
4079
- }
4080
-
4081
- // src/lib/helpers/withdraw-helper.ts
4082
- import { parseUnits } from "viem";
4083
- function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
4084
- const target = asset.toUpperCase();
4085
- return agents.map((agent) => {
4086
- const agentBalance = aggregated[agent.id];
4087
- const tokenBalance = agentBalance?.tokens.find(
4088
- (t) => t.chainId === chainId && t.asset.toUpperCase() === target
4089
- );
4090
- let balance = tokenBalance ? parseUnits(tokenBalance.amount, decimals) : 0n;
4091
- if (agent.balanceComposition === "tokens-plus-positions") {
4092
- const chainNameById = {
4093
- 1: "ETHEREUM",
4094
- 8453: "BASE",
4095
- 42161: "ARBITRUM"
4096
- };
4097
- const targetChain = chainNameById[chainId];
4098
- for (const position2 of agentBalance?.positions ?? []) {
4099
- const positionChain = position2.chain.trim().toUpperCase();
4100
- const matchesChain = positionChain === String(chainId) || targetChain !== void 0 && positionChain === targetChain;
4101
- if (!matchesChain || position2.asset.toUpperCase() !== target) continue;
4102
- if (position2.amountRaw !== void 0) {
4103
- try {
4104
- balance += BigInt(position2.amountRaw);
4105
- continue;
4106
- } catch {
4107
- }
4108
- }
4109
- balance += parseUnits(position2.amount, decimals);
4110
- }
4111
- }
4112
- return { agent, balance };
4113
- });
4114
- }
4115
- function planProportionalShares(balances, requested, totalAvailable) {
4116
- const plans = balances.map(({ agent, balance }) => ({
4117
- agent,
4118
- balance,
4119
- planned: totalAvailable > 0n ? balance * requested / totalAvailable : 0n
4120
- }));
4121
- const assigned = plans.reduce((s, p) => s + p.planned, 0n);
4122
- let remainder = requested - assigned;
4123
- const byHeadroom = [...plans].sort((a, b) => {
4124
- const diff = b.balance - b.planned - (a.balance - a.planned);
4125
- return diff > 0n ? 1 : diff < 0n ? -1 : 0;
4126
- });
4127
- for (const p of byHeadroom) {
4128
- if (remainder === 0n) break;
4129
- const headroom = p.balance - p.planned;
4130
- if (headroom <= 0n) continue;
4131
- const take = headroom < remainder ? headroom : remainder;
4132
- p.planned += take;
4133
- remainder -= take;
4134
- }
4135
- return plans;
4136
- }
4137
- function planDisabledDrain(disabled, requested) {
4138
- const sorted = [...disabled].filter((d) => d.balance > 0n).sort(
4139
- (a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0
4140
- );
4141
- const plans = [];
4142
- let remaining = requested;
4143
- for (const { agent, balance } of sorted) {
4144
- if (remaining === 0n) {
4145
- plans.push({ agent, balance, planned: 0n });
4146
- continue;
4147
- }
4148
- const take = balance < remaining ? balance : remaining;
4149
- plans.push({ agent, balance, planned: take });
4150
- remaining -= take;
4151
- }
4152
- return { plans, remaining };
4153
- }
4154
- function redistributeShare(plans, fromIndex, amount, candidatePool) {
4155
- const pool = candidatePool ?? plans.slice(fromIndex + 1);
4156
- const candidates = pool.filter((c) => c.balance - c.planned > 0n);
4157
- const totalHeadroom = candidates.reduce(
4158
- (s, c) => s + (c.balance - c.planned),
4159
- 0n
4160
- );
4161
- if (totalHeadroom === 0n) return;
4162
- let distributed = 0n;
4163
- for (const c of candidates) {
4164
- const headroom = c.balance - c.planned;
4165
- const proportional = headroom * amount / totalHeadroom;
4166
- const give = proportional > headroom ? headroom : proportional;
4167
- c.planned += give;
4168
- distributed += give;
4169
- }
4170
- let leftover = amount - distributed;
4171
- for (const c of candidates) {
4172
- if (leftover === 0n) break;
4173
- const headroom = c.balance - c.planned;
4174
- if (headroom <= 0n) continue;
4175
- const take = headroom < leftover ? headroom : leftover;
4176
- c.planned += take;
4177
- leftover -= take;
4178
- }
2382
+ globalThis.crypto.getRandomValues(bytes);
2383
+ return BigInt(bytesToHex(bytes));
4179
2384
  }
4180
- function sumWithdrawnAmount(results) {
4181
- return Object.values(results).reduce((sum, r) => sum + BigInt(r.amount), 0n);
2385
+ async function readPermit2Allowance(publicClient, token, owner) {
2386
+ return publicClient.readContract({
2387
+ address: token,
2388
+ abi: ERC20_ALLOWANCE_ABI,
2389
+ functionName: "allowance",
2390
+ args: [owner, PERMIT2_ADDRESS]
2391
+ });
2392
+ }
2393
+ async function readErc20Balance(publicClient, token, owner) {
2394
+ return publicClient.readContract({
2395
+ address: token,
2396
+ abi: ERC20_ALLOWANCE_ABI,
2397
+ functionName: "balanceOf",
2398
+ args: [owner]
2399
+ });
4182
2400
  }
4183
2401
 
4184
- // src/lib/helpers/account-apy-helper.ts
4185
- function balanceForApyScope(balance, chainId, tokenSymbol) {
4186
- if (!tokenSymbol) {
4187
- const total = Number(balance.totalBalance);
4188
- return Number.isFinite(total) && total > 0 ? total : 0;
2402
+ // src/lib/chain-guard.ts
2403
+ var CHAIN_NAMES = {
2404
+ 1: "Ethereum",
2405
+ 8453: "Base",
2406
+ 42161: "Arbitrum"
2407
+ };
2408
+ function chainName(chainId) {
2409
+ return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
2410
+ }
2411
+ async function ensureWalletOnChain(pub, wallet, expected) {
2412
+ const actual = await pub.getChainId();
2413
+ if (actual === expected) return;
2414
+ try {
2415
+ await wallet.switchChain({ id: expected });
2416
+ } catch (error) {
2417
+ throw new OwneyError(
2418
+ "CHAIN_MISMATCH",
2419
+ `Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
2420
+ {
2421
+ expectedChainId: expected,
2422
+ actualChainId: actual,
2423
+ cause: error instanceof Error ? error.message : String(error)
2424
+ }
2425
+ );
4189
2426
  }
4190
- const normalizedToken = tokenSymbol.toUpperCase();
4191
- const snapshots = balance.assetBalances?.filter(
4192
- (token) => Number(token.chainId) === chainId && String(token.asset).toUpperCase() === normalizedToken
4193
- );
4194
- if (snapshots?.length) {
4195
- const amount = snapshots.reduce((sum, token) => sum + Number(token.amount), 0);
4196
- if (Number.isFinite(amount)) return Math.max(0, amount);
2427
+ const after = await pub.getChainId();
2428
+ if (after !== expected) {
2429
+ throw new OwneyError(
2430
+ "CHAIN_MISMATCH",
2431
+ `Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
2432
+ { expectedChainId: expected, actualChainId: after }
2433
+ );
4197
2434
  }
4198
- return balance.tokens.reduce((total, token) => {
4199
- if (Number(token.chainId) !== chainId || String(token.asset).toUpperCase() !== normalizedToken) {
4200
- return total;
4201
- }
4202
- const amount = Number(token.amount);
4203
- return Number.isFinite(amount) && amount > 0 ? total + amount : total;
4204
- }, 0);
4205
2435
  }
4206
- function aggregateApyHistory(agentApys) {
4207
- const byDate = /* @__PURE__ */ new Map();
4208
- for (const accountApy of Object.values(agentApys)) {
4209
- const seen = /* @__PURE__ */ new Set();
4210
- for (const point of accountApy.history ?? []) {
4211
- if (!point.date || seen.has(point.date) || !Number.isFinite(point.apy)) continue;
4212
- seen.add(point.date);
4213
- const points = byDate.get(point.date) ?? [];
4214
- points.push(point);
4215
- byDate.set(point.date, points);
4216
- }
4217
- }
4218
- return [...byDate.entries()].sort(([left], [right]) => left.localeCompare(right)).flatMap(([date, points]) => {
4219
- if (points.length === 1 && !points[0].historicalBalance) {
4220
- return [{ date, apy: points[0].apy }];
2436
+
2437
+ // src/lib/sponsored-deposit.ts
2438
+ var AUTH_WINDOW_SECONDS = 15 * 60;
2439
+ function makeSponsoredDepositCallback(deps) {
2440
+ const post = deps.httpPost ?? postSponsorTransferAuth;
2441
+ return async (smartWallet, chainId, amount) => {
2442
+ const cid = chainId;
2443
+ const token = deps.tokenAddressByChain[cid];
2444
+ if (!token) {
2445
+ throw new OwneyError(
2446
+ "CHAIN_UNSUPPORTED",
2447
+ `No sponsored token configured for chain ${chainId}`
2448
+ );
4221
2449
  }
4222
- const unit = points[0].historicalBalance?.unit;
4223
- if (!unit || points.some(
4224
- ({ historicalBalance: balance }) => !balance || balance.unit !== unit || !Number.isFinite(balance.amount) || balance.amount < 0
4225
- )) return [];
4226
- const total = points.reduce((sum, p) => sum + p.historicalBalance.amount, 0);
4227
- if (total <= 0 || !Number.isFinite(total)) return [];
4228
- const apy = points.reduce((sum, p) => sum + p.apy * (p.historicalBalance.amount / total), 0);
4229
- return Number.isFinite(apy) ? [{ date, apy }] : [];
4230
- });
4231
- }
4232
- function aggregateApyByChainAndAsset(agentApys, agentBalances) {
4233
- const sums = {};
4234
- const weights = {};
4235
- for (const id of Object.keys(agentApys)) {
4236
- const cells = agentApys[id].apyByChainAndAsset;
4237
- const balance = agentBalances[id] ?? 0;
4238
- if (!cells || balance <= 0) continue;
4239
- for (const [chainKey, perAsset] of Object.entries(cells)) {
4240
- if (!perAsset) continue;
4241
- const chainId = Number(chainKey);
4242
- for (const [asset, apyValue] of Object.entries(perAsset)) {
4243
- const apy = Number(apyValue ?? 0);
4244
- if (apy === 0) continue;
4245
- sums[chainId] ??= {};
4246
- weights[chainId] ??= {};
4247
- sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
4248
- weights[chainId][asset] = (weights[chainId][asset] ?? 0) + balance;
2450
+ const pub = deps.getPublicClient(cid);
2451
+ const wallet = deps.getWalletClient(cid);
2452
+ await ensureWalletOnChain(pub, wallet, cid);
2453
+ try {
2454
+ const balance = await readErc20Balance(pub, token, deps.ownerAddress);
2455
+ if (balance < BigInt(amount)) {
2456
+ throw new OwneyError(
2457
+ "DEPOSIT_INSUFFICIENT_BALANCE",
2458
+ "Insufficient balance for this deposit.",
2459
+ { token, chainId: cid, balance: balance.toString(), amount }
2460
+ );
4249
2461
  }
2462
+ } catch (err) {
2463
+ if (err instanceof OwneyError) throw err;
2464
+ console.warn(
2465
+ "[owney-sdk] Deposit balance pre-check failed (non-fatal):",
2466
+ err instanceof Error ? err.message : String(err)
2467
+ );
4250
2468
  }
4251
- }
4252
- const out = {};
4253
- for (const chainKey of Object.keys(sums)) {
4254
- const chainId = Number(chainKey);
4255
- const perAssetOut = {};
4256
- for (const asset of Object.keys(sums[chainId])) {
4257
- const w = weights[chainId][asset];
4258
- if (w > 0) perAssetOut[asset] = sums[chainId][asset] / w;
4259
- }
4260
- if (Object.keys(perAssetOut).length > 0) {
4261
- out[chainId] = perAssetOut;
4262
- }
4263
- }
4264
- return out;
2469
+ const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
2470
+ const validAfter = 0n;
2471
+ const validBefore = BigInt(
2472
+ Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
2473
+ );
2474
+ const nonce = randomAuthNonce();
2475
+ const typedData = buildTransferWithAuthorizationTypedData({
2476
+ token,
2477
+ chainId: cid,
2478
+ tokenName,
2479
+ tokenVersion,
2480
+ message: {
2481
+ from: deps.ownerAddress,
2482
+ to: smartWallet,
2483
+ value: BigInt(amount),
2484
+ validAfter,
2485
+ validBefore,
2486
+ nonce
2487
+ }
2488
+ });
2489
+ const authSignature = await wallet.signTypedData({
2490
+ account: deps.ownerAddress,
2491
+ ...typedData
2492
+ });
2493
+ deps.onApproved?.();
2494
+ const result = await post({
2495
+ baseUrl: deps.baseUrl,
2496
+ apiKey: deps.apiKey,
2497
+ body: {
2498
+ chainId: cid,
2499
+ token,
2500
+ from: deps.ownerAddress,
2501
+ to: smartWallet,
2502
+ value: amount,
2503
+ validAfter: validAfter.toString(),
2504
+ validBefore: validBefore.toString(),
2505
+ nonce,
2506
+ authSignature,
2507
+ tokenName,
2508
+ tokenVersion
2509
+ }
2510
+ });
2511
+ return result.txHash;
2512
+ };
4265
2513
  }
4266
2514
 
4267
- // src/client.ts
4268
- import {
4269
- createPublicClient as createPublicClient4,
4270
- createWalletClient as createWalletClient3,
4271
- custom as custom3
4272
- } from "viem";
4273
- import { base as base4, arbitrum as arbitrum2, mainnet as mainnet2 } from "viem/chains";
4274
-
4275
2515
  // src/lib/sponsored-weth-deposit.ts
4276
2516
  var PERMIT_WINDOW_SECONDS = 15 * 60;
4277
2517
  function makeSponsoredWethCallback(deps) {
4278
2518
  const get = deps.httpGet ?? getSponsorRelayerAddress;
4279
2519
  const post = deps.httpPost ?? postSponsorPermit2Transfer;
4280
- return makeVerificationAwareDepositCallback(
4281
- async (smartWallet, chainId, amount, verification) => {
4282
- const cid = chainId;
4283
- const token = deps.tokenAddressByChain[cid];
4284
- if (!token) {
4285
- throw new OwneyError(
4286
- "CHAIN_UNSUPPORTED",
4287
- `No sponsored WETH configured for chain ${chainId}`
4288
- );
4289
- }
4290
- const amountWei = BigInt(amount);
4291
- const pub = deps.getPublicClient(cid);
4292
- const wallet = deps.getWalletClient(cid);
4293
- await ensureWalletOnChain(pub, wallet, cid);
4294
- try {
4295
- const balance = await readErc20Balance(pub, token, deps.ownerAddress);
4296
- if (balance < amountWei) {
4297
- throw new OwneyError(
4298
- "DEPOSIT_INSUFFICIENT_BALANCE",
4299
- "Insufficient WETH balance for this deposit.",
4300
- { token, chainId: cid, balance: balance.toString(), amount }
4301
- );
4302
- }
4303
- } catch (err) {
4304
- if (err instanceof OwneyError) throw err;
4305
- console.warn(
4306
- "[owney-sdk] WETH balance pre-check failed (non-fatal):",
4307
- err instanceof Error ? err.message : String(err)
4308
- );
4309
- }
4310
- const allowance = await readPermit2Allowance(
4311
- pub,
4312
- token,
4313
- deps.ownerAddress
2520
+ return async (smartWallet, chainId, amount) => {
2521
+ const cid = chainId;
2522
+ const token = deps.tokenAddressByChain[cid];
2523
+ if (!token) {
2524
+ throw new OwneyError(
2525
+ "CHAIN_UNSUPPORTED",
2526
+ `No sponsored WETH configured for chain ${chainId}`
4314
2527
  );
4315
- if (allowance < amountWei) {
2528
+ }
2529
+ const amountWei = BigInt(amount);
2530
+ const pub = deps.getPublicClient(cid);
2531
+ const wallet = deps.getWalletClient(cid);
2532
+ await ensureWalletOnChain(pub, wallet, cid);
2533
+ try {
2534
+ const balance = await readErc20Balance(pub, token, deps.ownerAddress);
2535
+ if (balance < amountWei) {
4316
2536
  throw new OwneyError(
4317
- "PERMIT2_APPROVAL_REQUIRED",
4318
- "WETH gasless deposits need a one-time Permit2 approval; call approvePermit2() first",
4319
- { token, chainId: cid, allowance: allowance.toString(), amount }
2537
+ "DEPOSIT_INSUFFICIENT_BALANCE",
2538
+ "Insufficient WETH balance for this deposit.",
2539
+ { token, chainId: cid, balance: balance.toString(), amount }
4320
2540
  );
4321
2541
  }
4322
- const relayer = await get({
4323
- baseUrl: deps.baseUrl,
4324
- apiKey: deps.apiKey,
4325
- chainId: cid
4326
- });
4327
- const nonce = randomPermit2Nonce();
4328
- const deadline = BigInt(
4329
- Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
2542
+ } catch (err) {
2543
+ if (err instanceof OwneyError) throw err;
2544
+ console.warn(
2545
+ "[owney-sdk] WETH balance pre-check failed (non-fatal):",
2546
+ err instanceof Error ? err.message : String(err)
4330
2547
  );
4331
- const typedData = buildPermitTransferFromTypedData({
4332
- chainId: cid,
4333
- message: {
4334
- permitted: { token, amount: amountWei },
4335
- spender: relayer,
4336
- nonce,
4337
- deadline
4338
- }
4339
- });
4340
- const signature = await wallet.signTypedData({
4341
- account: deps.ownerAddress,
4342
- ...typedData
4343
- });
4344
- deps.onApproved?.();
4345
- const result = await post({
4346
- baseUrl: deps.baseUrl,
4347
- apiKey: deps.apiKey,
4348
- ...verification?.agentId === "yieldseeker" ? { yieldseekerSignature: verification.signature } : {},
4349
- body: {
4350
- chainId: cid,
4351
- token,
4352
- from: deps.ownerAddress,
4353
- to: smartWallet,
4354
- amount,
4355
- nonce: nonce.toString(),
4356
- deadline: deadline.toString(),
4357
- signature,
4358
- ...verification?.agentId === "yieldseeker" ? {
4359
- yieldseekerUserId: verification.userId,
4360
- yieldseekerAgentId: verification.yieldseekerAgentId
4361
- } : {}
4362
- }
4363
- });
4364
- return result.txHash;
4365
2548
  }
4366
- );
2549
+ const allowance = await readPermit2Allowance(pub, token, deps.ownerAddress);
2550
+ if (allowance < amountWei) {
2551
+ throw new OwneyError(
2552
+ "PERMIT2_APPROVAL_REQUIRED",
2553
+ "WETH gasless deposits need a one-time Permit2 approval; call approvePermit2() first",
2554
+ { token, chainId: cid, allowance: allowance.toString(), amount }
2555
+ );
2556
+ }
2557
+ const relayer = await get({
2558
+ baseUrl: deps.baseUrl,
2559
+ apiKey: deps.apiKey,
2560
+ chainId: cid
2561
+ });
2562
+ const nonce = randomPermit2Nonce();
2563
+ const deadline = BigInt(
2564
+ Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
2565
+ );
2566
+ const typedData = buildPermitTransferFromTypedData({
2567
+ chainId: cid,
2568
+ message: {
2569
+ permitted: { token, amount: amountWei },
2570
+ spender: relayer,
2571
+ nonce,
2572
+ deadline
2573
+ }
2574
+ });
2575
+ const signature = await wallet.signTypedData({
2576
+ account: deps.ownerAddress,
2577
+ ...typedData
2578
+ });
2579
+ deps.onApproved?.();
2580
+ const result = await post({
2581
+ baseUrl: deps.baseUrl,
2582
+ apiKey: deps.apiKey,
2583
+ body: {
2584
+ chainId: cid,
2585
+ token,
2586
+ from: deps.ownerAddress,
2587
+ to: smartWallet,
2588
+ amount,
2589
+ nonce: nonce.toString(),
2590
+ deadline: deadline.toString(),
2591
+ signature
2592
+ }
2593
+ });
2594
+ return result.txHash;
2595
+ };
4367
2596
  }
4368
2597
 
4369
2598
  // src/lib/sponsored-calls-deposit.ts
4370
- import { encodeFunctionData as encodeFunctionData2, erc20Abi as erc20Abi2, toHex } from "viem";
2599
+ import { encodeFunctionData, erc20Abi, toHex } from "viem";
4371
2600
  var DEFAULT_POLL_INTERVAL_MS = 1500;
4372
2601
  var DEFAULT_MAX_POLLS = 30;
4373
2602
  async function paymasterSupported(provider, owner, chainId) {
@@ -4393,7 +2622,7 @@ function makeSponsoredCallsCallback(deps) {
4393
2622
  }
4394
2623
  return new URL(configured, origin).toString();
4395
2624
  };
4396
- return makeVerificationAwareDepositCallback(async (smartWallet, chainId, amount, verification) => {
2625
+ return async (smartWallet, chainId, amount) => {
4397
2626
  const cid = chainId;
4398
2627
  const token = deps.tokenAddressByChain[cid];
4399
2628
  if (!token) {
@@ -4409,37 +2638,11 @@ function makeSponsoredCallsCallback(deps) {
4409
2638
  { chainId }
4410
2639
  );
4411
2640
  }
4412
- const data = encodeFunctionData2({
4413
- abi: erc20Abi2,
2641
+ const data = encodeFunctionData({
2642
+ abi: erc20Abi,
4414
2643
  functionName: "transfer",
4415
2644
  args: [smartWallet, BigInt(amount)]
4416
2645
  });
4417
- let paymasterUrl = absolutePaymasterUrl();
4418
- if (verification?.agentId === "yieldseeker") {
4419
- if (chainId !== 8453) {
4420
- throw new OwneyError(
4421
- "CHAIN_UNSUPPORTED",
4422
- `Yieldseeker Base Account sponsorship is not available on chain ${chainId}.`
4423
- );
4424
- }
4425
- const { intent } = await postPaymasterIntent({
4426
- baseUrl: deps.routingApiBaseUrl,
4427
- apiKey: deps.apiKey,
4428
- yieldseekerSignature: verification.signature,
4429
- body: {
4430
- chainId,
4431
- token,
4432
- from: deps.ownerAddress,
4433
- to: smartWallet,
4434
- amount,
4435
- yieldseekerUserId: verification.userId,
4436
- yieldseekerAgentId: verification.yieldseekerAgentId
4437
- }
4438
- });
4439
- const url = new URL(paymasterUrl);
4440
- url.searchParams.set("owneyIntent", intent);
4441
- paymasterUrl = url.toString();
4442
- }
4443
2646
  const sendResult = await deps.provider.request({
4444
2647
  method: "wallet_sendCalls",
4445
2648
  params: [
@@ -4450,7 +2653,7 @@ function makeSponsoredCallsCallback(deps) {
4450
2653
  atomicRequired: false,
4451
2654
  calls: [{ to: token, value: "0x0", data }],
4452
2655
  capabilities: {
4453
- paymasterService: { url: paymasterUrl }
2656
+ paymasterService: { url: absolutePaymasterUrl() }
4454
2657
  }
4455
2658
  }
4456
2659
  ]
@@ -4480,7 +2683,7 @@ function makeSponsoredCallsCallback(deps) {
4480
2683
  `No receipt for calls ${callsId} after ${maxPolls} polls; the deposit may still settle.`,
4481
2684
  { chainId, callsId }
4482
2685
  );
4483
- });
2686
+ };
4484
2687
  }
4485
2688
 
4486
2689
  // src/client.ts
@@ -4510,7 +2713,7 @@ var SPONSORED_USDC_BY_CHAIN = {
4510
2713
  1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
4511
2714
  };
4512
2715
  var VIEM_CHAIN2 = {
4513
- 8453: base4,
2716
+ 8453: base2,
4514
2717
  42161: arbitrum2,
4515
2718
  1: mainnet2
4516
2719
  };
@@ -4522,6 +2725,7 @@ var SPONSORED_WETH_BY_CHAIN = {
4522
2725
  function shouldFallbackToUserPaid(error, asset, appCallback) {
4523
2726
  return (asset === "WETH" || asset === "USDC") && appCallback === void 0 && error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED" && error.details?.safeToFallback === true;
4524
2727
  }
2728
+ var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai"];
4525
2729
  var OwneySDK = class {
4526
2730
  agents = /* @__PURE__ */ new Map();
4527
2731
  activeAgents = /* @__PURE__ */ new Set();
@@ -4540,8 +2744,6 @@ var OwneySDK = class {
4540
2744
  orgAgentConfig;
4541
2745
  orgAgentConfigPromise = null;
4542
2746
  zyfaiRpcUrls;
4543
- yieldseekerApiBaseUrl;
4544
- yieldseekerSiweOrigin;
4545
2747
  routingApiBaseUrl;
4546
2748
  referralSource;
4547
2749
  cachedSponsoredCallback = null;
@@ -4564,8 +2766,6 @@ var OwneySDK = class {
4564
2766
  this.apiKey = config.apiKey;
4565
2767
  if (config.debug) setOwneyDebug(true);
4566
2768
  this.zyfaiRpcUrls = config.zyfaiRpcUrls;
4567
- this.yieldseekerApiBaseUrl = config.yieldseekerApiBaseUrl;
4568
- this.yieldseekerSiweOrigin = config.yieldseekerSiweOrigin;
4569
2769
  this.routingApiBaseUrl = config.routingApiBaseUrl;
4570
2770
  this.paymasterServiceUrl = config.paymasterServiceUrl;
4571
2771
  this.referralSource = config.referralSource;
@@ -4672,14 +2872,14 @@ var OwneySDK = class {
4672
2872
  // Casts work around viem's chain-narrowed Client vs the generic
4673
2873
  // PublicClient/WalletClient param types — structurally identical at
4674
2874
  // runtime, but the two share a name TS treats as unrelated.
4675
- getPublicClient: (cid) => createPublicClient4({
2875
+ getPublicClient: (cid) => createPublicClient2({
4676
2876
  chain: VIEM_CHAIN2[cid],
4677
- transport: custom3(provider)
2877
+ transport: custom(provider)
4678
2878
  }),
4679
- getWalletClient: (cid) => createWalletClient3({
2879
+ getWalletClient: (cid) => createWalletClient({
4680
2880
  account: owner,
4681
2881
  chain: VIEM_CHAIN2[cid],
4682
- transport: custom3(provider)
2882
+ transport: custom(provider)
4683
2883
  })
4684
2884
  });
4685
2885
  if (!onApproved) this.cachedSponsoredCallback = callback;
@@ -4696,8 +2896,6 @@ var OwneySDK = class {
4696
2896
  if (!onApproved && cached) return cached;
4697
2897
  const provider = this.requireConnectedProvider();
4698
2898
  const callback = makeSponsoredCallsCallback({
4699
- apiKey: this.apiKey,
4700
- routingApiBaseUrl: this.routingApiBaseUrl,
4701
2899
  provider,
4702
2900
  ownerAddress: this.state.walletAddress,
4703
2901
  paymasterServiceUrl: this.paymasterServiceUrl,
@@ -4727,14 +2925,14 @@ var OwneySDK = class {
4727
2925
  // Casts work around viem's chain-narrowed Client vs the generic
4728
2926
  // PublicClient/WalletClient param types — structurally identical at
4729
2927
  // runtime, but the two share a name TS treats as unrelated.
4730
- getPublicClient: (cid) => createPublicClient4({
2928
+ getPublicClient: (cid) => createPublicClient2({
4731
2929
  chain: VIEM_CHAIN2[cid],
4732
- transport: custom3(provider)
2930
+ transport: custom(provider)
4733
2931
  }),
4734
- getWalletClient: (cid) => createWalletClient3({
2932
+ getWalletClient: (cid) => createWalletClient({
4735
2933
  account: owner,
4736
2934
  chain: VIEM_CHAIN2[cid],
4737
- transport: custom3(provider)
2935
+ transport: custom(provider)
4738
2936
  })
4739
2937
  });
4740
2938
  if (!onApproved) this.cachedWethSponsoredCallback = callback;
@@ -4765,10 +2963,12 @@ var OwneySDK = class {
4765
2963
  this.orgAgentConfigPromise = fetchOrgAgentConfig(
4766
2964
  this.apiKey,
4767
2965
  this.routingApiBaseUrl
4768
- ).then((config) => {
4769
- this.orgAgentConfig = config;
4770
- return config;
4771
- });
2966
+ ).then(
2967
+ (config) => {
2968
+ this.orgAgentConfig = config;
2969
+ return config;
2970
+ }
2971
+ );
4772
2972
  }
4773
2973
  return this.orgAgentConfigPromise;
4774
2974
  }
@@ -4808,15 +3008,8 @@ var OwneySDK = class {
4808
3008
  this.routingApiBaseUrl
4809
3009
  );
4810
3010
  this.disabledAgents.clear();
4811
- for (const {
4812
- key: key2,
4813
- agent_type,
4814
- is_enabled,
4815
- is_configured
4816
- } of agentKeys) {
4817
- const configured = is_configured ?? Boolean(key2);
4818
- if (!configured) continue;
4819
- const agent = this.createAgent(agent_type, key2);
3011
+ for (const { key: key2, agent_type, is_enabled } of agentKeys) {
3012
+ const agent = await this.createAgent(agent_type, key2);
4820
3013
  if (!agent) continue;
4821
3014
  this.agents.set(agent_type, agent);
4822
3015
  if (is_enabled === false) {
@@ -4837,15 +3030,16 @@ var OwneySDK = class {
4837
3030
  this.initializingAgentsPromise = null;
4838
3031
  }
4839
3032
  }
4840
- createAgent(agentId, key2) {
3033
+ async createAgent(agentId, key2) {
4841
3034
  if (agentId === "zyfai") {
4842
- if (!key2) return null;
4843
3035
  return new ZyfaiAgent(key2, this.zyfaiRpcUrls, this.referralSource);
4844
3036
  }
4845
- if (agentId === "yieldseeker") {
4846
- return new YieldseekerAgent(this.apiKey, {
4847
- auth: { origin: this.yieldseekerSiweOrigin },
4848
- baseUrl: this.yieldseekerApiBaseUrl ?? getYieldseekerProxyBaseUrl(this.routingApiBaseUrl)
3037
+ if (agentId === "surfliquid") {
3038
+ if (!key2) return null;
3039
+ const { SurfLiquidAgent } = await import("./surfliquid.agent-XDJ672GM.js");
3040
+ return new SurfLiquidAgent({
3041
+ apiKey: this.apiKey,
3042
+ routingApiBaseUrl: this.routingApiBaseUrl
4849
3043
  });
4850
3044
  }
4851
3045
  return null;
@@ -4892,7 +3086,7 @@ var OwneySDK = class {
4892
3086
  * If provided, ALL specified agents must support the chainId or the call
4893
3087
  * throws before activating any agent.
4894
3088
  */
4895
- async activateAgent(chainId, agentId, asset) {
3089
+ async activateAgent(chainId, agentId) {
4896
3090
  const state = this.requireState();
4897
3091
  await this.ensureAgentsInitialized();
4898
3092
  if (agentId !== void 0) {
@@ -4928,7 +3122,7 @@ var OwneySDK = class {
4928
3122
  this.activeAgents.add(id);
4929
3123
  }
4930
3124
  state.chainId = chainId;
4931
- await this.activateAgentsInTurn(agents, state, chainId, asset);
3125
+ await this.activateAgentsInTurn(agents, state, chainId);
4932
3126
  return;
4933
3127
  }
4934
3128
  const compatible = [...this.agents.values()].filter(
@@ -4949,7 +3143,7 @@ var OwneySDK = class {
4949
3143
  const enabledCompatible = compatible.filter(
4950
3144
  (agent) => !this.isAgentDisabled(agent.id)
4951
3145
  );
4952
- await this.activateAgentsInTurn(enabledCompatible, state, chainId, asset);
3146
+ await this.activateAgentsInTurn(enabledCompatible, state, chainId);
4953
3147
  }
4954
3148
  /**
4955
3149
  * Activate agents ONE AT A TIME, each followed by its org policy.
@@ -4965,27 +3159,17 @@ var OwneySDK = class {
4965
3159
  * at a time anyway.
4966
3160
  *
4967
3161
  * Every agent is attempted even if an earlier one fails, so one declined
4968
- * signature can't deny the remaining agents their turn. Once all agents have
4969
- * had a chance, a partial failure identifies the agents that still need a
4970
- * retry; if none activated, the original provider error is preserved.
3162
+ * signature can't deny the remaining agents their turn. The first failure is
3163
+ * rethrown (matching the previous `Promise.all` rejection) once all agents
3164
+ * have had a chance to activate.
4971
3165
  */
4972
- async activateAgentsInTurn(agents, state, chainId, asset) {
3166
+ async activateAgentsInTurn(agents, state, chainId) {
4973
3167
  let firstError = null;
4974
- const activatedAgentIds = [];
4975
- const failedAgents = [];
4976
3168
  for (const agent of agents) {
4977
3169
  try {
4978
- await agent.activateAgent(state, chainId, asset);
3170
+ await agent.activateAgent(state, chainId);
4979
3171
  await this.applyOrgPolicyTo(agent, state, chainId);
4980
- activatedAgentIds.push(agent.id);
4981
3172
  } catch (error) {
4982
- const message = error !== null && typeof error === "object" && "message" in error && typeof error.message === "string" ? error.message : typeof error === "string" ? error : "No activation error message was returned.";
4983
- failedAgents.push({
4984
- agentId: agent.id,
4985
- code: error instanceof OwneyError ? error.code : void 0,
4986
- message,
4987
- ...error instanceof OwneyError && error.details ? { details: error.details } : {}
4988
- });
4989
3173
  if (firstError === null) {
4990
3174
  firstError = error;
4991
3175
  } else {
@@ -4993,18 +3177,7 @@ var OwneySDK = class {
4993
3177
  }
4994
3178
  }
4995
3179
  }
4996
- if (firstError === null) return;
4997
- if (activatedAgentIds.length === 0) throw firstError;
4998
- const failedAgentIds = failedAgents.map(({ agentId }) => agentId);
4999
- const activeNames = activatedAgentIds.map(this.formatAgentName).join(", ");
5000
- const failureMessages = failedAgents.map(
5001
- ({ agentId, message }) => `${this.formatAgentName(agentId)} activation failed: ${message}`
5002
- ).join(" ");
5003
- throw new OwneyError(
5004
- "AGENT_ACTIVATION_PARTIAL_FAILURE",
5005
- `${activeNames} activated. ${failureMessages}`,
5006
- { activatedAgentIds, failedAgentIds, failures: failedAgents }
5007
- );
3180
+ if (firstError !== null) throw firstError;
5008
3181
  }
5009
3182
  /**
5010
3183
  * Deposit into a specific agent, or distribute across all eligible agents.
@@ -5218,10 +3391,10 @@ var OwneySDK = class {
5218
3391
  agent,
5219
3392
  amount: i === agents.length - 1 ? perAgent + remainder : perAgent
5220
3393
  }));
5221
- const valid2 = splits.filter(
3394
+ const valid = splits.filter(
5222
3395
  (s) => s.amount > 0n && (exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset))
5223
3396
  );
5224
- if (valid2.length === agents.length) {
3397
+ if (valid.length === agents.length) {
5225
3398
  return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
5226
3399
  }
5227
3400
  const targets = agentsRequiringActivation.length > 0 ? agentsRequiringActivation : agents;
@@ -5240,11 +3413,6 @@ var OwneySDK = class {
5240
3413
  )
5241
3414
  }));
5242
3415
  }
5243
- formatAgentName(agentId) {
5244
- if (agentId === "zyfai") return "Zyfai";
5245
- if (agentId === "yieldseeker") return "Yieldseeker";
5246
- return agentId;
5247
- }
5248
3416
  async validateMinDepositAmount(agent, state, chainId, asset, amount) {
5249
3417
  const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
5250
3418
  const parsedAmount = BigInt(amount);
@@ -5271,17 +3439,16 @@ var OwneySDK = class {
5271
3439
  async hasExistingBalance(agent, state, chainId, asset, requireReliableRead = false) {
5272
3440
  try {
5273
3441
  const balance = await agent.getBalances(state, chainId);
5274
- const target = asset.toLowerCase();
5275
3442
  const token = balance.tokens.find(
5276
- (t) => t.chainId === chainId && t.asset.toLowerCase() === target
3443
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
5277
3444
  );
5278
3445
  const targetChainName = agent.supportedAssets.find((entry) => entry.chainId === chainId)?.chain?.trim().toUpperCase();
5279
- const position2 = (balance.positions ?? []).find((p) => {
3446
+ const position = (balance.positions ?? []).find((p) => {
5280
3447
  const positionChain = p.chain.trim().toUpperCase();
5281
3448
  const matchesChain = positionChain === String(chainId) || targetChainName !== void 0 && positionChain === targetChainName;
5282
- return matchesChain && p.asset.toLowerCase() === target && Number(p.amount) > 0;
3449
+ return matchesChain && isSameAsset(p.asset, asset) && Number(p.amount) > 0;
5283
3450
  });
5284
- return !!token && Number(token.amount) > 0 || !!position2;
3451
+ return !!token && Number(token.amount) > 0 || !!position;
5285
3452
  } catch (error) {
5286
3453
  if (requireReliableRead) {
5287
3454
  throw new OwneyError(
@@ -5326,6 +3493,34 @@ var OwneySDK = class {
5326
3493
  }
5327
3494
  return eligible;
5328
3495
  }
3496
+ /**
3497
+ * Agent ids the routing API provisioned for this org that support the given
3498
+ * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
3499
+ * surfliquid first). Returns `[]` when the org has no compatible agent — never
3500
+ * throws on an empty org. Loads agent keys on first call (apiKey only, no
3501
+ * wallet), so the UI can resolve which agent to use before the user connects.
3502
+ *
3503
+ * This is the source of truth for agent availability: an agent appears here
3504
+ * iff the routing API returned its key. No per-app feature flags.
3505
+ */
3506
+ async getEligibleAgentIds(chainId, asset) {
3507
+ try {
3508
+ await this.ensureAgentsInitialized();
3509
+ } catch (error) {
3510
+ if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
3511
+ return [];
3512
+ }
3513
+ throw error;
3514
+ }
3515
+ return [...this.agents.values()].filter((agent) => {
3516
+ const chainAssets = agent.supportedAssets.find(
3517
+ (sa) => sa.chainId === chainId
3518
+ );
3519
+ return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
3520
+ }).map((agent) => agent.id).sort(
3521
+ (a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
3522
+ );
3523
+ }
5329
3524
  // --- Fund operations ---
5330
3525
  /**
5331
3526
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
@@ -5362,9 +3557,19 @@ var OwneySDK = class {
5362
3557
  }
5363
3558
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
5364
3559
  if (!amount) {
3560
+ const aggregated2 = await this.getBalances();
3561
+ const funded = projectAgentBalancesForAsset(
3562
+ eligibleAgents,
3563
+ aggregated2.agentBalances,
3564
+ chainId,
3565
+ asset,
3566
+ assetInfo.decimals
3567
+ ).filter(
3568
+ ({ agent, balance }) => balance > 0n || aggregated2.agentErrors?.[agent.id] !== void 0
3569
+ ).map(({ agent }) => agent);
5365
3570
  const results2 = {};
5366
3571
  const agentErrors2 = {};
5367
- for (const agent of eligibleAgents) {
3572
+ for (const agent of funded) {
5368
3573
  try {
5369
3574
  results2[agent.id] = await agent.withdraw(state, chainId, token);
5370
3575
  } catch (err) {
@@ -5396,10 +3601,6 @@ var OwneySDK = class {
5396
3601
  }
5397
3602
  const requested = BigInt(amount);
5398
3603
  const aggregated = await this.getBalances();
5399
- const unavailableAgents = eligibleAgents.filter(
5400
- (agent) => !(agent.id in aggregated.agentBalances)
5401
- );
5402
- const unavailableAgentIds = unavailableAgents.map((agent) => agent.id);
5403
3604
  const balances = projectAgentBalancesForAsset(
5404
3605
  eligibleAgents,
5405
3606
  aggregated.agentBalances,
@@ -5408,18 +3609,7 @@ var OwneySDK = class {
5408
3609
  assetInfo.decimals
5409
3610
  );
5410
3611
  const totalAvailable = balances.reduce((sum, x) => sum + x.balance, 0n);
5411
- if (totalAvailable === 0n && unavailableAgents.length > 0) {
5412
- throw new OwneyError(
5413
- "WITHDRAW_BALANCE_UNAVAILABLE",
5414
- `Cannot safely plan the withdrawal because balance data is unavailable for: ${unavailableAgentIds.join(", ")}.`,
5415
- {
5416
- asset,
5417
- unavailableAgents: unavailableAgentIds,
5418
- agentErrors: aggregated.agentErrors
5419
- }
5420
- );
5421
- }
5422
- if (totalAvailable < requested && unavailableAgents.length === 0) {
3612
+ if (totalAvailable < requested) {
5423
3613
  throw new OwneyError(
5424
3614
  "WITHDRAW_INSUFFICIENT_BALANCE",
5425
3615
  `Requested withdrawal "${amount}" exceeds available balance "${totalAvailable.toString()}" for asset "${asset}".`,
@@ -5430,7 +3620,6 @@ var OwneySDK = class {
5430
3620
  }
5431
3621
  );
5432
3622
  }
5433
- const plannedTarget = totalAvailable < requested ? totalAvailable : requested;
5434
3623
  const disabledBalances = balances.filter(
5435
3624
  (b) => this.isAgentDisabled(b.agent.id)
5436
3625
  );
@@ -5439,7 +3628,7 @@ var OwneySDK = class {
5439
3628
  );
5440
3629
  const { plans: disabledPlans, remaining: afterDrain } = planDisabledDrain(
5441
3630
  disabledBalances,
5442
- plannedTarget
3631
+ requested
5443
3632
  );
5444
3633
  const enabledTotal = enabledBalances.reduce((s, b) => s + b.balance, 0n);
5445
3634
  const enabledPlans = afterDrain > 0n ? planProportionalShares(enabledBalances, afterDrain, enabledTotal) : enabledBalances.map(({ agent, balance }) => ({
@@ -5449,9 +3638,7 @@ var OwneySDK = class {
5449
3638
  }));
5450
3639
  const plans = [...disabledPlans, ...enabledPlans];
5451
3640
  const results = {};
5452
- const agentErrors = {
5453
- ...aggregated.agentErrors ?? {}
5454
- };
3641
+ const agentErrors = {};
5455
3642
  for (let i = 0; i < plans.length; i++) {
5456
3643
  const p = plans[i];
5457
3644
  if (p.planned === 0n) continue;
@@ -5498,8 +3685,7 @@ var OwneySDK = class {
5498
3685
  requested: amount,
5499
3686
  withdrawn: withdrawn.toString(),
5500
3687
  partialResults: results,
5501
- agentErrors,
5502
- ...unavailableAgentIds.length > 0 ? { unavailableAgents: unavailableAgentIds } : {}
3688
+ agentErrors
5503
3689
  }
5504
3690
  );
5505
3691
  }
@@ -5517,10 +3703,7 @@ var OwneySDK = class {
5517
3703
  if (agentId) {
5518
3704
  const agent = this.getAgent(agentId);
5519
3705
  const result = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
5520
- return {
5521
- ...result,
5522
- balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
5523
- };
3706
+ return result;
5524
3707
  }
5525
3708
  let totalBalance = 0;
5526
3709
  const results = {};
@@ -5528,13 +3711,7 @@ var OwneySDK = class {
5528
3711
  const balanceResults = await Promise.allSettled(
5529
3712
  entries.map(async ([id, agent]) => {
5530
3713
  const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
5531
- return [
5532
- id,
5533
- {
5534
- ...b,
5535
- balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
5536
- }
5537
- ];
3714
+ return [id, b];
5538
3715
  })
5539
3716
  );
5540
3717
  let successCount = 0;
@@ -5556,7 +3733,6 @@ var OwneySDK = class {
5556
3733
  const retryDelay = rateLimitDelay(reason);
5557
3734
  if (retryDelay !== void 0) agentRetryAt[agentId2] = Date.now() + retryDelay;
5558
3735
  agentErrors[agentId2] = reason instanceof Error ? reason.message : String(reason);
5559
- console.error(`[owney-sdk] Balance fetch failed for agent "${agentId2}":`, reason);
5560
3736
  }
5561
3737
  if (successCount === 0) {
5562
3738
  throw new OwneyError(
@@ -5669,10 +3845,7 @@ var OwneySDK = class {
5669
3845
  Promise.all(
5670
3846
  entries.map(async ([id, agent]) => {
5671
3847
  const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
5672
- return [
5673
- id,
5674
- balanceForApyScope(b, chainId, tokenSymbol)
5675
- ];
3848
+ return [id, balanceForApyScope(b, chainId, tokenSymbol)];
5676
3849
  })
5677
3850
  )
5678
3851
  ]);
@@ -5853,10 +4026,10 @@ var OwneySDK = class {
5853
4026
  );
5854
4027
  }
5855
4028
  const provider = this.requireConnectedProvider();
5856
- const wallet = createWalletClient3({
4029
+ const wallet = createWalletClient({
5857
4030
  account: state.walletAddress,
5858
4031
  chain: VIEM_CHAIN2[chainId],
5859
- transport: custom3(provider)
4032
+ transport: custom(provider)
5860
4033
  });
5861
4034
  const hash = await wallet.writeContract({
5862
4035
  address: token,
@@ -5866,9 +4039,9 @@ var OwneySDK = class {
5866
4039
  account: state.walletAddress,
5867
4040
  chain: VIEM_CHAIN2[chainId]
5868
4041
  });
5869
- const publicClient = createPublicClient4({
4042
+ const publicClient = createPublicClient2({
5870
4043
  chain: VIEM_CHAIN2[chainId],
5871
- transport: custom3(provider)
4044
+ transport: custom(provider)
5872
4045
  });
5873
4046
  const receipt = await publicClient.waitForTransactionReceipt({
5874
4047
  hash,
@@ -5905,9 +4078,7 @@ var OwneySDK = class {
5905
4078
  return this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
5906
4079
  }
5907
4080
  const results = {};
5908
- const agentEntries = [...this.agents.entries()].filter(
5909
- ([id]) => !this.isAgentDisabled(id)
5910
- );
4081
+ const agentEntries = [...this.agents.entries()];
5911
4082
  const apyResults = await Promise.all(
5912
4083
  agentEntries.map(async ([id, agent]) => {
5913
4084
  const apy = await this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
@@ -5982,13 +4153,13 @@ var OwneySDK = class {
5982
4153
  };
5983
4154
 
5984
4155
  // src/agents/zyfai/zyfai.siwx.ts
5985
- import { getAddress as getAddress3 } from "viem";
5986
- import { SiweMessage as SiweMessage2 } from "siwe";
4156
+ import { getAddress } from "viem";
4157
+ import { SiweMessage } from "siwe";
5987
4158
  import { ZyfaiSDK as ZyfaiSDK2 } from "@zyfai/sdk";
5988
4159
 
5989
4160
  // src/agents/zyfai/zyfai.siwx-cache.ts
5990
- var KEY_PREFIX4 = "owney.siwx.session";
5991
- var storage4 = () => {
4161
+ var KEY_PREFIX2 = "owney.siwx.session";
4162
+ var storage2 = () => {
5992
4163
  if (typeof window === "undefined") return null;
5993
4164
  try {
5994
4165
  return window.localStorage;
@@ -5996,8 +4167,8 @@ var storage4 = () => {
5996
4167
  return null;
5997
4168
  }
5998
4169
  };
5999
- var buildKey3 = (address) => `${KEY_PREFIX4}:${address.toLowerCase()}`;
6000
- var legacyKeyPrefix2 = (address) => `${KEY_PREFIX4}:${address.toLowerCase()}:`;
4170
+ var buildKey2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}`;
4171
+ var legacyKeyPrefix2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}:`;
6001
4172
  var memorySiwxSessions = /* @__PURE__ */ new Map();
6002
4173
  var readLegacySiwxSession = (store, address) => {
6003
4174
  if (!store) return null;
@@ -6028,17 +4199,17 @@ var readLegacySiwxSession = (store, address) => {
6028
4199
  };
6029
4200
  var readSiwxSession = (address, chainId) => {
6030
4201
  if (typeof window === "undefined") return null;
6031
- const key2 = buildKey3(address);
6032
- const store = storage4();
6033
- let raw2 = null;
4202
+ const key2 = buildKey2(address);
4203
+ const store = storage2();
4204
+ let raw = null;
6034
4205
  try {
6035
- raw2 = store?.getItem(key2) ?? null;
4206
+ raw = store?.getItem(key2) ?? null;
6036
4207
  } catch {
6037
- raw2 = null;
4208
+ raw = null;
6038
4209
  }
6039
- if (raw2) {
4210
+ if (raw) {
6040
4211
  try {
6041
- return JSON.parse(raw2);
4212
+ return JSON.parse(raw);
6042
4213
  } catch {
6043
4214
  memorySiwxSessions.delete(key2);
6044
4215
  try {
@@ -6057,18 +4228,18 @@ var readSiwxSession = (address, chainId) => {
6057
4228
  };
6058
4229
  var writeSiwxSession = (address, _chainId, session) => {
6059
4230
  if (typeof window === "undefined") return;
6060
- const key2 = buildKey3(address);
4231
+ const key2 = buildKey2(address);
6061
4232
  memorySiwxSessions.set(key2, session);
6062
- const store = storage4();
4233
+ const store = storage2();
6063
4234
  try {
6064
4235
  store?.setItem(key2, JSON.stringify(session));
6065
4236
  } catch {
6066
4237
  }
6067
4238
  };
6068
4239
  var clearSiwxSession = (address, _chainId) => {
6069
- const key2 = buildKey3(address);
4240
+ const key2 = buildKey2(address);
6070
4241
  memorySiwxSessions.delete(key2);
6071
- const store = storage4();
4242
+ const store = storage2();
6072
4243
  try {
6073
4244
  store?.removeItem(key2);
6074
4245
  } catch {
@@ -6108,8 +4279,8 @@ function buildSIWXConfig(deps) {
6108
4279
  statement: STATEMENT,
6109
4280
  issuedAt,
6110
4281
  toString() {
6111
- return new SiweMessage2({
6112
- address: getAddress3(accountAddress),
4282
+ return new SiweMessage({
4283
+ address: getAddress(accountAddress),
6113
4284
  chainId: numericChainId(chainId),
6114
4285
  domain,
6115
4286
  uri,
@@ -6151,7 +4322,7 @@ function buildSIWXConfig(deps) {
6151
4322
  const persistSession = async (session) => {
6152
4323
  const address = session.data.accountAddress;
6153
4324
  const id = numericChainId(session.data.chainId);
6154
- const message = new SiweMessage2(session.message);
4325
+ const message = new SiweMessage(session.message);
6155
4326
  const login = await post("/auth/login", {
6156
4327
  message,
6157
4328
  signature: session.signature,
@@ -6200,7 +4371,6 @@ export {
6200
4371
  NotConnectedError,
6201
4372
  OwneyError,
6202
4373
  OwneySDK,
6203
- YieldseekerAgent,
6204
4374
  createOwneySIWX,
6205
4375
  setOwneyDebug
6206
4376
  };