@owney/sdk 0.6.9-beta.6 → 0.6.9-beta.8

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.
@@ -0,0 +1,140 @@
1
+ // src/errors.ts
2
+ var OwneyError = class extends Error {
3
+ code;
4
+ details;
5
+ agentId;
6
+ constructor(code, message, details, agentId) {
7
+ const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
8
+ super(`${prefix} ${message}`);
9
+ this.name = "OwneyError";
10
+ this.code = code;
11
+ this.details = details;
12
+ this.agentId = agentId;
13
+ }
14
+ };
15
+ var AgentNotFoundError = class extends OwneyError {
16
+ constructor(agentId, available) {
17
+ super(
18
+ "AGENT_NOT_FOUND",
19
+ `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
20
+ { agentId, available },
21
+ agentId
22
+ );
23
+ this.name = "AgentNotFoundError";
24
+ }
25
+ };
26
+ var NotConnectedError = class extends OwneyError {
27
+ constructor() {
28
+ super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
29
+ this.name = "NotConnectedError";
30
+ }
31
+ };
32
+ var AgentChainIncompatibleError = class extends OwneyError {
33
+ incompatibleAgents;
34
+ connectedChainId;
35
+ constructor(incompatibleAgents, connectedChainId) {
36
+ const details = incompatibleAgents.map(
37
+ ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
38
+ ).join("; ");
39
+ super(
40
+ "AGENT_CHAIN_INCOMPATIBLE",
41
+ `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
42
+ { incompatibleAgents, connectedChainId }
43
+ );
44
+ this.name = "AgentChainIncompatibleError";
45
+ this.incompatibleAgents = incompatibleAgents;
46
+ this.connectedChainId = connectedChainId;
47
+ }
48
+ };
49
+
50
+ // src/lib/permit2.ts
51
+ import { bytesToHex } from "viem";
52
+ var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
53
+ var MAX_UINT256 = 2n ** 256n - 1n;
54
+ var ERC20_ALLOWANCE_ABI = [
55
+ {
56
+ type: "function",
57
+ name: "allowance",
58
+ stateMutability: "view",
59
+ inputs: [
60
+ { name: "owner", type: "address" },
61
+ { name: "spender", type: "address" }
62
+ ],
63
+ outputs: [{ name: "", type: "uint256" }]
64
+ },
65
+ {
66
+ type: "function",
67
+ name: "approve",
68
+ stateMutability: "nonpayable",
69
+ inputs: [
70
+ { name: "spender", type: "address" },
71
+ { name: "amount", type: "uint256" }
72
+ ],
73
+ outputs: [{ name: "", type: "bool" }]
74
+ },
75
+ {
76
+ type: "function",
77
+ name: "balanceOf",
78
+ stateMutability: "view",
79
+ inputs: [{ name: "account", type: "address" }],
80
+ outputs: [{ name: "", type: "uint256" }]
81
+ }
82
+ ];
83
+ function buildPermitTransferFromTypedData(input) {
84
+ return {
85
+ domain: {
86
+ name: "Permit2",
87
+ chainId: input.chainId,
88
+ verifyingContract: PERMIT2_ADDRESS
89
+ },
90
+ types: {
91
+ PermitTransferFrom: [
92
+ { name: "permitted", type: "TokenPermissions" },
93
+ { name: "spender", type: "address" },
94
+ { name: "nonce", type: "uint256" },
95
+ { name: "deadline", type: "uint256" }
96
+ ],
97
+ TokenPermissions: [
98
+ { name: "token", type: "address" },
99
+ { name: "amount", type: "uint256" }
100
+ ]
101
+ },
102
+ primaryType: "PermitTransferFrom",
103
+ message: input.message
104
+ };
105
+ }
106
+ function randomPermit2Nonce() {
107
+ const bytes = new Uint8Array(32);
108
+ globalThis.crypto.getRandomValues(bytes);
109
+ return BigInt(bytesToHex(bytes));
110
+ }
111
+ async function readPermit2Allowance(publicClient, token, owner) {
112
+ return publicClient.readContract({
113
+ address: token,
114
+ abi: ERC20_ALLOWANCE_ABI,
115
+ functionName: "allowance",
116
+ args: [owner, PERMIT2_ADDRESS]
117
+ });
118
+ }
119
+ async function readErc20Balance(publicClient, token, owner) {
120
+ return publicClient.readContract({
121
+ address: token,
122
+ abi: ERC20_ALLOWANCE_ABI,
123
+ functionName: "balanceOf",
124
+ args: [owner]
125
+ });
126
+ }
127
+
128
+ export {
129
+ OwneyError,
130
+ AgentNotFoundError,
131
+ NotConnectedError,
132
+ AgentChainIncompatibleError,
133
+ PERMIT2_ADDRESS,
134
+ MAX_UINT256,
135
+ ERC20_ALLOWANCE_ABI,
136
+ buildPermitTransferFromTypedData,
137
+ randomPermit2Nonce,
138
+ readPermit2Allowance,
139
+ readErc20Balance
140
+ };
package/dist/index.cjs CHANGED
@@ -80,8 +80,92 @@ var init_errors = __esm({
80
80
  }
81
81
  });
82
82
 
