@owney/sdk 0.7.16-beta.7 → 0.7.17-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/index.cjs CHANGED
@@ -1,18 +1,8 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res, err) => function __init() {
9
- if (err) throw err[0];
10
- try {
11
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
- } catch (e) {
13
- throw err = [e], e;
14
- }
15
- };
16
6
  var __export = (target, all) => {
17
7
  for (var name in all)
18
8
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -25,1245 +15,183 @@ var __copyProps = (to, from, except, desc) => {
25
15
  }
26
16
  return to;
27
17
  };
28
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
- // If the importer is in node compatibility mode or this is not an ESM
30
- // file that has been converted to a CommonJS file using a Babel-
31
- // compatible transform (i.e. "__esModule" has not been set), then set
32
- // "default" to the CommonJS "module.exports" for node compatibility.
33
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
- mod
35
- ));
36
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
19
 
38
- // src/lib/debug.ts
39
- function setOwneyDebug(enabled) {
40
- configuredDebug = enabled;
41
- }
42
- function isOwneyDebug() {
43
- return globalThis.__OWNEY_DEBUG__ === true || configuredDebug;
44
- }
45
- function debugLog(scope, message, data) {
46
- if (!isOwneyDebug()) return;
47
- if (data === void 0) {
48
- console.log(`[${scope}] ${message}`);
49
- } else {
50
- console.log(`[${scope}] ${message}`, data);
51
- }
52
- }
53
- var configuredDebug;
54
- var init_debug = __esm({
55
- "src/lib/debug.ts"() {
56
- "use strict";
57
- configuredDebug = false;
58
- }
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AgentChainIncompatibleError: () => AgentChainIncompatibleError,
24
+ AgentNotFoundError: () => AgentNotFoundError,
25
+ InvalidHistoryCursorError: () => InvalidHistoryCursorError,
26
+ NotConnectedError: () => NotConnectedError,
27
+ OwneyError: () => OwneyError,
28
+ OwneySDK: () => OwneySDK,
29
+ createOwneySIWX: () => createOwneySIWX,
30
+ setOwneyDebug: () => setOwneyDebug
59
31
  });
32
+ module.exports = __toCommonJS(index_exports);
60
33
 
61
34
  // src/errors.ts
