@owney/sdk 0.2.12 → 0.2.14

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/README.md CHANGED
@@ -125,7 +125,7 @@ await sdk.activateAgent(42161);
125
125
 
126
126
  ### `deposit(options)`
127
127
 
128
- Deposit funds into a specific agent, or split equally across all agents if `agentId` is omitted. Validates that the asset is supported by the target agent(s) on the active chain, and agent minimum deposit amounts are taken into account. When splitting across agents, `depositCallback` is invoked once per final valid agent with that agent's split amount and smart wallet address — expect multiple wallet prompts.
128
+ Deposit funds into a specific agent, or split equally across all agents if `agentId` is omitted. Validates that the asset is supported by the target agent(s) on the active chain, and per-agent minimum deposit amounts (defined per chain+asset on `agent.supportedAssets[].assets[].minDepositAmount`) are taken into account. When splitting across agents, `depositCallback` is invoked once per final valid agent with that agent's split amount and smart wallet address — expect multiple wallet prompts.
129
129
 
130
130
  | Param | Type | Description |
131
131
  | ------------------------- | -------------------- | --------------------------------------------------------------- |
@@ -167,13 +167,18 @@ console.log(results.agentResults.sail.amount); // "50000000"
167
167
 
168
168
  Withdraw funds from a specific agent, or all agents that support the active chain+asset if `agentId` is omitted. Validates that the asset is supported.
169
169
 
170
- When `agentId` is omitted with a partial `amount`, the SDK splits the requested amount proportionally across eligible agents based on each agent's per-asset balance. If an agent's withdraw fails, its share is redistributed to remaining not-yet-attempted agents (capped by their headroom). Throws:
170
+ When `agentId` is omitted with a partial `amount`, the SDK splits the requested amount proportionally across eligible agents based on each agent's per-asset balance. If an agent's withdraw fails, its share is redistributed to remaining not-yet-attempted agents (capped by their headroom).
171
+
172
+ Full withdrawals (no `amount`) iterate every eligible agent and continue on per-agent failures — successful agents still return their results. Per-agent failures (e.g. backend returns `success: false`) surface as `WITHDRAW_FAILED` from the agent and are caught at the aggregation layer.
173
+
174
+ Throws:
171
175
 
172
176
  - `WITHDRAW_INSUFFICIENT_BALANCE` — total available across agents is less than `amount`.
173
- - `WITHDRAW_ALL_FAILED` — every agent's withdraw call failed.
174
- - `WITHDRAW_PARTIAL_FAILURE` — some agents succeeded but total withdrawn is less than `amount`. Successful txs are surfaced via `error.details.partialResults`; per-agent failure messages via `error.details.agentErrors`.
177
+ - `WITHDRAW_ALL_FAILED` — every agent's withdraw call failed (full or partial). Carries per-agent failure messages via `error.details.agentErrors` (a `Record<agentId, string>`).
178
+ - `WITHDRAW_PARTIAL_FAILURE` — partial withdrawals only: some agents succeeded but total withdrawn is less than `amount`. Successful txs surfaced via `error.details.partialResults`; per-agent failures via `error.details.agentErrors`.
179
+ - `WITHDRAW_FAILED` — a single agent's underlying withdraw call returned an unsuccessful response. Includes `error.agentId` and the backend message in `error.details.response`.
175
180
 
176
- `WITHDRAW_ALL_FAILED` also carries per-agent failure messages via `error.details.agentErrors` (a `Record<agentId, string>`). Any error originating from a specific agent also has `error.agentId` set and a `[agent:<id>]` prefix on `error.message`.
181
+ Any error originating from a specific agent also has `error.agentId` set and a `[<code>][agent:<id>]` prefix on `error.message`.
177
182
 
178
183
  | Param | Type | Description |
179
184
  | ----------------- | -------------------- | --------------------------------------------- |
@@ -244,11 +249,17 @@ Returns: `AgentEarnings` (single agent) or `OwneyEarnings` (all agents)
244
249
  const earnings = await sdk.getEarnings("zyfai");
245
250
  console.log(earnings.smartWallet); // "0x..."
246
251
  console.log(earnings.lifetimeEarnings); // 42.5
252
+ console.log(earnings.tokens);
253
+ // [
254
+ // { chain: "BASE", chainId: 8453, asset: "USDC", amount: "30.0" },
255
+ // { chain: "ARBITRUM", chainId: 42161, asset: "USDC", amount: "12.5" },
256
+ // ]
247
257
 
248
258
  // All agents
249
259
  const allEarnings = await sdk.getEarnings();
