@owney/sdk 0.7.9 → 0.7.10-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-PWIKIQOX.js +140 -0
- package/dist/index.cjs +889 -210
- package/dist/index.d.cts +30 -2
- package/dist/index.d.ts +30 -2
- package/dist/index.js +208 -186
- package/dist/surfliquid.agent-VNGQUSXN.js +473 -0
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentChainIncompatibleError,
|
|
3
|
+
AgentNotFoundError,
|
|
4
|
+
ERC20_ALLOWANCE_ABI,
|
|
5
|
+
MAX_UINT256,
|
|
6
|
+
NotConnectedError,
|
|
7
|
+
OwneyError,
|
|
8
|
+
PERMIT2_ADDRESS,
|
|
9
|
+
buildPermitTransferFromTypedData,
|
|
10
|
+
randomPermit2Nonce,
|
|
11
|
+
readErc20Balance,
|
|
12
|
+
readPermit2Allowance
|
|
13
|
+
} from "./chunk-PWIKIQOX.js";
|
|
14
|
+
|
|
1
15
|
// src/agents/zyfai/zyfai.agent.ts
|
|
2
16
|
import { SMART_SESSIONS_VALIDATOR, ZyfaiSDK } from "@zyfai/sdk";
|
|
3
17
|
import { createPublicClient, http, parseAbi } from "viem";
|
|
@@ -56,55 +70,6 @@ var SupportedAssets = [
|
|
|
56
70
|
}
|
|
57
71
|
];
|
|
58
72
|
|
|
59
|
-
// src/errors.ts
|
|
60
|
-
var OwneyError = class extends Error {
|
|
61
|
-
code;
|
|
62
|
-
details;
|
|
63
|
-
agentId;
|
|
64
|
-
constructor(code, message, details, agentId) {
|
|
65
|
-
const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
|
|
66
|
-
super(`${prefix} ${message}`);
|
|
67
|
-
this.name = "OwneyError";
|
|
68
|
-
this.code = code;
|
|
69
|
-
this.details = details;
|
|
70
|
-
this.agentId = agentId;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
var AgentNotFoundError = class extends OwneyError {
|
|
74
|
-
constructor(agentId, available) {
|
|
75
|
-
super(
|
|
76
|
-
"AGENT_NOT_FOUND",
|
|
77
|
-
`Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
|
|
78
|
-
{ agentId, available },
|
|
79
|
-
agentId
|
|
80
|
-
);
|
|
81
|
-
this.name = "AgentNotFoundError";
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
var NotConnectedError = class extends OwneyError {
|
|
85
|
-
constructor() {
|
|
86
|
-
super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
|
|
87
|
-
this.name = "NotConnectedError";
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
var AgentChainIncompatibleError = class extends OwneyError {
|
|
91
|
-
incompatibleAgents;
|
|
92
|
-
connectedChainId;
|
|
93
|
-
constructor(incompatibleAgents, connectedChainId) {
|
|
94
|
-
const details = incompatibleAgents.map(
|
|
95
|
-
({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
|
|
96
|
-
).join("; ");
|
|
97
|
-
super(
|
|
98
|
-
"AGENT_CHAIN_INCOMPATIBLE",
|
|
99
|
-
`Chain ${connectedChainId} is not supported by the following agents: ${details}`,
|
|
100
|
-
{ incompatibleAgents, connectedChainId }
|
|
101
|
-
);
|
|
102
|
-
this.name = "AgentChainIncompatibleError";
|
|
103
|
-
this.incompatibleAgents = incompatibleAgents;
|
|
104
|
-
this.connectedChainId = connectedChainId;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
73
|
// src/lib/utils.ts
|
|
109
74
|
var isValidChainId = (chainId) => {
|
|
110
75
|
if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
|
@@ -116,6 +81,12 @@ var isValidChainId = (chainId) => {
|
|
|
116
81
|
}
|
|
117
82
|
return chainId;
|
|
118
83
|
};
|
|
84
|
+
function isSameAsset(tokenSymbol, asset) {
|
|
85
|
+
const token = tokenSymbol.toLowerCase();
|
|
86
|
+
const target = asset.toLowerCase();
|
|
87
|
+
if (token === target) return true;
|
|
88
|
+
return target === "weth" && token === "eth" || target === "eth" && token === "weth";
|
|
89
|
+
}
|
|
119
90
|
function hexToDecimal(hex, decimals = 6) {
|
|
120
91
|
const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
|
|
121
92
|
const parsed = BigInt(normalized);
|
|
@@ -149,6 +120,10 @@ var DECIMALS_BY_SYMBOL = {
|
|
|
149
120
|
wbtc: 8,
|
|
150
121
|
cbbtc: 8
|
|
151
122
|
};
|
|
123
|
+
function canonicalSymbol(symbol) {
|
|
124
|
+
const upper = symbol.toUpperCase();
|
|
125
|
+
return upper === "ETH" ? "WETH" : upper;
|
|
126
|
+
}
|
|
152
127
|
function tokenDecimals(symbol, explicit) {
|
|
153
128
|
if (typeof explicit === "number" && Number.isFinite(explicit))
|
|
154
129
|
return explicit;
|
|
@@ -213,55 +188,89 @@ function mapPendingAllocations(raw) {
|
|
|
213
188
|
function mapBalances(raw, _chainId, smartWallet) {
|
|
214
189
|
const portfolio = raw.portfolio;
|
|
215
190
|
const portfolioByChain = portfolio.portfolioByChain ?? {};
|
|
191
|
+
const rawPositions = portfolio.positions ?? [];
|
|
192
|
+
const detailByKey = /* @__PURE__ */ new Map();
|
|
193
|
+
for (const p of rawPositions) {
|
|
194
|
+
const cid = resolveChainId(p.chain ?? "");
|
|
195
|
+
const symbol = canonicalSymbol(p.token_symbol ?? "");
|
|
196
|
+
if (Number.isFinite(cid) && symbol) detailByKey.set(`${cid}:${symbol}`, p);
|
|
197
|
+
}
|
|
216
198
|
let totalBalance = 0;
|
|
217
199
|
const tokens = [];
|
|
200
|
+
const positions = [];
|
|
218
201
|
for (const [chainIdKey, tokensBySymbol] of Object.entries(portfolioByChain)) {
|
|
219
202
|
const positionChainId = Number(chainIdKey);
|
|
203
|
+
const chainName2 = CHAIN_ID_TO_NAME[positionChainId] ?? "BASE";
|
|
220
204
|
for (const [
|
|
221
205
|
symbol,
|
|
222
206
|
{ balance, balanceWithFee, decimals }
|
|
223
207
|
] of Object.entries(tokensBySymbol ?? {})) {
|
|
224
|
-
const amount = hexToDecimal(
|
|
208
|
+
const amount = hexToDecimal(
|
|
209
|
+
balanceWithFee ?? balance ?? "0",
|
|
210
|
+
tokenDecimals(symbol, decimals)
|
|
211
|
+
);
|
|
225
212
|
totalBalance += amount;
|
|
226
213
|
tokens.push({
|
|
227
|
-
chain:
|
|
214
|
+
chain: chainName2,
|
|
228
215
|
chainId: positionChainId,
|
|
229
216
|
asset: symbol,
|
|
230
217
|
amount: String(amount)
|
|
231
218
|
});
|
|
219
|
+
const detail = detailByKey.get(
|
|
220
|
+
`${positionChainId}:${canonicalSymbol(symbol)}`
|
|
221
|
+
);
|
|
222
|
+
positions.push({
|
|
223
|
+
chain: chainName2,
|
|
224
|
+
protocol: detail?.protocol_name ?? detail?.protocol_id ?? "",
|
|
225
|
+
protocolId: detail?.protocol_id,
|
|
226
|
+
pool: detail?.pool,
|
|
227
|
+
// Report the token the way the rest of owney spells it ("WETH", as the
|
|
228
|
+
// pre-portfolioByChain mapper did), not Zyfai's internal "eth".
|
|
229
|
+
asset: canonicalSymbol(symbol),
|
|
230
|
+
amount: String(amount),
|
|
231
|
+
apy: detail?.pool_apy,
|
|
232
|
+
tvl: detail?.pool_tvl,
|
|
233
|
+
// PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
|
|
234
|
+
// structural read keeps it undefined today and auto-populates later.
|
|
235
|
+
liquidity: detail?.liquidity
|
|
236
|
+
});
|
|
232
237
|
}
|
|
233
238
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
239
|
+
if (positions.length === 0) {
|
|
240
|
+
positions.push(
|
|
241
|
+
...(portfolio.positions ?? []).map((p) => ({
|
|
242
|
+
chain: p.chain ?? "",
|
|
243
|
+
protocol: p.protocol_name ?? p.protocol_id ?? "",
|
|
244
|
+
protocolId: p.protocol_id,
|
|
245
|
+
pool: p.pool,
|
|
246
|
+
asset: p.token_symbol ?? "",
|
|
247
|
+
// Fee-adjusted underlying amounts are decimal base-unit strings; the
|
|
248
|
+
// legacy `amount` fallback is hex. Runtime getBalances payloads often
|
|
249
|
+
// carry `decimals` (e.g. 18 for WETH) — prefer it when present,
|
|
250
|
+
// otherwise fall back to the per-symbol lookup.
|
|
251
|
+
amount: String(
|
|
252
|
+
p.underlyingAmountWithFee ?? p.underlyingAmount ? normalizeDecimalPlace(
|
|
253
|
+
p.underlyingAmountWithFee ?? p.underlyingAmount ?? "0",
|
|
254
|
+
tokenDecimals(
|
|
255
|
+
p.token_symbol,
|
|
256
|
+
p.decimals
|
|
257
|
+
)
|
|
258
|
+
) : hexToDecimal(
|
|
259
|
+
p.amount || "0",
|
|
260
|
+
tokenDecimals(
|
|
261
|
+
p.token_symbol,
|
|
262
|
+
p.decimals
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
),
|
|
266
|
+
apy: p.pool_apy,
|
|
267
|
+
tvl: p.pool_tvl,
|
|
268
|
+
// PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
|
|
269
|
+
// structural read keeps it undefined today and auto-populates later.
|
|
270
|
+
liquidity: p.liquidity
|
|
271
|
+
}))
|
|
272
|
+
);
|
|
273
|
+
}
|
|
265
274
|
const pendingAllocations = mapPendingAllocations(
|
|
266
275
|
portfolio.staleBalances
|
|
267
276
|
);
|
|
@@ -1344,6 +1353,37 @@ var ZyfaiAgent = class {
|
|
|
1344
1353
|
);
|
|
1345
1354
|
}
|
|
1346
1355
|
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Records the deposit with Zyfai, retrying transient failures.
|
|
1358
|
+
*
|
|
1359
|
+
* This runs AFTER the transfer has already landed on-chain, so it must never
|
|
1360
|
+
* fail the deposit — the funds moved. But it is also the ONLY source of the
|
|
1361
|
+
* "Top up wallet" entry the history is built from: Zyfai auto-deploys the
|
|
1362
|
+
* balance it detects either way, so when this call is lost the user's deposit
|
|
1363
|
+
* never appears in Activity (an earlier withdrawal stays the newest row) and
|
|
1364
|
+
* nothing ever backfills it. Retry, then log loudly enough to be recoverable.
|
|
1365
|
+
*/
|
|
1366
|
+
async logDepositWithRetry(chainId, txHash, amount, tokenAddress) {
|
|
1367
|
+
const ATTEMPTS = 3;
|
|
1368
|
+
const RETRY_DELAY_MS = 1e3;
|
|
1369
|
+
for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
|
|
1370
|
+
try {
|
|
1371
|
+
await (tokenAddress ? this.sdk.logDeposit(chainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(chainId, txHash, amount));
|
|
1372
|
+
return;
|
|
1373
|
+
} catch (logError) {
|
|
1374
|
+
if (attempt === ATTEMPTS) {
|
|
1375
|
+
console.error(
|
|
1376
|
+
"[owney-sdk] Deposit landed on-chain but logDeposit failed \u2014 it will be missing from Zyfai history:",
|
|
1377
|
+
{ txHash, chainId, amount, tokenAddress, error: logError }
|
|
1378
|
+
);
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
await new Promise(
|
|
1382
|
+
(resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt)
|
|
1383
|
+
);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1347
1387
|
/**
|
|
1348
1388
|
* True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
|
|
1349
1389
|
* to this EOA — the "new wallet" kind that is predeployed on the chains it
|
|
@@ -1647,14 +1687,12 @@ var ZyfaiAgent = class {
|
|
|
1647
1687
|
);
|
|
1648
1688
|
const txHash = await depositCallback(smartWallet, validChainId, amount);
|
|
1649
1689
|
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
);
|
|
1657
|
-
}
|
|
1690
|
+
await this.logDepositWithRetry(
|
|
1691
|
+
validChainId,
|
|
1692
|
+
txHash,
|
|
1693
|
+
amount,
|
|
1694
|
+
tokenAddress
|
|
1695
|
+
);
|
|
1658
1696
|
return { txHash, smartWallet, amount };
|
|
1659
1697
|
}
|
|
1660
1698
|
await this.ensureWalletDeployed(this.getAddress(), validChainId);
|
|
@@ -1909,11 +1947,10 @@ async function withFailureReporting(apiKey, agentType, fn) {
|
|
|
1909
1947
|
// src/lib/helpers/withdraw-helper.ts
|
|
1910
1948
|
import { parseUnits } from "viem";
|
|
1911
1949
|
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
1912
|
-
const target = asset.toUpperCase();
|
|
1913
1950
|
return agents.map((agent) => {
|
|
1914
1951
|
const agentBalance = aggregated[agent.id];
|
|
1915
1952
|
const tokenBalance = agentBalance?.tokens.find(
|
|
1916
|
-
(t) => t.chainId === chainId && t.asset
|
|
1953
|
+
(t) => t.chainId === chainId && isSameAsset(t.asset, asset)
|
|
1917
1954
|
);
|
|
1918
1955
|
if (!tokenBalance) return { agent, balance: 0n };
|
|
1919
1956
|
return { agent, balance: parseUnits(tokenBalance.amount, decimals) };
|
|
@@ -2183,84 +2220,6 @@ async function getSponsorRelayerAddress(input) {
|
|
|
2183
2220
|
return parsed.data.relayer;
|
|
2184
2221
|
}
|
|
2185
2222
|
|
|
2186
|
-
// src/lib/permit2.ts
|
|
2187
|
-
import { bytesToHex as bytesToHex2 } from "viem";
|
|
2188
|
-
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
2189
|
-
var MAX_UINT256 = 2n ** 256n - 1n;
|
|
2190
|
-
var ERC20_ALLOWANCE_ABI = [
|
|
2191
|
-
{
|
|
2192
|
-
type: "function",
|
|
2193
|
-
name: "allowance",
|
|
2194
|
-
stateMutability: "view",
|
|
2195
|
-
inputs: [
|
|
2196
|
-
{ name: "owner", type: "address" },
|
|
2197
|
-
{ name: "spender", type: "address" }
|
|
2198
|
-
],
|
|
2199
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
2200
|
-
},
|
|
2201
|
-
{
|
|
2202
|
-
type: "function",
|
|
2203
|
-
name: "approve",
|
|
2204
|
-
stateMutability: "nonpayable",
|
|
2205
|
-
inputs: [
|
|
2206
|
-
{ name: "spender", type: "address" },
|
|
2207
|
-
{ name: "amount", type: "uint256" }
|
|
2208
|
-
],
|
|
2209
|
-
outputs: [{ name: "", type: "bool" }]
|
|
2210
|
-
},
|
|
2211
|
-
{
|
|
2212
|
-
type: "function",
|
|
2213
|
-
name: "balanceOf",
|
|
2214
|
-
stateMutability: "view",
|
|
2215
|
-
inputs: [{ name: "account", type: "address" }],
|
|
2216
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
2217
|
-
}
|
|
2218
|
-
];
|
|
2219
|
-
function buildPermitTransferFromTypedData(input) {
|
|
2220
|
-
return {
|
|
2221
|
-
domain: {
|
|
2222
|
-
name: "Permit2",
|
|
2223
|
-
chainId: input.chainId,
|
|
2224
|
-
verifyingContract: PERMIT2_ADDRESS
|
|
2225
|
-
},
|
|
2226
|
-
types: {
|
|
2227
|
-
PermitTransferFrom: [
|
|
2228
|
-
{ name: "permitted", type: "TokenPermissions" },
|
|
2229
|
-
{ name: "spender", type: "address" },
|
|
2230
|
-
{ name: "nonce", type: "uint256" },
|
|
2231
|
-
{ name: "deadline", type: "uint256" }
|
|
2232
|
-
],
|
|
2233
|
-
TokenPermissions: [
|
|
2234
|
-
{ name: "token", type: "address" },
|
|
2235
|
-
{ name: "amount", type: "uint256" }
|
|
2236
|
-
]
|
|
2237
|
-
},
|
|
2238
|
-
primaryType: "PermitTransferFrom",
|
|
2239
|
-
message: input.message
|
|
2240
|
-
};
|
|
2241
|
-
}
|
|
2242
|
-
function randomPermit2Nonce() {
|
|
2243
|
-
const bytes = new Uint8Array(32);
|
|
2244
|
-
globalThis.crypto.getRandomValues(bytes);
|
|
2245
|
-
return BigInt(bytesToHex2(bytes));
|
|
2246
|
-
}
|
|
2247
|
-
async function readPermit2Allowance(publicClient, token, owner) {
|
|
2248
|
-
return publicClient.readContract({
|
|
2249
|
-
address: token,
|
|
2250
|
-
abi: ERC20_ALLOWANCE_ABI,
|
|
2251
|
-
functionName: "allowance",
|
|
2252
|
-
args: [owner, PERMIT2_ADDRESS]
|
|
2253
|
-
});
|
|
2254
|
-
}
|
|
2255
|
-
async function readErc20Balance(publicClient, token, owner) {
|
|
2256
|
-
return publicClient.readContract({
|
|
2257
|
-
address: token,
|
|
2258
|
-
abi: ERC20_ALLOWANCE_ABI,
|
|
2259
|
-
functionName: "balanceOf",
|
|
2260
|
-
args: [owner]
|
|
2261
|
-
});
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
2223
|
// src/lib/chain-guard.ts
|
|
2265
2224
|
var CHAIN_NAMES = {
|
|
2266
2225
|
1: "Ethereum",
|
|
@@ -2579,6 +2538,7 @@ var VIEM_CHAIN2 = {
|
|
|
2579
2538
|
42161: arbitrum2,
|
|
2580
2539
|
1: mainnet2
|
|
2581
2540
|
};
|
|
2541
|
+
var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai", "sail"];
|
|
2582
2542
|
var SPONSORED_WETH_BY_CHAIN = {
|
|
2583
2543
|
8453: "0x4200000000000000000000000000000000000006",
|
|
2584
2544
|
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
@@ -2607,6 +2567,7 @@ var OwneySDK = class {
|
|
|
2607
2567
|
zyfaiRpcUrls;
|
|
2608
2568
|
routingApiBaseUrl;
|
|
2609
2569
|
referralSource;
|
|
2570
|
+
surfliquidApiBaseUrl;
|
|
2610
2571
|
cachedSponsoredCallback = null;
|
|
2611
2572
|
cachedWethSponsoredCallback = null;
|
|
2612
2573
|
paymasterServiceUrl;
|
|
@@ -2619,6 +2580,7 @@ var OwneySDK = class {
|
|
|
2619
2580
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
2620
2581
|
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
2621
2582
|
this.referralSource = config.referralSource;
|
|
2583
|
+
this.surfliquidApiBaseUrl = config.surfliquidApiBaseUrl;
|
|
2622
2584
|
}
|
|
2623
2585
|
/**
|
|
2624
2586
|
* Establish connection state for all subsequent SDK calls.
|
|
@@ -2848,8 +2810,8 @@ var OwneySDK = class {
|
|
|
2848
2810
|
this.initializingAgentsPromise = (async () => {
|
|
2849
2811
|
const agentKeys = await fetchAgentKeys(this.apiKey);
|
|
2850
2812
|
this.disabledAgents.clear();
|
|
2851
|
-
for (const { key: key2, agent_type, is_enabled } of agentKeys) {
|
|
2852
|
-
const agent = this.createAgent(agent_type, key2);
|
|
2813
|
+
for (const { key: key2, agent_type, project_name, is_enabled } of agentKeys) {
|
|
2814
|
+
const agent = await this.createAgent(agent_type, key2, project_name);
|
|
2853
2815
|
if (!agent) continue;
|
|
2854
2816
|
this.agents.set(agent_type, agent);
|
|
2855
2817
|
if (is_enabled === false) {
|
|
@@ -2870,10 +2832,22 @@ var OwneySDK = class {
|
|
|
2870
2832
|
this.initializingAgentsPromise = null;
|
|
2871
2833
|
}
|
|
2872
2834
|
}
|
|
2873
|
-
createAgent(agentId, key2) {
|
|
2835
|
+
async createAgent(agentId, key2, projectName) {
|
|
2874
2836
|
if (agentId === "zyfai") {
|
|
2875
2837
|
return new ZyfaiAgent(key2, this.zyfaiRpcUrls, this.referralSource);
|
|
2876
2838
|
}
|
|
2839
|
+
if (agentId === "surfliquid") {
|
|
2840
|
+
if (!projectName) return null;
|
|
2841
|
+
const { SurfLiquidAgent } = await import("./surfliquid.agent-VNGQUSXN.js");
|
|
2842
|
+
return new SurfLiquidAgent({
|
|
2843
|
+
projectName,
|
|
2844
|
+
appId: key2,
|
|
2845
|
+
// Same-origin proxy override — SurfLiquid auth is an httpOnly cookie,
|
|
2846
|
+
// which WebKit (iOS) discards when it is third-party. See
|
|
2847
|
+
// OwneySDKConfig.surfliquidApiBaseUrl.
|
|
2848
|
+
apiBaseUrl: this.surfliquidApiBaseUrl
|
|
2849
|
+
});
|
|
2850
|
+
}
|
|
2877
2851
|
return null;
|
|
2878
2852
|
}
|
|
2879
2853
|
// --- Account lifecycle ---
|
|
@@ -3028,18 +3002,30 @@ var OwneySDK = class {
|
|
|
3028
3002
|
);
|
|
3029
3003
|
}
|
|
3030
3004
|
const agentResults = {};
|
|
3005
|
+
const agentErrors = {};
|
|
3031
3006
|
for (const { agent, amount: agentAmount } of agentAmounts) {
|
|
3032
|
-
|
|
3033
|
-
agent
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3007
|
+
try {
|
|
3008
|
+
agentResults[agent.id] = await this.depositWithFallback(
|
|
3009
|
+
agent,
|
|
3010
|
+
state,
|
|
3011
|
+
chainId,
|
|
3012
|
+
agentAmount,
|
|
3013
|
+
asset,
|
|
3014
|
+
effectiveCallback,
|
|
3015
|
+
depositCallback
|
|
3016
|
+
);
|
|
3017
|
+
} catch (error) {
|
|
3018
|
+
agentErrors[agent.id] = error instanceof Error ? error.message : String(error);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
if (Object.keys(agentResults).length === 0) {
|
|
3022
|
+
throw new OwneyError(
|
|
3023
|
+
"DEPOSIT_ALL_FAILED",
|
|
3024
|
+
`All ${agentAmounts.length} agent deposit(s) failed.`,
|
|
3025
|
+
{ agentErrors }
|
|
3040
3026
|
);
|
|
3041
3027
|
}
|
|
3042
|
-
return { agentResults };
|
|
3028
|
+
return Object.keys(agentErrors).length > 0 ? { agentResults, agentErrors } : { agentResults };
|
|
3043
3029
|
}
|
|
3044
3030
|
/**
|
|
3045
3031
|
* Invokes `agent.deposit` with the resolved sponsored callback, composing
|
|
@@ -3155,9 +3141,8 @@ var OwneySDK = class {
|
|
|
3155
3141
|
async hasExistingBalance(agent, state, chainId, asset) {
|
|
3156
3142
|
try {
|
|
3157
3143
|
const balance = await agent.getBalances(state, chainId);
|
|
3158
|
-
const target = asset.toLowerCase();
|
|
3159
3144
|
const token = balance.tokens.find(
|
|
3160
|
-
(t) => t.chainId === chainId && t.asset
|
|
3145
|
+
(t) => t.chainId === chainId && isSameAsset(t.asset, asset)
|
|
3161
3146
|
);
|
|
3162
3147
|
return !!token && Number(token.amount) > 0;
|
|
3163
3148
|
} catch {
|
|
@@ -3196,6 +3181,34 @@ var OwneySDK = class {
|
|
|
3196
3181
|
}
|
|
3197
3182
|
return eligible;
|
|
3198
3183
|
}
|
|
3184
|
+
/**
|
|
3185
|
+
* Agent ids the routing API provisioned for this org that support the given
|
|
3186
|
+
* chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
|
|
3187
|
+
* surfliquid first). Returns `[]` when the org has no compatible agent — never
|
|
3188
|
+
* throws on an empty org. Loads agent keys on first call (apiKey only, no
|
|
3189
|
+
* wallet), so the UI can resolve which agent to use before the user connects.
|
|
3190
|
+
*
|
|
3191
|
+
* This is the source of truth for agent availability: an agent appears here
|
|
3192
|
+
* iff the routing API returned its key. No per-app feature flags.
|
|
3193
|
+
*/
|
|
3194
|
+
async getEligibleAgentIds(chainId, asset) {
|
|
3195
|
+
try {
|
|
3196
|
+
await this.ensureAgentsInitialized();
|
|
3197
|
+
} catch (error) {
|
|
3198
|
+
if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
|
|
3199
|
+
return [];
|
|
3200
|
+
}
|
|
3201
|
+
throw error;
|
|
3202
|
+
}
|
|
3203
|
+
return [...this.agents.values()].filter((agent) => {
|
|
3204
|
+
const chainAssets = agent.supportedAssets.find(
|
|
3205
|
+
(sa) => sa.chainId === chainId
|
|
3206
|
+
);
|
|
3207
|
+
return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
|
|
3208
|
+
}).map((agent) => agent.id).sort(
|
|
3209
|
+
(a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
|
|
3210
|
+
);
|
|
3211
|
+
}
|
|
3199
3212
|
// --- Fund operations ---
|
|
3200
3213
|
/**
|
|
3201
3214
|
* Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
|
|
@@ -3231,9 +3244,17 @@ var OwneySDK = class {
|
|
|
3231
3244
|
}
|
|
3232
3245
|
const eligibleAgents = this.getEligibleAgents(chainId, asset);
|
|
3233
3246
|
if (!amount) {
|
|
3247
|
+
const aggregated2 = await this.getBalances();
|
|
3248
|
+
const funded = projectAgentBalancesForAsset(
|
|
3249
|
+
eligibleAgents,
|
|
3250
|
+
aggregated2.agentBalances,
|
|
3251
|
+
chainId,
|
|
3252
|
+
asset,
|
|
3253
|
+
assetInfo.decimals
|
|
3254
|
+
).filter((b) => b.balance > 0n);
|
|
3234
3255
|
const results2 = {};
|
|
3235
3256
|
const agentErrors2 = {};
|
|
3236
|
-
for (const agent of
|
|
3257
|
+
for (const { agent } of funded) {
|
|
3237
3258
|
try {
|
|
3238
3259
|
results2[agent.id] = await agent.withdraw(state, chainId, token);
|
|
3239
3260
|
} catch (err) {
|
|
@@ -3250,9 +3271,10 @@ var OwneySDK = class {
|
|
|
3250
3271
|
{ asset, agentErrors: agentErrors2 }
|
|
3251
3272
|
);
|
|
3252
3273
|
}
|
|
3274
|
+
const totalWithdrawn = funded.filter(({ agent }) => results2[agent.id] !== void 0).reduce((sum, { balance }) => sum + balance, 0n);
|
|
3253
3275
|
return {
|
|
3254
3276
|
agentResult: results2,
|
|
3255
|
-
totalWithdrawn:
|
|
3277
|
+
totalWithdrawn: totalWithdrawn.toString()
|
|
3256
3278
|
};
|
|
3257
3279
|
}
|
|
3258
3280
|
const requested = BigInt(amount);
|