@owney/sdk 0.7.27-beta.2 → 0.7.27-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-LUQ4H72X.js +542 -0
- package/dist/index.cjs +1810 -715
- package/dist/index.d.cts +33 -2
- package/dist/index.d.ts +33 -2
- package/dist/index.js +1038 -529
- package/dist/token-batch-family-VW6ZJLK5.js +26 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
6
16
|
var __export = (target, all) => {
|
|
7
17
|
for (var name in all)
|
|
8
18
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -15,153 +25,76 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
25
|
}
|
|
16
26
|
return to;
|
|
17
27
|
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
18
36
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
37
|
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
AgentChainIncompatibleError: () => AgentChainIncompatibleError,
|
|
24
|
-
AgentNotFoundError: () => AgentNotFoundError,
|
|
25
|
-
InvalidHistoryCursorError: () => InvalidHistoryCursorError,
|
|
26
|
-
NotConnectedError: () => NotConnectedError,
|
|
27
|
-
OwneyError: () => OwneyError,
|
|
28
|
-
OwneySDK: () => OwneySDK,
|
|
29
|
-
YieldseekerAgent: () => YieldseekerAgent,
|
|
30
|
-
clearWithdrawSwap: () => clearWithdrawSwap,
|
|
31
|
-
createOwneySIWX: () => createOwneySIWX,
|
|
32
|
-
listPendingDeposits: () => listPendingDeposits,
|
|
33
|
-
listPendingSwaps: () => listOrders,
|
|
34
|
-
listWithdrawSwaps: () => listWithdrawSwaps,
|
|
35
|
-
saveWithdrawSwap: () => saveWithdrawSwap,
|
|
36
|
-
setOwneyDebug: () => setOwneyDebug,
|
|
37
|
-
subscribeWithdrawSwaps: () => subscribeWithdrawSwaps,
|
|
38
|
-
updateWithdrawSwap: () => updateWithdrawSwap
|
|
39
|
-
});
|
|
40
|
-
module.exports = __toCommonJS(index_exports);
|
|
41
|
-
|
|
42
38
|
// src/errors.ts
|
|
43
|
-
var OwneyError
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
async function observeOrder(key2, run) {
|
|
95
|
-
const busy = () => new OwneyError(
|
|
96
|
-
"SWAP_REQUEST_FAILED",
|
|
97
|
-
"This order is already being observed.",
|
|
98
|
-
{ orderHash: key2, watchActive: true, settlementUnconfirmed: true }
|
|
99
|
-
);
|
|
100
|
-
if (active.has(key2)) throw busy();
|
|
101
|
-
active.add(key2);
|
|
102
|
-
try {
|
|
103
|
-
if (typeof navigator !== "undefined" && navigator.locks)
|
|
104
|
-
return await navigator.locks.request(`owney.swap.observe:${key2}`, { ifAvailable: true }, (lock) => {
|
|
105
|
-
if (!lock) throw busy();
|
|
106
|
-
return run();
|
|
107
|
-
});
|
|
108
|
-
return await run();
|
|
109
|
-
} finally {
|
|
110
|
-
active.delete(key2);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// src/lib/swap/swap.deadline.ts
|
|
115
|
-
async function bounded(work, timeoutMs, error) {
|
|
116
|
-
if (timeoutMs <= 0) throw error();
|
|
117
|
-
let timer;
|
|
118
|
-
try {
|
|
119
|
-
return await Promise.race([
|
|
120
|
-
Promise.resolve().then(work),
|
|
121
|
-
new Promise((_, reject) => {
|
|
122
|
-
timer = setTimeout(() => reject(error()), timeoutMs);
|
|
123
|
-
})
|
|
124
|
-
]);
|
|
125
|
-
} finally {
|
|
126
|
-
clearTimeout(timer);
|
|
39
|
+
var OwneyError, AgentNotFoundError, NotConnectedError, AgentChainIncompatibleError;
|
|
40
|
+
var init_errors = __esm({
|
|
41
|
+
"src/errors.ts"() {
|
|
42
|
+
"use strict";
|
|
43
|
+
OwneyError = class extends Error {
|
|
44
|
+
code;
|
|
45
|
+
details;
|
|
46
|
+
agentId;
|
|
47
|
+
constructor(code, message, details, agentId) {
|
|
48
|
+
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
49
|
+
super(`${prefix} ${message}`);
|
|
50
|
+
this.name = "OwneyError";
|
|
51
|
+
this.code = code;
|
|
52
|
+
this.details = details;
|
|
53
|
+
this.agentId = agentId;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
AgentNotFoundError = class extends OwneyError {
|
|
57
|
+
constructor(agentId, available) {
|
|
58
|
+
super(
|
|
59
|
+
"AGENT_NOT_FOUND",
|
|
60
|
+
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
61
|
+
{ agentId, available },
|
|
62
|
+
agentId
|
|
63
|
+
);
|
|
64
|
+
this.name = "AgentNotFoundError";
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
NotConnectedError = class extends OwneyError {
|
|
68
|
+
constructor() {
|
|
69
|
+
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
70
|
+
this.name = "NotConnectedError";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
AgentChainIncompatibleError = class extends OwneyError {
|
|
74
|
+
incompatibleAgents;
|
|
75
|
+
connectedChainId;
|
|
76
|
+
constructor(incompatibleAgents, connectedChainId) {
|
|
77
|
+
const details = incompatibleAgents.map(
|
|
78
|
+
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
79
|
+
).join("; ");
|
|
80
|
+
super(
|
|
81
|
+
"AGENT_CHAIN_INCOMPATIBLE",
|
|
82
|
+
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
83
|
+
{ incompatibleAgents, connectedChainId }
|
|
84
|
+
);
|
|
85
|
+
this.name = "AgentChainIncompatibleError";
|
|
86
|
+
this.incompatibleAgents = incompatibleAgents;
|
|
87
|
+
this.connectedChainId = connectedChainId;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
127
90
|
}
|
|
128
|
-
}
|
|
129
|
-
async function mapConcurrent(items, run, concurrency = 3) {
|
|
130
|
-
const results = new Array(items.length);
|
|
131
|
-
let next = 0;
|
|
132
|
-
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, async () => {
|
|
133
|
-
for (; ; ) {
|
|
134
|
-
const index = next++;
|
|
135
|
-
if (index >= items.length) return;
|
|
136
|
-
results[index] = await run(items[index]);
|
|
137
|
-
}
|
|
138
|
-
}));
|
|
139
|
-
return results;
|
|
140
|
-
}
|
|
91
|
+
});
|
|
141
92
|
|
|
142
93
|
// src/lib/permit2-batch.ts
|
|
143
|
-
var import_viem = require("viem");
|
|
144
|
-
var BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
145
|
-
var BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
146
|
-
var ARBITRUM_USDC_ADDRESS = "0xaf88d065e77c8cc2239327c5edb3a432268e5831";
|
|
147
94
|
function supportsSponsoredErc2612(chainId, token) {
|
|
148
95
|
const expected = chainId === 8453 ? BASE_USDC_ADDRESS : chainId === 42161 ? ARBITRUM_USDC_ADDRESS : void 0;
|
|
149
96
|
return expected !== void 0 && token.toLowerCase() === expected.toLowerCase();
|
|
150
97
|
}
|
|
151
|
-
var ERC2612_PERMIT_TYPES = {
|
|
152
|
-
Permit: [
|
|
153
|
-
{ name: "owner", type: "address" },
|
|
154
|
-
{ name: "spender", type: "address" },
|
|
155
|
-
{ name: "value", type: "uint256" },
|
|
156
|
-
{ name: "nonce", type: "uint256" },
|
|
157
|
-
{ name: "deadline", type: "uint256" }
|
|
158
|
-
]
|
|
159
|
-
};
|
|
160
|
-
var ERC2612_READ_ABI = (0, import_viem.parseAbi)([
|
|
161
|
-
"function name() view returns (string)",
|
|
162
|
-
"function version() view returns (string)",
|
|
163
|
-
"function nonces(address owner) view returns (uint256)"
|
|
164
|
-
]);
|
|
165
98
|
function erc2612TypedData(input) {
|
|
166
99
|
return {
|
|
167
100
|
domain: {
|
|
@@ -181,27 +114,6 @@ function erc2612TypedData(input) {
|
|
|
181
114
|
}
|
|
182
115
|
};
|
|
183
116
|
}
|
|
184
|
-
var PERMIT_BATCH_TYPES = {
|
|
185
|
-
PermitBatchWitnessTransferFrom: [
|
|
186
|
-
{ name: "permitted", type: "TokenPermissions[]" },
|
|
187
|
-
{ name: "spender", type: "address" },
|
|
188
|
-
{ name: "nonce", type: "uint256" },
|
|
189
|
-
{ name: "deadline", type: "uint256" },
|
|
190
|
-
{ name: "witness", type: "Deposit" }
|
|
191
|
-
],
|
|
192
|
-
Deposit: [{ name: "recipients", type: "address[]" }],
|
|
193
|
-
TokenPermissions: [
|
|
194
|
-
{ name: "token", type: "address" },
|
|
195
|
-
{ name: "amount", type: "uint256" }
|
|
196
|
-
]
|
|
197
|
-
};
|
|
198
|
-
var PERMIT2_BATCH_ABI = (0, import_viem.parseAbi)([
|
|
199
|
-
"struct TokenPermissions { address token; uint256 amount; }",
|
|
200
|
-
"struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
|
|
201
|
-
"struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
|
|
202
|
-
"function permitWitnessTransferFrom(PermitBatchTransferFrom permit,SignatureTransferDetails[] transferDetails,address owner,bytes32 witness,string witnessTypeString,bytes signature)",
|
|
203
|
-
"function nonceBitmap(address owner,uint256 wordPos) view returns (uint256)"
|
|
204
|
-
]);
|
|
205
117
|
function batchPermit(b) {
|
|
206
118
|
return {
|
|
207
119
|
permitted: b.transfers.map((t) => ({
|
|
@@ -228,7 +140,6 @@ function batchTypedData(b, spender) {
|
|
|
228
140
|
}
|
|
229
141
|
};
|
|
230
142
|
}
|
|
231
|
-
var BATCH_WITNESS_TYPE = "Deposit witness)Deposit(address[] recipients)TokenPermissions(address token,uint256 amount)";
|
|
232
143
|
function batchWitness(b) {
|
|
233
144
|
return (0, import_viem.hashStruct)({
|
|
234
145
|
types: PERMIT_BATCH_TYPES,
|
|
@@ -246,9 +157,451 @@ function batchArgs(b) {
|
|
|
246
157
|
b.signature
|
|
247
158
|
];
|
|
248
159
|
}
|
|
160
|
+
var import_viem, BATCH_PERMIT2_ADDRESS, BASE_USDC_ADDRESS, ARBITRUM_USDC_ADDRESS, ERC2612_PERMIT_TYPES, ERC2612_READ_ABI, PERMIT_BATCH_TYPES, PERMIT2_BATCH_ABI, BATCH_WITNESS_TYPE;
|
|
161
|
+
var init_permit2_batch = __esm({
|
|
162
|
+
"src/lib/permit2-batch.ts"() {
|
|
163
|
+
"use strict";
|
|
164
|
+
import_viem = require("viem");
|
|
165
|
+
BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
166
|
+
BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
167
|
+
ARBITRUM_USDC_ADDRESS = "0xaf88d065e77c8cc2239327c5edb3a432268e5831";
|
|
168
|
+
ERC2612_PERMIT_TYPES = {
|
|
169
|
+
Permit: [
|
|
170
|
+
{ name: "owner", type: "address" },
|
|
171
|
+
{ name: "spender", type: "address" },
|
|
172
|
+
{ name: "value", type: "uint256" },
|
|
173
|
+
{ name: "nonce", type: "uint256" },
|
|
174
|
+
{ name: "deadline", type: "uint256" }
|
|
175
|
+
]
|
|
176
|
+
};
|
|
177
|
+
ERC2612_READ_ABI = (0, import_viem.parseAbi)([
|
|
178
|
+
"function name() view returns (string)",
|
|
179
|
+
"function version() view returns (string)",
|
|
180
|
+
"function nonces(address owner) view returns (uint256)"
|
|
181
|
+
]);
|
|
182
|
+
PERMIT_BATCH_TYPES = {
|
|
183
|
+
PermitBatchWitnessTransferFrom: [
|
|
184
|
+
{ name: "permitted", type: "TokenPermissions[]" },
|
|
185
|
+
{ name: "spender", type: "address" },
|
|
186
|
+
{ name: "nonce", type: "uint256" },
|
|
187
|
+
{ name: "deadline", type: "uint256" },
|
|
188
|
+
{ name: "witness", type: "Deposit" }
|
|
189
|
+
],
|
|
190
|
+
Deposit: [{ name: "recipients", type: "address[]" }],
|
|
191
|
+
TokenPermissions: [
|
|
192
|
+
{ name: "token", type: "address" },
|
|
193
|
+
{ name: "amount", type: "uint256" }
|
|
194
|
+
]
|
|
195
|
+
};
|
|
196
|
+
PERMIT2_BATCH_ABI = (0, import_viem.parseAbi)([
|
|
197
|
+
"struct TokenPermissions { address token; uint256 amount; }",
|
|
198
|
+
"struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
|
|
199
|
+
"struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
|
|
200
|
+
"function permitWitnessTransferFrom(PermitBatchTransferFrom permit,SignatureTransferDetails[] transferDetails,address owner,bytes32 witness,string witnessTypeString,bytes signature)",
|
|
201
|
+
"function nonceBitmap(address owner,uint256 wordPos) view returns (uint256)"
|
|
202
|
+
]);
|
|
203
|
+
BATCH_WITNESS_TYPE = "Deposit witness)Deposit(address[] recipients)TokenPermissions(address token,uint256 amount)";
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// src/lib/token-batch-family.ts
|
|
208
|
+
var token_batch_family_exports = {};
|
|
209
|
+
__export(token_batch_family_exports, {
|
|
210
|
+
finishTokenBatchFamily: () => finishTokenBatchFamily,
|
|
211
|
+
loadTokenBatchFamily: () => loadTokenBatchFamily,
|
|
212
|
+
saveTokenBatchAttempt: () => saveTokenBatchAttempt,
|
|
213
|
+
tokenBatchAuthorizationId: () => tokenBatchAuthorizationId,
|
|
214
|
+
tokenBatchCall: () => tokenBatchCall,
|
|
215
|
+
tokenBatchClear: () => tokenBatchClear,
|
|
216
|
+
tokenBatchKey: () => tokenBatchKey,
|
|
217
|
+
tokenBatchRead: () => tokenBatchRead,
|
|
218
|
+
tokenBatchStoredBody: () => tokenBatchStoredBody,
|
|
219
|
+
tokenBatchWrite: () => tokenBatchWrite,
|
|
220
|
+
validateTokenBatchAttempt: () => validateTokenBatchAttempt
|
|
221
|
+
});
|
|
222
|
+
function tokenBatchRead(key2) {
|
|
223
|
+
const raw2 = typeof window === "undefined" ? memory.get(key2) : window.localStorage.getItem(key2) ?? void 0;
|
|
224
|
+
return raw2 && settled.get(key2) === raw2 ? void 0 : raw2;
|
|
225
|
+
}
|
|
226
|
+
function tokenBatchWrite(key2, value) {
|
|
227
|
+
if (typeof window === "undefined") memory.set(key2, value);
|
|
228
|
+
else window.localStorage.setItem(key2, value);
|
|
229
|
+
settled.delete(key2);
|
|
230
|
+
if (tokenBatchRead(key2) !== value)
|
|
231
|
+
throw pending("Deposit recovery data could not be saved.");
|
|
232
|
+
}
|
|
233
|
+
function tokenBatchClear(key2, expected) {
|
|
234
|
+
if (tokenBatchRead(key2) !== expected) return;
|
|
235
|
+
try {
|
|
236
|
+
if (typeof window === "undefined") memory.delete(key2);
|
|
237
|
+
else window.localStorage.removeItem(key2);
|
|
238
|
+
} catch {
|
|
239
|
+
settled.set(key2, expected);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function keys() {
|
|
243
|
+
if (typeof window === "undefined") return [...memory.keys()];
|
|
244
|
+
const storage8 = window.localStorage;
|
|
245
|
+
return Array.from(
|
|
246
|
+
{ length: storage8.length },
|
|
247
|
+
(_, i) => storage8.key(i)
|
|
248
|
+
).filter((key2) => key2 !== null);
|
|
249
|
+
}
|
|
250
|
+
function pending(message = "The saved deposit could not be verified. Its existing transactions remain pending.") {
|
|
251
|
+
return new OwneyError("DEPOSIT_IN_PROGRESS", message, {
|
|
252
|
+
sponsorPending: true,
|
|
253
|
+
notSubmitted: false,
|
|
254
|
+
safeToFallback: false
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function tokenBatchCall(body, phase) {
|
|
258
|
+
if (phase === "deposit")
|
|
259
|
+
return {
|
|
260
|
+
to: BATCH_PERMIT2_ADDRESS,
|
|
261
|
+
data: (0, import_viem2.encodeFunctionData)({
|
|
262
|
+
abi: PERMIT2_BATCH_ABI,
|
|
263
|
+
functionName: "permitWitnessTransferFrom",
|
|
264
|
+
args: batchArgs(body)
|
|
265
|
+
})
|
|
266
|
+
};
|
|
267
|
+
const p = body.erc2612Permit;
|
|
268
|
+
let v = Number((0, import_viem2.sliceHex)(p.signature, 64));
|
|
269
|
+
if (v < 27) v += 27;
|
|
270
|
+
return {
|
|
271
|
+
to: body.token,
|
|
272
|
+
data: (0, import_viem2.encodeFunctionData)({
|
|
273
|
+
abi: approvalAbi,
|
|
274
|
+
functionName: "permit",
|
|
275
|
+
args: [
|
|
276
|
+
body.from,
|
|
277
|
+
BATCH_PERMIT2_ADDRESS,
|
|
278
|
+
BigInt(p.value),
|
|
279
|
+
BigInt(p.deadline),
|
|
280
|
+
v,
|
|
281
|
+
(0, import_viem2.sliceHex)(p.signature, 0, 32),
|
|
282
|
+
(0, import_viem2.sliceHex)(p.signature, 32, 64)
|
|
283
|
+
]
|
|
284
|
+
})
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
async function validateBody(scope, body, relayer) {
|
|
288
|
+
if (!body || body.chainId !== scope.chainId || !(0, import_viem2.isAddressEqual)(body.from, scope.owner) || !(0, import_viem2.isAddressEqual)(body.token, scope.token) || !uint(body.nonce) || !uint(body.deadline) || BigInt(body.deadline) === 0n || !Array.isArray(body.transfers) || !body.transfers.length || body.transfers.length > 16 || body.transfers.some(
|
|
289
|
+
(t) => !(0, import_viem2.isAddress)(t.to) || !uint(t.amount) || BigInt(t.amount) === 0n
|
|
290
|
+
) || new Set(body.transfers.map((t) => t.to.toLowerCase())).size !== body.transfers.length)
|
|
291
|
+
throw pending();
|
|
292
|
+
if (!(0, import_viem2.isAddressEqual)(
|
|
293
|
+
await (0, import_viem2.recoverTypedDataAddress)({
|
|
294
|
+
...batchTypedData(body, relayer),
|
|
295
|
+
signature: body.signature
|
|
296
|
+
}),
|
|
297
|
+
body.from
|
|
298
|
+
))
|
|
299
|
+
throw pending();
|
|
300
|
+
const p = body.erc2612Permit;
|
|
301
|
+
if (p) {
|
|
302
|
+
if (!supportsSponsoredErc2612(body.chainId, body.token) || !uint(p.nonce) || !uint(p.deadline) || !uint(p.value) || BigInt(p.value) !== (1n << 256n) - 1n || p.deadline !== body.deadline || typeof p.tokenName !== "string" || typeof p.tokenVersion !== "string")
|
|
303
|
+
throw pending();
|
|
304
|
+
if (!(0, import_viem2.isAddressEqual)(
|
|
305
|
+
await (0, import_viem2.recoverTypedDataAddress)({
|
|
306
|
+
...erc2612TypedData({
|
|
307
|
+
chainId: body.chainId,
|
|
308
|
+
token: body.token,
|
|
309
|
+
owner: body.from,
|
|
310
|
+
permit: p
|
|
311
|
+
}),
|
|
312
|
+
signature: p.signature
|
|
313
|
+
}),
|
|
314
|
+
body.from
|
|
315
|
+
))
|
|
316
|
+
throw pending();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async function validateTokenBatchAttempt(scope, body, attempt, expectedRelayer) {
|
|
320
|
+
if (!attempt || !["approval", "deposit"].includes(attempt.phase) || !hashPattern.test(attempt.hash) || !uint(attempt.nonce) || !Number.isFinite(attempt.preparedAt) || typeof attempt.submissionAttempted !== "boolean" || attempt.predecessorHash !== void 0 && !hashPattern.test(attempt.predecessorHash))
|
|
321
|
+
throw pending();
|
|
322
|
+
if (typeof attempt.serializedTransaction !== "string" || !/^0x(?:[\da-f]{2}){1,32768}$/i.test(attempt.serializedTransaction))
|
|
323
|
+
throw pending();
|
|
324
|
+
const serialized = attempt.serializedTransaction;
|
|
325
|
+
if (!same((0, import_viem2.keccak256)(serialized), attempt.hash)) throw pending();
|
|
326
|
+
const tx = (0, import_viem2.parseTransaction)(serialized), relayer = await (0, import_viem2.recoverTransactionAddress)({
|
|
327
|
+
serializedTransaction: serialized
|
|
328
|
+
});
|
|
329
|
+
if (expectedRelayer && !(0, import_viem2.isAddressEqual)(relayer, expectedRelayer))
|
|
330
|
+
throw pending();
|
|
331
|
+
await validateBody(scope, body, relayer);
|
|
332
|
+
const call = tokenBatchCall(body, attempt.phase);
|
|
333
|
+
if (tx.chainId !== body.chainId || !tx.to || !(0, import_viem2.isAddressEqual)(tx.to, call.to) || (tx.value ?? 0n) !== 0n || tx.data !== call.data || !Number.isSafeInteger(tx.nonce) || String(tx.nonce) !== attempt.nonce)
|
|
334
|
+
throw pending();
|
|
335
|
+
return relayer;
|
|
336
|
+
}
|
|
337
|
+
function terminalOf(value, attempts) {
|
|
338
|
+
if (!value || !["confirmed", "failed", "expired"].includes(value.kind) || !uint(value.blockNumber))
|
|
339
|
+
return;
|
|
340
|
+
if (value.kind === "confirmed" && (!value.txHash || !attempts.some(
|
|
341
|
+
(a) => a.phase === "deposit" && same(a.hash, value.txHash)
|
|
342
|
+
)))
|
|
343
|
+
return;
|
|
344
|
+
if (value.txHash !== void 0 && !hashPattern.test(value.txHash)) return;
|
|
345
|
+
return {
|
|
346
|
+
kind: value.kind,
|
|
347
|
+
blockNumber: value.blockNumber,
|
|
348
|
+
...value.txHash ? { txHash: value.txHash } : {}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
async function validateFamily(scope, raw2) {
|
|
352
|
+
if (!raw2 || raw2.version !== 1 || !Array.isArray(raw2.attempts) || !raw2.attempts.length || !raw2.current || !(0, import_viem2.isAddress)(raw2.relayer) || !hashPattern.test(raw2.authorizationId))
|
|
353
|
+
throw pending();
|
|
354
|
+
if (!same(tokenBatchAuthorizationId(raw2.body, raw2.relayer), raw2.authorizationId))
|
|
355
|
+
throw pending();
|
|
356
|
+
const seen = /* @__PURE__ */ new Map();
|
|
357
|
+
const roots = /* @__PURE__ */ new Set();
|
|
358
|
+
for (const a of raw2.attempts) {
|
|
359
|
+
await validateTokenBatchAttempt(scope, raw2.body, a, raw2.relayer);
|
|
360
|
+
if (seen.has(a.hash.toLowerCase())) throw pending();
|
|
361
|
+
if (a.predecessorHash) {
|
|
362
|
+
const predecessor = seen.get(a.predecessorHash.toLowerCase());
|
|
363
|
+
if (!predecessor || predecessor.phase !== a.phase || BigInt(a.nonce) <= BigInt(predecessor.nonce))
|
|
364
|
+
throw pending();
|
|
365
|
+
} else {
|
|
366
|
+
if (roots.has(a.phase)) throw pending();
|
|
367
|
+
roots.add(a.phase);
|
|
368
|
+
}
|
|
369
|
+
seen.set(a.hash.toLowerCase(), a);
|
|
370
|
+
}
|
|
371
|
+
for (const phase of ["approval", "deposit"]) {
|
|
372
|
+
const current = raw2.current[phase];
|
|
373
|
+
if (current && !raw2.attempts.some((a) => a.phase === phase && same(a.hash, current)))
|
|
374
|
+
throw pending();
|
|
375
|
+
if (raw2.attempts.some((a) => a.phase === phase) && !current)
|
|
376
|
+
throw pending();
|
|
377
|
+
}
|
|
378
|
+
return {
|
|
379
|
+
...raw2,
|
|
380
|
+
body: tokenBatchStoredBody(raw2.body),
|
|
381
|
+
terminal: terminalOf(raw2.terminal, raw2.attempts)
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
async function importBody(scope, body) {
|
|
385
|
+
const attempts = [];
|
|
386
|
+
let relayer;
|
|
387
|
+
for (const phase of ["approval", "deposit"]) {
|
|
388
|
+
const bytes = phase === "approval" ? body.serializedPermitTransaction : body.serializedTransaction;
|
|
389
|
+
if (!bytes) continue;
|
|
390
|
+
const a = {
|
|
391
|
+
phase,
|
|
392
|
+
hash: (0, import_viem2.keccak256)(bytes),
|
|
393
|
+
serializedTransaction: bytes,
|
|
394
|
+
nonce: String((0, import_viem2.parseTransaction)(bytes).nonce),
|
|
395
|
+
preparedAt: 0,
|
|
396
|
+
submissionAttempted: true
|
|
397
|
+
};
|
|
398
|
+
relayer = await validateTokenBatchAttempt(scope, body, a, relayer);
|
|
399
|
+
attempts.push(a);
|
|
400
|
+
}
|
|
401
|
+
if (!relayer) return;
|
|
402
|
+
return {
|
|
403
|
+
version: 1,
|
|
404
|
+
authorizationId: tokenBatchAuthorizationId(body, relayer),
|
|
405
|
+
relayer,
|
|
406
|
+
body: tokenBatchStoredBody(body),
|
|
407
|
+
attempts,
|
|
408
|
+
current: Object.fromEntries(attempts.map((a) => [a.phase, a.hash]))
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function merge(base7, incoming) {
|
|
412
|
+
if (!same(base7.authorizationId, incoming.authorizationId)) throw pending();
|
|
413
|
+
const attempts = base7.attempts.map((a) => ({ ...a }));
|
|
414
|
+
for (const a of incoming.attempts) {
|
|
415
|
+
const existing = attempts.find((x) => same(x.hash, a.hash));
|
|
416
|
+
if (existing) existing.submissionAttempted ||= a.submissionAttempted;
|
|
417
|
+
else attempts.push(a);
|
|
418
|
+
}
|
|
419
|
+
return { ...base7, attempts };
|
|
420
|
+
}
|
|
421
|
+
async function loadTokenBatchFamily(scope, expectedHash, allowMissing = false) {
|
|
422
|
+
try {
|
|
423
|
+
const key2 = tokenBatchKey(scope), records = /* @__PURE__ */ new Map();
|
|
424
|
+
for (const k of keys().filter((k2) => k2.startsWith(`${key2}:family:`))) {
|
|
425
|
+
const raw2 = tokenBatchRead(k);
|
|
426
|
+
if (!raw2) continue;
|
|
427
|
+
const family = await validateFamily(scope, JSON.parse(raw2));
|
|
428
|
+
if (k !== `${key2}:family:${family.authorizationId}`) throw pending();
|
|
429
|
+
records.set(family.authorizationId, family);
|
|
430
|
+
}
|
|
431
|
+
let projectedId;
|
|
432
|
+
const projection = tokenBatchRead(key2);
|
|
433
|
+
if (projection) {
|
|
434
|
+
const imported = await importBody(scope, JSON.parse(projection));
|
|
435
|
+
if (imported) {
|
|
436
|
+
projectedId = imported.authorizationId;
|
|
437
|
+
const stored = records.get(projectedId);
|
|
438
|
+
if (stored)
|
|
439
|
+
for (const attempt of imported.attempts) {
|
|
440
|
+
const known = stored.attempts.find(
|
|
441
|
+
(a) => same(a.hash, attempt.hash)
|
|
442
|
+
);
|
|
443
|
+
if (known) attempt.submissionAttempted = known.submissionAttempted;
|
|
444
|
+
}
|
|
445
|
+
records.set(
|
|
446
|
+
projectedId,
|
|
447
|
+
stored ? await validateFamily(scope, merge(stored, imported)) : imported
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (expectedHash) {
|
|
452
|
+
let found = [...records.values()].filter(
|
|
453
|
+
(f) => f.attempts.some((a) => same(a.hash, expectedHash))
|
|
454
|
+
);
|
|
455
|
+
if (!found.length) {
|
|
456
|
+
const archive = tokenBatchRead(
|
|
457
|
+
`${key2}:expired:${expectedHash.toLowerCase()}`
|
|
458
|
+
);
|
|
459
|
+
if (archive) {
|
|
460
|
+
const f = await importBody(scope, JSON.parse(archive));
|
|
461
|
+
if (f?.attempts.some((a) => same(a.hash, expectedHash))) found = [f];
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
if (!found.length && allowMissing) return;
|
|
465
|
+
if (found.length !== 1) throw pending();
|
|
466
|
+
return found[0];
|
|
467
|
+
}
|
|
468
|
+
const active2 = [...records.values()].filter(
|
|
469
|
+
(f) => !f.terminal || f.authorizationId === projectedId
|
|
470
|
+
);
|
|
471
|
+
if (active2.length > 1) throw pending();
|
|
472
|
+
return active2[0];
|
|
473
|
+
} catch (error) {
|
|
474
|
+
if (error instanceof OwneyError) throw error;
|
|
475
|
+
throw pending();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
async function saveTokenBatchAttempt(scope, body, attempt, assertCurrent = () => {
|
|
479
|
+
}) {
|
|
480
|
+
try {
|
|
481
|
+
const relayer = await validateTokenBatchAttempt(scope, body, attempt), id = tokenBatchAuthorizationId(body, relayer), key2 = tokenBatchKey(scope), sidecar = `${key2}:family:${id}`;
|
|
482
|
+
const prior = await loadTokenBatchFamily(scope);
|
|
483
|
+
if (prior && prior.authorizationId !== id) throw pending();
|
|
484
|
+
let family = prior ?? {
|
|
485
|
+
version: 1,
|
|
486
|
+
authorizationId: id,
|
|
487
|
+
relayer,
|
|
488
|
+
body: tokenBatchStoredBody(body),
|
|
489
|
+
attempts: [],
|
|
490
|
+
current: {}
|
|
491
|
+
};
|
|
492
|
+
const saved = tokenBatchRead(sidecar);
|
|
493
|
+
if (saved)
|
|
494
|
+
family = merge(await validateFamily(scope, JSON.parse(saved)), family);
|
|
495
|
+
const sameAttempt = family.attempts.find((a) => same(a.hash, attempt.hash));
|
|
496
|
+
if (sameAttempt)
|
|
497
|
+
sameAttempt.submissionAttempted ||= attempt.submissionAttempted;
|
|
498
|
+
else family.attempts.push({ ...attempt });
|
|
499
|
+
family.current[attempt.phase] = attempt.hash;
|
|
500
|
+
family.body = { ...tokenBatchStoredBody(body) };
|
|
501
|
+
for (const phase of ["approval", "deposit"]) {
|
|
502
|
+
const current = family.attempts.find(
|
|
503
|
+
(a) => a.hash === family.current[phase]
|
|
504
|
+
);
|
|
505
|
+
if (current)
|
|
506
|
+
family.body[phase === "deposit" ? "serializedTransaction" : "serializedPermitTransaction"] = current.serializedTransaction;
|
|
507
|
+
}
|
|
508
|
+
family = await validateFamily(scope, family);
|
|
509
|
+
if (tokenBatchRead(sidecar) !== saved)
|
|
510
|
+
throw pending(
|
|
511
|
+
"Deposit recovery data changed. Retry the existing deposit."
|
|
512
|
+
);
|
|
513
|
+
assertCurrent();
|
|
514
|
+
tokenBatchWrite(sidecar, JSON.stringify(family));
|
|
515
|
+
assertCurrent();
|
|
516
|
+
tokenBatchWrite(key2, JSON.stringify(family.body));
|
|
517
|
+
return family;
|
|
518
|
+
} catch (error) {
|
|
519
|
+
if (error instanceof OwneyError) throw error;
|
|
520
|
+
throw pending(
|
|
521
|
+
"Deposit recovery data could not be saved. The earlier transaction remains tracked."
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function finishTokenBatchFamily(scope, family, terminal) {
|
|
526
|
+
const key2 = tokenBatchKey(scope), sidecar = `${key2}:family:${family.authorizationId}`;
|
|
527
|
+
try {
|
|
528
|
+
const saved = tokenBatchRead(sidecar), current = saved ? JSON.parse(saved) : family;
|
|
529
|
+
if (current.authorizationId !== family.authorizationId) return;
|
|
530
|
+
if (terminal.kind !== "confirmed" && current.attempts.some(
|
|
531
|
+
(a) => !family.attempts.some((known) => same(known.hash, a.hash))
|
|
532
|
+
))
|
|
533
|
+
return;
|
|
534
|
+
const evidence = terminalOf(terminal, current.attempts);
|
|
535
|
+
if (!evidence) return;
|
|
536
|
+
tokenBatchWrite(
|
|
537
|
+
sidecar,
|
|
538
|
+
JSON.stringify({ ...current, terminal: evidence })
|
|
539
|
+
);
|
|
540
|
+
const projected = tokenBatchRead(key2);
|
|
541
|
+
if (projected && tokenBatchAuthorizationId(JSON.parse(projected), family.relayer) === family.authorizationId)
|
|
542
|
+
tokenBatchClear(key2, projected);
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
var import_viem2, memory, settled, hashPattern, uint, same, tokenBatchKey, tokenBatchAuthorizationId, tokenBatchStoredBody, approvalAbi;
|
|
547
|
+
var init_token_batch_family = __esm({
|
|
548
|
+
"src/lib/token-batch-family.ts"() {
|
|
549
|
+
"use strict";
|
|
550
|
+
import_viem2 = require("viem");
|
|
551
|
+
init_errors();
|
|
552
|
+
init_permit2_batch();
|
|
553
|
+
memory = /* @__PURE__ */ new Map();
|
|
554
|
+
settled = /* @__PURE__ */ new Map();
|
|
555
|
+
hashPattern = /^0x[\da-f]{64}$/i;
|
|
556
|
+
uint = (value) => typeof value === "string" && /^\d{1,78}$/.test(value) && BigInt(value) < 1n << 256n;
|
|
557
|
+
same = (a, b) => a.toLowerCase() === b.toLowerCase();
|
|
558
|
+
tokenBatchKey = (s) => `owney.token-batch.v1:${(0, import_viem2.keccak256)((0, import_viem2.toBytes)(s.apiKey))}:${s.baseUrl ?? "default"}:${s.chainId}:${s.owner.toLowerCase()}:${s.token.toLowerCase()}`;
|
|
559
|
+
tokenBatchAuthorizationId = (body, relayer) => (0, import_viem2.keccak256)(
|
|
560
|
+
(0, import_viem2.encodeAbiParameters)(
|
|
561
|
+
[{ type: "address" }, { type: "bytes32" }],
|
|
562
|
+
[body.from, (0, import_viem2.hashTypedData)(batchTypedData(body, relayer))]
|
|
563
|
+
)
|
|
564
|
+
);
|
|
565
|
+
tokenBatchStoredBody = (body) => ({
|
|
566
|
+
...body,
|
|
567
|
+
transfers: body.transfers.map(({ to, amount }) => ({ to, amount }))
|
|
568
|
+
});
|
|
569
|
+
approvalAbi = (0, import_viem2.parseAbi)([
|
|
570
|
+
"function permit(address owner,address spender,uint256 value,uint256 deadline,uint8 v,bytes32 r,bytes32 s)"
|
|
571
|
+
]);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// src/index.ts
|
|
576
|
+
var index_exports = {};
|
|
577
|
+
__export(index_exports, {
|
|
578
|
+
AgentChainIncompatibleError: () => AgentChainIncompatibleError,
|
|
579
|
+
AgentNotFoundError: () => AgentNotFoundError,
|
|
580
|
+
InvalidHistoryCursorError: () => InvalidHistoryCursorError,
|
|
581
|
+
NotConnectedError: () => NotConnectedError,
|
|
582
|
+
OwneyError: () => OwneyError,
|
|
583
|
+
OwneySDK: () => OwneySDK,
|
|
584
|
+
YieldseekerAgent: () => YieldseekerAgent,
|
|
585
|
+
clearWithdrawSwap: () => clearWithdrawSwap,
|
|
586
|
+
createOwneySIWX: () => createOwneySIWX,
|
|
587
|
+
listPendingDeposits: () => listPendingDeposits,
|
|
588
|
+
listPendingSwaps: () => listOrders,
|
|
589
|
+
listWithdrawSwaps: () => listWithdrawSwaps,
|
|
590
|
+
saveWithdrawSwap: () => saveWithdrawSwap,
|
|
591
|
+
setOwneyDebug: () => setOwneyDebug,
|
|
592
|
+
subscribeWithdrawSwaps: () => subscribeWithdrawSwaps,
|
|
593
|
+
updateWithdrawSwap: () => updateWithdrawSwap
|
|
594
|
+
});
|
|
595
|
+
module.exports = __toCommonJS(index_exports);
|
|
596
|
+
|
|
597
|
+
// src/client.ts
|
|
598
|
+
init_token_batch_family();
|
|
599
|
+
|
|
600
|
+
// src/lib/token-batch-observer.ts
|
|
601
|
+
init_permit2_batch();
|
|
249
602
|
|
|
250
603
|
// src/lib/funding-evidence.ts
|
|
251
|
-
var
|
|
604
|
+
var import_viem3 = require("viem");
|
|
252
605
|
var import_account_abstraction = require("viem/account-abstraction");
|
|
253
606
|
function notifyFunding(callback, evidence) {
|
|
254
607
|
try {
|
|
@@ -257,9 +610,9 @@ function notifyFunding(callback, evidence) {
|
|
|
257
610
|
} catch {
|
|
258
611
|
}
|
|
259
612
|
}
|
|
260
|
-
var fullWithdrawalAbi = (0,
|
|
261
|
-
var withdrawalEventAbi = (0,
|
|
262
|
-
var accountExecutionAbi = (0,
|
|
613
|
+
var fullWithdrawalAbi = (0, import_viem3.parseAbi)(["function withdrawAllAssetToUser(address recipient, address asset)"]);
|
|
614
|
+
var withdrawalEventAbi = (0, import_viem3.parseAbi)(["event WithdrewTokenToUser(address indexed owner, address indexed recipient, address indexed token, uint256 amount)"]);
|
|
615
|
+
var accountExecutionAbi = (0, import_viem3.parseAbi)([
|
|
263
616
|
"function execute(address target,uint256 value,bytes data)",
|
|
264
617
|
"function executeBatch((address target,uint256 value,bytes data)[] calls)"
|
|
265
618
|
]);
|
|
@@ -269,7 +622,7 @@ function yieldseekerExecution(receipt, evidence) {
|
|
|
269
622
|
const operationEvents = receipt.logs.flatMap((log) => {
|
|
270
623
|
if (![entryPoint06, entryPoint07].includes(log.address.toLowerCase())) return [];
|
|
271
624
|
try {
|
|
272
|
-
const event = (0,
|
|
625
|
+
const event = (0, import_viem3.decodeEventLog)({ abi: import_account_abstraction.entryPoint06Abi, data: log.data, topics: log.topics });
|
|
273
626
|
return event.eventName === "UserOperationEvent" ? [{ ...event.args, logIndex: log.logIndex }] : [];
|
|
274
627
|
} catch {
|
|
275
628
|
return [];
|
|
@@ -292,7 +645,7 @@ function isFullYieldseekerWithdrawal(transaction, evidence, tokenAddress, receip
|
|
|
292
645
|
if (evidence.agentId !== "yieldseeker" || transaction.chainId !== evidence.chainId || transaction.hash.toLowerCase() !== evidence.txHash?.toLowerCase() || !evidence.agentWallet) return false;
|
|
293
646
|
const matchesFullCall = (data) => {
|
|
294
647
|
try {
|
|
295
|
-
const decoded = (0,
|
|
648
|
+
const decoded = (0, import_viem3.decodeFunctionData)({ abi: fullWithdrawalAbi, data });
|
|
296
649
|
return decoded.args[0].toLowerCase() === evidence.walletAddress.toLowerCase() && decoded.args[1].toLowerCase() === tokenAddress.toLowerCase();
|
|
297
650
|
} catch {
|
|
298
651
|
return false;
|
|
@@ -303,7 +656,7 @@ function isFullYieldseekerWithdrawal(transaction, evidence, tokenAddress, receip
|
|
|
303
656
|
const address = transaction.to?.toLowerCase();
|
|
304
657
|
if (address !== entryPoint06 && address !== entryPoint07) return false;
|
|
305
658
|
const version = address === entryPoint06 ? "0.6" : "0.7";
|
|
306
|
-
const decoded = (0,
|
|
659
|
+
const decoded = (0, import_viem3.decodeFunctionData)({ abi: version === "0.6" ? import_account_abstraction.entryPoint06Abi : import_account_abstraction.entryPoint07Abi, data: transaction.input });
|
|
307
660
|
if (decoded.functionName !== "handleOps") return false;
|
|
308
661
|
const operations = decoded.args[0].filter((operation2) => [evidence.agentWallet.toLowerCase(), evidence.walletAddress.toLowerCase()].includes(operation2.sender.toLowerCase()));
|
|
309
662
|
if (operations.length !== 1) return false;
|
|
@@ -319,14 +672,14 @@ function isFullYieldseekerWithdrawal(transaction, evidence, tokenAddress, receip
|
|
|
319
672
|
if (!receipt?.logs.some((log) => {
|
|
320
673
|
if (log.address.toLowerCase() !== address) return false;
|
|
321
674
|
try {
|
|
322
|
-
const event = (0,
|
|
675
|
+
const event = (0, import_viem3.decodeEventLog)({ abi: import_account_abstraction.entryPoint06Abi, data: log.data, topics: log.topics });
|
|
323
676
|
return event.eventName === "UserOperationEvent" && event.args.userOpHash.toLowerCase() === hash2.toLowerCase() && event.args.sender.toLowerCase() === operation.sender.toLowerCase() && event.args.success;
|
|
324
677
|
} catch {
|
|
325
678
|
return false;
|
|
326
679
|
}
|
|
327
680
|
})) return false;
|
|
328
681
|
if (operation.sender.toLowerCase() === evidence.agentWallet.toLowerCase()) return matchesFullCall(operation.callData);
|
|
329
|
-
const execution = (0,
|
|
682
|
+
const execution = (0, import_viem3.decodeFunctionData)({ abi: accountExecutionAbi, data: operation.callData });
|
|
330
683
|
const calls = execution.functionName === "execute" ? [{ target: execution.args[0], value: execution.args[1], data: execution.args[2] }] : execution.args[0];
|
|
331
684
|
return calls.length === 1 && calls[0].value === 0n && calls[0].target.toLowerCase() === evidence.agentWallet.toLowerCase() && matchesFullCall(calls[0].data);
|
|
332
685
|
} catch {
|
|
@@ -369,7 +722,7 @@ function inspectFundingReceipt(receipt, evidence, tokenAddress, direction, optio
|
|
|
369
722
|
if (seen.has(log.logIndex)) continue;
|
|
370
723
|
seen.add(log.logIndex);
|
|
371
724
|
try {
|
|
372
|
-
const event = (0,
|
|
725
|
+
const event = (0, import_viem3.decodeEventLog)({ abi: import_viem3.erc20Abi, data: log.data, topics: log.topics });
|
|
373
726
|
if (event.eventName !== "Transfer") continue;
|
|
374
727
|
const { from, to, value } = event.args;
|
|
375
728
|
if (direction === "withdraw" && value === 0n && from.toLowerCase() === agent && to.toLowerCase() === owner)
|
|
@@ -393,7 +746,7 @@ function inspectFundingReceipt(receipt, evidence, tokenAddress, direction, optio
|
|
|
393
746
|
const emptyPayout = direction === "withdraw" && evidence.agentId === "yieldseeker" && amount === 0n && zeroTransferLogs.length > 0 && execution.logs.some((log) => {
|
|
394
747
|
if (log.address.toLowerCase() !== agent) return false;
|
|
395
748
|
try {
|
|
396
|
-
const { args } = (0,
|
|
749
|
+
const { args } = (0, import_viem3.decodeEventLog)({ abi: withdrawalEventAbi, data: log.data, topics: log.topics });
|
|
397
750
|
return args.owner.toLowerCase() === owner && args.recipient.toLowerCase() === owner && args.token.toLowerCase() === tokenAddress.toLowerCase() && args.amount === 0n;
|
|
398
751
|
} catch {
|
|
399
752
|
return false;
|
|
@@ -425,6 +778,218 @@ function inspectFundingReceipt(receipt, evidence, tokenAddress, direction, optio
|
|
|
425
778
|
};
|
|
426
779
|
}
|
|
427
780
|
|
|
781
|
+
// src/lib/token-batch-observer.ts
|
|
782
|
+
init_token_batch_family();
|
|
783
|
+
var cursors = /* @__PURE__ */ new Map();
|
|
784
|
+
async function observeTokenBatchFamily(input) {
|
|
785
|
+
let expired = false, timer;
|
|
786
|
+
const assertCurrent = () => {
|
|
787
|
+
if (expired || Date.now() >= input.deadlineAt)
|
|
788
|
+
throw Error("observation ended");
|
|
789
|
+
input.assertCurrent();
|
|
790
|
+
};
|
|
791
|
+
const run = async () => {
|
|
792
|
+
assertCurrent();
|
|
793
|
+
const { scope, pub } = input;
|
|
794
|
+
const family = await loadTokenBatchFamily(
|
|
795
|
+
scope,
|
|
796
|
+
input.family.attempts[0].hash
|
|
797
|
+
);
|
|
798
|
+
assertCurrent();
|
|
799
|
+
if (!family || family.authorizationId !== input.family.authorizationId)
|
|
800
|
+
return { status: "unresolved" };
|
|
801
|
+
const attempts = family.attempts.filter((a) => a.phase === "deposit");
|
|
802
|
+
const key2 = `${tokenBatchKey(scope)}:${family.authorizationId}`;
|
|
803
|
+
const start = (cursors.get(key2) ?? 0) % Math.max(1, attempts.length);
|
|
804
|
+
const ordered = [...attempts.slice(start), ...attempts.slice(0, start)];
|
|
805
|
+
const reverted = [];
|
|
806
|
+
for (let index = 0; index < ordered.length; index += 3) {
|
|
807
|
+
assertCurrent();
|
|
808
|
+
const group = ordered.slice(index, index + 3);
|
|
809
|
+
cursors.set(key2, (start + index + group.length) % attempts.length);
|
|
810
|
+
const observations = await Promise.all(
|
|
811
|
+
group.map(async (attempt) => {
|
|
812
|
+
try {
|
|
813
|
+
await validateTokenBatchAttempt(
|
|
814
|
+
scope,
|
|
815
|
+
family.body,
|
|
816
|
+
attempt,
|
|
817
|
+
family.relayer
|
|
818
|
+
);
|
|
819
|
+
assertCurrent();
|
|
820
|
+
const receipt = await pub.getTransactionReceipt({
|
|
821
|
+
hash: attempt.hash
|
|
822
|
+
});
|
|
823
|
+
assertCurrent();
|
|
824
|
+
if (receipt.transactionHash?.toLowerCase() !== attempt.hash.toLowerCase() || typeof receipt.blockNumber !== "bigint" || !receipt.blockHash)
|
|
825
|
+
return;
|
|
826
|
+
if (receipt.status === "reverted")
|
|
827
|
+
return { kind: "reverted", receipt };
|
|
828
|
+
if (receipt.status !== "success" || receipt.from?.toLowerCase() !== family.relayer.toLowerCase() || receipt.to?.toLowerCase() !== BATCH_PERMIT2_ADDRESS.toLowerCase())
|
|
829
|
+
return;
|
|
830
|
+
const exact = family.body.transfers.every(
|
|
831
|
+
(t) => inspectFundingReceipt(
|
|
832
|
+
receipt,
|
|
833
|
+
{
|
|
834
|
+
agentId: "yieldseeker",
|
|
835
|
+
chainId: family.body.chainId,
|
|
836
|
+
token: "USDC",
|
|
837
|
+
walletAddress: family.body.from,
|
|
838
|
+
agentWallet: t.to,
|
|
839
|
+
intendedAmount: t.amount,
|
|
840
|
+
txHash: attempt.hash,
|
|
841
|
+
transfer: "pending",
|
|
842
|
+
registration: "pending",
|
|
843
|
+
delivery: "not-applicable"
|
|
844
|
+
},
|
|
845
|
+
family.body.token,
|
|
846
|
+
"deposit",
|
|
847
|
+
{ requireAmountMatch: true }
|
|
848
|
+
).transfer === "confirmed"
|
|
849
|
+
);
|
|
850
|
+
return exact ? { kind: "confirmed", receipt } : void 0;
|
|
851
|
+
} catch {
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
})
|
|
855
|
+
);
|
|
856
|
+
assertCurrent();
|
|
857
|
+
const winner = observations.find((o) => o?.kind === "confirmed");
|
|
858
|
+
if (winner) {
|
|
859
|
+
const latest2 = await loadTokenBatchFamily(
|
|
860
|
+
scope,
|
|
861
|
+
winner.receipt.transactionHash
|
|
862
|
+
);
|
|
863
|
+
assertCurrent();
|
|
864
|
+
if (!latest2) return { status: "unresolved" };
|
|
865
|
+
finishTokenBatchFamily(scope, latest2, {
|
|
866
|
+
kind: "confirmed",
|
|
867
|
+
txHash: winner.receipt.transactionHash,
|
|
868
|
+
blockNumber: winner.receipt.blockNumber.toString()
|
|
869
|
+
});
|
|
870
|
+
return {
|
|
871
|
+
status: "confirmed",
|
|
872
|
+
txHash: winner.receipt.transactionHash,
|
|
873
|
+
receipt: winner.receipt
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
for (const o of observations)
|
|
877
|
+
if (o?.kind === "reverted") reverted.push(o.receipt);
|
|
878
|
+
}
|
|
879
|
+
const latest = await loadTokenBatchFamily(scope, family.attempts[0].hash);
|
|
880
|
+
assertCurrent();
|
|
881
|
+
if (!latest) return { status: "unresolved" };
|
|
882
|
+
if (attempts.length > 0 && reverted.length === latest.attempts.filter((a) => a.phase === "deposit").length) {
|
|
883
|
+
const block2 = reverted.reduce(
|
|
884
|
+
(n, r) => r.blockNumber > n ? r.blockNumber : n,
|
|
885
|
+
0n
|
|
886
|
+
);
|
|
887
|
+
finishTokenBatchFamily(scope, latest, {
|
|
888
|
+
kind: "failed",
|
|
889
|
+
blockNumber: block2.toString()
|
|
890
|
+
});
|
|
891
|
+
return { status: "failed", receipts: reverted };
|
|
892
|
+
}
|
|
893
|
+
const block = await pub.getBlock({ blockTag: "finalized" });
|
|
894
|
+
assertCurrent();
|
|
895
|
+
if (typeof block.number !== "bigint" || !block.hash || typeof block.timestamp !== "bigint" || block.timestamp <= BigInt(family.body.deadline))
|
|
896
|
+
return { status: "unresolved" };
|
|
897
|
+
const nonce = BigInt(family.body.nonce);
|
|
898
|
+
const bitmap = await pub.readContract({
|
|
899
|
+
address: BATCH_PERMIT2_ADDRESS,
|
|
900
|
+
abi: PERMIT2_BATCH_ABI,
|
|
901
|
+
functionName: "nonceBitmap",
|
|
902
|
+
args: [family.body.from, nonce >> 8n],
|
|
903
|
+
blockNumber: block.number
|
|
904
|
+
});
|
|
905
|
+
assertCurrent();
|
|
906
|
+
if (typeof bitmap !== "bigint" || bitmap < 0n || bitmap >= 1n << 256n || (bitmap & 1n << (nonce & 255n)) !== 0n)
|
|
907
|
+
return { status: "unresolved" };
|
|
908
|
+
if ((await pub.getBlock({ blockNumber: block.number })).hash !== block.hash)
|
|
909
|
+
return { status: "unresolved" };
|
|
910
|
+
assertCurrent();
|
|
911
|
+
finishTokenBatchFamily(scope, latest, {
|
|
912
|
+
kind: "expired",
|
|
913
|
+
blockNumber: block.number.toString()
|
|
914
|
+
});
|
|
915
|
+
return { status: "expired", blockNumber: block.number };
|
|
916
|
+
};
|
|
917
|
+
try {
|
|
918
|
+
return await Promise.race([
|
|
919
|
+
run(),
|
|
920
|
+
new Promise((resolve) => {
|
|
921
|
+
timer = setTimeout(
|
|
922
|
+
() => {
|
|
923
|
+
expired = true;
|
|
924
|
+
resolve({ status: "unresolved" });
|
|
925
|
+
},
|
|
926
|
+
Math.max(0, input.deadlineAt - Date.now())
|
|
927
|
+
);
|
|
928
|
+
})
|
|
929
|
+
]);
|
|
930
|
+
} catch {
|
|
931
|
+
return { status: "unresolved" };
|
|
932
|
+
} finally {
|
|
933
|
+
expired = true;
|
|
934
|
+
if (timer) clearTimeout(timer);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// src/lib/swap/swap.observation.ts
|
|
939
|
+
init_errors();
|
|
940
|
+
var active = /* @__PURE__ */ new Set();
|
|
941
|
+
var isOrderObserved = (key2) => active.has(key2);
|
|
942
|
+
async function observeOrder(key2, run) {
|
|
943
|
+
const busy = () => new OwneyError(
|
|
944
|
+
"SWAP_REQUEST_FAILED",
|
|
945
|
+
"This order is already being observed.",
|
|
946
|
+
{ orderHash: key2, watchActive: true, settlementUnconfirmed: true }
|
|
947
|
+
);
|
|
948
|
+
if (active.has(key2)) throw busy();
|
|
949
|
+
active.add(key2);
|
|
950
|
+
try {
|
|
951
|
+
if (typeof navigator !== "undefined" && navigator.locks)
|
|
952
|
+
return await navigator.locks.request(`owney.swap.observe:${key2}`, { ifAvailable: true }, (lock) => {
|
|
953
|
+
if (!lock) throw busy();
|
|
954
|
+
return run();
|
|
955
|
+
});
|
|
956
|
+
return await run();
|
|
957
|
+
} finally {
|
|
958
|
+
active.delete(key2);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// src/lib/swap/swap.deadline.ts
|
|
963
|
+
async function bounded(work, timeoutMs, error) {
|
|
964
|
+
if (timeoutMs <= 0) throw error();
|
|
965
|
+
let timer;
|
|
966
|
+
try {
|
|
967
|
+
return await Promise.race([
|
|
968
|
+
Promise.resolve().then(work),
|
|
969
|
+
new Promise((_, reject) => {
|
|
970
|
+
timer = setTimeout(() => reject(error()), timeoutMs);
|
|
971
|
+
})
|
|
972
|
+
]);
|
|
973
|
+
} finally {
|
|
974
|
+
clearTimeout(timer);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
async function mapConcurrent(items, run, concurrency = 3) {
|
|
978
|
+
const results = new Array(items.length);
|
|
979
|
+
let next = 0;
|
|
980
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, async () => {
|
|
981
|
+
for (; ; ) {
|
|
982
|
+
const index = next++;
|
|
983
|
+
if (index >= items.length) return;
|
|
984
|
+
results[index] = await run(items[index]);
|
|
985
|
+
}
|
|
986
|
+
}));
|
|
987
|
+
return results;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// src/client.ts
|
|
991
|
+
init_permit2_batch();
|
|
992
|
+
|
|
428
993
|
// src/lib/helpers/funding-amount.ts
|
|
429
994
|
function isFundingAmount(value, allowZero = false) {
|
|
430
995
|
if (typeof value !== "string" || !/^\d{1,78}$/.test(value)) return false;
|
|
@@ -452,10 +1017,14 @@ function registerDepositBatch(callback, transfer) {
|
|
|
452
1017
|
batchCallbacks.set(callback, transfer);
|
|
453
1018
|
}
|
|
454
1019
|
|
|
1020
|
+
// src/lib/sponsored-deposit.ts
|
|
1021
|
+
init_errors();
|
|
1022
|
+
|
|
455
1023
|
// src/lib/transfer-auth.ts
|
|
456
|
-
var
|
|
1024
|
+
var import_viem4 = require("viem");
|
|
457
1025
|
|
|
458
1026
|
// src/lib/sponsor-client.ts
|
|
1027
|
+
init_errors();
|
|
459
1028
|
var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
460
1029
|
async function postPaymasterIntent(input) {
|
|
461
1030
|
const base7 = input.baseUrl ?? ROUTING_API_BASE_URL;
|
|
@@ -539,6 +1108,7 @@ async function postSponsorBatchTransfer(input) {
|
|
|
539
1108
|
`${input.baseUrl ?? ROUTING_API_BASE_URL}/api/v1/sponsor/permit2-batch`,
|
|
540
1109
|
{
|
|
541
1110
|
method: "POST",
|
|
1111
|
+
...input.signal ? { signal: input.signal } : {},
|
|
542
1112
|
headers: {
|
|
543
1113
|
"content-type": "application/json",
|
|
544
1114
|
"x-owney-api-key": input.apiKey
|
|
@@ -567,9 +1137,48 @@ async function postSponsorBatchTransfer(input) {
|
|
|
567
1137
|
}
|
|
568
1138
|
return parsed.data;
|
|
569
1139
|
}
|
|
1140
|
+
async function postSponsorBatchRecovery(input) {
|
|
1141
|
+
const failure = () => new OwneyError("SPONSOR_REQUEST_FAILED", "Deposit recovery is unavailable. The existing transaction remains tracked.", { safeToFallback: false });
|
|
1142
|
+
try {
|
|
1143
|
+
input.signal?.throwIfAborted();
|
|
1144
|
+
const response = await fetch(`${input.baseUrl ?? ROUTING_API_BASE_URL}/api/v1/sponsor/permit2-batch/recover`, { method: "POST", headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey }, body: JSON.stringify(input.body), signal: input.signal });
|
|
1145
|
+
input.signal?.throwIfAborted();
|
|
1146
|
+
if (response.status === 404) return;
|
|
1147
|
+
const payload = await response.json();
|
|
1148
|
+
input.signal?.throwIfAborted();
|
|
1149
|
+
if (!response.ok || payload?.success !== true) throw failure();
|
|
1150
|
+
const value = payload.data;
|
|
1151
|
+
const { isAddress: isAddress6, keccak256: keccak2565, parseTransaction: parseTransaction4, recoverTransactionAddress: recoverTransactionAddress2 } = await import("viem");
|
|
1152
|
+
const { validateTokenBatchAttempt: validateTokenBatchAttempt2 } = await Promise.resolve().then(() => (init_token_batch_family(), token_batch_family_exports));
|
|
1153
|
+
const phase = input.body.phase;
|
|
1154
|
+
const original = phase === "approval" ? input.body.serializedPermitTransaction : input.body.serializedTransaction;
|
|
1155
|
+
if (!original) throw failure();
|
|
1156
|
+
const hash2 = keccak2565(original), relayer = await recoverTransactionAddress2({ serializedTransaction: original });
|
|
1157
|
+
const validHash = (v) => typeof v === "string" && /^0x[\da-f]{64}$/i.test(v);
|
|
1158
|
+
if (!value || value.protocol !== 1 || value.phase !== phase || !validHash(value.txHash) || !isAddress6(value.relayer) || value.relayer.toLowerCase() !== relayer.toLowerCase()) throw failure();
|
|
1159
|
+
if (value.status !== "prepared" && value.txHash.toLowerCase() !== hash2.toLowerCase()) throw failure();
|
|
1160
|
+
if (value.status === "unresolved") {
|
|
1161
|
+
if (!["nonce-not-consumed", "authorization-used", "authorization-expired", "state-unavailable", "preparation-rejected", "relayer-changed"].includes(value.reason)) throw failure();
|
|
1162
|
+
} else {
|
|
1163
|
+
if (!("blockNumber" in value) || typeof value.blockNumber !== "string" || !/^\d{1,78}$/.test(value.blockNumber) || BigInt(value.blockNumber) >= 1n << 256n || !validHash(value.blockHash)) throw failure();
|
|
1164
|
+
if (value.status === "prepared") {
|
|
1165
|
+
if (value.predecessorHash?.toLowerCase() !== hash2.toLowerCase()) throw failure();
|
|
1166
|
+
const tx = parseTransaction4(value.serializedTransaction), old = parseTransaction4(original);
|
|
1167
|
+
if (!Number.isSafeInteger(tx.nonce) || tx.nonce <= old.nonce) throw failure();
|
|
1168
|
+
await validateTokenBatchAttempt2({ apiKey: input.apiKey, baseUrl: input.baseUrl, chainId: input.body.chainId, owner: input.body.from, token: input.body.token }, input.body, { phase, hash: value.txHash, serializedTransaction: value.serializedTransaction, nonce: String(tx.nonce), predecessorHash: hash2, preparedAt: Date.now(), submissionAttempted: false }, relayer);
|
|
1169
|
+
} else if (value.status === "included") {
|
|
1170
|
+
if (value.outcome !== "success" && value.outcome !== "reverted") throw failure();
|
|
1171
|
+
} else if (value.status !== "approval-satisfied" || phase !== "approval") throw failure();
|
|
1172
|
+
}
|
|
1173
|
+
input.signal?.throwIfAborted();
|
|
1174
|
+
return value;
|
|
1175
|
+
} catch {
|
|
1176
|
+
throw failure();
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
570
1179
|
|
|
571
1180
|
// src/lib/permit2.ts
|
|
572
|
-
var
|
|
1181
|
+
var import_viem5 = require("viem");
|
|
573
1182
|
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
574
1183
|
var MAX_UINT256 = 2n ** 256n - 1n;
|
|
575
1184
|
function permit2ApprovalAmount(requiredAmount) {
|
|
@@ -610,7 +1219,7 @@ var ERC20_ALLOWANCE_ABI = [
|
|
|
610
1219
|
function randomPermit2Nonce() {
|
|
611
1220
|
const bytes = new Uint8Array(32);
|
|
612
1221
|
globalThis.crypto.getRandomValues(bytes);
|
|
613
|
-
return BigInt((0,
|
|
1222
|
+
return BigInt((0, import_viem5.bytesToHex)(bytes));
|
|
614
1223
|
}
|
|
615
1224
|
async function readPermit2Allowance(publicClient, token, owner, blockNumber) {
|
|
616
1225
|
return publicClient.readContract({
|
|
@@ -631,6 +1240,7 @@ async function readErc20Balance(publicClient, token, owner) {
|
|
|
631
1240
|
}
|
|
632
1241
|
|
|
633
1242
|
// src/lib/chain-guard.ts
|
|
1243
|
+
init_errors();
|
|
634
1244
|
var CHAIN_NAMES = {
|
|
635
1245
|
1: "Ethereum",
|
|
636
1246
|
8453: "Base",
|
|
@@ -704,6 +1314,9 @@ function makeVerificationAwareDepositCallback(implementation) {
|
|
|
704
1314
|
return callback;
|
|
705
1315
|
}
|
|
706
1316
|
|
|
1317
|
+
// src/lib/agent-reads.ts
|
|
1318
|
+
init_errors();
|
|
1319
|
+
|
|
707
1320
|
// src/lib/rate-limit.ts
|
|
708
1321
|
function rateLimitDelay(error, now = Date.now()) {
|
|
709
1322
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1005,15 +1618,15 @@ function positionsEmpty(entries, chainId, token) {
|
|
|
1005
1618
|
function hasEmptyWithdrawalSnapshot(raw2, chainId, token) {
|
|
1006
1619
|
const snapshot = snapshotPortfolio(raw2);
|
|
1007
1620
|
if (!snapshot) return false;
|
|
1008
|
-
const
|
|
1009
|
-
if (
|
|
1621
|
+
const pending2 = snapshot.portfolio.pendingAsyncWithdrawals;
|
|
1622
|
+
if (pending2 !== void 0 && (!Array.isArray(pending2) || pending2.length > 0)) return false;
|
|
1010
1623
|
return chainBalancesMatch(snapshot.chains, chainId, token, (balance) => zero(balance.balance)) && positionsEmpty(snapshot.entries, chainId, token);
|
|
1011
1624
|
}
|
|
1012
1625
|
function hasIdleOnlyWithdrawalSnapshot(raw2, chainId, token, decimals, idle) {
|
|
1013
1626
|
const snapshot = snapshotPortfolio(raw2);
|
|
1014
1627
|
if (!snapshot) return false;
|
|
1015
|
-
const
|
|
1016
|
-
if (
|
|
1628
|
+
const pending2 = snapshot.portfolio.pendingAsyncWithdrawals;
|
|
1629
|
+
if (pending2 !== void 0 && (!Array.isArray(pending2) || pending2.some((value) => record(value)?.status !== "CLAIMED"))) return false;
|
|
1017
1630
|
return chainBalancesMatch(snapshot.chains, chainId, token, (balance) => {
|
|
1018
1631
|
const amount = units(balance.balance);
|
|
1019
1632
|
return amount !== void 0 && amount <= idle && (balance.decimals === void 0 || balance.decimals === decimals);
|
|
@@ -1021,7 +1634,8 @@ function hasIdleOnlyWithdrawalSnapshot(raw2, chainId, token, decimals, idle) {
|
|
|
1021
1634
|
}
|
|
1022
1635
|
|
|
1023
1636
|
// src/agents/zyfai/zyfai.deposit.ts
|
|
1024
|
-
var
|
|
1637
|
+
var import_viem6 = require("viem");
|
|
1638
|
+
init_errors();
|
|
1025
1639
|
|
|
1026
1640
|
// src/types/config.ts
|
|
1027
1641
|
var P_SUPPORTED_CHAINS = {
|
|
@@ -1075,16 +1689,16 @@ async function submitZyfaiDeposit({ sdk, state, chain: chain2, amount, asset, sm
|
|
|
1075
1689
|
const owner = state.walletAddress;
|
|
1076
1690
|
const provider = state.provider;
|
|
1077
1691
|
const token = SupportedAssets.find((value) => value.chainId === chain2.id && value.symbol === asset);
|
|
1078
|
-
if (!token || !(0,
|
|
1692
|
+
if (!token || !(0, import_viem6.isAddress)(owner) || !(0, import_viem6.isAddress)(smartWallet) || !/^\d+$/.test(amount) || BigInt(amount) <= 0n)
|
|
1079
1693
|
throw new OwneyError("AGENT_INVALID_RESPONSE", "Invalid Zyfai deposit transfer.", { chainId: chain2.id, asset }, "zyfai");
|
|
1080
1694
|
assertCurrent();
|
|
1081
1695
|
const prepared = await sdk.prepareEnterPosition({ userAddress: owner, chainId: chain2.id, amount, asset, strategy: "aggressive" });
|
|
1082
1696
|
assertCurrent();
|
|
1083
|
-
const expectedData = (0,
|
|
1697
|
+
const expectedData = (0, import_viem6.encodeFunctionData)({ abi: import_viem6.erc20Abi, functionName: "transfer", args: [smartWallet, BigInt(amount)] });
|
|
1084
1698
|
const transfer = prepared?.transfer;
|
|
1085
1699
|
if (!transfer || transfer.safeAddress?.toLowerCase() !== smartWallet.toLowerCase() || transfer.tokenAddress?.toLowerCase() !== token.address.toLowerCase() || transfer.to?.toLowerCase() !== token.address.toLowerCase() || transfer.data?.toLowerCase() !== expectedData.toLowerCase() || transfer.value !== "0")
|
|
1086
1700
|
throw new OwneyError("AGENT_INVALID_RESPONSE", "Zyfai prepared a different deposit transfer.", { chainId: chain2.id, asset }, "zyfai");
|
|
1087
|
-
const wallet = (0,
|
|
1701
|
+
const wallet = (0, import_viem6.createWalletClient)({ account: owner, chain: chain2, transport: (0, import_viem6.custom)({
|
|
1088
1702
|
request: async (args) => {
|
|
1089
1703
|
assertCurrent();
|
|
1090
1704
|
if (args.method === "eth_sendTransaction") {
|
|
@@ -1106,7 +1720,7 @@ async function submitZyfaiDeposit({ sdk, state, chain: chain2, amount, asset, sm
|
|
|
1106
1720
|
|
|
1107
1721
|
// src/agents/zyfai/zyfai.agent.ts
|
|
1108
1722
|
var import_sdk = require("@zyfai/sdk");
|
|
1109
|
-
var
|
|
1723
|
+
var import_viem9 = require("viem");
|
|
1110
1724
|
var import_chains = require("viem/chains");
|
|
1111
1725
|
|
|
1112
1726
|
// src/lib/debug.ts
|
|
@@ -1127,6 +1741,7 @@ function debugLog(scope, message, data) {
|
|
|
1127
1741
|
}
|
|
1128
1742
|
|
|
1129
1743
|
// src/lib/utils.ts
|
|
1744
|
+
init_errors();
|
|
1130
1745
|
var isValidChainId = (chainId) => {
|
|
1131
1746
|
if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
|
1132
1747
|
throw new OwneyError(
|
|
@@ -1162,8 +1777,8 @@ function matchesAsset(symbol2, asset) {
|
|
|
1162
1777
|
}
|
|
1163
1778
|
|
|
1164
1779
|
// src/agents/zyfai/zyfai.mapper.ts
|
|
1165
|
-
var
|
|
1166
|
-
var exactHexAmount = (raw2, decimals) => (0,
|
|
1780
|
+
var import_viem7 = require("viem");
|
|
1781
|
+
var exactHexAmount = (raw2, decimals) => (0, import_viem7.formatUnits)(BigInt(/^0x/i.test(raw2) ? raw2 : `0x${raw2}`), decimals);
|
|
1167
1782
|
var DECIMALS_BY_SYMBOL = {
|
|
1168
1783
|
usdc: 6,
|
|
1169
1784
|
weth: 18,
|
|
@@ -1202,7 +1817,7 @@ function resolveChainId(chain2) {
|
|
|
1202
1817
|
}
|
|
1203
1818
|
function mapPendingAllocations(raw2) {
|
|
1204
1819
|
if (!Array.isArray(raw2)) return void 0;
|
|
1205
|
-
const
|
|
1820
|
+
const pending2 = [];
|
|
1206
1821
|
for (const entry of raw2) {
|
|
1207
1822
|
if (typeof entry !== "object" || entry === null) continue;
|
|
1208
1823
|
const e = entry;
|
|
@@ -1216,7 +1831,7 @@ function mapPendingAllocations(raw2) {
|
|
|
1216
1831
|
} catch {
|
|
1217
1832
|
continue;
|
|
1218
1833
|
}
|
|
1219
|
-
|
|
1834
|
+
pending2.push({
|
|
1220
1835
|
chainId: e.chainId,
|
|
1221
1836
|
asset: e.tokenSymbol,
|
|
1222
1837
|
amount,
|
|
@@ -1224,7 +1839,7 @@ function mapPendingAllocations(raw2) {
|
|
|
1224
1839
|
...typeof e.updatedAt === "string" && e.updatedAt !== "" ? { since: e.updatedAt } : {}
|
|
1225
1840
|
});
|
|
1226
1841
|
}
|
|
1227
|
-
return
|
|
1842
|
+
return pending2.length > 0 ? pending2 : void 0;
|
|
1228
1843
|
}
|
|
1229
1844
|
function mapBalances(raw2, _chainId, smartWallet) {
|
|
1230
1845
|
const portfolio = raw2.portfolio;
|
|
@@ -1262,7 +1877,7 @@ function mapBalances(raw2, _chainId, smartWallet) {
|
|
|
1262
1877
|
// legacy `amount` fallback is hex. Runtime
|
|
1263
1878
|
// getBalances payloads often carry one (e.g. 18 for WETH) — prefer that
|
|
1264
1879
|
// when present, otherwise fall back to the per-symbol lookup.
|
|
1265
|
-
amount: p.underlyingAmountWithFee ?? p.underlyingAmount ? (0,
|
|
1880
|
+
amount: p.underlyingAmountWithFee ?? p.underlyingAmount ? (0, import_viem7.formatUnits)(
|
|
1266
1881
|
BigInt(p.underlyingAmountWithFee ?? p.underlyingAmount ?? "0"),
|
|
1267
1882
|
tokenDecimals(
|
|
1268
1883
|
p.token_symbol,
|
|
@@ -1664,6 +2279,9 @@ function decodeHistoryCursor(token) {
|
|
|
1664
2279
|
return parsed;
|
|
1665
2280
|
}
|
|
1666
2281
|
|
|
2282
|
+
// src/agents/zyfai/zyfai.agent.ts
|
|
2283
|
+
init_errors();
|
|
2284
|
+
|
|
1667
2285
|
// src/agents/zyfai/zyfai.auth-cache.ts
|
|
1668
2286
|
var KEY_PREFIX = "owney.zyfai.session";
|
|
1669
2287
|
var storage = () => {
|
|
@@ -1926,7 +2544,8 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
|
|
|
1926
2544
|
}
|
|
1927
2545
|
|
|
1928
2546
|
// src/lib/paid-rpc.ts
|
|
1929
|
-
var
|
|
2547
|
+
var import_viem8 = require("viem");
|
|
2548
|
+
init_errors();
|
|
1930
2549
|
var PAID_RPC_RETRY_COUNT = 3;
|
|
1931
2550
|
var PAID_RPC_RETRY_DELAY_MS = 1e3;
|
|
1932
2551
|
function configuredRpcProxyBaseUrl(baseUrl) {
|
|
@@ -1962,9 +2581,9 @@ function createPaidRpcClient(chain2, rpcUrls) {
|
|
|
1962
2581
|
rpcUrls,
|
|
1963
2582
|
chain2.id
|
|
1964
2583
|
);
|
|
1965
|
-
return (0,
|
|
2584
|
+
return (0, import_viem8.createPublicClient)({
|
|
1966
2585
|
chain: chain2,
|
|
1967
|
-
transport: (0,
|
|
2586
|
+
transport: (0, import_viem8.http)(url, {
|
|
1968
2587
|
retryCount: PAID_RPC_RETRY_COUNT,
|
|
1969
2588
|
retryDelay: PAID_RPC_RETRY_DELAY_MS
|
|
1970
2589
|
})
|
|
@@ -2061,7 +2680,7 @@ async function withPaidRpcDiagnostics(operation, chainId, rpcMethod, agentId) {
|
|
|
2061
2680
|
}
|
|
2062
2681
|
|
|
2063
2682
|
// src/agents/zyfai/zyfai.agent.ts
|
|
2064
|
-
var ERC7579_IS_MODULE_INSTALLED_ABI = (0,
|
|
2683
|
+
var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem9.parseAbi)([
|
|
2065
2684
|
"function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)"
|
|
2066
2685
|
]);
|
|
2067
2686
|
var WETH_ADDRESS_BY_CHAIN = {
|
|
@@ -2079,7 +2698,7 @@ function belowMinimumCeiling(rejection, token, decimals) {
|
|
|
2079
2698
|
const ceiling = (display) => {
|
|
2080
2699
|
const places = display.split(".")[1]?.length ?? 0;
|
|
2081
2700
|
if (places >= decimals) return void 0;
|
|
2082
|
-
return (0,
|
|
2701
|
+
return (0, import_viem9.parseUnits)(display, decimals) + 5n * 10n ** BigInt(decimals - places - 1);
|
|
2083
2702
|
};
|
|
2084
2703
|
const idle = ceiling(rejection.idle);
|
|
2085
2704
|
const minimum = ceiling(rejection.minimum);
|
|
@@ -2131,6 +2750,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2131
2750
|
connectedAddress = null;
|
|
2132
2751
|
connectedChainId = null;
|
|
2133
2752
|
smartWalletCache = /* @__PURE__ */ new Map();
|
|
2753
|
+
smartWalletReads = /* @__PURE__ */ new Map();
|
|
2134
2754
|
/**
|
|
2135
2755
|
* `${eoa}:${chainId}` keys we have already tried createSessionKey for. Guards
|
|
2136
2756
|
* against re-running it on every activation/deposit when Zyfai's
|
|
@@ -2148,6 +2768,9 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2148
2768
|
fundingHistoryCache = /* @__PURE__ */ new Map();
|
|
2149
2769
|
earningsReads = /* @__PURE__ */ new Map();
|
|
2150
2770
|
earningsRefreshes = /* @__PURE__ */ new Map();
|
|
2771
|
+
// Recalculation is wallet-wide across assets/chains. Bound attempts locally,
|
|
2772
|
+
// including failures; a negative result must not trigger a POST every poll.
|
|
2773
|
+
earningsCalculationAttempts = /* @__PURE__ */ new Map();
|
|
2151
2774
|
earningsSnapshot = null;
|
|
2152
2775
|
earningsGeneration = 0;
|
|
2153
2776
|
balanceSnapshots = /* @__PURE__ */ new WeakMap();
|
|
@@ -2239,7 +2862,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2239
2862
|
}, asset.address, entry.action === "Withdraw" ? "withdraw" : "deposit");
|
|
2240
2863
|
if (evidence.transfer === "confirmed" && evidence.confirmedAmount) {
|
|
2241
2864
|
Object.assign(tx, {
|
|
2242
|
-
amount: (0,
|
|
2865
|
+
amount: (0, import_viem9.formatUnits)(BigInt(evidence.confirmedAmount), asset.decimals),
|
|
2243
2866
|
amountRaw: evidence.confirmedAmount,
|
|
2244
2867
|
blockNumber: evidence.blockNumber,
|
|
2245
2868
|
logIndexes: evidence.logIndexes,
|
|
@@ -2323,9 +2946,11 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2323
2946
|
this.sdkHasConnected = true;
|
|
2324
2947
|
const executionSdk = this.sdk;
|
|
2325
2948
|
const generation = ++this.connectionGeneration;
|
|
2949
|
+
this.smartWalletCache.clear();
|
|
2950
|
+
this.smartWalletReads.clear();
|
|
2326
2951
|
this.connectedAddress = null;
|
|
2327
2952
|
this.connectedChainId = null;
|
|
2328
|
-
const
|
|
2953
|
+
const pending2 = (async () => {
|
|
2329
2954
|
const address = await this.connectAccountWithRetry(
|
|
2330
2955
|
state.provider,
|
|
2331
2956
|
validChainId,
|
|
@@ -2336,12 +2961,12 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2336
2961
|
this.connectedAddress = address;
|
|
2337
2962
|
this.connectedChainId = validChainId;
|
|
2338
2963
|
})();
|
|
2339
|
-
this.connectAuthPromise =
|
|
2964
|
+
this.connectAuthPromise = pending2;
|
|
2340
2965
|
this.connectAuthScope = scope;
|
|
2341
2966
|
try {
|
|
2342
|
-
await
|
|
2967
|
+
await pending2;
|
|
2343
2968
|
} finally {
|
|
2344
|
-
if (this.connectAuthPromise ===
|
|
2969
|
+
if (this.connectAuthPromise === pending2) {
|
|
2345
2970
|
this.connectAuthPromise = null;
|
|
2346
2971
|
this.connectAuthScope = null;
|
|
2347
2972
|
}
|
|
@@ -2434,18 +3059,29 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2434
3059
|
await this.connectAuth(state, chainId);
|
|
2435
3060
|
const validChainId = isValidChainId(chainId);
|
|
2436
3061
|
const ownerAddress = this.getAddress();
|
|
2437
|
-
const
|
|
2438
|
-
let smartWallet = this.smartWalletCache.get(cacheKey);
|
|
2439
|
-
if (!smartWallet) {
|
|
2440
|
-
const { address } = await this.sdk.getSmartWalletAddress(
|
|
2441
|
-
ownerAddress,
|
|
2442
|
-
validChainId
|
|
2443
|
-
);
|
|
2444
|
-
smartWallet = address;
|
|
2445
|
-
this.smartWalletCache.set(cacheKey, smartWallet);
|
|
2446
|
-
}
|
|
3062
|
+
const smartWallet = await this.readSmartWallet(ownerAddress, validChainId);
|
|
2447
3063
|
return { smartWallet, chainId: validChainId };
|
|
2448
3064
|
}
|
|
3065
|
+
/** Read-only resolution shared with recovery; never enters authentication. */
|
|
3066
|
+
readSmartWallet(owner, chainId) {
|
|
3067
|
+
const key2 = `${owner.toLowerCase()}_${chainId}`;
|
|
3068
|
+
const cached = this.smartWalletCache.get(key2);
|
|
3069
|
+
if (cached) return Promise.resolve(cached);
|
|
3070
|
+
const existing = this.smartWalletReads.get(key2);
|
|
3071
|
+
if (existing) return existing;
|
|
3072
|
+
const generation = this.connectionGeneration;
|
|
3073
|
+
const executionSdk = this.sdk;
|
|
3074
|
+
const pending2 = Promise.resolve().then(() => executionSdk.getSmartWalletAddress(owner, chainId)).then(({ address }) => {
|
|
3075
|
+
if (generation !== this.connectionGeneration || executionSdk !== this.sdk)
|
|
3076
|
+
throw new OwneyError("NOT_CONNECTED", "Wallet changed while resolving Zyfai.", void 0, this.id);
|
|
3077
|
+
this.smartWalletCache.set(key2, address);
|
|
3078
|
+
return address;
|
|
3079
|
+
}).finally(() => {
|
|
3080
|
+
if (this.smartWalletReads.get(key2) === pending2) this.smartWalletReads.delete(key2);
|
|
3081
|
+
});
|
|
3082
|
+
this.smartWalletReads.set(key2, pending2);
|
|
3083
|
+
return pending2;
|
|
3084
|
+
}
|
|
2449
3085
|
// --- IAgent: Connection lifecycle ---
|
|
2450
3086
|
async disconnect() {
|
|
2451
3087
|
const executionSdk = this.sdk;
|
|
@@ -2453,6 +3089,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2453
3089
|
this.earningsGeneration++;
|
|
2454
3090
|
this.earningsReads.clear();
|
|
2455
3091
|
this.earningsRefreshes.clear();
|
|
3092
|
+
this.earningsCalculationAttempts.clear();
|
|
2456
3093
|
this.earningsSnapshot = null;
|
|
2457
3094
|
if (this.connectedAddress && this.connectedChainId !== null) {
|
|
2458
3095
|
clearSession(this.connectedAddress, this.connectedChainId);
|
|
@@ -2462,6 +3099,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2462
3099
|
this.connectAuthPromise = null;
|
|
2463
3100
|
this.connectAuthScope = null;
|
|
2464
3101
|
this.smartWalletCache.clear();
|
|
3102
|
+
this.smartWalletReads.clear();
|
|
2465
3103
|
this.sdk = this.createSdk();
|
|
2466
3104
|
this.sdkHasConnected = false;
|
|
2467
3105
|
await executionSdk.disconnectAccount();
|
|
@@ -3068,7 +3706,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3068
3706
|
this.sdk.getPortfolio(owner).catch(() => void 0)
|
|
3069
3707
|
]);
|
|
3070
3708
|
assertScope();
|
|
3071
|
-
if (!(0,
|
|
3709
|
+
if (!(0, import_viem9.isAddress)(wallet.address) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase())
|
|
3072
3710
|
throw new OwneyError(
|
|
3073
3711
|
"AGENT_AUTH_FAILED",
|
|
3074
3712
|
"Could not verify Zyfai's withdrawal wallet.",
|
|
@@ -3082,7 +3720,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3082
3720
|
if (!empty && ceiling === void 0) return;
|
|
3083
3721
|
const idle = await this.getPublicClient(chainId).readContract({
|
|
3084
3722
|
address: asset.address,
|
|
3085
|
-
abi:
|
|
3723
|
+
abi: import_viem9.erc20Abi,
|
|
3086
3724
|
functionName: "balanceOf",
|
|
3087
3725
|
args: [wallet.address]
|
|
3088
3726
|
}).catch(() => void 0);
|
|
@@ -3307,7 +3945,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3307
3945
|
}
|
|
3308
3946
|
// --- IAgent: Portfolio reads ---
|
|
3309
3947
|
async getFundingWallet(state, chainId) {
|
|
3310
|
-
return
|
|
3948
|
+
return this.readSmartWallet(state.walletAddress, isValidChainId(chainId));
|
|
3311
3949
|
}
|
|
3312
3950
|
/** A positive deployed Safe balance is a conservative planning floor. Zero
|
|
3313
3951
|
* requires both the mapped Safe's exact idle balance and a fresh complete
|
|
@@ -3340,13 +3978,13 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3340
3978
|
this.sdk.getSmartWalletByEOA(owner)
|
|
3341
3979
|
]);
|
|
3342
3980
|
assertScope();
|
|
3343
|
-
if (!(0,
|
|
3981
|
+
if (!(0, import_viem9.isAddress)(wallet.address) || wallet.isDeployed !== false && (wallet.isDeployed !== true || wallet.isOwner !== true) || !registered.smartWallet || registered.smartWallet.toLowerCase() !== wallet.address.toLowerCase()) throw unavailable();
|
|
3344
3982
|
const client = this.getPublicClient(validChainId);
|
|
3345
3983
|
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
3346
3984
|
assertScope();
|
|
3347
3985
|
const idle = await client.readContract({
|
|
3348
3986
|
address: asset.address,
|
|
3349
|
-
abi:
|
|
3987
|
+
abi: import_viem9.erc20Abi,
|
|
3350
3988
|
functionName: "balanceOf",
|
|
3351
3989
|
args: [wallet.address],
|
|
3352
3990
|
blockNumber
|
|
@@ -3403,7 +4041,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3403
4041
|
if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
|
|
3404
4042
|
const idle = await client.readContract({
|
|
3405
4043
|
address: asset.address,
|
|
3406
|
-
abi:
|
|
4044
|
+
abi: import_viem9.erc20Abi,
|
|
3407
4045
|
functionName: "balanceOf",
|
|
3408
4046
|
args: [balance.smartWallet],
|
|
3409
4047
|
blockNumber
|
|
@@ -3422,17 +4060,22 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3422
4060
|
const existing = this.earningsReads.get(key2);
|
|
3423
4061
|
if (existing) return existing;
|
|
3424
4062
|
const generation = this.earningsGeneration;
|
|
3425
|
-
const
|
|
3426
|
-
|
|
4063
|
+
const executionSdk = this.sdk;
|
|
4064
|
+
const pending2 = Promise.resolve().then(() => {
|
|
4065
|
+
if (generation !== this.earningsGeneration || executionSdk !== this.sdk)
|
|
4066
|
+
throw new OwneyError("NOT_CONNECTED", "Wallet changed while reading Zyfai earnings.", void 0, this.id);
|
|
4067
|
+
return executionSdk.getOnchainEarnings(smartWallet);
|
|
4068
|
+
}).then((raw2) => {
|
|
4069
|
+
if (generation === this.earningsGeneration && executionSdk === this.sdk) {
|
|
3427
4070
|
this.earningsSnapshot = { key: key2, raw: raw2, at: Date.now() };
|
|
3428
4071
|
}
|
|
3429
4072
|
return raw2;
|
|
3430
4073
|
}).finally(() => {
|
|
3431
|
-
if (this.earningsReads.get(key2) ===
|
|
4074
|
+
if (this.earningsReads.get(key2) === pending2)
|
|
3432
4075
|
this.earningsReads.delete(key2);
|
|
3433
4076
|
});
|
|
3434
|
-
this.earningsReads.set(key2,
|
|
3435
|
-
return
|
|
4077
|
+
this.earningsReads.set(key2, pending2);
|
|
4078
|
+
return pending2;
|
|
3436
4079
|
}
|
|
3437
4080
|
async getEarnings(state, chainId) {
|
|
3438
4081
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
@@ -3443,27 +4086,44 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3443
4086
|
return mapEarnings(raw2, smartWallet);
|
|
3444
4087
|
}
|
|
3445
4088
|
async refreshEarnings(state, chainId) {
|
|
4089
|
+
const generation = this.earningsGeneration;
|
|
4090
|
+
await this.connectAuth(state, chainId);
|
|
4091
|
+
const executionSdk = this.sdk;
|
|
4092
|
+
const connectionGeneration = this.connectionGeneration;
|
|
4093
|
+
const assertCurrent = () => {
|
|
4094
|
+
if (generation !== this.earningsGeneration || connectionGeneration !== this.connectionGeneration || executionSdk !== this.sdk)
|
|
4095
|
+
throw new OwneyError("NOT_CONNECTED", "Wallet changed while refreshing Zyfai earnings.", void 0, this.id);
|
|
4096
|
+
};
|
|
4097
|
+
assertCurrent();
|
|
3446
4098
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
4099
|
+
assertCurrent();
|
|
3447
4100
|
const key2 = this.earningsKey(state, chainId, smartWallet);
|
|
3448
4101
|
const existing = this.earningsRefreshes.get(key2);
|
|
3449
4102
|
if (existing) return existing;
|
|
3450
|
-
const
|
|
3451
|
-
const pending = (async () => {
|
|
4103
|
+
const pending2 = (async () => {
|
|
3452
4104
|
const recent = this.earningsSnapshot;
|
|
3453
4105
|
const current = recent?.key === key2 && Date.now() - recent.at < 5e3 ? recent.raw : await this.readEarnings(key2, smartWallet);
|
|
3454
4106
|
const lastCheck = current.data.lastCheckTimestamp ? Date.parse(current.data.lastCheckTimestamp) : Number.NaN;
|
|
3455
|
-
const
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
4107
|
+
const mapped = mapEarnings(current, smartWallet);
|
|
4108
|
+
assertCurrent();
|
|
4109
|
+
const now = Date.now();
|
|
4110
|
+
const isFresh = Number.isFinite(lastCheck) && lastCheck <= now && now - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
|
|
4111
|
+
const negative = mapped.lifetimeEarnings < 0 || mapped.tokens.some((token) => Number(token.amount) < 0);
|
|
4112
|
+
const calculationKey = JSON.stringify([state.walletAddress?.toLowerCase(), smartWallet.toLowerCase()]);
|
|
4113
|
+
const attemptedAt = this.earningsCalculationAttempts.get(calculationKey);
|
|
4114
|
+
const canCalculate = attemptedAt === void 0 || now - attemptedAt >= EARNINGS_REFRESH_COOLDOWN_MS;
|
|
4115
|
+
if (isFresh && !negative || !canCalculate) return mapped;
|
|
4116
|
+
this.earningsCalculationAttempts.set(calculationKey, now);
|
|
4117
|
+
const earnings = await executionSdk.calculateOnchainEarnings(smartWallet);
|
|
4118
|
+
assertCurrent();
|
|
4119
|
+
this.earningsSnapshot = { key: key2, raw: earnings, at: Date.now() };
|
|
3460
4120
|
return mapEarnings(earnings, smartWallet);
|
|
3461
4121
|
})().finally(() => {
|
|
3462
|
-
if (this.earningsRefreshes.get(key2) ===
|
|
4122
|
+
if (this.earningsRefreshes.get(key2) === pending2)
|
|
3463
4123
|
this.earningsRefreshes.delete(key2);
|
|
3464
4124
|
});
|
|
3465
|
-
this.earningsRefreshes.set(key2,
|
|
3466
|
-
return
|
|
4125
|
+
this.earningsRefreshes.set(key2, pending2);
|
|
4126
|
+
return pending2;
|
|
3467
4127
|
}
|
|
3468
4128
|
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
3469
4129
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
@@ -3608,12 +4268,13 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
3608
4268
|
};
|
|
3609
4269
|
|
|
3610
4270
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
3611
|
-
var
|
|
4271
|
+
var import_viem16 = require("viem");
|
|
3612
4272
|
var import_chains4 = require("viem/chains");
|
|
4273
|
+
init_errors();
|
|
3613
4274
|
|
|
3614
4275
|
// src/agents/yieldseeker/yieldseeker.auth.ts
|
|
3615
4276
|
var import_siwe = require("siwe");
|
|
3616
|
-
var
|
|
4277
|
+
var import_viem10 = require("viem");
|
|
3617
4278
|
var import_chains2 = require("viem/chains");
|
|
3618
4279
|
|
|
3619
4280
|
// src/agents/yieldseeker/yieldseeker.auth-cache.ts
|
|
@@ -3728,7 +4389,7 @@ function createYieldseekerSiweMessage(address, chainId, dependencies = {}) {
|
|
|
3728
4389
|
return new import_siwe.SiweMessage({
|
|
3729
4390
|
scheme: url.protocol.slice(0, -1),
|
|
3730
4391
|
domain: url.host,
|
|
3731
|
-
address: (0,
|
|
4392
|
+
address: (0, import_viem10.getAddress)(address),
|
|
3732
4393
|
uri: url.origin,
|
|
3733
4394
|
version: "1",
|
|
3734
4395
|
chainId,
|
|
@@ -3828,15 +4489,15 @@ var YieldseekerAuth = class {
|
|
|
3828
4489
|
clearYieldseekerSession(state.walletAddress, chainId);
|
|
3829
4490
|
}
|
|
3830
4491
|
async sign(state, chainId) {
|
|
3831
|
-
const account = (0,
|
|
3832
|
-
const publicClient = (0,
|
|
4492
|
+
const account = (0, import_viem10.getAddress)(state.walletAddress);
|
|
4493
|
+
const publicClient = (0, import_viem10.createPublicClient)({
|
|
3833
4494
|
chain: import_chains2.base,
|
|
3834
|
-
transport: (0,
|
|
4495
|
+
transport: (0, import_viem10.custom)(state.provider)
|
|
3835
4496
|
});
|
|
3836
|
-
const walletClient = (0,
|
|
4497
|
+
const walletClient = (0, import_viem10.createWalletClient)({
|
|
3837
4498
|
account,
|
|
3838
4499
|
chain: import_chains2.base,
|
|
3839
|
-
transport: (0,
|
|
4500
|
+
transport: (0, import_viem10.custom)(state.provider)
|
|
3840
4501
|
});
|
|
3841
4502
|
await ensureWalletOnChain(
|
|
3842
4503
|
publicClient,
|
|
@@ -4003,7 +4664,8 @@ var YieldseekerApiClient = class {
|
|
|
4003
4664
|
};
|
|
4004
4665
|
|
|
4005
4666
|
// src/agents/yieldseeker/yieldseeker.mapper.ts
|
|
4006
|
-
var
|
|
4667
|
+
var import_viem11 = require("viem");
|
|
4668
|
+
init_errors();
|
|
4007
4669
|
|
|
4008
4670
|
// src/lib/helpers/snapshot-apy.ts
|
|
4009
4671
|
var DAY_MS = 864e5;
|
|
@@ -4070,7 +4732,7 @@ function raw(value, endpoint) {
|
|
|
4070
4732
|
return BigInt(value);
|
|
4071
4733
|
}
|
|
4072
4734
|
function decimal(value, decimals, endpoint) {
|
|
4073
|
-
return (0,
|
|
4735
|
+
return (0, import_viem11.formatUnits)(raw(value, endpoint), decimals);
|
|
4074
4736
|
}
|
|
4075
4737
|
function balanceRaw(value, endpoint) {
|
|
4076
4738
|
const amount = raw(value, endpoint);
|
|
@@ -4078,10 +4740,10 @@ function balanceRaw(value, endpoint) {
|
|
|
4078
4740
|
return amount;
|
|
4079
4741
|
}
|
|
4080
4742
|
function balanceDecimal(value, decimals, endpoint) {
|
|
4081
|
-
return (0,
|
|
4743
|
+
return (0, import_viem11.formatUnits)(balanceRaw(value, endpoint), decimals);
|
|
4082
4744
|
}
|
|
4083
4745
|
function usd(rawAmount2, decimals, price) {
|
|
4084
|
-
return Number((0,
|
|
4746
|
+
return Number((0, import_viem11.formatUnits)(rawAmount2, decimals)) * price;
|
|
4085
4747
|
}
|
|
4086
4748
|
function percent(value) {
|
|
4087
4749
|
const result = Number(value);
|
|
@@ -4107,7 +4769,7 @@ function assetAddressValue(record2, address) {
|
|
|
4107
4769
|
}
|
|
4108
4770
|
function position(value, asset, baseAssetDecimals) {
|
|
4109
4771
|
const option = value?.vaultOption;
|
|
4110
|
-
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0,
|
|
4772
|
+
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0, import_viem11.isAddress)(option.address)) {
|
|
4111
4773
|
return invalid("vault positions", "missing vault metadata");
|
|
4112
4774
|
}
|
|
4113
4775
|
return {
|
|
@@ -4200,7 +4862,7 @@ function mapYieldseekerEarnings(contexts) {
|
|
|
4200
4862
|
chain: "BASE",
|
|
4201
4863
|
chainId: 8453,
|
|
4202
4864
|
asset: context.asset,
|
|
4203
|
-
amount: (0,
|
|
4865
|
+
amount: (0, import_viem11.formatUnits)(amount, context.snapshot.baseAssetDecimals)
|
|
4204
4866
|
});
|
|
4205
4867
|
lifetimeEarnings += usd(
|
|
4206
4868
|
amount,
|
|
@@ -4356,7 +5018,7 @@ function allocationLegs(value, context, requireAmount) {
|
|
|
4356
5018
|
const symbol2 = typeof leg.assetSymbol === "string" ? leg.assetSymbol.toUpperCase() : "";
|
|
4357
5019
|
if ((requireAmount || symbol2) && symbol2 !== context.asset && !(context.asset === "WETH" && symbol2 === "ETH"))
|
|
4358
5020
|
return void 0;
|
|
4359
|
-
if (typeof leg.vaultAddress !== "string" || !(0,
|
|
5021
|
+
if (typeof leg.vaultAddress !== "string" || !(0, import_viem11.isAddress)(leg.vaultAddress)) return void 0;
|
|
4360
5022
|
const rawAmount2 = typeof leg.rawAmount === "string" && /^\d+$/.test(leg.rawAmount) ? BigInt(leg.rawAmount) : typeof leg.rawAmount === "number" && Number.isSafeInteger(leg.rawAmount) ? BigInt(leg.rawAmount) : void 0;
|
|
4361
5023
|
if (requireAmount && (rawAmount2 === void 0 || rawAmount2 <= 0n)) return void 0;
|
|
4362
5024
|
const vault = leg.vaultAddress.toLowerCase();
|
|
@@ -4383,7 +5045,7 @@ function allocationEntry(action, context) {
|
|
|
4383
5045
|
protocol: leg.protocol,
|
|
4384
5046
|
pool: leg.pool,
|
|
4385
5047
|
tokenSymbol: context.asset,
|
|
4386
|
-
amount: (0,
|
|
5048
|
+
amount: (0, import_viem11.formatUnits)(leg.rawAmount, decimals)
|
|
4387
5049
|
}));
|
|
4388
5050
|
const amountRaw = deposits.reduce((total, leg) => total + leg.rawAmount, 0n);
|
|
4389
5051
|
const rebalance = withdrawals.length > 0;
|
|
@@ -4405,7 +5067,7 @@ function allocationEntry(action, context) {
|
|
|
4405
5067
|
toProtocol: leg.protocol,
|
|
4406
5068
|
...leg.pool ? { toPool: leg.pool } : {},
|
|
4407
5069
|
tokenSymbol: context.asset,
|
|
4408
|
-
amount: (0,
|
|
5070
|
+
amount: (0, import_viem11.formatUnits)(leg.rawAmount, decimals),
|
|
4409
5071
|
status: "success"
|
|
4410
5072
|
})) : [],
|
|
4411
5073
|
transactions: [{
|
|
@@ -4415,7 +5077,7 @@ function allocationEntry(action, context) {
|
|
|
4415
5077
|
tokenSymbol: context.asset,
|
|
4416
5078
|
agentWallet: context.wallet.walletAddress,
|
|
4417
5079
|
amountRaw: String(amountRaw),
|
|
4418
|
-
amount: (0,
|
|
5080
|
+
amount: (0, import_viem11.formatUnits)(amountRaw, decimals)
|
|
4419
5081
|
}]
|
|
4420
5082
|
};
|
|
4421
5083
|
}
|
|
@@ -4547,7 +5209,7 @@ function mapYieldseekerHistory(contexts, options) {
|
|
|
4547
5209
|
const known = new Set(target.logIndexes ?? []);
|
|
4548
5210
|
if (tx.logIndexes?.some((index) => !known.has(index))) {
|
|
4549
5211
|
target.amountRaw = String(BigInt(target.amountRaw ?? "0") + BigInt(tx.amountRaw));
|
|
4550
|
-
target.amount = (0,
|
|
5212
|
+
target.amount = (0, import_viem11.formatUnits)(
|
|
4551
5213
|
BigInt(target.amountRaw),
|
|
4552
5214
|
YIELDSEEKER_ASSET_METADATA[target.tokenSymbol].decimals
|
|
4553
5215
|
);
|
|
@@ -4628,7 +5290,7 @@ function mapYieldseekerAgentApy(options, days) {
|
|
|
4628
5290
|
}
|
|
4629
5291
|
|
|
4630
5292
|
// src/lib/remaining-vault-balance.ts
|
|
4631
|
-
var
|
|
5293
|
+
var import_viem12 = require("viem");
|
|
4632
5294
|
async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber) {
|
|
4633
5295
|
const addresses = [...new Set(vaults.map((value) => value.toLowerCase()))];
|
|
4634
5296
|
if (addresses.length > 64) return void 0;
|
|
@@ -4639,8 +5301,8 @@ async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber)
|
|
|
4639
5301
|
blockNumber,
|
|
4640
5302
|
allowFailure: true,
|
|
4641
5303
|
contracts: batch.map((address) => ({
|
|
4642
|
-
address: (0,
|
|
4643
|
-
abi:
|
|
5304
|
+
address: (0, import_viem12.getAddress)(address),
|
|
5305
|
+
abi: import_viem12.erc20Abi,
|
|
4644
5306
|
functionName: "balanceOf",
|
|
4645
5307
|
args: [wallet]
|
|
4646
5308
|
}))
|
|
@@ -4650,15 +5312,15 @@ async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber)
|
|
|
4650
5312
|
for (let index = 0; index < batch.length; index++) {
|
|
4651
5313
|
const result = balances[index];
|
|
4652
5314
|
if (result?.status !== "success" || typeof result.result !== "bigint" || result.result < 0n) return void 0;
|
|
4653
|
-
if (result.result > 0n) funded.push({ address: (0,
|
|
5315
|
+
if (result.result > 0n) funded.push({ address: (0, import_viem12.getAddress)(batch[index]), shares: result.result });
|
|
4654
5316
|
}
|
|
4655
5317
|
if (!funded.length) return 0n;
|
|
4656
5318
|
const valuations = await client.multicall({
|
|
4657
5319
|
blockNumber,
|
|
4658
5320
|
allowFailure: true,
|
|
4659
5321
|
contracts: funded.flatMap(({ address, shares }) => [
|
|
4660
|
-
{ address, abi:
|
|
4661
|
-
{ address, abi:
|
|
5322
|
+
{ address, abi: import_viem12.erc4626Abi, functionName: "asset" },
|
|
5323
|
+
{ address, abi: import_viem12.erc4626Abi, functionName: "convertToAssets", args: [shares] }
|
|
4662
5324
|
])
|
|
4663
5325
|
});
|
|
4664
5326
|
if (valuations.length !== funded.length * 2) return void 0;
|
|
@@ -4674,12 +5336,12 @@ async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber)
|
|
|
4674
5336
|
}
|
|
4675
5337
|
|
|
4676
5338
|
// src/agents/yieldseeker/yieldseeker.wallet-version.ts
|
|
4677
|
-
var
|
|
5339
|
+
var import_viem13 = require("viem");
|
|
4678
5340
|
var YIELDSEEKER_FACTORY = "0x9c7410a0faCAC60850C46eE5b58B518daec95130";
|
|
4679
5341
|
var YIELDSEEKER_V1_IMPLEMENTATION = "0x32403455357589523435dB18b414057D7cE05051";
|
|
4680
5342
|
var YIELDSEEKER_V2_IMPLEMENTATION = "0x613Db9c924ADB7A7A90c11b02Cce20c913E3Fe50";
|
|
4681
5343
|
var ERC1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
|
|
4682
|
-
var walletAbi = (0,
|
|
5344
|
+
var walletAbi = (0, import_viem13.parseAbi)([
|
|
4683
5345
|
"function owner() view returns (address)",
|
|
4684
5346
|
"function ownerAgentIndex() view returns (uint256)",
|
|
4685
5347
|
"function baseAsset() view returns (address)",
|
|
@@ -4687,7 +5349,7 @@ var walletAbi = (0, import_viem12.parseAbi)([
|
|
|
4687
5349
|
"function upgradeToLatest()",
|
|
4688
5350
|
"event Upgraded(address indexed implementation)"
|
|
4689
5351
|
]);
|
|
4690
|
-
var factoryAbi = (0,
|
|
5352
|
+
var factoryAbi = (0, import_viem13.parseAbi)([
|
|
4691
5353
|
"function userWallets(address owner, uint256 index) view returns (address)",
|
|
4692
5354
|
"function agentWalletImplementation() view returns (address)"
|
|
4693
5355
|
]);
|
|
@@ -4695,9 +5357,9 @@ function yieldseekerOwnerPath(code) {
|
|
|
4695
5357
|
return !code || code === "0x" || /^0xef0100[0-9a-f]{40}$/i.test(code) ? "eoa" : "smart";
|
|
4696
5358
|
}
|
|
4697
5359
|
async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNumber) {
|
|
4698
|
-
const agentWallet = (0,
|
|
4699
|
-
const expectedOwner = (0,
|
|
4700
|
-
const expectedAsset = (0,
|
|
5360
|
+
const agentWallet = (0, import_viem13.getAddress)(wallet);
|
|
5361
|
+
const expectedOwner = (0, import_viem13.getAddress)(owner);
|
|
5362
|
+
const expectedAsset = (0, import_viem13.getAddress)(asset);
|
|
4701
5363
|
const [code, ownerCode, slot, actualOwner, index, actualAsset, actualFactory, latest] = await Promise.all([
|
|
4702
5364
|
client.getBytecode({ address: agentWallet, blockNumber }),
|
|
4703
5365
|
client.getBytecode({ address: expectedOwner, blockNumber }),
|
|
@@ -4711,7 +5373,7 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
|
|
|
4711
5373
|
if (!code || code === "0x" || !slot || /^0x0+$/.test(slot)) {
|
|
4712
5374
|
throw new Error("Yieldseeker wallet is not a deployed ERC1967 proxy");
|
|
4713
5375
|
}
|
|
4714
|
-
const implementation = (0,
|
|
5376
|
+
const implementation = (0, import_viem13.getAddress)(`0x${slot.slice(-40)}`);
|
|
4715
5377
|
const mapped = await client.readContract({
|
|
4716
5378
|
address: YIELDSEEKER_FACTORY,
|
|
4717
5379
|
abi: factoryAbi,
|
|
@@ -4719,8 +5381,8 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
|
|
|
4719
5381
|
args: [expectedOwner, index],
|
|
4720
5382
|
blockNumber
|
|
4721
5383
|
});
|
|
4722
|
-
const verified = (0,
|
|
4723
|
-
const version = !verified ? "unknown" : (0,
|
|
5384
|
+
const verified = (0, import_viem13.isAddressEqual)(actualOwner, expectedOwner) && (0, import_viem13.isAddressEqual)(actualAsset, expectedAsset) && (0, import_viem13.isAddressEqual)(actualFactory, YIELDSEEKER_FACTORY) && (0, import_viem13.isAddressEqual)(mapped, agentWallet);
|
|
5385
|
+
const version = !verified ? "unknown" : (0, import_viem13.isAddressEqual)(implementation, YIELDSEEKER_V2_IMPLEMENTATION) ? "v2" : (0, import_viem13.isAddressEqual)(implementation, YIELDSEEKER_V1_IMPLEMENTATION) ? "v1" : "unknown";
|
|
4724
5386
|
return {
|
|
4725
5387
|
agentWallet,
|
|
4726
5388
|
owner: actualOwner,
|
|
@@ -4729,16 +5391,17 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
|
|
|
4729
5391
|
implementation,
|
|
4730
5392
|
version,
|
|
4731
5393
|
verified,
|
|
4732
|
-
upgradeAvailable: version === "v1" && (0,
|
|
5394
|
+
upgradeAvailable: version === "v1" && (0, import_viem13.isAddressEqual)(latest, YIELDSEEKER_V2_IMPLEMENTATION)
|
|
4733
5395
|
};
|
|
4734
5396
|
}
|
|
4735
5397
|
var YIELDSEEKER_UPGRADE_ABI = walletAbi;
|
|
4736
5398
|
|
|
4737
5399
|
// src/agents/yieldseeker/yieldseeker.sponsored-withdraw.ts
|
|
4738
|
-
var
|
|
5400
|
+
var import_viem14 = require("viem");
|
|
4739
5401
|
var import_account_abstraction2 = require("viem/account-abstraction");
|
|
4740
5402
|
var import_accounts = require("viem/accounts");
|
|
4741
5403
|
var import_chains3 = require("viem/chains");
|
|
5404
|
+
init_errors();
|
|
4742
5405
|
var ENTRY_POINT_V06 = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
|
|
4743
5406
|
var USER_OP_FEE_HEADROOM = 2n;
|
|
4744
5407
|
var OBSERVATION_WINDOW_MS = 6e4;
|
|
@@ -4822,7 +5485,7 @@ function rpcDiagnostics(data) {
|
|
|
4822
5485
|
details.revertName = data.revertName;
|
|
4823
5486
|
if (typeof data?.aaCode === "string" && /^AA[0-9]{2}$/.test(data.aaCode)) details.aaCode = data.aaCode;
|
|
4824
5487
|
if (typeof data?.panicCode === "string" && /^0x[0-9a-fA-F]{1,2}$/.test(data.panicCode)) {
|
|
4825
|
-
const panicCode = (0,
|
|
5488
|
+
const panicCode = (0, import_viem14.toHex)(BigInt(data.panicCode));
|
|
4826
5489
|
if (["0x0", "0x1", "0x11", "0x12", "0x21", "0x22", "0x31", "0x32", "0x41", "0x51"].includes(panicCode))
|
|
4827
5490
|
details.panicCode = panicCode;
|
|
4828
5491
|
}
|
|
@@ -4863,9 +5526,9 @@ function savePending(onPending, evidence, beforeSubmission = false) {
|
|
|
4863
5526
|
);
|
|
4864
5527
|
}
|
|
4865
5528
|
}
|
|
4866
|
-
async function checkpoint(callback,
|
|
5529
|
+
async function checkpoint(callback, pending2) {
|
|
4867
5530
|
try {
|
|
4868
|
-
await callback?.(
|
|
5531
|
+
await callback?.(pending2);
|
|
4869
5532
|
} catch {
|
|
4870
5533
|
throw sponsorError(
|
|
4871
5534
|
"Withdrawal status cannot be saved before submission.",
|
|
@@ -5042,14 +5705,14 @@ async function submitEoa(input) {
|
|
|
5042
5705
|
throw sponsorError("Base did not return EIP-1559 gas fees.", true);
|
|
5043
5706
|
let operation = {
|
|
5044
5707
|
sender: input.agentWallet,
|
|
5045
|
-
nonce: (0,
|
|
5708
|
+
nonce: (0, import_viem14.toHex)(nonce),
|
|
5046
5709
|
initCode: "0x",
|
|
5047
5710
|
callData: input.callData,
|
|
5048
|
-
callGasLimit: (0,
|
|
5049
|
-
verificationGasLimit: (0,
|
|
5050
|
-
preVerificationGas: (0,
|
|
5051
|
-
maxFeePerGas: (0,
|
|
5052
|
-
maxPriorityFeePerGas: (0,
|
|
5711
|
+
callGasLimit: (0, import_viem14.toHex)(3e5),
|
|
5712
|
+
verificationGasLimit: (0, import_viem14.toHex)(3e5),
|
|
5713
|
+
preVerificationGas: (0, import_viem14.toHex)(6e4),
|
|
5714
|
+
maxFeePerGas: (0, import_viem14.toHex)(fees.maxFeePerGas * USER_OP_FEE_HEADROOM),
|
|
5715
|
+
maxPriorityFeePerGas: (0, import_viem14.toHex)(fees.maxPriorityFeePerGas),
|
|
5053
5716
|
paymasterAndData: "0x",
|
|
5054
5717
|
signature: "0x"
|
|
5055
5718
|
};
|
|
@@ -5057,7 +5720,7 @@ async function submitEoa(input) {
|
|
|
5057
5720
|
const stub = await rpc(
|
|
5058
5721
|
input.rpcUrl,
|
|
5059
5722
|
"pm_getPaymasterStubData",
|
|
5060
|
-
[operation, ENTRY_POINT_V06, (0,
|
|
5723
|
+
[operation, ENTRY_POINT_V06, (0, import_viem14.toHex)(8453), {}],
|
|
5061
5724
|
"prepare"
|
|
5062
5725
|
);
|
|
5063
5726
|
if (!stub.paymasterAndData?.startsWith("0x"))
|
|
@@ -5072,7 +5735,7 @@ async function submitEoa(input) {
|
|
|
5072
5735
|
const final = await rpc(
|
|
5073
5736
|
input.rpcUrl,
|
|
5074
5737
|
"pm_getPaymasterData",
|
|
5075
|
-
[operation, ENTRY_POINT_V06, (0,
|
|
5738
|
+
[operation, ENTRY_POINT_V06, (0, import_viem14.toHex)(8453), {}],
|
|
5076
5739
|
"prepare"
|
|
5077
5740
|
);
|
|
5078
5741
|
if (!final.paymasterAndData?.startsWith("0x"))
|
|
@@ -5082,10 +5745,10 @@ async function submitEoa(input) {
|
|
|
5082
5745
|
const userOpHash = operationHash(operation);
|
|
5083
5746
|
await assertOwnerSession(input.state, input.owner);
|
|
5084
5747
|
assertIntentFresh(input.expiresAt);
|
|
5085
|
-
const wallet = (0,
|
|
5748
|
+
const wallet = (0, import_viem14.createWalletClient)({
|
|
5086
5749
|
account: input.owner,
|
|
5087
5750
|
chain: import_chains3.base,
|
|
5088
|
-
transport: (0,
|
|
5751
|
+
transport: (0, import_viem14.custom)(input.state.provider)
|
|
5089
5752
|
});
|
|
5090
5753
|
input.assertCurrent?.();
|
|
5091
5754
|
const signature = await wallet.signMessage({ message: { raw: userOpHash } });
|
|
@@ -5166,13 +5829,13 @@ async function submitSmart(input) {
|
|
|
5166
5829
|
} catch {
|
|
5167
5830
|
throw sponsorError("This account cannot check paymaster support on Base.", true);
|
|
5168
5831
|
}
|
|
5169
|
-
const supportsPaymaster = capabilities?.[(0,
|
|
5832
|
+
const supportsPaymaster = capabilities?.[(0, import_viem14.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
|
|
5170
5833
|
if (supportsPaymaster !== true)
|
|
5171
5834
|
throw sponsorError("This account cannot use a paymaster on Base.", true);
|
|
5172
5835
|
await assertOwnerSession(input.state, input.owner);
|
|
5173
5836
|
let sent;
|
|
5174
5837
|
assertIntentFresh(input.expiresAt);
|
|
5175
|
-
const requestedId = (0,
|
|
5838
|
+
const requestedId = (0, import_viem14.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
5176
5839
|
savePending(input.onPending, { callsId: requestedId }, true);
|
|
5177
5840
|
input.assertCurrent?.();
|
|
5178
5841
|
await checkpoint(input.onBeforeSubmission, { callsId: requestedId });
|
|
@@ -5183,7 +5846,7 @@ async function submitSmart(input) {
|
|
|
5183
5846
|
params: [{
|
|
5184
5847
|
version: "2.0.0",
|
|
5185
5848
|
from: input.owner,
|
|
5186
|
-
chainId: (0,
|
|
5849
|
+
chainId: (0, import_viem14.toHex)(8453),
|
|
5187
5850
|
id: requestedId,
|
|
5188
5851
|
atomicRequired: false,
|
|
5189
5852
|
calls: [{ to: input.agentWallet, value: "0x0", data: input.callData }],
|
|
@@ -5258,7 +5921,7 @@ async function submitSmart(input) {
|
|
|
5258
5921
|
);
|
|
5259
5922
|
}
|
|
5260
5923
|
async function submitYieldseekerSponsoredWithdrawal(input) {
|
|
5261
|
-
const owner = (0,
|
|
5924
|
+
const owner = (0, import_viem14.getAddress)(input.state.walletAddress);
|
|
5262
5925
|
const { intent, rpcUrl } = await requestIntent({
|
|
5263
5926
|
apiKey: input.apiKey,
|
|
5264
5927
|
routingApiBaseUrl: input.routingApiBaseUrl,
|
|
@@ -5277,7 +5940,7 @@ async function submitYieldseekerSponsoredWithdrawal(input) {
|
|
|
5277
5940
|
return intent.ownerPath === "eoa" ? submitEoa(args) : submitSmart(args);
|
|
5278
5941
|
}
|
|
5279
5942
|
async function submitYieldseekerSponsoredUpgrade(input) {
|
|
5280
|
-
const owner = (0,
|
|
5943
|
+
const owner = (0, import_viem14.getAddress)(input.state.walletAddress);
|
|
5281
5944
|
const { intent, rpcUrl } = await requestIntent({
|
|
5282
5945
|
apiKey: input.apiKey,
|
|
5283
5946
|
routingApiBaseUrl: input.routingApiBaseUrl,
|
|
@@ -5297,6 +5960,57 @@ async function submitYieldseekerSponsoredUpgrade(input) {
|
|
|
5297
5960
|
return submitSmart({ ...input, owner, rpcUrl, expiresAt: intent.expiresAt });
|
|
5298
5961
|
}
|
|
5299
5962
|
|
|
5963
|
+
// src/agents/yieldseeker/yieldseeker.vault-reads.ts
|
|
5964
|
+
var import_viem15 = require("viem");
|
|
5965
|
+
var nativeAbi = (0, import_viem15.parseAbi)([
|
|
5966
|
+
"function underlying() view returns (address)",
|
|
5967
|
+
"function baseToken() view returns (address)",
|
|
5968
|
+
"function UNDERLYING_ASSET_ADDRESS() view returns (address)",
|
|
5969
|
+
"function balanceOfUnderlying(address owner) returns (uint256)"
|
|
5970
|
+
]);
|
|
5971
|
+
function nativeYieldseekerProtocol(option) {
|
|
5972
|
+
switch (option.provider?.toLowerCase()) {
|
|
5973
|
+
case "moonwell":
|
|
5974
|
+
return "moonwell";
|
|
5975
|
+
case "compound":
|
|
5976
|
+
return "compound";
|
|
5977
|
+
case "aave":
|
|
5978
|
+
return "aave";
|
|
5979
|
+
default:
|
|
5980
|
+
return void 0;
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5983
|
+
function yieldseekerUnderlyingCall(option) {
|
|
5984
|
+
const address = (0, import_viem15.getAddress)(option.address);
|
|
5985
|
+
switch (nativeYieldseekerProtocol(option)) {
|
|
5986
|
+
case "moonwell":
|
|
5987
|
+
return { address, abi: nativeAbi, functionName: "underlying" };
|
|
5988
|
+
case "compound":
|
|
5989
|
+
return { address, abi: nativeAbi, functionName: "baseToken" };
|
|
5990
|
+
case "aave":
|
|
5991
|
+
return { address, abi: nativeAbi, functionName: "UNDERLYING_ASSET_ADDRESS" };
|
|
5992
|
+
default:
|
|
5993
|
+
return { address, abi: import_viem15.erc4626Abi, functionName: "asset" };
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
async function readNativeYieldseekerAssets(client, option, wallet, balance, blockNumber) {
|
|
5997
|
+
if (nativeYieldseekerProtocol(option) !== "moonwell") {
|
|
5998
|
+
return balance;
|
|
5999
|
+
}
|
|
6000
|
+
try {
|
|
6001
|
+
const { data } = await client.call({
|
|
6002
|
+
to: (0, import_viem15.getAddress)(option.address),
|
|
6003
|
+
blockNumber,
|
|
6004
|
+
data: (0, import_viem15.encodeFunctionData)({ abi: nativeAbi, functionName: "balanceOfUnderlying", args: [(0, import_viem15.getAddress)(wallet)] })
|
|
6005
|
+
});
|
|
6006
|
+
if (!data) return void 0;
|
|
6007
|
+
const assets = (0, import_viem15.decodeFunctionResult)({ abi: nativeAbi, functionName: "balanceOfUnderlying", data });
|
|
6008
|
+
return assets > 0n ? assets : void 0;
|
|
6009
|
+
} catch {
|
|
6010
|
+
return void 0;
|
|
6011
|
+
}
|
|
6012
|
+
}
|
|
6013
|
+
|
|
5300
6014
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
5301
6015
|
var OWNEY_AGENT_NAME = "owney";
|
|
5302
6016
|
var OWNEY_AGENT_RULE_PRESET = "explorative";
|
|
@@ -5306,7 +6020,8 @@ var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
|
|
|
5306
6020
|
var YIELDSEEKER_VAULT_OPTIONS_CACHE_MS = 6e4;
|
|
5307
6021
|
var YIELDSEEKER_AGENT_LIST_CACHE_MS = 12e4;
|
|
5308
6022
|
var YIELDSEEKER_PORTFOLIO_CACHE_MS = 12e4;
|
|
5309
|
-
var
|
|
6023
|
+
var YIELDSEEKER_SETTLEMENT_BACKOFF_MS = [5e3, 1e4, 2e4, 4e4, 6e4];
|
|
6024
|
+
var YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS = 10 * 6e4;
|
|
5310
6025
|
var YIELDSEEKER_SETTLEMENT_ACTIVITY_CACHE_MS = 15e3;
|
|
5311
6026
|
var YIELDSEEKER_READ_FAILURE_COOLDOWN_MS = 6e4;
|
|
5312
6027
|
var YIELDSEEKER_SETTLEMENT_WINDOW_MS = 5 * 6e4;
|
|
@@ -5393,6 +6108,7 @@ var YieldseekerAgent = class {
|
|
|
5393
6108
|
receiptClient;
|
|
5394
6109
|
// A client preparation hint only; the routing API still checks live identity.
|
|
5395
6110
|
withdrawalVersionCache = /* @__PURE__ */ new Map();
|
|
6111
|
+
pendingWalletStatus = /* @__PURE__ */ new Map();
|
|
5396
6112
|
pendingUpgrades = /* @__PURE__ */ new Map();
|
|
5397
6113
|
transactionExecutor;
|
|
5398
6114
|
unwindReceiptWaiter;
|
|
@@ -5409,6 +6125,7 @@ var YieldseekerAgent = class {
|
|
|
5409
6125
|
liquidityVersions = /* @__PURE__ */ new Map();
|
|
5410
6126
|
snapshotFailures = /* @__PURE__ */ new Map();
|
|
5411
6127
|
standardReadFailures = /* @__PURE__ */ new Map();
|
|
6128
|
+
endpointReadFailures = /* @__PURE__ */ new Map();
|
|
5412
6129
|
reconcileUntil = /* @__PURE__ */ new Map();
|
|
5413
6130
|
allocationRefresh = /* @__PURE__ */ new Set();
|
|
5414
6131
|
activityRefreshUntil = /* @__PURE__ */ new Map();
|
|
@@ -5416,6 +6133,8 @@ var YieldseekerAgent = class {
|
|
|
5416
6133
|
// settlement; keep slow reconciliation after the fast window expires.
|
|
5417
6134
|
snapshotMovements = /* @__PURE__ */ new Map();
|
|
5418
6135
|
movementEpochs = /* @__PURE__ */ new Map();
|
|
6136
|
+
// Forced checks issued by the current movement's settlement schedule.
|
|
6137
|
+
settlementChecks = /* @__PURE__ */ new Map();
|
|
5419
6138
|
vaultOptions = /* @__PURE__ */ new Map();
|
|
5420
6139
|
pendingVaultOptions = /* @__PURE__ */ new Map();
|
|
5421
6140
|
constructor(owneyApiKey, options = {}) {
|
|
@@ -5439,19 +6158,31 @@ var YieldseekerAgent = class {
|
|
|
5439
6158
|
async getWalletStatus(state, chainId, asset, useCachedV2 = false) {
|
|
5440
6159
|
this.assertChain(chainId);
|
|
5441
6160
|
this.assertAsset(asset);
|
|
6161
|
+
const generation = this.readGeneration;
|
|
5442
6162
|
const context = await this.findAgent(state, chainId, asset);
|
|
6163
|
+
this.assertSession(generation, chainId, asset);
|
|
5443
6164
|
if (!context) return null;
|
|
5444
6165
|
const key2 = `${chainId}:${state.walletAddress.toLowerCase()}:${context.wallet.walletAddress.toLowerCase()}:${asset}`;
|
|
5445
6166
|
const cached = this.withdrawalVersionCache.get(key2);
|
|
5446
6167
|
if (useCachedV2 && cached && Date.now() - cached.at < 15 * 6e4) return { ...cached.status };
|
|
5447
|
-
const
|
|
6168
|
+
const existing = this.pendingWalletStatus.get(key2);
|
|
6169
|
+
if (existing) return { ...await existing };
|
|
6170
|
+
const pending2 = readYieldseekerWalletStatus(
|
|
5448
6171
|
this.getReceiptClient(),
|
|
5449
|
-
(0,
|
|
5450
|
-
(0,
|
|
6172
|
+
(0, import_viem16.getAddress)(context.wallet.walletAddress),
|
|
6173
|
+
(0, import_viem16.getAddress)(state.walletAddress),
|
|
5451
6174
|
YIELDSEEKER_ASSET_METADATA[asset].address
|
|
5452
|
-
)
|
|
5453
|
-
|
|
5454
|
-
|
|
6175
|
+
).then((status) => {
|
|
6176
|
+
this.assertSession(generation, chainId, asset);
|
|
6177
|
+
if (this.pendingWalletStatus.get(key2) !== pending2)
|
|
6178
|
+
throw new OwneyError("AGENT_API_ERROR", "Yieldseeker wallet verification changed. Please retry.", void 0, this.id);
|
|
6179
|
+
this.rememberWalletStatus(key2, status);
|
|
6180
|
+
return status;
|
|
6181
|
+
}).finally(() => {
|
|
6182
|
+
if (this.pendingWalletStatus.get(key2) === pending2) this.pendingWalletStatus.delete(key2);
|
|
6183
|
+
});
|
|
6184
|
+
this.pendingWalletStatus.set(key2, pending2);
|
|
6185
|
+
return { ...await pending2 };
|
|
5455
6186
|
}
|
|
5456
6187
|
rememberWalletStatus(key2, status) {
|
|
5457
6188
|
if (status.verified && status.version === "v2") {
|
|
@@ -5477,12 +6208,13 @@ var YieldseekerAgent = class {
|
|
|
5477
6208
|
const pendingKey2 = `owney.yieldseeker.upgrade:${before.owner.toLowerCase()}:${before.agentWallet.toLowerCase()}`;
|
|
5478
6209
|
const confirmUpgrade = async (hash2, receipt2) => {
|
|
5479
6210
|
this.withdrawalVersionCache.delete(versionKey);
|
|
5480
|
-
|
|
6211
|
+
this.pendingWalletStatus.delete(versionKey);
|
|
6212
|
+
const upgradeTopic = (0, import_viem16.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
|
|
5481
6213
|
const lastUpgrade = receipt2?.logs.filter((log) => log.address.toLowerCase() === before.agentWallet.toLowerCase() && log.topics[0] === upgradeTopic).at(-1);
|
|
5482
6214
|
const expectedUpgrade = (() => {
|
|
5483
6215
|
if (!lastUpgrade || lastUpgrade.removed) return false;
|
|
5484
6216
|
try {
|
|
5485
|
-
const event = (0,
|
|
6217
|
+
const event = (0, import_viem16.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
|
|
5486
6218
|
return event.args.implementation.toLowerCase() === YIELDSEEKER_V2_IMPLEMENTATION.toLowerCase();
|
|
5487
6219
|
} catch {
|
|
5488
6220
|
return false;
|
|
@@ -5620,7 +6352,7 @@ var YieldseekerAgent = class {
|
|
|
5620
6352
|
{ version: before.version },
|
|
5621
6353
|
this.id
|
|
5622
6354
|
);
|
|
5623
|
-
const data = (0,
|
|
6355
|
+
const data = (0, import_viem16.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
|
|
5624
6356
|
let txHash;
|
|
5625
6357
|
let receipt;
|
|
5626
6358
|
if (gasMode === "sponsored") {
|
|
@@ -5646,9 +6378,9 @@ var YieldseekerAgent = class {
|
|
|
5646
6378
|
agentWallet: before.agentWallet,
|
|
5647
6379
|
asset: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
5648
6380
|
callData: data,
|
|
5649
|
-
onPending: (
|
|
6381
|
+
onPending: (pending2) => {
|
|
5650
6382
|
const current = this.pendingUpgrades.has(pendingKey2) ? this.pendingUpgrades.get(pendingKey2) : JSON.parse(storage8.getItem(pendingKey2) ?? "null");
|
|
5651
|
-
const next = { startedAt: Date.now(), ...current, ...
|
|
6383
|
+
const next = { startedAt: Date.now(), ...current, ...pending2 };
|
|
5652
6384
|
storage8.setItem(pendingKey2, JSON.stringify(next));
|
|
5653
6385
|
this.pendingUpgrades.delete(pendingKey2);
|
|
5654
6386
|
}
|
|
@@ -5663,18 +6395,18 @@ var YieldseekerAgent = class {
|
|
|
5663
6395
|
let submittedHash;
|
|
5664
6396
|
try {
|
|
5665
6397
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5666
|
-
from: (0,
|
|
6398
|
+
from: (0, import_viem16.getAddress)(state.walletAddress),
|
|
5667
6399
|
to: before.agentWallet,
|
|
5668
6400
|
data,
|
|
5669
6401
|
value: "0",
|
|
5670
6402
|
chainId
|
|
5671
6403
|
}, (hash2) => {
|
|
5672
6404
|
submittedHash = hash2;
|
|
5673
|
-
const
|
|
5674
|
-
this.pendingUpgrades.set(pendingKey2,
|
|
6405
|
+
const pending2 = { txHash: hash2 };
|
|
6406
|
+
this.pendingUpgrades.set(pendingKey2, pending2);
|
|
5675
6407
|
try {
|
|
5676
6408
|
if (storage8) {
|
|
5677
|
-
storage8.setItem(pendingKey2, JSON.stringify(
|
|
6409
|
+
storage8.setItem(pendingKey2, JSON.stringify(pending2));
|
|
5678
6410
|
this.pendingUpgrades.delete(pendingKey2);
|
|
5679
6411
|
}
|
|
5680
6412
|
} catch {
|
|
@@ -5697,6 +6429,7 @@ var YieldseekerAgent = class {
|
|
|
5697
6429
|
}
|
|
5698
6430
|
async disconnect() {
|
|
5699
6431
|
this.withdrawalVersionCache.clear();
|
|
6432
|
+
this.pendingWalletStatus.clear();
|
|
5700
6433
|
this.readGeneration += 1;
|
|
5701
6434
|
this.auth.clear();
|
|
5702
6435
|
for (const key2 of this.users.keys()) {
|
|
@@ -5714,11 +6447,13 @@ var YieldseekerAgent = class {
|
|
|
5714
6447
|
this.liquidityVersions.clear();
|
|
5715
6448
|
this.snapshotFailures.clear();
|
|
5716
6449
|
this.standardReadFailures.clear();
|
|
6450
|
+
this.endpointReadFailures.clear();
|
|
5717
6451
|
this.reconcileUntil.clear();
|
|
5718
6452
|
this.allocationRefresh.clear();
|
|
5719
6453
|
this.activityRefreshUntil.clear();
|
|
5720
6454
|
this.snapshotMovements.clear();
|
|
5721
6455
|
this.movementEpochs.clear();
|
|
6456
|
+
this.settlementChecks.clear();
|
|
5722
6457
|
}
|
|
5723
6458
|
async activateAgent(state, chainId, asset) {
|
|
5724
6459
|
this.assertChain(chainId);
|
|
@@ -5771,12 +6506,12 @@ var YieldseekerAgent = class {
|
|
|
5771
6506
|
} else {
|
|
5772
6507
|
try {
|
|
5773
6508
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5774
|
-
from: (0,
|
|
6509
|
+
from: (0, import_viem16.getAddress)(state.walletAddress),
|
|
5775
6510
|
to: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
5776
|
-
data: (0,
|
|
5777
|
-
abi:
|
|
6511
|
+
data: (0, import_viem16.encodeFunctionData)({
|
|
6512
|
+
abi: import_viem16.erc20Abi,
|
|
5778
6513
|
functionName: "transfer",
|
|
5779
|
-
args: [(0,
|
|
6514
|
+
args: [(0, import_viem16.getAddress)(context.wallet.walletAddress), BigInt(amount)]
|
|
5780
6515
|
}),
|
|
5781
6516
|
value: "0",
|
|
5782
6517
|
chainId
|
|
@@ -5839,7 +6574,10 @@ var YieldseekerAgent = class {
|
|
|
5839
6574
|
ownerTransferAttempted = true;
|
|
5840
6575
|
}, gasMode, onBeforeSubmission, assertOperation);
|
|
5841
6576
|
} catch (error) {
|
|
5842
|
-
if (error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED")
|
|
6577
|
+
if (error instanceof OwneyError && error.code === "SPONSOR_REQUEST_FAILED") {
|
|
6578
|
+
this.withdrawalVersionCache.clear();
|
|
6579
|
+
this.pendingWalletStatus.clear();
|
|
6580
|
+
}
|
|
5843
6581
|
if (!ownerTransferAttempted || error?.code === 4001 || error instanceof OwneyError && (error.code === "AGENT_TRANSACTION_REVERTED" || error.details?.ownerTransferNotExecuted === true || error.code === "SPONSOR_REQUEST_FAILED" && (error.details?.safeToFallback === true || error.details?.executionFailed === true)))
|
|
5844
6582
|
notifyFunding(onProgress, {
|
|
5845
6583
|
...evidence,
|
|
@@ -5922,7 +6660,7 @@ var YieldseekerAgent = class {
|
|
|
5922
6660
|
);
|
|
5923
6661
|
const positionsRead = this.readWithdrawalPositions(state, chainId, context);
|
|
5924
6662
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
5925
|
-
const agentWallet = (0,
|
|
6663
|
+
const agentWallet = (0, import_viem16.getAddress)(context.wallet.walletAddress);
|
|
5926
6664
|
const readOwnerFunds = async (blockNumber) => {
|
|
5927
6665
|
const feeTracker = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5928
6666
|
address: agentWallet,
|
|
@@ -5931,18 +6669,18 @@ var YieldseekerAgent = class {
|
|
|
5931
6669
|
blockNumber
|
|
5932
6670
|
}), chainId, "eth_call", this.id);
|
|
5933
6671
|
this.assertSession(generation, chainId, asset);
|
|
5934
|
-
if (!(0,
|
|
6672
|
+
if (!(0, import_viem16.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
|
|
5935
6673
|
throw this.invalidResponse("wallet fee tracker");
|
|
5936
6674
|
const [idle2, fees] = await Promise.all([
|
|
5937
6675
|
withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5938
6676
|
address: metadata.address,
|
|
5939
|
-
abi:
|
|
6677
|
+
abi: import_viem16.erc20Abi,
|
|
5940
6678
|
functionName: "balanceOf",
|
|
5941
6679
|
args: [agentWallet],
|
|
5942
6680
|
blockNumber
|
|
5943
6681
|
}), chainId, "eth_call", this.id),
|
|
5944
6682
|
withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5945
|
-
address: (0,
|
|
6683
|
+
address: (0, import_viem16.getAddress)(feeTracker),
|
|
5946
6684
|
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
5947
6685
|
functionName: "getFeesOwed",
|
|
5948
6686
|
args: [agentWallet],
|
|
@@ -5984,21 +6722,35 @@ var YieldseekerAgent = class {
|
|
|
5984
6722
|
let active2 = true;
|
|
5985
6723
|
const checks = this.readVaultShares(values.map((position2) => position2.vaultOption), agentWallet, blockNumber).catch(() => []);
|
|
5986
6724
|
const reads = values.map(async (position2, index) => {
|
|
5987
|
-
const address = (0,
|
|
6725
|
+
const address = (0, import_viem16.getAddress)(position2.vaultOption.address);
|
|
5988
6726
|
try {
|
|
5989
6727
|
const group = (await checks).slice(index * 2, index * 2 + 2);
|
|
5990
6728
|
if (!active2 || group.length !== 2 || group.some((value) => value.status !== "success")) return null;
|
|
5991
6729
|
this.assertSession(generation, chainId, asset);
|
|
5992
6730
|
const [underlying, shares] = group.map((value) => value.result);
|
|
5993
|
-
if (typeof underlying !== "string" || !(0,
|
|
6731
|
+
if (typeof underlying !== "string" || !(0, import_viem16.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n) return null;
|
|
5994
6732
|
const verified = { ...position2, assetsRaw: shares.toString(), withdrawableAssetsRaw: "0" };
|
|
6733
|
+
if (shares > 0n && nativeYieldseekerProtocol(position2.vaultOption)) {
|
|
6734
|
+
const value = await readNativeYieldseekerAssets(
|
|
6735
|
+
this.getReceiptClient(),
|
|
6736
|
+
position2.vaultOption,
|
|
6737
|
+
agentWallet,
|
|
6738
|
+
shares,
|
|
6739
|
+
blockNumber
|
|
6740
|
+
);
|
|
6741
|
+
if (!active2 || value === void 0) return null;
|
|
6742
|
+
this.assertSession(generation, chainId, asset);
|
|
6743
|
+
verified.withdrawableAssetsRaw = value.toString();
|
|
6744
|
+
verifiedPositions.push(verified);
|
|
6745
|
+
return verified;
|
|
6746
|
+
}
|
|
5995
6747
|
if (shares > 0n) {
|
|
5996
6748
|
let positiveValue = false;
|
|
5997
6749
|
const valuations = await Promise.all(["convertToAssets", "previewRedeem"].map(async (functionName) => {
|
|
5998
6750
|
try {
|
|
5999
6751
|
const value = await this.getReceiptClient().readContract({
|
|
6000
6752
|
address,
|
|
6001
|
-
abi:
|
|
6753
|
+
abi: import_viem16.erc4626Abi,
|
|
6002
6754
|
functionName,
|
|
6003
6755
|
args: [shares],
|
|
6004
6756
|
blockNumber
|
|
@@ -6239,7 +6991,7 @@ var YieldseekerAgent = class {
|
|
|
6239
6991
|
delta: maxSettlementBasis.delta - payout,
|
|
6240
6992
|
expectedNetDeposits: maxSettlementBasis.expectedNetDeposits - payout
|
|
6241
6993
|
} : this.snapshotMovement(state, chainId, context, -payout);
|
|
6242
|
-
const account = (0,
|
|
6994
|
+
const account = (0, import_viem16.getAddress)(state.walletAddress);
|
|
6243
6995
|
let receipt;
|
|
6244
6996
|
const base7 = { agentId: this.id, chainId, token: asset, walletAddress: state.walletAddress, agentWallet: context.wallet.walletAddress, intendedAmount: amount ?? "MAX", transfer: "pending", registration: "not-applicable", delivery: "pending" };
|
|
6245
6997
|
if (amount === void 0) base7.maxCompletion = {
|
|
@@ -6250,11 +7002,11 @@ var YieldseekerAgent = class {
|
|
|
6250
7002
|
};
|
|
6251
7003
|
if (base7.maxCompletion) notifyFunding(onProgress, base7);
|
|
6252
7004
|
let submissionEvidence = base7;
|
|
6253
|
-
const data = amount === void 0 ? (0,
|
|
7005
|
+
const data = amount === void 0 ? (0, import_viem16.encodeFunctionData)({
|
|
6254
7006
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
6255
7007
|
functionName: "withdrawAllAssetToUser",
|
|
6256
7008
|
args: [account, metadata.address]
|
|
6257
|
-
}) : (0,
|
|
7009
|
+
}) : (0, import_viem16.encodeFunctionData)({
|
|
6258
7010
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
6259
7011
|
functionName: "withdrawAssetToUser",
|
|
6260
7012
|
args: [account, metadata.address, payout]
|
|
@@ -6271,16 +7023,16 @@ var YieldseekerAgent = class {
|
|
|
6271
7023
|
refreshYieldseekerSignature: (rejected) => this.auth.refreshToken(state, chainId, rejected),
|
|
6272
7024
|
userId: context.user.userId,
|
|
6273
7025
|
agentId: context.agent.agentId,
|
|
6274
|
-
agentWallet: (0,
|
|
7026
|
+
agentWallet: (0, import_viem16.getAddress)(context.wallet.walletAddress),
|
|
6275
7027
|
asset: metadata.address,
|
|
6276
7028
|
callData: data,
|
|
6277
|
-
onPending: (
|
|
6278
|
-
submissionEvidence = { ...submissionEvidence, ...
|
|
7029
|
+
onPending: (pending2) => {
|
|
7030
|
+
submissionEvidence = { ...submissionEvidence, ...pending2 };
|
|
6279
7031
|
notifyFunding(onProgress, submissionEvidence);
|
|
6280
7032
|
},
|
|
6281
|
-
onBeforeSubmission: async (
|
|
7033
|
+
onBeforeSubmission: async (pending2) => {
|
|
6282
7034
|
assertOperation?.();
|
|
6283
|
-
await onBeforeSubmission?.({ ...base7, ...
|
|
7035
|
+
await onBeforeSubmission?.({ ...base7, ...pending2 });
|
|
6284
7036
|
onOwnerTransferAttempted?.();
|
|
6285
7037
|
}
|
|
6286
7038
|
});
|
|
@@ -6293,7 +7045,7 @@ var YieldseekerAgent = class {
|
|
|
6293
7045
|
chainId,
|
|
6294
7046
|
{
|
|
6295
7047
|
from: account,
|
|
6296
|
-
to: (0,
|
|
7048
|
+
to: (0, import_viem16.getAddress)(context.wallet.walletAddress),
|
|
6297
7049
|
data,
|
|
6298
7050
|
value: "0",
|
|
6299
7051
|
chainId
|
|
@@ -6423,7 +7175,7 @@ var YieldseekerAgent = class {
|
|
|
6423
7175
|
async verifyWithdrawalCompletion(state, evidence) {
|
|
6424
7176
|
const unknown = (reason2) => ({ status: "unavailable", reason: reason2 });
|
|
6425
7177
|
const proof = evidence.maxCompletion;
|
|
6426
|
-
if (evidence.agentId !== this.id || evidence.walletAddress.toLowerCase() !== state.walletAddress.toLowerCase() || evidence.chainId !== 8453 || !proof || !evidence.agentWallet || !(0,
|
|
7178
|
+
if (evidence.agentId !== this.id || evidence.walletAddress.toLowerCase() !== state.walletAddress.toLowerCase() || evidence.chainId !== 8453 || !proof || !evidence.agentWallet || !(0, import_viem16.isAddress)(evidence.agentWallet) || !evidence.blockNumber || !/^\d+$/.test(evidence.blockNumber) || evidence.transfer !== "confirmed" || evidence.delivery !== "confirmed" || !this.isTransactionHash(evidence.txHash)) return unknown("PAYOUT_PROOF_UNAVAILABLE");
|
|
6427
7179
|
this.assertAsset(evidence.token);
|
|
6428
7180
|
const asset = evidence.token;
|
|
6429
7181
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
@@ -6438,28 +7190,35 @@ var YieldseekerAgent = class {
|
|
|
6438
7190
|
);
|
|
6439
7191
|
if (!Array.isArray(response?.vaultPositions)) return unknown("CATALOG_INVALID");
|
|
6440
7192
|
const positions = this.validateWithdrawalPositions(response.vaultPositions, evidence.chainId, asset);
|
|
6441
|
-
const vaults = new
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
eligible.
|
|
7193
|
+
const vaults = new Map(proof.vaults.map((address) => [address.toLowerCase(), { address }]));
|
|
7194
|
+
positions.forEach((p) => vaults.set(p.vaultOption.address.toLowerCase(), p.vaultOption));
|
|
7195
|
+
const needsInventory = !proof.inventoryComplete;
|
|
7196
|
+
if (needsInventory || [...vaults.values()].some((option) => !option.provider)) {
|
|
7197
|
+
const catalog = await this.loadVaultOptions(asset).catch(() => []);
|
|
7198
|
+
const eligible = catalog.filter((o) => o.chainId === evidence.chainId && o.assetAddress?.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem16.isAddress)(o.address));
|
|
7199
|
+
if (needsInventory && !eligible.length) return unknown("INVENTORY_INCOMPLETE");
|
|
7200
|
+
for (const option of eligible) {
|
|
7201
|
+
const key2 = option.address.toLowerCase();
|
|
7202
|
+
if (needsInventory || vaults.has(key2)) vaults.set(key2, option);
|
|
7203
|
+
}
|
|
6447
7204
|
}
|
|
6448
|
-
if (vaults.size > YIELDSEEKER_WITHDRAWAL_CANDIDATE_LIMIT || [...vaults].some((a) => !(0,
|
|
7205
|
+
if (vaults.size > YIELDSEEKER_WITHDRAWAL_CANDIDATE_LIMIT || [...vaults.keys()].some((a) => !(0, import_viem16.isAddress)(a)))
|
|
6449
7206
|
return unknown("INVENTORY_INVALID");
|
|
6450
7207
|
reason = "VAULT_PROOF_UNAVAILABLE";
|
|
6451
7208
|
const blockNumber = BigInt(evidence.blockNumber);
|
|
6452
|
-
const
|
|
6453
|
-
const
|
|
7209
|
+
const options = [...vaults.values()];
|
|
7210
|
+
const addresses = options.map((option) => option.address);
|
|
7211
|
+
const shares = await this.readVaultShares(options, evidence.agentWallet, blockNumber);
|
|
6454
7212
|
const checks = await Promise.all(addresses.map(async (address, i) => {
|
|
6455
7213
|
const group = shares.slice(i * 2, i * 2 + 2);
|
|
6456
7214
|
if (group.length !== 2 || group.some((r) => r.status !== "success")) return "unavailable";
|
|
6457
7215
|
const [underlying, value] = group.map((r) => r.result);
|
|
6458
7216
|
if (typeof underlying !== "string" || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof value !== "bigint" || value < 0n) return "unavailable";
|
|
6459
7217
|
if (value === 0n) return "complete";
|
|
7218
|
+
if (nativeYieldseekerProtocol(options[i])) return "remaining";
|
|
6460
7219
|
const amounts = await Promise.allSettled(["convertToAssets", "previewRedeem"].map((functionName) => this.getReceiptClient().readContract({
|
|
6461
|
-
address: (0,
|
|
6462
|
-
abi:
|
|
7220
|
+
address: (0, import_viem16.getAddress)(address),
|
|
7221
|
+
abi: import_viem16.erc4626Abi,
|
|
6463
7222
|
functionName,
|
|
6464
7223
|
args: [value],
|
|
6465
7224
|
blockNumber
|
|
@@ -6479,16 +7238,16 @@ var YieldseekerAgent = class {
|
|
|
6479
7238
|
}
|
|
6480
7239
|
}
|
|
6481
7240
|
async readVaultShares(options, wallet, blockNumber) {
|
|
6482
|
-
const owner = (0,
|
|
7241
|
+
const owner = (0, import_viem16.getAddress)(wallet);
|
|
6483
7242
|
const batches = Array.from({ length: Math.ceil(options.length / YIELDSEEKER_VAULTS_PER_RPC_BATCH) }, (_, index) => options.slice(index * YIELDSEEKER_VAULTS_PER_RPC_BATCH, (index + 1) * YIELDSEEKER_VAULTS_PER_RPC_BATCH));
|
|
6484
7243
|
const results = await Promise.all(batches.map((batch) => this.getReceiptClient().multicall({
|
|
6485
7244
|
blockNumber,
|
|
6486
7245
|
allowFailure: true,
|
|
6487
7246
|
contracts: batch.flatMap((option) => {
|
|
6488
|
-
const address = (0,
|
|
7247
|
+
const address = (0, import_viem16.getAddress)(option.address);
|
|
6489
7248
|
return [
|
|
6490
|
-
|
|
6491
|
-
{ address, abi:
|
|
7249
|
+
yieldseekerUnderlyingCall(option),
|
|
7250
|
+
{ address, abi: import_viem16.erc20Abi, functionName: "balanceOf", args: [owner] }
|
|
6492
7251
|
];
|
|
6493
7252
|
})
|
|
6494
7253
|
})));
|
|
@@ -6499,7 +7258,7 @@ var YieldseekerAgent = class {
|
|
|
6499
7258
|
const seen = /* @__PURE__ */ new Set();
|
|
6500
7259
|
for (const value of values) {
|
|
6501
7260
|
const option = value?.vaultOption;
|
|
6502
|
-
if (!option || typeof option.address !== "string" || !(0,
|
|
7261
|
+
if (!option || typeof option.address !== "string" || !(0, import_viem16.isAddress)(option.address) || seen.has(option.address.toLowerCase()) || option.chainId !== void 0 && option.chainId !== chainId || option.assetAddress !== void 0 && (typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== underlying) || typeof value.assetsRaw !== "string" || !/^\d+$/.test(value.assetsRaw) || typeof value.withdrawableAssetsRaw !== "string" || !/^\d+$/.test(value.withdrawableAssetsRaw))
|
|
6503
7262
|
throw this.invalidResponse("vault positions");
|
|
6504
7263
|
seen.add(option.address.toLowerCase());
|
|
6505
7264
|
}
|
|
@@ -6512,7 +7271,7 @@ var YieldseekerAgent = class {
|
|
|
6512
7271
|
const historic = this.readCache.get(`historic:${key2}`)?.value?.position;
|
|
6513
7272
|
const receivedAssets = new Set((historic?.movements ?? []).filter((movement) => movement.chainId === chainId && movement.agentWalletId === context.wallet.agentWalletId && movement.toAddress?.toLowerCase() === context.wallet.walletAddress.toLowerCase()).filter((movement) => typeof movement.assetAddress === "string").map((movement) => movement.assetAddress.toLowerCase()));
|
|
6514
7273
|
for (const option of this.vaultOptions.get(context.asset)?.value ?? []) {
|
|
6515
|
-
if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0,
|
|
7274
|
+
if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0, import_viem16.isAddress)(option.address) || !receivedAssets.has(option.address.toLowerCase()) || hints.has(option.address.toLowerCase())) continue;
|
|
6516
7275
|
hints.set(option.address.toLowerCase(), {
|
|
6517
7276
|
vaultOption: option,
|
|
6518
7277
|
assetsRaw: "0",
|
|
@@ -6566,7 +7325,7 @@ var YieldseekerAgent = class {
|
|
|
6566
7325
|
const read2 = async () => {
|
|
6567
7326
|
const client = this.getReceiptClient();
|
|
6568
7327
|
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
6569
|
-
const wallet = (0,
|
|
7328
|
+
const wallet = (0, import_viem16.getAddress)(context.wallet.walletAddress);
|
|
6570
7329
|
assertReadCurrent();
|
|
6571
7330
|
if (typeof blockNumber !== "bigint") throw unavailable();
|
|
6572
7331
|
const indexedPositions = this.validateWithdrawalPositions(positions ?? [], chainId, context.asset);
|
|
@@ -6579,7 +7338,7 @@ var YieldseekerAgent = class {
|
|
|
6579
7338
|
const [idle, feeTracker] = await Promise.all([
|
|
6580
7339
|
client.readContract({
|
|
6581
7340
|
address: metadata.address,
|
|
6582
|
-
abi:
|
|
7341
|
+
abi: import_viem16.erc20Abi,
|
|
6583
7342
|
functionName: "balanceOf",
|
|
6584
7343
|
args: [wallet],
|
|
6585
7344
|
blockNumber
|
|
@@ -6591,10 +7350,10 @@ var YieldseekerAgent = class {
|
|
|
6591
7350
|
blockNumber
|
|
6592
7351
|
})
|
|
6593
7352
|
]);
|
|
6594
|
-
if (typeof idle !== "bigint" || idle < 0n || !(0,
|
|
7353
|
+
if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem16.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
|
|
6595
7354
|
assertReadCurrent();
|
|
6596
7355
|
const fees = await client.readContract({
|
|
6597
|
-
address: (0,
|
|
7356
|
+
address: (0, import_viem16.getAddress)(feeTracker),
|
|
6598
7357
|
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
6599
7358
|
functionName: "getFeesOwed",
|
|
6600
7359
|
args: [wallet],
|
|
@@ -6646,7 +7405,7 @@ var YieldseekerAgent = class {
|
|
|
6646
7405
|
const group = results.slice(index * 2, index * 2 + 2);
|
|
6647
7406
|
if (group.length !== 2 || group.some((value2) => value2.status !== "success")) return false;
|
|
6648
7407
|
const [underlying, shares] = group.map((value2) => value2.result);
|
|
6649
|
-
if (typeof underlying !== "string" || !(0,
|
|
7408
|
+
if (typeof underlying !== "string" || !(0, import_viem16.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n) return false;
|
|
6650
7409
|
if (shares > 0n) known.add(option.address.toLowerCase());
|
|
6651
7410
|
const position2 = {
|
|
6652
7411
|
vaultOption: option,
|
|
@@ -6660,11 +7419,21 @@ var YieldseekerAgent = class {
|
|
|
6660
7419
|
verified.push(position2);
|
|
6661
7420
|
knownProof = proof(false);
|
|
6662
7421
|
if (shares === 0n) return true;
|
|
7422
|
+
if (nativeYieldseekerProtocol(option)) {
|
|
7423
|
+
const value2 = await readNativeYieldseekerAssets(client, option, wallet, shares, blockNumber);
|
|
7424
|
+
assertReadCurrent();
|
|
7425
|
+
if (value2 === void 0) return false;
|
|
7426
|
+
position2.withdrawableAssetsRaw = value2.toString();
|
|
7427
|
+
position2.withdrawableAssetsBase = value2.toString();
|
|
7428
|
+
deployed += value2;
|
|
7429
|
+
knownProof = proof(false);
|
|
7430
|
+
return true;
|
|
7431
|
+
}
|
|
6663
7432
|
let preview;
|
|
6664
7433
|
try {
|
|
6665
7434
|
const value2 = await client.readContract({
|
|
6666
|
-
address: (0,
|
|
6667
|
-
abi:
|
|
7435
|
+
address: (0, import_viem16.getAddress)(option.address),
|
|
7436
|
+
abi: import_viem16.erc4626Abi,
|
|
6668
7437
|
functionName: "previewRedeem",
|
|
6669
7438
|
args: [shares],
|
|
6670
7439
|
blockNumber
|
|
@@ -6677,8 +7446,8 @@ var YieldseekerAgent = class {
|
|
|
6677
7446
|
if (value === void 0 || value === 0n) {
|
|
6678
7447
|
try {
|
|
6679
7448
|
const converted = await client.readContract({
|
|
6680
|
-
address: (0,
|
|
6681
|
-
abi:
|
|
7449
|
+
address: (0, import_viem16.getAddress)(option.address),
|
|
7450
|
+
abi: import_viem16.erc4626Abi,
|
|
6682
7451
|
functionName: "convertToAssets",
|
|
6683
7452
|
args: [shares],
|
|
6684
7453
|
blockNumber
|
|
@@ -6718,7 +7487,7 @@ var YieldseekerAgent = class {
|
|
|
6718
7487
|
assertReadCurrent();
|
|
6719
7488
|
const eligible = /* @__PURE__ */ new Map();
|
|
6720
7489
|
for (const option of catalog ?? []) {
|
|
6721
|
-
if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0,
|
|
7490
|
+
if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem16.isAddress)(option.address))
|
|
6722
7491
|
eligible.set(option.address.toLowerCase(), option);
|
|
6723
7492
|
}
|
|
6724
7493
|
const extra = [...eligible].filter(([address]) => !candidates.has(address)).map(([, option]) => option);
|
|
@@ -6769,7 +7538,7 @@ var YieldseekerAgent = class {
|
|
|
6769
7538
|
const key2 = this.contextKey(state, evidence.chainId, evidence.token);
|
|
6770
7539
|
const generation = this.readGeneration, version = this.portfolioVersion(key2);
|
|
6771
7540
|
if (read2.readVersion !== version) return void 0;
|
|
6772
|
-
const wallet = (0,
|
|
7541
|
+
const wallet = (0, import_viem16.getAddress)(context.wallet.walletAddress);
|
|
6773
7542
|
const asset = YIELDSEEKER_ASSET_METADATA[evidence.token];
|
|
6774
7543
|
const client = this.getReceiptClient();
|
|
6775
7544
|
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
@@ -6777,10 +7546,10 @@ var YieldseekerAgent = class {
|
|
|
6777
7546
|
const vaults = [...this.balanceVaults.get(key2) ?? []];
|
|
6778
7547
|
const [invested, idle, tracker] = await Promise.all([
|
|
6779
7548
|
remainingVaultBalance(client, wallet, asset.address, vaults, blockNumber),
|
|
6780
|
-
client.readContract({ address: asset.address, abi:
|
|
7549
|
+
client.readContract({ address: asset.address, abi: import_viem16.erc20Abi, functionName: "balanceOf", args: [wallet], blockNumber }),
|
|
6781
7550
|
client.readContract({ address: wallet, abi: YIELDSEEKER_AGENT_WALLET_ABI, functionName: "feeTracker", blockNumber })
|
|
6782
7551
|
]);
|
|
6783
|
-
if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !(0,
|
|
7552
|
+
if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !(0, import_viem16.isAddress)(tracker) || /^0x0{40}$/i.test(tracker)) return void 0;
|
|
6784
7553
|
const fees = await client.readContract({
|
|
6785
7554
|
address: tracker,
|
|
6786
7555
|
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
@@ -6793,7 +7562,7 @@ var YieldseekerAgent = class {
|
|
|
6793
7562
|
const total = idle + invested > fees ? idle + invested - fees : 0n;
|
|
6794
7563
|
const displayed = balance.assetBalances?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
|
|
6795
7564
|
if (!displayed || !evidence.confirmedAmount || !/^\d+$/.test(evidence.confirmedAmount)) return void 0;
|
|
6796
|
-
const amount = (0,
|
|
7565
|
+
const amount = (0, import_viem16.parseUnits)(displayed.amount, asset.decimals);
|
|
6797
7566
|
if (amount < 0n) return void 0;
|
|
6798
7567
|
const displayUnit = evidence.token === "USDC" ? 5000n : 500000000000n;
|
|
6799
7568
|
const movementUnit = BigInt(evidence.confirmedAmount) / 1000n;
|
|
@@ -6810,16 +7579,18 @@ var YieldseekerAgent = class {
|
|
|
6810
7579
|
if (failure && failure.retryAt > Date.now()) this.snapshotFailures.set(key2, failure);
|
|
6811
7580
|
this.allocationRefresh.add(key2);
|
|
6812
7581
|
}
|
|
6813
|
-
invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() +
|
|
7582
|
+
invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() + YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS) {
|
|
6814
7583
|
this.assertAsset(asset);
|
|
6815
7584
|
const key2 = this.contextKey(state, chainId, asset);
|
|
6816
7585
|
const failure = this.snapshotFailures.get(key2);
|
|
6817
7586
|
this.advancePortfolioVersion(key2);
|
|
6818
7587
|
if (failure && failure.retryAt > Date.now()) this.snapshotFailures.set(key2, failure);
|
|
6819
7588
|
if (!this.snapshotMovements.has(key2)) this.snapshotMovements.set(key2, null);
|
|
6820
|
-
const until = Math.min(refreshUntil, Date.now() +
|
|
7589
|
+
const until = Math.min(refreshUntil, Date.now() + YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS);
|
|
7590
|
+
const activityUntil = Math.min(refreshUntil, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
|
|
7591
|
+
if (until > Date.now()) this.beginSettlement(key2, false);
|
|
6821
7592
|
this.reconcileUntil.set(key2, Math.max(this.reconcileUntil.get(key2) ?? 0, until));
|
|
6822
|
-
this.activityRefreshUntil.set(key2, Math.max(this.activityRefreshUntil.get(key2) ?? 0,
|
|
7593
|
+
this.activityRefreshUntil.set(key2, Math.max(this.activityRefreshUntil.get(key2) ?? 0, activityUntil));
|
|
6823
7594
|
}
|
|
6824
7595
|
endFundingBalanceRefresh(state, chainId, asset, read2) {
|
|
6825
7596
|
this.assertChain(chainId);
|
|
@@ -6848,9 +7619,9 @@ var YieldseekerAgent = class {
|
|
|
6848
7619
|
if (!context) return void 0;
|
|
6849
7620
|
const idle = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
6850
7621
|
address: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
6851
|
-
abi:
|
|
7622
|
+
abi: import_viem16.erc20Abi,
|
|
6852
7623
|
functionName: "balanceOf",
|
|
6853
|
-
args: [(0,
|
|
7624
|
+
args: [(0, import_viem16.getAddress)(context.wallet.walletAddress)]
|
|
6854
7625
|
}), chainId, "eth_call", this.id);
|
|
6855
7626
|
this.assertSession(generation, chainId, asset);
|
|
6856
7627
|
if (typeof idle !== "bigint" || idle < 0n) throw this.invalidResponse("wallet deposit balance");
|
|
@@ -6897,7 +7668,7 @@ var YieldseekerAgent = class {
|
|
|
6897
7668
|
);
|
|
6898
7669
|
const vaultAddresses = new Set(
|
|
6899
7670
|
catalog.flat().filter(
|
|
6900
|
-
(vaultOption) => vaultOption.chainId === chainId && (0,
|
|
7671
|
+
(vaultOption) => vaultOption.chainId === chainId && (0, import_viem16.isAddress)(vaultOption.address)
|
|
6901
7672
|
).map((vaultOption) => vaultOption.address.toLowerCase())
|
|
6902
7673
|
);
|
|
6903
7674
|
return mapYieldseekerHistory(contexts, {
|
|
@@ -6931,8 +7702,8 @@ var YieldseekerAgent = class {
|
|
|
6931
7702
|
async loadVaultOptions(asset) {
|
|
6932
7703
|
const cached = this.vaultOptions.get(asset);
|
|
6933
7704
|
if (cached && cached.expiresAt > Date.now()) return cached.value;
|
|
6934
|
-
const
|
|
6935
|
-
if (
|
|
7705
|
+
const pending2 = this.pendingVaultOptions.get(asset);
|
|
7706
|
+
if (pending2) return pending2;
|
|
6936
7707
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
6937
7708
|
const request2 = this.api.request(
|
|
6938
7709
|
`/chains/8453/assets/${metadata.address}/vault-options`
|
|
@@ -6970,8 +7741,8 @@ var YieldseekerAgent = class {
|
|
|
6970
7741
|
if (cached && cached.expiresAt > Date.now()) {
|
|
6971
7742
|
return Promise.resolve(cached.value);
|
|
6972
7743
|
}
|
|
6973
|
-
const
|
|
6974
|
-
if (
|
|
7744
|
+
const pending2 = this.pendingReads.get(key2);
|
|
7745
|
+
if (pending2) return pending2;
|
|
6975
7746
|
const generation = this.readGeneration;
|
|
6976
7747
|
const requestedAt = Date.now();
|
|
6977
7748
|
const request2 = Promise.resolve().then(read2).then((value) => {
|
|
@@ -7017,8 +7788,8 @@ var YieldseekerAgent = class {
|
|
|
7017
7788
|
const key2 = this.contextKey(state, chainId, asset);
|
|
7018
7789
|
const cached = this.agentContexts.get(key2);
|
|
7019
7790
|
if (cached?.agent.agentId === agent.agentId) return cached;
|
|
7020
|
-
const
|
|
7021
|
-
if (
|
|
7791
|
+
const pending2 = this.pendingWalletContexts.get(key2);
|
|
7792
|
+
if (pending2) return pending2;
|
|
7022
7793
|
const generation = this.readGeneration;
|
|
7023
7794
|
const request2 = this.walletRequest(
|
|
7024
7795
|
state,
|
|
@@ -7026,7 +7797,7 @@ var YieldseekerAgent = class {
|
|
|
7026
7797
|
`/users/${user.userId}/agents/${agent.agentId}/wallet`
|
|
7027
7798
|
).then((walletResponse) => {
|
|
7028
7799
|
this.assertSession(generation, chainId, asset);
|
|
7029
|
-
if (!walletResponse?.agentWallet || !(0,
|
|
7800
|
+
if (!walletResponse?.agentWallet || !(0, import_viem16.isAddress)(walletResponse.agentWallet.walletAddress)) {
|
|
7030
7801
|
throw this.invalidResponse("agent wallet");
|
|
7031
7802
|
}
|
|
7032
7803
|
const context = {
|
|
@@ -7056,7 +7827,7 @@ var YieldseekerAgent = class {
|
|
|
7056
7827
|
this.users.set(key2, persisted);
|
|
7057
7828
|
return persisted;
|
|
7058
7829
|
}
|
|
7059
|
-
const walletAddress = (0,
|
|
7830
|
+
const walletAddress = (0, import_viem16.getAddress)(state.walletAddress);
|
|
7060
7831
|
const generation = this.readGeneration;
|
|
7061
7832
|
let user = null;
|
|
7062
7833
|
try {
|
|
@@ -7118,8 +7889,8 @@ var YieldseekerAgent = class {
|
|
|
7118
7889
|
const key2 = this.contextKey(state, chainId, asset);
|
|
7119
7890
|
const cached = this.agentContexts.get(key2);
|
|
7120
7891
|
if (cached) return cached;
|
|
7121
|
-
const
|
|
7122
|
-
if (
|
|
7892
|
+
const pending2 = this.pendingAgents.get(key2);
|
|
7893
|
+
if (pending2) return pending2;
|
|
7123
7894
|
const generation = this.readGeneration;
|
|
7124
7895
|
const request2 = this.resolveAgent(state, chainId, asset, true).then(
|
|
7125
7896
|
async (context) => {
|
|
@@ -7229,8 +8000,21 @@ var YieldseekerAgent = class {
|
|
|
7229
8000
|
portfolioVersion(contextKey) {
|
|
7230
8001
|
return this.portfolioVersions.get(contextKey) ?? 0;
|
|
7231
8002
|
}
|
|
8003
|
+
/** Snapshot cache lifetime: the settlement backoff while a movement is being
|
|
8004
|
+
* checked, otherwise the routine non-forced cadence. */
|
|
7232
8005
|
portfolioCacheMs(contextKey) {
|
|
7233
|
-
|
|
8006
|
+
if ((this.reconcileUntil.get(contextKey) ?? 0) <= Date.now()) return YIELDSEEKER_PORTFOLIO_CACHE_MS;
|
|
8007
|
+
const checks = this.settlementChecks.get(contextKey) ?? 0;
|
|
8008
|
+
return YIELDSEEKER_SETTLEMENT_BACKOFF_MS[Math.min(checks, YIELDSEEKER_SETTLEMENT_BACKOFF_MS.length - 1)];
|
|
8009
|
+
}
|
|
8010
|
+
/** A pending movement inside its ten-minute window forces snapshots. */
|
|
8011
|
+
settling(contextKey) {
|
|
8012
|
+
return this.snapshotMovements.has(contextKey) && (this.reconcileUntil.get(contextKey) ?? 0) > Date.now();
|
|
8013
|
+
}
|
|
8014
|
+
/** Start a new forced-check schedule, or keep the active one. */
|
|
8015
|
+
beginSettlement(contextKey, restart) {
|
|
8016
|
+
if (!restart && (this.reconcileUntil.get(contextKey) ?? 0) > Date.now()) return;
|
|
8017
|
+
this.settlementChecks.set(contextKey, 0);
|
|
7234
8018
|
}
|
|
7235
8019
|
snapshotMovement(state, chainId, context, delta) {
|
|
7236
8020
|
const key2 = this.contextKey(state, chainId, context.asset);
|
|
@@ -7256,13 +8040,15 @@ var YieldseekerAgent = class {
|
|
|
7256
8040
|
expectedNetDeposits: BigInt(snapshot.netDepositsBase) + delta
|
|
7257
8041
|
};
|
|
7258
8042
|
}
|
|
7259
|
-
advancePortfolioVersion(contextKey, { snapshotOnly = false } = {}) {
|
|
8043
|
+
advancePortfolioVersion(contextKey, { snapshotOnly = false, keepPositions = false } = {}) {
|
|
7260
8044
|
const version = this.portfolioVersion(contextKey) + 1;
|
|
7261
8045
|
this.portfolioVersions.set(contextKey, version);
|
|
7262
8046
|
if (!snapshotOnly) this.liquidityVersions.set(contextKey, version);
|
|
7263
8047
|
this.snapshotFailures.delete(contextKey);
|
|
7264
|
-
|
|
8048
|
+
const kinds = !snapshotOnly ? ["snapshot", "positions", "historic", "actions"] : keepPositions ? ["snapshot"] : ["snapshot", "positions"];
|
|
8049
|
+
for (const kind of kinds) {
|
|
7265
8050
|
const key2 = `${kind}:${contextKey}`;
|
|
8051
|
+
if (snapshotOnly && kind === "positions" && this.pendingReads.has(key2)) continue;
|
|
7266
8052
|
this.readCache.delete(key2);
|
|
7267
8053
|
this.pendingReads.delete(key2);
|
|
7268
8054
|
}
|
|
@@ -7307,7 +8093,7 @@ var YieldseekerAgent = class {
|
|
|
7307
8093
|
if ((!cached || cached.expiresAt <= Date.now()) && !this.pendingReads.has(key2)) {
|
|
7308
8094
|
const failure = this.snapshotFailures.get(contextKey);
|
|
7309
8095
|
if (failure && failure.retryAt > Date.now()) throw failure.error;
|
|
7310
|
-
this.advancePortfolioVersion(contextKey, { snapshotOnly: true });
|
|
8096
|
+
this.advancePortfolioVersion(contextKey, { snapshotOnly: true, keepPositions: this.settling(contextKey) });
|
|
7311
8097
|
}
|
|
7312
8098
|
const version = this.portfolioVersion(contextKey);
|
|
7313
8099
|
const generation = this.readGeneration;
|
|
@@ -7315,6 +8101,8 @@ var YieldseekerAgent = class {
|
|
|
7315
8101
|
version,
|
|
7316
8102
|
read: this.cachedRead(key2, this.portfolioCacheMs(contextKey), () => {
|
|
7317
8103
|
const allocationChanged = this.allocationRefresh.delete(contextKey);
|
|
8104
|
+
const settling = this.settling(contextKey);
|
|
8105
|
+
if (settling) this.settlementChecks.set(contextKey, (this.settlementChecks.get(contextKey) ?? 0) + 1);
|
|
7318
8106
|
return this.requestPortfolioSnapshot(
|
|
7319
8107
|
state,
|
|
7320
8108
|
chainId,
|
|
@@ -7322,7 +8110,7 @@ var YieldseekerAgent = class {
|
|
|
7322
8110
|
contextKey,
|
|
7323
8111
|
version,
|
|
7324
8112
|
generation,
|
|
7325
|
-
allocationChanged ||
|
|
8113
|
+
allocationChanged || settling
|
|
7326
8114
|
);
|
|
7327
8115
|
})
|
|
7328
8116
|
};
|
|
@@ -7392,7 +8180,7 @@ var YieldseekerAgent = class {
|
|
|
7392
8180
|
const [positions, historic, actions] = await Promise.all([
|
|
7393
8181
|
options.includePositions === false ? Promise.resolve({ vaultPositions: [] }) : this.cachedRead(
|
|
7394
8182
|
`positions:${contextKey}`,
|
|
7395
|
-
|
|
8183
|
+
YIELDSEEKER_PORTFOLIO_CACHE_MS,
|
|
7396
8184
|
async () => {
|
|
7397
8185
|
const response = await this.walletRequest(
|
|
7398
8186
|
state,
|
|
@@ -7439,7 +8227,7 @@ var YieldseekerAgent = class {
|
|
|
7439
8227
|
this.agentPath(context, "deploy"),
|
|
7440
8228
|
{ method: "POST", body: {} }
|
|
7441
8229
|
);
|
|
7442
|
-
if (!deployed?.agentWallet || !(0,
|
|
8230
|
+
if (!deployed?.agentWallet || !(0, import_viem16.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
|
|
7443
8231
|
throw this.invalidResponse("agent deployment", {
|
|
7444
8232
|
reason: "Deploy did not return the expected Agent Wallet."
|
|
7445
8233
|
});
|
|
@@ -7448,7 +8236,8 @@ var YieldseekerAgent = class {
|
|
|
7448
8236
|
}
|
|
7449
8237
|
async refreshSnapshotAfterMovement(state, chainId, context, movement, settlement) {
|
|
7450
8238
|
const contextKey = this.contextKey(state, chainId, context.asset);
|
|
7451
|
-
this.
|
|
8239
|
+
this.beginSettlement(contextKey, true);
|
|
8240
|
+
this.reconcileUntil.set(contextKey, Date.now() + YIELDSEEKER_SETTLEMENT_SNAPSHOT_WINDOW_MS);
|
|
7452
8241
|
this.activityRefreshUntil.set(contextKey, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
|
|
7453
8242
|
const epoch = this.movementEpochs.get(contextKey) ?? 0;
|
|
7454
8243
|
this.snapshotMovements.set(contextKey, settlement?.epoch === epoch ? settlement : null);
|
|
@@ -7456,9 +8245,11 @@ var YieldseekerAgent = class {
|
|
|
7456
8245
|
const version = this.advancePortfolioVersion(contextKey);
|
|
7457
8246
|
const generation = this.readGeneration;
|
|
7458
8247
|
try {
|
|
8248
|
+
const ttl = this.portfolioCacheMs(contextKey);
|
|
8249
|
+
this.settlementChecks.set(contextKey, 1);
|
|
7459
8250
|
await this.cachedRead(
|
|
7460
8251
|
`snapshot:${contextKey}`,
|
|
7461
|
-
|
|
8252
|
+
ttl,
|
|
7462
8253
|
() => this.requestPortfolioSnapshot(state, chainId, context, contextKey, version, generation, true)
|
|
7463
8254
|
);
|
|
7464
8255
|
} catch (error) {
|
|
@@ -7474,10 +8265,14 @@ var YieldseekerAgent = class {
|
|
|
7474
8265
|
async walletRequest(state, chainId, path, options = {}) {
|
|
7475
8266
|
const read2 = (options.method ?? "GET") === "GET";
|
|
7476
8267
|
const userKey = this.userKey(state, chainId);
|
|
8268
|
+
const endpointKey = `${userKey}:${path}`;
|
|
7477
8269
|
if (read2) {
|
|
7478
8270
|
const failure = this.standardReadFailures.get(userKey);
|
|
7479
8271
|
if (failure && failure.retryAt > Date.now()) throw failure.error;
|
|
7480
8272
|
if (failure) this.standardReadFailures.delete(userKey);
|
|
8273
|
+
const endpointFailure = this.endpointReadFailures.get(endpointKey);
|
|
8274
|
+
if (endpointFailure && endpointFailure.retryAt > Date.now()) throw endpointFailure.error;
|
|
8275
|
+
if (endpointFailure) this.endpointReadFailures.delete(endpointKey);
|
|
7481
8276
|
}
|
|
7482
8277
|
const generation = this.readGeneration;
|
|
7483
8278
|
try {
|
|
@@ -7491,6 +8286,12 @@ var YieldseekerAgent = class {
|
|
|
7491
8286
|
error: mapped
|
|
7492
8287
|
});
|
|
7493
8288
|
}
|
|
8289
|
+
if (read2 && this.readGeneration === generation && error instanceof YieldseekerApiError && (error.status === 0 || error.status === 408 || error.status >= 500 && error.status < 600)) {
|
|
8290
|
+
this.endpointReadFailures.set(endpointKey, {
|
|
8291
|
+
retryAt: Date.now() + YIELDSEEKER_READ_FAILURE_COOLDOWN_MS,
|
|
8292
|
+
error: mapped
|
|
8293
|
+
});
|
|
8294
|
+
}
|
|
7494
8295
|
throw mapped;
|
|
7495
8296
|
}
|
|
7496
8297
|
}
|
|
@@ -7548,18 +8349,18 @@ var YieldseekerAgent = class {
|
|
|
7548
8349
|
return hash3;
|
|
7549
8350
|
}
|
|
7550
8351
|
this.assertTransaction(transaction, state, chainId);
|
|
7551
|
-
const account = (0,
|
|
7552
|
-
const walletClient = (0,
|
|
8352
|
+
const account = (0, import_viem16.getAddress)(state.walletAddress);
|
|
8353
|
+
const walletClient = (0, import_viem16.createWalletClient)({
|
|
7553
8354
|
account,
|
|
7554
8355
|
chain: import_chains4.base,
|
|
7555
|
-
transport: onBeforeSubmission ? (0,
|
|
8356
|
+
transport: onBeforeSubmission ? (0, import_viem16.custom)({ request: async (args) => {
|
|
7556
8357
|
if (args.method === "eth_sendTransaction") await onBeforeSubmission();
|
|
7557
8358
|
return state.provider.request(args);
|
|
7558
|
-
} }, { retryCount: 0 }) : (0,
|
|
8359
|
+
} }, { retryCount: 0 }) : (0, import_viem16.custom)(state.provider)
|
|
7559
8360
|
});
|
|
7560
|
-
const walletChainClient = (0,
|
|
8361
|
+
const walletChainClient = (0, import_viem16.createPublicClient)({
|
|
7561
8362
|
chain: import_chains4.base,
|
|
7562
|
-
transport: (0,
|
|
8363
|
+
transport: (0, import_viem16.custom)(state.provider)
|
|
7563
8364
|
});
|
|
7564
8365
|
await ensureWalletOnChain(
|
|
7565
8366
|
walletChainClient,
|
|
@@ -7569,7 +8370,7 @@ var YieldseekerAgent = class {
|
|
|
7569
8370
|
const hash2 = await walletClient.sendTransaction({
|
|
7570
8371
|
account,
|
|
7571
8372
|
chain: import_chains4.base,
|
|
7572
|
-
to: (0,
|
|
8373
|
+
to: (0, import_viem16.getAddress)(transaction.to),
|
|
7573
8374
|
data: transaction.data,
|
|
7574
8375
|
value: BigInt(transaction.value)
|
|
7575
8376
|
});
|
|
@@ -7673,12 +8474,12 @@ var YieldseekerAgent = class {
|
|
|
7673
8474
|
return receipt;
|
|
7674
8475
|
}
|
|
7675
8476
|
assertTransaction(transaction, state, chainId) {
|
|
7676
|
-
if (!transaction || typeof transaction.from !== "string" || !(0,
|
|
8477
|
+
if (!transaction || typeof transaction.from !== "string" || !(0, import_viem16.isAddress)(transaction.from) || typeof transaction.to !== "string" || !(0, import_viem16.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_viem16.getAddress)(transaction.from) !== (0, import_viem16.getAddress)(state.walletAddress)) {
|
|
7677
8478
|
throw this.invalidResponse("transaction");
|
|
7678
8479
|
}
|
|
7679
8480
|
}
|
|
7680
8481
|
assertAgent(agent) {
|
|
7681
|
-
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0,
|
|
8482
|
+
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem16.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
|
|
7682
8483
|
throw this.invalidResponse("agent");
|
|
7683
8484
|
}
|
|
7684
8485
|
}
|
|
@@ -7734,6 +8535,7 @@ var YieldseekerAgent = class {
|
|
|
7734
8535
|
};
|
|
7735
8536
|
|
|
7736
8537
|
// src/lib/routing-api.ts
|
|
8538
|
+
init_errors();
|
|
7737
8539
|
var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
7738
8540
|
var getRoutingApiBaseUrl = (override) => override ?? ROUTING_API_BASE_URL2;
|
|
7739
8541
|
async function fetchOrgAgentConfig(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
|
|
@@ -7798,7 +8600,11 @@ async function fetchAgentKeys(apiKey, baseUrl = ROUTING_API_BASE_URL2) {
|
|
|
7798
8600
|
return json.data;
|
|
7799
8601
|
}
|
|
7800
8602
|
|
|
8603
|
+
// src/client.ts
|
|
8604
|
+
init_errors();
|
|
8605
|
+
|
|
7801
8606
|
// src/lib/swap/swap-api.ts
|
|
8607
|
+
init_errors();
|
|
7802
8608
|
async function request(baseUrl, apiKey, path, init) {
|
|
7803
8609
|
const url = `${baseUrl}/api/v1/swap${path}`;
|
|
7804
8610
|
const controller = new AbortController();
|
|
@@ -7975,7 +8781,7 @@ function createSwapApi(baseUrl, apiKey) {
|
|
|
7975
8781
|
}
|
|
7976
8782
|
|
|
7977
8783
|
// src/lib/swap/swap.rpc.ts
|
|
7978
|
-
var
|
|
8784
|
+
var import_viem17 = require("viem");
|
|
7979
8785
|
var DEFAULT_RPC_URLS = {
|
|
7980
8786
|
// NOT cloudflare-eth.com, which used to lead this list. It answers
|
|
7981
8787
|
// eth_chainId happily, errors on eth_blockNumber, and — the part that
|
|
@@ -8015,16 +8821,17 @@ var DEFAULT_RPC_URLS = {
|
|
|
8015
8821
|
};
|
|
8016
8822
|
function swapReadTransport(chainId, overrides) {
|
|
8017
8823
|
const override = overrides?.[chainId];
|
|
8018
|
-
if (override) return (0,
|
|
8824
|
+
if (override) return (0, import_viem17.http)(override);
|
|
8019
8825
|
const urls = DEFAULT_RPC_URLS[chainId];
|
|
8020
|
-
if (!urls || urls.length === 0) return (0,
|
|
8021
|
-
return (0,
|
|
8826
|
+
if (!urls || urls.length === 0) return (0, import_viem17.http)();
|
|
8827
|
+
return (0, import_viem17.fallback)(urls.map((url) => (0, import_viem17.http)(url)));
|
|
8022
8828
|
}
|
|
8023
8829
|
function receiptTimeoutMs(chainId) {
|
|
8024
8830
|
return chainId === 1 ? 6e5 : 18e4;
|
|
8025
8831
|
}
|
|
8026
8832
|
|
|
8027
8833
|
// src/lib/swap/swap.wrap.ts
|
|
8834
|
+
init_errors();
|
|
8028
8835
|
var WRAP_SELECTOR = "0xd0e30db0";
|
|
8029
8836
|
var FALLBACK_WRAP_GAS = 50000n;
|
|
8030
8837
|
var APPROVE_GAS = 60000n;
|
|
@@ -8128,7 +8935,11 @@ function swapChain(chainId) {
|
|
|
8128
8935
|
return CHAINS[chainId];
|
|
8129
8936
|
}
|
|
8130
8937
|
|
|
8938
|
+
// src/lib/swap/swap.executor.ts
|
|
8939
|
+
init_errors();
|
|
8940
|
+
|
|
8131
8941
|
// src/lib/swap/swap.arrival.ts
|
|
8942
|
+
init_errors();
|
|
8132
8943
|
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
8133
8944
|
var DEFAULT_POLL_MS = 4e3;
|
|
8134
8945
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -8183,7 +8994,7 @@ async function awaitBalanceIncrease(options) {
|
|
|
8183
8994
|
}
|
|
8184
8995
|
|
|
8185
8996
|
// src/lib/swap/swap.secrets.ts
|
|
8186
|
-
var
|
|
8997
|
+
var import_viem18 = require("viem");
|
|
8187
8998
|
var SECRET_BYTES = 32;
|
|
8188
8999
|
function randomBytes(length) {
|
|
8189
9000
|
const bytes = new Uint8Array(length);
|
|
@@ -8205,13 +9016,16 @@ function mintSecrets(count) {
|
|
|
8205
9016
|
const secrets = [];
|
|
8206
9017
|
const secretHashes = [];
|
|
8207
9018
|
for (let i = 0; i < count; i++) {
|
|
8208
|
-
const secret = (0,
|
|
9019
|
+
const secret = (0, import_viem18.toHex)(randomBytes(SECRET_BYTES));
|
|
8209
9020
|
secrets.push(secret);
|
|
8210
|
-
secretHashes.push((0,
|
|
9021
|
+
secretHashes.push((0, import_viem18.keccak256)(secret));
|
|
8211
9022
|
}
|
|
8212
9023
|
return { secrets, secretHashes };
|
|
8213
9024
|
}
|
|
8214
9025
|
|
|
9026
|
+
// src/lib/swap/swap.order-runner.ts
|
|
9027
|
+
init_errors();
|
|
9028
|
+
|
|
8215
9029
|
// src/lib/swap/swap.types.ts
|
|
8216
9030
|
var SWAP_TERMINAL_STATUSES = [
|
|
8217
9031
|
"executed",
|
|
@@ -8322,6 +9136,7 @@ function runFusionOrder(deps, options) {
|
|
|
8322
9136
|
}
|
|
8323
9137
|
|
|
8324
9138
|
// src/lib/swap/swap.same-chain-runner.ts
|
|
9139
|
+
init_errors();
|
|
8325
9140
|
var DEFAULT_POLL_MS3 = 5e3;
|
|
8326
9141
|
var MAX_BACKOFF_MS2 = 3e4;
|
|
8327
9142
|
var backoffFor2 = (failures, base7) => Math.min(base7 * 2 ** Math.min(failures, 5), MAX_BACKOFF_MS2);
|
|
@@ -8440,12 +9255,12 @@ function listOrders(_now = Date.now()) {
|
|
|
8440
9255
|
if (!store) return [];
|
|
8441
9256
|
const out = [];
|
|
8442
9257
|
try {
|
|
8443
|
-
const
|
|
9258
|
+
const keys2 = [];
|
|
8444
9259
|
for (let i = 0; i < store.length; i++) {
|
|
8445
9260
|
const key2 = store.key(i);
|
|
8446
|
-
if (key2?.startsWith(`${KEY_PREFIX4}.`))
|
|
9261
|
+
if (key2?.startsWith(`${KEY_PREFIX4}.`)) keys2.push(key2);
|
|
8447
9262
|
}
|
|
8448
|
-
for (const key2 of
|
|
9263
|
+
for (const key2 of keys2) {
|
|
8449
9264
|
const raw2 = store.getItem(key2);
|
|
8450
9265
|
if (!raw2) continue;
|
|
8451
9266
|
try {
|
|
@@ -8832,6 +9647,7 @@ function submissionUnknown(error, orderHash) {
|
|
|
8832
9647
|
}
|
|
8833
9648
|
|
|
8834
9649
|
// src/lib/swap/swap.withdrawal-settlement.ts
|
|
9650
|
+
init_errors();
|
|
8835
9651
|
var rawAmount = (value) => typeof value === "string" && /^\d+$/.test(value) ? BigInt(value) : void 0;
|
|
8836
9652
|
var hash = (value) => typeof value === "string" && /^0x[\da-f]{64}$/i.test(value);
|
|
8837
9653
|
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -8880,7 +9696,7 @@ async function awaitWithdrawalPayouts(options) {
|
|
|
8880
9696
|
const candidates = /* @__PURE__ */ new Map();
|
|
8881
9697
|
const toDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
8882
9698
|
const fromDate = new Date(options.submittedAt - 5e3).toISOString();
|
|
8883
|
-
const
|
|
9699
|
+
const cursors2 = /* @__PURE__ */ new Set();
|
|
8884
9700
|
let cursor;
|
|
8885
9701
|
for (let pageNumber = 0; pageNumber < 10; pageNumber++) {
|
|
8886
9702
|
assertActive();
|
|
@@ -8906,8 +9722,8 @@ async function awaitWithdrawalPayouts(options) {
|
|
|
8906
9722
|
const confirmed = inspected.flatMap((value) => value.status === "fulfilled" && value.value.transfer === "confirmed" && value.value.delivery === "confirmed" && (rawAmount(value.value.blockNumber) ?? 0n) > options.baselineBlock ? [value.value] : []);
|
|
8907
9723
|
return confirmed.length === 1 ? confirmed[0] : void 0;
|
|
8908
9724
|
}
|
|
8909
|
-
if (!page.nextCursor ||
|
|
8910
|
-
|
|
9725
|
+
if (!page.nextCursor || cursors2.has(page.nextCursor)) return;
|
|
9726
|
+
cursors2.add(page.nextCursor);
|
|
8911
9727
|
cursor = page.nextCursor;
|
|
8912
9728
|
}
|
|
8913
9729
|
};
|
|
@@ -9052,8 +9868,8 @@ function verifiedFee(payout) {
|
|
|
9052
9868
|
}
|
|
9053
9869
|
|
|
9054
9870
|
// src/lib/swap/swap.permit.ts
|
|
9055
|
-
var
|
|
9056
|
-
var PERMIT_ABI = (0,
|
|
9871
|
+
var import_viem19 = require("viem");
|
|
9872
|
+
var PERMIT_ABI = (0, import_viem19.parseAbi)([
|
|
9057
9873
|
"function nonces(address owner) view returns (uint256)",
|
|
9058
9874
|
"function name() view returns (string)",
|
|
9059
9875
|
"function version() view returns (string)",
|
|
@@ -9080,7 +9896,7 @@ async function tryRead(read2) {
|
|
|
9080
9896
|
function matchDomain(name, versions, chainId, token, onChainSeparator) {
|
|
9081
9897
|
for (const version of versions) {
|
|
9082
9898
|
const domain = { name, version, chainId, verifyingContract: token };
|
|
9083
|
-
if ((0,
|
|
9899
|
+
if ((0, import_viem19.domainSeparator)({ domain }) === onChainSeparator) return domain;
|
|
9084
9900
|
}
|
|
9085
9901
|
return null;
|
|
9086
9902
|
}
|
|
@@ -9133,9 +9949,9 @@ async function buildErc2612Permit(reads, input) {
|
|
|
9133
9949
|
primaryType: "Permit",
|
|
9134
9950
|
message: { owner, spender, value, nonce, deadline }
|
|
9135
9951
|
});
|
|
9136
|
-
const { r, s, v, yParity } = (0,
|
|
9952
|
+
const { r, s, v, yParity } = (0, import_viem19.parseSignature)(signature);
|
|
9137
9953
|
const recoveryV = v ?? BigInt(yParity + 27);
|
|
9138
|
-
return (0,
|
|
9954
|
+
return (0, import_viem19.encodeAbiParameters)(
|
|
9139
9955
|
[
|
|
9140
9956
|
{ type: "address" },
|
|
9141
9957
|
{ type: "address" },
|
|
@@ -9226,12 +10042,12 @@ function listWithdrawSwaps(now = Date.now(), includeDismissed = false) {
|
|
|
9226
10042
|
if (!store) return [];
|
|
9227
10043
|
const out = [];
|
|
9228
10044
|
try {
|
|
9229
|
-
const
|
|
10045
|
+
const keys2 = [];
|
|
9230
10046
|
for (let i = 0; i < store.length; i++) {
|
|
9231
10047
|
const key2 = store.key(i);
|
|
9232
|
-
if (key2?.startsWith(`${KEY_PREFIX5}.`))
|
|
10048
|
+
if (key2?.startsWith(`${KEY_PREFIX5}.`)) keys2.push(key2);
|
|
9233
10049
|
}
|
|
9234
|
-
for (const key2 of
|
|
10050
|
+
for (const key2 of keys2) {
|
|
9235
10051
|
const raw2 = store.getItem(key2);
|
|
9236
10052
|
if (!raw2) continue;
|
|
9237
10053
|
try {
|
|
@@ -9291,12 +10107,12 @@ function listPendingDeposits(now = Date.now()) {
|
|
|
9291
10107
|
if (!store) return [];
|
|
9292
10108
|
const out = [];
|
|
9293
10109
|
try {
|
|
9294
|
-
const
|
|
10110
|
+
const keys2 = [];
|
|
9295
10111
|
for (let i = 0; i < store.length; i++) {
|
|
9296
10112
|
const key2 = store.key(i);
|
|
9297
|
-
if (key2?.startsWith(`${KEY_PREFIX6}.`))
|
|
10113
|
+
if (key2?.startsWith(`${KEY_PREFIX6}.`)) keys2.push(key2);
|
|
9298
10114
|
}
|
|
9299
|
-
for (const key2 of
|
|
10115
|
+
for (const key2 of keys2) {
|
|
9300
10116
|
const raw2 = store.getItem(key2);
|
|
9301
10117
|
if (!raw2) continue;
|
|
9302
10118
|
try {
|
|
@@ -9317,6 +10133,7 @@ function listPendingDeposits(now = Date.now()) {
|
|
|
9317
10133
|
}
|
|
9318
10134
|
|
|
9319
10135
|
// src/lib/health-report.ts
|
|
10136
|
+
init_errors();
|
|
9320
10137
|
var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
9321
10138
|
async function reportAgentFailure(apiKey, agentType, errorCode, baseUrl = ROUTING_API_BASE_URL3) {
|
|
9322
10139
|
try {
|
|
@@ -9350,7 +10167,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
|
|
|
9350
10167
|
}
|
|
9351
10168
|
|
|
9352
10169
|
// src/lib/helpers/withdraw-helper.ts
|
|
9353
|
-
var
|
|
10170
|
+
var import_viem20 = require("viem");
|
|
9354
10171
|
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
9355
10172
|
return agents.map((agent) => {
|
|
9356
10173
|
let invalidBalance = false;
|
|
@@ -9360,7 +10177,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
9360
10177
|
return 0n;
|
|
9361
10178
|
}
|
|
9362
10179
|
const [whole, fraction] = value.split(".");
|
|
9363
|
-
return raw2 ? BigInt(value) : (0,
|
|
10180
|
+
return raw2 ? BigInt(value) : (0, import_viem20.parseUnits)(fraction === void 0 ? whole : `${whole}.${fraction.slice(0, decimals)}`, decimals);
|
|
9364
10181
|
};
|
|
9365
10182
|
const agentBalance = aggregated[agent.id];
|
|
9366
10183
|
const tokenBalance = agentBalance?.tokens.find(
|
|
@@ -9569,7 +10386,7 @@ function aggregateDailyEarnings(series, tokenSymbol) {
|
|
|
9569
10386
|
}
|
|
9570
10387
|
return [...byAsset.entries()].map(([asset, components]) => {
|
|
9571
10388
|
const dates = [...new Set(components.flatMap((points2) => points2.map((point) => point.date)))].sort();
|
|
9572
|
-
const
|
|
10389
|
+
const cursors2 = components.map((points2) => ({
|
|
9573
10390
|
index: 0,
|
|
9574
10391
|
// Providers can have different lifetime/window offsets and start dates.
|
|
9575
10392
|
// Remove each opening reading before combining their earned amounts.
|
|
@@ -9579,7 +10396,7 @@ function aggregateDailyEarnings(series, tokenSymbol) {
|
|
|
9579
10396
|
const points = dates.map((date) => {
|
|
9580
10397
|
let amount = 0;
|
|
9581
10398
|
components.forEach((component, index) => {
|
|
9582
|
-
const cursor =
|
|
10399
|
+
const cursor = cursors2[index];
|
|
9583
10400
|
while (cursor.index < component.length && component[cursor.index].date <= date) {
|
|
9584
10401
|
cursor.current = component[cursor.index++].amount;
|
|
9585
10402
|
}
|
|
@@ -9592,13 +10409,314 @@ function aggregateDailyEarnings(series, tokenSymbol) {
|
|
|
9592
10409
|
}
|
|
9593
10410
|
|
|
9594
10411
|
// src/client.ts
|
|
9595
|
-
var
|
|
10412
|
+
var import_viem24 = require("viem");
|
|
9596
10413
|
var import_chains6 = require("viem/chains");
|
|
9597
10414
|
|
|
10415
|
+
// src/lib/sponsored-token-deposit.ts
|
|
10416
|
+
init_errors();
|
|
10417
|
+
|
|
10418
|
+
// src/lib/token-batch-execution.ts
|
|
10419
|
+
var import_viem21 = require("viem");
|
|
10420
|
+
init_errors();
|
|
10421
|
+
init_token_batch_family();
|
|
10422
|
+
async function executeTokenBatch(input, initial) {
|
|
10423
|
+
let body = initial, family, ended = false;
|
|
10424
|
+
const deadlineAt = Date.now() + 9e4, controller = new AbortController();
|
|
10425
|
+
let timer;
|
|
10426
|
+
const pending2 = () => new OwneyError(
|
|
10427
|
+
"DEPOSIT_IN_PROGRESS",
|
|
10428
|
+
"Deposit is awaiting confirmation. Its transaction is still being checked.",
|
|
10429
|
+
{
|
|
10430
|
+
sponsorPending: true,
|
|
10431
|
+
phase: body.serializedTransaction ? "deposit" : "approval",
|
|
10432
|
+
txHash: body.serializedTransaction ? (0, import_viem21.keccak256)(body.serializedTransaction) : body.serializedPermitTransaction ? (0, import_viem21.keccak256)(body.serializedPermitTransaction) : void 0,
|
|
10433
|
+
notSubmitted: false,
|
|
10434
|
+
safeToFallback: false
|
|
10435
|
+
}
|
|
10436
|
+
);
|
|
10437
|
+
const assertCurrent = () => {
|
|
10438
|
+
if (ended || Date.now() >= deadlineAt) throw pending2();
|
|
10439
|
+
input.assertCurrent?.();
|
|
10440
|
+
};
|
|
10441
|
+
const timeout = new Promise((_, reject) => {
|
|
10442
|
+
timer = setTimeout(() => {
|
|
10443
|
+
ended = true;
|
|
10444
|
+
controller.abort();
|
|
10445
|
+
reject(pending2());
|
|
10446
|
+
}, 9e4);
|
|
10447
|
+
});
|
|
10448
|
+
const bounded2 = async (work) => {
|
|
10449
|
+
const value = await Promise.race([work, timeout]);
|
|
10450
|
+
assertCurrent();
|
|
10451
|
+
return value;
|
|
10452
|
+
};
|
|
10453
|
+
const post = () => bounded2(
|
|
10454
|
+
postSponsorBatchTransfer({
|
|
10455
|
+
apiKey: input.apiKey,
|
|
10456
|
+
baseUrl: input.baseUrl,
|
|
10457
|
+
body,
|
|
10458
|
+
signal: controller.signal
|
|
10459
|
+
})
|
|
10460
|
+
);
|
|
10461
|
+
const replacements = { approval: 0, deposit: 0 };
|
|
10462
|
+
const unavailable = /* @__PURE__ */ new Set();
|
|
10463
|
+
const observedApprovals = /* @__PURE__ */ new Set();
|
|
10464
|
+
const checkpointed = /* @__PURE__ */ new Set();
|
|
10465
|
+
const accounted = /* @__PURE__ */ new Set();
|
|
10466
|
+
const remember = async (phase, bytes, hash2, predecessorHash) => {
|
|
10467
|
+
assertCurrent();
|
|
10468
|
+
if ((0, import_viem21.keccak256)(bytes) !== hash2) throw pending2();
|
|
10469
|
+
const tx = (0, import_viem21.parseTransaction)(bytes);
|
|
10470
|
+
const next = {
|
|
10471
|
+
...body,
|
|
10472
|
+
[phase === "deposit" ? "serializedTransaction" : "serializedPermitTransaction"]: bytes
|
|
10473
|
+
};
|
|
10474
|
+
family = await bounded2(
|
|
10475
|
+
saveTokenBatchAttempt(
|
|
10476
|
+
input,
|
|
10477
|
+
next,
|
|
10478
|
+
{
|
|
10479
|
+
phase,
|
|
10480
|
+
hash: hash2,
|
|
10481
|
+
serializedTransaction: bytes,
|
|
10482
|
+
nonce: String(tx.nonce),
|
|
10483
|
+
predecessorHash,
|
|
10484
|
+
preparedAt: Date.now(),
|
|
10485
|
+
submissionAttempted: false
|
|
10486
|
+
},
|
|
10487
|
+
assertCurrent
|
|
10488
|
+
)
|
|
10489
|
+
);
|
|
10490
|
+
body = { ...family.body, transfers: initial.transfers };
|
|
10491
|
+
};
|
|
10492
|
+
const reference = (hash2) => family ? {
|
|
10493
|
+
authorizationId: family.authorizationId,
|
|
10494
|
+
predecessorTxHash: family.attempts.find((a) => a.hash === hash2)?.predecessorHash
|
|
10495
|
+
} : void 0;
|
|
10496
|
+
const markSubmission = async (phase) => {
|
|
10497
|
+
const hash2 = phase === "deposit" ? family?.current.deposit : family?.current.approval;
|
|
10498
|
+
if (!family || !hash2) throw pending2();
|
|
10499
|
+
if (phase === "deposit" && !checkpointed.has(hash2)) {
|
|
10500
|
+
try {
|
|
10501
|
+
await bounded2(
|
|
10502
|
+
Promise.resolve(input.onBeforeSubmission?.(hash2, reference(hash2)))
|
|
10503
|
+
);
|
|
10504
|
+
} catch (error) {
|
|
10505
|
+
if (error instanceof OwneyError && error.code === "DEPOSIT_CHECKPOINT_FAILED")
|
|
10506
|
+
throw new OwneyError(error.code, error.message, {
|
|
10507
|
+
...error.details,
|
|
10508
|
+
notSubmitted: !family.attempts.some(
|
|
10509
|
+
(a) => a.phase === "deposit" && a.submissionAttempted
|
|
10510
|
+
),
|
|
10511
|
+
safeToFallback: false
|
|
10512
|
+
});
|
|
10513
|
+
throw error;
|
|
10514
|
+
}
|
|
10515
|
+
checkpointed.add(hash2);
|
|
10516
|
+
}
|
|
10517
|
+
assertCurrent();
|
|
10518
|
+
const attempt = family.attempts.find((a) => a.hash === hash2);
|
|
10519
|
+
family = await bounded2(
|
|
10520
|
+
saveTokenBatchAttempt(
|
|
10521
|
+
input,
|
|
10522
|
+
body,
|
|
10523
|
+
{ ...attempt, submissionAttempted: true },
|
|
10524
|
+
assertCurrent
|
|
10525
|
+
)
|
|
10526
|
+
);
|
|
10527
|
+
assertCurrent();
|
|
10528
|
+
if (phase === "deposit")
|
|
10529
|
+
try {
|
|
10530
|
+
input.onSubmitted?.(hash2, reference(hash2));
|
|
10531
|
+
} catch {
|
|
10532
|
+
}
|
|
10533
|
+
assertCurrent();
|
|
10534
|
+
};
|
|
10535
|
+
const observe = async () => {
|
|
10536
|
+
if (!family) return;
|
|
10537
|
+
const observation = await bounded2(
|
|
10538
|
+
observeTokenBatchFamily({
|
|
10539
|
+
scope: input,
|
|
10540
|
+
family,
|
|
10541
|
+
pub: input.pub,
|
|
10542
|
+
deadlineAt,
|
|
10543
|
+
assertCurrent
|
|
10544
|
+
})
|
|
10545
|
+
);
|
|
10546
|
+
if (observation.status === "confirmed") {
|
|
10547
|
+
const winning = family.attempts.find(
|
|
10548
|
+
(a) => a.hash === observation.txHash
|
|
10549
|
+
);
|
|
10550
|
+
if (!accounted.has(observation.txHash)) {
|
|
10551
|
+
const accounting = new AbortController();
|
|
10552
|
+
const accountingTimer = setTimeout(() => accounting.abort(), 8e3);
|
|
10553
|
+
void postSponsorBatchTransfer({
|
|
10554
|
+
apiKey: input.apiKey,
|
|
10555
|
+
baseUrl: input.baseUrl,
|
|
10556
|
+
body: {
|
|
10557
|
+
...body,
|
|
10558
|
+
serializedTransaction: winning.serializedTransaction
|
|
10559
|
+
},
|
|
10560
|
+
signal: accounting.signal
|
|
10561
|
+
}).catch(() => {
|
|
10562
|
+
}).finally(() => clearTimeout(accountingTimer));
|
|
10563
|
+
}
|
|
10564
|
+
return observation.txHash;
|
|
10565
|
+
}
|
|
10566
|
+
if (observation.status === "failed" || observation.status === "expired")
|
|
10567
|
+
throw new OwneyError(
|
|
10568
|
+
"SPONSOR_REQUEST_FAILED",
|
|
10569
|
+
observation.status === "expired" ? "The deposit authorization expired without transferring funds. Start a new deposit." : "Sponsored deposit transactions reverted. Please retry.",
|
|
10570
|
+
{ notSubmitted: true, safeToFallback: false }
|
|
10571
|
+
);
|
|
10572
|
+
};
|
|
10573
|
+
try {
|
|
10574
|
+
assertCurrent();
|
|
10575
|
+
family = await bounded2(
|
|
10576
|
+
loadTokenBatchFamily(
|
|
10577
|
+
input,
|
|
10578
|
+
initial.serializedTransaction ? (0, import_viem21.keccak256)(initial.serializedTransaction) : initial.serializedPermitTransaction ? (0, import_viem21.keccak256)(initial.serializedPermitTransaction) : void 0
|
|
10579
|
+
)
|
|
10580
|
+
);
|
|
10581
|
+
if (family) body = { ...family.body, transfers: initial.transfers };
|
|
10582
|
+
else
|
|
10583
|
+
tokenBatchWrite(
|
|
10584
|
+
tokenBatchKey(input),
|
|
10585
|
+
JSON.stringify(tokenBatchStoredBody(body))
|
|
10586
|
+
);
|
|
10587
|
+
if (family) {
|
|
10588
|
+
const winner = await observe();
|
|
10589
|
+
if (winner) return winner;
|
|
10590
|
+
}
|
|
10591
|
+
if (family)
|
|
10592
|
+
for (const attempt of family.attempts)
|
|
10593
|
+
family = await bounded2(
|
|
10594
|
+
saveTokenBatchAttempt(input, body, attempt, assertCurrent)
|
|
10595
|
+
);
|
|
10596
|
+
let needsPost = true;
|
|
10597
|
+
while (true) {
|
|
10598
|
+
assertCurrent();
|
|
10599
|
+
const winner = await observe();
|
|
10600
|
+
if (winner) return winner;
|
|
10601
|
+
if (needsPost) {
|
|
10602
|
+
needsPost = false;
|
|
10603
|
+
const signedPhase = body.serializedTransaction ? "deposit" : body.serializedPermitTransaction ? "approval" : void 0;
|
|
10604
|
+
if (signedPhase) await markSubmission(signedPhase);
|
|
10605
|
+
let result;
|
|
10606
|
+
try {
|
|
10607
|
+
result = await post();
|
|
10608
|
+
} catch (error) {
|
|
10609
|
+
assertCurrent();
|
|
10610
|
+
if (!family) {
|
|
10611
|
+
tokenBatchClear(
|
|
10612
|
+
tokenBatchKey(input),
|
|
10613
|
+
JSON.stringify(tokenBatchStoredBody(body))
|
|
10614
|
+
);
|
|
10615
|
+
throw error;
|
|
10616
|
+
}
|
|
10617
|
+
}
|
|
10618
|
+
if (result?.serializedPermitTransaction && !body.serializedPermitTransaction) {
|
|
10619
|
+
if (!result.permitTxHash) throw pending2();
|
|
10620
|
+
await remember(
|
|
10621
|
+
"approval",
|
|
10622
|
+
result.serializedPermitTransaction,
|
|
10623
|
+
result.permitTxHash
|
|
10624
|
+
);
|
|
10625
|
+
needsPost = true;
|
|
10626
|
+
continue;
|
|
10627
|
+
}
|
|
10628
|
+
if (result?.serializedTransaction && !body.serializedTransaction) {
|
|
10629
|
+
await remember(
|
|
10630
|
+
"deposit",
|
|
10631
|
+
result.serializedTransaction,
|
|
10632
|
+
result.txHash
|
|
10633
|
+
);
|
|
10634
|
+
needsPost = true;
|
|
10635
|
+
continue;
|
|
10636
|
+
}
|
|
10637
|
+
if (result && !result.status && !result.serializedTransaction && !result.serializedPermitTransaction && family?.current.deposit === result.txHash)
|
|
10638
|
+
accounted.add(result.txHash);
|
|
10639
|
+
const winner2 = await observe();
|
|
10640
|
+
if (winner2) return winner2;
|
|
10641
|
+
}
|
|
10642
|
+
const phase = body.serializedTransaction ? "deposit" : "approval";
|
|
10643
|
+
const current = family?.current[phase];
|
|
10644
|
+
if (!current) throw pending2();
|
|
10645
|
+
if (phase === "approval" && !observedApprovals.has(current)) {
|
|
10646
|
+
const receipt = await bounded2(
|
|
10647
|
+
input.pub.getTransactionReceipt({ hash: current }).catch(() => void 0)
|
|
10648
|
+
);
|
|
10649
|
+
if (receipt?.status === "success" && receipt.transactionHash?.toLowerCase() === current.toLowerCase() && receipt.from?.toLowerCase() === family.relayer.toLowerCase() && receipt.to?.toLowerCase() === body.token.toLowerCase()) {
|
|
10650
|
+
observedApprovals.add(current);
|
|
10651
|
+
needsPost = true;
|
|
10652
|
+
continue;
|
|
10653
|
+
}
|
|
10654
|
+
}
|
|
10655
|
+
if (replacements[phase] < 2 && !unavailable.has(phase)) {
|
|
10656
|
+
let recovered;
|
|
10657
|
+
try {
|
|
10658
|
+
recovered = await bounded2(
|
|
10659
|
+
postSponsorBatchRecovery({
|
|
10660
|
+
apiKey: input.apiKey,
|
|
10661
|
+
baseUrl: input.baseUrl,
|
|
10662
|
+
body: { ...body, phase },
|
|
10663
|
+
signal: controller.signal
|
|
10664
|
+
})
|
|
10665
|
+
);
|
|
10666
|
+
} catch {
|
|
10667
|
+
assertCurrent();
|
|
10668
|
+
}
|
|
10669
|
+
assertCurrent();
|
|
10670
|
+
if (!recovered) unavailable.add(phase);
|
|
10671
|
+
else if (recovered.status === "prepared") {
|
|
10672
|
+
if (recovered.predecessorHash !== current) throw pending2();
|
|
10673
|
+
await remember(
|
|
10674
|
+
phase,
|
|
10675
|
+
recovered.serializedTransaction,
|
|
10676
|
+
recovered.txHash,
|
|
10677
|
+
current
|
|
10678
|
+
);
|
|
10679
|
+
replacements[phase]++;
|
|
10680
|
+
needsPost = true;
|
|
10681
|
+
continue;
|
|
10682
|
+
} else if (phase === "approval" && (recovered.status === "approval-satisfied" || recovered.status === "included" && recovered.outcome === "success")) {
|
|
10683
|
+
needsPost = true;
|
|
10684
|
+
} else if (recovered.status === "included" && recovered.outcome === "reverted") {
|
|
10685
|
+
if (phase === "approval" && !family.attempts.some((a) => a.phase === "deposit") && family.attempts.filter((a) => a.phase === "approval").length === 1) {
|
|
10686
|
+
finishTokenBatchFamily(input, family, {
|
|
10687
|
+
kind: "failed",
|
|
10688
|
+
blockNumber: recovered.blockNumber
|
|
10689
|
+
});
|
|
10690
|
+
throw new OwneyError(
|
|
10691
|
+
"SPONSOR_REQUEST_FAILED",
|
|
10692
|
+
"Sponsored approval reverted. Please retry.",
|
|
10693
|
+
{ notSubmitted: true, safeToFallback: false }
|
|
10694
|
+
);
|
|
10695
|
+
}
|
|
10696
|
+
unavailable.add(phase);
|
|
10697
|
+
}
|
|
10698
|
+
}
|
|
10699
|
+
await bounded2(
|
|
10700
|
+
new Promise(
|
|
10701
|
+
(resolve) => setTimeout(
|
|
10702
|
+
resolve,
|
|
10703
|
+
Math.min(2e3, Math.max(0, deadlineAt - Date.now()))
|
|
10704
|
+
)
|
|
10705
|
+
)
|
|
10706
|
+
);
|
|
10707
|
+
}
|
|
10708
|
+
} finally {
|
|
10709
|
+
ended = true;
|
|
10710
|
+
if (timer) clearTimeout(timer);
|
|
10711
|
+
controller.abort();
|
|
10712
|
+
}
|
|
10713
|
+
}
|
|
10714
|
+
|
|
9598
10715
|
// src/lib/sponsored-token-batch.ts
|
|
9599
|
-
|
|
9600
|
-
var
|
|
9601
|
-
|
|
10716
|
+
init_token_batch_family();
|
|
10717
|
+
var import_viem22 = require("viem");
|
|
10718
|
+
init_errors();
|
|
10719
|
+
init_permit2_batch();
|
|
9602
10720
|
var expiredRecords = /* @__PURE__ */ new Map();
|
|
9603
10721
|
var inflight = /* @__PURE__ */ new Map();
|
|
9604
10722
|
var planOf = (transfers) => JSON.stringify(
|
|
@@ -9607,18 +10725,7 @@ var planOf = (transfers) => JSON.stringify(
|
|
|
9607
10725
|
amount: BigInt(t.amount).toString()
|
|
9608
10726
|
}))
|
|
9609
10727
|
);
|
|
9610
|
-
var pendingKey = (i) => `owney.token-batch.v1:${(0,
|
|
9611
|
-
function pendingTokenBatch(i) {
|
|
9612
|
-
try {
|
|
9613
|
-
const saved = read(pendingKey(i));
|
|
9614
|
-
if (!saved) return;
|
|
9615
|
-
const body = JSON.parse(saved);
|
|
9616
|
-
if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem19.isAddressEqual)(body.from, i.owner) || !(0, import_viem19.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
|
|
9617
|
-
return { txHash: (0, import_viem19.keccak256)(body.serializedTransaction), transfers: body.transfers.map(({ to, amount }) => ({ to, amount })) };
|
|
9618
|
-
} catch {
|
|
9619
|
-
return;
|
|
9620
|
-
}
|
|
9621
|
-
}
|
|
10728
|
+
var pendingKey = (i) => `owney.token-batch.v1:${(0, import_viem22.keccak256)((0, import_viem22.toBytes)(i.apiKey))}:${i.baseUrl ?? "default"}:${i.chainId}:${i.owner.toLowerCase()}:${i.token.toLowerCase()}`;
|
|
9622
10729
|
async function releaseExpiredTokenBatch(i) {
|
|
9623
10730
|
const key2 = pendingKey(i);
|
|
9624
10731
|
let timer;
|
|
@@ -9627,18 +10734,18 @@ async function releaseExpiredTokenBatch(i) {
|
|
|
9627
10734
|
let active2 = read(key2);
|
|
9628
10735
|
if (active2 && i.expectedTxHash) {
|
|
9629
10736
|
const current = JSON.parse(active2);
|
|
9630
|
-
if (!current.serializedTransaction || (0,
|
|
10737
|
+
if (!current.serializedTransaction || (0, import_viem22.keccak256)(current.serializedTransaction).toLowerCase() !== i.expectedTxHash.toLowerCase())
|
|
9631
10738
|
active2 = void 0;
|
|
9632
10739
|
}
|
|
9633
10740
|
const archiveKey = i.expectedTxHash ? `${key2}:expired:${i.expectedTxHash.toLowerCase()}` : void 0;
|
|
9634
10741
|
const saved = active2 ?? (archiveKey && (expiredRecords.get(archiveKey) ?? (typeof window === "undefined" ? void 0 : window.localStorage.getItem(archiveKey))));
|
|
9635
10742
|
if (!saved) return;
|
|
9636
10743
|
const body = JSON.parse(saved);
|
|
9637
|
-
if (!body.serializedTransaction || body.chainId !== i.chainId || !(0,
|
|
9638
|
-
const txHash = (0,
|
|
10744
|
+
if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem22.isAddressEqual)(body.from, i.owner) || !(0, import_viem22.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
|
|
10745
|
+
const txHash = (0, import_viem22.keccak256)(body.serializedTransaction);
|
|
9639
10746
|
if (i.expectedTxHash && txHash.toLowerCase() !== i.expectedTxHash.toLowerCase()) return;
|
|
9640
|
-
const transaction = (0,
|
|
9641
|
-
if (transaction.chainId !== i.chainId || !transaction.to || !(0,
|
|
10747
|
+
const transaction = (0, import_viem22.parseTransaction)(body.serializedTransaction);
|
|
10748
|
+
if (transaction.chainId !== i.chainId || !transaction.to || !(0, import_viem22.isAddressEqual)(transaction.to, BATCH_PERMIT2_ADDRESS) || (transaction.value ?? 0n) !== 0n || transaction.data !== (0, import_viem22.encodeFunctionData)({
|
|
9642
10749
|
abi: PERMIT2_BATCH_ABI,
|
|
9643
10750
|
functionName: "permitWitnessTransferFrom",
|
|
9644
10751
|
args: batchArgs(body)
|
|
@@ -9667,8 +10774,7 @@ async function releaseExpiredTokenBatch(i) {
|
|
|
9667
10774
|
}
|
|
9668
10775
|
} catch {
|
|
9669
10776
|
}
|
|
9670
|
-
if (
|
|
9671
|
-
else clear(key2, body);
|
|
10777
|
+
if (persisted) clear(key2, body);
|
|
9672
10778
|
}
|
|
9673
10779
|
return { txHash, transfers: body.transfers.map(({ to, amount }) => ({ to, amount })), blockNumber: block.number };
|
|
9674
10780
|
};
|
|
@@ -9686,37 +10792,17 @@ async function releaseExpiredTokenBatch(i) {
|
|
|
9686
10792
|
if (timer) clearTimeout(timer);
|
|
9687
10793
|
}
|
|
9688
10794
|
}
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
return value && settledRecords.get(key2) === value ? void 0 : value;
|
|
9692
|
-
}
|
|
9693
|
-
function storedBody(body) {
|
|
9694
|
-
return JSON.stringify({
|
|
9695
|
-
...body,
|
|
9696
|
-
transfers: body.transfers.map(({ to, amount }) => ({ to, amount }))
|
|
9697
|
-
});
|
|
9698
|
-
}
|
|
9699
|
-
function save(key2, body) {
|
|
9700
|
-
const value = storedBody(body);
|
|
9701
|
-
if (typeof window === "undefined") memory.set(key2, value);
|
|
9702
|
-
else window.localStorage.setItem(key2, value);
|
|
9703
|
-
settledRecords.delete(key2);
|
|
9704
|
-
}
|
|
10795
|
+
var read = tokenBatchRead;
|
|
10796
|
+
var storedBody = (body) => JSON.stringify(tokenBatchStoredBody(body));
|
|
9705
10797
|
function clear(key2, body) {
|
|
9706
|
-
|
|
9707
|
-
if (typeof window === "undefined") memory.delete(key2);
|
|
9708
|
-
else window.localStorage.removeItem(key2);
|
|
9709
|
-
settledRecords.delete(key2);
|
|
9710
|
-
} catch {
|
|
9711
|
-
settledRecords.set(key2, storedBody(body));
|
|
9712
|
-
}
|
|
10798
|
+
tokenBatchClear(key2, storedBody(body));
|
|
9713
10799
|
}
|
|
9714
10800
|
function sponsorTokenBatch(i) {
|
|
9715
10801
|
const key2 = pendingKey(i);
|
|
9716
10802
|
const plan = planOf(i.transfers);
|
|
9717
10803
|
const active2 = inflight.get(key2);
|
|
9718
10804
|
if (active2) {
|
|
9719
|
-
if (active2.plan !== plan
|
|
10805
|
+
if (active2.plan !== plan)
|
|
9720
10806
|
return Promise.reject(
|
|
9721
10807
|
new Error(
|
|
9722
10808
|
"A token deposit is already in progress. Wait for its result before depositing again."
|
|
@@ -9733,136 +10819,13 @@ async function execute(i, key2, plan) {
|
|
|
9733
10819
|
(t) => BigInt(t.amount) <= 0n || BigInt(t.amount) >= 1n << 256n
|
|
9734
10820
|
) || new Set(i.transfers.map((t) => t.to.toLowerCase())).size !== i.transfers.length)
|
|
9735
10821
|
throw new Error("Invalid token deposit shares.");
|
|
9736
|
-
const send =
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
const rejectedPreparation = (error) => !body.serializedTransaction && error instanceof OwneyError && typeof error.details?.statusCode === "number" && error.details.statusCode >= 400 && error.details.statusCode < 500 && ![408, 429].includes(error.details.statusCode);
|
|
9740
|
-
try {
|
|
9741
|
-
const post = () => postSponsorBatchTransfer({ apiKey: i.apiKey, baseUrl: i.baseUrl, body });
|
|
9742
|
-
const pendingError = (phase, txHash) => new OwneyError(
|
|
9743
|
-
"DEPOSIT_IN_PROGRESS",
|
|
9744
|
-
phase === "approval" ? "Deposit approval is awaiting confirmation. Retry the same amount to continue it." : "Deposit is awaiting confirmation. Its transaction is still being checked.",
|
|
9745
|
-
{ sponsorPending: true, phase, txHash, safeToFallback: false }
|
|
9746
|
-
);
|
|
9747
|
-
const assertReceipt = (receipt, phase) => {
|
|
9748
|
-
if (receipt.status !== "success") throw new OwneyError(
|
|
9749
|
-
"SPONSOR_REQUEST_FAILED",
|
|
9750
|
-
`Sponsored ${phase} transaction reverted. Please retry.`,
|
|
9751
|
-
{ notSubmitted: true, safeToFallback: false }
|
|
9752
|
-
);
|
|
9753
|
-
};
|
|
9754
|
-
const waitForConfirmation = async (phase, hash3) => {
|
|
9755
|
-
let receipt;
|
|
9756
|
-
try {
|
|
9757
|
-
receipt = await i.pub.waitForTransactionReceipt({ hash: hash3, confirmations: 1, timeout: 9e4, checkReplacement: false });
|
|
9758
|
-
} catch {
|
|
9759
|
-
receipt = await i.pub.getTransactionReceipt({ hash: hash3 }).catch(() => void 0);
|
|
9760
|
-
}
|
|
9761
|
-
if (!receipt) throw pendingError(phase, hash3);
|
|
9762
|
-
assertReceipt(receipt, phase);
|
|
9763
|
-
};
|
|
9764
|
-
const postSigned = async (phase, hash3) => {
|
|
9765
|
-
try {
|
|
9766
|
-
return await post();
|
|
9767
|
-
} catch (error) {
|
|
9768
|
-
if (rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true) throw error;
|
|
9769
|
-
await waitForConfirmation(phase, hash3);
|
|
9770
|
-
return void 0;
|
|
9771
|
-
}
|
|
9772
|
-
};
|
|
9773
|
-
if (body.erc2612Permit && !body.serializedPermitTransaction) {
|
|
9774
|
-
const preparedPermit = await postSponsorBatchTransfer({
|
|
9775
|
-
apiKey: i.apiKey,
|
|
9776
|
-
baseUrl: i.baseUrl,
|
|
9777
|
-
body
|
|
9778
|
-
});
|
|
9779
|
-
if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0, import_viem19.keccak256)(preparedPermit.serializedPermitTransaction) !== preparedPermit.permitTxHash)
|
|
9780
|
-
throw new Error(
|
|
9781
|
-
"Sponsorship API did not return a valid prepared permit transaction."
|
|
9782
|
-
);
|
|
9783
|
-
body = {
|
|
9784
|
-
...body,
|
|
9785
|
-
serializedPermitTransaction: preparedPermit.serializedPermitTransaction
|
|
9786
|
-
};
|
|
9787
|
-
save(key2, body);
|
|
9788
|
-
}
|
|
9789
|
-
if (!body.serializedTransaction) {
|
|
9790
|
-
const permitHash = body.serializedPermitTransaction ? (0, import_viem19.keccak256)(body.serializedPermitTransaction) : void 0;
|
|
9791
|
-
let prepared = permitHash ? await postSigned("approval", permitHash) : await post();
|
|
9792
|
-
if (prepared?.status === "pending") {
|
|
9793
|
-
if (!permitHash || prepared.phase !== "approval" || prepared.txHash !== permitHash)
|
|
9794
|
-
throw new Error("Sponsorship approval does not match the pending transaction.");
|
|
9795
|
-
await waitForConfirmation("approval", permitHash);
|
|
9796
|
-
prepared = void 0;
|
|
9797
|
-
}
|
|
9798
|
-
if (!prepared) prepared = await post();
|
|
9799
|
-
if (prepared.status === "pending" && permitHash && prepared.phase === "approval" && prepared.txHash === permitHash)
|
|
9800
|
-
throw pendingError("approval", permitHash);
|
|
9801
|
-
if (!prepared.serializedTransaction || (0, import_viem19.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
|
|
9802
|
-
throw new Error(
|
|
9803
|
-
"Sponsorship API did not return a valid prepared transaction."
|
|
9804
|
-
);
|
|
9805
|
-
body = {
|
|
9806
|
-
...body,
|
|
9807
|
-
serializedTransaction: prepared.serializedTransaction
|
|
9808
|
-
};
|
|
9809
|
-
save(key2, body);
|
|
9810
|
-
}
|
|
9811
|
-
await i.onBeforeSubmission?.((0, import_viem19.keccak256)(body.serializedTransaction));
|
|
9812
|
-
try {
|
|
9813
|
-
i.onSubmitted?.((0, import_viem19.keccak256)(body.serializedTransaction));
|
|
9814
|
-
} catch {
|
|
9815
|
-
}
|
|
9816
|
-
const hash2 = (0, import_viem19.keccak256)(body.serializedTransaction);
|
|
9817
|
-
const existing = await i.pub.getTransactionReceipt({ hash: hash2 }).catch(() => void 0);
|
|
9818
|
-
if (existing) {
|
|
9819
|
-
assertReceipt(existing, "deposit");
|
|
9820
|
-
void post().catch(() => void 0);
|
|
9821
|
-
clear(key2, body);
|
|
9822
|
-
return hash2;
|
|
9823
|
-
}
|
|
9824
|
-
let result = await postSigned("deposit", hash2);
|
|
9825
|
-
if (result?.status === "pending" && result.phase === "approval" && body.serializedPermitTransaction && result.txHash === (0, import_viem19.keccak256)(body.serializedPermitTransaction)) {
|
|
9826
|
-
await waitForConfirmation("approval", result.txHash);
|
|
9827
|
-
result = await postSigned("deposit", hash2);
|
|
9828
|
-
if (result?.status === "pending" && result.phase === "approval" && result.txHash === (0, import_viem19.keccak256)(body.serializedPermitTransaction)) throw pendingError("approval", result.txHash);
|
|
9829
|
-
}
|
|
9830
|
-
if (result) {
|
|
9831
|
-
if (result.txHash !== hash2 || result.status === "pending" && result.phase !== "deposit")
|
|
9832
|
-
throw new Error("Sponsorship receipt does not match the pending transaction.");
|
|
9833
|
-
if (result.status === "pending") await waitForConfirmation("deposit", hash2);
|
|
9834
|
-
}
|
|
9835
|
-
if (!result || result.status === "pending") void post().catch(() => void 0);
|
|
9836
|
-
clear(key2, body);
|
|
9837
|
-
return hash2;
|
|
9838
|
-
} catch (error) {
|
|
9839
|
-
if (initial.serializedTransaction && error instanceof OwneyError && error.code === "DEPOSIT_CHECKPOINT_FAILED") {
|
|
9840
|
-
throw new OwneyError(
|
|
9841
|
-
error.code,
|
|
9842
|
-
"Could not save recovery of the existing deposit.",
|
|
9843
|
-
{ ...error.details, notSubmitted: false, safeToFallback: false }
|
|
9844
|
-
);
|
|
9845
|
-
}
|
|
9846
|
-
if (!body.serializedTransaction && !body.serializedPermitTransaction || rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true)
|
|
9847
|
-
clear(key2, body);
|
|
9848
|
-
throw error;
|
|
9849
|
-
}
|
|
9850
|
-
};
|
|
9851
|
-
const saved = read(key2);
|
|
9852
|
-
if (i.resumeTxHash && pendingTokenBatch(i)?.txHash !== i.resumeTxHash)
|
|
9853
|
-
throw new OwneyError("DEPOSIT_IN_PROGRESS", "The saved deposit changed. Check its status before depositing again.");
|
|
10822
|
+
const send = (body) => executeTokenBatch(i, body);
|
|
10823
|
+
const family = await loadTokenBatchFamily(i, i.resumeTxHash);
|
|
10824
|
+
const saved = family ? JSON.stringify(family.body) : read(key2);
|
|
9854
10825
|
if (saved) {
|
|
9855
10826
|
const previous = JSON.parse(saved);
|
|
9856
|
-
if (previous.chainId !== i.chainId || !(0,
|
|
9857
|
-
throw new
|
|
9858
|
-
"Retry the previous token deposit and agent split first to reconcile its status."
|
|
9859
|
-
);
|
|
9860
|
-
if (await releaseExpiredTokenBatch({ ...i, expectedTxHash: previous.serializedTransaction ? (0, import_viem19.keccak256)(previous.serializedTransaction) : void 0 }))
|
|
9861
|
-
throw new OwneyError(
|
|
9862
|
-
"SPONSOR_REQUEST_FAILED",
|
|
9863
|
-
"The deposit authorization expired without transferring funds. Start a new deposit.",
|
|
9864
|
-
{ notSubmitted: true, safeToFallback: false }
|
|
9865
|
-
);
|
|
10827
|
+
if (previous.chainId !== i.chainId || !(0, import_viem22.isAddressEqual)(previous.from, i.owner) || !(0, import_viem22.isAddressEqual)(previous.token, i.token) || planOf(previous.transfers) !== plan)
|
|
10828
|
+
throw new OwneyError("DEPOSIT_IN_PROGRESS", "Retry the previous token deposit and agent split first to reconcile its status.");
|
|
9866
10829
|
i.onApproved?.();
|
|
9867
10830
|
return send({ ...previous, transfers: i.transfers });
|
|
9868
10831
|
}
|
|
@@ -9968,8 +10931,9 @@ function makeSponsoredTokenCallback(deps) {
|
|
|
9968
10931
|
pub,
|
|
9969
10932
|
wallet,
|
|
9970
10933
|
onApproved: deps.onApproved,
|
|
9971
|
-
onSubmitted: (hash2) => deps.onSubmitted?.(hash2, transfers),
|
|
9972
|
-
onBeforeSubmission: (hash2) => deps.onBeforeSubmission?.(hash2, transfers),
|
|
10934
|
+
onSubmitted: (hash2, reference) => deps.onSubmitted?.(hash2, transfers, reference),
|
|
10935
|
+
onBeforeSubmission: (hash2, reference) => deps.onBeforeSubmission?.(hash2, transfers, reference),
|
|
10936
|
+
assertCurrent: deps.assertCurrent,
|
|
9973
10937
|
resumeTxHash: deps.resumeTxHash
|
|
9974
10938
|
});
|
|
9975
10939
|
};
|
|
@@ -9981,6 +10945,7 @@ function makeSponsoredTokenCallback(deps) {
|
|
|
9981
10945
|
}
|
|
9982
10946
|
|
|
9983
10947
|
// src/lib/agent-deposit-batch.ts
|
|
10948
|
+
init_errors();
|
|
9984
10949
|
function deferred() {
|
|
9985
10950
|
let resolve, reject;
|
|
9986
10951
|
const promise = new Promise((yes, no) => {
|
|
@@ -10028,10 +10993,10 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
|
|
|
10028
10993
|
}
|
|
10029
10994
|
const txHash = await transfer(chainId, transfers);
|
|
10030
10995
|
funding.resolve(txHash);
|
|
10031
|
-
const
|
|
10996
|
+
const settled2 = await Promise.allSettled(tasks);
|
|
10032
10997
|
const agentResults = {};
|
|
10033
10998
|
const failures = [];
|
|
10034
|
-
for (const [index, result] of
|
|
10999
|
+
for (const [index, result] of settled2.entries()) {
|
|
10035
11000
|
if (result.status === "fulfilled")
|
|
10036
11001
|
agentResults[legs[index].id] = result.value;
|
|
10037
11002
|
else failures.push(legs[index].id);
|
|
@@ -10056,7 +11021,8 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
|
|
|
10056
11021
|
}
|
|
10057
11022
|
|
|
10058
11023
|
// src/lib/sponsored-calls-deposit.ts
|
|
10059
|
-
var
|
|
11024
|
+
var import_viem23 = require("viem");
|
|
11025
|
+
init_errors();
|
|
10060
11026
|
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
10061
11027
|
var DEFAULT_MAX_POLLS = 30;
|
|
10062
11028
|
async function paymasterSupported(provider, owner, chainId) {
|
|
@@ -10064,7 +11030,7 @@ async function paymasterSupported(provider, owner, chainId) {
|
|
|
10064
11030
|
method: "wallet_getCapabilities",
|
|
10065
11031
|
params: [owner]
|
|
10066
11032
|
});
|
|
10067
|
-
const forChain = caps?.[(0,
|
|
11033
|
+
const forChain = caps?.[(0, import_viem23.toHex)(chainId)] ?? caps?.[String(chainId)];
|
|
10068
11034
|
return Boolean(forChain?.paymasterService?.supported);
|
|
10069
11035
|
}
|
|
10070
11036
|
function makeSponsoredCallsCallback(deps) {
|
|
@@ -10101,8 +11067,8 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
10101
11067
|
const calls = transfers.map((transfer) => ({
|
|
10102
11068
|
to: token,
|
|
10103
11069
|
value: "0x0",
|
|
10104
|
-
data: (0,
|
|
10105
|
-
abi:
|
|
11070
|
+
data: (0, import_viem23.encodeFunctionData)({
|
|
11071
|
+
abi: import_viem23.erc20Abi,
|
|
10106
11072
|
functionName: "transfer",
|
|
10107
11073
|
args: [transfer.to, BigInt(transfer.amount)]
|
|
10108
11074
|
})
|
|
@@ -10134,7 +11100,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
10134
11100
|
url.searchParams.append("owneyIntent", intent);
|
|
10135
11101
|
paymasterUrl = url.toString();
|
|
10136
11102
|
}
|
|
10137
|
-
const requestedId = (0,
|
|
11103
|
+
const requestedId = (0, import_viem23.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
10138
11104
|
const progress = (id, transfer) => {
|
|
10139
11105
|
try {
|
|
10140
11106
|
deps.onCallsProgress?.(id, transfers, transfer);
|
|
@@ -10152,7 +11118,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
10152
11118
|
version: "2.0.0",
|
|
10153
11119
|
id: requestedId,
|
|
10154
11120
|
from: deps.ownerAddress,
|
|
10155
|
-
chainId: (0,
|
|
11121
|
+
chainId: (0, import_viem23.toHex)(chainId),
|
|
10156
11122
|
atomicRequired: transfers.length > 1,
|
|
10157
11123
|
calls,
|
|
10158
11124
|
capabilities: {
|
|
@@ -10306,6 +11272,7 @@ var OwneySDK = class {
|
|
|
10306
11272
|
paymasterServiceUrl;
|
|
10307
11273
|
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
10308
11274
|
agentReads = new AgentReads();
|
|
11275
|
+
depositFamilyReads = /* @__PURE__ */ new Map();
|
|
10309
11276
|
recoveredFundingReads = /* @__PURE__ */ new Set();
|
|
10310
11277
|
fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
|
|
10311
11278
|
activationChecks = /* @__PURE__ */ new Map();
|
|
@@ -10384,17 +11351,17 @@ var OwneySDK = class {
|
|
|
10384
11351
|
}
|
|
10385
11352
|
disconnectAgents() {
|
|
10386
11353
|
if (this.disconnectingAgents) return this.disconnectingAgents;
|
|
10387
|
-
const
|
|
11354
|
+
const pending2 = Promise.allSettled([...this.agents.values()].map(async (agent) => agent.disconnect())).then((results) => {
|
|
10388
11355
|
const failure = results.find((result) => result.status === "rejected");
|
|
10389
11356
|
if (failure?.status === "rejected") throw failure.reason;
|
|
10390
11357
|
});
|
|
10391
|
-
this.disconnectingAgents =
|
|
10392
|
-
void
|
|
10393
|
-
if (this.disconnectingAgents ===
|
|
11358
|
+
this.disconnectingAgents = pending2;
|
|
11359
|
+
void pending2.then(() => {
|
|
11360
|
+
if (this.disconnectingAgents === pending2) this.disconnectingAgents = null;
|
|
10394
11361
|
}, () => {
|
|
10395
|
-
if (this.disconnectingAgents ===
|
|
11362
|
+
if (this.disconnectingAgents === pending2) this.disconnectingAgents = null;
|
|
10396
11363
|
});
|
|
10397
|
-
return
|
|
11364
|
+
return pending2;
|
|
10398
11365
|
}
|
|
10399
11366
|
isAgentDisabled(agentId) {
|
|
10400
11367
|
return this.disabledAgents.has(agentId);
|
|
@@ -10441,11 +11408,13 @@ var OwneySDK = class {
|
|
|
10441
11408
|
return createPaidRpcClient(VIEM_CHAIN2[chainId], this.rpcUrls);
|
|
10442
11409
|
}
|
|
10443
11410
|
/** Builds the default USDC batch callback for the connected wallet. */
|
|
10444
|
-
getDefaultSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission) {
|
|
10445
|
-
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && this.cachedSponsoredCallback)
|
|
11411
|
+
getDefaultSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission, assertSubmissionCurrent) {
|
|
11412
|
+
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent && this.cachedSponsoredCallback)
|
|
10446
11413
|
return this.cachedSponsoredCallback;
|
|
10447
11414
|
const provider = this.requireConnectedProvider();
|
|
10448
|
-
const
|
|
11415
|
+
const connection = this.requireState();
|
|
11416
|
+
const owner = connection.walletAddress;
|
|
11417
|
+
const connectedChain = connection.chainId;
|
|
10449
11418
|
const callback = makeSponsoredTokenCallback({
|
|
10450
11419
|
apiKey: this.apiKey,
|
|
10451
11420
|
baseUrl: this.routingApiBaseUrl,
|
|
@@ -10454,22 +11423,26 @@ var OwneySDK = class {
|
|
|
10454
11423
|
onSubmitted,
|
|
10455
11424
|
onBeforeSubmission,
|
|
10456
11425
|
resumeTxHash,
|
|
11426
|
+
assertCurrent: () => {
|
|
11427
|
+
assertSubmissionCurrent?.();
|
|
11428
|
+
if (!this.state || this.state !== connection || this.state.chainId !== connectedChain || this.state.provider !== provider || this.state.walletAddress.toLowerCase() !== owner.toLowerCase()) throw new OwneyError("NOT_CONNECTED", "Wallet changed before deposit submission.");
|
|
11429
|
+
},
|
|
10457
11430
|
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
10458
11431
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
10459
11432
|
// PublicClient/WalletClient param types — structurally identical at
|
|
10460
11433
|
// runtime, but the two share a name TS treats as unrelated.
|
|
10461
11434
|
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
10462
|
-
getWalletChainClient: (cid) => (0,
|
|
11435
|
+
getWalletChainClient: (cid) => (0, import_viem24.createPublicClient)({
|
|
10463
11436
|
chain: VIEM_CHAIN2[cid],
|
|
10464
|
-
transport: (0,
|
|
11437
|
+
transport: (0, import_viem24.custom)(provider)
|
|
10465
11438
|
}),
|
|
10466
|
-
getWalletClient: (cid) => (0,
|
|
11439
|
+
getWalletClient: (cid) => (0, import_viem24.createWalletClient)({
|
|
10467
11440
|
account: owner,
|
|
10468
11441
|
chain: VIEM_CHAIN2[cid],
|
|
10469
|
-
transport: (0,
|
|
11442
|
+
transport: (0, import_viem24.custom)(provider)
|
|
10470
11443
|
})
|
|
10471
11444
|
});
|
|
10472
|
-
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission) this.cachedSponsoredCallback = callback;
|
|
11445
|
+
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent) this.cachedSponsoredCallback = callback;
|
|
10473
11446
|
return callback;
|
|
10474
11447
|
}
|
|
10475
11448
|
/** Builds the wallet-native sponsored calls callback for compatible paymasters. */
|
|
@@ -10498,11 +11471,13 @@ var OwneySDK = class {
|
|
|
10498
11471
|
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
10499
11472
|
* single-use batch authorization instead of an EIP-3009 authorization.
|
|
10500
11473
|
*/
|
|
10501
|
-
getDefaultWethSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission) {
|
|
10502
|
-
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && this.cachedWethSponsoredCallback)
|
|
11474
|
+
getDefaultWethSponsoredCallback(onApproved, onSubmitted, resumeTxHash, onBeforeSubmission, assertSubmissionCurrent) {
|
|
11475
|
+
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent && this.cachedWethSponsoredCallback)
|
|
10503
11476
|
return this.cachedWethSponsoredCallback;
|
|
10504
11477
|
const provider = this.requireConnectedProvider();
|
|
10505
|
-
const
|
|
11478
|
+
const connection = this.requireState();
|
|
11479
|
+
const owner = connection.walletAddress;
|
|
11480
|
+
const connectedChain = connection.chainId;
|
|
10506
11481
|
const callback = makeSponsoredTokenCallback({
|
|
10507
11482
|
apiKey: this.apiKey,
|
|
10508
11483
|
baseUrl: this.routingApiBaseUrl,
|
|
@@ -10511,22 +11486,26 @@ var OwneySDK = class {
|
|
|
10511
11486
|
onSubmitted,
|
|
10512
11487
|
onBeforeSubmission,
|
|
10513
11488
|
resumeTxHash,
|
|
11489
|
+
assertCurrent: () => {
|
|
11490
|
+
assertSubmissionCurrent?.();
|
|
11491
|
+
if (!this.state || this.state !== connection || this.state.chainId !== connectedChain || this.state.provider !== provider || this.state.walletAddress.toLowerCase() !== owner.toLowerCase()) throw new OwneyError("NOT_CONNECTED", "Wallet changed before deposit submission.");
|
|
11492
|
+
},
|
|
10514
11493
|
tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
|
|
10515
11494
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
10516
11495
|
// PublicClient/WalletClient param types — structurally identical at
|
|
10517
11496
|
// runtime, but the two share a name TS treats as unrelated.
|
|
10518
11497
|
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
10519
|
-
getWalletChainClient: (cid) => (0,
|
|
11498
|
+
getWalletChainClient: (cid) => (0, import_viem24.createPublicClient)({
|
|
10520
11499
|
chain: VIEM_CHAIN2[cid],
|
|
10521
|
-
transport: (0,
|
|
11500
|
+
transport: (0, import_viem24.custom)(provider)
|
|
10522
11501
|
}),
|
|
10523
|
-
getWalletClient: (cid) => (0,
|
|
11502
|
+
getWalletClient: (cid) => (0, import_viem24.createWalletClient)({
|
|
10524
11503
|
account: owner,
|
|
10525
11504
|
chain: VIEM_CHAIN2[cid],
|
|
10526
|
-
transport: (0,
|
|
11505
|
+
transport: (0, import_viem24.custom)(provider)
|
|
10527
11506
|
})
|
|
10528
11507
|
});
|
|
10529
|
-
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission) this.cachedWethSponsoredCallback = callback;
|
|
11508
|
+
if (!onApproved && !onSubmitted && !resumeTxHash && !onBeforeSubmission && !assertSubmissionCurrent) this.cachedWethSponsoredCallback = callback;
|
|
10530
11509
|
return callback;
|
|
10531
11510
|
}
|
|
10532
11511
|
getAgent(agentId) {
|
|
@@ -10850,10 +11829,10 @@ var OwneySDK = class {
|
|
|
10850
11829
|
}
|
|
10851
11830
|
notifyFunding(options.onProgress, evidence);
|
|
10852
11831
|
} : void 0;
|
|
10853
|
-
const onSubmitted = onProgress ? (hash2, destinations) => {
|
|
11832
|
+
const onSubmitted = onProgress ? (hash2, destinations, depositAuthorization) => {
|
|
10854
11833
|
for (const destination of destinations) {
|
|
10855
11834
|
const evidence = prepared.get(destination.to.toLowerCase());
|
|
10856
|
-
if (evidence) notifyFunding(onProgress, { ...evidence, txHash: hash2, transfer: "pending" });
|
|
11835
|
+
if (evidence) notifyFunding(onProgress, { ...evidence, txHash: hash2, ...depositAuthorization ? { depositAuthorization } : {}, transfer: "pending" });
|
|
10857
11836
|
}
|
|
10858
11837
|
} : void 0;
|
|
10859
11838
|
const onCallsProgress = onProgress ? (callsId, destinations, transfer) => {
|
|
@@ -10895,7 +11874,7 @@ var OwneySDK = class {
|
|
|
10895
11874
|
});
|
|
10896
11875
|
await checkpoint2(evidence);
|
|
10897
11876
|
} : void 0;
|
|
10898
|
-
const checkpointHash = checkpointDestinations ? (hash2, destinations) => checkpointDestinations(destinations, { txHash: hash2 }) : void 0;
|
|
11877
|
+
const checkpointHash = checkpointDestinations ? (hash2, destinations, depositAuthorization) => checkpointDestinations(destinations, { txHash: hash2, depositAuthorization }) : void 0;
|
|
10899
11878
|
const checkpointCalls = checkpointDestinations ? (id, destinations) => checkpointDestinations(destinations, { callsId: id }) : void 0;
|
|
10900
11879
|
const checkpointPaid = checkpoint2 ? (evidence) => checkpoint2([evidence]) : void 0;
|
|
10901
11880
|
const customCallback = depositCallback && checkpointDestinations ? makeVerificationAwareDepositCallback(async (to, cid, value, verification) => {
|
|
@@ -10905,19 +11884,20 @@ var OwneySDK = class {
|
|
|
10905
11884
|
}) : depositCallback;
|
|
10906
11885
|
if (options.resumeTxHash && (depositCallback || this.paymasterServiceUrl || !/^0x[\da-f]{64}$/i.test(options.resumeTxHash)))
|
|
10907
11886
|
throw new OwneyError("DEPOSIT_IN_PROGRESS", "This deposit cannot resume the saved relayer transaction.");
|
|
10908
|
-
const effectiveCallback = customCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress, checkpointCalls) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash) : this.getDefaultSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash));
|
|
11887
|
+
const effectiveCallback = customCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved, onSubmitted, onCallsProgress, checkpointCalls) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash, options.assertSubmissionCurrent) : this.getDefaultSponsoredCallback(onApproved, onSubmitted, options.resumeTxHash, checkpointHash, options.assertSubmissionCurrent));
|
|
10909
11888
|
try {
|
|
10910
11889
|
if (options.resumeTxHash) {
|
|
10911
11890
|
const token = SupportedAssets.find((value) => value.chainId === chainId && value.symbol === asset);
|
|
10912
|
-
const
|
|
11891
|
+
const family = token && await loadTokenBatchFamily({
|
|
10913
11892
|
apiKey: this.apiKey,
|
|
10914
11893
|
baseUrl: this.routingApiBaseUrl,
|
|
10915
11894
|
owner: state.walletAddress,
|
|
10916
11895
|
chainId,
|
|
10917
11896
|
token: token.address
|
|
10918
|
-
});
|
|
11897
|
+
}, options.resumeTxHash);
|
|
11898
|
+
const pending2 = family && { transfers: family.body.transfers };
|
|
10919
11899
|
const invalid2 = () => new OwneyError("DEPOSIT_IN_PROGRESS", "The saved deposit does not match this request. Check its status before depositing again.");
|
|
10920
|
-
if (!
|
|
11900
|
+
if (!pending2 || pending2.transfers.some((transfer) => !/^\d+$/.test(transfer.amount) || BigInt(transfer.amount) <= 0n) || pending2.transfers.reduce((sum, transfer) => sum + BigInt(transfer.amount), 0n) !== BigInt(amount)) throw invalid2();
|
|
10921
11901
|
const candidates = agentId ? [this.getAgent(agentId)] : this.getEligibleAgents(chainId, asset);
|
|
10922
11902
|
const wallets = await Promise.all(candidates.map(async (agent) => {
|
|
10923
11903
|
this.validateAssetSupport(agent, chainId, asset);
|
|
@@ -10927,7 +11907,7 @@ var OwneySDK = class {
|
|
|
10927
11907
|
if (this.state !== state || this.state.chainId !== chainId)
|
|
10928
11908
|
throw new OwneyError("NOT_CONNECTED", "Wallet changed while recovering the deposit.");
|
|
10929
11909
|
const usedAgents = /* @__PURE__ */ new Set();
|
|
10930
|
-
const legs =
|
|
11910
|
+
const legs = pending2.transfers.map((transfer) => {
|
|
10931
11911
|
const matches = wallets.filter((value) => value.wallet?.toLowerCase() === transfer.to.toLowerCase());
|
|
10932
11912
|
if (matches.length !== 1 || usedAgents.has(matches[0].agent.id)) throw invalid2();
|
|
10933
11913
|
const { agent } = matches[0];
|
|
@@ -11376,8 +12356,46 @@ var OwneySDK = class {
|
|
|
11376
12356
|
if (!token) throw new OwneyError("CHAIN_UNSUPPORTED", "Unsupported funding asset.");
|
|
11377
12357
|
const rpc2 = this.getPaidRpcClient(chainId);
|
|
11378
12358
|
let receipt;
|
|
12359
|
+
if (direction === "deposit" && !evidence.callsId && !evidence.userOpHash) {
|
|
12360
|
+
const scope = {
|
|
12361
|
+
apiKey: this.apiKey,
|
|
12362
|
+
baseUrl: this.routingApiBaseUrl,
|
|
12363
|
+
owner: state.walletAddress,
|
|
12364
|
+
chainId,
|
|
12365
|
+
token: token.address
|
|
12366
|
+
};
|
|
12367
|
+
const family = await loadTokenBatchFamily(scope, evidence.txHash, !evidence.depositAuthorization);
|
|
12368
|
+
assertCurrent();
|
|
12369
|
+
if (family) {
|
|
12370
|
+
if (evidence.depositAuthorization && evidence.depositAuthorization.authorizationId !== family.authorizationId || !family.body.transfers.some((t) => t.to.toLowerCase() === agentWallet.toLowerCase() && t.amount === evidence.intendedAmount))
|
|
12371
|
+
throw new OwneyError("DEPOSIT_IN_PROGRESS", "Deposit evidence does not match its signed authorization.");
|
|
12372
|
+
const familyKey = `${tokenBatchKey(scope)}:${family.authorizationId}`;
|
|
12373
|
+
let reading = this.depositFamilyReads.get(familyKey);
|
|
12374
|
+
if (!reading) {
|
|
12375
|
+
reading = observeTokenBatchFamily({ scope, family, pub: rpc2, deadlineAt: Date.now() + 8e3, assertCurrent }).finally(() => this.depositFamilyReads.delete(familyKey));
|
|
12376
|
+
this.depositFamilyReads.set(familyKey, reading);
|
|
12377
|
+
}
|
|
12378
|
+
const result = await reading;
|
|
12379
|
+
assertCurrent();
|
|
12380
|
+
evidence = { ...evidence, depositAuthorization: { authorizationId: family.authorizationId } };
|
|
12381
|
+
if (result.status === "confirmed") {
|
|
12382
|
+
receipt = result.receipt;
|
|
12383
|
+
evidence = { ...evidence, txHash: result.txHash };
|
|
12384
|
+
} else if (result.status === "expired" || result.status === "failed")
|
|
12385
|
+
return {
|
|
12386
|
+
...evidence,
|
|
12387
|
+
agentWallet,
|
|
12388
|
+
transfer: "failed",
|
|
12389
|
+
delivery: "not-applicable",
|
|
12390
|
+
registration: "not-applicable",
|
|
12391
|
+
confirmedAmount: "0",
|
|
12392
|
+
blockNumber: (result.status === "expired" ? result.blockNumber : result.receipts.reduce((n, r) => r.blockNumber > n ? r.blockNumber : n, 0n)).toString()
|
|
12393
|
+
};
|
|
12394
|
+
else return { ...evidence, agentWallet, transfer: "unknown", delivery: "not-applicable" };
|
|
12395
|
+
}
|
|
12396
|
+
}
|
|
11379
12397
|
try {
|
|
11380
|
-
receipt
|
|
12398
|
+
receipt ??= await rpc2.getTransactionReceipt({ hash: evidence.txHash });
|
|
11381
12399
|
} catch (error) {
|
|
11382
12400
|
if (direction === "deposit") {
|
|
11383
12401
|
const expired = await releaseExpiredTokenBatch({
|
|
@@ -11497,29 +12515,65 @@ var OwneySDK = class {
|
|
|
11497
12515
|
/** Whether a foreground deposit can resume the same signed batch, never a
|
|
11498
12516
|
* fresh authorization. The batch rail independently rechecks the exact plan. */
|
|
11499
12517
|
async canResumePendingDeposit(evidences, amount) {
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
if (
|
|
11516
|
-
const
|
|
11517
|
-
const
|
|
11518
|
-
|
|
11519
|
-
|
|
12518
|
+
try {
|
|
12519
|
+
if (this.paymasterServiceUrl || !evidences.length || !/^\d+$/.test(amount)) return false;
|
|
12520
|
+
const first = evidences[0];
|
|
12521
|
+
if (!first.txHash) return false;
|
|
12522
|
+
const { state, chainId, assertCurrent } = this.captureReadScope(first.chainId);
|
|
12523
|
+
const token = SupportedAssets.find((value) => value.chainId === chainId && value.symbol === first.token);
|
|
12524
|
+
if (!token) return false;
|
|
12525
|
+
const family = await loadTokenBatchFamily({
|
|
12526
|
+
apiKey: this.apiKey,
|
|
12527
|
+
baseUrl: this.routingApiBaseUrl,
|
|
12528
|
+
owner: state.walletAddress,
|
|
12529
|
+
chainId,
|
|
12530
|
+
token: token.address
|
|
12531
|
+
}, first.txHash);
|
|
12532
|
+
const transfers = family?.body.transfers;
|
|
12533
|
+
if (!family || !transfers || transfers.length !== evidences.length || transfers.reduce((n, t) => n + BigInt(t.amount), 0n).toString() !== amount) return false;
|
|
12534
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
12535
|
+
for (const e of evidences) {
|
|
12536
|
+
if (e.chainId !== chainId || e.token !== first.token || e.walletAddress.toLowerCase() !== state.walletAddress.toLowerCase() || e.callsId || e.userOpHash || !family.attempts.some((a) => a.phase === "deposit" && a.hash.toLowerCase() === e.txHash?.toLowerCase()) || e.depositAuthorization && e.depositAuthorization.authorizationId !== family.authorizationId) return false;
|
|
12537
|
+
const agent = this.getAgent(e.agentId);
|
|
12538
|
+
const wallet = agent.getFundingWallet ? await agent.getFundingWallet(state, chainId, e.token) : (await agent.getUserProfile(state, chainId)).smartWallet;
|
|
12539
|
+
assertCurrent();
|
|
12540
|
+
if (!wallet || destinations.has(wallet.toLowerCase()) || e.agentWallet && e.agentWallet.toLowerCase() !== wallet.toLowerCase() || !transfers.some((t) => t.to.toLowerCase() === wallet.toLowerCase() && t.amount === e.intendedAmount)) return false;
|
|
12541
|
+
destinations.add(wallet.toLowerCase());
|
|
12542
|
+
}
|
|
12543
|
+
assertCurrent();
|
|
12544
|
+
return true;
|
|
12545
|
+
} catch {
|
|
12546
|
+
return false;
|
|
12547
|
+
}
|
|
12548
|
+
}
|
|
12549
|
+
/** Validate signed journal membership, never just a caller-supplied family ID. */
|
|
12550
|
+
async validateDepositReplacement(previous, next) {
|
|
12551
|
+
try {
|
|
12552
|
+
if (!previous.length || previous.length !== next.length || previous.some((e) => e.transfer === "confirmed" || !/^\d+$/.test(e.intendedAmount))) return;
|
|
12553
|
+
const amount = previous.reduce((sum, e) => sum + BigInt(e.intendedAmount), 0n).toString();
|
|
12554
|
+
if (!await this.canResumePendingDeposit(previous, amount) || !await this.canResumePendingDeposit(next, amount)) return;
|
|
12555
|
+
const { state, chainId, assertCurrent } = this.captureReadScope(previous[0].chainId);
|
|
12556
|
+
const token = SupportedAssets.find((t) => t.chainId === chainId && t.symbol === previous[0].token);
|
|
12557
|
+
const family = await loadTokenBatchFamily({
|
|
12558
|
+
apiKey: this.apiKey,
|
|
12559
|
+
baseUrl: this.routingApiBaseUrl,
|
|
12560
|
+
owner: state.walletAddress,
|
|
12561
|
+
chainId,
|
|
12562
|
+
token: token.address
|
|
12563
|
+
}, previous[0].txHash);
|
|
12564
|
+
assertCurrent();
|
|
12565
|
+
if (!family || family.terminal) return;
|
|
12566
|
+
const predecessorTxHash = previous[0].txHash, replacementTxHash = next[0].txHash;
|
|
12567
|
+
const replacement = family.attempts.find((a) => a.phase === "deposit" && a.hash.toLowerCase() === replacementTxHash.toLowerCase());
|
|
12568
|
+
if (!replacement || replacement.predecessorHash?.toLowerCase() !== predecessorTxHash.toLowerCase()) return;
|
|
12569
|
+
for (const p of previous) {
|
|
12570
|
+
const matches = next.filter((n2) => n2.agentId === p.agentId), n = matches[0];
|
|
12571
|
+
if (matches.length !== 1 || p.txHash?.toLowerCase() !== predecessorTxHash.toLowerCase() || n.txHash?.toLowerCase() !== replacementTxHash.toLowerCase() || p.intendedAmount !== n.intendedAmount || p.agentWallet?.toLowerCase() !== n.agentWallet?.toLowerCase() || n.depositAuthorization?.authorizationId !== family.authorizationId || n.depositAuthorization.predecessorTxHash?.toLowerCase() !== predecessorTxHash.toLowerCase()) return;
|
|
12572
|
+
}
|
|
12573
|
+
return { authorizationId: family.authorizationId, predecessorTxHash, replacementTxHash };
|
|
12574
|
+
} catch {
|
|
12575
|
+
return;
|
|
11520
12576
|
}
|
|
11521
|
-
assertCurrent();
|
|
11522
|
-
return true;
|
|
11523
12577
|
}
|
|
11524
12578
|
/** Optional post-payout display proof; receipt verification and the provider
|
|
11525
12579
|
* adapter must agree before attaching it to this exact balance object. */
|
|
@@ -11549,13 +12603,13 @@ var OwneySDK = class {
|
|
|
11549
12603
|
metadata
|
|
11550
12604
|
] };
|
|
11551
12605
|
};
|
|
11552
|
-
const
|
|
12606
|
+
const pending2 = Promise.race([read2(), new Promise((resolve) => {
|
|
11553
12607
|
timer = setTimeout(() => resolve(balance), 2e3);
|
|
11554
12608
|
})]).catch(() => balance).finally(() => {
|
|
11555
12609
|
if (timer) clearTimeout(timer);
|
|
11556
12610
|
});
|
|
11557
|
-
checks.set(key2,
|
|
11558
|
-
const result = await
|
|
12611
|
+
checks.set(key2, pending2);
|
|
12612
|
+
const result = await pending2;
|
|
11559
12613
|
assertCurrent();
|
|
11560
12614
|
return result;
|
|
11561
12615
|
}
|
|
@@ -11647,11 +12701,11 @@ var OwneySDK = class {
|
|
|
11647
12701
|
);
|
|
11648
12702
|
}
|
|
11649
12703
|
await ensureWalletOnChain(
|
|
11650
|
-
(0,
|
|
11651
|
-
(0,
|
|
12704
|
+
(0, import_viem24.createPublicClient)({ chain: chain2, transport: (0, import_viem24.custom)(provider) }),
|
|
12705
|
+
(0, import_viem24.createWalletClient)({
|
|
11652
12706
|
account: state.walletAddress,
|
|
11653
12707
|
chain: chain2,
|
|
11654
|
-
transport: (0,
|
|
12708
|
+
transport: (0, import_viem24.custom)(provider)
|
|
11655
12709
|
}),
|
|
11656
12710
|
chainId
|
|
11657
12711
|
);
|
|
@@ -11671,19 +12725,22 @@ var OwneySDK = class {
|
|
|
11671
12725
|
* quote's source token. A quote naming ETH would have all of them reading
|
|
11672
12726
|
* the wrong asset.
|
|
11673
12727
|
*/
|
|
11674
|
-
async wrapNativeSource(quote, walletAddress, onStage, direction) {
|
|
12728
|
+
async wrapNativeSource(quote, walletAddress, onStage, direction, assertCurrent) {
|
|
11675
12729
|
const wrapper = requireWrapper(quote);
|
|
11676
12730
|
const chainId = quote.src.chainId;
|
|
11677
12731
|
const chain2 = swapChain(chainId);
|
|
11678
12732
|
const provider = this.requireConnectedProvider();
|
|
11679
|
-
const publicClient = (0,
|
|
12733
|
+
const publicClient = (0, import_viem24.createPublicClient)({
|
|
11680
12734
|
chain: chain2,
|
|
11681
12735
|
transport: swapReadTransport(chainId, this.zyfaiRpcUrls)
|
|
11682
12736
|
});
|
|
11683
|
-
const wallet = (0,
|
|
12737
|
+
const wallet = (0, import_viem24.createWalletClient)({
|
|
11684
12738
|
account: walletAddress,
|
|
11685
12739
|
chain: chain2,
|
|
11686
|
-
transport: (0,
|
|
12740
|
+
transport: (0, import_viem24.custom)({ request: (args) => {
|
|
12741
|
+
assertCurrent?.();
|
|
12742
|
+
return provider.request(args);
|
|
12743
|
+
} })
|
|
11687
12744
|
});
|
|
11688
12745
|
onStage?.("wrapping");
|
|
11689
12746
|
const { wrapped } = await wrapNative(
|
|
@@ -11704,6 +12761,7 @@ var OwneySDK = class {
|
|
|
11704
12761
|
return fees.maxFeePerGas ?? publicClient.getGasPrice();
|
|
11705
12762
|
},
|
|
11706
12763
|
sendTransaction: async (tx, onSubmitted) => {
|
|
12764
|
+
assertCurrent?.();
|
|
11707
12765
|
const hash2 = await wallet.sendTransaction({
|
|
11708
12766
|
to: tx.to,
|
|
11709
12767
|
data: tx.data,
|
|
@@ -11790,22 +12848,22 @@ var OwneySDK = class {
|
|
|
11790
12848
|
};
|
|
11791
12849
|
const srcChain = swapChain(quote.src.chainId);
|
|
11792
12850
|
const dstChain = swapChain(quote.dst.chainId);
|
|
11793
|
-
const wallet = (0,
|
|
12851
|
+
const wallet = (0, import_viem24.createWalletClient)({
|
|
11794
12852
|
account: state.walletAddress,
|
|
11795
12853
|
chain: srcChain,
|
|
11796
12854
|
// viem can await chain/account preparation before dispatching a wallet
|
|
11797
12855
|
// request. Recheck at the transport boundary so an expired attempt or
|
|
11798
12856
|
// replaced session cannot send after that internal await completes.
|
|
11799
|
-
transport: (0,
|
|
12857
|
+
transport: (0, import_viem24.custom)({ request: (args) => {
|
|
11800
12858
|
assertWallet();
|
|
11801
12859
|
return provider.request(args);
|
|
11802
12860
|
} }, { retryCount: 0 })
|
|
11803
12861
|
});
|
|
11804
|
-
const srcPublic = (0,
|
|
12862
|
+
const srcPublic = (0, import_viem24.createPublicClient)({
|
|
11805
12863
|
chain: srcChain,
|
|
11806
12864
|
transport: swapReadTransport(quote.src.chainId, this.zyfaiRpcUrls)
|
|
11807
12865
|
});
|
|
11808
|
-
const dstPublic = (0,
|
|
12866
|
+
const dstPublic = (0, import_viem24.createPublicClient)({
|
|
11809
12867
|
chain: dstChain,
|
|
11810
12868
|
transport: swapReadTransport(quote.dst.chainId, this.zyfaiRpcUrls)
|
|
11811
12869
|
});
|
|
@@ -11822,7 +12880,7 @@ var OwneySDK = class {
|
|
|
11822
12880
|
}
|
|
11823
12881
|
return dstPublic.readContract({
|
|
11824
12882
|
address: dst,
|
|
11825
|
-
abi:
|
|
12883
|
+
abi: import_viem24.erc20Abi,
|
|
11826
12884
|
functionName: "balanceOf",
|
|
11827
12885
|
args: [state.walletAddress]
|
|
11828
12886
|
});
|
|
@@ -11964,9 +13022,9 @@ var OwneySDK = class {
|
|
|
11964
13022
|
async readTokenBalance(chainId, token) {
|
|
11965
13023
|
const state = this.requireState();
|
|
11966
13024
|
return readErc20Balance(
|
|
11967
|
-
(0,
|
|
13025
|
+
(0, import_viem24.createPublicClient)({
|
|
11968
13026
|
chain: swapChain(chainId),
|
|
11969
|
-
transport: (0,
|
|
13027
|
+
transport: (0, import_viem24.custom)(this.requireConnectedProvider())
|
|
11970
13028
|
}),
|
|
11971
13029
|
token,
|
|
11972
13030
|
state.walletAddress
|
|
@@ -11976,9 +13034,9 @@ var OwneySDK = class {
|
|
|
11976
13034
|
async readTokenPermit2Allowance(chainId, token) {
|
|
11977
13035
|
const state = this.requireState();
|
|
11978
13036
|
return readPermit2Allowance(
|
|
11979
|
-
(0,
|
|
13037
|
+
(0, import_viem24.createPublicClient)({
|
|
11980
13038
|
chain: swapChain(chainId),
|
|
11981
|
-
transport: (0,
|
|
13039
|
+
transport: (0, import_viem24.custom)(this.requireConnectedProvider())
|
|
11982
13040
|
}),
|
|
11983
13041
|
token,
|
|
11984
13042
|
state.walletAddress
|
|
@@ -11991,13 +13049,19 @@ var OwneySDK = class {
|
|
|
11991
13049
|
* Native Base/Arbitrum USDC uses sponsored ERC-2612; configured paymaster
|
|
11992
13050
|
* wallet calls also cover approval without spending the received tokens.
|
|
11993
13051
|
*/
|
|
11994
|
-
async settleSwapDepositAmount(chainId, token, symbol2, received) {
|
|
13052
|
+
async settleSwapDepositAmount(chainId, token, symbol2, received, assertCurrent) {
|
|
11995
13053
|
if (symbol2 !== "WETH" && symbol2 !== "USDC" || this.paymasterServiceUrl || supportsSponsoredErc2612(chainId, token)) {
|
|
11996
13054
|
return received.toString();
|
|
11997
13055
|
}
|
|
11998
13056
|
const allowance = await this.readTokenPermit2Allowance(chainId, token);
|
|
13057
|
+
assertCurrent?.();
|
|
11999
13058
|
if (allowance < received) {
|
|
12000
|
-
await this.approvePermit2(
|
|
13059
|
+
await this.approvePermit2(
|
|
13060
|
+
symbol2,
|
|
13061
|
+
received,
|
|
13062
|
+
chainId,
|
|
13063
|
+
...assertCurrent ? [assertCurrent] : []
|
|
13064
|
+
);
|
|
12001
13065
|
}
|
|
12002
13066
|
const balance = await this.readTokenBalance(chainId, token);
|
|
12003
13067
|
return (balance < received ? balance : received).toString();
|
|
@@ -12005,9 +13069,9 @@ var OwneySDK = class {
|
|
|
12005
13069
|
async walletSeesBalance(chainId, token, amount) {
|
|
12006
13070
|
const provider = this.requireConnectedProvider();
|
|
12007
13071
|
const state = this.requireState();
|
|
12008
|
-
const pub = (0,
|
|
13072
|
+
const pub = (0, import_viem24.createPublicClient)({
|
|
12009
13073
|
chain: swapChain(chainId),
|
|
12010
|
-
transport: (0,
|
|
13074
|
+
transport: (0, import_viem24.custom)(provider)
|
|
12011
13075
|
});
|
|
12012
13076
|
const { arrived } = await awaitBalanceIncrease({
|
|
12013
13077
|
readBalance: () => pub.readContract({
|
|
@@ -12028,7 +13092,7 @@ var OwneySDK = class {
|
|
|
12028
13092
|
* so the deposit half of `swapAndDeposit` can be exercised on its own.
|
|
12029
13093
|
*/
|
|
12030
13094
|
runSwap(quote, options) {
|
|
12031
|
-
return executeSwap(this.buildSwapDeps(quote), { quote, ...options });
|
|
13095
|
+
return executeSwap(this.buildSwapDeps(quote, options.assertCurrent), { quote, ...options });
|
|
12032
13096
|
}
|
|
12033
13097
|
/**
|
|
12034
13098
|
* The half of the swap deps that only ever talks to the routing API.
|
|
@@ -12130,7 +13194,7 @@ var OwneySDK = class {
|
|
|
12130
13194
|
async resumePendingSwaps(options = {}) {
|
|
12131
13195
|
await mapConcurrent(listWithdrawSwaps(Date.now(), true).filter((record2) => record2.txHash && record2.status === "unknown" && (!options.orderHash || options.orderHash === record2.orderHash)), async (record2) => {
|
|
12132
13196
|
try {
|
|
12133
|
-
const rpc2 = (0,
|
|
13197
|
+
const rpc2 = (0, import_viem24.createPublicClient)({ chain: swapChain(record2.srcChainId), transport: swapReadTransport(record2.srcChainId, this.zyfaiRpcUrls) });
|
|
12134
13198
|
const receipt = await bounded(
|
|
12135
13199
|
() => rpc2.getTransactionReceipt({ hash: record2.txHash }),
|
|
12136
13200
|
8e3,
|
|
@@ -12140,10 +13204,10 @@ var OwneySDK = class {
|
|
|
12140
13204
|
} catch {
|
|
12141
13205
|
}
|
|
12142
13206
|
});
|
|
12143
|
-
const
|
|
13207
|
+
const pending2 = listOrders().filter((order) => !isOrderObserved(order.orderHash) && (!options.orderHash || order.orderHash === options.orderHash));
|
|
12144
13208
|
const runner = this.swapRunnerDeps();
|
|
12145
13209
|
const sameChain = this.resumeSameChainSwaps(options);
|
|
12146
|
-
const results = await mapConcurrent(
|
|
13210
|
+
const results = await mapConcurrent(pending2, async (order) => {
|
|
12147
13211
|
try {
|
|
12148
13212
|
await runFusionOrder(runner, {
|
|
12149
13213
|
orderHash: order.orderHash,
|
|
@@ -12316,45 +13380,69 @@ var OwneySDK = class {
|
|
|
12316
13380
|
*/
|
|
12317
13381
|
async swapAndDeposit(options) {
|
|
12318
13382
|
const state = this.requireState();
|
|
13383
|
+
options.assertCurrent?.();
|
|
13384
|
+
if (options.agentId) {
|
|
13385
|
+
this.validateAssetSupport(
|
|
13386
|
+
this.getAgent(options.agentId),
|
|
13387
|
+
options.to.chainId,
|
|
13388
|
+
options.to.symbol
|
|
13389
|
+
);
|
|
13390
|
+
}
|
|
12319
13391
|
const api = this.swapApi();
|
|
12320
13392
|
const quoted = await api.quote({
|
|
12321
13393
|
from: options.from,
|
|
12322
13394
|
to: options.to,
|
|
12323
13395
|
walletAddress: state.walletAddress
|
|
12324
13396
|
});
|
|
13397
|
+
options.assertCurrent?.();
|
|
12325
13398
|
const quote = quoted.requiresOnchainOrder ? await this.wrapNativeSource(
|
|
12326
13399
|
quoted,
|
|
12327
13400
|
state.walletAddress,
|
|
12328
|
-
options.onSwapProgress
|
|
13401
|
+
options.onSwapProgress,
|
|
13402
|
+
void 0,
|
|
13403
|
+
options.assertCurrent
|
|
12329
13404
|
) : quoted;
|
|
13405
|
+
options.assertCurrent?.();
|
|
12330
13406
|
await this.ensureSwapChain(quote.src.chainId);
|
|
13407
|
+
options.assertCurrent?.();
|
|
12331
13408
|
const swap = await this.runSwap(quote, {
|
|
12332
13409
|
walletAddress: state.walletAddress,
|
|
13410
|
+
...options.assertCurrent ? { assertCurrent: options.assertCurrent } : {},
|
|
12333
13411
|
...options.slippage === void 0 ? {} : { slippage: options.slippage },
|
|
12334
13412
|
...options.onSwapProgress ? { onStage: options.onSwapProgress } : {}
|
|
12335
13413
|
});
|
|
12336
13414
|
options.onSwapProgress?.("depositing");
|
|
12337
13415
|
try {
|
|
13416
|
+
options.assertCurrent?.();
|
|
12338
13417
|
await this.ensureSwapChain(quote.dst.chainId);
|
|
13418
|
+
options.assertCurrent?.();
|
|
12339
13419
|
await this.walletSeesBalance(
|
|
12340
13420
|
quote.dst.chainId,
|
|
12341
13421
|
quote.dst.address,
|
|
12342
13422
|
BigInt(swap.received)
|
|
12343
13423
|
);
|
|
13424
|
+
options.assertCurrent?.();
|
|
12344
13425
|
const amount = await this.settleSwapDepositAmount(
|
|
12345
13426
|
quote.dst.chainId,
|
|
12346
13427
|
quote.dst.address,
|
|
12347
13428
|
options.to.symbol,
|
|
12348
|
-
BigInt(swap.received)
|
|
13429
|
+
BigInt(swap.received),
|
|
13430
|
+
options.assertCurrent
|
|
12349
13431
|
);
|
|
13432
|
+
options.assertCurrent?.();
|
|
13433
|
+
await options.onBeforeDeposit?.();
|
|
13434
|
+
options.assertCurrent?.();
|
|
12350
13435
|
const deposit = await this.deposit({
|
|
12351
13436
|
amount,
|
|
12352
13437
|
asset: options.to.symbol,
|
|
12353
|
-
...options.agentId ? { agentId: options.agentId } : {}
|
|
13438
|
+
...options.agentId ? { agentId: options.agentId } : {},
|
|
13439
|
+
...options.onDepositProgress ? { onProgress: options.onDepositProgress } : {},
|
|
13440
|
+
...options.onBeforeDepositSubmission ? { onBeforeSubmission: options.onBeforeDepositSubmission } : {},
|
|
13441
|
+
...options.assertCurrent ? { assertSubmissionCurrent: options.assertCurrent } : {}
|
|
12354
13442
|
});
|
|
12355
13443
|
return { swap, deposit, deposited: amount };
|
|
12356
13444
|
} catch (error) {
|
|
12357
|
-
const
|
|
13445
|
+
const pending2 = {
|
|
12358
13446
|
id: `${quote.dst.chainId}-${options.to.symbol}-${Date.now()}`,
|
|
12359
13447
|
received: swap.received,
|
|
12360
13448
|
symbol: options.to.symbol,
|
|
@@ -12362,12 +13450,12 @@ var OwneySDK = class {
|
|
|
12362
13450
|
...options.agentId ? { agentId: options.agentId } : {},
|
|
12363
13451
|
createdAt: Date.now()
|
|
12364
13452
|
};
|
|
12365
|
-
savePendingDeposit(
|
|
13453
|
+
savePendingDeposit(pending2);
|
|
12366
13454
|
throw new OwneyError(
|
|
12367
13455
|
"SWAP_DEPOSIT_PENDING",
|
|
12368
13456
|
`The swap went through and your ${options.to.symbol} is in your wallet, but adding it to the agent didn't complete. Nothing needs swapping again.`,
|
|
12369
13457
|
{
|
|
12370
|
-
...
|
|
13458
|
+
...pending2,
|
|
12371
13459
|
cause: error instanceof Error ? error.message : String(error),
|
|
12372
13460
|
...error instanceof OwneyError ? { causeCode: error.code } : {}
|
|
12373
13461
|
}
|
|
@@ -12390,7 +13478,7 @@ var OwneySDK = class {
|
|
|
12390
13478
|
"Some withdrawal results remain unknown. Check Activity and balances before continuing.",
|
|
12391
13479
|
{ reason: "WITHDRAWAL_RESULTS_UNAVAILABLE", swapSubmitted: false }
|
|
12392
13480
|
);
|
|
12393
|
-
const rpc2 = (0,
|
|
13481
|
+
const rpc2 = (0, import_viem24.createPublicClient)({
|
|
12394
13482
|
chain: VIEM_CHAIN2[record2.srcChainId],
|
|
12395
13483
|
transport: swapReadTransport(record2.srcChainId, this.zyfaiRpcUrls)
|
|
12396
13484
|
});
|
|
@@ -12423,7 +13511,7 @@ var OwneySDK = class {
|
|
|
12423
13511
|
baselineBlock: BigInt(recovery.baselineBlock),
|
|
12424
13512
|
timeoutMs: 3e4,
|
|
12425
13513
|
assertCurrent: assertRecoveryCurrent,
|
|
12426
|
-
readBalance: () => rpc2.readContract({ address: asset.address, abi:
|
|
13514
|
+
readBalance: () => rpc2.readContract({ address: asset.address, abi: import_viem24.erc20Abi, functionName: "balanceOf", args: [state.walletAddress] }),
|
|
12427
13515
|
inspect: (value, fromHistory) => this.inspectFunding(value, "withdraw", { requireAmountMatch: fromHistory, refreshBalance: false }),
|
|
12428
13516
|
resolve: (value) => this.resolveSponsoredWithdrawalEvidence(value, { submittedAt: recovery.submittedAt }),
|
|
12429
13517
|
history: (value, fromDate, filters) => this.getFundingHistory(value, fromDate, filters),
|
|
@@ -12527,13 +13615,13 @@ var OwneySDK = class {
|
|
|
12527
13615
|
);
|
|
12528
13616
|
}
|
|
12529
13617
|
const srcChain = VIEM_CHAIN2[options.from.chainId];
|
|
12530
|
-
const srcPublic = (0,
|
|
13618
|
+
const srcPublic = (0, import_viem24.createPublicClient)({
|
|
12531
13619
|
chain: srcChain,
|
|
12532
13620
|
transport: swapReadTransport(options.from.chainId, this.zyfaiRpcUrls)
|
|
12533
13621
|
});
|
|
12534
13622
|
const readWalletBalance = () => srcPublic.readContract({
|
|
12535
13623
|
address: asset.address,
|
|
12536
|
-
abi:
|
|
13624
|
+
abi: import_viem24.erc20Abi,
|
|
12537
13625
|
functionName: "balanceOf",
|
|
12538
13626
|
args: [state.walletAddress]
|
|
12539
13627
|
});
|
|
@@ -12554,7 +13642,7 @@ var OwneySDK = class {
|
|
|
12554
13642
|
});
|
|
12555
13643
|
options.onSwapProgress?.("withdrawing");
|
|
12556
13644
|
const submittedAt = saved?.recovery?.submittedAt ?? Date.now();
|
|
12557
|
-
const requested = saved ? saved.recovery.requested === void 0 ? void 0 : BigInt(saved.recovery.requested) : options.amount === void 0 ? void 0 : (0,
|
|
13645
|
+
const requested = saved ? saved.recovery.requested === void 0 ? void 0 : BigInt(saved.recovery.requested) : options.amount === void 0 ? void 0 : (0, import_viem24.parseUnits)(options.amount, asset.decimals);
|
|
12558
13646
|
confirmationDeadline = Date.now() + (options.arrivalTimeoutMs ?? 18e4);
|
|
12559
13647
|
const attemptId = saved?.recovery?.attemptId ?? `withdraw-${globalThis.crypto.randomUUID()}`;
|
|
12560
13648
|
record2 = saved ?? {
|
|
@@ -12879,12 +13967,12 @@ var OwneySDK = class {
|
|
|
12879
13967
|
const submissionEvidence = /* @__PURE__ */ new Map();
|
|
12880
13968
|
const pendingSubmissions = () => Object.fromEntries([...submissionEvidence].filter(([id, evidence]) => evidence.agentId === id && evidence.chainId === chainId && evidence.token === token && evidence.walletAddress.toLowerCase() === state.walletAddress.toLowerCase() && evidence.transfer !== "failed" && evidence.delivery !== "failed" && (evidence.transfer === "unknown" || evidence.txHash || evidence.userOpHash || evidence.callsId)));
|
|
12881
13969
|
const throwUnconfirmed = (agentErrors2) => {
|
|
12882
|
-
const
|
|
12883
|
-
if (Object.keys(
|
|
13970
|
+
const pending2 = pendingSubmissions();
|
|
13971
|
+
if (Object.keys(pending2).length)
|
|
12884
13972
|
throw new OwneyError(
|
|
12885
13973
|
"WITHDRAW_UNCONFIRMED",
|
|
12886
13974
|
"The withdrawal was submitted, but its outcome could not be confirmed yet.",
|
|
12887
|
-
{ asset, amount, agentErrors: agentErrors2, agentFailures, pendingSubmissions:
|
|
13975
|
+
{ asset, amount, agentErrors: agentErrors2, agentFailures, pendingSubmissions: pending2 }
|
|
12888
13976
|
);
|
|
12889
13977
|
};
|
|
12890
13978
|
const submit = async (agent, requested2) => {
|
|
@@ -13045,7 +14133,7 @@ var OwneySDK = class {
|
|
|
13045
14133
|
if (this.isUserRejectedWithdrawal(originalFailure)) throw originalFailure;
|
|
13046
14134
|
if (entry.balance !== 0n && entry.agent.id !== "yieldseeker") {
|
|
13047
14135
|
const total = aggregated.agentBalances[entry.agent.id]?.assetBalances?.find((value) => value.chainId === chainId && value.asset.toUpperCase() === token);
|
|
13048
|
-
if (!total || (0,
|
|
14136
|
+
if (!total || (0, import_viem24.parseUnits)(total.amount, assetInfo.decimals) <= entry.balance) return;
|
|
13049
14137
|
}
|
|
13050
14138
|
try {
|
|
13051
14139
|
const otherAvailable = indexedAvailable - entry.balance;
|
|
@@ -13337,15 +14425,15 @@ var OwneySDK = class {
|
|
|
13337
14425
|
return this.aggregateEarnings([...this.getActiveAgents().entries()], refreshAgent);
|
|
13338
14426
|
}
|
|
13339
14427
|
async aggregateEarnings(entries, read2) {
|
|
13340
|
-
const
|
|
14428
|
+
const settled2 = await Promise.allSettled(entries.map(([, agent]) => read2(agent)));
|
|
13341
14429
|
const agentEarnings = {};
|
|
13342
14430
|
const agentErrors = {};
|
|
13343
14431
|
const agentRetryAt = {};
|
|
13344
14432
|
const failures = [];
|
|
13345
14433
|
let totalEarnings = 0;
|
|
13346
|
-
for (let i = 0; i <
|
|
14434
|
+
for (let i = 0; i < settled2.length; i++) {
|
|
13347
14435
|
const [id] = entries[i];
|
|
13348
|
-
const result =
|
|
14436
|
+
const result = settled2[i];
|
|
13349
14437
|
if (result.status === "fulfilled") {
|
|
13350
14438
|
agentEarnings[id] = result.value;
|
|
13351
14439
|
totalEarnings += Number(result.value.lifetimeEarnings);
|
|
@@ -13414,7 +14502,7 @@ var OwneySDK = class {
|
|
|
13414
14502
|
const entries = [...this.getActiveAgents().entries()].filter(
|
|
13415
14503
|
([, agent]) => agent.getDailyEarnings
|
|
13416
14504
|
);
|
|
13417
|
-
const
|
|
14505
|
+
const settled2 = await Promise.allSettled(
|
|
13418
14506
|
entries.map(
|
|
13419
14507
|
([, agent]) => this.readAgent(
|
|
13420
14508
|
agent,
|
|
@@ -13424,9 +14512,9 @@ var OwneySDK = class {
|
|
|
13424
14512
|
)
|
|
13425
14513
|
)
|
|
13426
14514
|
);
|
|
13427
|
-
const series =
|
|
14515
|
+
const series = settled2.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
|
13428
14516
|
if (entries.length && !series.length) {
|
|
13429
|
-
const failure =
|
|
14517
|
+
const failure = settled2.find((result) => result.status === "rejected");
|
|
13430
14518
|
if (failure?.status === "rejected") throw failure.reason;
|
|
13431
14519
|
}
|
|
13432
14520
|
return {
|
|
@@ -13649,12 +14737,12 @@ var OwneySDK = class {
|
|
|
13649
14737
|
]);
|
|
13650
14738
|
const existing = this.activationChecks.get(key2);
|
|
13651
14739
|
if (existing) return existing;
|
|
13652
|
-
const
|
|
13653
|
-
if (this.activationChecks.get(key2) ===
|
|
14740
|
+
const pending2 = Promise.resolve().then(() => agent.ensureAutoSelectProtocols(state, chainId, asset)).finally(() => {
|
|
14741
|
+
if (this.activationChecks.get(key2) === pending2)
|
|
13654
14742
|
this.activationChecks.delete(key2);
|
|
13655
14743
|
});
|
|
13656
|
-
this.activationChecks.set(key2,
|
|
13657
|
-
return
|
|
14744
|
+
this.activationChecks.set(key2, pending2);
|
|
14745
|
+
return pending2;
|
|
13658
14746
|
}
|
|
13659
14747
|
/**
|
|
13660
14748
|
* User-paid approval of Permit2 on the selected token for the active chain.
|
|
@@ -13667,7 +14755,7 @@ var OwneySDK = class {
|
|
|
13667
14755
|
* @param expectedChainId Chain captured by the deposit that requested approval.
|
|
13668
14756
|
* @returns the approval transaction hash.
|
|
13669
14757
|
*/
|
|
13670
|
-
async approvePermit2(asset = "WETH", requiredAmount = 0n, expectedChainId) {
|
|
14758
|
+
async approvePermit2(asset = "WETH", requiredAmount = 0n, expectedChainId, assertCurrent) {
|
|
13671
14759
|
const state = this.requireState();
|
|
13672
14760
|
const chainId = expectedChainId ?? this.requireChainId();
|
|
13673
14761
|
this.getEligibleAgents(chainId, asset, { excludeDisabled: true });
|
|
@@ -13679,18 +14767,22 @@ var OwneySDK = class {
|
|
|
13679
14767
|
);
|
|
13680
14768
|
}
|
|
13681
14769
|
const provider = this.requireConnectedProvider();
|
|
13682
|
-
const walletChainClient = (0,
|
|
14770
|
+
const walletChainClient = (0, import_viem24.createPublicClient)({
|
|
13683
14771
|
chain: VIEM_CHAIN2[chainId],
|
|
13684
|
-
transport: (0,
|
|
14772
|
+
transport: (0, import_viem24.custom)(provider)
|
|
13685
14773
|
});
|
|
13686
14774
|
const publicClient = this.getPaidRpcClient(chainId);
|
|
13687
14775
|
const approvalAmount = permit2ApprovalAmount(requiredAmount);
|
|
13688
|
-
const wallet = (0,
|
|
14776
|
+
const wallet = (0, import_viem24.createWalletClient)({
|
|
13689
14777
|
account: state.walletAddress,
|
|
13690
14778
|
chain: VIEM_CHAIN2[chainId],
|
|
13691
|
-
transport: (0,
|
|
14779
|
+
transport: (0, import_viem24.custom)({ request: (args) => {
|
|
14780
|
+
assertCurrent?.();
|
|
14781
|
+
return provider.request(args);
|
|
14782
|
+
} })
|
|
13692
14783
|
});
|
|
13693
14784
|
await ensureWalletOnChain(walletChainClient, wallet, chainId);
|
|
14785
|
+
assertCurrent?.();
|
|
13694
14786
|
const hash2 = await wallet.writeContract({
|
|
13695
14787
|
address: token,
|
|
13696
14788
|
abi: ERC20_ALLOWANCE_ABI,
|
|
@@ -13829,10 +14921,10 @@ var OwneySDK = class {
|
|
|
13829
14921
|
const agentErrors = {};
|
|
13830
14922
|
const agentFailures = [];
|
|
13831
14923
|
for (let i = 0; i < balanceResults.length; i++) {
|
|
13832
|
-
const
|
|
14924
|
+
const settled2 = balanceResults[i];
|
|
13833
14925
|
const [aid] = entries[i];
|
|
13834
|
-
if (
|
|
13835
|
-
const [id, positions] =
|
|
14926
|
+
if (settled2.status === "fulfilled") {
|
|
14927
|
+
const [id, positions] = settled2.value;
|
|
13836
14928
|
const per = computeAllocationApy(positions);
|
|
13837
14929
|
agentApy[id] = {
|
|
13838
14930
|
totalApy: per.totalApy,
|
|
@@ -13841,7 +14933,7 @@ var OwneySDK = class {
|
|
|
13841
14933
|
allPositions.push(...positions);
|
|
13842
14934
|
successCount += 1;
|
|
13843
14935
|
} else {
|
|
13844
|
-
const reason =
|
|
14936
|
+
const reason = settled2.reason;
|
|
13845
14937
|
agentFailures.push(reason);
|
|
13846
14938
|
agentErrors[aid] = reason instanceof Error ? reason.message : String(reason);
|
|
13847
14939
|
console.error(`getAllocationApy agent "${aid}" failed:`, reason);
|
|
@@ -13863,8 +14955,11 @@ var OwneySDK = class {
|
|
|
13863
14955
|
}
|
|
13864
14956
|
};
|
|
13865
14957
|
|
|
14958
|
+
// src/index.ts
|
|
14959
|
+
init_errors();
|
|
14960
|
+
|
|
13866
14961
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
13867
|
-
var
|
|
14962
|
+
var import_viem25 = require("viem");
|
|
13868
14963
|
var import_siwe2 = require("siwe");
|
|
13869
14964
|
var import_sdk2 = require("@zyfai/sdk");
|
|
13870
14965
|
|
|
@@ -13991,7 +15086,7 @@ function buildSIWXConfig(deps) {
|
|
|
13991
15086
|
issuedAt,
|
|
13992
15087
|
toString() {
|
|
13993
15088
|
return new import_siwe2.SiweMessage({
|
|
13994
|
-
address: (0,
|
|
15089
|
+
address: (0, import_viem25.getAddress)(accountAddress),
|
|
13995
15090
|
chainId: numericChainId(chainId),
|
|
13996
15091
|
domain,
|
|
13997
15092
|
uri,
|