@defisaver/positions-sdk 2.1.169-portfolio-api-dev → 2.1.169

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 (101) hide show
  1. package/cjs/aaveV3/index.d.ts +12 -2
  2. package/cjs/aaveV3/sgho.d.ts +16 -2
  3. package/cjs/aaveV4/lend.d.ts +43 -2
  4. package/cjs/claiming/aaveV3.d.ts +2 -2
  5. package/cjs/claiming/ethena.d.ts +1 -2
  6. package/cjs/claiming/king.d.ts +1 -2
  7. package/cjs/claiming/spark.d.ts +2 -2
  8. package/cjs/fluid/index.d.ts +49 -5
  9. package/cjs/liquity/index.d.ts +12 -2
  10. package/cjs/liquityV2/index.d.ts +23 -8
  11. package/cjs/liquityV2/index.js +19 -37
  12. package/cjs/markets/morphoBlue/index.d.ts +2 -0
  13. package/cjs/markets/morphoBlue/index.js +18 -1
  14. package/cjs/portfolio/index.d.ts +8 -16
  15. package/cjs/portfolio/index.js +520 -458
  16. package/cjs/savings/index.d.ts +2 -8
  17. package/cjs/savings/index.js +4 -33
  18. package/cjs/types/aave.d.ts +2 -98
  19. package/cjs/types/aaveV4.d.ts +0 -44
  20. package/cjs/types/compound.d.ts +2 -26
  21. package/cjs/types/curveUsd.d.ts +1 -9
  22. package/cjs/types/fluid.d.ts +0 -13
  23. package/cjs/types/index.d.ts +0 -1
  24. package/cjs/types/index.js +0 -1
  25. package/cjs/types/liquity.d.ts +0 -12
  26. package/cjs/types/liquityV2.d.ts +0 -24
  27. package/cjs/types/llamaLend.d.ts +1 -12
  28. package/cjs/types/morphoBlue.d.ts +1 -2
  29. package/cjs/types/morphoBlue.js +1 -0
  30. package/cjs/types/portfolio.d.ts +5 -125
  31. package/cjs/types/savings/index.d.ts +1 -9
  32. package/cjs/types/spark.d.ts +1 -21
  33. package/cjs/umbrella/index.d.ts +3 -2
  34. package/esm/aaveV3/index.d.ts +12 -2
  35. package/esm/aaveV3/sgho.d.ts +16 -2
  36. package/esm/aaveV4/lend.d.ts +43 -2
  37. package/esm/claiming/aaveV3.d.ts +2 -2
  38. package/esm/claiming/aaveV3.js +1 -1
  39. package/esm/claiming/ethena.d.ts +1 -2
  40. package/esm/claiming/king.d.ts +1 -2
  41. package/esm/claiming/spark.d.ts +2 -2
  42. package/esm/claiming/spark.js +1 -1
  43. package/esm/fluid/index.d.ts +49 -5
  44. package/esm/liquity/index.d.ts +12 -2
  45. package/esm/liquityV2/index.d.ts +23 -8
  46. package/esm/liquityV2/index.js +18 -35
  47. package/esm/markets/morphoBlue/index.d.ts +2 -0
  48. package/esm/markets/morphoBlue/index.js +16 -0
  49. package/esm/portfolio/index.d.ts +8 -16
  50. package/esm/portfolio/index.js +522 -458
  51. package/esm/savings/index.d.ts +2 -8
  52. package/esm/savings/index.js +3 -31
  53. package/esm/types/aave.d.ts +2 -98
  54. package/esm/types/aaveV4.d.ts +0 -44
  55. package/esm/types/compound.d.ts +2 -26
  56. package/esm/types/curveUsd.d.ts +1 -9
  57. package/esm/types/fluid.d.ts +0 -13
  58. package/esm/types/index.d.ts +0 -1
  59. package/esm/types/index.js +0 -1
  60. package/esm/types/liquity.d.ts +0 -12
  61. package/esm/types/liquityV2.d.ts +0 -24
  62. package/esm/types/llamaLend.d.ts +1 -12
  63. package/esm/types/morphoBlue.d.ts +1 -2
  64. package/esm/types/morphoBlue.js +1 -0
  65. package/esm/types/portfolio.d.ts +5 -125
  66. package/esm/types/savings/index.d.ts +1 -9
  67. package/esm/types/spark.d.ts +1 -21
  68. package/esm/umbrella/index.d.ts +3 -2
  69. package/package.json +2 -2
  70. package/src/aaveV3/index.ts +1 -2
  71. package/src/aaveV3/sgho.ts +17 -2
  72. package/src/aaveV4/lend.ts +48 -2
  73. package/src/claiming/aaveV3.ts +2 -4
  74. package/src/claiming/ethena.ts +5 -5
  75. package/src/claiming/king.ts +3 -3
  76. package/src/claiming/spark.ts +4 -6
  77. package/src/fluid/index.ts +3 -4
  78. package/src/liquity/index.ts +2 -2
  79. package/src/liquityV2/index.ts +22 -48
  80. package/src/markets/morphoBlue/index.ts +16 -0
  81. package/src/portfolio/index.ts +331 -306
  82. package/src/savings/index.ts +4 -41
  83. package/src/types/aave.ts +1 -104
  84. package/src/types/aaveV4.ts +0 -49
  85. package/src/types/compound.ts +2 -38
  86. package/src/types/curveUsd.ts +1 -17
  87. package/src/types/fluid.ts +0 -14
  88. package/src/types/index.ts +0 -1
  89. package/src/types/liquity.ts +1 -13
  90. package/src/types/liquityV2.ts +1 -26
  91. package/src/types/llamaLend.ts +1 -19
  92. package/src/types/morphoBlue.ts +1 -3
  93. package/src/types/portfolio.ts +5 -151
  94. package/src/types/savings/index.ts +1 -12
  95. package/src/types/spark.ts +1 -25
  96. package/src/umbrella/index.ts +1 -2
  97. package/cjs/portfolio/lendingProtocols.d.ts +0 -184
  98. package/cjs/portfolio/lendingProtocols.js +0 -196
  99. package/esm/portfolio/lendingProtocols.d.ts +0 -184
  100. package/esm/portfolio/lendingProtocols.js +0 -189
  101. package/src/portfolio/lendingProtocols.ts +0 -281
