@defisaver/positions-sdk 2.1.169-custom-fetching-dev → 2.1.169-custom-fetching-3-dev
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/cjs/aaveV2/index.d.ts +4 -4
- package/cjs/aaveV2/index.js +7 -7
- package/cjs/aaveV3/index.d.ts +4 -3
- package/cjs/aaveV3/index.js +14 -10
- package/cjs/aaveV3/merkl.d.ts +5 -1
- package/cjs/aaveV3/merkl.js +8 -3
- package/cjs/aaveV4/index.d.ts +4 -3
- package/cjs/aaveV4/index.js +19 -16
- package/cjs/aaveV4/merkl.d.ts +10 -2
- package/cjs/aaveV4/merkl.js +15 -6
- package/cjs/claiming/aaveV3.d.ts +2 -2
- package/cjs/claiming/aaveV3.js +5 -4
- package/cjs/claiming/king.d.ts +2 -2
- package/cjs/claiming/king.js +3 -2
- package/cjs/claiming/spark.d.ts +3 -3
- package/cjs/claiming/spark.js +8 -7
- package/cjs/claiming/uniswap.d.ts +2 -2
- package/cjs/claiming/uniswap.js +3 -2
- package/cjs/compoundV2/index.d.ts +4 -4
- package/cjs/compoundV2/index.js +9 -9
- package/cjs/compoundV3/index.d.ts +5 -4
- package/cjs/compoundV3/index.js +17 -13
- package/cjs/compoundV3/merkl.d.ts +1 -1
- package/cjs/compoundV3/merkl.js +2 -5
- package/cjs/curveUsd/index.d.ts +5 -5
- package/cjs/curveUsd/index.js +17 -17
- package/cjs/fluid/index.d.ts +23 -22
- package/cjs/fluid/index.js +75 -72
- package/cjs/fluid/merkl.d.ts +5 -3
- package/cjs/fluid/merkl.js +11 -6
- package/cjs/liquity/index.d.ts +4 -4
- package/cjs/liquity/index.js +23 -23
- package/cjs/liquityV2/index.d.ts +10 -10
- package/cjs/liquityV2/index.js +59 -59
- package/cjs/llamaLend/index.d.ts +5 -5
- package/cjs/llamaLend/index.js +13 -13
- package/cjs/maker/index.d.ts +6 -6
- package/cjs/maker/index.js +16 -16
- package/cjs/morphoBlue/index.d.ts +7 -7
- package/cjs/morphoBlue/index.js +28 -26
- package/cjs/morphoBlue/merkl.d.ts +5 -3
- package/cjs/morphoBlue/merkl.js +6 -8
- package/cjs/morphoMidnight/index.d.ts +5 -5
- package/cjs/morphoMidnight/index.js +18 -18
- package/cjs/portfolio/customDeFiData.js +45 -40
- package/cjs/services/merkl.d.ts +36 -2
- package/cjs/services/merkl.js +142 -19
- package/cjs/services/priceService.d.ts +12 -12
- package/cjs/services/priceService.js +30 -29
- package/cjs/services/viem.d.ts +10 -2
- package/cjs/services/viem.js +27 -1
- package/cjs/spark/index.d.ts +4 -4
- package/cjs/spark/index.js +9 -9
- package/cjs/types/merkl.d.ts +18 -0
- package/cjs/types/portfolio.d.ts +2 -0
- package/cjs/umbrella/index.d.ts +2 -2
- package/cjs/umbrella/index.js +5 -4
- package/esm/aaveV2/index.d.ts +4 -4
- package/esm/aaveV2/index.js +8 -8
- package/esm/aaveV3/index.d.ts +4 -3
- package/esm/aaveV3/index.js +15 -11
- package/esm/aaveV3/merkl.d.ts +5 -1
- package/esm/aaveV3/merkl.js +9 -4
- package/esm/aaveV4/index.d.ts +4 -3
- package/esm/aaveV4/index.js +20 -17
- package/esm/aaveV4/merkl.d.ts +10 -2
- package/esm/aaveV4/merkl.js +16 -7
- package/esm/claiming/aaveV3.d.ts +2 -2
- package/esm/claiming/aaveV3.js +5 -4
- package/esm/claiming/king.d.ts +2 -2
- package/esm/claiming/king.js +3 -2
- package/esm/claiming/spark.d.ts +3 -3
- package/esm/claiming/spark.js +8 -7
- package/esm/claiming/uniswap.d.ts +2 -2
- package/esm/claiming/uniswap.js +3 -2
- package/esm/compoundV2/index.d.ts +4 -4
- package/esm/compoundV2/index.js +9 -9
- package/esm/compoundV3/index.d.ts +5 -4
- package/esm/compoundV3/index.js +19 -15
- package/esm/compoundV3/merkl.d.ts +1 -1
- package/esm/compoundV3/merkl.js +3 -6
- package/esm/curveUsd/index.d.ts +5 -5
- package/esm/curveUsd/index.js +17 -17
- package/esm/fluid/index.d.ts +23 -22
- package/esm/fluid/index.js +76 -73
- package/esm/fluid/merkl.d.ts +5 -3
- package/esm/fluid/merkl.js +12 -7
- package/esm/liquity/index.d.ts +4 -4
- package/esm/liquity/index.js +23 -23
- package/esm/liquityV2/index.d.ts +10 -10
- package/esm/liquityV2/index.js +60 -60
- package/esm/llamaLend/index.d.ts +5 -5
- package/esm/llamaLend/index.js +13 -13
- package/esm/maker/index.d.ts +6 -6
- package/esm/maker/index.js +16 -16
- package/esm/morphoBlue/index.d.ts +7 -7
- package/esm/morphoBlue/index.js +29 -27
- package/esm/morphoBlue/merkl.d.ts +5 -3
- package/esm/morphoBlue/merkl.js +7 -9
- package/esm/morphoMidnight/index.d.ts +5 -5
- package/esm/morphoMidnight/index.js +18 -18
- package/esm/portfolio/customDeFiData.js +47 -42
- package/esm/services/merkl.d.ts +36 -2
- package/esm/services/merkl.js +136 -18
- package/esm/services/priceService.d.ts +12 -12
- package/esm/services/priceService.js +31 -30
- package/esm/services/viem.d.ts +10 -2
- package/esm/services/viem.js +25 -0
- package/esm/spark/index.d.ts +4 -4
- package/esm/spark/index.js +10 -10
- package/esm/types/merkl.d.ts +18 -0
- package/esm/types/portfolio.d.ts +2 -0
- package/esm/umbrella/index.d.ts +2 -2
- package/esm/umbrella/index.js +5 -4
- package/package.json +1 -1
- package/src/aaveV2/index.ts +7 -7
- package/src/aaveV3/index.ts +15 -11
- package/src/aaveV3/merkl.ts +9 -4
- package/src/aaveV4/index.ts +19 -16
- package/src/aaveV4/merkl.ts +16 -7
- package/src/claiming/aaveV3.ts +5 -3
- package/src/claiming/king.ts +6 -3
- package/src/claiming/spark.ts +9 -6
- package/src/claiming/uniswap.ts +4 -3
- package/src/compoundV2/index.ts +10 -9
- package/src/compoundV3/index.ts +20 -14
- package/src/compoundV3/merkl.ts +5 -4
- package/src/curveUsd/index.ts +19 -17
- package/src/fluid/index.ts +88 -70
- package/src/fluid/merkl.ts +12 -7
- package/src/liquity/index.ts +23 -23
- package/src/liquityV2/index.ts +64 -56
- package/src/llamaLend/index.ts +15 -13
- package/src/maker/index.ts +19 -16
- package/src/morphoBlue/index.ts +23 -20
- package/src/morphoBlue/merkl.ts +9 -6
- package/src/morphoMidnight/index.ts +13 -13
- package/src/portfolio/customDeFiData.ts +48 -41
- package/src/services/merkl.ts +152 -19
- package/src/services/priceService.ts +33 -30
- package/src/services/viem.ts +16 -0
- package/src/spark/index.ts +11 -8
- package/src/types/merkl.ts +20 -0
- package/src/types/portfolio.ts +2 -0
- package/src/umbrella/index.ts +6 -5
package/src/compoundV3/merkl.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getAssetInfoByAddress } from '@defisaver/tokens';
|
|
2
2
|
import { aprToApy } from '../moneymarket';
|
|
3
|
-
import {
|
|
3
|
+
import { fetchMerklOpportunities } from '../services/merkl';
|
|
4
4
|
import { compareAddresses, wethToEth } from '../services/utils';
|
|
5
5
|
import {
|
|
6
6
|
CompoundV3AssetData,
|
|
@@ -21,12 +21,13 @@ import {
|
|
|
21
21
|
* be gated and sized by a curated check in EligibilityMapping; unknown ids apply
|
|
22
22
|
* unconditionally, mirroring Aave V3.
|
|
23
23
|
*/
|
|
24
|
-
export const getCompoundV3MerklOpportunities = async (): Promise<MerklOpportunity[]> => {
|
|
24
|
+
export const getCompoundV3MerklOpportunities = async (asOfTimestamp?: number, chainId?: NetworkNumber): Promise<MerklOpportunity[]> => {
|
|
25
25
|
try {
|
|
26
|
-
return await
|
|
26
|
+
return await fetchMerklOpportunities({
|
|
27
27
|
mainProtocolId: 'compound-v3',
|
|
28
28
|
status: OpportunityStatus.LIVE,
|
|
29
|
-
|
|
29
|
+
...(chainId ? { chainId: chainId.toString() } : {}),
|
|
30
|
+
}, asOfTimestamp);
|
|
30
31
|
} catch (e) {
|
|
31
32
|
console.error('Failed to fetch Compound V3 Merkl campaigns', e);
|
|
32
33
|
return [];
|
package/src/curveUsd/index.ts
CHANGED
|
@@ -22,7 +22,7 @@ const ammRateToBorrowApy = (rateWei: string) => {
|
|
|
22
22
|
return new Dec(new Dec(2.718281828459).pow(exponent).minus(1)).mul(100).toString();
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
const getAndFormatBands = async (provider: Client, network: NetworkNumber, selectedMarket: CrvUSDMarketData, _minBand: string, _maxBand: string) => {
|
|
25
|
+
const getAndFormatBands = async (provider: Client, network: NetworkNumber, selectedMarket: CrvUSDMarketData, _minBand: string, _maxBand: string, blockNumber: Blockish = 'latest') => {
|
|
26
26
|
const contract = CrvUSDViewContractViem(provider, network);
|
|
27
27
|
const minBand = parseInt(_minBand, 10);
|
|
28
28
|
const maxBand = parseInt(_maxBand, 10);
|
|
@@ -46,7 +46,7 @@ const getAndFormatBands = async (provider: Client, network: NetworkNumber, selec
|
|
|
46
46
|
} else {
|
|
47
47
|
start = pivots[index - 1] + 1;
|
|
48
48
|
}
|
|
49
|
-
const pivotedBandsData = await contract.read.getBandsData([selectedMarket.controllerAddress, BigInt(start), BigInt(pivot)]);
|
|
49
|
+
const pivotedBandsData = await contract.read.getBandsData([selectedMarket.controllerAddress, BigInt(start), BigInt(pivot)], setViemBlockNumber(blockNumber));
|
|
50
50
|
return pivotedBandsData;
|
|
51
51
|
}))).flat();
|
|
52
52
|
|
|
@@ -59,17 +59,17 @@ const getAndFormatBands = async (provider: Client, network: NetworkNumber, selec
|
|
|
59
59
|
}));
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
export const _getCurveUsdGlobalData = async (provider: Client, network: NetworkNumber, selectedMarket: CrvUSDMarketData): Promise<CrvUSDGlobalMarketData> => {
|
|
62
|
+
export const _getCurveUsdGlobalData = async (provider: Client, network: NetworkNumber, selectedMarket: CrvUSDMarketData, blockNumber: Blockish = 'latest'): Promise<CrvUSDGlobalMarketData> => {
|
|
63
63
|
const contract = CrvUSDViewContractViem(provider, network);
|
|
64
64
|
const factoryContract = CrvUSDFactoryContractViem(provider, network);
|
|
65
65
|
const cntrollerContract = createViemContractFromConfigFunc('crvUSDwstETHController', selectedMarket.controllerAddress)(provider, network);
|
|
66
66
|
const debtAsset = selectedMarket.baseAsset;
|
|
67
67
|
|
|
68
68
|
const [debtCeiling, _, data, loanDiscountWei] = await Promise.all([
|
|
69
|
-
factoryContract.read.debt_ceiling([selectedMarket.controllerAddress]),
|
|
70
|
-
factoryContract.read.total_debt(),
|
|
71
|
-
contract.read.globalData([selectedMarket.controllerAddress]),
|
|
72
|
-
cntrollerContract.read.loan_discount(),
|
|
69
|
+
factoryContract.read.debt_ceiling([selectedMarket.controllerAddress], setViemBlockNumber(blockNumber)),
|
|
70
|
+
factoryContract.read.total_debt(setViemBlockNumber(blockNumber)),
|
|
71
|
+
contract.read.globalData([selectedMarket.controllerAddress], setViemBlockNumber(blockNumber)),
|
|
72
|
+
cntrollerContract.read.loan_discount(setViemBlockNumber(blockNumber)),
|
|
73
73
|
]);
|
|
74
74
|
|
|
75
75
|
// all prices are in 18 decimals
|
|
@@ -79,7 +79,7 @@ export const _getCurveUsdGlobalData = async (provider: Client, network: NetworkN
|
|
|
79
79
|
const borrowRate = ammRateToBorrowApy(data.ammRate.toString());
|
|
80
80
|
const futureBorrowRate = ammRateToBorrowApy(data.monetaryPolicyRate.toString());
|
|
81
81
|
|
|
82
|
-
const bandsData = await getAndFormatBands(provider, network, selectedMarket, data.minBand.toString(), data.maxBand.toString());
|
|
82
|
+
const bandsData = await getAndFormatBands(provider, network, selectedMarket, data.minBand.toString(), data.maxBand.toString(), blockNumber);
|
|
83
83
|
|
|
84
84
|
const leftToBorrow = new Dec(debtCeiling.toString()).minus(totalDebt).toString();
|
|
85
85
|
|
|
@@ -112,7 +112,8 @@ export const getCurveUsdGlobalData = async (
|
|
|
112
112
|
provider: EthereumProvider,
|
|
113
113
|
network: NetworkNumber,
|
|
114
114
|
selectedMarket: CrvUSDMarketData,
|
|
115
|
-
|
|
115
|
+
blockNumber: Blockish = 'latest',
|
|
116
|
+
): Promise<CrvUSDGlobalMarketData> => _getCurveUsdGlobalData(getViemProvider(provider, network), network, selectedMarket, blockNumber);
|
|
116
117
|
|
|
117
118
|
const getStatusForUser = (bandRange: string[], activeBand: string, crvUSDSupplied: string, collSupplied: string, healthPercent: string) => {
|
|
118
119
|
// if bands are equal, that can only be [0,0] which means user doesn't have loan (min number of bands is 4)
|
|
@@ -172,17 +173,17 @@ export const getCrvUsdAccountBalances = async (
|
|
|
172
173
|
/**
|
|
173
174
|
* @param borrowRate market borrow APY in % (`CrvUSDGlobalMarketData.borrowRate`); when omitted it is read from the view contract
|
|
174
175
|
*/
|
|
175
|
-
export const _getCurveUsdUserData = async (provider: Client, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData, activeBand: string, borrowRate?: string): Promise<CrvUSDUserData> => {
|
|
176
|
+
export const _getCurveUsdUserData = async (provider: Client, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData, activeBand: string, borrowRate?: string, blockNumber: Blockish = 'latest'): Promise<CrvUSDUserData> => {
|
|
176
177
|
const contract = CrvUSDViewContractViem(provider, network);
|
|
177
178
|
const collAsset = selectedMarket.collAsset;
|
|
178
179
|
const debtAsset = selectedMarket.baseAsset;
|
|
179
180
|
|
|
180
181
|
const [data, collStakingApy, marketBorrowRate] = await Promise.all([
|
|
181
|
-
contract.read.userData([selectedMarket.controllerAddress, address]),
|
|
182
|
+
contract.read.userData([selectedMarket.controllerAddress, address], setViemBlockNumber(blockNumber)),
|
|
182
183
|
STAKING_ASSETS.includes(collAsset) ? getStakingApy(collAsset) : Promise.resolve('0'),
|
|
183
184
|
borrowRate !== undefined
|
|
184
185
|
? Promise.resolve(borrowRate)
|
|
185
|
-
: contract.read.globalData([selectedMarket.controllerAddress]).then((globalData) => ammRateToBorrowApy(globalData.ammRate.toString())),
|
|
186
|
+
: contract.read.globalData([selectedMarket.controllerAddress], setViemBlockNumber(blockNumber)).then((globalData) => ammRateToBorrowApy(globalData.ammRate.toString())),
|
|
186
187
|
]);
|
|
187
188
|
|
|
188
189
|
const health = assetAmountInEth(data.health.toString());
|
|
@@ -223,7 +224,7 @@ export const _getCurveUsdUserData = async (provider: Client, network: NetworkNum
|
|
|
223
224
|
const priceHigh = assetAmountInEth(data.priceHigh.toString());
|
|
224
225
|
const priceLow = assetAmountInEth(data.priceLow.toString());
|
|
225
226
|
|
|
226
|
-
const _userBands = data.loanExists ? (await getAndFormatBands(provider, network, selectedMarket, data.bandRange[0].toString(), data.bandRange[1].toString())) : [];
|
|
227
|
+
const _userBands = data.loanExists ? (await getAndFormatBands(provider, network, selectedMarket, data.bandRange[0].toString(), data.bandRange[1].toString(), blockNumber)) : [];
|
|
227
228
|
|
|
228
229
|
const status = data.loanExists ? getStatusForUser(data.bandRange.map(b => b.toString()), activeBand, crvUSDSupplied, collSupplied, healthPercent) : CrvUSDStatus.Nonexistant;
|
|
229
230
|
|
|
@@ -267,10 +268,11 @@ export const getCurveUsdUserData = async (
|
|
|
267
268
|
selectedMarket: CrvUSDMarketData,
|
|
268
269
|
activeBand: string,
|
|
269
270
|
borrowRate?: string,
|
|
270
|
-
|
|
271
|
+
blockNumber: Blockish = 'latest',
|
|
272
|
+
): Promise<CrvUSDUserData> => _getCurveUsdUserData(getViemProvider(provider, network), network, address, selectedMarket, activeBand, borrowRate, blockNumber);
|
|
271
273
|
|
|
272
|
-
export const getCurveUsdFullPositionData = async (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData): Promise<CrvUSDUserData> => {
|
|
273
|
-
const marketData = await getCurveUsdGlobalData(provider, network, selectedMarket);
|
|
274
|
-
const positionData = await getCurveUsdUserData(provider, network, address, selectedMarket, marketData.activeBand, marketData.borrowRate);
|
|
274
|
+
export const getCurveUsdFullPositionData = async (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData, blockNumber: Blockish = 'latest'): Promise<CrvUSDUserData> => {
|
|
275
|
+
const marketData = await getCurveUsdGlobalData(provider, network, selectedMarket, blockNumber);
|
|
276
|
+
const positionData = await getCurveUsdUserData(provider, network, address, selectedMarket, marketData.activeBand, marketData.borrowRate, blockNumber);
|
|
275
277
|
return positionData;
|
|
276
278
|
};
|
package/src/fluid/index.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
FluidVaultDataStructOutputStruct,
|
|
23
23
|
FluidVaultType,
|
|
24
24
|
InnerFluidMarketData,
|
|
25
|
+
Blockish,
|
|
25
26
|
} from '../types';
|
|
26
27
|
import {
|
|
27
28
|
BTCPriceFeedContractViem,
|
|
@@ -66,7 +67,7 @@ import {
|
|
|
66
67
|
parseWstUSRPriceCalls,
|
|
67
68
|
} from '../services/priceService';
|
|
68
69
|
import { getStakingApy, STAKING_ASSETS } from '../staking';
|
|
69
|
-
import { getViemProvider } from '../services/viem';
|
|
70
|
+
import { getBlockTimestamp, getViemProvider, setViemBlockNumber } from '../services/viem';
|
|
70
71
|
import { attachFluidMerklIncentives, getFluidMerklCampaigns } from './merkl';
|
|
71
72
|
|
|
72
73
|
export {
|
|
@@ -101,6 +102,7 @@ const getChainLinkPricesForTokens = async (
|
|
|
101
102
|
tokens: string[],
|
|
102
103
|
network: NetworkNumber,
|
|
103
104
|
client: PublicClient,
|
|
105
|
+
blockNumber: Blockish = 'latest',
|
|
104
106
|
): Promise<{ [key: string]: string }> => {
|
|
105
107
|
const isMainnet = isMainnetNetwork(network);
|
|
106
108
|
|
|
@@ -158,7 +160,7 @@ const getChainLinkPricesForTokens = async (
|
|
|
158
160
|
|
|
159
161
|
const calls = [...staticCalls, ..._calls].filter((call) => call);
|
|
160
162
|
// @ts-ignore
|
|
161
|
-
const results = await client.multicall({ contracts: calls });
|
|
163
|
+
const results = await client.multicall({ contracts: calls, ...setViemBlockNumber(blockNumber) });
|
|
162
164
|
|
|
163
165
|
const ethPriceChainlink = new Dec(results[0].result as string).div(1e8).toString();
|
|
164
166
|
const btcPriceChainlink = new Dec(results[1].result as string).div(1e8).toString();
|
|
@@ -294,7 +296,7 @@ const getChainLinkPricesForTokens = async (
|
|
|
294
296
|
};
|
|
295
297
|
|
|
296
298
|
|
|
297
|
-
const getTokenPriceFromChainlink = async (asset: AssetData, network: NetworkNumber, provider: PublicClient) => {
|
|
299
|
+
const getTokenPriceFromChainlink = async (asset: AssetData, network: NetworkNumber, provider: PublicClient, blockNumber: Blockish = 'latest') => {
|
|
298
300
|
if (asset.symbol === 'sUSDS') {
|
|
299
301
|
return new Dec('105276929').div(1e8).toString();
|
|
300
302
|
}
|
|
@@ -305,15 +307,15 @@ const getTokenPriceFromChainlink = async (asset: AssetData, network: NetworkNumb
|
|
|
305
307
|
let loanTokenPrice;
|
|
306
308
|
if (asset.symbol === 'wstETH') {
|
|
307
309
|
// need to handle wstETH for l2s inside getWstETHPrice
|
|
308
|
-
loanTokenPrice = await getWstETHPriceFluid(provider, network);
|
|
310
|
+
loanTokenPrice = await getWstETHPriceFluid(provider, network, blockNumber);
|
|
309
311
|
} else if (isMainnet) {
|
|
310
312
|
const feedRegistryContract = FeedRegistryContractViem(provider, NetworkNumber.Eth);
|
|
311
|
-
loanTokenPrice = isTokenUSDA ? '100000000' : await feedRegistryContract.read.latestAnswer([loanTokenFeedAddress, USD_QUOTE]);
|
|
313
|
+
loanTokenPrice = isTokenUSDA ? '100000000' : await feedRegistryContract.read.latestAnswer([loanTokenFeedAddress, USD_QUOTE], setViemBlockNumber(blockNumber));
|
|
312
314
|
} else {
|
|
313
315
|
// Currently only base network is supported
|
|
314
316
|
const feedRegistryContract = DFSFeedRegistryContractViem(provider, network);
|
|
315
317
|
try {
|
|
316
|
-
const roundPriceData = isTokenUSDA ? [0, '100000000'] : await feedRegistryContract.read.latestRoundData([loanTokenFeedAddress, USD_QUOTE]);
|
|
318
|
+
const roundPriceData = isTokenUSDA ? [0, '100000000'] : await feedRegistryContract.read.latestRoundData([loanTokenFeedAddress, USD_QUOTE], setViemBlockNumber(blockNumber));
|
|
317
319
|
loanTokenPrice = roundPriceData[1].toString();
|
|
318
320
|
} catch (err) {
|
|
319
321
|
console.error(`Error fetching price for ${asset.symbol} on ${network}: ${err}`);
|
|
@@ -364,7 +366,7 @@ const getTradingApy = async (poolAddress: EthAddress) => {
|
|
|
364
366
|
return new Dec(data.tradingApy).div(100).toString();
|
|
365
367
|
};
|
|
366
368
|
|
|
367
|
-
const parseT1MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null) => {
|
|
369
|
+
const parseT1MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null, blockNumber: Blockish = 'latest') => {
|
|
368
370
|
const collAssetContract = getAssetInfoByAddress(data.supplyToken0, network);
|
|
369
371
|
const collAsset = getAssetInfo(getNativeAssetFromWrapped(collAssetContract.symbol), network);
|
|
370
372
|
const debtAssetContract = getAssetInfoByAddress(data.borrowToken0, network);
|
|
@@ -380,7 +382,7 @@ const parseT1MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
380
382
|
if (tokenPrices) {
|
|
381
383
|
debtPriceParsed = tokenPrices[debtAsset.symbol] || '0';
|
|
382
384
|
} else {
|
|
383
|
-
debtPriceParsed = await getTokenPriceFromChainlink(debtAssetContract, network, provider);
|
|
385
|
+
debtPriceParsed = await getTokenPriceFromChainlink(debtAssetContract, network, provider, blockNumber);
|
|
384
386
|
}
|
|
385
387
|
|
|
386
388
|
const collAssetData: FluidAssetData = {
|
|
@@ -484,7 +486,7 @@ const parseT1MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
484
486
|
} as FluidMarketData;
|
|
485
487
|
};
|
|
486
488
|
|
|
487
|
-
const parseT2MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null) => {
|
|
489
|
+
const parseT2MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null, blockNumber: Blockish = 'latest') => {
|
|
488
490
|
const collAsset0Contract = getAssetInfoByAddress(data.supplyToken0, network);
|
|
489
491
|
const collAsset0 = getAssetInfo(getNativeAssetFromWrapped(collAsset0Contract.symbol), network);
|
|
490
492
|
const collAsset1Contract = getAssetInfoByAddress(data.supplyToken1, network);
|
|
@@ -501,7 +503,7 @@ const parseT2MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
501
503
|
if (tokenPrices) {
|
|
502
504
|
prices = tokenPrices;
|
|
503
505
|
} else {
|
|
504
|
-
prices = await getChainLinkPricesForTokens([collAsset0Contract.address, collAsset1Contract.address, debtAssetContract.address], network, provider);
|
|
506
|
+
prices = await getChainLinkPricesForTokens([collAsset0Contract.address, collAsset1Contract.address, debtAssetContract.address], network, provider, blockNumber);
|
|
505
507
|
}
|
|
506
508
|
|
|
507
509
|
const {
|
|
@@ -677,7 +679,7 @@ const parseT2MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
677
679
|
} as FluidMarketData;
|
|
678
680
|
};
|
|
679
681
|
|
|
680
|
-
const parseT3MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null) => {
|
|
682
|
+
const parseT3MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null, blockNumber: Blockish = 'latest') => {
|
|
681
683
|
const collAssetContract = getAssetInfoByAddress(data.supplyToken0, network);
|
|
682
684
|
const collAsset = getAssetInfo(getNativeAssetFromWrapped(collAssetContract.symbol), network);
|
|
683
685
|
const debtAsset0Contract = getAssetInfoByAddress(data.borrowToken0, network);
|
|
@@ -715,7 +717,7 @@ const parseT3MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
715
717
|
if (tokenPrices) {
|
|
716
718
|
prices = tokenPrices;
|
|
717
719
|
} else {
|
|
718
|
-
prices = await getChainLinkPricesForTokens([collAssetContract.address, debtAsset0Contract.address, debtAsset1Contract.address], network, provider);
|
|
720
|
+
prices = await getChainLinkPricesForTokens([collAssetContract.address, debtAsset0Contract.address, debtAsset1Contract.address], network, provider, blockNumber);
|
|
719
721
|
}
|
|
720
722
|
|
|
721
723
|
const supplyRate = new Dec(data.supplyRateVault).div(100).toString();
|
|
@@ -867,7 +869,7 @@ const parseT3MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
867
869
|
} as FluidMarketData;
|
|
868
870
|
};
|
|
869
871
|
|
|
870
|
-
const parseT4MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null) => {
|
|
872
|
+
const parseT4MarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null, blockNumber: Blockish = 'latest') => {
|
|
871
873
|
const collAsset0Contract = getAssetInfoByAddress(data.supplyToken0, network);
|
|
872
874
|
const collAsset0 = getAssetInfo(getNativeAssetFromWrapped(collAsset0Contract.symbol), network);
|
|
873
875
|
const collAsset1Contract = getAssetInfoByAddress(data.supplyToken1, network);
|
|
@@ -889,7 +891,7 @@ const parseT4MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
889
891
|
} else {
|
|
890
892
|
prices = await getChainLinkPricesForTokens(
|
|
891
893
|
[collAsset0Contract.address, collAsset1Contract.address, debtAsset0Contract.address, debtAsset1Contract.address],
|
|
892
|
-
network, provider);
|
|
894
|
+
network, provider, blockNumber);
|
|
893
895
|
}
|
|
894
896
|
|
|
895
897
|
const {
|
|
@@ -1124,7 +1126,7 @@ const parseT4MarketData = async (provider: PublicClient, data: FluidVaultDataStr
|
|
|
1124
1126
|
} as FluidMarketData;
|
|
1125
1127
|
};
|
|
1126
1128
|
|
|
1127
|
-
const parseMarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null) => {
|
|
1129
|
+
const parseMarketData = async (provider: PublicClient, data: FluidVaultDataStructOutputStruct, network: NetworkNumber, tokenPrices: Record<string, string> | null = null, blockNumber: Blockish = 'latest') => {
|
|
1128
1130
|
const marketInfo = getFluidMarketInfoById(+(data.vaultId.toString()), network);
|
|
1129
1131
|
if (!marketInfo) {
|
|
1130
1132
|
console.error(`Fluid market with address ${data.vault} not supported.`);
|
|
@@ -1133,13 +1135,13 @@ const parseMarketData = async (provider: PublicClient, data: FluidVaultDataStruc
|
|
|
1133
1135
|
const vaultType = parseVaultType(+(data.vaultType.toString()));
|
|
1134
1136
|
switch (vaultType) {
|
|
1135
1137
|
case FluidVaultType.T1:
|
|
1136
|
-
return parseT1MarketData(provider, data, network, tokenPrices);
|
|
1138
|
+
return parseT1MarketData(provider, data, network, tokenPrices, blockNumber);
|
|
1137
1139
|
case FluidVaultType.T2:
|
|
1138
|
-
return parseT2MarketData(provider, data, network, tokenPrices);
|
|
1140
|
+
return parseT2MarketData(provider, data, network, tokenPrices, blockNumber);
|
|
1139
1141
|
case FluidVaultType.T3:
|
|
1140
|
-
return parseT3MarketData(provider, data, network, tokenPrices);
|
|
1142
|
+
return parseT3MarketData(provider, data, network, tokenPrices, blockNumber);
|
|
1141
1143
|
case FluidVaultType.T4:
|
|
1142
|
-
return parseT4MarketData(provider, data, network, tokenPrices);
|
|
1144
|
+
return parseT4MarketData(provider, data, network, tokenPrices, blockNumber);
|
|
1143
1145
|
default:
|
|
1144
1146
|
throw new Error(`Unknown vault type: ${vaultType}`);
|
|
1145
1147
|
}
|
|
@@ -1450,15 +1452,15 @@ const parseUserData = (userPositionData: FluidUserPositionStructOutputStruct, va
|
|
|
1450
1452
|
}
|
|
1451
1453
|
};
|
|
1452
1454
|
|
|
1453
|
-
export const _getFluidMarketData = async (provider: PublicClient, network: NetworkNumber, market: FluidMarketInfo) => {
|
|
1455
|
+
export const _getFluidMarketData = async (provider: PublicClient, network: NetworkNumber, market: FluidMarketInfo, blockNumber: Blockish = 'latest') => {
|
|
1454
1456
|
const view = FluidViewContractViem(provider, network);
|
|
1455
1457
|
|
|
1456
1458
|
const [data, merklCampaigns] = await Promise.all([
|
|
1457
|
-
view.read.getVaultData([market.marketAddress]),
|
|
1459
|
+
view.read.getVaultData([market.marketAddress], setViemBlockNumber(blockNumber)),
|
|
1458
1460
|
getFluidMerklCampaigns(network),
|
|
1459
1461
|
]);
|
|
1460
1462
|
|
|
1461
|
-
const marketData = await parseMarketData(provider, data, network);
|
|
1463
|
+
const marketData = await parseMarketData(provider, data, network, null, blockNumber);
|
|
1462
1464
|
return marketData ? attachFluidMerklIncentives(marketData, merklCampaigns) : marketData;
|
|
1463
1465
|
};
|
|
1464
1466
|
|
|
@@ -1466,23 +1468,26 @@ export const getFluidMarketData = async (
|
|
|
1466
1468
|
provider: EthereumProvider,
|
|
1467
1469
|
network: NetworkNumber,
|
|
1468
1470
|
market: FluidMarketInfo,
|
|
1469
|
-
|
|
1471
|
+
blockNumber: Blockish = 'latest',
|
|
1472
|
+
) => _getFluidMarketData(getViemProvider(provider, network), network, market, blockNumber);
|
|
1470
1473
|
|
|
1471
1474
|
export const _getFluidVaultIdsForUser = async (
|
|
1472
1475
|
provider: Client,
|
|
1473
1476
|
network: NetworkNumber,
|
|
1474
1477
|
user: EthAddress,
|
|
1478
|
+
blockNumber: Blockish = 'latest',
|
|
1475
1479
|
): Promise<string[]> => {
|
|
1476
1480
|
const view = FluidViewContractViem(provider, network);
|
|
1477
1481
|
|
|
1478
|
-
return (await view.read.getUserNftIds([user])).map((item: bigint) => item.toString());
|
|
1482
|
+
return (await view.read.getUserNftIds([user], setViemBlockNumber(blockNumber))).map((item: bigint) => item.toString());
|
|
1479
1483
|
};
|
|
1480
1484
|
|
|
1481
1485
|
export const getFluidVaultIdsForUser = async (
|
|
1482
1486
|
provider: EthereumProvider,
|
|
1483
1487
|
network: NetworkNumber,
|
|
1484
1488
|
user: EthAddress,
|
|
1485
|
-
|
|
1489
|
+
blockNumber: Blockish = 'latest',
|
|
1490
|
+
): Promise<string[]> => _getFluidVaultIdsForUser(getViemProvider(provider, network), network, user, blockNumber);
|
|
1486
1491
|
|
|
1487
1492
|
|
|
1488
1493
|
export const _getFluidPosition = async (
|
|
@@ -1493,10 +1498,11 @@ export const _getFluidPosition = async (
|
|
|
1493
1498
|
assetsData: FluidAssetsData
|
|
1494
1499
|
marketData: InnerFluidMarketData,
|
|
1495
1500
|
},
|
|
1501
|
+
blockNumber: Blockish = 'latest',
|
|
1496
1502
|
): Promise<FluidVaultData> => {
|
|
1497
1503
|
const view = FluidViewContractViem(provider, network);
|
|
1498
1504
|
|
|
1499
|
-
const data = await view.read.getPositionByNftId([BigInt(vaultId)]);
|
|
1505
|
+
const data = await view.read.getPositionByNftId([BigInt(vaultId)], setViemBlockNumber(blockNumber));
|
|
1500
1506
|
|
|
1501
1507
|
const userPositionData = data[0];
|
|
1502
1508
|
|
|
@@ -1511,15 +1517,16 @@ export const getFluidPosition = async (
|
|
|
1511
1517
|
assetsData: FluidAssetsData
|
|
1512
1518
|
marketData: InnerFluidMarketData,
|
|
1513
1519
|
},
|
|
1514
|
-
|
|
1520
|
+
blockNumber: Blockish = 'latest',
|
|
1521
|
+
): Promise<FluidVaultData> => _getFluidPosition(getViemProvider(provider, network), network, vaultId, extractedState, blockNumber);
|
|
1515
1522
|
|
|
1516
|
-
export const _getFluidPositionWithMarket = async (provider: PublicClient, network: NetworkNumber, vaultId: string) => {
|
|
1523
|
+
export const _getFluidPositionWithMarket = async (provider: PublicClient, network: NetworkNumber, vaultId: string, blockNumber: Blockish = 'latest') => {
|
|
1517
1524
|
const view = FluidViewContractViem(provider, network);
|
|
1518
1525
|
const [data, merklCampaigns] = await Promise.all([
|
|
1519
|
-
view.read.getPositionByNftId([BigInt(vaultId)]),
|
|
1526
|
+
view.read.getPositionByNftId([BigInt(vaultId)], setViemBlockNumber(blockNumber)),
|
|
1520
1527
|
getFluidMerklCampaigns(network),
|
|
1521
1528
|
]);
|
|
1522
|
-
const parsedMarketData = await parseMarketData(provider, data[1], network);
|
|
1529
|
+
const parsedMarketData = await parseMarketData(provider, data[1], network, null, blockNumber);
|
|
1523
1530
|
if (!parsedMarketData) {
|
|
1524
1531
|
return;
|
|
1525
1532
|
}
|
|
@@ -1536,17 +1543,18 @@ export const getFluidPositionWithMarket = async (
|
|
|
1536
1543
|
provider: EthereumProvider,
|
|
1537
1544
|
network: NetworkNumber,
|
|
1538
1545
|
vaultId: string,
|
|
1539
|
-
|
|
1546
|
+
blockNumber: Blockish = 'latest',
|
|
1547
|
+
) => _getFluidPositionWithMarket(getViemProvider(provider, network), network, vaultId, blockNumber);
|
|
1540
1548
|
|
|
1541
|
-
export const _getAllFluidMarketDataChunked = async (network: NetworkNumber, provider: PublicClient) => {
|
|
1549
|
+
export const _getAllFluidMarketDataChunked = async (network: NetworkNumber, provider: PublicClient, blockNumber: Blockish = 'latest') => {
|
|
1542
1550
|
const versions = getFluidVersionsDataForNetwork(network);
|
|
1543
1551
|
const view = FluidViewContractViem(provider, network);
|
|
1544
1552
|
const [data, merklCampaigns] = await Promise.all([
|
|
1545
|
-
Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress]))),
|
|
1553
|
+
Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress], setViemBlockNumber(blockNumber)))),
|
|
1546
1554
|
getFluidMerklCampaigns(network),
|
|
1547
1555
|
]);
|
|
1548
1556
|
return Promise.all(data.map(async (item) => {
|
|
1549
|
-
const marketData = await parseMarketData(provider, item, network);
|
|
1557
|
+
const marketData = await parseMarketData(provider, item, network, null, blockNumber);
|
|
1550
1558
|
return marketData ? attachFluidMerklIncentives(marketData, merklCampaigns) : marketData;
|
|
1551
1559
|
}));
|
|
1552
1560
|
};
|
|
@@ -1554,16 +1562,17 @@ export const _getAllFluidMarketDataChunked = async (network: NetworkNumber, prov
|
|
|
1554
1562
|
export const getAllFluidMarketDataChunked = async (
|
|
1555
1563
|
network: NetworkNumber,
|
|
1556
1564
|
provider: EthereumProvider,
|
|
1557
|
-
|
|
1565
|
+
blockNumber: Blockish = 'latest',
|
|
1566
|
+
) => _getAllFluidMarketDataChunked(network, getViemProvider(provider, network, { batch: { multicall: true } }), blockNumber);
|
|
1558
1567
|
|
|
1559
|
-
export const _getFluidTokenData = async (provider: Client, network: NetworkNumber, token: string) => {
|
|
1568
|
+
export const _getFluidTokenData = async (provider: Client, network: NetworkNumber, token: string, blockNumber: Blockish = 'latest') => {
|
|
1560
1569
|
const view = FluidViewContractViem(provider, network);
|
|
1561
1570
|
const fTokenAddress = getFTokenAddress(token, network);
|
|
1562
1571
|
const [
|
|
1563
1572
|
data,
|
|
1564
1573
|
rewardsApiResponse,
|
|
1565
1574
|
] = await Promise.all([
|
|
1566
|
-
await view.read.getFTokenData([fTokenAddress]),
|
|
1575
|
+
await view.read.getFTokenData([fTokenAddress], setViemBlockNumber(blockNumber)),
|
|
1567
1576
|
fetch(`https://api.fluid.instadapp.io/v2/lending/${network}/tokens/${fTokenAddress}`),
|
|
1568
1577
|
]);
|
|
1569
1578
|
let rewardsData = { rewards: [] } as any;
|
|
@@ -1596,7 +1605,8 @@ export const getFluidTokenData = async (
|
|
|
1596
1605
|
provider: EthereumProvider,
|
|
1597
1606
|
network: NetworkNumber,
|
|
1598
1607
|
token: string,
|
|
1599
|
-
|
|
1608
|
+
blockNumber: Blockish = 'latest',
|
|
1609
|
+
) => _getFluidTokenData(getViemProvider(provider, network), network, token, blockNumber);
|
|
1600
1610
|
|
|
1601
1611
|
const parseFDepositTokenData = (fTokenData: FluidFTokenDataStructOutput, userPosition: FluidUserEarnPositionStructOutput, apiData: any, fTokenAddress?: string) => {
|
|
1602
1612
|
const decimals = fTokenData.decimals.toString();
|
|
@@ -1619,14 +1629,14 @@ const parseFDepositTokenData = (fTokenData: FluidFTokenDataStructOutput, userPos
|
|
|
1619
1629
|
};
|
|
1620
1630
|
};
|
|
1621
1631
|
|
|
1622
|
-
export const _getFluidDepositData = async (provider: Client, network: NetworkNumber, token: string, address: EthAddress) => {
|
|
1632
|
+
export const _getFluidDepositData = async (provider: Client, network: NetworkNumber, token: string, address: EthAddress, blockNumber: Blockish = 'latest') => {
|
|
1623
1633
|
const view = FluidViewContractViem(provider, network);
|
|
1624
1634
|
const fTokenAddress = getFTokenAddress(token, network);
|
|
1625
1635
|
const [
|
|
1626
1636
|
[userPosition, fTokenData],
|
|
1627
1637
|
rewardsApiResponse,
|
|
1628
1638
|
] = await Promise.all([
|
|
1629
|
-
view.read.getUserEarnPositionWithFToken([fTokenAddress, address]),
|
|
1639
|
+
view.read.getUserEarnPositionWithFToken([fTokenAddress, address], setViemBlockNumber(blockNumber)),
|
|
1630
1640
|
fetch(`https://api.fluid.instadapp.io/v2/lending/${network}/tokens/${fTokenAddress}`),
|
|
1631
1641
|
]);
|
|
1632
1642
|
let rewardsData = { rewards: [] };
|
|
@@ -1644,15 +1654,16 @@ export const getFluidDepositData = async (
|
|
|
1644
1654
|
network: NetworkNumber,
|
|
1645
1655
|
token: string,
|
|
1646
1656
|
address: EthAddress,
|
|
1647
|
-
|
|
1657
|
+
blockNumber: Blockish = 'latest',
|
|
1658
|
+
) => _getFluidDepositData(getViemProvider(provider, network), network, token, address, blockNumber);
|
|
1648
1659
|
|
|
1649
|
-
export const _getAllUserEarnPositionsWithFTokens = async (provider: Client, network: NetworkNumber, user: EthAddress) => {
|
|
1660
|
+
export const _getAllUserEarnPositionsWithFTokens = async (provider: Client, network: NetworkNumber, user: EthAddress, blockNumber: Blockish = 'latest') => {
|
|
1650
1661
|
const view = FluidViewContractViem(provider, network);
|
|
1651
1662
|
const [
|
|
1652
1663
|
[userPositions, fTokensData],
|
|
1653
1664
|
rewardsApiResponse,
|
|
1654
1665
|
] = await Promise.all([
|
|
1655
|
-
view.read.getAllUserEarnPositionsWithFTokens([user]),
|
|
1666
|
+
view.read.getAllUserEarnPositionsWithFTokens([user], setViemBlockNumber(blockNumber)),
|
|
1656
1667
|
fetch(`https://api.fluid.instadapp.io/v2/lending/${network}/tokens`),
|
|
1657
1668
|
]);
|
|
1658
1669
|
|
|
@@ -1685,17 +1696,18 @@ export const getAllUserEarnPositionsWithFTokens = async (
|
|
|
1685
1696
|
provider: EthereumProvider,
|
|
1686
1697
|
network: NetworkNumber,
|
|
1687
1698
|
user: EthAddress,
|
|
1688
|
-
|
|
1699
|
+
blockNumber: Blockish = 'latest',
|
|
1700
|
+
) => _getAllUserEarnPositionsWithFTokens(getViemProvider(provider, network), network, user, blockNumber);
|
|
1689
1701
|
|
|
1690
|
-
export const _getUserPositions = async (provider: PublicClient, network: NetworkNumber, user: EthAddress) => {
|
|
1702
|
+
export const _getUserPositions = async (provider: PublicClient, network: NetworkNumber, user: EthAddress, blockNumber: Blockish = 'latest') => {
|
|
1691
1703
|
const view = FluidViewContractViem(provider, network);
|
|
1692
1704
|
|
|
1693
1705
|
const [data, merklCampaigns] = await Promise.all([
|
|
1694
|
-
view.read.getUserPositions([user]),
|
|
1706
|
+
view.read.getUserPositions([user], setViemBlockNumber(blockNumber)),
|
|
1695
1707
|
getFluidMerklCampaigns(network),
|
|
1696
1708
|
]);
|
|
1697
1709
|
|
|
1698
|
-
const parsedMarketData = (await Promise.all(data[1].map(async (vaultData) => parseMarketData(provider, vaultData, network))))
|
|
1710
|
+
const parsedMarketData = (await Promise.all(data[1].map(async (vaultData) => parseMarketData(provider, vaultData, network, null, blockNumber))))
|
|
1699
1711
|
.map(marketData => (marketData ? attachFluidMerklIncentives(marketData, merklCampaigns) : marketData));
|
|
1700
1712
|
|
|
1701
1713
|
const userData = data[0].map((position, i) => (parsedMarketData[i] && { ...parseUserData(position, parsedMarketData[i]) }));
|
|
@@ -1710,45 +1722,46 @@ export const getUserPositions = async (
|
|
|
1710
1722
|
provider: EthereumProvider,
|
|
1711
1723
|
network: NetworkNumber,
|
|
1712
1724
|
user: EthAddress,
|
|
1713
|
-
|
|
1725
|
+
blockNumber: Blockish = 'latest',
|
|
1726
|
+
) => _getUserPositions(getViemProvider(provider, network), network, user, blockNumber);
|
|
1714
1727
|
|
|
1715
|
-
const getTokenPricePortfolio = async (token: string, provider: PublicClient, network: NetworkNumber) => {
|
|
1728
|
+
const getTokenPricePortfolio = async (token: string, provider: PublicClient, network: NetworkNumber, blockNumber: Blockish = 'latest') => {
|
|
1716
1729
|
if (token === 'ETH') {
|
|
1717
1730
|
const ethFeedContract = ETHPriceFeedContractViem(provider, network);
|
|
1718
|
-
return ethFeedContract.read.latestAnswer();
|
|
1731
|
+
return ethFeedContract.read.latestAnswer(setViemBlockNumber(blockNumber));
|
|
1719
1732
|
}
|
|
1720
1733
|
if (token === 'WBTC') {
|
|
1721
1734
|
const wbtcFeedContract = BTCPriceFeedContractViem(provider, network);
|
|
1722
|
-
return wbtcFeedContract.read.latestAnswer();
|
|
1735
|
+
return wbtcFeedContract.read.latestAnswer(setViemBlockNumber(blockNumber));
|
|
1723
1736
|
}
|
|
1724
1737
|
if (token === 'wstETH') {
|
|
1725
|
-
return getWstETHPrice(provider, network);
|
|
1738
|
+
return getWstETHPrice(provider, network, blockNumber);
|
|
1726
1739
|
}
|
|
1727
1740
|
if (token === 'weETH' && network !== NetworkNumber.Plasma) {
|
|
1728
|
-
return getWeETHPrice(provider, network);
|
|
1741
|
+
return getWeETHPrice(provider, network, blockNumber);
|
|
1729
1742
|
}
|
|
1730
1743
|
|
|
1731
1744
|
if (token === 'wrsETH') {
|
|
1732
|
-
return getWsrETHPrice(provider, network);
|
|
1745
|
+
return getWsrETHPrice(provider, network, blockNumber);
|
|
1733
1746
|
}
|
|
1734
1747
|
|
|
1735
1748
|
if (token === 'syrupUSDT') {
|
|
1736
|
-
return getSyrupUSDTPrice(provider, network);
|
|
1749
|
+
return getSyrupUSDTPrice(provider, network, blockNumber);
|
|
1737
1750
|
}
|
|
1738
1751
|
|
|
1739
1752
|
if (token === 'wstUSR') {
|
|
1740
|
-
return getWstUSRPrice(provider, network);
|
|
1753
|
+
return getWstUSRPrice(provider, network, blockNumber);
|
|
1741
1754
|
}
|
|
1742
1755
|
|
|
1743
1756
|
const isMainnet = isMainnetNetwork(network);
|
|
1744
1757
|
const chainLinkFeedAddress = getChainlinkAssetAddress(token, network);
|
|
1745
1758
|
if (isMainnet) {
|
|
1746
1759
|
const feedRegistryContract = FeedRegistryContractViem(provider, NetworkNumber.Eth);
|
|
1747
|
-
return feedRegistryContract.read.latestAnswer([chainLinkFeedAddress, USD_QUOTE]);
|
|
1760
|
+
return feedRegistryContract.read.latestAnswer([chainLinkFeedAddress, USD_QUOTE], setViemBlockNumber(blockNumber));
|
|
1748
1761
|
}
|
|
1749
1762
|
|
|
1750
1763
|
const feedRegistryContract = DFSFeedRegistryContractViem(provider, network);
|
|
1751
|
-
return feedRegistryContract.read.latestRoundData([chainLinkFeedAddress, USD_QUOTE]);
|
|
1764
|
+
return feedRegistryContract.read.latestRoundData([chainLinkFeedAddress, USD_QUOTE], setViemBlockNumber(blockNumber));
|
|
1752
1765
|
};
|
|
1753
1766
|
|
|
1754
1767
|
const tokensWithoutChainlinkPrices = ['sUSDS', 'USDA', 'ezETH', 'rsETH', 'weETHs', 'LBTC'];
|
|
@@ -1778,12 +1791,12 @@ const handleTokenWithoutChainlinkPrice = (token: string, prices: Record<string,
|
|
|
1778
1791
|
return '0';
|
|
1779
1792
|
};
|
|
1780
1793
|
|
|
1781
|
-
const getTokensPricesForPortfolio = async (tokens: string[], provider: PublicClient, network: NetworkNumber) => {
|
|
1794
|
+
const getTokensPricesForPortfolio = async (tokens: string[], provider: PublicClient, network: NetworkNumber, blockNumber: Blockish = 'latest') => {
|
|
1782
1795
|
const tokensWithChainlinkPrices = tokens.filter((token) => !tokensWithoutChainlinkPrices.includes(token));
|
|
1783
1796
|
const pricesFromChainlink: Record<string, string> = {};
|
|
1784
1797
|
await Promise.all(tokensWithChainlinkPrices.map(async (token) => {
|
|
1785
1798
|
try {
|
|
1786
|
-
const price = await getTokenPricePortfolio(token, provider, network);
|
|
1799
|
+
const price = await getTokenPricePortfolio(token, provider, network, blockNumber);
|
|
1787
1800
|
if (typeof price === 'string') pricesFromChainlink[token] = price;
|
|
1788
1801
|
else if (typeof price === 'bigint') pricesFromChainlink[token] = new Dec(price).div(1e8).toString();
|
|
1789
1802
|
else pricesFromChainlink[token] = new Dec(price[1]!.toString() as string).div(1e8).toString();
|
|
@@ -1800,10 +1813,10 @@ const getTokensPricesForPortfolio = async (tokens: string[], provider: PublicCli
|
|
|
1800
1813
|
return pricesFromChainlink;
|
|
1801
1814
|
};
|
|
1802
1815
|
|
|
1803
|
-
export const _getUserPositionsPortfolio = async (provider: PublicClient, network: NetworkNumber, user: EthAddress) => {
|
|
1816
|
+
export const _getUserPositionsPortfolio = async (provider: PublicClient, network: NetworkNumber, user: EthAddress, blockNumber: Blockish = 'latest') => {
|
|
1804
1817
|
const view = FluidViewContractViem(provider, network);
|
|
1805
1818
|
|
|
1806
|
-
const data = await view.read.getUserPositions([user]);
|
|
1819
|
+
const data = await view.read.getUserPositions([user], setViemBlockNumber(blockNumber));
|
|
1807
1820
|
const tokens = Array.from(new Set(data[1].map((vaultData) => {
|
|
1808
1821
|
const vaultTokens = [getAssetInfoByAddress(vaultData.supplyToken0, network).symbol, getAssetInfoByAddress(vaultData.borrowToken0, network).symbol];
|
|
1809
1822
|
if (vaultData.supplyToken1 && !compareAddresses(ZERO_ADDRESS, vaultData.supplyToken1)) vaultTokens.push(getAssetInfoByAddress(vaultData.supplyToken1, network).symbol);
|
|
@@ -1817,11 +1830,11 @@ export const _getUserPositionsPortfolio = async (provider: PublicClient, network
|
|
|
1817
1830
|
if (!tokens.includes('WBTC')) tokens.push('WBTC');
|
|
1818
1831
|
|
|
1819
1832
|
const [tokenPrices, merklCampaigns] = await Promise.all([
|
|
1820
|
-
getTokensPricesForPortfolio(tokens, provider, network),
|
|
1833
|
+
getTokensPricesForPortfolio(tokens, provider, network, blockNumber),
|
|
1821
1834
|
getFluidMerklCampaigns(network),
|
|
1822
1835
|
]);
|
|
1823
1836
|
|
|
1824
|
-
const parsedMarketData = (await Promise.all(data[1].map(async (vaultData) => parseMarketData(provider, vaultData, network, tokenPrices))))
|
|
1837
|
+
const parsedMarketData = (await Promise.all(data[1].map(async (vaultData) => parseMarketData(provider, vaultData, network, tokenPrices, blockNumber))))
|
|
1825
1838
|
.map(marketData => (marketData ? attachFluidMerklIncentives(marketData, merklCampaigns) : marketData));
|
|
1826
1839
|
|
|
1827
1840
|
const userData = data[0].map((position, i) => (parsedMarketData[i] && { ...parseUserData(position, parsedMarketData[i]) }));
|
|
@@ -1833,12 +1846,13 @@ export const _getUserPositionsPortfolio = async (provider: PublicClient, network
|
|
|
1833
1846
|
};
|
|
1834
1847
|
|
|
1835
1848
|
|
|
1836
|
-
|
|
1849
|
+
/** `blockTimestamp` (unix seconds) is the historical block's timestamp when already known; otherwise it is read from the block. */
|
|
1850
|
+
export const _getAllFluidMarketDataPortfolio = async (provider: PublicClient, network: NetworkNumber, blockNumber: Blockish = 'latest', blockTimestamp?: number): Promise<Record<string, FluidMarketData>> => {
|
|
1837
1851
|
const versions = getFluidVersionsDataForNetwork(network);
|
|
1838
1852
|
if (versions.length === 0) return {};
|
|
1839
1853
|
|
|
1840
1854
|
const view = FluidViewContractViem(provider, network);
|
|
1841
|
-
const vaultsData = await Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress])));
|
|
1855
|
+
const vaultsData = await Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress], setViemBlockNumber(blockNumber))));
|
|
1842
1856
|
|
|
1843
1857
|
const tokens = Array.from(new Set(vaultsData.map((vaultData) => {
|
|
1844
1858
|
const vaultTokens = [getAssetInfoByAddress(vaultData.supplyToken0, network).symbol, getAssetInfoByAddress(vaultData.borrowToken0, network).symbol];
|
|
@@ -1852,11 +1866,13 @@ export const _getAllFluidMarketDataPortfolio = async (provider: PublicClient, ne
|
|
|
1852
1866
|
if (!tokens.includes('WBTC')) tokens.push('WBTC');
|
|
1853
1867
|
|
|
1854
1868
|
const [tokenPrices, merklCampaigns] = await Promise.all([
|
|
1855
|
-
getTokensPricesForPortfolio(tokens, provider, network),
|
|
1856
|
-
|
|
1869
|
+
getTokensPricesForPortfolio(tokens, provider, network, blockNumber),
|
|
1870
|
+
// Merkl rewards are keyed by time: a historical block resolves to its timestamp first (one RPC
|
|
1871
|
+
// call unless given, none for 'latest') so the rewards in force at that moment are attached.
|
|
1872
|
+
getBlockTimestamp(provider, blockNumber, blockTimestamp).then((asOfTimestamp) => getFluidMerklCampaigns(network, asOfTimestamp)),
|
|
1857
1873
|
]);
|
|
1858
1874
|
|
|
1859
|
-
const parsedMarketsData = await Promise.all(vaultsData.map(async (vaultData) => parseMarketData(provider, vaultData, network, tokenPrices)));
|
|
1875
|
+
const parsedMarketsData = await Promise.all(vaultsData.map(async (vaultData) => parseMarketData(provider, vaultData, network, tokenPrices, blockNumber)));
|
|
1860
1876
|
|
|
1861
1877
|
const marketsData: Record<string, FluidMarketData> = {};
|
|
1862
1878
|
parsedMarketsData.forEach((marketData, i) => {
|
|
@@ -1870,4 +1886,6 @@ export const _getAllFluidMarketDataPortfolio = async (provider: PublicClient, ne
|
|
|
1870
1886
|
export const getAllFluidMarketDataPortfolio = async (
|
|
1871
1887
|
provider: EthereumProvider,
|
|
1872
1888
|
network: NetworkNumber,
|
|
1873
|
-
|
|
1889
|
+
blockNumber: Blockish = 'latest',
|
|
1890
|
+
blockTimestamp?: number,
|
|
1891
|
+
): Promise<Record<string, FluidMarketData>> => _getAllFluidMarketDataPortfolio(getViemProvider(provider, network, { batch: { multicall: true } }), network, blockNumber, blockTimestamp);
|