83
+ // src/lib/permit2.ts
84
+ function buildPermitTransferFromTypedData(input) {
85
+ return {
86
+ domain: {
87
+ name: "Permit2",
88
+ chainId: input.chainId,
89
+ verifyingContract: PERMIT2_ADDRESS
90
+ },
91
+ types: {
92
+ PermitTransferFrom: [
93
+ { name: "permitted", type: "TokenPermissions" },
94
+ { name: "spender", type: "address" },
95
+ { name: "nonce", type: "uint256" },
96
+ { name: "deadline", type: "uint256" }
97
+ ],
98
+ TokenPermissions: [
99
+ { name: "token", type: "address" },
100
+ { name: "amount", type: "uint256" }
101
+ ]
102
+ },
103
+ primaryType: "PermitTransferFrom",
104
+ message: input.message
105
+ };
106
+ }
107
+ function randomPermit2Nonce() {
108
+ const bytes = new Uint8Array(32);
109
+ globalThis.crypto.getRandomValues(bytes);
110
+ return BigInt((0, import_viem4.bytesToHex)(bytes));
111
+ }
112
+ async function readPermit2Allowance(publicClient, token, owner) {
113
+ return publicClient.readContract({
114
+ address: token,
115
+ abi: ERC20_ALLOWANCE_ABI,
116
+ functionName: "allowance",
117
+ args: [owner, PERMIT2_ADDRESS]
118
+ });
119
+ }
120
+ async function readErc20Balance(publicClient, token, owner) {
121
+ return publicClient.readContract({
122
+ address: token,
123
+ abi: ERC20_ALLOWANCE_ABI,
124
+ functionName: "balanceOf",
125
+ args: [owner]
126
+ });
127
+ }
128
+ var import_viem4, PERMIT2_ADDRESS, MAX_UINT256, ERC20_ALLOWANCE_ABI;
129
+ var init_permit2 = __esm({
130
+ "src/lib/permit2.ts"() {
131
+ "use strict";
132
+ import_viem4 = require("viem");
133
+ PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
134
+ MAX_UINT256 = 2n ** 256n - 1n;
135
+ ERC20_ALLOWANCE_ABI = [
136
+ {
137
+ type: "function",
138
+ name: "allowance",
139
+ stateMutability: "view",
140
+ inputs: [
141
+ { name: "owner", type: "address" },
142
+ { name: "spender", type: "address" }
143
+ ],
144
+ outputs: [{ name: "", type: "uint256" }]
145
+ },
146
+ {
147
+ type: "function",
148
+ name: "approve",
149
+ stateMutability: "nonpayable",
150
+ inputs: [
151
+ { name: "spender", type: "address" },
152
+ { name: "amount", type: "uint256" }
153
+ ],
154
+ outputs: [{ name: "", type: "bool" }]
155
+ },
156
+ {
157
+ type: "function",
158
+ name: "balanceOf",
159
+ stateMutability: "view",
160
+ inputs: [{ name: "account", type: "address" }],
161
+ outputs: [{ name: "", type: "uint256" }]
162
+ }
163
+ ];
164
+ }
165
+ });
166
+
83
167
  // src/agents/surfliquid/surfliquid.constants.ts
