@owney/sdk 0.6.5-beta.0 → 0.6.5-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +217 -180
- package/dist/index.d.cts +25 -4
- package/dist/index.d.ts +25 -4
- package/dist/index.js +216 -179
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// src/agents/zyfai/zyfai.agent.ts
|
|
2
2
|
import { ZyfaiSDK } from "@zyfai/sdk";
|
|
3
3
|
import { createPublicClient, http } from "viem";
|
|
4
|
-
import { base, arbitrum } from "viem/chains";
|
|
4
|
+
import { base, arbitrum, mainnet } from "viem/chains";
|
|
5
5
|
|
|
6
6
|
// src/types/config.ts
|
|
7
7
|
var P_SUPPORTED_CHAINS = {
|
|
8
|
-
chainIds: [8453, 42161],
|
|
9
|
-
chains: ["BASE", "ARBITRUM"]
|
|
8
|
+
chainIds: [8453, 42161, 1],
|
|
9
|
+
chains: ["BASE", "ARBITRUM", "ETHEREUM"]
|
|
10
10
|
};
|
|
11
11
|
var SUPPORTED_TOKENS = ["USDC", "USDT", "WETH"];
|
|
12
12
|
var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
|
|
@@ -41,6 +41,12 @@ var SupportedAssets = [
|
|
|
41
41
|
symbol: "WETH",
|
|
42
42
|
chainId: 42161,
|
|
43
43
|
decimals: 18
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
address: `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`,
|
|
47
|
+
symbol: "USDC",
|
|
48
|
+
chainId: 1,
|
|
49
|
+
decimals: 6
|
|
44
50
|
}
|
|
45
51
|
];
|
|
46
52
|
|
|
@@ -107,8 +113,7 @@ var isValidChainId = (chainId) => {
|
|
|
107
113
|
function hexToDecimal(hex, decimals = 6) {
|
|
108
114
|
const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
|
|
109
115
|
const parsed = BigInt(normalized);
|
|
110
|
-
if (decimals <= 0)
|
|
111
|
-
return Number(parsed);
|
|
116
|
+
if (decimals <= 0) return Number(parsed);
|
|
112
117
|
const divisor = BigInt(10 ** decimals);
|
|
113
118
|
const whole = parsed / divisor;
|
|
114
119
|
const remainder = parsed % divisor;
|
|
@@ -121,6 +126,20 @@ var DayFilterMapping = {
|
|
|
121
126
|
};
|
|
122
127
|
|
|
123
128
|
// src/agents/zyfai/zyfai.mapper.ts
|
|
129
|
+
var DECIMALS_BY_SYMBOL = {
|
|
130
|
+
usdc: 6,
|
|
131
|
+
usdt: 6,
|
|
132
|
+
weth: 18,
|
|
133
|
+
eth: 18,
|
|
134
|
+
cbeth: 18,
|
|
135
|
+
wbtc: 8,
|
|
136
|
+
cbbtc: 8
|
|
137
|
+
};
|
|
138
|
+
function tokenDecimals(symbol, explicit) {
|
|
139
|
+
if (typeof explicit === "number" && Number.isFinite(explicit))
|
|
140
|
+
return explicit;
|
|
141
|
+
return DECIMALS_BY_SYMBOL[(symbol ?? "").toLowerCase()] ?? 6;
|
|
142
|
+
}
|
|
124
143
|
function mapDeposit(raw) {
|
|
125
144
|
return {
|
|
126
145
|
txHash: raw.txHash,
|
|
@@ -137,7 +156,8 @@ function mapWithdraw(raw) {
|
|
|
137
156
|
}
|
|
138
157
|
var CHAIN_ID_TO_NAME = {
|
|
139
158
|
8453: "BASE",
|
|
140
|
-
42161: "ARBITRUM"
|
|
159
|
+
42161: "ARBITRUM",
|
|
160
|
+
1: "ETHEREUM"
|
|
141
161
|
};
|
|
142
162
|
var NAME_TO_CHAIN_ID = Object.entries(
|
|
143
163
|
CHAIN_ID_TO_NAME
|
|
@@ -147,8 +167,7 @@ var NAME_TO_CHAIN_ID = Object.entries(
|
|
|
147
167
|
}, {});
|
|
148
168
|
function resolveChainId(chain) {
|
|
149
169
|
const asNum = Number(chain);
|
|
150
|
-
if (Number.isFinite(asNum) && asNum > 0)
|
|
151
|
-
return asNum;
|
|
170
|
+
if (Number.isFinite(asNum) && asNum > 0) return asNum;
|
|
152
171
|
return NAME_TO_CHAIN_ID[chain.trim().toLowerCase()] ?? NaN;
|
|
153
172
|
}
|
|
154
173
|
function mapBalances(raw, _chainId, smartWallet) {
|
|
@@ -178,9 +197,16 @@ function mapBalances(raw, _chainId, smartWallet) {
|
|
|
178
197
|
pool: p.pool,
|
|
179
198
|
asset: p.token_symbol ?? "",
|
|
180
199
|
// Position amount is hex-encoded base units (like the token balances
|
|
181
|
-
// above).
|
|
182
|
-
//
|
|
183
|
-
|
|
200
|
+
// above). `PositionSlot` doesn't type a `decimals` field, but runtime
|
|
201
|
+
// getBalances payloads often carry one (e.g. 18 for WETH) — prefer that
|
|
202
|
+
// when present, otherwise fall back to the per-symbol lookup so
|
|
203
|
+
// non-6-decimal assets like WETH don't render 1e12 too large.
|
|
204
|
+
amount: String(
|
|
205
|
+
hexToDecimal(
|
|
206
|
+
p.amount || "0",
|
|
207
|
+
tokenDecimals(p.token_symbol, p.decimals)
|
|
208
|
+
)
|
|
209
|
+
),
|
|
184
210
|
apy: p.pool_apy,
|
|
185
211
|
tvl: p.pool_tvl,
|
|
186
212
|
// PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
|
|
@@ -225,41 +251,39 @@ function mapEarnings(raw, smartWallet) {
|
|
|
225
251
|
};
|
|
226
252
|
}
|
|
227
253
|
function mapWeightedApyByChain(raw) {
|
|
228
|
-
if (!raw)
|
|
229
|
-
return void 0;
|
|
254
|
+
if (!raw) return void 0;
|
|
230
255
|
const out = {};
|
|
231
256
|
for (const [chainKey, tokenApy] of Object.entries(raw)) {
|
|
232
257
|
const chainId = Number(chainKey);
|
|
233
|
-
if (!SUPPORTED_CHAIN_IDS.includes(chainId))
|
|
234
|
-
continue;
|
|
258
|
+
if (!SUPPORTED_CHAIN_IDS.includes(chainId)) continue;
|
|
235
259
|
const perAsset = {};
|
|
236
260
|
for (const [symbol, apy] of Object.entries(tokenApy)) {
|
|
237
261
|
const token = symbol;
|
|
238
|
-
if (!SUPPORTED_TOKENS.includes(token))
|
|
239
|
-
continue;
|
|
262
|
+
if (!SUPPORTED_TOKENS.includes(token)) continue;
|
|
240
263
|
perAsset[token] = apy;
|
|
241
264
|
}
|
|
242
|
-
if (Object.keys(perAsset).length > 0)
|
|
243
|
-
out[chainId] = perAsset;
|
|
265
|
+
if (Object.keys(perAsset).length > 0) out[chainId] = perAsset;
|
|
244
266
|
}
|
|
245
267
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
246
268
|
}
|
|
247
|
-
function rawPoolApyForChain(entry, chainId) {
|
|
269
|
+
function rawPoolApyForChain(entry, chainId, tokenSymbol) {
|
|
248
270
|
let weightedSum = 0;
|
|
249
271
|
let totalBalance = 0;
|
|
250
272
|
for (const p of entry.positions ?? []) {
|
|
251
|
-
if (p.chainId !== chainId)
|
|
252
|
-
|
|
273
|
+
if (p.chainId !== chainId) continue;
|
|
274
|
+
if (tokenSymbol && p.tokenSymbol !== tokenSymbol) continue;
|
|
253
275
|
const balance = p.balance ?? 0;
|
|
254
|
-
if (balance <= 0 || typeof p.apy !== "number")
|
|
255
|
-
continue;
|
|
276
|
+
if (balance <= 0 || typeof p.apy !== "number") continue;
|
|
256
277
|
weightedSum += p.apy * balance;
|
|
257
278
|
totalBalance += balance;
|
|
258
279
|
}
|
|
259
280
|
return totalBalance > 0 ? weightedSum / totalBalance : null;
|
|
260
281
|
}
|
|
261
|
-
function mapApyHistory(raw, chainId) {
|
|
262
|
-
const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({
|
|
282
|
+
function mapApyHistory(raw, chainId, tokenSymbol) {
|
|
283
|
+
const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({
|
|
284
|
+
date,
|
|
285
|
+
apy: rawPoolApyForChain(entry, chainId, tokenSymbol)
|
|
286
|
+
})).filter((p) => p.apy !== null).sort((a, b) => a.date.localeCompare(b.date));
|
|
263
287
|
return {
|
|
264
288
|
walletAddress: raw.walletAddress,
|
|
265
289
|
weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0,
|
|
@@ -282,6 +306,7 @@ function mapEntries(rawEntries, chainId) {
|
|
|
282
306
|
"Withdraw from protocol": "Withdraw",
|
|
283
307
|
Rebalance: "Rebalance"
|
|
284
308
|
};
|
|
309
|
+
void chainId;
|
|
285
310
|
return rawEntries.map((entry) => {
|
|
286
311
|
const rawLog = entry.rebalanceLog;
|
|
287
312
|
const positions = entry.positions ?? [];
|
|
@@ -303,7 +328,15 @@ function mapEntries(rawEntries, chainId) {
|
|
|
303
328
|
fromPool: from.pool,
|
|
304
329
|
toPool: to.pool,
|
|
305
330
|
tokenSymbol: matched?.token_symbol ?? "",
|
|
306
|
-
amount: matched ? String(
|
|
331
|
+
amount: matched ? String(
|
|
332
|
+
hexToDecimal(
|
|
333
|
+
matched.amount || "0x",
|
|
334
|
+
tokenDecimals(
|
|
335
|
+
matched.token_symbol,
|
|
336
|
+
matched.decimals
|
|
337
|
+
)
|
|
338
|
+
)
|
|
339
|
+
) : "",
|
|
307
340
|
status: "success"
|
|
308
341
|
}
|
|
309
342
|
];
|
|
@@ -322,7 +355,12 @@ function mapEntries(rawEntries, chainId) {
|
|
|
322
355
|
txHashes: entry.transactionHash ? [entry.transactionHash] : [],
|
|
323
356
|
chainId: entry.chainId,
|
|
324
357
|
tokenSymbol: entry?.positions?.[0]?.token_symbol,
|
|
325
|
-
amount: hasAmount ? String(
|
|
358
|
+
amount: hasAmount ? String(
|
|
359
|
+
hexToDecimal(
|
|
360
|
+
rawAmount,
|
|
361
|
+
tokenDecimals(entry?.positions?.[0]?.token_symbol)
|
|
362
|
+
)
|
|
363
|
+
) : void 0
|
|
326
364
|
}
|
|
327
365
|
],
|
|
328
366
|
rebalanceLog
|
|
@@ -347,8 +385,7 @@ function mapApyByStrategy(raw) {
|
|
|
347
385
|
const supported = SupportedAssets.find(
|
|
348
386
|
(asset) => asset.chainId === entry.chain_id && asset.symbol === entry.token_symbol
|
|
349
387
|
);
|
|
350
|
-
if (!supported)
|
|
351
|
-
continue;
|
|
388
|
+
if (!supported) continue;
|
|
352
389
|
const chainKey = supported.chainId;
|
|
353
390
|
const symbolKey = supported.symbol;
|
|
354
391
|
const bucket = apyPerAsset[chainKey] ?? {};
|
|
@@ -378,10 +415,8 @@ function computeAllocationApy(positions) {
|
|
|
378
415
|
totalValue += value;
|
|
379
416
|
const chainId = resolveChainId(p.chain);
|
|
380
417
|
const token = p.asset;
|
|
381
|
-
if (!SUPPORTED_CHAIN_IDS.includes(chainId))
|
|
382
|
-
|
|
383
|
-
if (!SUPPORTED_TOKENS.includes(token))
|
|
384
|
-
continue;
|
|
418
|
+
if (!SUPPORTED_CHAIN_IDS.includes(chainId)) continue;
|
|
419
|
+
if (!SUPPORTED_TOKENS.includes(token)) continue;
|
|
385
420
|
const perAsset = buckets[chainId] ?? {};
|
|
386
421
|
const cell = perAsset[token] ?? { weightedSum: 0, value: 0 };
|
|
387
422
|
cell.weightedSum += apy * value;
|
|
@@ -398,8 +433,7 @@ function computeAllocationApy(positions) {
|
|
|
398
433
|
out[token] = cell.weightedSum / cell.value;
|
|
399
434
|
}
|
|
400
435
|
}
|
|
401
|
-
if (Object.keys(out).length > 0)
|
|
402
|
-
apyByChainAndAsset[chainId] = out;
|
|
436
|
+
if (Object.keys(out).length > 0) apyByChainAndAsset[chainId] = out;
|
|
403
437
|
}
|
|
404
438
|
const totalApy = totalValue > 0 ? String(weightedSum / totalValue) : "0";
|
|
405
439
|
return { totalApy, apyByChainAndAsset };
|
|
@@ -416,19 +450,14 @@ function extractWithdrawnAmount(logs, recipient, token, decimals) {
|
|
|
416
450
|
let total = 0n;
|
|
417
451
|
let matched = false;
|
|
418
452
|
for (const log of logs) {
|
|
419
|
-
if (log.address.toLowerCase() !== wantToken)
|
|
420
|
-
|
|
421
|
-
if ((log.topics[
|
|
422
|
-
|
|
423
|
-
if (topicToAddress(log.topics[2]) !== wantRecipient)
|
|
424
|
-
continue;
|
|
425
|
-
if (!log.data || log.data === "0x")
|
|
426
|
-
continue;
|
|
453
|
+
if (log.address.toLowerCase() !== wantToken) continue;
|
|
454
|
+
if ((log.topics[0] ?? "").toLowerCase() !== TRANSFER_TOPIC) continue;
|
|
455
|
+
if (topicToAddress(log.topics[2]) !== wantRecipient) continue;
|
|
456
|
+
if (!log.data || log.data === "0x") continue;
|
|
427
457
|
total += BigInt(log.data);
|
|
428
458
|
matched = true;
|
|
429
459
|
}
|
|
430
|
-
if (!matched)
|
|
431
|
-
return void 0;
|
|
460
|
+
if (!matched) return void 0;
|
|
432
461
|
return String(hexToDecimal(`0x${total.toString(16)}`, decimals));
|
|
433
462
|
}
|
|
434
463
|
|
|
@@ -444,8 +473,7 @@ function encodeHistoryCursor(payload) {
|
|
|
444
473
|
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64");
|
|
445
474
|
}
|
|
446
475
|
function decodeHistoryCursor(token) {
|
|
447
|
-
if (!token)
|
|
448
|
-
throw new InvalidHistoryCursorError("Cursor is empty.");
|
|
476
|
+
if (!token) throw new InvalidHistoryCursorError("Cursor is empty.");
|
|
449
477
|
let parsed;
|
|
450
478
|
try {
|
|
451
479
|
const json = Buffer.from(token, "base64").toString("utf8");
|
|
@@ -462,8 +490,7 @@ function decodeHistoryCursor(token) {
|
|
|
462
490
|
// src/agents/zyfai/zyfai.auth-cache.ts
|
|
463
491
|
var KEY_PREFIX = "owney.zyfai.session";
|
|
464
492
|
var storage = () => {
|
|
465
|
-
if (typeof window === "undefined")
|
|
466
|
-
return null;
|
|
493
|
+
if (typeof window === "undefined") return null;
|
|
467
494
|
try {
|
|
468
495
|
return window.localStorage;
|
|
469
496
|
} catch {
|
|
@@ -473,15 +500,13 @@ var storage = () => {
|
|
|
473
500
|
var buildKey = (address, chainId) => `${KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
|
|
474
501
|
var isJwtExpired = (token) => {
|
|
475
502
|
const parts = token.split(".");
|
|
476
|
-
if (parts.length !== 3)
|
|
477
|
-
return false;
|
|
503
|
+
if (parts.length !== 3) return false;
|
|
478
504
|
try {
|
|
479
505
|
const payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
480
506
|
const padded = payload + "=".repeat((4 - payload.length % 4) % 4);
|
|
481
507
|
const decoded = typeof atob === "function" ? atob(padded) : Buffer.from(padded, "base64").toString("utf8");
|
|
482
508
|
const claims = JSON.parse(decoded);
|
|
483
|
-
if (typeof claims.exp !== "number")
|
|
484
|
-
return false;
|
|
509
|
+
if (typeof claims.exp !== "number") return false;
|
|
485
510
|
return Date.now() / 1e3 >= claims.exp - 30;
|
|
486
511
|
} catch {
|
|
487
512
|
return false;
|
|
@@ -489,11 +514,9 @@ var isJwtExpired = (token) => {
|
|
|
489
514
|
};
|
|
490
515
|
var readSession = (address, chainId) => {
|
|
491
516
|
const store = storage();
|
|
492
|
-
if (!store)
|
|
493
|
-
return null;
|
|
517
|
+
if (!store) return null;
|
|
494
518
|
const raw = store.getItem(buildKey(address, chainId));
|
|
495
|
-
if (!raw)
|
|
496
|
-
return null;
|
|
519
|
+
if (!raw) return null;
|
|
497
520
|
try {
|
|
498
521
|
const parsed = JSON.parse(raw);
|
|
499
522
|
if (!parsed.token || isJwtExpired(parsed.token)) {
|
|
@@ -508,8 +531,7 @@ var readSession = (address, chainId) => {
|
|
|
508
531
|
};
|
|
509
532
|
var writeSession = (address, chainId, session) => {
|
|
510
533
|
const store = storage();
|
|
511
|
-
if (!store)
|
|
512
|
-
return;
|
|
534
|
+
if (!store) return;
|
|
513
535
|
try {
|
|
514
536
|
store.setItem(buildKey(address, chainId), JSON.stringify(session));
|
|
515
537
|
} catch {
|
|
@@ -517,8 +539,7 @@ var writeSession = (address, chainId, session) => {
|
|
|
517
539
|
};
|
|
518
540
|
var clearSession = (address, chainId) => {
|
|
519
541
|
const store = storage();
|
|
520
|
-
if (!store)
|
|
521
|
-
return;
|
|
542
|
+
if (!store) return;
|
|
522
543
|
try {
|
|
523
544
|
store.removeItem(buildKey(address, chainId));
|
|
524
545
|
} catch {
|
|
@@ -527,8 +548,7 @@ var clearSession = (address, chainId) => {
|
|
|
527
548
|
|
|
528
549
|
// src/agents/zyfai/autoSelect.ts
|
|
529
550
|
function buildAutoSelectUpdate(current, asset) {
|
|
530
|
-
if (current.autoSelectProtocols === true)
|
|
531
|
-
return null;
|
|
551
|
+
if (current.autoSelectProtocols === true) return null;
|
|
532
552
|
return {
|
|
533
553
|
asset,
|
|
534
554
|
autoSelectProtocols: true,
|
|
@@ -539,16 +559,18 @@ function buildAutoSelectUpdate(current, asset) {
|
|
|
539
559
|
// src/agents/zyfai/zyfai.agent.ts
|
|
540
560
|
var DEFAULT_ZYFAI_RPC_URLS = {
|
|
541
561
|
8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
542
|
-
42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
|
|
562
|
+
42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
563
|
+
1: "https://eth-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
|
|
543
564
|
};
|
|
544
565
|
var WETH_ADDRESS_BY_CHAIN = {
|
|
545
566
|
8453: "0x4200000000000000000000000000000000000006",
|
|
546
|
-
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
|
|
567
|
+
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
568
|
+
1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
|
547
569
|
};
|
|
548
|
-
var VIEM_CHAIN = { 8453: base, 42161: arbitrum };
|
|
570
|
+
var VIEM_CHAIN = { 8453: base, 42161: arbitrum, 1: mainnet };
|
|
549
571
|
var ZyfaiAgent = class {
|
|
550
572
|
id = "zyfai";
|
|
551
|
-
supportedChainIds = [8453, 42161];
|
|
573
|
+
supportedChainIds = [8453, 42161, 1];
|
|
552
574
|
supportedAssets = [
|
|
553
575
|
{
|
|
554
576
|
chainId: 8453,
|
|
@@ -565,6 +587,13 @@ var ZyfaiAgent = class {
|
|
|
565
587
|
{ symbol: "USDC", minDepositAmount: "1500000" },
|
|
566
588
|
{ symbol: "WETH", minDepositAmount: "500000000000000" }
|
|
567
589
|
]
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
chainId: 1,
|
|
593
|
+
chain: "ETHEREUM",
|
|
594
|
+
// Zyfai enforces a 10,000 USDC minimum portfolio on Ethereum mainnet
|
|
595
|
+
// (mainnet gas only pays off on large positions). 10_000 * 1e6 raw units.
|
|
596
|
+
assets: [{ symbol: "USDC", minDepositAmount: "10000000000" }]
|
|
568
597
|
}
|
|
569
598
|
];
|
|
570
599
|
sdk;
|
|
@@ -588,8 +617,7 @@ var ZyfaiAgent = class {
|
|
|
588
617
|
}
|
|
589
618
|
getPublicClient(chainId) {
|
|
590
619
|
const cached = this.publicClients.get(chainId);
|
|
591
|
-
if (cached)
|
|
592
|
-
return cached;
|
|
620
|
+
if (cached) return cached;
|
|
593
621
|
const client = createPublicClient({
|
|
594
622
|
chain: VIEM_CHAIN[chainId],
|
|
595
623
|
transport: http(this.rpcUrls[chainId])
|
|
@@ -599,33 +627,43 @@ var ZyfaiAgent = class {
|
|
|
599
627
|
}
|
|
600
628
|
/**
|
|
601
629
|
* Fills in the true withdrawn amount for `Withdraw` entries by decoding the
|
|
602
|
-
*
|
|
630
|
+
* on-chain `Transfer` that lands in the user's wallet. The Zyfai history
|
|
603
631
|
* payload only reports the *remaining* position for a partial withdraw (see
|
|
604
632
|
* the note in `mapEntries`), so without this the UI shows the leftover
|
|
605
633
|
* balance instead of the amount withdrawn.
|
|
606
634
|
*
|
|
635
|
+
* The withdrawn asset varies per entry (USDC or WETH), so it's resolved
|
|
636
|
+
* from `tx.tokenSymbol` (set by `mapEntries` from the entry's own
|
|
637
|
+
* position) rather than assumed to always be USDC. Zyfai sometimes
|
|
638
|
+
* denominates WETH as lowercase "eth" — that's normalized to WETH.
|
|
639
|
+
* Entries with no symbol (older payload shapes) fall back to USDC to
|
|
640
|
+
* preserve prior behavior.
|
|
641
|
+
*
|
|
607
642
|
* Mutates `entries` in place. Runs all lookups concurrently and is tolerant
|
|
608
643
|
* of RPC failures: an entry whose amount can't be resolved keeps
|
|
609
644
|
* `amount: undefined`, which consumers render as a hidden/retryable row
|
|
610
645
|
* rather than a wrong number.
|
|
611
646
|
*/
|
|
612
647
|
async resolveWithdrawnAmounts(entries, chainId, recipient) {
|
|
613
|
-
const asset = SupportedAssets.find(
|
|
614
|
-
(a) => a.chainId === chainId && a.symbol === "USDC"
|
|
615
|
-
);
|
|
616
|
-
if (!asset)
|
|
617
|
-
return;
|
|
618
648
|
const withdrawals = entries.filter(
|
|
619
649
|
(e) => e.action === "Withdraw" && e.transactions[0]?.txHashes[0]
|
|
620
650
|
);
|
|
621
|
-
if (withdrawals.length === 0)
|
|
622
|
-
return;
|
|
651
|
+
if (withdrawals.length === 0) return;
|
|
623
652
|
const client = this.getPublicClient(chainId);
|
|
624
653
|
await Promise.all(
|
|
625
654
|
withdrawals.map(async (entry) => {
|
|
626
655
|
const tx = entry.transactions[0];
|
|
627
656
|
const txHash = tx.txHashes[0];
|
|
628
|
-
const
|
|
657
|
+
const rawSymbol = tx.tokenSymbol;
|
|
658
|
+
const normalizedSymbol = rawSymbol ? rawSymbol.toLowerCase() === "eth" ? "WETH" : rawSymbol.toUpperCase() : "USDC";
|
|
659
|
+
const asset = SupportedAssets.find(
|
|
660
|
+
(a) => a.chainId === chainId && a.symbol === normalizedSymbol
|
|
661
|
+
) ?? SupportedAssets.find(
|
|
662
|
+
(a) => a.chainId === chainId && a.symbol === "USDC"
|
|
663
|
+
);
|
|
664
|
+
if (!asset) return;
|
|
665
|
+
const cacheKey = `${txHash}:${asset.address}`;
|
|
666
|
+
const cached = this.withdrawAmountCache.get(cacheKey);
|
|
629
667
|
if (cached !== void 0) {
|
|
630
668
|
tx.amount = cached;
|
|
631
669
|
return;
|
|
@@ -641,7 +679,7 @@ var ZyfaiAgent = class {
|
|
|
641
679
|
asset.decimals
|
|
642
680
|
);
|
|
643
681
|
if (amount !== void 0) {
|
|
644
|
-
this.withdrawAmountCache.set(
|
|
682
|
+
this.withdrawAmountCache.set(cacheKey, amount);
|
|
645
683
|
tx.amount = amount;
|
|
646
684
|
}
|
|
647
685
|
} catch {
|
|
@@ -660,13 +698,11 @@ var ZyfaiAgent = class {
|
|
|
660
698
|
* for some apps and the patch only matters in the browser anyway.
|
|
661
699
|
*/
|
|
662
700
|
installAuthCache() {
|
|
663
|
-
if (typeof window === "undefined")
|
|
664
|
-
return;
|
|
701
|
+
if (typeof window === "undefined") return;
|
|
665
702
|
const internals = this.sdk;
|
|
666
703
|
const original = internals.authenticateUser.bind(internals);
|
|
667
704
|
internals.authenticateUser = async () => {
|
|
668
|
-
if (internals.authenticatedUserId !== null)
|
|
669
|
-
return;
|
|
705
|
+
if (internals.authenticatedUserId !== null) return;
|
|
670
706
|
const address = internals.walletClient?.account?.address;
|
|
671
707
|
const chainId = internals.currentChainId;
|
|
672
708
|
if (address && chainId) {
|
|
@@ -741,12 +777,10 @@ var ZyfaiAgent = class {
|
|
|
741
777
|
return await this.sdk.connectAccount(provider, chainId);
|
|
742
778
|
} catch (error) {
|
|
743
779
|
const message = error instanceof Error ? error.message : String(error);
|
|
744
|
-
if (!message.toLowerCase().includes("unauthorized"))
|
|
745
|
-
throw error;
|
|
780
|
+
if (!message.toLowerCase().includes("unauthorized")) throw error;
|
|
746
781
|
const internals = this.sdk;
|
|
747
782
|
const address = internals.walletClient?.account?.address;
|
|
748
|
-
if (address)
|
|
749
|
-
clearSession(address, chainId);
|
|
783
|
+
if (address) clearSession(address, chainId);
|
|
750
784
|
return await this.sdk.connectAccount(provider, chainId);
|
|
751
785
|
}
|
|
752
786
|
}
|
|
@@ -876,10 +910,10 @@ var ZyfaiAgent = class {
|
|
|
876
910
|
const raw = await this.sdk.getOnchainEarnings(smartWallet);
|
|
877
911
|
return mapEarnings(raw, smartWallet);
|
|
878
912
|
}
|
|
879
|
-
async getAccountApy(state, chainId, days) {
|
|
913
|
+
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
880
914
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
881
915
|
const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
|
|
882
|
-
return mapApyHistory(raw, chainId);
|
|
916
|
+
return mapApyHistory(raw, chainId, tokenSymbol);
|
|
883
917
|
}
|
|
884
918
|
async getHistory(state, chainId, options) {
|
|
885
919
|
const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
|
|
@@ -944,8 +978,7 @@ var ZyfaiAgent = class {
|
|
|
944
978
|
},
|
|
945
979
|
asset
|
|
946
980
|
);
|
|
947
|
-
if (!update)
|
|
948
|
-
return false;
|
|
981
|
+
if (!update) return false;
|
|
949
982
|
await this.sdk.updateUserProfile(update);
|
|
950
983
|
return true;
|
|
951
984
|
}
|
|
@@ -1034,8 +1067,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
1034
1067
|
const tokenBalance = agentBalance?.tokens.find(
|
|
1035
1068
|
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
1036
1069
|
);
|
|
1037
|
-
if (!tokenBalance)
|
|
1038
|
-
return { agent, balance: 0n };
|
|
1070
|
+
if (!tokenBalance) return { agent, balance: 0n };
|
|
1039
1071
|
return { agent, balance: parseUnits(tokenBalance.amount, decimals) };
|
|
1040
1072
|
});
|
|
1041
1073
|
}
|
|
@@ -1052,11 +1084,9 @@ function planProportionalShares(balances, requested, totalAvailable) {
|
|
|
1052
1084
|
return diff > 0n ? 1 : diff < 0n ? -1 : 0;
|
|
1053
1085
|
});
|
|
1054
1086
|
for (const p of byHeadroom) {
|
|
1055
|
-
if (remainder === 0n)
|
|
1056
|
-
break;
|
|
1087
|
+
if (remainder === 0n) break;
|
|
1057
1088
|
const headroom = p.balance - p.planned;
|
|
1058
|
-
if (headroom <= 0n)
|
|
1059
|
-
continue;
|
|
1089
|
+
if (headroom <= 0n) continue;
|
|
1060
1090
|
const take = headroom < remainder ? headroom : remainder;
|
|
1061
1091
|
p.planned += take;
|
|
1062
1092
|
remainder -= take;
|
|
@@ -1085,8 +1115,7 @@ function redistributeShare(plans, fromIndex, amount, candidatePool) {
|
|
|
1085
1115
|
(s, c) => s + (c.balance - c.planned),
|
|
1086
1116
|
0n
|
|
1087
1117
|
);
|
|
1088
|
-
if (totalHeadroom === 0n)
|
|
1089
|
-
return;
|
|
1118
|
+
if (totalHeadroom === 0n) return;
|
|
1090
1119
|
let distributed = 0n;
|
|
1091
1120
|
for (const c of candidates) {
|
|
1092
1121
|
const headroom = c.balance - c.planned;
|
|
@@ -1097,11 +1126,9 @@ function redistributeShare(plans, fromIndex, amount, candidatePool) {
|
|
|
1097
1126
|
}
|
|
1098
1127
|
let leftover = amount - distributed;
|
|
1099
1128
|
for (const c of candidates) {
|
|
1100
|
-
if (leftover === 0n)
|
|
1101
|
-
break;
|
|
1129
|
+
if (leftover === 0n) break;
|
|
1102
1130
|
const headroom = c.balance - c.planned;
|
|
1103
|
-
if (headroom <= 0n)
|
|
1104
|
-
continue;
|
|
1131
|
+
if (headroom <= 0n) continue;
|
|
1105
1132
|
const take = headroom < leftover ? headroom : leftover;
|
|
1106
1133
|
c.planned += take;
|
|
1107
1134
|
leftover -= take;
|
|
@@ -1118,16 +1145,13 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
1118
1145
|
for (const id of Object.keys(agentApys)) {
|
|
1119
1146
|
const cells = agentApys[id].apyByChainAndAsset;
|
|
1120
1147
|
const balance = agentBalances[id] ?? 0;
|
|
1121
|
-
if (!cells || balance <= 0)
|
|
1122
|
-
continue;
|
|
1148
|
+
if (!cells || balance <= 0) continue;
|
|
1123
1149
|
for (const [chainKey, perAsset] of Object.entries(cells)) {
|
|
1124
|
-
if (!perAsset)
|
|
1125
|
-
continue;
|
|
1150
|
+
if (!perAsset) continue;
|
|
1126
1151
|
const chainId = Number(chainKey);
|
|
1127
1152
|
for (const [asset, apyValue] of Object.entries(perAsset)) {
|
|
1128
1153
|
const apy = Number(apyValue ?? 0);
|
|
1129
|
-
if (apy === 0)
|
|
1130
|
-
continue;
|
|
1154
|
+
if (apy === 0) continue;
|
|
1131
1155
|
sums[chainId] ??= {};
|
|
1132
1156
|
weights[chainId] ??= {};
|
|
1133
1157
|
sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
|
|
@@ -1141,8 +1165,7 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
1141
1165
|
const perAssetOut = {};
|
|
1142
1166
|
for (const asset of Object.keys(sums[chainId])) {
|
|
1143
1167
|
const w = weights[chainId][asset];
|
|
1144
|
-
if (w > 0)
|
|
1145
|
-
perAssetOut[asset] = sums[chainId][asset] / w;
|
|
1168
|
+
if (w > 0) perAssetOut[asset] = sums[chainId][asset] / w;
|
|
1146
1169
|
}
|
|
1147
1170
|
if (Object.keys(perAssetOut).length > 0) {
|
|
1148
1171
|
out[chainId] = perAssetOut;
|
|
@@ -1157,7 +1180,7 @@ import {
|
|
|
1157
1180
|
createWalletClient,
|
|
1158
1181
|
custom
|
|
1159
1182
|
} from "viem";
|
|
1160
|
-
import { base as base2, arbitrum as arbitrum2 } from "viem/chains";
|
|
1183
|
+
import { base as base2, arbitrum as arbitrum2, mainnet as mainnet2 } from "viem/chains";
|
|
1161
1184
|
|
|
1162
1185
|
// src/lib/transfer-auth.ts
|
|
1163
1186
|
import { bytesToHex } from "viem";
|
|
@@ -1203,7 +1226,10 @@ async function postSponsorTransferAuth(input) {
|
|
|
1203
1226
|
try {
|
|
1204
1227
|
res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
|
|
1205
1228
|
method: "POST",
|
|
1206
|
-
headers: {
|
|
1229
|
+
headers: {
|
|
1230
|
+
"content-type": "application/json",
|
|
1231
|
+
"x-owney-api-key": input.apiKey
|
|
1232
|
+
},
|
|
1207
1233
|
body: JSON.stringify(input.body)
|
|
1208
1234
|
});
|
|
1209
1235
|
} catch (networkError) {
|
|
@@ -1223,7 +1249,13 @@ async function postSponsorTransferAuth(input) {
|
|
|
1223
1249
|
throw new OwneyError(
|
|
1224
1250
|
"SPONSOR_REQUEST_FAILED",
|
|
1225
1251
|
`Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
|
|
1226
|
-
{
|
|
1252
|
+
{
|
|
1253
|
+
statusCode: res.status,
|
|
1254
|
+
responseBody: text.slice(0, 500),
|
|
1255
|
+
// 503 SPONSOR_UNAVAILABLE = relayer out of gas; the tx was rejected
|
|
1256
|
+
// before broadcast, so it is safe to fall back to a user-paid deposit.
|
|
1257
|
+
safeToFallback: res.status === 503
|
|
1258
|
+
}
|
|
1227
1259
|
);
|
|
1228
1260
|
}
|
|
1229
1261
|
return parsed.data;
|
|
@@ -1234,7 +1266,10 @@ async function postSponsorPermit2Transfer(input) {
|
|
|
1234
1266
|
try {
|
|
1235
1267
|
res = await fetch(`${base3}/api/v1/sponsor/permit2-transfer`, {
|
|
1236
1268
|
method: "POST",
|
|
1237
|
-
headers: {
|
|
1269
|
+
headers: {
|
|
1270
|
+
"content-type": "application/json",
|
|
1271
|
+
"x-owney-api-key": input.apiKey
|
|
1272
|
+
},
|
|
1238
1273
|
body: JSON.stringify(input.body)
|
|
1239
1274
|
});
|
|
1240
1275
|
} catch (networkError) {
|
|
@@ -1257,7 +1292,7 @@ async function postSponsorPermit2Transfer(input) {
|
|
|
1257
1292
|
{
|
|
1258
1293
|
statusCode: res.status,
|
|
1259
1294
|
responseBody: text.slice(0, 500),
|
|
1260
|
-
safeToFallback: res.status >= 400 && res.status < 500
|
|
1295
|
+
safeToFallback: res.status >= 400 && res.status < 500 || res.status === 503
|
|
1261
1296
|
}
|
|
1262
1297
|
);
|
|
1263
1298
|
}
|
|
@@ -1267,9 +1302,12 @@ async function getSponsorRelayerAddress(input) {
|
|
|
1267
1302
|
const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
1268
1303
|
let res;
|
|
1269
1304
|
try {
|
|
1270
|
-
res = await fetch(
|
|
1271
|
-
|
|
1272
|
-
|
|
1305
|
+
res = await fetch(
|
|
1306
|
+
`${base3}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
|
|
1307
|
+
{
|
|
1308
|
+
headers: { "x-owney-api-key": input.apiKey }
|
|
1309
|
+
}
|
|
1310
|
+
);
|
|
1273
1311
|
} catch (networkError) {
|
|
1274
1312
|
throw new OwneyError(
|
|
1275
1313
|
"SPONSOR_REQUEST_FAILED",
|
|
@@ -1287,7 +1325,11 @@ async function getSponsorRelayerAddress(input) {
|
|
|
1287
1325
|
throw new OwneyError(
|
|
1288
1326
|
"SPONSOR_REQUEST_FAILED",
|
|
1289
1327
|
`Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
|
|
1290
|
-
{
|
|
1328
|
+
{
|
|
1329
|
+
statusCode: res.status,
|
|
1330
|
+
responseBody: text.slice(0, 500),
|
|
1331
|
+
safeToFallback: true
|
|
1332
|
+
}
|
|
1291
1333
|
);
|
|
1292
1334
|
}
|
|
1293
1335
|
return parsed.data.relayer;
|
|
@@ -1474,18 +1516,21 @@ function decodeMultiAgentCursor(token) {
|
|
|
1474
1516
|
}
|
|
1475
1517
|
var SPONSORED_USDC_BY_CHAIN = {
|
|
1476
1518
|
8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
1477
|
-
42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
|
|
1519
|
+
42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
|
|
1520
|
+
1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
|
1478
1521
|
};
|
|
1479
1522
|
var VIEM_CHAIN2 = {
|
|
1480
1523
|
8453: base2,
|
|
1481
|
-
42161: arbitrum2
|
|
1524
|
+
42161: arbitrum2,
|
|
1525
|
+
1: mainnet2
|
|
1482
1526
|
};
|
|
1483
1527
|
var SPONSORED_WETH_BY_CHAIN = {
|
|
1484
1528
|
8453: "0x4200000000000000000000000000000000000006",
|
|
1485
|
-
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
|
|
1529
|
+
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
1530
|
+
1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
|
1486
1531
|
};
|
|
1487
1532
|
function shouldFallbackToUserPaid(error, asset, appCallback) {
|
|
1488
|
-
return asset === "WETH" && appCallback === void 0 && error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED" && error.details?.safeToFallback === true;
|
|
1533
|
+
return (asset === "WETH" || asset === "USDC") && appCallback === void 0 && error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED" && error.details?.safeToFallback === true;
|
|
1489
1534
|
}
|
|
1490
1535
|
var OwneySDK = class {
|
|
1491
1536
|
agents = /* @__PURE__ */ new Map();
|
|
@@ -1499,12 +1544,14 @@ var OwneySDK = class {
|
|
|
1499
1544
|
state = null;
|
|
1500
1545
|
apiKey;
|
|
1501
1546
|
zyfaiRpcUrls;
|
|
1547
|
+
routingApiBaseUrl;
|
|
1502
1548
|
cachedSponsoredCallback = null;
|
|
1503
1549
|
cachedWethSponsoredCallback = null;
|
|
1504
1550
|
initializingAgentsPromise = null;
|
|
1505
1551
|
constructor(config) {
|
|
1506
1552
|
this.apiKey = config.apiKey;
|
|
1507
1553
|
this.zyfaiRpcUrls = config.zyfaiRpcUrls;
|
|
1554
|
+
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
1508
1555
|
}
|
|
1509
1556
|
/**
|
|
1510
1557
|
* Establish connection state for all subsequent SDK calls.
|
|
@@ -1559,8 +1606,7 @@ var OwneySDK = class {
|
|
|
1559
1606
|
return this.state?.chainId ?? null;
|
|
1560
1607
|
}
|
|
1561
1608
|
requireState() {
|
|
1562
|
-
if (!this.state)
|
|
1563
|
-
throw new NotConnectedError();
|
|
1609
|
+
if (!this.state) throw new NotConnectedError();
|
|
1564
1610
|
return this.state;
|
|
1565
1611
|
}
|
|
1566
1612
|
requireChainId() {
|
|
@@ -1590,12 +1636,12 @@ var OwneySDK = class {
|
|
|
1590
1636
|
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
1591
1637
|
*/
|
|
1592
1638
|
getDefaultSponsoredCallback() {
|
|
1593
|
-
if (this.cachedSponsoredCallback)
|
|
1594
|
-
return this.cachedSponsoredCallback;
|
|
1639
|
+
if (this.cachedSponsoredCallback) return this.cachedSponsoredCallback;
|
|
1595
1640
|
const provider = this.requireConnectedProvider();
|
|
1596
1641
|
const owner = this.state.walletAddress;
|
|
1597
1642
|
this.cachedSponsoredCallback = makeSponsoredDepositCallback({
|
|
1598
1643
|
apiKey: this.apiKey,
|
|
1644
|
+
baseUrl: this.routingApiBaseUrl,
|
|
1599
1645
|
ownerAddress: owner,
|
|
1600
1646
|
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
1601
1647
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
@@ -1626,6 +1672,7 @@ var OwneySDK = class {
|
|
|
1626
1672
|
const owner = this.state.walletAddress;
|
|
1627
1673
|
this.cachedWethSponsoredCallback = makeSponsoredWethCallback({
|
|
1628
1674
|
apiKey: this.apiKey,
|
|
1675
|
+
baseUrl: this.routingApiBaseUrl,
|
|
1629
1676
|
ownerAddress: owner,
|
|
1630
1677
|
tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
|
|
1631
1678
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
@@ -1654,22 +1701,19 @@ var OwneySDK = class {
|
|
|
1654
1701
|
const active = /* @__PURE__ */ new Map();
|
|
1655
1702
|
for (const id of this.activeAgents) {
|
|
1656
1703
|
const agent = this.agents.get(id);
|
|
1657
|
-
if (agent)
|
|
1658
|
-
active.set(id, agent);
|
|
1704
|
+
if (agent) active.set(id, agent);
|
|
1659
1705
|
}
|
|
1660
1706
|
return active;
|
|
1661
1707
|
}
|
|
1662
1708
|
async ensureAgentsInitialized() {
|
|
1663
|
-
if (this.agents.size > 0)
|
|
1664
|
-
return;
|
|
1709
|
+
if (this.agents.size > 0) return;
|
|
1665
1710
|
if (!this.initializingAgentsPromise) {
|
|
1666
1711
|
this.initializingAgentsPromise = (async () => {
|
|
1667
1712
|
const agentKeys = await fetchAgentKeys(this.apiKey);
|
|
1668
1713
|
this.disabledAgents.clear();
|
|
1669
1714
|
for (const { key, agent_type, is_enabled } of agentKeys) {
|
|
1670
1715
|
const agent = this.createAgent(agent_type, key);
|
|
1671
|
-
if (!agent)
|
|
1672
|
-
continue;
|
|
1716
|
+
if (!agent) continue;
|
|
1673
1717
|
this.agents.set(agent_type, agent);
|
|
1674
1718
|
if (is_enabled === false) {
|
|
1675
1719
|
this.disabledAgents.add(agent_type);
|
|
@@ -1908,10 +1952,9 @@ var OwneySDK = class {
|
|
|
1908
1952
|
await this.approvePermit2();
|
|
1909
1953
|
continue;
|
|
1910
1954
|
}
|
|
1911
|
-
if (!shouldFallbackToUserPaid(error, asset, appCallback))
|
|
1912
|
-
throw error;
|
|
1955
|
+
if (!shouldFallbackToUserPaid(error, asset, appCallback)) throw error;
|
|
1913
1956
|
console.warn(
|
|
1914
|
-
|
|
1957
|
+
`[owney-sdk] ${asset} sponsorship unavailable, falling back to user-paid deposit:`,
|
|
1915
1958
|
error
|
|
1916
1959
|
);
|
|
1917
1960
|
return attempt(void 0);
|
|
@@ -1926,8 +1969,7 @@ var OwneySDK = class {
|
|
|
1926
1969
|
return BigInt(assetEntry?.minDepositAmount ?? "0");
|
|
1927
1970
|
}
|
|
1928
1971
|
splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
|
|
1929
|
-
if (agents.length === 0)
|
|
1930
|
-
return [];
|
|
1972
|
+
if (agents.length === 0) return [];
|
|
1931
1973
|
const perAgent = totalAmount / BigInt(agents.length);
|
|
1932
1974
|
const remainder = totalAmount % BigInt(agents.length);
|
|
1933
1975
|
const splits = agents.map((agent, i) => ({
|
|
@@ -1951,10 +1993,8 @@ var OwneySDK = class {
|
|
|
1951
1993
|
async validateMinDepositAmount(agent, state, chainId, asset, amount) {
|
|
1952
1994
|
const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
|
|
1953
1995
|
const parsedAmount = BigInt(amount);
|
|
1954
|
-
if (parsedAmount >= minDepositAmount)
|
|
1955
|
-
|
|
1956
|
-
if (await this.hasExistingBalance(agent, state, chainId, asset))
|
|
1957
|
-
return;
|
|
1996
|
+
if (parsedAmount >= minDepositAmount) return;
|
|
1997
|
+
if (await this.hasExistingBalance(agent, state, chainId, asset)) return;
|
|
1958
1998
|
throw new OwneyError(
|
|
1959
1999
|
"DEPOSIT_AMOUNT_BELOW_MINIMUM",
|
|
1960
2000
|
`Amount "${amount}" is below the required minimum deposit "${minDepositAmount.toString()}" for agent "${agent.id}" on chain ${chainId} for asset "${asset}".`,
|
|
@@ -2118,8 +2158,7 @@ var OwneySDK = class {
|
|
|
2118
2158
|
const agentErrors = {};
|
|
2119
2159
|
for (let i = 0; i < plans.length; i++) {
|
|
2120
2160
|
const p = plans[i];
|
|
2121
|
-
if (p.planned === 0n)
|
|
2122
|
-
continue;
|
|
2161
|
+
if (p.planned === 0n) continue;
|
|
2123
2162
|
try {
|
|
2124
2163
|
results[p.agent.id] = await p.agent.withdraw(
|
|
2125
2164
|
state,
|
|
@@ -2253,19 +2292,30 @@ var OwneySDK = class {
|
|
|
2253
2292
|
*/
|
|
2254
2293
|
async getAccountApy({
|
|
2255
2294
|
agentId,
|
|
2256
|
-
days
|
|
2295
|
+
days,
|
|
2296
|
+
tokenSymbol
|
|
2257
2297
|
}) {
|
|
2258
2298
|
const state = this.requireState();
|
|
2259
2299
|
const chainId = this.requireChainId();
|
|
2260
2300
|
if (agentId) {
|
|
2261
|
-
return this.getAgent(agentId).getAccountApy(
|
|
2301
|
+
return this.getAgent(agentId).getAccountApy(
|
|
2302
|
+
state,
|
|
2303
|
+
chainId,
|
|
2304
|
+
days,
|
|
2305
|
+
tokenSymbol
|
|
2306
|
+
);
|
|
2262
2307
|
}
|
|
2263
2308
|
const activeAgents = this.getActiveAgents();
|
|
2264
2309
|
const entries = [...activeAgents.entries()];
|
|
2265
2310
|
const [apyResults, balanceResults] = await Promise.all([
|
|
2266
2311
|
Promise.all(
|
|
2267
2312
|
entries.map(async ([id, agent]) => {
|
|
2268
|
-
const apy = await agent.getAccountApy(
|
|
2313
|
+
const apy = await agent.getAccountApy(
|
|
2314
|
+
state,
|
|
2315
|
+
chainId,
|
|
2316
|
+
days,
|
|
2317
|
+
tokenSymbol
|
|
2318
|
+
);
|
|
2269
2319
|
return [id, apy];
|
|
2270
2320
|
})
|
|
2271
2321
|
),
|
|
@@ -2288,15 +2338,13 @@ var OwneySDK = class {
|
|
|
2288
2338
|
let relevantBalance = 0;
|
|
2289
2339
|
for (const id of Object.keys(results)) {
|
|
2290
2340
|
const agentApy = Number(results[id].weightedApyAfterFee ?? 0);
|
|
2291
|
-
if (agentApy === 0)
|
|
2292
|
-
continue;
|
|
2341
|
+
if (agentApy === 0) continue;
|
|
2293
2342
|
relevantBalance += balances[id];
|
|
2294
2343
|
}
|
|
2295
2344
|
if (relevantBalance > 0) {
|
|
2296
2345
|
for (const id of Object.keys(results)) {
|
|
2297
2346
|
const agentApy = Number(results[id].weightedApyAfterFee ?? 0);
|
|
2298
|
-
if (agentApy === 0)
|
|
2299
|
-
continue;
|
|
2347
|
+
if (agentApy === 0) continue;
|
|
2300
2348
|
const weight = balances[id] / relevantBalance;
|
|
2301
2349
|
totalApy += agentApy * weight;
|
|
2302
2350
|
}
|
|
@@ -2351,8 +2399,7 @@ var OwneySDK = class {
|
|
|
2351
2399
|
const nextCursorMap = {};
|
|
2352
2400
|
let hasMore = false;
|
|
2353
2401
|
for (const { agentId: id, page } of perAgent) {
|
|
2354
|
-
if (!page)
|
|
2355
|
-
continue;
|
|
2402
|
+
if (!page) continue;
|
|
2356
2403
|
merged.push(...page.data);
|
|
2357
2404
|
if (page.hasMore && page.nextCursor) {
|
|
2358
2405
|
nextCursorMap[id] = page.nextCursor;
|
|
@@ -2361,16 +2408,12 @@ var OwneySDK = class {
|
|
|
2361
2408
|
}
|
|
2362
2409
|
merged.sort((a, b) => {
|
|
2363
2410
|
const dateDiff = new Date(b.date).getTime() - new Date(a.date).getTime();
|
|
2364
|
-
if (dateDiff !== 0)
|
|
2365
|
-
|
|
2366
|
-
if (a.agent !== b.agent)
|
|
2367
|
-
return a.agent < b.agent ? -1 : 1;
|
|
2411
|
+
if (dateDiff !== 0) return dateDiff;
|
|
2412
|
+
if (a.agent !== b.agent) return a.agent < b.agent ? -1 : 1;
|
|
2368
2413
|
const aTx = a.transactions?.[0]?.txHashes?.[0] ?? "";
|
|
2369
2414
|
const bTx = b.transactions?.[0]?.txHashes?.[0] ?? "";
|
|
2370
|
-
if (aTx !== bTx)
|
|
2371
|
-
|
|
2372
|
-
if (a.action !== b.action)
|
|
2373
|
-
return a.action < b.action ? -1 : 1;
|
|
2415
|
+
if (aTx !== bTx) return aTx < bTx ? -1 : 1;
|
|
2416
|
+
if (a.action !== b.action) return a.action < b.action ? -1 : 1;
|
|
2374
2417
|
return 0;
|
|
2375
2418
|
});
|
|
2376
2419
|
return {
|
|
@@ -2416,8 +2459,7 @@ var OwneySDK = class {
|
|
|
2416
2459
|
const state = this.requireState();
|
|
2417
2460
|
const chainId = this.requireChainId();
|
|
2418
2461
|
const agent = this.getAgent(agentId);
|
|
2419
|
-
if (typeof agent.ensureAutoSelectProtocols !== "function")
|
|
2420
|
-
return false;
|
|
2462
|
+
if (typeof agent.ensureAutoSelectProtocols !== "function") return false;
|
|
2421
2463
|
return agent.ensureAutoSelectProtocols(state, chainId, asset);
|
|
2422
2464
|
}
|
|
2423
2465
|
/**
|
|
@@ -2429,8 +2471,10 @@ var OwneySDK = class {
|
|
|
2429
2471
|
* @returns the approval transaction hash.
|
|
2430
2472
|
*/
|
|
2431
2473
|
async approvePermit2(asset = "WETH") {
|
|
2474
|
+
void asset;
|
|
2432
2475
|
const state = this.requireState();
|
|
2433
2476
|
const chainId = this.requireChainId();
|
|
2477
|
+
this.validateAssetSupport(this.getAgent("zyfai"), chainId, "WETH");
|
|
2434
2478
|
const token = SPONSORED_WETH_BY_CHAIN[chainId];
|
|
2435
2479
|
if (!token) {
|
|
2436
2480
|
throw new OwneyError(
|
|
@@ -2570,8 +2614,7 @@ import { ZyfaiSDK as ZyfaiSDK2 } from "@zyfai/sdk";
|
|
|
2570
2614
|
// src/agents/zyfai/zyfai.siwx-cache.ts
|
|
2571
2615
|
var KEY_PREFIX2 = "owney.siwx.session";
|
|
2572
2616
|
var storage2 = () => {
|
|
2573
|
-
if (typeof window === "undefined")
|
|
2574
|
-
return null;
|
|
2617
|
+
if (typeof window === "undefined") return null;
|
|
2575
2618
|
try {
|
|
2576
2619
|
return window.localStorage;
|
|
2577
2620
|
} catch {
|
|
@@ -2581,11 +2624,9 @@ var storage2 = () => {
|
|
|
2581
2624
|
var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
|
|
2582
2625
|
var readSiwxSession = (address, chainId) => {
|
|
2583
2626
|
const store = storage2();
|
|
2584
|
-
if (!store)
|
|
2585
|
-
return null;
|
|
2627
|
+
if (!store) return null;
|
|
2586
2628
|
const raw = store.getItem(buildKey2(address, chainId));
|
|
2587
|
-
if (!raw)
|
|
2588
|
-
return null;
|
|
2629
|
+
if (!raw) return null;
|
|
2589
2630
|
try {
|
|
2590
2631
|
return JSON.parse(raw);
|
|
2591
2632
|
} catch {
|
|
@@ -2595,8 +2636,7 @@ var readSiwxSession = (address, chainId) => {
|
|
|
2595
2636
|
};
|
|
2596
2637
|
var writeSiwxSession = (address, chainId, session) => {
|
|
2597
2638
|
const store = storage2();
|
|
2598
|
-
if (!store)
|
|
2599
|
-
return;
|
|
2639
|
+
if (!store) return;
|
|
2600
2640
|
try {
|
|
2601
2641
|
store.setItem(buildKey2(address, chainId), JSON.stringify(session));
|
|
2602
2642
|
} catch {
|
|
@@ -2604,8 +2644,7 @@ var writeSiwxSession = (address, chainId, session) => {
|
|
|
2604
2644
|
};
|
|
2605
2645
|
var clearSiwxSession = (address, chainId) => {
|
|
2606
2646
|
const store = storage2();
|
|
2607
|
-
if (!store)
|
|
2608
|
-
return;
|
|
2647
|
+
if (!store) return;
|
|
2609
2648
|
try {
|
|
2610
2649
|
store.removeItem(buildKey2(address, chainId));
|
|
2611
2650
|
} catch {
|
|
@@ -2668,12 +2707,10 @@ function buildSIWXConfig(deps) {
|
|
|
2668
2707
|
const jwt = readSession(address, id);
|
|
2669
2708
|
const stored = readSiwxSession(address, id);
|
|
2670
2709
|
if (!jwt) {
|
|
2671
|
-
if (stored)
|
|
2672
|
-
clearSiwxSession(address, id);
|
|
2710
|
+
if (stored) clearSiwxSession(address, id);
|
|
2673
2711
|
return [];
|
|
2674
2712
|
}
|
|
2675
|
-
if (!stored)
|
|
2676
|
-
return [];
|
|
2713
|
+
if (!stored) return [];
|
|
2677
2714
|
const session = {
|
|
2678
2715
|
// `stored.data.chainId` is a plain string in the cache (kept AppKit-free);
|
|
2679
2716
|
// it always holds a valid CaipNetworkId here, so narrow at the boundary.
|