@owney/sdk 0.6.0-beta.1 → 0.6.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/README.md CHANGED
@@ -407,17 +407,6 @@ const usdcBaseApy = await sdk.getAgentApy({
407
407
  console.log(usdcBaseApy.agentApy.zyfai.averageApy); // APY scoped to USDC on Base
408
408
  ```
409
409
 
410
- ### `getAgentAllocation()`
411
-
412
- Get the current fund allocation percentages across agents.
413
-
414
- Returns: `OwneyAgentAllocation`
415
-
416
- ```typescript
417
- const allocation = await sdk.getAgentAllocation();
418
- console.log(allocation.agentAllocation); // { zyfai: 100 }
419
- ```
420
-
421
410
  ## Types
422
411
 
423
412
  ### Configuration
@@ -630,10 +619,6 @@ interface AgentApyDetails {
630
619
  interface OwneyAgentApy {
631
620
  agentApy: Record<AgentId, AgentApy>;
632
621
  }
633
-
634
- interface OwneyAgentAllocation {
635
- agentAllocation: Record<AgentId, number>;
636
- }
637
622
  ```
638
623
 
639
624
  ### Callback Types
package/dist/index.cjs CHANGED
@@ -32,13 +32,15 @@ module.exports = __toCommonJS(src_exports);
32
32
 
33
33
  // src/agents/zyfai/zyfai.agent.ts
34
34
  var import_sdk = require("@zyfai/sdk");
35
+ var import_viem = require("viem");
36
+ var import_chains = require("viem/chains");
35
37
 
36
38
  // src/types/config.ts
37
39
  var P_SUPPORTED_CHAINS = {
38
40
  chainIds: [8453, 42161],
39
41
  chains: ["BASE", "ARBITRUM"]
40
42
  };
41
- var SUPPORTED_TOKENS = ["USDC", "USDT", "WETH"];
43
+ var SUPPORTED_TOKENS = ["USDC", "USDT"];
42
44
  var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
43
45
  var SUPPORTED_CHAINS = P_SUPPORTED_CHAINS.chains;
44
46
  var SupportedAssets = [
@@ -59,18 +61,6 @@ var SupportedAssets = [
59
61
  symbol: "USDT",
60
62
  chainId: 42161,
61
63
  decimals: 6
62
- },
63
- {
64
- address: `0x4200000000000000000000000000000000000006`,
65
- symbol: "WETH",
66
- chainId: 8453,
67
- decimals: 18
68
- },
69
- {
70
- address: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`,
71
- symbol: "WETH",
72
- chainId: 42161,
73
- decimals: 18
74
64
  }
75
65
  ];
76
66
 
@@ -280,6 +270,14 @@ function mapApyHistory(raw) {
280
270
  apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain)
281
271
  };
282
272
  }
273
+ function splitOpportunity(opportunity) {
274
+ const match = opportunity.match(/^(.*?)\s*\(([^)]*)\)\s*$/);
275
+ if (match) {
276
+ const pool = match[2].trim();
277
+ return { protocol: match[1].trim(), pool: pool || void 0 };
278
+ }
279
+ return { protocol: opportunity.trim() };
280
+ }
283
281
  function mapEntries(rawEntries, chainId) {
284
282
  const actionMap = {
285
283
  "Top up wallet": "Top up",
@@ -299,21 +297,26 @@ function mapEntries(rawEntries, chainId) {
299
297
  );
300
298
  oldApy = Number(rawLog.oldApy);
301
299
  newApy = Number(rawLog.newApy);
300
+ const from = splitOpportunity(rawLog.oldOpportunity);
301
+ const to = splitOpportunity(rawLog.newOpportunity);
302
302
  rebalanceLog = [
303
303
  {
304
- fromProtocol: rawLog.oldOpportunity.replace(/\s*\(.*?\)/g, "").trim(),
305
- toProtocol: rawLog.newOpportunity.replace(/\s*\(.*?\)/g, "").trim(),
304
+ fromProtocol: from.protocol,
305
+ toProtocol: to.protocol,
306
+ fromPool: from.pool,
307
+ toPool: to.pool,
306
308
  tokenSymbol: matched?.token_symbol ?? "",
307
309
  amount: matched ? String(hexToDecimal(matched.amount || "0x")) : "",
308
310
  status: "success"
309
311
  }
310
312
  ];
311
313
  }
314
+ const mappedAction = (entry.action ? actionMap[entry.action] : void 0) ?? entry.action;
312
315
  const rawAmount = entry?.positions?.[0]?.amount;
313
- const hasAmount = typeof rawAmount === "string" && rawAmount !== "" && rawAmount !== "0x" && rawAmount !== "0x0" && rawAmount !== "0";
316
+ const hasAmount = mappedAction !== "Withdraw" && typeof rawAmount === "string" && rawAmount !== "" && rawAmount !== "0x" && rawAmount !== "0x0" && rawAmount !== "0";
314
317
  return {
315
318
  agent: "zyfai",
316
- action: (entry.action ? actionMap[entry.action] : void 0) ?? entry.action,
319
+ action: mappedAction,
317
320
  date: entry.date || "",
318
321
  newApy: newApy === null ? null : String(newApy),
319
322
  oldApy: oldApy === null ? null : String(oldApy),
@@ -405,6 +408,33 @@ function computeAllocationApy(positions) {
405
408
  return { totalApy, apyByChainAndAsset };
406
409
  }
407
410
 
411
+ // src/agents/zyfai/zyfai.withdraw-amount.ts
412
+ var TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
413
+ function topicToAddress(topic) {
414
+ return `0x${(topic ?? "").slice(-40)}`.toLowerCase();
415
+ }
416
+ function extractWithdrawnAmount(logs, recipient, token, decimals) {
417
+ const wantRecipient = recipient.toLowerCase();
418
+ const wantToken = token.toLowerCase();
419
+ let total = 0n;
420
+ let matched = false;
421
+ for (const log of logs) {
422
+ if (log.address.toLowerCase() !== wantToken)
423
+ continue;
424
+ if ((log.topics[0] ?? "").toLowerCase() !== TRANSFER_TOPIC)
425
+ continue;
426
+ if (topicToAddress(log.topics[2]) !== wantRecipient)
427
+ continue;
428
+ if (!log.data || log.data === "0x")
429
+ continue;
430
+ total += BigInt(log.data);
431
+ matched = true;
432
+ }
433
+ if (!matched)
434
+ return void 0;
435
+ return String(hexToDecimal(`0x${total.toString(16)}`, decimals));
436
+ }
437
+
408
438
  // src/agents/zyfai/zyfai.history-cursor.ts
409
439
  var InvalidHistoryCursorError = class extends Error {
410
440
  code = "invalid_cursor";
@@ -503,10 +533,7 @@ var DEFAULT_ZYFAI_RPC_URLS = {
503
533
  8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
504
534
  42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
505
535
  };
506
- var WETH_ADDRESS_BY_CHAIN = {
507
- 8453: "0x4200000000000000000000000000000000000006",
508
- 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
509
- };
536
+ var VIEM_CHAIN = { 8453: import_chains.base, 42161: import_chains.arbitrum };
510
537
  var ZyfaiAgent = class {
511
538
  id = "zyfai";
512
539
  supportedChainIds = [8453, 42161];
@@ -514,18 +541,12 @@ var ZyfaiAgent = class {
514
541
  {
515
542
  chainId: 8453,
516
543
  chain: "BASE",
517
- assets: [
518
- { symbol: "USDC", minDepositAmount: "1500000" },
519
- { symbol: "WETH", minDepositAmount: "500000000000000" }
520
- ]
544
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
521
545
  },
522
546
  {
523
547
  chainId: 42161,
524
548
  chain: "ARBITRUM",
525
- assets: [
526
- { symbol: "USDC", minDepositAmount: "1500000" },
527
- { symbol: "WETH", minDepositAmount: "500000000000000" }
528
- ]
549
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
529
550
  }
530
551
  ];
531
552
  sdk;
@@ -533,13 +554,83 @@ var ZyfaiAgent = class {
533
554
  connectedChainId = null;
534
555
  smartWalletCache = /* @__PURE__ */ new Map();
535
556
  connectAuthPromise = null;
557
+ rpcUrls;
558
+ publicClients = /* @__PURE__ */ new Map();
559
+ // txHash -> resolved withdrawn amount. Receipts are immutable, so a
560
+ // successful decode is cached forever; failures are NOT cached so a transient
561
+ // RPC error retries on the next fetch.
562
+ withdrawAmountCache = /* @__PURE__ */ new Map();
536
563
  constructor(apiKey, rpcUrls) {
564
+ this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
537
565
  this.sdk = new import_sdk.ZyfaiSDK({
538
566
  apiKey,
539
- rpcUrls: rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS
567
+ rpcUrls: this.rpcUrls
540
568
  });
541
569
  this.installAuthCache();
542
570
  }
571
+ getPublicClient(chainId) {
572
+ const cached = this.publicClients.get(chainId);
573
+ if (cached)
574
+ return cached;
575
+ const client = (0, import_viem.createPublicClient)({
576
+ chain: VIEM_CHAIN[chainId],
577
+ transport: (0, import_viem.http)(this.rpcUrls[chainId])
578
+ });
579
+ this.publicClients.set(chainId, client);
580
+ return client;
581
+ }
582
+ /**
583
+ * Fills in the true withdrawn amount for `Withdraw` entries by decoding the
584
+ * USDC `Transfer` that lands in the user's wallet on-chain. The Zyfai history
585
+ * payload only reports the *remaining* position for a partial withdraw (see
586
+ * the note in `mapEntries`), so without this the UI shows the leftover
587
+ * balance instead of the amount withdrawn.
588
+ *
589
+ * Mutates `entries` in place. Runs all lookups concurrently and is tolerant
590
+ * of RPC failures: an entry whose amount can't be resolved keeps
591
+ * `amount: undefined`, which consumers render as a hidden/retryable row
592
+ * rather than a wrong number.
593
+ */
594
+ async resolveWithdrawnAmounts(entries, chainId, recipient) {
595
+ const asset = SupportedAssets.find(
596
+ (a) => a.chainId === chainId && a.symbol === "USDC"
597
+ );
598
+ if (!asset)
599
+ return;
600
+ const withdrawals = entries.filter(
601
+ (e) => e.action === "Withdraw" && e.transactions[0]?.txHashes[0]
602
+ );
603
+ if (withdrawals.length === 0)
604
+ return;
605
+ const client = this.getPublicClient(chainId);
606
+ await Promise.all(
607
+ withdrawals.map(async (entry) => {
608
+ const tx = entry.transactions[0];
609
+ const txHash = tx.txHashes[0];
610
+ const cached = this.withdrawAmountCache.get(txHash);
611
+ if (cached !== void 0) {
612
+ tx.amount = cached;
613
+ return;
614
+ }
615
+ try {
616
+ const receipt = await client.getTransactionReceipt({
617
+ hash: txHash
618
+ });
619
+ const amount = extractWithdrawnAmount(
620
+ receipt.logs,
621
+ recipient,
622
+ asset.address,
623
+ asset.decimals
624
+ );
625
+ if (amount !== void 0) {
626
+ this.withdrawAmountCache.set(txHash, amount);
627
+ tx.amount = amount;
628
+ }
629
+ } catch {
630
+ }
631
+ })
632
+ );
633
+ }
543
634
  /**
544
635
  * Patches `sdk.authenticateUser` so a fresh page can reuse the JWT from a
545
636
  * prior session instead of triggering a new SIWE prompt. Runs inside
@@ -691,7 +782,7 @@ var ZyfaiAgent = class {
691
782
  throw error;
692
783
  }
693
784
  }
694
- async deposit(state, chainId, amount, asset, depositCallback) {
785
+ async deposit(state, chainId, amount, depositCallback) {
695
786
  try {
696
787
  await this.connectFull(state, chainId);
697
788
  const validChainId = isValidChainId(chainId);
@@ -705,15 +796,13 @@ var ZyfaiAgent = class {
705
796
  validChainId,
706
797
  amount
707
798
  );
708
- const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
709
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
799
+ await this.sdk.logDeposit(validChainId, txHash, amount);
710
800
  return { txHash, smartWallet: wallet.address, amount };
711
801
  }
712
802
  const raw = await this.sdk.depositFunds(
713
803
  this.getAddress(),
714
804
  validChainId,
715
- amount,
716
- asset
805
+ amount
717
806
  );
718
807
  return mapDeposit(raw);
719
808
  } catch (error) {
@@ -792,8 +881,10 @@ var ZyfaiAgent = class {
792
881
  toDate,
793
882
  rawOffset: firstOvershoot ? firstOvershoot.rawIdx : offset
794
883
  }) : void 0;
884
+ const data = mapEntries(pageData, validChainId);
885
+ await this.resolveWithdrawnAmounts(data, validChainId, state.walletAddress);
795
886
  return {
796
- data: mapEntries(pageData, validChainId),
887
+ data,
797
888
  hasMore,
798
889
  nextCursor
799
890
  };
@@ -884,7 +975,7 @@ async function withFailureReporting(apiKey, agentType, fn) {
884
975
  }
885
976
 
886
977
  // src/lib/helpers/withdraw-helper.ts
887
- var import_viem = require("viem");
978
+ var import_viem2 = require("viem");
888
979
  function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
889
980
  const target = asset.toUpperCase();
890
981
  return agents.map((agent) => {
@@ -894,7 +985,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
894
985
  );
895
986
  if (!tokenBalance)
896
987
  return { agent, balance: 0n };
897
- return { agent, balance: (0, import_viem.parseUnits)(tokenBalance.amount, decimals) };
988
+ return { agent, balance: (0, import_viem2.parseUnits)(tokenBalance.amount, decimals) };
898
989
  });
899
990
  }
900
991
  function planProportionalShares(balances, requested, totalAvailable) {
@@ -1010,11 +1101,11 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
1010
1101
  }
1011
1102
 
1012
1103
  // src/client.ts
1013
- var import_viem3 = require("viem");
1014
- var import_chains = require("viem/chains");
1104
+ var import_viem4 = require("viem");
1105
+ var import_chains2 = require("viem/chains");
1015
1106
 
1016
1107
  // src/lib/transfer-auth.ts
1017
- var import_viem2 = require("viem");
1108
+ var import_viem3 = require("viem");
1018
1109
  var ERC20_META_ABI = [
1019
1110
  { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
1020
1111
  { type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
@@ -1046,16 +1137,16 @@ async function readTokenMeta(publicClient, token) {
1046
1137
  function randomAuthNonce() {
1047
1138
  const bytes = new Uint8Array(32);
1048
1139
  globalThis.crypto.getRandomValues(bytes);
1049
- return (0, import_viem2.bytesToHex)(bytes);
1140
+ return (0, import_viem3.bytesToHex)(bytes);
1050
1141
  }
1051
1142
 
1052
1143
  // src/lib/sponsor-client.ts
1053
1144
  var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
1054
1145
  async function postSponsorTransferAuth(input) {
1055
- const base2 = input.baseUrl ?? ROUTING_API_BASE_URL3;
1146
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
1056
1147
  let res;
1057
1148
  try {
1058
- res = await fetch(`${base2}/api/v1/sponsor/erc20-transfer-auth`, {
1149
+ res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
1059
1150
  method: "POST",
1060
1151
  headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey },
1061
1152
  body: JSON.stringify(input.body)
@@ -1158,9 +1249,9 @@ var SPONSORED_USDC_BY_CHAIN = {
1158
1249
  8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
1159
1250
  42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
1160
1251
  };
1161
- var VIEM_CHAIN = {
1162
- 8453: import_chains.base,
1163
- 42161: import_chains.arbitrum
1252
+ var VIEM_CHAIN2 = {
1253
+ 8453: import_chains2.base,
1254
+ 42161: import_chains2.arbitrum
1164
1255
  };
1165
1256
  var OwneySDK = class {
1166
1257
  agents = /* @__PURE__ */ new Map();
@@ -1273,14 +1364,14 @@ var OwneySDK = class {
1273
1364
  // Casts work around viem's chain-narrowed Client vs the generic
1274
1365
  // PublicClient/WalletClient param types — structurally identical at
1275
1366
  // runtime, but the two share a name TS treats as unrelated.
1276
- getPublicClient: (cid) => (0, import_viem3.createPublicClient)({
1277
- chain: VIEM_CHAIN[cid],
1278
- transport: (0, import_viem3.custom)(provider)
1367
+ getPublicClient: (cid) => (0, import_viem4.createPublicClient)({
1368
+ chain: VIEM_CHAIN2[cid],
1369
+ transport: (0, import_viem4.custom)(provider)
1279
1370
  }),
1280
- getWalletClient: (cid) => (0, import_viem3.createWalletClient)({
1371
+ getWalletClient: (cid) => (0, import_viem4.createWalletClient)({
1281
1372
  account: owner,
1282
- chain: VIEM_CHAIN[cid],
1283
- transport: (0, import_viem3.custom)(provider)
1373
+ chain: VIEM_CHAIN2[cid],
1374
+ transport: (0, import_viem4.custom)(provider)
1284
1375
  })
1285
1376
  });
1286
1377
  return this.cachedSponsoredCallback;
@@ -1438,7 +1529,7 @@ var OwneySDK = class {
1438
1529
  }
1439
1530
  const state = this.requireState();
1440
1531
  const chainId = this.requireChainId();
1441
- const effectiveCallback = depositCallback ?? (asset === "WETH" ? void 0 : this.getDefaultSponsoredCallback());
1532
+ const effectiveCallback = depositCallback ?? this.getDefaultSponsoredCallback();
1442
1533
  if (agentId) {
1443
1534
  if (this.isAgentDisabled(agentId)) {
1444
1535
  throw new OwneyError(
@@ -1453,13 +1544,7 @@ var OwneySDK = class {
1453
1544
  return withFailureReporting(
1454
1545
  this.apiKey,
1455
1546
  agent.id,
1456
- () => agent.deposit(
1457
- state,
1458
- chainId,
1459
- amount,
1460
- asset,
1461
- effectiveCallback
1462
- )
1547
+ () => agent.deposit(state, chainId, amount, effectiveCallback)
1463
1548
  );
1464
1549
  }
1465
1550
  const totalAmount = BigInt(amount);
@@ -1493,13 +1578,7 @@ var OwneySDK = class {
1493
1578
  agentResults[agent.id] = await withFailureReporting(
1494
1579
  this.apiKey,
1495
1580
  agent.id,
1496
- () => agent.deposit(
1497
- state,
1498
- chainId,
1499
- agentAmount,
1500
- asset,
1501
- effectiveCallback
1502
- )
1581
+ () => agent.deposit(state, chainId, agentAmount, effectiveCallback)
1503
1582
  );
1504
1583
  }
1505
1584
  return { agentResults };
@@ -2029,70 +2108,6 @@ var OwneySDK = class {
2029
2108
  agentApy: results
2030
2109
  };
2031
2110
  }
2032
- /**
2033
- * Get the current fund allocation percentages across agents.
2034
- * @returns Object with agent names as keys and allocation percentages as values
2035
- */
2036
- async getAgentAllocation() {
2037
- const state = this.requireState();
2038
- const chainId = this.requireChainId();
2039
- const activeAgents = this.getActiveAgents();
2040
- const balances = {};
2041
- const positionsByAgent = {};
2042
- let totalBalance = 0;
2043
- const entries = [...activeAgents.entries()];
2044
- const balanceResults = await Promise.allSettled(
2045
- entries.map(async ([id, agent]) => {
2046
- const b = await agent.getBalances(state, chainId);
2047
- return [id, Number(b.totalBalance), b.positions ?? []];
2048
- })
2049
- );
2050
- let successCount = 0;
2051
- const agentErrors = {};
2052
- for (let i = 0; i < balanceResults.length; i++) {
2053
- const settledResult = balanceResults[i];
2054
- const [agentId] = entries[i];
2055
- if (settledResult.status === "fulfilled") {
2056
- const [id, bal, agentPositions] = settledResult.value;
2057
- balances[id] = bal;
2058
- positionsByAgent[id] = agentPositions;
2059
- totalBalance += bal;
2060
- successCount += 1;
2061
- } else {
2062
- const reason = settledResult.reason;
2063
- agentErrors[agentId] = reason instanceof Error ? reason.message : String(reason);
2064
- console.error(`getAgentAllocation agent "${agentId}" failed:`, reason);
2065
- }
2066
- }
2067
- if (successCount === 0) {
2068
- throw new OwneyError(
2069
- "ALLOCATION_ALL_FAILED",
2070
- "Failed to fetch allocation: all agents failed.",
2071
- { agentErrors }
2072
- );
2073
- }
2074
- const allocation = {};
2075
- if (totalBalance === 0) {
2076
- for (const id of activeAgents.keys()) {
2077
- allocation[id] = 0;
2078
- }
2079
- } else {
2080
- for (const id of activeAgents.keys()) {
2081
- allocation[id] = balances[id] > 0 ? Math.max(1, Math.floor(balances[id] / totalBalance * 100)) : 0;
2082
- }
2083
- const remainder = 100 - Object.values(allocation).reduce((a, b) => a + b, 0);
2084
- if (remainder > 0) {
2085
- const largestId = [...activeAgents.keys()].reduce(
2086
- (a, b) => balances[a] >= balances[b] ? a : b
2087
- );
2088
- allocation[largestId] += remainder;
2089
- }
2090
- }
2091
- return {
2092
- agentAllocation: allocation,
2093
- agentPositions: positionsByAgent
2094
- };
2095
- }
2096
2111
  /**
2097
2112
  * Allocation-weighted APY from the current portfolio: each pool's APY
2098
2113
  * weighted by the user's position value in it. More accurate per-user than
@@ -2152,7 +2167,7 @@ var OwneySDK = class {
2152
2167
  };
2153
2168
 
2154
2169
  // src/agents/zyfai/zyfai.siwx.ts
2155
- var import_viem4 = require("viem");
2170
+ var import_viem5 = require("viem");
2156
2171
  var import_siwe = require("siwe");
2157
2172
  var import_sdk2 = require("@zyfai/sdk");
2158
2173
 
@@ -2234,7 +2249,7 @@ function buildSIWXConfig(deps) {
2234
2249
  issuedAt,
2235
2250
  toString() {
2236
2251
  return new import_siwe.SiweMessage({
2237
- address: (0, import_viem4.getAddress)(accountAddress),
2252
+ address: (0, import_viem5.getAddress)(accountAddress),
2238
2253
  chainId: numericChainId(chainId),
2239
2254
  domain,
2240
2255
  uri,
@@ -2310,9 +2325,9 @@ function buildSIWXConfig(deps) {
2310
2325
  }
2311
2326
  function createOwneySIWX(config) {
2312
2327
  const zyfai = new import_sdk2.ZyfaiSDK({ apiKey: config.apiKey });
2313
- const http = zyfai.httpClient;
2328
+ const http2 = zyfai.httpClient;
2314
2329
  return buildSIWXConfig({
2315
- post: (url, data) => http.post(url, data),
2330
+ post: (url, data) => http2.post(url, data),
2316
2331
  referralSource: config.referralSource
2317
2332
  });
2318
2333
  }
package/dist/index.d.cts CHANGED
@@ -14,7 +14,7 @@ interface ConnectionState {
14
14
  walletAddress: `0x${string}`;
15
15
  chainId: number | null;
16
16
  }
17
- declare const SUPPORTED_TOKENS: readonly ["USDC", "USDT", "WETH"];
17
+ declare const SUPPORTED_TOKENS: readonly ["USDC", "USDT"];
18
18
  declare const SUPPORTED_CHAIN_IDS: readonly [8453, 42161];
19
19
  declare const SUPPORTED_CHAINS: readonly ["BASE", "ARBITRUM"];
20
20
  type OwneySupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];
@@ -114,6 +114,15 @@ interface HistoryTransaction {
114
114
  interface RebalanceLog {
115
115
  fromProtocol: string;
116
116
  toProtocol: string;
117
+ /**
118
+ * Pool/vault sub-label for the source position (e.g. "USDC Core"), when the
119
+ * agent exposes one. Lets consumers disambiguate moves within the same
120
+ * protocol ("Morpho · USDC Core → Morpho · Spark USDC"). Absent when the
121
+ * agent only reports a bare protocol name.
122
+ */
123
+ fromPool?: string;
124
+ /** Pool/vault sub-label for the destination position. See {@link fromPool}. */
125
+ toPool?: string;
117
126
  tokenSymbol: string;
118
127
  amount: string;
119
128
  status: "success" | "failed";
@@ -162,11 +171,6 @@ interface AgentApy {
162
171
  interface OwneyAgentApy {
163
172
  agentApy: Record<AgentId, AgentApy>;
164
173
  }
165
- interface OwneyAgentAllocation {
166
- agentAllocation: Record<AgentId, number>;
167
- /** Per-agent positions. Empty array for agents that don't expose positions. */
168
- agentPositions: Record<AgentId, OwneyPosition[]>;
169
- }
170
174
 
171
175
  type DepositCallback = (smartWalletAddress: string, chainId: number, amount: string) => Promise<`0x${string}`> | `0x${string}`;
172
176
  interface IAgent {
@@ -175,7 +179,7 @@ interface IAgent {
175
179
  readonly supportedAssets: readonly AgentSupportedAssets[];
176
180
  disconnect(): Promise<void>;
177
181
  activateAgent(state: ConnectionState, chainId: number): Promise<void>;
178
- deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
182
+ deposit(state: ConnectionState, chainId: number, amount: string, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
179
183
  withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
180
184
  getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
181
185
  getEarnings(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
@@ -405,11 +409,6 @@ declare class OwneySDK {
405
409
  * @returns {AgentApy} for a single agent, or {OwneyAgentApy} with per-agent APY
406
410
  */
407
411
  getAgentApy({ agentId, days, tokenSymbol, chainId, }: AgentsApyOptions): Promise<OwneyAgentApy | AgentApy>;
408
- /**
409
- * Get the current fund allocation percentages across agents.
410
- * @returns Object with agent names as keys and allocation percentages as values
411
- */
412
- getAgentAllocation(): Promise<OwneyAgentAllocation>;
413
412
  /**
414
413
  * Allocation-weighted APY from the current portfolio: each pool's APY
415
414
  * weighted by the user's position value in it. More accurate per-user than
@@ -465,4 +464,4 @@ type OwneySIWXConfig = {
465
464
  */
466
465
  declare function createOwneySIWX(config: OwneySIWXConfig): SIWXConfig;
467
466
 
468
- export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentHistoryPosition, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, AllocationAgentApy, ApyByChainAndAsset, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, InvalidHistoryCursorError, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAllocationApy, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneyPosition, OwneySDK, OwneySDKConfig, OwneySIWXConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions, createOwneySIWX };
467
+ export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentHistoryPosition, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, AllocationAgentApy, ApyByChainAndAsset, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, InvalidHistoryCursorError, NotConnectedError, OwneyAccountApy, OwneyAgentApy, OwneyAgentHistory, OwneyAllocationApy, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneyPosition, OwneySDK, OwneySDKConfig, OwneySIWXConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions, createOwneySIWX };
package/dist/index.d.ts CHANGED
@@ -14,7 +14,7 @@ interface ConnectionState {
14
14
  walletAddress: `0x${string}`;
15
15
  chainId: number | null;
16
16
  }
17
- declare const SUPPORTED_TOKENS: readonly ["USDC", "USDT", "WETH"];
17
+ declare const SUPPORTED_TOKENS: readonly ["USDC", "USDT"];
18
18
  declare const SUPPORTED_CHAIN_IDS: readonly [8453, 42161];
19
19
  declare const SUPPORTED_CHAINS: readonly ["BASE", "ARBITRUM"];
20
20
  type OwneySupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];
@@ -114,6 +114,15 @@ interface HistoryTransaction {
114
114
  interface RebalanceLog {
115
115
  fromProtocol: string;
116
116
  toProtocol: string;
117
+ /**
118
+ * Pool/vault sub-label for the source position (e.g. "USDC Core"), when the
119
+ * agent exposes one. Lets consumers disambiguate moves within the same
120
+ * protocol ("Morpho · USDC Core → Morpho · Spark USDC"). Absent when the
121
+ * agent only reports a bare protocol name.
122
+ */
123
+ fromPool?: string;
124
+ /** Pool/vault sub-label for the destination position. See {@link fromPool}. */
125
+ toPool?: string;
117
126
  tokenSymbol: string;
118
127
  amount: string;
119
128
  status: "success" | "failed";
@@ -162,11 +171,6 @@ interface AgentApy {
162
171
  interface OwneyAgentApy {
163
172
  agentApy: Record<AgentId, AgentApy>;
164
173
  }
165
- interface OwneyAgentAllocation {
166
- agentAllocation: Record<AgentId, number>;
167
- /** Per-agent positions. Empty array for agents that don't expose positions. */
168
- agentPositions: Record<AgentId, OwneyPosition[]>;
169
- }
170
174
 
171
175
  type DepositCallback = (smartWalletAddress: string, chainId: number, amount: string) => Promise<`0x${string}`> | `0x${string}`;
172
176
  interface IAgent {
@@ -175,7 +179,7 @@ interface IAgent {
175
179
  readonly supportedAssets: readonly AgentSupportedAssets[];
176
180
  disconnect(): Promise<void>;
177
181
  activateAgent(state: ConnectionState, chainId: number): Promise<void>;
178
- deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
182
+ deposit(state: ConnectionState, chainId: number, amount: string, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
179
183
  withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
180
184
  getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
181
185
  getEarnings(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
@@ -405,11 +409,6 @@ declare class OwneySDK {
405
409
  * @returns {AgentApy} for a single agent, or {OwneyAgentApy} with per-agent APY
406
410
  */
407
411
  getAgentApy({ agentId, days, tokenSymbol, chainId, }: AgentsApyOptions): Promise<OwneyAgentApy | AgentApy>;
408
- /**
409
- * Get the current fund allocation percentages across agents.
410
- * @returns Object with agent names as keys and allocation percentages as values
411
- */
412
- getAgentAllocation(): Promise<OwneyAgentAllocation>;
413
412
  /**
414
413
  * Allocation-weighted APY from the current portfolio: each pool's APY
415
414
  * weighted by the user's position value in it. More accurate per-user than
@@ -465,4 +464,4 @@ type OwneySIWXConfig = {
465
464
  */
466
465
  declare function createOwneySIWX(config: OwneySIWXConfig): SIWXConfig;
467
466
 
468
- export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentHistoryPosition, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, AllocationAgentApy, ApyByChainAndAsset, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, InvalidHistoryCursorError, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAllocationApy, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneyPosition, OwneySDK, OwneySDKConfig, OwneySIWXConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions, createOwneySIWX };
467
+ export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentHistoryPosition, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, AllocationAgentApy, ApyByChainAndAsset, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, InvalidHistoryCursorError, NotConnectedError, OwneyAccountApy, OwneyAgentApy, OwneyAgentHistory, OwneyAllocationApy, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneyPosition, OwneySDK, OwneySDKConfig, OwneySIWXConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions, createOwneySIWX };
package/dist/index.js CHANGED
@@ -1,12 +1,14 @@
1
1
  // src/agents/zyfai/zyfai.agent.ts
2
2
  import { ZyfaiSDK } from "@zyfai/sdk";
3
+ import { createPublicClient, http } from "viem";
4
+ import { base, arbitrum } from "viem/chains";
3
5
 
4
6
  // src/types/config.ts
5
7
  var P_SUPPORTED_CHAINS = {
6
8
  chainIds: [8453, 42161],
7
9
  chains: ["BASE", "ARBITRUM"]
8
10
  };
9
- var SUPPORTED_TOKENS = ["USDC", "USDT", "WETH"];
11
+ var SUPPORTED_TOKENS = ["USDC", "USDT"];
10
12
  var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
11
13
  var SUPPORTED_CHAINS = P_SUPPORTED_CHAINS.chains;
12
14
  var SupportedAssets = [
@@ -27,18 +29,6 @@ var SupportedAssets = [
27
29
  symbol: "USDT",
28
30
  chainId: 42161,
29
31
  decimals: 6
30
- },
31
- {
32
- address: `0x4200000000000000000000000000000000000006`,
33
- symbol: "WETH",
34
- chainId: 8453,
35
- decimals: 18
36
- },
37
- {
38
- address: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`,
39
- symbol: "WETH",
40
- chainId: 42161,
41
- decimals: 18
42
32
  }
43
33
  ];
44
34
 
@@ -248,6 +238,14 @@ function mapApyHistory(raw) {
248
238
  apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain)
249
239
  };
250
240
  }