250
260
  console.log(allEarnings.totalEarnings); // "85.0"
251
261
  console.log(allEarnings.agentEarnings.zyfai.lifetimeEarnings); // 42.5
262
+ console.log(allEarnings.agentEarnings.zyfai.tokens); // per-chain, per-asset breakdown
252
263
  ```
253
264
 
254
265
  ### `getAccountApy({ agentId?, days })`
@@ -435,10 +446,16 @@ type OwneySupportedChainId = 8453 | 42161;
435
446
  type OwneySupportedChains = "BASE" | "ARBITRUM";
436
447
  type OwneySupportedTokens = "USDC" | "USDT";
437
448
 
449
+ type AgentSupportedAsset = {
450
+ readonly symbol: string;
451
+ /** Minimum deposit in the asset's smallest unit (e.g. wei, "0" for none). */
452
+ readonly minDepositAmount: string;
453
+ };
454
+
438
455
  type AgentSupportedAssets = {
439
456
  readonly chainId: number;
440
457
  readonly chain?: string;
441
- readonly assets: readonly string[];
458
+ readonly assets: readonly AgentSupportedAsset[];
442
459
  };
443
460
 
444
461
  interface OwneySDKConfig {
@@ -535,6 +552,7 @@ interface OwneyBalances {
535
552
  interface AgentEarnings {
536
553
  smartWallet: `0x${string}`;
537
554
  lifetimeEarnings: number;
555
+ tokens: OwneyToken[];
538
556
  }
539
557
 
540
558
  interface OwneyEarnings {
@@ -639,7 +657,7 @@ type DepositCallback = (
639
657
 
640
658
  ### Error Handling
641
659
 
642
- All errors thrown by the SDK are instances of `OwneyError` (which extends `Error`), each carrying a stable `code` string, optional `details` object, and optional `agentId` identifying the originating agent. When `agentId` is set, `error.message` is also prefixed with `[agent:<id>]` for logs.
660
+ All errors thrown by the SDK are instances of `OwneyError` (which extends `Error`), each carrying a stable `code` string, optional `details` object, and optional `agentId` identifying the originating agent. `error.message` is always prefixed with `[<code>]` (and `[<code>][agent:<id>]` when agent-scoped) so the code is visible in browser console logs without inspecting the error object.
643
661
 
644
662
  ```typescript
645
663
  import { OwneyError } from "@owney/sdk";
@@ -683,7 +701,7 @@ type OwneyErrorCode =
683
701
  | "ASSET_UNSUPPORTED" // Agent doesn't support the asset on the active chain
684
702
  | "ASSET_NO_COMPATIBLE_AGENTS" // No agents support the asset on the active chain
685
703
  // Deposit
686
- | "DEPOSIT_AMOUNT_BELOW_MINIMUM" // Amount below an agent's required minimum deposit
704
+ | "DEPOSIT_AMOUNT_BELOW_MINIMUM" // Amount below an agent's required minimum deposit for the chain+asset
687
705
  | "DEPOSIT_CALLBACK_REQUIRED" // Sail agent requires a depositCallback
688
706
  | "DEPOSIT_CALLBACK_INVALID" // depositCallback didn't return a tx hash
689
707
  | "DEPOSIT_NO_PERMITTED_TOKENS" // No permitted tokens available for deposit
@@ -692,6 +710,7 @@ type OwneyErrorCode =
692
710
  | "WITHDRAW_INSUFFICIENT_BALANCE" // Requested amount exceeds total available across agents
693
711
  | "WITHDRAW_ALL_FAILED" // Every eligible agent's withdraw call failed
694
712
  | "WITHDRAW_PARTIAL_FAILURE" // Some agents succeeded; total withdrawn < requested
713
+ | "WITHDRAW_FAILED" // Agent backend returned an unsuccessful withdraw response
695
714
  // API
696
715
  | "API_ROUTING_ERROR" // Routing API returned a non-OK HTTP status
697
716
  | "API_ROUTING_FAILED" // Routing API returned { success: false }
@@ -718,7 +737,3 @@ The three convenience subclasses extend `OwneyError` and remain backwards-compat
718
737
  | `NotConnectedError` | `NOT_CONNECTED` | — |
719
738
  | `AgentNotFoundError` | `AGENT_NOT_FOUND` | — |
720
739
  | `AgentChainIncompatibleError` | `AGENT_CHAIN_INCOMPATIBLE` | `incompatibleAgents`, `connectedChainId` |
