feat: add borrow instruction
This commit is contained in:
parent
5cd9478317
commit
d63da050ad
|
@ -29,7 +29,7 @@ body {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
align-items: centerconn;
|
align-items: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,29 @@
|
||||||
import {
|
import {
|
||||||
Account,
|
Account,
|
||||||
AccountInfo,
|
|
||||||
Connection,
|
Connection,
|
||||||
PublicKey,
|
PublicKey,
|
||||||
sendAndConfirmRawTransaction,
|
|
||||||
SYSVAR_CLOCK_PUBKEY,
|
|
||||||
TransactionInstruction,
|
TransactionInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import BN from "bn.js";
|
|
||||||
import * as BufferLayout from "buffer-layout";
|
|
||||||
import { sendTransaction } from "../contexts/connection";
|
import { sendTransaction } from "../contexts/connection";
|
||||||
import { notify } from "../utils/notifications";
|
import { notify } from "../utils/notifications";
|
||||||
import * as Layout from "./../utils/layout";
|
import { LendingReserve } from "./../models/lending/reserve";
|
||||||
import { depositInstruction, initReserveInstruction, LendingReserve } from "./../models/lending/reserve";
|
import { AccountLayout, MintInfo, MintLayout, Token } from "@solana/spl-token";
|
||||||
import { AccountLayout, MintInfo, Token } from "@solana/spl-token";
|
|
||||||
import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../constants/ids";
|
import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../constants/ids";
|
||||||
import { createUninitializedAccount, ensureSplAccount, findOrCreateAccountByMint } from "./account";
|
import { createUninitializedAccount, ensureSplAccount, findOrCreateAccountByMint } from "./account";
|
||||||
import { cache, GenericAccountParser, MintParser, ParsedAccount } from "../contexts/accounts";
|
import { cache, MintParser, ParsedAccount } from "../contexts/accounts";
|
||||||
import { TokenAccount } from "../models";
|
import { TokenAccount, LendingObligationLayout, borrowInstruction, LendingMarket } from "../models";
|
||||||
import { isConstructorDeclaration } from "typescript";
|
import { toLamports } from "../utils/utils";
|
||||||
import { LendingMarketParser } from "../models/lending";
|
|
||||||
import { sign } from "crypto";
|
|
||||||
import { fromLamports, toLamports } from "../utils/utils";
|
|
||||||
|
|
||||||
export const borrow = async (
|
export const borrow = async (
|
||||||
from: TokenAccount,
|
from: TokenAccount,
|
||||||
amount: number,
|
amount: number,
|
||||||
reserve: LendingReserve,
|
|
||||||
reserveAddress: PublicKey,
|
borrowReserve: LendingReserve,
|
||||||
|
borrowReserveAddress: PublicKey,
|
||||||
|
|
||||||
|
depositReserve: LendingReserve,
|
||||||
|
depositReserveAddress: PublicKey,
|
||||||
|
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
wallet: any) => {
|
wallet: any) => {
|
||||||
|
|
||||||
|
@ -37,9 +33,6 @@ export const borrow = async (
|
||||||
type: "warn",
|
type: "warn",
|
||||||
});
|
});
|
||||||
|
|
||||||
const isInitalized = true; // TODO: finish reserve init
|
|
||||||
|
|
||||||
// user from account
|
|
||||||
const signers: Account[] = [];
|
const signers: Account[] = [];
|
||||||
const instructions: TransactionInstruction[] = [];
|
const instructions: TransactionInstruction[] = [];
|
||||||
const cleanupInstructions: TransactionInstruction[] = [];
|
const cleanupInstructions: TransactionInstruction[] = [];
|
||||||
|
@ -49,11 +42,11 @@ export const borrow = async (
|
||||||
);
|
);
|
||||||
|
|
||||||
const [authority] = await PublicKey.findProgramAddress(
|
const [authority] = await PublicKey.findProgramAddress(
|
||||||
[reserve.lendingMarket.toBuffer()], // which account should be authority
|
[depositReserve.lendingMarket.toBuffer()], // which account should be authority
|
||||||
LENDING_PROGRAM_ID
|
LENDING_PROGRAM_ID
|
||||||
);
|
);
|
||||||
|
|
||||||
const mint = (await cache.query(connection, reserve.liquidityMint, MintParser)) as ParsedAccount<MintInfo>;
|
const mint = (await cache.query(connection, depositReserve.collateralMint, MintParser)) as ParsedAccount<MintInfo>;
|
||||||
const amountLamports = toLamports(amount, mint?.info);
|
const amountLamports = toLamports(amount, mint?.info);
|
||||||
|
|
||||||
const fromAccount = ensureSplAccount(
|
const fromAccount = ensureSplAccount(
|
||||||
|
@ -77,37 +70,77 @@ export const borrow = async (
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let toAccount: PublicKey;
|
let toAccount = await findOrCreateAccountByMint(
|
||||||
if (isInitalized) {
|
|
||||||
// get destination account
|
|
||||||
toAccount = await findOrCreateAccountByMint(
|
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
instructions,
|
instructions,
|
||||||
cleanupInstructions,
|
cleanupInstructions,
|
||||||
accountRentExempt,
|
accountRentExempt,
|
||||||
reserve.collateralMint,
|
borrowReserve.liquidityMint,
|
||||||
signers
|
signers
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
toAccount = createUninitializedAccount(
|
const obligation = createUninitializedAccount(
|
||||||
|
instructions,
|
||||||
|
wallet.publicKey,
|
||||||
|
await connection.getMinimumBalanceForRentExemption(
|
||||||
|
LendingObligationLayout.span
|
||||||
|
),
|
||||||
|
signers,
|
||||||
|
);
|
||||||
|
|
||||||
|
const obligationMint = createUninitializedAccount(
|
||||||
|
instructions,
|
||||||
|
wallet.publicKey,
|
||||||
|
await connection.getMinimumBalanceForRentExemption(
|
||||||
|
MintLayout.span
|
||||||
|
),
|
||||||
|
signers,
|
||||||
|
);
|
||||||
|
|
||||||
|
const obligationTokenOutput = createUninitializedAccount(
|
||||||
instructions,
|
instructions,
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
accountRentExempt,
|
accountRentExempt,
|
||||||
signers,
|
signers,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const market = cache.get(depositReserve.lendingMarket) as ParsedAccount<LendingMarket>;
|
||||||
|
|
||||||
|
|
||||||
|
const dexMarketAddress = market.info.quoteMint.equals(borrowReserve.liquidityMint) ?
|
||||||
|
borrowReserve.dexMarket :
|
||||||
|
depositReserve.dexMarket;
|
||||||
|
|
||||||
|
const dexMarket = cache.get(dexMarketAddress);
|
||||||
|
if(!dexMarket) {
|
||||||
|
throw new Error(`Dex market doesn't exsists.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dexOrderBookSide = market.info.quoteMint.equals(borrowReserve.liquidityMint) ?
|
||||||
|
dexMarket.info.bids :
|
||||||
|
dexMarket.info.asks;
|
||||||
|
|
||||||
// deposit
|
// deposit
|
||||||
instructions.push(
|
instructions.push(
|
||||||
depositInstruction(
|
borrowInstruction(
|
||||||
amountLamports,
|
amountLamports,
|
||||||
fromAccount,
|
fromAccount,
|
||||||
toAccount,
|
toAccount,
|
||||||
|
depositReserveAddress,
|
||||||
|
depositReserve.liquiditySupply,
|
||||||
|
borrowReserveAddress,
|
||||||
|
borrowReserve.liquiditySupply,
|
||||||
|
|
||||||
|
obligation,
|
||||||
|
obligationMint,
|
||||||
|
obligationTokenOutput,
|
||||||
|
wallet.publicKey,
|
||||||
|
|
||||||
authority,
|
authority,
|
||||||
reserveAddress,
|
|
||||||
reserve.liquiditySupply,
|
dexMarketAddress,
|
||||||
reserve.collateralMint,
|
dexOrderBookSide,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -19,22 +19,38 @@ export const BorrowInput = (props: { className?: string, reserve: LendingReserve
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const [value, setValue] = useState('');
|
const [value, setValue] = useState('');
|
||||||
|
|
||||||
const reserve = props.reserve;
|
const borrowReserve = props.reserve;
|
||||||
const address = props.address;
|
const borrowReserveAddress = props.address;
|
||||||
|
|
||||||
const name = useTokenName(reserve?.liquidityMint);
|
const [collateralReserve, setCollateralReserve] = useState<LendingReserve>();
|
||||||
const { balance: tokenBalance, accounts: fromAccounts } = useUserBalance(reserve?.liquidityMint);
|
|
||||||
|
const collateralReserveAddress = useMemo(() => {
|
||||||
|
return cache.byParser(LendingReserveParser)
|
||||||
|
.find(acc => cache.get(acc) === collateralReserve);
|
||||||
|
}, [collateralReserve])
|
||||||
|
|
||||||
|
const name = useTokenName(borrowReserve?.liquidityMint);
|
||||||
|
const {
|
||||||
|
balance: tokenBalance,
|
||||||
|
accounts: fromAccounts
|
||||||
|
} = useUserBalance(collateralReserve?.liquidityMint);
|
||||||
// const collateralBalance = useUserBalance(reserve?.collateralMint);
|
// const collateralBalance = useUserBalance(reserve?.collateralMint);
|
||||||
|
|
||||||
const onBorrow = useCallback(() => {
|
const onBorrow = useCallback(() => {
|
||||||
|
if(!collateralReserve || !collateralReserveAddress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
borrow(
|
borrow(
|
||||||
fromAccounts[0],
|
fromAccounts[0],
|
||||||
parseFloat(value),
|
parseFloat(value),
|
||||||
reserve,
|
borrowReserve,
|
||||||
address,
|
borrowReserveAddress,
|
||||||
|
collateralReserve,
|
||||||
|
new PublicKey(collateralReserveAddress),
|
||||||
connection,
|
connection,
|
||||||
wallet);
|
wallet);
|
||||||
}, [value, reserve, fromAccounts, address]);
|
}, [value, borrowReserve, fromAccounts, borrowReserveAddress]);
|
||||||
|
|
||||||
const bodyStyle: React.CSSProperties = {
|
const bodyStyle: React.CSSProperties = {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -51,7 +67,7 @@ export const BorrowInput = (props: { className?: string, reserve: LendingReserve
|
||||||
How much would you like to borrow?
|
How much would you like to borrow?
|
||||||
</div>
|
</div>
|
||||||
<div className="token-input">
|
<div className="token-input">
|
||||||
<TokenIcon mintAddress={reserve?.liquidityMint} />
|
<TokenIcon mintAddress={borrowReserve?.liquidityMint} />
|
||||||
<NumericInput value={value}
|
<NumericInput value={value}
|
||||||
onChange={(val: any) => {
|
onChange={(val: any) => {
|
||||||
setValue(val);
|
setValue(val);
|
||||||
|
|
|
@ -55,6 +55,7 @@ export const useLending = () => {
|
||||||
.map(acc => [
|
.map(acc => [
|
||||||
(acc?.info as LendingReserve).collateralMint.toBase58(),
|
(acc?.info as LendingReserve).collateralMint.toBase58(),
|
||||||
(acc?.info as LendingReserve).liquidityMint.toBase58(),
|
(acc?.info as LendingReserve).liquidityMint.toBase58(),
|
||||||
|
(acc?.info as LendingReserve).dexMarket.toBase58(),
|
||||||
])
|
])
|
||||||
].flat().filter((p) => p) as string[];
|
].flat().filter((p) => p) as string[];
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,6 @@ import { AccountInfo, Connection, PublicKey } from "@solana/web3.js";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { EventEmitter } from "./../utils/eventEmitter";
|
import { EventEmitter } from "./../utils/eventEmitter";
|
||||||
|
|
||||||
interface RecentPoolData {
|
|
||||||
pool_identifier: string;
|
|
||||||
volume24hA: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MarketsContextState {
|
export interface MarketsContextState {
|
||||||
midPriceInUSD: (mint: string) => number;
|
midPriceInUSD: (mint: string) => number;
|
||||||
marketEmitter: EventEmitter;
|
marketEmitter: EventEmitter;
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export * from "./account";
|
export * from "./account";
|
||||||
|
export * from './lending';
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import {
|
||||||
|
PublicKey,
|
||||||
|
SYSVAR_CLOCK_PUBKEY,
|
||||||
|
SYSVAR_RENT_PUBKEY,
|
||||||
|
TransactionInstruction,
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import BN from "bn.js";
|
||||||
|
import * as BufferLayout from "buffer-layout";
|
||||||
|
import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids";
|
||||||
|
import * as Layout from "./../../utils/layout";
|
||||||
|
import { LendingInstruction } from './lending';
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// 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
|
||||||
|
/// 9. `[]` Obligation token owner - uninitialized
|
||||||
|
/// 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
|
||||||
|
export const borrowInstruction = (
|
||||||
|
collateralAmount: number | BN,
|
||||||
|
from: PublicKey, // Collateral input SPL Token account. $authority can transfer $collateralAmount
|
||||||
|
to: PublicKey, // Liquidity output SPL Token account,
|
||||||
|
depositReserve: PublicKey,
|
||||||
|
depositReserveCollateralSupply: PublicKey,
|
||||||
|
borrowReserve: PublicKey,
|
||||||
|
borrowReserveLiquiditySupply: PublicKey,
|
||||||
|
|
||||||
|
obligation: PublicKey,
|
||||||
|
obligationMint: PublicKey,
|
||||||
|
obligationTokenOutput: PublicKey,
|
||||||
|
obligationTokenOwner: PublicKey,
|
||||||
|
|
||||||
|
lendingMarketAuthority: PublicKey,
|
||||||
|
|
||||||
|
dexMarket: PublicKey,
|
||||||
|
dexOrderBookSide: PublicKey,
|
||||||
|
): TransactionInstruction => {
|
||||||
|
const dataLayout = BufferLayout.struct([
|
||||||
|
BufferLayout.u8("instruction"),
|
||||||
|
Layout.uint64("collateralAmount"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const data = Buffer.alloc(dataLayout.span);
|
||||||
|
dataLayout.encode(
|
||||||
|
{
|
||||||
|
instruction: LendingInstruction.BorrowReserveLiquidity,
|
||||||
|
collateralAmount: new BN(collateralAmount),
|
||||||
|
},
|
||||||
|
data
|
||||||
|
);
|
||||||
|
|
||||||
|
const keys = [
|
||||||
|
{ pubkey: from, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: to, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: depositReserve, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: depositReserveCollateralSupply, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: borrowReserve, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: borrowReserveLiquiditySupply, isSigner: false, isWritable: false },
|
||||||
|
{ pubkey: obligation, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: obligationMint, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: obligationTokenOutput, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: obligationTokenOwner, isSigner: false, isWritable: false },
|
||||||
|
{ pubkey: lendingMarketAuthority, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: dexMarket, isSigner: false, isWritable: true },
|
||||||
|
{ pubkey: dexOrderBookSide, 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 },
|
||||||
|
];
|
||||||
|
return new TransactionInstruction({
|
||||||
|
keys,
|
||||||
|
programId: LENDING_PROGRAM_ID,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,2 +1,5 @@
|
||||||
export * from './market';
|
export * from './market';
|
||||||
export * from './reserve';
|
export * from './reserve';
|
||||||
|
export * from './obligation';
|
||||||
|
export * from './lending';
|
||||||
|
export * from './borrow';
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
export enum LendingInstruction {
|
||||||
|
InitLendingMarket = 0,
|
||||||
|
InitReserve = 1,
|
||||||
|
DepositReserveLiquidity = 2,
|
||||||
|
WithdrawReserveLiquidity = 3,
|
||||||
|
BorrowReserveLiquidity = 4,
|
||||||
|
RepayReserveLiquidity = 5
|
||||||
|
}
|
|
@ -1 +1,44 @@
|
||||||
export const x = 1;
|
import {
|
||||||
|
AccountInfo,
|
||||||
|
Connection,
|
||||||
|
PublicKey,
|
||||||
|
sendAndConfirmRawTransaction,
|
||||||
|
SYSVAR_CLOCK_PUBKEY,
|
||||||
|
SYSVAR_RENT_PUBKEY,
|
||||||
|
TransactionInstruction,
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import BN from "bn.js";
|
||||||
|
import * as BufferLayout from "buffer-layout";
|
||||||
|
import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids";
|
||||||
|
import { sendTransaction } from "../../contexts/connection";
|
||||||
|
import * as Layout from "./../../utils/layout";
|
||||||
|
import { LendingInstruction } from './lending';
|
||||||
|
|
||||||
|
export const LendingObligationLayout: typeof BufferLayout.Structure = BufferLayout.struct(
|
||||||
|
[
|
||||||
|
/// Slot when obligation was updated. Used for calculating interest.
|
||||||
|
Layout.uint64("lastUpdateSlot"),
|
||||||
|
/// Amount of collateral tokens deposited for this obligation
|
||||||
|
Layout.uint64("collateralAmount"),
|
||||||
|
/// Reserve which collateral tokens were deposited into
|
||||||
|
Layout.publicKey("collateralSupply"),
|
||||||
|
/// Borrow rate used for calculating interest.
|
||||||
|
Layout.uint128("cumulativeBorrowRate"),
|
||||||
|
/// Amount of tokens borrowed for this obligation plus interest
|
||||||
|
Layout.uint128("borrowAmount"),
|
||||||
|
/// Reserve which tokens were borrowed from
|
||||||
|
Layout.publicKey("borrowReserve"),
|
||||||
|
/// Mint address of the tokens for this obligation
|
||||||
|
Layout.publicKey("tokenMint"),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface LendingObligation {
|
||||||
|
lastUpdateSlot: BN;
|
||||||
|
collateralAmount: BN;
|
||||||
|
collateralSupply: PublicKey;
|
||||||
|
cumulativeBorrowRate: BN; // decimals
|
||||||
|
borrowAmount: BN; // decimals
|
||||||
|
borrowReserve: PublicKey;
|
||||||
|
tokenMint: PublicKey;
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import * as BufferLayout from "buffer-layout";
|
||||||
import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids";
|
import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids";
|
||||||
import { sendTransaction } from "../../contexts/connection";
|
import { sendTransaction } from "../../contexts/connection";
|
||||||
import * as Layout from "./../../utils/layout";
|
import * as Layout from "./../../utils/layout";
|
||||||
|
import { LendingInstruction } from './lending';
|
||||||
|
|
||||||
export const LendingReserveLayout: typeof BufferLayout.Structure = BufferLayout.struct(
|
export const LendingReserveLayout: typeof BufferLayout.Structure = BufferLayout.struct(
|
||||||
[
|
[
|
||||||
|
@ -108,7 +109,7 @@ export const initReserveInstruction = (
|
||||||
const data = Buffer.alloc(dataLayout.span);
|
const data = Buffer.alloc(dataLayout.span);
|
||||||
dataLayout.encode(
|
dataLayout.encode(
|
||||||
{
|
{
|
||||||
instruction: 1, // Init reserve instruction
|
instruction: LendingInstruction.InitReserve, // Init reserve instruction
|
||||||
liquidityAmount: new BN(liquidityAmount),
|
liquidityAmount: new BN(liquidityAmount),
|
||||||
maxUtilizationRate: maxUtilizationRate,
|
maxUtilizationRate: maxUtilizationRate,
|
||||||
},
|
},
|
||||||
|
@ -169,7 +170,7 @@ export const depositInstruction = (
|
||||||
const data = Buffer.alloc(dataLayout.span);
|
const data = Buffer.alloc(dataLayout.span);
|
||||||
dataLayout.encode(
|
dataLayout.encode(
|
||||||
{
|
{
|
||||||
instruction: 2, // Deposit instruction
|
instruction: LendingInstruction.DepositReserveLiquidity, // Deposit instruction
|
||||||
liquidityAmount: new BN(liquidityAmount),
|
liquidityAmount: new BN(liquidityAmount),
|
||||||
},
|
},
|
||||||
data
|
data
|
||||||
|
|
Loading…
Reference in New Issue