241
+ function splitOpportunity(opportunity) {
242
+ const match = opportunity.match(/^(.*?)\s*\(([^)]*)\)\s*$/);
243
+ if (match) {
244
+ const pool = match[2].trim();
245
+ return { protocol: match[1].trim(), pool: pool || void 0 };
246
+ }
247
+ return { protocol: opportunity.trim() };
248
+ }
251
249
  function mapEntries(rawEntries, chainId) {
252
250
  const actionMap = {
253
251
  "Top up wallet": "Top up",
@@ -267,21 +265,26 @@ function mapEntries(rawEntries, chainId) {
267
265
  );
268
266
  oldApy = Number(rawLog.oldApy);
269
267
  newApy = Number(rawLog.newApy);
268
+ const from = splitOpportunity(rawLog.oldOpportunity);
269
+ const to = splitOpportunity(rawLog.newOpportunity);
270
270
  rebalanceLog = [
271
271
  {
272
- fromProtocol: rawLog.oldOpportunity.replace(/\s*\(.*?\)/g, "").trim(),
273
- toProtocol: rawLog.newOpportunity.replace(/\s*\(.*?\)/g, "").trim(),
272
+ fromProtocol: from.protocol,
273
+ toProtocol: to.protocol,
274
+ fromPool: from.pool,
275
+ toPool: to.pool,
274
276
  tokenSymbol: matched?.token_symbol ?? "",
275
277
  amount: matched ? String(hexToDecimal(matched.amount || "0x")) : "",
276
278
  status: "success"
277
279
  }
278
280
  ];
279
281
  }
282
+ const mappedAction = (entry.action ? actionMap[entry.action] : void 0) ?? entry.action;
280
283
  const rawAmount = entry?.positions?.[0]?.amount;
281
- const hasAmount = typeof rawAmount === "string" && rawAmount !== "" && rawAmount !== "0x" && rawAmount !== "0x0" && rawAmount !== "0";
284
+ const hasAmount = mappedAction !== "Withdraw" && typeof rawAmount === "string" && rawAmount !== "" && rawAmount !== "0x" && rawAmount !== "0x0" && rawAmount !== "0";
282
285
  return {
283
286
  agent: "zyfai",
284
- action: (entry.action ? actionMap[entry.action] : void 0) ?? entry.action,
287
+ action: mappedAction,
285
288
  date: entry.date || "",
286
289
  newApy: newApy === null ? null : String(newApy),
287
290
  oldApy: oldApy === null ? null : String(oldApy),
@@ -373,6 +376,33 @@ function computeAllocationApy(positions) {
373
376
  return { totalApy, apyByChainAndAsset };
374
377
  }
375
378
 
379
+ // src/agents/zyfai/zyfai.withdraw-amount.ts
380
+ var TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
381
+ function topicToAddress(topic) {
382
+ return `0x${(topic ?? "").slice(-40)}`.toLowerCase();
383
+ }
384
+ function extractWithdrawnAmount(logs, recipient, token, decimals) {
385
+ const wantRecipient = recipient.toLowerCase();
386
+ const wantToken = token.toLowerCase();
387
+ let total = 0n;
388
+ let matched = false;
389
+ for (const log of logs) {
390
+ if (log.address.toLowerCase() !== wantToken)
391
+ continue;
392
+ if ((log.topics[0] ?? "").toLowerCase() !== TRANSFER_TOPIC)
393
+ continue;
394
+ if (topicToAddress(log.topics[2]) !== wantRecipient)
395
+ continue;
396
+ if (!log.data || log.data === "0x")
397
+ continue;
398
+ total += BigInt(log.data);
399
+ matched = true;
400
+ }
401
+ if (!matched)
402
+ return void 0;
403
+ return String(hexToDecimal(`0x${total.toString(16)}`, decimals));
404
+ }
405
+
376
406
  // src/agents/zyfai/zyfai.history-cursor.ts
377
407
  var InvalidHistoryCursorError = class extends Error {
378
408
  code = "invalid_cursor";
@@ -471,10 +501,7 @@ var DEFAULT_ZYFAI_RPC_URLS = {
471
501
  8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
472
502
  42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
473
503
  };
474
- var WETH_ADDRESS_BY_CHAIN = {
475
- 8453: "0x4200000000000000000000000000000000000006",
476
- 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
477
- };
504
+ var VIEM_CHAIN = { 8453: base, 42161: arbitrum };
478
505
  var ZyfaiAgent = class {
479
506
  id = "zyfai";
480
507
  supportedChainIds = [8453, 42161];
@@ -482,18 +509,12 @@ var ZyfaiAgent = class {
482
509
  {
483
510
  chainId: 8453,
484
511
  chain: "BASE",
485
- assets: [
486
- { symbol: "USDC", minDepositAmount: "1500000" },
487
- { symbol: "WETH", minDepositAmount: "500000000000000" }
488
- ]
512
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
489
513
  },
490
514
  {
491
515
  chainId: 42161,
492
516
  chain: "ARBITRUM",
493
- assets: [
494
- { symbol: "USDC", minDepositAmount: "1500000" },
495
- { symbol: "WETH", minDepositAmount: "500000000000000" }
496
- ]
517
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
497
518
  }
498
519
  ];
499
520
  sdk;
@@ -501,13 +522,83 @@ var ZyfaiAgent = class {
501
522
  connectedChainId = null;
502
523
  smartWalletCache = /* @__PURE__ */ new Map();
503
524
  connectAuthPromise = null;
525
+ rpcUrls;
526
+ publicClients = /* @__PURE__ */ new Map();
527
+ // txHash -> resolved withdrawn amount. Receipts are immutable, so a
528
+ // successful decode is cached forever; failures are NOT cached so a transient
529
+ // RPC error retries on the next fetch.
530
+ withdrawAmountCache = /* @__PURE__ */ new Map();
504
531
  constructor(apiKey, rpcUrls) {
532
+ this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
505
533
  this.sdk = new ZyfaiSDK({
506
534
  apiKey,
507
- rpcUrls: rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS
535
+ rpcUrls: this.rpcUrls
508
536
  });
509
537
  this.installAuthCache();
510
538
  }
539
+ getPublicClient(chainId) {
540
+ const cached = this.publicClients.get(chainId);
541
+ if (cached)
542
+ return cached;
543
+ const client = createPublicClient({
544
+ chain: VIEM_CHAIN[chainId],
545
+ transport: http(this.rpcUrls[chainId])
546
+ });
547
+ this.publicClients.set(chainId, client);
548
+ return client;
549
+ }
550
+ /**
551
+ * Fills in the true withdrawn amount for `Withdraw` entries by decoding the
552
+ * USDC `Transfer` that lands in the user's wallet on-chain. The Zyfai history
553
+ * payload only reports the *remaining* position for a partial withdraw (see
554
+ * the note in `mapEntries`), so without this the UI shows the leftover
555
+ * balance instead of the amount withdrawn.
556
+ *
557
+ * Mutates `entries` in place. Runs all lookups concurrently and is tolerant
558
+ * of RPC failures: an entry whose amount can't be resolved keeps
559
+ * `amount: undefined`, which consumers render as a hidden/retryable row
560
+ * rather than a wrong number.
561
+ */
562
+ async resolveWithdrawnAmounts(entries, chainId, recipient) {
563
+ const asset = SupportedAssets.find(
564
+ (a) => a.chainId === chainId && a.symbol === "USDC"
565
+ );
566
+ if (!asset)
567
+ return;
568
+ const withdrawals = entries.filter(
569
+ (e) => e.action === "Withdraw" && e.transactions[0]?.txHashes[0]
570
+ );
571
+ if (withdrawals.length === 0)
572
+ return;
573
+ const client = this.getPublicClient(chainId);
574
+ await Promise.all(
575
+ withdrawals.map(async (entry) => {
576
+ const tx = entry.transactions[0];
577
+ const txHash = tx.txHashes[0];
578
+ const cached = this.withdrawAmountCache.get(txHash);
579
+ if (cached !== void 0) {
580
+ tx.amount = cached;
581
+ return;
582
+ }
583
+ try {
584
+ const receipt = await client.getTransactionReceipt({
585
+ hash: txHash
586
+ });
587
+ const amount = extractWithdrawnAmount(
588
+ receipt.logs,
589
+ recipient,
590
+ asset.address,
591
+ asset.decimals
592
+ );
593
+ if (amount !== void 0) {
594
+ this.withdrawAmountCache.set(txHash, amount);
595
+ tx.amount = amount;
596
+ }
597
+ } catch {
598
+ }
599
+ })
600
+ );
601
+ }
511
602
  /**
512
603
  * Patches `sdk.authenticateUser` so a fresh page can reuse the JWT from a
513
604
  * prior session instead of triggering a new SIWE prompt. Runs inside
@@ -659,7 +750,7 @@ var ZyfaiAgent = class {
659
750
  throw error;
660
751
  }
661
752
  }
662
- async deposit(state, chainId, amount, asset, depositCallback) {
753
+ async deposit(state, chainId, amount, depositCallback) {
663
754
  try {
664
755
  await this.connectFull(state, chainId);
665
756
  const validChainId = isValidChainId(chainId);
@@ -673,15 +764,13 @@ var ZyfaiAgent = class {
673
764
  validChainId,
674
765
  amount
675
766
  );
676
- const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
677
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
767
+ await this.sdk.logDeposit(validChainId, txHash, amount);
678
768
  return { txHash, smartWallet: wallet.address, amount };
679
769
  }
680
770
  const raw = await this.sdk.depositFunds(
681
771
  this.getAddress(),
682
772
  validChainId,
683
- amount,
684
- asset
773
+ amount
685
774
  );
686
775
  return mapDeposit(raw);
687
776
  } catch (error) {
@@ -760,8 +849,10 @@ var ZyfaiAgent = class {
760
849
  toDate,
761
850
  rawOffset: firstOvershoot ? firstOvershoot.rawIdx : offset
762
851
  }) : void 0;
852
+ const data = mapEntries(pageData, validChainId);
853
+ await this.resolveWithdrawnAmounts(data, validChainId, state.walletAddress);
763
854
  return {
764
- data: mapEntries(pageData, validChainId),
855
+ data,
765
856
  hasMore,
766
857
  nextCursor
767
858
  };
@@ -979,11 +1070,11 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
979
1070
 
980
1071
  // src/client.ts
981
1072
  import {
982
- createPublicClient,
1073
+ createPublicClient as createPublicClient2,
983
1074
  createWalletClient,
984
1075
  custom
985
1076
  } from "viem";
986
- import { base, arbitrum } from "viem/chains";
1077
+ import { base as base2, arbitrum as arbitrum2 } from "viem/chains";
987
1078
 
988
1079
  // src/lib/transfer-auth.ts
989
1080
  import { bytesToHex } from "viem";
@@ -1024,10 +1115,10 @@ function randomAuthNonce() {
1024
1115
  // src/lib/sponsor-client.ts
1025
1116
  var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
1026
1117
  async function postSponsorTransferAuth(input) {
1027
- const base2 = input.baseUrl ?? ROUTING_API_BASE_URL3;
1118
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
1028
1119
  let res;
1029
1120
  try {
1030
- res = await fetch(`${base2}/api/v1/sponsor/erc20-transfer-auth`, {
1121
+ res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
1031
1122
  method: "POST",
1032
1123
  headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey },
1033
1124
  body: JSON.stringify(input.body)
@@ -1130,9 +1221,9 @@ var SPONSORED_USDC_BY_CHAIN = {
1130
1221
  8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
1131
1222
  42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
1132
1223
  };
1133
- var VIEM_CHAIN = {
1134
- 8453: base,
1135
- 42161: arbitrum
1224
+ var VIEM_CHAIN2 = {
1225
+ 8453: base2,
1226
+ 42161: arbitrum2
1136
1227
  };
1137
1228
  var OwneySDK = class {
1138
1229
  agents = /* @__PURE__ */ new Map();
@@ -1245,13 +1336,13 @@ var OwneySDK = class {
1245
1336
  // Casts work around viem's chain-narrowed Client vs the generic
1246
1337
  // PublicClient/WalletClient param types — structurally identical at
1247
1338
  // runtime, but the two share a name TS treats as unrelated.
1248
- getPublicClient: (cid) => createPublicClient({
1249
- chain: VIEM_CHAIN[cid],
1339
+ getPublicClient: (cid) => createPublicClient2({
1340
+ chain: VIEM_CHAIN2[cid],
1250
1341
  transport: custom(provider)
1251
1342
  }),
1252
1343
  getWalletClient: (cid) => createWalletClient({
1253
1344
  account: owner,
1254
- chain: VIEM_CHAIN[cid],
1345
+ chain: VIEM_CHAIN2[cid],
1255
1346
  transport: custom(provider)
1256
1347
  })
1257
1348
  });
@@ -1410,7 +1501,7 @@ var OwneySDK = class {
1410
1501
  }
1411
1502
  const state = this.requireState();
1412
1503
  const chainId = this.requireChainId();
1413
- const effectiveCallback = depositCallback ?? (asset === "WETH" ? void 0 : this.getDefaultSponsoredCallback());
1504
+ const effectiveCallback = depositCallback ?? this.getDefaultSponsoredCallback();
1414
1505
  if (agentId) {
1415
1506
  if (this.isAgentDisabled(agentId)) {
1416
1507
  throw new OwneyError(
@@ -1425,13 +1516,7 @@ var OwneySDK = class {
1425
1516
  return withFailureReporting(
1426
1517
  this.apiKey,
1427
1518
  agent.id,
1428
- () => agent.deposit(
1429
- state,
1430
- chainId,
1431
- amount,
1432
- asset,
1433
- effectiveCallback
1434
- )
1519
+ () => agent.deposit(state, chainId, amount, effectiveCallback)
1435
1520
  );
1436
1521
  }
1437
1522
  const totalAmount = BigInt(amount);
@@ -1465,13 +1550,7 @@ var OwneySDK = class {
1465
1550
  agentResults[agent.id] = await withFailureReporting(
1466
1551
  this.apiKey,
1467
1552
  agent.id,
1468
- () => agent.deposit(
1469
- state,
1470
- chainId,
1471
- agentAmount,
1472
- asset,
1473
- effectiveCallback
1474
- )
1553
+ () => agent.deposit(state, chainId, agentAmount, effectiveCallback)
1475
1554
  );
1476
1555
  }
1477
1556
  return { agentResults };
@@ -2001,70 +2080,6 @@ var OwneySDK = class {
2001
2080
  agentApy: results
2002
2081
  };
2003
2082
  }
2004
- /**
2005
- * Get the current fund allocation percentages across agents.
2006
- * @returns Object with agent names as keys and allocation percentages as values
2007
- */
2008
- async getAgentAllocation() {
2009
- const state = this.requireState();
2010
- const chainId = this.requireChainId();
2011
- const activeAgents = this.getActiveAgents();
2012
- const balances = {};
2013
- const positionsByAgent = {};
2014
- let totalBalance = 0;
2015
- const entries = [...activeAgents.entries()];
2016
- const balanceResults = await Promise.allSettled(
2017
- entries.map(async ([id, agent]) => {
2018
- const b = await agent.getBalances(state, chainId);
2019
- return [id, Number(b.totalBalance), b.positions ?? []];
2020
- })
2021
- );
2022
- let successCount = 0;
2023
- const agentErrors = {};
2024
- for (let i = 0; i < balanceResults.length; i++) {
2025
- const settledResult = balanceResults[i];
2026
- const [agentId] = entries[i];
2027
- if (settledResult.status === "fulfilled") {
2028
- const [id, bal, agentPositions] = settledResult.value;
2029
- balances[id] = bal;
2030
- positionsByAgent[id] = agentPositions;
2031
- totalBalance += bal;
2032
- successCount += 1;
2033
- } else {
2034
- const reason = settledResult.reason;
2035
- agentErrors[agentId] = reason instanceof Error ? reason.message : String(reason);
2036
- console.error(`getAgentAllocation agent "${agentId}" failed:`, reason);
2037
- }
2038
- }
2039
- if (successCount === 0) {
2040
- throw new OwneyError(
2041
- "ALLOCATION_ALL_FAILED",
2042
- "Failed to fetch allocation: all agents failed.",
2043
- { agentErrors }
2044
- );
2045
- }
2046
- const allocation = {};
2047
- if (totalBalance === 0) {
2048
- for (const id of activeAgents.keys()) {
2049
- allocation[id] = 0;
2050
- }
2051
- } else {
2052
- for (const id of activeAgents.keys()) {
2053
- allocation[id] = balances[id] > 0 ? Math.max(1, Math.floor(balances[id] / totalBalance * 100)) : 0;
2054
- }
2055
- const remainder = 100 - Object.values(allocation).reduce((a, b) => a + b, 0);
2056
- if (remainder > 0) {
2057
- const largestId = [...activeAgents.keys()].reduce(
2058
- (a, b) => balances[a] >= balances[b] ? a : b
2059
- );
2060
- allocation[largestId] += remainder;
2061
- }
2062
- }
2063
- return {
2064
- agentAllocation: allocation,
2065
- agentPositions: positionsByAgent
2066
- };
2067
- }
2068
2083
  /**
2069
2084
  * Allocation-weighted APY from the current portfolio: each pool's APY
2070
2085
  * weighted by the user's position value in it. More accurate per-user than
@@ -2282,9 +2297,9 @@ function buildSIWXConfig(deps) {
2282
2297
  }
2283
2298
  function createOwneySIWX(config) {
2284
2299
  const zyfai = new ZyfaiSDK2({ apiKey: config.apiKey });
2285
- const http = zyfai.httpClient;
2300
+ const http2 = zyfai.httpClient;
2286
2301
  return buildSIWXConfig({
2287
- post: (url, data) => http.post(url, data),
2302
+ post: (url, data) => http2.post(url, data),
2288
2303
  referralSource: config.referralSource
2289
2304
  });
2290
2305
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.6.0-beta.1",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",