@owney/sdk 0.2.7 → 0.2.9

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.ts CHANGED
@@ -1,5 +1,11 @@
1
+ type ZyfaiRpcUrlsConfig = Partial<Record<(typeof SUPPORTED_CHAIN_IDS)[number], string>>;
1
2
  interface OwneySDKConfig {
2
3
  apiKey: string;
4
+ /**
5
+ * Optional per-chain RPC overrides for Zyfai SDK network calls.
6
+ * Example: { 8453: "https://...", 42161: "https://..." }
7
+ */
8
+ zyfaiRpcUrls?: ZyfaiRpcUrlsConfig;
3
9
  }
4
10
  interface ConnectionState {
5
11
  provider: any;
@@ -18,6 +24,7 @@ interface IAgent {
18
24
  readonly id: string;
19
25
  readonly supportedChainIds: readonly OwneySupportedChainId[];
20
26
  readonly supportedAssets: readonly AgentSupportedAssets[];
27
+ readonly minDepositAmount: string;
21
28
  disconnect(): Promise<void>;
22
29
  activateAgent(state: ConnectionState, chainId: number): Promise<void>;
23
30
  deposit(state: ConnectionState, chainId: number, amount: string, depositCallback?: DepositCallback): Promise<OwneyDepositResult>;
@@ -190,10 +197,6 @@ interface AgentApy {
190
197
  interface OwneyAgentApy {
191
198
  agentApy: Record<AgentId, AgentApy>;
192
199
  }
193
- interface OwneyRouteResponse {
194
- agent: AgentId;
195
- chainId: number;
196
- }
197
200
  interface OwneyAgentAllocation {
198
201
  agentAllocation: Record<AgentId, number>;
199
202
  }
@@ -203,6 +206,7 @@ declare class OwneySDK {
203
206
  private activeAgents;
204
207
  private state;
205
208
  private apiKey;
209
+ private zyfaiRpcUrls?;
206
210
  private initializingAgentsPromise;
207
211
  constructor(config: OwneySDKConfig);
208
212
  /**
@@ -231,6 +235,7 @@ declare class OwneySDK {
231
235
  private getAgent;
232
236
  private getActiveAgents;
233
237
  private ensureAgentsInitialized;
238
+ private createAgent;
234
239
  /**
235
240
  * Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
236
241
  * Deploys the Safe contract and creates a session key if not already set up.
@@ -244,7 +249,7 @@ declare class OwneySDK {
244
249
  activateAgent(chainId: number, agentId?: AgentId[]): Promise<void>;
245
250
  /**
246
251
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
247
- * Validates that the asset is supported by the target agent(s) on the active chain.
252
+ * Validates that the asset is supported and amount meets minimums for the target agent(s).
248
253
  * @param options - Deposit parameters
249
254
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
250
255
  * @param options.asset - Asset symbol to deposit (e.g. "USDC")
@@ -255,6 +260,8 @@ declare class OwneySDK {
255
260
  * @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
256
261
  */
257
262
  deposit(options: DepositOptions): Promise<OwneyDepositResult | OwneyMultiDepositResult>;
263
+ private splitDepositAmount;
264
+ private validateMinDepositAmount;
258
265
  private validateAssetSupport;
259
266
  private getEligibleAgents;
260
267
  /**
@@ -334,7 +341,7 @@ declare class OwneySDK {
334
341
  getAgentAllocation(): Promise<OwneyAgentAllocation>;
335
342
  }
336
343
 
337
- 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_TOO_SMALL" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "WITHDRAW_NO_PERMITTED_TOKENS" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
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" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
338
345
  declare class OwneyError extends Error {
339
346
  readonly code: OwneyErrorCode;
340
347
  readonly details?: Record<string, unknown>;
@@ -358,4 +365,4 @@ declare class AgentChainIncompatibleError extends OwneyError {
358
365
  }>, connectedChainId: number);
359
366
  }
360
367
 
361
- 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, OwneyRouteResponse, OwneySDK, OwneySDKConfig, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions };
368
+ 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 };
package/dist/index.js CHANGED
@@ -273,17 +273,13 @@ function mapApyByStrategy(raw) {
273
273
  }
274
274
 
275
275
  // src/agents/zyfai/zyfai.agent.ts
276
- var ZYFAI_TIMING_PREFIX = "[AgentTiming][zyfai]";
277
- function logTiming(label, startedAt, meta) {
278
- const elapsedMs = Date.now() - startedAt;
279
- if (meta) {
280
- console.log(`${ZYFAI_TIMING_PREFIX} ${label} ${elapsedMs}ms`, meta);
281
- return;
282
- }
283
- console.log(`${ZYFAI_TIMING_PREFIX} ${label} ${elapsedMs}ms`);
284
- }
276
+ var DEFAULT_ZYFAI_RPC_URLS = {
277
+ 8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
278
+ 42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
279
+ };
285
280
  var ZyfaiAgent = class {
286
281
  id = "zyfai";
282
+ minDepositAmount = "0";
287
283
  supportedChainIds = [8453, 42161];
288
284
  supportedAssets = [
289
285
  {
@@ -302,8 +298,11 @@ var ZyfaiAgent = class {
302
298
  connectedChainId = null;
303
299
  smartWalletCache = /* @__PURE__ */ new Map();
304
300
  connectAuthPromise = null;
305
- constructor(apiKey) {
306
- this.sdk = new ZyfaiSDK({ apiKey });
301
+ constructor(apiKey, rpcUrls) {
302
+ this.sdk = new ZyfaiSDK({
303
+ apiKey,
304
+ rpcUrls: rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS
305
+ });
307
306
  }
308
307
  // --- Private helpers ---
309
308
  getAddress() {
@@ -317,17 +316,12 @@ var ZyfaiAgent = class {
317
316
  }
318
317
  /** Light connect: SIWE auth only. Re-auths if chain changed. */
319
318
  async connectAuth(state, chainId) {
320
- const startedAt = Date.now();
321
319
  const validChainId = isValidChainId(chainId);
322
320
  if (this.connectedAddress && this.connectedChainId === validChainId) {
323
- logTiming("connectAuth cache-hit", startedAt, { chainId: validChainId });
324
321
  return;
325
322
  }
326
323
  if (this.connectAuthPromise) {
327
324
  await this.connectAuthPromise;
328
- logTiming("connectAuth awaited-inflight", startedAt, {
329
- chainId: validChainId
330
- });
331
325
  return;
332
326
  }
333
327
  this.connectAuthPromise = (async () => {
@@ -340,69 +334,40 @@ var ZyfaiAgent = class {
340
334
  })();
341
335
  try {
342
336
  await this.connectAuthPromise;
343
- logTiming("connectAuth success", startedAt, { chainId: validChainId });
344
337
  } finally {
345
338
  this.connectAuthPromise = null;
346
339
  }
347
340
  }
348
341
  /** Full connect: SIWE auth + Safe deploy check + session key. */
349
342
  async connectFull(state, chainId) {
350
- const startedAt = Date.now();
351
343
  await this.connectAuth(state, chainId);
352
344
  const validChainId = isValidChainId(chainId);
353
345
  const address = this.getAddress();
354
- const walletLookupStart = Date.now();
355
346
  const wallet = await this.sdk.getSmartWalletAddress(address, validChainId);
356
- logTiming("connectFull getSmartWalletAddress", walletLookupStart, {
357
- chainId: validChainId
358
- });
359
347
  this.smartWalletCache.set(`${address}_${validChainId}`, wallet.address);
360
348
  if (!wallet.isDeployed) {
361
- const deployStart = Date.now();
362
349
  await this.sdk.deploySafe(address, validChainId, "aggressive", true);
363
- logTiming("connectFull deploySafe", deployStart, {
364
- chainId: validChainId
365
- });
366
350
  }
367
- const userDetailsStart = Date.now();
368
351
  const user = await this.sdk.getUserDetails();
369
- logTiming("connectFull getUserDetails", userDetailsStart, {
370
- chainId: validChainId
371
- });
372
352
  if (!user.hasActiveSessionKey) {
373
- const sessionKeyStart = Date.now();
374
353
  await this.sdk.createSessionKey(address, validChainId);
375
- logTiming("connectFull createSessionKey", sessionKeyStart, {
376
- chainId: validChainId
377
- });
378
354
  }
379
- logTiming("connectFull success", startedAt, { chainId: validChainId });
380
355
  }
381
356
  /** Connect + resolve smart wallet address for read operations. */
382
357
  async resolveSmartWallet(state, chainId) {
383
- const startedAt = Date.now();
384
358
  await this.connectAuth(state, chainId);
385
359
  const validChainId = isValidChainId(chainId);
386
360
  const ownerAddress = this.getAddress();
387
361
  const cacheKey = `${ownerAddress}_${validChainId}`;
388
362
  let smartWallet = this.smartWalletCache.get(cacheKey);
389
363
  if (!smartWallet) {
390
- const lookupStart = Date.now();
391
364
  const { address } = await this.sdk.getSmartWalletAddress(
392
365
  ownerAddress,
393
366
  validChainId
394
367
  );
395
- logTiming("resolveSmartWallet remote-lookup", lookupStart, {
396
- chainId: validChainId
397
- });
398
368
  smartWallet = address;
399
369
  this.smartWalletCache.set(cacheKey, smartWallet);
400
- } else {
401
- logTiming("resolveSmartWallet cache-hit", startedAt, {
402
- chainId: validChainId
403
- });
404
370
  }
405
- logTiming("resolveSmartWallet ready", startedAt, { chainId: validChainId });
406
371
  return { smartWallet, chainId: validChainId };
407
372
  }
408
373
  // --- IAgent: Connection lifecycle ---
@@ -462,14 +427,8 @@ var ZyfaiAgent = class {
462
427
  }
463
428
  // --- IAgent: Portfolio reads ---
464
429
  async getBalances(state, chainId) {
465
- const startedAt = Date.now();
466
430
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
467
- const portfolioStart = Date.now();
468
431
  const raw = await this.sdk.getPortfolio(this.getAddress());
469
- logTiming("getBalances getPortfolio", portfolioStart, {
470
- chainId: validChainId
471
- });
472
- logTiming("getBalances success", startedAt, { chainId: validChainId });
473
432
  return mapBalances(raw, validChainId, smartWallet);
474
433
  }
475
434
  async getEarnings(state, chainId) {
@@ -534,13 +493,13 @@ function mapWithdraw2(raw) {
534
493
  function mapPortfolioBalances(raw, smartWallet) {
535
494
  let total = 0;
536
495
  const tokens = [];
537
- for (const item of raw.result) {
538
- total += item.usd_value;
496
+ for (const item of raw.tokens) {
497
+ total += item.balanceFormatted;
539
498
  tokens.push({
540
- chain: item.chain.toUpperCase(),
541
- chainId: item.chain_id,
542
- asset: item.token === "USD\u20AE0" ? "USDT" : item.token,
543
- amount: String(item.usd_value)
499
+ chain: SUPPORTED_CHAINS[item.chain],
500
+ chainId: item.chain,
501
+ asset: item.symbol === "USD\u20AE0" ? "USDT" : item.symbol,
502
+ amount: item.balance
544
503
  });
545
504
  }
546
505
  return {
@@ -659,7 +618,7 @@ function mapHistory2(raw) {
659
618
  rewards: "Earned"
660
619
  };
661
620
  const filtered = raw.result.items.filter(
662
- (i) => i.status === "success" && i.transactions.length
621
+ (i) => !(i.type === "execution" && (i.status === "failed" || !i.transactions.length))
663
622
  );
664
623
  return {
665
624
  total: filtered.length,
@@ -723,18 +682,10 @@ function remapApyPerAssetToSymbols(raw) {
723
682
  var SAIL_API_BASE = "https://app.sail.money";
724
683
  var PROJECT_ID = "sail";
725
684
  var PAGE_ID = "home";
726
- var SAIL_TIMING_PREFIX = "[AgentTiming][sail]";
727
685
  var SAIL_PORTFOLIO_TIMEOUT_MS = 8e3;
728
- function logTiming2(label, startedAt, meta) {
729
- const elapsedMs = Date.now() - startedAt;
730
- if (meta) {
731
- console.log(`${SAIL_TIMING_PREFIX} ${label} ${elapsedMs}ms`, meta);
732
- return;
733
- }
734
- console.log(`${SAIL_TIMING_PREFIX} ${label} ${elapsedMs}ms`);
735
- }
736
686
  var SailAgent = class {
737
687
  id = "sail";
688
+ minDepositAmount = "4800000000";
738
689
  supportedChainIds = [8453, 42161];
739
690
  supportedAssets = [
740
691
  {
@@ -805,7 +756,6 @@ var SailAgent = class {
805
756
  }
806
757
  /** Initiate SIWE and sign with the user's wallet. */
807
758
  async signSiwe(state, chainId) {
808
- const startedAt = Date.now();
809
759
  const initiate = await this.request(
810
760
  "POST",
811
761
  `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/auth/initiate`,
@@ -820,7 +770,6 @@ var SailAgent = class {
820
770
  method: "personal_sign",
821
771
  params: [initiate.message, state.walletAddress]
822
772
  });
823
- logTiming2("signSiwe success", startedAt, { chainId });
824
773
  return {
825
774
  sessionId: initiate.sessionId,
826
775
  message: initiate.message,
@@ -829,14 +778,11 @@ var SailAgent = class {
829
778
  }
830
779
  /** Full connect: auth handles smart account creation via SIWE flow. */
831
780
  async connectFull(state, chainId) {
832
- const startedAt = Date.now();
833
781
  if (this.connectedAddress && this.connectedChainId === chainId) {
834
- logTiming2("connectFull cache-hit", startedAt, { chainId });
835
782
  return;
836
783
  }
837
784
  if (this.connectPromise) {
838
785
  await this.connectPromise;
839
- logTiming2("connectFull awaited-inflight", startedAt, { chainId });
840
786
  return;
841
787
  }
842
788
  if (!state.walletAddress) {
@@ -869,13 +815,11 @@ var SailAgent = class {
869
815
  })();
870
816
  try {
871
817
  await this.connectPromise;
872
- logTiming2("connectFull success", startedAt, { chainId });
873
818
  } finally {
874
819
  this.connectPromise = null;
875
820
  }
876
821
  }
877
822
  async resolveSmartWallet(state, chainId) {
878
- const startedAt = Date.now();
879
823
  await this.connectFull(state, chainId);
880
824
  const validChainId = isValidChainId(chainId);
881
825
  if (!this.smartWalletAddress) {
@@ -884,7 +828,6 @@ var SailAgent = class {
884
828
  "Wallet not connected. Call sdk.connect() first."
885
829
  );
886
830
  }
887
- logTiming2("resolveSmartWallet ready", startedAt, { chainId: validChainId });
888
831
  return {
889
832
  smartWallet: this.smartWalletAddress,
890
833
  chainId: validChainId
@@ -1009,13 +952,9 @@ var SailAgent = class {
1009
952
  }
1010
953
  // --- IAgent: Portfolio reads ---
1011
954
  async getBalances(state, chainId) {
1012
- const startedAt = Date.now();
1013
955
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1014
- const portfolioStart = Date.now();
1015
956
  try {
1016
- const raw = await this.getMetricsPortfolio(state, chainId);
1017
- logTiming2("getBalances getMetricsPortfolio", portfolioStart, { chainId });
1018
- logTiming2("getBalances success", startedAt, { chainId });
957
+ const raw = await this.getPortfolio();
1019
958
  return mapPortfolioBalances(raw, smartWallet);
1020
959
  } catch (error) {
1021
960
  if (error instanceof OwneyError && error.code === "API_SAIL_TIMEOUT") {
@@ -1025,9 +964,8 @@ var SailAgent = class {
1025
964
  chainId
1026
965
  }
1027
966
  );
1028
- logTiming2("getBalances timeout-fallback", startedAt, { chainId });
1029
967
  return mapPortfolioBalances(
1030
- { message: "timeout", result: [] },
968
+ { message: "timeout", tokens: [] },
1031
969
  smartWallet
1032
970
  );
1033
971
  }
@@ -1058,6 +996,14 @@ var SailAgent = class {
1058
996
  SAIL_PORTFOLIO_TIMEOUT_MS
1059
997
  );
1060
998
  }
999
+ async getPortfolio() {
1000
+ return this.request(
1001
+ "GET",
1002
+ `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/portfolio/tokens`,
1003
+ void 0,
1004
+ SAIL_PORTFOLIO_TIMEOUT_MS
1005
+ );
1006
+ }
1061
1007
  async getMetricsEarnings(state, chainId) {
1062
1008
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1063
1009
  return this.request(
@@ -1065,7 +1011,7 @@ var SailAgent = class {
1065
1011
  `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/earnings?smart_account=${smartWallet}`
1066
1012
  );
1067
1013
  }
1068
- async getMetricsBalance(state, chainId, currency) {
1014
+ async getMetricsBalance(state, chainId, currency = "usd") {
1069
1015
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1070
1016
  return this.request(
1071
1017
  "GET",
@@ -1213,27 +1159,16 @@ async function fetchAgentKeys(apiKey) {
1213
1159
  }
1214
1160
 
1215
1161
  // src/client.ts
1216
- var AGENT_CONSTRUCTORS = {
1217
- zyfai: ZyfaiAgent,
1218
- sail: SailAgent
1219
- };
1220
- var SDK_TIMING_PREFIX = "[OwneySDKTiming]";
1221
- function logTiming3(label, startedAt, meta) {
1222
- const elapsedMs = Date.now() - startedAt;
1223
- if (meta) {
1224
- console.log(`${SDK_TIMING_PREFIX} ${label} ${elapsedMs}ms`, meta);
1225
- return;
1226
- }
1227
- console.log(`${SDK_TIMING_PREFIX} ${label} ${elapsedMs}ms`);
1228
- }
1229
1162
  var OwneySDK = class {
1230
1163
  agents = /* @__PURE__ */ new Map();
1231
1164
  activeAgents = /* @__PURE__ */ new Set();
1232
1165
  state = null;
1233
1166
  apiKey;
1167
+ zyfaiRpcUrls;
1234
1168
  initializingAgentsPromise = null;
1235
1169
  constructor(config) {
1236
1170
  this.apiKey = config.apiKey;
1171
+ this.zyfaiRpcUrls = config.zyfaiRpcUrls;
1237
1172
  }
1238
1173
  /**
1239
1174
  * Establish connection state for all subsequent SDK calls.
@@ -1317,10 +1252,9 @@ var OwneySDK = class {
1317
1252
  this.initializingAgentsPromise = (async () => {
1318
1253
  const agentKeys = await fetchAgentKeys(this.apiKey);
1319
1254
  for (const { key, agent_type } of agentKeys) {
1320
- const AgentClass = AGENT_CONSTRUCTORS[agent_type];
1321
- if (!AgentClass)
1255
+ const agent = this.createAgent(agent_type, key);
1256
+ if (!agent)
1322
1257
  continue;
1323
- const agent = new AgentClass(key);
1324
1258
  this.agents.set(agent_type, agent);
1325
1259
  }
1326
1260
  if (this.agents.size === 0) {
@@ -1337,6 +1271,15 @@ var OwneySDK = class {
1337
1271
  this.initializingAgentsPromise = null;
1338
1272
  }
1339
1273
  }
1274
+ createAgent(agentId, key) {
1275
+ if (agentId === "zyfai") {
1276
+ return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1277
+ }
1278
+ if (agentId === "sail") {
1279
+ return new SailAgent(key);
1280
+ }
1281
+ return null;
1282
+ }
1340
1283
  // --- Account lifecycle ---
1341
1284
  /**
1342
1285
  * Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
@@ -1349,7 +1292,6 @@ var OwneySDK = class {
1349
1292
  * throws before activating any agent.
1350
1293
  */
1351
1294
  async activateAgent(chainId, agentId) {
1352
- const startedAt = Date.now();
1353
1295
  const state = this.requireState();
1354
1296
  await this.ensureAgentsInitialized();
1355
1297
  if (agentId !== void 0) {
@@ -1377,20 +1319,11 @@ var OwneySDK = class {
1377
1319
  state.chainId = chainId;
1378
1320
  Promise.all(
1379
1321
  agents.map(async (agent) => {
1380
- const agentStart = Date.now();
1381
1322
  await agent.activateAgent(state, chainId);
1382
- logTiming3("activateAgent background-agent-ready", agentStart, {
1383
- chainId,
1384
- agentId: agent.id
1385
- });
1386
1323
  })
1387
1324
  ).catch((error) => {
1388
1325
  console.error("activateAgent background init failed:", error);
1389
1326
  });
1390
- logTiming3("activateAgent scheduled", startedAt, {
1391
- chainId,
1392
- agentIds: uniqueIds
1393
- });
1394
1327
  return;
1395
1328
  }
1396
1329
  const compatible = [...this.agents.values()].filter(
@@ -1410,24 +1343,15 @@ var OwneySDK = class {
1410
1343
  state.chainId = chainId;
1411
1344
  Promise.all(
1412
1345
  compatible.map(async (agent) => {
1413
- const agentStart = Date.now();
1414
1346
  await agent.activateAgent(state, chainId);
1415
- logTiming3("activateAgent background-agent-ready", agentStart, {
1416
- chainId,
1417
- agentId: agent.id
1418
- });
1419
1347
  })
1420
1348
  ).catch((error) => {
1421
1349
  console.error("activateAgent background init failed:", error);
1422
1350
  });
1423
- logTiming3("activateAgent scheduled", startedAt, {
1424
- chainId,
1425
- agentIds: compatible.map((agent) => agent.id)
1426
- });
1427
1351
  }
1428
1352
  /**
1429
1353
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
1430
- * Validates that the asset is supported by the target agent(s) on the active chain.
1354
+ * Validates that the asset is supported and amount meets minimums for the target agent(s).
1431
1355
  * @param options - Deposit parameters
1432
1356
  * @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
1433
1357
  * @param options.asset - Asset symbol to deposit (e.g. "USDC")
@@ -1439,28 +1363,29 @@ var OwneySDK = class {
1439
1363
  */
1440
1364
  async deposit(options) {
1441
1365
  const { amount, asset, depositCallback, agentId } = options;
1366
+ if (BigInt(amount) === 0n) {
1367
+ return { agentResults: {} };
1368
+ }
1442
1369
  const state = this.requireState();
1443
1370
  const chainId = this.requireChainId();
1444
1371
  if (agentId) {
1445
1372
  const agent = this.getAgent(agentId);
1446
1373
  this.validateAssetSupport(agent, chainId, asset);
1374
+ this.validateMinDepositAmount(agent, amount);
1447
1375
  return agent.deposit(state, chainId, amount, depositCallback);
1448
1376
  }
1449
- const eligibleAgents = this.getEligibleAgents(chainId, asset);
1450
1377
  const totalAmount = BigInt(amount);
1451
- if (totalAmount < BigInt(eligibleAgents.length)) {
1378
+ const eligibleAgents = this.getEligibleAgents(chainId, asset);
1379
+ const agentAmounts = this.splitDepositAmount(totalAmount, eligibleAgents);
1380
+ if (agentAmounts.length === 0) {
1452
1381
  throw new OwneyError(
1453
- "DEPOSIT_AMOUNT_TOO_SMALL",
1454
- `Amount "${amount}" is too small to split across ${eligibleAgents.length} agents.`,
1455
- { amount, agentCount: eligibleAgents.length }
1382
+ "DEPOSIT_AMOUNT_BELOW_MINIMUM",
1383
+ `Amount "${amount}" cannot satisfy minimum deposit requirements for any eligible agent.`,
1384
+ { amount }
1456
1385
  );
1457
1386
  }
1458
- const perAgent = totalAmount / BigInt(eligibleAgents.length);
1459
- const remainder = totalAmount % BigInt(eligibleAgents.length);
1460
1387
  const agentResults = {};
1461
- for (let i = 0; i < eligibleAgents.length; i++) {
1462
- const agent = eligibleAgents[i];
1463
- const agentAmount = i === eligibleAgents.length - 1 ? String(perAgent + remainder) : String(perAgent);
1388
+ for (const { agent, amount: agentAmount } of agentAmounts) {
1464
1389
  agentResults[agent.id] = await agent.deposit(
1465
1390
  state,
1466
1391
  chainId,
@@ -1470,6 +1395,37 @@ var OwneySDK = class {
1470
1395
  }
1471
1396
  return { agentResults };
1472
1397
  }
1398
+ splitDepositAmount(totalAmount, agents) {
1399
+ if (agents.length === 0)
1400
+ return [];
1401
+ const perAgent = totalAmount / BigInt(agents.length);
1402
+ const remainder = totalAmount % BigInt(agents.length);
1403
+ const splits = agents.map((agent, i) => ({
1404
+ agent,
1405
+ amount: i === agents.length - 1 ? perAgent + remainder : perAgent
1406
+ }));
1407
+ const valid = splits.filter(
1408
+ (s) => s.amount >= BigInt(s.agent.minDepositAmount)
1409
+ );
1410
+ if (valid.length === agents.length) {
1411
+ return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
1412
+ }
1413
+ return this.splitDepositAmount(totalAmount, valid.map((s) => s.agent));
1414
+ }
1415
+ validateMinDepositAmount(agent, amount) {
1416
+ const minDepositAmount = BigInt(agent.minDepositAmount);
1417
+ const parsedAmount = BigInt(amount);
1418
+ if (parsedAmount < minDepositAmount) {
1419
+ throw new OwneyError(
1420
+ "DEPOSIT_AMOUNT_BELOW_MINIMUM",
1421
+ `Amount "${amount}" is below the required minimum deposit for agent "${agent.id}".`,
1422
+ {
1423
+ agentId: agent.id,
1424
+ amount
1425
+ }
1426
+ );
1427
+ }
1428
+ }
1473
1429
  validateAssetSupport(agent, chainId, asset) {
1474
1430
  const chainAssets = agent.supportedAssets.find(
1475
1431
  (sa) => sa.chainId === chainId
@@ -1548,12 +1504,10 @@ var OwneySDK = class {
1548
1504
  * @returns {AgentBalance} for a single agent, or {OwneyBalances} with totalBalance and per-agent breakdown
1549
1505
  */
1550
1506
  async getBalances(agentId) {
1551
- const startedAt = Date.now();
1552
1507
  const state = this.requireState();
1553
1508
  const chainId = this.requireChainId();
1554
1509
  if (agentId) {
1555
1510
  const result = await this.getAgent(agentId).getBalances(state, chainId);
1556
- logTiming3("getBalances single-agent", startedAt, { chainId, agentId });
1557
1511
  return result;
1558
1512
  }
1559
1513
  let totalBalance = 0;
@@ -1561,12 +1515,7 @@ var OwneySDK = class {
1561
1515
  const entries = [...this.getActiveAgents().entries()];
1562
1516
  const balanceResults = await Promise.allSettled(
1563
1517
  entries.map(async ([id, agent]) => {
1564
- const agentStartedAt = Date.now();
1565
1518
  const b = await agent.getBalances(state, chainId);
1566
- logTiming3("getBalances per-agent", agentStartedAt, {
1567
- chainId,
1568
- agentId: id
1569
- });
1570
1519
  return [id, b];
1571
1520
  })
1572
1521
  );
@@ -1587,11 +1536,6 @@ var OwneySDK = class {
1587
1536
  "Failed to fetch balances for all active agents."
1588
1537
  );
1589
1538
  }
1590
- logTiming3("getBalances aggregate", startedAt, {
1591
- chainId,
1592
- totalAgents: entries.length,
1593
- successCount
1594
- });
1595
1539
  return {
1596
1540
  totalBalance: String(totalBalance),
1597
1541
  agentBalances: results
@@ -1664,18 +1608,30 @@ var OwneySDK = class {
1664
1608
  results[id] = apy;
1665
1609
  }
1666
1610
  const balances = {};
1667
- let totalBalance = 0;
1668
1611
  for (const [id, bal] of balanceResults) {
1669
1612
  balances[id] = bal;
1670
- totalBalance += bal;
1671
1613
  }
1672
1614
  let totalApy = 0;
1673
- if (totalBalance > 0) {
1615
+ let relevantBalance = 0;
1616
+ for (const id of Object.keys(results)) {
1617
+ const agentApy = Number(results[id].weightedApyAfterFee ?? 0);
1618
+ if (agentApy === 0)
1619
+ continue;
1620
+ relevantBalance += balances[id];
1621
+ }
1622
+ if (relevantBalance > 0) {
1674
1623
  for (const id of Object.keys(results)) {
1675
- const weight = balances[id] / totalBalance;
1676
- totalApy += Number(results[id].weightedApyAfterFee ?? 0) * weight;
1624
+ const agentApy = Number(results[id].weightedApyAfterFee ?? 0);
1625
+ if (agentApy === 0)
1626
+ continue;
1627
+ const weight = balances[id] / relevantBalance;
1628
+ totalApy += agentApy * weight;
1677
1629
  }
1678
1630
  }
1631
+ console.log("account apy", {
1632
+ totalApy: String(totalApy),
1633
+ agentApy: results
1634
+ });
1679
1635
  return {
1680
1636
  totalApy: String(totalApy),
1681
1637
  agentApy: results
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -26,5 +26,8 @@
26
26
  "dotenv": "^17.3.1",
27
27
  "tsup": "^7.0.0",
28
28
  "typescript": "^5.0.0"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
29
32
  }
30
33
  }