@@ -20,12 +20,4 @@ export interface SavingsVaultData {
20
20
  asset: string;
21
21
  optionType: string;
22
22
  }
23
- /** The key of every savings vault getSavingsData reads. */
24
- export type SavingsVaultKey = MorphoVaultType | YearnVaultType | MakerDsrType | SkySavingsType | SparkSavingsVaultType | SummerVaultType | YearnV3VaultType;
25
- export type SavingsData = Partial<Record<SavingsVaultKey, SavingsVaultData>>;
26
- /** Why each vault that was read for a network came back without data. */
27
- export type SavingsErrors = Partial<Record<SavingsVaultKey, string>>;
28
- export interface SavingsDataWithErrors {
29
- data: SavingsData;
30
- errors: SavingsErrors;
31
- }
23
+ export type SavingsData = Partial<Record<MorphoVaultType | YearnVaultType | MakerDsrType | SkySavingsType | SparkSavingsVaultType | SummerVaultType | YearnV3VaultType, SavingsVaultData>>;
@@ -46,21 +46,6 @@ export interface SparkAssetData extends MMAssetData {
46
46
  eModeCategory: number;
47
47
  liquidationBonus: string;
48
48
  liquidationRatio: string;
49
- debtCeilingForIsolationMode?: string;
50
- isSiloed?: boolean;
51
- isolationModeTotalDebt?: string;
52
- isolationModeBorrowingEnabled?: boolean;
53
- assetId?: number;
54
- borrowRateStable?: string;
55
- supplyCap?: string;
56
- isInactive?: boolean;
57
- isFrozen?: boolean;
58
- isPaused?: boolean;
59
- canBeWithdrawn?: boolean;
60
- canBePayBacked?: boolean;
61
- disabledStableBorrowing?: boolean;
62
- isFlashLoanEnabled?: boolean;
63
- aTokenAddress?: EthAddress;
64
49
  }
