Skip to content

Commit

Permalink
option to include additional interest in net rate and yield calculati…
Browse files Browse the repository at this point in the history
…ons (#76)

* option to include xalgo staking apr in net rate and yield calculations

* fix import

* subtract xalgo staking apr if borrow

* generalise

* fix changeset comment
  • Loading branch information
gidonkatten authored Jan 5, 2025
1 parent 03b3261 commit 03313b7
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 3 deletions.
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

0 comments on commit 03313b7

Please sign in to comment.