721
-
722
- ## License
723
-
724
- MIT
package/dist/index.cjs CHANGED
@@ -65,7 +65,8 @@ var OwneyError = class extends Error {
65
65
  details;
66
66
  agentId;
67
67
  constructor(code, message, details, agentId) {
68
- super(agentId ? `[agent:${agentId}] ${message}` : message);
68
+ const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
69
+ super(`${prefix} ${message}`);
69
70
  this.name = "OwneyError";
70
71
  this.code = code;
71
72
  this.details = details;
@@ -186,9 +187,26 @@ function sumTokenEarnings(tokens) {
186
187
  return Object.values(tokens).reduce((sum, val) => sum + Number(val), 0);
187
188
  }
188
189
  function mapEarnings(raw, smartWallet) {
190
+ const totalEarningsByChain = raw.data.totalEarningsByChain;
191
+ const tokens = [];
192
+ for (const [chainIdKey, tokensBySymbol] of Object.entries(
193
+ totalEarningsByChain
194
+ )) {
195
+ const positionChainId = Number(chainIdKey);
196
+ for (const [symbol, earnings] of Object.entries(tokensBySymbol ?? {})) {
197
+ const amount = Number(earnings);
198
+ tokens.push({
199
+ chain: CHAIN_ID_TO_NAME[positionChainId] ?? "BASE",
200
+ chainId: positionChainId,
201
+ asset: symbol,
202
+ amount: String(amount)
203
+ });
204
+ }
205
+ }
189
206
  return {
190
207
  smartWallet,
191
- lifetimeEarnings: sumTokenEarnings(raw.data.totalEarningsByToken)
208
+ lifetimeEarnings: sumTokenEarnings(raw.data.totalEarningsByToken),
209
+ tokens
192
210
  };
193
211
  }
194
212
  function mapApyHistory(raw) {
@@ -299,18 +317,17 @@ var DEFAULT_ZYFAI_RPC_URLS = {
299
317
  };
300
318
  var ZyfaiAgent = class {
301
319
  id = "zyfai";
302
- minDepositAmount = "0";
303
320
  supportedChainIds = [8453, 42161];
304
321
  supportedAssets = [
305
322
  {
306
323
  chainId: 8453,
307
324
  chain: "BASE",
308
- assets: ["USDC"]
325
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
309
326
  },
310
327
  {
311
328
  chainId: 42161,
312
329
  chain: "ARBITRUM",
313
- assets: ["USDC"]
330
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
314
331
  }
315
332
  ];
316
333
  sdk;
@@ -430,6 +447,7 @@ var ZyfaiAgent = class {
430
447
  validChainId,
431
448
  amount
432
449
  );
450
+ console.log("zyf deposit raw", raw);
433
451
  return mapDeposit(raw);
434
452
  } catch (error) {
435
453
  await this.disconnect();
@@ -446,12 +464,22 @@ var ZyfaiAgent = class {
446
464
  amount,
447
465
  token
448
466
  );
467
+ console.log("zyf withdraw raw", raw);
468
+ if (!raw.success) {
469
+ throw new OwneyError(
470
+ "WITHDRAW_FAILED",
471
+ raw.message || "Zyfai withdraw failed.",
472
+ { chainId: validChainId, token, amount, response: raw },
473
+ this.id
474
+ );
475
+ }
449
476
  return mapWithdraw(raw);
450
477
  }
451
478
  // --- IAgent: Portfolio reads ---
452
479
  async getBalances(state, chainId) {
453
480
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
454
481
  const raw = await this.sdk.getPortfolio(this.getAddress());
482
+ console.log("zyf balance raw", raw);
455
483
  return mapBalances(raw, validChainId, smartWallet);
456
484
  }
457
485
  async getEarnings(state, chainId) {
@@ -482,7 +510,11 @@ var ZyfaiAgent = class {
482
510
  }
483
511
  async getUserProfile(state, chainId) {
484
512
  await this.connectAuth(state, chainId);
513
+ const validChainId = isValidChainId(chainId);
485
514
  const raw = await this.sdk.getUserDetails();
515
+ if (!raw.hasActiveSessionKey) {
516
+ await this.sdk.createSessionKey(this.getAddress(), validChainId);
517
+ }
486
518
  return mapUserProfile(raw, this.connectedAddress);
487
519
  }
488
520
  // --- IAgent: Discovery (no wallet required) ---
@@ -776,7 +808,7 @@ var OwneySDK = class {
776
808
  }
777
809
  /**
778
810
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
779
- * Validates that the asset is supported and amount meets minimums for the target agent(s).
811
+ * Validates that the asset is supported and amount meets minimums for the target agent(s).
780
812
  * @param options - Deposit parameters
781
813
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
782
814
  * @param options.asset - Asset symbol to deposit (e.g. "USDC")
@@ -796,12 +828,17 @@ var OwneySDK = class {
796
828
  if (agentId) {
797
829
  const agent = this.getAgent(agentId);
798
830
  this.validateAssetSupport(agent, chainId, asset);
799
- this.validateMinDepositAmount(agent, amount);
831
+ this.validateMinDepositAmount(agent, chainId, asset, amount);
800
832
  return agent.deposit(state, chainId, amount, depositCallback);
801
833
  }
802
834
  const totalAmount = BigInt(amount);
803
835
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
804
- const agentAmounts = this.splitDepositAmount(totalAmount, eligibleAgents);
836
+ const agentAmounts = this.splitDepositAmount(
837
+ totalAmount,
838
+ eligibleAgents,
839
+ chainId,
840
+ asset
841
+ );
805
842
  if (agentAmounts.length === 0) {
806
843
  throw new OwneyError(
807
844
  "DEPOSIT_AMOUNT_BELOW_MINIMUM",
@@ -820,7 +857,14 @@ var OwneySDK = class {
820
857
  }
821
858
  return { agentResults };
822
859
  }
823
- splitDepositAmount(totalAmount, agents) {
860
+ getMinDepositAmount(agent, chainId, asset) {
861
+ const chainAssets = agent.supportedAssets.find(
862
+ (sa) => sa.chainId === chainId
863
+ );
864
+ const assetEntry = chainAssets?.assets.find((a) => a.symbol === asset);
865
+ return BigInt(assetEntry?.minDepositAmount ?? "0");
866
+ }
867
+ splitDepositAmount(totalAmount, agents, chainId, asset) {
824
868
  if (agents.length === 0)
825
869
  return [];
826
870
  const perAgent = totalAmount / BigInt(agents.length);
@@ -830,23 +874,31 @@ var OwneySDK = class {
830
874
  amount: i === agents.length - 1 ? perAgent + remainder : perAgent
831
875
  }));
832
876
  const valid = splits.filter(
833
- (s) => s.amount >= BigInt(s.agent.minDepositAmount)
877
+ (s) => s.amount >= this.getMinDepositAmount(s.agent, chainId, asset)
834
878
  );
835
879
  if (valid.length === agents.length) {
836
880
  return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
837
881
  }
838
- return this.splitDepositAmount(totalAmount, valid.map((s) => s.agent));
882
+ return this.splitDepositAmount(
883
+ totalAmount,
884
+ valid.map((s) => s.agent),
885
+ chainId,
886
+ asset
887
+ );
839
888
  }
840
- validateMinDepositAmount(agent, amount) {
841
- const minDepositAmount = BigInt(agent.minDepositAmount);
889
+ validateMinDepositAmount(agent, chainId, asset, amount) {
890
+ const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
842
891
  const parsedAmount = BigInt(amount);
843
892
  if (parsedAmount < minDepositAmount) {
844
893
  throw new OwneyError(
845
894
  "DEPOSIT_AMOUNT_BELOW_MINIMUM",
846
- `Amount "${amount}" is below the required minimum deposit for agent "${agent.id}".`,
895
+ `Amount "${amount}" is below the required minimum deposit "${minDepositAmount.toString()}" for agent "${agent.id}" on chain ${chainId} for asset "${asset}".`,
847
896
  {
848
897
  agentId: agent.id,
849
- amount
898
+ chainId,
899
+ asset,
900
+ amount,
901
+ minDepositAmount: minDepositAmount.toString()
850
902
  }
851
903
  );
852
904
  }
@@ -855,7 +907,7 @@ var OwneySDK = class {
855
907
  const chainAssets = agent.supportedAssets.find(
856
908
  (sa) => sa.chainId === chainId
857
909
  );
858
- if (!chainAssets || !chainAssets.assets.includes(asset)) {
910
+ if (!chainAssets || !chainAssets.assets.some((a) => a.symbol === asset)) {
859
911
  throw new OwneyError(
860
912
  "ASSET_UNSUPPORTED",
861
913
  `Agent "${agent.id}" does not support asset "${asset}" on chain ${chainId}.`,
@@ -869,7 +921,7 @@ var OwneySDK = class {
869
921
  const chainAssets = agent.supportedAssets.find(
870
922
  (sa) => sa.chainId === chainId
871
923
  );
872
- return chainAssets && chainAssets.assets.includes(asset);
924
+ return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
873
925
  });
874
926
  if (eligible.length === 0) {
875
927
  throw new OwneyError(
@@ -912,8 +964,21 @@ var OwneySDK = class {
912
964
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
913
965
  if (!amount) {
914
966
  const results2 = {};
967
+ const agentErrors2 = {};
915
968
  for (const agent of eligibleAgents) {
916
- results2[agent.id] = await agent.withdraw(state, chainId, token);
969
+ try {
970
+ results2[agent.id] = await agent.withdraw(state, chainId, token);
971
+ } catch (err) {
972
+ console.error(`withdraw failed for agent "${agent.id}":`, err);
973
+ agentErrors2[agent.id] = err instanceof Error ? err.message : String(err);
974
+ }
975
+ }
976
+ if (Object.keys(results2).length === 0) {
977
+ throw new OwneyError(
978
+ "WITHDRAW_ALL_FAILED",
979
+ `Failed to withdraw "${asset}" from all eligible agents.`,
980
+ { asset, agentErrors: agentErrors2 }
981
+ );
917
982
  }
918
983
  return { agentResult: results2 };
919
984
  }
package/dist/index.d.cts CHANGED
@@ -24,7 +24,6 @@ interface IAgent {
24
24
  readonly id: string;
25
25
  readonly supportedChainIds: readonly OwneySupportedChainId[];
26
26
  readonly supportedAssets: readonly AgentSupportedAssets[];
27
- readonly minDepositAmount: string;
28
27
  disconnect(): Promise<void>;
29
28
  activateAgent(state: ConnectionState, chainId: number): Promise<void>;
30
29
  deposit(state: ConnectionState, chainId: number, amount: string, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
@@ -51,10 +50,14 @@ type AgentApyOptions = {
51
50
 
52
51
  type AgentId = "zyfai";
53
52
  type Asset = string;
53
+ type AgentSupportedAsset = {
54
+ readonly symbol: string;
55
+ readonly minDepositAmount: string;
56
+ };
54
57
  type AgentSupportedAssets = {
55
58
  readonly chainId: number;
56
59
  readonly chain?: string;
57
- readonly assets: readonly string[];
60
+ readonly assets: readonly AgentSupportedAsset[];
58
61
  };
59
62
  type DailyApyDays = "7D" | "14D" | "30D";
60
63
  type HistoryFilters = {
@@ -130,6 +133,7 @@ interface OwneyBalances {
130
133
  interface AgentEarnings {
131
134
  smartWallet: `0x${string}`;
132
135
  lifetimeEarnings: number;
136
+ tokens: OwneyToken[];
133
137
  }
134
138
  interface OwneyEarnings {
135
139
  totalEarnings: string;
@@ -249,7 +253,7 @@ declare class OwneySDK {
249
253
  activateAgent(chainId: number, agentId?: AgentId[]): Promise<void>;
250
254
  /**
251
255
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
252
- * Validates that the asset is supported and amount meets minimums for the target agent(s).
256
+ * Validates that the asset is supported and amount meets minimums for the target agent(s).
253
257
  * @param options - Deposit parameters
254
258
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
255
259
  * @param options.asset - Asset symbol to deposit (e.g. "USDC")
@@ -260,6 +264,7 @@ declare class OwneySDK {
260
264
  * @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
261
265
  */
262
266
  deposit(options: DepositOptions): Promise<OwneyDepositResult | OwneyMultiDepositResult>;
267
+ private getMinDepositAmount;
263
268
  private splitDepositAmount;
264
269
  private validateMinDepositAmount;
265
270
  private validateAssetSupport;
@@ -341,7 +346,7 @@ declare class OwneySDK {
341
346
  getAgentAllocation(): Promise<OwneyAgentAllocation>;
342
347
  }
343
348
 
344
- type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "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" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
349
+ type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "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" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
345
350
  declare class OwneyError extends Error {
346
351
  readonly code: OwneyErrorCode;
347
352
  readonly details?: Record<string, unknown>;
@@ -366,4 +371,4 @@ declare class AgentChainIncompatibleError extends OwneyError {
366
371
  }>, connectedChainId: number);
367
372
  }
368
373
 
369
- export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAgentStatus, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneySDK, OwneySDKConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions };
374
+ export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAgentStatus, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneySDK, OwneySDKConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions };
package/dist/index.d.ts CHANGED
@@ -24,7 +24,6 @@ interface IAgent {
24
24
  readonly id: string;
25
25
  readonly supportedChainIds: readonly OwneySupportedChainId[];
26
26
  readonly supportedAssets: readonly AgentSupportedAssets[];
27
- readonly minDepositAmount: string;
28
27
  disconnect(): Promise<void>;
29
28
  activateAgent(state: ConnectionState, chainId: number): Promise<void>;
30
29
  deposit(state: ConnectionState, chainId: number, amount: string, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
@@ -51,10 +50,14 @@ type AgentApyOptions = {
51
50
 
52
51
  type AgentId = "zyfai";
53
52
  type Asset = string;
53
+ type AgentSupportedAsset = {
54
+ readonly symbol: string;
55
+ readonly minDepositAmount: string;
56
+ };
54
57
  type AgentSupportedAssets = {
55
58
  readonly chainId: number;
56
59
  readonly chain?: string;
57
- readonly assets: readonly string[];
60
+ readonly assets: readonly AgentSupportedAsset[];
58
61
  };
59
62
  type DailyApyDays = "7D" | "14D" | "30D";
60
63
  type HistoryFilters = {
@@ -130,6 +133,7 @@ interface OwneyBalances {
130
133
  interface AgentEarnings {
131
134
  smartWallet: `0x${string}`;
132
135
  lifetimeEarnings: number;
136
+ tokens: OwneyToken[];
133
137
  }
134
138
  interface OwneyEarnings {
135
139
  totalEarnings: string;
@@ -249,7 +253,7 @@ declare class OwneySDK {
249
253
  activateAgent(chainId: number, agentId?: AgentId[]): Promise<void>;
250
254
  /**
251
255
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
252
- * Validates that the asset is supported and amount meets minimums for the target agent(s).
256
+ * Validates that the asset is supported and amount meets minimums for the target agent(s).
253
257
  * @param options - Deposit parameters
254
258
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
255
259
  * @param options.asset - Asset symbol to deposit (e.g. "USDC")
@@ -260,6 +264,7 @@ declare class OwneySDK {
260
264
  * @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
261
265
  */
262
266
  deposit(options: DepositOptions): Promise<OwneyDepositResult | OwneyMultiDepositResult>;
267
+ private getMinDepositAmount;
263
268
  private splitDepositAmount;
264
269
  private validateMinDepositAmount;
265
270
  private validateAssetSupport;
@@ -341,7 +346,7 @@ declare class OwneySDK {
341
346
  getAgentAllocation(): Promise<OwneyAgentAllocation>;
342
347
  }
343
348
 
344
- type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "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" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
349
+ type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "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" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
345
350
  declare class OwneyError extends Error {
346
351
  readonly code: OwneyErrorCode;
347
352
  readonly details?: Record<string, unknown>;
@@ -366,4 +371,4 @@ declare class AgentChainIncompatibleError extends OwneyError {
366
371
  }>, connectedChainId: number);
367
372
  }
368
373
 
369
- export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAgentStatus, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneySDK, OwneySDKConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions };
374
+ export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAgentStatus, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneySDK, OwneySDKConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions };
package/dist/index.js CHANGED
@@ -35,7 +35,8 @@ var OwneyError = class extends Error {
35
35
  details;
36
36
  agentId;
37
37
  constructor(code, message, details, agentId) {
38
- super(agentId ? `[agent:${agentId}] ${message}` : message);
38
+ const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
39
+ super(`${prefix} ${message}`);
39
40
  this.name = "OwneyError";
40
41
  this.code = code;
41
42
  this.details = details;
@@ -156,9 +157,26 @@ function sumTokenEarnings(tokens) {
156
157
  return Object.values(tokens).reduce((sum, val) => sum + Number(val), 0);
157
158
  }
158
159
  function mapEarnings(raw, smartWallet) {
160
+ const totalEarningsByChain = raw.data.totalEarningsByChain;
161
+ const tokens = [];
162
+ for (const [chainIdKey, tokensBySymbol] of Object.entries(
163
+ totalEarningsByChain
164
+ )) {
165
+ const positionChainId = Number(chainIdKey);
166
+ for (const [symbol, earnings] of Object.entries(tokensBySymbol ?? {})) {
167
+ const amount = Number(earnings);
168
+ tokens.push({
169
+ chain: CHAIN_ID_TO_NAME[positionChainId] ?? "BASE",
170
+ chainId: positionChainId,
171
+ asset: symbol,
172
+ amount: String(amount)
173
+ });
174
+ }
175
+ }
159
176
  return {
160
177
  smartWallet,
161
- lifetimeEarnings: sumTokenEarnings(raw.data.totalEarningsByToken)
178
+ lifetimeEarnings: sumTokenEarnings(raw.data.totalEarningsByToken),
179
+ tokens
162
180
  };
163
181
  }
164
182
  function mapApyHistory(raw) {
@@ -269,18 +287,17 @@ var DEFAULT_ZYFAI_RPC_URLS = {
269
287
  };
270
288
  var ZyfaiAgent = class {
271
289
  id = "zyfai";
272
- minDepositAmount = "0";
273
290
  supportedChainIds = [8453, 42161];
274
291
  supportedAssets = [
275
292
  {
276
293
  chainId: 8453,
277
294
  chain: "BASE",
278
- assets: ["USDC"]
295
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
279
296
  },
280
297
  {
281
298
  chainId: 42161,
282
299
  chain: "ARBITRUM",
283
- assets: ["USDC"]
300
+ assets: [{ symbol: "USDC", minDepositAmount: "1500000" }]
284
301
  }
285
302
  ];
286
303
  sdk;
@@ -400,6 +417,7 @@ var ZyfaiAgent = class {
400
417
  validChainId,
401
418
  amount
402
419
  );
420
+ console.log("zyf deposit raw", raw);
403
421
  return mapDeposit(raw);
404
422
  } catch (error) {
405
423
  await this.disconnect();
@@ -416,12 +434,22 @@ var ZyfaiAgent = class {
416
434
  amount,
417
435
  token
418
436
  );
437
+ console.log("zyf withdraw raw", raw);
438
+ if (!raw.success) {
439
+ throw new OwneyError(
440
+ "WITHDRAW_FAILED",
441
+ raw.message || "Zyfai withdraw failed.",
442
+ { chainId: validChainId, token, amount, response: raw },
443
+ this.id
444
+ );
445
+ }
419
446
  return mapWithdraw(raw);
420
447
  }
421
448
  // --- IAgent: Portfolio reads ---
422
449
  async getBalances(state, chainId) {
423
450
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
424
451
  const raw = await this.sdk.getPortfolio(this.getAddress());
452
+ console.log("zyf balance raw", raw);
425
453
  return mapBalances(raw, validChainId, smartWallet);
426
454
  }
427
455
  async getEarnings(state, chainId) {
@@ -452,7 +480,11 @@ var ZyfaiAgent = class {
452
480
  }
453
481
  async getUserProfile(state, chainId) {
454
482
  await this.connectAuth(state, chainId);
483
+ const validChainId = isValidChainId(chainId);
455
484
  const raw = await this.sdk.getUserDetails();
485
+ if (!raw.hasActiveSessionKey) {
486
+ await this.sdk.createSessionKey(this.getAddress(), validChainId);
487
+ }
456
488
  return mapUserProfile(raw, this.connectedAddress);
457
489
  }
458
490
  // --- IAgent: Discovery (no wallet required) ---
@@ -746,7 +778,7 @@ var OwneySDK = class {
746
778
  }
747
779
  /**
748
780
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
749
- * Validates that the asset is supported and amount meets minimums for the target agent(s).
781
+ * Validates that the asset is supported and amount meets minimums for the target agent(s).
750
782
  * @param options - Deposit parameters
751
783
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
752
784
  * @param options.asset - Asset symbol to deposit (e.g. "USDC")
@@ -766,12 +798,17 @@ var OwneySDK = class {
766
798
  if (agentId) {
767
799
  const agent = this.getAgent(agentId);
768
800
  this.validateAssetSupport(agent, chainId, asset);
769
- this.validateMinDepositAmount(agent, amount);
801
+ this.validateMinDepositAmount(agent, chainId, asset, amount);
770
802
  return agent.deposit(state, chainId, amount, depositCallback);
771
803
  }
772
804
  const totalAmount = BigInt(amount);
773
805
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
774
- const agentAmounts = this.splitDepositAmount(totalAmount, eligibleAgents);
806
+ const agentAmounts = this.splitDepositAmount(
807
+ totalAmount,
808
+ eligibleAgents,
809
+ chainId,
810
+ asset
811
+ );
775
812
  if (agentAmounts.length === 0) {
776
813
  throw new OwneyError(
777
814
  "DEPOSIT_AMOUNT_BELOW_MINIMUM",
@@ -790,7 +827,14 @@ var OwneySDK = class {
790
827
  }
791
828
  return { agentResults };
792
829
  }
793
- splitDepositAmount(totalAmount, agents) {
830
+ getMinDepositAmount(agent, chainId, asset) {
831
+ const chainAssets = agent.supportedAssets.find(
832
+ (sa) => sa.chainId === chainId
833
+ );
834
+ const assetEntry = chainAssets?.assets.find((a) => a.symbol === asset);
835
+ return BigInt(assetEntry?.minDepositAmount ?? "0");
836
+ }
837
+ splitDepositAmount(totalAmount, agents, chainId, asset) {
794
838
  if (agents.length === 0)
795
839
  return [];
796
840
  const perAgent = totalAmount / BigInt(agents.length);
@@ -800,23 +844,31 @@ var OwneySDK = class {
800
844
  amount: i === agents.length - 1 ? perAgent + remainder : perAgent
801
845
  }));
802
846
  const valid = splits.filter(
803
- (s) => s.amount >= BigInt(s.agent.minDepositAmount)
847
+ (s) => s.amount >= this.getMinDepositAmount(s.agent, chainId, asset)
804
848
  );
805
849
  if (valid.length === agents.length) {
806
850
  return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
807
851
  }
808
- return this.splitDepositAmount(totalAmount, valid.map((s) => s.agent));
852
+ return this.splitDepositAmount(
853
+ totalAmount,
854
+ valid.map((s) => s.agent),
855
+ chainId,
856
+ asset
857
+ );
809
858
  }
810
- validateMinDepositAmount(agent, amount) {
811
- const minDepositAmount = BigInt(agent.minDepositAmount);
859
+ validateMinDepositAmount(agent, chainId, asset, amount) {
860
+ const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
812
861
  const parsedAmount = BigInt(amount);
813
862
  if (parsedAmount < minDepositAmount) {
814
863
  throw new OwneyError(
815
864
  "DEPOSIT_AMOUNT_BELOW_MINIMUM",
816
- `Amount "${amount}" is below the required minimum deposit for agent "${agent.id}".`,
865
+ `Amount "${amount}" is below the required minimum deposit "${minDepositAmount.toString()}" for agent "${agent.id}" on chain ${chainId} for asset "${asset}".`,
817
866
  {
818
867
  agentId: agent.id,
819
- amount
868
+ chainId,
869
+ asset,
870
+ amount,
871
+ minDepositAmount: minDepositAmount.toString()
820
872
  }
821
873
  );
822
874
  }
@@ -825,7 +877,7 @@ var OwneySDK = class {
825
877
  const chainAssets = agent.supportedAssets.find(
826
878
  (sa) => sa.chainId === chainId
827
879
  );
828
- if (!chainAssets || !chainAssets.assets.includes(asset)) {
880
+ if (!chainAssets || !chainAssets.assets.some((a) => a.symbol === asset)) {
829
881
  throw new OwneyError(
830
882
  "ASSET_UNSUPPORTED",
831
883
  `Agent "${agent.id}" does not support asset "${asset}" on chain ${chainId}.`,
@@ -839,7 +891,7 @@ var OwneySDK = class {
839
891
  const chainAssets = agent.supportedAssets.find(
840
892
  (sa) => sa.chainId === chainId
841
893
  );
842
- return chainAssets && chainAssets.assets.includes(asset);
894
+ return chainAssets?.assets.some((a) => a.symbol === asset) ?? false;
843
895
  });
844
896
  if (eligible.length === 0) {
845
897
  throw new OwneyError(
@@ -882,8 +934,21 @@ var OwneySDK = class {
882
934
  const eligibleAgents = this.getEligibleAgents(chainId, asset);
883
935
  if (!amount) {
884
936
  const results2 = {};
937
+ const agentErrors2 = {};
885
938
  for (const agent of eligibleAgents) {
886
- results2[agent.id] = await agent.withdraw(state, chainId, token);
939
+ try {
940
+ results2[agent.id] = await agent.withdraw(state, chainId, token);
941
+ } catch (err) {
942
+ console.error(`withdraw failed for agent "${agent.id}":`, err);
943
+ agentErrors2[agent.id] = err instanceof Error ? err.message : String(err);
944
+ }
945
+ }
946
+ if (Object.keys(results2).length === 0) {
947
+ throw new OwneyError(
948
+ "WITHDRAW_ALL_FAILED",
949
+ `Failed to withdraw "${asset}" from all eligible agents.`,
950
+ { asset, agentErrors: agentErrors2 }
951
+ );
887
952
  }
888
953
  return { agentResult: results2 };
889
954
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "dev": "tsup --watch"
21
21
  },
22
22
  "dependencies": {
23
- "@zyfai/sdk": "^0.2.30",
23
+ "@zyfai/sdk": "^0.2.32",
24
24
  "viem": "^2.48.1"
25
25
  },
26
26
  "devDependencies": {
@@ -31,4 +31,4 @@
31
31
  "publishConfig": {
32
32
  "access": "public"
33
33
  }
34
- }
34
+ }