62
- var OwneyError, AgentNotFoundError, NotConnectedError, AgentChainIncompatibleError;
63
- var init_errors = __esm({
64
- "src/errors.ts"() {
65
- "use strict";
66
- OwneyError = class extends Error {
67
- code;
68
- details;
69
- agentId;
70
- constructor(code, message, details, agentId) {
71
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
72
- super(`${prefix} ${message}`);
73
- this.name = "OwneyError";
74
- this.code = code;
75
- this.details = details;
76
- this.agentId = agentId;
77
- }
78
- };
79
- AgentNotFoundError = class extends OwneyError {
80
- constructor(agentId, available) {
81
- super(
82
- "AGENT_NOT_FOUND",
83
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
84
- { agentId, available },
85
- agentId
86
- );
87
- this.name = "AgentNotFoundError";
88
- }
89
- };
90
- NotConnectedError = class extends OwneyError {
91
- constructor() {
92
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
93
- this.name = "NotConnectedError";
94
- }
95
- };
96
- AgentChainIncompatibleError = class extends OwneyError {
97
- incompatibleAgents;
98
- connectedChainId;
99
- constructor(incompatibleAgents, connectedChainId) {
100
- const details = incompatibleAgents.map(
101
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
102
- ).join("; ");
103
- super(
104
- "AGENT_CHAIN_INCOMPATIBLE",
105
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
106
- { incompatibleAgents, connectedChainId }
107
- );
108
- this.name = "AgentChainIncompatibleError";
109
- this.incompatibleAgents = incompatibleAgents;
110
- this.connectedChainId = connectedChainId;
111
- }
112
- };
113
- }
114
- });
115
-
116
- // src/lib/routing-api.ts
117
- var routing_api_exports = {};
118
- __export(routing_api_exports, {
119
- ROUTING_API_BASE_URL: () => ROUTING_API_BASE_URL,
120
- fetchAgentKeys: () => fetchAgentKeys,
121
- fetchOrgAgentConfig: () => fetchOrgAgentConfig
122
- });
123
- async function fetchOrgAgentConfig(apiKey, baseUrl = ROUTING_API_BASE_URL) {
124
- const url = `${baseUrl}/api/v1/agent/org-config`;
125
- try {
126
- const res = await fetch(url, {
127
- method: "GET",
128
- headers: {
129
- "Content-Type": "application/json",
130
- "x-owney-api-key": `${apiKey}`
131
- }
132
- });
133
- if (!res.ok) {
134
- if (res.status !== 404) {
135
- console.warn(
136
- `[owney-sdk] Could not read org agent config (${res.status}); leaving user profiles unchanged.`
137
- );
138
- }
139
- return null;
140
- }
141
- const json = await res.json();
142
- const policy = json.success ? json.data ?? null : null;
143
- debugLog(
144
- "owney-sdk",
145
- policy ? "org agent config: loaded" : "org agent config: none set by this partner \u2014 user profiles will be left as they are",
146
- policy ?? void 0
147
- );
148
- return policy;
149
- } catch (error) {
150
- console.warn(
151
- "[owney-sdk] Could not read org agent config (non-fatal):",
152
- error instanceof Error ? error.message : String(error)
153
- );
154
- return null;
35
+ var OwneyError = class extends Error {
36
+ code;
37
+ details;
38
+ agentId;
39
+ constructor(code, message, details, agentId) {
40
+ const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
41
+ super(`${prefix} ${message}`);
42
+ this.name = "OwneyError";
43
+ this.code = code;
44
+ this.details = details;
45
+ this.agentId = agentId;
155
46
  }
156
- }
157
- async function fetchAgentKeys(apiKey, baseUrl = ROUTING_API_BASE_URL) {
158
- const url = `${baseUrl}/api/v1/agent/keys`;
159
- const res = await fetch(url, {
160
- method: "GET",
161
- headers: {
162
- "Content-Type": "application/json",
163
- "x-owney-api-key": `${apiKey}`
164
- }
165
- });
166
- if (!res.ok) {
167
- const text = await res.text().catch(() => "");
168
- throw new OwneyError(
169
- "API_ROUTING_ERROR",
170
- `Routing API error ${res.status}: ${text}`,
171
- { statusCode: res.status, responseBody: text }
172
- );
173
- }
174
- const json = await res.json();
175
- if (!json.success) {
176
- throw new OwneyError(
177
- "API_ROUTING_FAILED",
178
- `Routing API request failed: ${json.message}`,
179
- { message: json.message }
47
+ };
48
+ var AgentNotFoundError = class extends OwneyError {
49
+ constructor(agentId, available) {
50
+ super(
51
+ "AGENT_NOT_FOUND",
52
+ `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
53
+ { agentId, available },
54
+ agentId
180
55
  );
56
+ this.name = "AgentNotFoundError";
181
57
  }
182
- return json.data;
183
- }
184
- var ROUTING_API_BASE_URL;
185
- var init_routing_api = __esm({
186
- "src/lib/routing-api.ts"() {
187
- "use strict";
188
- init_errors();
189
- init_debug();
190
- ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
191
- }
192
- });
193
-
194
- // src/lib/transfer-auth.ts
195
- function buildTransferWithAuthorizationTypedData(input) {
196
- return {
197
- domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
198
- types: {
199
- TransferWithAuthorization: [
200
- { name: "from", type: "address" },
201
- { name: "to", type: "address" },
202
- { name: "value", type: "uint256" },
203
- { name: "validAfter", type: "uint256" },
204
- { name: "validBefore", type: "uint256" },
205
- { name: "nonce", type: "bytes32" }
206
- ]
207
- },
208
- primaryType: "TransferWithAuthorization",
209
- message: input.message
210
- };
211
- }
212
- function buildReceiveWithAuthorizationTypedData(input) {
213
- const transfer = buildTransferWithAuthorizationTypedData(input);
214
- return {
215
- ...transfer,
216
- types: { ReceiveWithAuthorization: transfer.types.TransferWithAuthorization },
217
- primaryType: "ReceiveWithAuthorization"
218
- };
219
- }
220
- async function readTokenMeta(publicClient, token) {
221
- const [tokenName, tokenVersion] = await Promise.all([
222
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
223
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
224
- ]);
225
- return { tokenName, tokenVersion };
226
- }
227
- function randomAuthNonce() {
228
- const bytes = new Uint8Array(32);
229
- globalThis.crypto.getRandomValues(bytes);
230
- return (0, import_viem3.bytesToHex)(bytes);
231
- }
232
- var import_viem3, ERC20_META_ABI;
233
- var init_transfer_auth = __esm({
234
- "src/lib/transfer-auth.ts"() {
235
- "use strict";
236
- import_viem3 = require("viem");
237
- ERC20_META_ABI = [
238
- { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
239
- { type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
240
- ];
241
- }
242
- });
243
-
244
- // src/lib/permit2.ts
245
- function buildPermitTransferFromTypedData(input) {
246
- return {
247
- domain: {
248
- name: "Permit2",
249
- chainId: input.chainId,
250
- verifyingContract: PERMIT2_ADDRESS
251
- },
252
- types: {
253
- PermitTransferFrom: [
254
- { name: "permitted", type: "TokenPermissions" },
255
- { name: "spender", type: "address" },
256
- { name: "nonce", type: "uint256" },
257
- { name: "deadline", type: "uint256" }
258
- ],
259
- TokenPermissions: [
260
- { name: "token", type: "address" },
261
- { name: "amount", type: "uint256" }
262
- ]
263
- },
264
- primaryType: "PermitTransferFrom",
265
- message: input.message
266
- };
267
- }
268
- function randomPermit2Nonce() {
269
- const bytes = new Uint8Array(32);
270
- globalThis.crypto.getRandomValues(bytes);
271
- return BigInt((0, import_viem4.bytesToHex)(bytes));
272
- }
273
- async function readPermit2Allowance(publicClient, token, owner) {
274
- return publicClient.readContract({
275
- address: token,
276
- abi: ERC20_ALLOWANCE_ABI,
277
- functionName: "allowance",
278
- args: [owner, PERMIT2_ADDRESS]
279
- });
280
- }
281
- async function readErc20Balance(publicClient, token, owner) {
282
- return publicClient.readContract({
283
- address: token,
284
- abi: ERC20_ALLOWANCE_ABI,
285
- functionName: "balanceOf",
286
- args: [owner]
287
- });
288
- }
289
- var import_viem4, PERMIT2_ADDRESS, MAX_UINT256, ERC20_ALLOWANCE_ABI;
290
- var init_permit2 = __esm({
291
- "src/lib/permit2.ts"() {
292
- "use strict";
293
- import_viem4 = require("viem");
294
- PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
295
- MAX_UINT256 = 2n ** 256n - 1n;
296
- ERC20_ALLOWANCE_ABI = [
297
- {
298
- type: "function",
299
- name: "allowance",
300
- stateMutability: "view",
301
- inputs: [
302
- { name: "owner", type: "address" },
303
- { name: "spender", type: "address" }
304
- ],
305
- outputs: [{ name: "", type: "uint256" }]
306
- },
307
- {
308
- type: "function",
309
- name: "approve",
310
- stateMutability: "nonpayable",
311
- inputs: [
312
- { name: "spender", type: "address" },
313
- { name: "amount", type: "uint256" }
314
- ],
315
- outputs: [{ name: "", type: "bool" }]
316
- },
317
- {
318
- type: "function",
319
- name: "balanceOf",
320
- stateMutability: "view",
321
- inputs: [{ name: "account", type: "address" }],
322
- outputs: [{ name: "", type: "uint256" }]
323
- }
324
- ];
325
- }
326
- });
327
-
328
- // src/agents/surfliquid/surfliquid.constants.ts
329
- 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;
330
- var init_surfliquid_constants = __esm({
331
- "src/agents/surfliquid/surfliquid.constants.ts"() {
332
- "use strict";
333
- SURFLIQUID_CHAIN_ID = 8453;
334
- SURFLIQUID_CHAIN_NAME = "BASE";
335
- SURFLIQUID_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
336
- SURFLIQUID_USDC_DECIMALS = 6;
337
- SURFLIQUID_MIN_DEPOSIT = "0";
338
- SURFLIQUID_APPROVAL_TARGET = 100000000000n;
339
- SURFLIQUID_SUPPORTED_ASSETS = [
340
- {
341
- chainId: SURFLIQUID_CHAIN_ID,
342
- chain: SURFLIQUID_CHAIN_NAME,
343
- assets: [{ symbol: "USDC", minDepositAmount: SURFLIQUID_MIN_DEPOSIT }]
344
- }
345
- ];
346
- SURFLIQUID_ACTION_MAP = {
347
- // INITIAL_DEPOSIT is the user's real first deposit, so surface it like any
348
- // other funding ("Top up"). The mini-app intentionally hides the "Deposit"
349
- // action (it marks Zyfai's smart-account-creation event), which would
350
- // otherwise drop a SurfLiquid user's only history row.
351
- INITIAL_DEPOSIT: "Top up",
352
- DEPOSIT: "Top up",
353
- USER_DEPOSIT: "Top up",
354
- WITHDRAWAL: "Withdraw",
355
- USER_WITHDRAWAL: "Withdraw",
356
- REBALANCE: "Rebalance",
357
- REBALANCE_COMPLETED: "Rebalance",
358
- CROSS_CHAIN_REBALANCE: "Rebalance",
359
- MERKL_CLAIM: "Earned"
360
- };
361
- }
362
- });
363
-
364
- // src/agents/surfliquid/surfliquid.mapper.ts
365
- function mapMessage(message) {
366
- const action = SURFLIQUID_ACTION_MAP[message.transactionType];
367
- if (!action) return null;
368
- return {
369
- agent: "surfliquid",
370
- action,
371
- date: message.timestamp,
372
- oldApy: message.apyBefore != null ? String(message.apyBefore) : null,
373
- newApy: message.apyAfter != null ? String(message.apyAfter) : null,
374
- transactions: [
375
- {
376
- txHashes: [message.txHash],
377
- chainId: message.chainId,
378
- tokenSymbol: message.token ?? void 0,
379
- amount: message.amount != null ? String(message.amount) : void 0
380
- }
381
- ],
382
- rebalanceLog: []
383
- };
384
- }
385
- function mapHistory(result, _chainId) {
386
- const data = result.messages.map(mapMessage).filter((entry) => entry !== null);
387
- const hasMore = result.page < result.pages;
388
- return {
389
- data,
390
- hasMore,
391
- nextCursor: hasMore ? String(result.page + 1) : void 0
392
- };
393
- }
394
- function mapBalances2(vault, chainId, morphoStats) {
395
- const assets = (vault.assets ?? []).filter(
396
- (asset) => asset.assetSymbol === "USDC" && asset.chainId === chainId
397
- );
398
- const tokens = assets.map((asset) => ({
399
- chain: SURFLIQUID_CHAIN_NAME,
400
- chainId: SURFLIQUID_CHAIN_ID,
401
- asset: "USDC",
402
- amount: String(asset.currentValueUSD)
403
- }));
404
- const positions = assets.map((asset) => {
405
- const stats = morphoStats?.get(asset.morphoVaultAddress?.toLowerCase() ?? "");
406
- return {
407
- chain: SURFLIQUID_CHAIN_NAME,
408
- protocol: "Morpho",
409
- // The specific MetaMorpho vault (e.g. "Gauntlet USDC Frontier"), read from
410
- // Morpho — renders as "Morpho <vault>" alongside zyfai's vault detail.
411
- pool: stats?.name ?? void 0,
412
- asset: "USDC",
413
- amount: String(asset.currentValueUSD),
414
- apy: asset.currentAPY,
415
- // TVL + liquidity come straight from Morpho (SurfLiquid's API omits them).
416
- tvl: stats?.tvlUsd,
417
- liquidity: stats?.liquidityUsd
418
- };
419
- });
420
- const total = assets.reduce(
421
- (sum, asset) => sum + asset.currentValueUSD,
422
- 0
423
- );
424
- return {
425
- smartWallet: vault.userVaultAddress ?? void 0,
426
- totalBalance: String(total),
427
- totalBalanceAsset: "usdc",
428
- tokens,
429
- positions
430
- };
431
- }
432
- function mapAccountApy(vault, days) {
433
- const breakdown = vault.apyBreakdown;
434
- const windowed = breakdown ? breakdown[APY_WINDOW_KEY[days]] : void 0;
435
- const apy = windowed != null ? windowed : breakdown?.currentAPY ?? 0;
436
- return {
437
- walletAddress: vault.walletAddress ?? "",
438
- weightedApyAfterFee: apy,
439
- apyByChainAndAsset: { [SURFLIQUID_CHAIN_ID]: { USDC: apy } },
440
- // Parity with Sail: SurfLiquid's core-sdk exposes no daily net-APY series.
441
- history: []
442
- };
443
- }
444
- function mapEarnings2(vault, vaultAddress) {
445
- return {
446
- smartWallet: vaultAddress,
447
- lifetimeEarnings: vault.earned?.totalEarningsUSD ?? 0,
448
- tokens: []
449
- };
450
- }
451
- function mapUserProfile2(vault, address) {
452
- return {
453
- address,
454
- smartWallet: vault.userVaultAddress ?? "",
455
- chains: [SURFLIQUID_CHAIN_ID],
456
- // SurfLiquid uses cookie-based session auth — no session-key concept.
457
- hasActiveSessionKey: false,
458
- protocols: ["SurfLiquid"]
459
- };
460
- }
461
- var APY_WINDOW_KEY;
462
- var init_surfliquid_mapper = __esm({
463
- "src/agents/surfliquid/surfliquid.mapper.ts"() {
464
- "use strict";
465
- init_surfliquid_constants();
466
- APY_WINDOW_KEY = {
467
- "7D": "apy7d",
468
- "14D": "apy14d",
469
- "30D": "apy30d"
470
- };
471
- }
472
- });
473
-
474
- // src/agents/surfliquid/surfliquid.wallet-adapter.ts
475
- var import_core_sdk, OwneyWalletAdapter;
476
- var init_surfliquid_wallet_adapter = __esm({
477
- "src/agents/surfliquid/surfliquid.wallet-adapter.ts"() {
478
- "use strict";
479
- import_core_sdk = require("@surf_liquid/core-sdk");
480
- OwneyWalletAdapter = class extends import_core_sdk.BaseWalletAdapter {
481
- constructor(eip1193Provider) {
482
- super();
483
- this.eip1193Provider = eip1193Provider;
484
- }
485
- eip1193Provider;
486
- name = "owney";
487
- get installed() {
488
- return true;
489
- }
490
- resolveProvider() {
491
- return this.eip1193Provider;
492
- }
493
- };
494
- }
495
- });
496
-
497
- // src/agents/surfliquid/surfliquid.morpho.ts
498
- async function queryMorpho(query, vaultAddress, chainId) {
499
- try {
500
- const res = await fetch(MORPHO_API_URL, {
501
- method: "POST",
502
- headers: { "Content-Type": "application/json" },
503
- body: JSON.stringify({
504
- query,
505
- variables: { address: vaultAddress, chainId }
506
- })
507
- });
508
- if (!res.ok) return null;
509
- const json = await res.json();
510
- if (json.errors) return null;
511
- return json.data ?? null;
512
- } catch (error) {
513
- console.warn("surfliquid: Morpho vault stats fetch failed", {
514
- vaultAddress,
515
- chainId,
516
- error
517
- });
518
- return null;
519
- }
520
- }
521
- function toStats(name, tvlUsd, liquidityUsd) {
522
- if (typeof tvlUsd !== "number" || typeof liquidityUsd !== "number") {
523
- return null;
524
- }
525
- return {
526
- name: typeof name === "string" ? name : null,
527
- tvlUsd,
528
- liquidityUsd
529
- };
530
- }
531
- async function fetchMorphoVaultStats(vaultAddress, chainId) {
532
- const v1 = await queryMorpho(VAULT_STATS_QUERY, vaultAddress, chainId);
533
- const vault = v1?.vaultByAddress;
534
- const v1Stats = toStats(
535
- vault?.name,
536
- vault?.state?.totalAssetsUsd,
537
- vault?.liquidity?.usd
538
- );
539
- if (v1Stats) return v1Stats;
540
- const v2 = await queryMorpho(VAULT_V2_STATS_QUERY, vaultAddress, chainId);
541
- const vaultV2 = v2?.vaultV2ByAddress;
542
- return toStats(vaultV2?.name, vaultV2?.totalAssetsUsd, vaultV2?.liquidityUsd);
543
- }
544
- async function fetchMorphoStatsByVault(vaultAddresses, chainId) {
545
- const unique = [...new Set(vaultAddresses.map((a) => a.toLowerCase()))];
546
- const entries = await Promise.all(
547
- unique.map(
548
- async (address) => [address, await fetchMorphoVaultStats(address, chainId)]
549
- )
550
- );
551
- const byVault = /* @__PURE__ */ new Map();
552
- for (const [address, stats] of entries) {
553
- if (stats) byVault.set(address, stats);
554
- }
555
- return byVault;
556
- }
557
- var MORPHO_API_URL, VAULT_STATS_QUERY, VAULT_V2_STATS_QUERY;
558
- var init_surfliquid_morpho = __esm({
559
- "src/agents/surfliquid/surfliquid.morpho.ts"() {
560
- "use strict";
561
- MORPHO_API_URL = "https://api.morpho.org/graphql";
562
- VAULT_STATS_QUERY = `
563
- query VaultStats($address: String!, $chainId: Int!) {
564
- vaultByAddress(address: $address, chainId: $chainId) {
565
- name
566
- state { totalAssetsUsd }
567
- liquidity { usd }
568
- }
569
- }
570
- `;
571
- VAULT_V2_STATS_QUERY = `
572
- query VaultV2Stats($address: String!, $chainId: Int!) {
573
- vaultV2ByAddress(address: $address, chainId: $chainId) {
574
- name
575
- totalAssetsUsd
576
- liquidityUsd
577
- }
578
- }
579
- `;
580
- }
581
- });
582
-
583
- // src/agents/surfliquid/surfliquid.contracts.ts
584
- var import_viem6, SURFLIQUID_FACTORY_ADDRESS, SURFLIQUID_FACTORY_ABI, SURFLIQUID_VAULT_ABI, USDC_ABI;
585
- var init_surfliquid_contracts = __esm({
586
- "src/agents/surfliquid/surfliquid.contracts.ts"() {
587
- "use strict";
588
- import_viem6 = require("viem");
589
- SURFLIQUID_FACTORY_ADDRESS = "0x8fa50DeA8DB10987D7d22ac092001c3613C18779";
590
- SURFLIQUID_FACTORY_ABI = (0, import_viem6.parseAbi)([
591
- "function deployVault(address vaultOwner, bytes32 salt) returns (address)",
592
- "function computeVaultAddress(address vaultOwner, bytes32 salt) view returns (address)"
593
- ]);
594
- SURFLIQUID_VAULT_ABI = (0, import_viem6.parseAbi)([
595
- "function initialDeposit(address asset, address vault, uint256 amount)",
596
- "function userDeposit(address asset, uint256 amount)",
597
- // amount 0 withdraws everything; proceeds go to the vault's owner.
598
- "function withdraw(address asset, uint256 amount)",
599
- "function assetHasInitialDeposit(address asset) view returns (bool)",
600
- "function owner() view returns (address)"
601
- ]);
602
- USDC_ABI = (0, import_viem6.parseAbi)([
603
- "function approve(address spender, uint256 amount)",
604
- "function transfer(address to, uint256 amount)",
605
- "function balanceOf(address account) view returns (uint256)",
606
- "function receiveWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, bytes signature)"
607
- ]);
58
+ };
59
+ var NotConnectedError = class extends OwneyError {
60
+ constructor() {
61
+ super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
62
+ this.name = "NotConnectedError";
608
63
  }
609
- });
610
-
611
- // src/agents/surfliquid/surfliquid.calls.ts
612
- function buildDepositCalls(input) {
613
- const { smartAccount, vault, amount, authorization, deploySalt } = input;
614
- if (authorization.to.toLowerCase() !== smartAccount.toLowerCase()) {
615
- throw new Error("Transfer authorization must pay the smart account");
616
- }
617
- if (authorization.value < amount) {
618
- throw new Error("Transfer authorization is worth less than the deposit");
619
- }
620
- if (!input.hasInitialDeposit && !input.morphoVault) {
621
- throw new Error("A first deposit needs a target morpho vault");
622
- }
623
- const calls = [];
624
- if (deploySalt) {
625
- calls.push(
626
- call(SURFLIQUID_FACTORY_ADDRESS, SURFLIQUID_FACTORY_ABI, "deployVault", [
627
- smartAccount,
628
- deploySalt
629
- ])
64
+ };
65
+ var AgentChainIncompatibleError = class extends OwneyError {
66
+ incompatibleAgents;
67
+ connectedChainId;
68
+ constructor(incompatibleAgents, connectedChainId) {
69
+ const details = incompatibleAgents.map(
70
+ ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
71
+ ).join("; ");
72
+ super(
73
+ "AGENT_CHAIN_INCOMPATIBLE",
74
+ `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
75
+ { incompatibleAgents, connectedChainId }
630
76
  );
77
+ this.name = "AgentChainIncompatibleError";
78
+ this.incompatibleAgents = incompatibleAgents;
79
+ this.connectedChainId = connectedChainId;
631
80
  }
632
- calls.push(
633
- call(SURFLIQUID_USDC_ADDRESS, USDC_ABI, "receiveWithAuthorization", [
634
- authorization.from,
635
- authorization.to,
636
- authorization.value,
637
- authorization.validAfter,
638
- authorization.validBefore,
639
- authorization.nonce,
640
- authorization.signature
641
- ]),
642
- call(SURFLIQUID_USDC_ADDRESS, USDC_ABI, "approve", [vault, amount]),
643
- input.hasInitialDeposit ? call(vault, SURFLIQUID_VAULT_ABI, "userDeposit", [SURFLIQUID_USDC_ADDRESS, amount]) : call(vault, SURFLIQUID_VAULT_ABI, "initialDeposit", [
644
- SURFLIQUID_USDC_ADDRESS,
645
- input.morphoVault,
646
- amount
647
- ])
648
- );
649
- return calls;
650
- }
651
- function buildWithdrawCalls(input) {
652
- return [
653
- call(input.vault, SURFLIQUID_VAULT_ABI, "withdraw", [
654
- SURFLIQUID_USDC_ADDRESS,
655
- input.amount ?? 0n
656
- ])
657
- ];
658
- }
659
- function buildSweepCalls(input) {
660
- return [call(SURFLIQUID_USDC_ADDRESS, USDC_ABI, "transfer", [input.owner, input.amount])];
661
- }
662
- var import_viem7, call;
663
- var init_surfliquid_calls = __esm({
664
- "src/agents/surfliquid/surfliquid.calls.ts"() {
665
- "use strict";
666
- import_viem7 = require("viem");
667
- init_surfliquid_constants();
668
- init_surfliquid_contracts();
669
- call = (to, abi, functionName, args) => ({
670
- to,
671
- data: (0, import_viem7.encodeFunctionData)({ abi, functionName, args })
672
- });
673
- }
674
- });
81
+ };
675
82
 
676
- // src/agents/surfliquid/surfliquid.sponsorship.ts
677
- var surfliquid_sponsorship_exports = {};
678
- __export(surfliquid_sponsorship_exports, {
679
- SubmittedError: () => SubmittedError,
680
- depositSponsored: () => depositSponsored,
681
- isSafeToRetry: () => isSafeToRetry,
682
- withdrawSponsored: () => withdrawSponsored
683
- });
684
- async function resolveVault(ctx) {
685
- const registered = await ctx.api.getVault(ctx.wallet.ownerAddress);
686
- const smartAccount = ctx.wallet.smartAccountAddress;
687
- if (!registered.userVaultAddress) {
688
- const salt2 = registered.deploymentSalt ?? (await ctx.api.prepare(SURFLIQUID_CHAIN_ID)).salt;
689
- return {
690
- vault: await ctx.chain.computeVaultAddress(smartAccount, salt2),
691
- deploySalt: salt2,
692
- registerAfterDeposit: true
693
- };
694
- }
695
- const vault = registered.userVaultAddress;
696
- if (await ctx.chain.isDeployed(vault)) {
697
- const owner = await ctx.chain.readVaultOwner(vault);
698
- if (owner.toLowerCase() !== smartAccount.toLowerCase()) {
699
- throw new Error(`SurfLiquid vault ${vault} is not owned by the smart account`);
83
+ // src/lib/rate-limit.ts
84
+ function rateLimitDelay(error, now = Date.now()) {
85
+ const seen = /* @__PURE__ */ new Set();
86
+ let limited = false;
87
+ let delay = 0;
88
+ function visit(value, depth = 0) {
89
+ if (depth > 6 || value == null) return;
90
+ if (typeof value === "string") {
91
+ if (/rate[ _-]?limit|too many requests|HTTP_429|\b429\b/i.test(value))
92
+ limited = true;
93
+ return;
700
94
  }
701
- return { vault, registerAfterDeposit: false };
702
- }
703
- const salt = registered.deploymentSalt;
704
- const deployable = salt ? await ctx.chain.computeVaultAddress(smartAccount, salt) : void 0;
705
- if (!salt || deployable?.toLowerCase() !== vault.toLowerCase()) {
706
- throw new Error(`Registered SurfLiquid vault ${vault} does not match this smart account`);
707
- }
708
- return { vault, deploySalt: salt, registerAfterDeposit: false };
709
- }
710
- async function pickMorphoVault(api) {
711
- const candidates = await api.getBestVault("USDC");
712
- const candidate = candidates.find((option) => option.chainId === SURFLIQUID_CHAIN_ID);
713
- if (!candidate) {
714
- throw new Error(`SurfLiquid has no morpho vault for USDC on chain ${SURFLIQUID_CHAIN_ID}`);
715
- }
716
- return candidate.vaultAddress;
717
- }
718
- async function depositSponsored(input) {
719
- const { api, chain, wallet, amount } = input;
720
- const { vault, deploySalt, registerAfterDeposit } = await resolveVault(input);
721
- const hasInitialDeposit = deploySalt ? false : await chain.hasInitialDeposit(vault, SURFLIQUID_USDC_ADDRESS);
722
- const morphoVault = hasInitialDeposit ? void 0 : await pickMorphoVault(api);
723
- const { tokenName, tokenVersion } = await chain.readTokenMeta();
724
- const message = {
725
- from: wallet.ownerAddress,
726
- to: wallet.smartAccountAddress,
727
- value: amount,
728
- validAfter: 0n,
729
- validBefore: BigInt(Math.floor(Date.now() / 1e3)) + AUTHORIZATION_TTL_SECONDS,
730
- nonce: randomAuthNonce()
731
- };
732
- const signature = await wallet.signTransferAuthorization(
733
- buildReceiveWithAuthorizationTypedData({
734
- token: SURFLIQUID_USDC_ADDRESS,
735
- chainId: SURFLIQUID_CHAIN_ID,
736
- tokenName,
737
- tokenVersion,
738
- message
739
- })
740
- );
741
- const txHash = await wallet.sendCalls(
742
- buildDepositCalls({
743
- smartAccount: wallet.smartAccountAddress,
744
- vault,
745
- amount,
746
- authorization: { ...message, signature },
747
- hasInitialDeposit,
748
- morphoVault,
749
- deploySalt
750
- })
751
- );
752
- if (registerAfterDeposit && deploySalt) {
753
- try {
754
- await api.confirm({
755
- userVaultAddress: vault,
756
- homeChainId: SURFLIQUID_CHAIN_ID,
757
- deploymentSalt: deploySalt,
758
- initialAssets: []
759
- });
760
- } catch (error) {
761
- console.warn(
762
- "[owney-sdk] SurfLiquid vault registration failed after a successful deposit:",
763
- error instanceof Error ? error.message : String(error)
764
- );
95
+ if (typeof value !== "object" || seen.has(value)) return;
96
+ seen.add(value);
97
+ const record = value;
98
+ if ([record.status, record.statusCode, record.code].some(
99
+ (code) => String(code) === "429"
100
+ )) {
101
+ limited = true;
102
+ }
103
+ for (const key2 of ["retryAfterSeconds", "retryAfter"]) {
104
+ const seconds = Number(record[key2]);
105
+ if (Number.isFinite(seconds) && seconds > 0)
106
+ delay = Math.max(delay, seconds * 1e3);
107
+ }
108
+ const retryAt = Number(record.retryAt);
109
+ if (Number.isFinite(retryAt) && retryAt > now)
110
+ delay = Math.max(delay, retryAt - now);
111
+ const headers = record.headers;
112
+ const header = typeof headers?.get === "function" ? headers.get("Retry-After") : headers?.["retry-after"] ?? headers?.["Retry-After"];
113
+ if (typeof header === "string" || typeof header === "number") {
114
+ const seconds = Number(header);
115
+ const ms = Number.isFinite(seconds) ? seconds * 1e3 : Date.parse(String(header)) - now;
116
+ if (Number.isFinite(ms) && ms > 0) delay = Math.max(delay, ms);
117
+ }
118
+ for (const key2 of [
119
+ "message",
120
+ "code",
121
+ "cause",
122
+ "details",
123
+ "response",
124
+ "data",
125
+ "fields"
126
+ ]) {
127
+ visit(record[key2], depth + 1);
128
+ }
129
+ for (const key2 of ["agentErrors", "failures"]) {
130
+ const entries = record[key2];
131
+ if (entries && typeof entries === "object") {
132
+ for (const entry of Object.values(entries)) visit(entry, depth + 1);
133
+ }
765
134
  }
766
135
  }
767
- return { txHash, vault };
768
- }
769
- async function withdrawSponsored(input) {
770
- const { api, chain, wallet, amount } = input;
771
- const registered = await api.getVault(wallet.ownerAddress);
772
- if (!registered.userVaultAddress) {
773
- throw new Error("SurfLiquid has no vault registered for this wallet");
774
- }
775
- const vault = registered.userVaultAddress;
776
- const owner = await chain.readVaultOwner(vault);
777
- if (owner.toLowerCase() !== wallet.smartAccountAddress.toLowerCase()) {
778
- throw new Error(`SurfLiquid vault ${vault} is not owned by the smart account`);
779
- }
780
- const withdrawHash = await wallet.sendCalls(buildWithdrawCalls({ vault, amount }));
781
- try {
782
- const proceeds = await chain.usdcBalanceOf(wallet.smartAccountAddress);
783
- if (proceeds === 0n) return { txHash: withdrawHash, amount: "0" };
784
- const sweepHash = await wallet.sendCalls(
785
- buildSweepCalls({ owner: wallet.ownerAddress, amount: proceeds })
786
- );
787
- return { txHash: sweepHash, amount: proceeds.toString() };
788
- } catch (error) {
789
- throw new SubmittedError(
790
- `SurfLiquid withdrawal ${withdrawHash} landed but the sweep did not: ${error instanceof Error ? error.message : String(error)}`
791
- );
792
- }
136
+ visit(error);
137
+ return limited ? delay : void 0;
793
138
  }
794
- var AUTHORIZATION_TTL_SECONDS, SubmittedError, isSafeToRetry;
795
- var init_surfliquid_sponsorship = __esm({
796
- "src/agents/surfliquid/surfliquid.sponsorship.ts"() {
797
- "use strict";
798
- init_transfer_auth();
799
- init_surfliquid_constants();
800
- init_surfliquid_calls();
801
- AUTHORIZATION_TTL_SECONDS = 3600n;
802
- SubmittedError = class extends Error {
803
- constructor(message, userOpHash) {
804
- super(message);
805
- this.userOpHash = userOpHash;
806
- this.name = "SubmittedError";
807
- }
808
- userOpHash;
809
- };
810
- isSafeToRetry = (error) => !(error instanceof SubmittedError);
811
- }
812
- });
813
139
 
814
- // src/agents/surfliquid/surfliquid.smart-account.ts
815
- var surfliquid_smart_account_exports = {};
816
- __export(surfliquid_smart_account_exports, {
817
- createSponsoredChain: () => createSponsoredChain,
818
- createSponsoredWallet: () => createSponsoredWallet,
819
- pinAccount: () => pinAccount
820
- });
821
- function publicClientFor(rpcUrl) {
822
- return (0, import_viem8.createPublicClient)({ chain: import_chains2.base, transport: (0, import_viem8.http)(rpcUrl) });
823
- }
824
- function createSponsoredChain(rpcUrl) {
825
- const client = publicClientFor(rpcUrl);
826
- return {
827
- computeVaultAddress: (owner, salt) => client.readContract({
828
- address: SURFLIQUID_FACTORY_ADDRESS,
829
- abi: SURFLIQUID_FACTORY_ABI,
830
- functionName: "computeVaultAddress",
831
- args: [owner, salt]
832
- }),
833
- isDeployed: async (address) => {
834
- const code = await client.getCode({ address });
835
- return Boolean(code && code !== "0x");
836
- },
837
- readVaultOwner: (vault) => client.readContract({ address: vault, abi: SURFLIQUID_VAULT_ABI, functionName: "owner" }),
838
- hasInitialDeposit: (vault, asset) => client.readContract({
839
- address: vault,
840
- abi: SURFLIQUID_VAULT_ABI,
841
- functionName: "assetHasInitialDeposit",
842
- args: [asset]
843
- }),
844
- usdcBalanceOf: (address) => client.readContract({
845
- address: SURFLIQUID_USDC_ADDRESS,
846
- abi: USDC_ABI,
847
- functionName: "balanceOf",
848
- args: [address]
849
- }),
850
- // Cast: viem's OP-stack tx union does not match the generic PublicClient
851
- // the helper is typed against, though every method it uses is present.
852
- readTokenMeta: () => readTokenMeta(client, SURFLIQUID_USDC_ADDRESS)
853
- };
854
- }
855
- function pinAccount(provider, address) {
856
- return {
857
- ...provider,
858
- request: (args) => args.method === "eth_accounts" || args.method === "eth_requestAccounts" ? Promise.resolve([address]) : provider.request(args)
859
- };
860
- }
861
- async function createSponsoredWallet(input) {
862
- const entryPoint = { address: import_account_abstraction.entryPoint08Address, version: "0.8" };
863
- const account = await (0, import_accounts.toSimpleSmartAccount)({
864
- client: publicClientFor(input.rpcUrl),
865
- owner: pinAccount(input.provider, input.ownerAddress),
866
- entryPoint
867
- });
868
- const bundlerTransport = (0, import_viem8.http)(sponsorProxyUrl(input.routingApiBaseUrl), {
869
- fetchOptions: { headers: { "x-owney-api-key": input.apiKey } }
870
- });
871
- const pimlico = (0, import_pimlico.createPimlicoClient)({ transport: bundlerTransport, entryPoint });
872
- const smartAccountClient = (0, import_permissionless.createSmartAccountClient)({
873
- account,
874
- chain: import_chains2.base,
875
- bundlerTransport,
876
- paymaster: pimlico,
877
- userOperation: {
878
- estimateFeesPerGas: async () => (await pimlico.getUserOperationGasPrice()).fast
879
- }
880
- });
881
- const walletClient = (0, import_viem8.createWalletClient)({
882
- account: input.ownerAddress,
883
- chain: import_chains2.base,
884
- transport: (0, import_viem8.custom)(input.provider)
885
- });
886
- return {
887
- smartAccountAddress: account.address,
888
- ownerAddress: input.ownerAddress,
889
- // The EOA signs, not the smart account: USDC verifies ECDSA from the token holder.
890
- signTransferAuthorization: (typedData) => walletClient.signTypedData({
891
- account: input.ownerAddress,
892
- domain: typedData.domain,
893
- types: typedData.types,
894
- primaryType: typedData.primaryType,
895
- message: typedData.message
896
- }),
897
- sendCalls: async (calls) => {
898
- const userOpHash = await smartAccountClient.sendUserOperation({
899
- calls: calls.map((c) => ({ to: c.to, data: c.data, value: 0n }))
900
- });
901
- try {
902
- const receipt = await smartAccountClient.waitForUserOperationReceipt({ hash: userOpHash });
903
- return receipt.receipt.transactionHash;
904
- } catch (error) {
905
- throw new SubmittedError(
906
- `user operation ${userOpHash} was submitted but its receipt never arrived`,
907
- userOpHash
908
- );
909
- }
910
- }
911
- };
912
- }
913
- var import_permissionless, import_accounts, import_pimlico, import_viem8, import_account_abstraction, import_chains2, sponsorProxyUrl;
914
- var init_surfliquid_smart_account = __esm({
915
- "src/agents/surfliquid/surfliquid.smart-account.ts"() {
916
- "use strict";
917
- import_permissionless = require("permissionless");
918
- import_accounts = require("permissionless/accounts");
919
- import_pimlico = require("permissionless/clients/pimlico");
920
- import_viem8 = require("viem");
921
- import_account_abstraction = require("viem/account-abstraction");
922
- import_chains2 = require("viem/chains");
923
- init_transfer_auth();
924
- init_surfliquid_constants();
925
- init_surfliquid_contracts();
926
- init_surfliquid_sponsorship();
927
- sponsorProxyUrl = (routingApiBaseUrl) => `${routingApiBaseUrl.replace(/\/$/, "")}/api/v1/sponsor/pimlico-rpc/${SURFLIQUID_CHAIN_ID}`;
140
+ // src/lib/agent-reads.ts
141
+ var AgentReads = class {
142
+ inFlight = /* @__PURE__ */ new Map();
143
+ cooldowns = /* @__PURE__ */ new Map();
144
+ // A reconnect must not reuse work started by the previous connection.
145
+ clearInFlight() {
146
+ this.inFlight.clear();
147
+ }
148
+ limited(agentId, until) {
149
+ return new OwneyError(
150
+ "AGENT_RATE_LIMITED",
151
+ "Too many requests. Please wait before trying again.",
152
+ {
153
+ statusCode: 429,
154
+ retryAt: until,
155
+ retryAfterSeconds: Math.max(0, Math.ceil((until - Date.now()) / 1e3))
156
+ },
157
+ agentId
158
+ );
928
159
  }
929
- });
930
-
931
- // src/agents/surfliquid/surfliquid.agent.ts
932
- var surfliquid_agent_exports = {};
933
- __export(surfliquid_agent_exports, {
934
- SurfLiquidAgent: () => SurfLiquidAgent
935
- });
936
- var import_core_sdk2, import_viem9, import_chains3, APY_WINDOW_KEY2, SurfLiquidAgent;
937
- var init_surfliquid_agent = __esm({
938
- "src/agents/surfliquid/surfliquid.agent.ts"() {
939
- "use strict";
940
- import_core_sdk2 = require("@surf_liquid/core-sdk");
941
- import_viem9 = require("viem");
942
- import_chains3 = require("viem/chains");
943
- init_errors();
944
- init_surfliquid_constants();
945
- init_permit2();
946
- init_surfliquid_mapper();
947
- init_surfliquid_wallet_adapter();
948
- init_surfliquid_morpho();
949
- APY_WINDOW_KEY2 = {
950
- "7D": "apy7d",
951
- "14D": "apy14d",
952
- "30D": "apy30d"
953
- };
954
- SurfLiquidAgent = class {
955
- constructor(config) {
956
- this.config = config;
957
- }
958
- config;
959
- id = "surfliquid";
960
- supportedChainIds = [SURFLIQUID_CHAIN_ID];
961
- supportedAssets = SURFLIQUID_SUPPORTED_ASSETS;
962
- surf = null;
963
- connectedAddress = null;
964
- // In-flight connect+auth, shared by concurrent callers to dedupe SIWE.
965
- connectPromise = null;
966
- ensureSurf() {
967
- if (this.surf) return this.surf;
968
- this.surf = import_core_sdk2.SurfClient.create({
969
- projectName: this.config.projectName,
970
- appId: this.config.appId,
971
- environment: "mainnet",
972
- chainId: SURFLIQUID_CHAIN_ID,
973
- apiBaseUrl: this.config.apiBaseUrl,
974
- rpcUrl: this.config.rpcUrl,
975
- // Let the SDK auto-approve USDC to the vault before depositing.
976
- autoApprove: true
977
- });
978
- return this.surf;
979
- }
980
- /**
981
- * Connects + authenticates the SurfClient against owney's provider. Skips the
982
- * SIWE prompt when already authenticated for this wallet (cookie session).
983
- */
984
- async connect(state) {
985
- const surf = this.ensureSurf();
986
- const sameWallet = this.connectedAddress?.toLowerCase() === state.walletAddress.toLowerCase();
987
- if (sameWallet && surf.getAuthState().authenticated) {
988
- return surf;
989
- }
990
- if (this.connectPromise) return this.connectPromise;
991
- this.connectPromise = (async () => {
992
- surf.registerWalletAdapter(
993
- "owney",
994
- new OwneyWalletAdapter(state.provider)
995
- );
996
- await surf.connectWallet("owney");
997
- await surf.authenticate();
998
- this.connectedAddress = state.walletAddress;
999
- return surf;
1000
- })();
1001
- try {
1002
- return await this.connectPromise;
1003
- } finally {
1004
- this.connectPromise = null;
1005
- }
1006
- }
1007
- /**
1008
- * Returns the user's vault address, deploying one on first use. SurfLiquid's
1009
- * deposit requires the vault to exist, so this must run before depositing.
1010
- * Existing vault → returned as-is; otherwise `deployVault()` is sent
1011
- * (user-pays) and the freshly deployed address is returned.
1012
- */
1013
- async resolveVaultAddress(surf, owner) {
1014
- const vault = await surf.getVault(owner).catch(() => null);
1015
- if (vault?.exists && vault.userVaultAddress) {
1016
- return vault.userVaultAddress;
1017
- }
1018
- const { vaultAddress } = await surf.deployVault();
1019
- return vaultAddress;
1020
- }
1021
- /**
1022
- * Grants the user's vault a standing USDC allowance so SurfLiquid's
1023
- * `autoApprove` has nothing to do — see {@link SURFLIQUID_APPROVAL_TARGET}
1024
- * for why one prompt per deposit is worth removing.
1025
- *
1026
- * Fails OPEN on a read error: if the allowance can't be checked we simply
1027
- * return and let SurfLiquid's own per-deposit approve run, because a flaky
1028
- * RPC must never block a deposit. A failed or rejected APPROVE does
1029
- * propagate — the user declined a transaction, and letting SurfLiquid
1030
- * immediately ask again for a smaller one is exactly the double prompt this
1031
- * removes.
1032
- */
1033
- async ensureVaultAllowance(state, vaultAddress, amount) {
1034
- const spender = vaultAddress;
1035
- const transport = (0, import_viem9.custom)(state.provider);
1036
- const publicClient = (0, import_viem9.createPublicClient)({ chain: import_chains3.base, transport });
1037
- let allowance;
1038
- try {
1039
- allowance = await publicClient.readContract({
1040
- address: SURFLIQUID_USDC_ADDRESS,
1041
- abi: ERC20_ALLOWANCE_ABI,
1042
- functionName: "allowance",
1043
- args: [state.walletAddress, spender]
1044
- });
1045
- } catch (error) {
1046
- console.warn(
1047
- "[owney-sdk] SurfLiquid allowance pre-check failed; deferring to its per-deposit approve:",
1048
- error instanceof Error ? error.message : String(error)
1049
- );
1050
- return;
1051
- }
1052
- if (allowance >= amount) return;
1053
- const target = amount > SURFLIQUID_APPROVAL_TARGET ? amount : SURFLIQUID_APPROVAL_TARGET;
1054
- const wallet = (0, import_viem9.createWalletClient)({
1055
- account: state.walletAddress,
1056
- chain: import_chains3.base,
1057
- transport
1058
- });
1059
- const hash = await wallet.writeContract({
1060
- address: SURFLIQUID_USDC_ADDRESS,
1061
- abi: ERC20_ALLOWANCE_ABI,
1062
- functionName: "approve",
1063
- args: [spender, target],
1064
- account: state.walletAddress,
1065
- chain: import_chains3.base
1066
- });
1067
- const receipt = await publicClient.waitForTransactionReceipt({
1068
- hash,
1069
- confirmations: 1
1070
- });
1071
- if (receipt.status !== "success") {
1072
- throw new Error(`SurfLiquid USDC approval reverted (tx ${hash})`);
1073
- }
1074
- }
1075
- // --- IAgent: lifecycle ---
1076
- async disconnect() {
1077
- if (this.surf) {
1078
- await this.surf.disconnectWallet();
1079
- }
1080
- this.connectedAddress = null;
1081
- }
1082
- async activateAgent(state) {
1083
- await this.connect(state);
1084
- }
1085
- /** Their exported client, so `prepare`/`confirm` ride the SIWE cookie this session already holds. */
1086
- async vaultApi() {
1087
- const { HttpClient, VaultApiService } = await import("@surf_liquid/core-sdk");
1088
- return new VaultApiService(
1089
- new HttpClient({
1090
- baseUrl: this.config.apiBaseUrl ?? "https://api.surfliquid.com",
1091
- projectName: this.config.projectName,
1092
- projectId: this.config.projectName,
1093
- appId: this.config.appId ?? ""
1094
- })
1095
- );
1096
- }
1097
- async sponsoredWallet(state) {
1098
- if (!this.config.apiKey) return null;
1099
- const { createSponsoredWallet: createSponsoredWallet2 } = await Promise.resolve().then(() => (init_surfliquid_smart_account(), surfliquid_smart_account_exports));
1100
- const { ROUTING_API_BASE_URL: ROUTING_API_BASE_URL4 } = await Promise.resolve().then(() => (init_routing_api(), routing_api_exports));
1101
- return createSponsoredWallet2({
1102
- provider: state.provider,
1103
- ownerAddress: state.walletAddress,
1104
- // Apps rarely set this; without the default, sponsorship silently never runs in production.
1105
- routingApiBaseUrl: this.config.routingApiBaseUrl ?? ROUTING_API_BASE_URL4,
1106
- apiKey: this.config.apiKey,
1107
- rpcUrl: this.config.rpcUrl
1108
- });
1109
- }
1110
- /** Null means nothing happened on-chain, so the caller is free to retry as user-pays. */
1111
- async trySponsoredDeposit(state, amount) {
1112
- const wallet = await this.sponsoredWallet(state).catch(() => null);
1113
- if (!wallet) return null;
1114
- const { depositSponsored: depositSponsored2, isSafeToRetry: isSafeToRetry2 } = await Promise.resolve().then(() => (init_surfliquid_sponsorship(), surfliquid_sponsorship_exports));
1115
- const { createSponsoredChain: createSponsoredChain2 } = await Promise.resolve().then(() => (init_surfliquid_smart_account(), surfliquid_smart_account_exports));
1116
- try {
1117
- const { txHash, vault } = await depositSponsored2({
1118
- amount,
1119
- api: await this.vaultApi(),
1120
- chain: createSponsoredChain2(this.config.rpcUrl),
1121
- wallet
1122
- });
1123
- return { txHash, smartWallet: vault };
1124
- } catch (error) {
1125
- if (!isSafeToRetry2(error)) throw error;
1126
- console.warn(
1127
- "[owney-sdk] SurfLiquid sponsored deposit unavailable; falling back to user-pays:",
1128
- error instanceof Error ? error.message : String(error)
1129
- );
1130
- return null;
1131
- }
1132
- }
1133
- async trySponsoredWithdraw(state, amount) {
1134
- const wallet = await this.sponsoredWallet(state).catch(() => null);
1135
- if (!wallet) return null;
1136
- const { withdrawSponsored: withdrawSponsored2, isSafeToRetry: isSafeToRetry2 } = await Promise.resolve().then(() => (init_surfliquid_sponsorship(), surfliquid_sponsorship_exports));
1137
- const { createSponsoredChain: createSponsoredChain2 } = await Promise.resolve().then(() => (init_surfliquid_smart_account(), surfliquid_smart_account_exports));
1138
- try {
1139
- const result = await withdrawSponsored2({
1140
- amount: amount != null ? BigInt(amount) : void 0,
1141
- api: await this.vaultApi(),
1142
- chain: createSponsoredChain2(this.config.rpcUrl),
1143
- wallet
1144
- });
1145
- return {
1146
- txHash: result.txHash,
1147
- type: amount != null ? "partial" : "full",
1148
- amount: result.amount
1149
- };
1150
- } catch (error) {
1151
- if (!isSafeToRetry2(error)) throw error;
1152
- console.warn(
1153
- "[owney-sdk] SurfLiquid sponsored withdraw unavailable; falling back to user-pays:",
1154
- error instanceof Error ? error.message : String(error)
1155
- );
1156
- return null;
1157
- }
1158
- }
1159
- // --- IAgent: funds (gasless when sponsorship is reachable, else user-pays) ---
1160
- async deposit(state, _chainId, amount, _asset, _depositCallback) {
1161
- const surf = await this.connect(state);
1162
- const sponsored = await this.trySponsoredDeposit(state, BigInt(amount));
1163
- if (sponsored) return { ...sponsored, amount };
1164
- const human = (0, import_viem9.formatUnits)(BigInt(amount), SURFLIQUID_USDC_DECIMALS);
1165
- const smartWallet = await this.resolveVaultAddress(
1166
- surf,
1167
- state.walletAddress
1168
- );
1169
- await this.ensureVaultAllowance(state, smartWallet, BigInt(amount));
1170
- const tx = await surf.deposit({
1171
- asset: SURFLIQUID_USDC_ADDRESS,
1172
- amount: human
1173
- });
1174
- await tx.wait();
1175
- return { txHash: tx.hash, smartWallet, amount };
1176
- }
1177
- async withdraw(state, _chainId, _token, amount) {
1178
- const surf = await this.connect(state);
1179
- const sponsored = await this.trySponsoredWithdraw(state, amount);
1180
- if (sponsored) return sponsored;
1181
- const human = amount != null ? (0, import_viem9.formatUnits)(BigInt(amount), SURFLIQUID_USDC_DECIMALS) : void 0;
1182
- try {
1183
- const tx = await surf.withdraw({
1184
- asset: SURFLIQUID_USDC_ADDRESS,
1185
- amount: human
1186
- });
1187
- await tx.wait();
1188
- return {
1189
- txHash: tx.hash,
1190
- type: amount != null ? "partial" : "full",
1191
- amount: amount ?? "0"
1192
- };
1193
- } catch (error) {
1194
- throw new OwneyError(
1195
- "WITHDRAW_FAILED",
1196
- error instanceof Error ? error.message : "SurfLiquid withdraw failed.",
1197
- { chainId: SURFLIQUID_CHAIN_ID, amount },
1198
- this.id
1199
- );
1200
- }
1201
- }
1202
- // --- IAgent: portfolio reads ---
1203
- async getBalances(state, chainId) {
1204
- const surf = await this.connect(state);
1205
- const vault = await surf.getVault(state.walletAddress);
1206
- const morphoVaultAddresses = (vault.assets ?? []).filter((asset) => asset.assetSymbol === "USDC" && asset.chainId === chainId).map((asset) => asset.morphoVaultAddress).filter((address) => Boolean(address));
1207
- const morphoStats = await fetchMorphoStatsByVault(
1208
- morphoVaultAddresses,
1209
- chainId
1210
- );
1211
- return mapBalances2(vault, chainId, morphoStats);
1212
- }
1213
- async getEarnings(state) {
1214
- const surf = await this.connect(state);
1215
- const vault = await surf.getVault(state.walletAddress);
1216
- return mapEarnings2(vault, vault.userVaultAddress ?? state.walletAddress);
1217
- }
1218
- async getAccountApy(state, _chainId, days, _tokenSymbol) {
1219
- const surf = await this.connect(state);
1220
- const vault = await surf.getVault(state.walletAddress);
1221
- return mapAccountApy(vault, days);
1222
- }
1223
- async getHistory(state, chainId, options) {
1224
- const surf = await this.connect(state);
1225
- const page = options?.cursor ? Number(options.cursor) : 1;
1226
- const limit = options?.limit ?? 10;
1227
- const result = await surf.getAgentMessages(
1228
- state.walletAddress,
1229
- page,
1230
- limit,
1231
- options?.fromDate,
1232
- options?.toDate
160
+ run(agentId, key2, fetch2) {
161
+ const cooldown = this.cooldowns.get(agentId);
162
+ if (cooldown && cooldown.until > Date.now()) {
163
+ return Promise.reject(this.limited(agentId, cooldown.until));
164
+ }
165
+ const requestKey = JSON.stringify([agentId, key2]);
166
+ const existing = this.inFlight.get(requestKey);
167
+ if (existing) return existing;
168
+ const promise = Promise.resolve().then(fetch2).then(
169
+ (value) => {
170
+ if (this.cooldowns.get(agentId) === cooldown)
171
+ this.cooldowns.delete(agentId);
172
+ return value;
173
+ },
174
+ (error) => {
175
+ const requestedDelay = rateLimitDelay(error);
176
+ if (requestedDelay === void 0) throw error;
177
+ const previous = this.cooldowns.get(agentId);
178
+ const failures = previous && previous.until > Date.now() ? previous.failures : Math.min((previous?.failures ?? 0) + 1, 5);
179
+ const delay = Math.max(
180
+ requestedDelay,
181
+ Math.min(3e4 * 2 ** (failures - 1), 3e5)
1233
182
  );
1234
- return mapHistory(result, chainId);
183
+ const until = Math.max(previous?.until ?? 0, Date.now() + delay);
184
+ this.cooldowns.set(agentId, { until, failures });
185
+ throw this.limited(agentId, until);
1235
186
  }
1236
- async getUserProfile(state) {
1237
- const surf = await this.connect(state);
1238
- const vault = await surf.getVault(state.walletAddress);
1239
- return mapUserProfile2(vault, state.walletAddress);
1240
- }
1241
- // --- IAgent: discovery (no wallet) ---
1242
- async getAgentApy(days, _options) {
1243
- const surf = this.ensureSurf();
1244
- const assets = await surf.getSupportedAssets(SURFLIQUID_CHAIN_ID);
1245
- const usdc = assets.find((asset) => asset.assetSymbol === "USDC");
1246
- if (!usdc) return { averageApy: 0 };
1247
- const windowed = usdc[APY_WINDOW_KEY2[days]];
1248
- return { averageApy: windowed != null ? windowed : usdc.currentAPY };
1249
- }
1250
- };
187
+ ).finally(() => {
188
+ if (this.inFlight.get(requestKey) === promise)
189
+ this.inFlight.delete(requestKey);
190
+ });
191
+ this.inFlight.set(requestKey, promise);
192
+ return promise;
1251
193
  }
1252
- });
1253
-
1254
- // src/index.ts
1255
- var index_exports = {};
1256
- __export(index_exports, {
1257
- AgentChainIncompatibleError: () => AgentChainIncompatibleError,
1258
- AgentNotFoundError: () => AgentNotFoundError,
1259
- InvalidHistoryCursorError: () => InvalidHistoryCursorError,
1260
- NotConnectedError: () => NotConnectedError,
1261
- OwneyError: () => OwneyError,
1262
- OwneySDK: () => OwneySDK,
1263
- createOwneySIWX: () => createOwneySIWX,
1264
- setOwneyDebug: () => setOwneyDebug
1265
- });
1266
- module.exports = __toCommonJS(index_exports);
194
+ };
1267
195
 
1268
196
  // src/agents/zyfai/zyfai.agent.ts
1269
197
  var import_sdk = require("@zyfai/sdk");
@@ -1317,11 +245,24 @@ var SupportedAssets = [
1317
245
  }
1318
246
  ];
1319
247
 
1320
- // src/agents/zyfai/zyfai.mapper.ts
1321
- init_debug();
248
+ // src/lib/debug.ts
249
+ var configuredDebug = false;
250
+ function setOwneyDebug(enabled) {
251
+ configuredDebug = enabled;
252
+ }
253
+ function isOwneyDebug() {
254
+ return globalThis.__OWNEY_DEBUG__ === true || configuredDebug;
255
+ }
256
+ function debugLog(scope, message, data) {
257
+ if (!isOwneyDebug()) return;
258
+ if (data === void 0) {
259
+ console.log(`[${scope}] ${message}`);
260
+ } else {
261
+ console.log(`[${scope}] ${message}`, data);
262
+ }
263
+ }
1322
264
 
1323
265
  // src/lib/utils.ts
1324
- init_errors();
1325
266
  var isValidChainId = (chainId) => {
1326
267
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
1327
268
  throw new OwneyError(
@@ -1332,12 +273,6 @@ var isValidChainId = (chainId) => {
1332
273
  }
1333
274
  return chainId;
1334
275
  };
1335
- function isSameAsset(tokenSymbol, asset) {
1336
- const token = tokenSymbol.toLowerCase();
1337
- const target = asset.toLowerCase();
1338
- if (token === target) return true;
1339
- return target === "weth" && token === "eth" || target === "eth" && token === "weth";
1340
- }
1341
276
  function hexToDecimal(hex, decimals = 6) {
1342
277
  const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
1343
278
  const parsed = BigInt(normalized);
@@ -1800,9 +735,6 @@ function decodeHistoryCursor(token) {
1800
735
  return parsed;
1801
736
  }
1802
737
 
1803
- // src/agents/zyfai/zyfai.agent.ts
1804
- init_errors();
1805
-
1806
738
  // src/agents/zyfai/zyfai.auth-cache.ts
1807
739
  var KEY_PREFIX = "owney.zyfai.session";
1808
740
  var storage = () => {
@@ -2065,7 +997,6 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
2065
997
  }
2066
998
 
2067
999
  // src/agents/zyfai/zyfai.agent.ts
2068
- init_debug();
2069
1000
  var ERC7579_IS_MODULE_INSTALLED_ABI = (0, import_viem.parseAbi)([
2070
1001
  "function isModuleInstalled(uint256 moduleTypeId, address module, bytes additionalContext) view returns (bool)"
2071
1002
  ]);
@@ -2134,7 +1065,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
2134
1065
  // successful decode is cached forever; failures are NOT cached so a transient
2135
1066
  // RPC error retries on the next fetch.
2136
1067
  withdrawAmountCache = /* @__PURE__ */ new Map();
2137
- earningsRefreshInFlight = null;
1068
+ earningsReads = /* @__PURE__ */ new Map();
1069
+ earningsRefreshes = /* @__PURE__ */ new Map();
1070
+ earningsSnapshot = null;
1071
+ earningsGeneration = 0;
2138
1072
  constructor(apiKey, rpcUrls, referralSource) {
2139
1073
  this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
2140
1074
  this.sdk = new import_sdk.ZyfaiSDK({
@@ -2379,6 +1313,10 @@ var ZyfaiAgent = class _ZyfaiAgent {
2379
1313
  }
2380
1314
  // --- IAgent: Connection lifecycle ---
2381
1315
  async disconnect() {
1316
+ this.earningsGeneration++;
1317
+ this.earningsReads.clear();
1318
+ this.earningsRefreshes.clear();
1319
+ this.earningsSnapshot = null;
2382
1320
  if (this.connectedAddress && this.connectedChainId !== null) {
2383
1321
  clearSession(this.connectedAddress, this.connectedChainId);
2384
1322
  }
@@ -2571,39 +1509,8 @@ var ZyfaiAgent = class _ZyfaiAgent {
2571
1509
  } catch (error) {
2572
1510
  console.warn(
2573
1511
  "[zyfai] applyPoolPolicy failed (non-fatal):",
2574
- error instanceof Error ? error.message : String(error)
2575
- );
2576
- }
2577
- }
2578
- /**
2579
- * Records the deposit with Zyfai, retrying transient failures.
2580
- *
2581
- * This runs AFTER the transfer has already landed on-chain, so it must never
2582
- * fail the deposit — the funds moved. But it is also the ONLY source of the
2583
- * "Top up wallet" entry the history is built from: Zyfai auto-deploys the
2584
- * balance it detects either way, so when this call is lost the user's deposit
2585
- * never appears in Activity (an earlier withdrawal stays the newest row) and
2586
- * nothing ever backfills it. Retry, then log loudly enough to be recoverable.
2587
- */
2588
- async logDepositWithRetry(chainId, txHash, amount, tokenAddress) {
2589
- const ATTEMPTS = 3;
2590
- const RETRY_DELAY_MS = 1e3;
2591
- for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
2592
- try {
2593
- await (tokenAddress ? this.sdk.logDeposit(chainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(chainId, txHash, amount));
2594
- return;
2595
- } catch (logError) {
2596
- if (attempt === ATTEMPTS) {
2597
- console.error(
2598
- "[owney-sdk] Deposit landed on-chain but logDeposit failed \u2014 it will be missing from Zyfai history:",
2599
- { txHash, chainId, amount, tokenAddress, error: logError }
2600
- );
2601
- return;
2602
- }
2603
- await new Promise(
2604
- (resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt)
2605
- );
2606
- }
1512
+ error instanceof Error ? error.message : String(error)
1513
+ );
2607
1514
  }
2608
1515
  }
2609
1516
  /**
@@ -2909,12 +1816,14 @@ var ZyfaiAgent = class _ZyfaiAgent {
2909
1816
  );
2910
1817
  const txHash = await depositCallback(smartWallet, validChainId, amount);
2911
1818
  const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
2912
- await this.logDepositWithRetry(
2913
- validChainId,
2914
- txHash,
2915
- amount,
2916
- tokenAddress
2917
- );
1819
+ try {
1820
+ await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1821
+ } catch (logError) {
1822
+ console.warn(
1823
+ "[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
1824
+ logError
1825
+ );
1826
+ }
2918
1827
  return { txHash, smartWallet, amount };
2919
1828
  }
2920
1829
  await this.ensureWalletDeployed(this.getAddress(), validChainId);
@@ -2956,26 +1865,59 @@ var ZyfaiAgent = class _ZyfaiAgent {
2956
1865
  const raw = await this.sdk.getPortfolio(this.getAddress());
2957
1866
  return mapBalances(raw, validChainId, smartWallet);
2958
1867
  }
1868
+ earningsKey(state, chainId, smartWallet) {
1869
+ return JSON.stringify([
1870
+ state.walletAddress?.toLowerCase(),
1871
+ chainId,
1872
+ smartWallet.toLowerCase()
1873
+ ]);
1874
+ }
1875
+ readEarnings(key2, smartWallet) {
1876
+ const existing = this.earningsReads.get(key2);
1877
+ if (existing) return existing;
1878
+ const generation = this.earningsGeneration;
1879
+ const pending = Promise.resolve().then(() => this.sdk.getOnchainEarnings(smartWallet)).then((raw) => {
1880
+ if (generation === this.earningsGeneration) {
1881
+ this.earningsSnapshot = { key: key2, raw, at: Date.now() };
1882
+ }
1883
+ return raw;
1884
+ }).finally(() => {
1885
+ if (this.earningsReads.get(key2) === pending)
1886
+ this.earningsReads.delete(key2);
1887
+ });
1888
+ this.earningsReads.set(key2, pending);
1889
+ return pending;
1890
+ }
2959
1891
  async getEarnings(state, chainId) {
2960
1892
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
2961
- const raw = await this.sdk.getOnchainEarnings(smartWallet);
1893
+ const raw = await this.readEarnings(
1894
+ this.earningsKey(state, chainId, smartWallet),
1895
+ smartWallet
1896
+ );
2962
1897
  return mapEarnings(raw, smartWallet);
2963
1898
  }
2964
1899
  async refreshEarnings(state, chainId) {
2965
- if (this.earningsRefreshInFlight) return this.earningsRefreshInFlight;
2966
- this.earningsRefreshInFlight = (async () => {
2967
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
2968
- const current = await this.sdk.getOnchainEarnings(smartWallet);
1900
+ const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1901
+ const key2 = this.earningsKey(state, chainId, smartWallet);
1902
+ const existing = this.earningsRefreshes.get(key2);
1903
+ if (existing) return existing;
1904
+ const generation = this.earningsGeneration;
1905
+ const pending = (async () => {
1906
+ const recent = this.earningsSnapshot;
1907
+ const current = recent?.key === key2 && Date.now() - recent.at < 5e3 ? recent.raw : await this.readEarnings(key2, smartWallet);
2969
1908
  const lastCheck = current.data.lastCheckTimestamp ? Date.parse(current.data.lastCheckTimestamp) : Number.NaN;
2970
1909
  const isFresh = Number.isFinite(lastCheck) && Date.now() - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
2971
1910
  const earnings = isFresh ? current : await this.sdk.calculateOnchainEarnings(smartWallet);
1911
+ if (!isFresh && generation === this.earningsGeneration) {
1912
+ this.earningsSnapshot = { key: key2, raw: earnings, at: Date.now() };
1913
+ }
2972
1914
  return mapEarnings(earnings, smartWallet);
2973
- })();
2974
- try {
2975
- return await this.earningsRefreshInFlight;
2976
- } finally {
2977
- this.earningsRefreshInFlight = null;
2978
- }
1915
+ })().finally(() => {
1916
+ if (this.earningsRefreshes.get(key2) === pending)
1917
+ this.earningsRefreshes.delete(key2);
1918
+ });
1919
+ this.earningsRefreshes.set(key2, pending);
1920
+ return pending;
2979
1921
  }
2980
1922
  async getAccountApy(state, chainId, days, tokenSymbol) {
2981
1923
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
@@ -3095,13 +2037,71 @@ var ZyfaiAgent = class _ZyfaiAgent {
3095
2037
  }
3096
2038
  };
3097
2039
 
3098
- // src/client.ts
3099
- init_errors();
3100
- init_debug();
3101
- init_routing_api();
2040
+ // src/lib/routing-api.ts
2041
+ var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
2042
+ async function fetchOrgAgentConfig(apiKey, baseUrl = ROUTING_API_BASE_URL) {
2043
+ const url = `${baseUrl}/api/v1/agent/org-config`;
2044
+ try {
2045
+ const res = await fetch(url, {
2046
+ method: "GET",
2047
+ headers: {
2048
+ "Content-Type": "application/json",
2049
+ "x-owney-api-key": `${apiKey}`
2050
+ }
2051
+ });
2052
+ if (!res.ok) {
2053
+ if (res.status !== 404) {
2054
+ console.warn(
2055
+ `[owney-sdk] Could not read org agent config (${res.status}); leaving user profiles unchanged.`
2056
+ );
2057
+ }
2058
+ return null;
2059
+ }
2060
+ const json = await res.json();
2061
+ const policy = json.success ? json.data ?? null : null;
2062
+ debugLog(
2063
+ "owney-sdk",
2064
+ policy ? "org agent config: loaded" : "org agent config: none set by this partner \u2014 user profiles will be left as they are",
2065
+ policy ?? void 0
2066
+ );
2067
+ return policy;
2068
+ } catch (error) {
2069
+ console.warn(
2070
+ "[owney-sdk] Could not read org agent config (non-fatal):",
2071
+ error instanceof Error ? error.message : String(error)
2072
+ );
2073
+ return null;
2074
+ }
2075
+ }
2076
+ async function fetchAgentKeys(apiKey, baseUrl = ROUTING_API_BASE_URL) {
2077
+ const url = `${baseUrl}/api/v1/agent/keys`;
2078
+ const res = await fetch(url, {
2079
+ method: "GET",
2080
+ headers: {
2081
+ "Content-Type": "application/json",
2082
+ "x-owney-api-key": `${apiKey}`
2083
+ }
2084
+ });
2085
+ if (!res.ok) {
2086
+ const text = await res.text().catch(() => "");
2087
+ throw new OwneyError(
2088
+ "API_ROUTING_ERROR",
2089
+ `Routing API error ${res.status}: ${text}`,
2090
+ { statusCode: res.status, responseBody: text }
2091
+ );
2092
+ }
2093
+ const json = await res.json();
2094
+ if (!json.success) {
2095
+ throw new OwneyError(
2096
+ "API_ROUTING_FAILED",
2097
+ `Routing API request failed: ${json.message}`,
2098
+ { message: json.message }
2099
+ );
2100
+ }
2101
+ return json.data;
2102
+ }
3102
2103
 
3103
2104
  // src/lib/health-report.ts
3104
- init_errors();
3105
2105
  var ROUTING_API_BASE_URL2 = "https://owney-routing-api-243946518160.europe-west4.run.app";
3106
2106
  async function reportAgentFailure(apiKey, agentType, errorCode, baseUrl = ROUTING_API_BASE_URL2) {
3107
2107
  try {
@@ -3137,10 +2137,11 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
3137
2137
  // src/lib/helpers/withdraw-helper.ts
3138
2138
  var import_viem2 = require("viem");
3139
2139
  function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
2140
+ const target = asset.toUpperCase();
3140
2141
  return agents.map((agent) => {
3141
2142
  const agentBalance = aggregated[agent.id];
3142
2143
  const tokenBalance = agentBalance?.tokens.find(
3143
- (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
2144
+ (t) => t.chainId === chainId && t.asset.toUpperCase() === target
3144
2145
  );
3145
2146
  if (!tokenBalance) return { agent, balance: 0n };
3146
2147
  return { agent, balance: (0, import_viem2.parseUnits)(tokenBalance.amount, decimals) };
@@ -3250,21 +2251,52 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
3250
2251
  }
3251
2252
 
3252
2253
  // src/client.ts
3253
- var import_viem10 = require("viem");
3254
- var import_chains4 = require("viem/chains");
2254
+ var import_viem6 = require("viem");
2255
+ var import_chains2 = require("viem/chains");
3255
2256
 
3256
- // src/lib/sponsored-deposit.ts
3257
- init_errors();
3258
- init_transfer_auth();
2257
+ // src/lib/transfer-auth.ts
2258
+ var import_viem3 = require("viem");
2259
+ var ERC20_META_ABI = [
2260
+ { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
2261
+ { type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
2262
+ ];
2263
+ function buildTransferWithAuthorizationTypedData(input) {
2264
+ return {
2265
+ domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
2266
+ types: {
2267
+ TransferWithAuthorization: [
2268
+ { name: "from", type: "address" },
2269
+ { name: "to", type: "address" },
2270
+ { name: "value", type: "uint256" },
2271
+ { name: "validAfter", type: "uint256" },
2272
+ { name: "validBefore", type: "uint256" },
2273
+ { name: "nonce", type: "bytes32" }
2274
+ ]
2275
+ },
2276
+ primaryType: "TransferWithAuthorization",
2277
+ message: input.message
2278
+ };
2279
+ }
2280
+ async function readTokenMeta(publicClient, token) {
2281
+ const [tokenName, tokenVersion] = await Promise.all([
2282
+ publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
2283
+ publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
2284
+ ]);
2285
+ return { tokenName, tokenVersion };
2286
+ }
2287
+ function randomAuthNonce() {
2288
+ const bytes = new Uint8Array(32);
2289
+ globalThis.crypto.getRandomValues(bytes);
2290
+ return (0, import_viem3.bytesToHex)(bytes);
2291
+ }
3259
2292
 
3260
2293
  // src/lib/sponsor-client.ts
3261
- init_errors();
3262
2294
  var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
3263
2295
  async function postSponsorTransferAuth(input) {
3264
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2296
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
3265
2297
  let res;
3266
2298
  try {
3267
- res = await fetch(`${base5}/api/v1/sponsor/erc20-transfer-auth`, {
2299
+ res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
3268
2300
  method: "POST",
3269
2301
  headers: {
3270
2302
  "content-type": "application/json",
@@ -3301,10 +2333,10 @@ async function postSponsorTransferAuth(input) {
3301
2333
  return parsed.data;
3302
2334
  }
3303
2335
  async function postSponsorPermit2Transfer(input) {
3304
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2336
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
3305
2337
  let res;
3306
2338
  try {
3307
- res = await fetch(`${base5}/api/v1/sponsor/permit2-transfer`, {
2339
+ res = await fetch(`${base3}/api/v1/sponsor/permit2-transfer`, {
3308
2340
  method: "POST",
3309
2341
  headers: {
3310
2342
  "content-type": "application/json",
@@ -3339,11 +2371,11 @@ async function postSponsorPermit2Transfer(input) {
3339
2371
  return parsed.data;
3340
2372
  }
3341
2373
  async function getSponsorRelayerAddress(input) {
3342
- const base5 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2374
+ const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
3343
2375
  let res;
3344
2376
  try {
3345
2377
  res = await fetch(
3346
- `${base5}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
2378
+ `${base3}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
3347
2379
  {
3348
2380
  headers: { "x-owney-api-key": input.apiKey }
3349
2381
  }
@@ -3375,11 +2407,85 @@ async function getSponsorRelayerAddress(input) {
3375
2407
  return parsed.data.relayer;
3376
2408
  }
3377
2409
 
3378
- // src/lib/sponsored-deposit.ts
3379
- init_permit2();
2410
+ // src/lib/permit2.ts
2411
+ var import_viem4 = require("viem");
2412
+ var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
2413
+ var MAX_UINT256 = 2n ** 256n - 1n;
2414
+ var ERC20_ALLOWANCE_ABI = [
2415
+ {
2416
+ type: "function",
2417
+ name: "allowance",
2418
+ stateMutability: "view",
2419
+ inputs: [
2420
+ { name: "owner", type: "address" },
2421
+ { name: "spender", type: "address" }
2422
+ ],
2423
+ outputs: [{ name: "", type: "uint256" }]
2424
+ },
2425
+ {
2426
+ type: "function",
2427
+ name: "approve",
2428
+ stateMutability: "nonpayable",
2429
+ inputs: [
2430
+ { name: "spender", type: "address" },
2431
+ { name: "amount", type: "uint256" }
2432
+ ],
2433
+ outputs: [{ name: "", type: "bool" }]
2434
+ },
2435
+ {
2436
+ type: "function",
2437
+ name: "balanceOf",
2438
+ stateMutability: "view",
2439
+ inputs: [{ name: "account", type: "address" }],
2440
+ outputs: [{ name: "", type: "uint256" }]
2441
+ }
2442
+ ];
2443
+ function buildPermitTransferFromTypedData(input) {
2444
+ return {
2445
+ domain: {
2446
+ name: "Permit2",
2447
+ chainId: input.chainId,
2448
+ verifyingContract: PERMIT2_ADDRESS
2449
+ },
2450
+ types: {
2451
+ PermitTransferFrom: [
2452
+ { name: "permitted", type: "TokenPermissions" },
2453
+ { name: "spender", type: "address" },
2454
+ { name: "nonce", type: "uint256" },
2455
+ { name: "deadline", type: "uint256" }
2456
+ ],
2457
+ TokenPermissions: [
2458
+ { name: "token", type: "address" },
2459
+ { name: "amount", type: "uint256" }
2460
+ ]
2461
+ },
2462
+ primaryType: "PermitTransferFrom",
2463
+ message: input.message
2464
+ };
2465
+ }
2466
+ function randomPermit2Nonce() {
2467
+ const bytes = new Uint8Array(32);
2468
+ globalThis.crypto.getRandomValues(bytes);
2469
+ return BigInt((0, import_viem4.bytesToHex)(bytes));
2470
+ }
2471
+ async function readPermit2Allowance(publicClient, token, owner) {
2472
+ return publicClient.readContract({
2473
+ address: token,
2474
+ abi: ERC20_ALLOWANCE_ABI,
2475
+ functionName: "allowance",
2476
+ args: [owner, PERMIT2_ADDRESS]
2477
+ });
2478
+ }
2479
+ async function readErc20Balance(publicClient, token, owner) {
2480
+ return publicClient.readContract({
2481
+ address: token,
2482
+ abi: ERC20_ALLOWANCE_ABI,
2483
+ functionName: "balanceOf",
2484
+ args: [owner]
2485
+ });
2486
+ }
3380
2487
 
3381
2488
  // src/lib/chain-guard.ts
3382
- init_errors();
3383
2489
  var CHAIN_NAMES = {
3384
2490
  1: "Ethereum",
3385
2491
  8453: "Base",
@@ -3493,8 +2599,6 @@ function makeSponsoredDepositCallback(deps) {
3493
2599
  }
3494
2600
 
3495
2601
  // src/lib/sponsored-weth-deposit.ts
3496
- init_errors();
3497
- init_permit2();
3498
2602
  var PERMIT_WINDOW_SECONDS = 15 * 60;
3499
2603
  function makeSponsoredWethCallback(deps) {
3500
2604
  const get = deps.httpGet ?? getSponsorRelayerAddress;
@@ -3579,7 +2683,6 @@ function makeSponsoredWethCallback(deps) {
3579
2683
 
3580
2684
  // src/lib/sponsored-calls-deposit.ts
3581
2685
  var import_viem5 = require("viem");
3582
- init_errors();
3583
2686
  var DEFAULT_POLL_INTERVAL_MS = 1500;
3584
2687
  var DEFAULT_MAX_POLLS = 30;
3585
2688
  async function paymasterSupported(provider, owner, chainId) {
@@ -3670,7 +2773,6 @@ function makeSponsoredCallsCallback(deps) {
3670
2773
  }
3671
2774
 
3672
2775
  // src/client.ts
3673
- init_permit2();
3674
2776
  function encodeMultiAgentCursor(map) {
3675
2777
  return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
3676
2778
  }
@@ -3697,11 +2799,10 @@ var SPONSORED_USDC_BY_CHAIN = {
3697
2799
  1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
3698
2800
  };
3699
2801
  var VIEM_CHAIN2 = {
3700
- 8453: import_chains4.base,
3701
- 42161: import_chains4.arbitrum,
3702
- 1: import_chains4.mainnet
2802
+ 8453: import_chains2.base,
2803
+ 42161: import_chains2.arbitrum,
2804
+ 1: import_chains2.mainnet
3703
2805
  };
3704
- var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai"];
3705
2806
  var SPONSORED_WETH_BY_CHAIN = {
3706
2807
  8453: "0x4200000000000000000000000000000000000006",
3707
2808
  42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -3730,11 +2831,21 @@ var OwneySDK = class {
3730
2831
  zyfaiRpcUrls;
3731
2832
  routingApiBaseUrl;
3732
2833
  referralSource;
3733
- surfliquidApiBaseUrl;
3734
2834
  cachedSponsoredCallback = null;
3735
2835
  cachedWethSponsoredCallback = null;
3736
2836
  paymasterServiceUrl;
3737
2837
  cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
2838
+ agentReads = new AgentReads();
2839
+ activationChecks = /* @__PURE__ */ new Map();
2840
+ readAgent(agent, method, fetch2, params = null) {
2841
+ const key2 = JSON.stringify([
2842
+ this.state?.walletAddress.toLowerCase() ?? null,
2843
+ this.state?.chainId ?? null,
2844
+ method,
2845
+ params
2846
+ ]);
2847
+ return this.agentReads.run(agent.id, key2, fetch2);
2848
+ }
3738
2849
  initializingAgentsPromise = null;
3739
2850
  constructor(config) {
3740
2851
  this.apiKey = config.apiKey;
@@ -3743,7 +2854,6 @@ var OwneySDK = class {
3743
2854
  this.routingApiBaseUrl = config.routingApiBaseUrl;
3744
2855
  this.paymasterServiceUrl = config.paymasterServiceUrl;
3745
2856
  this.referralSource = config.referralSource;
3746
- this.surfliquidApiBaseUrl = config.surfliquidApiBaseUrl;
3747
2857
  }
3748
2858
  /**
3749
2859
  * Establish connection state for all subsequent SDK calls.
@@ -3762,6 +2872,8 @@ var OwneySDK = class {
3762
2872
  "No accounts found. Ensure the wallet is unlocked and connected."
3763
2873
  );
3764
2874
  }
2875
+ this.agentReads.clearInFlight();
2876
+ this.activationChecks.clear();
3765
2877
  this.state = { provider, walletAddress, chainId: null };
3766
2878
  this.cachedSponsoredCallback = null;
3767
2879
  this.cachedWethSponsoredCallback = null;
@@ -3777,6 +2889,8 @@ var OwneySDK = class {
3777
2889
  }
3778
2890
  this.activeAgents.clear();
3779
2891
  this.disabledAgents.clear();
2892
+ this.agentReads.clearInFlight();
2893
+ this.activationChecks.clear();
3780
2894
  this.state = null;
3781
2895
  this.cachedSponsoredCallback = null;
3782
2896
  this.cachedWethSponsoredCallback = null;
@@ -3843,14 +2957,14 @@ var OwneySDK = class {
3843
2957
  // Casts work around viem's chain-narrowed Client vs the generic
3844
2958
  // PublicClient/WalletClient param types — structurally identical at
3845
2959
  // runtime, but the two share a name TS treats as unrelated.
3846
- getPublicClient: (cid) => (0, import_viem10.createPublicClient)({
2960
+ getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
3847
2961
  chain: VIEM_CHAIN2[cid],
3848
- transport: (0, import_viem10.custom)(provider)
2962
+ transport: (0, import_viem6.custom)(provider)
3849
2963
  }),
3850
- getWalletClient: (cid) => (0, import_viem10.createWalletClient)({
2964
+ getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
3851
2965
  account: owner,
3852
2966
  chain: VIEM_CHAIN2[cid],
3853
- transport: (0, import_viem10.custom)(provider)
2967
+ transport: (0, import_viem6.custom)(provider)
3854
2968
  })
3855
2969
  });
3856
2970
  if (!onApproved) this.cachedSponsoredCallback = callback;
@@ -3896,14 +3010,14 @@ var OwneySDK = class {
3896
3010
  // Casts work around viem's chain-narrowed Client vs the generic
3897
3011
  // PublicClient/WalletClient param types — structurally identical at
3898
3012
  // runtime, but the two share a name TS treats as unrelated.
3899
- getPublicClient: (cid) => (0, import_viem10.createPublicClient)({
3013
+ getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
3900
3014
  chain: VIEM_CHAIN2[cid],
3901
- transport: (0, import_viem10.custom)(provider)
3015
+ transport: (0, import_viem6.custom)(provider)
3902
3016
  }),
3903
- getWalletClient: (cid) => (0, import_viem10.createWalletClient)({
3017
+ getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
3904
3018
  account: owner,
3905
3019
  chain: VIEM_CHAIN2[cid],
3906
- transport: (0, import_viem10.custom)(provider)
3020
+ transport: (0, import_viem6.custom)(provider)
3907
3021
  })
3908
3022
  });
3909
3023
  if (!onApproved) this.cachedWethSponsoredCallback = callback;
@@ -3979,8 +3093,8 @@ var OwneySDK = class {
3979
3093
  this.routingApiBaseUrl
3980
3094
  );
3981
3095
  this.disabledAgents.clear();
3982
- for (const { key: key2, agent_type, project_name, is_enabled } of agentKeys) {
3983
- const agent = await this.createAgent(agent_type, key2, project_name);
3096
+ for (const { key: key2, agent_type, is_enabled } of agentKeys) {
3097
+ const agent = this.createAgent(agent_type, key2);
3984
3098
  if (!agent) continue;
3985
3099
  this.agents.set(agent_type, agent);
3986
3100
  if (is_enabled === false) {
@@ -4001,25 +3115,42 @@ var OwneySDK = class {
4001
3115
  this.initializingAgentsPromise = null;
4002
3116
  }
4003
3117
  }
4004
- async createAgent(agentId, key2, projectName) {
3118
+ createAgent(agentId, key2) {
4005
3119
  if (agentId === "zyfai") {
4006
3120
  return new ZyfaiAgent(key2, this.zyfaiRpcUrls, this.referralSource);
4007
3121
  }
4008
- if (agentId === "surfliquid") {
4009
- if (!projectName) return null;
4010
- const { SurfLiquidAgent: SurfLiquidAgent2 } = await Promise.resolve().then(() => (init_surfliquid_agent(), surfliquid_agent_exports));
4011
- return new SurfLiquidAgent2({
4012
- projectName,
4013
- appId: key2,
4014
- // Same-origin proxy override — SurfLiquid auth is an httpOnly cookie,
4015
- // which WebKit (iOS) discards when it is third-party. See
4016
- // OwneySDKConfig.surfliquidApiBaseUrl.
4017
- apiBaseUrl: this.surfliquidApiBaseUrl,
4018
- apiKey: this.apiKey,
4019
- routingApiBaseUrl: this.routingApiBaseUrl
3122
+ return null;
3123
+ }
3124
+ /**
3125
+ * Discover the agents actually returned by routing for this organization.
3126
+ * Consumers should use this instead of hardcoding a global agent roster.
3127
+ */
3128
+ async getAvailableAgents(options = {}) {
3129
+ await this.ensureAgentsInitialized();
3130
+ const { chainId, asset, includeDisabled = false } = options;
3131
+ const available = [];
3132
+ for (const [id, agent] of this.agents) {
3133
+ const isEnabled = !this.isAgentDisabled(id);
3134
+ if (!includeDisabled && !isEnabled) continue;
3135
+ if (chainId !== void 0 && !agent.supportedChainIds.includes(chainId)) {
3136
+ continue;
3137
+ }
3138
+ if (asset !== void 0) {
3139
+ const supportsAsset = agent.supportedAssets.some(
3140
+ (entry) => (chainId === void 0 || entry.chainId === chainId) && entry.assets.some((candidate) => candidate.symbol === asset)
3141
+ );
3142
+ if (!supportsAsset) {
3143
+ continue;
3144
+ }
3145
+ }
3146
+ available.push({
3147
+ id,
3148
+ isEnabled,
3149
+ supportedChainIds: agent.supportedChainIds,
3150
+ supportedAssets: agent.supportedAssets
4020
3151
  });
4021
3152
  }
4022
- return null;
3153
+ return available;
4023
3154
  }
4024
3155
  // --- Account lifecycle ---
4025
3156
  /**
@@ -4068,9 +3199,7 @@ var OwneySDK = class {
4068
3199
  this.activeAgents.add(id);
4069
3200
  }
4070
3201
  state.chainId = chainId;
4071
- this.activateAgentsInTurn(agents, state, chainId).catch((error) => {
4072
- console.error("activateAgent background init failed:", error);
4073
- });
3202
+ await this.activateAgentsInTurn(agents, state, chainId);
4074
3203
  return;
4075
3204
  }
4076
3205
  const compatible = [...this.agents.values()].filter(
@@ -4091,11 +3220,7 @@ var OwneySDK = class {
4091
3220
  const enabledCompatible = compatible.filter(
4092
3221
  (agent) => !this.isAgentDisabled(agent.id)
4093
3222
  );
4094
- this.activateAgentsInTurn(enabledCompatible, state, chainId).catch(
4095
- (error) => {
4096
- console.error("activateAgent background init failed:", error);
4097
- }
4098
- );
3223
+ await this.activateAgentsInTurn(enabledCompatible, state, chainId);
4099
3224
  }
4100
3225
  /**
4101
3226
  * Activate agents ONE AT A TIME, each followed by its org policy.
@@ -4132,7 +3257,7 @@ var OwneySDK = class {
4132
3257
  if (firstError !== null) throw firstError;
4133
3258
  }
4134
3259
  /**
4135
- * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
3260
+ * Deposit into a specific agent, or distribute across all eligible agents.
4136
3261
  * Validates that the asset is supported and amount meets minimums for the target agent(s).
4137
3262
  * @param options - Deposit parameters
4138
3263
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
@@ -4140,7 +3265,8 @@ var OwneySDK = class {
4140
3265
  * @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
4141
3266
  * When agentId is omitted, this callback is invoked once per eligible agent with that agent's
4142
3267
  * split amount and smart wallet address — expect multiple wallet prompts.
4143
- * @param options.agentId - Optional. Target agent. Omit to split equally across all agents.
3268
+ * @param options.agentId - Optional explicit target. Otherwise split equally,
3269
+ * or fund remaining agents when a recovery deposit cannot meet every minimum.
4144
3270
  * @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
4145
3271
  */
4146
3272
  async deposit(options) {
@@ -4178,7 +3304,7 @@ var OwneySDK = class {
4178
3304
  });
4179
3305
  const exemptFlags = await Promise.all(
4180
3306
  eligibleAgents.map(
4181
- (a) => this.hasExistingBalance(a, state, chainId, asset)
3307
+ (a) => this.hasExistingBalance(a, state, chainId, asset, true)
4182
3308
  )
4183
3309
  );
4184
3310
  const exempt = new Set(
@@ -4192,15 +3318,42 @@ var OwneySDK = class {
4192
3318
  exempt
4193
3319
  );
4194
3320
  if (agentAmounts.length === 0) {
3321
+ const agentsRequiringActivation = eligibleAgents.filter(
3322
+ (agent) => !exempt.has(agent.id)
3323
+ );
3324
+ const perAgentMinimum = agentsRequiringActivation.reduce(
3325
+ (highest, agent) => {
3326
+ const minimum = this.getMinDepositAmount(agent, chainId, asset);
3327
+ return minimum > highest ? minimum : highest;
3328
+ },
3329
+ 0n
3330
+ );
3331
+ const minimumRequired = agentsRequiringActivation.length > 0 ? (perAgentMinimum > 0n ? perAgentMinimum : 1n) * BigInt(agentsRequiringActivation.length) : BigInt(eligibleAgents.length);
4195
3332
  throw new OwneyError(
4196
3333
  "DEPOSIT_AMOUNT_BELOW_MINIMUM",
4197
- `Amount "${amount}" cannot satisfy minimum deposit requirements for any eligible agent.`,
4198
- { amount }
3334
+ `Amount "${amount}" cannot activate every eligible agent. The combined minimum is "${minimumRequired.toString()}" for ${asset}.`,
3335
+ {
3336
+ amount,
3337
+ asset,
3338
+ chainId,
3339
+ minDepositAmount: minimumRequired.toString(),
3340
+ perAgentDepositAmount: perAgentMinimum.toString(),
3341
+ agentMinimums: agentsRequiringActivation.map((agent) => ({
3342
+ agentId: agent.id,
3343
+ minDepositAmount: this.getMinDepositAmount(
3344
+ agent,
3345
+ chainId,
3346
+ asset
3347
+ ).toString()
3348
+ }))
3349
+ }
4199
3350
  );
4200
3351
  }
4201
3352
  const agentResults = {};
4202
- const agentErrors = {};
4203
- for (const { agent, amount: agentAmount } of agentAmounts) {
3353
+ for (const [
3354
+ index,
3355
+ { agent, amount: agentAmount }
3356
+ ] of agentAmounts.entries()) {
4204
3357
  try {
4205
3358
  agentResults[agent.id] = await this.depositWithFallback(
4206
3359
  agent,
@@ -4212,17 +3365,22 @@ var OwneySDK = class {
4212
3365
  depositCallback
4213
3366
  );
4214
3367
  } catch (error) {
4215
- agentErrors[agent.id] = error instanceof Error ? error.message : String(error);
3368
+ if (Object.keys(agentResults).length === 0) throw error;
3369
+ throw new OwneyError(
3370
+ "DEPOSIT_PARTIAL_FAILURE",
3371
+ "Some deposits completed before another agent failed. Check activity and balances before depositing again; the failed transfer may still settle.",
3372
+ {
3373
+ agentResults,
3374
+ failedAgentId: agent.id,
3375
+ failedAmount: agentAmount,
3376
+ unattemptedAgentIds: agentAmounts.slice(index + 1).map(({ agent: agent2 }) => agent2.id),
3377
+ cause: error
3378
+ },
3379
+ agent.id
3380
+ );
4216
3381
  }
4217
3382
  }
4218
- if (Object.keys(agentResults).length === 0) {
4219
- throw new OwneyError(
4220
- "DEPOSIT_ALL_FAILED",
4221
- `All ${agentAmounts.length} agent deposit(s) failed.`,
4222
- { agentErrors }
4223
- );
4224
- }
4225
- return Object.keys(agentErrors).length > 0 ? { agentResults, agentErrors } : { agentResults };
3383
+ return { agentResults };
4226
3384
  }
4227
3385
  /**
4228
3386
  * Invokes `agent.deposit` with the resolved sponsored callback, composing
@@ -4293,6 +3451,17 @@ var OwneySDK = class {
4293
3451
  }
4294
3452
  splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
4295
3453
  if (agents.length === 0) return [];
3454
+ const agentsRequiringActivation = agents.filter(
3455
+ (agent) => !exempt.has(agent.id)
3456
+ );
3457
+ if (agentsRequiringActivation.length === agents.length) {
3458
+ const highestMinimum2 = agents.reduce((highest, agent) => {
3459
+ const minimum = this.getMinDepositAmount(agent, chainId, asset);
3460
+ return minimum > highest ? minimum : highest;
3461
+ }, 0n);
3462
+ const minimumRequired2 = (highestMinimum2 > 0n ? highestMinimum2 : 1n) * BigInt(agents.length);
3463
+ if (totalAmount < minimumRequired2) return [];
3464
+ }
4296
3465
  const perAgent = totalAmount / BigInt(agents.length);
4297
3466
  const remainder = totalAmount % BigInt(agents.length);
4298
3467
  const splits = agents.map((agent, i) => ({
@@ -4300,18 +3469,26 @@ var OwneySDK = class {
4300
3469
  amount: i === agents.length - 1 ? perAgent + remainder : perAgent
4301
3470
  }));
4302
3471
  const valid = splits.filter(
4303
- (s) => exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset)
3472
+ (s) => s.amount > 0n && (exempt.has(s.agent.id) || s.amount >= this.getMinDepositAmount(s.agent, chainId, asset))
4304
3473
  );
4305
3474
  if (valid.length === agents.length) {
4306
3475
  return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
4307
3476
  }
4308
- return this.splitDepositAmount(
4309
- totalAmount,
4310
- valid.map((s) => s.agent),
4311
- chainId,
4312
- asset,
4313
- exempt
4314
- );
3477
+ const targets = agentsRequiringActivation.length > 0 ? agentsRequiringActivation : agents;
3478
+ const highestMinimum = targets.reduce((highest, agent) => {
3479
+ const minimum = this.getMinDepositAmount(agent, chainId, asset);
3480
+ return minimum > highest ? minimum : highest;
3481
+ }, 0n);
3482
+ const minimumRequired = (highestMinimum > 0n ? highestMinimum : 1n) * BigInt(targets.length);
3483
+ if (totalAmount < minimumRequired) return [];
3484
+ const targetShare = totalAmount / BigInt(targets.length);
3485
+ const targetRemainder = totalAmount % BigInt(targets.length);
3486
+ return targets.map((agent, index) => ({
3487
+ agent,
3488
+ amount: String(
3489
+ targetShare + (index === targets.length - 1 ? targetRemainder : 0n)
3490
+ )
3491
+ }));
4315
3492
  }
4316
3493
  async validateMinDepositAmount(agent, state, chainId, asset, amount) {
4317
3494
  const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
@@ -4336,14 +3513,29 @@ var OwneySDK = class {
4336
3513
  * per-agent minimum. Fails closed: any error reading balances returns
4337
3514
  * false, so the minimum is enforced as today.
4338
3515
  */
4339
- async hasExistingBalance(agent, state, chainId, asset) {
3516
+ async hasExistingBalance(agent, state, chainId, asset, requireReliableRead = false) {
4340
3517
  try {
4341
3518
  const balance = await agent.getBalances(state, chainId);
3519
+ const target = asset.toLowerCase();
4342
3520
  const token = balance.tokens.find(
4343
- (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
3521
+ (t) => t.chainId === chainId && t.asset.toLowerCase() === target
4344
3522
  );
4345
- return !!token && Number(token.amount) > 0;
4346
- } catch {
3523
+ const targetChainName = agent.supportedAssets.find((entry) => entry.chainId === chainId)?.chain?.trim().toUpperCase();
3524
+ const position = (balance.positions ?? []).find((p) => {
3525
+ const positionChain = p.chain.trim().toUpperCase();
3526
+ const matchesChain = positionChain === String(chainId) || targetChainName !== void 0 && positionChain === targetChainName;
3527
+ return matchesChain && p.asset.toLowerCase() === target && Number(p.amount) > 0;
3528
+ });
3529
+ return !!token && Number(token.amount) > 0 || !!position;
3530
+ } catch (error) {
3531
+ if (requireReliableRead) {
3532
+ throw new OwneyError(
3533
+ "DEPOSIT_BALANCE_UNAVAILABLE",
3534
+ "Could not verify every agent balance. No deposit was submitted. Try again once balances are available.",
3535
+ { agentId: agent.id, chainId, asset, cause: error },
3536
+ agent.id
3537
+ );
3538
+ }
4347
3539
  return false;
4348
3540
  }
4349
3541
  }
@@ -4379,34 +3571,6 @@ var OwneySDK = class {
4379
3571
  }
4380
3572
  return eligible;
4381
3573
  }
4382
- /**
4383
- * Agent ids the routing API provisioned for this org that support the given
4384
- * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
4385
- * surfliquid first). Returns `[]` when the org has no compatible agent — never
4386
- * throws on an empty org. Loads agent keys on first call (apiKey only, no
4387
- * wallet), so the UI can resolve which agent to use before the user connects.
4388
- *
4389
- * This is the source of truth for agent availability: an agent appears here
4390
- * iff the routing API returned its key. No per-app feature flags.
4391
- */
4392
- async getEligibleAgentIds(chainId, asset) {
4393
- try {
4394
- await this.ensureAgentsInitialized();
4395
- } catch (error) {
4396
- if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
4397
- return [];
4398
- }
4399
- throw error;
4400
- }
4401
- return [...this.agents.values()].filter((agent) => {
4402
- const chainAssets = agent.supportedAssets.find(
4403
- (sa) => sa.chainId === chainId
4404
- );
4405
- return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
4406
- }).map((agent) => agent.id).sort(
4407
- (a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
4408
- );
4409
- }
4410
3574
  // --- Fund operations ---
4411
3575
  /**
4412
3576
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
@@ -4443,17 +3607,9 @@ var OwneySDK = class {
4443
3607
  }
4444
3608
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
4445
3609
  if (!amount) {
4446
- const aggregated2 = await this.getBalances();
4447
- const funded = projectAgentBalancesForAsset(
4448
- eligibleAgents,
4449
- aggregated2.agentBalances,
4450
- chainId,
4451
- asset,
4452
- assetInfo.decimals
4453
- ).filter((b) => b.balance > 0n);
4454
3610
  const results2 = {};
4455
3611
  const agentErrors2 = {};
4456
- for (const { agent } of funded) {
3612
+ for (const agent of eligibleAgents) {
4457
3613
  try {
4458
3614
  results2[agent.id] = await agent.withdraw(state, chainId, token);
4459
3615
  } catch (err) {
@@ -4475,10 +3631,9 @@ var OwneySDK = class {
4475
3631
  { asset, agentErrors: agentErrors2 }
4476
3632
  );
4477
3633
  }
4478
- const totalWithdrawn = funded.filter(({ agent }) => results2[agent.id] !== void 0).reduce((sum, { balance }) => sum + balance, 0n);
4479
3634
  return {
4480
3635
  agentResult: results2,
4481
- totalWithdrawn: totalWithdrawn.toString()
3636
+ totalWithdrawn: sumWithdrawnAmount(results2).toString()
4482
3637
  };
4483
3638
  }
4484
3639
  const requested = BigInt(amount);
@@ -4583,7 +3738,8 @@ var OwneySDK = class {
4583
3738
  const state = this.requireState();
4584
3739
  const chainId = this.requireChainId();
4585
3740
  if (agentId) {
4586
- const result = await this.getAgent(agentId).getBalances(state, chainId);
3741
+ const agent = this.getAgent(agentId);
3742
+ const result = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
4587
3743
  return result;
4588
3744
  }
4589
3745
  let totalBalance = 0;
@@ -4591,12 +3747,13 @@ var OwneySDK = class {
4591
3747
  const entries = [...this.getActiveAgents().entries()];
4592
3748
  const balanceResults = await Promise.allSettled(
4593
3749
  entries.map(async ([id, agent]) => {
4594
- const b = await agent.getBalances(state, chainId);
3750
+ const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
4595
3751
  return [id, b];
4596
3752
  })
4597
3753
  );
4598
3754
  let successCount = 0;
4599
3755
  const agentErrors = {};
3756
+ const agentFailures = [];
4600
3757
  for (let i = 0; i < balanceResults.length; i++) {
4601
3758
  const settledResult = balanceResults[i];
4602
3759
  const [agentId2] = entries[i];
@@ -4608,13 +3765,14 @@ var OwneySDK = class {
4608
3765
  continue;
4609
3766
  }
4610
3767
  const reason = settledResult.reason;
3768
+ agentFailures.push(reason);
4611
3769
  agentErrors[agentId2] = reason instanceof Error ? reason.message : String(reason);
4612
3770
  }
4613
3771
  if (successCount === 0) {
4614
3772
  throw new OwneyError(
4615
3773
  "BALANCE_ALL_FAILED",
4616
3774
  "Failed to fetch balances for all active agents.",
4617
- { agentErrors }
3775
+ { agentErrors, failures: agentFailures }
4618
3776
  );
4619
3777
  }
4620
3778
  return {
@@ -4632,14 +3790,15 @@ var OwneySDK = class {
4632
3790
  const state = this.requireState();
4633
3791
  const chainId = this.requireChainId();
4634
3792
  if (agentId) {
4635
- return this.getAgent(agentId).getEarnings(state, chainId);
3793
+ const agent = this.getAgent(agentId);
3794
+ return this.readAgent(agent, "earnings", () => agent.getEarnings(state, chainId));
4636
3795
  }
4637
3796
  let totalEarnings = 0;
4638
3797
  const results = {};
4639
3798
  const entries = [...this.getActiveAgents().entries()];
4640
3799
  const earningsResults = await Promise.all(
4641
3800
  entries.map(async ([id, agent]) => {
4642
- const e = await agent.getEarnings(state, chainId);
3801
+ const e = await this.readAgent(agent, "earnings", () => agent.getEarnings(state, chainId));
4643
3802
  return [id, e];
4644
3803
  })
4645
3804
  );
@@ -4659,7 +3818,11 @@ var OwneySDK = class {
4659
3818
  async refreshEarnings(agentId) {
4660
3819
  const state = this.requireState();
4661
3820
  const chainId = this.requireChainId();
4662
- const refreshAgent = (agent) => agent.refreshEarnings?.(state, chainId) ?? agent.getEarnings(state, chainId);
3821
+ const refreshAgent = (agent) => this.readAgent(
3822
+ agent,
3823
+ agent.refreshEarnings ? "refreshEarnings" : "earnings",
3824
+ () => agent.refreshEarnings?.(state, chainId) ?? agent.getEarnings(state, chainId)
3825
+ );
4663
3826
  if (agentId) return refreshAgent(this.getAgent(agentId));
4664
3827
  let totalEarnings = 0;
4665
3828
  const agentEarnings = {};
@@ -4690,11 +3853,12 @@ var OwneySDK = class {
4690
3853
  const state = this.requireState();
4691
3854
  const chainId = this.requireChainId();
4692
3855
  if (agentId) {
4693
- return this.getAgent(agentId).getAccountApy(
4694
- state,
4695
- chainId,
4696
- days,
4697
- tokenSymbol
3856
+ const agent = this.getAgent(agentId);
3857
+ return this.readAgent(
3858
+ agent,
3859
+ "accountApy",
3860
+ () => agent.getAccountApy(state, chainId, days, tokenSymbol),
3861
+ { days, tokenSymbol }
4698
3862
  );
4699
3863
  }
4700
3864
  const activeAgents = this.getActiveAgents();
@@ -4702,18 +3866,18 @@ var OwneySDK = class {
4702
3866
  const [apyResults, balanceResults] = await Promise.all([
4703
3867
  Promise.all(
4704
3868
  entries.map(async ([id, agent]) => {
4705
- const apy = await agent.getAccountApy(
4706
- state,
4707
- chainId,
4708
- days,
4709
- tokenSymbol
3869
+ const apy = await this.readAgent(
3870
+ agent,
3871
+ "accountApy",
3872
+ () => agent.getAccountApy(state, chainId, days, tokenSymbol),
3873
+ { days, tokenSymbol }
4710
3874
  );
4711
3875
  return [id, apy];
4712
3876
  })
4713
3877
  ),
4714
3878
  Promise.all(
4715
3879
  entries.map(async ([id, agent]) => {
4716
- const b = await agent.getBalances(state, chainId);
3880
+ const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
4717
3881
  return [id, Number(b.totalBalance)];
4718
3882
  })
4719
3883
  )
@@ -4770,7 +3934,8 @@ var OwneySDK = class {
4770
3934
  const chainId = this.requireChainId();
4771
3935
  const { agentId, filters } = options ?? {};
4772
3936
  if (agentId) {
4773
- return this.getAgent(agentId).getHistory(state, chainId, filters);
3937
+ const agent = this.getAgent(agentId);
3938
+ return this.readAgent(agent, "history", () => agent.getHistory(state, chainId, filters), filters);
4774
3939
  }
4775
3940
  const activeAgents = [...this.getActiveAgents().values()];
4776
3941
  const cursorMap = filters?.cursor ? decodeMultiAgentCursor(filters.cursor) : {};
@@ -4780,10 +3945,13 @@ var OwneySDK = class {
4780
3945
  if (filters?.cursor && agentCursor === void 0) {
4781
3946
  return { agentId: agent.id, page: null };
4782
3947
  }
4783
- const page = await agent.getHistory(state, chainId, {
4784
- ...filters,
4785
- cursor: agentCursor
4786
- });
3948
+ const agentFilters = { ...filters, cursor: agentCursor };
3949
+ const page = await this.readAgent(
3950
+ agent,
3951
+ "history",
3952
+ () => agent.getHistory(state, chainId, agentFilters),
3953
+ agentFilters
3954
+ );
4787
3955
  return { agentId: agent.id, page };
4788
3956
  })
4789
3957
  );
@@ -4823,13 +3991,14 @@ var OwneySDK = class {
4823
3991
  const state = this.requireState();
4824
3992
  const chainId = this.requireChainId();
4825
3993
  if (agentId) {
4826
- return this.getAgent(agentId).getUserProfile(state, chainId);
3994
+ const agent = this.getAgent(agentId);
3995
+ return this.readAgent(agent, "profile", () => agent.getUserProfile(state, chainId));
4827
3996
  }
4828
3997
  const results = {};
4829
3998
  const entries = [...this.getActiveAgents().entries()];
4830
3999
  const profileResults = await Promise.all(
4831
4000
  entries.map(async ([id, agent]) => {
4832
- const p = await agent.getUserProfile(state, chainId);
4001
+ const p = await this.readAgent(agent, "profile", () => agent.getUserProfile(state, chainId));
4833
4002
  return [id, p];
4834
4003
  })
4835
4004
  );
@@ -4852,7 +4021,20 @@ var OwneySDK = class {
4852
4021
  const chainId = this.requireChainId();
4853
4022
  const agent = this.getAgent(agentId);
4854
4023
  if (typeof agent.ensureAutoSelectProtocols !== "function") return false;
4855
- return agent.ensureAutoSelectProtocols(state, chainId, asset);
4024
+ const key2 = JSON.stringify([
4025
+ state.walletAddress.toLowerCase(),
4026
+ agentId,
4027
+ chainId,
4028
+ asset
4029
+ ]);
4030
+ const existing = this.activationChecks.get(key2);
4031
+ if (existing) return existing;
4032
+ const pending = Promise.resolve().then(() => agent.ensureAutoSelectProtocols(state, chainId, asset)).finally(() => {
4033
+ if (this.activationChecks.get(key2) === pending)
4034
+ this.activationChecks.delete(key2);
4035
+ });
4036
+ this.activationChecks.set(key2, pending);
4037
+ return pending;
4856
4038
  }
4857
4039
  /**
4858
4040
  * One-time, user-paid approval of Permit2 on the sponsored WETH token for
@@ -4875,10 +4057,10 @@ var OwneySDK = class {
4875
4057
  );
4876
4058
  }
4877
4059
  const provider = this.requireConnectedProvider();
4878
- const wallet = (0, import_viem10.createWalletClient)({
4060
+ const wallet = (0, import_viem6.createWalletClient)({
4879
4061
  account: state.walletAddress,
4880
4062
  chain: VIEM_CHAIN2[chainId],
4881
- transport: (0, import_viem10.custom)(provider)
4063
+ transport: (0, import_viem6.custom)(provider)
4882
4064
  });
4883
4065
  const hash = await wallet.writeContract({
4884
4066
  address: token,
@@ -4888,9 +4070,9 @@ var OwneySDK = class {
4888
4070
  account: state.walletAddress,
4889
4071
  chain: VIEM_CHAIN2[chainId]
4890
4072
  });
4891
- const publicClient = (0, import_viem10.createPublicClient)({
4073
+ const publicClient = (0, import_viem6.createPublicClient)({
4892
4074
  chain: VIEM_CHAIN2[chainId],
4893
- transport: (0, import_viem10.custom)(provider)
4075
+ transport: (0, import_viem6.custom)(provider)
4894
4076
  });
4895
4077
  const receipt = await publicClient.waitForTransactionReceipt({
4896
4078
  hash,
@@ -4923,13 +4105,14 @@ var OwneySDK = class {
4923
4105
  await this.ensureAgentsInitialized();
4924
4106
  const agentOptions = { tokenSymbol, chainId };
4925
4107
  if (agentId) {
4926
- return this.getAgent(agentId).getAgentApy(days, agentOptions);
4108
+ const agent = this.getAgent(agentId);
4109
+ return this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
4927
4110
  }
4928
4111
  const results = {};
4929
4112
  const agentEntries = [...this.agents.entries()];
4930
4113
  const apyResults = await Promise.all(
4931
4114
  agentEntries.map(async ([id, agent]) => {
4932
- const apy = await agent.getAgentApy(days, agentOptions);
4115
+ const apy = await this.readAgent(agent, "agentApy", () => agent.getAgentApy(days, agentOptions), { days, ...agentOptions });
4933
4116
  return [id, apy];
4934
4117
  })
4935
4118
  );
@@ -4956,7 +4139,7 @@ var OwneySDK = class {
4956
4139
  const entries = [...activeAgents.entries()];
4957
4140
  const balanceResults = await Promise.allSettled(
4958
4141
  entries.map(async ([id, agent]) => {
4959
- const b = await agent.getBalances(state, chainId);
4142
+ const b = await this.readAgent(agent, "balances", () => agent.getBalances(state, chainId));
4960
4143
  return [id, b.positions ?? []];
4961
4144
  })
4962
4145
  );
@@ -4964,6 +4147,7 @@ var OwneySDK = class {
4964
4147
  const allPositions = [];
4965
4148
  let successCount = 0;
4966
4149
  const agentErrors = {};
4150
+ const agentFailures = [];
4967
4151
  for (let i = 0; i < balanceResults.length; i++) {
4968
4152
  const settled = balanceResults[i];
4969
4153
  const [aid] = entries[i];
@@ -4978,6 +4162,7 @@ var OwneySDK = class {
4978
4162
  successCount += 1;
4979
4163
  } else {
4980
4164
  const reason = settled.reason;
4165
+ agentFailures.push(reason);
4981
4166
  agentErrors[aid] = reason instanceof Error ? reason.message : String(reason);
4982
4167
  console.error(`getAllocationApy agent "${aid}" failed:`, reason);
4983
4168
  }
@@ -4986,7 +4171,7 @@ var OwneySDK = class {
4986
4171
  throw new OwneyError(
4987
4172
  "ALLOCATION_ALL_FAILED",
4988
4173
  "Failed to fetch allocation APY: all agents failed.",
4989
- { agentErrors }
4174
+ { agentErrors, failures: agentFailures }
4990
4175
  );
4991
4176
  }
4992
4177
  const overall = computeAllocationApy(allPositions);
@@ -4998,12 +4183,8 @@ var OwneySDK = class {
4998
4183
  }
4999
4184
  };
5000
4185
 
5001
- // src/index.ts
5002
- init_errors();
5003
- init_debug();
5004
-
5005
4186
  // src/agents/zyfai/zyfai.siwx.ts
5006
- var import_viem11 = require("viem");
4187
+ var import_viem7 = require("viem");
5007
4188
  var import_siwe = require("siwe");
5008
4189
  var import_sdk2 = require("@zyfai/sdk");
5009
4190
 
@@ -5130,7 +4311,7 @@ function buildSIWXConfig(deps) {
5130
4311
  issuedAt,
5131
4312
  toString() {
5132
4313
  return new import_siwe.SiweMessage({
5133
- address: (0, import_viem11.getAddress)(accountAddress),
4314
+ address: (0, import_viem7.getAddress)(accountAddress),
5134
4315
  chainId: numericChainId(chainId),
5135
4316
  domain,
5136
4317
  uri,
@@ -5207,9 +4388,9 @@ function buildSIWXConfig(deps) {
5207
4388
  }
5208
4389
  function createOwneySIWX(config) {
5209
4390
  const zyfai = new import_sdk2.ZyfaiSDK({ apiKey: config.apiKey });
5210
- const http3 = zyfai.httpClient;
4391
+ const http2 = zyfai.httpClient;
5211
4392
  return buildSIWXConfig({
5212
- post: (url, data) => http3.post(url, data),
4393
+ post: (url, data) => http2.post(url, data),
5213
4394
  referralSource: config.referralSource
5214
4395
  });
5215
4396
  }