feat: add support for transfer authority

This commit is contained in:
bartosz-lipinski 2021-01-05 23:24:34 -06:00
parent d30ac691b1
commit 52d1d939c9
12 changed files with 109 additions and 52 deletions

View File

@ -147,14 +147,14 @@ export const borrow = async (
);
// create approval for transfer transactions
approve(
const transferAuthority = approve(
instructions,
cleanupInstructions,
fromAccount,
authority,
wallet.publicKey,
fromLamports
);
signers.push(transferAuthority);
const dexMarketAddress = borrowReserve.info.dexMarketOption
? borrowReserve.info.dexMarket
@ -189,7 +189,9 @@ export const borrow = async (
obligationTokenOutput,
wallet.publicKey,
depositReserve.info.lendingMarket,
authority,
transferAuthority.publicKey,
dexMarketAddress,
dexOrderBookSide,

View File

@ -58,15 +58,16 @@ export const deposit = async (
);
// create approval for transfer transactions
approve(
const transferAuthority = approve(
instructions,
cleanupInstructions,
fromAccount,
authority,
wallet.publicKey,
amountLamports
);
signers.push(transferAuthority);
let toAccount: PublicKey;
if (isInitalized) {
// get destination account
@ -90,7 +91,9 @@ export const deposit = async (
amountLamports,
fromAccount,
toAccount,
reserve.lendingMarket,
authority,
transferAuthority.publicKey,
reserveAddress,
reserve.liquiditySupply,
reserve.collateralMint
@ -112,6 +115,7 @@ export const deposit = async (
reserve.collateralSupply,
reserve.lendingMarket,
authority,
transferAuthority.publicKey,
reserve.dexMarket
)
);

View File

@ -55,14 +55,14 @@ export const liquidate = async (
);
// create approval for transfer transactions
approve(
const transferAuthority = approve(
instructions,
cleanupInstructions,
fromAccount,
authority,
wallet.publicKey,
amountLamports
);
signers.push(transferAuthority);
// get destination account
const toAccount = await findOrCreateAccountByMint(
@ -104,7 +104,9 @@ export const liquidate = async (
withdrawReserve.pubkey,
withdrawReserve.info.collateralSupply,
obligation.pubkey,
repayReserve.info.lendingMarket,
authority,
transferAuthority.publicKey,
dexMarketAddress,
dexOrderBookSide,
memory

View File

@ -51,14 +51,14 @@ export const repay = async (
const fromAccount = from.pubkey;
// create approval for transfer transactions
approve(
const transferAuthority = approve(
instructions,
cleanupInstructions,
fromAccount,
authority,
wallet.publicKey,
amountLamports
);
signers.push(transferAuthority);
// get destination account
const toAccount = await findOrCreateAccountByMint(
@ -76,9 +76,11 @@ export const repay = async (
instructions,
cleanupInstructions,
obligationToken.pubkey,
authority,
wallet.publicKey,
obligationToken.info.amount.toNumber()
obligationToken.info.amount.toNumber(),
// reuse transfer authority
transferAuthority.publicKey,
);
// TODO: add obligation
@ -95,7 +97,9 @@ export const repay = async (
obligation.pubkey,
obligation.info.tokenMint,
obligationToken.pubkey,
authority
repayReserve.info.lendingMarket,
authority,
transferAuthority.publicKey,
)
);

View File

@ -38,15 +38,16 @@ export const withdraw = async (
const fromAccount = from.pubkey;
// create approval for transfer transactions
approve(
const transferAuthority = approve(
instructions,
cleanupInstructions,
fromAccount,
authority,
wallet.publicKey,
amountLamports
);
signers.push(transferAuthority);
// get destination account
const toAccount = await findOrCreateAccountByMint(
wallet.publicKey,
@ -66,7 +67,9 @@ export const withdraw = async (
reserveAddress,
reserve.collateralMint,
reserve.liquiditySupply,
authority
reserve.lendingMarket,
authority,
transferAuthority.publicKey,
)
);

View File

@ -1,4 +1,4 @@
import { AccountInfo, PublicKey, TransactionInstruction } from "@solana/web3.js";
import { Account, AccountInfo, PublicKey, TransactionInstruction } from "@solana/web3.js";
import { AccountInfo as TokenAccountInfo, Token } from "@solana/spl-token";
import { TOKEN_PROGRAM_ID } from "../utils/ids";
@ -13,16 +13,20 @@ export function approve(
instructions: TransactionInstruction[],
cleanupInstructions: TransactionInstruction[],
account: PublicKey,
delegate: PublicKey,
owner: PublicKey,
amount: number,
): void {
// if delegate is not passed ephemeral transfer authority is used
delegate?: PublicKey,
): Account {
const tokenProgram = TOKEN_PROGRAM_ID;
const transferAuthority = new Account();
instructions.push(
Token.createApproveInstruction(
tokenProgram,
account,
delegate,
delegate ?? transferAuthority.publicKey,
owner,
[],
amount
@ -36,4 +40,6 @@ export function approve(
owner,
[]),
);
return transferAuthority;
}

View File

@ -15,23 +15,26 @@ export enum BorrowAmountType {
/// Borrow tokens from a reserve by depositing collateral tokens. The number of borrowed tokens
/// is calculated by market price. The debt obligation is tokenized.
///
/// 0. `[writable]` Collateral input SPL Token account, $authority can transfer $collateral_amount
/// 1. `[writable]` Liquidity output SPL Token account
/// 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.
/// 3. `[writable]` Deposit reserve collateral supply SPL Token account
/// 4. `[writable]` Borrow reserve account.
/// 5. `[writable]` Borrow reserve liquidity supply SPL Token account
/// 6. `[writable]` Obligation - uninitialized
/// 7. `[writable]` Obligation token mint - uninitialized
/// 8. `[writable]` Obligation token output - uninitialized
/// 6. `[writable]` Obligation
/// 7. `[writable]` Obligation token mint
/// 8. `[writable]` Obligation token output
/// 9. `[]` Obligation token owner
/// 10 `[]` Derived lending market authority ($authority).
/// 11 `[]` Dex market
/// 12 `[]` Dex order book side // could be bid/ask
/// 13 `[]` Temporary memory
/// 14 `[]` Clock sysvar
/// 15 `[]` Rent sysvar
/// 16 '[]` Token program id
/// 10 `[]` Lending market account.
/// 11 `[]` Derived lending market authority.
/// 12 `[]` User transfer authority ($authority).
/// 13 `[]` Dex market
/// 14 `[]` Dex market order book side
/// 15 `[]` Temporary memory
/// 16 `[]` Clock sysvar
/// 17 `[]` Rent sysvar
/// 18 '[]` Token program id
export const borrowInstruction = (
amount: number | BN,
amountType: BorrowAmountType,
@ -47,7 +50,9 @@ export const borrowInstruction = (
obligationTokenOutput: PublicKey,
obligationTokenOwner: PublicKey,
lendingMarket: PublicKey,
lendingMarketAuthority: PublicKey,
transferAuthority: PublicKey,
dexMarket: PublicKey,
dexOrderBookSide: PublicKey,
@ -89,7 +94,11 @@ export const borrowInstruction = (
{ pubkey: obligationMint, isSigner: false, isWritable: true },
{ pubkey: obligationTokenOutput, isSigner: false, isWritable: true },
{ pubkey: obligationTokenOwner, isSigner: false, isWritable: false },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: lendingMarketAuthority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: dexMarket, isSigner: false, isWritable: false },
{ pubkey: dexOrderBookSide, isSigner: false, isWritable: false },
{ pubkey: memory, isSigner: false, isWritable: false },

View File

@ -11,19 +11,23 @@ import { LendingReserve } from './reserve';
/// Deposit liquidity into a reserve. The output is a collateral token representing ownership
/// of the reserve liquidity pool.
///
/// 0. `[writable]` Liquidity input SPL Token account. $authority can transfer $liquidity_amount
/// 1. `[writable]` Collateral output SPL Token account,
/// 0. `[writable]` Source liquidity token account. $authority can transfer $liquidity_amount
/// 1. `[writable]` Destination collateral token account.
/// 2. `[writable]` Reserve account.
/// 3. `[writable]` Reserve liquidity supply SPL Token account.
/// 4. `[writable]` Reserve collateral SPL Token mint.
/// 5. `[]` Derived lending market authority ($authority).
/// 6. `[]` Clock sysvar
/// 7. '[]` Token program id
/// 5. `[]` Lending market account.
/// 6. `[]` Derived lending market authority.
/// 7. `[]` User transfer authority ($authority).
/// 8. `[]` Clock sysvar
/// 9. '[]` Token program id
export const depositInstruction = (
liquidityAmount: number | BN,
from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount
to: PublicKey, // Collateral output SPL Token account,
lendingMarket: PublicKey,
reserveAuthority: PublicKey,
transferAuthority: PublicKey,
reserveAccount: PublicKey,
reserveSupply: PublicKey,
collateralMint: PublicKey
@ -45,7 +49,9 @@ export const depositInstruction = (
{ pubkey: reserveAccount, isSigner: false, isWritable: true },
{ pubkey: reserveSupply, isSigner: false, isWritable: true },
{ pubkey: collateralMint, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: reserveAuthority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
];

View File

@ -7,19 +7,22 @@ import { TOKEN_PROGRAM_ID, LENDING_PROGRAM_ID } from '../../utils/ids';
/// Purchase collateral tokens at a discount rate if the chosen obligation is unhealthy.
///
/// 0. `[writable]` Liquidity input SPL Token account, $authority can transfer $liquidity_amount
/// 1. `[writable]` Collateral output SPL Token account
/// 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.
/// 3. `[writable]` Repay reserve liquidity supply SPL Token account
/// 4. `[writable]` Withdraw reserve account.
/// 5. `[writable]` Withdraw reserve collateral supply SPL Token account
/// 6. `[writable]` Obligation - initialized
/// 7. `[]` Derived lending market authority ($authority).
/// 8. `[]` Dex market
/// 9. `[]` Dex market orders
/// 10 `[]` Temporary memory
/// 11 `[]` Clock sysvar
/// 12 `[]` Token program id
/// 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 liquidateInstruction = (
liquidityAmount: number | BN,
from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount
@ -29,7 +32,9 @@ export const liquidateInstruction = (
withdrawReserve: PublicKey,
withdrawReserveCollateralSupply: PublicKey,
obligation: PublicKey,
lendingMarket: PublicKey,
authority: PublicKey,
transferAuthority: PublicKey,
dexMarket: PublicKey,
dexOrderBookSide: PublicKey,
memory: PublicKey
@ -61,7 +66,9 @@ export const liquidateInstruction = (
{ pubkey: obligation, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: authority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: dexMarket, isSigner: false, isWritable: false },
{ pubkey: dexOrderBookSide, isSigner: false, isWritable: false },

View File

@ -8,18 +8,21 @@ import { TOKEN_PROGRAM_ID, LENDING_PROGRAM_ID } from '../../utils/ids';
/// Repay loaned tokens to a reserve and receive collateral tokens. The obligation balance
/// will be recalculated for interest.
///
/// 0. `[writable]` Liquidity input SPL Token account, $authority can transfer $liquidity_amount
/// 1. `[writable]` Collateral output SPL Token account
/// 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.
/// 3. `[writable]` Repay reserve liquidity supply SPL Token account
/// 4. `[]` Withdraw reserve account.
/// 5. `[writable]` Withdraw reserve collateral supply SPL Token account
/// 6. `[writable]` Obligation - initialized
/// 7. `[writable]` Obligation token mint, $authority can transfer calculated amount
/// 8. `[writable]` Obligation token input
/// 9. `[]` Derived lending market authority ($authority).
/// 10 `[]` Clock sysvar
/// 11 `[]` Token program id
/// 7. `[writable]` Obligation token mint
/// 8. `[writable]` Obligation token input, $authority can transfer calculated amount
/// 9. `[]` Lending market account.
/// 10 `[]` Derived lending market authority.
/// 11 `[]` User transfer authority ($authority).
/// 12 `[]` Clock sysvar
/// 13 `[]` Token program id
export const repayInstruction = (
liquidityAmount: number | BN,
from: PublicKey, // Liquidity input SPL Token account. $authority can transfer $liquidity_amount
@ -31,7 +34,9 @@ export const repayInstruction = (
obligation: PublicKey,
obligationMint: PublicKey,
obligationInput: PublicKey,
authority: PublicKey
lendingMarket: PublicKey,
authority: PublicKey,
transferAuthority: PublicKey,
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('liquidityAmount')]);
@ -62,7 +67,10 @@ export const repayInstruction = (
{ pubkey: obligationMint, isSigner: false, isWritable: true },
{ pubkey: obligationInput, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: authority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
];

View File

@ -114,6 +114,7 @@ export const initReserveInstruction = (
collateralSupply: PublicKey,
lendingMarket: PublicKey,
lendingMarketAuthority: PublicKey,
transferAuthority: PublicKey,
dexMarket: PublicKey // TODO: optional
): TransactionInstruction => {
@ -145,6 +146,7 @@ export const initReserveInstruction = (
// NOTE: Why lending market needs to be a signer?
{ pubkey: lendingMarket, isSigner: true, isWritable: true },
{ pubkey: lendingMarketAuthority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },

View File

@ -12,7 +12,9 @@ export const withdrawInstruction = (
reserveAccount: PublicKey,
collateralMint: PublicKey,
reserveSupply: PublicKey,
authority: PublicKey
lendingMarket: PublicKey,
authority: PublicKey,
transferAuthority: PublicKey,
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('collateralAmount')]);
@ -31,7 +33,9 @@ export const withdrawInstruction = (
{ pubkey: reserveAccount, isSigner: false, isWritable: true },
{ pubkey: collateralMint, isSigner: false, isWritable: true },
{ pubkey: reserveSupply, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: authority, isSigner: false, isWritable: false },
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
];