UNPKG

@augustdigital/pools

Version:

External services interactions

417 lines 17.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLendingPools = getLendingPools; exports.getLendingPool = getLendingPool; exports.getLendingPoolAvailableRedemptions = getLendingPoolAvailableRedemptions; exports.getLendingPoolRedemptionHistory = getLendingPoolRedemptionHistory; exports.getAllLendingPoolPositions = getAllLendingPoolPositions; exports.getLendingPoolApr = getLendingPoolApr; exports.getLendingPoolTvl = getLendingPoolTvl; exports.getLendingPoolLoans = getLendingPoolLoans; exports.getHealthFactorOfBorrowersByPool = getHealthFactorOfBorrowersByPool; const utils_1 = require("@augustdigital/utils"); const helpers_1 = require("./helpers"); const ethers_1 = require("ethers"); const abis_1 = require("@augustdigital/abis"); const EthDater = require('ethereum-block-by-date'); async function getLendingPools({ rpcUrl, optionalFields, env, apiKey, pools, }) { let lendingPools; if (Array.isArray(pools) && pools?.length > 0) { lendingPools = pools; } else { const provider = (0, utils_1.createProvider)(rpcUrl); const chainId = Number((await provider.getNetwork()).chainId); const tokenizedVaults = await (0, utils_1.fetchTokenizedVaults)(); const poolAddresses = tokenizedVaults .filter((vault) => vault.chain === chainId) .map((vault) => vault.address); if (!poolAddresses?.length) return []; lendingPools = await (0, helpers_1.getPoolsData)({ pools: poolAddresses, rpcUrl, tokenizedVaults, }); } if (optionalFields?.loans) { try { lendingPools = await Promise.all(lendingPools?.map(async (p) => { if ((0, helpers_1.isBadVault)(p.address)) return p; const _rpcUrl = p?.rpcUrl ? p.rpcUrl : rpcUrl; const loans = await (0, helpers_1.getPoolLoans)({ pool: p, rpcUrl: _rpcUrl, env }); const loanData = await (0, helpers_1.getPoolLoansData)({ pool: p, loans, rpcUrl: _rpcUrl, env, apiKey, }); return { ...p, ...loanData, }; })); } catch (e) { console.error('#getLendingPools::loans_or_aprs:', e); } } if (env === 'DEV') console.log('#getLendingPools:', lendingPools); return lendingPools; } async function getLendingPool({ pool, rpcUrl, optionalFields, env, apiKey, }) { let returnedPool; try { if (typeof pool === 'string') { const tokenizedVault = (await (0, utils_1.fetchTokenizedVaults)(pool))?.[0]; [returnedPool] = await (0, helpers_1.getPoolsData)({ pools: [pool], rpcUrl, tokenizedVaults: [tokenizedVault], }); } else { returnedPool = pool; } if (optionalFields?.loans && !(0, helpers_1.isBadVault)(returnedPool.address)) { const loans = await (0, helpers_1.getPoolLoans)({ pool: returnedPool, rpcUrl }); const loanData = await (0, helpers_1.getPoolLoansData)({ pool: returnedPool, loans, rpcUrl, apiKey, }); returnedPool = { ...returnedPool, ...loanData, }; } } catch (e) { console.error('#getLendingPool::loans_or_aprs:', e); } if (env === 'DEV') console.log('#getLendingPool:', returnedPool); return returnedPool; } async function getLendingPoolAvailableRedemptions({ pool, address, rpcUrl, env, apiKey, }) { } async function getLendingPoolRedemptionHistory({ pool, address, rpcUrl, env, }) { try { const provider = (0, utils_1.createProvider)(rpcUrl); const chainId = Number((await provider.getNetwork()).chainId); const poolContract = (0, utils_1.createContract)({ address: pool, abi: abis_1.ABI_LENDING_POOLS, provider, }); let logPromises = []; const currentBlock = await provider.getBlockNumber(); let startingBlock = currentBlock - (0, helpers_1.determineBlockSkipInternal)(chainId); let endBlock = currentBlock; const cutoffBlock = currentBlock - (0, helpers_1.determineBlockCutoff)(chainId); while (endBlock >= cutoffBlock) { const logBloomsPromises = poolContract.queryFilter('WithdrawalProcessed', BigInt(startingBlock), BigInt(endBlock)); logPromises.push(logBloomsPromises); startingBlock -= (0, helpers_1.determineBlockSkipInternal)(chainId); endBlock -= (0, helpers_1.determineBlockSkipInternal)(chainId); } const logs = (await Promise.all(logPromises.flat())).flat(); const iface = new ethers_1.ethers.Interface([ 'event WithdrawalProcessed (uint256 assetsAmount, uint256 processedOn, address receiverAddr, uint256 requestedOn)', ]); const events = logs.map((log) => iface.parseLog(log)); const decimals = await poolContract?.decimals?.(); const redemptions = []; events?.forEach((ev) => { if (!ev?.args) return; const [assetsAmount, processedOn, receiverAddr, requestedOn] = ev.args; if (address) { if (receiverAddr === address) { redemptions.push({ receiver: receiverAddr, amount: (0, utils_1.toNormalizedBn)(assetsAmount, decimals), processed: new Date(Number(processedOn) * 1000), requested: new Date(Number(requestedOn) * 1000), pool, }); } } else { redemptions.push({ receiver: receiverAddr, amount: (0, utils_1.toNormalizedBn)(assetsAmount, decimals), processed: new Date(Number(processedOn) * 1000), requested: new Date(Number(requestedOn) * 1000), pool, }); } }); if (env === 'DEV') console.log('#getLendingPoolRedemptionHistory:', redemptions); return redemptions; } catch (e) { console.error('#getLendingPoolRedemptionHistory:', e); } } async function getAllLendingPoolPositions({ pools, rpcUrl, address, env, apiKey, }) { let _pools = []; if (pools && pools?.length) _pools = pools; else _pools = await getLendingPools({ rpcUrl, env, optionalFields: { loanAllocations: false, loans: false }, }); if (!_pools?.length) { console.error('#getAllLendingPoolPositions: error fetching pools'); return []; } return await Promise.all(_pools?.map(async (pool) => { const _rpcUrl = pool?.rpcUrl ? pool.rpcUrl : rpcUrl; const poolContract = (0, utils_1.createContract)({ provider: (0, utils_1.createProvider)(_rpcUrl), abi: abis_1.ABI_LENDING_POOLS, address: pool.address, }); const bal = await poolContract.balanceOf(address); const balance = (0, utils_1.toNormalizedBn)(bal || 0, pool.decimals); const availableRedemptions = []; function renderStatus() { if (availableRedemptions?.length) return 'REDEEM'; if (BigInt(balance.raw) > BigInt(0)) return 'STAKED'; return 'PENDING'; } const apy = pool?.apy ? pool?.apy : (await getLendingPoolApr({ pool: pool.address, rpcUrl: _rpcUrl, }))?.value; const aggregateAvailableRedemptions = availableRedemptions?.reduce((acc, curr) => acc + BigInt(curr.amount.raw), BigInt(0)); const underlyingSymbol = pool?.underlying?.symbol; return { ...pool, token: underlyingSymbol, position: pool?.name, apy, status: renderStatus(), availableRedemptions, redeemable: (0, utils_1.toNormalizedBn)(aggregateAvailableRedemptions, pool.decimals), walletBalance: balance.normalized, walletBalanceUsd: Number(balance.normalized) * (await (0, utils_1.fetchTokenPrice)(underlyingSymbol, null, this.coinGeckoKey)), }; })) .then((data) => { const filtered = data.filter((promise) => promise.status !== 'PENDING'); if (env === 'DEV') { console.log('#getAllLendingPoolPositions:', filtered); } return filtered; }) .catch((e) => { console.error('#getAllLendingPoolPositions:', e); return []; }); } async function getLendingPoolApr({ pool, rpcUrl, inputParams, env, optionalFields, apiKey, }) { try { const tokenizedVault = (await (0, utils_1.fetchTokenizedVaults)(pool))?.[0]; if (typeof inputParams === 'undefined') { let [returnedPool] = await (0, helpers_1.getPoolsData)({ pools: [pool], rpcUrl, tokenizedVaults: [tokenizedVault], }); const loans = await (0, helpers_1.getPoolLoans)({ pool: returnedPool, rpcUrl }); const loanData = await (0, helpers_1.getPoolLoansData)({ pool: returnedPool, loans, rpcUrl, apiKey, }); returnedPool = { ...returnedPool, ...loanData, }; return { timestamp: Math.floor(new Date().getTime() / 1000), value: loanData?.apy || 0, }; } if (typeof inputParams !== 'undefined' && !inputParams.order) inputParams.order = 'desc'; if (typeof inputParams !== 'undefined' && !inputParams.interval) inputParams.interval = 'days'; const provider = (0, utils_1.createProvider)(rpcUrl); let [returnedPool] = await (0, helpers_1.getPoolsData)({ pools: [pool], rpcUrl, tokenizedVaults: [tokenizedVault], }); const allLoans = await (0, helpers_1.getPoolLoans)({ pool: returnedPool, rpcUrl }); const dater = new EthDater(provider); const blocks = await dater.getEvery(inputParams.interval, inputParams.start.toUTCString(), new Date().toUTCString()); const orderedBlocks = inputParams.order === 'desc' ? (0, utils_1.orderObjArrByDate)(blocks) : blocks; const minAbi = [ 'function currentApr() view returns (uint256)', 'function principalAmount() view returns (uint256)', ]; const loanAprsHistorical = await Promise.all(orderedBlocks?.map(async ({ block, date }) => { let aggregateApr = BigInt(0); const amountOfLoans = BigInt(allLoans.length || 0); const loansApr = await Promise.all(allLoans.map(async (l) => { const loanContract = (0, utils_1.createContract)({ address: l, abi: abis_1.ABI_LOAN, provider, }); const loanAprAtBlock = await provider.call({ to: loanContract, data: new ethers_1.Interface(minAbi).encodeFunctionData('currentApr', []), blockTag: block, }); if (loanAprAtBlock === '0x') return { timestamp: (0, utils_1.dateToUnix)(new Date(date)), value: (0, utils_1.toNormalizedBn)(0, 0), }; const readableLoanAprAtBlock = new ethers_1.Interface(minAbi).decodeFunctionResult('currentApr', loanAprAtBlock); aggregateApr += readableLoanAprAtBlock?.[0]; return { timestamp: (0, utils_1.dateToUnix)(new Date(date)), value: (0, utils_1.toNormalizedBn)(readableLoanAprAtBlock?.[0], helpers_1.LOANS_APR_DECIMALS), }; })); return { timestamp: (0, utils_1.dateToUnix)(new Date(date)), value: (0, utils_1.toNormalizedBn)(aggregateApr / amountOfLoans, helpers_1.LOANS_APR_DECIMALS), }; })); if (env === 'DEV') { console.log('#getLendingPoolApr:', loanAprsHistorical); } return loanAprsHistorical; } catch (e) { console.error('#getLendingPoolApr:', e); } } async function getLendingPoolTvl({ pool, rpcUrl, inputParams, env, }) { try { if (typeof inputParams === 'undefined') { const tokenizedVault = (await (0, utils_1.fetchTokenizedVaults)(pool))?.[0]; let [returnedPool] = await (0, helpers_1.getPoolsData)({ pools: [pool], rpcUrl, tokenizedVaults: [tokenizedVault], }); const returnObj = { timestamp: (0, utils_1.dateToUnix)(new Date()), value: returnedPool.totalAssets, }; if (env === 'DEV') console.log('#getLendingPoolTvl:', returnObj); return [returnObj]; } if (typeof inputParams !== 'undefined' && !inputParams.order) inputParams.order = 'desc'; if (typeof inputParams !== 'undefined' && !inputParams.interval) inputParams.interval = 'days'; const provider = (0, utils_1.createProvider)(rpcUrl); const poolContract = (0, utils_1.createContract)({ address: pool, abi: abis_1.ABI_LENDING_POOLS, provider, }); const poolDecimals = await (0, utils_1.getDecimals)(provider, pool); const dater = new EthDater(provider); const blocks = await dater.getEvery(inputParams.interval, inputParams.start.toUTCString(), new Date().toUTCString()); const orderedBlocks = inputParams.order === 'desc' ? (0, utils_1.orderObjArrByDate)(blocks) : blocks; const minAbi = ['function totalAssets() view returns (uint256)']; const totalAssetsHistorical = await Promise.all(orderedBlocks?.map(async ({ block, date }) => { const totalAssetsAtBlock = await provider.call({ to: poolContract, data: new ethers_1.Interface(minAbi).encodeFunctionData('totalAssets', []), blockTag: block, }); if (totalAssetsAtBlock === '0x') return { timestamp: (0, utils_1.dateToUnix)(new Date(date)), value: (0, utils_1.toNormalizedBn)(0, 0), }; const readableTotalAssetsAtBlock = new ethers_1.Interface(minAbi).decodeFunctionResult('totalAssets', totalAssetsAtBlock); return { timestamp: (0, utils_1.dateToUnix)(new Date(date)), value: (0, utils_1.toNormalizedBn)(readableTotalAssetsAtBlock?.[0], poolDecimals), }; })); if (env === 'DEV') { console.log('#getLendingPoolTvl:', totalAssetsHistorical); } return totalAssetsHistorical; } catch (e) { console.error('#getLendingPoolTvl:', e); } } async function getLendingPoolLoans({ pool, rpcUrl, env, optionalFields, apiKey, }) { try { let returnedPool; if (typeof pool === 'string') { const tokenizedVault = (await (0, utils_1.fetchTokenizedVaults)(pool))?.[0]; [returnedPool] = await (0, helpers_1.getPoolsData)({ pools: [pool], rpcUrl, tokenizedVaults: [tokenizedVault], }); } else { returnedPool = pool; } const loans = await (0, helpers_1.getPoolLoans)({ pool: returnedPool, rpcUrl }); const loansData = await (0, helpers_1.getPoolLoansData)({ pool: returnedPool, loans, rpcUrl, apiKey, }); if (typeof pool === 'string') return loansData; return loansData; } catch (e) { console.error('#getLendingPoolLoans:', e); } } async function getHealthFactorOfBorrowersByPool({ rpcUrl, optionalFields, env, apiKey, }) { const pools = await getLendingPools({ rpcUrl, optionalFields, env, apiKey, }); const healthFactors = await Promise.all(pools.map(async (pool) => { return (0, helpers_1.getPoolBorrowerHealthFactor)({ pool, rpcUrl, env, apiKey, }); })); const healthFactorsByPool = {}; pools.map((pool, index) => { healthFactorsByPool[pool.address] = healthFactors[index]; }); return healthFactorsByPool; } //# sourceMappingURL=getters.js.map