@owney/sdk 0.6.9-beta.5 → 0.6.9-beta.7

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
@@ -21,6 +21,16 @@ interface OwneySDKConfig {
21
21
  * `createOwneySIWX` for apps that don't use the AppKit SIWX modal.
22
22
  */
23
23
  referralSource?: string;
24
+ /**
25
+ * Optional override for the SurfLiquid API base URL (defaults to the
26
+ * SurfLiquid SDK's production URL). SurfLiquid auth is an httpOnly
27
+ * SameSite=None cookie set by api.surfliquid.com — a THIRD-PARTY cookie from
28
+ * the embedding app's origin, which WebKit (all iOS browsers) discards, so
29
+ * every authenticated SurfLiquid call 401s on iOS. Point this at a
30
+ * same-origin reverse proxy (e.g. "/api/surf") so the session cookie becomes
31
+ * first-party. Relative paths resolve against the page origin.
32
+ */
33
+ surfliquidApiBaseUrl?: string;
24
34
  /**
25
35
  * Turn on the SDK's debug logging (default false). Traces the decisions that
26
36
  * are otherwise invisible — notably how the organization's agent policy is
@@ -43,7 +53,7 @@ type OwneySupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];
43
53
  type OwneySupportedChains = (typeof SUPPORTED_CHAINS)[number];
44
54
  type OwneySupportedTokens = (typeof SUPPORTED_TOKENS)[number];
45
55
 
46
- type AgentId = "zyfai" | "sail";
56
+ type AgentId = "zyfai" | "sail" | "surfliquid";
47
57
  type Asset = string;
48
58
  type AgentSupportedAsset = {
49
59
  readonly symbol: string;
@@ -150,6 +160,12 @@ interface OwneyDepositResult {
150
160
  }
151
161
  interface OwneyMultiDepositResult {
152
162
  agentResults: Record<string, OwneyDepositResult>;
163
+ /**
164
+ * Per-agent failure messages for agents that errored during a diversified
165
+ * deposit. Present only when at least one (but not all) agents failed —
166
+ * the deposit is partial, not total. Omitted when every agent succeeded.
167
+ */
168
+ agentErrors?: Record<string, string>;
153
169
  }
