@owney/sdk 0.7.16 → 0.7.17-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +425 -124
- package/dist/index.d.cts +25 -4
- package/dist/index.d.ts +25 -4
- package/dist/index.js +425 -124
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,165 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var OwneyError = class extends Error {
|
|
3
|
+
code;
|
|
4
|
+
details;
|
|
5
|
+
agentId;
|
|
6
|
+
constructor(code, message, details, agentId) {
|
|
7
|
+
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
8
|
+
super(`${prefix} ${message}`);
|
|
9
|
+
this.name = "OwneyError";
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.details = details;
|
|
12
|
+
this.agentId = agentId;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var AgentNotFoundError = class extends OwneyError {
|
|
16
|
+
constructor(agentId, available) {
|
|
17
|
+
super(
|
|
18
|
+
"AGENT_NOT_FOUND",
|
|
19
|
+
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
20
|
+
{ agentId, available },
|
|
21
|
+
agentId
|
|
22
|
+
);
|
|
23
|
+
this.name = "AgentNotFoundError";
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var NotConnectedError = class extends OwneyError {
|
|
27
|
+
constructor() {
|
|
28
|
+
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
29
|
+
this.name = "NotConnectedError";
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var AgentChainIncompatibleError = class extends OwneyError {
|
|
33
|
+
incompatibleAgents;
|
|
34
|
+
connectedChainId;
|
|
35
|
+
constructor(incompatibleAgents, connectedChainId) {
|
|
36
|
+
const details = incompatibleAgents.map(
|
|
37
|
+
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
38
|
+
).join("; ");
|
|
39
|
+
super(
|
|
40
|
+
"AGENT_CHAIN_INCOMPATIBLE",
|
|
41
|
+
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
42
|
+
{ incompatibleAgents, connectedChainId }
|
|
43
|
+
);
|
|
44
|
+
this.name = "AgentChainIncompatibleError";
|
|
45
|
+
this.incompatibleAgents = incompatibleAgents;
|
|
46
|
+
this.connectedChainId = connectedChainId;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/lib/rate-limit.ts
|
|
51
|
+
function rateLimitDelay(error, now = Date.now()) {
|
|
52
|
+
const seen = /* @__PURE__ */ new Set();
|
|
53
|
+
let limited = false;
|
|
54
|
+
let delay = 0;
|
|
55
|
+
function visit(value, depth = 0) {
|
|
56
|
+
if (depth > 6 || value == null) return;
|
|
57
|
+
if (typeof value === "string") {
|
|
58
|
+
if (/rate[ _-]?limit|too many requests|HTTP_429|\b429\b/i.test(value))
|
|
59
|
+
limited = true;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (typeof value !== "object" || seen.has(value)) return;
|
|
63
|
+
seen.add(value);
|
|
64
|
+
const record = value;
|
|
65
|
+
if ([record.status, record.statusCode, record.code].some(
|
|
66
|
+
(code) => String(code) === "429"
|
|
67
|
+
)) {
|
|
68
|
+
limited = true;
|
|
69
|
+
}
|
|
70
|
+
for (const key2 of ["retryAfterSeconds", "retryAfter"]) {
|
|
71
|
+
const seconds = Number(record[key2]);
|
|
72
|
+
if (Number.isFinite(seconds) && seconds > 0)
|
|
73
|
+
delay = Math.max(delay, seconds * 1e3);
|
|
74
|
+
}
|
|
75
|
+
const retryAt = Number(record.retryAt);
|
|
76
|
+
if (Number.isFinite(retryAt) && retryAt > now)
|
|
77
|
+
delay = Math.max(delay, retryAt - now);
|
|
78
|
+
const headers = record.headers;
|
|
79
|
+
const header = typeof headers?.get === "function" ? headers.get("Retry-After") : headers?.["retry-after"] ?? headers?.["Retry-After"];
|
|
80
|
+
if (typeof header === "string" || typeof header === "number") {
|
|
81
|
+
const seconds = Number(header);
|
|
82
|
+
const ms = Number.isFinite(seconds) ? seconds * 1e3 : Date.parse(String(header)) - now;
|
|
83
|
+
if (Number.isFinite(ms) && ms > 0) delay = Math.max(delay, ms);
|
|
84
|
+
}
|
|
85
|
+
for (const key2 of [
|
|
86
|
+
"message",
|
|
87
|
+
"code",
|
|
88
|
+
"cause",
|
|
89
|
+
"details",
|
|
90
|
+
"response",
|
|
91
|
+
"data",
|
|
92
|
+
"fields"
|
|
93
|
+
]) {
|
|
94
|
+
visit(record[key2], depth + 1);
|
|
95
|
+
}
|
|
96
|
+
for (const key2 of ["agentErrors", "failures"]) {
|
|
97
|
+
const entries = record[key2];
|
|
98
|
+
if (entries && typeof entries === "object") {
|
|
99
|
+
for (const entry of Object.values(entries)) visit(entry, depth + 1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
visit(error);
|
|
104
|
+
return limited ? delay : void 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/lib/agent-reads.ts
|
|
108
|
+
var AgentReads = class {
|
|
109
|
+
inFlight = /* @__PURE__ */ new Map();
|
|
110
|
+
cooldowns = /* @__PURE__ */ new Map();
|
|
111
|
+
// A reconnect must not reuse work started by the previous connection.
|
|
112
|
+
clearInFlight() {
|
|
113
|
+
this.inFlight.clear();
|
|
114
|
+
}
|
|
115
|
+
limited(agentId, until) {
|
|
116
|
+
return new OwneyError(
|
|
117
|
+
"AGENT_RATE_LIMITED",
|
|
118
|
+
"Too many requests. Please wait before trying again.",
|
|
119
|
+
{
|
|
120
|
+
statusCode: 429,
|
|
121
|
+
retryAt: until,
|
|
122
|
+
retryAfterSeconds: Math.max(0, Math.ceil((until - Date.now()) / 1e3))
|
|
123
|
+
},
|
|
124
|
+
agentId
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
run(agentId, key2, fetch2) {
|
|
128
|
+
const cooldown = this.cooldowns.get(agentId);
|
|
129
|
+
if (cooldown && cooldown.until > Date.now()) {
|
|
130
|
+
return Promise.reject(this.limited(agentId, cooldown.until));
|
|
131
|
+
}
|
|
132
|
+
const requestKey = JSON.stringify([agentId, key2]);
|
|
133
|
+
const existing = this.inFlight.get(requestKey);
|
|
134
|
+
if (existing) return existing;
|
|
135
|
+
const promise = Promise.resolve().then(fetch2).then(
|
|
136
|
+
(value) => {
|
|
137
|
+
if (this.cooldowns.get(agentId) === cooldown)
|
|
138
|
+
this.cooldowns.delete(agentId);
|
|
139
|
+
return value;
|
|
140
|
+
},
|
|
141
|
+
(error) => {
|
|
142
|
+
const requestedDelay = rateLimitDelay(error);
|
|
143
|
+
if (requestedDelay === void 0) throw error;
|
|
144
|
+
const previous = this.cooldowns.get(agentId);
|
|
145
|
+
const failures = previous && previous.until > Date.now() ? previous.failures : Math.min((previous?.failures ?? 0) + 1, 5);
|
|
146
|
+
const delay = Math.max(
|
|
147
|
+
requestedDelay,
|
|
148
|
+
Math.min(3e4 * 2 ** (failures - 1), 3e5)
|
|
149
|
+
);
|
|
150
|
+
const until = Math.max(previous?.until ?? 0, Date.now() + delay);
|
|
151
|
+
this.cooldowns.set(agentId, { until, failures });
|
|
152
|
+
throw this.limited(agentId, until);
|
|
153
|
+
}
|
|
154
|
+
).finally(() => {
|
|
155
|
+
if (this.inFlight.get(requestKey) === promise)
|
|
156
|
+
this.inFlight.delete(requestKey);
|
|
157
|
+
});
|
|
158
|
+
this.inFlight.set(requestKey, promise);
|
|
159
|
+
return promise;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
1
163
|
// src/agents/zyfai/zyfai.agent.ts
|
|
2
164
|
import { SMART_SESSIONS_VALIDATOR, ZyfaiSDK } from "@zyfai/sdk";
|
|
3
165
|
import { createPublicClient, http, parseAbi } from "viem";
|
|
@@ -67,55 +229,6 @@ function debugLog(scope, message, data) {
|
|
|
67
229
|
}
|
|
68
230
|
}
|
|
69
231
|
|
|
70
|
-
// src/errors.ts
|
|
71
|
-
var OwneyError = class extends Error {
|
|
72
|
-
code;
|
|
73
|
-
details;
|
|
74
|
-
agentId;
|
|
75
|
-
constructor(code, message, details, agentId) {
|
|
76
|
-
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
77
|
-
super(`${prefix} ${message}`);
|
|
78
|
-
this.name = "OwneyError";
|
|
79
|
-
this.code = code;
|
|
80
|
-
this.details = details;
|
|
81
|
-
this.agentId = agentId;
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
var AgentNotFoundError = class extends OwneyError {
|
|
85
|
-
constructor(agentId, available) {
|
|
86
|
-
super(
|
|
87
|
-
"AGENT_NOT_FOUND",
|
|
88
|
-
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
89
|
-
{ agentId, available },
|
|
90
|
-
agentId
|
|
91
|
-
);
|
|
92
|
-
this.name = "AgentNotFoundError";
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
var NotConnectedError = class extends OwneyError {
|
|
96
|
-
constructor() {
|
|
97
|
-
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
98
|
-
this.name = "NotConnectedError";
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
var AgentChainIncompatibleError = class extends OwneyError {
|
|
102
|
-
incompatibleAgents;
|
|
103
|
-
connectedChainId;
|
|
104
|
-
constructor(incompatibleAgents, connectedChainId) {
|
|
105
|
-
const details = incompatibleAgents.map(
|
|
106
|
-
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
107
|
-
).join("; ");
|
|
108
|
-
super(
|
|
109
|
-
"AGENT_CHAIN_INCOMPATIBLE",
|
|
110
|
-
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
111
|
-
{ incompatibleAgents, connectedChainId }
|
|
112
|
-
);
|
|
113
|
-
this.name = "AgentChainIncompatibleError";
|
|
114
|
-
this.incompatibleAgents = incompatibleAgents;
|
|
115
|
-
this.connectedChainId = connectedChainId;
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
232
|
// src/lib/utils.ts
|
|
120
233
|
var isValidChainId = (chainId) => {
|
|
121
234
|
if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
|
@@ -919,7 +1032,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
919
1032
|
// successful decode is cached forever; failures are NOT cached so a transient
|
|
920
1033
|
// RPC error retries on the next fetch.
|
|
921
1034
|
withdrawAmountCache = /* @__PURE__ */ new Map();
|
|
922
|
-
|
|
1035
|
+
earningsReads = /* @__PURE__ */ new Map();
|
|
1036
|
+
earningsRefreshes = /* @__PURE__ */ new Map();
|
|
1037
|
+
earningsSnapshot = null;
|
|
1038
|
+
earningsGeneration = 0;
|
|
923
1039
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
924
1040
|
this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
|
|
925
1041
|
this.sdk = new ZyfaiSDK({
|
|
@@ -1164,6 +1280,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1164
1280
|
}
|
|
1165
1281
|
// --- IAgent: Connection lifecycle ---
|
|
1166
1282
|
async disconnect() {
|
|
1283
|
+
this.earningsGeneration++;
|
|
1284
|
+
this.earningsReads.clear();
|
|
1285
|
+
this.earningsRefreshes.clear();
|
|
1286
|
+
this.earningsSnapshot = null;
|
|
1167
1287
|
if (this.connectedAddress && this.connectedChainId !== null) {
|
|
1168
1288
|
clearSession(this.connectedAddress, this.connectedChainId);
|
|
1169
1289
|
}
|
|
@@ -1712,26 +1832,59 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1712
1832
|
const raw = await this.sdk.getPortfolio(this.getAddress());
|
|
1713
1833
|
return mapBalances(raw, validChainId, smartWallet);
|
|
1714
1834
|
}
|
|
1835
|
+
earningsKey(state, chainId, smartWallet) {
|
|
1836
|
+
return JSON.stringify([
|
|
1837
|
+
state.walletAddress?.toLowerCase(),
|
|
1838
|
+
chainId,
|
|
1839
|
+
smartWallet.toLowerCase()
|
|
1840
|
+
]);
|
|
1841
|
+
}
|
|
1842
|
+
readEarnings(key2, smartWallet) {
|
|
1843
|
+
const existing = this.earningsReads.get(key2);
|
|
1844
|
+
if (existing) return existing;
|
|
1845
|
+
const generation = this.earningsGeneration;
|
|
1846
|
+
const pending = Promise.resolve().then(() => this.sdk.getOnchainEarnings(smartWallet)).then((raw) => {
|
|
1847
|
+
if (generation === this.earningsGeneration) {
|
|
1848
|
+
this.earningsSnapshot = { key: key2, raw, at: Date.now() };
|
|
1849
|
+
}
|
|
1850
|
+
return raw;
|
|
1851
|
+
}).finally(() => {
|
|
1852
|
+
if (this.earningsReads.get(key2) === pending)
|
|
1853
|
+
this.earningsReads.delete(key2);
|
|
1854
|
+
});
|
|
1855
|
+
this.earningsReads.set(key2, pending);
|
|
1856
|
+
return pending;
|
|
1857
|
+
}
|
|
1715
1858
|
async getEarnings(state, chainId) {
|
|
1716
1859
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1717
|
-
const raw = await this.
|
|
1860
|
+
const raw = await this.readEarnings(
|
|
1861
|
+
this.earningsKey(state, chainId, smartWallet),
|
|
1862
|
+
smartWallet
|
|
1863
|
+
);
|
|
1718
1864
|
return mapEarnings(raw, smartWallet);
|
|
1719
1865
|
}
|
|
1720
1866
|
async refreshEarnings(state, chainId) {
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1867
|
+
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1868
|
+
const key2 = this.earningsKey(state, chainId, smartWallet);
|
|
1869
|
+
const existing = this.earningsRefreshes.get(key2);
|
|
1870
|
+
if (existing) return existing;
|
|
1871
|
+
const generation = this.earningsGeneration;
|
|
1872
|
+
const pending = (async () => {
|
|
1873
|
+
const recent = this.earningsSnapshot;
|
|
1874
|
+
const current = recent?.key === key2 && Date.now() - recent.at < 5e3 ? recent.raw : await this.readEarnings(key2, smartWallet);
|
|
1725
1875
|
const lastCheck = current.data.lastCheckTimestamp ? Date.parse(current.data.lastCheckTimestamp) : Number.NaN;
|
|
1726
1876
|
const isFresh = Number.isFinite(lastCheck) && Date.now() - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
|
|
1727
1877
|
const earnings = isFresh ? current : await this.sdk.calculateOnchainEarnings(smartWallet);
|
|
1878
|
+
if (!isFresh && generation === this.earningsGeneration) {
|
|
1879
|
+
this.earningsSnapshot = { key: key2, raw: earnings, at: Date.now() };
|
|
1880
|
+
}
|
|
1728
1881
|
return mapEarnings(earnings, smartWallet);
|
|
1729
|
-
})()
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
}
|
|
1733
|
-
|
|
1734
|
-
|
|
1882
|
+
})().finally(() => {
|
|
1883
|
+
if (this.earningsRefreshes.get(key2) === pending)
|
|
1884
|
+
this.earningsRefreshes.delete(key2);
|
|
1885
|
+
});
|
|
1886
|
+
this.earningsRefreshes.set(key2, pending);
|
|
1887
|
+
return pending;
|
|
1735
1888
|
}
|
|
1736
1889
|
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
1737
1890
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
@@ -2653,6 +2806,17 @@ var OwneySDK = class {
|
|
|
2653
2806
|
cachedWethSponsoredCallback = null;
|
|
2654
2807
|
paymasterServiceUrl;
|
|
2655
2808
|
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
2809
|
+
agentReads = new AgentReads();
|
|
2810
|
+
activationChecks = /* @__PURE__ */ new Map();
|
|
2811
|
+
readAgent(agent, method, fetch2, params = null) {
|
|
2812
|
+
const key2 = JSON.stringify([
|
|
2813
|
+
this.state?.walletAddress.toLowerCase() ?? null,
|
|
2814
|
+
this.state?.chainId ?? null,
|
|
2815
|
+
method,
|
|
2816
|
+
params
|
|
2817
|
+
]);
|
|
2818
|
+
return this.agentReads.run(agent.id, key2, fetch2);
|
|
2819
|
+
}
|
|
2656
2820
|
initializingAgentsPromise = null;
|
|
2657
2821
|
constructor(config) {
|
|
2658
2822
|
this.apiKey = config.apiKey;
|
|
@@ -2679,6 +2843,8 @@ var OwneySDK = class {
|
|
|
2679
2843
|
"No accounts found. Ensure the wallet is unlocked and connected."
|
|
2680
2844
|
);
|
|
2681
2845
|
}
|
|
2846
|
+
this.agentReads.clearInFlight();
|
|
2847
|
+
this.activationChecks.clear();
|
|
2682
2848
|
this.state = { provider, walletAddress, chainId: null };
|
|
2683
2849
|
this.cachedSponsoredCallback = null;
|
|
2684
2850
|
this.cachedWethSponsoredCallback = null;
|
|
@@ -2694,6 +2860,8 @@ var OwneySDK = class {
|
|
|
2694
2860
|
}
|
|
2695
2861
|
this.activeAgents.clear();
|
|
2696
2862
|
this.disabledAgents.clear();
|
|
2863
|
+
this.agentReads.clearInFlight();
|
|
2864
|
+
this.activationChecks.clear();
|
|
2697
2865
|
this.state = null;
|
|
2698
2866
|
this.cachedSponsoredCallback = null;
|
|
2699
2867
|
this.cachedWethSponsoredCallback = null;
|
|
@@ -2924,6 +3092,37 @@ var OwneySDK = class {
|
|
|
2924
3092
|
}
|
|
2925
3093
|
return null;
|
|
2926
3094
|
}
|
|
3095
|
+
/**
|
|
3096
|
+
* Discover the agents actually returned by routing for this organization.
|
|
3097
|
+
* Consumers should use this instead of hardcoding a global agent roster.
|
|
3098
|
+
*/
|
|
3099
|
+
async getAvailableAgents(options = {}) {
|
|
3100
|
+
await this.ensureAgentsInitialized();
|
|
3101
|
+
const { chainId, asset, includeDisabled = false } = options;
|
|
3102
|
+
const available = [];
|
|
3103
|
+
for (const [id, agent] of this.agents) {
|
|
3104
|
+
const isEnabled = !this.isAgentDisabled(id);
|
|
3105
|
+
if (!includeDisabled && !isEnabled) continue;
|
|
3106
|
+
if (chainId !== void 0 && !agent.supportedChainIds.includes(chainId)) {
|
|
3107
|
+
continue;
|
|
3108
|
+
}
|
|
3109
|
+
if (asset !== void 0) {
|
|
3110
|
+
const supportsAsset = agent.supportedAssets.some(
|
|
3111
|
+
(entry) => (chainId === void 0 || entry.chainId === chainId) && entry.assets.some((candidate) => candidate.symbol === asset)
|
|
3112
|
+
);
|
|
3113
|
+
if (!supportsAsset) {
|
|
3114
|
+
continue;
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
available.push({
|
|
3118
|
+
id,
|
|
3119
|
+
isEnabled,
|
|
3120
|
+
supportedChainIds: agent.supportedChainIds,
|
|
3121
|
+
supportedAssets: agent.supportedAssets
|
|
3122
|
+
});
|
|
3123
|
+
}
|
|
3124
|
+
return available;
|
|
3125
|
+
}
|
|
2927
3126
|
// --- Account lifecycle ---
|
|
2928
3127
|
/**
|
|
2929
3128
|
* Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
|
|
@@ -2971,9 +3170,7 @@ var OwneySDK = class {
|
|
|
2971
3170
|
this.activeAgents.add(id);
|
|
2972
3171
|
}
|
|
2973
3172
|
state.chainId = chainId;
|
|
2974
|
-
this.activateAgentsInTurn(agents, state, chainId)
|
|
2975
|
-
console.error("activateAgent background init failed:", error);
|
|
2976
|
-
});
|
|
3173
|
+
await this.activateAgentsInTurn(agents, state, chainId);
|
|
2977
3174
|
return;
|
|
2978
3175
|
}
|
|
2979
3176
|
const compatible = [...this.agents.values()].filter(
|
|
@@ -2994,11 +3191,7 @@ var OwneySDK = class {
|
|
|
2994
3191
|
const enabledCompatible = compatible.filter(
|
|
2995
3192
|
(agent) => !this.isAgentDisabled(agent.id)
|
|
2996
3193
|
);
|
|
2997
|
-
this.activateAgentsInTurn(enabledCompatible, state, chainId)
|
|
2998
|
-
(error) => {
|
|
2999
|
-
console.error("activateAgent background init failed:", error);
|
|
3000
|
-
}
|
|
3001
|
-
);
|
|
3194
|
+
await this.activateAgentsInTurn(enabledCompatible, state, chainId);
|
|
3002
3195
|
}
|
|
3003
3196
|
/**
|
|
3004
3197
|
* Activate agents ONE AT A TIME, each followed by its org policy.
|
|
@@ -3035,7 +3228,7 @@ var OwneySDK = class {
|
|
|
3035
3228
|
if (firstError !== null) throw firstError;
|
|
3036
3229
|
}
|
|
3037
3230
|
/**
|
|
3038
|
-
* Deposit
|
|
3231
|
+
* Deposit into a specific agent, or distribute across all eligible agents.
|
|
3039
3232
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
3040
3233
|
* @param options - Deposit parameters
|
|
3041
3234
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -3043,7 +3236,8 @@ var OwneySDK = class {
|
|
|
3043
3236
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
3044
3237
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
3045
3238
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
3046
|
-
* @param options.agentId - Optional
|
|
3239
|
+
* @param options.agentId - Optional explicit target. Otherwise split equally,
|
|
3240
|
+
* or fund remaining agents when a recovery deposit cannot meet every minimum.
|
|
3047
3241
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
3048
3242
|
*/
|
|
3049
3243
|
async deposit(options) {
|
|
@@ -3081,7 +3275,7 @@ var OwneySDK = class {
|
|
|
3081
3275
|
});
|
|
3082
3276
|
const exemptFlags = await Promise.all(
|
|
3083
3277
|
eligibleAgents.map(
|
|
3084
|
-
(a) => this.hasExistingBalance(a, state, chainId, asset)
|
|
3278
|
+
(a) => this.hasExistingBalance(a, state, chainId, asset, true)
|
|
3085
3279
|
)
|
|
3086
3280
|
);
|
|
3087
3281
|
const exempt = new Set(
|
|
@@ -3095,23 +3289,67 @@ var OwneySDK = class {
|
|
|
3095
3289
|
exempt
|
|
3096
3290
|
);
|
|
3097
3291
|
if (agentAmounts.length === 0) {
|
|
3292
|
+
const agentsRequiringActivation = eligibleAgents.filter(
|
|
3293
|
+
(agent) => !exempt.has(agent.id)
|
|
3294
|
+
);
|
|
3295
|
+
const perAgentMinimum = agentsRequiringActivation.reduce(
|
|
3296
|
+
(highest, agent) => {
|
|
3297
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
3298
|
+
return minimum > highest ? minimum : highest;
|
|
3299
|
+
},
|
|
3300
|
+
0n
|
|
3301
|
+
);
|
|
3302
|
+
const minimumRequired = agentsRequiringActivation.length > 0 ? (perAgentMinimum > 0n ? perAgentMinimum : 1n) * BigInt(agentsRequiringActivation.length) : BigInt(eligibleAgents.length);
|
|
3098
3303
|
throw new OwneyError(
|
|
3099
3304
|
"DEPOSIT_AMOUNT_BELOW_MINIMUM",
|
|
3100
|
-
`Amount "${amount}" cannot
|
|
3101
|
-
{
|
|
3305
|
+
`Amount "${amount}" cannot activate every eligible agent. The combined minimum is "${minimumRequired.toString()}" for ${asset}.`,
|
|
3306
|
+
{
|
|
3307
|
+
amount,
|
|
3308
|
+
asset,
|
|
3309
|
+
chainId,
|
|
3310
|
+
minDepositAmount: minimumRequired.toString(),
|
|
3311
|
+
perAgentDepositAmount: perAgentMinimum.toString(),
|
|
3312
|
+
agentMinimums: agentsRequiringActivation.map((agent) => ({
|
|
3313
|
+
agentId: agent.id,
|
|
3314
|
+
minDepositAmount: this.getMinDepositAmount(
|
|
3315
|
+
agent,
|
|
3316
|
+
chainId,
|
|
3317
|
+
asset
|
|
3318
|
+
).toString()
|
|
3319
|
+
}))
|
|
3320
|
+
}
|
|
3102
3321
|
);
|
|
3103
3322
|
}
|
|
3104
3323
|
const agentResults = {};
|
|
3105
|
-
for (const
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3324
|
+
for (const [
|
|
3325
|
+
index,
|
|
3326
|
+
{ agent, amount: agentAmount }
|
|
3327
|
+
] of agentAmounts.entries()) {
|
|
3328
|
+
try {
|
|
3329
|
+
agentResults[agent.id] = await this.depositWithFallback(
|
|
3330
|
+
agent,
|
|
3331
|
+
state,
|
|
3332
|
+
chainId,
|
|
3333
|
+
agentAmount,
|
|
3334
|
+
asset,
|
|
3335
|
+
effectiveCallback,
|
|
3336
|
+
depositCallback
|
|
3337
|
+
);
|
|
3338
|
+
} catch (error) {
|
|
3339
|
+
if (Object.keys(agentResults).length === 0) throw error;
|
|
3340
|
+
throw new OwneyError(
|
|
3341
|
+
"DEPOSIT_PARTIAL_FAILURE",
|
|
3342
|
+
"Some deposits completed before another agent failed. Check activity and balances before depositing again; the failed transfer may still settle.",
|
|
3343
|
+
{
|
|
3344
|
+
agentResults,
|
|
3345
|
+
failedAgentId: agent.id,
|
|
3346
|
+
failedAmount: agentAmount,
|
|
3347
|
+
unattemptedAgentIds: agentAmounts.slice(index + 1).map(({ agent: agent2 }) => agent2.id),
|
|
3348
|
+
cause: error
|
|
3349
|
+
},
|
|
3350
|
+
agent.id
|
|
3351
|
+
);
|
|
3352
|
+
}
|
|
3115
3353
|
}
|
|
3116
3354
|
return { agentResults };
|
|
3117
3355
|
}
|
|
@@ -3184,6 +3422,17 @@ var OwneySDK = class {
|
|
|
3184
3422
|
}
|
|
3185
3423
|
splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
|
|
3186
3424
|
if (agents.length === 0) return [];
|
|
3425
|
+
const agentsRequiringActivation = agents.filter(
|
|
3426
|
+
(agent) => !exempt.has(agent.id)
|
|
3427
|
+
);
|
|
3428
|
+
if (agentsRequiringActivation.length === agents.length) {
|
|
3429
|
+
const highestMinimum2 = agents.reduce((highest, agent) => {
|
|
3430
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
3431
|
+
return minimum > highest ? minimum : highest;
|
|
3432
|
+
}, 0n);
|
|
3433
|
+
const minimumRequired2 = (highestMinimum2 > 0n ? highestMinimum2 : 1n) * BigInt(agents.length);
|
|
3434
|
+
if (totalAmount < minimumRequired2) return [];
|
|
3435
|
+
}
|
|
3187
3436
|
const perAgent = totalAmount / BigInt(agents.length);
|
|
3188
3437
|
const remainder = totalAmount % BigInt(agents.length);
|
|
3189
3438
|
const splits = agents.map((agent, i) => ({
|
|
@@ -3191,18 +3440,26 @@ var OwneySDK = class {
|
|
|
3191
3440
|
amount: i === agents.length - 1 ? perAgent + remainder : perAgent
|
|
3192
3441
|
}));
|
|
3193
3442
|
const valid = splits.filter(
|
|
3194
|
-
(s) => exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset)
|
|
3443
|
+
(s) => s.amount > 0n && (exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset))
|
|
3195
3444
|
);
|
|
3196
3445
|
if (valid.length === agents.length) {
|
|
3197
3446
|
return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
|
|
3198
3447
|
}
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
);
|
|
3448
|
+
const targets = agentsRequiringActivation.length > 0 ? agentsRequiringActivation : agents;
|
|
3449
|
+
const highestMinimum = targets.reduce((highest, agent) => {
|
|
3450
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
3451
|
+
return minimum > highest ? minimum : highest;
|
|
3452
|
+
}, 0n);
|
|
3453
|
+
const minimumRequired = (highestMinimum > 0n ? highestMinimum : 1n) * BigInt(targets.length);
|
|
3454
|
+
if (totalAmount < minimumRequired) return [];
|
|
3455
|
+
const targetShare = totalAmount / BigInt(targets.length);
|
|
3456
|
+
const targetRemainder = totalAmount % BigInt(targets.length);
|
|
3457
|
+
return targets.map((agent, index) => ({
|
|
3458
|
+
agent,
|
|
3459
|
+
amount: String(
|
|
3460
|
+
targetShare + (index === targets.length - 1 ? targetRemainder : 0n)
|
|
3461
|
+
)
|
|
3462
|
+
}));
|
|
3206
3463
|
}
|
|
3207
3464
|
async validateMinDepositAmount(agent, state, chainId, asset, amount) {
|
|
3208
3465
|
const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
|
|
@@ -3227,15 +3484,29 @@ var OwneySDK = class {
|
|
|
3227
3484
|
* per-agent minimum. Fails closed: any error reading balances returns
|
|
3228
3485
|
* false, so the minimum is enforced as today.
|
|
3229
3486
|
*/
|
|
3230
|
-
async hasExistingBalance(agent, state, chainId, asset) {
|
|
3487
|
+
async hasExistingBalance(agent, state, chainId, asset, requireReliableRead = false) {
|
|
3231
3488
|
try {
|
|
3232
3489
|
const balance = await agent.getBalances(state, chainId);
|
|
3233
3490
|
const target = asset.toLowerCase();
|
|
3234
3491
|
const token = balance.tokens.find(
|
|
3235
3492
|
(t) => t.chainId === chainId && t.asset.toLowerCase() === target
|
|
3236
3493
|
);
|
|
3237
|
-
|
|
3238
|
-
|
|
3494
|
+
const targetChainName = agent.supportedAssets.find((entry) => entry.chainId === chainId)?.chain?.trim().toUpperCase();
|
|
3495
|
+
const position = (balance.positions ?? []).find((p) => {
|
|
3496
|
+
const positionChain = p.chain.trim().toUpperCase();
|
|
3497
|
+
const matchesChain = positionChain === String(chainId) || targetChainName !== void 0 && positionChain === targetChainName;
|
|
3498
|
+
return matchesChain && p.asset.toLowerCase() === target && Number(p.amount) > 0;
|
|
3499
|
+
});
|
|
3500
|
+
return !!token && Number(token.amount) > 0 || !!position;
|
|
3501
|
+
} catch (error) {
|
|
3502
|
+
if (requireReliableRead) {
|
|
3503
|
+
throw new OwneyError(
|
|
3504
|
+
"DEPOSIT_BALANCE_UNAVAILABLE",
|
|
3505
|
+
"Could not verify every agent balance. No deposit was submitted. Try again once balances are available.",
|
|
3506
|
+
{ agentId: agent.id, chainId, asset, cause: error },
|
|
3507
|
+
agent.id
|
|
3508
|
+
);
|
|
3509
|
+
}
|
|
3239
3510
|
return false;
|
|
3240
3511
|
}
|
|
3241
3512
|
}
|
|
@@ -3438,7 +3709,8 @@ var OwneySDK = class {
|
|
|
3438
3709
|
const state = this.requireState();
|
|
3439
3710
|
const chainId = this.requireChainId();
|
|
3440
3711
|
if (agentId) {
|
|
3441
|
-
const
|
|
3712
|
+
const agent = this.getAgent(agentId);
|
|
3713
|
+
const result = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3442
3714
|
return result;
|
|
3443
3715
|
}
|
|
3444
3716
|
let totalBalance = 0;
|
|
@@ -3446,12 +3718,13 @@ var OwneySDK = class {
|
|
|
3446
3718
|
const entries = [...this.getActiveAgents().entries()];
|
|
3447
3719
|
const balanceResults = await Promise.allSettled(
|
|
3448
3720
|
entries.map(async ([id, agent]) => {
|
|
3449
|
-
const b = await agent.getBalances(state, chainId);
|
|
3721
|
+
const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3450
3722
|
return [id, b];
|
|
3451
3723
|
})
|
|
3452
3724
|
);
|
|
3453
3725
|
let successCount = 0;
|
|
3454
3726
|
const agentErrors = {};
|
|
3727
|
+
const agentFailures = [];
|
|
3455
3728
|
for (let i = 0; i < balanceResults.length; i++) {
|
|
3456
3729
|
const settledResult = balanceResults[i];
|
|
3457
3730
|
const [agentId2] = entries[i];
|
|
@@ -3463,13 +3736,14 @@ var OwneySDK = class {
|
|
|
3463
3736
|
continue;
|
|
3464
3737
|
}
|
|
3465
3738
|
const reason = settledResult.reason;
|
|
3739
|
+
agentFailures.push(reason);
|
|
3466
3740
|
agentErrors[agentId2] = reason instanceof Error ? reason.message : String(reason);
|
|
3467
3741
|
}
|
|
3468
3742
|
if (successCount === 0) {
|
|
3469
3743
|
throw new OwneyError(
|
|
3470
3744
|
"BALANCE_ALL_FAILED",
|
|
3471
3745
|
"Failed to fetch balances for all active agents.",
|
|
3472
|
-
{ agentErrors }
|
|
3746
|
+
{ agentErrors, failures: agentFailures }
|
|
3473
3747
|
);
|
|
3474
3748
|
}
|
|
3475
3749
|
return {
|
|
@@ -3487,14 +3761,15 @@ var OwneySDK = class {
|
|
|
3487
3761
|
const state = this.requireState();
|
|
3488
3762
|
const chainId = this.requireChainId();
|
|
3489
3763
|
if (agentId) {
|
|
3490
|
-
|
|
3764
|
+
const agent = this.getAgent(agentId);
|
|
3765
|
+
return this.readAgent(agent, "earnings", () => agent.getEarnings(state, chainId));
|
|
3491
3766
|
}
|
|
3492
3767
|
let totalEarnings = 0;
|
|
3493
3768
|
const results = {};
|
|
3494
3769
|
const entries = [...this.getActiveAgents().entries()];
|
|
3495
3770
|
const earningsResults = await Promise.all(
|
|
3496
3771
|
entries.map(async ([id, agent]) => {
|
|
3497
|
-
const e = await agent.getEarnings(state, chainId);
|
|
3772
|
+
const e = await this.readAgent(agent, "earnings", () => agent.getEarnings(state, chainId));
|
|
3498
3773
|
return [id, e];
|
|
3499
3774
|
})
|
|
3500
3775
|
);
|
|
@@ -3514,7 +3789,11 @@ var OwneySDK = class {
|
|
|
3514
3789
|
async refreshEarnings(agentId) {
|
|
3515
3790
|
const state = this.requireState();
|
|
3516
3791
|
const chainId = this.requireChainId();
|
|
3517
|
-
const refreshAgent = (agent) =>
|
|
3792
|
+
const refreshAgent = (agent) => this.readAgent(
|
|
3793
|
+
agent,
|
|
3794
|
+
agent.refreshEarnings ? "refreshEarnings" : "earnings",
|
|
3795
|
+
() => agent.refreshEarnings?.(state, chainId) ?? agent.getEarnings(state, chainId)
|
|
3796
|
+
);
|
|
3518
3797
|
if (agentId) return refreshAgent(this.getAgent(agentId));
|
|
3519
3798
|
let totalEarnings = 0;
|
|
3520
3799
|
const agentEarnings = {};
|
|
@@ -3545,11 +3824,12 @@ var OwneySDK = class {
|
|
|
3545
3824
|
const state = this.requireState();
|
|
3546
3825
|
const chainId = this.requireChainId();
|
|
3547
3826
|
if (agentId) {
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
tokenSymbol
|
|
3827
|
+
const agent = this.getAgent(agentId);
|
|
3828
|
+
return this.readAgent(
|
|
3829
|
+
agent,
|
|
3830
|
+
"accountApy",
|
|
3831
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
3832
|
+
{ days, tokenSymbol }
|
|
3553
3833
|
);
|
|
3554
3834
|
}
|
|
3555
3835
|
const activeAgents = this.getActiveAgents();
|
|
@@ -3557,18 +3837,18 @@ var OwneySDK = class {
|
|
|
3557
3837
|
const [apyResults, balanceResults] = await Promise.all([
|
|
3558
3838
|
Promise.all(
|
|
3559
3839
|
entries.map(async ([id, agent]) => {
|
|
3560
|
-
const apy = await
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
days,
|
|
3564
|
-
tokenSymbol
|
|
3840
|
+
const apy = await this.readAgent(
|
|
3841
|
+
agent,
|
|
3842
|
+
"accountApy",
|
|
3843
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
3844
|
+
{ days, tokenSymbol }
|
|
3565
3845
|
);
|
|
3566
3846
|
return [id, apy];
|
|
3567
3847
|
})
|
|
3568
3848
|
),
|
|
3569
3849
|
Promise.all(
|
|
3570
3850
|
entries.map(async ([id, agent]) => {
|
|
3571
|
-
const b = await agent.getBalances(state, chainId);
|
|
3851
|
+
const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3572
3852
|
return [id, Number(b.totalBalance)];
|
|
3573
3853
|
})
|
|
3574
3854
|
)
|
|
@@ -3625,7 +3905,8 @@ var OwneySDK = class {
|
|
|
3625
3905
|
const chainId = this.requireChainId();
|
|
3626
3906
|
const { agentId, filters } = options ?? {};
|
|
3627
3907
|
if (agentId) {
|
|
3628
|
-
|
|
3908
|
+
const agent = this.getAgent(agentId);
|
|
3909
|
+
return this.readAgent(agent, "history", () => agent.getHistory(state, chainId, filters), filters);
|
|
3629
3910
|
}
|
|
3630
3911
|
const activeAgents = [...this.getActiveAgents().values()];
|
|
3631
3912
|
const cursorMap = filters?.cursor ? decodeMultiAgentCursor(filters.cursor) : {};
|
|
@@ -3635,10 +3916,13 @@ var OwneySDK = class {
|
|
|
3635
3916
|
if (filters?.cursor && agentCursor === void 0) {
|
|
3636
3917
|
return { agentId: agent.id, page: null };
|
|
3637
3918
|
}
|
|
3638
|
-
const
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3919
|
+
const agentFilters = { ...filters, cursor: agentCursor };
|
|
3920
|
+
const page = await this.readAgent(
|
|
3921
|
+
agent,
|
|
3922
|
+
"history",
|
|
3923
|
+
() => agent.getHistory(state, chainId, agentFilters),
|
|
3924
|
+
agentFilters
|
|
3925
|
+
);
|
|
3642
3926
|
return { agentId: agent.id, page };
|
|
3643
3927
|
})
|
|
3644
3928
|
);
|
|
@@ -3678,13 +3962,14 @@ var OwneySDK = class {
|
|
|
3678
3962
|
const state = this.requireState();
|
|
3679
3963
|
const chainId = this.requireChainId();
|
|
3680
3964
|
if (agentId) {
|
|
3681
|
-
|
|
3965
|
+
const agent = this.getAgent(agentId);
|
|
3966
|
+
return this.readAgent(agent, "profile", () => agent.getUserProfile(state, chainId));
|
|
3682
3967
|
}
|
|
3683
3968
|
const results = {};
|
|
3684
3969
|
const entries = [...this.getActiveAgents().entries()];
|
|
3685
3970
|
const profileResults = await Promise.all(
|
|
3686
3971
|
entries.map(async ([id, agent]) => {
|
|
3687
|
-
const p = await agent.getUserProfile(state, chainId);
|
|
3972
|
+
const p = await this.readAgent(agent, "profile", () => agent.getUserProfile(state, chainId));
|
|
3688
3973
|
return [id, p];
|
|
3689
3974
|
})
|
|
3690
3975
|
);
|
|
@@ -3707,7 +3992,20 @@ var OwneySDK = class {
|
|
|
3707
3992
|
const chainId = this.requireChainId();
|
|
3708
3993
|
const agent = this.getAgent(agentId);
|
|
3709
3994
|
if (typeof agent.ensureAutoSelectProtocols !== "function") return false;
|
|
3710
|
-
|
|
3995
|
+
const key2 = JSON.stringify([
|
|
3996
|
+
state.walletAddress.toLowerCase(),
|
|
3997
|
+
agentId,
|
|
3998
|
+
chainId,
|
|
3999
|
+
asset
|
|
4000
|
+
]);
|
|
4001
|
+
const existing = this.activationChecks.get(key2);
|
|
4002
|
+
if (existing) return existing;
|
|
4003
|
+
const pending = Promise.resolve().then(() => agent.ensureAutoSelectProtocols(state, chainId, asset)).finally(() => {
|
|
4004
|
+
if (this.activationChecks.get(key2) === pending)
|
|
4005
|
+
this.activationChecks.delete(key2);
|
|
4006
|
+
});
|
|
4007
|
+
this.activationChecks.set(key2, pending);
|
|
4008
|
+
return pending;
|
|
3711
4009
|
}
|
|
3712
4010
|
/**
|
|
3713
4011
|
* One-time, user-paid approval of Permit2 on the sponsored WETH token for
|
|
@@ -3778,13 +4076,14 @@ var OwneySDK = class {
|
|
|
3778
4076
|
await this.ensureAgentsInitialized();
|
|
3779
4077
|
const agentOptions = { tokenSymbol, chainId };
|
|
3780
4078
|
if (agentId) {
|
|
3781
|
-
|
|
4079
|
+
const agent = this.getAgent(agentId);
|
|
4080
|
+
return this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
|
|
3782
4081
|
}
|
|
3783
4082
|
const results = {};
|
|
3784
4083
|
const agentEntries = [...this.agents.entries()];
|
|
3785
4084
|
const apyResults = await Promise.all(
|
|
3786
4085
|
agentEntries.map(async ([id, agent]) => {
|
|
3787
|
-
const apy = await agent.getAgentApy(days, agentOptions);
|
|
4086
|
+
const apy = await this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
|
|
3788
4087
|
return [id, apy];
|
|
3789
4088
|
})
|
|
3790
4089
|
);
|
|
@@ -3811,7 +4110,7 @@ var OwneySDK = class {
|
|
|
3811
4110
|
const entries = [...activeAgents.entries()];
|
|
3812
4111
|
const balanceResults = await Promise.allSettled(
|
|
3813
4112
|
entries.map(async ([id, agent]) => {
|
|
3814
|
-
const b = await agent.getBalances(state, chainId);
|
|
4113
|
+
const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3815
4114
|
return [id, b.positions ?? []];
|
|
3816
4115
|
})
|
|
3817
4116
|
);
|
|
@@ -3819,6 +4118,7 @@ var OwneySDK = class {
|
|
|
3819
4118
|
const allPositions = [];
|
|
3820
4119
|
let successCount = 0;
|
|
3821
4120
|
const agentErrors = {};
|
|
4121
|
+
const agentFailures = [];
|
|
3822
4122
|
for (let i = 0; i < balanceResults.length; i++) {
|
|
3823
4123
|
const settled = balanceResults[i];
|
|
3824
4124
|
const [aid] = entries[i];
|
|
@@ -3833,6 +4133,7 @@ var OwneySDK = class {
|
|
|
3833
4133
|
successCount += 1;
|
|
3834
4134
|
} else {
|
|
3835
4135
|
const reason = settled.reason;
|
|
4136
|
+
agentFailures.push(reason);
|
|
3836
4137
|
agentErrors[aid] = reason instanceof Error ? reason.message : String(reason);
|
|
3837
4138
|
console.error(`getAllocationApy agent "${aid}" failed:`, reason);
|
|
3838
4139
|
}
|
|
@@ -3841,7 +4142,7 @@ var OwneySDK = class {
|
|
|
3841
4142
|
throw new OwneyError(
|
|
3842
4143
|
"ALLOCATION_ALL_FAILED",
|
|
3843
4144
|
"Failed to fetch allocation APY: all agents failed.",
|
|
3844
|
-
{ agentErrors }
|
|
4145
|
+
{ agentErrors, failures: agentFailures }
|
|
3845
4146
|
);
|
|
3846
4147
|
}
|
|
3847
4148
|
const overall = computeAllocationApy(allPositions);
|