@owney/sdk 0.7.12-beta.1 → 0.7.12-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +213 -892
- package/dist/index.d.cts +5 -33
- package/dist/index.d.ts +5 -33
- package/dist/index.js +189 -211
- package/package.json +1 -3
- package/dist/chunk-PWIKIQOX.js +0 -140
- package/dist/surfliquid.agent-VNGQUSXN.js +0 -473
package/dist/index.cjs
CHANGED
|
@@ -3,14 +3,6 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __esm = (fn, res, err) => function __init() {
|
|
7
|
-
if (err) throw err[0];
|
|
8
|
-
try {
|
|
9
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
-
} catch (e) {
|
|
11
|
-
throw err = [e], e;
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
6
|
var __export = (target, all) => {
|
|
15
7
|
for (var name in all)
|
|
16
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -25,645 +17,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
25
17
|
};
|
|
26
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
19
|
|
|
28
|
-
// src/errors.ts
|
|
29
|
-
var OwneyError, AgentNotFoundError, NotConnectedError, AgentChainIncompatibleError;
|
|
30
|
-
var init_errors = __esm({
|
|
31
|
-
"src/errors.ts"() {
|
|
32
|
-
"use strict";
|
|
33
|
-
OwneyError = class extends Error {
|
|
34
|
-
code;
|
|
35
|
-
details;
|
|
36
|
-
agentId;
|
|
37
|
-
constructor(code, message, details, agentId) {
|
|
38
|
-
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
39
|
-
super(`${prefix} ${message}`);
|
|
40
|
-
this.name = "OwneyError";
|
|
41
|
-
this.code = code;
|
|
42
|
-
this.details = details;
|
|
43
|
-
this.agentId = agentId;
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
AgentNotFoundError = class extends OwneyError {
|
|
47
|
-
constructor(agentId, available) {
|
|
48
|
-
super(
|
|
49
|
-
"AGENT_NOT_FOUND",
|
|
50
|
-
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
51
|
-
{ agentId, available },
|
|
52
|
-
agentId
|
|
53
|
-
);
|
|
54
|
-
this.name = "AgentNotFoundError";
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
NotConnectedError = class extends OwneyError {
|
|
58
|
-
constructor() {
|
|
59
|
-
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
60
|
-
this.name = "NotConnectedError";
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
AgentChainIncompatibleError = class extends OwneyError {
|
|
64
|
-
incompatibleAgents;
|
|
65
|
-
connectedChainId;
|
|
66
|
-
constructor(incompatibleAgents, connectedChainId) {
|
|
67
|
-
const details = incompatibleAgents.map(
|
|
68
|
-
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
69
|
-
).join("; ");
|
|
70
|
-
super(
|
|
71
|
-
"AGENT_CHAIN_INCOMPATIBLE",
|
|
72
|
-
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
73
|
-
{ incompatibleAgents, connectedChainId }
|
|
74
|
-
);
|
|
75
|
-
this.name = "AgentChainIncompatibleError";
|
|
76
|
-
this.incompatibleAgents = incompatibleAgents;
|
|
77
|
-
this.connectedChainId = connectedChainId;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// src/lib/permit2.ts
|
|
84
|
-
function buildPermitTransferFromTypedData(input) {
|
|
85
|
-
return {
|
|
86
|
-
domain: {
|
|
87
|
-
name: "Permit2",
|
|
88
|
-
chainId: input.chainId,
|
|
89
|
-
verifyingContract: PERMIT2_ADDRESS
|
|
90
|
-
},
|
|
91
|
-
types: {
|
|
92
|
-
PermitTransferFrom: [
|
|
93
|
-
{ name: "permitted", type: "TokenPermissions" },
|
|
94
|
-
{ name: "spender", type: "address" },
|
|
95
|
-
{ name: "nonce", type: "uint256" },
|
|
96
|
-
{ name: "deadline", type: "uint256" }
|
|
97
|
-
],
|
|
98
|
-
TokenPermissions: [
|
|
99
|
-
{ name: "token", type: "address" },
|
|
100
|
-
{ name: "amount", type: "uint256" }
|
|
101
|
-
]
|
|
102
|
-
},
|
|
103
|
-
primaryType: "PermitTransferFrom",
|
|
104
|
-
message: input.message
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function randomPermit2Nonce() {
|
|
108
|
-
const bytes = new Uint8Array(32);
|
|
109
|
-
globalThis.crypto.getRandomValues(bytes);
|
|
110
|
-
return BigInt((0, import_viem4.bytesToHex)(bytes));
|
|
111
|
-
}
|
|
112
|
-
async function readPermit2Allowance(publicClient, token, owner) {
|
|
113
|
-
return publicClient.readContract({
|
|
114
|
-
address: token,
|
|
115
|
-
abi: ERC20_ALLOWANCE_ABI,
|
|
116
|
-
functionName: "allowance",
|
|
117
|
-
args: [owner, PERMIT2_ADDRESS]
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
async function readErc20Balance(publicClient, token, owner) {
|
|
121
|
-
return publicClient.readContract({
|
|
122
|
-
address: token,
|
|
123
|
-
abi: ERC20_ALLOWANCE_ABI,
|
|
124
|
-
functionName: "balanceOf",
|
|
125
|
-
args: [owner]
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
var import_viem4, PERMIT2_ADDRESS, MAX_UINT256, ERC20_ALLOWANCE_ABI;
|
|
129
|
-
var init_permit2 = __esm({
|
|
130
|
-
"src/lib/permit2.ts"() {
|
|
131
|
-
"use strict";
|
|
132
|
-
import_viem4 = require("viem");
|
|
133
|
-
PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
134
|
-
MAX_UINT256 = 2n ** 256n - 1n;
|
|
135
|
-
ERC20_ALLOWANCE_ABI = [
|
|
136
|
-
{
|
|
137
|
-
type: "function",
|
|
138
|
-
name: "allowance",
|
|
139
|
-
stateMutability: "view",
|
|
140
|
-
inputs: [
|
|
141
|
-
{ name: "owner", type: "address" },
|
|
142
|
-
{ name: "spender", type: "address" }
|
|
143
|
-
],
|
|
144
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
type: "function",
|
|
148
|
-
name: "approve",
|
|
149
|
-
stateMutability: "nonpayable",
|
|
150
|
-
inputs: [
|
|
151
|
-
{ name: "spender", type: "address" },
|
|
152
|
-
{ name: "amount", type: "uint256" }
|
|
153
|
-
],
|
|
154
|
-
outputs: [{ name: "", type: "bool" }]
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
type: "function",
|
|
158
|
-
name: "balanceOf",
|
|
159
|
-
stateMutability: "view",
|
|
160
|
-
inputs: [{ name: "account", type: "address" }],
|
|
161
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
162
|
-
}
|
|
163
|
-
];
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// src/agents/surfliquid/surfliquid.constants.ts
|
|
168
|
-
var SURFLIQUID_CHAIN_ID, SURFLIQUID_CHAIN_NAME, SURFLIQUID_USDC_ADDRESS, SURFLIQUID_USDC_DECIMALS, SURFLIQUID_MIN_DEPOSIT, SURFLIQUID_APPROVAL_TARGET, SURFLIQUID_SUPPORTED_ASSETS, SURFLIQUID_ACTION_MAP;
|
|
169
|
-
var init_surfliquid_constants = __esm({
|
|
170
|
-
"src/agents/surfliquid/surfliquid.constants.ts"() {
|
|
171
|
-
"use strict";
|
|
172
|
-
SURFLIQUID_CHAIN_ID = 8453;
|
|
173
|
-
SURFLIQUID_CHAIN_NAME = "BASE";
|
|
174
|
-
SURFLIQUID_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
175
|
-
SURFLIQUID_USDC_DECIMALS = 6;
|
|
176
|
-
SURFLIQUID_MIN_DEPOSIT = "0";
|
|
177
|
-
SURFLIQUID_APPROVAL_TARGET = 100000000000n;
|
|
178
|
-
SURFLIQUID_SUPPORTED_ASSETS = [
|
|
179
|
-
{
|
|
180
|
-
chainId: SURFLIQUID_CHAIN_ID,
|
|
181
|
-
chain: SURFLIQUID_CHAIN_NAME,
|
|
182
|
-
assets: [{ symbol: "USDC", minDepositAmount: SURFLIQUID_MIN_DEPOSIT }]
|
|
183
|
-
}
|
|
184
|
-
];
|
|
185
|
-
SURFLIQUID_ACTION_MAP = {
|
|
186
|
-
// INITIAL_DEPOSIT is the user's real first deposit, so surface it like any
|
|
187
|
-
// other funding ("Top up"). The mini-app intentionally hides the "Deposit"
|
|
188
|
-
// action (it marks Zyfai's smart-account-creation event), which would
|
|
189
|
-
// otherwise drop a SurfLiquid user's only history row.
|
|
190
|
-
INITIAL_DEPOSIT: "Top up",
|
|
191
|
-
DEPOSIT: "Top up",
|
|
192
|
-
USER_DEPOSIT: "Top up",
|
|
193
|
-
WITHDRAWAL: "Withdraw",
|
|
194
|
-
USER_WITHDRAWAL: "Withdraw",
|
|
195
|
-
REBALANCE: "Rebalance",
|
|
196
|
-
REBALANCE_COMPLETED: "Rebalance",
|
|
197
|
-
CROSS_CHAIN_REBALANCE: "Rebalance",
|
|
198
|
-
MERKL_CLAIM: "Earned"
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
// src/agents/surfliquid/surfliquid.mapper.ts
|
|
204
|
-
function mapMessage(message) {
|
|
205
|
-
const action = SURFLIQUID_ACTION_MAP[message.transactionType];
|
|
206
|
-
if (!action) return null;
|
|
207
|
-
return {
|
|
208
|
-
agent: "surfliquid",
|
|
209
|
-
action,
|
|
210
|
-
date: message.timestamp,
|
|
211
|
-
oldApy: message.apyBefore != null ? String(message.apyBefore) : null,
|
|
212
|
-
newApy: message.apyAfter != null ? String(message.apyAfter) : null,
|
|
213
|
-
transactions: [
|
|
214
|
-
{
|
|
215
|
-
txHashes: [message.txHash],
|
|
216
|
-
chainId: message.chainId,
|
|
217
|
-
tokenSymbol: message.token ?? void 0,
|
|
218
|
-
amount: message.amount != null ? String(message.amount) : void 0
|
|
219
|
-
}
|
|
220
|
-
],
|
|
221
|
-
rebalanceLog: []
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
function mapHistory(result, _chainId) {
|
|
225
|
-
const data = result.messages.map(mapMessage).filter((entry) => entry !== null);
|
|
226
|
-
const hasMore = result.page < result.pages;
|
|
227
|
-
return {
|
|
228
|
-
data,
|
|
229
|
-
hasMore,
|
|
230
|
-
nextCursor: hasMore ? String(result.page + 1) : void 0
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
function mapBalances2(vault, chainId, morphoStats) {
|
|
234
|
-
const assets = (vault.assets ?? []).filter(
|
|
235
|
-
(asset) => asset.assetSymbol === "USDC" && asset.chainId === chainId
|
|
236
|
-
);
|
|
237
|
-
const tokens = assets.map((asset) => ({
|
|
238
|
-
chain: SURFLIQUID_CHAIN_NAME,
|
|
239
|
-
chainId: SURFLIQUID_CHAIN_ID,
|
|
240
|
-
asset: "USDC",
|
|
241
|
-
amount: String(asset.currentValueUSD)
|
|
242
|
-
}));
|
|
243
|
-
const positions = assets.map((asset) => {
|
|
244
|
-
const stats = morphoStats?.get(asset.morphoVaultAddress?.toLowerCase() ?? "");
|
|
245
|
-
return {
|
|
246
|
-
chain: SURFLIQUID_CHAIN_NAME,
|
|
247
|
-
protocol: "Morpho",
|
|
248
|
-
// The specific MetaMorpho vault (e.g. "Gauntlet USDC Frontier"), read from
|
|
249
|
-
// Morpho — renders as "Morpho <vault>" alongside zyfai's vault detail.
|
|
250
|
-
pool: stats?.name ?? void 0,
|
|
251
|
-
asset: "USDC",
|
|
252
|
-
amount: String(asset.currentValueUSD),
|
|
253
|
-
apy: asset.currentAPY,
|
|
254
|
-
// TVL + liquidity come straight from Morpho (SurfLiquid's API omits them).
|
|
255
|
-
tvl: stats?.tvlUsd,
|
|
256
|
-
liquidity: stats?.liquidityUsd
|
|
257
|
-
};
|
|
258
|
-
});
|
|
259
|
-
const total = assets.reduce(
|
|
260
|
-
(sum, asset) => sum + asset.currentValueUSD,
|
|
261
|
-
0
|
|
262
|
-
);
|
|
263
|
-
return {
|
|
264
|
-
smartWallet: vault.userVaultAddress ?? void 0,
|
|
265
|
-
totalBalance: String(total),
|
|
266
|
-
totalBalanceAsset: "usdc",
|
|
267
|
-
tokens,
|
|
268
|
-
positions
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
function mapAccountApy(vault, days) {
|
|
272
|
-
const breakdown = vault.apyBreakdown;
|
|
273
|
-
const windowed = breakdown ? breakdown[APY_WINDOW_KEY[days]] : void 0;
|
|
274
|
-
const apy = windowed != null ? windowed : breakdown?.currentAPY ?? 0;
|
|
275
|
-
return {
|
|
276
|
-
walletAddress: vault.walletAddress ?? "",
|
|
277
|
-
weightedApyAfterFee: apy,
|
|
278
|
-
apyByChainAndAsset: { [SURFLIQUID_CHAIN_ID]: { USDC: apy } },
|
|
279
|
-
// Parity with Sail: SurfLiquid's core-sdk exposes no daily net-APY series.
|
|
280
|
-
history: []
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
function mapEarnings2(vault, vaultAddress) {
|
|
284
|
-
return {
|
|
285
|
-
smartWallet: vaultAddress,
|
|
286
|
-
lifetimeEarnings: vault.earned?.totalEarningsUSD ?? 0,
|
|
287
|
-
tokens: []
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
function mapUserProfile2(vault, address) {
|
|
291
|
-
return {
|
|
292
|
-
address,
|
|
293
|
-
smartWallet: vault.userVaultAddress ?? "",
|
|
294
|
-
chains: [SURFLIQUID_CHAIN_ID],
|
|
295
|
-
// SurfLiquid uses cookie-based session auth — no session-key concept.
|
|
296
|
-
hasActiveSessionKey: false,
|
|
297
|
-
protocols: ["SurfLiquid"]
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
var APY_WINDOW_KEY;
|
|
301
|
-
var init_surfliquid_mapper = __esm({
|
|
302
|
-
"src/agents/surfliquid/surfliquid.mapper.ts"() {
|
|
303
|
-
"use strict";
|
|
304
|
-
init_surfliquid_constants();
|
|
305
|
-
APY_WINDOW_KEY = {
|
|
306
|
-
"7D": "apy7d",
|
|
307
|
-
"14D": "apy14d",
|
|
308
|
-
"30D": "apy30d"
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
// src/agents/surfliquid/surfliquid.wallet-adapter.ts
|
|
314
|
-
var import_core_sdk, OwneyWalletAdapter;
|
|
315
|
-
var init_surfliquid_wallet_adapter = __esm({
|
|
316
|
-
"src/agents/surfliquid/surfliquid.wallet-adapter.ts"() {
|
|
317
|
-
"use strict";
|
|
318
|
-
import_core_sdk = require("@surf_liquid/core-sdk");
|
|
319
|
-
OwneyWalletAdapter = class extends import_core_sdk.BaseWalletAdapter {
|
|
320
|
-
constructor(eip1193Provider) {
|
|
321
|
-
super();
|
|
322
|
-
this.eip1193Provider = eip1193Provider;
|
|
323
|
-
}
|
|
324
|
-
eip1193Provider;
|
|
325
|
-
name = "owney";
|
|
326
|
-
get installed() {
|
|
327
|
-
return true;
|
|
328
|
-
}
|
|
329
|
-
resolveProvider() {
|
|
330
|
-
return this.eip1193Provider;
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
// src/agents/surfliquid/surfliquid.morpho.ts
|
|
337
|
-
async function queryMorpho(query, vaultAddress, chainId) {
|
|
338
|
-
try {
|
|
339
|
-
const res = await fetch(MORPHO_API_URL, {
|
|
340
|
-
method: "POST",
|
|
341
|
-
headers: { "Content-Type": "application/json" },
|
|
342
|
-
body: JSON.stringify({
|
|
343
|
-
query,
|
|
344
|
-
variables: { address: vaultAddress, chainId }
|
|
345
|
-
})
|
|
346
|
-
});
|
|
347
|
-
if (!res.ok) return null;
|
|
348
|
-
const json = await res.json();
|
|
349
|
-
if (json.errors) return null;
|
|
350
|
-
return json.data ?? null;
|
|
351
|
-
} catch (error) {
|
|
352
|
-
console.warn("surfliquid: Morpho vault stats fetch failed", {
|
|
353
|
-
vaultAddress,
|
|
354
|
-
chainId,
|
|
355
|
-
error
|
|
356
|
-
});
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
function toStats(name, tvlUsd, liquidityUsd) {
|
|
361
|
-
if (typeof tvlUsd !== "number" || typeof liquidityUsd !== "number") {
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
return {
|
|
365
|
-
name: typeof name === "string" ? name : null,
|
|
366
|
-
tvlUsd,
|
|
367
|
-
liquidityUsd
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
async function fetchMorphoVaultStats(vaultAddress, chainId) {
|
|
371
|
-
const v1 = await queryMorpho(VAULT_STATS_QUERY, vaultAddress, chainId);
|
|
372
|
-
const vault = v1?.vaultByAddress;
|
|
373
|
-
const v1Stats = toStats(
|
|
374
|
-
vault?.name,
|
|
375
|
-
vault?.state?.totalAssetsUsd,
|
|
376
|
-
vault?.liquidity?.usd
|
|
377
|
-
);
|
|
378
|
-
if (v1Stats) return v1Stats;
|
|
379
|
-
const v2 = await queryMorpho(VAULT_V2_STATS_QUERY, vaultAddress, chainId);
|
|
380
|
-
const vaultV2 = v2?.vaultV2ByAddress;
|
|
381
|
-
return toStats(vaultV2?.name, vaultV2?.totalAssetsUsd, vaultV2?.liquidityUsd);
|
|
382
|
-
}
|
|
383
|
-
async function fetchMorphoStatsByVault(vaultAddresses, chainId) {
|
|
384
|
-
const unique = [...new Set(vaultAddresses.map((a) => a.toLowerCase()))];
|
|
385
|
-
const entries = await Promise.all(
|
|
386
|
-
unique.map(
|
|
387
|
-
async (address) => [address, await fetchMorphoVaultStats(address, chainId)]
|
|
388
|
-
)
|
|
389
|
-
);
|
|
390
|
-
const byVault = /* @__PURE__ */ new Map();
|
|
391
|
-
for (const [address, stats] of entries) {
|
|
392
|
-
if (stats) byVault.set(address, stats);
|
|
393
|
-
}
|
|
394
|
-
return byVault;
|
|
395
|
-
}
|
|
396
|
-
var MORPHO_API_URL, VAULT_STATS_QUERY, VAULT_V2_STATS_QUERY;
|
|
397
|
-
var init_surfliquid_morpho = __esm({
|
|
398
|
-
"src/agents/surfliquid/surfliquid.morpho.ts"() {
|
|
399
|
-
"use strict";
|
|
400
|
-
MORPHO_API_URL = "https://api.morpho.org/graphql";
|
|
401
|
-
VAULT_STATS_QUERY = `
|
|
402
|
-
query VaultStats($address: String!, $chainId: Int!) {
|
|
403
|
-
vaultByAddress(address: $address, chainId: $chainId) {
|
|
404
|
-
name
|
|
405
|
-
state { totalAssetsUsd }
|
|
406
|
-
liquidity { usd }
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
`;
|
|
410
|
-
VAULT_V2_STATS_QUERY = `
|
|
411
|
-
query VaultV2Stats($address: String!, $chainId: Int!) {
|
|
412
|
-
vaultV2ByAddress(address: $address, chainId: $chainId) {
|
|
413
|
-
name
|
|
414
|
-
totalAssetsUsd
|
|
415
|
-
liquidityUsd
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
`;
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
// src/agents/surfliquid/surfliquid.agent.ts
|
|
423
|
-
var surfliquid_agent_exports = {};
|
|
424
|
-
__export(surfliquid_agent_exports, {
|
|
425
|
-
SurfLiquidAgent: () => SurfLiquidAgent
|
|
426
|
-
});
|
|
427
|
-
var import_core_sdk2, import_viem6, import_chains2, APY_WINDOW_KEY2, SurfLiquidAgent;
|
|
428
|
-
var init_surfliquid_agent = __esm({
|
|
429
|
-
"src/agents/surfliquid/surfliquid.agent.ts"() {
|
|
430
|
-
"use strict";
|
|
431
|
-
import_core_sdk2 = require("@surf_liquid/core-sdk");
|
|
432
|
-
import_viem6 = require("viem");
|
|
433
|
-
import_chains2 = require("viem/chains");
|
|
434
|
-
init_errors();
|
|
435
|
-
init_surfliquid_constants();
|
|
436
|
-
init_permit2();
|
|
437
|
-
init_surfliquid_mapper();
|
|
438
|
-
init_surfliquid_wallet_adapter();
|
|
439
|
-
init_surfliquid_morpho();
|
|
440
|
-
APY_WINDOW_KEY2 = {
|
|
441
|
-
"7D": "apy7d",
|
|
442
|
-
"14D": "apy14d",
|
|
443
|
-
"30D": "apy30d"
|
|
444
|
-
};
|
|
445
|
-
SurfLiquidAgent = class {
|
|
446
|
-
constructor(config) {
|
|
447
|
-
this.config = config;
|
|
448
|
-
}
|
|
449
|
-
config;
|
|
450
|
-
id = "surfliquid";
|
|
451
|
-
supportedChainIds = [SURFLIQUID_CHAIN_ID];
|
|
452
|
-
supportedAssets = SURFLIQUID_SUPPORTED_ASSETS;
|
|
453
|
-
surf = null;
|
|
454
|
-
connectedAddress = null;
|
|
455
|
-
// In-flight connect+auth, shared by concurrent callers to dedupe SIWE.
|
|
456
|
-
connectPromise = null;
|
|
457
|
-
ensureSurf() {
|
|
458
|
-
if (this.surf) return this.surf;
|
|
459
|
-
this.surf = import_core_sdk2.SurfClient.create({
|
|
460
|
-
projectName: this.config.projectName,
|
|
461
|
-
appId: this.config.appId,
|
|
462
|
-
environment: "mainnet",
|
|
463
|
-
chainId: SURFLIQUID_CHAIN_ID,
|
|
464
|
-
apiBaseUrl: this.config.apiBaseUrl,
|
|
465
|
-
rpcUrl: this.config.rpcUrl,
|
|
466
|
-
// Let the SDK auto-approve USDC to the vault before depositing.
|
|
467
|
-
autoApprove: true
|
|
468
|
-
});
|
|
469
|
-
return this.surf;
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* Connects + authenticates the SurfClient against owney's provider. Skips the
|
|
473
|
-
* SIWE prompt when already authenticated for this wallet (cookie session).
|
|
474
|
-
*/
|
|
475
|
-
async connect(state) {
|
|
476
|
-
const surf = this.ensureSurf();
|
|
477
|
-
const sameWallet = this.connectedAddress?.toLowerCase() === state.walletAddress.toLowerCase();
|
|
478
|
-
if (sameWallet && surf.getAuthState().authenticated) {
|
|
479
|
-
return surf;
|
|
480
|
-
}
|
|
481
|
-
if (this.connectPromise) return this.connectPromise;
|
|
482
|
-
this.connectPromise = (async () => {
|
|
483
|
-
surf.registerWalletAdapter(
|
|
484
|
-
"owney",
|
|
485
|
-
new OwneyWalletAdapter(state.provider)
|
|
486
|
-
);
|
|
487
|
-
await surf.connectWallet("owney");
|
|
488
|
-
await surf.authenticate();
|
|
489
|
-
this.connectedAddress = state.walletAddress;
|
|
490
|
-
return surf;
|
|
491
|
-
})();
|
|
492
|
-
try {
|
|
493
|
-
return await this.connectPromise;
|
|
494
|
-
} finally {
|
|
495
|
-
this.connectPromise = null;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* Returns the user's vault address, deploying one on first use. SurfLiquid's
|
|
500
|
-
* deposit requires the vault to exist, so this must run before depositing.
|
|
501
|
-
* Existing vault → returned as-is; otherwise `deployVault()` is sent
|
|
502
|
-
* (user-pays) and the freshly deployed address is returned.
|
|
503
|
-
*/
|
|
504
|
-
async resolveVaultAddress(surf, owner) {
|
|
505
|
-
const vault = await surf.getVault(owner).catch(() => null);
|
|
506
|
-
if (vault?.exists && vault.userVaultAddress) {
|
|
507
|
-
return vault.userVaultAddress;
|
|
508
|
-
}
|
|
509
|
-
const { vaultAddress } = await surf.deployVault();
|
|
510
|
-
return vaultAddress;
|
|
511
|
-
}
|
|
512
|
-
/**
|
|
513
|
-
* Grants the user's vault a standing USDC allowance so SurfLiquid's
|
|
514
|
-
* `autoApprove` has nothing to do — see {@link SURFLIQUID_APPROVAL_TARGET}
|
|
515
|
-
* for why one prompt per deposit is worth removing.
|
|
516
|
-
*
|
|
517
|
-
* Fails OPEN on a read error: if the allowance can't be checked we simply
|
|
518
|
-
* return and let SurfLiquid's own per-deposit approve run, because a flaky
|
|
519
|
-
* RPC must never block a deposit. A failed or rejected APPROVE does
|
|
520
|
-
* propagate — the user declined a transaction, and letting SurfLiquid
|
|
521
|
-
* immediately ask again for a smaller one is exactly the double prompt this
|
|
522
|
-
* removes.
|
|
523
|
-
*/
|
|
524
|
-
async ensureVaultAllowance(state, vaultAddress, amount) {
|
|
525
|
-
const spender = vaultAddress;
|
|
526
|
-
const transport = (0, import_viem6.custom)(state.provider);
|
|
527
|
-
const publicClient = (0, import_viem6.createPublicClient)({ chain: import_chains2.base, transport });
|
|
528
|
-
let allowance;
|
|
529
|
-
try {
|
|
530
|
-
allowance = await publicClient.readContract({
|
|
531
|
-
address: SURFLIQUID_USDC_ADDRESS,
|
|
532
|
-
abi: ERC20_ALLOWANCE_ABI,
|
|
533
|
-
functionName: "allowance",
|
|
534
|
-
args: [state.walletAddress, spender]
|
|
535
|
-
});
|
|
536
|
-
} catch (error) {
|
|
537
|
-
console.warn(
|
|
538
|
-
"[owney-sdk] SurfLiquid allowance pre-check failed; deferring to its per-deposit approve:",
|
|
539
|
-
error instanceof Error ? error.message : String(error)
|
|
540
|
-
);
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
if (allowance >= amount) return;
|
|
544
|
-
const target = amount > SURFLIQUID_APPROVAL_TARGET ? amount : SURFLIQUID_APPROVAL_TARGET;
|
|
545
|
-
const wallet = (0, import_viem6.createWalletClient)({
|
|
546
|
-
account: state.walletAddress,
|
|
547
|
-
chain: import_chains2.base,
|
|
548
|
-
transport
|
|
549
|
-
});
|
|
550
|
-
const hash = await wallet.writeContract({
|
|
551
|
-
address: SURFLIQUID_USDC_ADDRESS,
|
|
552
|
-
abi: ERC20_ALLOWANCE_ABI,
|
|
553
|
-
functionName: "approve",
|
|
554
|
-
args: [spender, target],
|
|
555
|
-
account: state.walletAddress,
|
|
556
|
-
chain: import_chains2.base
|
|
557
|
-
});
|
|
558
|
-
const receipt = await publicClient.waitForTransactionReceipt({
|
|
559
|
-
hash,
|
|
560
|
-
confirmations: 1
|
|
561
|
-
});
|
|
562
|
-
if (receipt.status !== "success") {
|
|
563
|
-
throw new Error(`SurfLiquid USDC approval reverted (tx ${hash})`);
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
// --- IAgent: lifecycle ---
|
|
567
|
-
async disconnect() {
|
|
568
|
-
if (this.surf) {
|
|
569
|
-
await this.surf.disconnectWallet();
|
|
570
|
-
}
|
|
571
|
-
this.connectedAddress = null;
|
|
572
|
-
}
|
|
573
|
-
async activateAgent(state) {
|
|
574
|
-
await this.connect(state);
|
|
575
|
-
}
|
|
576
|
-
// --- IAgent: funds (user-pays; asset is always USDC, callback ignored) ---
|
|
577
|
-
async deposit(state, _chainId, amount, _asset, _depositCallback) {
|
|
578
|
-
const surf = await this.connect(state);
|
|
579
|
-
const human = (0, import_viem6.formatUnits)(BigInt(amount), SURFLIQUID_USDC_DECIMALS);
|
|
580
|
-
const smartWallet = await this.resolveVaultAddress(
|
|
581
|
-
surf,
|
|
582
|
-
state.walletAddress
|
|
583
|
-
);
|
|
584
|
-
await this.ensureVaultAllowance(state, smartWallet, BigInt(amount));
|
|
585
|
-
const tx = await surf.deposit({
|
|
586
|
-
asset: SURFLIQUID_USDC_ADDRESS,
|
|
587
|
-
amount: human
|
|
588
|
-
});
|
|
589
|
-
await tx.wait();
|
|
590
|
-
return { txHash: tx.hash, smartWallet, amount };
|
|
591
|
-
}
|
|
592
|
-
async withdraw(state, _chainId, _token, amount) {
|
|
593
|
-
const surf = await this.connect(state);
|
|
594
|
-
const human = amount != null ? (0, import_viem6.formatUnits)(BigInt(amount), SURFLIQUID_USDC_DECIMALS) : void 0;
|
|
595
|
-
try {
|
|
596
|
-
const tx = await surf.withdraw({
|
|
597
|
-
asset: SURFLIQUID_USDC_ADDRESS,
|
|
598
|
-
amount: human
|
|
599
|
-
});
|
|
600
|
-
await tx.wait();
|
|
601
|
-
return {
|
|
602
|
-
txHash: tx.hash,
|
|
603
|
-
type: amount != null ? "partial" : "full",
|
|
604
|
-
amount: amount ?? "0"
|
|
605
|
-
};
|
|
606
|
-
} catch (error) {
|
|
607
|
-
throw new OwneyError(
|
|
608
|
-
"WITHDRAW_FAILED",
|
|
609
|
-
error instanceof Error ? error.message : "SurfLiquid withdraw failed.",
|
|
610
|
-
{ chainId: SURFLIQUID_CHAIN_ID, amount },
|
|
611
|
-
this.id
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
// --- IAgent: portfolio reads ---
|
|
616
|
-
async getBalances(state, chainId) {
|
|
617
|
-
const surf = await this.connect(state);
|
|
618
|
-
const vault = await surf.getVault(state.walletAddress);
|
|
619
|
-
const morphoVaultAddresses = (vault.assets ?? []).filter((asset) => asset.assetSymbol === "USDC" && asset.chainId === chainId).map((asset) => asset.morphoVaultAddress).filter((address) => Boolean(address));
|
|
620
|
-
const morphoStats = await fetchMorphoStatsByVault(
|
|
621
|
-
morphoVaultAddresses,
|
|
622
|
-
chainId
|
|
623
|
-
);
|
|
624
|
-
return mapBalances2(vault, chainId, morphoStats);
|
|
625
|
-
}
|
|
626
|
-
async getEarnings(state) {
|
|
627
|
-
const surf = await this.connect(state);
|
|
628
|
-
const vault = await surf.getVault(state.walletAddress);
|
|
629
|
-
return mapEarnings2(vault, vault.userVaultAddress ?? state.walletAddress);
|
|
630
|
-
}
|
|
631
|
-
async getAccountApy(state, _chainId, days, _tokenSymbol) {
|
|
632
|
-
const surf = await this.connect(state);
|
|
633
|
-
const vault = await surf.getVault(state.walletAddress);
|
|
634
|
-
return mapAccountApy(vault, days);
|
|
635
|
-
}
|
|
636
|
-
async getHistory(state, chainId, options) {
|
|
637
|
-
const surf = await this.connect(state);
|
|
638
|
-
const page = options?.cursor ? Number(options.cursor) : 1;
|
|
639
|
-
const limit = options?.limit ?? 10;
|
|
640
|
-
const result = await surf.getAgentMessages(
|
|
641
|
-
state.walletAddress,
|
|
642
|
-
page,
|
|
643
|
-
limit,
|
|
644
|
-
options?.fromDate,
|
|
645
|
-
options?.toDate
|
|
646
|
-
);
|
|
647
|
-
return mapHistory(result, chainId);
|
|
648
|
-
}
|
|
649
|
-
async getUserProfile(state) {
|
|
650
|
-
const surf = await this.connect(state);
|
|
651
|
-
const vault = await surf.getVault(state.walletAddress);
|
|
652
|
-
return mapUserProfile2(vault, state.walletAddress);
|
|
653
|
-
}
|
|
654
|
-
// --- IAgent: discovery (no wallet) ---
|
|
655
|
-
async getAgentApy(days, _options) {
|
|
656
|
-
const surf = this.ensureSurf();
|
|
657
|
-
const assets = await surf.getSupportedAssets(SURFLIQUID_CHAIN_ID);
|
|
658
|
-
const usdc = assets.find((asset) => asset.assetSymbol === "USDC");
|
|
659
|
-
if (!usdc) return { averageApy: 0 };
|
|
660
|
-
const windowed = usdc[APY_WINDOW_KEY2[days]];
|
|
661
|
-
return { averageApy: windowed != null ? windowed : usdc.currentAPY };
|
|
662
|
-
}
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
});
|
|
666
|
-
|
|
667
20
|
// src/index.ts
|
|
668
21
|
var index_exports = {};
|
|
669
22
|
__export(index_exports, {
|
|
@@ -736,8 +89,56 @@ var SupportedAssets = [
|
|
|
736
89
|
}
|
|
737
90
|
];
|
|
738
91
|
|
|
92
|
+
// src/errors.ts
|
|
93
|
+
var OwneyError = class extends Error {
|
|
94
|
+
code;
|
|
95
|
+
details;
|
|
96
|
+
agentId;
|
|
97
|
+
constructor(code, message, details, agentId) {
|
|
98
|
+
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
99
|
+
super(`${prefix} ${message}`);
|
|
100
|
+
this.name = "OwneyError";
|
|
101
|
+
this.code = code;
|
|
102
|
+
this.details = details;
|
|
103
|
+
this.agentId = agentId;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var AgentNotFoundError = class extends OwneyError {
|
|
107
|
+
constructor(agentId, available) {
|
|
108
|
+
super(
|
|
109
|
+
"AGENT_NOT_FOUND",
|
|
110
|
+
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
111
|
+
{ agentId, available },
|
|
112
|
+
agentId
|
|
113
|
+
);
|
|
114
|
+
this.name = "AgentNotFoundError";
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
var NotConnectedError = class extends OwneyError {
|
|
118
|
+
constructor() {
|
|
119
|
+
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
120
|
+
this.name = "NotConnectedError";
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var AgentChainIncompatibleError = class extends OwneyError {
|
|
124
|
+
incompatibleAgents;
|
|
125
|
+
connectedChainId;
|
|
126
|
+
constructor(incompatibleAgents, connectedChainId) {
|
|
127
|
+
const details = incompatibleAgents.map(
|
|
128
|
+
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
129
|
+
).join("; ");
|
|
130
|
+
super(
|
|
131
|
+
"AGENT_CHAIN_INCOMPATIBLE",
|
|
132
|
+
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
133
|
+
{ incompatibleAgents, connectedChainId }
|
|
134
|
+
);
|
|
135
|
+
this.name = "AgentChainIncompatibleError";
|
|
136
|
+
this.incompatibleAgents = incompatibleAgents;
|
|
137
|
+
this.connectedChainId = connectedChainId;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
739
141
|
// src/lib/utils.ts
|
|
740
|
-
init_errors();
|
|
741
142
|
var isValidChainId = (chainId) => {
|
|
742
143
|
if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
|
743
144
|
throw new OwneyError(
|
|
@@ -748,12 +149,6 @@ var isValidChainId = (chainId) => {
|
|
|
748
149
|
}
|
|
749
150
|
return chainId;
|
|
750
151
|
};
|
|
751
|
-
function isSameAsset(tokenSymbol, asset) {
|
|
752
|
-
const token = tokenSymbol.toLowerCase();
|
|
753
|
-
const target = asset.toLowerCase();
|
|
754
|
-
if (token === target) return true;
|
|
755
|
-
return target === "weth" && token === "eth" || target === "eth" && token === "weth";
|
|
756
|
-
}
|
|
757
152
|
function hexToDecimal(hex, decimals = 6) {
|
|
758
153
|
const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
|
|
759
154
|
const parsed = BigInt(normalized);
|
|
@@ -787,10 +182,6 @@ var DECIMALS_BY_SYMBOL = {
|
|
|
787
182
|
wbtc: 8,
|
|
788
183
|
cbbtc: 8
|
|
789
184
|
};
|
|
790
|
-
function canonicalSymbol(symbol) {
|
|
791
|
-
const upper = symbol.toUpperCase();
|
|
792
|
-
return upper === "ETH" ? "WETH" : upper;
|
|
793
|
-
}
|
|
794
185
|
function tokenDecimals(symbol, explicit) {
|
|
795
186
|
if (typeof explicit === "number" && Number.isFinite(explicit))
|
|
796
187
|
return explicit;
|
|
@@ -855,89 +246,55 @@ function mapPendingAllocations(raw) {
|
|
|
855
246
|
function mapBalances(raw, _chainId, smartWallet) {
|
|
856
247
|
const portfolio = raw.portfolio;
|
|
857
248
|
const portfolioByChain = portfolio.portfolioByChain ?? {};
|
|
858
|
-
const rawPositions = portfolio.positions ?? [];
|
|
859
|
-
const detailByKey = /* @__PURE__ */ new Map();
|
|
860
|
-
for (const p of rawPositions) {
|
|
861
|
-
const cid = resolveChainId(p.chain ?? "");
|
|
862
|
-
const symbol = canonicalSymbol(p.token_symbol ?? "");
|
|
863
|
-
if (Number.isFinite(cid) && symbol) detailByKey.set(`${cid}:${symbol}`, p);
|
|
864
|
-
}
|
|
865
249
|
let totalBalance = 0;
|
|
866
250
|
const tokens = [];
|
|
867
|
-
const positions = [];
|
|
868
251
|
for (const [chainIdKey, tokensBySymbol] of Object.entries(portfolioByChain)) {
|
|
869
252
|
const positionChainId = Number(chainIdKey);
|
|
870
|
-
const chainName2 = CHAIN_ID_TO_NAME[positionChainId] ?? "BASE";
|
|
871
253
|
for (const [
|
|
872
254
|
symbol,
|
|
873
255
|
{ balance, balanceWithFee, decimals }
|
|
874
256
|
] of Object.entries(tokensBySymbol ?? {})) {
|
|
875
|
-
const amount = hexToDecimal(
|
|
876
|
-
balanceWithFee ?? balance ?? "0",
|
|
877
|
-
tokenDecimals(symbol, decimals)
|
|
878
|
-
);
|
|
257
|
+
const amount = hexToDecimal(balanceWithFee ?? balance ?? "0", decimals);
|
|
879
258
|
totalBalance += amount;
|
|
880
259
|
tokens.push({
|
|
881
|
-
chain:
|
|
260
|
+
chain: CHAIN_ID_TO_NAME[positionChainId] ?? "BASE",
|
|
882
261
|
chainId: positionChainId,
|
|
883
262
|
asset: symbol,
|
|
884
263
|
amount: String(amount)
|
|
885
264
|
});
|
|
886
|
-
const detail = detailByKey.get(
|
|
887
|
-
`${positionChainId}:${canonicalSymbol(symbol)}`
|
|
888
|
-
);
|
|
889
|
-
positions.push({
|
|
890
|
-
chain: chainName2,
|
|
891
|
-
protocol: detail?.protocol_name ?? detail?.protocol_id ?? "",
|
|
892
|
-
protocolId: detail?.protocol_id,
|
|
893
|
-
pool: detail?.pool,
|
|
894
|
-
// Report the token the way the rest of owney spells it ("WETH", as the
|
|
895
|
-
// pre-portfolioByChain mapper did), not Zyfai's internal "eth".
|
|
896
|
-
asset: canonicalSymbol(symbol),
|
|
897
|
-
amount: String(amount),
|
|
898
|
-
apy: detail?.pool_apy,
|
|
899
|
-
tvl: detail?.pool_tvl,
|
|
900
|
-
// PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
|
|
901
|
-
// structural read keeps it undefined today and auto-populates later.
|
|
902
|
-
liquidity: detail?.liquidity
|
|
903
|
-
});
|
|
904
265
|
}
|
|
905
266
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
liquidity: p.liquidity
|
|
938
|
-
}))
|
|
939
|
-
);
|
|
940
|
-
}
|
|
267
|
+
const positions = (portfolio.positions ?? []).map((p) => ({
|
|
268
|
+
chain: p.chain ?? "",
|
|
269
|
+
protocol: p.protocol_name ?? p.protocol_id ?? "",
|
|
270
|
+
protocolId: p.protocol_id,
|
|
271
|
+
pool: p.pool,
|
|
272
|
+
asset: p.token_symbol ?? "",
|
|
273
|
+
// Fee-adjusted underlying amounts are decimal base-unit strings. The
|
|
274
|
+
// legacy `amount` fallback is hex. Runtime
|
|
275
|
+
// getBalances payloads often carry one (e.g. 18 for WETH) — prefer that
|
|
276
|
+
// when present, otherwise fall back to the per-symbol lookup.
|
|
277
|
+
amount: String(
|
|
278
|
+
p.underlyingAmountWithFee ?? p.underlyingAmount ? normalizeDecimalPlace(
|
|
279
|
+
p.underlyingAmountWithFee ?? p.underlyingAmount ?? "0",
|
|
280
|
+
tokenDecimals(
|
|
281
|
+
p.token_symbol,
|
|
282
|
+
p.decimals
|
|
283
|
+
)
|
|
284
|
+
) : hexToDecimal(
|
|
285
|
+
p.amount || "0",
|
|
286
|
+
tokenDecimals(
|
|
287
|
+
p.token_symbol,
|
|
288
|
+
p.decimals
|
|
289
|
+
)
|
|
290
|
+
)
|
|
291
|
+
),
|
|
292
|
+
apy: p.pool_apy,
|
|
293
|
+
tvl: p.pool_tvl,
|
|
294
|
+
// PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
|
|
295
|
+
// structural read keeps it undefined today and auto-populates later.
|
|
296
|
+
liquidity: p.liquidity
|
|
297
|
+
}));
|
|
941
298
|
const pendingAllocations = mapPendingAllocations(
|
|
942
299
|
portfolio.staleBalances
|
|
943
300
|
);
|
|
@@ -1232,9 +589,6 @@ function decodeHistoryCursor(token) {
|
|
|
1232
589
|
return parsed;
|
|
1233
590
|
}
|
|
1234
591
|
|
|
1235
|
-
// src/agents/zyfai/zyfai.agent.ts
|
|
1236
|
-
init_errors();
|
|
1237
|
-
|
|
1238
592
|
// src/agents/zyfai/zyfai.auth-cache.ts
|
|
1239
593
|
var KEY_PREFIX = "owney.zyfai.session";
|
|
1240
594
|
var storage = () => {
|
|
@@ -2023,37 +1377,6 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2023
1377
|
);
|
|
2024
1378
|
}
|
|
2025
1379
|
}
|
|
2026
|
-
/**
|
|
2027
|
-
* Records the deposit with Zyfai, retrying transient failures.
|
|
2028
|
-
*
|
|
2029
|
-
* This runs AFTER the transfer has already landed on-chain, so it must never
|
|
2030
|
-
* fail the deposit — the funds moved. But it is also the ONLY source of the
|
|
2031
|
-
* "Top up wallet" entry the history is built from: Zyfai auto-deploys the
|
|
2032
|
-
* balance it detects either way, so when this call is lost the user's deposit
|
|
2033
|
-
* never appears in Activity (an earlier withdrawal stays the newest row) and
|
|
2034
|
-
* nothing ever backfills it. Retry, then log loudly enough to be recoverable.
|
|
2035
|
-
*/
|
|
2036
|
-
async logDepositWithRetry(chainId, txHash, amount, tokenAddress) {
|
|
2037
|
-
const ATTEMPTS = 3;
|
|
2038
|
-
const RETRY_DELAY_MS = 1e3;
|
|
2039
|
-
for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
|
|
2040
|
-
try {
|
|
2041
|
-
await (tokenAddress ? this.sdk.logDeposit(chainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(chainId, txHash, amount));
|
|
2042
|
-
return;
|
|
2043
|
-
} catch (logError) {
|
|
2044
|
-
if (attempt === ATTEMPTS) {
|
|
2045
|
-
console.error(
|
|
2046
|
-
"[owney-sdk] Deposit landed on-chain but logDeposit failed \u2014 it will be missing from Zyfai history:",
|
|
2047
|
-
{ txHash, chainId, amount, tokenAddress, error: logError }
|
|
2048
|
-
);
|
|
2049
|
-
return;
|
|
2050
|
-
}
|
|
2051
|
-
await new Promise(
|
|
2052
|
-
(resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt)
|
|
2053
|
-
);
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
1380
|
/**
|
|
2058
1381
|
* True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
|
|
2059
1382
|
* to this EOA — the "new wallet" kind that is predeployed on the chains it
|
|
@@ -2357,12 +1680,14 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2357
1680
|
);
|
|
2358
1681
|
const txHash = await depositCallback(smartWallet, validChainId, amount);
|
|
2359
1682
|
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
2360
|
-
|
|
2361
|
-
validChainId,
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
1683
|
+
try {
|
|
1684
|
+
await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
|
|
1685
|
+
} catch (logError) {
|
|
1686
|
+
console.warn(
|
|
1687
|
+
"[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
|
|
1688
|
+
logError
|
|
1689
|
+
);
|
|
1690
|
+
}
|
|
2366
1691
|
return { txHash, smartWallet, amount };
|
|
2367
1692
|
}
|
|
2368
1693
|
await this.ensureWalletDeployed(this.getAddress(), validChainId);
|
|
@@ -2543,11 +1868,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2543
1868
|
}
|
|
2544
1869
|
};
|
|
2545
1870
|
|
|
2546
|
-
// src/client.ts
|
|
2547
|
-
init_errors();
|
|
2548
|
-
|
|
2549
1871
|
// src/lib/routing-api.ts
|
|
2550
|
-
init_errors();
|
|
2551
1872
|
var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
2552
1873
|
async function fetchOrgAgentConfig(apiKey) {
|
|
2553
1874
|
const url = `${ROUTING_API_BASE_URL}/api/v1/agent/org-config`;
|
|
@@ -2612,7 +1933,6 @@ async function fetchAgentKeys(apiKey) {
|
|
|
2612
1933
|
}
|
|
2613
1934
|
|
|
2614
1935
|
// src/lib/health-report.ts
|
|
2615
|
-
init_errors();
|
|
2616
1936
|
var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
2617
1937
|
async function reportAgentFailure(apiKey, agentType, errorCode) {
|
|
2618
1938
|
try {
|
|
@@ -2648,10 +1968,11 @@ async function withFailureReporting(apiKey, agentType, fn) {
|
|
|
2648
1968
|
// src/lib/helpers/withdraw-helper.ts
|
|
2649
1969
|
var import_viem2 = require("viem");
|
|
2650
1970
|
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
1971
|
+
const target = asset.toUpperCase();
|
|
2651
1972
|
return agents.map((agent) => {
|
|
2652
1973
|
const agentBalance = aggregated[agent.id];
|
|
2653
1974
|
const tokenBalance = agentBalance?.tokens.find(
|
|
2654
|
-
(t) => t.chainId === chainId &&
|
|
1975
|
+
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
2655
1976
|
);
|
|
2656
1977
|
if (!tokenBalance) return { agent, balance: 0n };
|
|
2657
1978
|
return { agent, balance: (0, import_viem2.parseUnits)(tokenBalance.amount, decimals) };
|
|
@@ -2761,11 +2082,8 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
2761
2082
|
}
|
|
2762
2083
|
|
|
2763
2084
|
// src/client.ts
|
|
2764
|
-
var
|
|
2765
|
-
var
|
|
2766
|
-
|
|
2767
|
-
// src/lib/sponsored-deposit.ts
|
|
2768
|
-
init_errors();
|
|
2085
|
+
var import_viem6 = require("viem");
|
|
2086
|
+
var import_chains2 = require("viem/chains");
|
|
2769
2087
|
|
|
2770
2088
|
// src/lib/transfer-auth.ts
|
|
2771
2089
|
var import_viem3 = require("viem");
|
|
@@ -2804,13 +2122,12 @@ function randomAuthNonce() {
|
|
|
2804
2122
|
}
|
|
2805
2123
|
|
|
2806
2124
|
// src/lib/sponsor-client.ts
|
|
2807
|
-
init_errors();
|
|
2808
2125
|
var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
2809
2126
|
async function postSponsorTransferAuth(input) {
|
|
2810
|
-
const
|
|
2127
|
+
const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
2811
2128
|
let res;
|
|
2812
2129
|
try {
|
|
2813
|
-
res = await fetch(`${
|
|
2130
|
+
res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
|
|
2814
2131
|
method: "POST",
|
|
2815
2132
|
headers: {
|
|
2816
2133
|
"content-type": "application/json",
|
|
@@ -2847,10 +2164,10 @@ async function postSponsorTransferAuth(input) {
|
|
|
2847
2164
|
return parsed.data;
|
|
2848
2165
|
}
|
|
2849
2166
|
async function postSponsorPermit2Transfer(input) {
|
|
2850
|
-
const
|
|
2167
|
+
const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
2851
2168
|
let res;
|
|
2852
2169
|
try {
|
|
2853
|
-
res = await fetch(`${
|
|
2170
|
+
res = await fetch(`${base3}/api/v1/sponsor/permit2-transfer`, {
|
|
2854
2171
|
method: "POST",
|
|
2855
2172
|
headers: {
|
|
2856
2173
|
"content-type": "application/json",
|
|
@@ -2885,11 +2202,11 @@ async function postSponsorPermit2Transfer(input) {
|
|
|
2885
2202
|
return parsed.data;
|
|
2886
2203
|
}
|
|
2887
2204
|
async function getSponsorRelayerAddress(input) {
|
|
2888
|
-
const
|
|
2205
|
+
const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
2889
2206
|
let res;
|
|
2890
2207
|
try {
|
|
2891
2208
|
res = await fetch(
|
|
2892
|
-
`${
|
|
2209
|
+
`${base3}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
|
|
2893
2210
|
{
|
|
2894
2211
|
headers: { "x-owney-api-key": input.apiKey }
|
|
2895
2212
|
}
|
|
@@ -2921,11 +2238,85 @@ async function getSponsorRelayerAddress(input) {
|
|
|
2921
2238
|
return parsed.data.relayer;
|
|
2922
2239
|
}
|
|
2923
2240
|
|
|
2924
|
-
// src/lib/
|
|
2925
|
-
|
|
2241
|
+
// src/lib/permit2.ts
|
|
2242
|
+
var import_viem4 = require("viem");
|
|
2243
|
+
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
2244
|
+
var MAX_UINT256 = 2n ** 256n - 1n;
|
|
2245
|
+
var ERC20_ALLOWANCE_ABI = [
|
|
2246
|
+
{
|
|
2247
|
+
type: "function",
|
|
2248
|
+
name: "allowance",
|
|
2249
|
+
stateMutability: "view",
|
|
2250
|
+
inputs: [
|
|
2251
|
+
{ name: "owner", type: "address" },
|
|
2252
|
+
{ name: "spender", type: "address" }
|
|
2253
|
+
],
|
|
2254
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
2255
|
+
},
|
|
2256
|
+
{
|
|
2257
|
+
type: "function",
|
|
2258
|
+
name: "approve",
|
|
2259
|
+
stateMutability: "nonpayable",
|
|
2260
|
+
inputs: [
|
|
2261
|
+
{ name: "spender", type: "address" },
|
|
2262
|
+
{ name: "amount", type: "uint256" }
|
|
2263
|
+
],
|
|
2264
|
+
outputs: [{ name: "", type: "bool" }]
|
|
2265
|
+
},
|
|
2266
|
+
{
|
|
2267
|
+
type: "function",
|
|
2268
|
+
name: "balanceOf",
|
|
2269
|
+
stateMutability: "view",
|
|
2270
|
+
inputs: [{ name: "account", type: "address" }],
|
|
2271
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
2272
|
+
}
|
|
2273
|
+
];
|
|
2274
|
+
function buildPermitTransferFromTypedData(input) {
|
|
2275
|
+
return {
|
|
2276
|
+
domain: {
|
|
2277
|
+
name: "Permit2",
|
|
2278
|
+
chainId: input.chainId,
|
|
2279
|
+
verifyingContract: PERMIT2_ADDRESS
|
|
2280
|
+
},
|
|
2281
|
+
types: {
|
|
2282
|
+
PermitTransferFrom: [
|
|
2283
|
+
{ name: "permitted", type: "TokenPermissions" },
|
|
2284
|
+
{ name: "spender", type: "address" },
|
|
2285
|
+
{ name: "nonce", type: "uint256" },
|
|
2286
|
+
{ name: "deadline", type: "uint256" }
|
|
2287
|
+
],
|
|
2288
|
+
TokenPermissions: [
|
|
2289
|
+
{ name: "token", type: "address" },
|
|
2290
|
+
{ name: "amount", type: "uint256" }
|
|
2291
|
+
]
|
|
2292
|
+
},
|
|
2293
|
+
primaryType: "PermitTransferFrom",
|
|
2294
|
+
message: input.message
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
function randomPermit2Nonce() {
|
|
2298
|
+
const bytes = new Uint8Array(32);
|
|
2299
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
2300
|
+
return BigInt((0, import_viem4.bytesToHex)(bytes));
|
|
2301
|
+
}
|
|
2302
|
+
async function readPermit2Allowance(publicClient, token, owner) {
|
|
2303
|
+
return publicClient.readContract({
|
|
2304
|
+
address: token,
|
|
2305
|
+
abi: ERC20_ALLOWANCE_ABI,
|
|
2306
|
+
functionName: "allowance",
|
|
2307
|
+
args: [owner, PERMIT2_ADDRESS]
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
async function readErc20Balance(publicClient, token, owner) {
|
|
2311
|
+
return publicClient.readContract({
|
|
2312
|
+
address: token,
|
|
2313
|
+
abi: ERC20_ALLOWANCE_ABI,
|
|
2314
|
+
functionName: "balanceOf",
|
|
2315
|
+
args: [owner]
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2926
2318
|
|
|
2927
2319
|
// src/lib/chain-guard.ts
|
|
2928
|
-
init_errors();
|
|
2929
2320
|
var CHAIN_NAMES = {
|
|
2930
2321
|
1: "Ethereum",
|
|
2931
2322
|
8453: "Base",
|
|
@@ -3039,8 +2430,6 @@ function makeSponsoredDepositCallback(deps) {
|
|
|
3039
2430
|
}
|
|
3040
2431
|
|
|
3041
2432
|
// src/lib/sponsored-weth-deposit.ts
|
|
3042
|
-
init_errors();
|
|
3043
|
-
init_permit2();
|
|
3044
2433
|
var PERMIT_WINDOW_SECONDS = 15 * 60;
|
|
3045
2434
|
function makeSponsoredWethCallback(deps) {
|
|
3046
2435
|
const get = deps.httpGet ?? getSponsorRelayerAddress;
|
|
@@ -3125,7 +2514,6 @@ function makeSponsoredWethCallback(deps) {
|
|
|
3125
2514
|
|
|
3126
2515
|
// src/lib/sponsored-calls-deposit.ts
|
|
3127
2516
|
var import_viem5 = require("viem");
|
|
3128
|
-
init_errors();
|
|
3129
2517
|
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
3130
2518
|
var DEFAULT_MAX_POLLS = 30;
|
|
3131
2519
|
async function paymasterSupported(provider, owner, chainId) {
|
|
@@ -3216,7 +2604,6 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
3216
2604
|
}
|
|
3217
2605
|
|
|
3218
2606
|
// src/client.ts
|
|
3219
|
-
init_permit2();
|
|
3220
2607
|
function encodeMultiAgentCursor(map) {
|
|
3221
2608
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
3222
2609
|
}
|
|
@@ -3243,11 +2630,10 @@ var SPONSORED_USDC_BY_CHAIN = {
|
|
|
3243
2630
|
1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
|
3244
2631
|
};
|
|
3245
2632
|
var VIEM_CHAIN2 = {
|
|
3246
|
-
8453:
|
|
3247
|
-
42161:
|
|
3248
|
-
1:
|
|
2633
|
+
8453: import_chains2.base,
|
|
2634
|
+
42161: import_chains2.arbitrum,
|
|
2635
|
+
1: import_chains2.mainnet
|
|
3249
2636
|
};
|
|
3250
|
-
var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai", "sail"];
|
|
3251
2637
|
var SPONSORED_WETH_BY_CHAIN = {
|
|
3252
2638
|
8453: "0x4200000000000000000000000000000000000006",
|
|
3253
2639
|
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
@@ -3276,7 +2662,6 @@ var OwneySDK = class {
|
|
|
3276
2662
|
zyfaiRpcUrls;
|
|
3277
2663
|
routingApiBaseUrl;
|
|
3278
2664
|
referralSource;
|
|
3279
|
-
surfliquidApiBaseUrl;
|
|
3280
2665
|
cachedSponsoredCallback = null;
|
|
3281
2666
|
cachedWethSponsoredCallback = null;
|
|
3282
2667
|
paymasterServiceUrl;
|
|
@@ -3289,7 +2674,6 @@ var OwneySDK = class {
|
|
|
3289
2674
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
3290
2675
|
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
3291
2676
|
this.referralSource = config.referralSource;
|
|
3292
|
-
this.surfliquidApiBaseUrl = config.surfliquidApiBaseUrl;
|
|
3293
2677
|
}
|
|
3294
2678
|
/**
|
|
3295
2679
|
* Establish connection state for all subsequent SDK calls.
|
|
@@ -3389,14 +2773,14 @@ var OwneySDK = class {
|
|
|
3389
2773
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
3390
2774
|
// PublicClient/WalletClient param types — structurally identical at
|
|
3391
2775
|
// runtime, but the two share a name TS treats as unrelated.
|
|
3392
|
-
getPublicClient: (cid) => (0,
|
|
2776
|
+
getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
|
|
3393
2777
|
chain: VIEM_CHAIN2[cid],
|
|
3394
|
-
transport: (0,
|
|
2778
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3395
2779
|
}),
|
|
3396
|
-
getWalletClient: (cid) => (0,
|
|
2780
|
+
getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
|
|
3397
2781
|
account: owner,
|
|
3398
2782
|
chain: VIEM_CHAIN2[cid],
|
|
3399
|
-
transport: (0,
|
|
2783
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3400
2784
|
})
|
|
3401
2785
|
});
|
|
3402
2786
|
if (!onApproved) this.cachedSponsoredCallback = callback;
|
|
@@ -3442,14 +2826,14 @@ var OwneySDK = class {
|
|
|
3442
2826
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
3443
2827
|
// PublicClient/WalletClient param types — structurally identical at
|
|
3444
2828
|
// runtime, but the two share a name TS treats as unrelated.
|
|
3445
|
-
getPublicClient: (cid) => (0,
|
|
2829
|
+
getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
|
|
3446
2830
|
chain: VIEM_CHAIN2[cid],
|
|
3447
|
-
transport: (0,
|
|
2831
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3448
2832
|
}),
|
|
3449
|
-
getWalletClient: (cid) => (0,
|
|
2833
|
+
getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
|
|
3450
2834
|
account: owner,
|
|
3451
2835
|
chain: VIEM_CHAIN2[cid],
|
|
3452
|
-
transport: (0,
|
|
2836
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3453
2837
|
})
|
|
3454
2838
|
});
|
|
3455
2839
|
if (!onApproved) this.cachedWethSponsoredCallback = callback;
|
|
@@ -3519,8 +2903,8 @@ var OwneySDK = class {
|
|
|
3519
2903
|
this.initializingAgentsPromise = (async () => {
|
|
3520
2904
|
const agentKeys = await fetchAgentKeys(this.apiKey);
|
|
3521
2905
|
this.disabledAgents.clear();
|
|
3522
|
-
for (const { key: key2, agent_type,
|
|
3523
|
-
const agent =
|
|
2906
|
+
for (const { key: key2, agent_type, is_enabled } of agentKeys) {
|
|
2907
|
+
const agent = this.createAgent(agent_type, key2);
|
|
3524
2908
|
if (!agent) continue;
|
|
3525
2909
|
this.agents.set(agent_type, agent);
|
|
3526
2910
|
if (is_enabled === false) {
|
|
@@ -3541,22 +2925,10 @@ var OwneySDK = class {
|
|
|
3541
2925
|
this.initializingAgentsPromise = null;
|
|
3542
2926
|
}
|
|
3543
2927
|
}
|
|
3544
|
-
|
|
2928
|
+
createAgent(agentId, key2) {
|
|
3545
2929
|
if (agentId === "zyfai") {
|
|
3546
2930
|
return new ZyfaiAgent(key2, this.zyfaiRpcUrls, this.referralSource);
|
|
3547
2931
|
}
|
|
3548
|
-
if (agentId === "surfliquid") {
|
|
3549
|
-
if (!projectName) return null;
|
|
3550
|
-
const { SurfLiquidAgent: SurfLiquidAgent2 } = await Promise.resolve().then(() => (init_surfliquid_agent(), surfliquid_agent_exports));
|
|
3551
|
-
return new SurfLiquidAgent2({
|
|
3552
|
-
projectName,
|
|
3553
|
-
appId: key2,
|
|
3554
|
-
// Same-origin proxy override — SurfLiquid auth is an httpOnly cookie,
|
|
3555
|
-
// which WebKit (iOS) discards when it is third-party. See
|
|
3556
|
-
// OwneySDKConfig.surfliquidApiBaseUrl.
|
|
3557
|
-
apiBaseUrl: this.surfliquidApiBaseUrl
|
|
3558
|
-
});
|
|
3559
|
-
}
|
|
3560
2932
|
return null;
|
|
3561
2933
|
}
|
|
3562
2934
|
// --- Account lifecycle ---
|
|
@@ -3638,9 +3010,9 @@ var OwneySDK = class {
|
|
|
3638
3010
|
/**
|
|
3639
3011
|
* Activate agents ONE AT A TIME, each followed by its org policy.
|
|
3640
3012
|
*
|
|
3641
|
-
* Every agent opens its activation with its own wallet signature
|
|
3642
|
-
*
|
|
3643
|
-
*
|
|
3013
|
+
* Every agent opens its activation with its own wallet signature, each
|
|
3014
|
+
* exchanged for that agent's own backend session — Zyfai's SIWX for a JWT,
|
|
3015
|
+
* Sail's SIWE. Run in parallel, that puts two `personal_sign` requests on one
|
|
3644
3016
|
* wallet connection in the same instant. Over WalletConnect both are
|
|
3645
3017
|
* delivered to the wallet, which renders one signing request at a time and
|
|
3646
3018
|
* queues or silently drops the other: neither promise settles, so activation
|
|
@@ -3740,30 +3112,18 @@ var OwneySDK = class {
|
|
|
3740
3112
|
);
|
|
3741
3113
|
}
|
|
3742
3114
|
const agentResults = {};
|
|
3743
|
-
const agentErrors = {};
|
|
3744
3115
|
for (const { agent, amount: agentAmount } of agentAmounts) {
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
depositCallback
|
|
3754
|
-
);
|
|
3755
|
-
} catch (error) {
|
|
3756
|
-
agentErrors[agent.id] = error instanceof Error ? error.message : String(error);
|
|
3757
|
-
}
|
|
3758
|
-
}
|
|
3759
|
-
if (Object.keys(agentResults).length === 0) {
|
|
3760
|
-
throw new OwneyError(
|
|
3761
|
-
"DEPOSIT_ALL_FAILED",
|
|
3762
|
-
`All ${agentAmounts.length} agent deposit(s) failed.`,
|
|
3763
|
-
{ agentErrors }
|
|
3116
|
+
agentResults[agent.id] = await this.depositWithFallback(
|
|
3117
|
+
agent,
|
|
3118
|
+
state,
|
|
3119
|
+
chainId,
|
|
3120
|
+
agentAmount,
|
|
3121
|
+
asset,
|
|
3122
|
+
effectiveCallback,
|
|
3123
|
+
depositCallback
|
|
3764
3124
|
);
|
|
3765
3125
|
}
|
|
3766
|
-
return
|
|
3126
|
+
return { agentResults };
|
|
3767
3127
|
}
|
|
3768
3128
|
/**
|
|
3769
3129
|
* Invokes `agent.deposit` with the resolved sponsored callback, composing
|
|
@@ -3879,8 +3239,9 @@ var OwneySDK = class {
|
|
|
3879
3239
|
async hasExistingBalance(agent, state, chainId, asset) {
|
|
3880
3240
|
try {
|
|
3881
3241
|
const balance = await agent.getBalances(state, chainId);
|
|
3242
|
+
const target = asset.toLowerCase();
|
|
3882
3243
|
const token = balance.tokens.find(
|
|
3883
|
-
(t) => t.chainId === chainId &&
|
|
3244
|
+
(t) => t.chainId === chainId && t.asset.toLowerCase() === target
|
|
3884
3245
|
);
|
|
3885
3246
|
return !!token && Number(token.amount) > 0;
|
|
3886
3247
|
} catch {
|
|
@@ -3919,34 +3280,6 @@ var OwneySDK = class {
|
|
|
3919
3280
|
}
|
|
3920
3281
|
return eligible;
|
|
3921
3282
|
}
|
|
3922
|
-
/**
|
|
3923
|
-
* Agent ids the routing API provisioned for this org that support the given
|
|
3924
|
-
* chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
|
|
3925
|
-
* surfliquid first). Returns `[]` when the org has no compatible agent — never
|
|
3926
|
-
* throws on an empty org. Loads agent keys on first call (apiKey only, no
|
|
3927
|
-
* wallet), so the UI can resolve which agent to use before the user connects.
|
|
3928
|
-
*
|
|
3929
|
-
* This is the source of truth for agent availability: an agent appears here
|
|
3930
|
-
* iff the routing API returned its key. No per-app feature flags.
|
|
3931
|
-
*/
|
|
3932
|
-
async getEligibleAgentIds(chainId, asset) {
|
|
3933
|
-
try {
|
|
3934
|
-
await this.ensureAgentsInitialized();
|
|
3935
|
-
} catch (error) {
|
|
3936
|
-
if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
|
|
3937
|
-
return [];
|
|
3938
|
-
}
|
|
3939
|
-
throw error;
|
|
3940
|
-
}
|
|
3941
|
-
return [...this.agents.values()].filter((agent) => {
|
|
3942
|
-
const chainAssets = agent.supportedAssets.find(
|
|
3943
|
-
(sa) => sa.chainId === chainId
|
|
3944
|
-
);
|
|
3945
|
-
return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
|
|
3946
|
-
}).map((agent) => agent.id).sort(
|
|
3947
|
-
(a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
|
|
3948
|
-
);
|
|
3949
|
-
}
|
|
3950
3283
|
// --- Fund operations ---
|
|
3951
3284
|
/**
|
|
3952
3285
|
* Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
|
|
@@ -3982,17 +3315,9 @@ var OwneySDK = class {
|
|
|
3982
3315
|
}
|
|
3983
3316
|
const eligibleAgents = this.getEligibleAgents(chainId, asset);
|
|
3984
3317
|
if (!amount) {
|
|
3985
|
-
const aggregated2 = await this.getBalances();
|
|
3986
|
-
const funded = projectAgentBalancesForAsset(
|
|
3987
|
-
eligibleAgents,
|
|
3988
|
-
aggregated2.agentBalances,
|
|
3989
|
-
chainId,
|
|
3990
|
-
asset,
|
|
3991
|
-
assetInfo.decimals
|
|
3992
|
-
).filter((b) => b.balance > 0n);
|
|
3993
3318
|
const results2 = {};
|
|
3994
3319
|
const agentErrors2 = {};
|
|
3995
|
-
for (const
|
|
3320
|
+
for (const agent of eligibleAgents) {
|
|
3996
3321
|
try {
|
|
3997
3322
|
results2[agent.id] = await agent.withdraw(state, chainId, token);
|
|
3998
3323
|
} catch (err) {
|
|
@@ -4009,10 +3334,9 @@ var OwneySDK = class {
|
|
|
4009
3334
|
{ asset, agentErrors: agentErrors2 }
|
|
4010
3335
|
);
|
|
4011
3336
|
}
|
|
4012
|
-
const totalWithdrawn = funded.filter(({ agent }) => results2[agent.id] !== void 0).reduce((sum, { balance }) => sum + balance, 0n);
|
|
4013
3337
|
return {
|
|
4014
3338
|
agentResult: results2,
|
|
4015
|
-
totalWithdrawn:
|
|
3339
|
+
totalWithdrawn: sumWithdrawnAmount(results2).toString()
|
|
4016
3340
|
};
|
|
4017
3341
|
}
|
|
4018
3342
|
const requested = BigInt(amount);
|
|
@@ -4404,10 +3728,10 @@ var OwneySDK = class {
|
|
|
4404
3728
|
);
|
|
4405
3729
|
}
|
|
4406
3730
|
const provider = this.requireConnectedProvider();
|
|
4407
|
-
const wallet = (0,
|
|
3731
|
+
const wallet = (0, import_viem6.createWalletClient)({
|
|
4408
3732
|
account: state.walletAddress,
|
|
4409
3733
|
chain: VIEM_CHAIN2[chainId],
|
|
4410
|
-
transport: (0,
|
|
3734
|
+
transport: (0, import_viem6.custom)(provider)
|
|
4411
3735
|
});
|
|
4412
3736
|
const hash = await wallet.writeContract({
|
|
4413
3737
|
address: token,
|
|
@@ -4417,9 +3741,9 @@ var OwneySDK = class {
|
|
|
4417
3741
|
account: state.walletAddress,
|
|
4418
3742
|
chain: VIEM_CHAIN2[chainId]
|
|
4419
3743
|
});
|
|
4420
|
-
const publicClient = (0,
|
|
3744
|
+
const publicClient = (0, import_viem6.createPublicClient)({
|
|
4421
3745
|
chain: VIEM_CHAIN2[chainId],
|
|
4422
|
-
transport: (0,
|
|
3746
|
+
transport: (0, import_viem6.custom)(provider)
|
|
4423
3747
|
});
|
|
4424
3748
|
const receipt = await publicClient.waitForTransactionReceipt({
|
|
4425
3749
|
hash,
|
|
@@ -4527,11 +3851,8 @@ var OwneySDK = class {
|
|
|
4527
3851
|
}
|
|
4528
3852
|
};
|
|
4529
3853
|
|
|
4530
|
-
// src/index.ts
|
|
4531
|
-
init_errors();
|
|
4532
|
-
|
|
4533
3854
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
4534
|
-
var
|
|
3855
|
+
var import_viem7 = require("viem");
|
|
4535
3856
|
var import_siwe = require("siwe");
|
|
4536
3857
|
var import_sdk2 = require("@zyfai/sdk");
|
|
4537
3858
|
|
|
@@ -4658,7 +3979,7 @@ function buildSIWXConfig(deps) {
|
|
|
4658
3979
|
issuedAt,
|
|
4659
3980
|
toString() {
|
|
4660
3981
|
return new import_siwe.SiweMessage({
|
|
4661
|
-
address: (0,
|
|
3982
|
+
address: (0, import_viem7.getAddress)(accountAddress),
|
|
4662
3983
|
chainId: numericChainId(chainId),
|
|
4663
3984
|
domain,
|
|
4664
3985
|
uri,
|