@owney/sdk 0.7.25-beta.4 → 0.7.25-beta.6
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 +72 -13
- package/dist/index.cjs +564 -180
- package/dist/index.d.cts +47 -6
- package/dist/index.d.ts +47 -6
- package/dist/index.js +505 -118
- 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,128 @@ 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
|
+
var DEFAULT_RPC_URLS = {
|
|
1137
|
+
1: "https://eth-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
1138
|
+
8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
1139
|
+
42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
|
|
1140
|
+
};
|
|
1141
|
+
function resolveRpcUrl(rpcUrls, chainId) {
|
|
1142
|
+
const url = rpcUrls?.[chainId]?.trim();
|
|
1143
|
+
if (url) return url;
|
|
1144
|
+
return DEFAULT_RPC_URLS[chainId];
|
|
1145
|
+
}
|
|
1146
|
+
function resolveRpcUrls(rpcUrls) {
|
|
1147
|
+
return {
|
|
1148
|
+
1: resolveRpcUrl(rpcUrls, 1),
|
|
1149
|
+
8453: resolveRpcUrl(rpcUrls, 8453),
|
|
1150
|
+
42161: resolveRpcUrl(rpcUrls, 42161)
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
function createPaidRpcClient(chain, rpcUrls) {
|
|
1154
|
+
const url = resolveRpcUrl(
|
|
1155
|
+
rpcUrls,
|
|
1156
|
+
chain.id
|
|
1157
|
+
);
|
|
1158
|
+
return (0, import_viem.createPublicClient)({
|
|
1159
|
+
chain,
|
|
1160
|
+
transport: (0, import_viem.http)(url, {
|
|
1161
|
+
retryCount: PAID_RPC_RETRY_COUNT,
|
|
1162
|
+
retryDelay: PAID_RPC_RETRY_DELAY_MS
|
|
1163
|
+
})
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
function headerValue(error, name) {
|
|
1167
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1168
|
+
let value;
|
|
1169
|
+
function visit(candidate, depth = 0) {
|
|
1170
|
+
if (value || depth > 6 || !candidate || typeof candidate !== "object")
|
|
1171
|
+
return;
|
|
1172
|
+
if (seen.has(candidate)) return;
|
|
1173
|
+
seen.add(candidate);
|
|
1174
|
+
const record = candidate;
|
|
1175
|
+
const headers = record.headers;
|
|
1176
|
+
const found = typeof headers?.get === "function" ? headers.get(name) : headers?.[name] ?? headers?.[name.toLowerCase()];
|
|
1177
|
+
if (typeof found === "string" && found) {
|
|
1178
|
+
value = found;
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
for (const key2 of ["cause", "details", "response", "error"])
|
|
1182
|
+
visit(record[key2], depth + 1);
|
|
1183
|
+
}
|
|
1184
|
+
visit(error);
|
|
1185
|
+
return value;
|
|
1186
|
+
}
|
|
1187
|
+
function statusCode(error) {
|
|
1188
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1189
|
+
let status;
|
|
1190
|
+
function visit(candidate, depth = 0) {
|
|
1191
|
+
if (status || depth > 6 || !candidate || typeof candidate !== "object")
|
|
1192
|
+
return;
|
|
1193
|
+
if (seen.has(candidate)) return;
|
|
1194
|
+
seen.add(candidate);
|
|
1195
|
+
const record = candidate;
|
|
1196
|
+
for (const key2 of ["status", "statusCode"]) {
|
|
1197
|
+
const parsed = Number(record[key2]);
|
|
1198
|
+
if (Number.isInteger(parsed) && parsed >= 100 && parsed <= 599) {
|
|
1199
|
+
status = parsed;
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
for (const key2 of ["cause", "details", "response", "error"])
|
|
1204
|
+
visit(record[key2], depth + 1);
|
|
1205
|
+
}
|
|
1206
|
+
visit(error);
|
|
1207
|
+
return status;
|
|
1208
|
+
}
|
|
1209
|
+
function paidRpcError(error, chainId, rpcMethod, agentId) {
|
|
1210
|
+
const delay = rateLimitDelay(error);
|
|
1211
|
+
const providerRequestId = headerValue(error, "x-alchemy-request-id") ?? headerValue(error, "x-request-id");
|
|
1212
|
+
if (delay === void 0) {
|
|
1213
|
+
return new OwneyError(
|
|
1214
|
+
"AGENT_API_ERROR",
|
|
1215
|
+
"The blockchain RPC request failed.",
|
|
1216
|
+
{
|
|
1217
|
+
rpcSource: "paid-rpc",
|
|
1218
|
+
chainId,
|
|
1219
|
+
rpcMethod,
|
|
1220
|
+
...statusCode(error) ? { statusCode: statusCode(error) } : {},
|
|
1221
|
+
...providerRequestId ? { providerRequestId } : {}
|
|
1222
|
+
},
|
|
1223
|
+
agentId
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1226
|
+
const retryAt = Date.now() + delay;
|
|
1227
|
+
return new OwneyError(
|
|
1228
|
+
"AGENT_RATE_LIMITED",
|
|
1229
|
+
"The blockchain RPC is rate limited. Please wait before trying again.",
|
|
1230
|
+
{
|
|
1231
|
+
rpcSource: "paid-rpc",
|
|
1232
|
+
chainId,
|
|
1233
|
+
rpcMethod,
|
|
1234
|
+
statusCode: 429,
|
|
1235
|
+
retryAt,
|
|
1236
|
+
retryAfterSeconds: Math.max(0, Math.ceil(delay / 1e3)),
|
|
1237
|
+
...providerRequestId ? { providerRequestId } : {}
|
|
1238
|
+
},
|
|
1239
|
+
agentId
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
async function withPaidRpcDiagnostics(operation, chainId, rpcMethod, agentId) {
|
|
1243
|
+
try {
|
|
1244
|
+
return await operation();
|
|
1245
|
+
} catch (error) {
|
|
1246
|
+
throw paidRpcError(error, chainId, rpcMethod, agentId);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1100
1250
|
// src/agents/zyfai/zyfai.agent.ts
|
|
1101
|
-
var ERC7579_IS_MODULE_INSTALLED_ABI = (0,
|
|
1251
|
+
var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem2.parseAbi)([
|
|
1102
1252
|
"function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)"
|
|
1103
1253
|
]);
|
|
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
1254
|
var WETH_ADDRESS_BY_CHAIN = {
|
|
1110
1255
|
8453: "0x4200000000000000000000000000000000000006",
|
|
1111
1256
|
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
@@ -1171,7 +1316,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1171
1316
|
earningsSnapshot = null;
|
|
1172
1317
|
earningsGeneration = 0;
|
|
1173
1318
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
1174
|
-
this.rpcUrls = rpcUrls
|
|
1319
|
+
this.rpcUrls = resolveRpcUrls(rpcUrls);
|
|
1175
1320
|
this.sdk = new import_sdk.ZyfaiSDK({
|
|
1176
1321
|
apiKey,
|
|
1177
1322
|
rpcUrls: this.rpcUrls,
|
|
@@ -1185,10 +1330,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1185
1330
|
getPublicClient(chainId) {
|
|
1186
1331
|
const cached = this.publicClients.get(chainId);
|
|
1187
1332
|
if (cached) return cached;
|
|
1188
|
-
const client = (
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1333
|
+
const client = createPaidRpcClient(
|
|
1334
|
+
VIEM_CHAIN[chainId],
|
|
1335
|
+
this.rpcUrls
|
|
1336
|
+
);
|
|
1192
1337
|
this.publicClients.set(chainId, client);
|
|
1193
1338
|
return client;
|
|
1194
1339
|
}
|
|
@@ -2156,7 +2301,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2156
2301
|
};
|
|
2157
2302
|
|
|
2158
2303
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
2159
|
-
var
|
|
2304
|
+
var import_viem7 = require("viem");
|
|
2160
2305
|
var import_chains3 = require("viem/chains");
|
|
2161
2306
|
|
|
2162
2307
|
// src/lib/chain-guard.ts
|
|
@@ -2195,7 +2340,7 @@ async function ensureWalletOnChain(pub, wallet, expected) {
|
|
|
2195
2340
|
}
|
|
2196
2341
|
|
|
2197
2342
|
// src/lib/transfer-auth.ts
|
|
2198
|
-
var
|
|
2343
|
+
var import_viem3 = require("viem");
|
|
2199
2344
|
|
|
2200
2345
|
// src/lib/sponsor-client.ts
|
|
2201
2346
|
var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
@@ -2311,7 +2456,7 @@ async function postSponsorBatchTransfer(input) {
|
|
|
2311
2456
|
}
|
|
2312
2457
|
|
|
2313
2458
|
// src/lib/permit2.ts
|
|
2314
|
-
var
|
|
2459
|
+
var import_viem4 = require("viem");
|
|
2315
2460
|
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
2316
2461
|
var MAX_UINT256 = 2n ** 256n - 1n;
|
|
2317
2462
|
function permit2ApprovalAmount(requiredAmount) {
|
|
@@ -2352,7 +2497,7 @@ var ERC20_ALLOWANCE_ABI = [
|
|
|
2352
2497
|
function randomPermit2Nonce() {
|
|
2353
2498
|
const bytes = new Uint8Array(32);
|
|
2354
2499
|
globalThis.crypto.getRandomValues(bytes);
|
|
2355
|
-
return BigInt((0,
|
|
2500
|
+
return BigInt((0, import_viem4.bytesToHex)(bytes));
|
|
2356
2501
|
}
|
|
2357
2502
|
async function readPermit2Allowance(publicClient, token, owner, blockNumber) {
|
|
2358
2503
|
return publicClient.readContract({
|
|
@@ -2395,7 +2540,7 @@ function makeVerificationAwareDepositCallback(implementation) {
|
|
|
2395
2540
|
|
|
2396
2541
|
// src/agents/yieldseeker/yieldseeker.auth.ts
|
|
2397
2542
|
var import_siwe = require("siwe");
|
|
2398
|
-
var
|
|
2543
|
+
var import_viem5 = require("viem");
|
|
2399
2544
|
var import_chains2 = require("viem/chains");
|
|
2400
2545
|
|
|
2401
2546
|
// src/agents/yieldseeker/yieldseeker.auth-cache.ts
|
|
@@ -2508,7 +2653,7 @@ function createYieldseekerSiweMessage(address, chainId, dependencies = {}) {
|
|
|
2508
2653
|
return new import_siwe.SiweMessage({
|
|
2509
2654
|
scheme: url.protocol.slice(0, -1),
|
|
2510
2655
|
domain: url.host,
|
|
2511
|
-
address: (0,
|
|
2656
|
+
address: (0, import_viem5.getAddress)(address),
|
|
2512
2657
|
uri: url.origin,
|
|
2513
2658
|
version: "1",
|
|
2514
2659
|
chainId,
|
|
@@ -2594,15 +2739,15 @@ var YieldseekerAuth = class {
|
|
|
2594
2739
|
clearYieldseekerSession(state.walletAddress, chainId);
|
|
2595
2740
|
}
|
|
2596
2741
|
async sign(state, chainId) {
|
|
2597
|
-
const account = (0,
|
|
2598
|
-
const publicClient = (0,
|
|
2742
|
+
const account = (0, import_viem5.getAddress)(state.walletAddress);
|
|
2743
|
+
const publicClient = (0, import_viem5.createPublicClient)({
|
|
2599
2744
|
chain: import_chains2.base,
|
|
2600
|
-
transport: (0,
|
|
2745
|
+
transport: (0, import_viem5.custom)(state.provider)
|
|
2601
2746
|
});
|
|
2602
|
-
const walletClient = (0,
|
|
2747
|
+
const walletClient = (0, import_viem5.createWalletClient)({
|
|
2603
2748
|
account,
|
|
2604
2749
|
chain: import_chains2.base,
|
|
2605
|
-
transport: (0,
|
|
2750
|
+
transport: (0, import_viem5.custom)(state.provider)
|
|
2606
2751
|
});
|
|
2607
2752
|
await ensureWalletOnChain(
|
|
2608
2753
|
publicClient,
|
|
@@ -2768,7 +2913,7 @@ var YieldseekerApiClient = class {
|
|
|
2768
2913
|
};
|
|
2769
2914
|
|
|
2770
2915
|
// src/agents/yieldseeker/yieldseeker.mapper.ts
|
|
2771
|
-
var
|
|
2916
|
+
var import_viem6 = require("viem");
|
|
2772
2917
|
|
|
2773
2918
|
// src/lib/helpers/snapshot-apy.ts
|
|
2774
2919
|
var DAY_MS = 864e5;
|
|
@@ -2835,10 +2980,10 @@ function raw(value, endpoint) {
|
|
|
2835
2980
|
return BigInt(value);
|
|
2836
2981
|
}
|
|
2837
2982
|
function decimal(value, decimals, endpoint) {
|
|
2838
|
-
return (0,
|
|
2983
|
+
return (0, import_viem6.formatUnits)(raw(value, endpoint), decimals);
|
|
2839
2984
|
}
|
|
2840
2985
|
function usd(rawAmount, decimals, price) {
|
|
2841
|
-
return Number((0,
|
|
2986
|
+
return Number((0, import_viem6.formatUnits)(rawAmount, decimals)) * price;
|
|
2842
2987
|
}
|
|
2843
2988
|
function percent(value) {
|
|
2844
2989
|
const result = Number(value);
|
|
@@ -2864,7 +3009,7 @@ function assetAddressValue(record, address) {
|
|
|
2864
3009
|
}
|
|
2865
3010
|
function position(value, asset, baseAssetDecimals) {
|
|
2866
3011
|
const option = value?.yieldOption;
|
|
2867
|
-
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0,
|
|
3012
|
+
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0, import_viem6.isAddress)(option.address)) {
|
|
2868
3013
|
return invalid("yield positions", "missing vault metadata");
|
|
2869
3014
|
}
|
|
2870
3015
|
return {
|
|
@@ -2945,7 +3090,7 @@ function mapYieldseekerEarnings(contexts) {
|
|
|
2945
3090
|
chain: "BASE",
|
|
2946
3091
|
chainId: 8453,
|
|
2947
3092
|
asset: context.asset,
|
|
2948
|
-
amount: (0,
|
|
3093
|
+
amount: (0, import_viem6.formatUnits)(amount, context.snapshot.baseAssetDecimals)
|
|
2949
3094
|
});
|
|
2950
3095
|
lifetimeEarnings += usd(
|
|
2951
3096
|
amount,
|
|
@@ -3212,6 +3357,9 @@ var YIELDSEEKER_USERNAME_PREFIX = "owney_";
|
|
|
3212
3357
|
var YIELDSEEKER_USERNAME_RANDOM_LENGTH = 14;
|
|
3213
3358
|
var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
|
|
3214
3359
|
var YIELDSEEKER_YIELD_OPTIONS_CACHE_MS = 6e4;
|
|
3360
|
+
var YIELDSEEKER_AGENT_LIST_CACHE_MS = 6e4;
|
|
3361
|
+
var YIELDSEEKER_PORTFOLIO_CACHE_MS = 3e4;
|
|
3362
|
+
var YIELDSEEKER_ACTIVITY_CACHE_MS = 6e4;
|
|
3215
3363
|
function generateYieldseekerUsername() {
|
|
3216
3364
|
const suffix = globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, YIELDSEEKER_USERNAME_RANDOM_LENGTH).toLowerCase();
|
|
3217
3365
|
return `${YIELDSEEKER_USERNAME_PREFIX}${suffix}`;
|
|
@@ -3255,6 +3403,7 @@ function query(params) {
|
|
|
3255
3403
|
var YieldseekerAgent = class {
|
|
3256
3404
|
id = "yieldseeker";
|
|
3257
3405
|
balanceComposition = "tokens-plus-positions";
|
|
3406
|
+
withdrawalRequiresWalletApproval = true;
|
|
3258
3407
|
supportedChainIds = [8453];
|
|
3259
3408
|
supportedAssets = [
|
|
3260
3409
|
{
|
|
@@ -3268,11 +3417,17 @@ var YieldseekerAgent = class {
|
|
|
3268
3417
|
];
|
|
3269
3418
|
api;
|
|
3270
3419
|
auth;
|
|
3420
|
+
rpcUrls;
|
|
3421
|
+
receiptClient;
|
|
3271
3422
|
transactionExecutor;
|
|
3272
3423
|
unwindReceiptWaiter;
|
|
3273
3424
|
agentContexts = /* @__PURE__ */ new Map();
|
|
3274
3425
|
users = /* @__PURE__ */ new Map();
|
|
3275
3426
|
pendingAgents = /* @__PURE__ */ new Map();
|
|
3427
|
+
pendingWalletContexts = /* @__PURE__ */ new Map();
|
|
3428
|
+
readCache = /* @__PURE__ */ new Map();
|
|
3429
|
+
pendingReads = /* @__PURE__ */ new Map();
|
|
3430
|
+
readGeneration = 0;
|
|
3276
3431
|
yieldOptions = /* @__PURE__ */ new Map();
|
|
3277
3432
|
pendingYieldOptions = /* @__PURE__ */ new Map();
|
|
3278
3433
|
constructor(owneyApiKey, options = {}) {
|
|
@@ -3282,10 +3437,16 @@ var YieldseekerAgent = class {
|
|
|
3282
3437
|
options.fetchFn
|
|
3283
3438
|
);
|
|
3284
3439
|
this.auth = new YieldseekerAuth(options.auth);
|
|
3440
|
+
this.rpcUrls = options.rpcUrls;
|
|
3285
3441
|
this.transactionExecutor = options.transactionExecutor;
|
|
3286
3442
|
this.unwindReceiptWaiter = options.unwindReceiptWaiter;
|
|
3287
3443
|
}
|
|
3444
|
+
getReceiptClient() {
|
|
3445
|
+
this.receiptClient ??= createPaidRpcClient(import_chains3.base, this.rpcUrls);
|
|
3446
|
+
return this.receiptClient;
|
|
3447
|
+
}
|
|
3288
3448
|
async disconnect() {
|
|
3449
|
+
this.readGeneration += 1;
|
|
3289
3450
|
this.auth.clear();
|
|
3290
3451
|
for (const key2 of this.users.keys()) {
|
|
3291
3452
|
const [walletAddress, chainId] = key2.split(":");
|
|
@@ -3294,6 +3455,9 @@ var YieldseekerAgent = class {
|
|
|
3294
3455
|
this.users.clear();
|
|
3295
3456
|
this.agentContexts.clear();
|
|
3296
3457
|
this.pendingAgents.clear();
|
|
3458
|
+
this.pendingWalletContexts.clear();
|
|
3459
|
+
this.readCache.clear();
|
|
3460
|
+
this.pendingReads.clear();
|
|
3297
3461
|
}
|
|
3298
3462
|
async activateAgent(state, chainId, asset) {
|
|
3299
3463
|
this.assertChain(chainId);
|
|
@@ -3330,12 +3494,12 @@ var YieldseekerAgent = class {
|
|
|
3330
3494
|
await this.waitForReceipt(state, chainId, txHash);
|
|
3331
3495
|
} else {
|
|
3332
3496
|
txHash = await this.submitTransaction(state, chainId, {
|
|
3333
|
-
from: (0,
|
|
3497
|
+
from: (0, import_viem7.getAddress)(state.walletAddress),
|
|
3334
3498
|
to: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
3335
|
-
data: (0,
|
|
3336
|
-
abi:
|
|
3499
|
+
data: (0, import_viem7.encodeFunctionData)({
|
|
3500
|
+
abi: import_viem7.erc20Abi,
|
|
3337
3501
|
functionName: "transfer",
|
|
3338
|
-
args: [(0,
|
|
3502
|
+
args: [(0, import_viem7.getAddress)(context.wallet.walletAddress), BigInt(amount)]
|
|
3339
3503
|
}),
|
|
3340
3504
|
value: "0",
|
|
3341
3505
|
chainId
|
|
@@ -3435,15 +3599,15 @@ var YieldseekerAgent = class {
|
|
|
3435
3599
|
remaining: remaining.toString()
|
|
3436
3600
|
});
|
|
3437
3601
|
}
|
|
3438
|
-
const account = (0,
|
|
3602
|
+
const account = (0, import_viem7.getAddress)(state.walletAddress);
|
|
3439
3603
|
const txHash = await this.submitTransaction(state, chainId, {
|
|
3440
3604
|
from: account,
|
|
3441
|
-
to: (0,
|
|
3442
|
-
data: amount === void 0 ? (0,
|
|
3605
|
+
to: (0, import_viem7.getAddress)(context.wallet.walletAddress),
|
|
3606
|
+
data: amount === void 0 ? (0, import_viem7.encodeFunctionData)({
|
|
3443
3607
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
3444
3608
|
functionName: "withdrawAllAssetToUser",
|
|
3445
3609
|
args: [account, metadata.address]
|
|
3446
|
-
}) : (0,
|
|
3610
|
+
}) : (0, import_viem7.encodeFunctionData)({
|
|
3447
3611
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
3448
3612
|
functionName: "withdrawAssetToUser",
|
|
3449
3613
|
args: [account, metadata.address, requested]
|
|
@@ -3499,7 +3663,7 @@ var YieldseekerAgent = class {
|
|
|
3499
3663
|
);
|
|
3500
3664
|
const vaultAddresses = new Set(
|
|
3501
3665
|
catalog.flat().filter(
|
|
3502
|
-
(yieldOption) => yieldOption.chainId === chainId && (0,
|
|
3666
|
+
(yieldOption) => yieldOption.chainId === chainId && (0, import_viem7.isAddress)(yieldOption.address)
|
|
3503
3667
|
).map((yieldOption) => yieldOption.address.toLowerCase())
|
|
3504
3668
|
);
|
|
3505
3669
|
return mapYieldseekerHistory(contexts, {
|
|
@@ -3556,6 +3720,86 @@ var YieldseekerAgent = class {
|
|
|
3556
3720
|
contextKey(state, chainId, asset) {
|
|
3557
3721
|
return `${this.userKey(state, chainId)}:${asset}`;
|
|
3558
3722
|
}
|
|
3723
|
+
cachedRead(key2, ttlMs, read2) {
|
|
3724
|
+
const cached = this.readCache.get(key2);
|
|
3725
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
3726
|
+
return Promise.resolve(cached.value);
|
|
3727
|
+
}
|
|
3728
|
+
const pending = this.pendingReads.get(key2);
|
|
3729
|
+
if (pending) return pending;
|
|
3730
|
+
const generation = this.readGeneration;
|
|
3731
|
+
const request = Promise.resolve().then(read2).then((value) => {
|
|
3732
|
+
if (this.readGeneration === generation) {
|
|
3733
|
+
this.readCache.set(key2, {
|
|
3734
|
+
expiresAt: Date.now() + ttlMs,
|
|
3735
|
+
value
|
|
3736
|
+
});
|
|
3737
|
+
}
|
|
3738
|
+
return value;
|
|
3739
|
+
}).finally(() => {
|
|
3740
|
+
if (this.pendingReads.get(key2) === request) {
|
|
3741
|
+
this.pendingReads.delete(key2);
|
|
3742
|
+
}
|
|
3743
|
+
});
|
|
3744
|
+
this.pendingReads.set(key2, request);
|
|
3745
|
+
return request;
|
|
3746
|
+
}
|
|
3747
|
+
agentListKey(state, chainId) {
|
|
3748
|
+
return `agents:${this.userKey(state, chainId)}`;
|
|
3749
|
+
}
|
|
3750
|
+
async listAgents(state, chainId, user) {
|
|
3751
|
+
const response = await this.cachedRead(
|
|
3752
|
+
this.agentListKey(state, chainId),
|
|
3753
|
+
YIELDSEEKER_AGENT_LIST_CACHE_MS,
|
|
3754
|
+
async () => {
|
|
3755
|
+
const response2 = await this.walletRequest(
|
|
3756
|
+
state,
|
|
3757
|
+
chainId,
|
|
3758
|
+
`/users/${user.userId}/agents`
|
|
3759
|
+
);
|
|
3760
|
+
if (!Array.isArray(response2?.agents)) {
|
|
3761
|
+
throw this.invalidResponse("agent list");
|
|
3762
|
+
}
|
|
3763
|
+
return response2;
|
|
3764
|
+
}
|
|
3765
|
+
);
|
|
3766
|
+
return response.agents;
|
|
3767
|
+
}
|
|
3768
|
+
async contextForAgent(state, chainId, user, agent, asset) {
|
|
3769
|
+
const key2 = this.contextKey(state, chainId, asset);
|
|
3770
|
+
const cached = this.agentContexts.get(key2);
|
|
3771
|
+
if (cached?.agent.agentId === agent.agentId) return cached;
|
|
3772
|
+
const pending = this.pendingWalletContexts.get(key2);
|
|
3773
|
+
if (pending) return pending;
|
|
3774
|
+
const generation = this.readGeneration;
|
|
3775
|
+
const request = this.walletRequest(
|
|
3776
|
+
state,
|
|
3777
|
+
chainId,
|
|
3778
|
+
`/users/${user.userId}/agents/${agent.agentId}/wallet`
|
|
3779
|
+
).then((walletResponse) => {
|
|
3780
|
+
if (!walletResponse?.agentWallet || !(0, import_viem7.isAddress)(walletResponse.agentWallet.walletAddress)) {
|
|
3781
|
+
throw this.invalidResponse("agent wallet");
|
|
3782
|
+
}
|
|
3783
|
+
const context = {
|
|
3784
|
+
user,
|
|
3785
|
+
agent,
|
|
3786
|
+
wallet: walletResponse.agentWallet,
|
|
3787
|
+
asset
|
|
3788
|
+
};
|
|
3789
|
+
if (this.readGeneration === generation) {
|
|
3790
|
+
this.agentContexts.set(key2, context);
|
|
3791
|
+
}
|
|
3792
|
+
return context;
|
|
3793
|
+
});
|
|
3794
|
+
this.pendingWalletContexts.set(key2, request);
|
|
3795
|
+
try {
|
|
3796
|
+
return await request;
|
|
3797
|
+
} finally {
|
|
3798
|
+
if (this.pendingWalletContexts.get(key2) === request) {
|
|
3799
|
+
this.pendingWalletContexts.delete(key2);
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3559
3803
|
async resolveUser(state, chainId) {
|
|
3560
3804
|
const key2 = this.userKey(state, chainId);
|
|
3561
3805
|
const inMemory = this.users.get(key2);
|
|
@@ -3565,7 +3809,7 @@ var YieldseekerAgent = class {
|
|
|
3565
3809
|
this.users.set(key2, persisted);
|
|
3566
3810
|
return persisted;
|
|
3567
3811
|
}
|
|
3568
|
-
const walletAddress = (0,
|
|
3812
|
+
const walletAddress = (0, import_viem7.getAddress)(state.walletAddress);
|
|
3569
3813
|
let user = null;
|
|
3570
3814
|
try {
|
|
3571
3815
|
const login = await this.providerRequest(
|
|
@@ -3652,16 +3896,9 @@ var YieldseekerAgent = class {
|
|
|
3652
3896
|
}
|
|
3653
3897
|
async resolveAgent(state, chainId, asset, createIfMissing) {
|
|
3654
3898
|
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
|
-
}
|
|
3899
|
+
const agents = await this.listAgents(state, chainId, user);
|
|
3663
3900
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
3664
|
-
let agent =
|
|
3901
|
+
let agent = agents.find(
|
|
3665
3902
|
(candidate) => this.isOwneyAgent(candidate) && candidate.chainId === chainId && candidate.type === "vault" && candidate.assetAddress.toLowerCase() === metadata.address.toLowerCase()
|
|
3666
3903
|
);
|
|
3667
3904
|
if (!agent && createIfMissing) {
|
|
@@ -3682,83 +3919,91 @@ var YieldseekerAgent = class {
|
|
|
3682
3919
|
}
|
|
3683
3920
|
);
|
|
3684
3921
|
agent = created?.agent;
|
|
3922
|
+
if (agent) {
|
|
3923
|
+
this.readCache.set(this.agentListKey(state, chainId), {
|
|
3924
|
+
expiresAt: Date.now() + YIELDSEEKER_AGENT_LIST_CACHE_MS,
|
|
3925
|
+
value: {
|
|
3926
|
+
agents: [...agents, agent]
|
|
3927
|
+
}
|
|
3928
|
+
});
|
|
3929
|
+
}
|
|
3685
3930
|
}
|
|
3686
3931
|
if (!agent) return null;
|
|
3687
3932
|
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 };
|
|
3933
|
+
return this.contextForAgent(state, chainId, user, agent, asset);
|
|
3697
3934
|
}
|
|
3698
3935
|
async loadPortfolio(state, chainId, options) {
|
|
3699
3936
|
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
|
-
}
|
|
3937
|
+
const agents = await this.listAgents(state, chainId, user);
|
|
3708
3938
|
const contexts = [];
|
|
3709
|
-
for (const agent of
|
|
3939
|
+
for (const agent of agents) {
|
|
3710
3940
|
const asset = this.assetForAgent(agent);
|
|
3711
3941
|
if (!this.isOwneyAgent(agent) || !asset || agent.chainId !== chainId || agent.type !== "vault" || options.asset && options.asset !== asset) {
|
|
3712
3942
|
continue;
|
|
3713
3943
|
}
|
|
3714
3944
|
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);
|
|
3945
|
+
contexts.push(this.contextForAgent(state, chainId, user, agent, asset));
|
|
3731
3946
|
}
|
|
3947
|
+
const resolvedContexts = await Promise.all(contexts);
|
|
3732
3948
|
return Promise.all(
|
|
3733
|
-
|
|
3949
|
+
resolvedContexts.map(
|
|
3734
3950
|
(context) => this.loadPortfolioContext(state, chainId, context, options)
|
|
3735
3951
|
)
|
|
3736
3952
|
);
|
|
3737
3953
|
}
|
|
3738
3954
|
async loadPortfolioContext(state, chainId, context, options = {}) {
|
|
3955
|
+
const contextKey = this.contextKey(state, chainId, context.asset);
|
|
3739
3956
|
const [snapshot, positions, historic, actions] = await Promise.all([
|
|
3740
|
-
this.
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3957
|
+
this.cachedRead(
|
|
3958
|
+
`snapshot:${contextKey}`,
|
|
3959
|
+
YIELDSEEKER_PORTFOLIO_CACHE_MS,
|
|
3960
|
+
async () => {
|
|
3961
|
+
const response = await this.walletRequest(
|
|
3962
|
+
state,
|
|
3963
|
+
chainId,
|
|
3964
|
+
`${this.agentPath(context, "snapshot")}${query({
|
|
3965
|
+
shouldOnlyUseRecentValue: true,
|
|
3966
|
+
shouldAllowStaleOnError: true
|
|
3967
|
+
})}`
|
|
3968
|
+
);
|
|
3969
|
+
if (!response?.agentSnapshot) {
|
|
3970
|
+
throw this.invalidResponse("agent snapshot");
|
|
3971
|
+
}
|
|
3972
|
+
return response;
|
|
3973
|
+
}
|
|
3747
3974
|
),
|
|
3748
|
-
this.
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3975
|
+
this.cachedRead(
|
|
3976
|
+
`positions:${contextKey}`,
|
|
3977
|
+
YIELDSEEKER_PORTFOLIO_CACHE_MS,
|
|
3978
|
+
async () => {
|
|
3979
|
+
const response = await this.walletRequest(
|
|
3980
|
+
state,
|
|
3981
|
+
chainId,
|
|
3982
|
+
this.agentPath(context, "yield-positions")
|
|
3983
|
+
);
|
|
3984
|
+
if (!Array.isArray(response?.yieldPositions)) {
|
|
3985
|
+
throw this.invalidResponse("yield positions");
|
|
3986
|
+
}
|
|
3987
|
+
return response;
|
|
3988
|
+
}
|
|
3752
3989
|
),
|
|
3753
|
-
options.historic ? this.
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
this.
|
|
3990
|
+
options.historic ? this.cachedRead(
|
|
3991
|
+
`historic:${contextKey}`,
|
|
3992
|
+
YIELDSEEKER_ACTIVITY_CACHE_MS,
|
|
3993
|
+
() => this.walletRequest(
|
|
3994
|
+
state,
|
|
3995
|
+
chainId,
|
|
3996
|
+
this.agentPath(context, "wallet/historic-position")
|
|
3997
|
+
)
|
|
3757
3998
|
) : Promise.resolve(void 0),
|
|
3758
|
-
options.actions ? this.
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
this.
|
|
3999
|
+
options.actions ? this.cachedRead(
|
|
4000
|
+
`actions:${contextKey}`,
|
|
4001
|
+
YIELDSEEKER_ACTIVITY_CACHE_MS,
|
|
4002
|
+
() => this.walletRequest(
|
|
4003
|
+
state,
|
|
4004
|
+
chainId,
|
|
4005
|
+
this.agentPath(context, "actions")
|
|
4006
|
+
)
|
|
3762
4007
|
) : Promise.resolve(void 0)
|
|
3763
4008
|
]);
|
|
3764
4009
|
if (!snapshot?.agentSnapshot) {
|
|
@@ -3784,7 +4029,7 @@ var YieldseekerAgent = class {
|
|
|
3784
4029
|
this.agentPath(context, "deploy"),
|
|
3785
4030
|
{ method: "POST", body: {} }
|
|
3786
4031
|
);
|
|
3787
|
-
if (!deployed?.agentWallet || !(0,
|
|
4032
|
+
if (!deployed?.agentWallet || !(0, import_viem7.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
|
|
3788
4033
|
throw this.invalidResponse("agent deployment", {
|
|
3789
4034
|
reason: "Deploy did not return the expected Agent Wallet."
|
|
3790
4035
|
});
|
|
@@ -3792,6 +4037,13 @@ var YieldseekerAgent = class {
|
|
|
3792
4037
|
context.wallet = deployed.agentWallet;
|
|
3793
4038
|
}
|
|
3794
4039
|
async refreshSnapshotAfterMovement(state, chainId, context, movement) {
|
|
4040
|
+
const contextKey = this.contextKey(state, chainId, context.asset);
|
|
4041
|
+
const invalidatePortfolio = () => {
|
|
4042
|
+
for (const kind of ["snapshot", "positions", "historic", "actions"]) {
|
|
4043
|
+
this.readCache.delete(`${kind}:${contextKey}`);
|
|
4044
|
+
}
|
|
4045
|
+
};
|
|
4046
|
+
invalidatePortfolio();
|
|
3795
4047
|
try {
|
|
3796
4048
|
const response = await this.walletRequest(
|
|
3797
4049
|
state,
|
|
@@ -3808,6 +4060,8 @@ var YieldseekerAgent = class {
|
|
|
3808
4060
|
`[owney-sdk] Yieldseeker ${movement} snapshot refresh failed:`,
|
|
3809
4061
|
error
|
|
3810
4062
|
);
|
|
4063
|
+
} finally {
|
|
4064
|
+
invalidatePortfolio();
|
|
3811
4065
|
}
|
|
3812
4066
|
}
|
|
3813
4067
|
agentPath(context, suffix) {
|
|
@@ -3858,6 +4112,7 @@ var YieldseekerAgent = class {
|
|
|
3858
4112
|
code,
|
|
3859
4113
|
`Yieldseeker request failed: ${error.providerCode}.`,
|
|
3860
4114
|
{
|
|
4115
|
+
rpcSource: "agent-api",
|
|
3861
4116
|
statusCode: error.status,
|
|
3862
4117
|
providerCode: error.providerCode,
|
|
3863
4118
|
...error.responseFields ? { fields: error.responseFields } : {}
|
|
@@ -3870,32 +4125,37 @@ var YieldseekerAgent = class {
|
|
|
3870
4125
|
return this.transactionExecutor(state, chainId, transaction);
|
|
3871
4126
|
}
|
|
3872
4127
|
this.assertTransaction(transaction, state, chainId);
|
|
3873
|
-
const account = (0,
|
|
3874
|
-
const walletClient = (0,
|
|
4128
|
+
const account = (0, import_viem7.getAddress)(state.walletAddress);
|
|
4129
|
+
const walletClient = (0, import_viem7.createWalletClient)({
|
|
3875
4130
|
account,
|
|
3876
4131
|
chain: import_chains3.base,
|
|
3877
|
-
transport: (0,
|
|
4132
|
+
transport: (0, import_viem7.custom)(state.provider)
|
|
3878
4133
|
});
|
|
3879
|
-
const
|
|
4134
|
+
const walletChainClient = (0, import_viem7.createPublicClient)({
|
|
3880
4135
|
chain: import_chains3.base,
|
|
3881
|
-
transport: (0,
|
|
4136
|
+
transport: (0, import_viem7.custom)(state.provider)
|
|
3882
4137
|
});
|
|
3883
4138
|
await ensureWalletOnChain(
|
|
3884
|
-
|
|
4139
|
+
walletChainClient,
|
|
3885
4140
|
walletClient,
|
|
3886
4141
|
8453
|
|
3887
4142
|
);
|
|
3888
4143
|
const hash = await walletClient.sendTransaction({
|
|
3889
4144
|
account,
|
|
3890
4145
|
chain: import_chains3.base,
|
|
3891
|
-
to: (0,
|
|
4146
|
+
to: (0, import_viem7.getAddress)(transaction.to),
|
|
3892
4147
|
data: transaction.data,
|
|
3893
4148
|
value: BigInt(transaction.value)
|
|
3894
4149
|
});
|
|
3895
|
-
const receipt = await
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
4150
|
+
const receipt = await withPaidRpcDiagnostics(
|
|
4151
|
+
() => this.getReceiptClient().waitForTransactionReceipt({
|
|
4152
|
+
hash,
|
|
4153
|
+
confirmations: 1
|
|
4154
|
+
}),
|
|
4155
|
+
8453,
|
|
4156
|
+
"eth_getTransactionReceipt",
|
|
4157
|
+
this.id
|
|
4158
|
+
);
|
|
3899
4159
|
if (receipt.status !== "success") {
|
|
3900
4160
|
throw new OwneyError(
|
|
3901
4161
|
"AGENT_TRANSACTION_REVERTED",
|
|
@@ -3911,14 +4171,15 @@ var YieldseekerAgent = class {
|
|
|
3911
4171
|
await this.unwindReceiptWaiter(state, chainId, transactionHash);
|
|
3912
4172
|
return;
|
|
3913
4173
|
}
|
|
3914
|
-
const
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
4174
|
+
const receipt = await withPaidRpcDiagnostics(
|
|
4175
|
+
() => this.getReceiptClient().waitForTransactionReceipt({
|
|
4176
|
+
hash: transactionHash,
|
|
4177
|
+
confirmations: 1
|
|
4178
|
+
}),
|
|
4179
|
+
8453,
|
|
4180
|
+
"eth_getTransactionReceipt",
|
|
4181
|
+
this.id
|
|
4182
|
+
);
|
|
3922
4183
|
if (receipt.status !== "success") {
|
|
3923
4184
|
throw new OwneyError(
|
|
3924
4185
|
"AGENT_TRANSACTION_REVERTED",
|
|
@@ -3929,12 +4190,12 @@ var YieldseekerAgent = class {
|
|
|
3929
4190
|
}
|
|
3930
4191
|
}
|
|
3931
4192
|
assertTransaction(transaction, state, chainId) {
|
|
3932
|
-
if (!transaction || typeof transaction.from !== "string" || !(0,
|
|
4193
|
+
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
4194
|
throw this.invalidResponse("transaction");
|
|
3934
4195
|
}
|
|
3935
4196
|
}
|
|
3936
4197
|
assertAgent(agent) {
|
|
3937
|
-
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0,
|
|
4198
|
+
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem7.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
|
|
3938
4199
|
throw this.invalidResponse("agent");
|
|
3939
4200
|
}
|
|
3940
4201
|
}
|
|
@@ -4087,7 +4348,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
|
|
|
4087
4348
|
}
|
|
4088
4349
|
|
|
4089
4350
|
// src/lib/helpers/withdraw-helper.ts
|
|
4090
|
-
var
|
|
4351
|
+
var import_viem8 = require("viem");
|
|
4091
4352
|
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
4092
4353
|
const target = asset.toUpperCase();
|
|
4093
4354
|
return agents.map((agent) => {
|
|
@@ -4095,7 +4356,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
4095
4356
|
const tokenBalance = agentBalance?.tokens.find(
|
|
4096
4357
|
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
4097
4358
|
);
|
|
4098
|
-
let balance = tokenBalance ? (0,
|
|
4359
|
+
let balance = tokenBalance ? (0, import_viem8.parseUnits)(tokenBalance.amount, decimals) : 0n;
|
|
4099
4360
|
if (agent.balanceComposition === "tokens-plus-positions") {
|
|
4100
4361
|
const chainNameById = {
|
|
4101
4362
|
1: "ETHEREUM",
|
|
@@ -4114,7 +4375,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
4114
4375
|
} catch {
|
|
4115
4376
|
}
|
|
4116
4377
|
}
|
|
4117
|
-
balance += (0,
|
|
4378
|
+
balance += (0, import_viem8.parseUnits)(position2.amount, decimals);
|
|
4118
4379
|
}
|
|
4119
4380
|
}
|
|
4120
4381
|
return { agent, balance };
|
|
@@ -4273,15 +4534,50 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
4273
4534
|
}
|
|
4274
4535
|
|
|
4275
4536
|
// src/client.ts
|
|
4276
|
-
var
|
|
4537
|
+
var import_viem12 = require("viem");
|
|
4277
4538
|
var import_chains4 = require("viem/chains");
|
|
4278
4539
|
|
|
4279
4540
|
// src/lib/sponsored-token-batch.ts
|
|
4280
|
-
var
|
|
4541
|
+
var import_viem10 = require("viem");
|
|
4281
4542
|
|
|
4282
4543
|
// src/lib/permit2-batch.ts
|
|
4283
|
-
var
|
|
4544
|
+
var import_viem9 = require("viem");
|
|
4284
4545
|
var BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
4546
|
+
var BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
4547
|
+
var MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
4548
|
+
var ERC2612_PERMIT_TYPES = {
|
|
4549
|
+
Permit: [
|
|
4550
|
+
{ name: "owner", type: "address" },
|
|
4551
|
+
{ name: "spender", type: "address" },
|
|
4552
|
+
{ name: "value", type: "uint256" },
|
|
4553
|
+
{ name: "nonce", type: "uint256" },
|
|
4554
|
+
{ name: "deadline", type: "uint256" }
|
|
4555
|
+
]
|
|
4556
|
+
};
|
|
4557
|
+
var ERC2612_READ_ABI = (0, import_viem9.parseAbi)([
|
|
4558
|
+
"function name() view returns (string)",
|
|
4559
|
+
"function version() view returns (string)",
|
|
4560
|
+
"function nonces(address owner) view returns (uint256)"
|
|
4561
|
+
]);
|
|
4562
|
+
function erc2612TypedData(input) {
|
|
4563
|
+
return {
|
|
4564
|
+
domain: {
|
|
4565
|
+
name: input.permit.tokenName,
|
|
4566
|
+
version: input.permit.tokenVersion,
|
|
4567
|
+
chainId: input.chainId,
|
|
4568
|
+
verifyingContract: input.token
|
|
4569
|
+
},
|
|
4570
|
+
types: ERC2612_PERMIT_TYPES,
|
|
4571
|
+
primaryType: "Permit",
|
|
4572
|
+
message: {
|
|
4573
|
+
owner: input.owner,
|
|
4574
|
+
spender: BATCH_PERMIT2_ADDRESS,
|
|
4575
|
+
value: BigInt(input.permit.value),
|
|
4576
|
+
nonce: BigInt(input.permit.nonce),
|
|
4577
|
+
deadline: BigInt(input.permit.deadline)
|
|
4578
|
+
}
|
|
4579
|
+
};
|
|
4580
|
+
}
|
|
4285
4581
|
var PERMIT_BATCH_TYPES = {
|
|
4286
4582
|
PermitBatchWitnessTransferFrom: [
|
|
4287
4583
|
{ name: "permitted", type: "TokenPermissions[]" },
|
|
@@ -4296,7 +4592,7 @@ var PERMIT_BATCH_TYPES = {
|
|
|
4296
4592
|
{ name: "amount", type: "uint256" }
|
|
4297
4593
|
]
|
|
4298
4594
|
};
|
|
4299
|
-
var PERMIT2_BATCH_ABI = (0,
|
|
4595
|
+
var PERMIT2_BATCH_ABI = (0, import_viem9.parseAbi)([
|
|
4300
4596
|
"struct TokenPermissions { address token; uint256 amount; }",
|
|
4301
4597
|
"struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
|
|
4302
4598
|
"struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
|
|
@@ -4355,7 +4651,7 @@ function clear(key2) {
|
|
|
4355
4651
|
else window.localStorage.removeItem(key2);
|
|
4356
4652
|
}
|
|
4357
4653
|
function sponsorTokenBatch(i) {
|
|
4358
|
-
const key2 = `owney.token-batch.v1:${(0,
|
|
4654
|
+
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
4655
|
const plan = planOf(i.transfers);
|
|
4360
4656
|
const active = inflight.get(key2);
|
|
4361
4657
|
if (active) {
|
|
@@ -4386,7 +4682,7 @@ async function execute(i, key2, plan) {
|
|
|
4386
4682
|
baseUrl: i.baseUrl,
|
|
4387
4683
|
body
|
|
4388
4684
|
});
|
|
4389
|
-
if (!prepared.serializedTransaction || (0,
|
|
4685
|
+
if (!prepared.serializedTransaction || (0, import_viem10.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
|
|
4390
4686
|
throw new Error(
|
|
4391
4687
|
"Sponsorship API did not return a valid prepared transaction."
|
|
4392
4688
|
);
|
|
@@ -4401,7 +4697,7 @@ async function execute(i, key2, plan) {
|
|
|
4401
4697
|
baseUrl: i.baseUrl,
|
|
4402
4698
|
body
|
|
4403
4699
|
});
|
|
4404
|
-
if (result.txHash !== (0,
|
|
4700
|
+
if (result.txHash !== (0, import_viem10.keccak256)(body.serializedTransaction))
|
|
4405
4701
|
throw new Error(
|
|
4406
4702
|
"Sponsorship receipt does not match the pending transaction."
|
|
4407
4703
|
);
|
|
@@ -4416,7 +4712,7 @@ async function execute(i, key2, plan) {
|
|
|
4416
4712
|
const saved = read(key2);
|
|
4417
4713
|
if (saved) {
|
|
4418
4714
|
const previous = JSON.parse(saved);
|
|
4419
|
-
if (previous.chainId !== i.chainId || !(0,
|
|
4715
|
+
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
4716
|
throw new Error(
|
|
4421
4717
|
"Retry the previous token deposit and agent split first to reconcile its status."
|
|
4422
4718
|
);
|
|
@@ -4433,28 +4729,67 @@ async function execute(i, key2, plan) {
|
|
|
4433
4729
|
"DEPOSIT_INSUFFICIENT_BALANCE",
|
|
4434
4730
|
"Insufficient token balance for this deposit."
|
|
4435
4731
|
);
|
|
4436
|
-
if (allowance < total)
|
|
4732
|
+
if (allowance < total && (i.chainId !== 8453 || !(0, import_viem10.isAddressEqual)(i.token, BASE_USDC_ADDRESS)))
|
|
4437
4733
|
throw new OwneyError(
|
|
4438
4734
|
"PERMIT2_APPROVAL_REQUIRED",
|
|
4439
4735
|
"token deposits need a one-time Permit2 approval."
|
|
4440
4736
|
);
|
|
4441
|
-
const
|
|
4737
|
+
const now = (await i.pub.getBlock()).timestamp;
|
|
4738
|
+
let erc2612Permit;
|
|
4739
|
+
if (allowance < total) {
|
|
4740
|
+
const [tokenName, tokenVersion, permitNonce] = await Promise.all([
|
|
4741
|
+
i.pub.readContract({
|
|
4742
|
+
address: i.token,
|
|
4743
|
+
abi: ERC2612_READ_ABI,
|
|
4744
|
+
functionName: "name"
|
|
4745
|
+
}),
|
|
4746
|
+
i.pub.readContract({
|
|
4747
|
+
address: i.token,
|
|
4748
|
+
abi: ERC2612_READ_ABI,
|
|
4749
|
+
functionName: "version"
|
|
4750
|
+
}),
|
|
4751
|
+
i.pub.readContract({
|
|
4752
|
+
address: i.token,
|
|
4753
|
+
abi: ERC2612_READ_ABI,
|
|
4754
|
+
functionName: "nonces",
|
|
4755
|
+
args: [i.owner]
|
|
4756
|
+
})
|
|
4757
|
+
]);
|
|
4758
|
+
const unsignedPermit = {
|
|
4759
|
+
value: MAX_UINT256.toString(),
|
|
4760
|
+
nonce: permitNonce.toString(),
|
|
4761
|
+
deadline: (now + 900n).toString(),
|
|
4762
|
+
tokenName,
|
|
4763
|
+
tokenVersion
|
|
4764
|
+
};
|
|
4765
|
+
const signature2 = await i.wallet.signTypedData({
|
|
4766
|
+
account: i.owner,
|
|
4767
|
+
...erc2612TypedData({
|
|
4768
|
+
chainId: 8453,
|
|
4769
|
+
token: i.token,
|
|
4770
|
+
owner: i.owner,
|
|
4771
|
+
permit: unsignedPermit
|
|
4772
|
+
})
|
|
4773
|
+
});
|
|
4774
|
+
erc2612Permit = { ...unsignedPermit, signature: signature2 };
|
|
4775
|
+
}
|
|
4776
|
+
const spender = erc2612Permit ? MULTICALL3_ADDRESS : await getSponsorRelayerAddress({
|
|
4442
4777
|
apiKey: i.apiKey,
|
|
4443
4778
|
baseUrl: i.baseUrl,
|
|
4444
4779
|
chainId: i.chainId
|
|
4445
4780
|
});
|
|
4446
|
-
const now = (await i.pub.getBlock()).timestamp;
|
|
4447
4781
|
const unsigned = {
|
|
4448
4782
|
chainId: i.chainId,
|
|
4449
4783
|
token: i.token,
|
|
4450
4784
|
from: i.owner,
|
|
4451
4785
|
transfers: i.transfers,
|
|
4452
4786
|
nonce: randomPermit2Nonce().toString(),
|
|
4453
|
-
deadline: (now + 900n).toString()
|
|
4787
|
+
deadline: (now + 900n).toString(),
|
|
4788
|
+
...erc2612Permit ? { erc2612Permit } : {}
|
|
4454
4789
|
};
|
|
4455
4790
|
const signature = await i.wallet.signTypedData({
|
|
4456
4791
|
account: i.owner,
|
|
4457
|
-
...batchTypedData(unsigned,
|
|
4792
|
+
...batchTypedData(unsigned, spender)
|
|
4458
4793
|
});
|
|
4459
4794
|
i.onApproved?.();
|
|
4460
4795
|
return send({ ...unsigned, signature });
|
|
@@ -4474,8 +4809,8 @@ function makeSponsoredTokenCallback(deps) {
|
|
|
4474
4809
|
"CHAIN_UNSUPPORTED",
|
|
4475
4810
|
`No sponsored token configured for chain ${chainId}`
|
|
4476
4811
|
);
|
|
4477
|
-
const pub = deps.getPublicClient(chainId), wallet = deps.getWalletClient(chainId);
|
|
4478
|
-
await ensureWalletOnChain(
|
|
4812
|
+
const pub = deps.getPublicClient(chainId), walletChain = deps.getWalletChainClient?.(chainId) ?? pub, wallet = deps.getWalletClient(chainId);
|
|
4813
|
+
await ensureWalletOnChain(walletChain, wallet, chainId);
|
|
4479
4814
|
return sponsorTokenBatch({
|
|
4480
4815
|
apiKey: deps.apiKey,
|
|
4481
4816
|
baseUrl: deps.baseUrl,
|
|
@@ -4571,7 +4906,7 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
|
|
|
4571
4906
|
}
|
|
4572
4907
|
|
|
4573
4908
|
// src/lib/sponsored-calls-deposit.ts
|
|
4574
|
-
var
|
|
4909
|
+
var import_viem11 = require("viem");
|
|
4575
4910
|
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
4576
4911
|
var DEFAULT_MAX_POLLS = 30;
|
|
4577
4912
|
async function paymasterSupported(provider, owner, chainId) {
|
|
@@ -4579,7 +4914,7 @@ async function paymasterSupported(provider, owner, chainId) {
|
|
|
4579
4914
|
method: "wallet_getCapabilities",
|
|
4580
4915
|
params: [owner]
|
|
4581
4916
|
});
|
|
4582
|
-
const forChain = caps?.[(0,
|
|
4917
|
+
const forChain = caps?.[(0, import_viem11.toHex)(chainId)] ?? caps?.[String(chainId)];
|
|
4583
4918
|
return Boolean(forChain?.paymasterService?.supported);
|
|
4584
4919
|
}
|
|
4585
4920
|
function makeSponsoredCallsCallback(deps) {
|
|
@@ -4616,8 +4951,8 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
4616
4951
|
const calls = transfers.map((transfer) => ({
|
|
4617
4952
|
to: token,
|
|
4618
4953
|
value: "0x0",
|
|
4619
|
-
data: (0,
|
|
4620
|
-
abi:
|
|
4954
|
+
data: (0, import_viem11.encodeFunctionData)({
|
|
4955
|
+
abi: import_viem11.erc20Abi,
|
|
4621
4956
|
functionName: "transfer",
|
|
4622
4957
|
args: [transfer.to, BigInt(transfer.amount)]
|
|
4623
4958
|
})
|
|
@@ -4655,7 +4990,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
4655
4990
|
{
|
|
4656
4991
|
version: "2.0.0",
|
|
4657
4992
|
from: deps.ownerAddress,
|
|
4658
|
-
chainId: (0,
|
|
4993
|
+
chainId: (0, import_viem11.toHex)(chainId),
|
|
4659
4994
|
atomicRequired: transfers.length > 1,
|
|
4660
4995
|
calls,
|
|
4661
4996
|
capabilities: {
|
|
@@ -4777,6 +5112,7 @@ var OwneySDK = class {
|
|
|
4777
5112
|
// leave every user's agent profile alone.
|
|
4778
5113
|
orgAgentConfig;
|
|
4779
5114
|
orgAgentConfigPromise = null;
|
|
5115
|
+
rpcUrls;
|
|
4780
5116
|
zyfaiRpcUrls;
|
|
4781
5117
|
yieldseekerApiBaseUrl;
|
|
4782
5118
|
yieldseekerSiweOrigin;
|
|
@@ -4801,6 +5137,7 @@ var OwneySDK = class {
|
|
|
4801
5137
|
constructor(config) {
|
|
4802
5138
|
this.apiKey = config.apiKey;
|
|
4803
5139
|
if (config.debug) setOwneyDebug(true);
|
|
5140
|
+
this.rpcUrls = config.rpcUrls;
|
|
4804
5141
|
this.zyfaiRpcUrls = config.zyfaiRpcUrls;
|
|
4805
5142
|
this.yieldseekerApiBaseUrl = config.yieldseekerApiBaseUrl;
|
|
4806
5143
|
this.yieldseekerSiweOrigin = config.yieldseekerSiweOrigin;
|
|
@@ -4891,6 +5228,9 @@ var OwneySDK = class {
|
|
|
4891
5228
|
}
|
|
4892
5229
|
return this.state.provider;
|
|
4893
5230
|
}
|
|
5231
|
+
getPaidRpcClient(chainId) {
|
|
5232
|
+
return createPaidRpcClient(VIEM_CHAIN2[chainId], this.rpcUrls);
|
|
5233
|
+
}
|
|
4894
5234
|
/** Builds the default USDC batch callback for the connected wallet. */
|
|
4895
5235
|
getDefaultSponsoredCallback(onApproved) {
|
|
4896
5236
|
if (!onApproved && this.cachedSponsoredCallback)
|
|
@@ -4906,14 +5246,15 @@ var OwneySDK = class {
|
|
|
4906
5246
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
4907
5247
|
// PublicClient/WalletClient param types — structurally identical at
|
|
4908
5248
|
// runtime, but the two share a name TS treats as unrelated.
|
|
4909
|
-
getPublicClient: (cid) => (
|
|
5249
|
+
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
5250
|
+
getWalletChainClient: (cid) => (0, import_viem12.createPublicClient)({
|
|
4910
5251
|
chain: VIEM_CHAIN2[cid],
|
|
4911
|
-
transport: (0,
|
|
5252
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4912
5253
|
}),
|
|
4913
|
-
getWalletClient: (cid) => (0,
|
|
5254
|
+
getWalletClient: (cid) => (0, import_viem12.createWalletClient)({
|
|
4914
5255
|
account: owner,
|
|
4915
5256
|
chain: VIEM_CHAIN2[cid],
|
|
4916
|
-
transport: (0,
|
|
5257
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4917
5258
|
})
|
|
4918
5259
|
});
|
|
4919
5260
|
if (!onApproved) this.cachedSponsoredCallback = callback;
|
|
@@ -4956,14 +5297,15 @@ var OwneySDK = class {
|
|
|
4956
5297
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
4957
5298
|
// PublicClient/WalletClient param types — structurally identical at
|
|
4958
5299
|
// runtime, but the two share a name TS treats as unrelated.
|
|
4959
|
-
getPublicClient: (cid) => (
|
|
5300
|
+
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
5301
|
+
getWalletChainClient: (cid) => (0, import_viem12.createPublicClient)({
|
|
4960
5302
|
chain: VIEM_CHAIN2[cid],
|
|
4961
|
-
transport: (0,
|
|
5303
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4962
5304
|
}),
|
|
4963
|
-
getWalletClient: (cid) => (0,
|
|
5305
|
+
getWalletClient: (cid) => (0, import_viem12.createWalletClient)({
|
|
4964
5306
|
account: owner,
|
|
4965
5307
|
chain: VIEM_CHAIN2[cid],
|
|
4966
|
-
transport: (0,
|
|
5308
|
+
transport: (0, import_viem12.custom)(provider)
|
|
4967
5309
|
})
|
|
4968
5310
|
});
|
|
4969
5311
|
if (!onApproved) this.cachedWethSponsoredCallback = callback;
|
|
@@ -5069,12 +5411,17 @@ var OwneySDK = class {
|
|
|
5069
5411
|
createAgent(agentId, key2) {
|
|
5070
5412
|
if (agentId === "zyfai") {
|
|
5071
5413
|
if (!key2) return null;
|
|
5072
|
-
return new ZyfaiAgent(
|
|
5414
|
+
return new ZyfaiAgent(
|
|
5415
|
+
key2,
|
|
5416
|
+
this.rpcUrls ?? this.zyfaiRpcUrls,
|
|
5417
|
+
this.referralSource
|
|
5418
|
+
);
|
|
5073
5419
|
}
|
|
5074
5420
|
if (agentId === "yieldseeker") {
|
|
5075
5421
|
return new YieldseekerAgent(this.apiKey, {
|
|
5076
5422
|
auth: { origin: this.yieldseekerSiweOrigin },
|
|
5077
|
-
baseUrl: this.yieldseekerApiBaseUrl ?? getYieldseekerProxyBaseUrl(this.routingApiBaseUrl)
|
|
5423
|
+
baseUrl: this.yieldseekerApiBaseUrl ?? getYieldseekerProxyBaseUrl(this.routingApiBaseUrl),
|
|
5424
|
+
rpcUrls: this.rpcUrls
|
|
5078
5425
|
});
|
|
5079
5426
|
}
|
|
5080
5427
|
return null;
|
|
@@ -5410,10 +5757,12 @@ var OwneySDK = class {
|
|
|
5410
5757
|
* Invokes `agent.deposit` with the resolved sponsored callback, composing
|
|
5411
5758
|
* two independent auto-recovery mechanisms:
|
|
5412
5759
|
*
|
|
5413
|
-
* 1. Missing Permit2 allowance
|
|
5414
|
-
* callback and the attempt fails with
|
|
5415
|
-
*
|
|
5416
|
-
*
|
|
5760
|
+
* 1. Missing Permit2 allowance outside the atomic Base-USDC path: when the
|
|
5761
|
+
* app did not supply its own callback and the attempt fails with
|
|
5762
|
+
* `PERMIT2_APPROVAL_REQUIRED`, this is the wallet's first Permit2 deposit
|
|
5763
|
+
* for that token. Base USDC bundles a gasless ERC-2612 approval inside
|
|
5764
|
+
* its sponsored deposit and never reaches this branch. Other tokens send
|
|
5765
|
+
* the one-time user-paid Permit2 approval via `approvePermit2()` and
|
|
5417
5766
|
* retry the SAME sponsored attempt once. Bounded to one approval attempt
|
|
5418
5767
|
* per call so a wallet/agent that keeps reporting the allowance as
|
|
5419
5768
|
* missing can't loop forever. If `approvePermit2()` itself throws (e.g.
|
|
@@ -5604,6 +5953,32 @@ var OwneySDK = class {
|
|
|
5604
5953
|
}
|
|
5605
5954
|
return eligible;
|
|
5606
5955
|
}
|
|
5956
|
+
/**
|
|
5957
|
+
* Run owner-approved withdrawals before relayer-only withdrawals. Wallet
|
|
5958
|
+
* approval is the only point at which the user can cancel the aggregate
|
|
5959
|
+
* operation, so no relayer leg should commit before it has completed.
|
|
5960
|
+
*/
|
|
5961
|
+
orderAgentsForWithdrawal(agents) {
|
|
5962
|
+
return agents.map((agent, index) => ({ agent, index })).sort((left, right) => {
|
|
5963
|
+
const approvalOrder = Number(Boolean(right.agent.withdrawalRequiresWalletApproval)) - Number(Boolean(left.agent.withdrawalRequiresWalletApproval));
|
|
5964
|
+
return approvalOrder || left.index - right.index;
|
|
5965
|
+
}).map(({ agent }) => agent);
|
|
5966
|
+
}
|
|
5967
|
+
isUserRejectedWithdrawal(error) {
|
|
5968
|
+
let current = error;
|
|
5969
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5970
|
+
while (current && typeof current === "object" && !seen.has(current)) {
|
|
5971
|
+
seen.add(current);
|
|
5972
|
+
const candidate = current;
|
|
5973
|
+
if (candidate.code === 4001 || candidate.code === "4001") return true;
|
|
5974
|
+
const message = [candidate.message, candidate.shortMessage].filter((value) => typeof value === "string").join(" ");
|
|
5975
|
+
if (/user (?:rejected|denied)|rejected by user/i.test(message)) {
|
|
5976
|
+
return true;
|
|
5977
|
+
}
|
|
5978
|
+
current = candidate.cause;
|
|
5979
|
+
}
|
|
5980
|
+
return false;
|
|
5981
|
+
}
|
|
5607
5982
|
// --- Fund operations ---
|
|
5608
5983
|
/**
|
|
5609
5984
|
* Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
|
|
@@ -5639,13 +6014,15 @@ var OwneySDK = class {
|
|
|
5639
6014
|
);
|
|
5640
6015
|
}
|
|
5641
6016
|
const eligibleAgents = this.getEligibleAgents(chainId, asset);
|
|
6017
|
+
const withdrawalAgents = this.orderAgentsForWithdrawal(eligibleAgents);
|
|
5642
6018
|
if (!amount) {
|
|
5643
6019
|
const results2 = {};
|
|
5644
6020
|
const agentErrors2 = {};
|
|
5645
|
-
for (const agent of
|
|
6021
|
+
for (const agent of withdrawalAgents) {
|
|
5646
6022
|
try {
|
|
5647
6023
|
results2[agent.id] = await agent.withdraw(state, chainId, token);
|
|
5648
6024
|
} catch (err) {
|
|
6025
|
+
if (this.isUserRejectedWithdrawal(err)) throw err;
|
|
5649
6026
|
console.error(`withdraw failed for agent "${agent.id}":`, err);
|
|
5650
6027
|
agentErrors2[agent.id] = err instanceof Error ? err.message : String(err);
|
|
5651
6028
|
const code = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
|
|
@@ -5726,12 +6103,13 @@ var OwneySDK = class {
|
|
|
5726
6103
|
planned: 0n
|
|
5727
6104
|
}));
|
|
5728
6105
|
const plans = [...disabledPlans, ...enabledPlans];
|
|
6106
|
+
const orderedPlans = this.orderAgentsForWithdrawal(plans.map((p) => p.agent)).map((agent) => plans.find((plan) => plan.agent === agent));
|
|
5729
6107
|
const results = {};
|
|
5730
6108
|
const agentErrors = {
|
|
5731
6109
|
...aggregated.agentErrors ?? {}
|
|
5732
6110
|
};
|
|
5733
|
-
for (let i = 0; i <
|
|
5734
|
-
const p =
|
|
6111
|
+
for (let i = 0; i < orderedPlans.length; i++) {
|
|
6112
|
+
const p = orderedPlans[i];
|
|
5735
6113
|
if (p.planned === 0n) continue;
|
|
5736
6114
|
try {
|
|
5737
6115
|
results[p.agent.id] = await p.agent.withdraw(
|
|
@@ -5741,6 +6119,7 @@ var OwneySDK = class {
|
|
|
5741
6119
|
p.planned.toString()
|
|
5742
6120
|
);
|
|
5743
6121
|
} catch (err) {
|
|
6122
|
+
if (this.isUserRejectedWithdrawal(err)) throw err;
|
|
5744
6123
|
console.error(`withdraw failed for agent "${p.agent.id}":`, err);
|
|
5745
6124
|
agentErrors[p.agent.id] = err instanceof Error ? err.message : String(err);
|
|
5746
6125
|
const code = err instanceof OwneyError ? err.code : "SDK_AGENT_FAILURE";
|
|
@@ -5752,7 +6131,7 @@ var OwneySDK = class {
|
|
|
5752
6131
|
);
|
|
5753
6132
|
const failedAmount = p.planned;
|
|
5754
6133
|
p.planned = 0n;
|
|
5755
|
-
redistributeShare(
|
|
6134
|
+
redistributeShare(orderedPlans, i, failedAmount);
|
|
5756
6135
|
}
|
|
5757
6136
|
}
|
|
5758
6137
|
if (Object.keys(results).length === 0) {
|
|
@@ -6199,17 +6578,18 @@ var OwneySDK = class {
|
|
|
6199
6578
|
);
|
|
6200
6579
|
}
|
|
6201
6580
|
const provider = this.requireConnectedProvider();
|
|
6202
|
-
const
|
|
6581
|
+
const walletChainClient = (0, import_viem12.createPublicClient)({
|
|
6203
6582
|
chain: VIEM_CHAIN2[chainId],
|
|
6204
|
-
transport: (0,
|
|
6583
|
+
transport: (0, import_viem12.custom)(provider)
|
|
6205
6584
|
});
|
|
6585
|
+
const publicClient = this.getPaidRpcClient(chainId);
|
|
6206
6586
|
const approvalAmount = permit2ApprovalAmount(requiredAmount);
|
|
6207
|
-
const wallet = (0,
|
|
6587
|
+
const wallet = (0, import_viem12.createWalletClient)({
|
|
6208
6588
|
account: state.walletAddress,
|
|
6209
6589
|
chain: VIEM_CHAIN2[chainId],
|
|
6210
|
-
transport: (0,
|
|
6590
|
+
transport: (0, import_viem12.custom)(provider)
|
|
6211
6591
|
});
|
|
6212
|
-
await ensureWalletOnChain(
|
|
6592
|
+
await ensureWalletOnChain(walletChainClient, wallet, chainId);
|
|
6213
6593
|
const hash = await wallet.writeContract({
|
|
6214
6594
|
address: token,
|
|
6215
6595
|
abi: ERC20_ALLOWANCE_ABI,
|
|
@@ -6218,10 +6598,14 @@ var OwneySDK = class {
|
|
|
6218
6598
|
account: state.walletAddress,
|
|
6219
6599
|
chain: VIEM_CHAIN2[chainId]
|
|
6220
6600
|
});
|
|
6221
|
-
const receipt = await
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6601
|
+
const receipt = await withPaidRpcDiagnostics(
|
|
6602
|
+
() => publicClient.waitForTransactionReceipt({
|
|
6603
|
+
hash,
|
|
6604
|
+
confirmations: 1
|
|
6605
|
+
}),
|
|
6606
|
+
chainId,
|
|
6607
|
+
"eth_getTransactionReceipt"
|
|
6608
|
+
);
|
|
6225
6609
|
if (receipt.status !== "success") {
|
|
6226
6610
|
throw new Error(`Permit2 approval reverted (tx ${hash})`);
|
|
6227
6611
|
}
|
|
@@ -6365,7 +6749,7 @@ var OwneySDK = class {
|
|
|
6365
6749
|
};
|
|
6366
6750
|
|
|
6367
6751
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
6368
|
-
var
|
|
6752
|
+
var import_viem13 = require("viem");
|
|
6369
6753
|
var import_siwe2 = require("siwe");
|
|
6370
6754
|
var import_sdk2 = require("@zyfai/sdk");
|
|
6371
6755
|
|
|
@@ -6492,7 +6876,7 @@ function buildSIWXConfig(deps) {
|
|
|
6492
6876
|
issuedAt,
|
|
6493
6877
|
toString() {
|
|
6494
6878
|
return new import_siwe2.SiweMessage({
|
|
6495
|
-
address: (0,
|
|
6879
|
+
address: (0, import_viem13.getAddress)(accountAddress),
|
|
6496
6880
|
chainId: numericChainId(chainId),
|
|
6497
6881
|
domain,
|
|
6498
6882
|
uri,
|