@owney/sdk 0.6.7-beta.1 → 0.6.7-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -28,7 +28,7 @@ type OwneySupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];
28
28
  type OwneySupportedChains = (typeof SUPPORTED_CHAINS)[number];
29
29
  type OwneySupportedTokens = (typeof SUPPORTED_TOKENS)[number];
30
30
 
31
- type AgentId = "zyfai" | "sail" | "surfliquid";
31
+ type AgentId = "zyfai" | "sail";
32
32
  type Asset = string;
33
33
  type AgentSupportedAsset = {
34
34
  readonly symbol: string;
@@ -101,12 +101,6 @@ interface OwneyDepositResult {
101
101
  }
102
102
  interface OwneyMultiDepositResult {
103
103
  agentResults: Record<string, OwneyDepositResult>;
104
- /**
105
- * Per-agent failure messages for agents that errored during a diversified
106
- * deposit. Present only when at least one (but not all) agents failed —
107
- * the deposit is partial, not total. Omitted when every agent succeeded.
108
- */
109
- agentErrors?: Record<string, string>;
110
104
  }
111
105
  interface AgentWithdrawResult {
112
106
  txHash?: string;
@@ -428,17 +422,6 @@ declare class OwneySDK {
428
422
  private hasExistingBalance;
429
423
  private validateAssetSupport;
430
424
  private getEligibleAgents;
431
- /**
432
- * Agent ids the routing API provisioned for this org that support the given
433
- * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
434
- * surfliquid first). Returns `[]` when the org has no compatible agent — never
435
- * throws on an empty org. Loads agent keys on first call (apiKey only, no
436
- * wallet), so the UI can resolve which agent to use before the user connects.
437
- *
438
- * This is the source of truth for agent availability: an agent appears here
439
- * iff the routing API returned its key. No per-app feature flags.
440
- */
441
- getEligibleAgentIds(chainId: number, asset: string): Promise<AgentId[]>;
442
425
  /**
443
426
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
444
427
  * Validates that the asset is supported by the target agent(s) on the active chain.
@@ -534,7 +517,7 @@ declare class OwneySDK {
534
517
  getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
535
518
  }
536
519
 
537
- type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_ALL_FAILED" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
520
+ type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
538
521
  declare class OwneyError extends Error {
539
522
  readonly code: OwneyErrorCode;
540
523
  readonly details?: Record<string, unknown>;
package/dist/index.d.ts CHANGED
@@ -28,7 +28,7 @@ type OwneySupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];
28
28
  type OwneySupportedChains = (typeof SUPPORTED_CHAINS)[number];
29
29
  type OwneySupportedTokens = (typeof SUPPORTED_TOKENS)[number];
30
30
 
31
- type AgentId = "zyfai" | "sail" | "surfliquid";
31
+ type AgentId = "zyfai" | "sail";
32
32
  type Asset = string;
33
33
  type AgentSupportedAsset = {
34
34
  readonly symbol: string;
@@ -101,12 +101,6 @@ interface OwneyDepositResult {
101
101
  }
102
102
  interface OwneyMultiDepositResult {
103
103
  agentResults: Record<string, OwneyDepositResult>;
104
- /**
105
- * Per-agent failure messages for agents that errored during a diversified
106
- * deposit. Present only when at least one (but not all) agents failed —
107
- * the deposit is partial, not total. Omitted when every agent succeeded.
108
- */
109
- agentErrors?: Record<string, string>;
110
104
  }
111
105
  interface AgentWithdrawResult {
112
106
  txHash?: string;
@@ -428,17 +422,6 @@ declare class OwneySDK {
428
422
  private hasExistingBalance;
429
423
  private validateAssetSupport;
430
424
  private getEligibleAgents;
431
- /**
432
- * Agent ids the routing API provisioned for this org that support the given
433
- * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
434
- * surfliquid first). Returns `[]` when the org has no compatible agent — never
435
- * throws on an empty org. Loads agent keys on first call (apiKey only, no
436
- * wallet), so the UI can resolve which agent to use before the user connects.
437
- *
438
- * This is the source of truth for agent availability: an agent appears here
439
- * iff the routing API returned its key. No per-app feature flags.
440
- */
441
- getEligibleAgentIds(chainId: number, asset: string): Promise<AgentId[]>;
442
425
  /**
443
426
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
444
427
  * Validates that the asset is supported by the target agent(s) on the active chain.
@@ -534,7 +517,7 @@ declare class OwneySDK {
534
517
  getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
535
518
  }
536
519
 
537
- type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_ALL_FAILED" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
520
+ type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
538
521
  declare class OwneyError extends Error {
539
522
  readonly code: OwneyErrorCode;
540
523
  readonly details?: Record<string, unknown>;
package/dist/index.js CHANGED
@@ -1,10 +1,3 @@
1
- import {
2
- AgentChainIncompatibleError,
3
- AgentNotFoundError,
4
- NotConnectedError,
5
- OwneyError
6
- } from "./chunk-GMNQBWUB.js";
7
-
8
1
  // src/agents/zyfai/zyfai.agent.ts
9
2
  import { ZyfaiSDK } from "@zyfai/sdk";
10
3
  import { createPublicClient, http } from "viem";
@@ -63,6 +56,55 @@ var SupportedAssets = [
63
56
  }
64
57
  ];
65
58
 
59
+ // src/errors.ts
60
+ var OwneyError = class extends Error {
61
+ code;
62
+ details;
63
+ agentId;
64
+ constructor(code, message, details, agentId) {
65
+ const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
66
+ super(`${prefix} ${message}`);
67
+ this.name = "OwneyError";
68
+ this.code = code;
69
+ this.details = details;
70
+ this.agentId = agentId;
71
+ }
72
+ };
73
+ var AgentNotFoundError = class extends OwneyError {
74
+ constructor(agentId, available) {
75
+ super(
76
+ "AGENT_NOT_FOUND",
77
+ `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
78
+ { agentId, available },
79
+ agentId
80
+ );
81
+ this.name = "AgentNotFoundError";
82
+ }
83
+ };
84
+ var NotConnectedError = class extends OwneyError {
85
+ constructor() {
86
+ super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
87
+ this.name = "NotConnectedError";
88
+ }
89
+ };
90
+ var AgentChainIncompatibleError = class extends OwneyError {
91
+ incompatibleAgents;
92
+ connectedChainId;
93
+ constructor(incompatibleAgents, connectedChainId) {
94
+ const details = incompatibleAgents.map(
95
+ ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
96
+ ).join("; ");
97
+ super(
98
+ "AGENT_CHAIN_INCOMPATIBLE",
99
+ `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
100
+ { incompatibleAgents, connectedChainId }
101
+ );
102
+ this.name = "AgentChainIncompatibleError";
103
+ this.incompatibleAgents = incompatibleAgents;
104
+ this.connectedChainId = connectedChainId;
105
+ }
106
+ };
107
+
66
108
  // src/lib/utils.ts
67
109
  var isValidChainId = (chainId) => {
68
110
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
@@ -137,46 +179,46 @@ function resolveChainId(chain) {
137
179
  function mapBalances(raw, _chainId, smartWallet) {
138
180
  const portfolio = raw.portfolio;
139
181
  const portfolioByChain = portfolio.portfolioByChain ?? {};
140
- const rawPositions = portfolio.positions ?? [];
141
- const detailByKey = /* @__PURE__ */ new Map();
142
- for (const p of rawPositions) {
143
- const cid = resolveChainId(p.chain ?? "");
144
- const symbol = (p.token_symbol ?? "").toUpperCase();
145
- if (Number.isFinite(cid) && symbol) detailByKey.set(`${cid}:${symbol}`, p);
146
- }
147
182
  let totalBalance = 0;
148
183
  const tokens = [];
149
- const positions = [];
150
184
  for (const [chainIdKey, tokensBySymbol] of Object.entries(portfolioByChain)) {
151
185
  const positionChainId = Number(chainIdKey);
152
- const chainName = CHAIN_ID_TO_NAME[positionChainId] ?? "BASE";
153
186
  for (const [symbol, { balance, decimals }] of Object.entries(
154
187
  tokensBySymbol ?? {}
155
188
  )) {
156
- const amount = hexToDecimal(balance || "0", tokenDecimals(symbol, decimals));
189
+ const amount = hexToDecimal(balance || "0", decimals);
157
190
  totalBalance += amount;
158
191
  tokens.push({
159
- chain: chainName,
192
+ chain: CHAIN_ID_TO_NAME[positionChainId] ?? "BASE",
160
193
  chainId: positionChainId,
161
194
  asset: symbol,
162
195
  amount: String(amount)
163
196
  });
164
- const detail = detailByKey.get(`${positionChainId}:${symbol.toUpperCase()}`);
165
- positions.push({
166
- chain: chainName,
167
- protocol: detail?.protocol_name ?? detail?.protocol_id ?? "",
168
- protocolId: detail?.protocol_id,
169
- pool: detail?.pool,
170
- asset: symbol,
171
- amount: String(amount),
172
- apy: detail?.pool_apy,
173
- tvl: detail?.pool_tvl,
174
- // PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
175
- // structural read keeps it undefined today and auto-populates later.
176
- liquidity: detail?.liquidity
177
- });
178
197
  }
179
198
  }
199
+ const positions = (portfolio.positions ?? []).map((p) => ({
200
+ chain: p.chain ?? "",
201
+ protocol: p.protocol_name ?? p.protocol_id ?? "",
202
+ protocolId: p.protocol_id,
203
+ pool: p.pool,
204
+ asset: p.token_symbol ?? "",
205
+ // Position amount is hex-encoded base units (like the token balances
206
+ // above). `PositionSlot` doesn't type a `decimals` field, but runtime
207
+ // getBalances payloads often carry one (e.g. 18 for WETH) — prefer that
208
+ // when present, otherwise fall back to the per-symbol lookup so
209
+ // non-6-decimal assets like WETH don't render 1e12 too large.
210
+ amount: String(
211
+ hexToDecimal(
212
+ p.amount || "0",
213
+ tokenDecimals(p.token_symbol, p.decimals)
214
+ )
215
+ ),
216
+ apy: p.pool_apy,
217
+ tvl: p.pool_tvl,
218
+ // PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
219
+ // structural read keeps it undefined today and auto-populates later.
220
+ liquidity: p.liquidity
221
+ }));
180
222
  return {
181
223
  smartWallet,
182
224
  totalBalance: String(totalBalance),
@@ -461,7 +503,8 @@ var storage = () => {
461
503
  return null;
462
504
  }
463
505
  };
464
- var buildKey = (address, chainId) => `${KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
506
+ var buildKey = (address) => `${KEY_PREFIX}:${address.toLowerCase()}`;
507
+ var legacyKeyPrefix = (address) => `${KEY_PREFIX}:${address.toLowerCase()}:`;
465
508
  var isJwtExpired = (token) => {
466
509
  const parts = token.split(".");
467
510
  if (parts.length !== 3) return false;
@@ -478,9 +521,37 @@ var isJwtExpired = (token) => {
478
521
  };
479
522
  var memorySessions = /* @__PURE__ */ new Map();
480
523
  var isFreshSession = (session) => !!session && !!session.token && !isJwtExpired(session.token);
481
- var readSession = (address, chainId) => {
524
+ var readLegacySession = (store, address) => {
525
+ if (!store) return null;
526
+ const prefix = legacyKeyPrefix(address);
527
+ const legacyKeys = [];
528
+ try {
529
+ for (let i = 0; i < store.length; i++) {
530
+ const key = store.key(i);
531
+ if (key?.startsWith(prefix)) legacyKeys.push(key);
532
+ }
533
+ } catch {
534
+ return null;
535
+ }
536
+ let adopted = null;
537
+ for (const key of legacyKeys) {
538
+ if (!adopted) {
539
+ try {
540
+ const parsed = JSON.parse(store.getItem(key) ?? "");
541
+ if (isFreshSession(parsed)) adopted = parsed;
542
+ } catch {
543
+ }
544
+ }
545
+ try {
546
+ store.removeItem(key);
547
+ } catch {
548
+ }
549
+ }
550
+ return adopted;
551
+ };
552
+ var readSession = (address, _chainId) => {
482
553
  if (typeof window === "undefined") return null;
483
- const key = buildKey(address, chainId);
554
+ const key = buildKey(address);
484
555
  const store = storage();
485
556
  let raw = null;
486
557
  try {
@@ -501,14 +572,19 @@ var readSession = (address, chainId) => {
501
572
  }
502
573
  return null;
503
574
  }
575
+ const legacy = readLegacySession(store, address);
576
+ if (legacy) {
577
+ writeSession(address, _chainId, legacy);
578
+ return legacy;
579
+ }
504
580
  const cached = memorySessions.get(key);
505
581
  if (isFreshSession(cached)) return cached;
506
582
  if (cached) memorySessions.delete(key);
507
583
  return null;
508
584
  };
509
- var writeSession = (address, chainId, session) => {
585
+ var writeSession = (address, _chainId, session) => {
510
586
  if (typeof window === "undefined") return;
511
- const key = buildKey(address, chainId);
587
+ const key = buildKey(address);
512
588
  memorySessions.set(key, session);
513
589
  const store = storage();
514
590
  try {
@@ -516,14 +592,15 @@ var writeSession = (address, chainId, session) => {
516
592
  } catch {
517
593
  }
518
594
  };
519
- var clearSession = (address, chainId) => {
520
- const key = buildKey(address, chainId);
595
+ var clearSession = (address, _chainId) => {
596
+ const key = buildKey(address);
521
597
  memorySessions.delete(key);
522
598
  const store = storage();
523
599
  try {
524
600
  store?.removeItem(key);
525
601
  } catch {
526
602
  }
603
+ readLegacySession(store, address);
527
604
  };
528
605
 
529
606
  // src/agents/zyfai/autoSelect.ts
@@ -1551,7 +1628,6 @@ var VIEM_CHAIN2 = {
1551
1628
  42161: arbitrum2,
1552
1629
  1: mainnet2
1553
1630
  };
1554
- var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai", "sail"];
1555
1631
  var SPONSORED_WETH_BY_CHAIN = {
1556
1632
  8453: "0x4200000000000000000000000000000000000006",
1557
1633
  42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -1739,8 +1815,8 @@ var OwneySDK = class {
1739
1815
  this.initializingAgentsPromise = (async () => {
1740
1816
  const agentKeys = await fetchAgentKeys(this.apiKey);
1741
1817
  this.disabledAgents.clear();
1742
- for (const { key, agent_type, project_name, is_enabled } of agentKeys) {
1743
- const agent = await this.createAgent(agent_type, key, project_name);
1818
+ for (const { key, agent_type, is_enabled } of agentKeys) {
1819
+ const agent = this.createAgent(agent_type, key);
1744
1820
  if (!agent) continue;
1745
1821
  this.agents.set(agent_type, agent);
1746
1822
  if (is_enabled === false) {
@@ -1761,15 +1837,10 @@ var OwneySDK = class {
1761
1837
  this.initializingAgentsPromise = null;
1762
1838
  }
1763
1839
  }
1764
- async createAgent(agentId, key, projectName) {
1840
+ createAgent(agentId, key) {
1765
1841
  if (agentId === "zyfai") {
1766
1842
  return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1767
1843
  }
1768
- if (agentId === "surfliquid") {
1769
- if (!projectName) return null;
1770
- const { SurfLiquidAgent } = await import("./surfliquid.agent-OMOYXWLP.js");
1771
- return new SurfLiquidAgent({ projectName, appId: key });
1772
- }
1773
1844
  return null;
1774
1845
  }
1775
1846
  // --- Account lifecycle ---
@@ -1922,30 +1993,18 @@ var OwneySDK = class {
1922
1993
  );
1923
1994
  }
1924
1995
  const agentResults = {};
1925
- const agentErrors = {};
1926
1996
  for (const { agent, amount: agentAmount } of agentAmounts) {
1927
- try {
1928
- agentResults[agent.id] = await this.depositWithFallback(
1929
- agent,
1930
- state,
1931
- chainId,
1932
- agentAmount,
1933
- asset,
1934
- effectiveCallback,
1935
- depositCallback
1936
- );
1937
- } catch (error) {
1938
- agentErrors[agent.id] = error instanceof Error ? error.message : String(error);
1939
- }
1940
- }
1941
- if (Object.keys(agentResults).length === 0) {
1942
- throw new OwneyError(
1943
- "DEPOSIT_ALL_FAILED",
1944
- `All ${agentAmounts.length} agent deposit(s) failed.`,
1945
- { agentErrors }
1997
+ agentResults[agent.id] = await this.depositWithFallback(
1998
+ agent,
1999
+ state,
2000
+ chainId,
2001
+ agentAmount,
2002
+ asset,
2003
+ effectiveCallback,
2004
+ depositCallback
1946
2005
  );
1947
2006
  }
1948
- return Object.keys(agentErrors).length > 0 ? { agentResults, agentErrors } : { agentResults };
2007
+ return { agentResults };
1949
2008
  }
1950
2009
  /**
1951
2010
  * Invokes `agent.deposit` with the resolved sponsored callback, composing
@@ -2102,34 +2161,6 @@ var OwneySDK = class {
2102
2161
  }
2103
2162
  return eligible;
2104
2163
  }
2105
- /**
2106
- * Agent ids the routing API provisioned for this org that support the given
2107
- * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
2108
- * surfliquid first). Returns `[]` when the org has no compatible agent — never
2109
- * throws on an empty org. Loads agent keys on first call (apiKey only, no
2110
- * wallet), so the UI can resolve which agent to use before the user connects.
2111
- *
2112
- * This is the source of truth for agent availability: an agent appears here
2113
- * iff the routing API returned its key. No per-app feature flags.
2114
- */
2115
- async getEligibleAgentIds(chainId, asset) {
2116
- try {
2117
- await this.ensureAgentsInitialized();
2118
- } catch (error) {
2119
- if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
2120
- return [];
2121
- }
2122
- throw error;
2123
- }
2124
- return [...this.agents.values()].filter((agent) => {
2125
- const chainAssets = agent.supportedAssets.find(
2126
- (sa) => sa.chainId === chainId
2127
- );
2128
- return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
2129
- }).map((agent) => agent.id).sort(
2130
- (a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
2131
- );
2132
- }
2133
2164
  // --- Fund operations ---
2134
2165
  /**
2135
2166
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
@@ -2165,17 +2196,9 @@ var OwneySDK = class {
2165
2196
  }
2166
2197
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
2167
2198
  if (!amount) {
2168
- const aggregated2 = await this.getBalances();
2169
- const funded = projectAgentBalancesForAsset(
2170
- eligibleAgents,
2171
- aggregated2.agentBalances,
2172
- chainId,
2173
- asset,
2174
- assetInfo.decimals
2175
- ).filter((b) => b.balance > 0n);
2176
2199
  const results2 = {};
2177
2200
  const agentErrors2 = {};
2178
- for (const { agent } of funded) {
2201
+ for (const agent of eligibleAgents) {
2179
2202
  try {
2180
2203
  results2[agent.id] = await agent.withdraw(state, chainId, token);
2181
2204
  } catch (err) {
@@ -2192,10 +2215,9 @@ var OwneySDK = class {
2192
2215
  { asset, agentErrors: agentErrors2 }
2193
2216
  );
2194
2217
  }
2195
- const totalWithdrawn = funded.filter(({ agent }) => results2[agent.id] !== void 0).reduce((sum, { balance }) => sum + balance, 0n);
2196
2218
  return {
2197
2219
  agentResult: results2,
2198
- totalWithdrawn: totalWithdrawn.toString()
2220
+ totalWithdrawn: sumWithdrawnAmount(results2).toString()
2199
2221
  };
2200
2222
  }
2201
2223
  const requested = BigInt(amount);
@@ -2703,11 +2725,39 @@ var storage2 = () => {
2703
2725
  return null;
2704
2726
  }
2705
2727
  };
2706
- var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2728
+ var buildKey2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}`;
2729
+ var legacyKeyPrefix2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}:`;
2707
2730
  var memorySiwxSessions = /* @__PURE__ */ new Map();
2731
+ var readLegacySiwxSession = (store, address) => {
2732
+ if (!store) return null;
2733
+ const prefix = legacyKeyPrefix2(address);
2734
+ const legacyKeys = [];
2735
+ try {
2736
+ for (let i = 0; i < store.length; i++) {
2737
+ const key = store.key(i);
2738
+ if (key?.startsWith(prefix)) legacyKeys.push(key);
2739
+ }
2740
+ } catch {
2741
+ return null;
2742
+ }
2743
+ let adopted = null;
2744
+ for (const key of legacyKeys) {
2745
+ if (!adopted) {
2746
+ try {
2747
+ adopted = JSON.parse(store.getItem(key) ?? "");
2748
+ } catch {
2749
+ }
2750
+ }
2751
+ try {
2752
+ store.removeItem(key);
2753
+ } catch {
2754
+ }
2755
+ }
2756
+ return adopted;
2757
+ };
2708
2758
  var readSiwxSession = (address, chainId) => {
2709
2759
  if (typeof window === "undefined") return null;
2710
- const key = buildKey2(address, chainId);
2760
+ const key = buildKey2(address);
2711
2761
  const store = storage2();
2712
2762
  let raw = null;
2713
2763
  try {
@@ -2727,11 +2777,16 @@ var readSiwxSession = (address, chainId) => {
2727
2777
  return null;
2728
2778
  }
2729
2779
  }
2780
+ const legacy = readLegacySiwxSession(store, address);
2781
+ if (legacy) {
2782
+ writeSiwxSession(address, chainId, legacy);
2783
+ return legacy;
2784
+ }
2730
2785
  return memorySiwxSessions.get(key) ?? null;
2731
2786
  };
2732
- var writeSiwxSession = (address, chainId, session) => {
2787
+ var writeSiwxSession = (address, _chainId, session) => {
2733
2788
  if (typeof window === "undefined") return;
2734
- const key = buildKey2(address, chainId);
2789
+ const key = buildKey2(address);
2735
2790
  memorySiwxSessions.set(key, session);
2736
2791
  const store = storage2();
2737
2792
  try {
@@ -2739,14 +2794,15 @@ var writeSiwxSession = (address, chainId, session) => {
2739
2794
  } catch {
2740
2795
  }
2741
2796
  };
2742
- var clearSiwxSession = (address, chainId) => {
2743
- const key = buildKey2(address, chainId);
2797
+ var clearSiwxSession = (address, _chainId) => {
2798
+ const key = buildKey2(address);
2744
2799
  memorySiwxSessions.delete(key);
2745
2800
  const store = storage2();
2746
2801
  try {
2747
2802
  store?.removeItem(key);
2748
2803
  } catch {
2749
2804
  }
2805
+ readLegacySiwxSession(store, address);
2750
2806
  };
2751
2807
 
2752
2808
  // src/agents/zyfai/zyfai.siwx.ts
@@ -2810,9 +2866,12 @@ function buildSIWXConfig(deps) {
2810
2866
  }
2811
2867
  if (!stored) return [];
2812
2868
  const session = {
2813
- // `stored.data.chainId` is a plain string in the cache (kept AppKit-free);
2814
- // it always holds a valid CaipNetworkId here, so narrow at the boundary.
2815
- data: stored.data,
2869
+ // `stored.data` is kept AppKit-free in the cache, so narrow at the
2870
+ // boundary. Echo the REQUESTED chain rather than the one originally
2871
+ // signed: the Zyfai JWT is account-scoped (no chain claim), so one
2872
+ // signature is valid for every chain, and AppKit would otherwise treat
2873
+ // the session as not covering the active network and re-prompt.
2874
+ data: { ...stored.data, chainId },
2816
2875
  message: stored.message,
2817
2876
  signature: stored.signature
2818
2877
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.6.7-beta.1",
3
+ "version": "0.6.7-beta.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -23,9 +23,7 @@
23
23
  "test:watch": "vitest"
24
24
  },
25
25
  "dependencies": {
26
- "@surf_liquid/core-sdk": "^0.4.0",
27
26
  "@zyfai/sdk": "0.2.40",
28
- "ethers": "^6.17.0",
29
27
  "siwe": "^3.0.0",
30
28
  "viem": "^2.48.1"
31
29
  },
@@ -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
- };