import { DeploylessViewerClient } from 'deployless-view'; import { BigNumber, providers } from 'ethers'; import { UiPoolDataProvider as ParaUiPoolDataProvider } from '../UiPoolDataProvider-contract'; import BaseService from '../commons/BaseService'; import { UiPoolDataProvider } from './typechain/UiPoolDataProvider'; import { UiPoolDataProviderFactory } from './typechain/UiPoolDataProviderFactory'; export class BenddaoUiProviderService extends BaseService { private readonly poolAddressesProviderForBenddao: string; private readonly poolAddressesProviderForPara: string; private readonly deployLessViewer; private readonly instance: UiPoolDataProvider; private readonly paraUiPoolDataProviderInstance: ParaUiPoolDataProvider; // eslint-disable-next-line public constructor( provider: providers.Provider, uiPoolDataProviderForBenddao: string, poolAddressesProviderForBenddao: string, uiPoolDataProviderAddressForPara: string, poolAddressesProviderForPara: string, chainId: number, ) { super(provider, UiPoolDataProviderFactory); this.poolAddressesProviderForBenddao = poolAddressesProviderForBenddao; this.poolAddressesProviderForPara = poolAddressesProviderForPara; this.deployLessViewer = new DeploylessViewerClient(provider); this.paraUiPoolDataProviderInstance = new ParaUiPoolDataProvider({ uiPoolDataProviderAddress: uiPoolDataProviderAddressForPara, provider, chainId, }); this.instance = UiPoolDataProviderFactory.connect( uiPoolDataProviderForBenddao, provider, ); } public async getUsersBenddaoReserveInfo( userAddr: string, nTokenMap: Record, ) { const nftsData = await this.instance.getUserNftsData( this.poolAddressesProviderForBenddao, userAddr, ); const result = await this.deployLessViewer.batchGetAllTokensByOwner( userAddr, nftsData.map(nft => ({ nft: nft.bNftAddress, // enumerable nftType: 1, })), ); // build info map const infoMap = nftsData.reduce< Record< string, { underlyingAsset: string; bNftAddress: string; suppliedList: number[]; tokenTraitMultipliers: Record; loansDataMap: Record< number, { loanId: BigNumber; state: BigNumber; reserveAsset: string; totalCollateralInReserve: BigNumber; totalDebtInReserve: BigNumber; availableBorrowsInReserve: BigNumber; healthFactor: BigNumber; liquidatePrice: BigNumber; bidderAddress: string; bidPrice: BigNumber; bidBorrowAmount: BigNumber; bidFine: BigNumber; } >; } > >((acc, nft, currentIndex) => { acc[nft.underlyingAsset] = { ...nft, suppliedList: result.tokenInfos[0][0][currentIndex] as number[], tokenTraitMultipliers: {}, loansDataMap: {}, }; return acc; }, {}); const hasLoanAssetAddrList = nftsData .filter(nft => nft.totalCollateral.gt(0)) .map( each => Array(each.totalCollateral.toNumber()).fill( each.underlyingAsset, ) as string[], ) .flat(); const hasLoanNftIdList = nftsData .filter(nft => nft.totalCollateral.gt(0)) .map(each => infoMap[each.underlyingAsset].suppliedList) .flat(); const loadsData = await this.instance.getSimpleLoansData( this.poolAddressesProviderForBenddao, hasLoanAssetAddrList, hasLoanNftIdList, ); hasLoanAssetAddrList.forEach((assetAddr, index) => { infoMap[assetAddr].loansDataMap[hasLoanNftIdList[index]] = loadsData[index]; }); const supportedTokenAddrs = nftsData .filter( nft => nft.totalCollateral.gt(0) && nTokenMap[nft.underlyingAsset], ) .map(each => each.underlyingAsset); const supportedNTokenAddrs = nftsData .filter( nft => nft.totalCollateral.gt(0) && nTokenMap[nft.underlyingAsset], ) .map(each => nTokenMap[each.underlyingAsset]); const supportedNTokenIds = nftsData .filter( nft => nft.totalCollateral.gt(0) && nTokenMap[nft.underlyingAsset], ) .map(each => infoMap[each.underlyingAsset].suppliedList); const nTokenData = await this.paraUiPoolDataProviderInstance.getNtokenData({ lendingPoolAddressProvider: this.poolAddressesProviderForPara, nTokenAddresses: supportedNTokenAddrs, tokenIds: supportedNTokenIds, }); supportedTokenAddrs.forEach((assetAddr, index) => { supportedNTokenIds[index].forEach((nftId, index2) => { infoMap[assetAddr].tokenTraitMultipliers[nftId] = nTokenData[index][index2].multiplier; }); }); return infoMap; } }