65
50
  export interface SparkAssetsData {
66
51
  [token: string]: SparkAssetData;
@@ -116,12 +101,7 @@ export interface SparkAggregatedPositionData {
116
101
  minHealthRatio: string;
117
102
  exposure: string;
118
103
  }
119
- /**
120
- * Fields sparkGetAggregatedPositionData adds to every Spark position at runtime, on top of those declared below.
121
- * Optional, so code that builds a position by hand keeps compiling.
122
- */
123
- export type SparkPositionAggregatedFields = Partial<Omit<SparkAggregatedPositionData, keyof MMPositionData | 'ratio' | 'collRatio' | 'suppliedUsd' | 'borrowedUsd' | 'borrowLimitUsd' | 'suppliedCollateralUsd' | 'incentiveUsd' | 'totalInterestUsd'>>;
124
- export interface SparkPositionData extends MMPositionData, SparkPositionAggregatedFields {
104
+ export interface SparkPositionData extends MMPositionData {
125
105
  ratio: string;
126
106
  minRatio: string;
127
107
  collRatio: string;
@@ -1,4 +1,5 @@
1
1
  import { Client } from 'viem';
2
2
  import { EthAddress, NetworkNumber } from '../types/common';
3
- import { UmbrellaStakingData } from '../types/aave';
4
- export declare const getUmbrellaData: (provider: Client, network: NetworkNumber, address: EthAddress) => Promise<UmbrellaStakingData>;
3
+ export declare const getUmbrellaData: (provider: Client, network: NetworkNumber, address: EthAddress) => Promise<{
4
+ [k: string]: any;
5
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.169-portfolio-api-dev",
3
+ "version": "2.1.169",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -22,7 +22,7 @@
22
22
  "repository": "https://github.com/defisaver/defisaver-positions-sdk",
23
23
  "license": "ISC",
24
24
  "dependencies": {
25
- "@defisaver/tokens": "^1.7.45",
25
+ "@defisaver/tokens": "^1.7.50",
26
26
  "@types/lodash": "^4.17.15",
27
27
  "@types/memoizee": "^0.4.12",
28
28
  "decimal.js": "^10.6.0",
@@ -31,7 +31,6 @@ import {
31
31
  EModeCategoriesData,
32
32
  EModeCategoryData,
33
33
  EModeCategoryDataMapping,
34
- StakeAaveData,
35
34
  } from '../types';
36
35
  import {
37
36
  Blockish,
@@ -853,7 +852,7 @@ export const fetchYearlyMeritApyForStakingGho = async () => {
853
852
  }
854
853
  };
855
854
 
856
- export const getStakeAaveData = async (provider: Client, network: NetworkNumber, address: EthAddress): Promise<StakeAaveData> => {
855
+ export const getStakeAaveData = async (provider: Client, network: NetworkNumber, address: EthAddress) => {
857
856
  const stkGhoAddress = getAssetInfo('stkGHO').address as HexString;
858
857
  const stkAaveAddress = getAssetInfo('stkAAVE').address as HexString;
859
858
 
@@ -1,10 +1,25 @@
1
1
  import Dec from 'decimal.js';
2
2
  import { EthAddress, NetworkNumber } from '../types/common';
3
- import { SghoData } from '../types/aave';
4
3
  import { DEFAULT_TIMEOUT } from '../services/utils';
5
4
  import { ZERO_ADDRESS } from '../constants';
6
5
 
7
- export type { SghoData, SghoUserData } from '../types/aave';
6
+ export interface SghoUserData {
7
+ shares: string;
8
+ balance: string;
9
+ maxDeposit: string;
10
+ maxWithdraw: string;
11
+ underlyingBalance: string;
12
+ }
13
+
14
+ export interface SghoData {
15
+ totalAssets: string;
16
+ totalSupply: string;
17
+ supplyCap: string;
18
+ /** Target savings rate as an APY percent (e.g. "4.25" for 4.25%). */
19
+ targetRate: string;
20
+ paused: boolean;
21
+ user: SghoUserData;
22
+ }
8
23
 
9
24
  const EMPTY_SGHO_DATA: SghoData = {
10
25
  totalAssets: '0',
@@ -7,9 +7,26 @@ import {
7
7
  EthereumProvider,
8
8
  NetworkNumber,
9
9
  } from '../types/common';
10
- import { AaveV4TokenizationSpokeDataParsed } from '../types/aaveV4';
11
10
 
12
- export type { AaveV4TokenizationSpokeData, AaveV4TokenizationSpokeDataParsed } from '../types/aaveV4';
11
+ export interface AaveV4TokenizationSpokeData {
12
+ underlyingAsset: EthAddress;
13
+ assetId: string;
14
+ decimals: number;
15
+ spoke: EthAddress;
16
+ spokeActive: boolean;
17
+ spokeHalted: boolean;
18
+ spokeDepositCap: string;
19
+ spokeTotalAssets: string;
20
+ spokeTotalShares: string;
21
+ hub: EthAddress;
22
+ hubLiquidity: string;
23
+ hubDrawnRate: string;
24
+ convertToShares: string;
25
+ convertToAssets: string;
26
+ user: EthAddress;
27
+ userSuppliedAssets: string;
28
+ userSuppliedShares: string;
29
+ }
13
30
 
14
31
  export const AAVE_V4_TOKENIZED_SPOKES: Record<string, EthAddress> = {
15
32
  EURC_CORE: '0x6D9e2Cdd61CaF69af99b275704B6e272C41c6718',
@@ -85,6 +102,34 @@ export const aaveV4GetTokenizedVaultAddress = (
85
102
  return AAVE_V4_TOKENIZED_SPOKES[key];
86
103
  };
87
104
 
105
+ /** Parsed tokenization spoke data with human-readable supplied amounts for display */
106
+ export interface AaveV4TokenizationSpokeDataParsed {
107
+ vaultAddress: EthAddress;
108
+ key: string | null;
109
+ symbol: string;
110
+ hubKey: string;
111
+ // ---- Spoke ----
112
+ spokeActive: boolean;
113
+ spokeHalted: boolean;
114
+ /** Deposit cap in asset units (wei string) */
115
+ spokeDepositCap: string;
116
+ /** Total assets currently in spoke in asset units (wei string) */
117
+ spokeTotalAssets: string;
118
+ // ---- Hub ----
119
+ /** Available hub liquidity in asset units (wei string) */
120
+ hubLiquidity: string;
121
+ /** The conversion rate from assets to shares expressed in asset units. */
122
+ convertToShares: string;
123
+ // ---- User ----
124
+ userSuppliedAssetsEth: string;
125
+ userSuppliedSharesEth: string;
126
+ userSuppliedAssets: string;
127
+ userSuppliedShares: string;
128
+ underlyingAsset: EthAddress;
129
+ spoke: EthAddress;
130
+ decimals: number;
131
+ }
132
+
88
133
  const AAVE_V4_TOKENIZED_SPOKE_ADDRESS_TO_KEY: Record<string, string> = Object.entries(
89
134
  AAVE_V4_TOKENIZED_SPOKES,
90
135
  ).reduce((acc, [k, v]) => {
@@ -144,3 +189,4 @@ export async function getAaveV4TokenizationSpokesData(
144
189
  }).filter(item => item != null);
145
190
  }
146
191
 
192
+
@@ -1,9 +1,7 @@
1
1
  import { Client } from 'viem';
2
2
  import Dec from 'decimal.js';
3
3
  import { EthAddress, NetworkNumber } from '../types';
4
- import {
5
- AaveRewardsClaimableToken, ClaimableToken, ClaimType, MerklRewardsClaimableToken,
6
- } from '../types/claiming';
4
+ import { ClaimableToken, ClaimType, MerklRewardsClaimableToken } from '../types/claiming';
7
5
  import {
8
6
  AaveIncentiveDataProviderV3ContractViem,
9
7
  AaveRewardsControllerViem,
@@ -39,7 +37,7 @@ export async function getUnclaimedRewardsForAllMarkets(
39
37
  network: NetworkNumber,
40
38
  walletAddress: EthAddress,
41
39
  marketAddress: EthAddress,
42
- ): Promise<AaveRewardsClaimableToken[]> {
40
+ ): Promise<ClaimableToken[]> {
43
41
  const contract = AaveIncentiveDataProviderV3ContractViem(provider, network);
44
42
  const tokensData = await contract.read.getUserReservesIncentivesData([marketAddress, walletAddress]);
45
43
  const allTokensDataArrays = tokensData.reduce((acc: any[], val) => {
@@ -2,7 +2,7 @@ import { getAssetInfo } from '@defisaver/tokens';
2
2
  import Dec from 'decimal.js';
3
3
  import { getAddress } from 'viem';
4
4
  import { EthAddress } from '../types/common';
5
- import { ClaimType, EthenaAirdropClaimableToken } from '../types/claiming';
5
+ import { ClaimType } from '../types/claiming';
6
6
  import { getEthAmountForDecimals } from '../services/utils';
7
7
 
8
8
  export const fetchEthenaAirdropReward = async (address: EthAddress) => {
@@ -23,11 +23,11 @@ export const fetchEthenaAirdropReward = async (address: EthAddress) => {
23
23
  }
24
24
  };
25
25
 
26
- export const fetchEthenaAirdropRewards = async (walletAddresses: EthAddress[]): Promise<Record<string, EthenaAirdropClaimableToken[]>> => {
26
+ export const fetchEthenaAirdropRewards = async (walletAddresses: EthAddress[]): Promise<Record<string, any[]>> => {
27
27
  const apiDataPromises = walletAddresses.map(address => fetchEthenaAirdropReward(address));
28
28
  const apiDataArray = await Promise.all(apiDataPromises);
29
29
 
30
- const results: Record<string, EthenaAirdropClaimableToken[]> = {};
30
+ const results: Record<string, any[]> = {};
31
31
  for (let i = 0; i < walletAddresses.length; i++) {
32
32
  const walletAddress = walletAddresses[i];
33
33
  const data = apiDataArray[i];
@@ -36,7 +36,7 @@ export const fetchEthenaAirdropRewards = async (walletAddresses: EthAddress[]):
36
36
  continue;
37
37
  }
38
38
 
39
- const processedRewards: EthenaAirdropClaimableToken[] = [];
39
+ const processedRewards = [];
40
40
  const assetInfo = getAssetInfo('sENA');
41
41
 
42
42
  const amount = getEthAmountForDecimals(data.events[0].awardAmount, assetInfo.decimals);
@@ -47,7 +47,7 @@ export const fetchEthenaAirdropRewards = async (walletAddresses: EthAddress[]):
47
47
  underlyingSymbol: assetInfo.symbol,
48
48
  amount,
49
49
  claimType: ClaimType.ETHENA_AIRDROP,
50
- tokenAddress: assetInfo.address as EthAddress,
50
+ tokenAddress: assetInfo.address,
51
51
  walletAddress,
52
52
  label: 'Ethena Airdrop',
53
53
  });
@@ -3,7 +3,7 @@ import { assetAmountInEth } from '@defisaver/tokens';
3
3
  import { Client } from 'viem';
4
4
  import { UUPSViem } from '../contracts';
5
5
  import { EthAddress, HexString, NetworkNumber } from '../types/common';
6
- import { ClaimType, KingRewardsClaimableToken } from '../types/claiming';
6
+ import { ClaimType } from '../types/claiming';
7
7
 
8
8
  export const fetchKingRewards = async (walletAddress: EthAddress) => {
9
9
  try {
@@ -19,7 +19,7 @@ export const fetchKingRewards = async (walletAddress: EthAddress) => {
19
19
  }
20
20
  };
21
21
 
22
- export const getKingRewards = async (provider: Client, network: NetworkNumber, walletAddresses: EthAddress[]): Promise<Record<string, KingRewardsClaimableToken[]>> => {
22
+ export const getKingRewards = async (provider: Client, network: NetworkNumber, walletAddresses: EthAddress[]) => {
23
23
  // Fetch all API data in parallel (these are external API calls, can't be batched with multicall)
24
24
  const apiDataPromises = walletAddresses.map(address => fetchKingRewards(address));
25
25
  const apiDataArray = await Promise.all(apiDataPromises);
@@ -31,7 +31,7 @@ export const getKingRewards = async (provider: Client, network: NetworkNumber, w
31
31
  const cumulativeResults = await Promise.all(cumulativePromises);
32
32
 
33
33
  // Process results
34
- const results: Record<string, KingRewardsClaimableToken[]> = {};
34
+ const results: Record<string, any[]> = {};
35
35
 
36
36
  for (let i = 0; i < walletAddresses.length; i++) {
37
37
  const walletAddress = walletAddresses[i];
@@ -7,9 +7,7 @@ import {
7
7
  SparkRewardsControllerViem,
8
8
  } from '../contracts';
9
9
  import { EthAddress, NetworkNumber } from '../types/common';
10
- import {
11
- ClaimType, SparkAirdropClaimableToken, SparkAirdropType, SparkRewardsClaimableToken,
12
- } from '../types/claiming';
10
+ import { ClaimType, SparkAirdropType, SparkRewardsClaimableToken } from '../types/claiming';
13
11
  import { compareAddresses, getEthAmountForDecimals } from '../services/utils';
14
12
 
15
13
  const IGNITION_REWARDS = '0xCBA0C0a2a0B6Bb11233ec4EA85C5bFfea33e724d';
@@ -52,7 +50,7 @@ export const fetchSparkAirdropRewards = async (
52
50
  provider: Client,
53
51
  network: NetworkNumber,
54
52
  walletAddresses: EthAddress[],
55
- ): Promise<Record<string, SparkAirdropClaimableToken[]>> => {
53
+ ) => {
56
54
  // Fetch all API data in parallel (these are external API calls, can't be batched with multicall)
57
55
  const apiDataPromises = walletAddresses.map(address => fetchSpkAirdropRewards(address));
58
56
  const apiDataArray = await Promise.all(apiDataPromises);
@@ -94,7 +92,7 @@ export const fetchSparkAirdropRewards = async (
94
92
  const cumulativeClaimedAmounts = await getCumulativeClaimedSpkAirdrop(provider, network, contractCallsData);
95
93
 
96
94
  // Process results
97
- const results: Record<string, SparkAirdropClaimableToken[]> = {};
95
+ const results: Record<string, any[]> = {};
98
96
  let contractCallIndex = 0;
99
97
 
100
98
  for (const { walletAddress, data } of allClaimData) {
@@ -103,7 +101,7 @@ export const fetchSparkAirdropRewards = async (
103
101
  continue;
104
102
  }
105
103
 
106
- const processedRewards: SparkAirdropClaimableToken[] = [];
104
+ const processedRewards = [];
107
105
  for (let i = 0; i < data.length; i++) {
108
106
  const rewardInfo = data[i];
109
107
  const assetInfo = getAssetInfoByAddress(rewardInfo.token_address);
@@ -11,7 +11,6 @@ import {
11
11
  FluidAggregatedVaultData,
12
12
  FluidAssetData,
13
13
  FluidAssetsData,
14
- FluidEarnPositionData,
15
14
  FluidFTokenDataStructOutput,
16
15
  FluidMarketData,
17
16
  FluidMarketInfo,
@@ -1599,7 +1598,7 @@ export const getFluidTokenData = async (
1599
1598
  token: string,
1600
1599
  ) => _getFluidTokenData(getViemProvider(provider, network), network, token);
1601
1600
 
1602
- const parseFDepositTokenData = (fTokenData: FluidFTokenDataStructOutput, userPosition: FluidUserEarnPositionStructOutput, apiData: any, fTokenAddress?: string): FluidEarnPositionData => {
1601
+ const parseFDepositTokenData = (fTokenData: FluidFTokenDataStructOutput, userPosition: FluidUserEarnPositionStructOutput, apiData: any, fTokenAddress?: string) => {
1603
1602
  const decimals = fTokenData.decimals.toString();
1604
1603
  const depositRate = new Dec(getEthAmountForDecimals(fTokenData.convertToShares.toString(), decimals)).toString();
1605
1604
  const withdrawRate = new Dec(getEthAmountForDecimals(fTokenData.convertToAssets.toString(), decimals)).toString();
@@ -1647,7 +1646,7 @@ export const getFluidDepositData = async (
1647
1646
  address: EthAddress,
1648
1647
  ) => _getFluidDepositData(getViemProvider(provider, network), network, token, address);
1649
1648
 
1650
- export const _getAllUserEarnPositionsWithFTokens = async (provider: Client, network: NetworkNumber, user: EthAddress): Promise<FluidEarnPositionData[]> => {
1649
+ export const _getAllUserEarnPositionsWithFTokens = async (provider: Client, network: NetworkNumber, user: EthAddress) => {
1651
1650
  const view = FluidViewContractViem(provider, network);
1652
1651
  const [
1653
1652
  [userPositions, fTokensData],
@@ -1666,7 +1665,7 @@ export const _getAllUserEarnPositionsWithFTokens = async (provider: Client, netw
1666
1665
  rewardsData = await rewardsApiResponse.json();
1667
1666
  }
1668
1667
 
1669
- const parsedRes = fTokensData.reduce<FluidEarnPositionData[]>((acc, fTokenData, i) => {
1668
+ const parsedRes = fTokensData.reduce<ReturnType<typeof parseFDepositTokenData>[]>((acc, fTokenData, i) => {
1670
1669
  const userPosition = userPositions[i];
1671
1670
  const deposited = userPosition?.underlyingAssets;
1672
1671
 
@@ -13,7 +13,7 @@ import {
13
13
  LiquityTroveManagerContractViem,
14
14
  LiquityViewContractViem,
15
15
  } from '../contracts';
16
- import { LIQUITY_TROVE_STATUS_ENUM, LiquityStakingData, LiquityTroveInfo } from '../types';
16
+ import { LIQUITY_TROVE_STATUS_ENUM, LiquityTroveInfo } from '../types';
17
17
  import { ZERO_ADDRESS } from '../constants';
18
18
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
19
19
  import { getEthAmountForDecimals } from '../services/utils';
@@ -127,7 +127,7 @@ export const _getLiquityTroveInfo = async (provider: Client, network: NetworkNum
127
127
 
128
128
  export const getLiquityTroveInfo = async (provider: EthereumProvider, network: NetworkNumber, address: EthAddress): Promise<LiquityTroveInfo> => _getLiquityTroveInfo(getViemProvider(provider, network, { batch: { multicall: true } }), network, address);
129
129
 
130
- export const getLiquityStakingData = async (provider: Client, network: NetworkNumber, address: EthAddress): Promise<LiquityStakingData> => {
130
+ export const getLiquityStakingData = async (provider: Client, network: NetworkNumber, address: EthAddress) => {
131
131
  const lqtyStakingView = LiquityLQTYStakingViem(provider, network);
132
132
  const stabilityPoolView = LiquityStabilityPoolViem(provider, network);
133
133
  const [
@@ -12,7 +12,7 @@ import {
12
12
  } from '../types/common';
13
13
  import {
14
14
  LIQUITY_V2_TROVE_STATUS_ENUM,
15
- LiquityV2AssetsData, LiquityV2MarketData, LiquityV2MarketInfo, LiquityV2SBoldYBoldData, LiquityV2StakingData, LiquityV2TroveData, LiquityV2UsedAssets,
15
+ LiquityV2AssetsData, LiquityV2MarketData, LiquityV2MarketInfo, LiquityV2TroveData, LiquityV2UsedAssets,
16
16
  LiquityV2Versions,
17
17
  } from '../types';
18
18
  import { getStakingApy, STAKING_ASSETS } from '../staking';
@@ -162,35 +162,31 @@ export const nftContractCreationBlockMapping = {
162
162
  [LiquityV2Versions.LiquityV2REthLegacy]: 21686257,
163
163
  };
164
164
 
165
- interface TroveTransfer {
166
- from?: EthAddress,
167
- to?: EthAddress,
168
- tokenId: string,
169
- blockNumber: number,
170
- }
171
-
172
- /** Every Transfer of a market's trove NFT since the contract was created (or, on a fork, in the last 1000 blocks). */
173
- const getTroveTransfers = async (provider: PublicClient, network: NetworkNumber, troveNFTAddress: EthAddress, limitBlocksForEventFetching: boolean, market: LiquityV2Versions): Promise<TroveTransfer[]> => {
165
+ const getTransferredTroves = async (provider: PublicClient, network: NetworkNumber, troveNFTAddress: EthAddress, limitBlocksForEventFetching: boolean, market: LiquityV2Versions, account: EthAddress): Promise<{ troveId: string }[]> => {
174
166
  const nftContract = createViemContractFromConfigFunc('LiquityV2TroveNFT', troveNFTAddress)(provider, network);
175
167
  const nftContractCreationBlock = nftContractCreationBlockMapping[market];
176
168
  const currentBlock = +(await provider.getBlockNumber()).toString();
177
169
  const _events = await nftContract.getEvents.Transfer({}, { fromBlock: limitBlocksForEventFetching ? BigInt(currentBlock - 1000) : BigInt(nftContractCreationBlock) });
178
- return _events.map((event) => ({
170
+ const events = _events.map((event) => ({
179
171
  from: event.args.from, to: event.args.to, tokenId: event.args.tokenId!.toString(), blockNumber: +(event.blockNumber.toString()),
180
172
  }));
181
- };
173
+ const userTransferredTroves = events.filter((event) => compareAddresses(event.to, account));
182
174
 
183
- /** The troves transferred to an account that it still holds: no later transfer of the same trove. */
184
- const getAccountTransferredTroves = (events: TroveTransfer[], account: EthAddress): { troveId: string }[] => events
185
- .filter((event) => compareAddresses(event.to, account))
186
- .filter((event) => !events.some((e) => event.blockNumber < e.blockNumber && e.tokenId === event.tokenId))
187
- .map((event) => ({ troveId: event.tokenId }));
188
-
189
- const getTransferredTroves = async (provider: PublicClient, network: NetworkNumber, troveNFTAddress: EthAddress, limitBlocksForEventFetching: boolean, market: LiquityV2Versions, account: EthAddress): Promise<{ troveId: string }[]> => (
190
- getAccountTransferredTroves(await getTroveTransfers(provider, network, troveNFTAddress, limitBlocksForEventFetching, market), account));
175
+ // check if the last know transfer address is the user
176
+ userTransferredTroves.forEach((event, index) => {
177
+ const otherTransfers = events.filter((e) => event.blockNumber < e.blockNumber && e.tokenId === event.tokenId);
178
+ // @ts-ignore
179
+ userTransferredTroves[index].invalid = !!otherTransfers.length;
180
+ });
181
+ // @ts-ignore
182
+ return userTransferredTroves.filter((event) => !event.invalid).map((event) => ({ troveId: event.tokenId }));
183
+ };
191
184
 
192
- /** The troves an account opened and still owns, then the ones transferred to it, each once. */
193
- const mergeTroveIds = (userTroves: { troveId: string }[], userTransferredTroves: { troveId: string }[]): { troveId: string }[] => {
185
+ export const _getLiquityV2UserTroveIds = async (provider: PublicClient, network: NetworkNumber, selectedMarket: LiquityV2MarketInfo, troveNFTAddress: EthAddress, limitBlocksForEventFetching: boolean, account: EthAddress): Promise<{ troves: { troveId: string }[], nextFreeTroveIndex: string }> => {
186
+ const [{ troves: userTroves, nextFreeTroveIndex }, userTransferredTroves] = await Promise.all([
187
+ getUserTroves(provider, network, selectedMarket.isLegacy, account, selectedMarket.marketAddress),
188
+ getTransferredTroves(provider, network, troveNFTAddress, limitBlocksForEventFetching, selectedMarket.value, account),
189
+ ]);
194
190
  const troves = [...userTroves.map(({ troveId }) => ({ troveId })), ...userTransferredTroves];
195
191
  const filteredTroves = troves.filter((value, index, self) => index === self.findIndex((t) => (
196
192
  t.troveId === value.troveId
@@ -199,30 +195,8 @@ const mergeTroveIds = (userTroves: { troveId: string }[], userTransferredTroves:
199
195
  const troveIds = filteredTroves.map((trove) => trove.troveId);
200
196
  const troveIdsSet = new Set(troveIds);
201
197
  const troveIdsArray = Array.from(troveIdsSet);
202
- return troveIdsArray.map((troveId) => troves.find((trove) => trove.troveId === troveId)) as { troveId: string }[];
203
- };
204
-
205
- /**
206
- * The trove ids of several accounts in one market: the market's NFT transfers are read once for all of them, rather
207
- * than once per account as _getLiquityV2UserTroveIds does.
208
- */
209
- export const _getLiquityV2UsersTroveIds = async (provider: PublicClient, network: NetworkNumber, selectedMarket: LiquityV2MarketInfo, troveNFTAddress: EthAddress, limitBlocksForEventFetching: boolean, accounts: EthAddress[]): Promise<Record<EthAddress, string[]>> => {
210
- const [userTroves, events] = await Promise.all([
211
- Promise.all(accounts.map((account) => getUserTroves(provider, network, selectedMarket.isLegacy, account, selectedMarket.marketAddress))),
212
- getTroveTransfers(provider, network, troveNFTAddress, limitBlocksForEventFetching, selectedMarket.value),
213
- ]);
214
- return Object.fromEntries(accounts.map((account, i) => [
215
- account,
216
- mergeTroveIds(userTroves[i].troves, getAccountTransferredTroves(events, account)).map(({ troveId }) => troveId),
217
- ]));
218
- };
219
-
220
- export const _getLiquityV2UserTroveIds = async (provider: PublicClient, network: NetworkNumber, selectedMarket: LiquityV2MarketInfo, troveNFTAddress: EthAddress, limitBlocksForEventFetching: boolean, account: EthAddress): Promise<{ troves: { troveId: string }[], nextFreeTroveIndex: string }> => {
221
- const [{ troves: userTroves, nextFreeTroveIndex }, userTransferredTroves] = await Promise.all([
222
- getUserTroves(provider, network, selectedMarket.isLegacy, account, selectedMarket.marketAddress),
223
- getTransferredTroves(provider, network, troveNFTAddress, limitBlocksForEventFetching, selectedMarket.value, account),
224
- ]);
225
- return { troves: mergeTroveIds(userTroves, userTransferredTroves), nextFreeTroveIndex };
198
+ const trovesNoDuplicates = troveIdsArray.map((troveId) => troves.find((trove) => trove.troveId === troveId)) as { troveId: string }[];
199
+ return { troves: trovesNoDuplicates, nextFreeTroveIndex };
226
200
  };
227
201
 
228
202
  export const getLiquityV2UserTroveIds = async (
@@ -605,7 +579,7 @@ const calculateSPApy = (
605
579
  return apy;
606
580
  };
607
581
 
608
- export const getLiquityV2Staking = async (provider: Client, network: NetworkNumber, market: LiquityV2Versions, user: EthAddress): Promise<LiquityV2StakingData> => {
582
+ export const getLiquityV2Staking = async (provider: Client, network: NetworkNumber, market: LiquityV2Versions, user: EthAddress) => {
609
583
  const stabilityPoolView = createViemContractFromConfigFunc('LiquityV2StabilityPool', stabilityPoolAddrForMarket[market])(provider, network);
610
584
  const activePoolView = createViemContractFromConfigFunc('LiquityV2ActivePool', activePoolAddrForMarket[market])(provider, network);
611
585
 
@@ -664,7 +638,7 @@ export const getLiquityV2Staking = async (provider: Client, network: NetworkNumb
664
638
  };
665
639
  };
666
640
 
667
- export const getLiquitySAndYBold = async (provider: Client, network: NetworkNumber, markets: any, user: EthAddress): Promise<LiquityV2SBoldYBoldData> => {
641
+ export const getLiquitySAndYBold = async (provider: Client, network: NetworkNumber, markets: any, user: EthAddress) => {
668
642
  const sBold = LiquityV2sBoldVaultViem(provider, network);
669
643
  const yBold = createViemContractFromConfigFunc('Erc4626', '0x9F4330700a36B29952869fac9b33f45EEdd8A3d8')(provider, network);
670
644
  const stYBold = createViemContractFromConfigFunc('Erc4626', '0x23346B04a7f55b8760E5860AA5A77383D63491cD')(provider, network);
@@ -1659,6 +1659,21 @@ export const MORPHO_BLUE_CBXRP_USDC_625_BASE = (networkId: NetworkNumber = Netwo
1659
1659
  marketId: '0xd4a903dc6d949519060c7707f9604fdc9772c046e05c2e3a8fce0bd7196e4109',
1660
1660
  protocolName: 'morpho-blue',
1661
1661
  });
1662
+ export const MORPHO_BLUE_CBHYPE_USDC_625_BASE = (networkId: NetworkNumber = NetworkNumber.Base): MorphoBlueMarketData => ({
1663
+ chainIds: [NetworkNumber.Base],
1664
+ label: 'Morpho Blue',
1665
+ shortLabel: 'cbHYPE/USDC',
1666
+ value: MorphoBlueVersions.MorphoBlueCbHYPEUSDC_625_Base,
1667
+ url: 'cbhypeusdc-76629002',
1668
+ loanToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
1669
+ collateralToken: '0xB200000000000000000000451d033a5000cb479e',
1670
+ oracle: '0x7FaD8B8De2DDb7b4B415e1Aa3613e45EeF9E4bFf',
1671
+ oracleType: MorphoBlueOracleType.MARKET_RATE,
1672
+ irm: '0x46415998764C29aB2a25CbeA6254146D50D22687',
1673
+ lltv: 0.625,
1674
+ marketId: '0x76629002c9fdb20fb2092053a4f22c5c65e04a81887218b9546f2a2d82b4c0a8',
1675
+ protocolName: 'morpho-blue',
1676
+ });
1662
1677
 
1663
1678
  // ARBITRUM
1664
1679
  export const MORPHO_BLUE_SYRUPUSDC_USDC_915_ARB = (networkId: NetworkNumber = NetworkNumber.Eth): MorphoBlueMarketData => ({
@@ -1935,6 +1950,7 @@ export const MorphoBlueMarkets = (networkId: NetworkNumber) => ({
1935
1950
  [MorphoBlueVersions.MorphoBlueUSDeUSDC_915_Base]: MORPHO_BLUE_USDE_USDC_915_BASE(networkId),
1936
1951
  [MorphoBlueVersions.MorphoBlueCbEthUSDC_770_Base]: MORPHO_BLUE_CBETH_USDC_770_BASE(networkId),
1937
1952
  [MorphoBlueVersions.MorphoBlueCbXRPUSDC_625_Base]: MORPHO_BLUE_CBXRP_USDC_625_BASE(networkId),
1953
+ [MorphoBlueVersions.MorphoBlueCbHYPEUSDC_625_Base]: MORPHO_BLUE_CBHYPE_USDC_625_BASE(networkId),
1938
1954
  [MorphoBlueVersions.MorphoBlueWsuperOETHbWETH_915_Base]: MORPHO_BLUE_WSUPEROETHB_WETH_915_BASE(networkId),
1939
1955
  [MorphoBlueVersions.MorphoBlueCbEthEth_945_Base]: MORPHO_BLUE_CBETH_ETH_945_BASE(networkId),
1940
1956
  [MorphoBlueVersions.MorphoBlueCbEthEth_965_Base]: MORPHO_BLUE_CBETH_ETH_965_BASE(networkId),