@defisaver/positions-sdk 2.1.33 → 2.1.35

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.
Files changed (40) hide show
  1. package/cjs/config/contracts.d.ts +91 -0
  2. package/cjs/config/contracts.js +9 -1
  3. package/cjs/contracts.d.ts +629 -0
  4. package/cjs/contracts.js +2 -1
  5. package/cjs/markets/aave/marketAssets.js +1 -1
  6. package/cjs/savings/index.d.ts +4 -3
  7. package/cjs/savings/index.js +43 -12
  8. package/cjs/savings/skyOptions/index.d.ts +7 -0
  9. package/cjs/savings/skyOptions/index.js +122 -0
  10. package/cjs/savings/skyOptions/options.d.ts +2 -0
  11. package/cjs/savings/skyOptions/options.js +11 -0
  12. package/cjs/types/savings/index.d.ts +3 -1
  13. package/cjs/types/savings/index.js +1 -0
  14. package/cjs/types/savings/sky.d.ts +11 -0
  15. package/cjs/types/savings/sky.js +7 -0
  16. package/esm/config/contracts.d.ts +91 -0
  17. package/esm/config/contracts.js +8 -0
  18. package/esm/contracts.d.ts +629 -0
  19. package/esm/contracts.js +1 -0
  20. package/esm/markets/aave/marketAssets.js +1 -1
  21. package/esm/savings/index.d.ts +4 -3
  22. package/esm/savings/index.js +43 -13
  23. package/esm/savings/skyOptions/index.d.ts +7 -0
  24. package/esm/savings/skyOptions/index.js +81 -0
  25. package/esm/savings/skyOptions/options.d.ts +2 -0
  26. package/esm/savings/skyOptions/options.js +8 -0
  27. package/esm/types/savings/index.d.ts +3 -1
  28. package/esm/types/savings/index.js +1 -0
  29. package/esm/types/savings/sky.d.ts +11 -0
  30. package/esm/types/savings/sky.js +4 -0
  31. package/package.json +1 -1
  32. package/src/aaveV3/index.ts +14 -3
  33. package/src/config/contracts.ts +8 -0
  34. package/src/contracts.ts +3 -1
  35. package/src/markets/aave/marketAssets.ts +1 -1
  36. package/src/savings/index.ts +38 -11
  37. package/src/savings/skyOptions/index.ts +95 -0
  38. package/src/savings/skyOptions/options.ts +9 -0
  39. package/src/types/savings/index.ts +3 -1
  40. package/src/types/savings/sky.ts +13 -0
@@ -7,12 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { MakerDsrType, } from '../types';
10
+ import { MakerDsrType, SkySavingsType, } from '../types';
11
11
  import * as morphoVaults from './morphoVaults';
12
12
  import * as yearnVaults from './yearnVaults';
13
13
  import * as makerDsr from './makerDsr';
14
+ import * as skyOptions from './skyOptions';
14
15
  import * as sparkSavingsVaults from './sparkSavingsVaults';
