@owney/sdk 0.7.28-beta.0 → 0.7.28-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 +192 -25
- package/dist/index.d.cts +149 -4
- package/dist/index.d.ts +149 -4
- package/dist/index.js +192 -25
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -510,7 +510,7 @@ function rawPoolApyForChain(entry, chainId, tokenSymbol) {
|
|
|
510
510
|
let weightedSum = 0;
|
|
511
511
|
let totalBalance = 0;
|
|
512
512
|
for (const p of entry.positions ?? []) {
|
|
513
|
-
if (p.chainId !== chainId) continue;
|
|
513
|
+
if (chainId !== void 0 && p.chainId !== chainId) continue;
|
|
514
514
|
if (tokenSymbol && p.tokenSymbol?.toUpperCase() !== tokenSymbol.toUpperCase()) continue;
|
|
515
515
|
const balance = p.balance ?? 0;
|
|
516
516
|
const apy = netApy(p.apy_withFee, p.apy, "apy_withFee");
|
|
@@ -520,6 +520,28 @@ function rawPoolApyForChain(entry, chainId, tokenSymbol) {
|
|
|
520
520
|
}
|
|
521
521
|
return totalBalance > 0 ? weightedSum / totalBalance : null;
|
|
522
522
|
}
|
|
523
|
+
function historyCoverage(raw) {
|
|
524
|
+
const chains = /* @__PURE__ */ new Map();
|
|
525
|
+
const assets = /* @__PURE__ */ new Map();
|
|
526
|
+
for (const date of Object.keys(raw.history ?? {}).sort()) {
|
|
527
|
+
void date;
|
|
528
|
+
const seenChains = /* @__PURE__ */ new Set();
|
|
529
|
+
const seenAssets = /* @__PURE__ */ new Set();
|
|
530
|
+
for (const p of (raw.history ?? {})[date].positions ?? []) {
|
|
531
|
+
const balance = p.balance ?? 0;
|
|
532
|
+
const apy = netApy(p.apy_withFee, p.apy, "apy_withFee");
|
|
533
|
+
if (balance <= 0 || typeof apy !== "number") continue;
|
|
534
|
+
seenChains.add(p.chainId);
|
|
535
|
+
if (p.tokenSymbol) seenAssets.add(p.tokenSymbol.toUpperCase());
|
|
536
|
+
}
|
|
537
|
+
for (const c of seenChains) chains.set(c, (chains.get(c) ?? 0) + 1);
|
|
538
|
+
for (const a of seenAssets) assets.set(a, (assets.get(a) ?? 0) + 1);
|
|
539
|
+
}
|
|
540
|
+
return {
|
|
541
|
+
chains: [...chains].map(([chainId, days]) => ({ chainId, days })),
|
|
542
|
+
assets: [...assets].map(([asset, days]) => ({ asset, days }))
|
|
543
|
+
};
|
|
544
|
+
}
|
|
523
545
|
function mapApyHistory(raw, chainId, tokenSymbol) {
|
|
524
546
|
const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({
|
|
525
547
|
date,
|
|
@@ -530,7 +552,7 @@ function mapApyHistory(raw, chainId, tokenSymbol) {
|
|
|
530
552
|
...tokenSymbol ? {
|
|
531
553
|
historicalBalance: {
|
|
532
554
|
amount: (entry.positions ?? []).filter(
|
|
533
|
-
(p) => p.chainId === chainId && p.tokenSymbol?.toUpperCase() === tokenSymbol.toUpperCase() && Number.isFinite(p.balance) && p.balance > 0 && Number.isFinite(p.apy_withFee ?? p.apy)
|
|
555
|
+
(p) => (chainId === void 0 || p.chainId === chainId) && p.tokenSymbol?.toUpperCase() === tokenSymbol.toUpperCase() && Number.isFinite(p.balance) && p.balance > 0 && Number.isFinite(p.apy_withFee ?? p.apy)
|
|
534
556
|
).reduce((sum, p) => sum + p.balance, 0),
|
|
535
557
|
unit: tokenSymbol.toUpperCase()
|
|
536
558
|
}
|
|
@@ -540,7 +562,8 @@ function mapApyHistory(raw, chainId, tokenSymbol) {
|
|
|
540
562
|
walletAddress: raw.walletAddress,
|
|
541
563
|
weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0,
|
|
542
564
|
apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain),
|
|
543
|
-
history
|
|
565
|
+
history,
|
|
566
|
+
coverage: historyCoverage(raw)
|
|
544
567
|
};
|
|
545
568
|
}
|
|
546
569
|
function splitOpportunity(opportunity) {
|
|
@@ -999,6 +1022,9 @@ function splittingNeedsUpdate(current, desired) {
|
|
|
999
1022
|
}
|
|
1000
1023
|
|
|
1001
1024
|
// src/agents/zyfai/pool-policy.ts
|
|
1025
|
+
function orgPolicyForConnect(policy, userPoolCustomization) {
|
|
1026
|
+
return userPoolCustomization ? { ...policy, poolPolicy: null } : policy;
|
|
1027
|
+
}
|
|
1002
1028
|
function toZyfaiCustomizations(policy, availableByProtocol, chainsByProtocol) {
|
|
1003
1029
|
const selectionByKey = /* @__PURE__ */ new Map();
|
|
1004
1030
|
for (const selection of policy.selections) {
|
|
@@ -1090,6 +1116,47 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
|
|
|
1090
1116
|
if (desiredProtocols === null) return false;
|
|
1091
1117
|
return !protocolListsEqual(current.protocols, desiredProtocols);
|
|
1092
1118
|
}
|
|
1119
|
+
function mapAvailablePools(raw) {
|
|
1120
|
+
const byChain = raw ?? {};
|
|
1121
|
+
if (typeof byChain !== "object" || byChain === null) return [];
|
|
1122
|
+
const result = [];
|
|
1123
|
+
for (const [chainIdStr, byToken] of Object.entries(byChain)) {
|
|
1124
|
+
const chainId = Number(chainIdStr);
|
|
1125
|
+
if (!Number.isFinite(chainId)) continue;
|
|
1126
|
+
for (const [token, entry] of Object.entries(byToken ?? {})) {
|
|
1127
|
+
for (const pool of entry?.pools ?? []) {
|
|
1128
|
+
if (!pool?.name) continue;
|
|
1129
|
+
result.push({
|
|
1130
|
+
chainId,
|
|
1131
|
+
token,
|
|
1132
|
+
name: pool.name,
|
|
1133
|
+
apy: pool.info?.combined_apy ?? null,
|
|
1134
|
+
tvlUsd: pool.info?.tvlUsd ?? null,
|
|
1135
|
+
link: pool.info?.link ?? null
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
return result;
|
|
1141
|
+
}
|
|
1142
|
+
function assemblePoolCatalog(protocols, poolsByProtocol, asset, chains) {
|
|
1143
|
+
const wanted = asset.toUpperCase();
|
|
1144
|
+
const allowedChains = chains && chains.length > 0 ? new Set(chains) : void 0;
|
|
1145
|
+
const catalog = [];
|
|
1146
|
+
for (const protocol of protocols) {
|
|
1147
|
+
const pools = (poolsByProtocol.get(protocol.id) ?? []).filter(
|
|
1148
|
+
(p) => p.token.toUpperCase() === wanted && (allowedChains === void 0 || allowedChains.has(p.chainId))
|
|
1149
|
+
);
|
|
1150
|
+
if (pools.length === 0) continue;
|
|
1151
|
+
catalog.push({
|
|
1152
|
+
protocolId: protocol.id,
|
|
1153
|
+
name: protocol.name,
|
|
1154
|
+
logo: protocol.imageUrl ?? null,
|
|
1155
|
+
pools
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
return catalog;
|
|
1159
|
+
}
|
|
1093
1160
|
|
|
1094
1161
|
// src/agents/zyfai/zyfai.agent.ts
|
|
1095
1162
|
var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem.parseAbi)([
|
|
@@ -1516,7 +1583,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1516
1583
|
* connecting, so a Zyfai hiccup must leave the user connected with their
|
|
1517
1584
|
* profile unchanged, never fail activation.
|
|
1518
1585
|
*/
|
|
1519
|
-
async applyPoolPolicy(policy) {
|
|
1586
|
+
async applyPoolPolicy(policy, opts = {}) {
|
|
1520
1587
|
try {
|
|
1521
1588
|
const { protocols: universe } = await this.sdk.getAvailableProtocols(
|
|
1522
1589
|
this.supportedChainIds[0]
|
|
@@ -1530,7 +1597,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1530
1597
|
universeIds,
|
|
1531
1598
|
chainsByProtocol
|
|
1532
1599
|
});
|
|
1533
|
-
let strategy;
|
|
1600
|
+
let strategy = opts.strategy;
|
|
1534
1601
|
const desiredProtocols = deriveProtocols(
|
|
1535
1602
|
policy,
|
|
1536
1603
|
universeIds,
|
|
@@ -1610,6 +1677,50 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1610
1677
|
);
|
|
1611
1678
|
}
|
|
1612
1679
|
}
|
|
1680
|
+
/**
|
|
1681
|
+
* The deposit-time Pools step's catalogue: every protocol Zyfai offers this
|
|
1682
|
+
* user, each with the pools (name, APY, TVL, link) selectable for `asset`
|
|
1683
|
+
* under `strategy`. Sourced from the same two Zyfai calls `applyPoolPolicy`
|
|
1684
|
+
* uses, so "shown" and "selectable" are one set. A protocol whose pool
|
|
1685
|
+
* lookup fails is skipped rather than failing the whole catalogue.
|
|
1686
|
+
*/
|
|
1687
|
+
async getPoolCatalog(params) {
|
|
1688
|
+
const { protocols: universe } = await this.sdk.getAvailableProtocols(
|
|
1689
|
+
this.supportedChainIds[0]
|
|
1690
|
+
);
|
|
1691
|
+
const poolResults = await Promise.all(
|
|
1692
|
+
universe.map(async (protocol) => {
|
|
1693
|
+
try {
|
|
1694
|
+
const raw = await this.sdk.getAvailablePools(
|
|
1695
|
+
protocol.id,
|
|
1696
|
+
params.strategy
|
|
1697
|
+
);
|
|
1698
|
+
return [protocol.id, mapAvailablePools(raw)];
|
|
1699
|
+
} catch (error) {
|
|
1700
|
+
console.warn(
|
|
1701
|
+
`[zyfai] getPoolCatalog: getAvailablePools(${protocol.id}) failed, skipping (non-fatal):`,
|
|
1702
|
+
error instanceof Error ? error.message : String(error)
|
|
1703
|
+
);
|
|
1704
|
+
return null;
|
|
1705
|
+
}
|
|
1706
|
+
})
|
|
1707
|
+
);
|
|
1708
|
+
const poolsByProtocol = /* @__PURE__ */ new Map();
|
|
1709
|
+
for (const result of poolResults) {
|
|
1710
|
+
if (result) poolsByProtocol.set(result[0], result[1]);
|
|
1711
|
+
}
|
|
1712
|
+
return assemblePoolCatalog(universe, poolsByProtocol, params.asset);
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Apply a user's own pool selection (the deposit-time Pools step) to their
|
|
1716
|
+
* Zyfai profile. Same two writes as the org path — this is `applyPoolPolicy`
|
|
1717
|
+
* driven by the user's `policy` instead of the organization's, with the
|
|
1718
|
+
* deposit's chosen `strategy` passed through so pool names validate against
|
|
1719
|
+
* the strategy the user just picked rather than their stored one.
|
|
1720
|
+
*/
|
|
1721
|
+
async setPoolSelection(policy, opts = {}) {
|
|
1722
|
+
await this.applyPoolPolicy(policy, opts);
|
|
1723
|
+
}
|
|
1613
1724
|
/**
|
|
1614
1725
|
* True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
|
|
1615
1726
|
* to this EOA — the "new wallet" kind that is predeployed on the chains it
|
|
@@ -1736,11 +1847,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1736
1847
|
);
|
|
1737
1848
|
return;
|
|
1738
1849
|
}
|
|
1739
|
-
await this.ensureSessionKey(
|
|
1740
|
-
ownerAddress,
|
|
1741
|
-
chainId,
|
|
1742
|
-
wallet.address
|
|
1743
|
-
);
|
|
1850
|
+
await this.ensureSessionKey(ownerAddress, chainId, wallet.address);
|
|
1744
1851
|
} catch (error) {
|
|
1745
1852
|
console.warn(
|
|
1746
1853
|
"[zyfai] session-key check at activation failed (non-fatal):",
|
|
@@ -1851,11 +1958,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1851
1958
|
"zyfai:onboard",
|
|
1852
1959
|
"Safe already has code -> no deploy needed, checking the session key"
|
|
1853
1960
|
);
|
|
1854
|
-
await this.ensureSessionKey(
|
|
1855
|
-
ownerAddress,
|
|
1856
|
-
chainId,
|
|
1857
|
-
wallet.address
|
|
1858
|
-
);
|
|
1961
|
+
await this.ensureSessionKey(ownerAddress, chainId, wallet.address);
|
|
1859
1962
|
return wallet.address;
|
|
1860
1963
|
}
|
|
1861
1964
|
const poolFirst = await this.isPredeployedPoolWallet(
|
|
@@ -2022,14 +2125,17 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2022
2125
|
this.earningsRefreshes.set(key2, pending);
|
|
2023
2126
|
return pending;
|
|
2024
2127
|
}
|
|
2025
|
-
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
2128
|
+
async getAccountApy(state, chainId, days, tokenSymbol, scopeChainId) {
|
|
2026
2129
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
2027
2130
|
const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
|
|
2028
|
-
|
|
2131
|
+
const scope = scopeChainId === null ? void 0 : scopeChainId ?? chainId;
|
|
2132
|
+
return mapApyHistory(raw, scope, tokenSymbol);
|
|
2029
2133
|
}
|
|
2030
2134
|
async getDailyEarnings(state, chainId, days, tokenSymbol) {
|
|
2031
2135
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
2032
|
-
const start = new Date(
|
|
2136
|
+
const start = new Date(
|
|
2137
|
+
Date.now() - (DayFilterMapping[days] + 1) * 864e5
|
|
2138
|
+
);
|
|
2033
2139
|
const raw = await this.sdk.getDailyEarnings(
|
|
2034
2140
|
smartWallet,
|
|
2035
2141
|
start.toISOString().slice(0, 10)
|
|
@@ -2151,6 +2257,9 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2151
2257
|
|
|
2152
2258
|
// src/lib/history-fanout.ts
|
|
2153
2259
|
var SEPARATOR = "@";
|
|
2260
|
+
function isSupportedChainId(value) {
|
|
2261
|
+
return SUPPORTED_CHAIN_IDS.includes(value);
|
|
2262
|
+
}
|
|
2154
2263
|
function fanoutKey(leg) {
|
|
2155
2264
|
return leg.chainId === void 0 ? leg.agentId : `${leg.agentId}${SEPARATOR}${leg.chainId}`;
|
|
2156
2265
|
}
|
|
@@ -2173,6 +2282,16 @@ function decodeFanoutCursor(token) {
|
|
|
2173
2282
|
}
|
|
2174
2283
|
return parsed;
|
|
2175
2284
|
}
|
|
2285
|
+
function transactionChainId(entry) {
|
|
2286
|
+
let found;
|
|
2287
|
+
for (const tx of entry.transactions ?? []) {
|
|
2288
|
+
if (tx.chainId === void 0) continue;
|
|
2289
|
+
if (!isSupportedChainId(tx.chainId)) return void 0;
|
|
2290
|
+
if (found !== void 0 && found !== tx.chainId) return void 0;
|
|
2291
|
+
found = tx.chainId;
|
|
2292
|
+
}
|
|
2293
|
+
return found;
|
|
2294
|
+
}
|
|
2176
2295
|
function mergeHistoryPages(pages) {
|
|
2177
2296
|
const merged = [];
|
|
2178
2297
|
const nextCursorMap = {};
|
|
@@ -2191,7 +2310,9 @@ function mergeHistoryPages(pages) {
|
|
|
2191
2310
|
const prior = seen.get(id);
|
|
2192
2311
|
if (prior) {
|
|
2193
2312
|
prior.legs += 1;
|
|
2194
|
-
|
|
2313
|
+
const own = transactionChainId(prior.entry);
|
|
2314
|
+
if (own === void 0) delete prior.entry.chainId;
|
|
2315
|
+
else prior.entry.chainId = own;
|
|
2195
2316
|
continue;
|
|
2196
2317
|
}
|
|
2197
2318
|
const entry = leg.chainId === void 0 ? { ...e } : { ...e, chainId: leg.chainId };
|
|
@@ -4312,6 +4433,7 @@ var OwneySDK = class {
|
|
|
4312
4433
|
orgAgentConfig;
|
|
4313
4434
|
orgAgentConfigPromise = null;
|
|
4314
4435
|
zyfaiRpcUrls;
|
|
4436
|
+
userPoolCustomization = false;
|
|
4315
4437
|
routingApiBaseUrl;
|
|
4316
4438
|
referralSource;
|
|
4317
4439
|
cachedSponsoredCallback = null;
|
|
@@ -4337,6 +4459,7 @@ var OwneySDK = class {
|
|
|
4337
4459
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
4338
4460
|
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
4339
4461
|
this.referralSource = config.referralSource;
|
|
4462
|
+
this.userPoolCustomization = config.userPoolCustomization ?? false;
|
|
4340
4463
|
}
|
|
4341
4464
|
/**
|
|
4342
4465
|
* Establish connection state for all subsequent SDK calls.
|
|
@@ -4563,7 +4686,8 @@ var OwneySDK = class {
|
|
|
4563
4686
|
try {
|
|
4564
4687
|
const policy = await this.getOrgAgentConfig();
|
|
4565
4688
|
if (!policy) return;
|
|
4566
|
-
|
|
4689
|
+
const effective = orgPolicyForConnect(policy, this.userPoolCustomization);
|
|
4690
|
+
await agent.applyOrgPolicy(state, chainId, effective);
|
|
4567
4691
|
} catch (error) {
|
|
4568
4692
|
console.warn(
|
|
4569
4693
|
`[owney-sdk] applyOrgPolicy(${agent.id}) failed (non-fatal):`,
|
|
@@ -6380,20 +6504,57 @@ var OwneySDK = class {
|
|
|
6380
6504
|
chainId
|
|
6381
6505
|
};
|
|
6382
6506
|
}
|
|
6507
|
+
/**
|
|
6508
|
+
* The deposit-time pool catalogue (ROUT-569): every protocol with its
|
|
6509
|
+
* selectable pools (name, APY, TVL, link) for `asset` under `strategy`.
|
|
6510
|
+
* Defaults to the zyfai agent, the only one with pool customization today.
|
|
6511
|
+
*/
|
|
6512
|
+
async getPoolCatalog(params) {
|
|
6513
|
+
await this.ensureAgentsInitialized();
|
|
6514
|
+
const agent = this.getAgent(params.agentId ?? "zyfai");
|
|
6515
|
+
if (!agent.getPoolCatalog) {
|
|
6516
|
+
throw new OwneyError(
|
|
6517
|
+
"POOL_CATALOG_UNSUPPORTED",
|
|
6518
|
+
`Agent ${agent.id} does not support pool customization`
|
|
6519
|
+
);
|
|
6520
|
+
}
|
|
6521
|
+
return agent.getPoolCatalog({
|
|
6522
|
+
asset: params.asset,
|
|
6523
|
+
strategy: params.strategy
|
|
6524
|
+
});
|
|
6525
|
+
}
|
|
6526
|
+
/**
|
|
6527
|
+
* Apply a user's deposit-time pool selection to their account (ROUT-569).
|
|
6528
|
+
* `strategy` is the one chosen in the deposit flow, passed through so pool
|
|
6529
|
+
* names validate against it rather than the user's stored strategy.
|
|
6530
|
+
*/
|
|
6531
|
+
async setPoolSelection(params) {
|
|
6532
|
+
await this.ensureAgentsInitialized();
|
|
6533
|
+
const agent = this.getAgent(params.agentId ?? "zyfai");
|
|
6534
|
+
if (!agent.setPoolSelection) {
|
|
6535
|
+
throw new OwneyError(
|
|
6536
|
+
"POOL_SELECTION_UNSUPPORTED",
|
|
6537
|
+
`Agent ${agent.id} does not support pool customization`
|
|
6538
|
+
);
|
|
6539
|
+
}
|
|
6540
|
+
await agent.setPoolSelection(params.policy, { strategy: params.strategy });
|
|
6541
|
+
}
|
|
6383
6542
|
async getAccountApy({
|
|
6384
6543
|
agentId,
|
|
6385
6544
|
days,
|
|
6386
|
-
tokenSymbol
|
|
6545
|
+
tokenSymbol,
|
|
6546
|
+
chainId: scope
|
|
6387
6547
|
}) {
|
|
6388
6548
|
const state = this.requireState();
|
|
6389
6549
|
const chainId = this.requireChainId();
|
|
6550
|
+
const scopeChainId = scope === "all" ? null : scope;
|
|
6390
6551
|
if (agentId) {
|
|
6391
6552
|
const agent = this.getAgent(agentId);
|
|
6392
6553
|
return this.readAgent(
|
|
6393
6554
|
agent,
|
|
6394
6555
|
"accountApy",
|
|
6395
|
-
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
6396
|
-
{ days, tokenSymbol }
|
|
6556
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol, scopeChainId),
|
|
6557
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6397
6558
|
);
|
|
6398
6559
|
}
|
|
6399
6560
|
const activeAgents = this.getActiveAgents();
|
|
@@ -6404,8 +6565,14 @@ var OwneySDK = class {
|
|
|
6404
6565
|
const apy = await this.readAgent(
|
|
6405
6566
|
agent,
|
|
6406
6567
|
"accountApy",
|
|
6407
|
-
() => agent.getAccountApy(
|
|
6408
|
-
|
|
6568
|
+
() => agent.getAccountApy(
|
|
6569
|
+
state,
|
|
6570
|
+
chainId,
|
|
6571
|
+
days,
|
|
6572
|
+
tokenSymbol,
|
|
6573
|
+
scopeChainId
|
|
6574
|
+
),
|
|
6575
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6409
6576
|
);
|
|
6410
6577
|
return [id, apy];
|
|
6411
6578
|
})
|
package/dist/index.d.cts
CHANGED
|
@@ -276,6 +276,15 @@ interface OwneySDKConfig {
|
|
|
276
276
|
* already-deployed app: set `globalThis.__OWNEY_DEBUG__ = true` in devtools.
|
|
277
277
|
*/
|
|
278
278
|
debug?: boolean;
|
|
279
|
+
/**
|
|
280
|
+
* When true, the organization's pool policy is NOT applied on connect, so a
|
|
281
|
+
* user's own deposit-time pool selection (ROUT-569) is never overwritten by
|
|
282
|
+
* the org-level one on their next reconnect. Splitting and the rest of the
|
|
283
|
+
* org policy still apply. Turn this on in apps that expose the deposit-time
|
|
284
|
+
* Pools step (the spread flow); leave it off where the partner dashboard's
|
|
285
|
+
* pool customization is the source of truth.
|
|
286
|
+
*/
|
|
287
|
+
userPoolCustomization?: boolean;
|
|
279
288
|
/**
|
|
280
289
|
* Absolute URL of an ERC-7677 paymaster service. When set, deposits go out as
|
|
281
290
|
* an EIP-5792 `wallet_sendCalls` with `capabilities.paymasterService`, so a
|
|
@@ -374,6 +383,18 @@ type WithdrawOptions = {
|
|
|
374
383
|
type AccountApyOptions = {
|
|
375
384
|
agentId?: AgentId;
|
|
376
385
|
days: LookbackDays;
|
|
386
|
+
/**
|
|
387
|
+
* Chain to scope the daily series to, instead of the one `activateAgent`
|
|
388
|
+
* last set (ROUT-479).
|
|
389
|
+
*
|
|
390
|
+
* `"all"` blends every chain the wallet held that day, which is what the
|
|
391
|
+
* chart's "All chains" filter asks for. Unlike the history and earnings
|
|
392
|
+
* reads this needs no fan-out: the provider's daily-APY payload is already
|
|
393
|
+
* wallet-wide and names each position's chain, so the scope is a filter over
|
|
394
|
+
* one response rather than several calls. Omit for the active chain, which
|
|
395
|
+
* stays the default.
|
|
396
|
+
*/
|
|
397
|
+
chainId?: OwneySupportedChainId | "all";
|
|
377
398
|
/**
|
|
378
399
|
* Optional asset symbol (e.g. "USDC", "WETH") to scope the daily APY series
|
|
379
400
|
* to a specific asset on the active chain. Without it the series blends every
|
|
@@ -476,6 +497,61 @@ type OrgAgentConfig = {
|
|
|
476
497
|
poolPolicy?: OrgPoolPolicy | null;
|
|
477
498
|
};
|
|
478
499
|
|
|
500
|
+
/**
|
|
501
|
+
* Pool policy: Owney's org-level protocol/pool policy -> Zyfai's two mismatched
|
|
502
|
+
* write shapes.
|
|
503
|
+
*
|
|
504
|
+
* Zyfai splits "which protocols and pools may this user's funds sit in" across
|
|
505
|
+
* two calls that do not share an axis:
|
|
506
|
+
*
|
|
507
|
+
* updateUserProfile({ protocols }) per ASSET, chain-agnostic
|
|
508
|
+
* customizeBatch([{ protocolId, per (PROTOCOL, CHAIN), asset-agnostic
|
|
509
|
+
* chainId, pools, autoselect }])
|
|
510
|
+
*
|
|
511
|
+
* `protocols` is an explicit ALLOW-LIST: a protocol left out of it is disabled
|
|
512
|
+
* for that asset, on every chain, immediately. `customizeBatch` is the opposite
|
|
513
|
+
* shape — one record per (protocol, chain) pair, asset-agnostic, and per
|
|
514
|
+
* docs.zyf.ai it "creates or updates a record for the (user, protocol, chain)
|
|
515
|
+
* combination"; "previous customizations for the same combination are
|
|
516
|
+
* overwritten".
|
|
517
|
+
*
|
|
518
|
+
* That second property is the reason this file exists rather than a single
|
|
519
|
+
* flat translation: customizeBatch overwrites only the combinations it is
|
|
520
|
+
* GIVEN. The partner's stored policy (`OrgPoolPolicy.selections`) is sparse —
|
|
521
|
+
* only the protocols they actually narrowed appear — but the payload we send
|
|
522
|
+
* must be EXHAUSTIVE over every (protocol, chain) pair Zyfai offers this user.
|
|
523
|
+
* If we only sent the narrowed pairs, a partner who restricts Morpho, saves,
|
|
524
|
+
* then later re-ticks every pool box would never be able to undo it: nothing
|
|
525
|
+
* in the (sparse) policy would tell us to send a record clearing it, and the
|
|
526
|
+
* old restrictive record would stay live on the user's profile forever.
|
|
527
|
+
*
|
|
528
|
+
* Pure functions, kept out of the agent so the mapping is testable without a
|
|
529
|
+
* Zyfai client. See splitting.ts for the same pattern on the other lever.
|
|
530
|
+
*/
|
|
531
|
+
|
|
532
|
+
/** One selectable pool, with the figures the deposit-time Pools step shows. */
|
|
533
|
+
type AvailablePool = {
|
|
534
|
+
chainId: number;
|
|
535
|
+
token: string;
|
|
536
|
+
name: string;
|
|
537
|
+
/** combined_apy (pool + rewards), already a percent. null when absent. */
|
|
538
|
+
apy: number | null;
|
|
539
|
+
/** TVL in USD. null when absent. See ZyfCustomizationPoolInfo: `tvl` is in
|
|
540
|
+
* the pool's own token, `tvlUsd` is the dollar figure — only the latter is
|
|
541
|
+
* safe to show with a currency symbol. */
|
|
542
|
+
tvlUsd: number | null;
|
|
543
|
+
/** Per-pool deep link (e.g. the Morpho vault page). null when absent. */
|
|
544
|
+
link: string | null;
|
|
545
|
+
};
|
|
546
|
+
/** One protocol with its pools for the deposit asset — what the Pools step
|
|
547
|
+
* renders: a protocol row that opens to a list of selectable pools. */
|
|
548
|
+
type PoolCatalogProtocol = {
|
|
549
|
+
protocolId: string;
|
|
550
|
+
name: string;
|
|
551
|
+
logo: string | null;
|
|
552
|
+
pools: AvailablePool[];
|
|
553
|
+
};
|
|
554
|
+
|
|
479
555
|
interface OwneyDepositResult {
|
|
480
556
|
txHash: string;
|
|
481
557
|
smartWallet: string;
|
|
@@ -606,6 +682,28 @@ interface ApyHistoryPoint {
|
|
|
606
682
|
unit: string;
|
|
607
683
|
};
|
|
608
684
|
}
|
|
685
|
+
/**
|
|
686
|
+
* What the APY chart's chain/asset menus are allowed to offer, and how far
|
|
687
|
+
* back each option reaches (ROUT-479).
|
|
688
|
+
*
|
|
689
|
+
* An option only earns a place if some day in the window held a real position
|
|
690
|
+
* on it — a balance and a rate. Listing anything else would offer a filter
|
|
691
|
+
* that draws a blank chart. `days` is what the menu prints beside each row,
|
|
692
|
+
* and the legs genuinely differ: a wallet can hold USDC for a fortnight and
|
|
693
|
+
* WETH for three days.
|
|
694
|
+
*/
|
|
695
|
+
interface ApyCoverage {
|
|
696
|
+
chains: {
|
|
697
|
+
chainId: number;
|
|
698
|
+
days: number;
|
|
699
|
+
}[];
|
|
700
|
+
/** Legs whose `tokenSymbol` the provider left unset are absent — they cannot
|
|
701
|
+
* be named, so they cannot be picked. Their chain still counts. */
|
|
702
|
+
assets: {
|
|
703
|
+
asset: string;
|
|
704
|
+
days: number;
|
|
705
|
+
}[];
|
|
706
|
+
}
|
|
609
707
|
interface AccountAgentApy {
|
|
610
708
|
walletAddress: string;
|
|
611
709
|
weightedApyAfterFee?: number;
|
|
@@ -616,6 +714,8 @@ interface AccountAgentApy {
|
|
|
616
714
|
* date. Empty when the provider returns no daily history.
|
|
617
715
|
*/
|
|
618
716
|
history?: ApyHistoryPoint[];
|
|
717
|
+
/** Which chains/assets this history can be filtered down to. */
|
|
718
|
+
coverage?: ApyCoverage;
|
|
619
719
|
}
|
|
620
720
|
interface OwneyAccountApy {
|
|
621
721
|
totalApy: string;
|
|
@@ -779,6 +879,23 @@ interface IAgent {
|
|
|
779
879
|
* unchanged rather than break the connect.
|
|
780
880
|
*/
|
|
781
881
|
applyOrgPolicy?(state: ConnectionState, chainId: number, policy: OrgAgentConfig): Promise<void>;
|
|
882
|
+
/**
|
|
883
|
+
* The deposit-time pool catalogue for one asset and strategy: protocols with
|
|
884
|
+
* their selectable pools and figures. Optional — an agent with no pool
|
|
885
|
+
* customization omits it. (ROUT-569)
|
|
886
|
+
*/
|
|
887
|
+
getPoolCatalog?(params: {
|
|
888
|
+
asset: string;
|
|
889
|
+
strategy: "conservative" | "aggressive";
|
|
890
|
+
}): Promise<PoolCatalogProtocol[]>;
|
|
891
|
+
/**
|
|
892
|
+
* Apply a user's own pool selection to their account, driven by the
|
|
893
|
+
* deposit-time Pools step. Optional, and non-fatal like `applyOrgPolicy`.
|
|
894
|
+
* (ROUT-569)
|
|
895
|
+
*/
|
|
896
|
+
setPoolSelection?(policy: OrgPoolPolicy, opts?: {
|
|
897
|
+
strategy?: "conservative" | "aggressive";
|
|
898
|
+
}): Promise<void>;
|
|
782
899
|
deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
|
|
783
900
|
withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
|
|
784
901
|
getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
|
|
@@ -793,7 +910,14 @@ interface IAgent {
|
|
|
793
910
|
* Optional asset symbol ("USDC" / "WETH") scoping the daily series to a
|
|
794
911
|
* single asset on the chain. Agents without per-asset positions ignore it.
|
|
795
912
|
*/
|
|
796
|
-
tokenSymbol?: string
|
|
913
|
+
tokenSymbol?: string,
|
|
914
|
+
/**
|
|
915
|
+
* Chain the series is scoped to, when that differs from the chain the
|
|
916
|
+
* connection is on. `null` spans every chain the wallet held (ROUT-479);
|
|
917
|
+
* omitted means `chainId`. Kept apart from `chainId` because that one
|
|
918
|
+
* still resolves the wallet and must stay a real, connected chain.
|
|
919
|
+
*/
|
|
920
|
+
scopeChainId?: number | null): Promise<AccountAgentApy>;
|
|
797
921
|
/**
|
|
798
922
|
* Daily cumulative NET earnings for the window, scoped to a chain/asset.
|
|
799
923
|
* Backs the "recent earnings" subline, whose figure must reconcile with the
|
|
@@ -822,7 +946,7 @@ type AgentApyOptions = {
|
|
|
822
946
|
chainId?: number;
|
|
823
947
|
};
|
|
824
948
|
|
|
825
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
949
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "POOL_CATALOG_UNSUPPORTED" | "POOL_SELECTION_UNSUPPORTED" | "VALIDATION_INVALID_DAYS";
|
|
826
950
|
declare class OwneyError extends Error {
|
|
827
951
|
readonly code: OwneyErrorCode;
|
|
828
952
|
readonly details?: Record<string, unknown>;
|
|
@@ -986,6 +1110,7 @@ declare class OwneySDK {
|
|
|
986
1110
|
private orgAgentConfig;
|
|
987
1111
|
private orgAgentConfigPromise;
|
|
988
1112
|
private zyfaiRpcUrls?;
|
|
1113
|
+
private userPoolCustomization;
|
|
989
1114
|
private routingApiBaseUrl?;
|
|
990
1115
|
private referralSource?;
|
|
991
1116
|
private cachedSponsoredCallback;
|
|
@@ -1596,7 +1721,27 @@ declare class OwneySDK {
|
|
|
1596
1721
|
* agents that answered.
|
|
1597
1722
|
*/
|
|
1598
1723
|
getDailyEarnings({ agentId, days, tokenSymbol, chainIds, }: DailyEarningsOptions): Promise<AccountDailyEarnings>;
|
|
1599
|
-
|
|
1724
|
+
/**
|
|
1725
|
+
* The deposit-time pool catalogue (ROUT-569): every protocol with its
|
|
1726
|
+
* selectable pools (name, APY, TVL, link) for `asset` under `strategy`.
|
|
1727
|
+
* Defaults to the zyfai agent, the only one with pool customization today.
|
|
1728
|
+
*/
|
|
1729
|
+
getPoolCatalog(params: {
|
|
1730
|
+
asset: OwneySupportedTokens;
|
|
1731
|
+
strategy: "conservative" | "aggressive";
|
|
1732
|
+
agentId?: AgentId;
|
|
1733
|
+
}): Promise<PoolCatalogProtocol[]>;
|
|
1734
|
+
/**
|
|
1735
|
+
* Apply a user's deposit-time pool selection to their account (ROUT-569).
|
|
1736
|
+
* `strategy` is the one chosen in the deposit flow, passed through so pool
|
|
1737
|
+
* names validate against it rather than the user's stored strategy.
|
|
1738
|
+
*/
|
|
1739
|
+
setPoolSelection(params: {
|
|
1740
|
+
policy: OrgPoolPolicy;
|
|
1741
|
+
strategy?: "conservative" | "aggressive";
|
|
1742
|
+
agentId?: AgentId;
|
|
1743
|
+
}): Promise<void>;
|
|
1744
|
+
getAccountApy({ agentId, days, tokenSymbol, chainId: scope, }: AccountApyOptions): Promise<OwneyAccountApy | AccountAgentApy>;
|
|
1600
1745
|
/**
|
|
1601
1746
|
* Get transaction history for a specific agent, or all agents.
|
|
1602
1747
|
*
|
|
@@ -1738,4 +1883,4 @@ type StoredOrder = {
|
|
|
1738
1883
|
*/
|
|
1739
1884
|
declare function listOrders(now?: number): StoredOrder[];
|
|
1740
1885
|
|
|
1741
|
-
export { type AccountAgentApy, type AccountApyOptions, type AccountDailyEarnings, type AgentApy, type AgentApyDetails, type AgentBalance, AgentChainIncompatibleError, type AgentEarnings, type AgentHistoryEntry, type AgentHistoryPosition, type AgentId, AgentNotFoundError, type AgentSupportedAsset, type AgentSupportedAssets, type AgentUserProfile, type AgentWithdrawResult, type AgentsApyOptions, type AllocationAgentApy, type AllocationApyOptions, type ApyByChainAndAsset, type ApyHistoryPoint, type Asset, type AssetDailyEarnings, type AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DailyEarningsOptions, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, type LookbackDays, NotConnectedError, type OwneyAccountApy, type OwneyAgentApy, type OwneyAgentHistory, type OwneyAllocationApy, type OwneyBalances, type OwneyDepositResult, type OwneyEarnings, OwneyError, type OwneyErrorCode, type OwneyMultiDepositResult, type OwneyPosition, OwneySDK, type OwneySDKConfig, type OwneySIWXConfig, type OwneySupportedChainId, type OwneySupportedChains, type OwneySupportedTokens, type OwneyToken, type OwneyUserProfile, type OwneyWithdrawAllLeg, type OwneyWithdrawAllResult, type OwneyWithdrawResult, type PendingDeposit, type RebalanceLog, type SwapChainTokens, type SwapDirection, type SwapOrderStatus, type SwapQuote, type SwapQuoteParams, type SwapRail, type SwapStage, type SwapTokenInfo, type SwapTokenSearchResult, type WithdrawOptions, type WithdrawSwapRecord, type WithdrawSwapStatus, clearWithdrawSwap, createOwneySIWX, listPendingDeposits, listOrders as listPendingSwaps, listWithdrawSwaps, saveWithdrawSwap, setOwneyDebug, subscribeWithdrawSwaps, updateWithdrawSwap };
|
|
1886
|
+
export { type AccountAgentApy, type AccountApyOptions, type AccountDailyEarnings, type AgentApy, type AgentApyDetails, type AgentBalance, AgentChainIncompatibleError, type AgentEarnings, type AgentHistoryEntry, type AgentHistoryPosition, type AgentId, AgentNotFoundError, type AgentSupportedAsset, type AgentSupportedAssets, type AgentUserProfile, type AgentWithdrawResult, type AgentsApyOptions, type AllocationAgentApy, type AllocationApyOptions, type ApyByChainAndAsset, type ApyCoverage, type ApyHistoryPoint, type Asset, type AssetDailyEarnings, type AvailableAgent, type AvailableAgentsOptions, type AvailablePool, type ConnectionState, type DailyApyDays, type DailyEarningsOptions, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, type LookbackDays, NotConnectedError, type OrgPoolPolicy, type OrgPoolSelection, type OwneyAccountApy, type OwneyAgentApy, type OwneyAgentHistory, type OwneyAllocationApy, type OwneyBalances, type OwneyDepositResult, type OwneyEarnings, OwneyError, type OwneyErrorCode, type OwneyMultiDepositResult, type OwneyPosition, OwneySDK, type OwneySDKConfig, type OwneySIWXConfig, type OwneySupportedChainId, type OwneySupportedChains, type OwneySupportedTokens, type OwneyToken, type OwneyUserProfile, type OwneyWithdrawAllLeg, type OwneyWithdrawAllResult, type OwneyWithdrawResult, type PendingDeposit, type PoolCatalogProtocol, type RebalanceLog, type SwapChainTokens, type SwapDirection, type SwapOrderStatus, type SwapQuote, type SwapQuoteParams, type SwapRail, type SwapStage, type SwapTokenInfo, type SwapTokenSearchResult, type WithdrawOptions, type WithdrawSwapRecord, type WithdrawSwapStatus, clearWithdrawSwap, createOwneySIWX, listPendingDeposits, listOrders as listPendingSwaps, listWithdrawSwaps, saveWithdrawSwap, setOwneyDebug, subscribeWithdrawSwaps, updateWithdrawSwap };
|
package/dist/index.d.ts
CHANGED
|
@@ -276,6 +276,15 @@ interface OwneySDKConfig {
|
|
|
276
276
|
* already-deployed app: set `globalThis.__OWNEY_DEBUG__ = true` in devtools.
|
|
277
277
|
*/
|
|
278
278
|
debug?: boolean;
|
|
279
|
+
/**
|
|
280
|
+
* When true, the organization's pool policy is NOT applied on connect, so a
|
|
281
|
+
* user's own deposit-time pool selection (ROUT-569) is never overwritten by
|
|
282
|
+
* the org-level one on their next reconnect. Splitting and the rest of the
|
|
283
|
+
* org policy still apply. Turn this on in apps that expose the deposit-time
|
|
284
|
+
* Pools step (the spread flow); leave it off where the partner dashboard's
|
|
285
|
+
* pool customization is the source of truth.
|
|
286
|
+
*/
|
|
287
|
+
userPoolCustomization?: boolean;
|
|
279
288
|
/**
|
|
280
289
|
* Absolute URL of an ERC-7677 paymaster service. When set, deposits go out as
|
|
281
290
|
* an EIP-5792 `wallet_sendCalls` with `capabilities.paymasterService`, so a
|
|
@@ -374,6 +383,18 @@ type WithdrawOptions = {
|
|
|
374
383
|
type AccountApyOptions = {
|
|
375
384
|
agentId?: AgentId;
|
|
376
385
|
days: LookbackDays;
|
|
386
|
+
/**
|
|
387
|
+
* Chain to scope the daily series to, instead of the one `activateAgent`
|
|
388
|
+
* last set (ROUT-479).
|
|
389
|
+
*
|
|
390
|
+
* `"all"` blends every chain the wallet held that day, which is what the
|
|
391
|
+
* chart's "All chains" filter asks for. Unlike the history and earnings
|
|
392
|
+
* reads this needs no fan-out: the provider's daily-APY payload is already
|
|
393
|
+
* wallet-wide and names each position's chain, so the scope is a filter over
|
|
394
|
+
* one response rather than several calls. Omit for the active chain, which
|
|
395
|
+
* stays the default.
|
|
396
|
+
*/
|
|
397
|
+
chainId?: OwneySupportedChainId | "all";
|
|
377
398
|
/**
|
|
378
399
|
* Optional asset symbol (e.g. "USDC", "WETH") to scope the daily APY series
|
|
379
400
|
* to a specific asset on the active chain. Without it the series blends every
|
|
@@ -476,6 +497,61 @@ type OrgAgentConfig = {
|
|
|
476
497
|
poolPolicy?: OrgPoolPolicy | null;
|
|
477
498
|
};
|
|
478
499
|
|
|
500
|
+
/**
|
|
501
|
+
* Pool policy: Owney's org-level protocol/pool policy -> Zyfai's two mismatched
|
|
502
|
+
* write shapes.
|
|
503
|
+
*
|
|
504
|
+
* Zyfai splits "which protocols and pools may this user's funds sit in" across
|
|
505
|
+
* two calls that do not share an axis:
|
|
506
|
+
*
|
|
507
|
+
* updateUserProfile({ protocols }) per ASSET, chain-agnostic
|
|
508
|
+
* customizeBatch([{ protocolId, per (PROTOCOL, CHAIN), asset-agnostic
|
|
509
|
+
* chainId, pools, autoselect }])
|
|
510
|
+
*
|
|
511
|
+
* `protocols` is an explicit ALLOW-LIST: a protocol left out of it is disabled
|
|
512
|
+
* for that asset, on every chain, immediately. `customizeBatch` is the opposite
|
|
513
|
+
* shape — one record per (protocol, chain) pair, asset-agnostic, and per
|
|
514
|
+
* docs.zyf.ai it "creates or updates a record for the (user, protocol, chain)
|
|
515
|
+
* combination"; "previous customizations for the same combination are
|
|
516
|
+
* overwritten".
|
|
517
|
+
*
|
|
518
|
+
* That second property is the reason this file exists rather than a single
|
|
519
|
+
* flat translation: customizeBatch overwrites only the combinations it is
|
|
520
|
+
* GIVEN. The partner's stored policy (`OrgPoolPolicy.selections`) is sparse —
|
|
521
|
+
* only the protocols they actually narrowed appear — but the payload we send
|
|
522
|
+
* must be EXHAUSTIVE over every (protocol, chain) pair Zyfai offers this user.
|
|
523
|
+
* If we only sent the narrowed pairs, a partner who restricts Morpho, saves,
|
|
524
|
+
* then later re-ticks every pool box would never be able to undo it: nothing
|
|
525
|
+
* in the (sparse) policy would tell us to send a record clearing it, and the
|
|
526
|
+
* old restrictive record would stay live on the user's profile forever.
|
|
527
|
+
*
|
|
528
|
+
* Pure functions, kept out of the agent so the mapping is testable without a
|
|
529
|
+
* Zyfai client. See splitting.ts for the same pattern on the other lever.
|
|
530
|
+
*/
|
|
531
|
+
|
|
532
|
+
/** One selectable pool, with the figures the deposit-time Pools step shows. */
|
|
533
|
+
type AvailablePool = {
|
|
534
|
+
chainId: number;
|
|
535
|
+
token: string;
|
|
536
|
+
name: string;
|
|
537
|
+
/** combined_apy (pool + rewards), already a percent. null when absent. */
|
|
538
|
+
apy: number | null;
|
|
539
|
+
/** TVL in USD. null when absent. See ZyfCustomizationPoolInfo: `tvl` is in
|
|
540
|
+
* the pool's own token, `tvlUsd` is the dollar figure — only the latter is
|
|
541
|
+
* safe to show with a currency symbol. */
|
|
542
|
+
tvlUsd: number | null;
|
|
543
|
+
/** Per-pool deep link (e.g. the Morpho vault page). null when absent. */
|
|
544
|
+
link: string | null;
|
|
545
|
+
};
|
|
546
|
+
/** One protocol with its pools for the deposit asset — what the Pools step
|
|
547
|
+
* renders: a protocol row that opens to a list of selectable pools. */
|
|
548
|
+
type PoolCatalogProtocol = {
|
|
549
|
+
protocolId: string;
|
|
550
|
+
name: string;
|
|
551
|
+
logo: string | null;
|
|
552
|
+
pools: AvailablePool[];
|
|
553
|
+
};
|
|
554
|
+
|
|
479
555
|
interface OwneyDepositResult {
|
|
480
556
|
txHash: string;
|
|
481
557
|
smartWallet: string;
|
|
@@ -606,6 +682,28 @@ interface ApyHistoryPoint {
|
|
|
606
682
|
unit: string;
|
|
607
683
|
};
|
|
608
684
|
}
|
|
685
|
+
/**
|
|
686
|
+
* What the APY chart's chain/asset menus are allowed to offer, and how far
|
|
687
|
+
* back each option reaches (ROUT-479).
|
|
688
|
+
*
|
|
689
|
+
* An option only earns a place if some day in the window held a real position
|
|
690
|
+
* on it — a balance and a rate. Listing anything else would offer a filter
|
|
691
|
+
* that draws a blank chart. `days` is what the menu prints beside each row,
|
|
692
|
+
* and the legs genuinely differ: a wallet can hold USDC for a fortnight and
|
|
693
|
+
* WETH for three days.
|
|
694
|
+
*/
|
|
695
|
+
interface ApyCoverage {
|
|
696
|
+
chains: {
|
|
697
|
+
chainId: number;
|
|
698
|
+
days: number;
|
|
699
|
+
}[];
|
|
700
|
+
/** Legs whose `tokenSymbol` the provider left unset are absent — they cannot
|
|
701
|
+
* be named, so they cannot be picked. Their chain still counts. */
|
|
702
|
+
assets: {
|
|
703
|
+
asset: string;
|
|
704
|
+
days: number;
|
|
705
|
+
}[];
|
|
706
|
+
}
|
|
609
707
|
interface AccountAgentApy {
|
|
610
708
|
walletAddress: string;
|
|
611
709
|
weightedApyAfterFee?: number;
|
|
@@ -616,6 +714,8 @@ interface AccountAgentApy {
|
|
|
616
714
|
* date. Empty when the provider returns no daily history.
|
|
617
715
|
*/
|
|
618
716
|
history?: ApyHistoryPoint[];
|
|
717
|
+
/** Which chains/assets this history can be filtered down to. */
|
|
718
|
+
coverage?: ApyCoverage;
|
|
619
719
|
}
|
|
620
720
|
interface OwneyAccountApy {
|
|
621
721
|
totalApy: string;
|
|
@@ -779,6 +879,23 @@ interface IAgent {
|
|
|
779
879
|
* unchanged rather than break the connect.
|
|
780
880
|
*/
|
|
781
881
|
applyOrgPolicy?(state: ConnectionState, chainId: number, policy: OrgAgentConfig): Promise<void>;
|
|
882
|
+
/**
|
|
883
|
+
* The deposit-time pool catalogue for one asset and strategy: protocols with
|
|
884
|
+
* their selectable pools and figures. Optional — an agent with no pool
|
|
885
|
+
* customization omits it. (ROUT-569)
|
|
886
|
+
*/
|
|
887
|
+
getPoolCatalog?(params: {
|
|
888
|
+
asset: string;
|
|
889
|
+
strategy: "conservative" | "aggressive";
|
|
890
|
+
}): Promise<PoolCatalogProtocol[]>;
|
|
891
|
+
/**
|
|
892
|
+
* Apply a user's own pool selection to their account, driven by the
|
|
893
|
+
* deposit-time Pools step. Optional, and non-fatal like `applyOrgPolicy`.
|
|
894
|
+
* (ROUT-569)
|
|
895
|
+
*/
|
|
896
|
+
setPoolSelection?(policy: OrgPoolPolicy, opts?: {
|
|
897
|
+
strategy?: "conservative" | "aggressive";
|
|
898
|
+
}): Promise<void>;
|
|
782
899
|
deposit(state: ConnectionState, chainId: number, amount: string, asset: OwneySupportedTokens, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
|
|
783
900
|
withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
|
|
784
901
|
getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
|
|
@@ -793,7 +910,14 @@ interface IAgent {
|
|
|
793
910
|
* Optional asset symbol ("USDC" / "WETH") scoping the daily series to a
|
|
794
911
|
* single asset on the chain. Agents without per-asset positions ignore it.
|
|
795
912
|
*/
|
|
796
|
-
tokenSymbol?: string
|
|
913
|
+
tokenSymbol?: string,
|
|
914
|
+
/**
|
|
915
|
+
* Chain the series is scoped to, when that differs from the chain the
|
|
916
|
+
* connection is on. `null` spans every chain the wallet held (ROUT-479);
|
|
917
|
+
* omitted means `chainId`. Kept apart from `chainId` because that one
|
|
918
|
+
* still resolves the wallet and must stay a real, connected chain.
|
|
919
|
+
*/
|
|
920
|
+
scopeChainId?: number | null): Promise<AccountAgentApy>;
|
|
797
921
|
/**
|
|
798
922
|
* Daily cumulative NET earnings for the window, scoped to a chain/asset.
|
|
799
923
|
* Backs the "recent earnings" subline, whose figure must reconcile with the
|
|
@@ -822,7 +946,7 @@ type AgentApyOptions = {
|
|
|
822
946
|
chainId?: number;
|
|
823
947
|
};
|
|
824
948
|
|
|
825
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
949
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "POOL_CATALOG_UNSUPPORTED" | "POOL_SELECTION_UNSUPPORTED" | "VALIDATION_INVALID_DAYS";
|
|
826
950
|
declare class OwneyError extends Error {
|
|
827
951
|
readonly code: OwneyErrorCode;
|
|
828
952
|
readonly details?: Record<string, unknown>;
|
|
@@ -986,6 +1110,7 @@ declare class OwneySDK {
|
|
|
986
1110
|
private orgAgentConfig;
|
|
987
1111
|
private orgAgentConfigPromise;
|
|
988
1112
|
private zyfaiRpcUrls?;
|
|
1113
|
+
private userPoolCustomization;
|
|
989
1114
|
private routingApiBaseUrl?;
|
|
990
1115
|
private referralSource?;
|
|
991
1116
|
private cachedSponsoredCallback;
|
|
@@ -1596,7 +1721,27 @@ declare class OwneySDK {
|
|
|
1596
1721
|
* agents that answered.
|
|
1597
1722
|
*/
|
|
1598
1723
|
getDailyEarnings({ agentId, days, tokenSymbol, chainIds, }: DailyEarningsOptions): Promise<AccountDailyEarnings>;
|
|
1599
|
-
|
|
1724
|
+
/**
|
|
1725
|
+
* The deposit-time pool catalogue (ROUT-569): every protocol with its
|
|
1726
|
+
* selectable pools (name, APY, TVL, link) for `asset` under `strategy`.
|
|
1727
|
+
* Defaults to the zyfai agent, the only one with pool customization today.
|
|
1728
|
+
*/
|
|
1729
|
+
getPoolCatalog(params: {
|
|
1730
|
+
asset: OwneySupportedTokens;
|
|
1731
|
+
strategy: "conservative" | "aggressive";
|
|
1732
|
+
agentId?: AgentId;
|
|
1733
|
+
}): Promise<PoolCatalogProtocol[]>;
|
|
1734
|
+
/**
|
|
1735
|
+
* Apply a user's deposit-time pool selection to their account (ROUT-569).
|
|
1736
|
+
* `strategy` is the one chosen in the deposit flow, passed through so pool
|
|
1737
|
+
* names validate against it rather than the user's stored strategy.
|
|
1738
|
+
*/
|
|
1739
|
+
setPoolSelection(params: {
|
|
1740
|
+
policy: OrgPoolPolicy;
|
|
1741
|
+
strategy?: "conservative" | "aggressive";
|
|
1742
|
+
agentId?: AgentId;
|
|
1743
|
+
}): Promise<void>;
|
|
1744
|
+
getAccountApy({ agentId, days, tokenSymbol, chainId: scope, }: AccountApyOptions): Promise<OwneyAccountApy | AccountAgentApy>;
|
|
1600
1745
|
/**
|
|
1601
1746
|
* Get transaction history for a specific agent, or all agents.
|
|
1602
1747
|
*
|
|
@@ -1738,4 +1883,4 @@ type StoredOrder = {
|
|
|
1738
1883
|
*/
|
|
1739
1884
|
declare function listOrders(now?: number): StoredOrder[];
|
|
1740
1885
|
|
|
1741
|
-
export { type AccountAgentApy, type AccountApyOptions, type AccountDailyEarnings, type AgentApy, type AgentApyDetails, type AgentBalance, AgentChainIncompatibleError, type AgentEarnings, type AgentHistoryEntry, type AgentHistoryPosition, type AgentId, AgentNotFoundError, type AgentSupportedAsset, type AgentSupportedAssets, type AgentUserProfile, type AgentWithdrawResult, type AgentsApyOptions, type AllocationAgentApy, type AllocationApyOptions, type ApyByChainAndAsset, type ApyHistoryPoint, type Asset, type AssetDailyEarnings, type AvailableAgent, type AvailableAgentsOptions, type ConnectionState, type DailyApyDays, type DailyEarningsOptions, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, type LookbackDays, NotConnectedError, type OwneyAccountApy, type OwneyAgentApy, type OwneyAgentHistory, type OwneyAllocationApy, type OwneyBalances, type OwneyDepositResult, type OwneyEarnings, OwneyError, type OwneyErrorCode, type OwneyMultiDepositResult, type OwneyPosition, OwneySDK, type OwneySDKConfig, type OwneySIWXConfig, type OwneySupportedChainId, type OwneySupportedChains, type OwneySupportedTokens, type OwneyToken, type OwneyUserProfile, type OwneyWithdrawAllLeg, type OwneyWithdrawAllResult, type OwneyWithdrawResult, type PendingDeposit, type RebalanceLog, type SwapChainTokens, type SwapDirection, type SwapOrderStatus, type SwapQuote, type SwapQuoteParams, type SwapRail, type SwapStage, type SwapTokenInfo, type SwapTokenSearchResult, type WithdrawOptions, type WithdrawSwapRecord, type WithdrawSwapStatus, clearWithdrawSwap, createOwneySIWX, listPendingDeposits, listOrders as listPendingSwaps, listWithdrawSwaps, saveWithdrawSwap, setOwneyDebug, subscribeWithdrawSwaps, updateWithdrawSwap };
|
|
1886
|
+
export { type AccountAgentApy, type AccountApyOptions, type AccountDailyEarnings, type AgentApy, type AgentApyDetails, type AgentBalance, AgentChainIncompatibleError, type AgentEarnings, type AgentHistoryEntry, type AgentHistoryPosition, type AgentId, AgentNotFoundError, type AgentSupportedAsset, type AgentSupportedAssets, type AgentUserProfile, type AgentWithdrawResult, type AgentsApyOptions, type AllocationAgentApy, type AllocationApyOptions, type ApyByChainAndAsset, type ApyCoverage, type ApyHistoryPoint, type Asset, type AssetDailyEarnings, type AvailableAgent, type AvailableAgentsOptions, type AvailablePool, type ConnectionState, type DailyApyDays, type DailyEarningsOptions, type DailyEarningsPoint, type DepositCallback, type DepositOptions, type HistoryAction, type HistoryFilters, type HistoryOptions, type HistoryTransaction, type IAgent, InvalidHistoryCursorError, type LookbackDays, NotConnectedError, type OrgPoolPolicy, type OrgPoolSelection, type OwneyAccountApy, type OwneyAgentApy, type OwneyAgentHistory, type OwneyAllocationApy, type OwneyBalances, type OwneyDepositResult, type OwneyEarnings, OwneyError, type OwneyErrorCode, type OwneyMultiDepositResult, type OwneyPosition, OwneySDK, type OwneySDKConfig, type OwneySIWXConfig, type OwneySupportedChainId, type OwneySupportedChains, type OwneySupportedTokens, type OwneyToken, type OwneyUserProfile, type OwneyWithdrawAllLeg, type OwneyWithdrawAllResult, type OwneyWithdrawResult, type PendingDeposit, type PoolCatalogProtocol, type RebalanceLog, type SwapChainTokens, type SwapDirection, type SwapOrderStatus, type SwapQuote, type SwapQuoteParams, type SwapRail, type SwapStage, type SwapTokenInfo, type SwapTokenSearchResult, type WithdrawOptions, type WithdrawSwapRecord, type WithdrawSwapStatus, clearWithdrawSwap, createOwneySIWX, listPendingDeposits, listOrders as listPendingSwaps, listWithdrawSwaps, saveWithdrawSwap, setOwneyDebug, subscribeWithdrawSwaps, updateWithdrawSwap };
|
package/dist/index.js
CHANGED
|
@@ -470,7 +470,7 @@ function rawPoolApyForChain(entry, chainId, tokenSymbol) {
|
|
|
470
470
|
let weightedSum = 0;
|
|
471
471
|
let totalBalance = 0;
|
|
472
472
|
for (const p of entry.positions ?? []) {
|
|
473
|
-
if (p.chainId !== chainId) continue;
|
|
473
|
+
if (chainId !== void 0 && p.chainId !== chainId) continue;
|
|
474
474
|
if (tokenSymbol && p.tokenSymbol?.toUpperCase() !== tokenSymbol.toUpperCase()) continue;
|
|
475
475
|
const balance = p.balance ?? 0;
|
|
476
476
|
const apy = netApy(p.apy_withFee, p.apy, "apy_withFee");
|
|
@@ -480,6 +480,28 @@ function rawPoolApyForChain(entry, chainId, tokenSymbol) {
|
|
|
480
480
|
}
|
|
481
481
|
return totalBalance > 0 ? weightedSum / totalBalance : null;
|
|
482
482
|
}
|
|
483
|
+
function historyCoverage(raw) {
|
|
484
|
+
const chains = /* @__PURE__ */ new Map();
|
|
485
|
+
const assets = /* @__PURE__ */ new Map();
|
|
486
|
+
for (const date of Object.keys(raw.history ?? {}).sort()) {
|
|
487
|
+
void date;
|
|
488
|
+
const seenChains = /* @__PURE__ */ new Set();
|
|
489
|
+
const seenAssets = /* @__PURE__ */ new Set();
|
|
490
|
+
for (const p of (raw.history ?? {})[date].positions ?? []) {
|
|
491
|
+
const balance = p.balance ?? 0;
|
|
492
|
+
const apy = netApy(p.apy_withFee, p.apy, "apy_withFee");
|
|
493
|
+
if (balance <= 0 || typeof apy !== "number") continue;
|
|
494
|
+
seenChains.add(p.chainId);
|
|
495
|
+
if (p.tokenSymbol) seenAssets.add(p.tokenSymbol.toUpperCase());
|
|
496
|
+
}
|
|
497
|
+
for (const c of seenChains) chains.set(c, (chains.get(c) ?? 0) + 1);
|
|
498
|
+
for (const a of seenAssets) assets.set(a, (assets.get(a) ?? 0) + 1);
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
chains: [...chains].map(([chainId, days]) => ({ chainId, days })),
|
|
502
|
+
assets: [...assets].map(([asset, days]) => ({ asset, days }))
|
|
503
|
+
};
|
|
504
|
+
}
|
|
483
505
|
function mapApyHistory(raw, chainId, tokenSymbol) {
|
|
484
506
|
const history = Object.entries(raw.history ?? {}).map(([date, entry]) => ({
|
|
485
507
|
date,
|
|
@@ -490,7 +512,7 @@ function mapApyHistory(raw, chainId, tokenSymbol) {
|
|
|
490
512
|
...tokenSymbol ? {
|
|
491
513
|
historicalBalance: {
|
|
492
514
|
amount: (entry.positions ?? []).filter(
|
|
493
|
-
(p) => p.chainId === chainId && p.tokenSymbol?.toUpperCase() === tokenSymbol.toUpperCase() && Number.isFinite(p.balance) && p.balance > 0 && Number.isFinite(p.apy_withFee ?? p.apy)
|
|
515
|
+
(p) => (chainId === void 0 || p.chainId === chainId) && p.tokenSymbol?.toUpperCase() === tokenSymbol.toUpperCase() && Number.isFinite(p.balance) && p.balance > 0 && Number.isFinite(p.apy_withFee ?? p.apy)
|
|
494
516
|
).reduce((sum, p) => sum + p.balance, 0),
|
|
495
517
|
unit: tokenSymbol.toUpperCase()
|
|
496
518
|
}
|
|
@@ -500,7 +522,8 @@ function mapApyHistory(raw, chainId, tokenSymbol) {
|
|
|
500
522
|
walletAddress: raw.walletAddress,
|
|
501
523
|
weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0,
|
|
502
524
|
apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain),
|
|
503
|
-
history
|
|
525
|
+
history,
|
|
526
|
+
coverage: historyCoverage(raw)
|
|
504
527
|
};
|
|
505
528
|
}
|
|
506
529
|
function splitOpportunity(opportunity) {
|
|
@@ -959,6 +982,9 @@ function splittingNeedsUpdate(current, desired) {
|
|
|
959
982
|
}
|
|
960
983
|
|
|
961
984
|
// src/agents/zyfai/pool-policy.ts
|
|
985
|
+
function orgPolicyForConnect(policy, userPoolCustomization) {
|
|
986
|
+
return userPoolCustomization ? { ...policy, poolPolicy: null } : policy;
|
|
987
|
+
}
|
|
962
988
|
function toZyfaiCustomizations(policy, availableByProtocol, chainsByProtocol) {
|
|
963
989
|
const selectionByKey = /* @__PURE__ */ new Map();
|
|
964
990
|
for (const selection of policy.selections) {
|
|
@@ -1050,6 +1076,47 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
|
|
|
1050
1076
|
if (desiredProtocols === null) return false;
|
|
1051
1077
|
return !protocolListsEqual(current.protocols, desiredProtocols);
|
|
1052
1078
|
}
|
|
1079
|
+
function mapAvailablePools(raw) {
|
|
1080
|
+
const byChain = raw ?? {};
|
|
1081
|
+
if (typeof byChain !== "object" || byChain === null) return [];
|
|
1082
|
+
const result = [];
|
|
1083
|
+
for (const [chainIdStr, byToken] of Object.entries(byChain)) {
|
|
1084
|
+
const chainId = Number(chainIdStr);
|
|
1085
|
+
if (!Number.isFinite(chainId)) continue;
|
|
1086
|
+
for (const [token, entry] of Object.entries(byToken ?? {})) {
|
|
1087
|
+
for (const pool of entry?.pools ?? []) {
|
|
1088
|
+
if (!pool?.name) continue;
|
|
1089
|
+
result.push({
|
|
1090
|
+
chainId,
|
|
1091
|
+
token,
|
|
1092
|
+
name: pool.name,
|
|
1093
|
+
apy: pool.info?.combined_apy ?? null,
|
|
1094
|
+
tvlUsd: pool.info?.tvlUsd ?? null,
|
|
1095
|
+
link: pool.info?.link ?? null
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
return result;
|
|
1101
|
+
}
|
|
1102
|
+
function assemblePoolCatalog(protocols, poolsByProtocol, asset, chains) {
|
|
1103
|
+
const wanted = asset.toUpperCase();
|
|
1104
|
+
const allowedChains = chains && chains.length > 0 ? new Set(chains) : void 0;
|
|
1105
|
+
const catalog = [];
|
|
1106
|
+
for (const protocol of protocols) {
|
|
1107
|
+
const pools = (poolsByProtocol.get(protocol.id) ?? []).filter(
|
|
1108
|
+
(p) => p.token.toUpperCase() === wanted && (allowedChains === void 0 || allowedChains.has(p.chainId))
|
|
1109
|
+
);
|
|
1110
|
+
if (pools.length === 0) continue;
|
|
1111
|
+
catalog.push({
|
|
1112
|
+
protocolId: protocol.id,
|
|
1113
|
+
name: protocol.name,
|
|
1114
|
+
logo: protocol.imageUrl ?? null,
|
|
1115
|
+
pools
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
return catalog;
|
|
1119
|
+
}
|
|
1053
1120
|
|
|
1054
1121
|
// src/agents/zyfai/zyfai.agent.ts
|
|
1055
1122
|
var ERC7579_IS_MODULE_INSTALLED_ABI = parseAbi([
|
|
@@ -1476,7 +1543,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1476
1543
|
* connecting, so a Zyfai hiccup must leave the user connected with their
|
|
1477
1544
|
* profile unchanged, never fail activation.
|
|
1478
1545
|
*/
|
|
1479
|
-
async applyPoolPolicy(policy) {
|
|
1546
|
+
async applyPoolPolicy(policy, opts = {}) {
|
|
1480
1547
|
try {
|
|
1481
1548
|
const { protocols: universe } = await this.sdk.getAvailableProtocols(
|
|
1482
1549
|
this.supportedChainIds[0]
|
|
@@ -1490,7 +1557,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1490
1557
|
universeIds,
|
|
1491
1558
|
chainsByProtocol
|
|
1492
1559
|
});
|
|
1493
|
-
let strategy;
|
|
1560
|
+
let strategy = opts.strategy;
|
|
1494
1561
|
const desiredProtocols = deriveProtocols(
|
|
1495
1562
|
policy,
|
|
1496
1563
|
universeIds,
|
|
@@ -1570,6 +1637,50 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1570
1637
|
);
|
|
1571
1638
|
}
|
|
1572
1639
|
}
|
|
1640
|
+
/**
|
|
1641
|
+
* The deposit-time Pools step's catalogue: every protocol Zyfai offers this
|
|
1642
|
+
* user, each with the pools (name, APY, TVL, link) selectable for `asset`
|
|
1643
|
+
* under `strategy`. Sourced from the same two Zyfai calls `applyPoolPolicy`
|
|
1644
|
+
* uses, so "shown" and "selectable" are one set. A protocol whose pool
|
|
1645
|
+
* lookup fails is skipped rather than failing the whole catalogue.
|
|
1646
|
+
*/
|
|
1647
|
+
async getPoolCatalog(params) {
|
|
1648
|
+
const { protocols: universe } = await this.sdk.getAvailableProtocols(
|
|
1649
|
+
this.supportedChainIds[0]
|
|
1650
|
+
);
|
|
1651
|
+
const poolResults = await Promise.all(
|
|
1652
|
+
universe.map(async (protocol) => {
|
|
1653
|
+
try {
|
|
1654
|
+
const raw = await this.sdk.getAvailablePools(
|
|
1655
|
+
protocol.id,
|
|
1656
|
+
params.strategy
|
|
1657
|
+
);
|
|
1658
|
+
return [protocol.id, mapAvailablePools(raw)];
|
|
1659
|
+
} catch (error) {
|
|
1660
|
+
console.warn(
|
|
1661
|
+
`[zyfai] getPoolCatalog: getAvailablePools(${protocol.id}) failed, skipping (non-fatal):`,
|
|
1662
|
+
error instanceof Error ? error.message : String(error)
|
|
1663
|
+
);
|
|
1664
|
+
return null;
|
|
1665
|
+
}
|
|
1666
|
+
})
|
|
1667
|
+
);
|
|
1668
|
+
const poolsByProtocol = /* @__PURE__ */ new Map();
|
|
1669
|
+
for (const result of poolResults) {
|
|
1670
|
+
if (result) poolsByProtocol.set(result[0], result[1]);
|
|
1671
|
+
}
|
|
1672
|
+
return assemblePoolCatalog(universe, poolsByProtocol, params.asset);
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Apply a user's own pool selection (the deposit-time Pools step) to their
|
|
1676
|
+
* Zyfai profile. Same two writes as the org path — this is `applyPoolPolicy`
|
|
1677
|
+
* driven by the user's `policy` instead of the organization's, with the
|
|
1678
|
+
* deposit's chosen `strategy` passed through so pool names validate against
|
|
1679
|
+
* the strategy the user just picked rather than their stored one.
|
|
1680
|
+
*/
|
|
1681
|
+
async setPoolSelection(policy, opts = {}) {
|
|
1682
|
+
await this.applyPoolPolicy(policy, opts);
|
|
1683
|
+
}
|
|
1573
1684
|
/**
|
|
1574
1685
|
* True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
|
|
1575
1686
|
* to this EOA — the "new wallet" kind that is predeployed on the chains it
|
|
@@ -1696,11 +1807,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1696
1807
|
);
|
|
1697
1808
|
return;
|
|
1698
1809
|
}
|
|
1699
|
-
await this.ensureSessionKey(
|
|
1700
|
-
ownerAddress,
|
|
1701
|
-
chainId,
|
|
1702
|
-
wallet.address
|
|
1703
|
-
);
|
|
1810
|
+
await this.ensureSessionKey(ownerAddress, chainId, wallet.address);
|
|
1704
1811
|
} catch (error) {
|
|
1705
1812
|
console.warn(
|
|
1706
1813
|
"[zyfai] session-key check at activation failed (non-fatal):",
|
|
@@ -1811,11 +1918,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1811
1918
|
"zyfai:onboard",
|
|
1812
1919
|
"Safe already has code -> no deploy needed, checking the session key"
|
|
1813
1920
|
);
|
|
1814
|
-
await this.ensureSessionKey(
|
|
1815
|
-
ownerAddress,
|
|
1816
|
-
chainId,
|
|
1817
|
-
wallet.address
|
|
1818
|
-
);
|
|
1921
|
+
await this.ensureSessionKey(ownerAddress, chainId, wallet.address);
|
|
1819
1922
|
return wallet.address;
|
|
1820
1923
|
}
|
|
1821
1924
|
const poolFirst = await this.isPredeployedPoolWallet(
|
|
@@ -1982,14 +2085,17 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1982
2085
|
this.earningsRefreshes.set(key2, pending);
|
|
1983
2086
|
return pending;
|
|
1984
2087
|
}
|
|
1985
|
-
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
2088
|
+
async getAccountApy(state, chainId, days, tokenSymbol, scopeChainId) {
|
|
1986
2089
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1987
2090
|
const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
|
|
1988
|
-
|
|
2091
|
+
const scope = scopeChainId === null ? void 0 : scopeChainId ?? chainId;
|
|
2092
|
+
return mapApyHistory(raw, scope, tokenSymbol);
|
|
1989
2093
|
}
|
|
1990
2094
|
async getDailyEarnings(state, chainId, days, tokenSymbol) {
|
|
1991
2095
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1992
|
-
const start = new Date(
|
|
2096
|
+
const start = new Date(
|
|
2097
|
+
Date.now() - (DayFilterMapping[days] + 1) * 864e5
|
|
2098
|
+
);
|
|
1993
2099
|
const raw = await this.sdk.getDailyEarnings(
|
|
1994
2100
|
smartWallet,
|
|
1995
2101
|
start.toISOString().slice(0, 10)
|
|
@@ -2111,6 +2217,9 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2111
2217
|
|
|
2112
2218
|
// src/lib/history-fanout.ts
|
|
2113
2219
|
var SEPARATOR = "@";
|
|
2220
|
+
function isSupportedChainId(value) {
|
|
2221
|
+
return SUPPORTED_CHAIN_IDS.includes(value);
|
|
2222
|
+
}
|
|
2114
2223
|
function fanoutKey(leg) {
|
|
2115
2224
|
return leg.chainId === void 0 ? leg.agentId : `${leg.agentId}${SEPARATOR}${leg.chainId}`;
|
|
2116
2225
|
}
|
|
@@ -2133,6 +2242,16 @@ function decodeFanoutCursor(token) {
|
|
|
2133
2242
|
}
|
|
2134
2243
|
return parsed;
|
|
2135
2244
|
}
|
|
2245
|
+
function transactionChainId(entry) {
|
|
2246
|
+
let found;
|
|
2247
|
+
for (const tx of entry.transactions ?? []) {
|
|
2248
|
+
if (tx.chainId === void 0) continue;
|
|
2249
|
+
if (!isSupportedChainId(tx.chainId)) return void 0;
|
|
2250
|
+
if (found !== void 0 && found !== tx.chainId) return void 0;
|
|
2251
|
+
found = tx.chainId;
|
|
2252
|
+
}
|
|
2253
|
+
return found;
|
|
2254
|
+
}
|
|
2136
2255
|
function mergeHistoryPages(pages) {
|
|
2137
2256
|
const merged = [];
|
|
2138
2257
|
const nextCursorMap = {};
|
|
@@ -2151,7 +2270,9 @@ function mergeHistoryPages(pages) {
|
|
|
2151
2270
|
const prior = seen.get(id);
|
|
2152
2271
|
if (prior) {
|
|
2153
2272
|
prior.legs += 1;
|
|
2154
|
-
|
|
2273
|
+
const own = transactionChainId(prior.entry);
|
|
2274
|
+
if (own === void 0) delete prior.entry.chainId;
|
|
2275
|
+
else prior.entry.chainId = own;
|
|
2155
2276
|
continue;
|
|
2156
2277
|
}
|
|
2157
2278
|
const entry = leg.chainId === void 0 ? { ...e } : { ...e, chainId: leg.chainId };
|
|
@@ -4293,6 +4414,7 @@ var OwneySDK = class {
|
|
|
4293
4414
|
orgAgentConfig;
|
|
4294
4415
|
orgAgentConfigPromise = null;
|
|
4295
4416
|
zyfaiRpcUrls;
|
|
4417
|
+
userPoolCustomization = false;
|
|
4296
4418
|
routingApiBaseUrl;
|
|
4297
4419
|
referralSource;
|
|
4298
4420
|
cachedSponsoredCallback = null;
|
|
@@ -4318,6 +4440,7 @@ var OwneySDK = class {
|
|
|
4318
4440
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
4319
4441
|
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
4320
4442
|
this.referralSource = config.referralSource;
|
|
4443
|
+
this.userPoolCustomization = config.userPoolCustomization ?? false;
|
|
4321
4444
|
}
|
|
4322
4445
|
/**
|
|
4323
4446
|
* Establish connection state for all subsequent SDK calls.
|
|
@@ -4544,7 +4667,8 @@ var OwneySDK = class {
|
|
|
4544
4667
|
try {
|
|
4545
4668
|
const policy = await this.getOrgAgentConfig();
|
|
4546
4669
|
if (!policy) return;
|
|
4547
|
-
|
|
4670
|
+
const effective = orgPolicyForConnect(policy, this.userPoolCustomization);
|
|
4671
|
+
await agent.applyOrgPolicy(state, chainId, effective);
|
|
4548
4672
|
} catch (error) {
|
|
4549
4673
|
console.warn(
|
|
4550
4674
|
`[owney-sdk] applyOrgPolicy(${agent.id}) failed (non-fatal):`,
|
|
@@ -6361,20 +6485,57 @@ var OwneySDK = class {
|
|
|
6361
6485
|
chainId
|
|
6362
6486
|
};
|
|
6363
6487
|
}
|
|
6488
|
+
/**
|
|
6489
|
+
* The deposit-time pool catalogue (ROUT-569): every protocol with its
|
|
6490
|
+
* selectable pools (name, APY, TVL, link) for `asset` under `strategy`.
|
|
6491
|
+
* Defaults to the zyfai agent, the only one with pool customization today.
|
|
6492
|
+
*/
|
|
6493
|
+
async getPoolCatalog(params) {
|
|
6494
|
+
await this.ensureAgentsInitialized();
|
|
6495
|
+
const agent = this.getAgent(params.agentId ?? "zyfai");
|
|
6496
|
+
if (!agent.getPoolCatalog) {
|
|
6497
|
+
throw new OwneyError(
|
|
6498
|
+
"POOL_CATALOG_UNSUPPORTED",
|
|
6499
|
+
`Agent ${agent.id} does not support pool customization`
|
|
6500
|
+
);
|
|
6501
|
+
}
|
|
6502
|
+
return agent.getPoolCatalog({
|
|
6503
|
+
asset: params.asset,
|
|
6504
|
+
strategy: params.strategy
|
|
6505
|
+
});
|
|
6506
|
+
}
|
|
6507
|
+
/**
|
|
6508
|
+
* Apply a user's deposit-time pool selection to their account (ROUT-569).
|
|
6509
|
+
* `strategy` is the one chosen in the deposit flow, passed through so pool
|
|
6510
|
+
* names validate against it rather than the user's stored strategy.
|
|
6511
|
+
*/
|
|
6512
|
+
async setPoolSelection(params) {
|
|
6513
|
+
await this.ensureAgentsInitialized();
|
|
6514
|
+
const agent = this.getAgent(params.agentId ?? "zyfai");
|
|
6515
|
+
if (!agent.setPoolSelection) {
|
|
6516
|
+
throw new OwneyError(
|
|
6517
|
+
"POOL_SELECTION_UNSUPPORTED",
|
|
6518
|
+
`Agent ${agent.id} does not support pool customization`
|
|
6519
|
+
);
|
|
6520
|
+
}
|
|
6521
|
+
await agent.setPoolSelection(params.policy, { strategy: params.strategy });
|
|
6522
|
+
}
|
|
6364
6523
|
async getAccountApy({
|
|
6365
6524
|
agentId,
|
|
6366
6525
|
days,
|
|
6367
|
-
tokenSymbol
|
|
6526
|
+
tokenSymbol,
|
|
6527
|
+
chainId: scope
|
|
6368
6528
|
}) {
|
|
6369
6529
|
const state = this.requireState();
|
|
6370
6530
|
const chainId = this.requireChainId();
|
|
6531
|
+
const scopeChainId = scope === "all" ? null : scope;
|
|
6371
6532
|
if (agentId) {
|
|
6372
6533
|
const agent = this.getAgent(agentId);
|
|
6373
6534
|
return this.readAgent(
|
|
6374
6535
|
agent,
|
|
6375
6536
|
"accountApy",
|
|
6376
|
-
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
6377
|
-
{ days, tokenSymbol }
|
|
6537
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol, scopeChainId),
|
|
6538
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6378
6539
|
);
|
|
6379
6540
|
}
|
|
6380
6541
|
const activeAgents = this.getActiveAgents();
|
|
@@ -6385,8 +6546,14 @@ var OwneySDK = class {
|
|
|
6385
6546
|
const apy = await this.readAgent(
|
|
6386
6547
|
agent,
|
|
6387
6548
|
"accountApy",
|
|
6388
|
-
() => agent.getAccountApy(
|
|
6389
|
-
|
|
6549
|
+
() => agent.getAccountApy(
|
|
6550
|
+
state,
|
|
6551
|
+
chainId,
|
|
6552
|
+
days,
|
|
6553
|
+
tokenSymbol,
|
|
6554
|
+
scopeChainId
|
|
6555
|
+
),
|
|
6556
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6390
6557
|
);
|
|
6391
6558
|
return [id, apy];
|
|
6392
6559
|
})
|