@owney/sdk 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -603,13 +603,83 @@ type DepositCallback = (
603
603
  ) => Promise<`0x${string}`> | `0x${string}`;
604
604
  ```
605
605
 
606
- ### Error Classes
606
+ ### Error Handling
607
607
 
608
- | Error | Thrown when |
609
- |-------|------------|
610
- | `NotConnectedError` | A wallet-dependent method is called before `connect()` |
611
- | `AgentNotFoundError` | An unknown agent ID is passed (e.g. a typo) |
612
- | `AgentChainIncompatibleError` | `activateAgent` is called with agents that don't support the given chain. Exposes `incompatibleAgents` and `connectedChainId` properties for programmatic handling. |
608
+ All errors thrown by the SDK are instances of `OwneyError` (which extends `Error`), each carrying a stable `code` string and optional `details` object for programmatic handling.
609
+
610
+ ```typescript
611
+ import { OwneyError } from "@owney/sdk";
612
+
613
+ try {
614
+ await sdk.getBalances();
615
+ } catch (error) {
616
+ if (error instanceof OwneyError) {
617
+ switch (error.code) {
618
+ case "NOT_CONNECTED":
619
+ // prompt user to connect wallet
620
+ break;
621
+ case "NO_ACTIVE_CHAIN":
622
+ // prompt user to activate an agent
623
+ break;
624
+ case "BALANCE_ALL_FAILED":
625
+ // all agents failed to return balances
626
+ break;
627
+ default:
628
+ console.error(`[${error.code}] ${error.message}`, error.details);
629
+ }
630
+ }
631
+ }
632
+ ```
633
+
634
+ ```typescript
635
+ type OwneyErrorCode =
636
+ // Connection & wallet
637
+ | "NOT_CONNECTED" // Wallet-dependent method called before connect()
638
+ | "NO_ACTIVE_CHAIN" // Method called before activateAgent()
639
+ | "WALLET_NO_ACCOUNTS" // Provider returned no accounts during connect()
640
+ | "WALLET_ADDRESS_REQUIRED" // Wallet address missing during agent auth
641
+ // Agent resolution
642
+ | "AGENT_NOT_FOUND" // Unknown agent ID passed
643
+ | "AGENT_CHAIN_INCOMPATIBLE" // Agent(s) don't support the given chain
644
+ | "AGENT_EMPTY_LIST" // Empty agentId array passed to activateAgent()
645
+ // Chain
646
+ | "CHAIN_UNSUPPORTED" // Chain ID not in supported list (8453, 42161)
647
+ | "CHAIN_NO_COMPATIBLE_AGENTS" // No agents support the given chain
648
+ // Asset
649
+ | "ASSET_UNSUPPORTED" // Agent doesn't support the asset on the active chain
650
+ | "ASSET_NO_COMPATIBLE_AGENTS" // No agents support the asset on the active chain
651
+ // Deposit
652
+ | "DEPOSIT_AMOUNT_TOO_SMALL" // Amount too small to split across agents
653
+ | "DEPOSIT_CALLBACK_REQUIRED" // Sail agent requires a depositCallback
654
+ | "DEPOSIT_CALLBACK_INVALID" // depositCallback didn't return a tx hash
655
+ | "DEPOSIT_NO_PERMITTED_TOKENS" // No permitted tokens available for deposit
656
+ // Withdraw
657
+ | "WITHDRAW_NO_PERMITTED_TOKENS" // No permitted tokens available for withdrawal
658
+ // API
659
+ | "API_ROUTING_ERROR" // Routing API returned a non-OK HTTP status
660
+ | "API_ROUTING_FAILED" // Routing API returned { success: false }
661
+ | "API_SAIL_ERROR" // Sail API returned a non-OK HTTP status
662
+ | "API_SAIL_TIMEOUT" // Sail API request timed out
663
+ | "API_NO_AGENTS" // No supported agents returned by routing API
664
+ // Aggregation
665
+ | "BALANCE_ALL_FAILED" // All agents failed to return balances
666
+ | "ALLOCATION_ALL_FAILED" // All agents failed to return allocation data
667
+ // Validation
668
+ | "VALIDATION_INVALID_DAYS"; // Invalid days value (expected "7D", "14D", or "30D")
669
+
670
+ class OwneyError extends Error {
671
+ readonly code: OwneyErrorCode;
672
+ readonly details?: Record<string, unknown>;
673
+ }
674
+ ```
675
+
676
+ The three convenience subclasses extend `OwneyError` and remain backwards-compatible:
677
+
678
+ | Class | Code | Extra properties |
679
+ |-------|------|------------------|
680
+ | `NotConnectedError` | `NOT_CONNECTED` | — |
681
+ | `AgentNotFoundError` | `AGENT_NOT_FOUND` | — |
682
+ | `AgentChainIncompatibleError` | `AGENT_CHAIN_INCOMPATIBLE` | `incompatibleAgents`, `connectedChainId` |
613
683
 
614
684
  ## License
615
685
 
package/dist/index.cjs CHANGED
@@ -303,15 +303,6 @@ function mapApyByStrategy(raw) {
303
303
  }
304
304
 
305
305
  // src/agents/zyfai/zyfai.agent.ts
306
- var ZYFAI_TIMING_PREFIX = "[AgentTiming][zyfai]";
307
- function logTiming(label, startedAt, meta) {
308
- const elapsedMs = Date.now() - startedAt;
309
- if (meta) {
310
- console.log(`${ZYFAI_TIMING_PREFIX} ${label} ${elapsedMs}ms`, meta);
311
- return;
312
- }
313
- console.log(`${ZYFAI_TIMING_PREFIX} ${label} ${elapsedMs}ms`);
314
- }
315
306
  var ZyfaiAgent = class {
316
307
  id = "zyfai";
317
308
  supportedChainIds = [8453, 42161];
@@ -332,8 +323,8 @@ var ZyfaiAgent = class {
332
323
  connectedChainId = null;
333
324
  smartWalletCache = /* @__PURE__ */ new Map();
334
325
  connectAuthPromise = null;
335
- constructor(apiKey) {
336
- this.sdk = new import_sdk.ZyfaiSDK({ apiKey });
326
+ constructor(apiKey, rpcUrls) {
327
+ this.sdk = new import_sdk.ZyfaiSDK({ apiKey, rpcUrls });
337
328
  }
338
329
  // --- Private helpers ---
339
330
  getAddress() {
@@ -347,17 +338,12 @@ var ZyfaiAgent = class {
347
338
  }
348
339
  /** Light connect: SIWE auth only. Re-auths if chain changed. */
349
340
  async connectAuth(state, chainId) {
350
- const startedAt = Date.now();
351
341
  const validChainId = isValidChainId(chainId);
352
342
  if (this.connectedAddress && this.connectedChainId === validChainId) {
353
- logTiming("connectAuth cache-hit", startedAt, { chainId: validChainId });
354
343
  return;
355
344
  }
356
345
  if (this.connectAuthPromise) {
357
346
  await this.connectAuthPromise;
358
- logTiming("connectAuth awaited-inflight", startedAt, {
359
- chainId: validChainId
360
- });
361
347
  return;
362
348
  }
363
349
  this.connectAuthPromise = (async () => {
@@ -370,69 +356,40 @@ var ZyfaiAgent = class {
370
356
  })();
371
357
  try {
372
358
  await this.connectAuthPromise;
373
- logTiming("connectAuth success", startedAt, { chainId: validChainId });
374
359
  } finally {
375
360
  this.connectAuthPromise = null;
376
361
  }
377
362
  }
378
363
  /** Full connect: SIWE auth + Safe deploy check + session key. */
379
364
  async connectFull(state, chainId) {
380
- const startedAt = Date.now();
381
365
  await this.connectAuth(state, chainId);
382
366
  const validChainId = isValidChainId(chainId);
383
367
  const address = this.getAddress();
384
- const walletLookupStart = Date.now();
385
368
  const wallet = await this.sdk.getSmartWalletAddress(address, validChainId);
386
- logTiming("connectFull getSmartWalletAddress", walletLookupStart, {
387
- chainId: validChainId
388
- });
389
369
  this.smartWalletCache.set(`${address}_${validChainId}`, wallet.address);
390
370
  if (!wallet.isDeployed) {
391
- const deployStart = Date.now();
392
371
  await this.sdk.deploySafe(address, validChainId, "aggressive", true);
393
- logTiming("connectFull deploySafe", deployStart, {
394
- chainId: validChainId
395
- });
396
372
  }
397
- const userDetailsStart = Date.now();
398
373
  const user = await this.sdk.getUserDetails();
399
- logTiming("connectFull getUserDetails", userDetailsStart, {
400
- chainId: validChainId
401
- });
402
374
  if (!user.hasActiveSessionKey) {
403
- const sessionKeyStart = Date.now();
404
375
  await this.sdk.createSessionKey(address, validChainId);
405
- logTiming("connectFull createSessionKey", sessionKeyStart, {
406
- chainId: validChainId
407
- });
408
376
  }
409
- logTiming("connectFull success", startedAt, { chainId: validChainId });
410
377
  }
411
378
  /** Connect + resolve smart wallet address for read operations. */
412
379
  async resolveSmartWallet(state, chainId) {
413
- const startedAt = Date.now();
414
380
  await this.connectAuth(state, chainId);
415
381
  const validChainId = isValidChainId(chainId);
416
382
  const ownerAddress = this.getAddress();
417
383
  const cacheKey = `${ownerAddress}_${validChainId}`;
418
384
  let smartWallet = this.smartWalletCache.get(cacheKey);
419
385
  if (!smartWallet) {
420
- const lookupStart = Date.now();
421
386
  const { address } = await this.sdk.getSmartWalletAddress(
422
387
  ownerAddress,
423
388
  validChainId
424
389
  );
425
- logTiming("resolveSmartWallet remote-lookup", lookupStart, {
426
- chainId: validChainId
427
- });
428
390
  smartWallet = address;
429
391
  this.smartWalletCache.set(cacheKey, smartWallet);
430
- } else {
431
- logTiming("resolveSmartWallet cache-hit", startedAt, {
432
- chainId: validChainId
433
- });
434
392
  }
435
- logTiming("resolveSmartWallet ready", startedAt, { chainId: validChainId });
436
393
  return { smartWallet, chainId: validChainId };
437
394
  }
438
395
  // --- IAgent: Connection lifecycle ---
@@ -492,14 +449,8 @@ var ZyfaiAgent = class {
492
449
  }
493
450
  // --- IAgent: Portfolio reads ---
494
451
  async getBalances(state, chainId) {
495
- const startedAt = Date.now();
496
452
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
497
- const portfolioStart = Date.now();
498
453
  const raw = await this.sdk.getPortfolio(this.getAddress());
499
- logTiming("getBalances getPortfolio", portfolioStart, {
500
- chainId: validChainId
501
- });
502
- logTiming("getBalances success", startedAt, { chainId: validChainId });
503
454
  return mapBalances(raw, validChainId, smartWallet);
504
455
  }
505
456
  async getEarnings(state, chainId) {
@@ -564,13 +515,13 @@ function mapWithdraw2(raw) {
564
515
  function mapPortfolioBalances(raw, smartWallet) {
565
516
  let total = 0;
566
517
  const tokens = [];
567
- for (const item of raw.result) {
568
- total += item.usd_value;
518
+ for (const item of raw.tokens) {
519
+ total += item.balanceFormatted;
569
520
  tokens.push({
570
- chain: item.chain.toUpperCase(),
571
- chainId: item.chain_id,
572
- asset: item.token === "USD\u20AE0" ? "USDT" : item.token,
573
- amount: String(item.usd_value)
521
+ chain: SUPPORTED_CHAINS[item.chain],
522
+ chainId: item.chain,
523
+ asset: item.symbol === "USD\u20AE0" ? "USDT" : item.symbol,
524
+ amount: item.balance
574
525
  });
575
526
  }
576
527
  return {
@@ -753,16 +704,7 @@ function remapApyPerAssetToSymbols(raw) {
753
704
  var SAIL_API_BASE = "https://app.sail.money";
754
705
  var PROJECT_ID = "sail";
755
706
  var PAGE_ID = "home";
756
- var SAIL_TIMING_PREFIX = "[AgentTiming][sail]";
757
707
  var SAIL_PORTFOLIO_TIMEOUT_MS = 8e3;
758
- function logTiming2(label, startedAt, meta) {
759
- const elapsedMs = Date.now() - startedAt;
760
- if (meta) {
761
- console.log(`${SAIL_TIMING_PREFIX} ${label} ${elapsedMs}ms`, meta);
762
- return;
763
- }
764
- console.log(`${SAIL_TIMING_PREFIX} ${label} ${elapsedMs}ms`);
765
- }
766
708
  var SailAgent = class {
767
709
  id = "sail";
768
710
  supportedChainIds = [8453, 42161];
@@ -835,7 +777,6 @@ var SailAgent = class {
835
777
  }
836
778
  /** Initiate SIWE and sign with the user's wallet. */
837
779
  async signSiwe(state, chainId) {
838
- const startedAt = Date.now();
839
780
  const initiate = await this.request(
840
781
  "POST",
841
782
  `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/auth/initiate`,
@@ -850,7 +791,6 @@ var SailAgent = class {
850
791
  method: "personal_sign",
851
792
  params: [initiate.message, state.walletAddress]
852
793
  });
853
- logTiming2("signSiwe success", startedAt, { chainId });
854
794
  return {
855
795
  sessionId: initiate.sessionId,
856
796
  message: initiate.message,
@@ -859,14 +799,11 @@ var SailAgent = class {
859
799
  }
860
800
  /** Full connect: auth handles smart account creation via SIWE flow. */
861
801
  async connectFull(state, chainId) {
862
- const startedAt = Date.now();
863
802
  if (this.connectedAddress && this.connectedChainId === chainId) {
864
- logTiming2("connectFull cache-hit", startedAt, { chainId });
865
803
  return;
866
804
  }
867
805
  if (this.connectPromise) {
868
806
  await this.connectPromise;
869
- logTiming2("connectFull awaited-inflight", startedAt, { chainId });
870
807
  return;
871
808
  }
872
809
  if (!state.walletAddress) {
@@ -899,13 +836,11 @@ var SailAgent = class {
899
836
  })();
900
837
  try {
901
838
  await this.connectPromise;
902
- logTiming2("connectFull success", startedAt, { chainId });
903
839
  } finally {
904
840
  this.connectPromise = null;
905
841
  }
906
842
  }
907
843
  async resolveSmartWallet(state, chainId) {
908
- const startedAt = Date.now();
909
844
  await this.connectFull(state, chainId);
910
845
  const validChainId = isValidChainId(chainId);
911
846
  if (!this.smartWalletAddress) {
@@ -914,7 +849,6 @@ var SailAgent = class {
914
849
  "Wallet not connected. Call sdk.connect() first."
915
850
  );
916
851
  }
917
- logTiming2("resolveSmartWallet ready", startedAt, { chainId: validChainId });
918
852
  return {
919
853
  smartWallet: this.smartWalletAddress,
920
854
  chainId: validChainId
@@ -1039,13 +973,9 @@ var SailAgent = class {
1039
973
  }
1040
974
  // --- IAgent: Portfolio reads ---
1041
975
  async getBalances(state, chainId) {
1042
- const startedAt = Date.now();
1043
976
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1044
- const portfolioStart = Date.now();
1045
977
  try {
1046
- const raw = await this.getMetricsPortfolio(state, chainId);
1047
- logTiming2("getBalances getMetricsPortfolio", portfolioStart, { chainId });
1048
- logTiming2("getBalances success", startedAt, { chainId });
978
+ const raw = await this.getPortfolio();
1049
979
  return mapPortfolioBalances(raw, smartWallet);
1050
980
  } catch (error) {
1051
981
  if (error instanceof OwneyError && error.code === "API_SAIL_TIMEOUT") {
@@ -1055,9 +985,8 @@ var SailAgent = class {
1055
985
  chainId
1056
986
  }
1057
987
  );
1058
- logTiming2("getBalances timeout-fallback", startedAt, { chainId });
1059
988
  return mapPortfolioBalances(
1060
- { message: "timeout", result: [] },
989
+ { message: "timeout", tokens: [] },
1061
990
  smartWallet
1062
991
  );
1063
992
  }
@@ -1088,6 +1017,14 @@ var SailAgent = class {
1088
1017
  SAIL_PORTFOLIO_TIMEOUT_MS
1089
1018
  );
1090
1019
  }
1020
+ async getPortfolio() {
1021
+ return this.request(
1022
+ "GET",
1023
+ `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/portfolio/tokens`,
1024
+ void 0,
1025
+ SAIL_PORTFOLIO_TIMEOUT_MS
1026
+ );
1027
+ }
1091
1028
  async getMetricsEarnings(state, chainId) {
1092
1029
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1093
1030
  return this.request(
@@ -1095,7 +1032,7 @@ var SailAgent = class {
1095
1032
  `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/earnings?smart_account=${smartWallet}`
1096
1033
  );
1097
1034
  }
1098
- async getMetricsBalance(state, chainId, currency) {
1035
+ async getMetricsBalance(state, chainId, currency = "usd") {
1099
1036
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1100
1037
  return this.request(
1101
1038
  "GET",
@@ -1243,27 +1180,16 @@ async function fetchAgentKeys(apiKey) {
1243
1180
  }
1244
1181
 
1245
1182
  // src/client.ts
1246
- var AGENT_CONSTRUCTORS = {
1247
- zyfai: ZyfaiAgent,
1248
- sail: SailAgent
1249
- };
1250
- var SDK_TIMING_PREFIX = "[OwneySDKTiming]";
1251
- function logTiming3(label, startedAt, meta) {
1252
- const elapsedMs = Date.now() - startedAt;
1253
- if (meta) {
1254
- console.log(`${SDK_TIMING_PREFIX} ${label} ${elapsedMs}ms`, meta);
1255
- return;
1256
- }
1257
- console.log(`${SDK_TIMING_PREFIX} ${label} ${elapsedMs}ms`);
1258
- }
1259
1183
  var OwneySDK = class {
1260
1184
  agents = /* @__PURE__ */ new Map();
1261
1185
  activeAgents = /* @__PURE__ */ new Set();
1262
1186
  state = null;
1263
1187
  apiKey;
1188
+ zyfaiRpcUrls;
1264
1189
  initializingAgentsPromise = null;
1265
1190
  constructor(config) {
1266
1191
  this.apiKey = config.apiKey;
1192
+ this.zyfaiRpcUrls = config.zyfaiRpcUrls;
1267
1193
  }
1268
1194
  /**
1269
1195
  * Establish connection state for all subsequent SDK calls.
@@ -1347,10 +1273,9 @@ var OwneySDK = class {
1347
1273
  this.initializingAgentsPromise = (async () => {
1348
1274
  const agentKeys = await fetchAgentKeys(this.apiKey);
1349
1275
  for (const { key, agent_type } of agentKeys) {
1350
- const AgentClass = AGENT_CONSTRUCTORS[agent_type];
1351
- if (!AgentClass)
1276
+ const agent = this.createAgent(agent_type, key);
1277
+ if (!agent)
1352
1278
  continue;
1353
- const agent = new AgentClass(key);
1354
1279
  this.agents.set(agent_type, agent);
1355
1280
  }
1356
1281
  if (this.agents.size === 0) {
@@ -1367,6 +1292,15 @@ var OwneySDK = class {
1367
1292
  this.initializingAgentsPromise = null;
1368
1293
  }
1369
1294
  }
1295
+ createAgent(agentId, key) {
1296
+ if (agentId === "zyfai") {
1297
+ return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1298
+ }
1299
+ if (agentId === "sail") {
1300
+ return new SailAgent(key);
1301
+ }
1302
+ return null;
1303
+ }
1370
1304
  // --- Account lifecycle ---
1371
1305
  /**
1372
1306
  * Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
@@ -1379,7 +1313,6 @@ var OwneySDK = class {
1379
1313
  * throws before activating any agent.
1380
1314
  */
1381
1315
  async activateAgent(chainId, agentId) {
1382
- const startedAt = Date.now();
1383
1316
  const state = this.requireState();
1384
1317
  await this.ensureAgentsInitialized();
1385
1318
  if (agentId !== void 0) {
@@ -1407,20 +1340,11 @@ var OwneySDK = class {
1407
1340
  state.chainId = chainId;
1408
1341
  Promise.all(
1409
1342
  agents.map(async (agent) => {
1410
- const agentStart = Date.now();
1411
1343
  await agent.activateAgent(state, chainId);
1412
- logTiming3("activateAgent background-agent-ready", agentStart, {
1413
- chainId,
1414
- agentId: agent.id
1415
- });
1416
1344
  })
1417
1345
  ).catch((error) => {
1418
1346
  console.error("activateAgent background init failed:", error);
1419
1347
  });
1420
- logTiming3("activateAgent scheduled", startedAt, {
1421
- chainId,
1422
- agentIds: uniqueIds
1423
- });
1424
1348
  return;
1425
1349
  }
1426
1350
  const compatible = [...this.agents.values()].filter(
@@ -1440,20 +1364,11 @@ var OwneySDK = class {
1440
1364
  state.chainId = chainId;
1441
1365
  Promise.all(
1442
1366
  compatible.map(async (agent) => {
1443
- const agentStart = Date.now();
1444
1367
  await agent.activateAgent(state, chainId);
1445
- logTiming3("activateAgent background-agent-ready", agentStart, {
1446
- chainId,
1447
- agentId: agent.id
1448
- });
1449
1368
  })
1450
1369
  ).catch((error) => {
1451
1370
  console.error("activateAgent background init failed:", error);
1452
1371
  });
1453
- logTiming3("activateAgent scheduled", startedAt, {
1454
- chainId,
1455
- agentIds: compatible.map((agent) => agent.id)
1456
- });
1457
1372
  }
1458
1373
  /**
1459
1374
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
@@ -1578,12 +1493,10 @@ var OwneySDK = class {
1578
1493
  * @returns {AgentBalance} for a single agent, or {OwneyBalances} with totalBalance and per-agent breakdown
1579
1494
  */
1580
1495
  async getBalances(agentId) {
1581
- const startedAt = Date.now();
1582
1496
  const state = this.requireState();
1583
1497
  const chainId = this.requireChainId();
1584
1498
  if (agentId) {
1585
1499
  const result = await this.getAgent(agentId).getBalances(state, chainId);
1586
- logTiming3("getBalances single-agent", startedAt, { chainId, agentId });
1587
1500
  return result;
1588
1501
  }
1589
1502
  let totalBalance = 0;
@@ -1591,12 +1504,7 @@ var OwneySDK = class {
1591
1504
  const entries = [...this.getActiveAgents().entries()];
1592
1505
  const balanceResults = await Promise.allSettled(
1593
1506
  entries.map(async ([id, agent]) => {
1594
- const agentStartedAt = Date.now();
1595
1507
  const b = await agent.getBalances(state, chainId);
1596
- logTiming3("getBalances per-agent", agentStartedAt, {
1597
- chainId,
1598
- agentId: id
1599
- });
1600
1508
  return [id, b];
1601
1509
  })
1602
1510
  );
@@ -1617,11 +1525,6 @@ var OwneySDK = class {
1617
1525
  "Failed to fetch balances for all active agents."
1618
1526
  );
1619
1527
  }
1620
- logTiming3("getBalances aggregate", startedAt, {
1621
- chainId,
1622
- totalAgents: entries.length,
1623
- successCount
1624
- });
1625
1528
  return {
1626
1529
  totalBalance: String(totalBalance),
1627
1530
  agentBalances: results
package/dist/index.d.cts 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;
@@ -203,6 +209,7 @@ declare class OwneySDK {
203
209
  private activeAgents;
204
210
  private state;
205
211
  private apiKey;
212
+ private zyfaiRpcUrls?;
206
213
  private initializingAgentsPromise;
207
214
  constructor(config: OwneySDKConfig);
208
215
  /**
@@ -231,6 +238,7 @@ declare class OwneySDK {
231
238
  private getAgent;
232
239
  private getActiveAgents;
233
240
  private ensureAgentsInitialized;
241
+ private createAgent;
234
242
  /**
235
243
  * Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
236
244
  * Deploys the Safe contract and creates a session key if not already set up.
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;
@@ -203,6 +209,7 @@ declare class OwneySDK {
203
209
  private activeAgents;
204
210
  private state;
205
211
  private apiKey;
212
+ private zyfaiRpcUrls?;
206
213
  private initializingAgentsPromise;
207
214
  constructor(config: OwneySDKConfig);
208
215
  /**
@@ -231,6 +238,7 @@ declare class OwneySDK {
231
238
  private getAgent;
232
239
  private getActiveAgents;
233
240
  private ensureAgentsInitialized;
241
+ private createAgent;
234
242
  /**
235
243
  * Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
236
244
  * Deploys the Safe contract and creates a session key if not already set up.
package/dist/index.js CHANGED
@@ -273,15 +273,6 @@ 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
- }
285
276
  var ZyfaiAgent = class {
286
277
  id = "zyfai";
287
278
  supportedChainIds = [8453, 42161];
@@ -302,8 +293,8 @@ var ZyfaiAgent = class {
302
293
  connectedChainId = null;
303
294
  smartWalletCache = /* @__PURE__ */ new Map();
304
295
  connectAuthPromise = null;
305
- constructor(apiKey) {
306
- this.sdk = new ZyfaiSDK({ apiKey });
296
+ constructor(apiKey, rpcUrls) {
297
+ this.sdk = new ZyfaiSDK({ apiKey, rpcUrls });
307
298
  }
308
299
  // --- Private helpers ---
309
300
  getAddress() {
@@ -317,17 +308,12 @@ var ZyfaiAgent = class {
317
308
  }
318
309
  /** Light connect: SIWE auth only. Re-auths if chain changed. */
319
310
  async connectAuth(state, chainId) {
320
- const startedAt = Date.now();
321
311
  const validChainId = isValidChainId(chainId);
322
312
  if (this.connectedAddress && this.connectedChainId === validChainId) {
323
- logTiming("connectAuth cache-hit", startedAt, { chainId: validChainId });
324
313
  return;
325
314
  }
326
315
  if (this.connectAuthPromise) {
327
316
  await this.connectAuthPromise;
328
- logTiming("connectAuth awaited-inflight", startedAt, {
329
- chainId: validChainId
330
- });
331
317
  return;
332
318
  }
333
319
  this.connectAuthPromise = (async () => {
@@ -340,69 +326,40 @@ var ZyfaiAgent = class {
340
326
  })();
341
327
  try {
342
328
  await this.connectAuthPromise;
343
- logTiming("connectAuth success", startedAt, { chainId: validChainId });
344
329
  } finally {
345
330
  this.connectAuthPromise = null;
346
331
  }
347
332
  }
348
333
  /** Full connect: SIWE auth + Safe deploy check + session key. */
349
334
  async connectFull(state, chainId) {
350
- const startedAt = Date.now();
351
335
  await this.connectAuth(state, chainId);
352
336
  const validChainId = isValidChainId(chainId);
353
337
  const address = this.getAddress();
354
- const walletLookupStart = Date.now();
355
338
  const wallet = await this.sdk.getSmartWalletAddress(address, validChainId);
356
- logTiming("connectFull getSmartWalletAddress", walletLookupStart, {
357
- chainId: validChainId
358
- });
359
339
  this.smartWalletCache.set(`${address}_${validChainId}`, wallet.address);
360
340
  if (!wallet.isDeployed) {
361
- const deployStart = Date.now();
362
341
  await this.sdk.deploySafe(address, validChainId, "aggressive", true);
363
- logTiming("connectFull deploySafe", deployStart, {
364
- chainId: validChainId
365
- });
366
342
  }
367
- const userDetailsStart = Date.now();
368
343
  const user = await this.sdk.getUserDetails();
369
- logTiming("connectFull getUserDetails", userDetailsStart, {
370
- chainId: validChainId
371
- });
372
344
  if (!user.hasActiveSessionKey) {
373
- const sessionKeyStart = Date.now();
374
345
  await this.sdk.createSessionKey(address, validChainId);
375
- logTiming("connectFull createSessionKey", sessionKeyStart, {
376
- chainId: validChainId
377
- });
378
346
  }
379
- logTiming("connectFull success", startedAt, { chainId: validChainId });
380
347
  }
381
348
  /** Connect + resolve smart wallet address for read operations. */
382
349
  async resolveSmartWallet(state, chainId) {
383
- const startedAt = Date.now();
384
350
  await this.connectAuth(state, chainId);
385
351
  const validChainId = isValidChainId(chainId);
386
352
  const ownerAddress = this.getAddress();
387
353
  const cacheKey = `${ownerAddress}_${validChainId}`;
388
354
  let smartWallet = this.smartWalletCache.get(cacheKey);
389
355
  if (!smartWallet) {
390
- const lookupStart = Date.now();
391
356
  const { address } = await this.sdk.getSmartWalletAddress(
392
357
  ownerAddress,
393
358
  validChainId
394
359
  );
395
- logTiming("resolveSmartWallet remote-lookup", lookupStart, {
396
- chainId: validChainId
397
- });
398
360
  smartWallet = address;
399
361
  this.smartWalletCache.set(cacheKey, smartWallet);
400
- } else {
401
- logTiming("resolveSmartWallet cache-hit", startedAt, {
402
- chainId: validChainId
403
- });
404
362
  }
405
- logTiming("resolveSmartWallet ready", startedAt, { chainId: validChainId });
406
363
  return { smartWallet, chainId: validChainId };
407
364
  }
408
365
  // --- IAgent: Connection lifecycle ---
@@ -462,14 +419,8 @@ var ZyfaiAgent = class {
462
419
  }
463
420
  // --- IAgent: Portfolio reads ---
464
421
  async getBalances(state, chainId) {
465
- const startedAt = Date.now();
466
422
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
467
- const portfolioStart = Date.now();
468
423
  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
424
  return mapBalances(raw, validChainId, smartWallet);
474
425
  }
475
426
  async getEarnings(state, chainId) {
@@ -534,13 +485,13 @@ function mapWithdraw2(raw) {
534
485
  function mapPortfolioBalances(raw, smartWallet) {
535
486
  let total = 0;
536
487
  const tokens = [];
537
- for (const item of raw.result) {
538
- total += item.usd_value;
488
+ for (const item of raw.tokens) {
489
+ total += item.balanceFormatted;
539
490
  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)
491
+ chain: SUPPORTED_CHAINS[item.chain],
492
+ chainId: item.chain,
493
+ asset: item.symbol === "USD\u20AE0" ? "USDT" : item.symbol,
494
+ amount: item.balance
544
495
  });
545
496
  }
546
497
  return {
@@ -723,16 +674,7 @@ function remapApyPerAssetToSymbols(raw) {
723
674
  var SAIL_API_BASE = "https://app.sail.money";
724
675
  var PROJECT_ID = "sail";
725
676
  var PAGE_ID = "home";
726
- var SAIL_TIMING_PREFIX = "[AgentTiming][sail]";
727
677
  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
678
  var SailAgent = class {
737
679
  id = "sail";
738
680
  supportedChainIds = [8453, 42161];
@@ -805,7 +747,6 @@ var SailAgent = class {
805
747
  }
806
748
  /** Initiate SIWE and sign with the user's wallet. */
807
749
  async signSiwe(state, chainId) {
808
- const startedAt = Date.now();
809
750
  const initiate = await this.request(
810
751
  "POST",
811
752
  `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/auth/initiate`,
@@ -820,7 +761,6 @@ var SailAgent = class {
820
761
  method: "personal_sign",
821
762
  params: [initiate.message, state.walletAddress]
822
763
  });
823
- logTiming2("signSiwe success", startedAt, { chainId });
824
764
  return {
825
765
  sessionId: initiate.sessionId,
826
766
  message: initiate.message,
@@ -829,14 +769,11 @@ var SailAgent = class {
829
769
  }
830
770
  /** Full connect: auth handles smart account creation via SIWE flow. */
831
771
  async connectFull(state, chainId) {
832
- const startedAt = Date.now();
833
772
  if (this.connectedAddress && this.connectedChainId === chainId) {
834
- logTiming2("connectFull cache-hit", startedAt, { chainId });
835
773
  return;
836
774
  }
837
775
  if (this.connectPromise) {
838
776
  await this.connectPromise;
839
- logTiming2("connectFull awaited-inflight", startedAt, { chainId });
840
777
  return;
841
778
  }
842
779
  if (!state.walletAddress) {
@@ -869,13 +806,11 @@ var SailAgent = class {
869
806
  })();
870
807
  try {
871
808
  await this.connectPromise;
872
- logTiming2("connectFull success", startedAt, { chainId });
873
809
  } finally {
874
810
  this.connectPromise = null;
875
811
  }
876
812
  }
877
813
  async resolveSmartWallet(state, chainId) {
878
- const startedAt = Date.now();
879
814
  await this.connectFull(state, chainId);
880
815
  const validChainId = isValidChainId(chainId);
881
816
  if (!this.smartWalletAddress) {
@@ -884,7 +819,6 @@ var SailAgent = class {
884
819
  "Wallet not connected. Call sdk.connect() first."
885
820
  );
886
821
  }
887
- logTiming2("resolveSmartWallet ready", startedAt, { chainId: validChainId });
888
822
  return {
889
823
  smartWallet: this.smartWalletAddress,
890
824
  chainId: validChainId
@@ -1009,13 +943,9 @@ var SailAgent = class {
1009
943
  }
1010
944
  // --- IAgent: Portfolio reads ---
1011
945
  async getBalances(state, chainId) {
1012
- const startedAt = Date.now();
1013
946
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1014
- const portfolioStart = Date.now();
1015
947
  try {
1016
- const raw = await this.getMetricsPortfolio(state, chainId);
1017
- logTiming2("getBalances getMetricsPortfolio", portfolioStart, { chainId });
1018
- logTiming2("getBalances success", startedAt, { chainId });
948
+ const raw = await this.getPortfolio();
1019
949
  return mapPortfolioBalances(raw, smartWallet);
1020
950
  } catch (error) {
1021
951
  if (error instanceof OwneyError && error.code === "API_SAIL_TIMEOUT") {
@@ -1025,9 +955,8 @@ var SailAgent = class {
1025
955
  chainId
1026
956
  }
1027
957
  );
1028
- logTiming2("getBalances timeout-fallback", startedAt, { chainId });
1029
958
  return mapPortfolioBalances(
1030
- { message: "timeout", result: [] },
959
+ { message: "timeout", tokens: [] },
1031
960
  smartWallet
1032
961
  );
1033
962
  }
@@ -1058,6 +987,14 @@ var SailAgent = class {
1058
987
  SAIL_PORTFOLIO_TIMEOUT_MS
1059
988
  );
1060
989
  }
990
+ async getPortfolio() {
991
+ return this.request(
992
+ "GET",
993
+ `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/portfolio/tokens`,
994
+ void 0,
995
+ SAIL_PORTFOLIO_TIMEOUT_MS
996
+ );
997
+ }
1061
998
  async getMetricsEarnings(state, chainId) {
1062
999
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1063
1000
  return this.request(
@@ -1065,7 +1002,7 @@ var SailAgent = class {
1065
1002
  `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/earnings?smart_account=${smartWallet}`
1066
1003
  );
1067
1004
  }
1068
- async getMetricsBalance(state, chainId, currency) {
1005
+ async getMetricsBalance(state, chainId, currency = "usd") {
1069
1006
  const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1070
1007
  return this.request(
1071
1008
  "GET",
@@ -1213,27 +1150,16 @@ async function fetchAgentKeys(apiKey) {
1213
1150
  }
1214
1151
 
1215
1152
  // 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
1153
  var OwneySDK = class {
1230
1154
  agents = /* @__PURE__ */ new Map();
1231
1155
  activeAgents = /* @__PURE__ */ new Set();
1232
1156
  state = null;
1233
1157
  apiKey;
1158
+ zyfaiRpcUrls;
1234
1159
  initializingAgentsPromise = null;
1235
1160
  constructor(config) {
1236
1161
  this.apiKey = config.apiKey;
1162
+ this.zyfaiRpcUrls = config.zyfaiRpcUrls;
1237
1163
  }
1238
1164
  /**
1239
1165
  * Establish connection state for all subsequent SDK calls.
@@ -1317,10 +1243,9 @@ var OwneySDK = class {
1317
1243
  this.initializingAgentsPromise = (async () => {
1318
1244
  const agentKeys = await fetchAgentKeys(this.apiKey);
1319
1245
  for (const { key, agent_type } of agentKeys) {
1320
- const AgentClass = AGENT_CONSTRUCTORS[agent_type];
1321
- if (!AgentClass)
1246
+ const agent = this.createAgent(agent_type, key);
1247
+ if (!agent)
1322
1248
  continue;
1323
- const agent = new AgentClass(key);
1324
1249
  this.agents.set(agent_type, agent);
1325
1250
  }
1326
1251
  if (this.agents.size === 0) {
@@ -1337,6 +1262,15 @@ var OwneySDK = class {
1337
1262
  this.initializingAgentsPromise = null;
1338
1263
  }
1339
1264
  }
1265
+ createAgent(agentId, key) {
1266
+ if (agentId === "zyfai") {
1267
+ return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1268
+ }
1269
+ if (agentId === "sail") {
1270
+ return new SailAgent(key);
1271
+ }
1272
+ return null;
1273
+ }
1340
1274
  // --- Account lifecycle ---
1341
1275
  /**
1342
1276
  * Activate the user's smart wallet for the specified agents, or all chain-compatible agents if omitted.
@@ -1349,7 +1283,6 @@ var OwneySDK = class {
1349
1283
  * throws before activating any agent.
1350
1284
  */
1351
1285
  async activateAgent(chainId, agentId) {
1352
- const startedAt = Date.now();
1353
1286
  const state = this.requireState();
1354
1287
  await this.ensureAgentsInitialized();
1355
1288
  if (agentId !== void 0) {
@@ -1377,20 +1310,11 @@ var OwneySDK = class {
1377
1310
  state.chainId = chainId;
1378
1311
  Promise.all(
1379
1312
  agents.map(async (agent) => {
1380
- const agentStart = Date.now();
1381
1313
  await agent.activateAgent(state, chainId);
1382
- logTiming3("activateAgent background-agent-ready", agentStart, {
1383
- chainId,
1384
- agentId: agent.id
1385
- });
1386
1314
  })
1387
1315
  ).catch((error) => {
1388
1316
  console.error("activateAgent background init failed:", error);
1389
1317
  });
1390
- logTiming3("activateAgent scheduled", startedAt, {
1391
- chainId,
1392
- agentIds: uniqueIds
1393
- });
1394
1318
  return;
1395
1319
  }
1396
1320
  const compatible = [...this.agents.values()].filter(
@@ -1410,20 +1334,11 @@ var OwneySDK = class {
1410
1334
  state.chainId = chainId;
1411
1335
  Promise.all(
1412
1336
  compatible.map(async (agent) => {
1413
- const agentStart = Date.now();
1414
1337
  await agent.activateAgent(state, chainId);
1415
- logTiming3("activateAgent background-agent-ready", agentStart, {
1416
- chainId,
1417
- agentId: agent.id
1418
- });
1419
1338
  })
1420
1339
  ).catch((error) => {
1421
1340
  console.error("activateAgent background init failed:", error);
1422
1341
  });
1423
- logTiming3("activateAgent scheduled", startedAt, {
1424
- chainId,
1425
- agentIds: compatible.map((agent) => agent.id)
1426
- });
1427
1342
  }
1428
1343
  /**
1429
1344
  * Deposit funds into a specific agent, or split equally across all agents if agentId is omitted.
@@ -1548,12 +1463,10 @@ var OwneySDK = class {
1548
1463
  * @returns {AgentBalance} for a single agent, or {OwneyBalances} with totalBalance and per-agent breakdown
1549
1464
  */
1550
1465
  async getBalances(agentId) {
1551
- const startedAt = Date.now();
1552
1466
  const state = this.requireState();
1553
1467
  const chainId = this.requireChainId();
1554
1468
  if (agentId) {
1555
1469
  const result = await this.getAgent(agentId).getBalances(state, chainId);
1556
- logTiming3("getBalances single-agent", startedAt, { chainId, agentId });
1557
1470
  return result;
1558
1471
  }
1559
1472
  let totalBalance = 0;
@@ -1561,12 +1474,7 @@ var OwneySDK = class {
1561
1474
  const entries = [...this.getActiveAgents().entries()];
1562
1475
  const balanceResults = await Promise.allSettled(
1563
1476
  entries.map(async ([id, agent]) => {
1564
- const agentStartedAt = Date.now();
1565
1477
  const b = await agent.getBalances(state, chainId);
1566
- logTiming3("getBalances per-agent", agentStartedAt, {
1567
- chainId,
1568
- agentId: id
1569
- });
1570
1478
  return [id, b];
1571
1479
  })
1572
1480
  );
@@ -1587,11 +1495,6 @@ var OwneySDK = class {
1587
1495
  "Failed to fetch balances for all active agents."
1588
1496
  );
1589
1497
  }
1590
- logTiming3("getBalances aggregate", startedAt, {
1591
- chainId,
1592
- totalAgents: entries.length,
1593
- successCount
1594
- });
1595
1498
  return {
1596
1499
  totalBalance: String(totalBalance),
1597
1500
  agentBalances: 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.8",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",