@augustdigital/pools
Version:
External services interactions
417 lines • 17.2 kB
JavaScript
"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