diff --git a/src/models/lending/depositObligationCollateral.ts b/src/models/lending/depositObligationCollateral.ts new file mode 100644 index 0000000..44ca3a5 --- /dev/null +++ b/src/models/lending/depositObligationCollateral.ts @@ -0,0 +1,67 @@ +import { + PublicKey, + TransactionInstruction, +} from "@solana/web3.js"; +import BN from "bn.js"; +import * as BufferLayout from "buffer-layout"; +import { TOKEN_PROGRAM_ID, LENDING_PROGRAM_ID } from "../../utils/ids"; +import * as Layout from "./../../utils/layout"; +import { LendingInstruction } from "./lending"; + +/// Deposit additional collateral to an obligation. +/// +/// 0. `[writable]` Source collateral token account, minted by deposit reserve collateral mint, +/// $authority can transfer $collateral_amount +/// 1. `[writable]` Destination deposit reserve collateral supply SPL Token account +/// 2. `[]` Deposit reserve account. +/// 3. `[writable]` Obligation +/// 4. `[writable]` Obligation token mint +/// 5. `[writable]` Obligation token output +/// 6. `[]` Lending market account. +/// 7. `[]` Derived lending market authority. +/// 8. `[]` User transfer authority ($authority). +/// 9. '[]` Token program id +export const depositObligationCollateralInstruction = ( + collateralAmount: number | BN, + from: PublicKey, + to: PublicKey, + depositReserve: PublicKey, + obligation: PublicKey, + obligationMint: PublicKey, + obligationTokenOutput: PublicKey, + lendingMarket: PublicKey, + lendingMarketAuthority: PublicKey, + transferAuthority: PublicKey, +): TransactionInstruction => { + const dataLayout = BufferLayout.struct([ + BufferLayout.u8("instruction"), + Layout.uint64("collateralAmount"), + ]); + + const data = Buffer.alloc(dataLayout.span); + dataLayout.encode( + { + instruction: LendingInstruction.DepositObligationCollateral, + collateralAmount: new BN(collateralAmount), + }, + data + ); + + const keys = [ + { pubkey: from, isSigner: false, isWritable: true }, + { pubkey: to, isSigner: false, isWritable: true }, + { pubkey: depositReserve, isSigner: false, isWritable: false }, + { pubkey: obligation, isSigner: false, isWritable: true }, + { pubkey: obligationMint, isSigner: false, isWritable: true }, + { pubkey: obligationTokenOutput, isSigner: false, isWritable: true }, + { pubkey: lendingMarket, isSigner: false, isWritable: false }, + { pubkey: lendingMarketAuthority, isSigner: false, isWritable: false }, + { pubkey: transferAuthority, isSigner: true, isWritable: false }, + { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, + ]; + return new TransactionInstruction({ + keys, + programId: LENDING_PROGRAM_ID, + data, + }); +}; diff --git a/src/models/lending/index.ts b/src/models/lending/index.ts index a3f2a08..cf975ba 100644 --- a/src/models/lending/index.ts +++ b/src/models/lending/index.ts @@ -5,3 +5,5 @@ export * from "./lending"; export * from "./borrow"; export * from "./deposit"; export * from "./withdraw"; +export * from "./depositObligationCollateral"; +export * from "./withdrawObligationCollateral"; diff --git a/src/models/lending/lending.ts b/src/models/lending/lending.ts index 77a866e..d7035f2 100644 --- a/src/models/lending/lending.ts +++ b/src/models/lending/lending.ts @@ -8,6 +8,8 @@ export enum LendingInstruction { RepayObligationLiquidity = 6, LiquidateObligation = 7, AccrueReserveInterest = 8, + DepositObligationCollateral = 9, + WithdrawObligationCollateral = 10, } export const TransactionListLookup: { [key: number]: string } = { @@ -16,4 +18,6 @@ export const TransactionListLookup: { [key: number]: string } = { 5: "Borrow", 6: "Repay", 7: "Liquidate", + 9: "DepositObligationCollateral", + 10: "WithdrawObligationCollateral", }; diff --git a/src/models/lending/withdrawObligationCollateral.ts b/src/models/lending/withdrawObligationCollateral.ts new file mode 100644 index 0000000..8920153 --- /dev/null +++ b/src/models/lending/withdrawObligationCollateral.ts @@ -0,0 +1,82 @@ +import { + PublicKey, + SYSVAR_CLOCK_PUBKEY, + TransactionInstruction, +} from "@solana/web3.js"; +import BN from "bn.js"; +import * as BufferLayout from "buffer-layout"; +import { TOKEN_PROGRAM_ID, LENDING_PROGRAM_ID } from "../../utils/ids"; +import * as Layout from "./../../utils/layout"; +import { LendingInstruction } from "./lending"; + +/// Withdraw excess collateral from an obligation. The loan must remain healthy. +/// +/// 0. `[writable]` Source withdraw reserve collateral supply SPL Token account +/// 1. `[writable]` Destination collateral token account, minted by withdraw reserve +/// collateral mint. $authority can transfer $collateral_amount +/// 2. `[]` Withdraw reserve account. +/// 3. `[]` Borrow reserve account. +/// 4. `[writable]` Obligation +/// 5. `[writable]` Obligation token mint +/// 6. `[writable]` Obligation token input +/// 7. `[]` Lending market account. +/// 8. `[]` Derived lending market authority. +/// 9. `[]` User transfer authority ($authority). +/// 10 `[]` Dex market +/// 11 `[]` Dex market order book side +/// 12 `[]` Temporary memory +/// 13 `[]` Clock sysvar +/// 14 '[]` Token program id +export const withdrawObligationCollateralInstruction = ( + collateralAmount: number | BN, + from: PublicKey, + to: PublicKey, + withdrawReserve: PublicKey, + borrowReserve: PublicKey, + obligation: PublicKey, + obligationMint: PublicKey, + obligationTokenInput: PublicKey, + lendingMarket: PublicKey, + lendingMarketAuthority: PublicKey, + transferAuthority: PublicKey, + dexMarket: PublicKey, + dexOrderBookSide: PublicKey, + memory: PublicKey, +): TransactionInstruction => { + const dataLayout = BufferLayout.struct([ + BufferLayout.u8("instruction"), + Layout.uint64("collateralAmount"), + ]); + + const data = Buffer.alloc(dataLayout.span); + dataLayout.encode( + { + instruction: LendingInstruction.WithdrawObligationCollateral, + collateralAmount: new BN(collateralAmount), + }, + data + ); + + const keys = [ + { pubkey: from, isSigner: false, isWritable: true }, + { pubkey: to, isSigner: false, isWritable: true }, + { pubkey: withdrawReserve, isSigner: false, isWritable: false }, + { pubkey: borrowReserve, isSigner: false, isWritable: false }, + { pubkey: obligation, isSigner: false, isWritable: true }, + { pubkey: obligationMint, isSigner: false, isWritable: true }, + { pubkey: obligationTokenInput, isSigner: false, isWritable: true }, + { pubkey: lendingMarket, isSigner: false, isWritable: false }, + { pubkey: lendingMarketAuthority, isSigner: false, isWritable: false }, + { pubkey: transferAuthority, isSigner: true, isWritable: false }, + { pubkey: dexMarket, isSigner: false, isWritable: false }, + { pubkey: dexOrderBookSide, isSigner: false, isWritable: false }, + { pubkey: memory, isSigner: false, isWritable: false }, + { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, + { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, + ]; + return new TransactionInstruction({ + keys, + programId: LENDING_PROGRAM_ID, + data, + }); +};