@owney/sdk 0.7.28-beta.1 → 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 +176 -24
- package/dist/index.d.cts +149 -4
- package/dist/index.d.ts +149 -4
- package/dist/index.js +176 -24
- 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)
|
|
@@ -4327,6 +4433,7 @@ var OwneySDK = class {
|
|
|
4327
4433
|
orgAgentConfig;
|
|
4328
4434
|
orgAgentConfigPromise = null;
|
|
4329
4435
|
zyfaiRpcUrls;
|
|
4436
|
+
userPoolCustomization = false;
|
|
4330
4437
|
routingApiBaseUrl;
|
|
4331
4438
|
referralSource;
|
|
4332
4439
|
cachedSponsoredCallback = null;
|
|
@@ -4352,6 +4459,7 @@ var OwneySDK = class {
|
|
|
4352
4459
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
4353
4460
|
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
4354
4461
|
this.referralSource = config.referralSource;
|
|
4462
|
+
this.userPoolCustomization = config.userPoolCustomization ?? false;
|
|
4355
4463
|
}
|
|
4356
4464
|
/**
|
|
4357
4465
|
* Establish connection state for all subsequent SDK calls.
|
|
@@ -4578,7 +4686,8 @@ var OwneySDK = class {
|
|
|
4578
4686
|
try {
|
|
4579
4687
|
const policy = await this.getOrgAgentConfig();
|
|
4580
4688
|
if (!policy) return;
|
|
4581
|
-
|
|
4689
|
+
const effective = orgPolicyForConnect(policy, this.userPoolCustomization);
|
|
4690
|
+
await agent.applyOrgPolicy(state, chainId, effective);
|
|
4582
4691
|
} catch (error) {
|
|
4583
4692
|
console.warn(
|
|
4584
4693
|
`[owney-sdk] applyOrgPolicy(${agent.id}) failed (non-fatal):`,
|
|
@@ -6395,20 +6504,57 @@ var OwneySDK = class {
|
|
|
6395
6504
|
chainId
|
|
6396
6505
|
};
|
|
6397
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
|
+
}
|
|
6398
6542
|
async getAccountApy({
|
|
6399
6543
|
agentId,
|
|
6400
6544
|
days,
|
|
6401
|
-
tokenSymbol
|
|
6545
|
+
tokenSymbol,
|
|
6546
|
+
chainId: scope
|
|
6402
6547
|
}) {
|
|
6403
6548
|
const state = this.requireState();
|
|
6404
6549
|
const chainId = this.requireChainId();
|
|
6550
|
+
const scopeChainId = scope === "all" ? null : scope;
|
|
6405
6551
|
if (agentId) {
|
|
6406
6552
|
const agent = this.getAgent(agentId);
|
|
6407
6553
|
return this.readAgent(
|
|
6408
6554
|
agent,
|
|
6409
6555
|
"accountApy",
|
|
6410
|
-
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
6411
|
-
{ days, tokenSymbol }
|
|
6556
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol, scopeChainId),
|
|
6557
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6412
6558
|
);
|
|
6413
6559
|
}
|
|
6414
6560
|
const activeAgents = this.getActiveAgents();
|
|
@@ -6419,8 +6565,14 @@ var OwneySDK = class {
|
|
|
6419
6565
|
const apy = await this.readAgent(
|
|
6420
6566
|
agent,
|
|
6421
6567
|
"accountApy",
|
|
6422
|
-
() => agent.getAccountApy(
|
|
6423
|
-
|
|
6568
|
+
() => agent.getAccountApy(
|
|
6569
|
+
state,
|
|
6570
|
+
chainId,
|
|
6571
|
+
days,
|
|
6572
|
+
tokenSymbol,
|
|
6573
|
+
scopeChainId
|
|
6574
|
+
),
|
|
6575
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6424
6576
|
);
|
|
6425
6577
|
return [id, apy];
|
|
6426
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)
|
|
@@ -4308,6 +4414,7 @@ var OwneySDK = class {
|
|
|
4308
4414
|
orgAgentConfig;
|
|
4309
4415
|
orgAgentConfigPromise = null;
|
|
4310
4416
|
zyfaiRpcUrls;
|
|
4417
|
+
userPoolCustomization = false;
|
|
4311
4418
|
routingApiBaseUrl;
|
|
4312
4419
|
referralSource;
|
|
4313
4420
|
cachedSponsoredCallback = null;
|
|
@@ -4333,6 +4440,7 @@ var OwneySDK = class {
|
|
|
4333
4440
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
4334
4441
|
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
4335
4442
|
this.referralSource = config.referralSource;
|
|
4443
|
+
this.userPoolCustomization = config.userPoolCustomization ?? false;
|
|
4336
4444
|
}
|
|
4337
4445
|
/**
|
|
4338
4446
|
* Establish connection state for all subsequent SDK calls.
|
|
@@ -4559,7 +4667,8 @@ var OwneySDK = class {
|
|
|
4559
4667
|
try {
|
|
4560
4668
|
const policy = await this.getOrgAgentConfig();
|
|
4561
4669
|
if (!policy) return;
|
|
4562
|
-
|
|
4670
|
+
const effective = orgPolicyForConnect(policy, this.userPoolCustomization);
|
|
4671
|
+
await agent.applyOrgPolicy(state, chainId, effective);
|
|
4563
4672
|
} catch (error) {
|
|
4564
4673
|
console.warn(
|
|
4565
4674
|
`[owney-sdk] applyOrgPolicy(${agent.id}) failed (non-fatal):`,
|
|
@@ -6376,20 +6485,57 @@ var OwneySDK = class {
|
|
|
6376
6485
|
chainId
|
|
6377
6486
|
};
|
|
6378
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
|
+
}
|
|
6379
6523
|
async getAccountApy({
|
|
6380
6524
|
agentId,
|
|
6381
6525
|
days,
|
|
6382
|
-
tokenSymbol
|
|
6526
|
+
tokenSymbol,
|
|
6527
|
+
chainId: scope
|
|
6383
6528
|
}) {
|
|
6384
6529
|
const state = this.requireState();
|
|
6385
6530
|
const chainId = this.requireChainId();
|
|
6531
|
+
const scopeChainId = scope === "all" ? null : scope;
|
|
6386
6532
|
if (agentId) {
|
|
6387
6533
|
const agent = this.getAgent(agentId);
|
|
6388
6534
|
return this.readAgent(
|
|
6389
6535
|
agent,
|
|
6390
6536
|
"accountApy",
|
|
6391
|
-
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
6392
|
-
{ days, tokenSymbol }
|
|
6537
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol, scopeChainId),
|
|
6538
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6393
6539
|
);
|
|
6394
6540
|
}
|
|
6395
6541
|
const activeAgents = this.getActiveAgents();
|
|
@@ -6400,8 +6546,14 @@ var OwneySDK = class {
|
|
|
6400
6546
|
const apy = await this.readAgent(
|
|
6401
6547
|
agent,
|
|
6402
6548
|
"accountApy",
|
|
6403
|
-
() => agent.getAccountApy(
|
|
6404
|
-
|
|
6549
|
+
() => agent.getAccountApy(
|
|
6550
|
+
state,
|
|
6551
|
+
chainId,
|
|
6552
|
+
days,
|
|
6553
|
+
tokenSymbol,
|
|
6554
|
+
scopeChainId
|
|
6555
|
+
),
|
|
6556
|
+
{ days, tokenSymbol, scopeChainId }
|
|
6405
6557
|
);
|
|
6406
6558
|
return [id, apy];
|
|
6407
6559
|
})
|