@owney/sdk 0.2.10 → 0.2.12

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.js CHANGED
@@ -98,15 +98,6 @@ function hexToDecimal(hex, decimals = 6) {
98
98
  const remainder = parsed % divisor;
99
99
  return Number(whole) + Number(remainder) / Number(divisor);
100
100
  }
101
- function normalizeDecimalPlace(value, decimals = 6) {
102
- const parsed = BigInt(value);
103
- if (decimals <= 0)
104
- return Number(parsed);
105
- const divisor = BigInt(10 ** decimals);
106
- const whole = parsed / divisor;
107
- const remainder = parsed % divisor;
108
- return Number(whole) + Number(remainder) / Number(divisor);
109
- }
110
101
  var DayFilterMapping = {
111
102
  "30D": 30,
112
103
  "14D": 14,
@@ -132,34 +123,25 @@ var CHAIN_ID_TO_NAME = {
132
123
  8453: "BASE",
133
124
  42161: "ARBITRUM"
134
125
  };
135
- var CHAIN_NAME_TO_ID = {
136
- BASE: 8453,
137
- ARBITRUM: 42161
138
- };
139
- function mapBalances(raw, chainId, smartWallet) {
126
+ function mapBalances(raw, _chainId, smartWallet) {
140
127
  const portfolio = raw.portfolio;
141
- const tokenMap = /* @__PURE__ */ new Map();
142
- for (const p of portfolio.positions || []) {
143
- const symbol = p.token_symbol || "USDC";
144
- const positionChainId = (p.chain ? CHAIN_NAME_TO_ID[p.chain.toUpperCase()] : void 0) ?? chainId;
145
- const key = `${symbol}:${positionChainId}`;
146
- const current = tokenMap.get(key);
147
- tokenMap.set(key, {
148
- symbol,
149
- chainId: positionChainId,
150
- amount: (current?.amount ?? 0) + normalizeDecimalPlace(p.underlyingAmount || "0")
151
- });
152
- }
128
+ const portfolioByChain = portfolio.portfolioByChain ?? {};
153
129
  let totalBalance = 0;
154
130
  const tokens = [];
155
- for (const [, entry] of tokenMap) {
156
- totalBalance += entry.amount;
157
- tokens.push({
158
- chain: CHAIN_ID_TO_NAME[entry.chainId] ?? "BASE",
159
- chainId: entry.chainId,
160
- asset: entry.symbol,
161
- amount: String(entry.amount)
162
- });
131
+ for (const [chainIdKey, tokensBySymbol] of Object.entries(portfolioByChain)) {
132
+ const positionChainId = Number(chainIdKey);
133
+ for (const [symbol, { balance, decimals }] of Object.entries(
134
+ tokensBySymbol ?? {}
135
+ )) {
136
+ const amount = hexToDecimal(balance || "0", decimals);
137
+ totalBalance += amount;
138
+ tokens.push({
139
+ chain: CHAIN_ID_TO_NAME[positionChainId] ?? "BASE",
140
+ chainId: positionChainId,
141
+ asset: symbol,
142
+ amount: String(amount)
143
+ });
144
+ }
163
145
  }
164
146
  return {
165
147
  smartWallet,
@@ -185,7 +167,7 @@ function mapApyHistory(raw) {
185
167
  weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0
186
168
  };
187
169
  }
188
- function mapHistory(raw) {
170
+ function mapHistory(raw, chainId) {
189
171
  const actionMap = {
190
172
  "Deposit to protocol": "Deposit",
191
173
  "Top up wallet": "Top up",
@@ -194,7 +176,7 @@ function mapHistory(raw) {
194
176
  };
195
177
  return {
196
178
  total: raw.total,
197
- data: raw.data.map((entry) => {
179
+ data: raw.data.filter((d) => d.chainId === chainId).map((entry) => {
198
180
  const rawLog = entry.rebalanceLog;
199
181
  const positions = entry.positions ?? [];
200
182
  let rebalanceLog = [];
@@ -227,7 +209,9 @@ function mapHistory(raw) {
227
209
  txHashes: entry.transactionHash ? [entry.transactionHash] : [],
228
210
  chainId: entry.chainId,
229
211
  tokenSymbol: entry?.positions?.[0]?.token_symbol,
230
- amount: String(hexToDecimal(entry?.positions?.[0]?.amount || "0x"))
212
+ amount: String(
213
+ hexToDecimal(entry?.positions?.[0]?.amount || "0x")
214
+ )
231
215
  }
232
216
  ],
233
217
  rebalanceLog
@@ -453,7 +437,7 @@ var ZyfaiAgent = class {
453
437
  async getHistory(state, chainId, options) {
454
438
  const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
455
439
  const raw = await this.sdk.getHistory(smartWallet, validChainId, options);
456
- return mapHistory(raw);
440
+ return mapHistory(raw, validChainId);
457
441
  }
458
442
  // --- IAgent: Agent control ---
459
443
  async pause(state, chainId) {
@@ -484,691 +468,6 @@ var ZyfaiAgent = class {
484
468
  }
485
469
  };
486
470
 
487
- // src/agents/sail/sail.mapper.ts
488
- function mapDeposit2(raw) {
489
- return {
490
- txHash: raw.txHash,
491
- smartWallet: raw.smartWallet,
492
- amount: raw.amount
493
- };
494
- }
495
- function mapWithdraw2(raw) {
496
- return {
497
- txHash: raw.txHash,
498
- type: raw.type,
499
- amount: raw.amount
500
- };
501
- }
502
- function mapPortfolioBalances(raw, smartWallet) {
503
- let total = 0;
504
- const tokens = [];
505
- for (const item of raw.tokens) {
506
- total += item.balanceFormatted;
507
- tokens.push({
508
- chain: SUPPORTED_CHAINS[item.chain],
509
- chainId: item.chain,
510
- asset: item.symbol === "USD\u20AE0" ? "USDT" : item.symbol,
511
- amount: item.balance
512
- });
513
- }
514
- return {
515
- smartWallet,
516
- totalBalance: String(total),
517
- tokens
518
- };
519
- }
520
- function mapEarnings2(raw, smartWallet) {
521
- return {
522
- smartWallet,
523
- lifetimeEarnings: raw.result
524
- };
525
- }
526
- function mapApyHistory2(raw, walletAddress) {
527
- const apyPerAsset = remapApyPerAssetToSymbols(raw.result.apy_per_asset);
528
- return {
529
- walletAddress,
530
- weightedApyAfterFee: raw.result.apy,
531
- weightedApyAfterFeeDetails: apyPerAsset ? { apyPerAsset } : void 0
532
- };
533
- }
534
- function mapSailTransaction(tx) {
535
- switch (tx.type) {
536
- case "deposit":
537
- case "redeem":
538
- return {
539
- txHashes: tx.tx_hashes,
540
- chainId: tx.chain_id,
541
- tokenSymbol: tx.asset,
542
- amount: String(tx.amount)
543
- };
544
- case "swap":
545
- return {
546
- txHashes: tx.tx_hashes,
547
- chainId: tx.chain_id,
548
- tokenSymbol: tx.from_asset,
549
- amount: String(tx.amount)
550
- };
551
- case "bridge":
552
- return {
553
- txHashes: tx.tx_hashes,
554
- chainId: Number(tx.from_chain_id),
555
- tokenSymbol: tx.asset,
556
- amount: String(tx.amount)
557
- };
558
- }
559
- }
560
- function buildRebalanceLogs(transactions, failedTransactions) {
561
- const redeems = transactions.filter(
562
- (tx) => tx.type === "redeem"
563
- );
564
- const deposits = transactions.filter(
565
- (tx) => tx.type === "deposit"
566
- );
567
- const failedRedeems = failedTransactions.filter(
568
- (tx) => tx.type === "redeem"
569
- );
570
- const failedDeposits = failedTransactions.filter(
571
- (tx) => tx.type === "deposit"
572
- );
573
- const logs = [];
574
- const matchedDeposits = /* @__PURE__ */ new Set();
575
- const matchedRedeems = /* @__PURE__ */ new Set();
576
- for (let r = 0; r < redeems.length; r++) {
577
- const idx = deposits.findIndex(
578
- (d, i) => !matchedDeposits.has(i) && d.amount === redeems[r].amount
579
- );
580
- if (idx !== -1) {
581
- matchedDeposits.add(idx);
582
- matchedRedeems.add(r);
583
- logs.push({
584
- fromProtocol: redeems[r].protocol_name,
585
- toProtocol: deposits[idx].protocol_name,
586
- tokenSymbol: redeems[r].asset,
587
- amount: String(redeems[r].amount),
588
- status: "success"
589
- });
590
- }
591
- }
592
- for (let i = 0; i < deposits.length; i++) {
593
- if (matchedDeposits.has(i))
594
- continue;
595
- const failedRedeem = failedRedeems.find(
596
- (fr) => fr.amount === deposits[i].amount
597
- );
598
- logs.push({
599
- fromProtocol: failedRedeem ? failedRedeem.protocol_name : "Wallet",
600
- toProtocol: deposits[i].protocol_name,
601
- tokenSymbol: deposits[i].asset,
602
- amount: String(deposits[i].amount),
603
- status: failedRedeem ? "failed" : "success"
604
- });
605
- }
606
- for (let i = 0; i < redeems.length; i++) {
607
- if (matchedRedeems.has(i))
608
- continue;
609
- const failedDeposit = failedDeposits.find(
610
- (fd) => fd.amount === redeems[i].amount
611
- );
612
- logs.push({
613
- fromProtocol: redeems[i].protocol_name,
614
- toProtocol: failedDeposit ? failedDeposit.protocol_name : "Wallet",
615
- tokenSymbol: redeems[i].asset,
616
- amount: String(redeems[i].amount),
617
- status: failedDeposit ? "failed" : "success"
618
- });
619
- }
620
- return logs;
621
- }
622
- function mapHistory2(raw) {
623
- const actionMap = {
624
- execution: "Rebalance",
625
- deposit: "Top up",
626
- withdraw: "Withdraw",
627
- rewards: "Earned"
628
- };
629
- const filtered = raw.result.items.filter(
630
- (i) => !(i.type === "execution" && (i.status === "failed" || !i.transactions.length))
631
- );
632
- return {
633
- total: filtered.length,
634
- data: filtered.map((entry) => ({
635
- agent: "sail",
636
- action: actionMap[entry.type] ?? entry.type,
637
- date: entry.time,
638
- newApy: String(entry.new_apy),
639
- oldApy: String(entry.previous_apy),
640
- transactions: (entry.transactions ?? []).map(mapSailTransaction),
641
- rebalanceLog: buildRebalanceLogs(
642
- entry.transactions ?? [],
643
- entry.failed_transactions ?? []
644
- )
645
- }))
646
- };
647
- }
648
- function mapAgentStatus2(raw) {
649
- return {
650
- success: raw.success,
651
- strategy: raw.strategy,
652
- protocols: raw.protocols
653
- };
654
- }
655
- function mapUserProfile2(raw) {
656
- return {
657
- address: raw.result.smart_account,
658
- smartWallet: raw.result.smart_account,
659
- chains: [],
660
- hasActiveSessionKey: false,
661
- protocols: []
662
- };
663
- }
664
- function mapApyByStrategy2(raw) {
665
- const apyPerAsset = remapApyPerAssetToSymbols(raw.result.apy_per_asset);
666
- return {
667
- averageApy: raw.result.apy,
668
- detailedApys: apyPerAsset ? { apyPerAsset } : void 0
669
- };
670
- }
671
- function remapApyPerAssetToSymbols(raw) {
672
- if (!raw)
673
- return void 0;
674
- const remapped = {};
675
- for (const asset of SupportedAssets) {
676
- const chainKey = asset.chainId;
677
- const apyByAddress = raw[String(chainKey)];
678
- if (!apyByAddress)
679
- continue;
680
- const apy = apyByAddress[asset.address] ?? apyByAddress[asset.address.toLowerCase()];
681
- if (apy === void 0)
682
- continue;
683
- const bucket = remapped[chainKey] ?? {};
684
- bucket[asset.symbol] = apy;
685
- remapped[chainKey] = bucket;
686
- }
687
- return Object.keys(remapped).length > 0 ? remapped : void 0;
688
- }
689
-
690
- // src/agents/sail/sail.agent.ts
691
- import { parseUnits } from "viem";
692
- var SAIL_API_BASE = "https://app.sail.money";
693
- var PROJECT_ID = "sail";
694
- var PAGE_ID = "home";
695
- var SAIL_PORTFOLIO_TIMEOUT_MS = 8e3;
696
- var SailAgent = class {
697
- id = "sail";
698
- minDepositAmount = "4800000000";
699
- supportedChainIds = [8453, 42161];
700
- supportedAssets = [
701
- {
702
- chainId: 8453,
703
- chain: "BASE",
704
- assets: ["USDC"]
705
- },
706
- {
707
- chainId: 42161,
708
- chain: "ARBITRUM",
709
- assets: ["USDC", "USDT"]
710
- }
711
- ];
712
- apiKey;
713
- authToken = null;
714
- accountToken = null;
715
- connectedAddress = null;
716
- smartWalletAddress = null;
717
- connectedChainId = null;
718
- connectPromise = null;
719
- constructor(apiKey) {
720
- this.apiKey = apiKey;
721
- }
722
- // --- Private helpers ---
723
- async request(method, path, body, timeoutMs) {
724
- const headers = {
725
- "Content-Type": "application/json",
726
- "X-Business-API-Key": this.apiKey
727
- };
728
- if (this.authToken) {
729
- headers["Authorization"] = `Bearer ${this.authToken}`;
730
- }
731
- if (this.accountToken) {
732
- headers["X-Account-Token"] = this.accountToken;
733
- }
734
- const controller = new AbortController();
735
- const timeoutId = typeof timeoutMs === "number" && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
736
- let res;
737
- try {
738
- res = await fetch(`${SAIL_API_BASE}${path}`, {
739
- method,
740
- headers,
741
- body: body ? JSON.stringify(body) : void 0,
742
- signal: controller.signal
743
- });
744
- } catch (error) {
745
- if (error instanceof Error && error.name === "AbortError" && timeoutMs) {
746
- throw new OwneyError(
747
- "API_SAIL_TIMEOUT",
748
- `Sail API timeout ${timeoutMs}ms: ${method} ${path}`,
749
- { timeoutMs, method, path },
750
- this.id
751
- );
752
- }
753
- throw error;
754
- } finally {
755
- if (timeoutId)
756
- clearTimeout(timeoutId);
757
- }
758
- if (!res.ok) {
759
- const text = await res.text().catch(() => "");
760
- throw new OwneyError(
761
- "API_SAIL_ERROR",
762
- `Sail API error ${res.status}: ${text}`,
763
- { statusCode: res.status, method, path, responseBody: text },
764
- this.id
765
- );
766
- }
767
- return res.json();
768
- }
769
- /** Initiate SIWE and sign with the user's wallet. */
770
- async signSiwe(state, chainId) {
771
- const initiate = await this.request(
772
- "POST",
773
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/auth/initiate`,
774
- {
775
- method: "siwe",
776
- address: state.walletAddress,
777
- chainId,
778
- identityMode: "byWallet"
779
- }
780
- );
781
- const signature = await state.provider.request({
782
- method: "personal_sign",
783
- params: [initiate.message, state.walletAddress]
784
- });
785
- return {
786
- sessionId: initiate.sessionId,
787
- message: initiate.message,
788
- signature
789
- };
790
- }
791
- /** Full connect: auth handles smart account creation via SIWE flow. */
792
- async connectFull(state, chainId) {
793
- if (this.connectedAddress && this.connectedChainId === chainId) {
794
- return;
795
- }
796
- if (this.connectPromise) {
797
- await this.connectPromise;
798
- return;
799
- }
800
- if (!state.walletAddress) {
801
- throw new OwneyError(
802
- "WALLET_ADDRESS_REQUIRED",
803
- "Wallet address is required. Call sdk.connect(provider) first.",
804
- void 0,
805
- this.id
806
- );
807
- }
808
- this.connectPromise = (async () => {
809
- const { sessionId, signature, message } = await this.signSiwe(
810
- state,
811
- chainId
812
- );
813
- const complete = await this.request(
814
- "POST",
815
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/auth/complete`,
816
- {
817
- method: "custom",
818
- sessionId,
819
- signature,
820
- walletAddress: state.walletAddress,
821
- identityMode: "byWallet"
822
- }
823
- );
824
- this.authToken = complete.token;
825
- this.accountToken = complete.accountToken;
826
- this.connectedAddress = state.walletAddress;
827
- this.smartWalletAddress = complete.walletAddress;
828
- this.connectedChainId = chainId;
829
- })();
830
- try {
831
- await this.connectPromise;
832
- } finally {
833
- this.connectPromise = null;
834
- }
835
- }
836
- async resolveSmartWallet(state, chainId) {
837
- await this.connectFull(state, chainId);
838
- const validChainId = isValidChainId(chainId);
839
- if (!this.smartWalletAddress) {
840
- throw new OwneyError(
841
- "NOT_CONNECTED",
842
- "Wallet not connected. Call sdk.connect() first.",
843
- void 0,
844
- this.id
845
- );
846
- }
847
- return {
848
- smartWallet: this.smartWalletAddress,
849
- chainId: validChainId
850
- };
851
- }
852
- // --- IAgent: Connection lifecycle ---
853
- async disconnect() {
854
- this.authToken = null;
855
- this.accountToken = null;
856
- this.connectedAddress = null;
857
- this.smartWalletAddress = null;
858
- this.connectedChainId = null;
859
- }
860
- // --- IAgent: Account lifecycle ---
861
- async activateAgent(state, chainId) {
862
- try {
863
- await this.connectFull(state, chainId);
864
- } catch (error) {
865
- await this.disconnect();
866
- throw error;
867
- }
868
- }
869
- async deposit(state, chainId, amount, depositCallback) {
870
- if (!depositCallback) {
871
- throw new OwneyError(
872
- "DEPOSIT_CALLBACK_REQUIRED",
873
- "depositCallback is required for Sail. Provide a callback that transfers tokens and returns the transaction hash.",
874
- void 0,
875
- this.id
876
- );
877
- }
878
- try {
879
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
880
- const depositInfo = await this.getDepositInfo();
881
- const resolvedTokenAddress = depositInfo.permittedTokens[0]?.address;
882
- if (!resolvedTokenAddress) {
883
- throw new OwneyError(
884
- "DEPOSIT_NO_PERMITTED_TOKENS",
885
- "No permitted tokens available for deposit.",
886
- void 0,
887
- this.id
888
- );
889
- }
890
- await this.executePreHooks(resolvedTokenAddress, amount, chainId);
891
- const txHash = await depositCallback(smartWallet, chainId, amount);
892
- if (!txHash) {
893
- throw new OwneyError(
894
- "DEPOSIT_CALLBACK_INVALID",
895
- "depositCallback must return a transaction hash (txHash) for Sail deposits.",
896
- void 0,
897
- this.id
898
- );
899
- }
900
- const postResult = await this.executePostHooks(
901
- resolvedTokenAddress,
902
- amount,
903
- chainId,
904
- txHash
905
- );
906
- return mapDeposit2({
907
- txHash: postResult.transactionHash,
908
- smartWallet,
909
- amount
910
- });
911
- } catch (error) {
912
- await this.disconnect();
913
- throw error;
914
- }
915
- }
916
- // --- Private deposit flow helpers ---
917
- async getDepositInfo() {
918
- return this.request(
919
- "GET",
920
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/deposit-info`
921
- );
922
- }
923
- async executePreHooks(tokenAddress, amount, chainId) {
924
- return this.request(
925
- "POST",
926
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/deposit/pre-hooks`,
927
- { tokenAddress, amount, chainId }
928
- );
929
- }
930
- async executePostHooks(tokenAddress, amount, chainId, txHash) {
931
- return this.request(
932
- "POST",
933
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/deposit/post-hooks`,
934
- { tokenAddress, amount, chainId, txHash }
935
- );
936
- }
937
- // --- Private withdraw flow helpers ---
938
- async getWithdrawInfo() {
939
- return this.request(
940
- "GET",
941
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/withdraw-info`
942
- );
943
- }
944
- // --- IAgent: Fund operations ---
945
- async withdraw(state, chainId, token, amount) {
946
- await this.connectFull(state, chainId);
947
- const withdrawInfo = await this.getWithdrawInfo();
948
- const selectedTokenAddress = SupportedAssets.find(
949
- (a) => a.symbol === token && a.chainId === chainId
950
- );
951
- if (!selectedTokenAddress) {
952
- throw new OwneyError(
953
- "WITHDRAW_NO_PERMITTED_TOKENS",
954
- "Unsupported asset.",
955
- void 0,
956
- this.id
957
- );
958
- }
959
- const tokenAddress = withdrawInfo.permittedTokens.find(
960
- (t) => t.address === selectedTokenAddress.address
961
- )?.address;
962
- if (!tokenAddress) {
963
- throw new OwneyError(
964
- "WITHDRAW_NO_PERMITTED_TOKENS",
965
- "No permitted tokens available for withdrawal.",
966
- void 0,
967
- this.id
968
- );
969
- }
970
- const resolvedAmount = amount ?? withdrawInfo.currentBalance;
971
- const { signature: adminWalletSignature, message: adminWalletPayload } = await this.signSiwe(state, chainId);
972
- const payload = {
973
- amount: String(resolvedAmount),
974
- tokenAddress,
975
- chainId,
976
- adminWalletSignature,
977
- adminWalletPayload
978
- };
979
- const raw = await this.request(
980
- "POST",
981
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/withdraw`,
982
- payload
983
- );
984
- return mapWithdraw2({
985
- txHash: raw.transactionHash,
986
- type: amount ? "partial" : "full",
987
- amount: parseUnits(
988
- resolvedAmount,
989
- selectedTokenAddress.decimals
990
- ).toString()
991
- });
992
- }
993
- // --- IAgent: Portfolio reads ---
994
- async getBalances(state, chainId) {
995
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
996
- try {
997
- const raw = await this.getPortfolio();
998
- return mapPortfolioBalances(raw, smartWallet);
999
- } catch (error) {
1000
- if (error instanceof OwneyError && error.code === "API_SAIL_TIMEOUT") {
1001
- console.warn(
1002
- "Sail portfolio request timed out; using empty snapshot.",
1003
- {
1004
- chainId
1005
- }
1006
- );
1007
- return mapPortfolioBalances(
1008
- { message: "timeout", tokens: [] },
1009
- smartWallet
1010
- );
1011
- }
1012
- throw error;
1013
- }
1014
- }
1015
- async getEarnings(state, chainId) {
1016
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1017
- const raw = await this.getMetricsEarnings(state, chainId);
1018
- return mapEarnings2(raw, smartWallet);
1019
- }
1020
- async getAccountApy(state, chainId, days) {
1021
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1022
- const raw = await this.getMetricsYield(days, state, chainId);
1023
- return mapApyHistory2(raw, smartWallet);
1024
- }
1025
- async getHistory(state, chainId, options) {
1026
- const raw = await this.getMetricsHistory(state, chainId, options);
1027
- return mapHistory2(raw);
1028
- }
1029
- // -- Sail-specific: Metrics ---
1030
- async getMetricsPortfolio(state, chainId) {
1031
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1032
- return this.request(
1033
- "GET",
1034
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/portfolio?${smartWallet ? `smart_account=${smartWallet}` : ""}`,
1035
- void 0,
1036
- SAIL_PORTFOLIO_TIMEOUT_MS
1037
- );
1038
- }
1039
- async getPortfolio() {
1040
- return this.request(
1041
- "GET",
1042
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/portfolio/tokens`,
1043
- void 0,
1044
- SAIL_PORTFOLIO_TIMEOUT_MS
1045
- );
1046
- }
1047
- async getMetricsEarnings(state, chainId) {
1048
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1049
- return this.request(
1050
- "GET",
1051
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/earnings?smart_account=${smartWallet}`
1052
- );
1053
- }
1054
- async getMetricsBalance(state, chainId, currency = "usd") {
1055
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1056
- return this.request(
1057
- "GET",
1058
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/balance?smart_account=${smartWallet}&currency=${currency}&limit=1000`
1059
- );
1060
- }
1061
- async getMetricsHistory(state, chainId, filters) {
1062
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1063
- const params = new URLSearchParams();
1064
- params.set("smart_account", smartWallet);
1065
- if (filters?.fromDate) {
1066
- params.set("start_date", filters.fromDate);
1067
- }
1068
- if (filters?.toDate) {
1069
- params.set("end_date", filters.toDate);
1070
- }
1071
- return this.request(
1072
- "GET",
1073
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/history?${params.toString()}`
1074
- );
1075
- }
1076
- async getMetricsUser(state, chainId, currency) {
1077
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1078
- return this.request(
1079
- "GET",
1080
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/user-metrics?smart_account=${smartWallet}&currency=${currency}`
1081
- );
1082
- }
1083
- async getMetricsYield(days, state, chainId) {
1084
- let walletAddress = "";
1085
- if (state && chainId) {
1086
- const { smartWallet } = await this.resolveSmartWallet(state, chainId);
1087
- walletAddress = smartWallet;
1088
- }
1089
- const dayCount = DayFilterMapping[days];
1090
- if (dayCount === void 0) {
1091
- throw new OwneyError(
1092
- "VALIDATION_INVALID_DAYS",
1093
- `Invalid days value: "${days}". Expected one of: "7D", "14D", "30D".`,
1094
- { days },
1095
- this.id
1096
- );
1097
- }
1098
- const now = /* @__PURE__ */ new Date();
1099
- const end = now.toISOString().split("T")[0];
1100
- const start = new Date(now.getTime() - dayCount * 864e5).toISOString().split("T")[0];
1101
- return this.request(
1102
- "GET",
1103
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/metrics/yield?start=${start}&end=${end}${walletAddress ? `&smart_account=${walletAddress}` : ""}`
1104
- );
1105
- }
1106
- // --- Sail-specific: Automation jobs ---
1107
- async getAutomationStatus(state, chainId) {
1108
- await this.connectFull(state, chainId);
1109
- return this.request(
1110
- "GET",
1111
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/automation/status`
1112
- );
1113
- }
1114
- async startAutomation(state, chainId, graphId, prompt, options) {
1115
- await this.connectFull(state, chainId);
1116
- return this.request(
1117
- "POST",
1118
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/automation/start`,
1119
- {
1120
- graphId,
1121
- prompt,
1122
- paramValues: options?.paramValues ?? {},
1123
- iterations: options?.iterations ?? 1,
1124
- branchId: options?.branchId
1125
- }
1126
- );
1127
- }
1128
- async pauseAutomation(state, chainId) {
1129
- await this.connectFull(state, chainId);
1130
- return this.request(
1131
- "POST",
1132
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/automation/pause`
1133
- );
1134
- }
1135
- async resumeAutomation(state, chainId) {
1136
- await this.connectFull(state, chainId);
1137
- return this.request(
1138
- "POST",
1139
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/automation/resume`
1140
- );
1141
- }
1142
- async stopAutomation(state, chainId) {
1143
- await this.connectFull(state, chainId);
1144
- return this.request(
1145
- "POST",
1146
- `/api/v1/projects/${PROJECT_ID}/pages/${PAGE_ID}/automation/stop`
1147
- );
1148
- }
1149
- // --- IAgent: Agent control ---
1150
- async pause(state, chainId) {
1151
- await this.connectFull(state, chainId);
1152
- await this.pauseAutomation(state, chainId);
1153
- return mapAgentStatus2({ success: true });
1154
- }
1155
- async resume(state, chainId) {
1156
- await this.connectFull(state, chainId);
1157
- await this.resumeAutomation(state, chainId);
1158
- return mapAgentStatus2({ success: true });
1159
- }
1160
- async getUserProfile(state, chainId) {
1161
- await this.connectFull(state, chainId);
1162
- const raw = await this.getMetricsUser(state, chainId, "usd");
1163
- return mapUserProfile2(raw);
1164
- }
1165
- // --- IAgent: Discovery (no wallet required) ---
1166
- async getAgentApy(days, _options) {
1167
- const raw = await this.getMetricsYield(days);
1168
- return mapApyByStrategy2(raw);
1169
- }
1170
- };
1171
-
1172
471
  // src/lib/routing-api.ts
1173
472
  var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
1174
473
  async function fetchAgentKeys(apiKey) {
@@ -1257,7 +556,7 @@ function sumWithdrawnAmount(results) {
1257
556
  }
1258
557
 
1259
558
  // src/client.ts
1260
- import { formatUnits, parseUnits as parseUnits2 } from "viem";
559
+ import { parseUnits } from "viem";
1261
560
  var OwneySDK = class {
1262
561
  agents = /* @__PURE__ */ new Map();
1263
562
  activeAgents = /* @__PURE__ */ new Set();
@@ -1374,9 +673,6 @@ var OwneySDK = class {
1374
673
  if (agentId === "zyfai") {
1375
674
  return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1376
675
  }
1377
- if (agentId === "sail") {
1378
- return new SailAgent(key);
1379
- }
1380
676
  return null;
1381
677
  }
1382
678
  // --- Account lifecycle ---
@@ -1600,7 +896,7 @@ var OwneySDK = class {
1600
896
  );
1601
897
  if (!tokenBalance)
1602
898
  return { agent, balance: 0n };
1603
- const balance = parseUnits2(tokenBalance.amount, assetInfo.decimals);
899
+ const balance = parseUnits(tokenBalance.amount, assetInfo.decimals);
1604
900
  return { agent, balance };
1605
901
  });
1606
902
  const totalAvailable = balances.reduce((sum, x) => sum + x.balance, 0n);
@@ -1627,7 +923,7 @@ var OwneySDK = class {
1627
923
  state,
1628
924
  chainId,
1629
925
  token,
1630
- p.agent.id === "sail" ? formatUnits(p.planned, assetInfo.decimals) : p.planned.toString()
926
+ p.planned.toString()
1631
927
  );
1632
928
  } catch (err) {
1633
929
  console.error(`withdraw failed for agent "${p.agent.id}":`, err);
@@ -1889,7 +1185,7 @@ var OwneySDK = class {
1889
1185
  * @param options.days - Lookback period: "7D", "14D", or "30D"
1890
1186
  * @param options.tokenSymbol - Optional asset symbol ("USDC" / "WETH") to
1891
1187
  * scope the APY to a specific asset+chain. Agents whose backends do not
1892
- * support per-asset APY (currently Sail) ignore this.
1188
+ * support per-asset APY ignore this.
1893
1189
  * @param options.chainId - Optional chain id for per-asset APY lookups.
1894
1190
  * Typically paired with `tokenSymbol`.
1895
1191
  * @returns {AgentApy} for a single agent, or {OwneyAgentApy} with per-agent APY