154
170
  interface AgentWithdrawResult {
155
171
  txHash?: string;
@@ -391,6 +407,7 @@ declare class OwneySDK {
391
407
  private zyfaiRpcUrls?;
392
408
  private routingApiBaseUrl?;
393
409
  private referralSource?;
410
+ private surfliquidApiBaseUrl?;
394
411
  private cachedSponsoredCallback;
395
412
  private cachedWethSponsoredCallback;
396
413
  private initializingAgentsPromise;
@@ -514,6 +531,17 @@ declare class OwneySDK {
514
531
  private hasExistingBalance;
515
532
  private validateAssetSupport;
516
533
  private getEligibleAgents;
534
+ /**
535
+ * Agent ids the routing API provisioned for this org that support the given
536
+ * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
537
+ * surfliquid first). Returns `[]` when the org has no compatible agent — never
538
+ * throws on an empty org. Loads agent keys on first call (apiKey only, no
539
+ * wallet), so the UI can resolve which agent to use before the user connects.
540
+ *
541
+ * This is the source of truth for agent availability: an agent appears here
542
+ * iff the routing API returned its key. No per-app feature flags.
543
+ */
544
+ getEligibleAgentIds(chainId: number, asset: string): Promise<AgentId[]>;
517
545
  /**
518
546
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
519
547
  * Validates that the asset is supported by the target agent(s) on the active chain.
@@ -609,7 +637,7 @@ declare class OwneySDK {
609
637
  getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
610
638
  }
611
639
 
612
- 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_INSUFFICIENT_BALANCE" | "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";
640
+ 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" | "DEPOSIT_INSUFFICIENT_BALANCE" | "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";
613
641
  declare class OwneyError extends Error {
614
642
  readonly code: OwneyErrorCode;
615
643
  readonly details?: Record<string, unknown>;
package/dist/index.d.ts CHANGED
@@ -21,6 +21,16 @@ interface OwneySDKConfig {
21
21
  * `createOwneySIWX` for apps that don't use the AppKit SIWX modal.
22
22
  */
23
23
  referralSource?: string;
24
+ /**
25
+ * Optional override for the SurfLiquid API base URL (defaults to the
26
+ * SurfLiquid SDK's production URL). SurfLiquid auth is an httpOnly
27
+ * SameSite=None cookie set by api.surfliquid.com — a THIRD-PARTY cookie from
28
+ * the embedding app's origin, which WebKit (all iOS browsers) discards, so
29
+ * every authenticated SurfLiquid call 401s on iOS. Point this at a
30
+ * same-origin reverse proxy (e.g. "/api/surf") so the session cookie becomes
31
+ * first-party. Relative paths resolve against the page origin.
32
+ */
33
+ surfliquidApiBaseUrl?: string;
24
34
  /**
25
35
  * Turn on the SDK's debug logging (default false). Traces the decisions that
26
36
  * are otherwise invisible — notably how the organization's agent policy is
@@ -43,7 +53,7 @@ type OwneySupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];
43
53
  type OwneySupportedChains = (typeof SUPPORTED_CHAINS)[number];
44
54
  type OwneySupportedTokens = (typeof SUPPORTED_TOKENS)[number];
45
55
 
46
- type AgentId = "zyfai" | "sail";
56
+ type AgentId = "zyfai" | "sail" | "surfliquid";
47
57
  type Asset = string;
48
58
  type AgentSupportedAsset = {
49
59
  readonly symbol: string;
@@ -150,6 +160,12 @@ interface OwneyDepositResult {
150
160
  }
151
161
  interface OwneyMultiDepositResult {
152
162
  agentResults: Record<string, OwneyDepositResult>;
163
+ /**
164
+ * Per-agent failure messages for agents that errored during a diversified
165
+ * deposit. Present only when at least one (but not all) agents failed —
166
+ * the deposit is partial, not total. Omitted when every agent succeeded.
167
+ */
168
+ agentErrors?: Record<string, string>;
153
169
  }
154
170
  interface AgentWithdrawResult {
155
171
  txHash?: string;
@@ -391,6 +407,7 @@ declare class OwneySDK {
391
407
  private zyfaiRpcUrls?;
392
408
  private routingApiBaseUrl?;
393
409
  private referralSource?;
410
+ private surfliquidApiBaseUrl?;
394
411
  private cachedSponsoredCallback;
395
412
  private cachedWethSponsoredCallback;
396
413
  private initializingAgentsPromise;
@@ -514,6 +531,17 @@ declare class OwneySDK {
514
531
  private hasExistingBalance;
515
532
  private validateAssetSupport;
516
533
  private getEligibleAgents;
534
+ /**
535
+ * Agent ids the routing API provisioned for this org that support the given
536
+ * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
537
+ * surfliquid first). Returns `[]` when the org has no compatible agent — never
538
+ * throws on an empty org. Loads agent keys on first call (apiKey only, no
539
+ * wallet), so the UI can resolve which agent to use before the user connects.
540
+ *
541
+ * This is the source of truth for agent availability: an agent appears here
542
+ * iff the routing API returned its key. No per-app feature flags.
543
+ */
544
+ getEligibleAgentIds(chainId: number, asset: string): Promise<AgentId[]>;
517
545
  /**
518
546
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
519
547
  * Validates that the asset is supported by the target agent(s) on the active chain.
@@ -609,7 +637,7 @@ declare class OwneySDK {
609
637
  getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
610
638
  }
611
639
 
612
- 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_INSUFFICIENT_BALANCE" | "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";
640
+ 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" | "DEPOSIT_INSUFFICIENT_BALANCE" | "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";
613
641
  declare class OwneyError extends Error {
614
642
  readonly code: OwneyErrorCode;
615
643
  readonly details?: Record<string, unknown>;
package/dist/index.js CHANGED
@@ -1,3 +1,17 @@
1
+ import {
2
+ AgentChainIncompatibleError,
3
+ AgentNotFoundError,
4
+ ERC20_ALLOWANCE_ABI,
5
+ MAX_UINT256,
6
+ NotConnectedError,
7
+ OwneyError,
8
+ PERMIT2_ADDRESS,
9
+ buildPermitTransferFromTypedData,
10
+ randomPermit2Nonce,
11
+ readErc20Balance,
12
+ readPermit2Allowance
13
+ } from "./chunk-PWIKIQOX.js";
14
+
1
15
  // src/agents/zyfai/zyfai.agent.ts
2
16
  import { ZyfaiSDK } from "@zyfai/sdk";
3
17
  import { createPublicClient, http } from "viem";
@@ -56,55 +70,6 @@ var SupportedAssets = [
56
70
  }
57
71
  ];
58
72
 
59
- // src/errors.ts
60
- var OwneyError = class extends Error {
61
- code;
62
- details;
63
- agentId;
64
- constructor(code, message, details, agentId) {
65
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
66
- super(`${prefix} ${message}`);
67
- this.name = "OwneyError";
68
- this.code = code;
69
- this.details = details;
70
- this.agentId = agentId;
71
- }
72
- };
73
- var AgentNotFoundError = class extends OwneyError {
74
- constructor(agentId, available) {
75
- super(
76
- "AGENT_NOT_FOUND",
77
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
78
- { agentId, available },
79
- agentId
80
- );
81
- this.name = "AgentNotFoundError";
82
- }
83
- };
84
- var NotConnectedError = class extends OwneyError {
85
- constructor() {
86
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
87
- this.name = "NotConnectedError";
88
- }
89
- };
90
- var AgentChainIncompatibleError = class extends OwneyError {
91
- incompatibleAgents;
92
- connectedChainId;
93
- constructor(incompatibleAgents, connectedChainId) {
94
- const details = incompatibleAgents.map(
95
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
96
- ).join("; ");
97
- super(
98
- "AGENT_CHAIN_INCOMPATIBLE",
99
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
100
- { incompatibleAgents, connectedChainId }
101
- );
102
- this.name = "AgentChainIncompatibleError";
103
- this.incompatibleAgents = incompatibleAgents;
104
- this.connectedChainId = connectedChainId;
105
- }
106
- };
107
-
108
73
  // src/lib/utils.ts
109
74
  var isValidChainId = (chainId) => {
110
75
  if (!SUPPORTED_CHAIN_IDS.includes(chainId)) {
@@ -179,46 +144,46 @@ function resolveChainId(chain) {
179
144
  function mapBalances(raw, _chainId, smartWallet) {
180
145
  const portfolio = raw.portfolio;
181
146
  const portfolioByChain = portfolio.portfolioByChain ?? {};
147
+ const rawPositions = portfolio.positions ?? [];
148
+ const detailByKey = /* @__PURE__ */ new Map();
149
+ for (const p of rawPositions) {
150
+ const cid = resolveChainId(p.chain ?? "");
151
+ const symbol = (p.token_symbol ?? "").toUpperCase();
152
+ if (Number.isFinite(cid) && symbol) detailByKey.set(`${cid}:${symbol}`, p);
153
+ }
182
154
  let totalBalance = 0;
183
155
  const tokens = [];
156
+ const positions = [];
184
157
  for (const [chainIdKey, tokensBySymbol] of Object.entries(portfolioByChain)) {
185
158
  const positionChainId = Number(chainIdKey);
159
+ const chainName = CHAIN_ID_TO_NAME[positionChainId] ?? "BASE";
186
160
  for (const [symbol, { balance, decimals }] of Object.entries(
187
161
  tokensBySymbol ?? {}
188
162
  )) {
189
- const amount = hexToDecimal(balance || "0", decimals);
163
+ const amount = hexToDecimal(balance || "0", tokenDecimals(symbol, decimals));
190
164
  totalBalance += amount;
191
165
  tokens.push({
192
- chain: CHAIN_ID_TO_NAME[positionChainId] ?? "BASE",
166
+ chain: chainName,
193
167
  chainId: positionChainId,
194
168
  asset: symbol,
195
169
  amount: String(amount)
196
170
  });
171
+ const detail = detailByKey.get(`${positionChainId}:${symbol.toUpperCase()}`);
172
+ positions.push({
173
+ chain: chainName,
174
+ protocol: detail?.protocol_name ?? detail?.protocol_id ?? "",
175
+ protocolId: detail?.protocol_id,
176
+ pool: detail?.pool,
177
+ asset: symbol,
178
+ amount: String(amount),
179
+ apy: detail?.pool_apy,
180
+ tvl: detail?.pool_tvl,
181
+ // PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
182
+ // structural read keeps it undefined today and auto-populates later.
183
+ liquidity: detail?.liquidity
184
+ });
197
185
  }
198
186
  }
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
- }));
222
187
  return {
223
188
  smartWallet,
224
189
  totalBalance: String(totalBalance),
@@ -1856,84 +1821,6 @@ async function getSponsorRelayerAddress(input) {
1856
1821
  return parsed.data.relayer;
1857
1822
  }
1858
1823
 
1859
- // src/lib/permit2.ts
1860
- import { bytesToHex as bytesToHex2 } from "viem";
1861
- var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
1862
- var MAX_UINT256 = 2n ** 256n - 1n;
1863
- var ERC20_ALLOWANCE_ABI = [
1864
- {
1865
- type: "function",
1866
- name: "allowance",
1867
- stateMutability: "view",
1868
- inputs: [
1869
- { name: "owner", type: "address" },
1870
- { name: "spender", type: "address" }
1871
- ],
1872
- outputs: [{ name: "", type: "uint256" }]
1873
- },
1874
- {
1875
- type: "function",
1876
- name: "approve",
1877
- stateMutability: "nonpayable",
1878
- inputs: [
1879
- { name: "spender", type: "address" },
1880
- { name: "amount", type: "uint256" }
1881
- ],
1882
- outputs: [{ name: "", type: "bool" }]
1883
- },
1884
- {
1885
- type: "function",
1886
- name: "balanceOf",
1887
- stateMutability: "view",
1888
- inputs: [{ name: "account", type: "address" }],
1889
- outputs: [{ name: "", type: "uint256" }]
1890
- }
1891
- ];
1892
- function buildPermitTransferFromTypedData(input) {
1893
- return {
1894
- domain: {
1895
- name: "Permit2",
1896
- chainId: input.chainId,
1897
- verifyingContract: PERMIT2_ADDRESS
1898
- },
1899
- types: {
1900
- PermitTransferFrom: [
1901
- { name: "permitted", type: "TokenPermissions" },
1902
- { name: "spender", type: "address" },
1903
- { name: "nonce", type: "uint256" },
1904
- { name: "deadline", type: "uint256" }
1905
- ],
1906
- TokenPermissions: [
1907
- { name: "token", type: "address" },
1908
- { name: "amount", type: "uint256" }
1909
- ]
1910
- },
1911
- primaryType: "PermitTransferFrom",
1912
- message: input.message
1913
- };
1914
- }
1915
- function randomPermit2Nonce() {
1916
- const bytes = new Uint8Array(32);
1917
- globalThis.crypto.getRandomValues(bytes);
1918
- return BigInt(bytesToHex2(bytes));
1919
- }
1920
- async function readPermit2Allowance(publicClient, token, owner) {
1921
- return publicClient.readContract({
1922
- address: token,
1923
- abi: ERC20_ALLOWANCE_ABI,
1924
- functionName: "allowance",
1925
- args: [owner, PERMIT2_ADDRESS]
1926
- });
1927
- }
1928
- async function readErc20Balance(publicClient, token, owner) {
1929
- return publicClient.readContract({
1930
- address: token,
1931
- abi: ERC20_ALLOWANCE_ABI,
1932
- functionName: "balanceOf",
1933
- args: [owner]
1934
- });
1935
- }
1936
-
1937
1824
  // src/lib/sponsored-deposit.ts
1938
1825
  var AUTH_WINDOW_SECONDS = 15 * 60;
1939
1826
  function makeSponsoredDepositCallback(deps) {
@@ -2116,6 +2003,7 @@ var VIEM_CHAIN2 = {
2116
2003
  42161: arbitrum2,
2117
2004
  1: mainnet2
2118
2005
  };
2006
+ var AGENT_ELIGIBILITY_ORDER = ["surfliquid", "zyfai", "sail"];
2119
2007
  var SPONSORED_WETH_BY_CHAIN = {
2120
2008
  8453: "0x4200000000000000000000000000000000000006",
2121
2009
  42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
@@ -2144,6 +2032,7 @@ var OwneySDK = class {
2144
2032
  zyfaiRpcUrls;
2145
2033
  routingApiBaseUrl;
2146
2034
  referralSource;
2035
+ surfliquidApiBaseUrl;
2147
2036
  cachedSponsoredCallback = null;
2148
2037
  cachedWethSponsoredCallback = null;
2149
2038
  initializingAgentsPromise = null;
@@ -2153,6 +2042,7 @@ var OwneySDK = class {
2153
2042
  this.zyfaiRpcUrls = config.zyfaiRpcUrls;
2154
2043
  this.routingApiBaseUrl = config.routingApiBaseUrl;
2155
2044
  this.referralSource = config.referralSource;
2045
+ this.surfliquidApiBaseUrl = config.surfliquidApiBaseUrl;
2156
2046
  }
2157
2047
  /**
2158
2048
  * Establish connection state for all subsequent SDK calls.
@@ -2360,8 +2250,8 @@ var OwneySDK = class {
2360
2250
  this.initializingAgentsPromise = (async () => {
2361
2251
  const agentKeys = await fetchAgentKeys(this.apiKey);
2362
2252
  this.disabledAgents.clear();
2363
- for (const { key: key2, agent_type, is_enabled } of agentKeys) {
2364
- const agent = this.createAgent(agent_type, key2);
2253
+ for (const { key: key2, agent_type, project_name, is_enabled } of agentKeys) {
2254
+ const agent = await this.createAgent(agent_type, key2, project_name);
2365
2255
  if (!agent) continue;
2366
2256
  this.agents.set(agent_type, agent);
2367
2257
  if (is_enabled === false) {
@@ -2382,10 +2272,22 @@ var OwneySDK = class {
2382
2272
  this.initializingAgentsPromise = null;
2383
2273
  }
2384
2274
  }
2385
- createAgent(agentId, key2) {
2275
+ async createAgent(agentId, key2, projectName) {
2386
2276
  if (agentId === "zyfai") {
2387
2277
  return new ZyfaiAgent(key2, this.zyfaiRpcUrls, this.referralSource);
2388
2278
  }
2279
+ if (agentId === "surfliquid") {
2280
+ if (!projectName) return null;
2281
+ const { SurfLiquidAgent } = await import("./surfliquid.agent-JOJJ3C5Y.js");
2282
+ return new SurfLiquidAgent({
2283
+ projectName,
2284
+ appId: key2,
2285
+ // Same-origin proxy override — SurfLiquid auth is an httpOnly cookie,
2286
+ // which WebKit (iOS) discards when it is third-party. See
2287
+ // OwneySDKConfig.surfliquidApiBaseUrl.
2288
+ apiBaseUrl: this.surfliquidApiBaseUrl
2289
+ });
2290
+ }
2389
2291
  return null;
2390
2292
  }
2391
2293
  // --- Account lifecycle ---
@@ -2540,18 +2442,30 @@ var OwneySDK = class {
2540
2442
  );
2541
2443
  }
2542
2444
  const agentResults = {};
2445
+ const agentErrors = {};
2543
2446
  for (const { agent, amount: agentAmount } of agentAmounts) {
2544
- agentResults[agent.id] = await this.depositWithFallback(
2545
- agent,
2546
- state,
2547
- chainId,
2548
- agentAmount,
2549
- asset,
2550
- effectiveCallback,
2551
- depositCallback
2447
+ try {
2448
+ agentResults[agent.id] = await this.depositWithFallback(
2449
+ agent,
2450
+ state,
2451
+ chainId,
2452
+ agentAmount,
2453
+ asset,
2454
+ effectiveCallback,
2455
+ depositCallback
2456
+ );
2457
+ } catch (error) {
2458
+ agentErrors[agent.id] = error instanceof Error ? error.message : String(error);
2459
+ }
2460
+ }
2461
+ if (Object.keys(agentResults).length === 0) {
2462
+ throw new OwneyError(
2463
+ "DEPOSIT_ALL_FAILED",
2464
+ `All ${agentAmounts.length} agent deposit(s) failed.`,
2465
+ { agentErrors }
2552
2466
  );
2553
2467
  }
2554
- return { agentResults };
2468
+ return Object.keys(agentErrors).length > 0 ? { agentResults, agentErrors } : { agentResults };
2555
2469
  }
2556
2470
  /**
2557
2471
  * Invokes `agent.deposit` with the resolved sponsored callback, composing
@@ -2708,6 +2622,34 @@ var OwneySDK = class {
2708
2622
  }
2709
2623
  return eligible;
2710
2624
  }
2625
+ /**
2626
+ * Agent ids the routing API provisioned for this org that support the given
2627
+ * chain + asset, ordered by preference ({@link AGENT_ELIGIBILITY_ORDER},
2628
+ * surfliquid first). Returns `[]` when the org has no compatible agent — never
2629
+ * throws on an empty org. Loads agent keys on first call (apiKey only, no
2630
+ * wallet), so the UI can resolve which agent to use before the user connects.
2631
+ *
2632
+ * This is the source of truth for agent availability: an agent appears here
2633
+ * iff the routing API returned its key. No per-app feature flags.
2634
+ */
2635
+ async getEligibleAgentIds(chainId, asset) {
2636
+ try {
2637
+ await this.ensureAgentsInitialized();
2638
+ } catch (error) {
2639
+ if (error instanceof OwneyError && error.code === "API_NO_AGENTS") {
2640
+ return [];
2641
+ }
2642
+ throw error;
2643
+ }
2644
+ return [...this.agents.values()].filter((agent) => {
2645
+ const chainAssets = agent.supportedAssets.find(
2646
+ (sa) => sa.chainId === chainId
2647
+ );
2648
+ return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
2649
+ }).map((agent) => agent.id).sort(
2650
+ (a, b) => AGENT_ELIGIBILITY_ORDER.indexOf(a) - AGENT_ELIGIBILITY_ORDER.indexOf(b)
2651
+ );
2652
+ }
2711
2653
  // --- Fund operations ---
2712
2654
  /**
2713
2655
  * Withdraw funds from a specific agent, or all agents that support the active chain+asset if agentId is omitted.
@@ -2743,9 +2685,17 @@ var OwneySDK = class {
2743
2685
  }
2744
2686
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
2745
2687
  if (!amount) {
2688
+ const aggregated2 = await this.getBalances();
2689
+ const funded = projectAgentBalancesForAsset(
2690
+ eligibleAgents,
2691
+ aggregated2.agentBalances,
2692
+ chainId,
2693
+ asset,
2694
+ assetInfo.decimals
2695
+ ).filter((b) => b.balance > 0n);
2746
2696
  const results2 = {};
2747
2697
  const agentErrors2 = {};
2748
- for (const agent of eligibleAgents) {
2698
+ for (const { agent } of funded) {
2749
2699
  try {
2750
2700
  results2[agent.id] = await agent.withdraw(state, chainId, token);
2751
2701
  } catch (err) {
@@ -2762,9 +2712,10 @@ var OwneySDK = class {
2762
2712
  { asset, agentErrors: agentErrors2 }
2763
2713
  );
2764
2714
  }
2715
+ const totalWithdrawn = funded.filter(({ agent }) => results2[agent.id] !== void 0).reduce((sum, { balance }) => sum + balance, 0n);
2765
2716
  return {
2766
2717
  agentResult: results2,
2767
- totalWithdrawn: sumWithdrawnAmount(results2).toString()
2718
+ totalWithdrawn: totalWithdrawn.toString()
2768
2719
  };
2769
2720
  }
2770
2721
  const requested = BigInt(amount);