diff --git a/src/actions/borrow.tsx b/src/actions/borrow.tsx index df442b2..3fdb2d1 100644 --- a/src/actions/borrow.tsx +++ b/src/actions/borrow.tsx @@ -56,6 +56,11 @@ export const borrow = async ( let instructions: TransactionInstruction[] = []; let cleanupInstructions: TransactionInstruction[] = []; + const [authority] = await PublicKey.findProgramAddress( + [depositReserve.info.lendingMarket.toBuffer()], + LENDING_PROGRAM_ID + ); + const accountRentExempt = await connection.getMinimumBalanceForRentExemption(AccountLayout.span); const obligation = existingObligation @@ -90,6 +95,35 @@ export const borrow = async ( signers ); + if (!obligationAccount) { + instructions.push( + initObligationInstruction( + depositReserve.pubkey, + borrowReserve.pubkey, + obligation, + obligationMint, + obligationTokenOutput, + wallet.publicKey, + depositReserve.info.lendingMarket, + authority, + ) + ); + } + + // Creates host fee account if it doesn't exsist + let hostFeeReceiver = LEND_HOST_FEE_ADDRESS + ? findOrCreateAccountByMint( + wallet.publicKey, + LEND_HOST_FEE_ADDRESS, + instructions, + cleanupInstructions, + accountRentExempt, + depositReserve.info.collateralMint, + signers + ) + : undefined; + + if (instructions.length > 0) { // create all accounts in one transaction let tx = await sendTransaction(connection, wallet, instructions, [...signers]); @@ -111,11 +145,6 @@ export const borrow = async ( instructions = []; cleanupInstructions = []; - const [authority] = await PublicKey.findProgramAddress( - [depositReserve.info.lendingMarket.toBuffer()], - LENDING_PROGRAM_ID - ); - let amountLamports: number = 0; let fromLamports: number = 0; if (amountType === BorrowAmountType.LiquidityBorrowAmount) { @@ -173,34 +202,6 @@ export const borrow = async ( const memory = createTempMemoryAccount(instructions, wallet.publicKey, signers, LENDING_PROGRAM_ID); - // Creates host fee account if it doesn't exsist - let hostFeeReceiver = LEND_HOST_FEE_ADDRESS - ? findOrCreateAccountByMint( - wallet.publicKey, - LEND_HOST_FEE_ADDRESS, - instructions, - cleanupInstructions, - accountRentExempt, - depositReserve.info.collateralMint, - signers - ) - : undefined; - - if (!obligationAccount) { - instructions.push( - initObligationInstruction( - depositReserve.pubkey, - borrowReserve.pubkey, - obligation, - obligationMint, - obligationTokenOutput, - wallet.publicKey, - depositReserve.info.lendingMarket, - authority, - ) - ); - } - // borrow instructions.push( borrowInstruction( @@ -239,8 +240,8 @@ export const borrow = async ( type: 'success', description: `Transaction - ${tx}`, }); - } catch { - // TODO: + } catch (ex) { + console.error(ex) throw new Error(); } }; diff --git a/src/models/lending/borrow.ts b/src/models/lending/borrow.ts index ab740c4..de71b64 100644 --- a/src/models/lending/borrow.ts +++ b/src/models/lending/borrow.ts @@ -17,7 +17,7 @@ export enum BorrowAmountType { /// 0. `[writable]` Source collateral token account, minted by deposit reserve collateral mint, /// $authority can transfer $collateral_amount /// 1. `[writable]` Destination liquidity token account, minted by borrow reserve liquidity mint -/// 2. `[writable]` Deposit reserve account. +/// 2. `[]` Deposit reserve account. /// 3. `[writable]` Deposit reserve collateral supply SPL Token account /// 4. `[writable]` Borrow reserve account. /// 5. `[writable]` Borrow reserve liquidity supply SPL Token account @@ -78,7 +78,7 @@ export const borrowInstruction = ( const keys = [ { pubkey: from, isSigner: false, isWritable: true }, { pubkey: to, isSigner: false, isWritable: true }, - { pubkey: depositReserve, isSigner: false, isWritable: true }, + { pubkey: depositReserve, isSigner: false, isWritable: false }, { pubkey: depositReserveCollateralSupply, isSigner: false, diff --git a/src/models/lending/lending.ts b/src/models/lending/lending.ts index 07206b9..e6c4334 100644 --- a/src/models/lending/lending.ts +++ b/src/models/lending/lending.ts @@ -7,4 +7,5 @@ export enum LendingInstruction { BorrowLiquidity = 5, RepayOblogationLiquidity = 6, LiquidateObligation = 7, + AccrueReserveInterest = 8, } diff --git a/src/models/lending/liquidate.ts b/src/models/lending/liquidate.ts index 7e55e80..386dea6 100644 --- a/src/models/lending/liquidate.ts +++ b/src/models/lending/liquidate.ts @@ -10,7 +10,7 @@ import { TOKEN_PROGRAM_ID, LENDING_PROGRAM_ID } from '../../utils/ids'; /// 0. `[writable]` Source liquidity token account, minted by repay reserve liquidity mint /// $authority can transfer $collateral_amount /// 1. `[writable]` Destination collateral token account, minted by withdraw reserve collateral mint -/// 2. `[writable]` Repay reserve account. +/// 2. `[]` Repay reserve account. /// 3. `[writable]` Repay reserve liquidity supply SPL Token account /// 4. `[writable]` Withdraw reserve account. /// 5. `[writable]` Withdraw reserve collateral supply SPL Token account @@ -57,7 +57,7 @@ export const liquidateInstruction = ( { pubkey: repayReserveAccount, isSigner: false, isWritable: true }, { pubkey: repayReserveLiquiditySupply, isSigner: false, isWritable: true }, - { pubkey: withdrawReserve, isSigner: false, isWritable: true }, + { pubkey: withdrawReserve, isSigner: false, isWritable: false }, { pubkey: withdrawReserveCollateralSupply, isSigner: false, diff --git a/src/models/lending/obligation.ts b/src/models/lending/obligation.ts index e238e58..567620f 100644 --- a/src/models/lending/obligation.ts +++ b/src/models/lending/obligation.ts @@ -63,6 +63,19 @@ export const healthFactorToRiskColor = (health: number) => { return ''; } +/// Initializes a new loan obligation. +/// /// +/// 0. `[]` Deposit reserve account. /// 0. `[]` Deposit reserve account. +/// 1. `[writable]` Borrow reserve account. /// 1. `[]` Borrow reserve account. +/// 2. `[writable]` Obligation /// 2. `[writable]` Obligation +/// 3. `[writable]` Obligation token mint /// 3. `[writable]` Obligation token mint +/// 4. `[writable]` Obligation token output /// 4. `[writable]` Obligation token output +/// 5. `[]` Obligation token owner /// 5. `[]` Obligation token owner +/// 6. `[]` Lending market account. /// 6. `[]` Lending market account. +/// 7. `[]` Derived lending market authority. /// 7. `[]` Derived lending market authority. +/// 8. `[]` Clock sysvar /// 8. `[]` Clock sysvar +/// 9. `[]` Rent sysvar /// 9. `[]` Rent sysvar +/// 10 '[]` Token program id /// 10 '[]` Token program id export const initObligationInstruction = ( depositReserve: PublicKey, borrowReserve: PublicKey, @@ -89,8 +102,8 @@ export const initObligationInstruction = ( ); const keys = [ - { pubkey: depositReserve, isSigner: false, isWritable: true }, - { pubkey: borrowReserve, isSigner: false, isWritable: true }, + { pubkey: depositReserve, isSigner: false, isWritable: false }, + { pubkey: borrowReserve, isSigner: false, isWritable: false }, { pubkey: obligation, isSigner: false, isWritable: true }, { pubkey: obligationMint, isSigner: false, isWritable: true }, { pubkey: obligationTokenOutput, isSigner: false, isWritable: true }, diff --git a/src/models/lending/reserve.ts b/src/models/lending/reserve.ts index 6356f70..4bf053e 100644 --- a/src/models/lending/reserve.ts +++ b/src/models/lending/reserve.ts @@ -204,6 +204,32 @@ export const initReserveInstruction = ( }); }; +export const accrueInterestInstruction = ( + reserveAccount: PublicKey[], +): TransactionInstruction => { + const dataLayout = BufferLayout.struct([ + BufferLayout.u8('instruction'), + ]); + + const data = Buffer.alloc(dataLayout.span); + dataLayout.encode( + { + instruction: LendingInstruction.AccrueReserveInterest, + }, + data + ); + + const keys = [ + { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, + ...reserveAccount.map(reserve => ({ pubkey: reserve, isSigner: false, isWritable: true })) + ]; + return new TransactionInstruction({ + keys, + programId: LENDING_PROGRAM_ID, + data, + }); +}; + export const calculateUtilizationRatio = (reserve: LendingReserve) => { const totalBorrows = wadToLamports(reserve.state.borrowedLiquidityWad).toNumber(); const currentUtilization = totalBorrows / (reserve.state.availableLiquidity.toNumber() + totalBorrows);