84
- var SURFLIQUID_CHAIN_ID, SURFLIQUID_CHAIN_NAME, SURFLIQUID_USDC_ADDRESS, SURFLIQUID_USDC_DECIMALS, SURFLIQUID_MIN_DEPOSIT, SURFLIQUID_SUPPORTED_ASSETS, SURFLIQUID_ACTION_MAP;
168
+ var SURFLIQUID_CHAIN_ID, SURFLIQUID_CHAIN_NAME, SURFLIQUID_USDC_ADDRESS, SURFLIQUID_USDC_DECIMALS, SURFLIQUID_MIN_DEPOSIT, SURFLIQUID_APPROVAL_TARGET, SURFLIQUID_SUPPORTED_ASSETS, SURFLIQUID_ACTION_MAP;
85
169
  var init_surfliquid_constants = __esm({
86
170
  "src/agents/surfliquid/surfliquid.constants.ts"() {
87
171
  "use strict";
@@ -90,6 +174,7 @@ var init_surfliquid_constants = __esm({
90
174
  SURFLIQUID_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
91
175
  SURFLIQUID_USDC_DECIMALS = 6;
92
176
  SURFLIQUID_MIN_DEPOSIT = "0";
177
+ SURFLIQUID_APPROVAL_TARGET = 100000000000n;
93
178
  SURFLIQUID_SUPPORTED_ASSETS = [
94
179
  {
95
180
  chainId: SURFLIQUID_CHAIN_ID,
@@ -249,27 +334,20 @@ var init_surfliquid_wallet_adapter = __esm({
249
334
  });
250
335
 
251
336
  // src/agents/surfliquid/surfliquid.morpho.ts
252
- async function fetchMorphoVaultStats(vaultAddress, chainId) {
337
+ async function queryMorpho(query, vaultAddress, chainId) {
253
338
  try {
254
339
  const res = await fetch(MORPHO_API_URL, {
255
340
  method: "POST",
256
341
  headers: { "Content-Type": "application/json" },
257
342
  body: JSON.stringify({
258
- query: VAULT_STATS_QUERY,
343
+ query,
259
344
  variables: { address: vaultAddress, chainId }
260
345
  })
261
346
  });
262
347
  if (!res.ok) return null;
263
348
  const json = await res.json();
264
349
  if (json.errors) return null;
265
- const vault = json.data?.vaultByAddress;
266
- const tvlUsd = vault?.state?.totalAssetsUsd;
267
- const liquidityUsd = vault?.liquidity?.usd;
268
- if (typeof tvlUsd !== "number" || typeof liquidityUsd !== "number") {
269
- return null;
270
- }
271
- const name = typeof vault?.name === "string" ? vault.name : null;
272
- return { name, tvlUsd, liquidityUsd };
350
+ return json.data ?? null;
273
351
  } catch (error) {
274
352
  console.warn("surfliquid: Morpho vault stats fetch failed", {
275
353
  vaultAddress,
@@ -279,6 +357,29 @@ async function fetchMorphoVaultStats(vaultAddress, chainId) {
279
357
  return null;
280
358
  }
281
359
  }
360
+ function toStats(name, tvlUsd, liquidityUsd) {
361
+ if (typeof tvlUsd !== "number" || typeof liquidityUsd !== "number") {
362
+ return null;
363
+ }
364
+ return {
365
+ name: typeof name === "string" ? name : null,
366
+ tvlUsd,
367
+ liquidityUsd
368
+ };
369
+ }
370
+ async function fetchMorphoVaultStats(vaultAddress, chainId) {
371
+ const v1 = await queryMorpho(VAULT_STATS_QUERY, vaultAddress, chainId);
372
+ const vault = v1?.vaultByAddress;
373
+ const v1Stats = toStats(
374
+ vault?.name,
375
+ vault?.state?.totalAssetsUsd,
376
+ vault?.liquidity?.usd
377
+ );
378
+ if (v1Stats) return v1Stats;
379
+ const v2 = await queryMorpho(VAULT_V2_STATS_QUERY, vaultAddress, chainId);
380
+ const vaultV2 = v2?.vaultV2ByAddress;
381
+ return toStats(vaultV2?.name, vaultV2?.totalAssetsUsd, vaultV2?.liquidityUsd);
382
+ }
282
383
  async function fetchMorphoStatsByVault(vaultAddresses, chainId) {
283
384
  const unique = [...new Set(vaultAddresses.map((a) => a.toLowerCase()))];
284
385
  const entries = await Promise.all(
@@ -292,7 +393,7 @@ async function fetchMorphoStatsByVault(vaultAddresses, chainId) {
292
393
  }
293
394
  return byVault;
294
395
  }
295
- var MORPHO_API_URL, VAULT_STATS_QUERY;
396
+ var MORPHO_API_URL, VAULT_STATS_QUERY, VAULT_V2_STATS_QUERY;
296
397
  var init_surfliquid_morpho = __esm({
297
398
  "src/agents/surfliquid/surfliquid.morpho.ts"() {
298
399
  "use strict";
@@ -305,6 +406,15 @@ var init_surfliquid_morpho = __esm({
305
406
  liquidity { usd }
306
407
  }
307
408
  }
409
+ `;
410
+ VAULT_V2_STATS_QUERY = `
411
+ query VaultV2Stats($address: String!, $chainId: Int!) {
412
+ vaultV2ByAddress(address: $address, chainId: $chainId) {
413
+ name
414
+ totalAssetsUsd
415
+ liquidityUsd
416
+ }
417
+ }
308
418
  `;
309
419
  }
310
420
  });
@@ -314,14 +424,16 @@ var surfliquid_agent_exports = {};
314
424
  __export(surfliquid_agent_exports, {
315
425
  SurfLiquidAgent: () => SurfLiquidAgent
316
426
  });
317
- var import_core_sdk2, import_viem5, APY_WINDOW_KEY2, SurfLiquidAgent;
427
+ var import_core_sdk2, import_viem5, import_chains2, APY_WINDOW_KEY2, SurfLiquidAgent;
318
428
  var init_surfliquid_agent = __esm({
319
429
  "src/agents/surfliquid/surfliquid.agent.ts"() {
320
430
  "use strict";
321
431
  import_core_sdk2 = require("@surf_liquid/core-sdk");
322
432
  import_viem5 = require("viem");
433
+ import_chains2 = require("viem/chains");
323
434
  init_errors();
324
435
  init_surfliquid_constants();
436
+ init_permit2();
325
437
  init_surfliquid_mapper();
326
438
  init_surfliquid_wallet_adapter();
327
439
  init_surfliquid_morpho();
@@ -397,6 +509,60 @@ var init_surfliquid_agent = __esm({
397
509
  const { vaultAddress } = await surf.deployVault();
398
510
  return vaultAddress;
399
511
  }
512
+ /**
513
+ * Grants the user's vault a standing USDC allowance so SurfLiquid's
514
+ * `autoApprove` has nothing to do — see {@link SURFLIQUID_APPROVAL_TARGET}
515
+ * for why one prompt per deposit is worth removing.
516
+ *
517
+ * Fails OPEN on a read error: if the allowance can't be checked we simply
518
+ * return and let SurfLiquid's own per-deposit approve run, because a flaky
519
+ * RPC must never block a deposit. A failed or rejected APPROVE does
520
+ * propagate — the user declined a transaction, and letting SurfLiquid
521
+ * immediately ask again for a smaller one is exactly the double prompt this
522
+ * removes.
523
+ */
524
+ async ensureVaultAllowance(state, vaultAddress, amount) {
525
+ const spender = vaultAddress;
526
+ const transport = (0, import_viem5.custom)(state.provider);
527
+ const publicClient = (0, import_viem5.createPublicClient)({ chain: import_chains2.base, transport });
528
+ let allowance;
529
+ try {
530
+ allowance = await publicClient.readContract({
531
+ address: SURFLIQUID_USDC_ADDRESS,
532
+ abi: ERC20_ALLOWANCE_ABI,
533
+ functionName: "allowance",
534
+ args: [state.walletAddress, spender]
535
+ });
536
+ } catch (error) {
537
+ console.warn(
538
+ "[owney-sdk] SurfLiquid allowance pre-check failed; deferring to its per-deposit approve:",
539
+ error instanceof Error ? error.message : String(error)
540
+ );
541
+ return;
542
+ }
543
+ if (allowance >= amount) return;
544
+ const target = amount > SURFLIQUID_APPROVAL_TARGET ? amount : SURFLIQUID_APPROVAL_TARGET;
545
+ const wallet = (0, import_viem5.createWalletClient)({
546
+ account: state.walletAddress,
547
+ chain: import_chains2.base,
548
+ transport
549
+ });
550
+ const hash = await wallet.writeContract({
551
+ address: SURFLIQUID_USDC_ADDRESS,
552
+ abi: ERC20_ALLOWANCE_ABI,
553
+ functionName: "approve",
554
+ args: [spender, target],
555
+ account: state.walletAddress,
556
+ chain: import_chains2.base
557
+ });
558
+ const receipt = await publicClient.waitForTransactionReceipt({
559
+ hash,
560
+ confirmations: 1
561
+ });
562
+ if (receipt.status !== "success") {
563
+ throw new Error(`SurfLiquid USDC approval reverted (tx ${hash})`);
564
+ }
565
+ }
400
566
  // --- IAgent: lifecycle ---
401
567
  async disconnect() {
402
568
  if (this.surf) {
@@ -415,6 +581,7 @@ var init_surfliquid_agent = __esm({
415
581
  surf,
416
582
  state.walletAddress
417
583
  );
584
+ await this.ensureVaultAllowance(state, smartWallet, BigInt(amount));
418
585
  const tx = await surf.deposit({
419
586
  asset: SURFLIQUID_USDC_ADDRESS,
420
587
  amount: human
@@ -581,6 +748,12 @@ var isValidChainId = (chainId) => {
581
748
  }
582
749
  return chainId;
583
750
  };
751
+ function isSameAsset(tokenSymbol, asset) {
752
+ const token = tokenSymbol.toLowerCase();
753
+ const target = asset.toLowerCase();
754
+ if (token === target) return true;
755
+ return target === "weth" && token === "eth" || target === "eth" && token === "weth";
756
+ }
584
757
  function hexToDecimal(hex, decimals = 6) {
585
758
  const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
586
759
  const parsed = BigInt(normalized);
@@ -1789,6 +1962,37 @@ var ZyfaiAgent = class {
1789
1962
  );
1790
1963
  }
1791
1964
  }
1965
+ /**
1966
+ * Records the deposit with Zyfai, retrying transient failures.
1967
+ *
1968
+ * This runs AFTER the transfer has already landed on-chain, so it must never
1969
+ * fail the deposit — the funds moved. But it is also the ONLY source of the
1970
+ * "Top up wallet" entry the history is built from: Zyfai auto-deploys the
1971
+ * balance it detects either way, so when this call is lost the user's deposit
1972
+ * never appears in Activity (an earlier withdrawal stays the newest row) and
1973
+ * nothing ever backfills it. Retry, then log loudly enough to be recoverable.
1974
+ */
1975
+ async logDepositWithRetry(chainId, txHash, amount, tokenAddress) {
1976
+ const ATTEMPTS = 3;
1977
+ const RETRY_DELAY_MS = 1e3;
1978
+ for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
1979
+ try {
1980
+ await (tokenAddress ? this.sdk.logDeposit(chainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(chainId, txHash, amount));
1981
+ return;
1982
+ } catch (logError) {
1983
+ if (attempt === ATTEMPTS) {
1984
+ console.error(
1985
+ "[owney-sdk] Deposit landed on-chain but logDeposit failed \u2014 it will be missing from Zyfai history:",
1986
+ { txHash, chainId, amount, tokenAddress, error: logError }
1987
+ );
1988
+ return;
1989
+ }
1990
+ await new Promise(
1991
+ (resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt)
1992
+ );
1993
+ }
1994
+ }
1995
+ }
1792
1996
  async deposit(state, chainId, amount, asset, depositCallback) {
1793
1997
  try {
1794
1998
  await this.connectFull(state, chainId);
@@ -1804,14 +2008,12 @@ var ZyfaiAgent = class {
1804
2008
  amount
1805
2009
  );
1806
2010
  const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
1807
- try {
1808
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1809
- } catch (logError) {
1810
- console.warn(
1811
- "[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
1812
- logError
1813
- );
1814
- }
2011
+ await this.logDepositWithRetry(
2012
+ validChainId,
2013
+ txHash,
2014
+ amount,
2015
+ tokenAddress
2016
+ );
1815
2017
  return { txHash, smartWallet: wallet.address, amount };
1816
2018
  }
1817
2019
  const raw = await this.sdk.depositFunds(
@@ -2055,11 +2257,10 @@ async function withFailureReporting(apiKey, agentType, fn) {
2055
2257
  // src/lib/helpers/withdraw-helper.ts
2056
2258
  var import_viem2 = require("viem");
2057
2259
  function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
2058
- const target = asset.toUpperCase();
2059
2260
  return agents.map((agent) => {
2060
2261
  const agentBalance = aggregated[agent.id];
2061
2262
  const tokenBalance = agentBalance?.tokens.find(
2062
- (t) => t.chainId === chainId && t.asset.toUpperCase() === target
2263
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
2063
2264
  );
2064
2265
  if (!tokenBalance) return { agent, balance: 0n };
2065
2266
  return { agent, balance: (0, import_viem2.parseUnits)(tokenBalance.amount, decimals) };
@@ -2170,7 +2371,7 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
2170
2371
 
2171
2372
  // src/client.ts
2172
2373
  var import_viem6 = require("viem");
2173
- var import_chains2 = require("viem/chains");
2374
+ var import_chains3 = require("viem/chains");
2174
2375
 
2175
2376
  // src/lib/sponsored-deposit.ts
2176
2377
  init_errors();
@@ -2215,10 +2416,10 @@ function randomAuthNonce() {
2215
2416
  init_errors();
2216
2417
  var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
2217
2418
  async function postSponsorTransferAuth(input) {
2218
- const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2419
+ const base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2219
2420
  let res;
2220
2421
  try {
2221
- res = await fetch(`${base3}/api/v1/sponsor/erc20-transfer-auth`, {
2422
+ res = await fetch(`${base4}/api/v1/sponsor/erc20-transfer-auth`, {
2222
2423
  method: "POST",
2223
2424
  headers: {
2224
2425
  "content-type": "application/json",
@@ -2255,10 +2456,10 @@ async function postSponsorTransferAuth(input) {
2255
2456
  return parsed.data;
2256
2457
  }
2257
2458
  async function postSponsorPermit2Transfer(input) {
2258
- const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2459
+ const base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2259
2460
  let res;
2260
2461
  try {
2261
- res = await fetch(`${base3}/api/v1/sponsor/permit2-transfer`, {
2462
+ res = await fetch(`${base4}/api/v1/sponsor/permit2-transfer`, {
2262
2463
  method: "POST",
2263
2464
  headers: {
2264
2465
  "content-type": "application/json",
@@ -2293,11 +2494,11 @@ async function postSponsorPermit2Transfer(input) {
2293
2494
  return parsed.data;
2294
2495
  }
2295
2496
  async function getSponsorRelayerAddress(input) {
2296
- const base3 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2497
+ const base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
2297
2498
  let res;
2298
2499
  try {
2299
2500
  res = await fetch(
2300
- `${base3}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
2501
+ `${base4}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
2301
2502
  {
2302
2503
  headers: { "x-owney-api-key": input.apiKey }
2303
2504
  }
@@ -2329,85 +2530,8 @@ async function getSponsorRelayerAddress(input) {
2329
2530
  return parsed.data.relayer;
2330
2531
  }
2331
2532
 
2332
- // src/lib/permit2.ts
2333
- var import_viem4 = require("viem");
2334
- var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
2335
- var MAX_UINT256 = 2n ** 256n - 1n;
2336
- var ERC20_ALLOWANCE_ABI = [
2337
- {
2338
- type: "function",
2339
- name: "allowance",
2340
- stateMutability: "view",
2341
- inputs: [
2342
- { name: "owner", type: "address" },
2343
- { name: "spender", type: "address" }
2344
- ],
2345
- outputs: [{ name: "", type: "uint256" }]
2346
- },
2347
- {
2348
- type: "function",
2349
- name: "approve",
2350
- stateMutability: "nonpayable",
2351
- inputs: [
2352
- { name: "spender", type: "address" },
2353
- { name: "amount", type: "uint256" }
2354
- ],
2355
- outputs: [{ name: "", type: "bool" }]
2356
- },
2357
- {
2358
- type: "function",
2359
- name: "balanceOf",
2360
- stateMutability: "view",
2361
- inputs: [{ name: "account", type: "address" }],
2362
- outputs: [{ name: "", type: "uint256" }]
2363
- }
2364
- ];
2365
- function buildPermitTransferFromTypedData(input) {
2366
- return {
2367
- domain: {
2368
- name: "Permit2",
2369
- chainId: input.chainId,
2370
- verifyingContract: PERMIT2_ADDRESS
2371
- },
2372
- types: {
2373
- PermitTransferFrom: [
2374
- { name: "permitted", type: "TokenPermissions" },
2375
- { name: "spender", type: "address" },
2376
- { name: "nonce", type: "uint256" },
2377
- { name: "deadline", type: "uint256" }
2378
- ],
2379
- TokenPermissions: [
2380
- { name: "token", type: "address" },
2381
- { name: "amount", type: "uint256" }
2382
- ]
2383
- },
2384
- primaryType: "PermitTransferFrom",
2385
- message: input.message
2386
- };
2387
- }
2388
- function randomPermit2Nonce() {
2389
- const bytes = new Uint8Array(32);
2390
- globalThis.crypto.getRandomValues(bytes);
2391
- return BigInt((0, import_viem4.bytesToHex)(bytes));
2392
- }
2393
- async function readPermit2Allowance(publicClient, token, owner) {
2394
- return publicClient.readContract({
2395
- address: token,
2396
- abi: ERC20_ALLOWANCE_ABI,
2397
- functionName: "allowance",
2398
- args: [owner, PERMIT2_ADDRESS]
2399
- });
2400
- }
2401
- async function readErc20Balance(publicClient, token, owner) {
2402
- return publicClient.readContract({
2403
- address: token,
2404
- abi: ERC20_ALLOWANCE_ABI,
2405
- functionName: "balanceOf",
2406
- args: [owner]
2407
- });
2408
- }
2409
-
2410
2533
  // src/lib/sponsored-deposit.ts
2534
+ init_permit2();
2411
2535
  var AUTH_WINDOW_SECONDS = 15 * 60;
2412
2536
  function makeSponsoredDepositCallback(deps) {
2413
2537
  const post = deps.httpPost ?? postSponsorTransferAuth;
@@ -2482,6 +2606,7 @@ function makeSponsoredDepositCallback(deps) {
2482
2606
 
2483
2607
  // src/lib/sponsored-weth-deposit.ts
2484
2608
  init_errors();
2609
+ init_permit2();
2485
2610
  var PERMIT_WINDOW_SECONDS = 15 * 60;
2486
2611
  function makeSponsoredWethCallback(deps) {
2487
2612
  const get = deps.httpGet ?? getSponsorRelayerAddress;
@@ -2560,6 +2685,7 @@ function makeSponsoredWethCallback(deps) {
2560
2685
  }
2561
2686
 
2562
2687
  // src/client.ts
2688
+ init_permit2();
2563
2689
  function encodeMultiAgentCursor(map) {
2564
2690
  return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
2565
2691
  }
@@ -2586,9 +2712,9 @@ var SPONSORED_USDC_BY_CHAIN = {
2586
2712
  1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
2587
2713
  };
2588
2714
  var VIEM_CHAIN2 = {
2589
- 8453: import_chains2.base,
2590
- 42161: import_chains2.arbitrum,
2591
- 1: import_chains2.mainnet
2715
+ 8453: import_chains3.base,
2716
+ 42161: import_chains3.arbitrum,
2717
+ 1: import_chains3.mainnet
2592
2718
  };
2593
2719
  var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai", "sail"];
2594
2720
  var SPONSORED_WETH_BY_CHAIN = {
@@ -3168,9 +3294,8 @@ var OwneySDK = class {
3168
3294
  async hasExistingBalance(agent, state, chainId, asset) {
3169
3295
  try {
3170
3296
  const balance = await agent.getBalances(state, chainId);
3171
- const target = asset.toLowerCase();
3172
3297
  const token = balance.tokens.find(
3173
- (t) => t.chainId === chainId && t.asset.toLowerCase() === target
3298
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
3174
3299
  );
3175
3300
  return !!token && Number(token.amount) > 0;
3176
3301
  } catch {
package/dist/index.js CHANGED
@@ -1,9 +1,16 @@
1
1
  import {
2
2
  AgentChainIncompatibleError,
3
3
  AgentNotFoundError,
4
+ ERC20_ALLOWANCE_ABI,
5
+ MAX_UINT256,
4
6
  NotConnectedError,
5
- OwneyError
6
- } from "./chunk-GMNQBWUB.js";
7
+ OwneyError,
8
+ PERMIT2_ADDRESS,
9
+ buildPermitTransferFromTypedData,
10
+ randomPermit2Nonce,
11
+ readErc20Balance,
12
+ readPermit2Allowance
13
+ } from "./chunk-PWIKIQOX.js";
7
14
 
8
15
  // src/agents/zyfai/zyfai.agent.ts
9
16
  import { ZyfaiSDK } from "@zyfai/sdk";
@@ -74,6 +81,12 @@ var isValidChainId = (chainId) => {
74
81
  }
75
82
  return chainId;
76
83
  };
84
+ function isSameAsset(tokenSymbol, asset) {
85
+ const token = tokenSymbol.toLowerCase();
86
+ const target = asset.toLowerCase();
87
+ if (token === target) return true;
88
+ return target === "weth" && token === "eth" || target === "eth" && token === "weth";
89
+ }
77
90
  function hexToDecimal(hex, decimals = 6) {
78
91
  const normalized = hex.startsWith("0x") || hex.startsWith("0X") ? hex : `0x${hex}`;
79
92
  const parsed = BigInt(normalized);
@@ -1279,6 +1292,37 @@ var ZyfaiAgent = class {
1279
1292
  );
1280
1293
  }
1281
1294
  }
1295
+ /**
1296
+ * Records the deposit with Zyfai, retrying transient failures.
1297
+ *
1298
+ * This runs AFTER the transfer has already landed on-chain, so it must never
1299
+ * fail the deposit — the funds moved. But it is also the ONLY source of the
1300
+ * "Top up wallet" entry the history is built from: Zyfai auto-deploys the
1301
+ * balance it detects either way, so when this call is lost the user's deposit
1302
+ * never appears in Activity (an earlier withdrawal stays the newest row) and
1303
+ * nothing ever backfills it. Retry, then log loudly enough to be recoverable.
1304
+ */
1305
+ async logDepositWithRetry(chainId, txHash, amount, tokenAddress) {
1306
+ const ATTEMPTS = 3;
1307
+ const RETRY_DELAY_MS = 1e3;
1308
+ for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
1309
+ try {
1310
+ await (tokenAddress ? this.sdk.logDeposit(chainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(chainId, txHash, amount));
1311
+ return;
1312
+ } catch (logError) {
1313
+ if (attempt === ATTEMPTS) {
1314
+ console.error(
1315
+ "[owney-sdk] Deposit landed on-chain but logDeposit failed \u2014 it will be missing from Zyfai history:",
1316
+ { txHash, chainId, amount, tokenAddress, error: logError }
1317
+ );
1318
+ return;
1319
+ }
1320
+ await new Promise(
1321
+ (resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt)
1322
+ );
1323
+ }
1324
+ }
1325
+ }
1282
1326
  async deposit(state, chainId, amount, asset, depositCallback) {
1283
1327
  try {
1284
1328
  await this.connectFull(state, chainId);
@@ -1294,14 +1338,12 @@ var ZyfaiAgent = class {
1294
1338
  amount
1295
1339
  );
1296
1340
  const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
1297
- try {
1298
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1299
- } catch (logError) {
1300
- console.warn(
1301
- "[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
1302
- logError
1303
- );
1304
- }
1341
+ await this.logDepositWithRetry(
1342
+ validChainId,
1343
+ txHash,
1344
+ amount,
1345
+ tokenAddress
1346
+ );
1305
1347
  return { txHash, smartWallet: wallet.address, amount };
1306
1348
  }
1307
1349
  const raw = await this.sdk.depositFunds(
@@ -1540,11 +1582,10 @@ async function withFailureReporting(apiKey, agentType, fn) {
1540
1582
  // src/lib/helpers/withdraw-helper.ts
1541
1583
  import { parseUnits } from "viem";
1542
1584
  function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
1543
- const target = asset.toUpperCase();
1544
1585
  return agents.map((agent) => {
1545
1586
  const agentBalance = aggregated[agent.id];
1546
1587
  const tokenBalance = agentBalance?.tokens.find(
1547
- (t) => t.chainId === chainId && t.asset.toUpperCase() === target
1588
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
1548
1589
  );
1549
1590
  if (!tokenBalance) return { agent, balance: 0n };
1550
1591
  return { agent, balance: parseUnits(tokenBalance.amount, decimals) };
@@ -1814,84 +1855,6 @@ async function getSponsorRelayerAddress(input) {
1814
1855
  return parsed.data.relayer;
1815
1856
  }
1816
1857
 
1817
- // src/lib/permit2.ts
1818
- import { bytesToHex as bytesToHex2 } from "viem";
1819
- var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
1820
- var MAX_UINT256 = 2n ** 256n - 1n;
1821
- var ERC20_ALLOWANCE_ABI = [
1822
- {
1823
- type: "function",
1824
- name: "allowance",
1825
- stateMutability: "view",
1826
- inputs: [
1827
- { name: "owner", type: "address" },
1828
- { name: "spender", type: "address" }
1829
- ],
1830
- outputs: [{ name: "", type: "uint256" }]
1831
- },
1832
- {
1833
- type: "function",
1834
- name: "approve",
1835
- stateMutability: "nonpayable",
1836
- inputs: [
1837
- { name: "spender", type: "address" },
1838
- { name: "amount", type: "uint256" }
1839
- ],
1840
- outputs: [{ name: "", type: "bool" }]
1841
- },
1842
- {
1843
- type: "function",
1844
- name: "balanceOf",
1845
- stateMutability: "view",
1846
- inputs: [{ name: "account", type: "address" }],
1847
- outputs: [{ name: "", type: "uint256" }]
1848
- }
1849
- ];
1850
- function buildPermitTransferFromTypedData(input) {
1851
- return {
1852
- domain: {
1853
- name: "Permit2",
1854
- chainId: input.chainId,
1855
- verifyingContract: PERMIT2_ADDRESS
1856
- },
1857
- types: {
1858
- PermitTransferFrom: [
1859
- { name: "permitted", type: "TokenPermissions" },
1860
- { name: "spender", type: "address" },
1861
- { name: "nonce", type: "uint256" },
1862
- { name: "deadline", type: "uint256" }
1863
- ],
1864
- TokenPermissions: [
1865
- { name: "token", type: "address" },
1866
- { name: "amount", type: "uint256" }
1867
- ]
1868
- },
1869
- primaryType: "PermitTransferFrom",
1870
- message: input.message
1871
- };
1872
- }
1873
- function randomPermit2Nonce() {
1874
- const bytes = new Uint8Array(32);
1875
- globalThis.crypto.getRandomValues(bytes);
1876
- return BigInt(bytesToHex2(bytes));
1877
- }
1878
- async function readPermit2Allowance(publicClient, token, owner) {
1879
- return publicClient.readContract({
1880
- address: token,
1881
- abi: ERC20_ALLOWANCE_ABI,
1882
- functionName: "allowance",
1883
- args: [owner, PERMIT2_ADDRESS]
1884
- });
1885
- }
1886
- async function readErc20Balance(publicClient, token, owner) {
1887
- return publicClient.readContract({
1888
- address: token,
1889
- abi: ERC20_ALLOWANCE_ABI,
1890
- functionName: "balanceOf",
1891
- args: [owner]
1892
- });
1893
- }
1894
-
1895
1858
  // src/lib/sponsored-deposit.ts
1896
1859
  var AUTH_WINDOW_SECONDS = 15 * 60;
1897
1860
  function makeSponsoredDepositCallback(deps) {
@@ -2349,7 +2312,7 @@ var OwneySDK = class {
2349
2312
  }
2350
2313
  if (agentId === "surfliquid") {
2351
2314
  if (!projectName) return null;
2352
- const { SurfLiquidAgent } = await import("./surfliquid.agent-OMOYXWLP.js");
2315
+ const { SurfLiquidAgent } = await import("./surfliquid.agent-VNGQUSXN.js");
2353
2316
  return new SurfLiquidAgent({
2354
2317
  projectName,
2355
2318
  appId: key2,
@@ -2652,9 +2615,8 @@ var OwneySDK = class {
2652
2615
  async hasExistingBalance(agent, state, chainId, asset) {
2653
2616
  try {
2654
2617
  const balance = await agent.getBalances(state, chainId);
2655
- const target = asset.toLowerCase();
2656
2618
  const token = balance.tokens.find(
2657
- (t) => t.chainId === chainId && t.asset.toLowerCase() === target
2619
+ (t) => t.chainId === chainId && isSameAsset(t.asset, asset)
2658
2620
  );
2659
2621
  return !!token && Number(token.amount) > 0;
2660
2622
  } catch {
@@ -1,10 +1,17 @@
1
1
  import {
2
+ ERC20_ALLOWANCE_ABI,
2
3
  OwneyError
3
- } from "./chunk-GMNQBWUB.js";
4
+ } from "./chunk-PWIKIQOX.js";
4
5
 
5
6
  // src/agents/surfliquid/surfliquid.agent.ts
6
7
  import { SurfClient } from "@surf_liquid/core-sdk";
7
- import { formatUnits } from "viem";
8
+ import {
9
+ createPublicClient,
10
+ createWalletClient,
11
+ custom,
12
+ formatUnits
13
+ } from "viem";
14
+ import { base } from "viem/chains";
8
15
 
9
16
  // src/agents/surfliquid/surfliquid.constants.ts
10
17
  var SURFLIQUID_CHAIN_ID = 8453;
@@ -12,6 +19,7 @@ var SURFLIQUID_CHAIN_NAME = "BASE";
12
19
  var SURFLIQUID_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
13
20
  var SURFLIQUID_USDC_DECIMALS = 6;
14
21
  var SURFLIQUID_MIN_DEPOSIT = "0";
22
+ var SURFLIQUID_APPROVAL_TARGET = 100000000000n;
15
23
  var SURFLIQUID_SUPPORTED_ASSETS = [
16
24
  {
17
25
  chainId: SURFLIQUID_CHAIN_ID,
@@ -166,27 +174,29 @@ var VAULT_STATS_QUERY = `
166
174
  }
167
175
  }
168
176
  `;
169
- async function fetchMorphoVaultStats(vaultAddress, chainId) {
177
+ var VAULT_V2_STATS_QUERY = `
178
+ query VaultV2Stats($address: String!, $chainId: Int!) {
179
+ vaultV2ByAddress(address: $address, chainId: $chainId) {
180
+ name
181
+ totalAssetsUsd
182
+ liquidityUsd
183
+ }
184
+ }
185
+ `;
186
+ async function queryMorpho(query, vaultAddress, chainId) {
170
187
  try {
171
188
  const res = await fetch(MORPHO_API_URL, {
172
189
  method: "POST",
173
190
  headers: { "Content-Type": "application/json" },
174
191
  body: JSON.stringify({
175
- query: VAULT_STATS_QUERY,
192
+ query,
176
193
  variables: { address: vaultAddress, chainId }
177
194
  })
178
195
  });
179
196
  if (!res.ok) return null;
180
197
  const json = await res.json();
181
198
  if (json.errors) return null;
182
- const vault = json.data?.vaultByAddress;
183
- const tvlUsd = vault?.state?.totalAssetsUsd;
184
- const liquidityUsd = vault?.liquidity?.usd;
185
- if (typeof tvlUsd !== "number" || typeof liquidityUsd !== "number") {
186
- return null;
187
- }
188
- const name = typeof vault?.name === "string" ? vault.name : null;
189
- return { name, tvlUsd, liquidityUsd };
199
+ return json.data ?? null;
190
200
  } catch (error) {
191
201
  console.warn("surfliquid: Morpho vault stats fetch failed", {
192
202
  vaultAddress,
@@ -196,6 +206,29 @@ async function fetchMorphoVaultStats(vaultAddress, chainId) {
196
206
  return null;
197
207
  }
198
208
  }
209
+ function toStats(name, tvlUsd, liquidityUsd) {
210
+ if (typeof tvlUsd !== "number" || typeof liquidityUsd !== "number") {
211
+ return null;
212
+ }
213
+ return {
214
+ name: typeof name === "string" ? name : null,
215
+ tvlUsd,
216
+ liquidityUsd
217
+ };
218
+ }
219
+ async function fetchMorphoVaultStats(vaultAddress, chainId) {
220
+ const v1 = await queryMorpho(VAULT_STATS_QUERY, vaultAddress, chainId);
221
+ const vault = v1?.vaultByAddress;
222
+ const v1Stats = toStats(
223
+ vault?.name,
224
+ vault?.state?.totalAssetsUsd,
225
+ vault?.liquidity?.usd
226
+ );
227
+ if (v1Stats) return v1Stats;
228
+ const v2 = await queryMorpho(VAULT_V2_STATS_QUERY, vaultAddress, chainId);
229
+ const vaultV2 = v2?.vaultV2ByAddress;
230
+ return toStats(vaultV2?.name, vaultV2?.totalAssetsUsd, vaultV2?.liquidityUsd);
231
+ }
199
232
  async function fetchMorphoStatsByVault(vaultAddresses, chainId) {
200
233
  const unique = [...new Set(vaultAddresses.map((a) => a.toLowerCase()))];
201
234
  const entries = await Promise.all(
@@ -283,6 +316,60 @@ var SurfLiquidAgent = class {
283
316
  const { vaultAddress } = await surf.deployVault();
284
317
  return vaultAddress;
285
318
  }
319
+ /**
320
+ * Grants the user's vault a standing USDC allowance so SurfLiquid's
321
+ * `autoApprove` has nothing to do — see {@link SURFLIQUID_APPROVAL_TARGET}
322
+ * for why one prompt per deposit is worth removing.
323
+ *
324
+ * Fails OPEN on a read error: if the allowance can't be checked we simply
325
+ * return and let SurfLiquid's own per-deposit approve run, because a flaky
326
+ * RPC must never block a deposit. A failed or rejected APPROVE does
327
+ * propagate — the user declined a transaction, and letting SurfLiquid
328
+ * immediately ask again for a smaller one is exactly the double prompt this
329
+ * removes.
330
+ */
331
+ async ensureVaultAllowance(state, vaultAddress, amount) {
332
+ const spender = vaultAddress;
333
+ const transport = custom(state.provider);
334
+ const publicClient = createPublicClient({ chain: base, transport });
335
+ let allowance;
336
+ try {
337
+ allowance = await publicClient.readContract({
338
+ address: SURFLIQUID_USDC_ADDRESS,
339
+ abi: ERC20_ALLOWANCE_ABI,
340
+ functionName: "allowance",
341
+ args: [state.walletAddress, spender]
342
+ });
343
+ } catch (error) {
344
+ console.warn(
345
+ "[owney-sdk] SurfLiquid allowance pre-check failed; deferring to its per-deposit approve:",
346
+ error instanceof Error ? error.message : String(error)
347
+ );
348
+ return;
349
+ }
350
+ if (allowance >= amount) return;
351
+ const target = amount > SURFLIQUID_APPROVAL_TARGET ? amount : SURFLIQUID_APPROVAL_TARGET;
352
+ const wallet = createWalletClient({
353
+ account: state.walletAddress,
354
+ chain: base,
355
+ transport
356
+ });
357
+ const hash = await wallet.writeContract({
358
+ address: SURFLIQUID_USDC_ADDRESS,
359
+ abi: ERC20_ALLOWANCE_ABI,
360
+ functionName: "approve",
361
+ args: [spender, target],
362
+ account: state.walletAddress,
363
+ chain: base
364
+ });
365
+ const receipt = await publicClient.waitForTransactionReceipt({
366
+ hash,
367
+ confirmations: 1
368
+ });
369
+ if (receipt.status !== "success") {
370
+ throw new Error(`SurfLiquid USDC approval reverted (tx ${hash})`);
371
+ }
372
+ }
286
373
  // --- IAgent: lifecycle ---
287
374
  async disconnect() {
288
375
  if (this.surf) {
@@ -301,6 +388,7 @@ var SurfLiquidAgent = class {
301
388
  surf,
302
389
  state.walletAddress
303
390
  );
391
+ await this.ensureVaultAllowance(state, smartWallet, BigInt(amount));
304
392
  const tx = await surf.deposit({
305
393
  asset: SURFLIQUID_USDC_ADDRESS,
306
394
  amount: human
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.6.9-beta.6",
3
+ "version": "0.6.9-beta.8",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -1,55 +0,0 @@
1
- // src/errors.ts
2
- var OwneyError = class extends Error {
3
- code;
4
- details;
5
- agentId;
6
- constructor(code, message, details, agentId) {
7
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
8
- super(`${prefix} ${message}`);
9
- this.name = "OwneyError";
10
- this.code = code;
11
- this.details = details;
12
- this.agentId = agentId;
13
- }
14
- };
15
- var AgentNotFoundError = class extends OwneyError {
16
- constructor(agentId, available) {
17
- super(
18
- "AGENT_NOT_FOUND",
19
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
20
- { agentId, available },
21
- agentId
22
- );
23
- this.name = "AgentNotFoundError";
24
- }
25
- };
26
- var NotConnectedError = class extends OwneyError {
27
- constructor() {
28
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
29
- this.name = "NotConnectedError";
30
- }
31
- };
32
- var AgentChainIncompatibleError = class extends OwneyError {
33
- incompatibleAgents;
34
- connectedChainId;
35
- constructor(incompatibleAgents, connectedChainId) {
36
- const details = incompatibleAgents.map(
37
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
38
- ).join("; ");
39
- super(
40
- "AGENT_CHAIN_INCOMPATIBLE",
41
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
42
- { incompatibleAgents, connectedChainId }
43
- );
44
- this.name = "AgentChainIncompatibleError";
45
- this.incompatibleAgents = incompatibleAgents;
46
- this.connectedChainId = connectedChainId;
47
- }
48
- };
49
-
50
- export {
51
- OwneyError,
52
- AgentNotFoundError,
53
- NotConnectedError,
54
- AgentChainIncompatibleError
55
- };