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

v2.0.2 fixes #55

Merged
merged 1 commit into from
Jul 25, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import BigNumber from 'bignumber.js';
import styles from './ReserveStats.module.scss';
import classNames from 'classnames';
import { ChevronDownIcon, ChevronUpIcon, CopyIcon } from '@chakra-ui/icons';
import { computeExtremeRates } from '@solendprotocol/solend-sdk';
import { useAtom } from 'jotai';
import humanizeDuration from 'humanize-duration';
import { SLOT_RATE } from 'utils/utils';
Expand Down Expand Up @@ -213,11 +212,7 @@ function ReserveStats({
<Metric
row
label='Target borrow APR'
value={formatPercent(
reserve.maxBorrowApr === reserve.targetBorrowApr
? computeExtremeRates(reserve.targetBorrowApr)
: reserve.targetBorrowApr,
)}
value={formatPercent(reserve.targetBorrowApr)}
tooltip='When utilization is equal to the target utilization, borrow APR will be this value.'
/>
<Metric
Expand All @@ -235,9 +230,7 @@ function ReserveStats({
row
label='Max borrow APR'
value={formatPercent(
reserve.maxBorrowApr === reserve.targetBorrowApr
? computeExtremeRates(reserve.maxBorrowApr)
: reserve.maxBorrowApr,
reserve.maxBorrowApr,
)}
tooltip='Maximum possible borrow APR.'
/>
Expand All @@ -251,9 +244,7 @@ function ReserveStats({
row
label='Supermax borrow APR'
value={formatPercent(
reserve.maxBorrowApr === reserve.targetBorrowApr
? computeExtremeRates(reserve.maxBorrowApr)
: reserve.maxBorrowApr,
reserve.superMaxBorrowRate
)}
tooltip='Maximum possible borrow APR.'
/>
Expand Down
9 changes: 2 additions & 7 deletions solend-lite/src/stores/pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
getReservesOfPool,
parseLendingMarket,
parseRateLimiter,
PoolType,
} from '@solendprotocol/solend-sdk';
import { DEBUG_MODE, PROGRAM_ID } from 'common/config';
import { atomWithRefresh } from './shared';
Expand All @@ -33,13 +34,6 @@ export type SelectedReserveType = ReserveType & {
logo: string | null;
};

export type PoolType = {
name: string | null;
address: string;
authorityAddress: string;
reserves: Array<ReserveType>;
};

export type SelectedPoolType = {
name: string | null;
address: string;
Expand Down Expand Up @@ -67,6 +61,7 @@ export const poolsAtom = atomWithDefault<{ [address: string]: PoolType }>(
name: pool.name,
authorityAddress: pool.authorityAddress,
address: pool.address,
owner: pool.owner,
reserves: [] as Array<ReserveType>,
},
]),
Expand Down
2 changes: 1 addition & 1 deletion solend-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@solendprotocol/solend-sdk",
"version": "0.6.16",
"version": "0.6.20",
"private": true,
"main": "src/index.ts",
"module": "src/index.ts",
Expand Down
49 changes: 46 additions & 3 deletions solend-sdk/src/core/action/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
syncNative,
depositObligationCollateralInstruction,
withdrawObligationCollateralInstruction,
forgiveDebtInstruction,
} from "../../instructions";
import { POSITION_LIMIT } from "../constants";
import { EnvironmentType, PoolType, ReserveType } from "../types";
Expand All @@ -49,7 +50,8 @@ export type ActionType =
| "mint"
| "redeem"
| "depositCollateral"
| "withdrawCollateral";
| "withdrawCollateral"
| "forgive";

export class SolendActionCore {
programId: PublicKey;
Expand Down Expand Up @@ -139,12 +141,13 @@ export class SolendActionCore {
publicKey: PublicKey,
connection: Connection,
environment: EnvironmentType = "production",
customObligationAddress?: PublicKey,
hostAta?: PublicKey
) {
const seed = pool.address.slice(0, 32);
const programId = getProgramId(environment);

const obligationAddress = await PublicKey.createWithSeed(
const obligationAddress = customObligationAddress ?? await PublicKey.createWithSeed(
publicKey,
seed,
programId
Expand Down Expand Up @@ -228,6 +231,32 @@ export class SolendActionCore {
);
}

static async buildForgiveTxns(
pool: PoolType,
reserve: ReserveType,
connection: Connection,
amount: string,
publicKey: PublicKey,
obligationAddress: PublicKey,
environment: EnvironmentType = "production"
) {
const axn = await SolendActionCore.initialize(
pool,
reserve,
"deposit",
new BN(amount),
publicKey,
connection,
environment,
obligationAddress
);

await axn.addSupportIxs("forgive");
await axn.addForgiveIx();

return axn
}

static async buildDepositTxns(
pool: PoolType,
reserve: ReserveType,
Expand Down Expand Up @@ -269,6 +298,7 @@ export class SolendActionCore {
publicKey,
connection,
environment,
undefined,
hostAta
);

Expand Down Expand Up @@ -499,6 +529,19 @@ export class SolendActionCore {
return signature;
}

addForgiveIx() {
this.lendingIxs.push(
forgiveDebtInstruction(
this.obligationAddress,
new PublicKey(this.reserve.address),
new PublicKey(this.pool.address),
new PublicKey(this.pool.owner),
this.amount,
this.programId
)
);
}

addDepositIx() {
this.lendingIxs.push(
depositReserveLiquidityAndObligationCollateralInstruction(
Expand Down Expand Up @@ -707,7 +750,7 @@ export class SolendActionCore {
}

async addSupportIxs(action: ActionType) {
if (["withdraw", "borrow", "withdrawCollateral"].includes(action)) {
if (["withdraw", "borrow", "withdrawCollateral", "forgive"].includes(action)) {
await this.addRefreshIxs();
}
if (!["mint", "redeem"].includes(action)) {
Expand Down
1 change: 1 addition & 0 deletions solend-sdk/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type PoolType = {
name: string | null;
address: string;
authorityAddress: string;
owner: string;
reserves: Array<ReserveType>;
};

Expand Down
1 change: 1 addition & 0 deletions solend-sdk/src/core/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./utils";
export * from "./pools";
export * from "./obligations";
export * from "./wallet";
export * from "./rates";
42 changes: 6 additions & 36 deletions solend-sdk/src/core/utils/rates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,16 @@ const calculateBorrowAPR = (reserve: Reserve) => {
);
const maxBorrowRate = new BigNumber(reserve.config.maxBorrowRate / 100);

borrowAPR = weight.times(maxBorrowRate.minus(optimalBorrowRate)).plus(optimalBorrowRate)
borrowAPR = weight
.times(maxBorrowRate.minus(optimalBorrowRate))
.plus(optimalBorrowRate)
} else {
const weight = currentUtilization
.minus(optimalUtilization)
.dividedBy(maxUtilizationRate.minus(optimalUtilization));
.minus(maxUtilizationRate)
.dividedBy(new BigNumber(100).minus(maxUtilizationRate));

const maxBorrowRate = new BigNumber(reserve.config.maxBorrowRate / 100)
const superMaxBorrowRate = new BigNumber(reserve.config.superMaxBorrowRate.toString()).dividedBy(100);
const superMaxBorrowRate = new BigNumber(reserve.config.superMaxBorrowRate / 100);

borrowAPR = weight
.times(superMaxBorrowRate.minus(maxBorrowRate))
Expand Down Expand Up @@ -106,35 +108,3 @@ export const calculateSupplyInterest = (reserve: Reserve, showApy: boolean) =>

export const calculateBorrowInterest = (reserve: Reserve, showApy: boolean) =>
showApy ? calculateBorrowAPY(reserve) : calculateBorrowAPR(reserve);

export function computeExtremeRates(configRate: number) {
const rate = 0.5;
let cleanRate = configRate;

if (configRate >= 2.47) {
cleanRate = Number(configRate.toString().replace(".", ""));
}

switch (cleanRate) {
case 251:
return rate * 6;
case 252:
return rate * 7;
case 253:
return rate * 8;
case 254:
return rate * 10;
case 255:
return rate * 12;
case 250:
return rate * 20;
case 249:
return rate * 30;
case 248:
return rate * 40;
case 247:
return rate * 50;
default:
return cleanRate;
}
}
32 changes: 0 additions & 32 deletions solend-sdk/src/core/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,35 +124,3 @@ export async function createObligationAddress(
)
).toBase58();
}

export function computeExtremeRates(configRate: number) {
const rate = 0.5;
let cleanRate = configRate;

if (configRate >= 2.47) {
cleanRate = Number(configRate.toString().replace(".", ""));
}

switch (cleanRate) {
case 251:
return rate * 6;
case 252:
return rate * 7;
case 253:
return rate * 8;
case 254:
return rate * 10;
case 255:
return rate * 12;
case 250:
return rate * 20;
case 249:
return rate * 30;
case 248:
return rate * 40;
case 247:
return rate * 50;
default:
return cleanRate;
}
}
9 changes: 5 additions & 4 deletions solend-sdk/src/instructions/forgiveDebt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import * as BufferLayout from "buffer-layout";
import * as Layout from "../utils/layout";
import { LendingInstruction } from "./instruction";
import BN from "bn.js";

export const ForgiveDebtInstruction = (
export const forgiveDebtInstruction = (
obligation: PublicKey,
reserve: PublicKey,
lendingMarket: PublicKey,
lendingMarketOwner: PublicKey,
liquidityAmount: number,
liquidityAmount: number | BN,
lendingProgramId: PublicKey
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([
Expand All @@ -19,8 +20,8 @@ export const ForgiveDebtInstruction = (
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: LendingInstruction.SetLendingMarketOwnerAndConfig,
liquidityAmount: liquidityAmount,
instruction: LendingInstruction.ForgiveDebt,
liquidityAmount: new BN(liquidityAmount),
},
data
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { LendingInstruction } from "./instruction";
///
/// 0. `[writable]` Lending market account.
/// 1. `[signer]` Current owner.
export const SetLendingMarketOwnerAndConfigInstruction = (
export const setLendingMarketOwnerAndConfigInstruction = (
lendingMarket: PublicKey,
currentMarketOwner: PublicKey,
newMarketOwner: PublicKey,
Expand Down