From 3b98580cbbeb0e32f253edd1bfb94c6fcb1af98c Mon Sep 17 00:00:00 2001 From: codewithgun Date: Mon, 30 Dec 2024 22:44:04 +0800 Subject: [PATCH] refactor: remove seed liquidity from sdk --- ts-client/src/dlmm/index.ts | 544 +---------------- ts-client/src/dlmm/types/index.ts | 5 - ts-client/src/test/ilm.test.ts | 549 ------------------ .../test/position_managed_by_operator.test.ts | 420 -------------- ts-client/src/test/single_bin.test.ts | 242 -------- 5 files changed, 1 insertion(+), 1759 deletions(-) delete mode 100644 ts-client/src/test/ilm.test.ts delete mode 100644 ts-client/src/test/position_managed_by_operator.test.ts delete mode 100644 ts-client/src/test/single_bin.test.ts diff --git a/ts-client/src/dlmm/index.ts b/ts-client/src/dlmm/index.ts index 8265c12c..e0690b57 100644 --- a/ts-client/src/dlmm/index.ts +++ b/ts-client/src/dlmm/index.ts @@ -5,15 +5,12 @@ import { NATIVE_MINT, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, - createAssociatedTokenAccountInstruction, - createTransferInstruction, getAssociatedTokenAddressSync, unpackMint, } from "@solana/spl-token"; import { AccountMeta, Cluster, - ComputeBudgetProgram, Connection, PublicKey, SYSVAR_CLOCK_PUBKEY, @@ -86,15 +83,7 @@ import { presetParameter2BinStepFilter, } from "./helpers/accountFilters"; import { DEFAULT_ADD_LIQUIDITY_CU } from "./helpers/computeUnit"; -import { - Rounding, - compressBinAmount, - computeBaseFactorFromFeeBps, - distributeAmountToCompressedBinsByRatio, - generateAmountForBinRange, - getPositionCount, - mulShr, -} from "./helpers/math"; +import { Rounding, computeBaseFactorFromFeeBps, mulShr } from "./helpers/math"; import { DynamicPosition, IPosition, @@ -120,11 +109,9 @@ import { BinArrayBitmapExtension, BinArrayBitmapExtensionAccount, BinLiquidity, - BinLiquidityDistribution, ClmmProgram, Clock, ClockLayout, - CompressedBinDepositAmounts, EmissionRate, FeeInfo, InitCustomizablePermissionlessPairIx, @@ -134,7 +121,6 @@ import { LbPairAccount, LbPosition, LiquidityOneSideParameter, - LiquidityParameter, LiquidityParameterByStrategy, LiquidityParameterByWeight, MEMO_PROGRAM_ID, @@ -147,7 +133,6 @@ import { ProgramStrategyParameter, RemainingAccountsInfoSlice, ResizeSide, - SeedLiquidityResponse, SwapExactOutParams, SwapFee, SwapParams, @@ -4687,533 +4672,6 @@ export class DLMM { ); } - /** - * The `seedLiquidity` function create multiple grouped instructions. The grouped instructions will be either [initialize bin array + initialize position instructions] or [deposit instruction] combination. - * @param - * - `owner`: The public key of the positions owner. - * - `seedAmount`: Lamport amount to be seeded to the pool. - * - `minPrice`: Start price in UI format - * - `maxPrice`: End price in UI format - * - `base`: Base key - * @returns {Promise} - */ - public async seedLiquidity( - owner: PublicKey, - seedAmount: BN, - curvature: number, - minPrice: number, - maxPrice: number, - base: PublicKey - ): Promise { - const toLamportMultiplier = new Decimal( - 10 ** (this.tokenY.mint.decimals - this.tokenX.mint.decimals) - ); - - const minPricePerLamport = new Decimal(minPrice).mul(toLamportMultiplier); - const maxPricePerLamport = new Decimal(maxPrice).mul(toLamportMultiplier); - - const minBinId = new BN( - DLMM.getBinIdFromPrice(minPricePerLamport, this.lbPair.binStep, false) - ); - - const maxBinId = new BN( - DLMM.getBinIdFromPrice(maxPricePerLamport, this.lbPair.binStep, true) - ); - - if (minBinId.toNumber() < this.lbPair.activeId) { - throw new Error("minPrice < current pair price"); - } - - if (minBinId.toNumber() >= maxBinId.toNumber()) { - throw new Error("Price range too small"); - } - - // Generate amount for each bin - const k = 1.0 / curvature; - - const binDepositAmount = generateAmountForBinRange( - seedAmount, - this.lbPair.binStep, - this.tokenX.mint.decimals, - this.tokenY.mint.decimals, - minBinId, - maxBinId, - k - ); - - const decompressMultiplier = new BN(10 ** this.tokenX.mint.decimals); - - let { compressedBinAmount, compressionLoss } = compressBinAmount( - binDepositAmount, - decompressMultiplier - ); - - // Distribute loss after compression back to bins based on bin ratio with total deposited amount - let { - newCompressedBinAmount: compressedBinDepositAmount, - loss: finalLoss, - } = distributeAmountToCompressedBinsByRatio( - compressedBinAmount, - compressionLoss, - decompressMultiplier, - new BN(2 ** 32 - 1) // u32 - ); - - // This amount will be deposited to the last bin without compression - const positionCount = getPositionCount(minBinId, maxBinId.sub(new BN(1))); - - const seederTokenX = getAssociatedTokenAddressSync( - this.lbPair.tokenXMint, - owner, - false - ); - - const initializeBinArraysAndPositionIxs = []; - const addLiquidityIxs = []; - const appendedInitBinArrayIx = new Set(); - - for (let i = 0; i < positionCount.toNumber(); i++) { - const lowerBinId = minBinId.add(DEFAULT_BIN_PER_POSITION.mul(new BN(i))); - const upperBinId = lowerBinId - .add(DEFAULT_BIN_PER_POSITION) - .sub(new BN(1)); - - const lowerBinArrayIndex = binIdToBinArrayIndex(lowerBinId); - const upperBinArrayIndex = binIdToBinArrayIndex(upperBinId); - - const [positionPda, _bump] = derivePosition( - this.pubkey, - base, - lowerBinId, - DEFAULT_BIN_PER_POSITION, - this.program.programId - ); - - const [lowerBinArray] = deriveBinArray( - this.pubkey, - lowerBinArrayIndex, - this.program.programId - ); - - const [upperBinArray] = deriveBinArray( - this.pubkey, - upperBinArrayIndex, - this.program.programId - ); - - const accounts = - await this.program.provider.connection.getMultipleAccountsInfo([ - lowerBinArray, - upperBinArray, - positionPda, - ]); - - let instructions: TransactionInstruction[] = []; - - const lowerBinArrayAccount = accounts[0]; - if ( - !lowerBinArrayAccount && - !appendedInitBinArrayIx.has(lowerBinArray.toBase58()) - ) { - instructions.push( - await this.program.methods - .initializeBinArray(lowerBinArrayIndex) - .accounts({ - lbPair: this.pubkey, - binArray: lowerBinArray, - funder: owner, - }) - .instruction() - ); - - appendedInitBinArrayIx.add(lowerBinArray.toBase58()); - } - - const upperBinArrayAccount = accounts[1]; - if ( - !upperBinArrayAccount && - !appendedInitBinArrayIx.has(upperBinArray.toBase58()) - ) { - instructions.push( - await this.program.methods - .initializeBinArray(upperBinArrayIndex) - .accounts({ - lbPair: this.pubkey, - binArray: upperBinArray, - funder: owner, - }) - .instruction() - ); - - appendedInitBinArrayIx.add(upperBinArray.toBase58()); - } - - const positionAccount = accounts[2]; - if (!positionAccount) { - instructions.push( - await this.program.methods - .initializePositionPda( - lowerBinId.toNumber(), - DEFAULT_BIN_PER_POSITION.toNumber() - ) - .accounts({ - lbPair: this.pubkey, - position: positionPda, - base, - owner, - payer: owner, - }) - .instruction() - ); - } - - // Initialize bin arrays and initialize position account in 1 tx - if (instructions.length > 1) { - instructions.push( - await getEstimatedComputeUnitIxWithBuffer( - this.program.provider.connection, - instructions, - owner - ) - ); - initializeBinArraysAndPositionIxs.push(instructions); - instructions = []; - } - - const positionDeposited = - positionAccount && - wrapPosition(this.program, positionPda, positionAccount) - .liquidityShares() - .reduce((total, cur) => total.add(cur), new BN(0)) - .gt(new BN(0)); - - if (!positionDeposited) { - const cappedUpperBinId = Math.min( - upperBinId.toNumber(), - maxBinId.toNumber() - 1 - ); - - const bins: CompressedBinDepositAmounts = []; - - for (let i = lowerBinId.toNumber(); i <= cappedUpperBinId; i++) { - bins.push({ - binId: i, - amount: compressedBinDepositAmount.get(i).toNumber(), - }); - } - - // TODO: support token2022 - instructions.push( - await this.program.methods - .addLiquidityOneSidePrecise({ - bins, - decompressMultiplier, - }) - .accounts({ - position: positionPda, - lbPair: this.pubkey, - binArrayBitmapExtension: this.binArrayBitmapExtension - ? this.binArrayBitmapExtension.publicKey - : this.program.programId, - userToken: seederTokenX, - reserve: this.lbPair.reserveX, - tokenMint: this.lbPair.tokenXMint, - binArrayLower: lowerBinArray, - binArrayUpper: upperBinArray, - sender: owner, - }) - .instruction() - ); - - // Last position - if (i + 1 >= positionCount.toNumber() && !finalLoss.isZero()) { - instructions.push( - await this.program.methods - .addLiquidityOneSide({ - amount: finalLoss, - activeId: this.lbPair.activeId, - maxActiveBinSlippage: 0, - binLiquidityDist: [ - { - binId: cappedUpperBinId, - weight: 1, - }, - ], - }) - .accounts({ - position: positionPda, - lbPair: this.pubkey, - binArrayBitmapExtension: this.binArrayBitmapExtension - ? this.binArrayBitmapExtension.publicKey - : this.program.programId, - userToken: seederTokenX, - reserve: this.lbPair.reserveX, - tokenMint: this.lbPair.tokenXMint, - binArrayLower: lowerBinArray, - binArrayUpper: upperBinArray, - sender: owner, - }) - .instruction() - ); - } - - addLiquidityIxs.push([ - ComputeBudgetProgram.setComputeUnitLimit({ - units: DEFAULT_ADD_LIQUIDITY_CU, - }), - ...instructions, - ]); - } - } - - return { - initializeBinArraysAndPositionIxs, - addLiquidityIxs, - }; - } - - /** - * The `seedLiquidity` function create multiple grouped instructions. The grouped instructions will be either [initialize bin array + initialize position instructions] or [deposit instruction] combination. - * @param - * - `payer`: The public key of the tx payer. - * - `base`: Base key - * - `seedAmount`: Token X lamport amount to be seeded to the pool. - * - `price`: TokenX/TokenY Price in UI format - * - `roundingUp`: Whether to round up the price - * - `positionOwner`: The owner of the position - * - `feeOwner`: Position fee owner - * - `operator`: Operator of the position. Operator able to manage the position on behalf of the position owner. However, liquidity withdrawal issue by the operator can only send to the position owner. - * - `lockReleasePoint`: The lock release point of the position. - * - `shouldSeedPositionOwner` (optional): Whether to send 1 lamport amount of token X to the position owner to prove ownership. - * - * The returned instructions need to be executed sequentially if it was separated into multiple transactions. - * @returns {Promise} - */ - public async seedLiquiditySingleBin( - payer: PublicKey, - base: PublicKey, - seedAmount: BN, - price: number, - roundingUp: boolean, - positionOwner: PublicKey, - feeOwner: PublicKey, - operator: PublicKey, - lockReleasePoint: BN, - shouldSeedPositionOwner: boolean = false - ): Promise { - const pricePerLamport = DLMM.getPricePerLamport( - this.tokenX.mint.decimals, - this.tokenY.mint.decimals, - price - ); - const binIdNumber = DLMM.getBinIdFromPrice( - pricePerLamport, - this.lbPair.binStep, - !roundingUp - ); - - const binId = new BN(binIdNumber); - - const [positionPda] = derivePosition( - this.pubkey, - base, - binId, - new BN(1), - this.program.programId - ); - - const binArrayIndex = binIdToBinArrayIndex(binId); - const [binArrayKey] = deriveBinArray( - this.pubkey, - binArrayIndex, - this.program.programId - ); - - const preInstructions = []; - - const [ - { ataPubKey: userTokenX, ix: createPayerTokenXIx }, - { ataPubKey: userTokenY, ix: createPayerTokenYIx }, - ] = await Promise.all([ - getOrCreateATAInstruction( - this.program.provider.connection, - this.tokenX.publicKey, - operator, - payer - ), - getOrCreateATAInstruction( - this.program.provider.connection, - this.tokenY.publicKey, - operator, - payer - ), - ]); - - // create userTokenX and userTokenY accounts - createPayerTokenXIx && preInstructions.push(createPayerTokenXIx); - createPayerTokenYIx && preInstructions.push(createPayerTokenYIx); - - let [binArrayBitmapExtension] = deriveBinArrayBitmapExtension( - this.pubkey, - this.program.programId - ); - - const [binArrayAccount, positionAccount, bitmapExtensionAccount] = - await this.program.provider.connection.getMultipleAccountsInfo([ - binArrayKey, - positionPda, - binArrayBitmapExtension, - ]); - - if (isOverflowDefaultBinArrayBitmap(binArrayIndex)) { - if (!bitmapExtensionAccount) { - preInstructions.push( - await this.program.methods - .initializeBinArrayBitmapExtension() - .accounts({ - binArrayBitmapExtension, - funder: payer, - lbPair: this.pubkey, - }) - .instruction() - ); - } - } else { - binArrayBitmapExtension = this.program.programId; - } - - const operatorTokenX = getAssociatedTokenAddressSync( - this.lbPair.tokenXMint, - operator, - true - ); - const positionOwnerTokenX = getAssociatedTokenAddressSync( - this.lbPair.tokenXMint, - positionOwner, - true - ); - - if (shouldSeedPositionOwner) { - const positionOwnerTokenXAccount = - await this.program.provider.connection.getAccountInfo( - positionOwnerTokenX - ); - if (positionOwnerTokenXAccount) { - const account = AccountLayout.decode(positionOwnerTokenXAccount.data); - if (account.amount == BigInt(0)) { - // send 1 lamport to position owner token X to prove ownership - const transferIx = createTransferInstruction( - operatorTokenX, - positionOwnerTokenX, - payer, - 1 - ); - preInstructions.push(transferIx); - } - } else { - const createPositionOwnerTokenXIx = - createAssociatedTokenAccountInstruction( - payer, - positionOwnerTokenX, - positionOwner, - this.lbPair.tokenXMint - ); - preInstructions.push(createPositionOwnerTokenXIx); - - // send 1 lamport to position owner token X to prove ownership - const transferIx = createTransferInstruction( - operatorTokenX, - positionOwnerTokenX, - payer, - 1 - ); - preInstructions.push(transferIx); - } - } - - if (!binArrayAccount) { - preInstructions.push( - await this.program.methods - .initializeBinArray(binArrayIndex) - .accounts({ - binArray: binArrayKey, - funder: payer, - lbPair: this.pubkey, - }) - .instruction() - ); - } - - if (!positionAccount) { - preInstructions.push( - await this.program.methods - .initializePositionByOperator( - binId.toNumber(), - 1, - feeOwner, - lockReleasePoint - ) - .accounts({ - payer, - base, - position: positionPda, - lbPair: this.pubkey, - owner: positionOwner, - operator, - operatorTokenX, - ownerTokenX: positionOwnerTokenX, - }) - .instruction() - ); - } - - const binLiquidityDist: BinLiquidityDistribution = { - binId: binIdNumber, - distributionX: BASIS_POINT_MAX, - distributionY: 0, - }; - - const addLiquidityParams: LiquidityParameter = { - amountX: seedAmount, - amountY: new BN(0), - binLiquidityDist: [binLiquidityDist], - }; - - const { slices, accounts: transferHookAccounts } = - this.getPotentialToken2022IxDataAndAccounts(ActionType.Liquidity); - - const depositLiquidityIx = await this.program.methods - .addLiquidity2(addLiquidityParams, { - slices, - }) - .accounts({ - position: positionPda, - lbPair: this.pubkey, - binArrayBitmapExtension, - userTokenX, - userTokenY, - reserveX: this.lbPair.reserveX, - reserveY: this.lbPair.reserveY, - tokenXMint: this.lbPair.tokenXMint, - tokenYMint: this.lbPair.tokenYMint, - sender: operator, - tokenXProgram: TOKEN_PROGRAM_ID, - tokenYProgram: TOKEN_PROGRAM_ID, - memoProgram: MEMO_PROGRAM_ID, - }) - .remainingAccounts(transferHookAccounts) - .remainingAccounts([ - { - pubkey: binArrayKey, - isSigner: false, - isWritable: true, - }, - ]) - .instruction(); - - return [...preInstructions, depositLiquidityIx]; - } - /** * Initializes bin arrays for the given bin array indexes if it wasn't initialized. * diff --git a/ts-client/src/dlmm/types/index.ts b/ts-client/src/dlmm/types/index.ts index 85330906..0dae11f5 100644 --- a/ts-client/src/dlmm/types/index.ts +++ b/ts-client/src/dlmm/types/index.ts @@ -416,11 +416,6 @@ export enum BitmapType { U512, } -export interface SeedLiquidityResponse { - initializeBinArraysAndPositionIxs: TransactionInstruction[][]; - addLiquidityIxs: TransactionInstruction[][]; -} - export interface Clock { slot: BN; epochStartTimestamp: BN; diff --git a/ts-client/src/test/ilm.test.ts b/ts-client/src/test/ilm.test.ts deleted file mode 100644 index cb25396d..00000000 --- a/ts-client/src/test/ilm.test.ts +++ /dev/null @@ -1,549 +0,0 @@ -import { BN, web3 } from "@coral-xyz/anchor"; -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - createMint, - getOrCreateAssociatedTokenAccount, - mintTo, -} from "@solana/spl-token"; -import { - Connection, - Keypair, - PublicKey, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import babar from "babar"; -import Decimal from "decimal.js"; -import fs from "fs"; -import { LBCLMM_PROGRAM_IDS } from "../dlmm/constants"; -import { - deriveCustomizablePermissionlessLbPair, - getBinArrayLowerUpperBinId, - getPriceOfBinByBinId, -} from "../dlmm/helpers"; -import { DLMM } from "../dlmm/index"; -import { ActivationType } from "../dlmm/types"; - -const keypairBuffer = fs.readFileSync( - "../keys/localnet/admin-bossj3JvwiNK7pvjr149DqdtJxf2gdygbcmEPTkb2F1.json", - "utf-8" -); -const connection = new Connection("http://127.0.0.1:8899", "confirmed"); -const keypair = Keypair.fromSecretKey( - new Uint8Array(JSON.parse(keypairBuffer)) -); -const programId = new PublicKey(LBCLMM_PROGRAM_IDS["localhost"]); - -describe("ILM test", () => { - describe("WEN", () => { - const baseKeypair = Keypair.generate(); - const wenDecimal = 5; - const usdcDecimal = 6; - const feeBps = new BN(500); - const lockDuration = new BN(0); - - let WEN: web3.PublicKey; - let USDC: web3.PublicKey; - let userWEN: web3.PublicKey; - let userUSDC: web3.PublicKey; - let pairKey: web3.PublicKey; - let pair: DLMM; - - const toLamportMultiplier = new Decimal(10 ** (wenDecimal - usdcDecimal)); - - const minPrice = 0.000001; - const maxPrice = 0.00003; - const binStep = 100; - const curvature = 0.6; - const seedAmount = new BN(200_000_000_000); - - const minBinId = DLMM.getBinIdFromPrice( - new Decimal(minPrice).mul(toLamportMultiplier), - binStep, - false - ); - - beforeAll(async () => { - WEN = await createMint( - connection, - keypair, - keypair.publicKey, - null, - wenDecimal, - Keypair.generate(), - null, - TOKEN_PROGRAM_ID - ); - - USDC = await createMint( - connection, - keypair, - keypair.publicKey, - null, - usdcDecimal, - Keypair.generate(), - null, - TOKEN_PROGRAM_ID - ); - - const userWenInfo = await getOrCreateAssociatedTokenAccount( - connection, - keypair, - WEN, - keypair.publicKey, - false, - "confirmed", - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ); - userWEN = userWenInfo.address; - - const userUsdcInfo = await getOrCreateAssociatedTokenAccount( - connection, - keypair, - USDC, - keypair.publicKey, - false, - "confirmed", - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ); - userUSDC = userUsdcInfo.address; - - await mintTo( - connection, - keypair, - WEN, - userWEN, - keypair.publicKey, - 200_000_000_000 * 10 ** wenDecimal, - [], - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID - ); - - await mintTo( - connection, - keypair, - USDC, - userUSDC, - keypair.publicKey, - 1_000_000_000 * 10 ** usdcDecimal, - [], - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID - ); - - const slot = await connection.getSlot(); - const activationPoint = new BN(slot).add(new BN(100)); - - let rawTx = await DLMM.createCustomizablePermissionlessLbPair( - connection, - new BN(binStep), - WEN, - USDC, - new BN(minBinId.toString()), - feeBps, - ActivationType.Slot, - false, // No alpha vault. Set to true the program will deterministically whitelist the alpha vault to swap before the pool start trading. Check: https://github.com/MeteoraAg/alpha-vault-sdk initialize{Prorata|Fcfs}Vault method to create the alpha vault. - keypair.publicKey, - activationPoint, - { - cluster: "localhost", - } - ); - - let txHash = await sendAndConfirmTransaction(connection, rawTx, [ - keypair, - ]).catch((e) => { - console.error(e); - throw e; - }); - console.log("Create permissioned LB pair", txHash); - - [pairKey] = deriveCustomizablePermissionlessLbPair(WEN, USDC, programId); - - pair = await DLMM.create(connection, pairKey, { - cluster: "localhost", - }); - }); - - it("seed liquidity", async () => { - const { initializeBinArraysAndPositionIxs, addLiquidityIxs } = - await pair.seedLiquidity( - keypair.publicKey, - seedAmount, - curvature, - minPrice, - maxPrice, - baseKeypair.publicKey - ); - - // Initialize all bin array and position, transaction order can be in sequence or not - { - const { blockhash, lastValidBlockHeight } = - await connection.getLatestBlockhash("confirmed"); - const transactions = []; - - for (const groupIx of initializeBinArraysAndPositionIxs) { - const tx = new Transaction({ - feePayer: keypair.publicKey, - blockhash, - lastValidBlockHeight, - }).add(...groupIx); - - const signers = [keypair, baseKeypair]; - - transactions.push(sendAndConfirmTransaction(connection, tx, signers)); - } - - await Promise.all(transactions) - .then((txs) => { - txs.map(console.log); - }) - .catch((e) => { - console.error(e); - throw e; - }); - } - - const beforeTokenXBalance = await connection - .getTokenAccountBalance(userWEN) - .then((i) => new BN(i.value.amount)); - - { - const { blockhash, lastValidBlockHeight } = - await connection.getLatestBlockhash("confirmed"); - - const transactions = []; - - // Deposit to positions created in above step. The add liquidity order can be in sequence or not. - for (const groupIx of addLiquidityIxs) { - const tx = new Transaction({ - feePayer: keypair.publicKey, - blockhash, - lastValidBlockHeight, - }).add(...groupIx); - - const signers = [keypair]; - - transactions.push(sendAndConfirmTransaction(connection, tx, signers)); - } - - await Promise.all(transactions) - .then((txs) => { - txs.map(console.log); - }) - .catch((e) => { - console.error(e); - throw e; - }); - } - - const afterTokenXBalance = await connection - .getTokenAccountBalance(userWEN) - .then((i) => new BN(i.value.amount)); - - const actualDepositedAmount = beforeTokenXBalance.sub(afterTokenXBalance); - expect(actualDepositedAmount.toString()).toEqual(seedAmount.toString()); - - let binArrays = await pair.getBinArrays(); - binArrays = binArrays.sort((a, b) => - a.account.index.cmp(b.account.index) - ); - - const binLiquidities = binArrays - .map((ba) => { - const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId( - ba.account.index - ); - const binWithLiquidity: [number, number][] = []; - for (let i = lowerBinId.toNumber(); i <= upperBinId.toNumber(); i++) { - const binAmountX = - ba.account.bins[i - lowerBinId.toNumber()].amountX; - const binPrice = getPriceOfBinByBinId(i, pair.lbPair.binStep); - const liquidity = new Decimal(binAmountX.toString()) - .mul(binPrice) - .floor() - .toNumber(); - binWithLiquidity.push([i, liquidity]); - } - return binWithLiquidity; - }) - .flat(); - - console.log(binLiquidities.filter((b) => b[1] > 0).reverse()); - console.log(binLiquidities.filter((b) => b[1] > 0)); - console.log(babar(binLiquidities)); - }); - }); - - describe("Shaky", () => { - const baseKeypair = Keypair.generate(); - const sharkyDecimal = 6; - const usdcDecimal = 6; - const feeBps = new BN(250); - - let SHARKY: web3.PublicKey; - let USDC: web3.PublicKey; - let userSHAKY: web3.PublicKey; - let userUSDC: web3.PublicKey; - let pairKey: web3.PublicKey; - let pair: DLMM; - - const toLamportMultiplier = new Decimal( - 10 ** (sharkyDecimal - usdcDecimal) - ); - - const minPrice = 0.5; - const maxPrice = 1.62; - const binStep = 80; - const curvature = 1; - const seedAmount = new BN(5_000_000_000_000); - - const minBinId = DLMM.getBinIdFromPrice( - new Decimal(minPrice).mul(toLamportMultiplier), - binStep, - false - ); - - beforeAll(async () => { - SHARKY = await createMint( - connection, - keypair, - keypair.publicKey, - null, - sharkyDecimal, - Keypair.generate(), - null, - TOKEN_PROGRAM_ID - ); - - USDC = await createMint( - connection, - keypair, - keypair.publicKey, - null, - usdcDecimal, - Keypair.generate(), - null, - TOKEN_PROGRAM_ID - ); - - const userShakyInfo = await getOrCreateAssociatedTokenAccount( - connection, - keypair, - SHARKY, - keypair.publicKey, - false, - "confirmed", - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ); - userSHAKY = userShakyInfo.address; - - const userUsdcInfo = await getOrCreateAssociatedTokenAccount( - connection, - keypair, - USDC, - keypair.publicKey, - false, - "confirmed", - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ); - userUSDC = userUsdcInfo.address; - - await mintTo( - connection, - keypair, - SHARKY, - userSHAKY, - keypair.publicKey, - 200_000_000_000 * 10 ** sharkyDecimal, - [], - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID - ); - - await mintTo( - connection, - keypair, - USDC, - userUSDC, - keypair.publicKey, - 1_000_000_000 * 10 ** usdcDecimal, - [], - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID - ); - - const slot = await connection.getSlot(); - const activationPoint = new BN(slot).add(new BN(100)); - - let rawTx = await DLMM.createCustomizablePermissionlessLbPair( - connection, - new BN(binStep), - SHARKY, - USDC, - new BN(minBinId.toString()), - feeBps, - ActivationType.Slot, - false, // No alpha vault. Set to true the program will deterministically whitelist the alpha vault to swap before the pool start trading. Check: https://github.com/MeteoraAg/alpha-vault-sdk initialize{Prorata|Fcfs}Vault method to create the alpha vault. - keypair.publicKey, - activationPoint, - { - cluster: "localhost", - } - ); - - let txHash = await sendAndConfirmTransaction(connection, rawTx, [ - keypair, - ]).catch((e) => { - console.error(e); - throw e; - }); - console.log("Create permissioned LB pair", txHash); - - [pairKey] = deriveCustomizablePermissionlessLbPair( - SHARKY, - USDC, - programId - ); - - pair = await DLMM.create(connection, pairKey, { - cluster: "localhost", - }); - }); - - it("seed liquidity", async () => { - const { initializeBinArraysAndPositionIxs, addLiquidityIxs } = - await pair.seedLiquidity( - keypair.publicKey, - seedAmount, - curvature, - minPrice, - maxPrice, - baseKeypair.publicKey - ); - - // Initialize all bin array and position, transaction order can be in sequence or not - { - const { blockhash, lastValidBlockHeight } = - await connection.getLatestBlockhash("confirmed"); - const transactions = []; - - for (const groupIx of initializeBinArraysAndPositionIxs) { - const tx = new Transaction({ - feePayer: keypair.publicKey, - blockhash, - lastValidBlockHeight, - }).add(...groupIx); - - const signers = [keypair, baseKeypair]; - - transactions.push(sendAndConfirmTransaction(connection, tx, signers)); - } - - await Promise.all(transactions) - .then((txs) => { - txs.map(console.log); - }) - .catch((e) => { - console.error(e); - throw e; - }); - } - - const beforeTokenXBalance = await connection - .getTokenAccountBalance(userSHAKY) - .then((i) => new BN(i.value.amount)); - - { - const { blockhash, lastValidBlockHeight } = - await connection.getLatestBlockhash("confirmed"); - - const transactions = []; - - // Deposit to positions created in above step. The add liquidity order can be in sequence or not. - for (const groupIx of addLiquidityIxs) { - const tx = new Transaction({ - feePayer: keypair.publicKey, - blockhash, - lastValidBlockHeight, - }).add(...groupIx); - - const signers = [keypair]; - - transactions.push(sendAndConfirmTransaction(connection, tx, signers)); - } - - await Promise.all(transactions) - .then((txs) => { - txs.map(console.log); - }) - .catch((e) => { - console.error(e); - throw e; - }); - } - - const afterTokenXBalance = await connection - .getTokenAccountBalance(userSHAKY) - .then((i) => new BN(i.value.amount)); - - const actualDepositedAmount = beforeTokenXBalance.sub(afterTokenXBalance); - expect(actualDepositedAmount.toString()).toEqual(seedAmount.toString()); - - let binArrays = await pair.getBinArrays(); - binArrays = binArrays.sort((a, b) => - a.account.index.cmp(b.account.index) - ); - - const binLiquidities = binArrays - .map((ba) => { - const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId( - ba.account.index - ); - const binWithLiquidity: [number, number][] = []; - for (let i = lowerBinId.toNumber(); i <= upperBinId.toNumber(); i++) { - const binAmountX = - ba.account.bins[i - lowerBinId.toNumber()].amountX; - const binPrice = getPriceOfBinByBinId(i, pair.lbPair.binStep); - const liquidity = new Decimal(binAmountX.toString()) - .mul(binPrice) - .floor() - .toNumber(); - binWithLiquidity.push([i, liquidity]); - } - return binWithLiquidity; - }) - .flat(); - - console.log(binLiquidities.filter((b) => b[1] > 0).reverse()); - console.log(binLiquidities.filter((b) => b[1] > 0)); - console.log(babar(binLiquidities)); - }); - }); -}); diff --git a/ts-client/src/test/position_managed_by_operator.test.ts b/ts-client/src/test/position_managed_by_operator.test.ts deleted file mode 100644 index 956fd4d7..00000000 --- a/ts-client/src/test/position_managed_by_operator.test.ts +++ /dev/null @@ -1,420 +0,0 @@ -// import { BN, web3 } from "@coral-xyz/anchor"; -// import { -// ASSOCIATED_TOKEN_PROGRAM_ID, -// TOKEN_PROGRAM_ID, -// createMint, -// getAssociatedTokenAddressSync, -// getOrCreateAssociatedTokenAccount, -// mintTo, -// } from "@solana/spl-token"; -// import { -// Connection, -// Keypair, -// LAMPORTS_PER_SOL, -// PublicKey, -// sendAndConfirmTransaction, -// } from "@solana/web3.js"; -// import Decimal from "decimal.js"; -// import fs from "fs"; -// import { -// LBCLMM_PROGRAM_IDS, -// DEFAULT_BIN_PER_POSITION, -// } from "../dlmm/constants"; -// import { derivePermissionLbPair, derivePosition } from "../dlmm/helpers"; -// import { DLMM } from "../dlmm/index"; -// import { ActivationType, StrategyType } from "../dlmm/types"; - -// const keypairBuffer = fs.readFileSync( -// "../keys/localnet/admin-bossj3JvwiNK7pvjr149DqdtJxf2gdygbcmEPTkb2F1.json", -// "utf-8" -// ); -// const connection = new Connection("http://127.0.0.1:8899", "confirmed"); -// const keypair = Keypair.fromSecretKey( -// new Uint8Array(JSON.parse(keypairBuffer)) -// ); -// const programId = new PublicKey(LBCLMM_PROGRAM_IDS["localhost"]); - -// describe("Position by operator", () => { -// describe("Position by operator management", () => { -// const baseKeypair = Keypair.generate(); -// const wenDecimal = 5; -// const usdcDecimal = 6; -// const feeBps = new BN(500); - -// let WEN: web3.PublicKey; -// let USDC: web3.PublicKey; -// let operatorWEN: web3.PublicKey; -// let operatorUSDC: web3.PublicKey; -// let pairKey: web3.PublicKey; -// let pair: DLMM; -// let position: web3.PublicKey; - -// const toLamportMultiplier = new Decimal(10 ** (wenDecimal - usdcDecimal)); - -// const minPrice = 1; -// const binStep = 100; - -// const minBinId = DLMM.getBinIdFromPrice( -// new Decimal(minPrice).mul(toLamportMultiplier), -// binStep, -// false -// ); - -// const operatorKeypair = Keypair.generate(); -// const mockMultisigKeypair = Keypair.generate(); - -// beforeAll(async () => { -// const signature = await connection.requestAirdrop( -// operatorKeypair.publicKey, -// 10 * LAMPORTS_PER_SOL -// ); -// await connection.confirmTransaction(signature, "finalized"); - -// WEN = await createMint( -// connection, -// keypair, -// keypair.publicKey, -// null, -// wenDecimal, -// Keypair.generate(), -// null, -// TOKEN_PROGRAM_ID -// ); - -// USDC = await createMint( -// connection, -// keypair, -// keypair.publicKey, -// null, -// usdcDecimal, -// Keypair.generate(), -// null, -// TOKEN_PROGRAM_ID -// ); - -// const operatorWenInfo = await getOrCreateAssociatedTokenAccount( -// connection, -// keypair, -// WEN, -// operatorKeypair.publicKey, -// false, -// "confirmed", -// { -// commitment: "confirmed", -// }, -// TOKEN_PROGRAM_ID, -// ASSOCIATED_TOKEN_PROGRAM_ID -// ); -// operatorWEN = operatorWenInfo.address; - -// const mockMultisigWenInfo = await getOrCreateAssociatedTokenAccount( -// connection, -// keypair, -// WEN, -// mockMultisigKeypair.publicKey, -// true, -// "confirmed", -// { -// commitment: "confirmed", -// }, -// TOKEN_PROGRAM_ID, -// ASSOCIATED_TOKEN_PROGRAM_ID -// ); - -// const operatorUsdcInfo = await getOrCreateAssociatedTokenAccount( -// connection, -// keypair, -// USDC, -// operatorKeypair.publicKey, -// false, -// "confirmed", -// { -// commitment: "confirmed", -// }, -// TOKEN_PROGRAM_ID, -// ASSOCIATED_TOKEN_PROGRAM_ID -// ); -// operatorUSDC = operatorUsdcInfo.address; - -// await mintTo( -// connection, -// keypair, -// WEN, -// operatorWEN, -// keypair.publicKey, -// 200_000_000_000 * 10 ** wenDecimal, -// [], -// { -// commitment: "confirmed", -// }, -// TOKEN_PROGRAM_ID -// ); - -// await mintTo( -// connection, -// keypair, -// USDC, -// operatorUSDC, -// keypair.publicKey, -// 1_000_000_000 * 10 ** usdcDecimal, -// [], -// { -// commitment: "confirmed", -// }, -// TOKEN_PROGRAM_ID -// ); - -// await mintTo( -// connection, -// keypair, -// WEN, -// mockMultisigWenInfo.address, -// keypair.publicKey, -// 200_000_000_000 * 10 ** wenDecimal, -// [], -// {} -// ); - -// let rawTx = await DLMM.createPermissionLbPair( -// connection, -// new BN(binStep), -// WEN, -// USDC, -// new BN(minBinId.toString()), -// baseKeypair.publicKey, -// keypair.publicKey, -// feeBps, -// ActivationType.Slot, -// { cluster: "localhost" } -// ); -// let txHash = await sendAndConfirmTransaction(connection, rawTx, [ -// keypair, -// baseKeypair, -// ]).catch((e) => { -// console.error(e); -// throw e; -// }); -// console.log("Create permissioned LB pair", txHash); - -// [pairKey] = derivePermissionLbPair( -// baseKeypair.publicKey, -// WEN, -// USDC, -// new BN(binStep), -// programId -// ); - -// pair = await DLMM.create(connection, pairKey, { -// cluster: "localhost", -// }); -// }); - -// it("Create position with operator", async () => { -// await pair.refetchStates(); - -// const lowerBinId = new BN(minBinId).sub( -// DEFAULT_BIN_PER_POSITION.div(new BN(2)) -// ); -// const positionWidth = new BN(DEFAULT_BIN_PER_POSITION); - -// const transaction = await pair.initializePositionByOperator({ -// lowerBinId, -// positionWidth: new BN(DEFAULT_BIN_PER_POSITION), -// owner: mockMultisigKeypair.publicKey, -// feeOwner: mockMultisigKeypair.publicKey, -// operator: operatorKeypair.publicKey, -// payer: operatorKeypair.publicKey, -// base: baseKeypair.publicKey, -// lockReleasePoint: new BN(0), -// }); - -// const txHash = await sendAndConfirmTransaction(connection, transaction, [ -// operatorKeypair, -// baseKeypair, -// ]).catch((e) => { -// console.error(e); -// throw e; -// }); - -// console.log("Initialize position with operator", txHash); - -// [position] = derivePosition( -// pair.pubkey, -// baseKeypair.publicKey, -// lowerBinId, -// positionWidth, -// pair.program.programId -// ); - -// const positionState = await pair.program.account.positionV2.fetch( -// position -// ); - -// expect(positionState.owner.toBase58()).toBe( -// mockMultisigKeypair.publicKey.toBase58() -// ); -// expect(positionState.feeOwner.toBase58()).toBe( -// mockMultisigKeypair.publicKey.toBase58() -// ); -// expect(positionState.operator.toBase58()).toBe( -// operatorKeypair.publicKey.toBase58() -// ); -// }); - -// it("Operator add liquidity to the position", async () => { -// await pair.refetchStates(); - -// const positionState = await pair.program.account.positionV2.fetch( -// position -// ); - -// const [beforeOperatorTokenX, beforeOperatorTokenY] = await Promise.all([ -// connection -// .getTokenAccountBalance(operatorWEN) -// .then((b) => new BN(b.value.amount)), -// connection -// .getTokenAccountBalance(operatorUSDC) -// .then((b) => new BN(b.value.amount)), -// ]); - -// let transaction = await pair.addLiquidityByStrategy({ -// positionPubKey: position, -// totalXAmount: new BN(1000 * 10 ** wenDecimal), -// totalYAmount: new BN(0), -// strategy: { -// strategyType: StrategyType.SpotImBalanced, -// maxBinId: positionState.upperBinId, -// minBinId, -// }, -// user: operatorKeypair.publicKey, -// slippage: 0, -// }); - -// let txHash = await sendAndConfirmTransaction(connection, transaction, [ -// operatorKeypair, -// ]).catch((e) => { -// console.error(e); -// throw e; -// }); - -// transaction = await pair.addLiquidityByStrategy({ -// positionPubKey: position, -// totalXAmount: new BN(0), -// totalYAmount: new BN(1000 * 10 ** usdcDecimal), -// strategy: { -// strategyType: StrategyType.SpotImBalanced, -// maxBinId: minBinId - 1, -// minBinId: positionState.lowerBinId, -// }, -// user: operatorKeypair.publicKey, -// slippage: 0, -// }); - -// txHash = await sendAndConfirmTransaction(connection, transaction, [ -// operatorKeypair, -// ]).catch((e) => { -// console.error(e); -// throw e; -// }); - -// const [afterOperatorTokenX, afterOperatorTokenY] = await Promise.all([ -// connection -// .getTokenAccountBalance(operatorWEN) -// .then((b) => new BN(b.value.amount)), -// connection -// .getTokenAccountBalance(operatorUSDC) -// .then((b) => new BN(b.value.amount)), -// ]); - -// // Debit from operator -// expect(afterOperatorTokenY.lt(beforeOperatorTokenY)).toBeTruthy(); -// expect(afterOperatorTokenX.lt(beforeOperatorTokenX)).toBeTruthy(); - -// console.log("Operator add liquidity to the position", txHash); -// }); - -// it("Operator remove liquidity from the position, owner (multisig) receive the liquidity", async () => { -// await pair.refetchStates(); - -// const positionState = await pair.program.account.positionV2.fetch( -// position -// ); - -// const mockMultisigWEN = getAssociatedTokenAddressSync( -// WEN, -// positionState.owner, -// true, -// TOKEN_PROGRAM_ID -// ); -// const mockMultisigUSDC = getAssociatedTokenAddressSync( -// USDC, -// positionState.owner, -// true, -// TOKEN_PROGRAM_ID -// ); - -// const [beforeOwnerWEN, beforeOwnerUSDC] = await Promise.all([ -// connection -// .getTokenAccountBalance(mockMultisigWEN) -// .then((b) => new BN(b.value.amount)) -// .catch((_) => new BN(0)), -// connection -// .getTokenAccountBalance(mockMultisigUSDC) -// .then((b) => new BN(b.value.amount)) -// .catch((_) => new BN(0)), -// ]); - -// const binIds = []; - -// for ( -// let i = positionState.lowerBinId; -// i <= positionState.upperBinId; -// i++ -// ) { -// binIds.push(i); -// } - -// const transaction = await pair.removeLiquidity({ -// user: operatorKeypair.publicKey, -// position, -// binIds, -// bps: new BN(10000), -// shouldClaimAndClose: true, -// }); - -// const transactions = []; -// if (!Array.isArray(transaction)) { -// transactions.push(transaction); -// } else { -// transactions.push(...transaction); -// } - -// for (const tx of transactions) { -// const txHash = await sendAndConfirmTransaction(connection, tx, [ -// operatorKeypair, -// ]).catch((e) => { -// console.error(e); -// throw e; -// }); - -// console.log( -// "Withdraw to owner, claim fees, and close transaction", -// txHash -// ); -// } - -// const [afterOwnerWEN, afterOwnerUSDC] = await Promise.all([ -// connection -// .getTokenAccountBalance(mockMultisigWEN) -// .then((b) => new BN(b.value.amount)), -// connection -// .getTokenAccountBalance(mockMultisigUSDC) -// .then((b) => new BN(b.value.amount)), -// ]); - -// // Credit to owner -// expect(afterOwnerWEN.gt(beforeOwnerUSDC)).toBeTruthy(); -// expect(afterOwnerUSDC.gt(beforeOwnerUSDC)).toBeTruthy(); -// }); -// }); -// }); diff --git a/ts-client/src/test/single_bin.test.ts b/ts-client/src/test/single_bin.test.ts deleted file mode 100644 index 56fe3415..00000000 --- a/ts-client/src/test/single_bin.test.ts +++ /dev/null @@ -1,242 +0,0 @@ -import { BN, web3 } from "@coral-xyz/anchor"; -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - AccountLayout, - TOKEN_PROGRAM_ID, - createAssociatedTokenAccount, - createMint, - getAssociatedTokenAddressSync, - getOrCreateAssociatedTokenAccount, - mintTo, - transfer, -} from "@solana/spl-token"; -import { - Connection, - Keypair, - PublicKey, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import babar from "babar"; -import Decimal from "decimal.js"; -import fs from "fs"; -import { LBCLMM_PROGRAM_IDS } from "../dlmm/constants"; -import { - deriveCustomizablePermissionlessLbPair, - getBinArrayLowerUpperBinId, - getPriceOfBinByBinId, -} from "../dlmm/helpers"; -import { DLMM } from "../dlmm/index"; -import { ActivationType } from "../dlmm/types"; -import e from "express"; - -const keypairBuffer = fs.readFileSync( - "../keys/localnet/admin-bossj3JvwiNK7pvjr149DqdtJxf2gdygbcmEPTkb2F1.json", - "utf-8" -); -const connection = new Connection("http://127.0.0.1:8899", "confirmed"); -const owner = Keypair.fromSecretKey( - new Uint8Array(JSON.parse(keypairBuffer)) -); -const programId = new PublicKey(LBCLMM_PROGRAM_IDS["localhost"]); - -describe("Single Bin Seed Liquidity Test", () => { - describe("TokenX decimals < TokenY decimals", () => { - const baseKeypair = Keypair.generate(); - const positionOwnerKeypair = Keypair.generate(); - const feeOwnerKeypair = Keypair.generate(); - - const wenDecimal = 5; - const usdcDecimal = 6; - const feeBps = new BN(500); - const initialPrice = 0.000001; - const binStep = 100; - const wenSeedAmount = new BN(200_000 * 10 ** wenDecimal); - - let WEN: web3.PublicKey; - let USDC: web3.PublicKey; - let userWEN: web3.PublicKey; - let userUSDC: web3.PublicKey; - let pairKey: web3.PublicKey; - let pair: DLMM; - let positionOwnerTokenX: web3.PublicKey; - - const initialPricePerLamport = DLMM.getPricePerLamport(wenDecimal, usdcDecimal, initialPrice); - const binId = DLMM.getBinIdFromPrice(initialPricePerLamport, binStep, false); - - beforeAll(async () => { - WEN = await createMint( - connection, - owner, - owner.publicKey, - null, - wenDecimal, - Keypair.generate(), - null, - TOKEN_PROGRAM_ID - ); - - USDC = await createMint( - connection, - owner, - owner.publicKey, - null, - usdcDecimal, - Keypair.generate(), - null, - TOKEN_PROGRAM_ID - ); - - const userWenInfo = await getOrCreateAssociatedTokenAccount( - connection, - owner, - WEN, - owner.publicKey, - false, - "confirmed", - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ); - userWEN = userWenInfo.address; - - const userUsdcInfo = await getOrCreateAssociatedTokenAccount( - connection, - owner, - USDC, - owner.publicKey, - false, - "confirmed", - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ); - userUSDC = userUsdcInfo.address; - - await mintTo( - connection, - owner, - WEN, - userWEN, - owner.publicKey, - wenSeedAmount.toNumber() + 1, - [], - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID - ); - - await mintTo( - connection, - owner, - USDC, - userUSDC, - owner.publicKey, - 1_000_000_000 * 10 ** usdcDecimal, - [], - { - commitment: "confirmed", - }, - TOKEN_PROGRAM_ID - ); - - const slot = await connection.getSlot(); - const activationPoint = new BN(slot).add(new BN(100)); - - let rawTx = await DLMM.createCustomizablePermissionlessLbPair( - connection, - new BN(binStep), - WEN, - USDC, - new BN(binId.toString()), - feeBps, - ActivationType.Slot, - false, // No alpha vault. Set to true the program will deterministically whitelist the alpha vault to swap before the pool start trading. Check: https://github.com/MeteoraAg/alpha-vault-sdk initialize{Prorata|Fcfs}Vault method to create the alpha vault. - owner.publicKey, - activationPoint, - { - cluster: "localhost", - } - ); - - let txHash = await sendAndConfirmTransaction(connection, rawTx, [ - owner, - ]).catch((e) => { - console.error(e); - throw e; - }); - console.log("Create permissioned LB pair", txHash); - - [pairKey] = deriveCustomizablePermissionlessLbPair(WEN, USDC, programId); - - pair = await DLMM.create(connection, pairKey, { - cluster: "localhost", - }); - - positionOwnerTokenX = getAssociatedTokenAddressSync( - WEN, positionOwnerKeypair.publicKey, true - ); - }); - - it("seed liquidity single bin", async () => { - try { - const positionOwnerTokenXBalance = await connection.getTokenAccountBalance(positionOwnerTokenX) - - if (positionOwnerTokenXBalance.value.amount == "0") { - await transfer(connection, owner, userWEN, positionOwnerTokenX, owner, 1); - - } - } catch (err) { - await createAssociatedTokenAccount(connection, owner, WEN, positionOwnerKeypair.publicKey); - await transfer(connection, owner, userWEN, positionOwnerTokenX, owner, 1); - } - - const ixs = await pair.seedLiquiditySingleBin( - owner.publicKey, - baseKeypair.publicKey, - wenSeedAmount, - initialPrice, - true, - positionOwnerKeypair.publicKey, - feeOwnerKeypair.publicKey, - owner.publicKey, - new BN(0) - ); - - const { blockhash, lastValidBlockHeight } = - await connection.getLatestBlockhash("confirmed"); - const tx = new Transaction({ - feePayer: owner.publicKey, - blockhash, - lastValidBlockHeight, - }).add(...ixs); - - - const beforeTokenXBalance = await connection - .getTokenAccountBalance(userWEN) - .then((i) => new BN(i.value.amount)); - - await sendAndConfirmTransaction(connection, tx, [ - owner, - baseKeypair, - ]).catch((e) => { - console.error(e) - }); - - const afterTokenXBalance = await connection - .getTokenAccountBalance(userWEN) - .then((i) => new BN(i.value.amount)); - - // minus 1 send to positionOwnerTokenX account - const actualDepositedAmount = beforeTokenXBalance.sub(afterTokenXBalance); - expect(actualDepositedAmount.toString()).toEqual(wenSeedAmount.toString()); - }) - - }) - -});