diff --git a/packages/contract-helpers/src/index.ts b/packages/contract-helpers/src/index.ts index 82be851e..da1c0e46 100644 --- a/packages/contract-helpers/src/index.ts +++ b/packages/contract-helpers/src/index.ts @@ -5,6 +5,7 @@ export { } from './permissions-manager/types/PermissionManagerTypes'; export * from './v3-UiIncentiveDataProvider-contract'; export * from './v3-UiPoolDataProvider-contract'; +export * from './v3-UiPoolDataProvider-legacy-contract'; export * from './wallet-balance-provider'; export * from './cl-feed-registry'; // export * from './uiStakeDataProvider-contract'; diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/_mocks.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/_mocks.ts index 0d650294..4ec8bbe4 100644 --- a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/_mocks.ts +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/_mocks.ts @@ -149,6 +149,11 @@ export const reservesMock: ReservesData = { _hex: '0x0', _isBigNumber: true, }), + virtualAccActive: false, + virtualUnderlyingBalance: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), }, { underlyingAsset: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', @@ -296,6 +301,11 @@ export const reservesMock: ReservesData = { _hex: '0x0', _isBigNumber: true, }), + virtualAccActive: false, + virtualUnderlyingBalance: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), }, ], 1: { diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/index.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/index.ts index 4c97b096..2f670c8d 100644 --- a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/index.ts +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/index.ts @@ -58,6 +58,7 @@ export class UiPoolDataProvider implements UiPoolDataProviderInterface { private readonly _contract: UiPoolDataProviderContract; private readonly chainId: number; + /** * Constructor * @param context The ui pool data provider context @@ -190,6 +191,9 @@ export class UiPoolDataProvider implements UiPoolDataProviderInterface { debtCeilingDecimals: reserveRaw.debtCeilingDecimals.toNumber(), isSiloedBorrowing: reserveRaw.isSiloedBorrowing, flashLoanEnabled: reserveRaw.flashLoanEnabled, + virtualAccActive: reserveRaw.virtualAccActive, + virtualUnderlyingBalance: + reserveRaw.virtualUnderlyingBalance.toString(), }), ); diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3.d.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3.d.ts index 93607603..24a2497b 100644 --- a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3.d.ts +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3.d.ts @@ -157,6 +157,8 @@ export class IUiPoolDataProviderV3 extends BaseContract { string, string, boolean, + boolean?, + BigNumber?, ] & { underlyingAsset: string; name: string; @@ -212,6 +214,8 @@ export class IUiPoolDataProviderV3 extends BaseContract { eModePriceSource: string; eModeLabel: string; borrowableInIsolation: boolean; + virtualAccActive?: boolean; + virtualUnderlyingBalance?: BigNumber; })[], [BigNumber, BigNumber, BigNumber, number] & { marketReferenceCurrencyUnit: BigNumber; @@ -315,6 +319,8 @@ export class IUiPoolDataProviderV3 extends BaseContract { string, string, boolean, + boolean, + BigNumber, ] & { underlyingAsset: string; name: string; @@ -370,6 +376,8 @@ export class IUiPoolDataProviderV3 extends BaseContract { eModePriceSource: string; eModeLabel: string; borrowableInIsolation: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: BigNumber; })[], [BigNumber, BigNumber, BigNumber, number] & { marketReferenceCurrencyUnit: BigNumber; @@ -473,6 +481,8 @@ export class IUiPoolDataProviderV3 extends BaseContract { string, string, boolean, + boolean, + BigNumber, ] & { underlyingAsset: string; name: string; @@ -528,6 +538,8 @@ export class IUiPoolDataProviderV3 extends BaseContract { eModePriceSource: string; eModeLabel: string; borrowableInIsolation: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: BigNumber; })[], [BigNumber, BigNumber, BigNumber, number] & { marketReferenceCurrencyUnit: BigNumber; diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3__factory.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3__factory.ts index e629a32f..8a3b8423 100644 --- a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3__factory.ts +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/typechain/IUiPoolDataProviderV3__factory.ts @@ -291,6 +291,16 @@ const _abi = [ name: 'borrowableInIsolation', type: 'bool', }, + { + internalType: 'bool', + name: 'virtualAccActive', + type: 'bool', + }, + { + internalType: 'uint128', + name: 'virtualUnderlyingBalance', + type: 'uint128', + }, ], internalType: 'struct IUiPoolDataProviderV3.AggregatedReserveData[]', name: '', @@ -412,7 +422,33 @@ const _abi = [ stateMutability: 'view', type: 'function', }, -]; + { + inputs: [], + name: 'marketReferenceCurrencyPriceInUsdProxyAggregator', + outputs: [ + { + internalType: 'contract IEACAggregatorProxy', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'networkBaseTokenPriceInUsdProxyAggregator', + outputs: [ + { + internalType: 'contract IEACAggregatorProxy', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const; export class IUiPoolDataProviderV3__factory { static readonly abi = _abi; diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/types.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/types.ts index 90c377e4..0515eab3 100644 --- a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/types.ts +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/types.ts @@ -56,6 +56,8 @@ export interface ReservesData { eModeLabel: string; borrowableInIsolation: boolean; flashLoanEnabled: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: BigNumber; }>; 1: { marketReferenceCurrencyUnit: BigNumber; @@ -141,6 +143,8 @@ export interface ReserveDataHumanized { eModeLabel: string; borrowableInIsolation: boolean; flashLoanEnabled: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: string; } export interface ReservesDataHumanized { diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/uiPoolDataProvider.test.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/uiPoolDataProvider.test.ts index d957f816..c1828712 100644 --- a/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/uiPoolDataProvider.test.ts +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-contract/uiPoolDataProvider.test.ts @@ -196,6 +196,8 @@ describe('UiPoolDataProvider', () => { debtCeilingDecimals: 0, borrowableInIsolation: false, flashLoanEnabled: false, + virtualAccActive: false, + virtualUnderlyingBalance: '0', }, { id: '137-0xa478c2975ab1ea89e8196811f51a7b7ade33eb11-0x88757f2f99175387ab4c6a4b3067c77a695b0349', @@ -257,6 +259,8 @@ describe('UiPoolDataProvider', () => { debtCeilingDecimals: 0, borrowableInIsolation: false, flashLoanEnabled: false, + virtualAccActive: false, + virtualUnderlyingBalance: '0', }, ], baseCurrencyData: { diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/_mocks.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/_mocks.ts new file mode 100644 index 00000000..bdb43d60 --- /dev/null +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/_mocks.ts @@ -0,0 +1,348 @@ +import { BigNumber } from 'ethers'; +import { UserReserveData } from '../v3-UiPoolDataProvider-contract'; +import { LegacyReservesData } from './types'; + +export const reservesMock: LegacyReservesData = { + 0: [ + { + underlyingAsset: '0x3E0437898a5667a4769B1Ca5A34aAB1ae7E81377', + name: '', + symbol: 'AMPL', + decimals: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + baseLTVasCollateral: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + reserveLiquidationThreshold: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + reserveLiquidationBonus: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + reserveFactor: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + usageAsCollateralEnabled: false, + borrowingEnabled: true, + stableBorrowRateEnabled: false, + isActive: true, + isFrozen: false, + isPaused: false, + isSiloedBorrowing: false, + liquidityIndex: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + variableBorrowIndex: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + liquidityRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + variableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + stableDebtTokenAddress: '0x9157d57DC97A7AFFC7b0a78E78fe25e1401B1dCc', + variableDebtTokenAddress: '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + totalPrincipalStableDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + averageStableRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableDebtLastUpdateTimestamp: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + totalScaledVariableDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + priceInMarketReferenceCurrency: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + priceOracle: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + variableRateSlope1: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + variableRateSlope2: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableRateSlope1: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableRateSlope2: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + baseStableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + baseVariableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + optimalUsageRatio: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + // new + debtCeiling: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + eModeCategoryId: 1, + borrowCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + supplyCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + eModeLtv: 1, + eModeLiquidationThreshold: 1, + eModeLiquidationBonus: 1, + eModePriceSource: '0x3E0437898a5667a4769B1Ca5A34aAB1ae7E81377', + eModeLabel: 'test label', + borrowableInIsolation: false, + flashLoanEnabled: false, + accruedToTreasury: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + unbacked: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + isolationModeTotalDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + debtCeilingDecimals: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + }, + { + underlyingAsset: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11', + name: '', + symbol: 'UNI-V2', + decimals: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + baseLTVasCollateral: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + reserveLiquidationThreshold: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + reserveLiquidationBonus: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + reserveFactor: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + usageAsCollateralEnabled: false, + borrowingEnabled: true, + stableBorrowRateEnabled: false, + isActive: true, + isFrozen: false, + isPaused: false, + isSiloedBorrowing: false, + liquidityIndex: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + variableBorrowIndex: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + liquidityRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + variableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + stableDebtTokenAddress: '0x9157d57DC97A7AFFC7b0a78E78fe25e1401B1dCc', + variableDebtTokenAddress: '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + totalPrincipalStableDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + averageStableRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableDebtLastUpdateTimestamp: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + totalScaledVariableDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + priceInMarketReferenceCurrency: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + priceOracle: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + variableRateSlope1: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + variableRateSlope2: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableRateSlope1: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableRateSlope2: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + baseStableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + baseVariableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + optimalUsageRatio: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + // new + debtCeiling: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + eModeCategoryId: 1, + borrowCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + supplyCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + eModeLtv: 1, + eModeLiquidationThreshold: 1, + eModeLiquidationBonus: 1, + eModePriceSource: '0x3E0437898a5667a4769B1Ca5A34aAB1ae7E81377', + eModeLabel: 'test label', + borrowableInIsolation: false, + flashLoanEnabled: false, + accruedToTreasury: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + unbacked: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + isolationModeTotalDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + debtCeilingDecimals: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + }, + ], + 1: { + marketReferenceCurrencyUnit: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + marketReferenceCurrencyPriceInUsd: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + + networkBaseTokenPriceInUsd: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + networkBaseTokenPriceDecimals: 0, + }, +}; + +export const userReservesMock: UserReserveData = { + 0: [ + { + underlyingAsset: '0xB597cd8D3217ea6477232F9217fa70837ff667Af', + scaledATokenBalance: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + usageAsCollateralEnabledOnUser: false, + stableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + scaledVariableDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + principalStableDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + stableBorrowLastUpdateTimestamp: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + }, + ], + 1: 1, +}; diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/index.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/index.ts new file mode 100644 index 00000000..21a605a3 --- /dev/null +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/index.ts @@ -0,0 +1,242 @@ +import { isAddress } from 'ethers/lib/utils'; +import { ReservesHelperInput, UserReservesHelperInput } from '../index'; +import { + PoolBaseCurrencyHumanized, + ReserveDataHumanized, + ReservesDataHumanized, + UiPoolDataProviderContext, + UserReserveData, + UserReserveDataHumanized, +} from '../v3-UiPoolDataProvider-contract'; +import { IUiPoolDataProviderV3 as UiPoolDataProviderContract } from './typechain/IUiPoolDataProviderV3'; +import { IUiPoolDataProviderV3__factory } from './typechain/IUiPoolDataProviderV3__factory'; +import { LegacyReservesData } from './types'; + +export * from './types'; + +const ammSymbolMap: Record = { + '0xae461ca67b15dc8dc81ce7615e0320da1a9ab8d5': 'UNIDAIUSDC', + '0x004375dff511095cc5a197a54140a24efef3a416': 'UNIWBTCUSDC', + '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11': 'UNIDAIWETH', + '0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc': 'UNIUSDCWETH', + '0xdfc14d2af169b0d36c4eff567ada9b2e0cae044f': 'UNIAAVEWETH', + '0xb6909b960dbbe7392d405429eb2b3649752b4838': 'UNIBATWETH', + '0x3da1313ae46132a397d90d95b1424a9a7e3e0fce': 'UNICRVWETH', + '0xa2107fa5b38d9bbd2c461d6edf11b11a50f6b974': 'UNILINKWETH', + '0xc2adda861f89bbb333c90c492cb837741916a225': 'UNIMKRWETH', + '0x8bd1661da98ebdd3bd080f0be4e6d9be8ce9858c': 'UNIRENWETH', + '0x43ae24960e5534731fc831386c07755a2dc33d47': 'UNISNXWETH', + '0xd3d2e2692501a5c9ca623199d38826e513033a17': 'UNIUNIWETH', + '0xbb2b8038a1640196fbe3e38816f3e67cba72d940': 'UNIWBTCWETH', + '0x2fdbadf3c4d5a8666bc06645b8358ab803996e28': 'UNIYFIWETH', + '0x1eff8af5d577060ba4ac8a29a13525bb0ee2a3d5': 'BPTWBTCWETH', + '0x59a19d8c652fa0284f44113d0ff9aba70bd46fb4': 'BPTBALWETH', +}; + +export interface LegacyUiPoolDataProviderInterface { + getReservesList: (args: ReservesHelperInput) => Promise; + getReservesData: (args: ReservesHelperInput) => Promise; + getUserReservesData: ( + args: UserReservesHelperInput, + ) => Promise; + getReservesHumanized: ( + args: ReservesHelperInput, + ) => Promise; + getUserReservesHumanized: (args: UserReservesHelperInput) => Promise<{ + userReserves: UserReserveDataHumanized[]; + userEmodeCategoryId: number; + }>; +} + +/** + * This class is only intended to be used with v2 markets + * or v3 markets that do not have the v3.1 upgrade applied + */ +export class LegacyUiPoolDataProvider + implements LegacyUiPoolDataProviderInterface +{ + private readonly _contract: UiPoolDataProviderContract; + + private readonly chainId: number; + /** + * Constructor + * @param context The ui pool data provider context + */ + public constructor(context: UiPoolDataProviderContext) { + if (!isAddress(context.uiPoolDataProviderAddress)) { + throw new Error('contract address is not valid'); + } + + this._contract = IUiPoolDataProviderV3__factory.connect( + context.uiPoolDataProviderAddress, + context.provider, + ); + this.chainId = context.chainId; + } + + /** + * Get the underlying asset address for each lending pool reserve + */ + public async getReservesList({ + lendingPoolAddressProvider, + }: ReservesHelperInput): Promise { + if (!isAddress(lendingPoolAddressProvider)) { + throw new Error('Lending pool address is not valid'); + } + + return this._contract.getReservesList(lendingPoolAddressProvider); + } + + /** + * Get data for each lending pool reserve + */ + public async getReservesData({ + lendingPoolAddressProvider, + }: ReservesHelperInput): Promise { + if (!isAddress(lendingPoolAddressProvider)) { + throw new Error('Lending pool address is not valid'); + } + + return this._contract.getReservesData(lendingPoolAddressProvider); + } + + /** + * Get data for each user reserve on the lending pool + */ + public async getUserReservesData({ + lendingPoolAddressProvider, + user, + }: UserReservesHelperInput): Promise { + if (!isAddress(lendingPoolAddressProvider)) { + throw new Error('Lending pool address is not valid'); + } + + if (!isAddress(user)) { + throw new Error('User address is not a valid ethereum address'); + } + + return this._contract.getUserReservesData(lendingPoolAddressProvider, user); + } + + public async getReservesHumanized({ + lendingPoolAddressProvider, + }: ReservesHelperInput): Promise { + const { 0: reservesRaw, 1: poolBaseCurrencyRaw }: LegacyReservesData = + await this.getReservesData({ lendingPoolAddressProvider }); + + const reservesData: ReserveDataHumanized[] = reservesRaw.map( + reserveRaw => ({ + id: `${this.chainId}-${reserveRaw.underlyingAsset}-${lendingPoolAddressProvider}`.toLowerCase(), + underlyingAsset: reserveRaw.underlyingAsset.toLowerCase(), + name: reserveRaw.name, + symbol: ammSymbolMap[reserveRaw.underlyingAsset.toLowerCase()] + ? ammSymbolMap[reserveRaw.underlyingAsset.toLowerCase()] + : reserveRaw.symbol, + decimals: reserveRaw.decimals.toNumber(), + baseLTVasCollateral: reserveRaw.baseLTVasCollateral.toString(), + reserveLiquidationThreshold: + reserveRaw.reserveLiquidationThreshold.toString(), + reserveLiquidationBonus: reserveRaw.reserveLiquidationBonus.toString(), + reserveFactor: reserveRaw.reserveFactor.toString(), + usageAsCollateralEnabled: reserveRaw.usageAsCollateralEnabled, + borrowingEnabled: reserveRaw.borrowingEnabled, + stableBorrowRateEnabled: reserveRaw.stableBorrowRateEnabled, + isActive: reserveRaw.isActive, + isFrozen: reserveRaw.isFrozen, + liquidityIndex: reserveRaw.liquidityIndex.toString(), + variableBorrowIndex: reserveRaw.variableBorrowIndex.toString(), + liquidityRate: reserveRaw.liquidityRate.toString(), + variableBorrowRate: reserveRaw.variableBorrowRate.toString(), + stableBorrowRate: reserveRaw.stableBorrowRate.toString(), + lastUpdateTimestamp: reserveRaw.lastUpdateTimestamp, + aTokenAddress: reserveRaw.aTokenAddress.toString(), + stableDebtTokenAddress: reserveRaw.stableDebtTokenAddress.toString(), + variableDebtTokenAddress: + reserveRaw.variableDebtTokenAddress.toString(), + interestRateStrategyAddress: + reserveRaw.interestRateStrategyAddress.toString(), + availableLiquidity: reserveRaw.availableLiquidity.toString(), + totalPrincipalStableDebt: + reserveRaw.totalPrincipalStableDebt.toString(), + averageStableRate: reserveRaw.averageStableRate.toString(), + stableDebtLastUpdateTimestamp: + reserveRaw.stableDebtLastUpdateTimestamp.toNumber(), + totalScaledVariableDebt: reserveRaw.totalScaledVariableDebt.toString(), + priceInMarketReferenceCurrency: + reserveRaw.priceInMarketReferenceCurrency.toString(), + priceOracle: reserveRaw.priceOracle, + variableRateSlope1: reserveRaw.variableRateSlope1.toString(), + variableRateSlope2: reserveRaw.variableRateSlope2.toString(), + stableRateSlope1: reserveRaw.stableRateSlope1.toString(), + stableRateSlope2: reserveRaw.stableRateSlope2.toString(), + baseStableBorrowRate: reserveRaw.baseStableBorrowRate.toString(), + baseVariableBorrowRate: reserveRaw.baseVariableBorrowRate.toString(), + optimalUsageRatio: reserveRaw.optimalUsageRatio.toString(), + // new fields + isPaused: reserveRaw.isPaused, + debtCeiling: reserveRaw.debtCeiling.toString(), + eModeCategoryId: reserveRaw.eModeCategoryId, + borrowCap: reserveRaw.borrowCap.toString(), + supplyCap: reserveRaw.supplyCap.toString(), + eModeLtv: reserveRaw.eModeLtv, + eModeLiquidationThreshold: reserveRaw.eModeLiquidationThreshold, + eModeLiquidationBonus: reserveRaw.eModeLiquidationBonus, + eModePriceSource: reserveRaw.eModePriceSource.toString(), + eModeLabel: reserveRaw.eModeLabel.toString(), + borrowableInIsolation: reserveRaw.borrowableInIsolation, + accruedToTreasury: reserveRaw.accruedToTreasury.toString(), + unbacked: reserveRaw.unbacked.toString(), + isolationModeTotalDebt: reserveRaw.isolationModeTotalDebt.toString(), + debtCeilingDecimals: reserveRaw.debtCeilingDecimals.toNumber(), + isSiloedBorrowing: reserveRaw.isSiloedBorrowing, + flashLoanEnabled: reserveRaw.flashLoanEnabled, + virtualAccActive: false, + virtualUnderlyingBalance: '0', + }), + ); + + const baseCurrencyData: PoolBaseCurrencyHumanized = { + // this is to get the decimals from the unit so 1e18 = string length of 19 - 1 to get the number of 0 + marketReferenceCurrencyDecimals: + poolBaseCurrencyRaw.marketReferenceCurrencyUnit.toString().length - 1, + marketReferenceCurrencyPriceInUsd: + poolBaseCurrencyRaw.marketReferenceCurrencyPriceInUsd.toString(), + networkBaseTokenPriceInUsd: + poolBaseCurrencyRaw.networkBaseTokenPriceInUsd.toString(), + networkBaseTokenPriceDecimals: + poolBaseCurrencyRaw.networkBaseTokenPriceDecimals, + }; + + return { + reservesData, + baseCurrencyData, + }; + } + + public async getUserReservesHumanized({ + lendingPoolAddressProvider, + user, + }: UserReservesHelperInput): Promise<{ + userReserves: UserReserveDataHumanized[]; + userEmodeCategoryId: number; + }> { + const { 0: userReservesRaw, 1: userEmodeCategoryId }: UserReserveData = + await this.getUserReservesData({ lendingPoolAddressProvider, user }); + + return { + userReserves: userReservesRaw.map(userReserveRaw => ({ + id: `${this.chainId}-${user}-${userReserveRaw.underlyingAsset}-${lendingPoolAddressProvider}`.toLowerCase(), + underlyingAsset: userReserveRaw.underlyingAsset.toLowerCase(), + scaledATokenBalance: userReserveRaw.scaledATokenBalance.toString(), + usageAsCollateralEnabledOnUser: + userReserveRaw.usageAsCollateralEnabledOnUser, + stableBorrowRate: userReserveRaw.stableBorrowRate.toString(), + scaledVariableDebt: userReserveRaw.scaledVariableDebt.toString(), + principalStableDebt: userReserveRaw.principalStableDebt.toString(), + stableBorrowLastUpdateTimestamp: + userReserveRaw.stableBorrowLastUpdateTimestamp.toNumber(), + })), + userEmodeCategoryId, + }; + } +} diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/legacyUiPoolDataProvider.test.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/legacyUiPoolDataProvider.test.ts new file mode 100644 index 00000000..40acd5e7 --- /dev/null +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/legacyUiPoolDataProvider.test.ts @@ -0,0 +1,318 @@ +import { providers } from 'ethers'; +import { reservesMock, userReservesMock } from './_mocks'; +import { LegacyUiPoolDataProvider } from './index'; + +describe('UiPoolDataProvider', () => { + const mockValidEthereumAddress = '0x88757f2f99175387ab4c6a4b3067c77a695b0349'; + const mockInvalidEthereumAddress = '0x0'; + + const createValidInstance = () => { + const instance = new LegacyUiPoolDataProvider({ + uiPoolDataProviderAddress: mockValidEthereumAddress, + provider: new providers.JsonRpcProvider(), + chainId: 137, + }); + + const mockGetReservesData = jest.fn(); + const mockGetUserReservesData = jest.fn(); + + mockGetReservesData.mockResolvedValue(reservesMock); + mockGetUserReservesData.mockResolvedValue(userReservesMock); + + // @ts-expect-error readonly + instance._contract = { + getReservesList: jest.fn(), + getReservesData: mockGetReservesData, + getUserReservesData: mockGetUserReservesData, + }; + + return instance; + }; + + describe('creating', () => { + it('should throw an error if the contractAddress is not valid', () => { + expect( + () => + new LegacyUiPoolDataProvider({ + uiPoolDataProviderAddress: mockInvalidEthereumAddress, + provider: new providers.JsonRpcProvider(), + chainId: 137, + }), + ).toThrowError('contract address is not valid'); + }); + it('should work if all info is correct', () => { + const instance = new LegacyUiPoolDataProvider({ + uiPoolDataProviderAddress: mockValidEthereumAddress, + provider: new providers.JsonRpcProvider(), + chainId: 137, + }); + + expect(instance instanceof LegacyUiPoolDataProvider).toEqual(true); + }); + }); + + describe('getReservesList - to get 100% in coverage :( pointless test', () => { + it('should not throw', async () => { + const instance = createValidInstance(); + await expect( + instance.getReservesList({ + lendingPoolAddressProvider: mockValidEthereumAddress, + }), + ).resolves.not.toThrow(); + }); + it('should throw when lendingPoolAddressProvider is not valid address', async () => { + const instance = createValidInstance(); + await expect( + instance.getReservesList({ + lendingPoolAddressProvider: mockInvalidEthereumAddress, + }), + ).rejects.toThrow('Lending pool address is not valid'); + }); + }); + + describe('getReservesData', () => { + it('should throw when lendingPoolAddressProvider is not valid address', async () => { + const instance = createValidInstance(); + await expect( + instance.getReservesData({ + lendingPoolAddressProvider: mockInvalidEthereumAddress, + }), + ).rejects.toThrow('Lending pool address is not valid'); + }); + it('should not throw', async () => { + const instance = createValidInstance(); + await expect( + instance.getReservesData({ + lendingPoolAddressProvider: mockValidEthereumAddress, + }), + ).resolves.not.toThrow(); + }); + }); + + describe('getUserReservesData', () => { + it('should throw when lendingPoolAddressProvider is not valid address', async () => { + const instance = createValidInstance(); + await expect( + instance.getUserReservesData({ + lendingPoolAddressProvider: mockInvalidEthereumAddress, + user: mockValidEthereumAddress, + }), + ).rejects.toThrow('Lending pool address is not valid'); + }); + it('should throw if user is not a valid ethereum address', async () => { + const instance = createValidInstance(); + await expect( + instance.getUserReservesData({ + lendingPoolAddressProvider: mockValidEthereumAddress, + user: mockInvalidEthereumAddress, + }), + ).rejects.toThrow('User address is not a valid ethereum address'); + }); + + it('should not throw if user is a valid ethereum address', async () => { + const instance = createValidInstance(); + await expect( + instance.getUserReservesData({ + lendingPoolAddressProvider: mockValidEthereumAddress, + user: mockValidEthereumAddress, + }), + ).resolves.not.toThrow(); + }); + }); + + describe('getReservesHumanized', () => { + it('should throw if lendingPoolAddressProvider is not a valid ethereum address', async () => { + const instance = createValidInstance(); + await expect( + instance.getReservesHumanized({ + lendingPoolAddressProvider: mockInvalidEthereumAddress, + }), + ).rejects.toThrow('Lending pool address is not valid'); + }); + it('should not throw', async () => { + const instance = createValidInstance(); + const result = await instance.getReservesHumanized({ + lendingPoolAddressProvider: mockValidEthereumAddress, + }); + expect(result).toEqual({ + reservesData: [ + { + id: '137-0x3e0437898a5667a4769b1ca5a34aab1ae7e81377-0x88757f2f99175387ab4c6a4b3067c77a695b0349', + underlyingAsset: '0x3e0437898a5667a4769b1ca5a34aab1ae7e81377', + name: '', + symbol: 'AMPL', + decimals: 0, + baseLTVasCollateral: '0', + reserveLiquidationThreshold: '0', + reserveLiquidationBonus: '0', + reserveFactor: '0', + usageAsCollateralEnabled: false, + borrowingEnabled: true, + stableBorrowRateEnabled: false, + isActive: true, + isFrozen: false, + isPaused: false, + isSiloedBorrowing: false, + liquidityIndex: '0', + variableBorrowIndex: '0', + liquidityRate: '0', + variableBorrowRate: '0', + stableBorrowRate: '0', + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + stableDebtTokenAddress: + '0x9157d57DC97A7AFFC7b0a78E78fe25e1401B1dCc', + variableDebtTokenAddress: + '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: + '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: '0', + totalPrincipalStableDebt: '0', + averageStableRate: '0', + stableDebtLastUpdateTimestamp: 0, + totalScaledVariableDebt: '0', + priceInMarketReferenceCurrency: '0', + priceOracle: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseStableBorrowRate: '0', + baseVariableBorrowRate: '0', + optimalUsageRatio: '0', + // new + debtCeiling: '0', + eModeCategoryId: 1, + borrowCap: '0', + supplyCap: '0', + eModeLtv: 1, + eModeLiquidationThreshold: 1, + eModeLiquidationBonus: 1, + eModePriceSource: '0x3E0437898a5667a4769B1Ca5A34aAB1ae7E81377', + eModeLabel: 'test label', + accruedToTreasury: '0', + unbacked: '0', + isolationModeTotalDebt: '0', + debtCeilingDecimals: 0, + borrowableInIsolation: false, + flashLoanEnabled: false, + virtualAccActive: false, + virtualUnderlyingBalance: '0', + }, + { + id: '137-0xa478c2975ab1ea89e8196811f51a7b7ade33eb11-0x88757f2f99175387ab4c6a4b3067c77a695b0349', + underlyingAsset: '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11', + name: '', + symbol: 'UNIDAIWETH', + decimals: 0, + baseLTVasCollateral: '0', + reserveLiquidationThreshold: '0', + reserveLiquidationBonus: '0', + reserveFactor: '0', + usageAsCollateralEnabled: false, + borrowingEnabled: true, + stableBorrowRateEnabled: false, + isActive: true, + isFrozen: false, + isPaused: false, + isSiloedBorrowing: false, + liquidityIndex: '0', + variableBorrowIndex: '0', + liquidityRate: '0', + variableBorrowRate: '0', + stableBorrowRate: '0', + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + stableDebtTokenAddress: + '0x9157d57DC97A7AFFC7b0a78E78fe25e1401B1dCc', + variableDebtTokenAddress: + '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: + '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: '0', + totalPrincipalStableDebt: '0', + averageStableRate: '0', + stableDebtLastUpdateTimestamp: 0, + totalScaledVariableDebt: '0', + priceInMarketReferenceCurrency: '0', + priceOracle: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', + baseStableBorrowRate: '0', + baseVariableBorrowRate: '0', + optimalUsageRatio: '0', + // new + debtCeiling: '0', + eModeCategoryId: 1, + borrowCap: '0', + supplyCap: '0', + eModeLtv: 1, + eModeLiquidationThreshold: 1, + eModeLiquidationBonus: 1, + eModePriceSource: '0x3E0437898a5667a4769B1Ca5A34aAB1ae7E81377', + eModeLabel: 'test label', + accruedToTreasury: '0', + unbacked: '0', + isolationModeTotalDebt: '0', + debtCeilingDecimals: 0, + borrowableInIsolation: false, + flashLoanEnabled: false, + virtualAccActive: false, + virtualUnderlyingBalance: '0', + }, + ], + baseCurrencyData: { + marketReferenceCurrencyDecimals: 0, + marketReferenceCurrencyPriceInUsd: '0', + networkBaseTokenPriceInUsd: '0', + networkBaseTokenPriceDecimals: 0, + }, + }); + }); + }); + describe('getUserReservesHumanized', () => { + it('should throw if lendingPoolAddressProvider is not a valid ethereum address', async () => { + const instance = createValidInstance(); + await expect( + instance.getUserReservesHumanized({ + lendingPoolAddressProvider: mockInvalidEthereumAddress, + user: mockValidEthereumAddress, + }), + ).rejects.toThrow('Lending pool address is not valid'); + }); + it('should throw if user is not a valid ethereum address', async () => { + const instance = createValidInstance(); + await expect( + instance.getUserReservesHumanized({ + lendingPoolAddressProvider: mockValidEthereumAddress, + user: mockInvalidEthereumAddress, + }), + ).rejects.toThrow('User address is not a valid ethereum address'); + }); + it('should be ok', async () => { + const instance = createValidInstance(); + const result = await instance.getUserReservesHumanized({ + lendingPoolAddressProvider: mockValidEthereumAddress, + user: mockValidEthereumAddress, + }); + + expect(result).toEqual({ + userReserves: [ + { + id: '137-0x88757f2f99175387ab4c6a4b3067c77a695b0349-0xb597cd8d3217ea6477232f9217fa70837ff667af-0x88757f2f99175387ab4c6a4b3067c77a695b0349', + principalStableDebt: '0', + scaledATokenBalance: '0', + scaledVariableDebt: '0', + stableBorrowLastUpdateTimestamp: 0, + stableBorrowRate: '0', + underlyingAsset: '0xb597cd8d3217ea6477232f9217fa70837ff667af', + usageAsCollateralEnabledOnUser: false, + }, + ], + userEmodeCategoryId: 1, + }); + }); + }); +}); diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/typechain/IUiPoolDataProviderV3.d.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/typechain/IUiPoolDataProviderV3.d.ts new file mode 100644 index 00000000..93607603 --- /dev/null +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/typechain/IUiPoolDataProviderV3.d.ts @@ -0,0 +1,611 @@ +/* Autogenerated file. Do not edit manually. */ +/* eslint-disable */ + +import { + ethers, + EventFilter, + Signer, + BigNumber, + BigNumberish, + PopulatedTransaction, + BaseContract, + ContractTransaction, + CallOverrides, +} from 'ethers'; +import { BytesLike } from '@ethersproject/bytes'; +import { Listener, Provider } from '@ethersproject/providers'; +import { FunctionFragment, EventFragment, Result } from '@ethersproject/abi'; +import type { TypedEventFilter, TypedEvent, TypedListener } from './common'; + +interface IUiPoolDataProviderV3Interface extends ethers.utils.Interface { + functions: { + 'getReservesData(address)': FunctionFragment; + 'getReservesList(address)': FunctionFragment; + 'getUserReservesData(address,address)': FunctionFragment; + }; + + encodeFunctionData( + functionFragment: 'getReservesData', + values: [string], + ): string; + encodeFunctionData( + functionFragment: 'getReservesList', + values: [string], + ): string; + encodeFunctionData( + functionFragment: 'getUserReservesData', + values: [string, string], + ): string; + + decodeFunctionResult( + functionFragment: 'getReservesData', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'getReservesList', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'getUserReservesData', + data: BytesLike, + ): Result; + + events: {}; +} + +export class IUiPoolDataProviderV3 extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + listeners, EventArgsObject>( + eventFilter?: TypedEventFilter, + ): Array>; + off, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener, + ): this; + on, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener, + ): this; + once, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener, + ): this; + removeListener, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener, + ): this; + removeAllListeners, EventArgsObject>( + eventFilter: TypedEventFilter, + ): this; + + listeners(eventName?: string): Array; + off(eventName: string, listener: Listener): this; + on(eventName: string, listener: Listener): this; + once(eventName: string, listener: Listener): this; + removeListener(eventName: string, listener: Listener): this; + removeAllListeners(eventName?: string): this; + + queryFilter, EventArgsObject>( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>>; + + interface: IUiPoolDataProviderV3Interface; + + functions: { + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise< + [ + ([ + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + boolean, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + number, + string, + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + boolean, + BigNumber, + BigNumber, + number, + BigNumber, + BigNumber, + number, + number, + number, + string, + string, + boolean, + ] & { + underlyingAsset: string; + name: string; + symbol: string; + decimals: BigNumber; + baseLTVasCollateral: BigNumber; + reserveLiquidationThreshold: BigNumber; + reserveLiquidationBonus: BigNumber; + reserveFactor: BigNumber; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + stableBorrowRateEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + liquidityRate: BigNumber; + variableBorrowRate: BigNumber; + stableBorrowRate: BigNumber; + lastUpdateTimestamp: number; + aTokenAddress: string; + stableDebtTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: BigNumber; + totalPrincipalStableDebt: BigNumber; + averageStableRate: BigNumber; + stableDebtLastUpdateTimestamp: BigNumber; + totalScaledVariableDebt: BigNumber; + priceInMarketReferenceCurrency: BigNumber; + priceOracle: string; + variableRateSlope1: BigNumber; + variableRateSlope2: BigNumber; + stableRateSlope1: BigNumber; + stableRateSlope2: BigNumber; + baseStableBorrowRate: BigNumber; + baseVariableBorrowRate: BigNumber; + optimalUsageRatio: BigNumber; + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: BigNumber; + unbacked: BigNumber; + isolationModeTotalDebt: BigNumber; + flashLoanEnabled: boolean; + debtCeiling: BigNumber; + debtCeilingDecimals: BigNumber; + eModeCategoryId: number; + borrowCap: BigNumber; + supplyCap: BigNumber; + eModeLtv: number; + eModeLiquidationThreshold: number; + eModeLiquidationBonus: number; + eModePriceSource: string; + eModeLabel: string; + borrowableInIsolation: boolean; + })[], + [BigNumber, BigNumber, BigNumber, number] & { + marketReferenceCurrencyUnit: BigNumber; + marketReferenceCurrencyPriceInUsd: BigNumber; + networkBaseTokenPriceInUsd: BigNumber; + networkBaseTokenPriceDecimals: number; + }, + ] + >; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise<[string[]]>; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise< + [ + ([ + string, + BigNumber, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + ] & { + underlyingAsset: string; + scaledATokenBalance: BigNumber; + usageAsCollateralEnabledOnUser: boolean; + stableBorrowRate: BigNumber; + scaledVariableDebt: BigNumber; + principalStableDebt: BigNumber; + stableBorrowLastUpdateTimestamp: BigNumber; + })[], + number, + ] + >; + }; + + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise< + [ + ([ + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + boolean, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + number, + string, + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + boolean, + BigNumber, + BigNumber, + number, + BigNumber, + BigNumber, + number, + number, + number, + string, + string, + boolean, + ] & { + underlyingAsset: string; + name: string; + symbol: string; + decimals: BigNumber; + baseLTVasCollateral: BigNumber; + reserveLiquidationThreshold: BigNumber; + reserveLiquidationBonus: BigNumber; + reserveFactor: BigNumber; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + stableBorrowRateEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + liquidityRate: BigNumber; + variableBorrowRate: BigNumber; + stableBorrowRate: BigNumber; + lastUpdateTimestamp: number; + aTokenAddress: string; + stableDebtTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: BigNumber; + totalPrincipalStableDebt: BigNumber; + averageStableRate: BigNumber; + stableDebtLastUpdateTimestamp: BigNumber; + totalScaledVariableDebt: BigNumber; + priceInMarketReferenceCurrency: BigNumber; + priceOracle: string; + variableRateSlope1: BigNumber; + variableRateSlope2: BigNumber; + stableRateSlope1: BigNumber; + stableRateSlope2: BigNumber; + baseStableBorrowRate: BigNumber; + baseVariableBorrowRate: BigNumber; + optimalUsageRatio: BigNumber; + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: BigNumber; + unbacked: BigNumber; + isolationModeTotalDebt: BigNumber; + flashLoanEnabled: boolean; + debtCeiling: BigNumber; + debtCeilingDecimals: BigNumber; + eModeCategoryId: number; + borrowCap: BigNumber; + supplyCap: BigNumber; + eModeLtv: number; + eModeLiquidationThreshold: number; + eModeLiquidationBonus: number; + eModePriceSource: string; + eModeLabel: string; + borrowableInIsolation: boolean; + })[], + [BigNumber, BigNumber, BigNumber, number] & { + marketReferenceCurrencyUnit: BigNumber; + marketReferenceCurrencyPriceInUsd: BigNumber; + networkBaseTokenPriceInUsd: BigNumber; + networkBaseTokenPriceDecimals: number; + }, + ] + >; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise< + [ + ([ + string, + BigNumber, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + ] & { + underlyingAsset: string; + scaledATokenBalance: BigNumber; + usageAsCollateralEnabledOnUser: boolean; + stableBorrowRate: BigNumber; + scaledVariableDebt: BigNumber; + principalStableDebt: BigNumber; + stableBorrowLastUpdateTimestamp: BigNumber; + })[], + number, + ] + >; + + callStatic: { + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise< + [ + ([ + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + boolean, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + number, + string, + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + boolean, + BigNumber, + BigNumber, + number, + BigNumber, + BigNumber, + number, + number, + number, + string, + string, + boolean, + ] & { + underlyingAsset: string; + name: string; + symbol: string; + decimals: BigNumber; + baseLTVasCollateral: BigNumber; + reserveLiquidationThreshold: BigNumber; + reserveLiquidationBonus: BigNumber; + reserveFactor: BigNumber; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + stableBorrowRateEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + liquidityRate: BigNumber; + variableBorrowRate: BigNumber; + stableBorrowRate: BigNumber; + lastUpdateTimestamp: number; + aTokenAddress: string; + stableDebtTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: BigNumber; + totalPrincipalStableDebt: BigNumber; + averageStableRate: BigNumber; + stableDebtLastUpdateTimestamp: BigNumber; + totalScaledVariableDebt: BigNumber; + priceInMarketReferenceCurrency: BigNumber; + priceOracle: string; + variableRateSlope1: BigNumber; + variableRateSlope2: BigNumber; + stableRateSlope1: BigNumber; + stableRateSlope2: BigNumber; + baseStableBorrowRate: BigNumber; + baseVariableBorrowRate: BigNumber; + optimalUsageRatio: BigNumber; + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: BigNumber; + unbacked: BigNumber; + isolationModeTotalDebt: BigNumber; + flashLoanEnabled: boolean; + debtCeiling: BigNumber; + debtCeilingDecimals: BigNumber; + eModeCategoryId: number; + borrowCap: BigNumber; + supplyCap: BigNumber; + eModeLtv: number; + eModeLiquidationThreshold: number; + eModeLiquidationBonus: number; + eModePriceSource: string; + eModeLabel: string; + borrowableInIsolation: boolean; + })[], + [BigNumber, BigNumber, BigNumber, number] & { + marketReferenceCurrencyUnit: BigNumber; + marketReferenceCurrencyPriceInUsd: BigNumber; + networkBaseTokenPriceInUsd: BigNumber; + networkBaseTokenPriceDecimals: number; + }, + ] + >; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise< + [ + ([ + string, + BigNumber, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + ] & { + underlyingAsset: string; + scaledATokenBalance: BigNumber; + usageAsCollateralEnabledOnUser: boolean; + stableBorrowRate: BigNumber; + scaledVariableDebt: BigNumber; + principalStableDebt: BigNumber; + stableBorrowLastUpdateTimestamp: BigNumber; + })[], + number, + ] + >; + }; + + filters: {}; + + estimateGas: { + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise; + }; + + populateTransaction: { + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise; + }; +} diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/typechain/IUiPoolDataProviderV3__factory.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/typechain/IUiPoolDataProviderV3__factory.ts new file mode 100644 index 00000000..e629a32f --- /dev/null +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/typechain/IUiPoolDataProviderV3__factory.ts @@ -0,0 +1,432 @@ +/* Autogenerated file. Do not edit manually. */ +/* eslint-disable */ + +import { Contract, Signer, utils } from 'ethers'; +import { Provider } from '@ethersproject/providers'; +import type { + IUiPoolDataProviderV3, + IUiPoolDataProviderV3Interface, +} from './IUiPoolDataProviderV3'; + +const _abi = [ + { + inputs: [ + { + internalType: 'contract IPoolAddressesProvider', + name: 'provider', + type: 'address', + }, + ], + name: 'getReservesData', + outputs: [ + { + components: [ + { + internalType: 'address', + name: 'underlyingAsset', + type: 'address', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'string', + name: 'symbol', + type: 'string', + }, + { + internalType: 'uint256', + name: 'decimals', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'baseLTVasCollateral', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'reserveLiquidationThreshold', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'reserveLiquidationBonus', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'reserveFactor', + type: 'uint256', + }, + { + internalType: 'bool', + name: 'usageAsCollateralEnabled', + type: 'bool', + }, + { + internalType: 'bool', + name: 'borrowingEnabled', + type: 'bool', + }, + { + internalType: 'bool', + name: 'stableBorrowRateEnabled', + type: 'bool', + }, + { + internalType: 'bool', + name: 'isActive', + type: 'bool', + }, + { + internalType: 'bool', + name: 'isFrozen', + type: 'bool', + }, + { + internalType: 'uint128', + name: 'liquidityIndex', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'variableBorrowIndex', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'liquidityRate', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'variableBorrowRate', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'stableBorrowRate', + type: 'uint128', + }, + { + internalType: 'uint40', + name: 'lastUpdateTimestamp', + type: 'uint40', + }, + { + internalType: 'address', + name: 'aTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'stableDebtTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'variableDebtTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'interestRateStrategyAddress', + type: 'address', + }, + { + internalType: 'uint256', + name: 'availableLiquidity', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'totalPrincipalStableDebt', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'averageStableRate', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'stableDebtLastUpdateTimestamp', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'totalScaledVariableDebt', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'priceInMarketReferenceCurrency', + type: 'uint256', + }, + { + internalType: 'address', + name: 'priceOracle', + type: 'address', + }, + { + internalType: 'uint256', + name: 'variableRateSlope1', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'variableRateSlope2', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'stableRateSlope1', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'stableRateSlope2', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'baseStableBorrowRate', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'baseVariableBorrowRate', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'optimalUsageRatio', + type: 'uint256', + }, + { + internalType: 'bool', + name: 'isPaused', + type: 'bool', + }, + { + internalType: 'bool', + name: 'isSiloedBorrowing', + type: 'bool', + }, + { + internalType: 'uint128', + name: 'accruedToTreasury', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'unbacked', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'isolationModeTotalDebt', + type: 'uint128', + }, + { + internalType: 'bool', + name: 'flashLoanEnabled', + type: 'bool', + }, + { + internalType: 'uint256', + name: 'debtCeiling', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'debtCeilingDecimals', + type: 'uint256', + }, + { + internalType: 'uint8', + name: 'eModeCategoryId', + type: 'uint8', + }, + { + internalType: 'uint256', + name: 'borrowCap', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'supplyCap', + type: 'uint256', + }, + { + internalType: 'uint16', + name: 'eModeLtv', + type: 'uint16', + }, + { + internalType: 'uint16', + name: 'eModeLiquidationThreshold', + type: 'uint16', + }, + { + internalType: 'uint16', + name: 'eModeLiquidationBonus', + type: 'uint16', + }, + { + internalType: 'address', + name: 'eModePriceSource', + type: 'address', + }, + { + internalType: 'string', + name: 'eModeLabel', + type: 'string', + }, + { + internalType: 'bool', + name: 'borrowableInIsolation', + type: 'bool', + }, + ], + internalType: 'struct IUiPoolDataProviderV3.AggregatedReserveData[]', + name: '', + type: 'tuple[]', + }, + { + components: [ + { + internalType: 'uint256', + name: 'marketReferenceCurrencyUnit', + type: 'uint256', + }, + { + internalType: 'int256', + name: 'marketReferenceCurrencyPriceInUsd', + type: 'int256', + }, + { + internalType: 'int256', + name: 'networkBaseTokenPriceInUsd', + type: 'int256', + }, + { + internalType: 'uint8', + name: 'networkBaseTokenPriceDecimals', + type: 'uint8', + }, + ], + internalType: 'struct IUiPoolDataProviderV3.BaseCurrencyInfo', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IPoolAddressesProvider', + name: 'provider', + type: 'address', + }, + ], + name: 'getReservesList', + outputs: [ + { + internalType: 'address[]', + name: '', + type: 'address[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IPoolAddressesProvider', + name: 'provider', + type: 'address', + }, + { + internalType: 'address', + name: 'user', + type: 'address', + }, + ], + name: 'getUserReservesData', + outputs: [ + { + components: [ + { + internalType: 'address', + name: 'underlyingAsset', + type: 'address', + }, + { + internalType: 'uint256', + name: 'scaledATokenBalance', + type: 'uint256', + }, + { + internalType: 'bool', + name: 'usageAsCollateralEnabledOnUser', + type: 'bool', + }, + { + internalType: 'uint256', + name: 'stableBorrowRate', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'scaledVariableDebt', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'principalStableDebt', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'stableBorrowLastUpdateTimestamp', + type: 'uint256', + }, + ], + internalType: 'struct IUiPoolDataProviderV3.UserReserveData[]', + name: '', + type: 'tuple[]', + }, + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, +]; + +export class IUiPoolDataProviderV3__factory { + static readonly abi = _abi; + static createInterface(): IUiPoolDataProviderV3Interface { + return new utils.Interface(_abi) as IUiPoolDataProviderV3Interface; + } + static connect( + address: string, + signerOrProvider: Signer | Provider, + ): IUiPoolDataProviderV3 { + return new Contract( + address, + _abi, + signerOrProvider, + ) as IUiPoolDataProviderV3; + } +} diff --git a/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/types.ts b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/types.ts new file mode 100644 index 00000000..bbf21410 --- /dev/null +++ b/packages/contract-helpers/src/v3-UiPoolDataProvider-legacy-contract/types.ts @@ -0,0 +1,66 @@ +import { BigNumber } from 'ethers'; + +export interface LegacyReservesData { + 0: Array<{ + underlyingAsset: string; + name: string; + symbol: string; + decimals: BigNumber; + baseLTVasCollateral: BigNumber; + reserveLiquidationThreshold: BigNumber; + reserveLiquidationBonus: BigNumber; + reserveFactor: BigNumber; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + stableBorrowRateEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + liquidityRate: BigNumber; + variableBorrowRate: BigNumber; + stableBorrowRate: BigNumber; + lastUpdateTimestamp: number; + aTokenAddress: string; + stableDebtTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: BigNumber; + totalPrincipalStableDebt: BigNumber; + averageStableRate: BigNumber; + stableDebtLastUpdateTimestamp: BigNumber; + totalScaledVariableDebt: BigNumber; + priceInMarketReferenceCurrency: BigNumber; + priceOracle: string; + variableRateSlope1: BigNumber; + variableRateSlope2: BigNumber; + stableRateSlope1: BigNumber; + stableRateSlope2: BigNumber; + baseStableBorrowRate: BigNumber; + baseVariableBorrowRate: BigNumber; + optimalUsageRatio: BigNumber; + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: BigNumber; + unbacked: BigNumber; + isolationModeTotalDebt: BigNumber; + debtCeiling: BigNumber; + debtCeilingDecimals: BigNumber; + eModeCategoryId: number; + borrowCap: BigNumber; + supplyCap: BigNumber; + eModeLtv: number; + eModeLiquidationThreshold: number; + eModeLiquidationBonus: number; + eModePriceSource: string; + eModeLabel: string; + borrowableInIsolation: boolean; + flashLoanEnabled: boolean; + }>; + 1: { + marketReferenceCurrencyUnit: BigNumber; + marketReferenceCurrencyPriceInUsd: BigNumber; + networkBaseTokenPriceInUsd: BigNumber; + networkBaseTokenPriceDecimals: number; + }; +} diff --git a/packages/math-utils/src/formatters/reserve/calculate-reserve-debt.ts b/packages/math-utils/src/formatters/reserve/calculate-reserve-debt.ts index 12ecf29f..4390b690 100644 --- a/packages/math-utils/src/formatters/reserve/calculate-reserve-debt.ts +++ b/packages/math-utils/src/formatters/reserve/calculate-reserve-debt.ts @@ -11,6 +11,7 @@ export interface CalculateReserveDebtRequest { lastUpdateTimestamp: number; averageStableRate: string; stableDebtLastUpdateTimestamp: number; + virtualUnderlyingBalance: string; } export interface CalculateReserveDebtResponse { @@ -27,7 +28,9 @@ export function calculateReserveDebt( const totalVariableDebt = getTotalVariableDebt(reserveDebt, currentTimestamp); const totalStableDebt = getTotalStableDebt(reserveDebt, currentTimestamp); const totalDebt = totalVariableDebt.plus(totalStableDebt); - const totalLiquidity = totalDebt.plus(reserveDebt.availableLiquidity); + const totalLiquidity = totalDebt + .plus(reserveDebt.availableLiquidity) + .plus(reserveDebt.virtualUnderlyingBalance); return { totalVariableDebt, totalStableDebt, diff --git a/packages/math-utils/src/formatters/reserve/index.ts b/packages/math-utils/src/formatters/reserve/index.ts index 1f7a4b19..a090982d 100644 --- a/packages/math-utils/src/formatters/reserve/index.ts +++ b/packages/math-utils/src/formatters/reserve/index.ts @@ -82,6 +82,8 @@ export interface ReserveData { eModeLiquidationThreshold: number; eModeLiquidationBonus: number; unbacked: string; + virtualAccActive: boolean; + virtualUnderlyingBalance: string; } interface GetComputedReserveFieldsResponse { diff --git a/packages/math-utils/src/mocks.ts b/packages/math-utils/src/mocks.ts index acbb5c23..e2c650fd 100644 --- a/packages/math-utils/src/mocks.ts +++ b/packages/math-utils/src/mocks.ts @@ -47,6 +47,8 @@ export class ReserveMock { eModeLiquidationThreshold: 7000, // 70% eModeLiquidationBonus: 0, unbacked: '0', + virtualAccActive: false, + virtualUnderlyingBalance: '0', }; }