@owney/sdk 0.7.25-beta.4 → 0.7.25-beta.7
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/README.md +67 -14
- package/dist/index.cjs +590 -181
- package/dist/index.d.cts +51 -9
- package/dist/index.d.ts +51 -9
- package/dist/index.js +531 -119
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -159,6 +159,34 @@ function rateLimitDelay(error, now = Date.now()) {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
// src/lib/agent-reads.ts
|
|
162
|
+
function rateLimitDiagnostics(error) {
|
|
163
|
+
const seen = /* @__PURE__ */ new Set();
|
|
164
|
+
let details = {};
|
|
165
|
+
function visit(value, depth = 0) {
|
|
166
|
+
if (depth > 6 || !value || typeof value !== "object" || seen.has(value))
|
|
167
|
+
return;
|
|
168
|
+
seen.add(value);
|
|
169
|
+
const record = value;
|
|
170
|
+
for (const key2 of [
|
|
171
|
+
"rpcSource",
|
|
172
|
+
"chainId",
|
|
173
|
+
"rpcMethod",
|
|
174
|
+
"providerRequestId",
|
|
175
|
+
"statusCode"
|
|
176
|
+
]) {
|
|
177
|
+
const candidate = record[key2];
|
|
178
|
+
if (candidate !== void 0 && details[key2] === void 0)
|
|
179
|
+
details = { ...details, [key2]: candidate };
|
|
180
|
+
}
|
|
181
|
+
for (const key2 of ["details", "cause", "response", "fields", "error"])
|
|
182
|
+
visit(record[key2], depth + 1);
|
|
183
|
+
}
|
|
184
|
+
visit(error);
|
|
185
|
+
return {
|
|
186
|
+
rpcSource: details.rpcSource ?? "agent-api",
|
|
187
|
+
...details
|
|
188
|
+
};
|
|
189
|
+
}
|
|
162
190
|
var AgentReads = class {
|
|
163
191
|
inFlight = /* @__PURE__ */ new Map();
|
|
164
192
|
cooldowns = /* @__PURE__ */ new Map();
|
|
@@ -166,14 +194,15 @@ var AgentReads = class {
|
|
|
166
194
|
clearInFlight() {
|
|
167
195
|
this.inFlight.clear();
|
|
168
196
|
}
|
|
169
|
-
limited(agentId, until) {
|
|
197
|
+
limited(agentId, until, diagnostics) {
|
|
170
198
|
return new OwneyError(
|
|
171
199
|
"AGENT_RATE_LIMITED",
|
|
172
200
|
"Too many requests. Please wait before trying again.",
|
|
173
201
|
{
|
|
174
202
|
statusCode: 429,
|
|
175
203
|
retryAt: until,
|
|
176
|
-
retryAfterSeconds: Math.max(0, Math.ceil((until - Date.now()) / 1e3))
|
|
204
|
+
retryAfterSeconds: Math.max(0, Math.ceil((until - Date.now()) / 1e3)),
|
|
205
|
+
...diagnostics
|
|
177
206
|
},
|
|
178
207
|
agentId
|
|
179
208
|
);
|
|
@@ -181,7 +210,9 @@ var AgentReads = class {
|
|
|
181
210
|
run(agentId, key2, fetch2) {
|
|
182
211
|
const cooldown = this.cooldowns.get(agentId);
|
|
183
212
|
if (cooldown && cooldown.until > Date.now()) {
|
|
184
|
-
return Promise.reject(
|
|
213
|
+
return Promise.reject(
|
|
214
|
+
this.limited(agentId, cooldown.until, cooldown.diagnostics)
|
|
215
|
+
);
|
|
185
216
|
}
|
|
186
217
|
const requestKey = JSON.stringify([agentId, key2]);
|
|
187
218
|
const existing = this.inFlight.get(requestKey);
|
|
@@ -202,8 +233,9 @@ var AgentReads = class {
|
|
|
202
233
|
Math.min(3e4 * 2 ** (failures - 1), 3e5)
|
|
203
234
|
);
|
|
204
235
|
const until = Math.max(previous?.until ?? 0, Date.now() + delay);
|
|
205
|
-
|
|
206
|
-
|
|
236
|
+
const diagnostics = rateLimitDiagnostics(error);
|
|
237
|
+
this.cooldowns.set(agentId, { until, failures, diagnostics });
|
|
238
|
+
throw this.limited(agentId, until, diagnostics);
|
|
207
239
|
}
|
|
208
240
|
).finally(() => {
|
|
209
241
|
if (this.inFlight.get(requestKey) === promise)
|
|
@@ -216,7 +248,7 @@ var AgentReads = class {
|
|
|
216
248
|
|
|
217
249
|
// src/agents/zyfai/zyfai.agent.ts
|
|
218
250
|
var import_sdk = require("@zyfai/sdk");
|
|
219
|
-
var
|
|
251
|
+
var import_viem2 = require("viem");
|
|
220
252
|
var import_chains = require("viem/chains");
|
|
221
253
|
|
|
222
254
|
// src/types/config.ts
|
|
@@ -1097,15 +1129,145 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
|
|
|
1097
1129
|
return !protocolListsEqual(current.protocols, desiredProtocols);
|
|
1098
1130
|
}
|
|
1099
1131
|
|
|
1132
|
+
// src/lib/paid-rpc.ts
|
|
1133
|
+
var import_viem = require("viem");
|
|
1134
|
+
var PAID_RPC_RETRY_COUNT = 3;
|
|
1135
|
+
var PAID_RPC_RETRY_DELAY_MS = 1e3;
|
|
1136
|
+
function configuredRpcProxyBaseUrl(baseUrl) {
|
|
1137
|
+
const configured = (baseUrl ?? "")?.trim();
|
|
1138
|
+
if (!configured) {
|
|
1139
|
+
throw new Error(
|
|
1140
|
+
"OWNEY_ROUTING_API_BASE_URL is required for RPC proxy requests unless routingApiBaseUrl or all rpcUrls are configured."
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
return configured;
|
|
1144
|
+
}
|
|
1145
|
+
function rpcProxyUrl(chainId, apiKey, baseUrl) {
|
|
1146
|
+
const url = new URL(
|
|
1147
|
+
`${configuredRpcProxyBaseUrl(baseUrl).replace(/\/$/, "")}/api/v1/rpc/${chainId}`
|
|
1148
|
+
);
|
|
1149
|
+
if (apiKey) url.searchParams.set("apiKey", apiKey);
|
|
1150
|
+
return url.toString();
|
|
1151
|
+
}
|
|
1152
|
+
function resolveRpcUrl(rpcUrls, chainId, apiKey = "", baseUrl) {
|
|
1153
|
+
const url = rpcUrls?.[chainId]?.trim();
|
|
1154
|
+
if (url) return url;
|
|
1155
|
+
return rpcProxyUrl(chainId, apiKey, baseUrl);
|
|
1156
|
+
}
|
|
1157
|
+
function resolveRpcUrls(rpcUrls, apiKey = "", baseUrl) {
|
|
1158
|
+
return {
|
|
1159
|
+
1: resolveRpcUrl(rpcUrls, 1, apiKey, baseUrl),
|
|
1160
|
+
8453: resolveRpcUrl(rpcUrls, 8453, apiKey, baseUrl),
|
|
1161
|
+
42161: resolveRpcUrl(rpcUrls, 42161, apiKey, baseUrl)
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
function createPaidRpcClient(chain, rpcUrls) {
|
|
1165
|
+
const url = resolveRpcUrl(
|
|
1166
|
+
rpcUrls,
|
|
1167
|
+
chain.id
|
|
1168
|
+
);
|
|
1169
|
+
return (0, import_viem.createPublicClient)({
|
|
1170
|
+
chain,
|
|
1171
|
+
transport: (0, import_viem.http)(url, {
|
|
1172
|
+
retryCount: PAID_RPC_RETRY_COUNT,
|
|
1173
|
+
retryDelay: PAID_RPC_RETRY_DELAY_MS
|
|
1174
|
+
})
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
function headerValue(error, name) {
|
|
1178
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1179
|
+
let value;
|
|
1180
|
+
function visit(candidate, depth = 0) {
|
|
1181
|
+
if (value || depth > 6 || !candidate || typeof candidate !== "object")
|
|
1182
|
+
return;
|
|
1183
|
+
if (seen.has(candidate)) return;
|
|
1184
|
+
seen.add(candidate);
|
|
1185
|
+
const record = candidate;
|
|
1186
|
+
const headers = record.headers;
|
|
1187
|
+
let found;
|
|
1188
|
+
if (typeof headers?.get === "function") {
|
|
1189
|
+
found = headers.get(name);
|
|
1190
|
+
} else {
|
|
1191
|
+
const headerRecord = headers;
|
|
1192
|
+
found = headerRecord?.[name] ?? headerRecord?.[name.toLowerCase()];
|
|
1193
|
+
}
|
|
1194
|
+
if (typeof found === "string" && found) {
|
|
1195
|
+
value = found;
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
for (const key2 of ["cause", "details", "response", "error"])
|
|
1199
|
+
visit(record[key2], depth + 1);
|
|
1200
|
+
}
|
|
1201
|
+
visit(error);
|
|
1202
|
+
return value;
|
|
1203
|
+
}
|
|
1204
|
+
function statusCode(error) {
|
|
1205
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1206
|
+
let status;
|
|
1207
|
+
function visit(candidate, depth = 0) {
|
|
1208
|
+
if (status || depth > 6 || !candidate || typeof candidate !== "object")
|
|
1209
|
+
return;
|
|
1210
|
+
if (seen.has(candidate)) return;
|
|
1211
|
+
seen.add(candidate);
|
|
1212
|
+
const record = candidate;
|
|
1213
|
+
for (const key2 of ["status", "statusCode"]) {
|
|
1214
|
+
const parsed = Number(record[key2]);
|
|
1215
|
+
if (Number.isInteger(parsed) && parsed >= 100 && parsed <= 599) {
|
|
1216
|
+
status = parsed;
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
for (const key2 of ["cause", "details", "response", "error"])
|
|
1221
|
+
visit(record[key2], depth + 1);
|
|
1222
|
+
}
|
|
1223
|
+
visit(error);
|
|
1224
|
+
return status;
|
|
1225
|
+
}
|
|
1226
|
+
function paidRpcError(error, chainId, rpcMethod, agentId) {
|
|
1227
|
+
const delay = rateLimitDelay(error);
|
|
1228
|
+
const providerRequestId = headerValue(error, "x-alchemy-request-id") ?? headerValue(error, "x-request-id");
|
|
1229
|
+
if (delay === void 0) {
|
|
1230
|
+
return new OwneyError(
|
|
1231
|
+
"AGENT_API_ERROR",
|
|
1232
|
+
"The blockchain RPC request failed.",
|
|
1233
|
+
{
|
|
1234
|
+
rpcSource: "paid-rpc",
|
|
1235
|
+
chainId,
|
|
1236
|
+
rpcMethod,
|
|
1237
|
+
...statusCode(error) ? { statusCode: statusCode(error) } : {},
|
|
1238
|
+
...providerRequestId ? { providerRequestId } : {}
|
|
1239
|
+
},
|
|
1240
|
+
agentId
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
const retryAt = Date.now() + delay;
|
|
1244
|
+
return new OwneyError(
|
|
1245
|
+
"AGENT_RATE_LIMITED",
|
|
1246
|
+
"The blockchain RPC is rate limited. Please wait before trying again.",
|
|
1247
|
+
{
|
|
1248
|
+
rpcSource: "paid-rpc",
|
|
1249
|
+
chainId,
|
|
1250
|
+
rpcMethod,
|
|
1251
|
+
statusCode: 429,
|
|
1252
|
+
retryAt,
|
|
1253
|
+
retryAfterSeconds: Math.max(0, Math.ceil(delay / 1e3)),
|
|
1254
|
+
...providerRequestId ? { providerRequestId } : {}
|
|
1255
|
+
},
|
|
1256
|
+
agentId
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
async function withPaidRpcDiagnostics(operation, chainId, rpcMethod, agentId) {
|
|
1260
|
+
try {
|
|
1261
|
+
return await operation();
|
|
1262
|
+
} catch (error) {
|
|
1263
|
+
throw paidRpcError(error, chainId, rpcMethod, agentId);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1100
1267
|
// src/agents/zyfai/zyfai.agent.ts
|
|
1101
|
-
var ERC7579_IS_MODULE_INSTALLED_ABI = (0,
|
|
1268
|
+
var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem2.parseAbi)([
|
|
1102
1269
|
"function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)"
|
|
1103
1270
|
]);
|
|
1104
|
-
var DEFAULT_ZYFAI_RPC_URLS = {
|
|
1105
|
-
8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
1106
|
-
42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
1107
|
-
1: "https://eth-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
|
|
1108
|
-
};
|
|
1109
1271
|
var WETH_ADDRESS_BY_CHAIN = {
|
|
1110
1272
|
8453: "0x4200000000000000000000000000000000000006",
|
|
1111
1273
|
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
@@ -1171,7 +1333,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1171
1333
|
earningsSnapshot = null;
|
|
1172
1334
|
earningsGeneration = 0;
|
|
1173
1335
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
1174
|
-
this.rpcUrls = rpcUrls
|
|
1336
|
+
this.rpcUrls = resolveRpcUrls(rpcUrls);
|
|
1175
1337
|
this.sdk = new import_sdk.ZyfaiSDK({
|
|
1176
1338
|
apiKey,
|
|
1177
1339
|
rpcUrls: this.rpcUrls,
|
|
@@ -1185,10 +1347,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1185
1347
|
getPublicClient(chainId) {
|
|
1186
1348
|
const cached = this.publicClients.get(chainId);
|
|
1187
1349
|
if (cached) return cached;
|
|
1188
|
-
const client = (
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1350
|
+
const client = createPaidRpcClient(
|
|
1351
|
+
VIEM_CHAIN[chainId],
|
|
1352
|
+
this.rpcUrls
|
|
1353
|
+
);
|
|
1192
1354
|
this.publicClients.set(chainId, client);
|
|
1193
1355
|
return client;
|
|
1194
1356
|
}
|
|
@@ -2156,7 +2318,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2156
2318
|
};
|
|
2157
2319
|
|
|
2158
2320
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
2159
|
-
var
|
|
2321
|
+
var import_viem7 = require("viem");
|
|
2160
2322
|
var import_chains3 = require("viem/chains");
|
|
2161
2323
|
|
|
2162
2324
|
// src/lib/chain-guard.ts
|
|
@@ -2195,7 +2357,7 @@ async function ensureWalletOnChain(pub, wallet, expected) {
|
|
|
2195
2357
|
}
|
|
2196
2358
|
|
|
2197
2359
|
// src/lib/transfer-auth.ts
|
|
2198
|
-
var
|
|
2360
|
+
var import_viem3 = require("viem");
|
|
2199
2361
|
|
|
2200
2362
|
// src/lib/sponsor-client.ts
|
|
2201
2363
|
var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
@@ -2311,7 +2473,7 @@ async function postSponsorBatchTransfer(input) {
|
|
|
2311
2473
|
}
|
|
2312
2474
|
|
|
2313
2475
|
// src/lib/permit2.ts
|
|
2314
|
-
var
|
|
2476
|
+
var import_viem4 = require("viem");
|
|
2315
2477
|
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
2316
2478
|
var MAX_UINT256 = 2n ** 256n - 1n;
|
|
2317
2479
|
function permit2ApprovalAmount(requiredAmount) {
|
|
@@ -2352,7 +2514,7 @@ var ERC20_ALLOWANCE_ABI = [
|
|
|
2352
2514
|
function randomPermit2Nonce() {
|
|
2353
2515
|
const bytes = new Uint8Array(32);
|
|
2354
2516
|
globalThis.crypto.getRandomValues(bytes);
|
|
2355
|
-
return BigInt((0,
|
|
2517
|
+
return BigInt((0, import_viem4.bytesToHex)(bytes));
|
|
2356
2518
|
}
|
|
2357
2519
|
async function readPermit2Allowance(publicClient, token, owner, blockNumber) {
|
|
2358
2520
|
return publicClient.readContract({
|
|
@@ -2395,7 +2557,7 @@ function makeVerificationAwareDepositCallback(implementation) {
|
|
|
2395
2557
|
|
|
2396
2558
|
// src/agents/yieldseeker/yieldseeker.auth.ts
|
|
2397
2559
|
var import_siwe = require("siwe");
|
|
2398
|
-
var
|
|
2560
|
+
var import_viem5 = require("viem");
|
|
2399
2561
|
var import_chains2 = require("viem/chains");
|
|
2400
2562
|
|
|
2401
2563
|
// src/agents/yieldseeker/yieldseeker.auth-cache.ts
|
|
@@ -2508,7 +2670,7 @@ function createYieldseekerSiweMessage(address, chainId, dependencies = {}) {
|
|
|
2508
2670
|
return new import_siwe.SiweMessage({
|
|
2509
2671
|
scheme: url.protocol.slice(0, -1),
|
|
2510
2672
|
domain: url.host,
|
|
2511
|
-
address: (0,
|
|
2673
|
+
address: (0, import_viem5.getAddress)(address),
|
|
2512
2674
|
uri: url.origin,
|
|
2513
2675
|
version: "1",
|
|
2514
2676
|
chainId,
|
|
@@ -2594,15 +2756,15 @@ var YieldseekerAuth = class {
|
|
|
2594
2756
|
clearYieldseekerSession(state.walletAddress, chainId);
|
|
2595
2757
|
}
|
|
2596
2758
|
async sign(state, chainId) {
|
|
2597
|
-
const account = (0,
|
|
2598
|
-
const publicClient = (0,
|
|
2759
|
+
const account = (0, import_viem5.getAddress)(state.walletAddress);
|
|
2760
|
+
const publicClient = (0, import_viem5.createPublicClient)({
|
|
2599
2761
|
chain: import_chains2.base,
|
|
2600
|
-
transport: (0,
|
|
2762
|
+
transport: (0, import_viem5.custom)(state.provider)
|
|
2601
2763
|
});
|
|
2602
|
-
const walletClient = (0,
|
|
2764
|
+
const walletClient = (0, import_viem5.createWalletClient)({
|
|
2603
2765
|
account,
|
|
2604
2766
|
chain: import_chains2.base,
|
|
2605
|
-
transport: (0,
|
|
2767
|
+
transport: (0, import_viem5.custom)(state.provider)
|
|
2606
2768
|
});
|
|
2607
2769
|
await ensureWalletOnChain(
|
|
2608
2770
|
publicClient,
|
|
@@ -2768,7 +2930,7 @@ var YieldseekerApiClient = class {
|
|
|
2768
2930
|
};
|
|
2769
2931
|
|
|
2770
2932
|
// src/agents/yieldseeker/yieldseeker.mapper.ts
|
|
2771
|
-
var
|
|
2933
|
+
var import_viem6 = require("viem");
|
|
2772
2934
|
|
|
2773
2935
|
// src/lib/helpers/snapshot-apy.ts
|
|
2774
2936
|
var DAY_MS = 864e5;
|
|
@@ -2835,10 +2997,10 @@ function raw(value, endpoint) {
|
|
|
2835
2997
|
return BigInt(value);
|
|
2836
2998
|
}
|
|
2837
2999
|
function decimal(value, decimals, endpoint) {
|
|
2838
|
-
return (0,
|
|
3000
|
+
return (0, import_viem6.formatUnits)(raw(value, endpoint), decimals);
|
|
2839
3001
|
}
|
|
2840
3002
|
function usd(rawAmount, decimals, price) {
|
|
2841
|
-
return Number((0,
|
|
3003
|
+
return Number((0, import_viem6.formatUnits)(rawAmount, decimals)) * price;
|
|
2842
3004
|
}
|
|
2843
3005
|
function percent(value) {
|
|
2844
3006
|
const result = Number(value);
|
|
@@ -2864,7 +3026,7 @@ function assetAddressValue(record, address) {
|
|
|
2864
3026
|
}
|
|
2865
3027
|
function position(value, asset, baseAssetDecimals) {
|
|
2866
3028
|
const option = value?.yieldOption;
|
|
2867
|
-
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0,
|
|
3029
|
+
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0, import_viem6.isAddress)(option.address)) {
|
|
2868
3030
|
return invalid("yield positions", "missing vault metadata");
|
|
2869
3031
|
}
|
|
2870
3032
|
return {
|
|
@@ -2945,7 +3107,7 @@ function mapYieldseekerEarnings(contexts) {
|
|
|
2945
3107
|
chain: "BASE",
|
|
2946
3108
|
chainId: 8453,
|
|
2947
3109
|
asset: context.asset,
|
|
2948
|
-
amount: (0,
|
|
3110
|
+
amount: (0, import_viem6.formatUnits)(amount, context.snapshot.baseAssetDecimals)
|
|
2949
3111
|
});
|
|
2950
3112
|
lifetimeEarnings += usd(
|
|
2951
3113
|
amount,
|
|
@@ -3212,6 +3374,9 @@ var YIELDSEEKER_USERNAME_PREFIX = "owney_";
|
|
|
3212
3374
|
var YIELDSEEKER_USERNAME_RANDOM_LENGTH = 14;
|
|
3213
3375
|
var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
|
|
3214
3376
|
var YIELDSEEKER_YIELD_OPTIONS_CACHE_MS = 6e4;
|
|
3377
|
+
var YIELDSEEKER_AGENT_LIST_CACHE_MS = 6e4;
|
|
3378
|
+
var YIELDSEEKER_PORTFOLIO_CACHE_MS = 3e4;
|
|
3379
|
+
var YIELDSEEKER_ACTIVITY_CACHE_MS = 6e4;
|
|
3215
3380
|
function generateYieldseekerUsername() {
|
|
3216
3381
|
const suffix = globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, YIELDSEEKER_USERNAME_RANDOM_LENGTH).toLowerCase();
|
|
3217
3382
|
return `${YIELDSEEKER_USERNAME_PREFIX}${suffix}`;
|
|
@@ -3255,6 +3420,7 @@ function query(params) {
|
|
|
3255
3420
|
var YieldseekerAgent = class {
|
|
3256
3421
|
id = "yieldseeker";
|
|
3257
3422
|
balanceComposition = "tokens-plus-positions";
|
|
3423
|
+
withdrawalRequiresWalletApproval = true;
|
|
3258
3424
|
supportedChainIds = [8453];
|
|
3259
3425
|
supportedAssets = [
|
|
3260
3426
|
{
|
|
@@ -3268,11 +3434,17 @@ var YieldseekerAgent = class {
|
|
|
3268
3434
|
];
|
|
3269
3435
|
api;
|
|
3270
3436
|
auth;
|
|
3437
|
+
rpcUrls;
|
|
3438
|
+
receiptClient;
|
|
3271
3439
|
transactionExecutor;
|
|
3272
3440
|
unwindReceiptWaiter;
|
|
3273
3441
|
agentContexts = /* @__PURE__ */ new Map();
|
|
3274
3442
|
users = /* @__PURE__ */ new Map();
|
|
3275
3443
|
pendingAgents = /* @__PURE__ */ new Map();
|
|
3444
|
+
pendingWalletContexts = /* @__PURE__ */ new Map();
|
|
3445
|
+
readCache = /* @__PURE__ */ new Map();
|
|
3446
|
+
pendingReads = /* @__PURE__ */ new Map();
|
|
3447
|
+
readGeneration = 0;
|
|
3276
3448
|
yieldOptions = /* @__PURE__ */ new Map();
|
|
3277
3449
|
pendingYieldOptions = /* @__PURE__ */ new Map();
|
|
3278
3450
|
constructor(owneyApiKey, options = {}) {
|
|
@@ -3282,10 +3454,16 @@ var YieldseekerAgent = class {
|
|
|
3282
3454
|
options.fetchFn
|
|
3283
3455
|
);
|
|
3284
3456
|
this.auth = new YieldseekerAuth(options.auth);
|
|
3457
|
+
this.rpcUrls = options.rpcUrls;
|
|
3285
3458
|
this.transactionExecutor = options.transactionExecutor;
|
|
3286
3459
|
this.unwindReceiptWaiter = options.unwindReceiptWaiter;
|
|
3287
3460
|
}
|
|
3461
|
+
getReceiptClient() {
|
|
3462
|
+
this.receiptClient ??= createPaidRpcClient(import_chains3.base, this.rpcUrls);
|
|
3463
|
+
return this.receiptClient;
|
|
3464
|
+
}
|
|
3288
3465
|
async disconnect() {
|
|
3466
|
+
this.readGeneration += 1;
|
|
3289
3467
|
this.auth.clear();
|
|
3290
3468
|
for (const key2 of this.users.keys()) {
|
|
3291
3469
|
const [walletAddress, chainId] = key2.split(":");
|
|
@@ -3294,6 +3472,9 @@ var YieldseekerAgent = class {
|
|
|
3294
3472
|
this.users.clear();
|
|
3295
3473
|
this.agentContexts.clear();
|
|
3296
3474
|
this.pendingAgents.clear();
|
|
3475
|
+
this.pendingWalletContexts.clear();
|
|
3476
|
+
this.readCache.clear();
|
|
3477
|
+
this.pendingReads.clear();
|
|
3297
3478
|
}
|
|
3298
3479
|
async activateAgent(state, chainId, asset) {
|
|
3299
3480
|
this.assertChain(chainId);
|
|
@@ -3330,12 +3511,12 @@ var YieldseekerAgent = class {
|
|
|
3330
3511
|
await this.waitForReceipt(state, chainId, txHash);
|
|
3331
3512
|
} else {
|
|
3332
3513
|
txHash = await this.submitTransaction(state, chainId, {
|
|
3333
|
-
from: (0,
|
|
3514
|
+
from: (0, import_viem7.getAddress)(state.walletAddress),
|
|
3334
3515
|
to: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
3335
|
-
data: (0,
|
|
3336
|
-
abi:
|
|
3516
|
+
data: (0, import_viem7.encodeFunctionData)({
|
|
3517
|
+
abi: import_viem7.erc20Abi,
|
|
3337
3518
|
functionName: "transfer",
|
|
3338
|
-
args: [(0,
|
|
3519
|
+
args: [(0, import_viem7.getAddress)(context.wallet.walletAddress), BigInt(amount)]
|
|
3339
3520
|
}),
|
|
3340
3521
|
value: "0",
|
|
3341
3522
|
chainId
|
|
@@ -3435,15 +3616,15 @@ var YieldseekerAgent = class {
|
|
|
3435
3616
|
remaining: remaining.toString()
|
|
3436
3617
|
});
|
|
3437
3618
|
}
|
|
3438
|
-
const account = (0,
|
|
3619
|
+
const account = (0, import_viem7.getAddress)(state.walletAddress);
|
|
3439
3620
|
const txHash = await this.submitTransaction(state, chainId, {
|
|
3440
3621
|
from: account,
|
|
3441
|
-
to: (0,
|
|
3442
|
-
data: amount === void 0 ? (0,
|
|
3622
|
+
to: (0, import_viem7.getAddress)(context.wallet.walletAddress),
|
|
3623
|
+
data: amount === void 0 ? (0, import_viem7.encodeFunctionData)({
|
|
3443
3624
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
3444
3625
|
functionName: "withdrawAllAssetToUser",
|
|
3445
3626
|
args: [account, metadata.address]
|
|
3446
|
-
}) : (0,
|
|
3627
|
+
}) : (0, import_viem7.encodeFunctionData)({
|
|
3447
3628
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
3448
3629
|
functionName: "withdrawAssetToUser",
|
|
3449
3630
|
args: [account, metadata.address, requested]
|
|
@@ -3499,7 +3680,7 @@ var YieldseekerAgent = class {
|
|
|
3499
3680
|
);
|
|
3500
3681
|
const vaultAddresses = new Set(
|
|
3501
3682
|
catalog.flat().filter(
|
|
3502
|
-
(yieldOption) => yieldOption.chainId === chainId && (0,
|
|
3683
|
+
(yieldOption) => yieldOption.chainId === chainId && (0, import_viem7.isAddress)(yieldOption.address)
|
|
3503
3684
|
).map((yieldOption) => yieldOption.address.toLowerCase())
|
|
3504
3685
|
);
|
|
3505
3686
|
return mapYieldseekerHistory(contexts, {
|
|
@@ -3556,6 +3737,86 @@ var YieldseekerAgent = class {
|
|
|
3556
3737
|
contextKey(state, chainId, asset) {
|
|
3557
3738
|
return `${this.userKey(state, chainId)}:${asset}`;
|
|
3558
3739
|
}
|
|
3740
|
+
cachedRead(key2, ttlMs, read2) {
|
|
3741
|
+
const cached = this.readCache.get(key2);
|
|
3742
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
3743
|
+
return Promise.resolve(cached.value);
|
|
3744
|
+
}
|
|
3745
|
+
const pending = this.pendingReads.get(key2);
|
|
3746
|
+
if (pending) return pending;
|
|
3747
|
+
const generation = this.readGeneration;
|
|
3748
|
+
const request = Promise.resolve().then(read2).then((value) => {
|
|
3749
|
+
if (this.readGeneration === generation) {
|
|
3750
|
+
this.readCache.set(key2, {
|
|
3751
|
+
expiresAt: Date.now() + ttlMs,
|
|
3752
|
+
value
|
|
3753
|
+
});
|
|
3754
|
+
}
|
|
3755
|
+
return value;
|
|
3756
|
+
}).finally(() => {
|
|
3757
|
+
if (this.pendingReads.get(key2) === request) {
|
|
3758
|
+
this.pendingReads.delete(key2);
|
|
3759
|
+
}
|
|
3760
|
+
});
|
|
3761
|
+
this.pendingReads.set(key2, request);
|
|
3762
|
+
return request;
|
|
3763
|
+
}
|
|
3764
|
+
agentListKey(state, chainId) {
|
|
3765
|
+
return `agents:${this.userKey(state, chainId)}`;
|
|
3766
|
+
}
|
|
3767
|
+
async listAgents(state, chainId, user) {
|
|
3768
|
+
const response = await this.cachedRead(
|
|
3769
|
+
this.agentListKey(state, chainId),
|
|
3770
|
+
YIELDSEEKER_AGENT_LIST_CACHE_MS,
|
|
3771
|
+
async () => {
|
|
3772
|
+
const response2 = await this.walletRequest(
|
|
3773
|
+
state,
|
|
3774
|
+
chainId,
|
|
3775
|
+
`/users/${user.userId}/agents`
|
|
3776
|
+
);
|
|
3777
|
+
if (!Array.isArray(response2?.agents)) {
|
|
3778
|
+
throw this.invalidResponse("agent list");
|
|
3779
|
+
}
|
|
3780
|
+
return response2;
|
|
3781
|
+
}
|
|
3782
|
+
);
|
|
3783
|
+
return response.agents;
|
|
3784
|
+
}
|
|
3785
|
+
async contextForAgent(state, chainId, user, agent, asset) {
|
|
3786
|
+
const key2 = this.contextKey(state, chainId, asset);
|
|
3787
|
+
const cached = this.agentContexts.get(key2);
|
|
3788
|
+
if (cached?.agent.agentId === agent.agentId) return cached;
|
|
3789
|
+
const pending = this.pendingWalletContexts.get(key2);
|
|
3790
|
+
if (pending) return pending;
|
|
3791
|
+
const generation = this.readGeneration;
|
|
3792
|
+
const request = this.walletRequest(
|
|
3793
|
+
state,
|
|
3794
|
+
chainId,
|
|
3795
|
+
`/users/${user.userId}/agents/${agent.agentId}/wallet`
|
|
3796
|
+
).then((walletResponse) => {
|
|
3797
|
+
if (!walletResponse?.agentWallet || !(0, import_viem7.isAddress)(walletResponse.agentWallet.walletAddress)) {
|
|
3798
|
+
throw this.invalidResponse("agent wallet");
|
|
3799
|
+
}
|
|
3800
|
+
const context = {
|
|
3801
|
+
user,
|
|
3802
|
+
agent,
|
|
3803
|
+
wallet: walletResponse.agentWallet,
|
|
3804
|
+
asset
|
|
3805
|
+
};
|
|
3806
|
+
if (this.readGeneration === generation) {
|
|
3807
|
+
this.agentContexts.set(key2, context);
|
|
3808
|
+
}
|
|
3809
|
+
return context;
|
|
3810
|
+
});
|
|
3811
|
+
this.pendingWalletContexts.set(key2, request);
|
|
3812
|
+
try {
|
|
3813
|
+
return await request;
|
|
3814
|
+
} finally {
|
|
3815
|
+
if (this.pendingWalletContexts.get(key2) === request) {
|
|
3816
|
+
this.pendingWalletContexts.delete(key2);
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3559
3820
|
async resolveUser(state, chainId) {
|
|
3560
3821
|
const key2 = this.userKey(state, chainId);
|
|
3561
3822
|
const inMemory = this.users.get(key2);
|
|
@@ -3565,7 +3826,7 @@ var YieldseekerAgent = class {
|
|
|
3565
3826
|
this.users.set(key2, persisted);
|
|
3566
3827
|
return persisted;
|
|
3567
3828
|
}
|
|
3568
|
-
const walletAddress = (0,
|
|
3829
|
+
const walletAddress = (0, import_viem7.getAddress)(state.walletAddress);
|
|
3569
3830
|
let user = null;
|
|
3570
3831
|
try {
|
|
3571
3832
|
const login = await this.providerRequest(
|
|
@@ -3652,16 +3913,9 @@ var YieldseekerAgent = class {
|
|
|
3652
3913
|
}
|
|
3653
3914
|
async resolveAgent(state, chainId, asset, createIfMissing) {
|
|
3654
3915
|
const user = await this.resolveUser(state, chainId);
|
|
3655
|
-
const
|
|
3656
|
-
state,
|
|
3657
|
-
chainId,
|
|
3658
|
-
`/users/${user.userId}/agents`
|
|
3659
|
-
);
|
|
3660
|
-
if (!Array.isArray(response?.agents)) {
|
|
3661
|
-
throw this.invalidResponse("agent list");
|
|
3662
|
-
}
|
|
3916
|
+
const agents = await this.listAgents(state, chainId, user);
|
|
3663
3917
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
3664
|
-
let agent =
|
|
3918
|
+
let agent = agents.find(
|
|
3665
3919
|
(candidate) => this.isOwneyAgent(candidate) && candidate.chainId === chainId && candidate.type === "vault" && candidate.assetAddress.toLowerCase() === metadata.address.toLowerCase()
|
|
3666
3920
|
);
|
|
3667
3921
|
if (!agent && createIfMissing) {
|
|
@@ -3682,83 +3936,91 @@ var YieldseekerAgent = class {
|
|
|
3682
3936
|
}
|
|
3683
3937
|
);
|
|
3684
3938
|
agent = created?.agent;
|
|
3939
|
+
if (agent) {
|
|
3940
|
+
this.readCache.set(this.agentListKey(state, chainId), {
|
|
3941
|
+
expiresAt: Date.now() + YIELDSEEKER_AGENT_LIST_CACHE_MS,
|
|
3942
|
+
value: {
|
|
3943
|
+
agents: [...agents, agent]
|
|
3944
|
+
}
|
|
3945
|
+
});
|
|
3946
|
+
}
|
|
3685
3947
|
}
|
|
3686
3948
|
if (!agent) return null;
|
|
3687
3949
|
this.assertAgent(agent);
|
|
3688
|
-
|
|
3689
|
-
state,
|
|
3690
|
-
chainId,
|
|
3691
|
-
`/users/${user.userId}/agents/${agent.agentId}/wallet`
|
|
3692
|
-
);
|
|
3693
|
-
if (!walletResponse?.agentWallet || !(0, import_viem6.isAddress)(walletResponse.agentWallet.walletAddress)) {
|
|
3694
|
-
throw this.invalidResponse("agent wallet");
|
|
3695
|
-
}
|
|
3696
|
-
return { user, agent, wallet: walletResponse.agentWallet, asset };
|
|
3950
|
+
return this.contextForAgent(state, chainId, user, agent, asset);
|
|
3697
3951
|
}
|
|
3698
3952
|
async loadPortfolio(state, chainId, options) {
|
|
3699
3953
|
const user = await this.resolveUser(state, chainId);
|
|
3700
|
-
const
|
|
3701
|
-
state,
|
|
3702
|
-
chainId,
|
|
3703
|
-
`/users/${user.userId}/agents`
|
|
3704
|
-
);
|
|
3705
|
-
if (!Array.isArray(response?.agents)) {
|
|
3706
|
-
throw this.invalidResponse("agent list");
|
|
3707
|
-
}
|
|
3954
|
+
const agents = await this.listAgents(state, chainId, user);
|
|
3708
3955
|
const contexts = [];
|
|
3709
|
-
for (const agent of
|
|
3956
|
+
for (const agent of agents) {
|
|
3710
3957
|
const asset = this.assetForAgent(agent);
|
|
3711
3958
|
if (!this.isOwneyAgent(agent) || !asset || agent.chainId !== chainId || agent.type !== "vault" || options.asset && options.asset !== asset) {
|
|
3712
3959
|
continue;
|
|
3713
3960
|
}
|
|
3714
3961
|
this.assertAgent(agent);
|
|
3715
|
-
|
|
3716
|
-
state,
|
|
3717
|
-
chainId,
|
|
3718
|
-
`/users/${user.userId}/agents/${agent.agentId}/wallet`
|
|
3719
|
-
);
|
|
3720
|
-
if (!walletResponse?.agentWallet || !(0, import_viem6.isAddress)(walletResponse.agentWallet.walletAddress)) {
|
|
3721
|
-
throw this.invalidResponse("agent wallet");
|
|
3722
|
-
}
|
|
3723
|
-
const context = {
|
|
3724
|
-
user,
|
|
3725
|
-
agent,
|
|
3726
|
-
wallet: walletResponse.agentWallet,
|
|
3727
|
-
asset
|
|
3728
|
-
};
|
|
3729
|
-
this.agentContexts.set(this.contextKey(state, chainId, asset), context);
|
|
3730
|
-
contexts.push(context);
|
|
3962
|
+
contexts.push(this.contextForAgent(state, chainId, user, agent, asset));
|
|
3731
3963
|
}
|
|
3964
|
+
const resolvedContexts = await Promise.all(contexts);
|
|
3732
3965
|
return Promise.all(
|
|
3733
|
-
|
|
3966
|
+
resolvedContexts.map(
|
|
3734
3967
|
(context) => this.loadPortfolioContext(state, chainId, context, options)
|
|
3735
3968
|
)
|
|
3736
3969
|
);
|
|
3737
3970
|
}
|
|
3738
3971
|
async loadPortfolioContext(state, chainId, context, options = {}) {
|
|
3972
|
+
const contextKey = this.contextKey(state, chainId, context.asset);
|
|
3739
3973
|
const [snapshot, positions, historic, actions] = await Promise.all([
|
|
3740
|
-
this.
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3974
|
+
this.cachedRead(
|
|
3975
|
+
`snapshot:${contextKey}`,
|
|
3976
|
+
YIELDSEEKER_PORTFOLIO_CACHE_MS,
|
|
3977
|
+
async () => {
|
|
3978
|
+
const response = await this.walletRequest(
|
|
3979
|
+
state,
|
|
3980
|
+
chainId,
|
|
3981
|
+
`${this.agentPath(context, "snapshot")}${query({
|
|
3982
|
+
shouldOnlyUseRecentValue: true,
|
|
3983
|
+
shouldAllowStaleOnError: true
|
|
3984
|
+
})}`
|
|
3985
|
+
);
|
|
3986
|
+
if (!response?.agentSnapshot) {
|
|
3987
|
+
throw this.invalidResponse("agent snapshot");
|
|
3988
|
+
}
|
|
3989
|
+
return response;
|
|
3990
|
+
}
|
|
3747
3991
|
),
|
|
3748
|
-
this.
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3992
|
+
this.cachedRead(
|
|
3993
|
+
`positions:${contextKey}`,
|
|
3994
|
+
YIELDSEEKER_PORTFOLIO_CACHE_MS,
|
|
3995
|
+
async () => {
|
|
3996
|
+
const response = await this.walletRequest(
|
|
3997
|
+
state,
|
|
3998
|
+
chainId,
|
|
3999
|
+
this.agentPath(context, "yield-positions")
|
|
4000
|
+
);
|
|
4001
|
+
if (!Array.isArray(response?.yieldPositions)) {
|
|
4002
|
+
throw this.invalidResponse("yield positions");
|
|
4003
|
+
}
|
|
4004
|
+
return response;
|
|
4005
|
+
}
|
|
3752
4006
|
),
|
|
3753
|
-
options.historic ? this.
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
this.
|
|
4007
|
+
options.historic ? this.cachedRead(
|
|
4008
|
+
`historic:${contextKey}`,
|
|
4009
|
+
YIELDSEEKER_ACTIVITY_CACHE_MS,
|
|
4010
|
+
() => this.walletRequest(
|
|
4011
|
+
state,
|
|
4012
|
+
chainId,
|
|
4013
|
+
this.agentPath(context, "wallet/historic-position")
|
|
4014
|
+
)
|
|
3757
4015
|
) : Promise.resolve(void 0),
|
|
3758
|
-
options.actions ? this.
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
this.
|
|
4016
|
+
options.actions ? this.cachedRead(
|
|
4017
|
+
`actions:${contextKey}`,
|
|
4018
|
+
YIELDSEEKER_ACTIVITY_CACHE_MS,
|
|
4019
|
+
() => this.walletRequest(
|
|
4020
|
+
state,
|
|
4021
|
+
chainId,
|
|
4022
|
+
this.agentPath(context, "actions")
|
|
4023
|
+
)
|
|
3762
4024
|
) : Promise.resolve(void 0)
|
|
3763
4025
|
]);
|
|
3764
4026
|
if (!snapshot?.agentSnapshot) {
|
|
@@ -3784,7 +4046,7 @@ var YieldseekerAgent = class {
|
|
|
3784
4046
|
this.agentPath(context, "deploy"),
|
|
3785
4047
|
{ method: "POST", body: {} }
|
|
3786
4048
|
);
|
|
3787
|
-
if (!deployed?.agentWallet || !(0,
|
|
4049
|
+
if (!deployed?.agentWallet || !(0, import_viem7.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
|
|
3788
4050
|
throw this.invalidResponse("agent deployment", {
|
|
3789
4051
|
reason: "Deploy did not return the expected Agent Wallet."
|
|
3790
4052
|
});
|
|
@@ -3792,6 +4054,13 @@ var YieldseekerAgent = class {
|
|
|
3792
4054
|
context.wallet = deployed.agentWallet;
|
|
3793
4055
|
}
|
|
3794
4056
|
async refreshSnapshotAfterMovement(state, chainId, context, movement) {
|
|
4057
|
+
const contextKey = this.contextKey(state, chainId, context.asset);
|
|
4058
|
+
const invalidatePortfolio = () => {
|
|
4059
|
+
for (const kind of ["snapshot", "positions", "historic", "actions"]) {
|
|
4060
|
+
this.readCache.delete(`${kind}:${contextKey}`);
|
|
4061
|
+
}
|
|
4062
|
+
};
|
|
4063
|
+
invalidatePortfolio();
|
|
3795
4064
|
try {
|
|
3796
4065
|
const response = await this.walletRequest(
|
|
3797
4066
|
state,
|
|
@@ -3808,6 +4077,8 @@ var YieldseekerAgent = class {
|
|
|
3808
4077
|
`[owney-sdk] Yieldseeker ${movement} snapshot refresh failed:`,
|
|
3809
4078
|
error
|
|
3810
4079
|
);
|
|
4080
|
+
} finally {
|
|
4081
|
+
invalidatePortfolio();
|
|
3811
4082
|
}
|
|
3812
4083
|
}
|
|
3813
4084
|
agentPath(context, suffix) {
|
|
@@ -3858,6 +4129,7 @@ var YieldseekerAgent = class {
|
|
|
3858
4129
|
code,
|
|
3859
4130
|
`Yieldseeker request failed: ${error.providerCode}.`,
|
|
3860
4131
|
{
|
|
4132
|
+
rpcSource: "agent-api",
|
|
3861
4133
|
statusCode: error.status,
|
|
3862
4134
|
providerCode: error.providerCode,
|
|
3863
4135
|
...error.responseFields ? { fields: error.responseFields } : {}
|
|
@@ -3870,32 +4142,37 @@ var YieldseekerAgent = class {
|
|
|
3870
4142
|
return this.transactionExecutor(state, chainId, transaction);
|
|
3871
4143
|
}
|
|
3872
4144
|
this.assertTransaction(transaction, state, chainId);
|
|
3873
|
-
const account = (0,
|
|
3874
|
-
const walletClient = (0,
|
|
4145
|
+
const account = (0, import_viem7.getAddress)(state.walletAddress);
|
|
4146
|
+
const walletClient = (0, import_viem7.createWalletClient)({
|
|
3875
4147
|
account,
|
|
3876
4148
|
chain: import_chains3.base,
|
|
3877
|
-
transport: (0,
|
|
4149
|
+
transport: (0, import_viem7.custom)(state.provider)
|
|
3878
4150
|
});
|
|
3879
|
-
const
|
|
4151
|
+
const walletChainClient = (0, import_viem7.createPublicClient)({
|
|
3880
4152
|
chain: import_chains3.base,
|
|
3881
|
-
transport: (0,
|
|
4153
|
+
transport: (0, import_viem7.custom)(state.provider)
|
|
3882
4154
|
});
|
|
3883
4155
|
await ensureWalletOnChain(
|
|
3884
|
-
|
|
4156
|
+
walletChainClient,
|
|
3885
4157
|
walletClient,
|
|
3886
4158
|
8453
|
|
3887
4159
|
);
|
|
3888
4160
|
const hash = await walletClient.sendTransaction({
|
|
3889
4161
|
account,
|
|
3890
4162
|
chain: import_chains3.base,
|
|
3891
|
-
to: (0,
|
|
4163
|
+
to: (0, import_viem7.getAddress)(transaction.to),
|
|
3892
4164
|
data: transaction.data,
|
|
3893
4165
|
value: BigInt(transaction.value)
|
|
3894
4166
|
});
|
|
3895
|
-
const receipt = await
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
4167
|
+
const receipt = await withPaidRpcDiagnostics(
|
|
4168
|
+
() => this.getReceiptClient().waitForTransactionReceipt({
|
|
4169
|
+
hash,
|
|
4170
|
+
confirmations: 1
|
|
4171
|
+
}),
|
|
4172
|
+
8453,
|
|
4173
|
+
"eth_getTransactionReceipt",
|
|
4174
|
+
this.id
|
|
4175
|
+
);
|
|
3899
4176
|
if (receipt.status !== "success") {
|
|
3900
4177
|
throw new OwneyError(
|
|
3901
4178
|
"AGENT_TRANSACTION_REVERTED",
|
|
@@ -3911,14 +4188,15 @@ var YieldseekerAgent = class {
|
|
|
3911
4188
|
await this.unwindReceiptWaiter(state, chainId, transactionHash);
|
|
3912
4189
|
return;
|
|
3913
4190
|
}
|
|
3914
|
-
const
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
4191
|
+
const receipt = await withPaidRpcDiagnostics(
|
|
4192
|
+
() => this.getReceiptClient().waitForTransactionReceipt({
|
|
4193
|
+
hash: transactionHash,
|
|
4194
|
+
confirmations: 1
|
|
4195
|
+
}),
|
|
4196
|
+
8453,
|
|
4197
|
+
"eth_getTransactionReceipt",
|
|
4198
|
+
this.id
|
|
4199
|
+
);
|
|
3922
4200
|
if (receipt.status !== "success") {
|
|
3923
4201
|
throw new OwneyError(
|
|
3924
4202
|
"AGENT_TRANSACTION_REVERTED",
|
|
@@ -3929,12 +4207,12 @@ var YieldseekerAgent = class {
|
|
|
3929
4207
|
}
|
|
3930
4208
|
}
|
|
3931
4209
|
assertTransaction(transaction, state, chainId) {
|
|
3932
|
-
if (!transaction || typeof transaction.from !== "string" || !(0,
|
|
4210
|
+
if (!transaction || typeof transaction.from !== "string" || !(0, import_viem7.isAddress)(transaction.from) || typeof transaction.to !== "string" || !(0, import_viem7.isAddress)(transaction.to) || typeof transaction.data !== "string" || !/^0x[a-fA-F0-9]*$/.test(transaction.data) || typeof transaction.value !== "string" || !/^[0-9]+$/.test(transaction.value) || transaction.chainId !== chainId || (0, import_viem7.getAddress)(transaction.from) !== (0, import_viem7.getAddress)(state.walletAddress)) {
|
|
3933
4211
|
throw this.invalidResponse("transaction");
|
|
3934
4212
|
}
|
|
3935
4213
|
}
|
|
3936
4214
|
assertAgent(agent) {
|
|
3937
|
-
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0,
|
|
4215
|
+
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem7.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
|
|
3938
4216
|
throw this.invalidResponse("agent");
|
|
3939
4217
|
}
|
|
3940
4218
|
}
|
|
@@ -4087,7 +4365,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
|
|
|
4087
4365
|
}
|
|
4088
4366
|
|
|
4089
4367
|
// src/lib/helpers/withdraw-helper.ts
|
|
4090
|
-
var
|
|
4368
|
+
var import_viem8 = require("viem");
|
|
4091
4369
|
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
4092
4370
|
const target = asset.toUpperCase();
|
|
4093
4371
|
return agents.map((agent) => {
|
|
@@ -4095,7 +4373,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
4095
4373
|
const tokenBalance = agentBalance?.tokens.find(
|
|
4096
4374
|
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
4097
4375
|
);
|
|
4098
|
-
let balance = tokenBalance ? (0,
|
|
4376
|
+
let balance = tokenBalance ? (0, import_viem8.parseUnits)(tokenBalance.amount, decimals) : 0n;
|
|
4099
4377
|
if (agent.balanceComposition === "tokens-plus-positions") {
|
|
4100
4378
|
const chainNameById = {
|
|
4101
4379
|
1: "ETHEREUM",
|
|
@@ -4114,7 +4392,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
4114
4392
|
} catch {
|
|
4115
4393
|
}
|
|
4116
4394
|
}
|
|
4117
|
-
balance += (0,
|
|
4395
|
+
balance += (0, import_viem8.parseUnits)(position2.amount, decimals);
|
|
4118
4396
|
}
|
|
4119
4397
|
}
|
|
4120
4398
|
return { agent, balance };
|
|
@@ -4273,15 +4551,50 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
4273
4551
|
}
|
|
4274
4552
|
|
|
4275
4553
|
// src/client.ts
|
|
4276
|
-
var
|
|
4554
|
+
var import_viem12 = require("viem");
|
|
4277
4555
|
var import_chains4 = require("viem/chains");
|
|
4278
4556
|
|
|
4279
4557
|
// src/lib/sponsored-token-batch.ts
|
|
4280
|
-
var
|
|
4558
|
+
var import_viem10 = require("viem");
|
|
4281
4559
|
|
|
4282
4560
|
// src/lib/permit2-batch.ts
|
|
4283
|
-
var
|
|
4561
|
+
var import_viem9 = require("viem");
|
|
4284
4562
|
var BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
4563
|
+
var BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
4564
|
+
var MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
4565
|
+
var ERC2612_PERMIT_TYPES = {
|
|
4566
|
+
Permit: [
|
|
4567
|
+
{ name: "owner", type: "address" },
|
|
4568
|
+
{ name: "spender", type: "address" },
|
|
4569
|
+
{ name: "value", type: "uint256" },
|
|
4570
|
+
{ name: "nonce", type: "uint256" },
|
|
4571
|
+
{ name: "deadline", type: "uint256" }
|
|
4572
|
+
]
|
|
4573
|
+
};
|
|
4574
|
+
var ERC2612_READ_ABI = (0, import_viem9.parseAbi)([
|
|
4575
|
+
"function name() view returns (string)",
|
|
4576
|
+
"function version() view returns (string)",
|
|
4577
|
+
"function nonces(address owner) view returns (uint256)"
|
|
4578
|
+
]);
|
|
4579
|
+
function erc2612TypedData(input) {
|
|
4580
|
+
return {
|
|
4581
|
+
domain: {
|
|
4582
|
+
name: input.permit.tokenName,
|
|
4583
|
+
version: input.permit.tokenVersion,
|
|
4584
|
+
chainId: input.chainId,
|
|
4585
|
+
verifyingContract: input.token
|
|
4586
|
+
},
|
|
4587
|
+
types: ERC2612_PERMIT_TYPES,
|
|
4588
|
+
primaryType: "Permit",
|
|
4589
|
+
message: {
|
|
4590
|
+
owner: input.owner,
|
|
4591
|
+
spender: BATCH_PERMIT2_ADDRESS,
|
|
4592
|
+
value: BigInt(input.permit.value),
|
|
4593
|
+
nonce: BigInt(input.permit.nonce),
|
|
4594
|
+
deadline: BigInt(input.permit.deadline)
|
|
4595
|
+
}
|
|
4596
|
+
};
|
|
4597
|
+
}
|
|
4285
4598
|
var PERMIT_BATCH_TYPES = {
|
|
4286
4599
|
PermitBatchWitnessTransferFrom: [
|
|
4287
4600
|
{ name: "permitted", type: "TokenPermissions[]" },
|
|
@@ -4296,7 +4609,7 @@ var PERMIT_BATCH_TYPES = {
|
|
|
4296
4609
|
{ name: "amount", type: "uint256" }
|
|
4297
4610
|
]
|
|
4298
4611
|
};
|
|
4299
|
-
var PERMIT2_BATCH_ABI = (0,
|
|
4612
|
+
var PERMIT2_BATCH_ABI = (0, import_viem9.parseAbi)([
|
|
4300
4613
|
"struct TokenPermissions { address token; uint256 amount; }",
|
|
4301
4614
|
"struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
|
|
4302
4615
|
"struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
|
|
@@ -4355,7 +4668,7 @@ function clear(key2) {
|
|
|
4355
4668
|
else window.localStorage.removeItem(key2);
|
|
4356
4669
|
}
|
|
4357
4670
|
function sponsorTokenBatch(i) {
|
|
4358
|
-
const key2 = `owney.token-batch.v1:${(0,
|
|
4671
|
+
const key2 = `owney.token-batch.v1:${(0, import_viem10.keccak256)((0, import_viem10.toBytes)(i.apiKey))}:${i.baseUrl ?? "default"}:${i.chainId}:${i.owner.toLowerCase()}:${i.token.toLowerCase()}`;
|
|
4359
4672
|
const plan = planOf(i.transfers);
|
|
4360
4673
|
const active = inflight.get(key2);
|
|
4361
4674
|
if (active) {
|
|
@@ -4386,7 +4699,7 @@ async function execute(i, key2, plan) {
|
|
|
4386
4699
|
baseUrl: i.baseUrl,
|
|
4387
4700
|
body
|
|
4388
4701
|
});
|
|
4389
|
-
if (!prepared.serializedTransaction || (0,
|
|
4702
|
+
if (!prepared.serializedTransaction || (0, import_viem10.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
|
|
4390
4703
|
throw new Error(
|
|
4391
4704
|
"Sponsorship API did not return a valid prepared transaction."
|
|
4392
4705
|
);
|
|
@@ -4401,7 +4714,7 @@ async function execute(i, key2, plan) {
|
|
|
4401
4714
|
baseUrl: i.baseUrl,
|
|
4402
4715
|
body
|
|
4403
4716
|
});
|
|
4404
|
-
if (result.txHash !== (0,
|
|
4717
|
+
if (result.txHash !== (0, import_viem10.keccak256)(body.serializedTransaction))
|
|
4405
4718
|
throw new Error(
|
|
4406
4719
|
"Sponsorship receipt does not match the pending transaction."
|
|
4407
4720
|
);
|
|
@@ -4416,7 +4729,7 @@ async function execute(i, key2, plan) {
|
|
|
4416
4729
|
const saved = read(key2);
|
|
4417
4730
|
if (saved) {
|
|
4418
4731
|
const previous = JSON.parse(saved);
|
|
4419
|
-
if (previous.chainId !== i.chainId || !(0,
|
|
4732
|
+
if (previous.chainId !== i.chainId || !(0, import_viem10.isAddressEqual)(previous.from, i.owner) || !(0, import_viem10.isAddressEqual)(previous.token, i.token) || planOf(previous.transfers) !== plan)
|
|
4420
4733
|
throw new Error(
|
|
4421
4734
|
"Retry the previous token deposit and agent split first to reconcile its status."
|
|
4422
4735
|
);
|
|
@@ -4433,28 +4746,67 @@ async function execute(i, key2, plan) {
|
|
|
4433
4746
|
"DEPOSIT_INSUFFICIENT_BALANCE",
|
|
4434
4747
|
"Insufficient token balance for this deposit."
|
|
4435
4748
|
);
|
|
4436
|
-
if (allowance < total)
|
|
4749
|
+
if (allowance < total && (i.chainId !== 8453 || !(0, import_viem10.isAddressEqual)(i.token, BASE_USDC_ADDRESS)))
|
|
4437
4750
|
throw new OwneyError(
|
|
4438
4751
|
"PERMIT2_APPROVAL_REQUIRED",
|
|
4439
4752
|
"token deposits need a one-time Permit2 approval."
|
|
4440
4753
|
);
|
|
4441
|
-
const
|
|
4754
|
+
const now = (await i.pub.getBlock()).timestamp;
|
|
4755
|
+
let erc2612Permit;
|
|
4756
|
+
if (allowance < total) {
|
|
4757
|
+
const [tokenName, tokenVersion, permitNonce] = await Promise.all([
|
|
4758
|
+
i.pub.readContract({
|
|
4759
|
+
address: i.token,
|
|
4760
|
+
abi: ERC2612_READ_ABI,
|
|
4761
|
+
functionName: "name"
|
|
4762
|
+
}),
|
|
4763
|
+
i.pub.readContract({
|
|
4764
|
+
address: i.token,
|
|
4765
|
+
abi: ERC2612_READ_ABI,
|
|
4766
|
+
functionName: "version"
|
|
4767
|
+
}),
|
|
4768
|
+
i.pub.readContract({
|
|
4769
|
+
address: i.token,
|
|
4770
|
+
abi: ERC2612_READ_ABI,
|
|
4771
|
+
functionName: "nonces",
|
|
4772
|
+
args: [i.owner]
|
|
4773
|
+
})
|
|
4774
|
+
]);
|
|
4775
|
+
const unsignedPermit = {
|
|
4776
|
+
value: MAX_UINT256.toString(),
|
|
4777
|
+
nonce: permitNonce.toString(),
|
|
4778
|
+
deadline: (now + 900n).toString(),
|
|
4779
|
+
tokenName,
|
|
4780
|
+
tokenVersion
|
|
4781
|
+
};
|
|
4782
|
+
const signature2 = await i.wallet.signTypedData({
|
|
4783
|
+
account: i.owner,
|
|
4784
|
+
...erc2612TypedData({
|
|
4785
|
+
chainId: 8453,
|
|
4786
|
+
token: i.token,
|
|
4787
|
+
owner: i.owner,
|
|
4788
|
+
permit: unsignedPermit
|
|
4789
|
+
})
|
|
4790
|
+
});
|
|
4791
|
+
erc2612Permit = { ...unsignedPermit, signature: signature2 };
|
|
4792
|
+
}
|
|
4793
|
+
const spender = erc2612Permit ? MULTICALL3_ADDRESS : await getSponsorRelayerAddress({
|
|
4442
4794
|
apiKey: i.apiKey,
|
|
4443
4795
|
baseUrl: i.baseUrl,
|
|
4444
4796
|
chainId: i.chainId
|
|
4445
4797
|
});
|
|
4446
|
-
const now = (await i.pub.getBlock()).timestamp;
|
|
4447
4798
|
const unsigned = {
|
|
4448
4799
|
chainId: i.chainId,
|
|
4449
4800
|
token: i.token,
|
|
4450
4801
|
from: i.owner,
|
|
4451
4802
|
transfers: i.transfers,
|
|
4452
4803
|
nonce: randomPermit2Nonce().toString(),
|
|
4453
|
-
deadline: (now + 900n).toString()
|
|
4804
|
+
deadline: (now + 900n).toString(),
|
|
4805
|
+
...erc2612Permit ? { erc2612Permit } : {}
|
|
4454
4806
|
};
|
|
4455
4807
|
const signature = await i.wallet.signTypedData({
|
|
4456
4808
|
account: i.owner,
|
|
4457
|
-
...batchTypedData(unsigned,
|
|
4809
|
+
...batchTypedData(unsigned, spender)
|
|
4458
4810
|
});
|
|
4459
4811
|
i.onApproved?.();
|
|
4460
4812
|
return send({ ...unsigned, signature });
|
|
@@ -4474,8 +4826,8 @@ function makeSponsoredTokenCallback(deps) {
|
|
|
4474
4826
|
"CHAIN_UNSUPPORTED",
|
|
4475
4827
|
`No sponsored token configured for chain ${chainId}`
|
|
4476
4828
|
);
|
|
4477
|
-
const pub = deps.getPublicClient(chainId), wallet = deps.getWalletClient(chainId);
|
|
4478
|
-
await ensureWalletOnChain(
|
|
4829
|
+
const pub = deps.getPublicClient(chainId), walletChain = deps.getWalletChainClient?.(chainId) ?? pub, wallet = deps.getWalletClient(chainId);
|
|
4830
|
+
await ensureWalletOnChain(walletChain, wallet, chainId);
|
|
4479
4831
|
return sponsorTokenBatch({
|
|
4480
4832
|
apiKey: deps.apiKey,
|
|
4481
4833
|
baseUrl: deps.baseUrl,
|
|
@@ -4571,7 +4923,7 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
|
|
|
4571
4923
|
}
|
|
4572
4924
|
|
|
4573
4925
|
// src/lib/sponsored-calls-deposit.ts
|
|
4574
|
-
var
|
|
4926
|
+
var import_viem11 = require("viem");
|
|
4575
4927
|
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
4576
4928
|
var DEFAULT_MAX_POLLS = 30;
|
|
4577
4929
|
async function paymasterSupported(provider, owner, chainId) {
|
|
@@ -4579,7 +4931,7 @@ async function paymasterSupported(provider, owner, chainId) {
|
|
|
4579
4931
|
method: "wallet_getCapabilities",
|
|
4580
4932
|
params: [owner]
|
|
4581
4933
|
});
|
|
4582
|
-
const forChain = caps?.[(0,
|
|
4934
|
+
const forChain = caps?.[(0, import_viem11.toHex)(chainId)] ?? caps?.[String(chainId)];
|
|
4583
4935
|
return Boolean(forChain?.paymasterService?.supported);
|
|
4584
4936
|
}
|
|
4585
4937
|
function makeSponsoredCallsCallback(deps) {
|
|
@@ -4616,8 +4968,8 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
4616
4968
|
const calls = transfers.map((transfer) => ({
|
|
4617
4969
|
to: token,
|
|
4618
4970
|
value: "0x0",
|
|
4619
|
-
data: (0,
|
|
4620
|
-
abi:
|
|
4971
|
+
data: (0, import_viem11.encodeFunctionData)({
|
|
4972
|
+
abi: import_viem11.erc20Abi,
|
|
4621
4973
|
functionName: "transfer",
|
|
4622
4974
|
args: [transfer.to, BigInt(transfer.amount)]
|
|
4623
4975
|
})
|
|
@@ -4655,7 +5007,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
4655
5007
|
{
|
|
4656
5008
|
version: "2.0.0",
|
|
4657
5009
|
from: deps.ownerAddress,
|
|
4658
|
-
chainId: (0,
|
|
5010
|
+
chainId: (0, import_viem11.toHex)(chainId),
|
|
4659
5011
|
atomicRequired: transfers.length > 1,
|
|
4660
5012
|
calls,
|
|
4661
5013
|
capabilities: {
|
|
@@ -4777,6 +5129,7 @@ var OwneySDK = class {
|
|
|
4777
5129
|
// leave every user's agent profile alone.
|
|
4778
5130
|
orgAgentConfig;
|
|
4779
5131
|
orgAgentConfigPromise = null;
|
|
5132
|
+
rpcUrls;
|
|
4780
5133
|
zyfaiRpcUrls;
|
|
4781
5134
|
yieldseekerApiBaseUrl;
|
|
4782
5135
|
yieldseekerSiweOrigin;
|
|
@@ -4801,7 +5154,12 @@ var OwneySDK = class {
|
|
|
4801
5154
|
constructor(config) {
|
|
4802
5155
|
this.apiKey = config.apiKey;
|
|
4803
5156
|
if (config.debug) setOwneyDebug(true);
|
|
4804
|
-
this.
|
|
5157
|
+
this.rpcUrls = resolveRpcUrls(
|
|
5158
|
+
config.rpcUrls,
|
|
5159
|
+
config.apiKey,
|
|
5160
|
+
config.routingApiBaseUrl
|
|
5161
|
+
);
|
|
5162
|
+
this.zyfaiRpcUrls = config.rpcUrls ? void 0 : config.zyfaiRpcUrls;
|
|
4805
5163
|
this.yieldseekerApiBaseUrl = config.yieldseekerApiBaseUrl;
|
|
4806
5164
|
this.yieldseekerSiweOrigin = config.yieldseekerSiweOrigin;
|
|
4807
5165
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
@@ -4891,6 +5249,9 @@ var OwneySDK = class {
|
|
|
4891
5249
|
}
|
|
4892
5250
|
return this.state.provider;
|
|
4893
5251
|
}
|
|
5252
|
+
getPaidRpcClient(chainId) {
|
|
5253
|
+
return createPaidRpcClient(VIEM_CHAIN2[chainId], this.rpcUrls);
|
|
5254
|
+
}
|
|
4894
5255
|
/** Builds the default USDC batch callback for the connected wallet. */
|
|
4895
5256
|
getDefaultSponsoredCallback(onApproved) {
|
|
4896
5257
|
if (!onApproved && this.cachedSponsoredCallback)
|
|
@@ -4906,14 +5267,15 @@ var OwneySDK = class {
|
|
|
4906
5267
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
4907
5268
|
// PublicClient/WalletClient param types — structurally identical at
|
|
4908
5269
|
// runtime, but the two share a name TS treats as unrelated.
|
|
4909
|
-
getPublicClient: (cid) => (
|
|
5270
|
+
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
5271
|
+
getWalletChainClient: (cid) => (0, import_viem12.createPublicClient)({
|
|
4910
5272
|
chain: VIEM_CHAIN2[cid],
|
|
4911
|
-
transport: (0,
|
|
5273
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4912
5274
|
}),
|
|
4913
|
-
getWalletClient: (cid) => (0,
|
|
5275
|
+
getWalletClient: (cid) => (0, import_viem12.createWalletClient)({
|
|
4914
5276
|
account: owner,
|
|
4915
5277
|
chain: VIEM_CHAIN2[cid],
|
|
4916
|
-
transport: (0,
|
|
5278
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4917
5279
|
})
|
|
4918
5280
|
});
|
|
4919
5281
|
if (!onApproved) this.cachedSponsoredCallback = callback;
|
|
@@ -4956,14 +5318,15 @@ var OwneySDK = class {
|
|
|
4956
5318
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
4957
5319
|
// PublicClient/WalletClient param types — structurally identical at
|
|
4958
5320
|
// runtime, but the two share a name TS treats as unrelated.
|
|
4959
|
-
getPublicClient: (cid) => (
|
|
5321
|
+
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
5322
|
+
getWalletChainClient: (cid) => (0, import_viem12.createPublicClient)({
|
|
4960
5323
|
chain: VIEM_CHAIN2[cid],
|
|
4961
|
-
transport: (0,
|
|
5324
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4962
5325
|
}),
|
|
4963
|
-
getWalletClient: (cid) => (0,
|
|
5326
|
+
getWalletClient: (cid) => (0, import_viem12.createWalletClient)({
|
|
4964
5327
|
account: owner,
|
|
4965
5328
|
chain: VIEM_CHAIN2[cid],
|
|
4966
|
-
transport: (0,
|
|
5329
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4967
5330
|
})
|
|
4968
5331
|
});
|
|
4969
5332
|
if (!onApproved) this.cachedWethSponsoredCallback = callback;
|
|
@@ -5069,12 +5432,21 @@ var OwneySDK = class {
|
|
|
5069
5432
|
createAgent(agentId, key2) {
|
|
5070
5433
|
if (agentId === "zyfai") {
|
|
5071
5434
|
if (!key2) return null;
|
|
5072
|
-
return new ZyfaiAgent(
|
|
5435
|
+
return new ZyfaiAgent(
|
|
5436
|
+
key2,
|
|
5437
|
+
this.zyfaiRpcUrls ? resolveRpcUrls(
|
|
5438
|
+
this.zyfaiRpcUrls,
|
|
5439
|
+
this.apiKey,
|
|
5440
|
+
this.routingApiBaseUrl
|
|
5441
|
+
) : this.rpcUrls,
|
|
5442
|
+
this.referralSource
|
|
5443
|
+
);
|
|
5073
5444
|
}
|
|
5074
5445
|
if (agentId === "yieldseeker") {
|
|
5075
5446
|
return new YieldseekerAgent(this.apiKey, {
|
|
5076
5447
|
auth: { origin: this.yieldseekerSiweOrigin },
|
|
5077
|
-
baseUrl: this.yieldseekerApiBaseUrl ?? getYieldseekerProxyBaseUrl(this.routingApiBaseUrl)
|
|
5448
|
+
baseUrl: this.yieldseekerApiBaseUrl ?? getYieldseekerProxyBaseUrl(this.routingApiBaseUrl),
|
|
5449
|
+
rpcUrls: this.rpcUrls
|
|
5078
5450
|
});
|
|
5079
5451
|
}
|
|
5080
5452
|
return null;
|
|
@@ -5410,10 +5782,12 @@ var OwneySDK = class {
|
|
|
5410
5782
|
* Invokes `agent.deposit` with the resolved sponsored callback, composing
|
|
5411
5783
|
* two independent auto-recovery mechanisms:
|
|
5412
5784
|
*
|
|
5413
|
-
* 1. Missing Permit2 allowance
|
|
5414
|
-
* callback and the attempt fails with
|
|
5415
|
-
*
|
|
5416
|
-
*
|
|
5785
|
+
* 1. Missing Permit2 allowance outside the atomic Base-USDC path: when the
|
|
5786
|
+
* app did not supply its own callback and the attempt fails with
|
|
5787
|
+
* `PERMIT2_APPROVAL_REQUIRED`, this is the wallet's first Permit2 deposit
|
|
5788
|
+
* for that token. Base USDC bundles a gasless ERC-2612 approval inside
|
|
5789
|
+
* its sponsored deposit and never reaches this branch. Other tokens send
|
|
5790
|
+
* the one-time user-paid Permit2 approval via `approvePermit2()` and
|
|
5417
5791
|
* retry the SAME sponsored attempt once. Bounded to one approval attempt
|
|
5418
5792
|
* per call so a wallet/agent that keeps reporting the allowance as
|
|
5419
5793
|
* missing can't loop forever. If `approvePermit2()` itself throws (e.g.
|
|
@@ -5604,6 +5978,32 @@ var OwneySDK = class {
|
|
|
5604
5978
|
}
|
|
5605
5979
|
return eligible;
|
|
5606
5980
|
}
|
|
5981
|
+
/**
|
|
5982
|
+
* Run owner-approved withdrawals before relayer-only withdrawals. Wallet
|
|
5983
|
+
* approval is the only point at which the user can cancel the aggregate
|
|
5984
|
+
* operation, so no relayer leg should commit before it has completed.
|
|
5985
|
+
*/
|
|
5986
|
+
orderAgentsForWithdrawal(agents) {
|
|
5987
|
+
return agents.map((agent, index) => ({ agent, index })).sort((left, right) => {
|
|
5988
|
+
const approvalOrder = Number(Boolean(right.agent.withdrawalRequiresWalletApproval)) - Number(Boolean(left.agent.withdrawalRequiresWalletApproval));
|
|
5989
|
+
return approvalOrder || left.index - right.index;
|
|
5990
|
+
}).map(({ agent }) => agent);
|
|
5991
|
+
}
|
|
5992
|
+
isUserRejectedWithdrawal(error) {
|
|
5993
|
+
let current = error;
|
|
5994
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5995
|
+
while (current && typeof current === "object" && !seen.has(current)) {
|
|
5996
|
+
seen.add(current);
|
|
5997
|
+
const candidate = current;
|
|
5998
|
+
if (candidate.code === 4001 || candidate.code === "4001") return true;
|
|
5999
|
+
const message = [candidate.message, candidate.shortMessage].filter((value) => typeof value === "string").join(" ");
|
|
6000
|
+
if (/user (?:rejected|denied)|rejected by user/i.test(message)) {
|
|
6001
|
+
return true;
|
|
6002
|
+
}
|
|
6003
|
+
current = candidate.cause;
|
|
6004
|
+
}
|
|
6005
|
+
return false;
|
|
6006
|
+
}
|
|
5607
6007
|
// --- Fund operations ---
|
|
5608
6008
|
/**
|
|
5609
6009
|
* Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
|
|
@@ -5639,13 +6039,15 @@ var OwneySDK = class {
|
|
|
5639
6039
|
);
|
|
5640
6040
|
}
|
|
5641
6041
|
const eligibleAgents = this.getEligibleAgents(chainId, asset);
|
|
6042
|
+
const withdrawalAgents = this.orderAgentsForWithdrawal(eligibleAgents);
|
|
5642
6043
|
if (!amount) {
|
|
5643
6044
|
const results2 = {};
|
|
5644
6045
|
const agentErrors2 = {};
|
|
5645
|
-
for (const agent of
|
|
6046
|
+
for (const agent of withdrawalAgents) {
|
|
5646
6047
|
try {
|
|
5647
6048
|
results2[agent.id] = await agent.withdraw(state, chainId, token);
|
|
5648
6049
|
} catch (err) {
|
|
6050
|
+
if (this.isUserRejectedWithdrawal(err)) throw err;
|
|
5649
6051
|
console.error(`withdraw failed for agent "${agent.id}":`, err);
|
|
5650
6052
|
agentErrors2[agent.id] = err instanceof Error ? err.message : String(err);
|
|
5651
6053
|
const code = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
|
|
@@ -5726,12 +6128,13 @@ var OwneySDK = class {
|
|
|
5726
6128
|
planned: 0n
|
|
5727
6129
|
}));
|
|
5728
6130
|
const plans = [...disabledPlans, ...enabledPlans];
|
|
6131
|
+
const orderedPlans = this.orderAgentsForWithdrawal(plans.map((p) => p.agent)).map((agent) => plans.find((plan) => plan.agent === agent));
|
|
5729
6132
|
const results = {};
|
|
5730
6133
|
const agentErrors = {
|
|
5731
6134
|
...aggregated.agentErrors ?? {}
|
|
5732
6135
|
};
|
|
5733
|
-
for (let i = 0; i <
|
|
5734
|
-
const p =
|
|
6136
|
+
for (let i = 0; i < orderedPlans.length; i++) {
|
|
6137
|
+
const p = orderedPlans[i];
|
|
5735
6138
|
if (p.planned === 0n) continue;
|
|
5736
6139
|
try {
|
|
5737
6140
|
results[p.agent.id] = await p.agent.withdraw(
|
|
@@ -5741,6 +6144,7 @@ var OwneySDK = class {
|
|
|
5741
6144
|
p.planned.toString()
|
|
5742
6145
|
);
|
|
5743
6146
|
} catch (err) {
|
|
6147
|
+
if (this.isUserRejectedWithdrawal(err)) throw err;
|
|
5744
6148
|
console.error(`withdraw failed for agent "${p.agent.id}":`, err);
|
|
5745
6149
|
agentErrors[p.agent.id] = err instanceof Error ? err.message : String(err);
|
|
5746
6150
|
const code = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
|
|
@@ -5752,7 +6156,7 @@ var OwneySDK = class {
|
|
|
5752
6156
|
);
|
|
5753
6157
|
const failedAmount = p.planned;
|
|
5754
6158
|
p.planned = 0n;
|
|
5755
|
-
redistributeShare(
|
|
6159
|
+
redistributeShare(orderedPlans, i, failedAmount);
|
|
5756
6160
|
}
|
|
5757
6161
|
}
|
|
5758
6162
|
if (Object.keys(results).length === 0) {
|
|
@@ -6199,17 +6603,18 @@ var OwneySDK = class {
|
|
|
6199
6603
|
);
|
|
6200
6604
|
}
|
|
6201
6605
|
const provider = this.requireConnectedProvider();
|
|
6202
|
-
const
|
|
6606
|
+
const walletChainClient = (0, import_viem12.createPublicClient)({
|
|
6203
6607
|
chain: VIEM_CHAIN2[chainId],
|
|
6204
|
-
transport: (0,
|
|
6608
|
+
transport: (0, import_viem12.custom)(provider)
|
|
6205
6609
|
});
|
|
6610
|
+
const publicClient = this.getPaidRpcClient(chainId);
|
|
6206
6611
|
const approvalAmount = permit2ApprovalAmount(requiredAmount);
|
|
6207
|
-
const wallet = (0,
|
|
6612
|
+
const wallet = (0, import_viem12.createWalletClient)({
|
|
6208
6613
|
account: state.walletAddress,
|
|
6209
6614
|
chain: VIEM_CHAIN2[chainId],
|
|
6210
|
-
transport: (0,
|
|
6615
|
+
transport: (0, import_viem12.custom)(provider)
|
|
6211
6616
|
});
|
|
6212
|
-
await ensureWalletOnChain(
|
|
6617
|
+
await ensureWalletOnChain(walletChainClient, wallet, chainId);
|
|
6213
6618
|
const hash = await wallet.writeContract({
|
|
6214
6619
|
address: token,
|
|
6215
6620
|
abi: ERC20_ALLOWANCE_ABI,
|
|
@@ -6218,10 +6623,14 @@ var OwneySDK = class {
|
|
|
6218
6623
|
account: state.walletAddress,
|
|
6219
6624
|
chain: VIEM_CHAIN2[chainId]
|
|
6220
6625
|
});
|
|
6221
|
-
const receipt = await
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6626
|
+
const receipt = await withPaidRpcDiagnostics(
|
|
6627
|
+
() => publicClient.waitForTransactionReceipt({
|
|
6628
|
+
hash,
|
|
6629
|
+
confirmations: 1
|
|
6630
|
+
}),
|
|
6631
|
+
chainId,
|
|
6632
|
+
"eth_getTransactionReceipt"
|
|
6633
|
+
);
|
|
6225
6634
|
if (receipt.status !== "success") {
|
|
6226
6635
|
throw new Error(`Permit2 approval reverted (tx ${hash})`);
|
|
6227
6636
|
}
|
|
@@ -6365,7 +6774,7 @@ var OwneySDK = class {
|
|
|
6365
6774
|
};
|
|
6366
6775
|
|
|
6367
6776
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
6368
|
-
var
|
|
6777
|
+
var import_viem13 = require("viem");
|
|
6369
6778
|
var import_siwe2 = require("siwe");
|
|
6370
6779
|
var import_sdk2 = require("@zyfai/sdk");
|
|
6371
6780
|
|
|
@@ -6492,7 +6901,7 @@ function buildSIWXConfig(deps) {
|
|
|
6492
6901
|
issuedAt,
|
|
6493
6902
|
toString() {
|
|
6494
6903
|
return new import_siwe2.SiweMessage({
|
|
6495
|
-
address: (0,
|
|
6904
|
+
address: (0, import_viem13.getAddress)(accountAddress),
|
|
6496
6905
|
chainId: numericChainId(chainId),
|
|
6497
6906
|
domain,
|
|
6498
6907
|
uri,
|