15
- export { morphoVaults, yearnVaults, makerDsr, sparkSavingsVaults, };
16
+ export { morphoVaults, yearnVaults, makerDsr, skyOptions, sparkSavingsVaults, };
16
17
  export const getSavingsData = (provider, network, accounts) => __awaiter(void 0, void 0, void 0, function* () {
17
18
  const morphoVaultsList = Object.keys(morphoVaults.morphoVaultsOptions.MORPHO_VAULTS);
18
19
  const yearnVaultsList = Object.keys(yearnVaults.yearnVaultsOptions.YEARN_VAULTS);
@@ -20,23 +21,52 @@ export const getSavingsData = (provider, network, accounts) => __awaiter(void 0,
20
21
  const savingsData = {};
21
22
  yield Promise.all([
22
23
  ...morphoVaultsList.map((vaultKey) => __awaiter(void 0, void 0, void 0, function* () {
23
- const vault = morphoVaults.morphoVaultsOptions.getMorphoVault(vaultKey);
24
- const data = yield morphoVaults.getMorphoVaultData(provider, network, vault, accounts);
25
- savingsData[vaultKey] = data;
24
+ try {
25
+ const vault = morphoVaults.morphoVaultsOptions.getMorphoVault(vaultKey);
26
+ const data = yield morphoVaults.getMorphoVaultData(provider, network, vault, accounts);
27
+ savingsData[vaultKey] = data;
28
+ }
29
+ catch (err) {
30
+ console.error(`[getSavingsData] Error fetching morpho vault ${vaultKey}:`, err);
31
+ }
26
32
  })),
27
33
  ...yearnVaultsList.map((vaultKey) => __awaiter(void 0, void 0, void 0, function* () {
28
- const vault = yearnVaults.yearnVaultsOptions.getYearnVault(vaultKey);
29
- const data = yield yearnVaults.getYearnVaultData(provider, network, vault, accounts);
30
- savingsData[vaultKey] = data;
34
+ try {
35
+ const vault = yearnVaults.yearnVaultsOptions.getYearnVault(vaultKey);
36
+ const data = yield yearnVaults.getYearnVaultData(provider, network, vault, accounts);
37
+ savingsData[vaultKey] = data;
38
+ }
39
+ catch (err) {
40
+ console.error(`[getSavingsData] Error fetching yearn vault ${vaultKey}:`, err);
41
+ }
31
42
  })),
32
43
  ...sparkSavingsVaultsList.map((vaultKey) => __awaiter(void 0, void 0, void 0, function* () {
33
- const vault = sparkSavingsVaults.sparkSavingsVaultsOptions.getSparkSavingsVault(vaultKey);
34
- const data = yield sparkSavingsVaults.getSparkSavingsVaultData(provider, network, vault, accounts);
35
- savingsData[vaultKey] = data;
44
+ try {
45
+ const vault = sparkSavingsVaults.sparkSavingsVaultsOptions.getSparkSavingsVault(vaultKey);
46
+ const data = yield sparkSavingsVaults.getSparkSavingsVaultData(provider, network, vault, accounts);
47
+ savingsData[vaultKey] = data;
48
+ }
49
+ catch (err) {
50
+ console.error(`[getSavingsData] Error fetching yearn vault ${vaultKey}:`, err);
51
+ }
36
52
  })),
37
53
  (() => __awaiter(void 0, void 0, void 0, function* () {
38
- const data = yield makerDsr.getMakerDsrData(provider, network, accounts);
39
- savingsData[MakerDsrType.MakerDsrVault] = data;
54
+ try {
55
+ const data = yield makerDsr.getMakerDsrData(provider, network, accounts);
56
+ savingsData[MakerDsrType.MakerDsrVault] = data;
57
+ }
58
+ catch (err) {
59
+ console.error('[getSavingsData] Error fetching maker DSR data:', err);
60
+ }
61
+ }))(),
62
+ (() => __awaiter(void 0, void 0, void 0, function* () {
63
+ try {
64
+ const data = yield skyOptions.getSkyOptionData(provider, network, accounts);
65
+ savingsData[SkySavingsType.SkySavings] = data;
66
+ }
67
+ catch (err) {
68
+ console.error('[getSavingsData] Error fetching Sky savings data:', err);
69
+ }
40
70
  }))(),
41
71
  ]);
42
72
  return savingsData;
@@ -0,0 +1,7 @@
1
+ import { Client } from 'viem';
2
+ import { EthAddress, EthereumProvider, NetworkNumber } from '../../types/common';
3
+ import { SavingsVaultData } from '../../types';
4
+ import * as skySavingsOptions from './options';
5
+ export { skySavingsOptions };
6
+ export declare const _getSkyOptionData: (provider: Client, network: NetworkNumber, accounts: EthAddress[]) => Promise<SavingsVaultData>;
7
+ export declare function getSkyOptionData(provider: EthereumProvider, network: NetworkNumber, accounts: EthAddress[]): Promise<SavingsVaultData>;
@@ -0,0 +1,81 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import Dec from 'decimal.js';
11
+ import { assetAmountInEth } from '@defisaver/tokens';
12
+ import * as skySavingsOptions from './options';
13
+ import { getViemProvider } from '../../services/viem';
14
+ import { SKY_SAVINGS_OPTION } from './options';
15
+ import { SkySavingsContractView } from '../../contracts';
16
+ export { skySavingsOptions };
17
+ /**
18
+ * Converts shares to assets using ERC4626 standard formula
19
+ * Formula: assets = shares * totalAssets / totalSupply
20
+ *
21
+ * @param shares - The amount of shares to convert
22
+ * @param totalAssets - Total assets in the vault
23
+ * @param totalSupply - Total supply of shares
24
+ * @returns The equivalent amount of assets
25
+ */
26
+ const convertToAssets = (shares, totalAssets, totalSupply) => {
27
+ // If no shares or no total supply, return 0 (or shares if totalSupply is 0 per ERC4626 spec)
28
+ if (shares === BigInt(0)) {
29
+ return BigInt(0);
30
+ }
31
+ // Per ERC4626 spec: if totalSupply == 0, return shares (1:1 ratio)
32
+ if (totalSupply === BigInt(0)) {
33
+ return shares;
34
+ }
35
+ // Standard ERC4626 formula: assets = shares * totalAssets / totalSupply
36
+ return BigInt(new Dec(shares.toString())
37
+ .mul(totalAssets.toString())
38
+ .div(totalSupply.toString())
39
+ .toFixed(0));
40
+ };
41
+ export const _getSkyOptionData = (provider, network, accounts) => __awaiter(void 0, void 0, void 0, function* () {
42
+ const skySavingsContract = SkySavingsContractView(provider, network);
43
+ const shares = {};
44
+ const [totalAssets, totalSupply] = yield Promise.all([
45
+ skySavingsContract.read.totalAssets(),
46
+ skySavingsContract.read.totalSupply(),
47
+ ...accounts.map((account) => __awaiter(void 0, void 0, void 0, function* () {
48
+ const share = yield skySavingsContract.read.balanceOf([account]);
49
+ shares[account.toLowerCase()] = share;
50
+ return share;
51
+ })),
52
+ ]);
53
+ const poolSize = assetAmountInEth(totalAssets.toString(), SKY_SAVINGS_OPTION.asset);
54
+ const supplied = {};
55
+ accounts.forEach((account) => {
56
+ const normalizedAccount = account.toLowerCase();
57
+ const share = shares[normalizedAccount] || BigInt(0);
58
+ // Use local convertToAssets for each account to convert sUSDS shares to USDS assets
59
+ const assetsWei = convertToAssets(share, totalAssets, totalSupply);
60
+ const suppliedAmount = assetAmountInEth(assetsWei.toString(), SKY_SAVINGS_OPTION.asset);
61
+ supplied[normalizedAccount] = suppliedAmount;
62
+ });
63
+ return {
64
+ poolSize,
65
+ supplied,
66
+ liquidity: poolSize,
67
+ asset: SKY_SAVINGS_OPTION.asset,
68
+ optionType: SKY_SAVINGS_OPTION.type,
69
+ };
70
+ });
71
+ export function getSkyOptionData(provider, network, accounts) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ return _getSkyOptionData(getViemProvider(provider, network, {
74
+ batch: {
75
+ multicall: {
76
+ batchSize: 2500000,
77
+ },
78
+ },
79
+ }), network, accounts);
80
+ });
81
+ }
@@ -0,0 +1,2 @@
1
+ import { SkySavingsOption } from '../../types';
2
+ export declare const SKY_SAVINGS_OPTION: SkySavingsOption;
@@ -0,0 +1,8 @@
1
+ import { SkySavingsType } from '../../types';
2
+ export const SKY_SAVINGS_OPTION = {
3
+ type: SkySavingsType.SkySavings,
4
+ name: 'Sky Savings',
5
+ asset: 'USDS',
6
+ address: '0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD',
7
+ isLegacy: false,
8
+ };
@@ -1,11 +1,13 @@
1
1
  import { EthAddress } from '../common';
