@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.cjs
CHANGED
|
@@ -31,6 +31,168 @@ __export(index_exports, {
|
|
|
31
31
|
});
|
|
32
32
|
module.exports = __toCommonJS(index_exports);
|
|
33
33
|
|
|
34
|
+
// src/errors.ts
|
|
35
|
+
var OwneyError = class extends Error {
|
|
36
|
+
code;
|
|
37
|
+
details;
|
|
38
|
+
agentId;
|
|
39
|
+
constructor(code, message, details, agentId) {
|
|
40
|
+
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
41
|
+
super(`${prefix} ${message}`);
|
|
42
|
+
this.name = "OwneyError";
|
|
43
|
+
this.code = code;
|
|
44
|
+
this.details = details;
|
|
45
|
+
this.agentId = agentId;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var AgentNotFoundError = class extends OwneyError {
|
|
49
|
+
constructor(agentId, available) {
|
|
50
|
+
super(
|
|
51
|
+
"AGENT_NOT_FOUND",
|
|
52
|
+
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
53
|
+
{ agentId, available },
|
|
54
|
+
agentId
|
|
55
|
+
);
|
|
56
|
+
this.name = "AgentNotFoundError";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var NotConnectedError = class extends OwneyError {
|
|
60
|
+
constructor() {
|
|
61
|
+
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
62
|
+
this.name = "NotConnectedError";
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var AgentChainIncompatibleError = class extends OwneyError {
|
|
66
|
+
incompatibleAgents;
|
|
67
|
+
connectedChainId;
|
|
68
|
+
constructor(incompatibleAgents, connectedChainId) {
|
|
69
|
+
const details = incompatibleAgents.map(
|
|
70
|
+
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
71
|
+
).join("; ");
|
|
72
|
+
super(
|
|
73
|
+
"AGENT_CHAIN_INCOMPATIBLE",
|
|
74
|
+
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
75
|
+
{ incompatibleAgents, connectedChainId }
|
|
76
|
+
);
|
|
77
|
+
this.name = "AgentChainIncompatibleError";
|
|
78
|
+
this.incompatibleAgents = incompatibleAgents;
|
|
79
|
+
this.connectedChainId = connectedChainId;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// src/lib/rate-limit.ts
|
|
84
|
+
function rateLimitDelay(error, now = Date.now()) {
|
|
85
|
+
const seen = /* @__PURE__ */ new Set();
|
|
86
|
+
let limited = false;
|
|
87
|
+
let delay = 0;
|
|
88
|
+
function visit(value, depth = 0) {
|
|
89
|
+
if (depth > 6 || value == null) return;
|
|
90
|
+
if (typeof value === "string") {
|
|
91
|
+
if (/rate[ _-]?limit|too many requests|HTTP_429|\b429\b/i.test(value))
|
|
92
|
+
limited = true;
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (typeof value !== "object" || seen.has(value)) return;
|
|
96
|
+
seen.add(value);
|
|
97
|
+
const record = value;
|
|
98
|
+
if ([record.status, record.statusCode, record.code].some(
|
|
99
|
+
(code) => String(code) === "429"
|
|
100
|
+
)) {
|
|
101
|
+
limited = true;
|
|
102
|
+
}
|
|
103
|
+
for (const key2 of ["retryAfterSeconds", "retryAfter"]) {
|
|
104
|
+
const seconds = Number(record[key2]);
|
|
105
|
+
if (Number.isFinite(seconds) && seconds > 0)
|
|
106
|
+
delay = Math.max(delay, seconds * 1e3);
|
|
107
|
+
}
|
|
108
|
+
const retryAt = Number(record.retryAt);
|
|
109
|
+
if (Number.isFinite(retryAt) && retryAt > now)
|
|
110
|
+
delay = Math.max(delay, retryAt - now);
|
|
111
|
+
const headers = record.headers;
|
|
112
|
+
const header = typeof headers?.get === "function" ? headers.get("Retry-After") : headers?.["retry-after"] ?? headers?.["Retry-After"];
|
|
113
|
+
if (typeof header === "string" || typeof header === "number") {
|
|
114
|
+
const seconds = Number(header);
|
|
115
|
+
const ms = Number.isFinite(seconds) ? seconds * 1e3 : Date.parse(String(header)) - now;
|
|
116
|
+
if (Number.isFinite(ms) && ms > 0) delay = Math.max(delay, ms);
|
|
117
|
+
}
|
|
118
|
+
for (const key2 of [
|
|
119
|
+
"message",
|
|
120
|
+
"code",
|
|
121
|
+
"cause",
|
|
122
|
+
"details",
|
|
123
|
+
"response",
|
|
124
|
+
"data",
|
|
125
|
+
"fields"
|
|
126
|
+
]) {
|
|
127
|
+
visit(record[key2], depth + 1);
|
|
128
|
+
}
|
|
129
|
+
for (const key2 of ["agentErrors", "failures"]) {
|
|
130
|
+
const entries = record[key2];
|
|
131
|
+
if (entries && typeof entries === "object") {
|
|
132
|
+
for (const entry of Object.values(entries)) visit(entry, depth + 1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
visit(error);
|
|
137
|
+
return limited ? delay : void 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/lib/agent-reads.ts
|
|
141
|
+
var AgentReads = class {
|
|
142
|
+
inFlight = /* @__PURE__ */ new Map();
|
|
143
|
+
cooldowns = /* @__PURE__ */ new Map();
|
|
144
|
+
// A reconnect must not reuse work started by the previous connection.
|
|
145
|
+
clearInFlight() {
|
|
146
|
+
this.inFlight.clear();
|
|
147
|
+
}
|
|
148
|
+
limited(agentId, until) {
|
|
149
|
+
return new OwneyError(
|
|
150
|
+
"AGENT_RATE_LIMITED",
|
|
151
|
+
"Too many requests. Please wait before trying again.",
|
|
152
|
+
{
|
|
153
|
+
statusCode: 429,
|
|
154
|
+
retryAt: until,
|
|
155
|
+
retryAfterSeconds: Math.max(0, Math.ceil((until - Date.now()) / 1e3))
|
|
156
|
+
},
|
|
157
|
+
agentId
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
run(agentId, key2, fetch2) {
|
|
161
|
+
const cooldown = this.cooldowns.get(agentId);
|
|
162
|
+
if (cooldown && cooldown.until > Date.now()) {
|
|
163
|
+
return Promise.reject(this.limited(agentId, cooldown.until));
|
|
164
|
+
}
|
|
165
|
+
const requestKey = JSON.stringify([agentId, key2]);
|
|
166
|
+
const existing = this.inFlight.get(requestKey);
|
|
167
|
+
if (existing) return existing;
|
|
168
|
+
const promise = Promise.resolve().then(fetch2).then(
|
|
169
|
+
(value) => {
|
|
170
|
+
if (this.cooldowns.get(agentId) === cooldown)
|
|
171
|
+
this.cooldowns.delete(agentId);
|
|
172
|
+
return value;
|
|
173
|
+
},
|
|
174
|
+
(error) => {
|
|
175
|
+
const requestedDelay = rateLimitDelay(error);
|
|
176
|
+
if (requestedDelay === void 0) throw error;
|
|
177
|
+
const previous = this.cooldowns.get(agentId);
|
|
178
|
+
const failures = previous && previous.until > Date.now() ? previous.failures : Math.min((previous?.failures ?? 0) + 1, 5);
|
|
179
|
+
const delay = Math.max(
|
|
180
|
+
requestedDelay,
|
|
181
|
+
Math.min(3e4 * 2 ** (failures - 1), 3e5)
|
|
182
|
+
);
|
|
183
|
+
const until = Math.max(previous?.until ?? 0, Date.now() + delay);
|
|
184
|
+
this.cooldowns.set(agentId, { until, failures });
|
|
185
|
+
throw this.limited(agentId, until);
|
|
186
|
+
}
|
|
187
|
+
).finally(() => {
|
|
188
|
+
if (this.inFlight.get(requestKey) === promise)
|
|
189
|
+
this.inFlight.delete(requestKey);
|
|
190
|
+
});
|
|
191
|
+
this.inFlight.set(requestKey, promise);
|
|
192
|
+
return promise;
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
34
196
|
// src/agents/zyfai/zyfai.agent.ts
|
|
35
197
|
var import_sdk = require("@zyfai/sdk");
|
|
36
198
|
var import_viem = require("viem");
|
|
@@ -100,55 +262,6 @@ function debugLog(scope, message, data) {
|
|
|
100
262
|
}
|
|
101
263
|
}
|
|
102
264
|
|
|
103
|
-
// src/errors.ts
|
|
104
|
-
var OwneyError = class extends Error {
|
|
105
|
-
code;
|
|
106
|
-
details;
|
|
107
|
-
agentId;
|
|
108
|
-
constructor(code, message, details, agentId) {
|
|
109
|
-
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
110
|
-
super(`${prefix} ${message}`);
|
|
111
|
-
this.name = "OwneyError";
|
|
112
|
-
this.code = code;
|
|
113
|
-
this.details = details;
|
|
114
|
-
this.agentId = agentId;
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
var AgentNotFoundError = class extends OwneyError {
|
|
118
|
-
constructor(agentId, available) {
|
|
119
|
-
super(
|
|
120
|
-
"AGENT_NOT_FOUND",
|
|
121
|
-
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
122
|
-
{ agentId, available },
|
|
123
|
-
agentId
|
|
124
|
-
);
|
|
125
|
-
this.name = "AgentNotFoundError";
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
var NotConnectedError = class extends OwneyError {
|
|
129
|
-
constructor() {
|
|
130
|
-
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
131
|
-
this.name = "NotConnectedError";
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
var AgentChainIncompatibleError = class extends OwneyError {
|
|
135
|
-
incompatibleAgents;
|
|
136
|
-
connectedChainId;
|
|
137
|
-
constructor(incompatibleAgents, connectedChainId) {
|
|
138
|
-
const details = incompatibleAgents.map(
|
|
139
|
-
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
140
|
-
).join("; ");
|
|
141
|
-
super(
|
|
142
|
-
"AGENT_CHAIN_INCOMPATIBLE",
|
|
143
|
-
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
144
|
-
{ incompatibleAgents, connectedChainId }
|
|
145
|
-
);
|
|
146
|
-
this.name = "AgentChainIncompatibleError";
|
|
147
|
-
this.incompatibleAgents = incompatibleAgents;
|
|
148
|
-
this.connectedChainId = connectedChainId;
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
265
|
// src/lib/utils.ts
|
|
153
266
|
var isValidChainId = (chainId) => {
|
|
154
267
|
if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
|
@@ -952,7 +1065,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
952
1065
|
// successful decode is cached forever; failures are NOT cached so a transient
|
|
953
1066
|
// RPC error retries on the next fetch.
|
|
954
1067
|
withdrawAmountCache = /* @__PURE__ */ new Map();
|
|
955
|
-
|
|
1068
|
+
earningsReads = /* @__PURE__ */ new Map();
|
|
1069
|
+
earningsRefreshes = /* @__PURE__ */ new Map();
|
|
1070
|
+
earningsSnapshot = null;
|
|
1071
|
+
earningsGeneration = 0;
|
|
956
1072
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
957
1073
|
this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
|
|
958
1074
|
this.sdk = new import_sdk.ZyfaiSDK({
|
|
@@ -1197,6 +1313,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1197
1313
|
}
|
|
1198
1314
|
// --- IAgent: Connection lifecycle ---
|
|
1199
1315
|
async disconnect() {
|
|
1316
|
+
this.earningsGeneration++;
|
|
1317
|
+
this.earningsReads.clear();
|
|
1318
|
+
this.earningsRefreshes.clear();
|
|
1319
|
+
this.earningsSnapshot = null;
|
|
1200
1320
|
if (this.connectedAddress && this.connectedChainId !== null) {
|
|
1201
1321
|
clearSession(this.connectedAddress, this.connectedChainId);
|
|
1202
1322
|
}
|
|
@@ -1745,26 +1865,59 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1745
1865
|
const raw = await this.sdk.getPortfolio(this.getAddress());
|
|
1746
1866
|
return mapBalances(raw, validChainId, smartWallet);
|
|
1747
1867
|
}
|
|
1868
|
+
earningsKey(state, chainId, smartWallet) {
|
|
1869
|
+
return JSON.stringify([
|
|
1870
|
+
state.walletAddress?.toLowerCase(),
|
|
1871
|
+
chainId,
|
|
1872
|
+
smartWallet.toLowerCase()
|
|
1873
|
+
]);
|
|
1874
|
+
}
|
|
1875
|
+
readEarnings(key2, smartWallet) {
|
|
1876
|
+
const existing = this.earningsReads.get(key2);
|
|
1877
|
+
if (existing) return existing;
|
|
1878
|
+
const generation = this.earningsGeneration;
|
|
1879
|
+
const pending = Promise.resolve().then(() => this.sdk.getOnchainEarnings(smartWallet)).then((raw) => {
|
|
1880
|
+
if (generation === this.earningsGeneration) {
|
|
1881
|
+
this.earningsSnapshot = { key: key2, raw, at: Date.now() };
|
|
1882
|
+
}
|
|
1883
|
+
return raw;
|
|
1884
|
+
}).finally(() => {
|
|
1885
|
+
if (this.earningsReads.get(key2) === pending)
|
|
1886
|
+
this.earningsReads.delete(key2);
|
|
1887
|
+
});
|
|
1888
|
+
this.earningsReads.set(key2, pending);
|
|
1889
|
+
return pending;
|
|
1890
|
+
}
|
|
1748
1891
|
async getEarnings(state, chainId) {
|
|
1749
1892
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1750
|
-
const raw = await this.
|
|
1893
|
+
const raw = await this.readEarnings(
|
|
1894
|
+
this.earningsKey(state, chainId, smartWallet),
|
|
1895
|
+
smartWallet
|
|
1896
|
+
);
|
|
1751
1897
|
return mapEarnings(raw, smartWallet);
|
|
1752
1898
|
}
|
|
1753
1899
|
async refreshEarnings(state, chainId) {
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1900
|
+
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1901
|
+
const key2 = this.earningsKey(state, chainId, smartWallet);
|
|
1902
|
+
const existing = this.earningsRefreshes.get(key2);
|
|
1903
|
+
if (existing) return existing;
|
|
1904
|
+
const generation = this.earningsGeneration;
|
|
1905
|
+
const pending = (async () => {
|
|
1906
|
+
const recent = this.earningsSnapshot;
|
|
1907
|
+
const current = recent?.key === key2 && Date.now() - recent.at < 5e3 ? recent.raw : await this.readEarnings(key2, smartWallet);
|
|
1758
1908
|
const lastCheck = current.data.lastCheckTimestamp ? Date.parse(current.data.lastCheckTimestamp) : Number.NaN;
|
|
1759
1909
|
const isFresh = Number.isFinite(lastCheck) && Date.now() - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
|
|
1760
1910
|
const earnings = isFresh ? current : await this.sdk.calculateOnchainEarnings(smartWallet);
|
|
1911
|
+
if (!isFresh && generation === this.earningsGeneration) {
|
|
1912
|
+
this.earningsSnapshot = { key: key2, raw: earnings, at: Date.now() };
|
|
1913
|
+
}
|
|
1761
1914
|
return mapEarnings(earnings, smartWallet);
|
|
1762
|
-
})()
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1915
|
+
})().finally(() => {
|
|
1916
|
+
if (this.earningsRefreshes.get(key2) === pending)
|
|
1917
|
+
this.earningsRefreshes.delete(key2);
|
|
1918
|
+
});
|
|
1919
|
+
this.earningsRefreshes.set(key2, pending);
|
|
1920
|
+
return pending;
|
|
1768
1921
|
}
|
|
1769
1922
|
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
1770
1923
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
@@ -2682,6 +2835,17 @@ var OwneySDK = class {
|
|
|
2682
2835
|
cachedWethSponsoredCallback = null;
|
|
2683
2836
|
paymasterServiceUrl;
|
|
2684
2837
|
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
2838
|
+
agentReads = new AgentReads();
|
|
2839
|
+
activationChecks = /* @__PURE__ */ new Map();
|
|
2840
|
+
readAgent(agent, method, fetch2, params = null) {
|
|
2841
|
+
const key2 = JSON.stringify([
|
|
2842
|
+
this.state?.walletAddress.toLowerCase() ?? null,
|
|
2843
|
+
this.state?.chainId ?? null,
|
|
2844
|
+
method,
|
|
2845
|
+
params
|
|
2846
|
+
]);
|
|
2847
|
+
return this.agentReads.run(agent.id, key2, fetch2);
|
|
2848
|
+
}
|
|
2685
2849
|
initializingAgentsPromise = null;
|
|
2686
2850
|
constructor(config) {
|
|
2687
2851
|
this.apiKey = config.apiKey;
|
|
@@ -2708,6 +2872,8 @@ var OwneySDK = class {
|
|
|
2708
2872
|
"No accounts found. Ensure the wallet is unlocked and connected."
|
|
2709
2873
|
);
|
|
2710
2874
|
}
|
|
2875
|
+
this.agentReads.clearInFlight();
|
|
2876
|
+
this.activationChecks.clear();
|
|
2711
2877
|
this.state = { provider, walletAddress, chainId: null };
|
|
2712
2878
|
this.cachedSponsoredCallback = null;
|
|
2713
2879
|
this.cachedWethSponsoredCallback = null;
|
|
@@ -2723,6 +2889,8 @@ var OwneySDK = class {
|
|
|
2723
2889
|
}
|
|
2724
2890
|
this.activeAgents.clear();
|
|
2725
2891
|
this.disabledAgents.clear();
|
|
2892
|
+
this.agentReads.clearInFlight();
|
|
2893
|
+
this.activationChecks.clear();
|
|
2726
2894
|
this.state = null;
|
|
2727
2895
|
this.cachedSponsoredCallback = null;
|
|
2728
2896
|
this.cachedWethSponsoredCallback = null;
|
|
@@ -2953,6 +3121,37 @@ var OwneySDK = class {
|
|
|
2953
3121
|
}
|
|
2954
3122
|
return null;
|
|
2955
3123
|
}
|
|
3124
|
+
/**
|
|
3125
|
+
* Discover the agents actually returned by routing for this organization.
|
|
3126
|
+
* Consumers should use this instead of hardcoding a global agent roster.
|
|
3127
|
+
*/
|
|
3128
|
+
async getAvailableAgents(options = {}) {
|
|
3129
|
+
await this.ensureAgentsInitialized();
|
|
3130
|
+
const { chainId, asset, includeDisabled = false } = options;
|
|
3131
|
+
const available = [];
|
|
3132
|
+
for (const [id, agent] of this.agents) {
|
|
3133
|
+
const isEnabled = !this.isAgentDisabled(id);
|
|
3134
|
+
if (!includeDisabled && !isEnabled) continue;
|
|
3135
|
+
if (chainId !== void 0 && !agent.supportedChainIds.includes(chainId)) {
|
|
3136
|
+
continue;
|
|
3137
|
+
}
|
|
3138
|
+
if (asset !== void 0) {
|
|
3139
|
+
const supportsAsset = agent.supportedAssets.some(
|
|
3140
|
+
(entry) => (chainId === void 0 || entry.chainId === chainId) && entry.assets.some((candidate) => candidate.symbol === asset)
|
|
3141
|
+
);
|
|
3142
|
+
if (!supportsAsset) {
|
|
3143
|
+
continue;
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
available.push({
|
|
3147
|
+
id,
|
|
3148
|
+
isEnabled,
|
|
3149
|
+
supportedChainIds: agent.supportedChainIds,
|
|
3150
|
+
supportedAssets: agent.supportedAssets
|
|
3151
|
+
});
|
|
3152
|
+
}
|
|
3153
|
+
return available;
|
|
3154
|
+
}
|
|
2956
3155
|
// --- Account lifecycle ---
|
|
2957
3156
|
/**
|
|
2958
3157
|
* Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
|
|
@@ -3000,9 +3199,7 @@ var OwneySDK = class {
|
|
|
3000
3199
|
this.activeAgents.add(id);
|
|
3001
3200
|
}
|
|
3002
3201
|
state.chainId = chainId;
|
|
3003
|
-
this.activateAgentsInTurn(agents, state, chainId)
|
|
3004
|
-
console.error("activateAgent background init failed:", error);
|
|
3005
|
-
});
|
|
3202
|
+
await this.activateAgentsInTurn(agents, state, chainId);
|
|
3006
3203
|
return;
|
|
3007
3204
|
}
|
|
3008
3205
|
const compatible = [...this.agents.values()].filter(
|
|
@@ -3023,11 +3220,7 @@ var OwneySDK = class {
|
|
|
3023
3220
|
const enabledCompatible = compatible.filter(
|
|
3024
3221
|
(agent) => !this.isAgentDisabled(agent.id)
|
|
3025
3222
|
);
|
|
3026
|
-
this.activateAgentsInTurn(enabledCompatible, state, chainId)
|
|
3027
|
-
(error) => {
|
|
3028
|
-
console.error("activateAgent background init failed:", error);
|
|
3029
|
-
}
|
|
3030
|
-
);
|
|
3223
|
+
await this.activateAgentsInTurn(enabledCompatible, state, chainId);
|
|
3031
3224
|
}
|
|
3032
3225
|
/**
|
|
3033
3226
|
* Activate agents ONE AT A TIME, each followed by its org policy.
|
|
@@ -3064,7 +3257,7 @@ var OwneySDK = class {
|
|
|
3064
3257
|
if (firstError !== null) throw firstError;
|
|
3065
3258
|
}
|
|
3066
3259
|
/**
|
|
3067
|
-
* Deposit
|
|
3260
|
+
* Deposit into a specific agent, or distribute across all eligible agents.
|
|
3068
3261
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
3069
3262
|
* @param options - Deposit parameters
|
|
3070
3263
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -3072,7 +3265,8 @@ var OwneySDK = class {
|
|
|
3072
3265
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
3073
3266
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
3074
3267
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
3075
|
-
* @param options.agentId - Optional
|
|
3268
|
+
* @param options.agentId - Optional explicit target. Otherwise split equally,
|
|
3269
|
+
* or fund remaining agents when a recovery deposit cannot meet every minimum.
|
|
3076
3270
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
3077
3271
|
*/
|
|
3078
3272
|
async deposit(options) {
|
|
@@ -3110,7 +3304,7 @@ var OwneySDK = class {
|
|
|
3110
3304
|
});
|
|
3111
3305
|
const exemptFlags = await Promise.all(
|
|
3112
3306
|
eligibleAgents.map(
|
|
3113
|
-
(a) => this.hasExistingBalance(a, state, chainId, asset)
|
|
3307
|
+
(a) => this.hasExistingBalance(a, state, chainId, asset, true)
|
|
3114
3308
|
)
|
|
3115
3309
|
);
|
|
3116
3310
|
const exempt = new Set(
|
|
@@ -3124,23 +3318,67 @@ var OwneySDK = class {
|
|
|
3124
3318
|
exempt
|
|
3125
3319
|
);
|
|
3126
3320
|
if (agentAmounts.length === 0) {
|
|
3321
|
+
const agentsRequiringActivation = eligibleAgents.filter(
|
|
3322
|
+
(agent) => !exempt.has(agent.id)
|
|
3323
|
+
);
|
|
3324
|
+
const perAgentMinimum = agentsRequiringActivation.reduce(
|
|
3325
|
+
(highest, agent) => {
|
|
3326
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
3327
|
+
return minimum > highest ? minimum : highest;
|
|
3328
|
+
},
|
|
3329
|
+
0n
|
|
3330
|
+
);
|
|
3331
|
+
const minimumRequired = agentsRequiringActivation.length > 0 ? (perAgentMinimum > 0n ? perAgentMinimum : 1n) * BigInt(agentsRequiringActivation.length) : BigInt(eligibleAgents.length);
|
|
3127
3332
|
throw new OwneyError(
|
|
3128
3333
|
"DEPOSIT_AMOUNT_BELOW_MINIMUM",
|
|
3129
|
-
`Amount "${amount}" cannot
|
|
3130
|
-
{
|
|
3334
|
+
`Amount "${amount}" cannot activate every eligible agent. The combined minimum is "${minimumRequired.toString()}" for ${asset}.`,
|
|
3335
|
+
{
|
|
3336
|
+
amount,
|
|
3337
|
+
asset,
|
|
3338
|
+
chainId,
|
|
3339
|
+
minDepositAmount: minimumRequired.toString(),
|
|
3340
|
+
perAgentDepositAmount: perAgentMinimum.toString(),
|
|
3341
|
+
agentMinimums: agentsRequiringActivation.map((agent) => ({
|
|
3342
|
+
agentId: agent.id,
|
|
3343
|
+
minDepositAmount: this.getMinDepositAmount(
|
|
3344
|
+
agent,
|
|
3345
|
+
chainId,
|
|
3346
|
+
asset
|
|
3347
|
+
).toString()
|
|
3348
|
+
}))
|
|
3349
|
+
}
|
|
3131
3350
|
);
|
|
3132
3351
|
}
|
|
3133
3352
|
const agentResults = {};
|
|
3134
|
-
for (const
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3353
|
+
for (const [
|
|
3354
|
+
index,
|
|
3355
|
+
{ agent, amount: agentAmount }
|
|
3356
|
+
] of agentAmounts.entries()) {
|
|
3357
|
+
try {
|
|
3358
|
+
agentResults[agent.id] = await this.depositWithFallback(
|
|
3359
|
+
agent,
|
|
3360
|
+
state,
|
|
3361
|
+
chainId,
|
|
3362
|
+
agentAmount,
|
|
3363
|
+
asset,
|
|
3364
|
+
effectiveCallback,
|
|
3365
|
+
depositCallback
|
|
3366
|
+
);
|
|
3367
|
+
} catch (error) {
|
|
3368
|
+
if (Object.keys(agentResults).length === 0) throw error;
|
|
3369
|
+
throw new OwneyError(
|
|
3370
|
+
"DEPOSIT_PARTIAL_FAILURE",
|
|
3371
|
+
"Some deposits completed before another agent failed. Check activity and balances before depositing again; the failed transfer may still settle.",
|
|
3372
|
+
{
|
|
3373
|
+
agentResults,
|
|
3374
|
+
failedAgentId: agent.id,
|
|
3375
|
+
failedAmount: agentAmount,
|
|
3376
|
+
unattemptedAgentIds: agentAmounts.slice(index + 1).map(({ agent: agent2 }) => agent2.id),
|
|
3377
|
+
cause: error
|
|
3378
|
+
},
|
|
3379
|
+
agent.id
|
|
3380
|
+
);
|
|
3381
|
+
}
|
|
3144
3382
|
}
|
|
3145
3383
|
return { agentResults };
|
|
3146
3384
|
}
|
|
@@ -3213,6 +3451,17 @@ var OwneySDK = class {
|
|
|
3213
3451
|
}
|
|
3214
3452
|
splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
|
|
3215
3453
|
if (agents.length === 0) return [];
|
|
3454
|
+
const agentsRequiringActivation = agents.filter(
|
|
3455
|
+
(agent) => !exempt.has(agent.id)
|
|
3456
|
+
);
|
|
3457
|
+
if (agentsRequiringActivation.length === agents.length) {
|
|
3458
|
+
const highestMinimum2 = agents.reduce((highest, agent) => {
|
|
3459
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
3460
|
+
return minimum > highest ? minimum : highest;
|
|
3461
|
+
}, 0n);
|
|
3462
|
+
const minimumRequired2 = (highestMinimum2 > 0n ? highestMinimum2 : 1n) * BigInt(agents.length);
|
|
3463
|
+
if (totalAmount < minimumRequired2) return [];
|
|
3464
|
+
}
|
|
3216
3465
|
const perAgent = totalAmount / BigInt(agents.length);
|
|
3217
3466
|
const remainder = totalAmount % BigInt(agents.length);
|
|
3218
3467
|
const splits = agents.map((agent, i) => ({
|
|
@@ -3220,18 +3469,26 @@ var OwneySDK = class {
|
|
|
3220
3469
|
amount: i === agents.length - 1 ? perAgent + remainder : perAgent
|
|
3221
3470
|
}));
|
|
3222
3471
|
const valid = splits.filter(
|
|
3223
|
-
(s) => exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset)
|
|
3472
|
+
(s) => s.amount > 0n && (exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset))
|
|
3224
3473
|
);
|
|
3225
3474
|
if (valid.length === agents.length) {
|
|
3226
3475
|
return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
|
|
3227
3476
|
}
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
);
|
|
3477
|
+
const targets = agentsRequiringActivation.length > 0 ? agentsRequiringActivation : agents;
|
|
3478
|
+
const highestMinimum = targets.reduce((highest, agent) => {
|
|
3479
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
3480
|
+
return minimum > highest ? minimum : highest;
|
|
3481
|
+
}, 0n);
|
|
3482
|
+
const minimumRequired = (highestMinimum > 0n ? highestMinimum : 1n) * BigInt(targets.length);
|
|
3483
|
+
if (totalAmount < minimumRequired) return [];
|
|
3484
|
+
const targetShare = totalAmount / BigInt(targets.length);
|
|
3485
|
+
const targetRemainder = totalAmount % BigInt(targets.length);
|
|
3486
|
+
return targets.map((agent, index) => ({
|
|
3487
|
+
agent,
|
|
3488
|
+
amount: String(
|
|
3489
|
+
targetShare + (index === targets.length - 1 ? targetRemainder : 0n)
|
|
3490
|
+
)
|
|
3491
|
+
}));
|
|
3235
3492
|
}
|
|
3236
3493
|
async validateMinDepositAmount(agent, state, chainId, asset, amount) {
|
|
3237
3494
|
const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
|
|
@@ -3256,15 +3513,29 @@ var OwneySDK = class {
|
|
|
3256
3513
|
* per-agent minimum. Fails closed: any error reading balances returns
|
|
3257
3514
|
* false, so the minimum is enforced as today.
|
|
3258
3515
|
*/
|
|
3259
|
-
async hasExistingBalance(agent, state, chainId, asset) {
|
|
3516
|
+
async hasExistingBalance(agent, state, chainId, asset, requireReliableRead = false) {
|
|
3260
3517
|
try {
|
|
3261
3518
|
const balance = await agent.getBalances(state, chainId);
|
|
3262
3519
|
const target = asset.toLowerCase();
|
|
3263
3520
|
const token = balance.tokens.find(
|
|
3264
3521
|
(t) => t.chainId === chainId && t.asset.toLowerCase() === target
|
|
3265
3522
|
);
|
|
3266
|
-
|
|
3267
|
-
|
|
3523
|
+
const targetChainName = agent.supportedAssets.find((entry) => entry.chainId === chainId)?.chain?.trim().toUpperCase();
|
|
3524
|
+
const position = (balance.positions ?? []).find((p) => {
|
|
3525
|
+
const positionChain = p.chain.trim().toUpperCase();
|
|
3526
|
+
const matchesChain = positionChain === String(chainId) || targetChainName !== void 0 && positionChain === targetChainName;
|
|
3527
|
+
return matchesChain && p.asset.toLowerCase() === target && Number(p.amount) > 0;
|
|
3528
|
+
});
|
|
3529
|
+
return !!token && Number(token.amount) > 0 || !!position;
|
|
3530
|
+
} catch (error) {
|
|
3531
|
+
if (requireReliableRead) {
|
|
3532
|
+
throw new OwneyError(
|
|
3533
|
+
"DEPOSIT_BALANCE_UNAVAILABLE",
|
|
3534
|
+
"Could not verify every agent balance. No deposit was submitted. Try again once balances are available.",
|
|
3535
|
+
{ agentId: agent.id, chainId, asset, cause: error },
|
|
3536
|
+
agent.id
|
|
3537
|
+
);
|
|
3538
|
+
}
|
|
3268
3539
|
return false;
|
|
3269
3540
|
}
|
|
3270
3541
|
}
|
|
@@ -3467,7 +3738,8 @@ var OwneySDK = class {
|
|
|
3467
3738
|
const state = this.requireState();
|
|
3468
3739
|
const chainId = this.requireChainId();
|
|
3469
3740
|
if (agentId) {
|
|
3470
|
-
const
|
|
3741
|
+
const agent = this.getAgent(agentId);
|
|
3742
|
+
const result = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3471
3743
|
return result;
|
|
3472
3744
|
}
|
|
3473
3745
|
let totalBalance = 0;
|
|
@@ -3475,12 +3747,13 @@ var OwneySDK = class {
|
|
|
3475
3747
|
const entries = [...this.getActiveAgents().entries()];
|
|
3476
3748
|
const balanceResults = await Promise.allSettled(
|
|
3477
3749
|
entries.map(async ([id, agent]) => {
|
|
3478
|
-
const b = await agent.getBalances(state, chainId);
|
|
3750
|
+
const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3479
3751
|
return [id, b];
|
|
3480
3752
|
})
|
|
3481
3753
|
);
|
|
3482
3754
|
let successCount = 0;
|
|
3483
3755
|
const agentErrors = {};
|
|
3756
|
+
const agentFailures = [];
|
|
3484
3757
|
for (let i = 0; i < balanceResults.length; i++) {
|
|
3485
3758
|
const settledResult = balanceResults[i];
|
|
3486
3759
|
const [agentId2] = entries[i];
|
|
@@ -3492,13 +3765,14 @@ var OwneySDK = class {
|
|
|
3492
3765
|
continue;
|
|
3493
3766
|
}
|
|
3494
3767
|
const reason = settledResult.reason;
|
|
3768
|
+
agentFailures.push(reason);
|
|
3495
3769
|
agentErrors[agentId2] = reason instanceof Error ? reason.message : String(reason);
|
|
3496
3770
|
}
|
|
3497
3771
|
if (successCount === 0) {
|
|
3498
3772
|
throw new OwneyError(
|
|
3499
3773
|
"BALANCE_ALL_FAILED",
|
|
3500
3774
|
"Failed to fetch balances for all active agents.",
|
|
3501
|
-
{ agentErrors }
|
|
3775
|
+
{ agentErrors, failures: agentFailures }
|
|
3502
3776
|
);
|
|
3503
3777
|
}
|
|
3504
3778
|
return {
|
|
@@ -3516,14 +3790,15 @@ var OwneySDK = class {
|
|
|
3516
3790
|
const state = this.requireState();
|
|
3517
3791
|
const chainId = this.requireChainId();
|
|
3518
3792
|
if (agentId) {
|
|
3519
|
-
|
|
3793
|
+
const agent = this.getAgent(agentId);
|
|
3794
|
+
return this.readAgent(agent, "earnings", () => agent.getEarnings(state, chainId));
|
|
3520
3795
|
}
|
|
3521
3796
|
let totalEarnings = 0;
|
|
3522
3797
|
const results = {};
|
|
3523
3798
|
const entries = [...this.getActiveAgents().entries()];
|
|
3524
3799
|
const earningsResults = await Promise.all(
|
|
3525
3800
|
entries.map(async ([id, agent]) => {
|
|
3526
|
-
const e = await agent.getEarnings(state, chainId);
|
|
3801
|
+
const e = await this.readAgent(agent, "earnings", () => agent.getEarnings(state, chainId));
|
|
3527
3802
|
return [id, e];
|
|
3528
3803
|
})
|
|
3529
3804
|
);
|
|
@@ -3543,7 +3818,11 @@ var OwneySDK = class {
|
|
|
3543
3818
|
async refreshEarnings(agentId) {
|
|
3544
3819
|
const state = this.requireState();
|
|
3545
3820
|
const chainId = this.requireChainId();
|
|
3546
|
-
const refreshAgent = (agent) =>
|
|
3821
|
+
const refreshAgent = (agent) => this.readAgent(
|
|
3822
|
+
agent,
|
|
3823
|
+
agent.refreshEarnings ? "refreshEarnings" : "earnings",
|
|
3824
|
+
() => agent.refreshEarnings?.(state, chainId) ?? agent.getEarnings(state, chainId)
|
|
3825
|
+
);
|
|
3547
3826
|
if (agentId) return refreshAgent(this.getAgent(agentId));
|
|
3548
3827
|
let totalEarnings = 0;
|
|
3549
3828
|
const agentEarnings = {};
|
|
@@ -3574,11 +3853,12 @@ var OwneySDK = class {
|
|
|
3574
3853
|
const state = this.requireState();
|
|
3575
3854
|
const chainId = this.requireChainId();
|
|
3576
3855
|
if (agentId) {
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
tokenSymbol
|
|
3856
|
+
const agent = this.getAgent(agentId);
|
|
3857
|
+
return this.readAgent(
|
|
3858
|
+
agent,
|
|
3859
|
+
"accountApy",
|
|
3860
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
3861
|
+
{ days, tokenSymbol }
|
|
3582
3862
|
);
|
|
3583
3863
|
}
|
|
3584
3864
|
const activeAgents = this.getActiveAgents();
|
|
@@ -3586,18 +3866,18 @@ var OwneySDK = class {
|
|
|
3586
3866
|
const [apyResults, balanceResults] = await Promise.all([
|
|
3587
3867
|
Promise.all(
|
|
3588
3868
|
entries.map(async ([id, agent]) => {
|
|
3589
|
-
const apy = await
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
days,
|
|
3593
|
-
tokenSymbol
|
|
3869
|
+
const apy = await this.readAgent(
|
|
3870
|
+
agent,
|
|
3871
|
+
"accountApy",
|
|
3872
|
+
() => agent.getAccountApy(state, chainId, days, tokenSymbol),
|
|
3873
|
+
{ days, tokenSymbol }
|
|
3594
3874
|
);
|
|
3595
3875
|
return [id, apy];
|
|
3596
3876
|
})
|
|
3597
3877
|
),
|
|
3598
3878
|
Promise.all(
|
|
3599
3879
|
entries.map(async ([id, agent]) => {
|
|
3600
|
-
const b = await agent.getBalances(state, chainId);
|
|
3880
|
+
const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3601
3881
|
return [id, Number(b.totalBalance)];
|
|
3602
3882
|
})
|
|
3603
3883
|
)
|
|
@@ -3654,7 +3934,8 @@ var OwneySDK = class {
|
|
|
3654
3934
|
const chainId = this.requireChainId();
|
|
3655
3935
|
const { agentId, filters } = options ?? {};
|
|
3656
3936
|
if (agentId) {
|
|
3657
|
-
|
|
3937
|
+
const agent = this.getAgent(agentId);
|
|
3938
|
+
return this.readAgent(agent, "history", () => agent.getHistory(state, chainId, filters), filters);
|
|
3658
3939
|
}
|
|
3659
3940
|
const activeAgents = [...this.getActiveAgents().values()];
|
|
3660
3941
|
const cursorMap = filters?.cursor ? decodeMultiAgentCursor(filters.cursor) : {};
|
|
@@ -3664,10 +3945,13 @@ var OwneySDK = class {
|
|
|
3664
3945
|
if (filters?.cursor && agentCursor === void 0) {
|
|
3665
3946
|
return { agentId: agent.id, page: null };
|
|
3666
3947
|
}
|
|
3667
|
-
const
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3948
|
+
const agentFilters = { ...filters, cursor: agentCursor };
|
|
3949
|
+
const page = await this.readAgent(
|
|
3950
|
+
agent,
|
|
3951
|
+
"history",
|
|
3952
|
+
() => agent.getHistory(state, chainId, agentFilters),
|
|
3953
|
+
agentFilters
|
|
3954
|
+
);
|
|
3671
3955
|
return { agentId: agent.id, page };
|
|
3672
3956
|
})
|
|
3673
3957
|
);
|
|
@@ -3707,13 +3991,14 @@ var OwneySDK = class {
|
|
|
3707
3991
|
const state = this.requireState();
|
|
3708
3992
|
const chainId = this.requireChainId();
|
|
3709
3993
|
if (agentId) {
|
|
3710
|
-
|
|
3994
|
+
const agent = this.getAgent(agentId);
|
|
3995
|
+
return this.readAgent(agent, "profile", () => agent.getUserProfile(state, chainId));
|
|
3711
3996
|
}
|
|
3712
3997
|
const results = {};
|
|
3713
3998
|
const entries = [...this.getActiveAgents().entries()];
|
|
3714
3999
|
const profileResults = await Promise.all(
|
|
3715
4000
|
entries.map(async ([id, agent]) => {
|
|
3716
|
-
const p = await agent.getUserProfile(state, chainId);
|
|
4001
|
+
const p = await this.readAgent(agent, "profile", () => agent.getUserProfile(state, chainId));
|
|
3717
4002
|
return [id, p];
|
|
3718
4003
|
})
|
|
3719
4004
|
);
|
|
@@ -3736,7 +4021,20 @@ var OwneySDK = class {
|
|
|
3736
4021
|
const chainId = this.requireChainId();
|
|
3737
4022
|
const agent = this.getAgent(agentId);
|
|
3738
4023
|
if (typeof agent.ensureAutoSelectProtocols !== "function") return false;
|
|
3739
|
-
|
|
4024
|
+
const key2 = JSON.stringify([
|
|
4025
|
+
state.walletAddress.toLowerCase(),
|
|
4026
|
+
agentId,
|
|
4027
|
+
chainId,
|
|
4028
|
+
asset
|
|
4029
|
+
]);
|
|
4030
|
+
const existing = this.activationChecks.get(key2);
|
|
4031
|
+
if (existing) return existing;
|
|
4032
|
+
const pending = Promise.resolve().then(() => agent.ensureAutoSelectProtocols(state, chainId, asset)).finally(() => {
|
|
4033
|
+
if (this.activationChecks.get(key2) === pending)
|
|
4034
|
+
this.activationChecks.delete(key2);
|
|
4035
|
+
});
|
|
4036
|
+
this.activationChecks.set(key2, pending);
|
|
4037
|
+
return pending;
|
|
3740
4038
|
}
|
|
3741
4039
|
/**
|
|
3742
4040
|
* One-time, user-paid approval of Permit2 on the sponsored WETH token for
|
|
@@ -3807,13 +4105,14 @@ var OwneySDK = class {
|
|
|
3807
4105
|
await this.ensureAgentsInitialized();
|
|
3808
4106
|
const agentOptions = { tokenSymbol, chainId };
|
|
3809
4107
|
if (agentId) {
|
|
3810
|
-
|
|
4108
|
+
const agent = this.getAgent(agentId);
|
|
4109
|
+
return this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
|
|
3811
4110
|
}
|
|
3812
4111
|
const results = {};
|
|
3813
4112
|
const agentEntries = [...this.agents.entries()];
|
|
3814
4113
|
const apyResults = await Promise.all(
|
|
3815
4114
|
agentEntries.map(async ([id, agent]) => {
|
|
3816
|
-
const apy = await agent.getAgentApy(days, agentOptions);
|
|
4115
|
+
const apy = await this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
|
|
3817
4116
|
return [id, apy];
|
|
3818
4117
|
})
|
|
3819
4118
|
);
|
|
@@ -3840,7 +4139,7 @@ var OwneySDK = class {
|
|
|
3840
4139
|
const entries = [...activeAgents.entries()];
|
|
3841
4140
|
const balanceResults = await Promise.allSettled(
|
|
3842
4141
|
entries.map(async ([id, agent]) => {
|
|
3843
|
-
const b = await agent.getBalances(state, chainId);
|
|
4142
|
+
const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
|
|
3844
4143
|
return [id, b.positions ?? []];
|
|
3845
4144
|
})
|
|
3846
4145
|
);
|
|
@@ -3848,6 +4147,7 @@ var OwneySDK = class {
|
|
|
3848
4147
|
const allPositions = [];
|
|
3849
4148
|
let successCount = 0;
|
|
3850
4149
|
const agentErrors = {};
|
|
4150
|
+
const agentFailures = [];
|
|
3851
4151
|
for (let i = 0; i < balanceResults.length; i++) {
|
|
3852
4152
|
const settled = balanceResults[i];
|
|
3853
4153
|
const [aid] = entries[i];
|
|
@@ -3862,6 +4162,7 @@ var OwneySDK = class {
|
|
|
3862
4162
|
successCount += 1;
|
|
3863
4163
|
} else {
|
|
3864
4164
|
const reason = settled.reason;
|
|
4165
|
+
agentFailures.push(reason);
|
|
3865
4166
|
agentErrors[aid] = reason instanceof Error ? reason.message : String(reason);
|
|
3866
4167
|
console.error(`getAllocationApy agent "${aid}" failed:`, reason);
|
|
3867
4168
|
}
|
|
@@ -3870,7 +4171,7 @@ var OwneySDK = class {
|
|
|
3870
4171
|
throw new OwneyError(
|
|
3871
4172
|
"ALLOCATION_ALL_FAILED",
|
|
3872
4173
|
"Failed to fetch allocation APY: all agents failed.",
|
|
3873
|
-
{ agentErrors }
|
|
4174
|
+
{ agentErrors, failures: agentFailures }
|
|
3874
4175
|
);
|
|
3875
4176
|
}
|
|
3876
4177
|
const overall = computeAllocationApy(allPositions);
|