@defisaver/positions-sdk 2.1.167 → 2.1.168
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.js +8 -29
- package/cjs/aaveV3/index.js +2 -31
- package/cjs/aaveV4/index.d.ts +25 -0
- package/cjs/aaveV4/index.js +4 -1
- package/cjs/compoundV2/index.d.ts +1 -1
- package/cjs/compoundV2/index.js +2 -2
- package/cjs/curveUsd/index.d.ts +1 -1
- package/cjs/curveUsd/index.js +6 -1
- package/cjs/fluid/index.js +13 -12
- package/cjs/helpers/aaveBalances.d.ts +5 -0
- package/cjs/helpers/aaveBalances.js +51 -0
- package/cjs/helpers/fluidBalances.d.ts +6 -0
- package/cjs/helpers/fluidBalances.js +36 -0
- package/cjs/liquityV2/index.d.ts +8 -0
- package/cjs/liquityV2/index.js +3 -3
- package/cjs/llamaLend/index.d.ts +1 -1
- package/cjs/llamaLend/index.js +6 -1
- package/cjs/morphoMidnight/index.d.ts +1 -1
- package/cjs/morphoMidnight/index.js +6 -1
- package/cjs/portfolio/index.d.ts +1 -0
- package/cjs/portfolio/index.js +3 -0
- package/cjs/portfolio/lendingSummaries.d.ts +7 -0
- package/cjs/portfolio/lendingSummaries.js +262 -0
- package/cjs/portfolio/lendingSummaryTransport.d.ts +8 -0
- package/cjs/portfolio/lendingSummaryTransport.js +109 -0
- package/cjs/spark/index.js +2 -31
- package/cjs/types/index.d.ts +1 -0
- package/cjs/types/index.js +1 -0
- package/cjs/types/lendingSummary.d.ts +34 -0
- package/cjs/types/lendingSummary.js +2 -0
- package/esm/aaveV2/index.js +11 -32
- package/esm/aaveV3/index.js +3 -32
- package/esm/aaveV4/index.d.ts +25 -0
- package/esm/aaveV4/index.js +3 -1
- package/esm/compoundV2/index.d.ts +1 -1
- package/esm/compoundV2/index.js +2 -2
- package/esm/curveUsd/index.d.ts +1 -1
- package/esm/curveUsd/index.js +6 -1
- package/esm/fluid/index.js +13 -12
- package/esm/helpers/aaveBalances.d.ts +5 -0
- package/esm/helpers/aaveBalances.js +45 -0
- package/esm/helpers/fluidBalances.d.ts +6 -0
- package/esm/helpers/fluidBalances.js +28 -0
- package/esm/liquityV2/index.d.ts +8 -0
- package/esm/liquityV2/index.js +1 -1
- package/esm/llamaLend/index.d.ts +1 -1
- package/esm/llamaLend/index.js +6 -1
- package/esm/morphoMidnight/index.d.ts +1 -1
- package/esm/morphoMidnight/index.js +6 -1
- package/esm/portfolio/index.d.ts +1 -0
- package/esm/portfolio/index.js +1 -0
- package/esm/portfolio/lendingSummaries.d.ts +7 -0
- package/esm/portfolio/lendingSummaries.js +256 -0
- package/esm/portfolio/lendingSummaryTransport.d.ts +8 -0
- package/esm/portfolio/lendingSummaryTransport.js +104 -0
- package/esm/spark/index.js +4 -33
- package/esm/types/index.d.ts +1 -0
- package/esm/types/index.js +1 -0
- package/esm/types/lendingSummary.d.ts +34 -0
- package/esm/types/lendingSummary.js +1 -0
- package/package.json +1 -1
- package/src/aaveV2/index.ts +8 -48
- package/src/aaveV3/index.ts +2 -48
- package/src/aaveV4/index.ts +6 -1
- package/src/compoundV2/index.ts +2 -2
- package/src/curveUsd/index.ts +6 -1
- package/src/fluid/index.ts +13 -12
- package/src/helpers/aaveBalances.ts +41 -0
- package/src/helpers/fluidBalances.ts +34 -0
- package/src/liquityV2/index.ts +1 -1
- package/src/llamaLend/index.ts +6 -1
- package/src/morphoMidnight/index.ts +6 -1
- package/src/portfolio/index.ts +2 -0
- package/src/portfolio/lendingSummaries.ts +216 -0
- package/src/portfolio/lendingSummaryTransport.ts +84 -0
- package/src/spark/index.ts +3 -49
- package/src/types/index.ts +2 -1
- package/src/types/lendingSummary.ts +41 -0
package/esm/aaveV4/index.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import Dec from 'decimal.js';
|
|
11
11
|
import { assetAmountInEth, assetAmountInWei, getAssetInfoByAddress } from '@defisaver/tokens';
|
|
12
|
-
import { getViemProvider } from '../services/viem';
|
|
12
|
+
import { getViemProvider, setViemBlockNumber } from '../services/viem';
|
|
13
13
|
import { IncentiveKind, } from '../types';
|
|
14
14
|
import { AaveV4ViewContractViem } from '../contracts';
|
|
15
15
|
import { getStakingApy, STAKING_ASSETS } from '../staking';
|
|
@@ -251,6 +251,8 @@ export function _getAaveV4AccountData(provider_1, network_1, spokeData_1, addres
|
|
|
251
251
|
riskPremiumBps });
|
|
252
252
|
});
|
|
253
253
|
}
|
|
254
|
+
/** Shared raw read; no spoke metadata or market enrichment. */
|
|
255
|
+
export const _getAaveV4LoanBalances = (provider, network, block, address, spoke) => (AaveV4ViewContractViem(provider, network, block).read.getLoanData([spoke, address], setViemBlockNumber(block)));
|
|
254
256
|
/**
|
|
255
257
|
* Lightweight existence check for Loan Shifter / UI discovery.
|
|
256
258
|
* Reads only `getLoanData(spoke, user)` and returns whether any reserve has
|
|
@@ -17,7 +17,7 @@ export declare const EMPTY_COMPOUND_DATA: {
|
|
|
17
17
|
borrowStableSupplyUnstable: boolean;
|
|
18
18
|
exposure: string;
|
|
19
19
|
};
|
|
20
|
-
export declare const _getCompoundV2AccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress) => Promise<PositionBalances>;
|
|
20
|
+
export declare const _getCompoundV2AccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, tokens?: EthAddress[]) => Promise<PositionBalances>;
|
|
21
21
|
export declare const getCompoundV2AccountBalances: (provider: EthereumProvider, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress) => Promise<PositionBalances>;
|
|
22
22
|
export declare const _getCompoundV2AccountData: (provider: Client, network: NetworkNumber, address: EthAddress, assetsData: CompoundV2AssetsData) => Promise<CompoundV2PositionData>;
|
|
23
23
|
export declare const getCompoundV2AccountData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, assetsData: CompoundV2AssetsData) => Promise<CompoundV2PositionData>;
|
package/esm/compoundV2/index.js
CHANGED
|
@@ -101,7 +101,7 @@ const getAllMarketAddresses = (provider, network, block) => __awaiter(void 0, vo
|
|
|
101
101
|
const contract = ComptrollerContractViem(provider, network);
|
|
102
102
|
return contract.read.getAllMarkets(setViemBlockNumber(block));
|
|
103
103
|
});
|
|
104
|
-
export const _getCompoundV2AccountBalances = (provider, network, block, addressMapping, address) => __awaiter(void 0, void 0, void 0, function* () {
|
|
104
|
+
export const _getCompoundV2AccountBalances = (provider, network, block, addressMapping, address, tokens) => __awaiter(void 0, void 0, void 0, function* () {
|
|
105
105
|
let balances = {
|
|
106
106
|
collateral: {},
|
|
107
107
|
debt: {},
|
|
@@ -109,7 +109,7 @@ export const _getCompoundV2AccountBalances = (provider, network, block, addressM
|
|
|
109
109
|
if (!address) {
|
|
110
110
|
return balances;
|
|
111
111
|
}
|
|
112
|
-
const assets = yield getAllMarketAddresses(provider, network, block);
|
|
112
|
+
const assets = tokens || (yield getAllMarketAddresses(provider, network, block));
|
|
113
113
|
const assetInfo = assets.map(a => getAssetInfoByAddress(a, network));
|
|
114
114
|
const loanInfoContract = CompoundLoanInfoContractViem(provider, network, block);
|
|
115
115
|
const loanInfo = yield loanInfoContract.read.getTokenBalances([address, assets], setViemBlockNumber(block));
|
package/esm/curveUsd/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { CrvUSDGlobalMarketData, CrvUSDMarketData, CrvUSDUserData } from '../typ
|
|
|
3
3
|
import { Blockish, EthAddress, EthereumProvider, NetworkNumber, PositionBalances } from '../types/common';
|
|
4
4
|
export declare const _getCurveUsdGlobalData: (provider: Client, network: NetworkNumber, selectedMarket: CrvUSDMarketData) => Promise<CrvUSDGlobalMarketData>;
|
|
5
5
|
export declare const getCurveUsdGlobalData: (provider: EthereumProvider, network: NetworkNumber, selectedMarket: CrvUSDMarketData) => Promise<CrvUSDGlobalMarketData>;
|
|
6
|
-
export declare const _getCrvUsdAccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress) => Promise<PositionBalances>;
|
|
6
|
+
export declare const _getCrvUsdAccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress, includeDeposited?: boolean) => Promise<PositionBalances>;
|
|
7
7
|
export declare const getCrvUsdAccountBalances: (provider: EthereumProvider, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress) => Promise<PositionBalances>;
|
|
8
8
|
/**
|
|
9
9
|
* @param borrowRate market borrow APY in % (`CrvUSDGlobalMarketData.borrowRate`); when omitted it is read from the view contract
|
package/esm/curveUsd/index.js
CHANGED
|
@@ -99,7 +99,7 @@ const getStatusForUser = (bandRange, activeBand, crvUSDSupplied, collSupplied, h
|
|
|
99
99
|
return CrvUSDStatus.SoftLiquidated; // or is fully soft liquidated
|
|
100
100
|
return CrvUSDStatus.Nonexistant;
|
|
101
101
|
};
|
|
102
|
-
export const _getCrvUsdAccountBalances = (
|
|
102
|
+
export const _getCrvUsdAccountBalances = (provider_1, network_1, block_1, addressMapping_1, address_1, controllerAddress_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, block_1, addressMapping_1, address_1, controllerAddress_1, ...args_1], void 0, function* (provider, network, block, addressMapping, address, controllerAddress, includeDeposited = false) {
|
|
103
103
|
let balances = {
|
|
104
104
|
collateral: {},
|
|
105
105
|
debt: {},
|
|
@@ -118,6 +118,11 @@ export const _getCrvUsdAccountBalances = (provider, network, block, addressMappi
|
|
|
118
118
|
[addressMapping ? getAssetInfo(wethToEth(selectedMarket.baseAsset), network).address.toLowerCase() : wethToEth(selectedMarket.baseAsset)]: data.debtAmount.toString(),
|
|
119
119
|
},
|
|
120
120
|
};
|
|
121
|
+
if (includeDeposited) {
|
|
122
|
+
balances.deposited = {
|
|
123
|
+
[addressMapping ? getAssetInfo(wethToEth(selectedMarket.baseAsset), network).address.toLowerCase() : wethToEth(selectedMarket.baseAsset)]: data.curveUsdCollateralAmount.toString(),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
121
126
|
return balances;
|
|
122
127
|
});
|
|
123
128
|
export const getCrvUsdAccountBalances = (provider, network, block, addressMapping, address, controllerAddress) => __awaiter(void 0, void 0, void 0, function* () { return _getCrvUsdAccountBalances(getViemProvider(provider, network), network, block, addressMapping, address, controllerAddress); });
|
package/esm/fluid/index.js
CHANGED
|
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import Dec from 'decimal.js';
|
|
11
11
|
import { assetAmountInEth, getAssetInfo, getAssetInfoByAddress, } from '@defisaver/tokens';
|
|
12
|
+
import { fluidTokenAmount } from '../helpers/fluidBalances';
|
|
12
13
|
import { IncentiveKind, NetworkNumber, } from '../types/common';
|
|
13
14
|
import { FluidVaultType, } from '../types';
|
|
14
15
|
import { BTCPriceFeedContractViem, DFSFeedRegistryContractViem, ETHPriceFeedContractViem, FeedRegistryContractViem, FluidViewContractViem, } from '../contracts';
|
|
@@ -925,8 +926,8 @@ const parseT1UserData = (userPositionData, vaultData) => {
|
|
|
925
926
|
const collAsset = getAssetInfo(marketData.collAsset0);
|
|
926
927
|
const debtAsset = getAssetInfo(marketData.debtAsset0);
|
|
927
928
|
// for T2 and T4 - this is the number of shares
|
|
928
|
-
const supplied =
|
|
929
|
-
const borrowed =
|
|
929
|
+
const supplied = fluidTokenAmount(userPositionData.supply, collAsset.decimals);
|
|
930
|
+
const borrowed = fluidTokenAmount(userPositionData.borrow, debtAsset.decimals);
|
|
930
931
|
const collUsedAsset = Object.assign(Object.assign({}, EMPTY_USED_ASSET), { symbol: collAsset.symbol, collateral: true, supplied, suppliedUsd: new Dec(supplied).mul(assetsData[collAsset.symbol].price).toString(), isSupplied: new Dec(supplied).gt(0) });
|
|
931
932
|
const debtUsedAsset = Object.assign(Object.assign({}, EMPTY_USED_ASSET), { symbol: debtAsset.symbol, collateral: false, borrowed, borrowedUsd: new Dec(borrowed).mul(assetsData[debtAsset.symbol].price).toString(), isBorrowed: new Dec(borrowed).gt(0) });
|
|
932
933
|
const usedAssets = {
|
|
@@ -946,9 +947,9 @@ const parseT2UserData = (userPositionData, vaultData) => {
|
|
|
946
947
|
const collAsset1 = getAssetInfo(marketData.collAsset1);
|
|
947
948
|
const debtAsset = getAssetInfo(marketData.debtAsset0);
|
|
948
949
|
const supplyShares = getEthAmountForDecimals(userPositionData.supply.toString(), 18); // this is supplied in coll shares
|
|
949
|
-
const borrowed =
|
|
950
|
-
const supplied0 =
|
|
951
|
-
const supplied1 =
|
|
950
|
+
const borrowed = fluidTokenAmount(userPositionData.borrow, debtAsset.decimals); // this is actual token borrow
|
|
951
|
+
const supplied0 = fluidTokenAmount(userPositionData.supply, collAsset0.decimals, assetsData[collAsset0.symbol].tokenPerSupplyShare);
|
|
952
|
+
const supplied1 = fluidTokenAmount(userPositionData.supply, collAsset1.decimals, assetsData[collAsset1.symbol].tokenPerSupplyShare);
|
|
952
953
|
const collUsedAsset0 = {
|
|
953
954
|
symbol: collAsset0.symbol,
|
|
954
955
|
collateral: true,
|
|
@@ -991,10 +992,10 @@ const parseT3UserData = (userPositionData, vaultData) => {
|
|
|
991
992
|
const collAsset = getAssetInfo(marketData.collAsset0);
|
|
992
993
|
const debtAsset0 = getAssetInfo(marketData.debtAsset0);
|
|
993
994
|
const debtAsset1 = getAssetInfo(marketData.debtAsset1);
|
|
994
|
-
const supplied =
|
|
995
|
+
const supplied = fluidTokenAmount(userPositionData.supply, collAsset.decimals); // this is actual token supply
|
|
995
996
|
const borrowShares = getEthAmountForDecimals(userPositionData.borrow.toString(), 18); // this is actual token borrow
|
|
996
|
-
const borrowed0 =
|
|
997
|
-
const borrowed1 =
|
|
997
|
+
const borrowed0 = fluidTokenAmount(userPositionData.borrow, debtAsset0.decimals, assetsData[debtAsset0.symbol].tokenPerBorrowShare);
|
|
998
|
+
const borrowed1 = fluidTokenAmount(userPositionData.borrow, debtAsset1.decimals, assetsData[debtAsset1.symbol].tokenPerBorrowShare);
|
|
998
999
|
const collUsedAsset = {
|
|
999
1000
|
symbol: collAsset.symbol,
|
|
1000
1001
|
collateral: true,
|
|
@@ -1039,10 +1040,10 @@ const parseT4UserData = (userPositionData, vaultData) => {
|
|
|
1039
1040
|
const debtAsset1 = getAssetInfo(marketData.debtAsset1);
|
|
1040
1041
|
const supplyShares = getEthAmountForDecimals(userPositionData.supply.toString(), 18); // this is actual token supply
|
|
1041
1042
|
const borrowShares = getEthAmountForDecimals(userPositionData.borrow.toString(), 18); // this is actual token borrow
|
|
1042
|
-
const supplied0 =
|
|
1043
|
-
const supplied1 =
|
|
1044
|
-
const borrowed0 =
|
|
1045
|
-
const borrowed1 =
|
|
1043
|
+
const supplied0 = fluidTokenAmount(userPositionData.supply, collAsset0.decimals, assetsData[collAsset0.symbol].tokenPerSupplyShare);
|
|
1044
|
+
const supplied1 = fluidTokenAmount(userPositionData.supply, collAsset1.decimals, assetsData[collAsset1.symbol].tokenPerSupplyShare);
|
|
1045
|
+
const borrowed0 = fluidTokenAmount(userPositionData.borrow, debtAsset0.decimals, assetsData[debtAsset0.symbol].tokenPerBorrowShare);
|
|
1046
|
+
const borrowed1 = fluidTokenAmount(userPositionData.borrow, debtAsset1.decimals, assetsData[debtAsset1.symbol].tokenPerBorrowShare);
|
|
1046
1047
|
const collUsedAsset0 = {
|
|
1047
1048
|
symbol: collAsset0.symbol,
|
|
1048
1049
|
collateral: true,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Client } from 'viem';
|
|
2
|
+
import { AaveMarketInfo, SparkMarketData } from '../types';
|
|
3
|
+
import { Blockish, EthAddress, NetworkNumber, PositionBalances } from '../types/common';
|
|
4
|
+
/** Raw token balances shared by Aave/Spark getters and lending previews. */
|
|
5
|
+
export declare function getAaveLikeBalances(client: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, market: Pick<AaveMarketInfo | SparkMarketData, 'providerAddress' | 'protocolData' | 'protocolDataAddress'>, view: 'AaveLoanInfoV2' | 'AaveV3View' | 'SparkView', tokens?: EthAddress[]): Promise<PositionBalances>;
|
|
@@ -0,0 +1,45 @@
|
|
|
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 { getAssetInfoByAddress } from '@defisaver/tokens';
|
|
12
|
+
import { createViemContractFromConfigFunc } from '../contracts';
|
|
13
|
+
import { setViemBlockNumber } from '../services/viem';
|
|
14
|
+
import { wethToEth, wethToEthByAddress } from '../services/utils';
|
|
15
|
+
/** Raw token balances shared by Aave/Spark getters and lending previews. */
|
|
16
|
+
export function getAaveLikeBalances(client, network, block, addressMapping, address, market, view, tokens) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const balances = { collateral: {}, debt: {} };
|
|
19
|
+
if (!address)
|
|
20
|
+
return balances;
|
|
21
|
+
let reserves;
|
|
22
|
+
if (tokens)
|
|
23
|
+
reserves = tokens.map(tokenAddress => ({ tokenAddress, symbol: getAssetInfoByAddress(tokenAddress, network).symbol }));
|
|
24
|
+
else {
|
|
25
|
+
if (!market.protocolData)
|
|
26
|
+
throw new Error('Missing protocol data provider');
|
|
27
|
+
reserves = [...yield createViemContractFromConfigFunc(market.protocolData, market.protocolDataAddress)(client, network)
|
|
28
|
+
.read.getAllReservesTokens(setViemBlockNumber(block))];
|
|
29
|
+
}
|
|
30
|
+
const addresses = reserves.map(token => token.tokenAddress);
|
|
31
|
+
const contract = createViemContractFromConfigFunc(view)(client, network, block);
|
|
32
|
+
const middle = tokens ? Math.ceil(addresses.length / 2) : Math.floor(addresses.length / 2);
|
|
33
|
+
// Preserve legacy V2 single-call and V3/Spark two-call behavior.
|
|
34
|
+
const parts = !tokens && view === 'AaveLoanInfoV2' ? [addresses] : [addresses.slice(0, middle), addresses.slice(middle)];
|
|
35
|
+
const data = (yield Promise.all((tokens ? parts.filter(part => part.length) : parts)
|
|
36
|
+
.map(part => contract.read.getTokenBalances([market.providerAddress, address, part], setViemBlockNumber(block))))).flat();
|
|
37
|
+
data.forEach((token, i) => {
|
|
38
|
+
// The views leave token.token unset; input order identifies the reserve.
|
|
39
|
+
const key = addressMapping ? wethToEthByAddress(reserves[i].tokenAddress, network).toLowerCase() : wethToEth(reserves[i].symbol);
|
|
40
|
+
balances.collateral[key] = token.balance.toString();
|
|
41
|
+
balances.debt[key] = new Dec(token.borrowsStable.toString()).add(token.borrowsVariable.toString()).toString();
|
|
42
|
+
});
|
|
43
|
+
return balances;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FluidUserPositionStructOutputStruct, FluidVaultDataStructOutputStruct } from '../types';
|
|
2
|
+
import { NetworkNumber, PositionBalances } from '../types/common';
|
|
3
|
+
/** Convert raw tokens, or raw 18-decimal shares with a human-readable token/share ratio. */
|
|
4
|
+
export declare const fluidTokenAmount: (amount: bigint, decimals: number, perShare?: string) => string;
|
|
5
|
+
/** The same token/share conversion used by the full Fluid user parsers, without prices or yield. */
|
|
6
|
+
export declare function parseFluidBalances(position: FluidUserPositionStructOutputStruct, vault: FluidVaultDataStructOutputStruct, network: NetworkNumber): PositionBalances;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import Dec from 'decimal.js';
|
|
2
|
+
import { getAssetInfoByAddress } from '@defisaver/tokens';
|
|
3
|
+
/** Convert raw tokens, or raw 18-decimal shares with a human-readable token/share ratio. */
|
|
4
|
+
export const fluidTokenAmount = (amount, decimals, perShare) => (new Dec(amount.toString()).div(new Dec(10).pow(perShare === undefined ? decimals : 18)).mul(perShare !== null && perShare !== void 0 ? perShare : 1).toString());
|
|
5
|
+
/** The same token/share conversion used by the full Fluid user parsers, without prices or yield. */
|
|
6
|
+
export function parseFluidBalances(position, vault, network) {
|
|
7
|
+
const type = Number(vault.vaultType);
|
|
8
|
+
if (![10000, 20000, 30000, 40000].includes(type))
|
|
9
|
+
throw new Error('Unsupported Fluid vault');
|
|
10
|
+
const side = (amount, tokens, ratios) => {
|
|
11
|
+
const balances = {};
|
|
12
|
+
tokens.forEach((address, i) => {
|
|
13
|
+
const token = getAssetInfoByAddress(address, network);
|
|
14
|
+
if (!Number.isFinite(token.decimals) || !token.symbol)
|
|
15
|
+
throw new Error('Fluid token metadata unavailable');
|
|
16
|
+
const perShare = ratios ? fluidTokenAmount(ratios[i], token.decimals) : undefined;
|
|
17
|
+
const value = fluidTokenAmount(amount, token.decimals, perShare);
|
|
18
|
+
balances[token.symbol] = new Dec(balances[token.symbol] || 0).add(value).toString();
|
|
19
|
+
});
|
|
20
|
+
return balances;
|
|
21
|
+
};
|
|
22
|
+
const smartSupply = type === 20000 || type === 40000;
|
|
23
|
+
const smartDebt = type === 30000 || type === 40000;
|
|
24
|
+
return {
|
|
25
|
+
collateral: side(position.supply, smartSupply ? [vault.supplyToken0, vault.supplyToken1] : [vault.supplyToken0], smartSupply ? [vault.dexSupplyData.token0PerSupplyShare, vault.dexSupplyData.token1PerSupplyShare] : undefined),
|
|
26
|
+
debt: side(position.borrow, smartDebt ? [vault.borrowToken0, vault.borrowToken1] : [vault.borrowToken0], smartDebt ? [vault.dexBorrowData.token0PerBorrowShare, vault.dexBorrowData.token1PerBorrowShare] : undefined),
|
|
27
|
+
};
|
|
28
|
+
}
|
package/esm/liquityV2/index.d.ts
CHANGED
|
@@ -11,6 +11,14 @@ export type SPYieldGainParameters = {
|
|
|
11
11
|
};
|
|
12
12
|
export declare const _getLiquityV2MarketData: (provider: Client, network: NetworkNumber, selectedMarket: LiquityV2MarketInfo) => Promise<LiquityV2MarketData>;
|
|
13
13
|
export declare const getLiquityV2MarketData: (provider: EthereumProvider, network: NetworkNumber, selectedMarket: LiquityV2MarketInfo) => Promise<LiquityV2MarketData>;
|
|
14
|
+
export declare const nftContractCreationBlockMapping: {
|
|
15
|
+
liquityv2eth: number;
|
|
16
|
+
liquityv2wsteth: number;
|
|
17
|
+
liquityv2reth: number;
|
|
18
|
+
liquityv2ethlegacy: number;
|
|
19
|
+
liquityv2wstethlegacy: number;
|
|
20
|
+
liquityv2rethlegacy: number;
|
|
21
|
+
};
|
|
14
22
|
export declare const _getLiquityV2UserTroveIds: (provider: PublicClient, network: NetworkNumber, selectedMarket: LiquityV2MarketInfo, troveNFTAddress: EthAddress, limitBlocksForEventFetching: boolean, account: EthAddress) => Promise<{
|
|
15
23
|
troves: {
|
|
16
24
|
troveId: string;
|
package/esm/liquityV2/index.js
CHANGED
|
@@ -112,7 +112,7 @@ const getUserTroves = (provider_1, network_1, isLegacy_1, account_1, marketAddre
|
|
|
112
112
|
return { troves: existingTroves.filter((trove) => trove.ownedByUser), nextFreeTroveIndex };
|
|
113
113
|
return getUserTroves(provider, network, isLegacy, account, marketAddress, newStartIndex, newStartIndex + 100, existingTroves);
|
|
114
114
|
});
|
|
115
|
-
const nftContractCreationBlockMapping = {
|
|
115
|
+
export const nftContractCreationBlockMapping = {
|
|
116
116
|
[LiquityV2Versions.LiquityV2Eth]: 22516079,
|
|
117
117
|
[LiquityV2Versions.LiquityV2WstEth]: 22516099,
|
|
118
118
|
[LiquityV2Versions.LiquityV2REth]: 22516118,
|
package/esm/llamaLend/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { LlamaLendGlobalMarketData, LlamaLendMarketData, LlamaLendUserData } fro
|
|
|
3
3
|
import { Blockish, EthAddress, EthereumProvider, NetworkNumber, PositionBalances } from '../types/common';
|
|
4
4
|
export declare const _getLlamaLendGlobalData: (provider: Client, network: NetworkNumber, selectedMarket: LlamaLendMarketData) => Promise<LlamaLendGlobalMarketData>;
|
|
5
5
|
export declare const getLlamaLendGlobalData: (provider: EthereumProvider, network: NetworkNumber, selectedMarket: LlamaLendMarketData) => Promise<LlamaLendGlobalMarketData>;
|
|
6
|
-
export declare const _getLlamaLendAccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress) => Promise<PositionBalances>;
|
|
6
|
+
export declare const _getLlamaLendAccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress, includeDeposited?: boolean) => Promise<PositionBalances>;
|
|
7
7
|
export declare const getLlamaLendAccountBalances: (provider: EthereumProvider, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress) => Promise<PositionBalances>;
|
|
8
8
|
export declare const _getLlamaLendUserData: (provider: Client, network: NetworkNumber, address: EthAddress, selectedMarket: LlamaLendMarketData, marketData: LlamaLendGlobalMarketData) => Promise<LlamaLendUserData>;
|
|
9
9
|
export declare const getLlamaLendUserData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, selectedMarket: LlamaLendMarketData, marketData: LlamaLendGlobalMarketData) => Promise<LlamaLendUserData>;
|
package/esm/llamaLend/index.js
CHANGED
|
@@ -153,7 +153,7 @@ const getStatusForUser = (bandRange, activeBand, debtSupplied, collSupplied, hea
|
|
|
153
153
|
return LlamaLendStatus.SoftLiquidated; // or is fully soft liquidated
|
|
154
154
|
return LlamaLendStatus.Nonexistant;
|
|
155
155
|
};
|
|
156
|
-
export const _getLlamaLendAccountBalances = (
|
|
156
|
+
export const _getLlamaLendAccountBalances = (provider_1, network_1, block_1, addressMapping_1, address_1, controllerAddress_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, block_1, addressMapping_1, address_1, controllerAddress_1, ...args_1], void 0, function* (provider, network, block, addressMapping, address, controllerAddress, includeDeposited = false) {
|
|
157
157
|
let balances = {
|
|
158
158
|
collateral: {},
|
|
159
159
|
debt: {},
|
|
@@ -172,6 +172,11 @@ export const _getLlamaLendAccountBalances = (provider, network, block, addressMa
|
|
|
172
172
|
[addressMapping ? getAssetInfo(wethToEth(selectedMarket.baseAsset), network).address.toLowerCase() : wethToEth(selectedMarket.baseAsset)]: data.debtAmount.toString(),
|
|
173
173
|
},
|
|
174
174
|
};
|
|
175
|
+
if (includeDeposited) {
|
|
176
|
+
balances.deposited = {
|
|
177
|
+
[addressMapping ? getAssetInfo(wethToEth(selectedMarket.baseAsset), network).address.toLowerCase() : wethToEth(selectedMarket.baseAsset)]: data.debtTokenCollateralAmount.toString(),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
175
180
|
return balances;
|
|
176
181
|
});
|
|
177
182
|
export const getLlamaLendAccountBalances = (provider, network, block, addressMapping, address, controllerAddress) => __awaiter(void 0, void 0, void 0, function* () { return _getLlamaLendAccountBalances(getViemProvider(provider, network), network, block, addressMapping, address, controllerAddress); });
|
|
@@ -5,7 +5,7 @@ export declare function _getMorphoMidnightMarketData(provider: Client, network:
|
|
|
5
5
|
export declare function getMorphoMidnightMarketData(provider: EthereumProvider, network: NetworkNumber, selectedMarket: MorphoMidnightMarketData): Promise<MorphoMidnightMarketInfo>;
|
|
6
6
|
export declare function _getMorphoMidnightAccountData(provider: Client, network: NetworkNumber, account: EthAddress, selectedMarket: MorphoMidnightMarketData, marketInfo: MorphoMidnightMarketInfo): Promise<MorphoMidnightPositionData>;
|
|
7
7
|
export declare function getMorphoMidnightAccountData(provider: EthereumProvider, network: NetworkNumber, account: EthAddress, selectedMarket: MorphoMidnightMarketData, marketInfo: MorphoMidnightMarketInfo): Promise<MorphoMidnightPositionData>;
|
|
8
|
-
export declare const _getMorphoMidnightAccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, selectedMarket: MorphoMidnightMarketData) => Promise<PositionBalances>;
|
|
8
|
+
export declare const _getMorphoMidnightAccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, selectedMarket: MorphoMidnightMarketData, includeCredit?: boolean) => Promise<PositionBalances>;
|
|
9
9
|
export declare const getMorphoMidnightAccountBalances: (provider: EthereumProvider, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, selectedMarket: MorphoMidnightMarketData) => Promise<PositionBalances>;
|
|
10
10
|
export declare function getMorphoMidnightEarn(provider: Client, network: NetworkNumber, account: EthAddress, selectedMarket: MorphoMidnightMarketData, marketInfo: MorphoMidnightMarketInfo): Promise<{
|
|
11
11
|
apy: string;
|
|
@@ -210,7 +210,7 @@ export function getMorphoMidnightAccountData(provider, network, account, selecte
|
|
|
210
210
|
return _getMorphoMidnightAccountData(getViemProvider(provider, network), network, account, selectedMarket, marketInfo);
|
|
211
211
|
});
|
|
212
212
|
}
|
|
213
|
-
export const _getMorphoMidnightAccountBalances = (
|
|
213
|
+
export const _getMorphoMidnightAccountBalances = (provider_1, network_1, block_1, addressMapping_1, address_1, selectedMarket_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, block_1, addressMapping_1, address_1, selectedMarket_1, ...args_1], void 0, function* (provider, network, block, addressMapping, address, selectedMarket, includeCredit = false) {
|
|
214
214
|
const balances = { collateral: {}, debt: {} };
|
|
215
215
|
if (!address)
|
|
216
216
|
return balances;
|
|
@@ -230,6 +230,11 @@ export const _getMorphoMidnightAccountBalances = (provider, network, block, addr
|
|
|
230
230
|
collateral[addressMapping ? collInfo.address.toLowerCase() : wethToEth(collInfo.symbol)] = assetAmountInEth(rawAmount, wethToEth(collInfo.symbol));
|
|
231
231
|
});
|
|
232
232
|
balances.collateral = collateral;
|
|
233
|
+
if (includeCredit) {
|
|
234
|
+
balances.deposited = {
|
|
235
|
+
[addressMapping ? loanTokenInfo.address.toLowerCase() : wethToEth(loanTokenInfo.symbol)]: assetAmountInEth(positionInfo.credit.toString(), wethToEth(loanTokenInfo.symbol)),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
233
238
|
return balances;
|
|
234
239
|
});
|
|
235
240
|
export const getMorphoMidnightAccountBalances = (provider, network, block, addressMapping, address, selectedMarket) => __awaiter(void 0, void 0, void 0, function* () { return _getMorphoMidnightAccountBalances(getViemProvider(provider, network), network, block, addressMapping, address, selectedMarket); });
|
package/esm/portfolio/index.d.ts
CHANGED
package/esm/portfolio/index.js
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EthAddress, EthereumProvider, NetworkNumber } from '../types/common';
|
|
2
|
+
import { LendingSummaryOptions, WalletLendingSummaries } from '../types/lendingSummary';
|
|
3
|
+
/** Lending-only balances at one snapshot, valued with caller-supplied market prices.
|
|
4
|
+
* One shared client/limiter covers every wallet. Failed reads remain partial; cancellation
|
|
5
|
+
* discards results. Morpho Blue earn deposits, rewards and savings are excluded.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getWalletLendingSummaries(provider: EthereumProvider, network: NetworkNumber, walletAddresses: EthAddress[], options: LendingSummaryOptions): Promise<WalletLendingSummaries>;
|
|
@@ -0,0 +1,256 @@
|
|
|
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
|
+
/* global BigInt */
|
|
11
|
+
import Dec from 'decimal.js';
|
|
12
|
+
import { getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
|
|
13
|
+
import { custom, parseAbi, parseAbiItem, } from 'viem';
|
|
14
|
+
import { AaveMarkets, AaveV4Spokes, CompoundMarkets, compoundV2CollateralAssets, CrvUsdMarkets, LiquityV2Markets, LlamaLendMarkets, MorphoBlueMarkets, MorphoMidnightMarkets, SparkMarkets, } from '../markets';
|
|
15
|
+
import { AaveVersions, CompoundVersions } from '../types';
|
|
16
|
+
import { NetworkNumber, } from '../types/common';
|
|
17
|
+
import { getConfigContractAbi, getConfigContractAddress } from '../contracts';
|
|
18
|
+
import { getViemProvider } from '../services/viem';
|
|
19
|
+
import { getWrappedNativeAssetFromUnwrapped } from '../services/utils';
|
|
20
|
+
import { getAaveLikeBalances } from '../helpers/aaveBalances';
|
|
21
|
+
import { parseFluidBalances } from '../helpers/fluidBalances';
|
|
22
|
+
import { _getAaveV4LoanBalances } from '../aaveV4';
|
|
23
|
+
import { _getCompoundV2AccountBalances } from '../compoundV2';
|
|
24
|
+
import { _getCompoundV3AccountBalances } from '../compoundV3';
|
|
25
|
+
import { _getCrvUsdAccountBalances } from '../curveUsd';
|
|
26
|
+
import { _getLlamaLendAccountBalances } from '../llamaLend';
|
|
27
|
+
import { _getMorphoBlueAccountBalances } from '../morphoBlue';
|
|
28
|
+
import { _getMorphoMidnightAccountBalances } from '../morphoMidnight';
|
|
29
|
+
import { _getLiquityAccountBalances } from '../liquity';
|
|
30
|
+
import { _getUserCdps } from '../maker';
|
|
31
|
+
import { nftContractCreationBlockMapping } from '../liquityV2';
|
|
32
|
+
import { lendingSummaryTransport } from './lendingSummaryTransport';
|
|
33
|
+
const nftAbi = parseAbi([
|
|
34
|
+
'function troveNFT() view returns (address)', 'function balanceOf(address) view returns (uint256)',
|
|
35
|
+
'function ownerOf(uint256) view returns (address)',
|
|
36
|
+
]);
|
|
37
|
+
const transfer = parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)');
|
|
38
|
+
const units = (value, decimals = 18) => new Dec(String(value)).div(new Dec(10).pow(decimals)).toString();
|
|
39
|
+
const positive = (value) => new Dec(String(value)).gt(0);
|
|
40
|
+
const supported = (list, network) => Object.values(list).filter(m => m.chainIds.includes(network));
|
|
41
|
+
/** Lending-only balances at one snapshot, valued with caller-supplied market prices.
|
|
42
|
+
* One shared client/limiter covers every wallet. Failed reads remain partial; cancellation
|
|
43
|
+
* discards results. Morpho Blue earn deposits, rewards and savings are excluded.
|
|
44
|
+
*/
|
|
45
|
+
export function getWalletLendingSummaries(provider, network, walletAddresses, options) {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
var _a, _b, _c, _d, _e;
|
|
48
|
+
const addresses = [...new Set(walletAddresses.map(address => {
|
|
49
|
+
if (!/^0x[0-9a-f]{40}$/i.test(address))
|
|
50
|
+
throw new Error('Invalid wallet address');
|
|
51
|
+
return address.toLowerCase();
|
|
52
|
+
}))];
|
|
53
|
+
const summaries = Object.fromEntries(addresses.map(address => [address, {
|
|
54
|
+
status: 'complete', positions: [], protocols: [], suppliedUsd: '0', valuationComplete: true, errors: [],
|
|
55
|
+
}]));
|
|
56
|
+
if (!addresses.length || ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted))
|
|
57
|
+
return { summaries: {}, rateLimited: false };
|
|
58
|
+
const maxCalldataBytes = options.isSim ? 2000 : 32000;
|
|
59
|
+
const transport = lendingSummaryTransport(provider, options.signal, options.blockNumber, maxCalldataBytes);
|
|
60
|
+
const client = getViemProvider(transport.provider, network, {
|
|
61
|
+
transport: custom(transport.provider, { retryCount: 0 }), batch: { multicall: { batchSize: maxCalldataBytes } },
|
|
62
|
+
});
|
|
63
|
+
let snapshot;
|
|
64
|
+
try {
|
|
65
|
+
snapshot = (_b = options.blockNumber) !== null && _b !== void 0 ? _b : yield client.getBlockNumber();
|
|
66
|
+
transport.pinBlock(snapshot);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if ((_c = options.signal) === null || _c === void 0 ? void 0 : _c.aborted)
|
|
70
|
+
return { summaries: {}, rateLimited: transport.isRateLimited() };
|
|
71
|
+
for (const summary of Object.values(summaries)) {
|
|
72
|
+
summary.status = 'failed';
|
|
73
|
+
summary.errors.push(String(error));
|
|
74
|
+
}
|
|
75
|
+
return { summaries, rateLimited: transport.isRateLimited() };
|
|
76
|
+
}
|
|
77
|
+
const block = Number(snapshot);
|
|
78
|
+
// Dynamic ABI boundary for user-scoped CDP/NFT reads; money markets use their existing readers.
|
|
79
|
+
const read = (name, functionName, args = []) => client.readContract({
|
|
80
|
+
address: getConfigContractAddress(name, network, block), abi: getConfigContractAbi(name, network, block), functionName, args,
|
|
81
|
+
});
|
|
82
|
+
const nftRead = (address, functionName, args = []) => client.readContract({
|
|
83
|
+
address, abi: nftAbi, functionName, args,
|
|
84
|
+
});
|
|
85
|
+
const cache = new Map();
|
|
86
|
+
const shared = (key, fetch) => {
|
|
87
|
+
if (!cache.has(key))
|
|
88
|
+
cache.set(key, fetch());
|
|
89
|
+
return cache.get(key);
|
|
90
|
+
};
|
|
91
|
+
const tasks = [];
|
|
92
|
+
const tokens = new Set();
|
|
93
|
+
const valuations = [];
|
|
94
|
+
let prices = {};
|
|
95
|
+
const run = (address, protocol, key, work) => __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
var _a;
|
|
97
|
+
try {
|
|
98
|
+
if (!((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted))
|
|
99
|
+
yield work();
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
summaries[address].errors.push(`${protocol}:${key}: ${String(error).split('\n')[0]}`);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
const add = (address_1, protocol_1, key_1, balances_1, ...args_1) => __awaiter(this, [address_1, protocol_1, key_1, balances_1, ...args_1], void 0, function* (address, protocol, key, balances, human = false) {
|
|
106
|
+
const supply = Object.entries(balances.collateral || {}).concat(Object.entries(balances.deposited || {}));
|
|
107
|
+
const debt = Object.entries(balances.debt || {});
|
|
108
|
+
if (![...supply, ...debt].some(([, amount]) => positive(amount)))
|
|
109
|
+
return;
|
|
110
|
+
const entry = {
|
|
111
|
+
id: `${protocol}:${key}`,
|
|
112
|
+
protocol,
|
|
113
|
+
suppliedUsd: (supply.some(([, amount]) => positive(amount)) ? null : '0'),
|
|
114
|
+
debtUsd: (debt.some(([, amount]) => positive(amount)) ? null : '0'),
|
|
115
|
+
};
|
|
116
|
+
summaries[address].positions.push(entry);
|
|
117
|
+
const normalize = (amounts) => {
|
|
118
|
+
const result = {};
|
|
119
|
+
amounts.filter(([, amount]) => positive(amount)).forEach(([symbol, amount]) => {
|
|
120
|
+
const token = symbol.startsWith('0x') ? getAssetInfoByAddress(symbol, network) : getAssetInfo(getWrappedNativeAssetFromUnwrapped(symbol), network);
|
|
121
|
+
if (!token.address || !Number.isFinite(token.decimals))
|
|
122
|
+
throw new Error(`Token metadata unavailable: ${symbol}`);
|
|
123
|
+
const id = token.address.toLowerCase();
|
|
124
|
+
tokens.add(id);
|
|
125
|
+
result[id] = (result[id] || new Dec(0)).add(human ? amount : units(amount, token.decimals));
|
|
126
|
+
});
|
|
127
|
+
return result;
|
|
128
|
+
};
|
|
129
|
+
const amounts = [normalize(supply), normalize(debt)];
|
|
130
|
+
valuations.push(() => {
|
|
131
|
+
['suppliedUsd', 'debtUsd'].forEach((field, i) => {
|
|
132
|
+
try {
|
|
133
|
+
entry[field] = Object.entries(amounts[i]).reduce((total, [token, amount]) => {
|
|
134
|
+
const price = new Dec(prices[token] || 0);
|
|
135
|
+
if (!price.isFinite() || !price.gt(0))
|
|
136
|
+
throw new Error(`Price unavailable: ${token}`);
|
|
137
|
+
return total.add(amount.mul(price));
|
|
138
|
+
}, new Dec(0)).toString();
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
summaries[address].errors.push(`${entry.id}: ${String(error)}`);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
const balanceTask = (address, protocol, key, fetch, human = false) => tasks.push(run(address, protocol, key, () => __awaiter(this, void 0, void 0, function* () { return add(address, protocol, key, yield fetch(), human); })));
|
|
147
|
+
for (const address of addresses) {
|
|
148
|
+
const aaveMarkets = supported(AaveMarkets(network), network).filter(m => [AaveVersions.AaveV2, AaveVersions.AaveV3, AaveVersions.AaveV3Lido, AaveVersions.AaveV3Etherfi].includes(m.value));
|
|
149
|
+
for (const market of [...aaveMarkets, ...supported(SparkMarkets(network), network)]) {
|
|
150
|
+
const v2 = market.value === AaveVersions.AaveV2;
|
|
151
|
+
const spark = !aaveMarkets.some(m => m.value === market.value);
|
|
152
|
+
balanceTask(address, spark ? 'spark' : v2 ? 'aaveV2' : 'aaveV3', market.value, () => getAaveLikeBalances(client, network, block, false, address, market, spark ? 'SparkView' : v2 ? 'AaveLoanInfoV2' : 'AaveV3View', market.assets.map(asset => getAssetInfo(getWrappedNativeAssetFromUnwrapped(asset), network).address)));
|
|
153
|
+
}
|
|
154
|
+
for (const spoke of supported(AaveV4Spokes(network), network)) {
|
|
155
|
+
balanceTask(address, 'aaveV4', spoke.value, () => __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
const { reserves } = yield _getAaveV4LoanBalances(client, network, block, address, spoke.address);
|
|
157
|
+
const balances = { collateral: {}, debt: {} };
|
|
158
|
+
reserves.forEach(r => {
|
|
159
|
+
balances.collateral[r.underlying] = new Dec(balances.collateral[r.underlying] || 0).add(r.supplied.toString()).toString();
|
|
160
|
+
balances.debt[r.underlying] = new Dec(balances.debt[r.underlying] || 0).add(r.totalDebt.toString()).toString();
|
|
161
|
+
});
|
|
162
|
+
return balances;
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
for (const market of supported(CompoundMarkets(network), network)) {
|
|
166
|
+
const v2 = market.value === CompoundVersions.CompoundV2;
|
|
167
|
+
balanceTask(address, v2 ? 'compoundV2' : 'compoundV3', market.value, () => (v2
|
|
168
|
+
? _getCompoundV2AccountBalances(client, network, block, false, address, compoundV2CollateralAssets.map(a => a.address))
|
|
169
|
+
: _getCompoundV3AccountBalances(client, network, block, false, address, market.baseMarketAddress)));
|
|
170
|
+
}
|
|
171
|
+
for (const market of supported(MorphoBlueMarkets(network), network))
|
|
172
|
+
balanceTask(address, 'morphoBlue', market.value, () => _getMorphoBlueAccountBalances(client, network, block, false, address, market), true);
|
|
173
|
+
for (const market of supported(MorphoMidnightMarkets(network), network))
|
|
174
|
+
balanceTask(address, 'morphoMidnight', market.value, () => _getMorphoMidnightAccountBalances(client, network, block, false, address, market, true), true);
|
|
175
|
+
if (network === NetworkNumber.Eth)
|
|
176
|
+
for (const market of supported(CrvUsdMarkets(network), network))
|
|
177
|
+
balanceTask(address, 'crvUsd', market.value, () => _getCrvUsdAccountBalances(client, network, block, false, address, market.controllerAddress, true));
|
|
178
|
+
if ([NetworkNumber.Eth, NetworkNumber.Arb].includes(network))
|
|
179
|
+
for (const market of supported(LlamaLendMarkets(network), network))
|
|
180
|
+
balanceTask(address, 'llamaLend', market.value, () => _getLlamaLendAccountBalances(client, network, block, false, address, market.controllerAddress, true));
|
|
181
|
+
if (network === NetworkNumber.Eth) {
|
|
182
|
+
balanceTask(address, 'liquity', 'trove', () => _getLiquityAccountBalances(client, network, block, false, address));
|
|
183
|
+
tasks.push(run(address, 'maker', 'discovery', () => __awaiter(this, void 0, void 0, function* () {
|
|
184
|
+
const cdps = yield _getUserCdps(client, network, address);
|
|
185
|
+
yield Promise.all(cdps.map(cdp => run(address, 'maker', String(cdp.id), () => __awaiter(this, void 0, void 0, function* () {
|
|
186
|
+
const [collateral, debt] = yield read('McdVat', 'urns', [cdp.ilk, cdp.urn]);
|
|
187
|
+
const rate = positive(debt) ? (yield shared(`maker:${cdp.ilk}`, () => read('McdVat', 'ilks', [cdp.ilk])))[1] : 0;
|
|
188
|
+
yield add(address, 'maker', String(cdp.id), { collateral: { [cdp.asset]: units(collateral) }, debt: { DAI: new Dec(units(debt)).mul(units(rate, 27)).toString() } }, true);
|
|
189
|
+
}))));
|
|
190
|
+
})));
|
|
191
|
+
for (const market of supported(LiquityV2Markets(network), network)) {
|
|
192
|
+
tasks.push(run(address, 'liquityV2', market.value, () => __awaiter(this, void 0, void 0, function* () {
|
|
193
|
+
const nft = yield shared(`nft:${market.value}`, () => nftRead(market.marketAddress, 'troveNFT'));
|
|
194
|
+
const count = yield nftRead(nft, 'balanceOf', [address]);
|
|
195
|
+
if (count === BigInt(0))
|
|
196
|
+
return;
|
|
197
|
+
const logs = yield client.getLogs({
|
|
198
|
+
address: nft, event: transfer, args: { to: address }, fromBlock: BigInt(nftContractCreationBlockMapping[market.value]), toBlock: snapshot,
|
|
199
|
+
});
|
|
200
|
+
const owned = (yield Promise.all([...new Set(logs.map(log => log.args.tokenId))].map((id) => __awaiter(this, void 0, void 0, function* () {
|
|
201
|
+
try {
|
|
202
|
+
return (yield nftRead(nft, 'ownerOf', [id])).toLowerCase() === address ? id : null;
|
|
203
|
+
}
|
|
204
|
+
catch (_a) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
})))).filter((id) => id !== null);
|
|
208
|
+
if (BigInt(owned.length) !== count)
|
|
209
|
+
summaries[address].errors.push(`liquityV2:${market.value}: Not all owned troves could be discovered`);
|
|
210
|
+
yield Promise.all(owned.map(id => run(address, 'liquityV2', `${market.value}:${id}`, () => __awaiter(this, void 0, void 0, function* () {
|
|
211
|
+
const data = yield read(market.isLegacy ? 'LiquityV2LegacyView' : 'LiquityV2View', 'getTroveInfo', [market.marketAddress, id]);
|
|
212
|
+
if (data.owner.toLowerCase() !== address)
|
|
213
|
+
throw new Error('Trove ownership changed');
|
|
214
|
+
yield add(address, 'liquityV2', `${market.value}:${id}`, { collateral: { [market.collateralToken]: data.collAmount.toString() }, debt: { [market.debtToken]: data.debtAmount.toString() } });
|
|
215
|
+
}))));
|
|
216
|
+
})));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if ([NetworkNumber.Eth, NetworkNumber.Arb, NetworkNumber.Base, NetworkNumber.Plasma].includes(network)) {
|
|
220
|
+
tasks.push(run(address, 'fluid', 'discovery', () => __awaiter(this, void 0, void 0, function* () {
|
|
221
|
+
const [positions, vaults] = yield read('FluidView', 'getUserPositions', [address]);
|
|
222
|
+
yield Promise.all(positions.map((p, i) => run(address, 'fluid', String(p.nftId), () => __awaiter(this, void 0, void 0, function* () {
|
|
223
|
+
if (positive(p.supply) || positive(p.borrow))
|
|
224
|
+
yield add(address, 'fluid', String(p.nftId), parseFluidBalances(p, vaults[i], network), true);
|
|
225
|
+
}))));
|
|
226
|
+
})));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
yield Promise.all(tasks);
|
|
230
|
+
if ((_d = options.signal) === null || _d === void 0 ? void 0 : _d.aborted)
|
|
231
|
+
return { summaries: {}, rateLimited: transport.isRateLimited() };
|
|
232
|
+
if (tokens.size) {
|
|
233
|
+
try {
|
|
234
|
+
prices = yield options.resolvePrices(network, [...tokens], options.signal);
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
for (const summary of Object.values(summaries))
|
|
238
|
+
if (summary.positions.length)
|
|
239
|
+
summary.errors.push(`Prices: ${String(error)}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if ((_e = options.signal) === null || _e === void 0 ? void 0 : _e.aborted)
|
|
243
|
+
return { summaries: {}, rateLimited: transport.isRateLimited() };
|
|
244
|
+
valuations.forEach(value => value());
|
|
245
|
+
for (const summary of Object.values(summaries)) {
|
|
246
|
+
summary.positions.sort((a, b) => a.id.localeCompare(b.id));
|
|
247
|
+
summary.protocols = [...new Set(summary.positions.map(p => p.protocol))];
|
|
248
|
+
summary.suppliedUsd = summary.positions.reduce((total, p) => total.add(p.suppliedUsd || 0), new Dec(0)).toString();
|
|
249
|
+
summary.valuationComplete = summary.positions.every(p => p.suppliedUsd !== null && p.debtUsd !== null);
|
|
250
|
+
summary.errors = [...new Set(summary.errors)];
|
|
251
|
+
if (summary.errors.length)
|
|
252
|
+
summary.status = 'partial';
|
|
253
|
+
}
|
|
254
|
+
return { summaries, rateLimited: transport.isRateLimited() };
|
|
255
|
+
});
|
|
256
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EthereumProvider } from '../types/common';
|
|
2
|
+
export declare const isLendingSummaryRateLimit: (error: unknown) => boolean;
|
|
3
|
+
/** One limiter for all reads, including split multicalls. No retries after cancellation/429. */
|
|
4
|
+
export declare function lendingSummaryTransport(provider: EthereumProvider, signal?: AbortSignal, blockNumber?: bigint, maxCalldataBytes?: number): {
|
|
5
|
+
provider: EthereumProvider;
|
|
6
|
+
isRateLimited: () => boolean;
|
|
7
|
+
pinBlock: (value: bigint) => void;
|
|
8
|
+
};
|