2
2
  import { MakerDsrType } from './makerDsr';
3
3
  import { MorphoVaultType } from './morphoVaults';
4
+ import { SkySavingsType } from './sky';
4
5
  import { SparkSavingsVaultType } from './sparkSavingsVaults';
5
6
  import { YearnVaultType } from './yearnVaults';
6
7
  export * from './morphoVaults';
7
8
  export * from './yearnVaults';
8
9
  export * from './makerDsr';
10
+ export * from './sky';
9
11
  export * from './sparkSavingsVaults';
10
12
  export interface SavingsVaultData {
11
13
  poolSize: string;
@@ -14,4 +16,4 @@ export interface SavingsVaultData {
14
16
  asset: string;
15
17
  optionType: string;
16
18
  }
17
- export type SavingsData = Partial<Record<MorphoVaultType | YearnVaultType | MakerDsrType | SparkSavingsVaultType, SavingsVaultData>>;
19
+ export type SavingsData = Partial<Record<MorphoVaultType | YearnVaultType | MakerDsrType | SkySavingsType | SparkSavingsVaultType, SavingsVaultData>>;
@@ -1,4 +1,5 @@
1
1
  export * from './morphoVaults';
2
2
  export * from './yearnVaults';
3
3
  export * from './makerDsr';
4
+ export * from './sky';
4
5
  export * from './sparkSavingsVaults';
@@ -0,0 +1,11 @@
1
+ import { EthAddress } from '../common';
2
+ export declare enum SkySavingsType {
3
+ SkySavings = "sky_savings"
4
+ }
5
+ export interface SkySavingsOption {
6
+ type: SkySavingsType;
7
+ name: string;
8
+ asset: string;
9
+ address: EthAddress;
10
+ isLegacy: boolean;
11
+ }
@@ -0,0 +1,4 @@
1
+ export var SkySavingsType;
2
+ (function (SkySavingsType) {
3
+ SkySavingsType["SkySavings"] = "sky_savings";
4
+ })(SkySavingsType || (SkySavingsType = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.33",
3
+ "version": "2.1.35",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -12,7 +12,11 @@ import { aaveAnyGetAggregatedPositionData, aaveV3IsInIsolationMode, aaveV3IsInSi
12
12
  import { AAVE_V3 } from '../markets/aave';
13
13
  import { aprToApy, calculateBorrowingAssetLimit } from '../moneymarket';
14
14
  import {
15
- getWrappedNativeAssetFromUnwrapped, isEnabledOnBitmap, isLayer2Network, wethToEth, wethToEthByAddress,
15
+ getWrappedNativeAssetFromUnwrapped,
16
+ isEnabledOnBitmap,
17
+ isLayer2Network,
18
+ wethToEth,
19
+ wethToEthByAddress,
16
20
  } from '../services/utils';
17
21
  import { getStakingApy, STAKING_ASSETS } from '../staking';
18
22
  import {
@@ -28,12 +32,19 @@ import {
28
32
  EModeCategoryDataMapping,
29
33
  } from '../types/aave';
30
34
  import {
31
- Blockish, EthAddress, EthereumProvider, IncentiveEligibilityId, IncentiveKind, NetworkNumber, PositionBalances, HexString,
35
+ Blockish,
36
+ EthAddress,
37
+ EthereumProvider,
38
+ IncentiveEligibilityId,
39
+ IncentiveKind,
40
+ NetworkNumber,
41
+ PositionBalances,
42
+ HexString,
32
43
  } from '../types/common';
33
44
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
34
45
  import { getMeritCampaigns } from './merit';
35
46
  import { getAaveUnderlyingSymbol, getMerkleCampaigns } from './merkl';
36
- import { SECONDS_PER_DAY, SECONDS_PER_YEAR } from '../constants';
47
+ import { SECONDS_PER_YEAR } from '../constants';
37
48
 
38
49
  export const aaveV3EmodeCategoriesMapping = (extractedState: any, usedAssets: AaveV3UsedAssets) => {
39
50
  const { eModeCategoriesData }: { assetsData: AaveV3AssetsData, eModeCategoriesData: EModeCategoriesData } = extractedState;
@@ -1282,4 +1282,12 @@ export const MakerDsr = {
1282
1282
  }
1283
1283
  export const SparkSavingsVault = {
1284
1284
  "abi": [{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nowChi","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
1285
+ } as const;
1286
+ export const SkySavings = {
1287
+ "abi": [{"inputs":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],
1288
+ "networks": {
1289
+ "1": {
1290
+ "address": "0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD",
1291
+ }
1292
+ }
1285
1293
  } as const;
package/src/contracts.ts CHANGED
@@ -158,4 +158,6 @@ export const StkAAVEViem = createViemContractFromConfigFunc('StkAAVE');
158
158
 
159
159
  export const YearnViewContractViem = createViemContractFromConfigFunc('YearnView');
160
160
 
161
- export const MakerDsrContractViem = createViemContractFromConfigFunc('MakerDsr');
161
+ export const MakerDsrContractViem = createViemContractFromConfigFunc('MakerDsr');
162
+
163
+ export const SkySavingsContractView = createViemContractFromConfigFunc('SkySavings');
@@ -10,7 +10,7 @@ export const aaveV2AssetsDefaultMarket = ['USDT', 'WBTC', 'ETH', 'YFI', 'ZRX', '
10
10
 
11
11
  export const aaveV3AssetsDefaultMarketEth = [
12
12
  'ETH', 'wstETH', 'WBTC', 'USDC', 'DAI', 'LINK', 'AAVE', 'cbETH', 'USDT', 'rETH', 'LUSD', 'CRV', 'MKR', 'SNX', 'BAL', 'UNI', 'LDO', 'ENS', '1INCH', 'FRAX', 'GHO', 'RPL', 'sDAI', 'STG', 'KNC', 'FXS', 'crvUSD', 'PYUSD', 'weETH', 'osETH', 'USDe', 'ETHx', 'sUSDe', 'tBTC', 'cbBTC', 'USDS', 'rsETH', 'LBTC', 'eBTC', 'RLUSD', 'PT eUSDe May', 'PT sUSDe July', 'USDtb',
13
- 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov', 'PT USDe Nov', 'PT sUSDe Feb', 'PT USDe Feb', 'mUSD',
13
+ 'eUSDe', 'PT USDe July', 'PT eUSDe Aug', 'EURC', 'FBTC', 'PT sUSDe Sep', 'PT USDe Sep', 'tETH', 'ezETH', 'XAUt', 'PT sUSDe Nov', 'PT USDe Nov', 'PT sUSDe Feb', 'PT USDe Feb', 'mUSD', 'syrupUSDT',
14
14
  ];
15
15
  export const aaveV3AssetsDefaultMarketOpt = [
16
16
  'DAI', 'USDC.e', 'USDT', 'SUSD', 'AAVE', 'LINK', 'WBTC', 'ETH', 'OP', 'wstETH', 'LUSD', 'MAI', 'rETH', 'USDC',
@@ -2,6 +2,7 @@ import {
2
2
  MakerDsrType,
3
3
  MorphoVaultType,
4
4
  SavingsData,
5
+ SkySavingsType,
5
6
  SparkSavingsVaultType,
6
7
  YearnVaultType,
7
8
  } from '../types';
@@ -9,12 +10,14 @@ import { EthAddress, EthereumProvider, NetworkNumber } from '../types/common';
9
10
  import * as morphoVaults from './morphoVaults';
10
11
  import * as yearnVaults from './yearnVaults';
11
12
  import * as makerDsr from './makerDsr';
13
+ import * as skyOptions from './skyOptions';
12
14
  import * as sparkSavingsVaults from './sparkSavingsVaults';
13
15
 
14
16
  export {
15
17
  morphoVaults,
16
18
  yearnVaults,
17
19
  makerDsr,
20
+ skyOptions,
18
21
  sparkSavingsVaults,
19
22
  };
20
23
 
@@ -31,23 +34,47 @@ export const getSavingsData = async (
31
34
 
32
35
  await Promise.all([
33
36
  ...morphoVaultsList.map(async (vaultKey) => {
34
- const vault = morphoVaults.morphoVaultsOptions.getMorphoVault(vaultKey);
35
- const data = await morphoVaults.getMorphoVaultData(provider, network, vault, accounts);
36
- savingsData[vaultKey] = data;
37
+ try {
38
+ const vault = morphoVaults.morphoVaultsOptions.getMorphoVault(vaultKey);
39
+ const data = await morphoVaults.getMorphoVaultData(provider, network, vault, accounts);
40
+ savingsData[vaultKey] = data;
41
+ } catch (err) {
42
+ console.error(`[getSavingsData] Error fetching morpho vault ${vaultKey}:`, err);
43
+ }
37
44
  }),
38
45
  ...yearnVaultsList.map(async (vaultKey) => {
39
- const vault = yearnVaults.yearnVaultsOptions.getYearnVault(vaultKey);
40
- const data = await yearnVaults.getYearnVaultData(provider, network, vault, accounts);
41
- savingsData[vaultKey] = data;
46
+ try {
47
+ const vault = yearnVaults.yearnVaultsOptions.getYearnVault(vaultKey);
48
+ const data = await yearnVaults.getYearnVaultData(provider, network, vault, accounts);
49
+ savingsData[vaultKey] = data;
50
+ } catch (err) {
51
+ console.error(`[getSavingsData] Error fetching yearn vault ${vaultKey}:`, err);
52
+ }
42
53
  }),
43
54
  ...sparkSavingsVaultsList.map(async (vaultKey) => {
44
- const vault = sparkSavingsVaults.sparkSavingsVaultsOptions.getSparkSavingsVault(vaultKey);
45
- const data = await sparkSavingsVaults.getSparkSavingsVaultData(provider, network, vault, accounts);
46
- savingsData[vaultKey] = data;
55
+ try {
56
+ const vault = sparkSavingsVaults.sparkSavingsVaultsOptions.getSparkSavingsVault(vaultKey);
57
+ const data = await sparkSavingsVaults.getSparkSavingsVaultData(provider, network, vault, accounts);
58
+ savingsData[vaultKey] = data;
59
+ } catch (err) {
60
+ console.error(`[getSavingsData] Error fetching yearn vault ${vaultKey}:`, err);
61
+ }
47
62
  }),
48
63
  (async () => {
49
- const data = await makerDsr.getMakerDsrData(provider, network, accounts);
50
- savingsData[MakerDsrType.MakerDsrVault] = data;
64
+ try {
65
+ const data = await makerDsr.getMakerDsrData(provider, network, accounts);
66
+ savingsData[MakerDsrType.MakerDsrVault] = data;
67
+ } catch (err) {
68
+ console.error('[getSavingsData] Error fetching maker DSR data:', err);
69
+ }
70
+ })(),
71
+ (async () => {
72
+ try {
73
+ const data = await skyOptions.getSkyOptionData(provider, network, accounts);
74
+ savingsData[SkySavingsType.SkySavings] = data;
75
+ } catch (err) {
76
+ console.error('[getSavingsData] Error fetching Sky savings data:', err);
77
+ }
51
78
  })(),
52
79
  ]);
53
80
 
@@ -0,0 +1,95 @@
1
+ import { Client } from 'viem';
2
+ import Dec from 'decimal.js';
3
+ import { assetAmountInEth } from '@defisaver/tokens';
4
+ import { EthAddress, EthereumProvider, NetworkNumber } from '../../types/common';
5
+ import { SavingsVaultData } from '../../types';
6
+ import * as skySavingsOptions from './options';
7
+ import { getViemProvider } from '../../services/viem';
8
+ import { SKY_SAVINGS_OPTION } from './options';
9
+ import { SkySavingsContractView } from '../../contracts';
10
+
11
+ export { skySavingsOptions };
12
+
13
+ /**
14
+ * Converts shares to assets using ERC4626 standard formula
15
+ * Formula: assets = shares * totalAssets / totalSupply
16
+ *
17
+ * @param shares - The amount of shares to convert
18
+ * @param totalAssets - Total assets in the vault
19
+ * @param totalSupply - Total supply of shares
20
+ * @returns The equivalent amount of assets
21
+ */
22
+ const convertToAssets = (shares: bigint, totalAssets: bigint, totalSupply: bigint): bigint => {
23
+ // If no shares or no total supply, return 0 (or shares if totalSupply is 0 per ERC4626 spec)
24
+ if (shares === BigInt(0)) {
25
+ return BigInt(0);
26
+ }
27
+
28
+ // Per ERC4626 spec: if totalSupply == 0, return shares (1:1 ratio)
29
+ if (totalSupply === BigInt(0)) {
30
+ return shares;
31
+ }
32
+
33
+ // Standard ERC4626 formula: assets = shares * totalAssets / totalSupply
34
+ return BigInt(
35
+ new Dec(shares.toString())
36
+ .mul(totalAssets.toString())
37
+ .div(totalSupply.toString())
38
+ .toFixed(0),
39
+ );
40
+ };
41
+
42
+ export const _getSkyOptionData = async (
43
+ provider: Client,
44
+ network: NetworkNumber,
45
+ accounts: EthAddress[],
46
+ ): Promise<SavingsVaultData> => {
47
+ const skySavingsContract = SkySavingsContractView(provider, network);
48
+
49
+ const shares: Record<EthAddress, bigint> = {};
50
+
51
+ const [totalAssets, totalSupply] = await Promise.all([
52
+ skySavingsContract.read.totalAssets(),
53
+ skySavingsContract.read.totalSupply(),
54
+ ...accounts.map(async (account) => {
55
+ const share = await skySavingsContract.read.balanceOf([account]);
56
+ shares[account.toLowerCase() as EthAddress] = share;
57
+ return share;
58
+ }),
59
+ ]);
60
+
61
+ const poolSize = assetAmountInEth(totalAssets.toString(), SKY_SAVINGS_OPTION.asset);
62
+
63
+ const supplied: Record<EthAddress, string> = {};
64
+ accounts.forEach((account) => {
65
+ const normalizedAccount = account.toLowerCase() as EthAddress;
66
+ const share = shares[normalizedAccount] || BigInt(0);
67
+
68
+ // Use local convertToAssets for each account to convert sUSDS shares to USDS assets
69
+ const assetsWei = convertToAssets(share, totalAssets, totalSupply);
70
+ const suppliedAmount = assetAmountInEth(assetsWei.toString(), SKY_SAVINGS_OPTION.asset);
71
+ supplied[normalizedAccount] = suppliedAmount;
72
+ });
73
+
74
+ return {
75
+ poolSize,
76
+ supplied,
77
+ liquidity: poolSize,
78
+ asset: SKY_SAVINGS_OPTION.asset,
79
+ optionType: SKY_SAVINGS_OPTION.type,
80
+ };
81
+ };
82
+
83
+ export async function getSkyOptionData(
84
+ provider: EthereumProvider,
85
+ network: NetworkNumber,
86
+ accounts: EthAddress[],
87
+ ): Promise<SavingsVaultData> {
88
+ return _getSkyOptionData(getViemProvider(provider, network, {
89
+ batch: {
90
+ multicall: {
91
+ batchSize: 2500000,
92
+ },
93
+ },
94
+ }), network, accounts);
95
+ }
@@ -0,0 +1,9 @@
1
+ import { SkySavingsOption, SkySavingsType } from '../../types';
2
+
3
+ export const SKY_SAVINGS_OPTION: SkySavingsOption = {
4
+ type: SkySavingsType.SkySavings,
5
+ name: 'Sky Savings',
6
+ asset: 'USDS',
7
+ address: '0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD',
8
+ isLegacy: false,
9
+ };
@@ -1,12 +1,14 @@
1
1
  import { EthAddress } from '../common';
2
2
  import { MakerDsrType } from './makerDsr';
3
3
  import { MorphoVaultType } from './morphoVaults';
4
+ import { SkySavingsType } from './sky';
4
5
  import { SparkSavingsVaultType } from './sparkSavingsVaults';
5
6
  import { YearnVaultType } from './yearnVaults';
6
7
 
7
8
  export * from './morphoVaults';
8
9
  export * from './yearnVaults';
9
10
  export * from './makerDsr';
11
+ export * from './sky';
10
12
  export * from './sparkSavingsVaults';
11
13
 
12
14
  export interface SavingsVaultData {
@@ -17,4 +19,4 @@ export interface SavingsVaultData {
17
19
  optionType: string,
18
20
  }
19
21
 
20
- export type SavingsData = Partial<Record<MorphoVaultType | YearnVaultType | MakerDsrType | SparkSavingsVaultType, SavingsVaultData>>;
22
+ export type SavingsData = Partial<Record<MorphoVaultType | YearnVaultType | MakerDsrType | SkySavingsType | SparkSavingsVaultType, SavingsVaultData>>;
@@ -0,0 +1,13 @@
1
+ import { EthAddress } from '../common';
2
+
3
+ export enum SkySavingsType {
4
+ SkySavings = 'sky_savings',
5
+ }
6
+
7
+ export interface SkySavingsOption {
8
+ type: SkySavingsType;
9
+ name: string;
10
+ asset: string;
11
+ address: EthAddress;
12
+ isLegacy: boolean;
13
+ }