@owney/sdk 0.7.12-beta.1 → 0.7.12

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 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: chainName2,
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
- if (positions.length === 0) {
907
- positions.push(
908
- ...(portfolio.positions ?? []).map((p) => ({
909
- chain: p.chain ?? "",
910
- protocol: p.protocol_name ?? p.protocol_id ?? "",
911
- protocolId: p.protocol_id,
912
- pool: p.pool,
913
- asset: p.token_symbol ?? "",
914
- // Fee-adjusted underlying amounts are decimal base-unit strings; the
915
- // legacy `amount` fallback is hex. Runtime getBalances payloads often
916
- // carry `decimals` (e.g. 18 for WETH) — prefer it when present,
917
- // otherwise fall back to the per-symbol lookup.
918
- amount: String(
919
- p.underlyingAmountWithFee ?? p.underlyingAmount ? normalizeDecimalPlace(
920
- p.underlyingAmountWithFee ?? p.underlyingAmount ?? "0",
921
- tokenDecimals(
922
- p.token_symbol,
923
- p.decimals
924
- )
925
- ) : hexToDecimal(
926
- p.amount || "0",
927
- tokenDecimals(
928
- p.token_symbol,
929
- p.decimals
930
- )
931
- )
932
- ),
933
- apy: p.pool_apy,
934
- tvl: p.pool_tvl,
935
- // PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
936
- // structural read keeps it undefined today and auto-populates later.
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
- await this.logDepositWithRetry(
2361
- validChainId,
2362
- txHash,
2363
- amount,
2364
- tokenAddress
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 && isSameAsset(t.asset, asset)
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 import_viem7 = require("viem");
2765
- var import_chains3 = require("viem/chains");
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 base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2127
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2811
2128
  let res;
2812
2129
  try {
2813
- res = await fetch(`${base4}/api/v1/sponsor/erc20-transfer-auth`, {
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 base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2167
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2851
2168
  let res;
2852
2169
  try {
2853
- res = await fetch(`${base4}/api/v1/sponsor/permit2-transfer`, {
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 base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2205
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2889
2206
  let res;
2890
2207
  try {
2891
2208
  res = await fetch(
2892
- `${base4}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
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/sponsored-deposit.ts
2925
- init_permit2();
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: import_chains3.base,
3247
- 42161: import_chains3.arbitrum,
3248
- 1: import_chains3.mainnet
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, import_viem7.createPublicClient)({
2776
+ getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
3393
2777
  chain: VIEM_CHAIN2[cid],
3394
- transport: (0, import_viem7.custom)(provider)
2778
+ transport: (0, import_viem6.custom)(provider)
3395
2779
  }),
3396
- getWalletClient: (cid) => (0, import_viem7.createWalletClient)({
2780
+ getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
3397
2781
  account: owner,
3398
2782
  chain: VIEM_CHAIN2[cid],
3399
- transport: (0, import_viem7.custom)(provider)
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, import_viem7.createPublicClient)({
2829
+ getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
3446
2830
  chain: VIEM_CHAIN2[cid],
3447
- transport: (0, import_viem7.custom)(provider)
2831
+ transport: (0, import_viem6.custom)(provider)
3448
2832
  }),
3449
- getWalletClient: (cid) => (0, import_viem7.createWalletClient)({
2833
+ getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
3450
2834
  account: owner,
3451
2835
  chain: VIEM_CHAIN2[cid],
3452
- transport: (0, import_viem7.custom)(provider)
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, project_name, is_enabled } of agentKeys) {
3523
- const agent = await this.createAgent(agent_type, key2, project_name);
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
- async createAgent(agentId, key2, projectName) {
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 — Zyfai's
3642
- * SIWX (exchanged for a JWT) and SurfLiquid's SIWE (exchanged for an httpOnly
3643
- * cookie). Run in parallel, that puts two `personal_sign` requests on one
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
- try {
3746
- agentResults[agent.id] = await this.depositWithFallback(
3747
- agent,
3748
- state,
3749
- chainId,
3750
- agentAmount,
3751
- asset,
3752
- effectiveCallback,
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 Object.keys(agentErrors).length > 0 ? { agentResults, agentErrors } : { agentResults };
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 && isSameAsset(t.asset, asset)
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 { agent } of funded) {
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: totalWithdrawn.toString()
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, import_viem7.createWalletClient)({
3731
+ const wallet = (0, import_viem6.createWalletClient)({
4408
3732
  account: state.walletAddress,
4409
3733
  chain: VIEM_CHAIN2[chainId],
4410
- transport: (0, import_viem7.custom)(provider)
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, import_viem7.createPublicClient)({
3744
+ const publicClient = (0, import_viem6.createPublicClient)({
4421
3745
  chain: VIEM_CHAIN2[chainId],
4422
- transport: (0, import_viem7.custom)(provider)
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 import_viem8 = require("viem");
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, import_viem8.getAddress)(accountAddress),
3982
+ address: (0, import_viem7.getAddress)(accountAddress),
4662
3983
  chainId: numericChainId(chainId),
4663
3984
  domain,
4664
3985
  uri,