UNPKG

@ajna-finance/sdk

Version:

A typescript SDK that can be used to create Dapps in Ajna ecosystem.

697 lines 34.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Pool = void 0; const tslib_1 = require("tslib"); const ethcall_1 = require("ethcall"); const ethers_1 = require("ethers"); const constants_1 = require("../constants"); const common_1 = require("../contracts/common"); const erc20_1 = require("../contracts/erc20"); const erc20_pool_1 = require("../contracts/erc20-pool"); const pool_1 = require("../contracts/pool"); const pool_info_utils_1 = require("../contracts/pool-info-utils"); const position_manager_1 = require("../contracts/position-manager"); const types_1 = require("../types"); const numeric_1 = require("../utils/numeric"); const pricing_1 = require("../utils/pricing"); const ClaimableReserveAuction_1 = require("./ClaimableReserveAuction"); const PoolUtils_1 = require("./PoolUtils"); const Liquidation_1 = require("./Liquidation"); const time_1 = require("../utils/time"); const Bucket_1 = require("./Bucket"); const erc721_pool_factory_1 = require("../contracts/erc721-pool-factory"); const lender_helper_1 = require("../contracts/lender-helper"); /** * Abstract baseclass used for pools, regardless of collateral type. */ class Pool { constructor(provider, poolAddress, ajnaAddress, contract, contractMulti) { this.provider = provider; this.poolAddress = poolAddress; this.poolInfoContractUtils = (0, pool_info_utils_1.getPoolInfoUtilsContract)(provider); this.contractUtilsMulti = (0, pool_info_utils_1.getPoolInfoUtilsContractMulti)(); this.utils = new PoolUtils_1.PoolUtils(provider); this.ajnaAddress = ajnaAddress; this.name = 'pool'; this.ethcallProvider = {}; this.contract = contract; this.contractMulti = contractMulti; this.quoteAddress = ethers_1.constants.AddressZero; this.collateralAddress = ethers_1.constants.AddressZero; this.lenderHelper = (0, lender_helper_1.getLenderHelperContract)(this.provider); } initialize() { return tslib_1.__awaiter(this, void 0, void 0, function* () { this.ethcallProvider = new ethcall_1.Provider(); yield this.ethcallProvider.init(this.provider); const [quoteAddressResponse, collateralAddressResponse] = yield Promise.all([ (0, pool_1.quoteTokenAddress)(this.contract), (0, pool_1.collateralAddress)(this.contract), ]); this.quoteAddress = quoteAddressResponse; this.collateralAddress = collateralAddressResponse; try { const quoteToken = (0, erc20_1.getErc20Contract)(this.quoteAddress, this.provider); this.quoteSymbol = (yield quoteToken.symbol()).replace(/"+/g, ''); } catch (e) { const quoteToken = (0, erc20_1.getDSTokenContract)(this.quoteAddress, this.provider); this.quoteSymbol = ethers_1.utils.parseBytes32String(yield quoteToken.symbol()).replace(/"+/g, ''); } }); } /** * Approve this pool to manage Ajna token. * @param signer pool user * @param allowance approval amount (or MaxUint256) * @returns promise to transaction */ ajnaApprove(signer, allowance) { return tslib_1.__awaiter(this, void 0, void 0, function* () { return (0, erc20_pool_1.approve)(signer, this.poolAddress, this.ajnaAddress, allowance); }); } /** * Approve this pool to manage quote token. * @param signer pool user * @param allowance normalized approval amount (or MaxUint256) * @returns promise to transaction */ quoteApprove(signer, allowance) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const denormalizedAllowance = allowance.eq(ethers_1.constants.MaxUint256) ? allowance : allowance.div(yield (0, pool_1.quoteTokenScale)(this.contract)); return (0, erc20_pool_1.approve)(signer, this.poolAddress, this.quoteAddress, denormalizedAllowance); }); } /** * Retrieves pool reference prices. * @returns {@link PriceInfo} */ getPrices() { return tslib_1.__awaiter(this, void 0, void 0, function* () { const [hpb, hpbIndex, htp, htpIndex, lup, lupIndex] = yield (0, pool_info_utils_1.poolPricesInfo)(this.poolInfoContractUtils, this.poolAddress); const [, , liquidationDebt] = yield (0, pool_1.debtInfo)(this.contract); const llbIndex = yield (0, pool_1.depositIndex)(this.contract, liquidationDebt); const llb = (0, pricing_1.indexToPrice)(llbIndex); return { hpb, hpbIndex: +hpbIndex, htp, htpIndex: +htpIndex, lup, lupIndex: +lupIndex, llb, llbIndex: +llbIndex, }; }); } /** * Retrieves pool statistics. * @returns {@link Stats} */ getStats() { return tslib_1.__awaiter(this, void 0, void 0, function* () { // PoolInfoUtils multicall const poolLoansInfoCall = this.contractUtilsMulti.poolLoansInfo(this.poolAddress); const poolUtilizationInfoCall = this.contractUtilsMulti.poolUtilizationInfo(this.poolAddress); const poolReservesInfo = this.contractUtilsMulti.poolReservesInfo(this.poolAddress); const utilsData = yield this.ethcallProvider.all([ poolLoansInfoCall, poolUtilizationInfoCall, poolReservesInfo, ]); const [poolSize, loansCount, , pendingInflator] = utilsData[0]; const [minDebtAmount, collateralization, actualUtilization, targetUtilization] = utilsData[1]; const [reserves, claimableReserves, claimableReservesRemaining, auctionPrice] = utilsData[2]; // Pool multicall const poolData = yield this.ethcallProvider.all([ this.contractMulti.debtInfo(), this.contractMulti.interestRateInfo(), ]); const [debt, , liquidationDebt] = poolData[0]; const rateInfo = poolData[1]; return { poolSize: ethers_1.BigNumber.from(poolSize), debt, liquidationDebt, loansCount: +loansCount, minDebtAmount: ethers_1.BigNumber.from(minDebtAmount), collateralization: ethers_1.BigNumber.from(collateralization), actualUtilization: ethers_1.BigNumber.from(actualUtilization), targetUtilization: ethers_1.BigNumber.from(targetUtilization), reserves: ethers_1.BigNumber.from(reserves), claimableReserves: ethers_1.BigNumber.from(claimableReserves), claimableReservesRemaining: ethers_1.BigNumber.from(claimableReservesRemaining), reserveAuctionPrice: ethers_1.BigNumber.from(auctionPrice), borrowRate: rateInfo[0], interestRateLastUpdated: new Date(+rateInfo[1] * 1000), pendingInflator: ethers_1.BigNumber.from(pendingInflator), }; }); } /** * Measuring from highest price bucket with liquidity, determines index at which all liquidity in * the book has been utilized by specified debt; useful for estimating LUP. * @param debtAmount pool debt to be applied to liquidity * @returns fenwick index */ depositIndex(debtAmount) { return tslib_1.__awaiter(this, void 0, void 0, function* () { return yield (0, pool_1.depositIndex)(this.contract, debtAmount); }); } /** * Enables signer to bundle transactions together atomically in a single request. * @param signer consumer initiating transactions * @param callData array of transactions to sign and submit * @returns promise to transaction */ multicall(signer, callData) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const contractPoolWithSigner = this.contract.connect(signer); return (0, common_1.multicall)(contractPoolWithSigner, callData); }); } lpAllowance(index, spender, owner) { return tslib_1.__awaiter(this, void 0, void 0, function* () { return yield (0, pool_1.lpAllowance)(this.contract, index, spender, owner); }); } increaseLPAllowance(signer, indexes, amounts) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (indexes.length !== amounts.length) { throw new types_1.SdkError('indexes and amounts must be same length'); } const poolWithSigner = this.contract.connect(signer); const spender = (0, position_manager_1.getPositionManagerContract)(signer).address; return (0, pool_1.increaseLPAllowance)(poolWithSigner, spender, indexes, amounts); }); } /** * Checks if LP allowances are sufficient to memorialize position. * @param signer Consumer initiating transactions. * @param indices Fenwick index of the desired bucket. * @returns `true` if LP allowances are sufficient to memorialize position otherwise `false`. */ areLPAllowancesSufficient(signer, indices) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const spender = (0, position_manager_1.getPositionManagerContract)(signer).address; const signerAddress = yield signer.getAddress(); const allowancePromises = indices.map(index => this.contractMulti.lpAllowance(index, spender, signerAddress)); const allowances = yield this.ethcallProvider.all(allowancePromises); const balancePromises = indices.map(index => (0, pool_1.lenderInfo)(this.contract, signerAddress, index)); const balances = yield Promise.all(balancePromises); for (let i = 0; i < allowances.length; ++i) { const allowance = allowances[i]; const balance = balances[i][0]; if (allowance.lt(balance)) { return false; } } return true; }); } /** * @param minPrice lowest desired price * @param maxPrice highest desired price * @returns array of {@link Bucket}s between specified prices */ getBucketsByPriceRange(minPrice, maxPrice) { if (minPrice.gt(maxPrice)) throw new types_1.SdkError('maxPrice must exceed minPrice'); const buckets = new Array(); for (let index = (0, pricing_1.priceToIndex)(maxPrice); index <= (0, pricing_1.priceToIndex)(minPrice); index++) { buckets.push(new Bucket_1.Bucket(this.provider, this, index)); } return buckets; } /** Retrieves origination fee rate for this pool; multiply by new debt to get fee. @returns origination fee rate, in WAD precision */ getOriginationFeeRate() { return tslib_1.__awaiter(this, void 0, void 0, function* () { return yield this.poolInfoContractUtils.borrowFeeRate(this.poolAddress); }); } /** * Retrieve information for a specific loan. * @param borrowerAddress identifies the loan * @returns {@link Loan} */ getLoan(borrowerAddress) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const poolPricesInfoCall = this.contractUtilsMulti.poolPricesInfo(this.poolAddress); const poolLoansInfoCall = this.contractUtilsMulti.poolLoansInfo(this.poolAddress); const borrowerInfoCall = this.contractUtilsMulti.borrowerInfo(this.poolAddress, borrowerAddress); const auctionStatusCall = this.contractUtilsMulti.auctionStatus(this.poolAddress, borrowerAddress); const poolBorrowerInfoCall = this.contractMulti.borrowerInfo(borrowerAddress); const response = yield this.ethcallProvider.all([ poolPricesInfoCall, poolLoansInfoCall, borrowerInfoCall, auctionStatusCall, poolBorrowerInfoCall, ]); const [, , , , lup] = response[0]; const [, , , pendingInflator] = response[1]; const [debt, collateral, t0np, tp] = response[2]; const [kickTimestamp] = response[3]; const [, , npTpRatio] = response[4]; const collateralization = debt.gt(0) ? (0, numeric_1.wdiv)((0, numeric_1.wmul)(collateral, lup), (0, numeric_1.wmul)(debt, constants_1.COLLATERALIZATION_FACTOR)) : (0, numeric_1.toWad)(1); const np = (0, numeric_1.wmul)(t0np, pendingInflator); return { collateralization, debt, collateral, thresholdPrice: tp, neutralPrice: np, liquidationBond: this.calculateLiquidationBond(npTpRatio, debt), isKicked: !kickTimestamp.eq(ethers_1.BigNumber.from(0)), }; }); } /** * Retrieve information for a list of loans. * @param borrowerAddresses identifies the loans * @returns map of Loans, indexed by borrowerAddress */ getLoans(borrowerAddresses) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const calls = []; // push pool-level requests followed by request for each loan calls.push(this.contractUtilsMulti.poolPricesInfo(this.poolAddress)); calls.push(this.contractUtilsMulti.poolLoansInfo(this.poolAddress)); for (const loan of borrowerAddresses) { calls.push(this.contractUtilsMulti.borrowerInfo(this.poolAddress, loan)); calls.push(this.contractUtilsMulti.auctionStatus(this.poolAddress, loan)); calls.push(this.contractMulti.borrowerInfo(loan)); } // perform the multicall const response = yield this.ethcallProvider.all(calls); // since loan details depend upon pool-level data, parse pool data first const retval = new Map(); let i = 0; const [, , , , lup] = response[i]; const [, , , pendingInflator] = response[++i]; // calculate npTpRatio, needed for calculating liquidation bonds // iterate through borrower info, offset by the 3 pool-level requests let borrowerIndex = 0; while (borrowerIndex < borrowerAddresses.length) { const [debt, collateral, t0np, tp] = response[++i]; const kickTimestamp = response[++i][0]; const [, , npTpRatio] = response[++i]; const collateralization = debt.gt(0) ? (0, numeric_1.wdiv)((0, numeric_1.wmul)(collateral, lup), (0, numeric_1.wmul)(debt, constants_1.COLLATERALIZATION_FACTOR)) : (0, numeric_1.toWad)(1); const np = (0, numeric_1.wmul)(t0np, pendingInflator); retval.set(borrowerAddresses[borrowerIndex++], { collateralization, debt, collateral, thresholdPrice: tp, neutralPrice: np, liquidationBond: this.calculateLiquidationBond(npTpRatio, debt), isKicked: !kickTimestamp.eq(ethers_1.BigNumber.from(0)), }); } return retval; }); } /** * @param borrowerAddress identifies the loan under liquidation * @returns {@link Liquidation} models liquidation of a specific loan */ getLiquidation(borrowerAddress) { return new Liquidation_1.Liquidation(this.provider, this.contract, borrowerAddress); } /** * Retrieve statuses for multiple liquidations from the PoolInfoUtils contract. * @param borrowerAddresses identifies loans under liquidation * @returns map of AuctionStatuses, indexed by borrower address */ getLiquidationStatuses(borrowerAddresses) { return tslib_1.__awaiter(this, void 0, void 0, function* () { // assemble calldata for requests const calls = []; for (const loan of borrowerAddresses) { calls.push(this.contractUtilsMulti.auctionStatus(this.poolAddress, loan)); } // perform the multicall const response = yield this.ethcallProvider.all(calls); // prepare return value const retval = new Map(); for (let i = 0; i < response.length; ++i) { const [kickTimestamp, collateral, debtToCover, isCollateralized, price, neutralPrice] = response[i]; retval.set(borrowerAddresses[i], Liquidation_1.Liquidation._prepareAuctionStatus(yield (0, time_1.getBlockTime)(this.provider), kickTimestamp, collateral, debtToCover, isCollateralized, price, neutralPrice)); } return retval; }); } /** * Calculates bond required to liquidate a borrower. * @param npTpRatio relationship between neutral price and threshold price * @param borrowerDebt loan debt * @returns required liquidation bond, in WAD precision */ calculateLiquidationBond(npTpRatio, borrowerDebt) { // bondFactor = min((NP-to-TP-ratio - 1)/10, 0.03) const bondFactor = (0, numeric_1.min)((0, numeric_1.wdiv)(npTpRatio.sub((0, numeric_1.toWad)(1)), (0, numeric_1.toWad)(10)), (0, numeric_1.toWad)(0.03)); // bondSize = bondFactor * borrowerDebt return (0, numeric_1.wmul)(bondFactor, borrowerDebt); } /** * Calculate a loan's neutral price. * @param thresholdPrice loan debt * 1.04 / pledged collateral * @param npTpRatio relationship between neutral price and threshold price * @returns neutral price, in WAD precision */ calculateNeutralPrice(thresholdPrice, npTpRatio) { return (0, numeric_1.min)((0, numeric_1.wmul)(thresholdPrice, npTpRatio), constants_1.MAX_INFLATED_PRICE_WAD); } /** * Calculate neutral price to threshold price approx. "ratio". * @param rate current pool "borrower" interest rate * @returns relationship between the neutral price and threshold price */ calculateNpTpRatio(rate) { return (0, numeric_1.toWad)(1).add((0, numeric_1.wdiv)((0, numeric_1.wsqrt)(rate), (0, numeric_1.toWad)(2))); } /** * Initiates a liquidation of a loan. * @param signer kicker * @param borrowerAddress identifies the loan to liquidate * @param limitIndex reverts if neutral price of loan drops below this bucket before TX processed * @returns promise to transaction */ kick(signer_1, borrowerAddress_1) { return tslib_1.__awaiter(this, arguments, void 0, function* (signer, borrowerAddress, limitIndex = constants_1.MAX_FENWICK_INDEX) { const contractPoolWithSigner = this.contract.connect(signer); return (0, pool_1.kick)(contractPoolWithSigner, borrowerAddress, limitIndex); }); } /** * Checks whether threshold price of a loan is currently above the LUP; * does NOT estimate whether it would be profitable to liquidate the loan. * @param borrowerAddress identifies the loan to check * @returns true if loan may be liquidated, otherwise false */ isKickable(borrowerAddress) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const poolPricesInfoCall = this.contractUtilsMulti.poolPricesInfo(this.poolAddress); const borrowerInfoCall = this.contractUtilsMulti.borrowerInfo(this.poolAddress, borrowerAddress); const response = yield this.ethcallProvider.all([ poolPricesInfoCall, borrowerInfoCall, ]); const [, , , , lup] = response[0]; const [debt, collateral] = response[1]; const tp = collateral.gt(0) ? debt.div(collateral) : ethers_1.BigNumber.from(0); return lup.lte((0, numeric_1.toWad)(tp)); }); } /** * Retrieves status of an auction kicker's liquidation bond. * @param kickerAddress identifies the actor who kicked liquidations */ kickerInfo(kickerAddress) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const [claimable, locked] = yield (0, pool_1.kickerInfo)(this.contract, kickerAddress); return { claimable, locked, }; }); } /** * Called by kickers to withdraw liquidation bond from one or more auctions kicked. * @param signer kicker * @param maxAmount optional amount of bond to withdraw; defaults to all * @returns promise to transaction */ withdrawBonds(signer_1) { return tslib_1.__awaiter(this, arguments, void 0, function* (signer, maxAmount = ethers_1.constants.MaxUint256) { const contractPoolWithSigner = this.contract.connect(signer); const recipient = yield signer.getAddress(); return (0, pool_1.withdrawBonds)(contractPoolWithSigner, recipient, maxAmount); }); } /** * Estimates how drawing more debt and/or pledging more collateral would impact loan. * @param borrowerAddress identifies the loan * @param debtAmount additional amount of debt to draw (or 0) * @param collateralAmount additional amount of collateral to pledge (or 0) * @returns {@link LoanEstimate} */ estimateLoan(borrowerAddress, debtAmount, collateralAmount) { return tslib_1.__awaiter(this, void 0, void 0, function* () { // obtain the borrower debt, and origination fee const borrowerInfoCall = this.contractUtilsMulti.borrowerInfo(this.poolAddress, borrowerAddress); const origFeeCall = this.contractUtilsMulti.borrowFeeRate(this.poolAddress); let response = yield this.ethcallProvider.all([ borrowerInfoCall, origFeeCall, ]); const [borrowerDebt, collateral] = response[0]; const originationFeeRate = ethers_1.BigNumber.from(response[1]); debtAmount = debtAmount.add((0, numeric_1.wmul)(debtAmount, originationFeeRate)); // determine pool debt let [poolDebt] = yield (0, pool_1.debtInfo)(this.contract); // determine where this would push the LUP, the current interest rate, and loan count poolDebt = poolDebt.add(debtAmount); const lupIndexCall = this.contractMulti.depositIndex(poolDebt); const rateCall = this.contractMulti.interestRateInfo(); const loansInfoCall = this.contractMulti.loansInfo(); const totalAuctionsInPoolCall = this.contractMulti.totalAuctionsInPool(); response = yield this.ethcallProvider.all([ lupIndexCall, rateCall, loansInfoCall, totalAuctionsInPoolCall, ]); const lupIndex = +response[0]; const rate = ethers_1.BigNumber.from(response[1][0]); let noOfLoans = +response[2][2]; const noOfAuctions = +response[3]; noOfLoans += noOfAuctions; const lup = (0, pricing_1.indexToPrice)(lupIndex); // calculate the new amount of debt and collateralization const newDebt = borrowerDebt.add(debtAmount); const newCollateral = collateral.add(collateralAmount); const zero = ethers_1.constants.Zero; const thresholdPrice = newCollateral.eq(zero) ? zero : (0, numeric_1.wmul)((0, numeric_1.wdiv)(newDebt, newCollateral), constants_1.COLLATERALIZATION_FACTOR); const encumbered = lup.eq(zero) ? zero : (0, numeric_1.wmul)((0, numeric_1.wdiv)(newDebt, lup), constants_1.COLLATERALIZATION_FACTOR); const collateralization = encumbered.eq(zero) ? (0, numeric_1.toWad)(1) : (0, numeric_1.wdiv)(newCollateral, encumbered); // calculate the hypothetical neutral price const npTpRatio = this.calculateNpTpRatio(rate); const neutralPrice = this.calculateNeutralPrice(thresholdPrice, npTpRatio); return { collateralization, debt: newDebt, collateral: newCollateral, thresholdPrice, neutralPrice, isKicked: collateralization.lt(ethers_1.constants.One), liquidationBond: this.calculateLiquidationBond(npTpRatio, newDebt), lup: (0, pricing_1.indexToPrice)(lupIndex), lupIndex: lupIndex, }; }); } /** * Estimates how repaying debt and/or pulling collateral would impact loan. * @param borrowerAddress identifies the loan * @param debtAmount amount of debt to repay (or 0) * @param collateralAmount amount of collateral to pull (or 0) * @returns {@link LoanEstimate} */ estimateRepay(borrowerAddress, debtAmount, collateralAmount) { return tslib_1.__awaiter(this, void 0, void 0, function* () { // obtain the borrower debt const utilsContract = (0, pool_info_utils_1.getPoolInfoUtilsContract)(this.provider); const [borrowerDebt, collateral] = yield (0, pool_info_utils_1.borrowerInfo)(utilsContract, this.poolAddress, borrowerAddress); // determine pool debt const [poolDebt, ,] = yield (0, pool_1.debtInfo)(this.contract); // determine where this would push the LUP, the current interest rate, and loan count const lupIndexCall = this.contractMulti.depositIndex(poolDebt.sub(debtAmount)); const rateCall = this.contractMulti.interestRateInfo(); const loansInfoCall = this.contractMulti.loansInfo(); const totalAuctionsInPoolCall = this.contractMulti.totalAuctionsInPool(); const response = yield this.ethcallProvider.all([ lupIndexCall, rateCall, loansInfoCall, totalAuctionsInPoolCall, ]); const lupIndex = +response[0]; const rate = ethers_1.BigNumber.from(response[1][0]); let noOfLoans = +response[1][2]; const noOfAuctions = +response[2]; noOfLoans += noOfAuctions; const lup = (0, pricing_1.indexToPrice)(lupIndex); const zero = ethers_1.constants.Zero; // calculate the new amount of debt and collateralization const newDebt = borrowerDebt.sub(debtAmount).isNegative() ? zero : borrowerDebt.sub(debtAmount); const newCollateral = collateral.sub(collateralAmount).isNegative() ? zero : collateral.sub(collateralAmount); const thresholdPrice = newCollateral.eq(zero) ? zero : (0, numeric_1.wdiv)((0, numeric_1.wmul)(newDebt, constants_1.COLLATERALIZATION_FACTOR), newCollateral); const encumbered = lup.eq(zero) ? zero : (0, numeric_1.wdiv)((0, numeric_1.wmul)(newDebt, constants_1.COLLATERALIZATION_FACTOR), lup); const collateralization = encumbered.eq(zero) ? (0, numeric_1.toWad)(1) : (0, numeric_1.wdiv)(newCollateral, encumbered); // calculate the hypothetical neutral price const npTpRatio = this.calculateNpTpRatio(rate); const neutralPrice = this.calculateNeutralPrice(thresholdPrice, npTpRatio); return { collateralization, debt: newDebt, collateral: newCollateral, thresholdPrice, neutralPrice, isKicked: collateralization.lt(ethers_1.constants.One), liquidationBond: this.calculateLiquidationBond(npTpRatio, newDebt), lup: (0, pricing_1.indexToPrice)(lupIndex), lupIndex: lupIndex, }; }); } /** * Determines whether interest rate will increase, decrease, or remain the same as a result of * updating the interest rate, without regard to the 12-hour rate update interval. * @param poolStats pool statistics obtained from @link{Pool.getStats} */ estimateUpdateInterest(poolStats) { // calculating as numbers because squaring a WAD is complicated const mau = +(0, numeric_1.fromWad)(poolStats.actualUtilization); const mau102 = mau * 1.02; const tu = +(0, numeric_1.fromWad)(poolStats.targetUtilization); if (4 * (tu - mau102) < Math.pow((tu + mau102 - 1), 2) - 1) { // raise rates return (0, numeric_1.wmul)(poolStats.borrowRate, (0, numeric_1.toWad)('1.1')); } else if (4 * (tu - mau) > 1 - Math.pow((tu + mau - 1), 2)) { // lower rates return (0, numeric_1.wmul)(poolStats.borrowRate, (0, numeric_1.toWad)('0.9')); } else { // rates remain unchanged return poolStats.borrowRate; } } /** * May be called periodically by actors to adjust interest rate if no other TXes have occurred * in the past 12 hours. * @param signer actor who wants to update the interest rate * @returns transaction */ updateInterest(signer) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const contractPoolWithSigner = this.contract.connect(signer); return (0, pool_1.updateInterest)(contractPoolWithSigner); }); } /** * Updates the neutral price of a borrower's own loan, often useful after partial repayment. * @param borrower borrower who wishes to stamp their own loan */ stampLoan(signer) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const contractPoolWithSigner = this.contract.connect(signer); return (0, pool_1.stampLoan)(contractPoolWithSigner); }); } /** * Returns `Claimable Reserve Auction` (`CRA`) wrapper object. * @returns CRA wrapper object */ getClaimableReserveAuction() { return new ClaimableReserveAuction_1.ClaimableReserveAuction(this.provider, this.contract, this.poolInfoContractUtils, this.poolAddress); } /** * Create a new empty LP token for the purpose of memorializing lender position(s). * @param signer lender * @param subset optional subset of NFT ids in pool * @returns promise to transaction */ mintLPToken(signer, subset) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const subsetHash = subset ? (0, erc721_pool_factory_1.getSubsetHash)(subset.map(val => ethers_1.BigNumber.from(val))) : constants_1.ERC20_NON_SUBSET_HASH; return (0, position_manager_1.mint)(signer, yield signer.getAddress(), this.poolAddress, subsetHash); }); } /** * Burn an empty LP token which has already been redeemed for LP in all buckets. * @param signer LP token holder * @param tokenId identifies the empty token to burn * @returns promise to transaction */ burnLPToken(signer, tokenId) { return tslib_1.__awaiter(this, void 0, void 0, function* () { return (0, position_manager_1.burn)(signer, tokenId, this.poolAddress); }); } approvePositionManagerLPTransferor(signer) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const addr = (0, position_manager_1.getPositionManagerContract)(signer).address; return (0, pool_1.approveLPTransferors)(signer, this.contract, [addr]); }); } /** * Approve lend helper to manage quote token. * @param signer pool user * @param allowance normalized approval amount (or MaxUint256) * @returns promise to transaction */ quoteApproveHelper(signer, allowance) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const denormalizedAllowance = allowance.eq(ethers_1.constants.MaxUint256) ? allowance : allowance.div(yield (0, pool_1.quoteTokenScale)(this.contract)); return (0, erc20_pool_1.approve)(signer, this.lenderHelper.address, this.quoteAddress, denormalizedAllowance); }); } approveLenderHelperLPTransferor(signer) { return tslib_1.__awaiter(this, void 0, void 0, function* () { return (0, pool_1.approveLPTransferors)(signer, this.contract, [this.lenderHelper.address]); }); } isLenderHelperLPTransferorApproved(signer) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const signerAddress = yield signer.getAddress(); return yield this.contract.approvedTransferors(signerAddress, this.lenderHelper.address); }); } increaseLenderHelperLPAllowance(signer, indexes, amounts) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (indexes.length !== amounts.length) { throw new types_1.SdkError('indexes and amounts must be same length'); } const poolWithSigner = this.contract.connect(signer); return (0, pool_1.increaseLPAllowance)(poolWithSigner, this.lenderHelper.address, indexes, amounts); }); } isLPTransferorApproved(signer) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const transferor = (0, position_manager_1.getPositionManagerContract)(signer).address; const signerAddress = yield signer.getAddress(); return yield this.contract.approvedTransferors(signerAddress, transferor); }); } revokePositionManagerLPTransferor(signer) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const addr = (0, position_manager_1.getPositionManagerContract)(signer).address; return (0, pool_1.revokeLPTransferors)(signer, this.contract, [addr]); }); } } exports.Pool = Pool; //# sourceMappingURL=Pool.js.map