UNPKG

test-raydium-sdk-v2

Version:

An SDK for building applications on top of Raydium.

1,593 lines (1,404 loc) 56.3 kB
import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { PublicKey, TransactionInstruction, ComputeBudgetProgram, SystemProgram, Connection, Keypair, Signer, } from "@solana/web3.js"; import BN from "bn.js"; import { createLogger, parseBigNumberish, RENT_PROGRAM_ID, METADATA_PROGRAM_ID, InstructionType, getATAAddress, MEMO_PROGRAM_ID, } from "@/common"; import { bool, s32, struct, u128, u64, u8 } from "@/marshmallow"; import { ReturnTypeMakeInstructions, ClmmPoolPersonalPosition, OpenPositionFromLiquidityExtInfo, ManipulateLiquidityExtInfo, ClosePositionExtInfo, InitRewardExtInfo, OpenPositionFromBaseExtInfo, } from "./type"; import { ClmmPositionLayout, ObservationInfoLayout } from "./layout"; import { getPdaPoolId, getPdaPoolVaultId, getPdaTickArrayAddress, getPdaMetadataKey, getPdaProtocolPositionAddress, getPdaPersonalPositionAddress, getPdaOperationAccount, getPdaExBitmapAccount, getPdaPoolRewardVaulId, } from "./utils/pda"; import { TickUtils } from "./utils/tick"; import { PoolUtils } from "./utils/pool"; import { generatePubKey } from "../account/util"; import { ApiV3Token, ApiV3PoolInfoConcentratedItem, ClmmKeys } from "@/api/type"; const logger = createLogger("Raydium_Clmm"); const anchorDataBuf = { createPool: [233, 146, 209, 142, 207, 104, 64, 188], initReward: [95, 135, 192, 196, 242, 129, 230, 68], setRewardEmissions: [112, 52, 167, 75, 32, 201, 211, 137], openPosition: [77, 184, 74, 214, 112, 86, 241, 199], closePosition: [123, 134, 81, 0, 49, 68, 98, 98], increaseLiquidity: [133, 29, 89, 223, 69, 238, 176, 10], decreaseLiquidity: [58, 127, 188, 62, 79, 82, 196, 96], swap: [43, 4, 237, 11, 26, 201, 30, 98], // [248, 198, 158, 145, 225, 117, 135, 200], collectReward: [18, 237, 166, 197, 34, 16, 213, 144], }; interface CreatePoolInstruction { connection: Connection; programId: PublicKey; owner: PublicKey; mintA: ApiV3Token; mintB: ApiV3Token; ammConfigId: PublicKey; initialPriceX64: BN; startTime: BN; forerunCreate?: boolean; } export class ClmmInstrument { static createPoolInstruction( programId: PublicKey, poolId: PublicKey, poolCreator: PublicKey, ammConfigId: PublicKey, observationId: PublicKey, mintA: PublicKey, mintVaultA: PublicKey, mintProgramIdA: PublicKey, mintB: PublicKey, mintVaultB: PublicKey, mintProgramIdB: PublicKey, exTickArrayBitmap: PublicKey, sqrtPriceX64: BN, startTime: BN, ): TransactionInstruction { const dataLayout = struct([u128("sqrtPriceX64"), u64("startTime")]); const keys = [ { pubkey: poolCreator, isSigner: true, isWritable: true }, { pubkey: ammConfigId, isSigner: false, isWritable: false }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: mintA, isSigner: false, isWritable: false }, { pubkey: mintB, isSigner: false, isWritable: false }, { pubkey: mintVaultA, isSigner: false, isWritable: true }, { pubkey: mintVaultB, isSigner: false, isWritable: true }, { pubkey: observationId, isSigner: false, isWritable: false }, { pubkey: exTickArrayBitmap, isSigner: false, isWritable: true }, { pubkey: mintProgramIdA, isSigner: false, isWritable: false }, { pubkey: mintProgramIdB, isSigner: false, isWritable: false }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: RENT_PROGRAM_ID, isSigner: false, isWritable: false }, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { sqrtPriceX64, startTime, }, data, ); const aData = Buffer.from([...anchorDataBuf.createPool, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static async createPoolInstructions(props: CreatePoolInstruction): Promise< ReturnTypeMakeInstructions<{ poolId: PublicKey; observationId: PublicKey; mintAVault: PublicKey; mintBVault: PublicKey; }> > { const { connection, programId, owner, mintA, mintB, ammConfigId, initialPriceX64, startTime, forerunCreate } = props; const observationId = generatePubKey({ fromPublicKey: owner, programId }); const [mintAAddress, mintBAddress] = [new PublicKey(mintA.address), new PublicKey(mintB.address)]; const ins = [ SystemProgram.createAccountWithSeed({ fromPubkey: owner, basePubkey: owner, seed: observationId.seed, newAccountPubkey: observationId.publicKey, lamports: forerunCreate ? 0 : await connection.getMinimumBalanceForRentExemption(ObservationInfoLayout.span), space: ObservationInfoLayout.span, programId, }), ]; const { publicKey: poolId } = getPdaPoolId(programId, ammConfigId, mintAAddress, mintBAddress); const { publicKey: mintAVault } = getPdaPoolVaultId(programId, poolId, mintAAddress); const { publicKey: mintBVault } = getPdaPoolVaultId(programId, poolId, mintBAddress); ins.push( this.createPoolInstruction( programId, poolId, owner, ammConfigId, observationId.publicKey, mintAAddress, mintAVault, new PublicKey(mintA.programId || TOKEN_PROGRAM_ID), mintBAddress, mintBVault, new PublicKey(mintB.programId || TOKEN_PROGRAM_ID), getPdaExBitmapAccount(programId, poolId).publicKey, initialPriceX64, startTime, ), ); return { signers: [], instructions: ins, instructionTypes: [InstructionType.CreateAccount, InstructionType.ClmmCreatePool], address: { poolId, observationId: observationId.publicKey, mintAVault, mintBVault }, lookupTableAddress: [], }; } static openPositionFromLiquidityInstruction( programId: PublicKey, payer: PublicKey, poolId: PublicKey, positionNftOwner: PublicKey, positionNftMint: PublicKey, positionNftAccount: PublicKey, metadataAccount: PublicKey, protocolPosition: PublicKey, tickArrayLower: PublicKey, tickArrayUpper: PublicKey, personalPosition: PublicKey, ownerTokenAccountA: PublicKey, ownerTokenAccountB: PublicKey, tokenVaultA: PublicKey, tokenVaultB: PublicKey, tokenMintA: PublicKey, tokenMintB: PublicKey, tickLowerIndex: number, tickUpperIndex: number, tickArrayLowerStartIndex: number, tickArrayUpperStartIndex: number, liquidity: BN, amountMaxA: BN, amountMaxB: BN, withMetadata: "create" | "no-create", exTickArrayBitmap?: PublicKey, ): TransactionInstruction { const dataLayout = struct([ s32("tickLowerIndex"), s32("tickUpperIndex"), s32("tickArrayLowerStartIndex"), s32("tickArrayUpperStartIndex"), u128("liquidity"), u64("amountMaxA"), u64("amountMaxB"), bool("withMetadata"), u8("optionBaseFlag"), bool("baseFlag"), ]); const remainingAccounts = [ ...(exTickArrayBitmap ? [{ pubkey: exTickArrayBitmap, isSigner: false, isWritable: true }] : []), ]; const keys = [ { pubkey: payer, isSigner: true, isWritable: true }, { pubkey: positionNftOwner, isSigner: false, isWritable: false }, { pubkey: positionNftMint, isSigner: true, isWritable: true }, { pubkey: positionNftAccount, isSigner: false, isWritable: true }, { pubkey: metadataAccount, isSigner: false, isWritable: true }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: protocolPosition, isSigner: false, isWritable: true }, { pubkey: tickArrayLower, isSigner: false, isWritable: true }, { pubkey: tickArrayUpper, isSigner: false, isWritable: true }, { pubkey: personalPosition, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountA, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountB, isSigner: false, isWritable: true }, { pubkey: tokenVaultA, isSigner: false, isWritable: true }, { pubkey: tokenVaultB, isSigner: false, isWritable: true }, { pubkey: RENT_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: tokenMintA, isSigner: false, isWritable: false }, { pubkey: tokenMintB, isSigner: false, isWritable: false }, ...remainingAccounts, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { tickLowerIndex, tickUpperIndex, tickArrayLowerStartIndex, tickArrayUpperStartIndex, liquidity, amountMaxA, amountMaxB, withMetadata: withMetadata === "create", baseFlag: false, optionBaseFlag: 0, }, data, ); const aData = Buffer.from([...anchorDataBuf.openPosition, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static async openPositionInstructions({ poolInfo, poolKeys, ownerInfo, tickLower, tickUpper, liquidity, amountMaxA, amountMaxB, withMetadata, getEphemeralSigners, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerInfo: { feePayer: PublicKey; wallet: PublicKey; tokenAccountA: PublicKey; tokenAccountB: PublicKey; }; tickLower: number; tickUpper: number; liquidity: BN; amountMaxA: BN; amountMaxB: BN; withMetadata: "create" | "no-create"; getEphemeralSigners?: (k: number) => any; }): Promise<ReturnTypeMakeInstructions> { const signers: Signer[] = []; const [programId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; let nftMintAccount; if (getEphemeralSigners) { nftMintAccount = new PublicKey((await getEphemeralSigners(1))[0]); } else { const _k = Keypair.generate(); signers.push(_k); nftMintAccount = _k.publicKey; } const tickArrayLowerStartIndex = TickUtils.getTickArrayStartIndexByTick(tickLower, poolInfo.config.tickSpacing); const tickArrayUpperStartIndex = TickUtils.getTickArrayStartIndexByTick(tickUpper, poolInfo.config.tickSpacing); const { publicKey: tickArrayLower } = getPdaTickArrayAddress(programId, id, tickArrayLowerStartIndex); const { publicKey: tickArrayUpper } = getPdaTickArrayAddress(programId, id, tickArrayUpperStartIndex); const { publicKey: positionNftAccount } = getATAAddress(ownerInfo.wallet, nftMintAccount, TOKEN_PROGRAM_ID); const { publicKey: metadataAccount } = getPdaMetadataKey(nftMintAccount); const { publicKey: personalPosition } = getPdaPersonalPositionAddress(programId, nftMintAccount); const { publicKey: protocolPosition } = getPdaProtocolPositionAddress(programId, id, tickLower, tickUpper); const ins = this.openPositionFromLiquidityInstruction( programId, ownerInfo.feePayer, id, ownerInfo.wallet, nftMintAccount, positionNftAccount, metadataAccount, protocolPosition, tickArrayLower, tickArrayUpper, personalPosition, ownerInfo.tokenAccountA, ownerInfo.tokenAccountB, new PublicKey(poolKeys.vault.A), new PublicKey(poolKeys.vault.B), new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address), tickLower, tickUpper, tickArrayLowerStartIndex, tickArrayUpperStartIndex, liquidity, amountMaxA, amountMaxB, withMetadata, ); return { signers, instructions: [ins], instructionTypes: [InstructionType.ClmmOpenPosition], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], address: { nftMint: nftMintAccount, tickArrayLower, tickArrayUpper, positionNftAccount, metadataAccount, personalPosition, protocolPosition, }, }; } static async openPositionFromBaseInstructions({ poolInfo, poolKeys, ownerInfo, tickLower, tickUpper, base, baseAmount, otherAmountMax, withMetadata, getEphemeralSigners, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerInfo: { feePayer: PublicKey; wallet: PublicKey; tokenAccountA: PublicKey; tokenAccountB: PublicKey; }; tickLower: number; tickUpper: number; base: "MintA" | "MintB"; baseAmount: BN; otherAmountMax: BN; withMetadata: "create" | "no-create"; getEphemeralSigners?: (k: number) => any; }): Promise<ReturnTypeMakeInstructions<OpenPositionFromBaseExtInfo>> { const signers: Signer[] = []; const [programId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; let nftMintAccount: PublicKey; if (getEphemeralSigners) { nftMintAccount = new PublicKey((await getEphemeralSigners(1))[0]); } else { const _k = Keypair.generate(); signers.push(_k); nftMintAccount = _k.publicKey; } const tickArrayLowerStartIndex = TickUtils.getTickArrayStartIndexByTick(tickLower, poolInfo.config.tickSpacing); const tickArrayUpperStartIndex = TickUtils.getTickArrayStartIndexByTick(tickUpper, poolInfo.config.tickSpacing); const { publicKey: tickArrayLower } = getPdaTickArrayAddress(programId, id, tickArrayLowerStartIndex); const { publicKey: tickArrayUpper } = getPdaTickArrayAddress(programId, id, tickArrayUpperStartIndex); const { publicKey: positionNftAccount } = getATAAddress(ownerInfo.wallet, nftMintAccount, TOKEN_PROGRAM_ID); const { publicKey: metadataAccount } = getPdaMetadataKey(nftMintAccount); const { publicKey: personalPosition } = getPdaPersonalPositionAddress(programId, nftMintAccount); const { publicKey: protocolPosition } = getPdaProtocolPositionAddress(programId, id, tickLower, tickUpper); const ins = this.openPositionFromBaseInstruction( programId, ownerInfo.feePayer, id, ownerInfo.wallet, nftMintAccount, positionNftAccount, metadataAccount, protocolPosition, tickArrayLower, tickArrayUpper, personalPosition, ownerInfo.tokenAccountA, ownerInfo.tokenAccountB, new PublicKey(poolKeys.vault.A), new PublicKey(poolKeys.vault.B), new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address), tickLower, tickUpper, tickArrayLowerStartIndex, tickArrayUpperStartIndex, withMetadata, base, baseAmount, otherAmountMax, PoolUtils.isOverflowDefaultTickarrayBitmap(poolInfo.config.tickSpacing, [ tickArrayLowerStartIndex, tickArrayUpperStartIndex, ]) ? getPdaExBitmapAccount(programId, id).publicKey : undefined, ); return { address: { nftMint: nftMintAccount, tickArrayLower, tickArrayUpper, positionNftAccount, metadataAccount, personalPosition, protocolPosition, }, instructions: [ins], signers, instructionTypes: [InstructionType.ClmmOpenPosition], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], }; } static openPositionFromBaseInstruction( programId: PublicKey, payer: PublicKey, poolId: PublicKey, positionNftOwner: PublicKey, positionNftMint: PublicKey, positionNftAccount: PublicKey, metadataAccount: PublicKey, protocolPosition: PublicKey, tickArrayLower: PublicKey, tickArrayUpper: PublicKey, personalPosition: PublicKey, ownerTokenAccountA: PublicKey, ownerTokenAccountB: PublicKey, tokenVaultA: PublicKey, tokenVaultB: PublicKey, tokenMintA: PublicKey, tokenMintB: PublicKey, tickLowerIndex: number, tickUpperIndex: number, tickArrayLowerStartIndex: number, tickArrayUpperStartIndex: number, withMetadata: "create" | "no-create", base: "MintA" | "MintB", baseAmount: BN, otherAmountMax: BN, exTickArrayBitmap?: PublicKey, ): TransactionInstruction { const dataLayout = struct([ s32("tickLowerIndex"), s32("tickUpperIndex"), s32("tickArrayLowerStartIndex"), s32("tickArrayUpperStartIndex"), u128("liquidity"), u64("amountMaxA"), u64("amountMaxB"), bool("withMetadata"), u8("optionBaseFlag"), bool("baseFlag"), ]); const remainingAccounts = [ ...(exTickArrayBitmap ? [{ pubkey: exTickArrayBitmap, isSigner: false, isWritable: true }] : []), ]; const keys = [ { pubkey: payer, isSigner: true, isWritable: true }, { pubkey: positionNftOwner, isSigner: false, isWritable: false }, { pubkey: positionNftMint, isSigner: true, isWritable: true }, { pubkey: positionNftAccount, isSigner: false, isWritable: true }, { pubkey: metadataAccount, isSigner: false, isWritable: true }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: protocolPosition, isSigner: false, isWritable: true }, { pubkey: tickArrayLower, isSigner: false, isWritable: true }, { pubkey: tickArrayUpper, isSigner: false, isWritable: true }, { pubkey: personalPosition, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountA, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountB, isSigner: false, isWritable: true }, { pubkey: tokenVaultA, isSigner: false, isWritable: true }, { pubkey: tokenVaultB, isSigner: false, isWritable: true }, { pubkey: RENT_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: tokenMintA, isSigner: false, isWritable: false }, { pubkey: tokenMintB, isSigner: false, isWritable: false }, ...remainingAccounts, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { tickLowerIndex, tickUpperIndex, tickArrayLowerStartIndex, tickArrayUpperStartIndex, liquidity: new BN(0), amountMaxA: base === "MintA" ? baseAmount : otherAmountMax, amountMaxB: base === "MintA" ? otherAmountMax : baseAmount, withMetadata: withMetadata === "create", baseFlag: base === "MintA", optionBaseFlag: 1, }, data, ); const aData = Buffer.from([...anchorDataBuf.openPosition, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static async openPositionFromLiquidityInstructions({ poolInfo, poolKeys, ownerInfo, tickLower, tickUpper, liquidity, amountMaxA, amountMaxB, withMetadata, getEphemeralSigners, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerInfo: { wallet: PublicKey; tokenAccountA: PublicKey; tokenAccountB: PublicKey; }; tickLower: number; tickUpper: number; liquidity: BN; amountMaxA: BN; amountMaxB: BN; withMetadata: "create" | "no-create"; getEphemeralSigners?: (k: number) => any; }): Promise<ReturnTypeMakeInstructions<OpenPositionFromLiquidityExtInfo["address"]>> { let nftMintAccount: PublicKey; const signers: Keypair[] = []; if (getEphemeralSigners) { nftMintAccount = new PublicKey((await getEphemeralSigners(1))[0]); } else { const _k = Keypair.generate(); signers.push(_k); nftMintAccount = _k.publicKey; } const [programId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; const tickArrayLowerStartIndex = TickUtils.getTickArrayStartIndexByTick(tickLower, poolInfo.config.tickSpacing); const tickArrayUpperStartIndex = TickUtils.getTickArrayStartIndexByTick(tickUpper, poolInfo.config.tickSpacing); const { publicKey: tickArrayLower } = getPdaTickArrayAddress(programId, id, tickArrayLowerStartIndex); const { publicKey: tickArrayUpper } = getPdaTickArrayAddress(programId, id, tickArrayUpperStartIndex); const { publicKey: positionNftAccount } = getATAAddress(ownerInfo.wallet, nftMintAccount, TOKEN_PROGRAM_ID); const { publicKey: metadataAccount } = getPdaMetadataKey(nftMintAccount); const { publicKey: personalPosition } = getPdaPersonalPositionAddress(programId, nftMintAccount); const { publicKey: protocolPosition } = getPdaProtocolPositionAddress(programId, id, tickLower, tickUpper); const ins = this.openPositionFromLiquidityInstruction( programId, ownerInfo.wallet, id, ownerInfo.wallet, nftMintAccount, positionNftAccount, metadataAccount, protocolPosition, tickArrayLower, tickArrayUpper, personalPosition, ownerInfo.tokenAccountA, ownerInfo.tokenAccountB, new PublicKey(poolKeys.vault.A), new PublicKey(poolKeys.vault.B), new PublicKey(poolKeys.mintA.address), new PublicKey(poolKeys.mintB.address), tickLower, tickUpper, tickArrayLowerStartIndex, tickArrayUpperStartIndex, liquidity, amountMaxA, amountMaxB, withMetadata, PoolUtils.isOverflowDefaultTickarrayBitmap(poolInfo.config.tickSpacing, [ tickArrayLowerStartIndex, tickArrayUpperStartIndex, ]) ? getPdaExBitmapAccount(programId, id).publicKey : undefined, ); return { address: { nftMint: nftMintAccount, tickArrayLower, tickArrayUpper, positionNftAccount, metadataAccount, personalPosition, protocolPosition, }, instructions: [ins], signers, instructionTypes: [InstructionType.ClmmOpenPosition], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], }; } static closePositionInstruction( programId: PublicKey, positionNftOwner: PublicKey, positionNftMint: PublicKey, positionNftAccount: PublicKey, personalPosition: PublicKey, ): TransactionInstruction { const dataLayout = struct([]); const keys = [ { pubkey: positionNftOwner, isSigner: true, isWritable: true }, { pubkey: positionNftMint, isSigner: false, isWritable: true }, { pubkey: positionNftAccount, isSigner: false, isWritable: true }, { pubkey: personalPosition, isSigner: false, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode({}, data); const aData = Buffer.from([...anchorDataBuf.closePosition, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static closePositionInstructions({ poolInfo, poolKeys, ownerInfo, ownerPosition, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerPosition: ClmmPositionLayout; ownerInfo: { wallet: PublicKey; }; }): ReturnTypeMakeInstructions<ClosePositionExtInfo["address"]> { const programId = new PublicKey(poolInfo.programId); const { publicKey: positionNftAccount } = getATAAddress(ownerInfo.wallet, ownerPosition.nftMint, TOKEN_PROGRAM_ID); const { publicKey: personalPosition } = getPdaPersonalPositionAddress(programId, ownerPosition.nftMint); const ins: TransactionInstruction[] = []; ins.push( this.closePositionInstruction( programId, ownerInfo.wallet, ownerPosition.nftMint, positionNftAccount, personalPosition, ), ); return { address: { positionNftAccount, personalPosition, }, signers: [], instructions: ins, instructionTypes: [InstructionType.ClmmClosePosition], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], }; } static increasePositionFromLiquidityInstruction( programId: PublicKey, positionNftOwner: PublicKey, positionNftAccount: PublicKey, personalPosition: PublicKey, poolId: PublicKey, protocolPosition: PublicKey, tickArrayLower: PublicKey, tickArrayUpper: PublicKey, ownerTokenAccountA: PublicKey, ownerTokenAccountB: PublicKey, mintVaultA: PublicKey, mintVaultB: PublicKey, mintMintA: PublicKey, mintMintB: PublicKey, liquidity: BN, amountMaxA: BN, amountMaxB: BN, exTickArrayBitmap?: PublicKey, ): TransactionInstruction { const dataLayout = struct([ u128("liquidity"), u64("amountMaxA"), u64("amountMaxB"), u8("optionBaseFlag"), bool("baseFlag"), ]); const remainingAccounts = [ ...(exTickArrayBitmap ? [{ pubkey: exTickArrayBitmap, isSigner: false, isWritable: true }] : []), ]; const keys = [ { pubkey: positionNftOwner, isSigner: true, isWritable: false }, { pubkey: positionNftAccount, isSigner: false, isWritable: false }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: protocolPosition, isSigner: false, isWritable: true }, { pubkey: personalPosition, isSigner: false, isWritable: true }, { pubkey: tickArrayLower, isSigner: false, isWritable: true }, { pubkey: tickArrayUpper, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountA, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountB, isSigner: false, isWritable: true }, { pubkey: mintVaultA, isSigner: false, isWritable: true }, { pubkey: mintVaultB, isSigner: false, isWritable: true }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: mintMintA, isSigner: false, isWritable: false }, { pubkey: mintMintB, isSigner: false, isWritable: false }, ...remainingAccounts, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { liquidity, amountMaxA, amountMaxB, optionBaseFlag: 0, baseFlag: false, }, data, ); const aData = Buffer.from([...anchorDataBuf.increaseLiquidity, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static increasePositionFromLiquidityInstructions({ poolInfo, poolKeys, ownerPosition, ownerInfo, liquidity, amountMaxA, amountMaxB, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerPosition: ClmmPositionLayout; ownerInfo: { wallet: PublicKey; tokenAccountA: PublicKey; tokenAccountB: PublicKey; }; liquidity: BN; amountMaxA: BN; amountMaxB: BN; }): ReturnTypeMakeInstructions<ManipulateLiquidityExtInfo["address"]> { const [programId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; const tickArrayLowerStartIndex = TickUtils.getTickArrayStartIndexByTick( ownerPosition.tickLower, poolInfo.config.tickSpacing, ); const tickArrayUpperStartIndex = TickUtils.getTickArrayStartIndexByTick( ownerPosition.tickUpper, poolInfo.config.tickSpacing, ); const { publicKey: tickArrayLower } = getPdaTickArrayAddress(programId, id, tickArrayLowerStartIndex); const { publicKey: tickArrayUpper } = getPdaTickArrayAddress(programId, id, tickArrayUpperStartIndex); const { publicKey: positionNftAccount } = getATAAddress(ownerInfo.wallet, ownerPosition.nftMint, TOKEN_PROGRAM_ID); const { publicKey: personalPosition } = getPdaPersonalPositionAddress(programId, ownerPosition.nftMint); const { publicKey: protocolPosition } = getPdaProtocolPositionAddress( programId, id, ownerPosition.tickLower, ownerPosition.tickUpper, ); const ins = this.increasePositionFromLiquidityInstruction( programId, ownerInfo.wallet, positionNftAccount, personalPosition, id, protocolPosition, tickArrayLower, tickArrayUpper, ownerInfo.tokenAccountA, ownerInfo.tokenAccountB, new PublicKey(poolKeys.vault.A), new PublicKey(poolKeys.vault.B), new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address), liquidity, amountMaxA, amountMaxB, PoolUtils.isOverflowDefaultTickarrayBitmap(poolInfo.config.tickSpacing, [ tickArrayLowerStartIndex, tickArrayUpperStartIndex, ]) ? getPdaExBitmapAccount(programId, id).publicKey : undefined, ); return { address: { tickArrayLower, tickArrayUpper, positionNftAccount, personalPosition, protocolPosition, }, signers: [], instructions: [ins], instructionTypes: [InstructionType.ClmmIncreasePosition], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], }; } static increasePositionFromBaseInstructions({ poolInfo, poolKeys, ownerPosition, ownerInfo, base, baseAmount, otherAmountMax, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerPosition: ClmmPoolPersonalPosition; ownerInfo: { wallet: PublicKey; tokenAccountA: PublicKey; tokenAccountB: PublicKey; }; base: "MintA" | "MintB"; baseAmount: BN; otherAmountMax: BN; }): ReturnTypeMakeInstructions<ManipulateLiquidityExtInfo["address"]> { const [programId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; const tickArrayLowerStartIndex = TickUtils.getTickArrayStartIndexByTick( ownerPosition.tickLower, poolInfo.config.tickSpacing, ); const tickArrayUpperStartIndex = TickUtils.getTickArrayStartIndexByTick( ownerPosition.tickUpper, poolInfo.config.tickSpacing, ); const { publicKey: tickArrayLower } = getPdaTickArrayAddress(programId, id, tickArrayLowerStartIndex); const { publicKey: tickArrayUpper } = getPdaTickArrayAddress(programId, id, tickArrayUpperStartIndex); const { publicKey: positionNftAccount } = getATAAddress(ownerInfo.wallet, ownerPosition.nftMint, TOKEN_PROGRAM_ID); const { publicKey: personalPosition } = getPdaPersonalPositionAddress(programId, ownerPosition.nftMint); const { publicKey: protocolPosition } = getPdaProtocolPositionAddress( programId, id, ownerPosition.tickLower, ownerPosition.tickUpper, ); return { address: { tickArrayLower, tickArrayUpper, positionNftAccount, personalPosition, protocolPosition, }, instructions: [ this.increasePositionFromBaseInstruction( programId, ownerInfo.wallet, positionNftAccount, personalPosition, id, protocolPosition, tickArrayLower, tickArrayUpper, ownerInfo.tokenAccountA, ownerInfo.tokenAccountB, new PublicKey(poolKeys.vault.A), new PublicKey(poolKeys.vault.B), new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address), base, baseAmount, otherAmountMax, PoolUtils.isOverflowDefaultTickarrayBitmap(poolInfo.config.tickSpacing, [ tickArrayLowerStartIndex, tickArrayUpperStartIndex, ]) ? getPdaExBitmapAccount(programId, id).publicKey : undefined, ), ], signers: [], instructionTypes: [InstructionType.ClmmIncreasePosition], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], }; } static increasePositionFromBaseInstruction( programId: PublicKey, positionNftOwner: PublicKey, positionNftAccount: PublicKey, personalPosition: PublicKey, poolId: PublicKey, protocolPosition: PublicKey, tickArrayLower: PublicKey, tickArrayUpper: PublicKey, ownerTokenAccountA: PublicKey, ownerTokenAccountB: PublicKey, mintVaultA: PublicKey, mintVaultB: PublicKey, mintMintA: PublicKey, mintMintB: PublicKey, base: "MintA" | "MintB", baseAmount: BN, otherAmountMax: BN, exTickArrayBitmap?: PublicKey, ): TransactionInstruction { const dataLayout = struct([ u128("liquidity"), u64("amountMaxA"), u64("amountMaxB"), u8("optionBaseFlag"), bool("baseFlag"), ]); const remainingAccounts = [ ...(exTickArrayBitmap ? [{ pubkey: exTickArrayBitmap, isSigner: false, isWritable: true }] : []), ]; const keys = [ { pubkey: positionNftOwner, isSigner: true, isWritable: false }, { pubkey: positionNftAccount, isSigner: false, isWritable: false }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: protocolPosition, isSigner: false, isWritable: true }, { pubkey: personalPosition, isSigner: false, isWritable: true }, { pubkey: tickArrayLower, isSigner: false, isWritable: true }, { pubkey: tickArrayUpper, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountA, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountB, isSigner: false, isWritable: true }, { pubkey: mintVaultA, isSigner: false, isWritable: true }, { pubkey: mintVaultB, isSigner: false, isWritable: true }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: mintMintA, isSigner: false, isWritable: false }, { pubkey: mintMintB, isSigner: false, isWritable: false }, ...remainingAccounts, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { liquidity: new BN(0), amountMaxA: base === "MintA" ? baseAmount : otherAmountMax, amountMaxB: base === "MintA" ? otherAmountMax : baseAmount, baseFlag: base === "MintA", optionBaseFlag: 1, }, data, ); const aData = Buffer.from([...anchorDataBuf.increaseLiquidity, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static decreaseLiquidityInstruction( programId: PublicKey, positionNftOwner: PublicKey, positionNftAccount: PublicKey, personalPosition: PublicKey, poolId: PublicKey, protocolPosition: PublicKey, tickArrayLower: PublicKey, tickArrayUpper: PublicKey, ownerTokenAccountA: PublicKey, ownerTokenAccountB: PublicKey, mintVaultA: PublicKey, mintVaultB: PublicKey, mintMintA: PublicKey, mintMintB: PublicKey, rewardAccounts: { poolRewardVault: PublicKey; ownerRewardVault: PublicKey; rewardMint: PublicKey; }[], liquidity: BN, amountMinA: BN, amountMinB: BN, exTickArrayBitmap?: PublicKey, ): TransactionInstruction { const dataLayout = struct([u128("liquidity"), u64("amountMinA"), u64("amountMinB")]); const remainingAccounts = [ ...(exTickArrayBitmap ? [{ pubkey: exTickArrayBitmap, isSigner: false, isWritable: true }] : []), ...rewardAccounts .map((i) => [ { pubkey: i.poolRewardVault, isSigner: false, isWritable: true }, { pubkey: i.ownerRewardVault, isSigner: false, isWritable: true }, { pubkey: i.rewardMint, isSigner: false, isWritable: false }, ]) .flat(), ]; const keys = [ { pubkey: positionNftOwner, isSigner: true, isWritable: false }, { pubkey: positionNftAccount, isSigner: false, isWritable: false }, { pubkey: personalPosition, isSigner: false, isWritable: true }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: protocolPosition, isSigner: false, isWritable: true }, { pubkey: mintVaultA, isSigner: false, isWritable: true }, { pubkey: mintVaultB, isSigner: false, isWritable: true }, { pubkey: tickArrayLower, isSigner: false, isWritable: true }, { pubkey: tickArrayUpper, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountA, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccountB, isSigner: false, isWritable: true }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: MEMO_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: mintMintA, isSigner: false, isWritable: false }, { pubkey: mintMintB, isSigner: false, isWritable: false }, ...remainingAccounts, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { liquidity, amountMinA, amountMinB, }, data, ); const aData = Buffer.from([...anchorDataBuf.decreaseLiquidity, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static decreaseLiquidityInstructions({ poolInfo, poolKeys, ownerPosition, ownerInfo, liquidity, amountMinA, amountMinB, programId, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerPosition: ClmmPositionLayout; ownerInfo: { wallet: PublicKey; tokenAccountA: PublicKey; tokenAccountB: PublicKey; rewardAccounts: PublicKey[]; }; liquidity: BN; amountMinA: BN; amountMinB: BN; programId?: PublicKey; }): ReturnTypeMakeInstructions<ManipulateLiquidityExtInfo["address"]> { const [poolProgramId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; const tickArrayLowerStartIndex = TickUtils.getTickArrayStartIndexByTick( ownerPosition.tickLower, poolInfo.config.tickSpacing, ); const tickArrayUpperStartIndex = TickUtils.getTickArrayStartIndexByTick( ownerPosition.tickUpper, poolInfo.config.tickSpacing, ); const { publicKey: tickArrayLower } = getPdaTickArrayAddress(poolProgramId, id, tickArrayLowerStartIndex); const { publicKey: tickArrayUpper } = getPdaTickArrayAddress(poolProgramId, id, tickArrayUpperStartIndex); const { publicKey: positionNftAccount } = getATAAddress(ownerInfo.wallet, ownerPosition.nftMint, programId); const { publicKey: personalPosition } = getPdaPersonalPositionAddress(poolProgramId, ownerPosition.nftMint); const { publicKey: protocolPosition } = getPdaProtocolPositionAddress( poolProgramId, id, ownerPosition.tickLower, ownerPosition.tickUpper, ); const rewardAccounts: { poolRewardVault: PublicKey; ownerRewardVault: PublicKey; rewardMint: PublicKey; }[] = []; for (let i = 0; i < poolInfo.rewardDefaultInfos.length; i++) { rewardAccounts.push({ poolRewardVault: new PublicKey(poolKeys.rewardInfos[i].vault), ownerRewardVault: ownerInfo.rewardAccounts[i], rewardMint: new PublicKey(poolInfo.rewardDefaultInfos[i].mint.address), }); } const ins: TransactionInstruction[] = []; ins.push( this.decreaseLiquidityInstruction( poolProgramId, ownerInfo.wallet, positionNftAccount, personalPosition, id, protocolPosition, tickArrayLower, tickArrayUpper, ownerInfo.tokenAccountA, ownerInfo.tokenAccountB, new PublicKey(poolKeys.vault.A), new PublicKey(poolKeys.vault.B), new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address), rewardAccounts, liquidity, amountMinA, amountMinB, PoolUtils.isOverflowDefaultTickarrayBitmap(poolInfo.config.tickSpacing, [ tickArrayLowerStartIndex, tickArrayUpperStartIndex, ]) ? getPdaExBitmapAccount(poolProgramId, id).publicKey : undefined, ), ); return { address: { tickArrayLower, tickArrayUpper, positionNftAccount, personalPosition, protocolPosition, }, signers: [], instructions: ins, instructionTypes: [InstructionType.ClmmDecreasePosition], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], }; } static swapInstruction( programId: PublicKey, payer: PublicKey, poolId: PublicKey, ammConfigId: PublicKey, inputTokenAccount: PublicKey, outputTokenAccount: PublicKey, inputVault: PublicKey, outputVault: PublicKey, inputMint: PublicKey, outputMint: PublicKey, tickArray: PublicKey[], observationId: PublicKey, amount: BN, otherAmountThreshold: BN, sqrtPriceLimitX64: BN, isBaseInput: boolean, exTickArrayBitmap?: PublicKey, ): TransactionInstruction { const dataLayout = struct([ u64("amount"), u64("otherAmountThreshold"), u128("sqrtPriceLimitX64"), bool("isBaseInput"), ]); const remainingAccounts = [ ...(exTickArrayBitmap ? [{ pubkey: exTickArrayBitmap, isSigner: false, isWritable: true }] : []), ...tickArray.map((i) => ({ pubkey: i, isSigner: false, isWritable: true })), ]; const keys = [ { pubkey: payer, isSigner: true, isWritable: false }, { pubkey: ammConfigId, isSigner: false, isWritable: false }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: inputTokenAccount, isSigner: false, isWritable: true }, { pubkey: outputTokenAccount, isSigner: false, isWritable: true }, { pubkey: inputVault, isSigner: false, isWritable: true }, { pubkey: outputVault, isSigner: false, isWritable: true }, { pubkey: observationId, isSigner: false, isWritable: true }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: MEMO_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: inputMint, isSigner: false, isWritable: false }, { pubkey: outputMint, isSigner: false, isWritable: false }, ...remainingAccounts, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { amount, otherAmountThreshold, sqrtPriceLimitX64, isBaseInput, }, data, ); const aData = Buffer.from([...anchorDataBuf.swap, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static makeSwapBaseInInstructions({ poolInfo, poolKeys, ownerInfo, inputMint, amountIn, amountOutMin, sqrtPriceLimitX64, remainingAccounts, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerInfo: { wallet: PublicKey; tokenAccountA: PublicKey; tokenAccountB: PublicKey; }; inputMint: PublicKey; amountIn: BN; amountOutMin: BN; sqrtPriceLimitX64: BN; remainingAccounts: PublicKey[]; }): ReturnTypeMakeInstructions { const [programId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; const [mintAVault, mintBVault] = [new PublicKey(poolKeys.vault.A), new PublicKey(poolKeys.vault.B)]; const [mintA, mintB] = [new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address)]; const isInputMintA = poolInfo.mintA.address === inputMint.toString(); const ins = [ this.swapInstruction( programId, ownerInfo.wallet, id, new PublicKey(poolInfo.config.id), isInputMintA ? ownerInfo.tokenAccountA : ownerInfo.tokenAccountB, isInputMintA ? ownerInfo.tokenAccountB : ownerInfo.tokenAccountA, isInputMintA ? mintAVault : mintBVault, isInputMintA ? mintBVault : mintAVault, isInputMintA ? mintA : mintB, isInputMintA ? mintB : mintA, remainingAccounts, // poolInfo.observationId, // to do get from api mintAVault, amountIn, amountOutMin, sqrtPriceLimitX64, true, getPdaExBitmapAccount(programId, id).publicKey, ), ]; return { signers: [], instructions: ins, instructionTypes: [InstructionType.ClmmSwapBaseIn], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], address: {}, }; } static initRewardInstruction( programId: PublicKey, payer: PublicKey, poolId: PublicKey, operationId: PublicKey, ammConfigId: PublicKey, ownerTokenAccount: PublicKey, rewardProgramId: PublicKey, rewardMint: PublicKey, rewardVault: PublicKey, openTime: number, endTime: number, emissionsPerSecondX64: BN, ): TransactionInstruction { const dataLayout = struct([u64("openTime"), u64("endTime"), u128("emissionsPerSecondX64")]); const keys = [ { pubkey: payer, isSigner: true, isWritable: true }, { pubkey: ownerTokenAccount, isSigner: false, isWritable: true }, { pubkey: ammConfigId, isSigner: false, isWritable: false }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: operationId, isSigner: false, isWritable: true }, { pubkey: rewardMint, isSigner: false, isWritable: false }, { pubkey: rewardVault, isSigner: false, isWritable: true }, { pubkey: rewardProgramId, isSigner: false, isWritable: false }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: RENT_PROGRAM_ID, isSigner: false, isWritable: false }, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { openTime: parseBigNumberish(openTime), endTime: parseBigNumberish(endTime), emissionsPerSecondX64, }, data, ); const aData = Buffer.from([...anchorDataBuf.initReward, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static initRewardInstructions({ poolInfo, poolKeys, ownerInfo, rewardInfo, }: { poolInfo: ApiV3PoolInfoConcentratedItem; poolKeys: ClmmKeys; ownerInfo: { wallet: PublicKey; tokenAccount: PublicKey; }; rewardInfo: { programId: PublicKey; mint: PublicKey; openTime: number; endTime: number; emissionsPerSecondX64: BN; }; }): ReturnTypeMakeInstructions<InitRewardExtInfo["address"]> { const [programId, id] = [new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)]; const poolRewardVault = getPdaPoolRewardVaulId(programId, id, rewardInfo.mint).publicKey; const operationId = getPdaOperationAccount(programId).publicKey; const ins = [ this.initRewardInstruction( programId, ownerInfo.wallet, id, operationId, new PublicKey(poolInfo.config.id), ownerInfo.tokenAccount, rewardInfo.programId, rewardInfo.mint, poolRewardVault, rewardInfo.openTime, rewardInfo.endTime, rewardInfo.emissionsPerSecondX64, ), ]; return { address: { poolRewardVault, operationId }, signers: [], instructions: ins, instructionTypes: [InstructionType.ClmmInitReward], lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [], }; } static setRewardInstruction( programId: PublicKey, payer: PublicKey, poolId: PublicKey, operationId: PublicKey, ammConfigId: PublicKey, ownerTokenAccount: PublicKey, rewardVault: PublicKey, rewardMint: PublicKey, rewardIndex: number, openTime: number, endTime: number, emissionsPerSecondX64: BN, ): TransactionInstruction { const dataLayout = struct([u8("rewardIndex"), u128("emissionsPerSecondX64"), u64("openTime"), u64("endTime")]); const keys = [ { pubkey: payer, isSigner: true, isWritable: true }, { pubkey: ammConfigId, isSigner: false, isWritable: false }, { pubkey: poolId, isSigner: false, isWritable: true }, { pubkey: operationId, isSigner: false, isWritable: true }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: rewardVault, isSigner: false, isWritable: true }, { pubkey: ownerTokenAccount, isSigner: false, isWritable: true }, { pubkey: rewardMint, isSigner: false, isWritable: true }, ]; const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { rewardIndex, emissionsPerSecondX64, openTime: parseBigNumberish(openTime), endTime: parseBigNumberish(endTime), }, data, ); const aData = Buffer.from([...anchorDataBuf.setRewardEmissions, ...data]); return new TransactionInstruction({ keys, programId, data: aData, }); } static setRewardInstructions({