update state and instructions

This commit is contained in:
jordansexton 2021-06-10 22:43:35 -05:00
parent 002723fa44
commit 955ade8ae5
16 changed files with 126 additions and 76 deletions

View File

@ -10,6 +10,7 @@ import * as Layout from '../../utils/layout';
import { calculateUtilizationRatio, Reserve } from '../state/reserve';
import { LendingInstruction } from './instruction';
/// 10
/// Borrow liquidity from a reserve by depositing collateral tokens. Requires a refreshed
/// obligation and reserve.
///
@ -28,6 +29,11 @@ import { LendingInstruction } from './instruction';
/// 8. `[]` Clock sysvar.
/// 9. `[]` Token program id.
/// 10 `[optional, writable]` Host fee receiver account.
///
/// BorrowObligationLiquidity {
/// /// Amount of liquidity to borrow - u64::MAX for 100% of borrowing power
/// liquidity_amount: u64,
/// },
export const borrowObligationLiquidityInstruction = (
liquidityAmount: number | BN,
sourceLiquidity: PublicKey,

View File

@ -9,6 +9,7 @@ import * as BufferLayout from 'buffer-layout';
import * as Layout from './../../utils/layout';
import { LendingInstruction } from './instruction';
/// 8
/// Deposit collateral to an obligation. Requires a refreshed reserve.
///
/// Accounts expected by this instruction:
@ -25,6 +26,11 @@ import { LendingInstruction } from './instruction';
/// 7. `[signer]` User transfer authority ($authority).
/// 8. `[]` Clock sysvar.
/// 9. `[]` Token program id.
///
/// DepositObligationCollateral {
/// /// Amount of collateral tokens to deposit
/// collateral_amount: u64,
/// },
export const depositObligationCollateralInstruction = (
collateralAmount: number | BN,
sourceCollateral: PublicKey,

View File

@ -11,6 +11,7 @@ import { calculateUtilizationRatio, Reserve } from '../state/reserve';
import { calculateBorrowAPY } from './borrowObligationLiquidity';
import { LendingInstruction } from './instruction';
/// 4
/// Deposit liquidity into a reserve in exchange for collateral. Collateral represents a share
/// of the reserve liquidity pool.
///
@ -27,6 +28,11 @@ import { LendingInstruction } from './instruction';
/// 7. `[signer]` User transfer authority ($authority).
/// 8. `[]` Clock sysvar.
/// 9. `[]` Token program id.
///
/// DepositReserveLiquidity {
/// /// Amount of liquidity to deposit in exchange for collateral tokens
/// liquidity_amount: u64,
/// },
export const depositReserveLiquidityInstruction = (
liquidityAmount: number | BN,
sourceLiquidity: PublicKey,

View File

@ -8,26 +8,38 @@ import * as BufferLayout from 'buffer-layout';
import * as Layout from '../../utils/layout';
import { LendingInstruction } from './instruction';
// @TODO: move to @oyster/common
export const ORACLE_PROGRAM_ID = new PublicKey(
// @FIXME: replace with Pyth
'XXX',
);
/// 0
/// Initializes a new lending market.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Lending market account - uninitialized.
/// 1. `[]` Quote currency SPL Token mint.
/// 2. `[]` Rent sysvar.
/// 3. `[]` Token program id.
// InitLendingMarket {
// /// Owner authority which can add new reserves
// owner: Pubkey,
// },
/// 1. `[]` Rent sysvar.
/// 2. `[]` Token program id.
/// 3. `[]` Oracle program id.
///
/// InitLendingMarket {
/// /// Owner authority which can add new reserves
/// owner: Pubkey,
/// /// Currency market prices are quoted in
/// /// e.g. "USD" null padded (`*b"USD\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"`) or SPL token mint pubkey
/// quote_currency: [u8; 32],
/// },
export const initLendingMarketInstruction = (
owner: PublicKey,
quoteCurrency: Buffer,
lendingMarket: PublicKey,
quoteTokenMint: PublicKey,
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([
BufferLayout.u8('instruction'),
Layout.publicKey('owner'),
BufferLayout.blob(32, 'quoteCurrency'),
]);
const data = Buffer.alloc(dataLayout.span);
@ -35,15 +47,16 @@ export const initLendingMarketInstruction = (
{
instruction: LendingInstruction.InitLendingMarket,
owner,
quoteCurrency,
},
data,
);
const keys = [
{ pubkey: lendingMarket, isSigner: false, isWritable: true },
{ pubkey: quoteTokenMint, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: ORACLE_PROGRAM_ID, isSigner: false, isWritable: false },
];
return new TransactionInstruction({

View File

@ -8,6 +8,7 @@ import {
import * as BufferLayout from 'buffer-layout';
import { LendingInstruction } from './instruction';
/// 6
/// Initializes a new lending market obligation.
///
/// Accounts expected by this instruction:

View File

@ -11,6 +11,7 @@ import * as Layout from '../../utils/layout';
import { ReserveConfig } from '../state';
import { LendingInstruction } from './instruction';
/// 2
/// Initializes a new lending market reserve.
///
/// Accounts expected by this instruction:
@ -22,25 +23,25 @@ import { LendingInstruction } from './instruction';
/// 3. `[]` Reserve liquidity SPL Token mint.
/// 4. `[writable]` Reserve liquidity supply SPL Token account - uninitialized.
/// 5. `[writable]` Reserve liquidity fee receiver - uninitialized.
/// 6. `[writable]` Reserve collateral SPL Token mint - uninitialized.
/// 7. `[writable]` Reserve collateral token supply - uninitialized.
/// 8. `[]` Quote currency SPL Token mint.
/// 9. `[]` Lending market account.
/// 10 `[]` Derived lending market authority.
/// 11 `[signer]` Lending market owner.
/// 12 `[signer]` User transfer authority ($authority).
/// 13 `[]` Clock sysvar.
/// 13 `[]` Rent sysvar.
/// 14 `[]` Token program id.
/// 15 `[optional]` Reserve liquidity oracle account.
/// Not required for quote currency reserves.
/// Must match base and quote currency mint, and quote currency decimals.
// InitReserve {
// /// Initial amount of liquidity to deposit into the new reserve
// liquidity_amount: u64,
// /// Reserve configuration values
// config: ReserveConfig,
// },
/// 6. `[]` Pyth product account.
/// 7. `[]` Pyth price account.
/// This will be used as the reserve liquidity oracle account.
/// 8. `[writable]` Reserve collateral SPL Token mint - uninitialized.
/// 9. `[writable]` Reserve collateral token supply - uninitialized.
/// 10 `[]` Lending market account.
/// 11 `[]` Derived lending market authority.
/// 12 `[signer]` Lending market owner.
/// 13 `[signer]` User transfer authority ($authority).
/// 14 `[]` Clock sysvar.
/// 15 `[]` Rent sysvar.
/// 16 `[]` Token program id.
///
/// InitReserve {
/// /// Initial amount of liquidity to deposit into the new reserve
/// liquidity_amount: u64,
/// /// Reserve configuration values
/// config: ReserveConfig,
/// },
export const initReserveInstruction = (
liquidityAmount: number | BN,
config: ReserveConfig,
@ -50,13 +51,14 @@ export const initReserveInstruction = (
liquidityMint: PublicKey,
liquiditySupply: PublicKey,
liquidityFeeReceiver: PublicKey,
pythProduct: PublicKey,
pythPrice: PublicKey,
collateralMint: PublicKey,
collateralSupply: PublicKey,
lendingMarket: PublicKey,
lendingMarketAuthority: PublicKey,
lendingMarketOwner: PublicKey,
transferAuthority: PublicKey,
oracle?: PublicKey,
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([
BufferLayout.u8('instruction'),
@ -97,6 +99,8 @@ export const initReserveInstruction = (
{ pubkey: liquidityMint, isSigner: false, isWritable: false },
{ pubkey: liquiditySupply, isSigner: false, isWritable: true },
{ pubkey: liquidityFeeReceiver, isSigner: false, isWritable: true },
{ pubkey: pythProduct, isSigner: false, isWritable: false },
{ pubkey: pythPrice, isSigner: false, isWritable: false },
{ pubkey: collateralMint, isSigner: false, isWritable: true },
{ pubkey: collateralSupply, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: true },
@ -107,10 +111,6 @@ export const initReserveInstruction = (
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
];
if (oracle) {
keys.push({ pubkey: oracle, isSigner: false, isWritable: false });
}
return new TransactionInstruction({
keys,
programId: LENDING_PROGRAM_ID,

View File

@ -9,6 +9,7 @@ import * as BufferLayout from 'buffer-layout';
import * as Layout from '../../utils/layout';
import { LendingInstruction } from './instruction';
/// 12
/// Repay borrowed liquidity to a reserve to receive collateral at a discount from an unhealthy
/// obligation. Requires a refreshed obligation and reserves.
///
@ -29,6 +30,11 @@ import { LendingInstruction } from './instruction';
/// 9. `[signer]` User transfer authority ($authority).
/// 10 `[]` Clock sysvar.
/// 11 `[]` Token program id.
///
/// LiquidateObligation {
/// /// Amount of liquidity to repay - u64::MAX for up to 100% of borrowed amount
/// liquidity_amount: u64,
/// },
export const liquidateObligationInstruction = (
liquidityAmount: number | BN,
sourceLiquidity: PublicKey,

View File

@ -9,6 +9,7 @@ import * as BufferLayout from 'buffer-layout';
import * as Layout from '../../utils/layout';
import { LendingInstruction } from './instruction';
/// 5
/// Redeem collateral from a reserve in exchange for liquidity.
///
/// Accounts expected by this instruction:
@ -24,6 +25,11 @@ import { LendingInstruction } from './instruction';
/// 7. `[signer]` User transfer authority ($authority).
/// 8. `[]` Clock sysvar.
/// 9. `[]` Token program id.
///
/// RedeemReserveCollateral {
/// /// Amount of collateral tokens to redeem in exchange for liquidity
/// collateral_amount: u64,
/// },
export const redeemReserveCollateralInstruction = (
collateralAmount: number | BN,
sourceCollateral: PublicKey,

View File

@ -7,6 +7,7 @@ import {
import BufferLayout from 'buffer-layout';
import { LendingInstruction } from './instruction';
/// 7
/// Refresh an obligation's accrued interest and collateral and liquidity prices. Requires
/// refreshed reserves, as all obligation collateral deposit reserves in order, followed by all
/// liquidity borrow reserves in order.

View File

@ -7,18 +7,18 @@ import {
import * as BufferLayout from 'buffer-layout';
import { LendingInstruction } from './instruction';
/// 3
/// Accrue interest and update market price of liquidity on a reserve.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Reserve account.
/// 1. `[]` Clock sysvar.
/// 2. `[optional]` Reserve liquidity oracle account.
/// Required if the reserve currency is not the lending market quote
/// currency.
/// 1. `[]` Reserve liquidity oracle account.
/// Must be the Pyth price account specified at InitReserve.
/// 2. `[]` Clock sysvar.
export const refreshReserveInstruction = (
reserve: PublicKey,
oracle?: PublicKey,
oracle: PublicKey,
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction')]);
@ -27,13 +27,10 @@ export const refreshReserveInstruction = (
const keys = [
{ pubkey: reserve, isSigner: false, isWritable: true },
{ pubkey: oracle, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
];
if (oracle) {
keys.push({ pubkey: oracle, isSigner: false, isWritable: false });
}
return new TransactionInstruction({
keys,
programId: LENDING_PROGRAM_ID,

View File

@ -9,6 +9,7 @@ import * as BufferLayout from 'buffer-layout';
import * as Layout from '../../utils/layout';
import { LendingInstruction } from './instruction';
/// 11
/// Repay borrowed liquidity to a reserve. Requires a refreshed obligation and reserve.
///
/// Accounts expected by this instruction:
@ -20,10 +21,14 @@ import { LendingInstruction } from './instruction';
/// 2. `[writable]` Repay reserve account - refreshed.
/// 3. `[writable]` Obligation account - refreshed.
/// 4. `[]` Lending market account.
/// 5. `[]` Derived lending market authority.
/// 6. `[signer]` User transfer authority ($authority).
/// 7. `[]` Clock sysvar.
/// 8. `[]` Token program id.
/// 5. `[signer]` User transfer authority ($authority).
/// 6. `[]` Clock sysvar.
/// 7. `[]` Token program id.
///
/// RepayObligationLiquidity {
/// /// Amount of liquidity to repay - u64::MAX for 100% of borrowed amount
/// liquidity_amount: u64,
/// },
export const repayObligationLiquidityInstruction = (
liquidityAmount: number | BN,
sourceLiquidity: PublicKey,
@ -31,7 +36,6 @@ export const repayObligationLiquidityInstruction = (
repayReserve: PublicKey,
obligation: PublicKey,
lendingMarket: PublicKey,
lendingMarketAuthority: PublicKey,
transferAuthority: PublicKey,
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([
@ -54,7 +58,6 @@ export const repayObligationLiquidityInstruction = (
{ pubkey: repayReserve, isSigner: false, isWritable: true },
{ pubkey: obligation, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: lendingMarketAuthority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: true, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },

View File

@ -4,16 +4,18 @@ import * as BufferLayout from 'buffer-layout';
import * as Layout from '../../utils/layout';
import { LendingInstruction } from './instruction';
/// 1
/// Sets the new owner of a lending market.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Lending market account.
/// 1. `[signer]` Current owner.
// SetLendingMarketOwner {
// /// The new owner
// new_owner: Pubkey,
// },
///
/// SetLendingMarketOwner {
/// /// The new owner
/// new_owner: Pubkey,
/// },
export const setLendingMarketOwnerInstruction = (
newOwner: PublicKey,
lendingMarket: PublicKey,

View File

@ -9,6 +9,7 @@ import * as BufferLayout from 'buffer-layout';
import * as Layout from './../../utils/layout';
import { LendingInstruction } from './instruction';
/// 9
/// Withdraw collateral from an obligation. Requires a refreshed obligation and reserve.
///
/// Accounts expected by this instruction:
@ -23,6 +24,11 @@ import { LendingInstruction } from './instruction';
/// 6. `[signer]` Obligation owner.
/// 7. `[]` Clock sysvar.
/// 8. `[]` Token program id.
///
/// WithdrawObligationCollateral {
/// /// Amount of collateral tokens to withdraw - u64::MAX for up to 100% of deposited amount
/// collateral_amount: u64,
/// },
export const withdrawObligationCollateralInstruction = (
collateralAmount: number | BN,
sourceCollateral: PublicKey,

View File

@ -5,7 +5,7 @@ import * as Layout from '../../utils/layout';
export interface LendingMarket {
version: number;
isInitialized: boolean;
quoteTokenMint: PublicKey;
quoteCurrency: Buffer;
tokenProgramId: PublicKey;
}
@ -14,9 +14,9 @@ export const LendingMarketLayout: typeof BufferLayout.Structure = BufferLayout.s
BufferLayout.u8('version'),
BufferLayout.u8('bumpSeed'),
Layout.publicKey('owner'),
Layout.publicKey('quoteTokenMint'),
BufferLayout.blob(32, 'quoteCurrency'),
Layout.publicKey('tokenProgramId'),
Layout.publicKey('oracleProgramId'),
BufferLayout.blob(128, 'padding'),
],
);

View File

@ -55,7 +55,7 @@ export const ObligationCollateralLayout: typeof BufferLayout.Structure = BufferL
[
Layout.publicKey('depositReserve'),
Layout.uint64('depositedAmount'),
Layout.uint64('marketValue'),
Layout.uint128('marketValue'),
],
);
@ -64,7 +64,7 @@ export const ObligationLiquidityLayout: typeof BufferLayout.Structure = BufferLa
Layout.publicKey('borrowReserve'),
Layout.uint128('cumulativeBorrowRateWads'),
Layout.uint128('borrowedAmountWads'),
Layout.uint64('marketValue'),
Layout.uint128('marketValue'),
],
);
@ -109,19 +109,16 @@ export const ObligationParser = (
return;
}
const depositsBuffer = dataFlat.slice(
0,
depositsLen * ObligationCollateralLayout.span,
);
const depositsSpan = depositsLen * ObligationCollateralLayout.span;
const borrowsSpan = borrowsLen * ObligationLiquidityLayout.span;
const depositsBuffer = dataFlat.slice(0, depositsSpan);
const deposits = BufferLayout.seq(
ObligationCollateralLayout,
depositsLen,
).decode(depositsBuffer) as ObligationCollateral[];
const borrowsBuffer = dataFlat.slice(
depositsBuffer.length,
borrowsLen * ObligationLiquidityLayout.span,
);
const borrowsBuffer = dataFlat.slice(depositsSpan, depositsSpan + borrowsSpan);
const borrows = BufferLayout.seq(
ObligationLiquidityLayout,
borrowsLen,

View File

@ -23,9 +23,9 @@ export interface ReserveLiquidity {
oracleOption: number;
oraclePubkey: PublicKey;
availableAmount: BN;
borrowedAmountWads: BN;
cumulativeBorrowRateWads: BN;
marketPrice: BN;
borrowedAmountWads: BN; // decimals
cumulativeBorrowRateWads: BN; // decimals
marketPrice: BN; // decimals
}
export interface ReserveCollateral {
@ -62,14 +62,11 @@ export const ReserveLayout: typeof BufferLayout.Structure = BufferLayout.struct(
BufferLayout.u8('mintDecimals'),
Layout.publicKey('supplyPubkey'),
Layout.publicKey('feeReceiver'),
// @FIXME: oracle option
// TODO: replace u32 option with generic equivalent
BufferLayout.u32('oracleOption'),
Layout.publicKey('oracle'),
Layout.publicKey('oraclePubkey'),
Layout.uint64('availableAmount'),
Layout.uint128('borrowedAmountWads'),
Layout.uint128('cumulativeBorrowRateWads'),
Layout.uint64('marketPrice'),
Layout.uint128('marketPrice'),
],
'liquidity',
),
@ -93,14 +90,18 @@ export const ReserveLayout: typeof BufferLayout.Structure = BufferLayout.struct(
BufferLayout.u8('optimalBorrowRate'),
BufferLayout.u8('maxBorrowRate'),
BufferLayout.struct(
[Layout.uint64('borrowFeeWad'), BufferLayout.u8('hostFeePercentage')],
[
Layout.uint64('borrowFeeWad'),
Layout.uint64('flashLoanFeeWad'),
BufferLayout.u8('hostFeePercentage')
],
'fees',
),
],
'config'
),
BufferLayout.blob(256, 'padding'),
BufferLayout.blob(248, 'padding'),
],
);
@ -146,7 +147,6 @@ export const reserveMarketCap = (reserve?: Reserve) => {
reserve?.liquidity.borrowedAmountWads,
).toNumber();
const total = available + borrowed;
return total;
};