diff --git a/packages/contract-helpers/src/UiPoolDataProviderV3-contract/_mocks.ts b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/_mocks.ts new file mode 100644 index 00000000..97e2167d --- /dev/null +++ b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/_mocks.ts @@ -0,0 +1,291 @@ +import { BigNumber } from 'ethers'; +import { EModeData, ReservesData, UserReserveData } from './types'; + +export const reservesMock: ReservesData = { + 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, + 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, + }), + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + variableDebtTokenAddress: '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: 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, + }), + baseVariableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + optimalUsageRatio: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + // new + debtCeiling: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + borrowCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + supplyCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + 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, + }), + virtualAccActive: false, + virtualUnderlyingBalance: 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, + 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, + }), + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + variableDebtTokenAddress: '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: 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, + }), + baseVariableBorrowRate: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + optimalUsageRatio: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + // new + debtCeiling: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + borrowCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + supplyCap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + 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, + }), + virtualAccActive: false, + virtualUnderlyingBalance: 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, + scaledVariableDebt: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + }, + ], + 1: 1, +}; + +export const eModesMock: EModeData = { + id: 1, + eMode: { + ltv: 1, + liquidationThreshold: 1, + liquidationBonus: 1, + label: 'test label', + collateralBitmap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + borrowableBitmap: BigNumber.from({ + _hex: '0x0', + _isBigNumber: true, + }), + }, +}; diff --git a/packages/contract-helpers/src/UiPoolDataProviderV3-contract/index.ts b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/index.ts new file mode 100644 index 00000000..906432e1 --- /dev/null +++ b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/index.ts @@ -0,0 +1,237 @@ +import { providers } from 'ethers'; +import { isAddress } from 'ethers/lib/utils'; +import { ReservesHelperInput, UserReservesHelperInput } from '../index'; +import { UiPoolDataProviderV3 } from './typechain/UiPoolDataProviderV3'; +import { UiPoolDataProviderV3__factory } from './typechain/UiPoolDataProviderV3__factory'; +import { + ReservesData, + UserReserveData, + PoolBaseCurrencyHumanized, + ReserveDataHumanized, + ReservesDataHumanized, + UserReserveDataHumanized, + EModeData, +} 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 UiPoolDataProviderContext { + uiPoolDataProviderAddress: string; + provider: providers.Provider; + chainId: number; +} + +export interface UiPoolDataProviderInterface { + getReservesList: (args: ReservesHelperInput) => Promise; + getReservesData: (args: ReservesHelperInput) => Promise; + getUserReservesData: ( + args: UserReservesHelperInput, + ) => Promise; + getEModes: (args: ReservesHelperInput) => Promise; + getReservesHumanized: ( + args: ReservesHelperInput, + ) => Promise; + getUserReservesHumanized: (args: UserReservesHelperInput) => Promise<{ + userReserves: UserReserveDataHumanized[]; + userEmodeCategoryId: number; + }>; +} + +export class UiPoolDataProvider implements UiPoolDataProviderInterface { + private readonly _contract: UiPoolDataProviderV3; + + 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 = UiPoolDataProviderV3__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 }: ReservesData = + await this.getReservesData({ lendingPoolAddressProvider }); + + const reservesData: ReserveDataHumanized[] = reservesRaw.map(reserveRaw => { + const virtualUnderlyingBalance = + reserveRaw.virtualUnderlyingBalance.toString(); + const { virtualAccActive } = reserveRaw; + return { + 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, + isActive: reserveRaw.isActive, + isFrozen: reserveRaw.isFrozen, + liquidityIndex: reserveRaw.liquidityIndex.toString(), + variableBorrowIndex: reserveRaw.variableBorrowIndex.toString(), + liquidityRate: reserveRaw.liquidityRate.toString(), + variableBorrowRate: reserveRaw.variableBorrowRate.toString(), + lastUpdateTimestamp: reserveRaw.lastUpdateTimestamp, + aTokenAddress: reserveRaw.aTokenAddress.toString(), + variableDebtTokenAddress: + reserveRaw.variableDebtTokenAddress.toString(), + interestRateStrategyAddress: + reserveRaw.interestRateStrategyAddress.toString(), + availableLiquidity: reserveRaw.availableLiquidity.toString(), + totalScaledVariableDebt: reserveRaw.totalScaledVariableDebt.toString(), + priceInMarketReferenceCurrency: + reserveRaw.priceInMarketReferenceCurrency.toString(), + priceOracle: reserveRaw.priceOracle, + variableRateSlope1: reserveRaw.variableRateSlope1.toString(), + variableRateSlope2: reserveRaw.variableRateSlope2.toString(), + baseVariableBorrowRate: reserveRaw.baseVariableBorrowRate.toString(), + optimalUsageRatio: reserveRaw.optimalUsageRatio.toString(), + // new fields + isPaused: reserveRaw.isPaused, + debtCeiling: reserveRaw.debtCeiling.toString(), + borrowCap: reserveRaw.borrowCap.toString(), + supplyCap: reserveRaw.supplyCap.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, + virtualUnderlyingBalance, + }; + }); + + 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, + scaledVariableDebt: userReserveRaw.scaledVariableDebt.toString(), + })), + userEmodeCategoryId, + }; + } + + public async getEModes({ + lendingPoolAddressProvider, + }: ReservesHelperInput): Promise { + if (!isAddress(lendingPoolAddressProvider)) { + throw new Error('Lending pool address is not valid'); + } + + return this._contract.getEModes(lendingPoolAddressProvider); + } +} diff --git a/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/UiPoolDataProviderV3.ts b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/UiPoolDataProviderV3.ts new file mode 100644 index 00000000..ead93d40 --- /dev/null +++ b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/UiPoolDataProviderV3.ts @@ -0,0 +1,563 @@ +/* Autogenerated file. Do not edit manually. */ +/* eslint-disable */ +import type { + BaseContract, + BigNumber, + BigNumberish, + BytesLike, + CallOverrides, + PopulatedTransaction, + Signer, + utils, +} from 'ethers'; +import type { FunctionFragment, Result } from '@ethersproject/abi'; +import type { Listener, Provider } from '@ethersproject/providers'; +import type { + TypedEventFilter, + TypedEvent, + TypedListener, + OnEvent, +} from './common'; + +export declare namespace DataTypes { + export type EModeCategoryStruct = { + ltv: BigNumberish; + liquidationThreshold: BigNumberish; + liquidationBonus: BigNumberish; + collateralBitmap: BigNumberish; + label: string; + borrowableBitmap: BigNumberish; + }; + + export type EModeCategoryStructOutput = [ + number, + number, + number, + BigNumber, + string, + BigNumber, + ] & { + ltv: number; + liquidationThreshold: number; + liquidationBonus: number; + collateralBitmap: BigNumber; + label: string; + borrowableBitmap: BigNumber; + }; +} + +export declare namespace IUiPoolDataProviderV3 { + export type EmodeStruct = { + id: BigNumberish; + eMode: DataTypes.EModeCategoryStruct; + }; + + export type EmodeStructOutput = [ + number, + DataTypes.EModeCategoryStructOutput, + ] & { id: number; eMode: DataTypes.EModeCategoryStructOutput }; + + export type AggregatedReserveDataStruct = { + underlyingAsset: string; + name: string; + symbol: string; + decimals: BigNumberish; + baseLTVasCollateral: BigNumberish; + reserveLiquidationThreshold: BigNumberish; + reserveLiquidationBonus: BigNumberish; + reserveFactor: BigNumberish; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: BigNumberish; + variableBorrowIndex: BigNumberish; + liquidityRate: BigNumberish; + variableBorrowRate: BigNumberish; + lastUpdateTimestamp: BigNumberish; + aTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: BigNumberish; + totalScaledVariableDebt: BigNumberish; + priceInMarketReferenceCurrency: BigNumberish; + priceOracle: string; + variableRateSlope1: BigNumberish; + variableRateSlope2: BigNumberish; + baseVariableBorrowRate: BigNumberish; + optimalUsageRatio: BigNumberish; + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: BigNumberish; + unbacked: BigNumberish; + isolationModeTotalDebt: BigNumberish; + flashLoanEnabled: boolean; + debtCeiling: BigNumberish; + debtCeilingDecimals: BigNumberish; + borrowCap: BigNumberish; + supplyCap: BigNumberish; + borrowableInIsolation: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: BigNumberish; + }; + + export type AggregatedReserveDataStructOutput = [ + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + number, + string, + string, + string, + BigNumber, + BigNumber, + BigNumber, + string, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + BigNumber, + BigNumber, + BigNumber, + boolean, + BigNumber, + BigNumber, + BigNumber, + BigNumber, + boolean, + boolean, + BigNumber, + ] & { + underlyingAsset: string; + name: string; + symbol: string; + decimals: BigNumber; + baseLTVasCollateral: BigNumber; + reserveLiquidationThreshold: BigNumber; + reserveLiquidationBonus: BigNumber; + reserveFactor: BigNumber; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + liquidityRate: BigNumber; + variableBorrowRate: BigNumber; + lastUpdateTimestamp: number; + aTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: BigNumber; + totalScaledVariableDebt: BigNumber; + priceInMarketReferenceCurrency: BigNumber; + priceOracle: string; + variableRateSlope1: BigNumber; + variableRateSlope2: BigNumber; + baseVariableBorrowRate: BigNumber; + optimalUsageRatio: BigNumber; + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: BigNumber; + unbacked: BigNumber; + isolationModeTotalDebt: BigNumber; + flashLoanEnabled: boolean; + debtCeiling: BigNumber; + debtCeilingDecimals: BigNumber; + borrowCap: BigNumber; + supplyCap: BigNumber; + borrowableInIsolation: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: BigNumber; + }; + + export type BaseCurrencyInfoStruct = { + marketReferenceCurrencyUnit: BigNumberish; + marketReferenceCurrencyPriceInUsd: BigNumberish; + networkBaseTokenPriceInUsd: BigNumberish; + networkBaseTokenPriceDecimals: BigNumberish; + }; + + export type BaseCurrencyInfoStructOutput = [ + BigNumber, + BigNumber, + BigNumber, + number, + ] & { + marketReferenceCurrencyUnit: BigNumber; + marketReferenceCurrencyPriceInUsd: BigNumber; + networkBaseTokenPriceInUsd: BigNumber; + networkBaseTokenPriceDecimals: number; + }; + + export type UserReserveDataStruct = { + underlyingAsset: string; + scaledATokenBalance: BigNumberish; + usageAsCollateralEnabledOnUser: boolean; + scaledVariableDebt: BigNumberish; + }; + + export type UserReserveDataStructOutput = [ + string, + BigNumber, + boolean, + BigNumber, + ] & { + underlyingAsset: string; + scaledATokenBalance: BigNumber; + usageAsCollateralEnabledOnUser: boolean; + scaledVariableDebt: BigNumber; + }; +} + +export interface UiPoolDataProviderV3Interface extends utils.Interface { + functions: { + 'ETH_CURRENCY_UNIT()': FunctionFragment; + 'MKR_ADDRESS()': FunctionFragment; + 'bytes32ToString(bytes32)': FunctionFragment; + 'getEModes(address)': FunctionFragment; + 'getReservesData(address)': FunctionFragment; + 'getReservesList(address)': FunctionFragment; + 'getUserReservesData(address,address)': FunctionFragment; + 'marketReferenceCurrencyPriceInUsdProxyAggregator()': FunctionFragment; + 'networkBaseTokenPriceInUsdProxyAggregator()': FunctionFragment; + }; + + getFunction( + nameOrSignatureOrTopic: + | 'ETH_CURRENCY_UNIT' + | 'MKR_ADDRESS' + | 'bytes32ToString' + | 'getEModes' + | 'getReservesData' + | 'getReservesList' + | 'getUserReservesData' + | 'marketReferenceCurrencyPriceInUsdProxyAggregator' + | 'networkBaseTokenPriceInUsdProxyAggregator', + ): FunctionFragment; + + encodeFunctionData( + functionFragment: 'ETH_CURRENCY_UNIT', + values?: undefined, + ): string; + encodeFunctionData( + functionFragment: 'MKR_ADDRESS', + values?: undefined, + ): string; + encodeFunctionData( + functionFragment: 'bytes32ToString', + values: [BytesLike], + ): string; + encodeFunctionData(functionFragment: 'getEModes', values: [string]): string; + encodeFunctionData( + functionFragment: 'getReservesData', + values: [string], + ): string; + encodeFunctionData( + functionFragment: 'getReservesList', + values: [string], + ): string; + encodeFunctionData( + functionFragment: 'getUserReservesData', + values: [string, string], + ): string; + encodeFunctionData( + functionFragment: 'marketReferenceCurrencyPriceInUsdProxyAggregator', + values?: undefined, + ): string; + encodeFunctionData( + functionFragment: 'networkBaseTokenPriceInUsdProxyAggregator', + values?: undefined, + ): string; + + decodeFunctionResult( + functionFragment: 'ETH_CURRENCY_UNIT', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'MKR_ADDRESS', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'bytes32ToString', + data: BytesLike, + ): Result; + decodeFunctionResult(functionFragment: 'getEModes', data: BytesLike): Result; + decodeFunctionResult( + functionFragment: 'getReservesData', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'getReservesList', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'getUserReservesData', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'marketReferenceCurrencyPriceInUsdProxyAggregator', + data: BytesLike, + ): Result; + decodeFunctionResult( + functionFragment: 'networkBaseTokenPriceInUsdProxyAggregator', + data: BytesLike, + ): Result; + + events: {}; +} + +export interface UiPoolDataProviderV3 extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + interface: UiPoolDataProviderV3Interface; + + queryFilter( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>; + + listeners( + eventFilter?: TypedEventFilter, + ): Array>; + listeners(eventName?: string): Array; + removeAllListeners( + eventFilter: TypedEventFilter, + ): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + + functions: { + ETH_CURRENCY_UNIT(overrides?: CallOverrides): Promise<[BigNumber]>; + + MKR_ADDRESS(overrides?: CallOverrides): Promise<[string]>; + + bytes32ToString( + _bytes32: BytesLike, + overrides?: CallOverrides, + ): Promise<[string]>; + + getEModes( + provider: string, + overrides?: CallOverrides, + ): Promise<[IUiPoolDataProviderV3.EmodeStructOutput[]]>; + + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise< + [ + IUiPoolDataProviderV3.AggregatedReserveDataStructOutput[], + IUiPoolDataProviderV3.BaseCurrencyInfoStructOutput, + ] + >; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise<[string[]]>; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise<[IUiPoolDataProviderV3.UserReserveDataStructOutput[], number]>; + + marketReferenceCurrencyPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise<[string]>; + + networkBaseTokenPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise<[string]>; + }; + + ETH_CURRENCY_UNIT(overrides?: CallOverrides): Promise; + + MKR_ADDRESS(overrides?: CallOverrides): Promise; + + bytes32ToString( + _bytes32: BytesLike, + overrides?: CallOverrides, + ): Promise; + + getEModes( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise< + [ + IUiPoolDataProviderV3.AggregatedReserveDataStructOutput[], + IUiPoolDataProviderV3.BaseCurrencyInfoStructOutput, + ] + >; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise<[IUiPoolDataProviderV3.UserReserveDataStructOutput[], number]>; + + marketReferenceCurrencyPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + + networkBaseTokenPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + + callStatic: { + ETH_CURRENCY_UNIT(overrides?: CallOverrides): Promise; + + MKR_ADDRESS(overrides?: CallOverrides): Promise; + + bytes32ToString( + _bytes32: BytesLike, + overrides?: CallOverrides, + ): Promise; + + getEModes( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise< + [ + IUiPoolDataProviderV3.AggregatedReserveDataStructOutput[], + IUiPoolDataProviderV3.BaseCurrencyInfoStructOutput, + ] + >; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise<[IUiPoolDataProviderV3.UserReserveDataStructOutput[], number]>; + + marketReferenceCurrencyPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + + networkBaseTokenPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + }; + + filters: {}; + + estimateGas: { + ETH_CURRENCY_UNIT(overrides?: CallOverrides): Promise; + + MKR_ADDRESS(overrides?: CallOverrides): Promise; + + bytes32ToString( + _bytes32: BytesLike, + overrides?: CallOverrides, + ): Promise; + + getEModes(provider: string, overrides?: CallOverrides): Promise; + + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise; + + marketReferenceCurrencyPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + + networkBaseTokenPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + }; + + populateTransaction: { + ETH_CURRENCY_UNIT(overrides?: CallOverrides): Promise; + + MKR_ADDRESS(overrides?: CallOverrides): Promise; + + bytes32ToString( + _bytes32: BytesLike, + overrides?: CallOverrides, + ): Promise; + + getEModes( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getReservesData( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getReservesList( + provider: string, + overrides?: CallOverrides, + ): Promise; + + getUserReservesData( + provider: string, + user: string, + overrides?: CallOverrides, + ): Promise; + + marketReferenceCurrencyPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + + networkBaseTokenPriceInUsdProxyAggregator( + overrides?: CallOverrides, + ): Promise; + }; +} diff --git a/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/UiPoolDataProviderV3__factory.ts b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/UiPoolDataProviderV3__factory.ts new file mode 100644 index 00000000..e5ce0256 --- /dev/null +++ b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/UiPoolDataProviderV3__factory.ts @@ -0,0 +1,502 @@ +/* Autogenerated file. Do not edit manually. */ +/* eslint-disable */ + +import { Contract, Signer, utils } from 'ethers'; +import type { Provider } from '@ethersproject/providers'; +import type { + UiPoolDataProviderV3, + UiPoolDataProviderV3Interface, +} from './UiPoolDataProviderV3'; + +const _abi = [ + { + inputs: [ + { + internalType: 'contract IEACAggregatorProxy', + name: '_networkBaseTokenPriceInUsdProxyAggregator', + type: 'address', + }, + { + internalType: 'contract IEACAggregatorProxy', + name: '_marketReferenceCurrencyPriceInUsdProxyAggregator', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'ETH_CURRENCY_UNIT', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MKR_ADDRESS', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: '_bytes32', + type: 'bytes32', + }, + ], + name: 'bytes32ToString', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IPoolAddressesProvider', + name: 'provider', + type: 'address', + }, + ], + name: 'getEModes', + outputs: [ + { + components: [ + { + internalType: 'uint8', + name: 'id', + type: 'uint8', + }, + { + components: [ + { + internalType: 'uint16', + name: 'ltv', + type: 'uint16', + }, + { + internalType: 'uint16', + name: 'liquidationThreshold', + type: 'uint16', + }, + { + internalType: 'uint16', + name: 'liquidationBonus', + type: 'uint16', + }, + { + internalType: 'uint128', + name: 'collateralBitmap', + type: 'uint128', + }, + { + internalType: 'string', + name: 'label', + type: 'string', + }, + { + internalType: 'uint128', + name: 'borrowableBitmap', + type: 'uint128', + }, + ], + internalType: 'struct DataTypes.EModeCategory', + name: 'eMode', + type: 'tuple', + }, + ], + internalType: 'struct IUiPoolDataProviderV3.Emode[]', + name: '', + type: 'tuple[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + 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: '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: 'uint40', + name: 'lastUpdateTimestamp', + type: 'uint40', + }, + { + internalType: 'address', + name: 'aTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'variableDebtTokenAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'interestRateStrategyAddress', + type: 'address', + }, + { + internalType: 'uint256', + name: 'availableLiquidity', + 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: '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: 'uint256', + name: 'borrowCap', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'supplyCap', + type: 'uint256', + }, + { + internalType: 'bool', + name: 'borrowableInIsolation', + type: 'bool', + }, + { + internalType: 'bool', + name: 'virtualAccActive', + type: 'bool', + }, + { + internalType: 'uint128', + name: 'virtualUnderlyingBalance', + type: 'uint128', + }, + ], + 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: 'scaledVariableDebt', + type: 'uint256', + }, + ], + internalType: 'struct IUiPoolDataProviderV3.UserReserveData[]', + name: '', + type: 'tuple[]', + }, + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + 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 UiPoolDataProviderV3__factory { + static readonly abi = _abi; + static createInterface(): UiPoolDataProviderV3Interface { + return new utils.Interface(_abi) as UiPoolDataProviderV3Interface; + } + static connect( + address: string, + signerOrProvider: Signer | Provider, + ): UiPoolDataProviderV3 { + return new Contract( + address, + _abi, + signerOrProvider, + ) as UiPoolDataProviderV3; + } +} diff --git a/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/common.ts b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/common.ts new file mode 100644 index 00000000..0fb82cd3 --- /dev/null +++ b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/typechain/common.ts @@ -0,0 +1,43 @@ +/* Autogenerated file. Do not edit manually. */ +/* eslint-disable */ +import type { Listener } from '@ethersproject/providers'; +import type { Event, EventFilter } from 'ethers'; + +export interface TypedEvent< + TArgsArray extends Array = any, + TArgsObject = any, +> extends Event { + args: TArgsArray & TArgsObject; +} + +export interface TypedEventFilter<_TEvent extends TypedEvent> + extends EventFilter {} + +export interface TypedListener { + (...listenerArg: [...__TypechainArgsArray, TEvent]): void; +} + +type __TypechainArgsArray = T extends TypedEvent ? U : never; + +export interface OnEvent { + ( + eventFilter: TypedEventFilter, + listener: TypedListener, + ): TRes; + (eventName: string, listener: Listener): TRes; +} + +export type MinEthersFactory = { + deploy(...a: ARGS[]): Promise; +}; + +export type GetContractTypeFromFactory = F extends MinEthersFactory< + infer C, + any +> + ? C + : never; + +export type GetARGsTypeFromFactory = F extends MinEthersFactory + ? Parameters + : never; diff --git a/packages/contract-helpers/src/UiPoolDataProviderV3-contract/types.ts b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/types.ts new file mode 100644 index 00000000..f11b848a --- /dev/null +++ b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/types.ts @@ -0,0 +1,143 @@ +import { BigNumber } from 'ethers'; + +export interface EModeCategory { + ltv: number; + liquidationThreshold: number; + liquidationBonus: number; + collateralBitmap: BigNumber; + label: string; + borrowableBitmap: BigNumber; +} + +export interface EModeData { + id: number; + eMode: EModeCategory; +} + +export interface ReservesData { + 0: Array<{ + underlyingAsset: string; + name: string; + symbol: string; + decimals: BigNumber; + baseLTVasCollateral: BigNumber; + reserveLiquidationThreshold: BigNumber; + reserveLiquidationBonus: BigNumber; + reserveFactor: BigNumber; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: BigNumber; + variableBorrowIndex: BigNumber; + liquidityRate: BigNumber; + variableBorrowRate: BigNumber; + lastUpdateTimestamp: number; + aTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: BigNumber; + totalScaledVariableDebt: BigNumber; + priceInMarketReferenceCurrency: BigNumber; + priceOracle: string; + variableRateSlope1: BigNumber; + variableRateSlope2: BigNumber; + baseVariableBorrowRate: BigNumber; + optimalUsageRatio: BigNumber; + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: BigNumber; + unbacked: BigNumber; + isolationModeTotalDebt: BigNumber; + flashLoanEnabled: boolean; + debtCeiling: BigNumber; + debtCeilingDecimals: BigNumber; + borrowCap: BigNumber; + supplyCap: BigNumber; + borrowableInIsolation: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: BigNumber; + }>; + 1: { + marketReferenceCurrencyUnit: BigNumber; + marketReferenceCurrencyPriceInUsd: BigNumber; + networkBaseTokenPriceInUsd: BigNumber; + networkBaseTokenPriceDecimals: number; + }; +} + +export interface UserReserveData { + 0: Array<{ + underlyingAsset: string; + scaledATokenBalance: BigNumber; + usageAsCollateralEnabledOnUser: boolean; + scaledVariableDebt: BigNumber; + }>; + 1: number; +} + +export interface PoolBaseCurrencyHumanized { + marketReferenceCurrencyDecimals: number; + marketReferenceCurrencyPriceInUsd: string; + networkBaseTokenPriceInUsd: string; + networkBaseTokenPriceDecimals: number; +} + +export interface ReserveDataHumanized { + id: string; + underlyingAsset: string; + name: string; + symbol: string; + decimals: number; + baseLTVasCollateral: string; + reserveLiquidationThreshold: string; + reserveLiquidationBonus: string; + reserveFactor: string; + usageAsCollateralEnabled: boolean; + borrowingEnabled: boolean; + isActive: boolean; + isFrozen: boolean; + liquidityIndex: string; + variableBorrowIndex: string; + liquidityRate: string; + variableBorrowRate: string; + lastUpdateTimestamp: number; + aTokenAddress: string; + variableDebtTokenAddress: string; + interestRateStrategyAddress: string; + availableLiquidity: string; + totalScaledVariableDebt: string; + priceInMarketReferenceCurrency: string; + priceOracle: string; + variableRateSlope1: string; + variableRateSlope2: string; + baseVariableBorrowRate: string; + optimalUsageRatio: string; + // v3 only + isPaused: boolean; + isSiloedBorrowing: boolean; + accruedToTreasury: string; + unbacked: string; + isolationModeTotalDebt: string; + flashLoanEnabled: boolean; + debtCeiling: string; + debtCeilingDecimals: number; + borrowCap: string; + supplyCap: string; + borrowableInIsolation: boolean; + virtualAccActive: boolean; + virtualUnderlyingBalance: string; +} + +export interface ReservesDataHumanized { + reservesData: ReserveDataHumanized[]; + baseCurrencyData: PoolBaseCurrencyHumanized; +} + +export interface UserReserveDataHumanized { + id: string; + underlyingAsset: string; + scaledATokenBalance: string; + usageAsCollateralEnabledOnUser: boolean; + scaledVariableDebt: string; +} diff --git a/packages/contract-helpers/src/UiPoolDataProviderV3-contract/uiPoolDataProvider.test.ts b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/uiPoolDataProvider.test.ts new file mode 100644 index 00000000..08d21f0f --- /dev/null +++ b/packages/contract-helpers/src/UiPoolDataProviderV3-contract/uiPoolDataProvider.test.ts @@ -0,0 +1,293 @@ +import { providers } from 'ethers'; +import { eModesMock, reservesMock, userReservesMock } from './_mocks'; +import { UiPoolDataProvider } from './index'; + +describe('UiPoolDataProvider', () => { + const mockValidEthereumAddress = '0x88757f2f99175387ab4c6a4b3067c77a695b0349'; + const mockInvalidEthereumAddress = '0x0'; + + const createValidInstance = () => { + const instance = new UiPoolDataProvider({ + uiPoolDataProviderAddress: mockValidEthereumAddress, + provider: new providers.JsonRpcProvider(), + chainId: 137, + }); + + const mockGetReservesData = jest.fn(); + const mockGetUserReservesData = jest.fn(); + const mockGetEModes = jest.fn(); + + mockGetReservesData.mockResolvedValue(reservesMock); + mockGetUserReservesData.mockResolvedValue(userReservesMock); + mockGetEModes.mockResolvedValue(eModesMock); + + // @ts-expect-error readonly + instance._contract = { + getReservesList: jest.fn(), + getReservesData: mockGetReservesData, + getUserReservesData: mockGetUserReservesData, + getEModes: mockGetEModes, + }; + + return instance; + }; + + describe('creating', () => { + it('should throw an error if the contractAddress is not valid', () => { + expect( + () => + new UiPoolDataProvider({ + 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 UiPoolDataProvider({ + uiPoolDataProviderAddress: mockValidEthereumAddress, + provider: new providers.JsonRpcProvider(), + chainId: 137, + }); + + expect(instance instanceof UiPoolDataProvider).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('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('getEModes', () => { + it('should throw when lendingPoolAddressProvider is not valid address', async () => { + const instance = createValidInstance(); + await expect( + instance.getEModes({ + lendingPoolAddressProvider: mockInvalidEthereumAddress, + }), + ).rejects.toThrow('Lending pool address is not valid'); + }); + it('should not throw', async () => { + const instance = createValidInstance(); + await expect( + instance.getEModes({ + lendingPoolAddressProvider: 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, + isActive: true, + isFrozen: false, + isPaused: false, + isSiloedBorrowing: false, + liquidityIndex: '0', + variableBorrowIndex: '0', + liquidityRate: '0', + variableBorrowRate: '0', + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + variableDebtTokenAddress: + '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: + '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: '0', + totalScaledVariableDebt: '0', + priceInMarketReferenceCurrency: '0', + priceOracle: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + variableRateSlope1: '0', + variableRateSlope2: '0', + baseVariableBorrowRate: '0', + optimalUsageRatio: '0', + // new + debtCeiling: '0', + borrowCap: '0', + supplyCap: '0', + 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, + isActive: true, + isFrozen: false, + isPaused: false, + isSiloedBorrowing: false, + liquidityIndex: '0', + variableBorrowIndex: '0', + liquidityRate: '0', + variableBorrowRate: '0', + lastUpdateTimestamp: 1631772892, + aTokenAddress: '0xb8a16bbab34FA7A5C09Ec7679EAfb8fEC06897bc', + variableDebtTokenAddress: + '0xb7b7AF565495670713C92B8848fC8A650a968F81', + interestRateStrategyAddress: + '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + availableLiquidity: '0', + totalScaledVariableDebt: '0', + priceInMarketReferenceCurrency: '0', + priceOracle: '0x796ec26fc7df8D81BCB5BABF74ccdE0E2B122164', + variableRateSlope1: '0', + variableRateSlope2: '0', + baseVariableBorrowRate: '0', + optimalUsageRatio: '0', + // new + debtCeiling: '0', + borrowCap: '0', + supplyCap: '0', + 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', + scaledATokenBalance: '0', + scaledVariableDebt: '0', + underlyingAsset: '0xb597cd8d3217ea6477232f9217fa70837ff667af', + usageAsCollateralEnabledOnUser: false, + }, + ], + userEmodeCategoryId: 1, + }); + }); + }); +});