Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

option to include additional interest in net rate and yield calculations #76

Merged
merged 5 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dirty-waves-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@folks-finance/algorand-sdk": patch
---

option to include additional interest in net rate and yield calculations
12 changes: 10 additions & 2 deletions src/lend/loan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { getOraclePrices, prepareRefreshPricesInOracleAdapter } from "./oracle";
import { getEscrows, loanLocalState, userLoanInfo } from "./utils";

import type {
AssetsAdditionalInterest,
LoanInfo,
LoanLocalState,
LPToken,
Expand Down Expand Up @@ -146,6 +147,7 @@ async function retrieveLoanLocalState(
* @param poolManagerAppId - pool manager application to query about
* @param oracle - oracle to query
* @param userAddr - account address for the user
* @param additionalInterests - optional additional interest to consider in loan net rate/yield
* @returns Promise<UserLoanInfo[]> user loans infos
*/
async function retrieveUserLoansInfo(
Expand All @@ -154,6 +156,7 @@ async function retrieveUserLoansInfo(
poolManagerAppId: number,
oracle: Oracle,
userAddr: string,
additionalInterests?: AssetsAdditionalInterest,
): Promise<UserLoanInfo[]> {
const userLoanInfos: UserLoanInfo[] = [];

Expand All @@ -178,7 +181,10 @@ async function retrieveUserLoansInfo(
);
if (state === undefined) throw Error(`Could not find loan ${loanAppId} in escrow ${escrowAddr}`);
const localState = loanLocalState(state, loanAppId, escrowAddr);
userLoanInfos.push({ ...userLoanInfo(localState, poolManagerInfo, loanInfo, oraclePrices), currentRound });
userLoanInfos.push({
...userLoanInfo(localState, poolManagerInfo, loanInfo, oraclePrices, additionalInterests),
currentRound,
});
}

return userLoanInfos;
Expand All @@ -193,6 +199,7 @@ async function retrieveUserLoansInfo(
* @param poolManagerAppId - pool manager application to query about
* @param oracle - oracle to query
* @param escrowAddr - account address for the loan escrow
* @param additionalInterests - optional additional interest to consider in loan net rate/yield
* @returns Promise<UserLoanInfo> user loan info
*/
async function retrieveUserLoanInfo(
Expand All @@ -201,6 +208,7 @@ async function retrieveUserLoanInfo(
poolManagerAppId: number,
oracle: Oracle,
escrowAddr: string,
additionalInterests?: AssetsAdditionalInterest,
): Promise<UserLoanInfo> {
// get all prerequisites
const loanInfoReq = retrieveLoanInfo(client, loanAppId);
Expand All @@ -212,7 +220,7 @@ async function retrieveUserLoanInfo(
const { currentRound, localState: state } = await getAccountApplicationLocalState(client, loanAppId, escrowAddr);
if (state === undefined) throw Error(`Could not find loan ${loanAppId} in escrow ${escrowAddr}`);
const localState = loanLocalState(state, loanAppId, escrowAddr);
return { ...userLoanInfo(localState, poolInfo, loanInfo, oraclePrices), currentRound };
return { ...userLoanInfo(localState, poolInfo, loanInfo, oraclePrices, additionalInterests), currentRound };
}

/**
Expand Down
9 changes: 9 additions & 0 deletions src/lend/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,13 @@ interface UserLoanInfo {
liquidationMargin: bigint; // 4 d.p.
}

interface AssetAdditionalInterest {
rateBps: bigint; // 4 d.p.
yieldBps: bigint; // 4 d.p.
}

type AssetsAdditionalInterest = Partial<Record<number, AssetAdditionalInterest>>; // assetId -> interest

interface Oracle {
oracle0AppId: number;
oracle1AppId?: number;
Expand Down Expand Up @@ -397,6 +404,8 @@ export {
UserLoanInfoCollateral,
UserLoanInfoBorrow,
UserLoanInfo,
AssetAdditionalInterest,
AssetsAdditionalInterest,
Oracle,
OraclePrice,
OraclePrices,
Expand Down
30 changes: 29 additions & 1 deletion src/lend/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { encodeAddress, getApplicationAddress } from "algosdk";

import { compoundEverySecond, maximum, mulScale, ONE_10_DP, ONE_16_DP, ONE_4_DP, SECONDS_IN_YEAR } from "../math-lib";
import {
compoundEverySecond,
maximum,
mulScale,
ONE_10_DP,
ONE_12_DP,
ONE_16_DP,
ONE_4_DP,
SECONDS_IN_YEAR,
} from "../math-lib";
import { enc, fromIntToByteHex, getParsedValueFromState, parseUint64s, unixTime } from "../utils";

import {
Expand All @@ -15,6 +24,7 @@ import {
} from "./formulae";

import type {
AssetsAdditionalInterest,
DepositStakingInfo,
DepositStakingProgramInfo,
LoanInfo,
Expand Down Expand Up @@ -359,13 +369,15 @@ export function loanLocalState(state: TealKeyValue[], loanAppId: number, escrowA
* @param poolManagerInfo - pool manager info which is returned by retrievePoolManagerInfo function
* @param loanInfo - loan info which is returned by retrieveLoanInfo function
* @param oraclePrices - oracle prices which is returned by getOraclePrices function
* @param additionalInterests - optional additional interest to consider in loan net rate/yield
* @returns Promise<UserLoansInfo> user loans info
*/
export function userLoanInfo(
localState: LoanLocalState,
poolManagerInfo: PoolManagerInfo,
loanInfo: LoanInfo,
oraclePrices: OraclePrices,
additionalInterests?: AssetsAdditionalInterest,
): UserLoanInfo {
const { pools: poolManagerPools } = poolManagerInfo;
const { pools: loanPools } = loanInfo;
Expand Down Expand Up @@ -403,6 +415,14 @@ export function userLoanInfo(
netRate += balanceValue * depositInterestRate;
netYield += balanceValue * depositInterestYield;

// add additional interests if specified
if (additionalInterests && additionalInterests[assetId]) {
const { rateBps, yieldBps } = additionalInterests[assetId];
// multiply by 1e12 to standardise at 16 d.p.
netRate += balanceValue * rateBps * ONE_12_DP;
netYield += balanceValue * yieldBps * ONE_12_DP;
}

collaterals.push({
poolAppId,
assetId,
Expand Down Expand Up @@ -463,6 +483,14 @@ export function userLoanInfo(
netRate -= borrowBalanceValue * interestRate;
netYield -= borrowBalanceValue * interestYield;

// subtracts additional interests if specified
if (additionalInterests && additionalInterests[assetId]) {
const { rateBps, yieldBps } = additionalInterests[assetId];
// multiply by 1e12 to standardise at 16 d.p.
netRate -= borrowBalanceValue * rateBps * ONE_12_DP;
netYield -= borrowBalanceValue * yieldBps * ONE_12_DP;
}

borrows.push({
poolAppId,
assetId,
Expand Down
2 changes: 2 additions & 0 deletions src/math-lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const HOURS_IN_YEAR = BigInt(365 * 24);
const ONE_2_DP = BigInt(1e2);
const ONE_4_DP = BigInt(1e4);
const ONE_10_DP = BigInt(1e10);
const ONE_12_DP = BigInt(1e12);
const ONE_14_DP = BigInt(1e14);
const ONE_16_DP = BigInt(1e16);

Expand Down Expand Up @@ -81,6 +82,7 @@ export {
HOURS_IN_YEAR,
ONE_16_DP,
ONE_14_DP,
ONE_12_DP,
ONE_10_DP,
ONE_4_DP,
ONE_2_DP,
Expand Down
Loading