UNPKG

@raydium-io/raydium-sdk-v2

Version:

An SDK for building applications on top of Raydium.

1 lines 1.15 MB
{"version":3,"sources":["../../../src/raydium/tradeV2/trade.ts","../../../node_modules/decimal.js/decimal.mjs","../../../src/common/accountInfo.ts","../../../src/common/logger.ts","../../../src/common/bignumber.ts","../../../src/module/amount.ts","../../../src/module/formatter.ts","../../../src/module/fraction.ts","../../../src/common/constant.ts","../../../src/raydium/token/constant.ts","../../../src/module/token.ts","../../../src/common/pubKey.ts","../../../src/module/currency.ts","../../../src/module/percent.ts","../../../src/module/price.ts","../../../src/common/lodash.ts","../../../src/common/pda.ts","../../../src/common/txTool/txUtils.ts","../../../src/common/txTool/txType.ts","../../../src/common/programId.ts","../../../src/common/transfer.ts","../../../src/common/txTool/lookupTable.ts","../../../src/common/txTool/txTool.ts","../../../src/common/utility.ts","../../../src/common/fee.ts","../../../src/marshmallow/index.ts","../../../src/marshmallow/buffer-layout.ts","../../../src/raydium/clmm/clmm.ts","../../../src/raydium/token/utils.ts","../../../src/raydium/clmm/instrument.ts","../../../src/raydium/clmm/utils/tick.ts","../../../src/raydium/clmm/utils/constants.ts","../../../src/raydium/clmm/utils/math.ts","../../../src/raydium/clmm/utils/util.ts","../../../src/raydium/clmm/utils/pda.ts","../../../src/raydium/clmm/utils/pool.ts","../../../src/raydium/clmm/utils/position.ts","../../../src/raydium/clmm/utils/tickQuery.ts","../../../src/raydium/clmm/utils/tickarrayBitmap.ts","../../../src/raydium/clmm/layout.ts","../../../src/raydium/cpmm/layout.ts","../../../src/raydium/cpmm/instruction.ts","../../../src/raydium/cpmm/pda.ts","../../../src/raydium/cpmm/curve/calculator.ts","../../../src/raydium/cpmm/curve/constantProduct.ts","../../../src/raydium/cpmm/curve/fee.ts","../../../src/raydium/liquidity/constant.ts","../../../src/raydium/liquidity/layout.ts","../../../src/raydium/liquidity/utils.ts","../../../src/raydium/liquidity/instruction.ts","../../../src/raydium/liquidity/serum.ts","../../../src/raydium/liquidity/stable.ts","../../../src/raydium/account/layout.ts","../../../src/raydium/account/util.ts","../../../src/raydium/account/instruction.ts","../../../src/raydium/token/layout.ts","../../../src/raydium/serum/id.ts","../../../src/raydium/serum/layout.ts","../../../src/raydium/serum/serum.ts","../../../src/raydium/tradeV2/instrument.ts","../../../src/raydium/launchpad/instrument.ts","../../../src/raydium/launchpad/layout.ts","../../../src/raydium/launchpad/pda.ts","../../../src/raydium/launchpad/curve/constantProductCurve.ts","../../../src/raydium/launchpad/curve/curve.ts","../../../src/raydium/launchpad/curve/fixedPriceCurve.ts","../../../src/raydium/launchpad/curve/linearPriceCurve.ts","../../../src/raydium/launchpad/curve/func.ts","../../../src/raydium/launchpad/launchpad.ts"],"sourcesContent":["import { EpochInfo, PublicKey, SystemProgram } from \"@solana/web3.js\";\nimport {\n createTransferInstruction,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n createAssociatedTokenAccountIdempotentInstruction,\n TransferFee,\n TransferFeeConfig,\n createSyncNativeInstruction,\n} from \"@solana/spl-token\";\nimport BN from \"bn.js\";\nimport Decimal from \"decimal.js\";\nimport { AmmV4Keys, ApiV3PoolInfoConcentratedItem, ApiV3Token, ClmmKeys, PoolKeys } from \"@/api\";\nimport {\n AMM_V4,\n BigNumberish,\n CLMM_PROGRAM_ID,\n CREATE_CPMM_POOL_PROGRAM,\n fetchMultipleMintInfos,\n getMultipleAccountsInfoWithCustomFlags,\n minExpirationTime,\n parseBigNumberish,\n solToWSol,\n WSOLMint,\n} from \"@/common\";\nimport { MakeMultiTxData, MakeTxData } from \"@/common/txTool/txTool\";\nimport { InstructionType, TxVersion } from \"@/common/txTool/txType\";\nimport { publicKey, struct } from \"../../marshmallow\";\nimport { Price, TokenAmount } from \"../../module\";\nimport {\n ClmmInstrument,\n ClmmParsedRpcData,\n ComputeClmmPoolInfo,\n MAX_SQRT_PRICE_X64,\n MIN_SQRT_PRICE_X64,\n PoolUtils,\n ReturnTypeComputeAmountOutBaseOut,\n ReturnTypeComputeAmountOutFormat,\n ReturnTypeFetchMultiplePoolTickArrays,\n SqrtPriceMath,\n} from \"../../raydium/clmm\";\nimport { PoolInfoLayout } from \"../../raydium/clmm/layout\";\nimport { CpmmPoolInfoLayout, getPdaPoolAuthority } from \"../../raydium/cpmm\";\nimport {\n ComputeAmountOutParam,\n getLiquidityAssociatedAuthority,\n liquidityStateV4Layout,\n toAmmComputePoolInfo,\n} from \"../../raydium/liquidity\";\nimport { ComputeBudgetConfig, ReturnTypeFetchMultipleMintInfos, TransferAmountFee } from \"../../raydium/type\";\nimport { closeAccountInstruction, createWSolAccountInstructions } from \"../account/instruction\";\nimport { TokenAccount } from \"../account/types\";\nimport { CpmmComputeData } from \"../cpmm\";\nimport { AmmRpcData } from \"../liquidity\";\nimport ModuleBase, { ModuleBaseProps } from \"../moduleBase\";\nimport { Market, MARKET_STATE_LAYOUT_V3 } from \"../serum\";\nimport { toApiV3Token, toToken, toTokenAmount } from \"../token\";\nimport { makeSwapInstruction } from \"./instrument\";\nimport {\n BasicPoolInfo,\n ComputeAmountOutAmmLayout,\n ComputeAmountOutLayout,\n ComputePoolType,\n ComputeRoutePathType,\n ReturnTypeFetchMultipleInfo,\n ReturnTypeGetAllRoute,\n RoutePathType,\n} from \"./type\";\nimport {\n buyExactInInstruction,\n Curve,\n getPdaCreatorVault,\n getPdaLaunchpadAuth,\n getPdaPlatformVault,\n LaunchpadConfigInfo,\n LaunchpadPlatformInfo,\n LaunchpadPoolInfo,\n PlatformConfig,\n sellExactInInstruction,\n SwapInfoReturn,\n} from \"../launchpad\";\n\nconst ZERO = new BN(0);\nexport default class TradeV2 extends ModuleBase {\n constructor(params: ModuleBaseProps) {\n super(params);\n }\n\n private async getWSolAccounts(): Promise<TokenAccount[]> {\n this.scope.checkOwner();\n await this.scope.account.fetchWalletTokenAccounts();\n const tokenAccounts = this.scope.account.tokenAccounts.filter((acc) => acc.mint.equals(WSOLMint));\n tokenAccounts.sort((a, b) => {\n if (a.isAssociated) return 1;\n if (b.isAssociated) return -1;\n return a.amount.lt(b.amount) ? -1 : 1;\n });\n return tokenAccounts;\n }\n\n public async unWrapWSol<T extends TxVersion>(props: {\n amount: BigNumberish;\n computeBudgetConfig?: ComputeBudgetConfig;\n tokenProgram?: PublicKey;\n txVersion?: T;\n feePayer?: PublicKey;\n }): Promise<MakeTxData<T>> {\n const { amount, tokenProgram, txVersion = TxVersion.LEGACY, feePayer } = props;\n const tokenAccounts = await this.getWSolAccounts();\n const txBuilder = this.createTxBuilder(feePayer);\n txBuilder.addCustomComputeBudget(props.computeBudgetConfig);\n // const ins = await createWSolAccountInstructions({\n // connection: this.scope.connection,\n // owner: this.scope.ownerPubKey,\n // payer: this.scope.ownerPubKey,\n // amount: 0,\n // });\n // txBuilder.addInstruction(ins);\n\n const amountBN = parseBigNumberish(amount);\n for (let i = 0; i < tokenAccounts.length; i++) {\n if (amountBN.gte(tokenAccounts[i].amount)) {\n txBuilder.addInstruction({\n instructions: [\n closeAccountInstruction({\n tokenAccount: tokenAccounts[i].publicKey!,\n payer: this.scope.ownerPubKey,\n owner: this.scope.ownerPubKey,\n programId: tokenProgram,\n }),\n ],\n });\n amountBN.sub(tokenAccounts[i].amount);\n } else {\n txBuilder.addInstruction({\n instructions: [\n closeAccountInstruction({\n tokenAccount: tokenAccounts[i].publicKey!,\n payer: this.scope.ownerPubKey,\n owner: this.scope.ownerPubKey,\n programId: tokenProgram,\n }),\n ],\n });\n }\n }\n\n return txBuilder.versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n public async wrapWSol<T extends TxVersion>(\n amount: BigNumberish,\n tokenProgram?: PublicKey,\n txVersion?: T,\n feePayer?: PublicKey,\n ): Promise<MakeTxData<T>> {\n // const tokenAccounts = await this.getWSolAccounts();\n\n const txBuilder = this.createTxBuilder(feePayer);\n\n const ins = await createWSolAccountInstructions({\n connection: this.scope.connection,\n owner: this.scope.ownerPubKey,\n payer: this.scope.ownerPubKey,\n amount,\n skipCloseAccount: true,\n });\n txBuilder.addInstruction(ins);\n\n // if (tokenAccounts.length) {\n // // already have wsol account\n // txBuilder.addInstruction({\n // instructions: [\n // makeTransferInstruction({\n // destination: tokenAccounts[0].publicKey!,\n // source: ins.addresses.newAccount,\n // amount,\n // owner: this.scope.ownerPubKey,\n // tokenProgram,\n // }),\n // ],\n // endInstructions: [\n // closeAccountInstruction({\n // tokenAccount: ins.addresses.newAccount,\n // payer: this.scope.ownerPubKey,\n // owner: this.scope.ownerPubKey,\n // programId: tokenProgram,\n // }),\n // ],\n // });\n // }\n return txBuilder.versionBuild({ txVersion: txVersion ?? TxVersion.LEGACY }) as Promise<MakeTxData<T>>;\n }\n\n public async swap<T extends TxVersion>({\n swapInfo,\n swapPoolKeys,\n ownerInfo,\n computeBudgetConfig,\n routeProgram,\n txVersion,\n feePayer,\n }: {\n txVersion: T;\n swapInfo: ComputeAmountOutLayout;\n swapPoolKeys?: PoolKeys[];\n ownerInfo: {\n associatedOnly: boolean;\n checkCreateATAOwner: boolean;\n };\n routeProgram: PublicKey;\n computeBudgetConfig?: ComputeBudgetConfig;\n feePayer?: PublicKey;\n }): Promise<MakeMultiTxData<T>> {\n const txBuilder = this.createTxBuilder(feePayer);\n const amountIn = swapInfo.amountIn;\n const amountOut = swapInfo.amountOut;\n const useSolBalance = amountIn.amount.token.mint.equals(WSOLMint);\n const isOutputSol = amountOut.amount.token.mint.equals(WSOLMint);\n const inputMint = amountIn.amount.token.mint;\n const outputMint = amountOut.amount.token.mint;\n\n const { account: sourceAcc, instructionParams: sourceAccInsParams } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: amountIn.amount.token.isToken2022 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID,\n mint: inputMint,\n notUseTokenAccount: useSolBalance,\n owner: this.scope.ownerPubKey,\n skipCloseAccount: !useSolBalance,\n createInfo: useSolBalance\n ? {\n payer: this.scope.ownerPubKey,\n amount: amountIn.amount.raw,\n }\n : undefined,\n associatedOnly: useSolBalance ? false : ownerInfo.associatedOnly,\n checkCreateATAOwner: ownerInfo.checkCreateATAOwner,\n });\n\n sourceAccInsParams && txBuilder.addInstruction(sourceAccInsParams);\n\n if (sourceAcc === undefined) {\n throw Error(\"input account check error\");\n }\n\n let destinationAcc: PublicKey;\n if (swapInfo.routeType === \"route\" && !isOutputSol) {\n destinationAcc = this.scope.account.getAssociatedTokenAccount(\n outputMint,\n amountOut.amount.token.isToken2022 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID,\n );\n } else {\n const { account, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: amountOut.amount.token.isToken2022 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID,\n mint: outputMint,\n notUseTokenAccount: isOutputSol,\n owner: this.scope.ownerPubKey,\n skipCloseAccount: true,\n createInfo: {\n payer: this.scope.ownerPubKey,\n amount: 0,\n },\n associatedOnly: isOutputSol ? false : ownerInfo.associatedOnly,\n checkCreateATAOwner: ownerInfo.checkCreateATAOwner,\n });\n destinationAcc = account!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n\n if (isOutputSol) {\n txBuilder.addInstruction({\n endInstructions: [\n closeAccountInstruction({\n owner: this.scope.ownerPubKey,\n payer: this.scope.ownerPubKey,\n tokenAccount: destinationAcc,\n programId: TOKEN_PROGRAM_ID,\n }),\n ],\n endInstructionTypes: [InstructionType.CloseAccount],\n });\n }\n\n let routeTokenAcc: PublicKey | undefined = undefined;\n if (swapInfo.routeType === \"route\") {\n const middleMint = swapInfo.middleToken;\n routeTokenAcc = this.scope.account.getAssociatedTokenAccount(\n middleMint.mint,\n middleMint.isToken2022 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID,\n );\n }\n\n const poolKeys = swapPoolKeys ? swapPoolKeys : await this.computePoolToPoolKeys({ pools: swapInfo.poolInfoList });\n const swapIns = makeSwapInstruction({\n routeProgram,\n inputMint,\n swapInfo: {\n ...swapInfo,\n poolInfo: [...swapInfo.poolInfoList],\n poolKey: poolKeys,\n outputMint,\n },\n ownerInfo: {\n wallet: this.scope.ownerPubKey,\n sourceToken: sourceAcc,\n routeToken: routeTokenAcc,\n destinationToken: destinationAcc!,\n },\n });\n\n if (swapInfo.feeConfig !== undefined) {\n const checkTxBuilder = this.createTxBuilder();\n checkTxBuilder.addInstruction({\n instructions: [\n createTransferInstruction(\n sourceAcc,\n swapInfo.feeConfig.feeAccount,\n this.scope.ownerPubKey,\n swapInfo.feeConfig.feeAmount.toNumber(),\n ),\n ],\n instructionTypes: [InstructionType.TransferAmount],\n });\n checkTxBuilder.addInstruction(swapIns);\n\n const { transactions } =\n txVersion === TxVersion.V0 ? await checkTxBuilder.sizeCheckBuildV0() : await checkTxBuilder.sizeCheckBuild();\n if (transactions.length < 2) {\n txBuilder.addInstruction({\n instructions: [\n createTransferInstruction(\n sourceAcc,\n swapInfo.feeConfig.feeAccount,\n this.scope.ownerPubKey,\n swapInfo.feeConfig.feeAmount.toNumber(),\n ),\n ],\n instructionTypes: [InstructionType.TransferAmount],\n });\n }\n }\n txBuilder.addInstruction(swapIns);\n\n if (txVersion === TxVersion.V0)\n return txBuilder.sizeCheckBuildV0({ computeBudgetConfig, address: swapIns.address }) as Promise<\n MakeMultiTxData<T>\n >;\n return txBuilder.sizeCheckBuild({ computeBudgetConfig, address: swapIns.address }) as Promise<MakeMultiTxData<T>>;\n }\n\n public async swapClmmToLaunchMint<T extends TxVersion>({\n inputMint,\n inputAmount,\n fixClmmOut = false,\n clmmPoolId,\n launchPoolId,\n priceLimit,\n slippage = 0.01,\n shareFeeRate = new BN(0),\n shareFeeReceiver,\n\n launchPlatformInfo,\n slot,\n mintInfo,\n epochInfo: propsEpochInfo,\n\n ownerInfo = { useSOLBalance: true },\n checkCreateATAOwner = false,\n computeBudgetConfig,\n txVersion,\n }: {\n inputMint: string | PublicKey;\n inputAmount: BN;\n fixClmmOut?: boolean;\n clmmPoolId: string | PublicKey;\n launchPoolId: string | PublicKey;\n priceLimit?: Decimal;\n epochInfo?: EpochInfo;\n slippage: number; // from 0~1\n shareFeeRate?: BN;\n shareFeeReceiver?: PublicKey;\n\n launchPlatformInfo?: Pick<LaunchpadPlatformInfo, \"feeRate\" | \"creatorFeeRate\">;\n slot?: number;\n mintInfo?: ApiV3Token;\n\n ownerInfo?: {\n useSOLBalance?: boolean;\n feePayer?: PublicKey;\n };\n checkCreateATAOwner?: boolean;\n computeBudgetConfig?: ComputeBudgetConfig;\n txVersion: T;\n }): Promise<\n MakeTxData<\n T,\n {\n routes: { mint: PublicKey; amount: BN; decimal: number }[];\n outAmount: BN;\n minOutAmount: BN;\n }\n >\n > {\n const feePayer = ownerInfo?.feePayer || this.scope.ownerPubKey;\n const epochInfo = propsEpochInfo ?? (await this.scope.fetchEpochInfo());\n\n const {\n clmmPoolData,\n clmmComputeAmount: { maxClmmAmountIn, clmmAmountOut, remainingAccounts },\n launchPoolInfo,\n launchAuthProgramId,\n launchSwapInfo,\n outAmount,\n minOutAmount,\n } = await this.computeClmmToLaunchAmount({\n inputMint,\n inputAmount,\n fixClmmOut,\n clmmPoolId,\n launchPoolId,\n slippage,\n epochInfo,\n shareFeeRate,\n launchPlatformInfo,\n slot,\n mintInfo,\n });\n const baseIn = inputMint.toString() === clmmPoolData.poolInfo.mintA.address;\n\n const mintAUseSOLBalance = ownerInfo.useSOLBalance && clmmPoolData.poolInfo.mintA.address === WSOLMint.toBase58();\n const mintBUseSOLBalance = ownerInfo.useSOLBalance && clmmPoolData.poolInfo.mintB.address === WSOLMint.toBase58();\n const tokenAccountMap: Record<string, PublicKey> = {};\n\n let sqrtPriceLimitX64: BN;\n if (!priceLimit || priceLimit.equals(new Decimal(0))) {\n sqrtPriceLimitX64 = baseIn ? MIN_SQRT_PRICE_X64.add(new BN(1)) : MAX_SQRT_PRICE_X64.sub(new BN(1));\n } else {\n sqrtPriceLimitX64 = SqrtPriceMath.priceToSqrtPriceX64(\n priceLimit,\n clmmPoolData.poolInfo.mintA.decimals,\n clmmPoolData.poolInfo.mintB.decimals,\n );\n }\n\n const txBuilder = this.createTxBuilder(feePayer);\n\n const [clmmMintA, clmmMintB] = [\n new PublicKey(clmmPoolData.poolInfo.mintA.address),\n new PublicKey(clmmPoolData.poolInfo.mintB.address),\n ];\n const [clmmMintAProgram, clmmMintBProgram] = [\n new PublicKey(clmmPoolData.poolInfo.mintA.programId),\n new PublicKey(clmmPoolData.poolInfo.mintB.programId),\n ];\n\n const ownerTokenAccountA = this.scope.account.getAssociatedTokenAccount(clmmMintA, clmmMintAProgram);\n const ownerTokenAccountB = this.scope.account.getAssociatedTokenAccount(clmmMintB, clmmMintBProgram);\n\n txBuilder.addInstruction({\n instructions: [\n createAssociatedTokenAccountIdempotentInstruction(\n this.scope.ownerPubKey,\n ownerTokenAccountA,\n this.scope.ownerPubKey,\n clmmMintA,\n clmmMintAProgram,\n ),\n createAssociatedTokenAccountIdempotentInstruction(\n this.scope.ownerPubKey,\n ownerTokenAccountB,\n this.scope.ownerPubKey,\n clmmMintB,\n clmmMintBProgram,\n ),\n ],\n });\n\n if ((baseIn && mintAUseSOLBalance) || (!baseIn && mintBUseSOLBalance)) {\n txBuilder.addInstruction({\n instructions: [\n SystemProgram.transfer({\n fromPubkey: this.scope.ownerPubKey,\n toPubkey: baseIn ? ownerTokenAccountA : ownerTokenAccountB,\n lamports: BigInt(maxClmmAmountIn.toString()),\n }),\n createSyncNativeInstruction(baseIn ? ownerTokenAccountA : ownerTokenAccountB),\n ],\n });\n }\n\n tokenAccountMap[clmmPoolData.poolInfo.mintA.address] = ownerTokenAccountA;\n tokenAccountMap[clmmPoolData.poolInfo.mintB.address] = ownerTokenAccountB;\n\n if (!ownerTokenAccountA || !ownerTokenAccountB)\n this.logAndCreateError(\"user do not have token account\", {\n ownerTokenAccountA,\n ownerTokenAccountB,\n });\n\n txBuilder.addInstruction(\n fixClmmOut\n ? ClmmInstrument.makeSwapBaseOutInstructions({\n poolInfo: clmmPoolData.poolInfo,\n poolKeys: clmmPoolData.poolKeys,\n observationId: clmmPoolData.computePoolInfo.observationId,\n ownerInfo: {\n wallet: this.scope.ownerPubKey,\n tokenAccountA: ownerTokenAccountA!,\n tokenAccountB: ownerTokenAccountB!,\n },\n outputMint: baseIn ? clmmMintB : clmmMintA,\n amountOut: clmmAmountOut,\n amountInMax: maxClmmAmountIn,\n sqrtPriceLimitX64,\n remainingAccounts,\n })\n : ClmmInstrument.makeSwapBaseInInstructions({\n poolInfo: clmmPoolData.poolInfo,\n poolKeys: clmmPoolData.poolKeys,\n observationId: clmmPoolData.computePoolInfo.observationId,\n ownerInfo: {\n wallet: this.scope.ownerPubKey,\n tokenAccountA: ownerTokenAccountA!,\n tokenAccountB: ownerTokenAccountB!,\n },\n inputMint: new PublicKey(inputMint),\n amountIn: inputAmount,\n amountOutMin: clmmAmountOut,\n sqrtPriceLimitX64,\n remainingAccounts,\n }),\n );\n\n const launchMintAProgram = launchPoolInfo.mintProgramFlag === 0 ? TOKEN_PROGRAM_ID : TOKEN_2022_PROGRAM_ID;\n const launchTokenAccountA = this.scope.account.getAssociatedTokenAccount(launchPoolInfo.mintA, launchMintAProgram);\n let launchTokenAccountB = tokenAccountMap[launchPoolInfo.mintB.toBase58()];\n\n txBuilder.addInstruction({\n instructions: [\n createAssociatedTokenAccountIdempotentInstruction(\n this.scope.ownerPubKey,\n launchTokenAccountA,\n this.scope.ownerPubKey,\n launchPoolInfo.mintA,\n launchMintAProgram,\n ),\n ],\n });\n\n if (!launchTokenAccountB) {\n const mintBUseSol = launchPoolInfo.mintB.equals(WSOLMint);\n const { account, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: TOKEN_PROGRAM_ID,\n mint: launchPoolInfo.mintB,\n notUseTokenAccount: mintBUseSol,\n owner: this.scope.ownerPubKey,\n skipCloseAccount: !mintBUseSol,\n createInfo: mintBUseSol\n ? {\n payer: this.scope.ownerPubKey!,\n amount: clmmAmountOut,\n }\n : undefined,\n associatedOnly: false,\n checkCreateATAOwner,\n });\n launchTokenAccountB = account!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n\n txBuilder.addInstruction({\n instructions: [\n buyExactInInstruction(\n launchPoolInfo.programId,\n this.scope.ownerPubKey,\n launchAuthProgramId,\n launchPoolInfo.configId,\n launchPoolInfo.platformId,\n new PublicKey(launchPoolId),\n launchTokenAccountA,\n launchTokenAccountB,\n launchPoolInfo.vaultA,\n launchPoolInfo.vaultB,\n launchPoolInfo.mintA,\n launchPoolInfo.mintB,\n launchMintAProgram,\n TOKEN_PROGRAM_ID,\n\n getPdaPlatformVault(launchPoolInfo.programId, launchPoolInfo.platformId, launchPoolInfo.mintB).publicKey,\n getPdaCreatorVault(launchPoolInfo.programId, launchPoolInfo.creator, launchPoolInfo.mintB).publicKey,\n\n launchSwapInfo.amountB.lt(clmmAmountOut) ? launchSwapInfo.amountB : clmmAmountOut,\n minOutAmount,\n shareFeeRate,\n shareFeeReceiver,\n ),\n ],\n });\n\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n\n return txBuilder.versionBuild({\n txVersion,\n extInfo: {\n routes: [\n {\n mint: new PublicKey(inputMint),\n amount: fixClmmOut ? maxClmmAmountIn : inputAmount,\n decimal: clmmPoolData.poolInfo[baseIn ? \"mintA\" : \"mintB\"].decimals,\n },\n {\n mint: baseIn ? clmmMintB : clmmMintA,\n amount: clmmAmountOut,\n decimal: clmmPoolData.poolInfo[baseIn ? \"mintB\" : \"mintA\"].decimals,\n },\n {\n mint: launchPoolInfo.mintA,\n amount: outAmount,\n decimal: launchPoolInfo.mintDecimalsA,\n },\n ],\n outAmount,\n minOutAmount,\n },\n }) as Promise<\n MakeTxData<\n T,\n {\n routes: { mint: PublicKey; amount: BN; decimal: number }[];\n outAmount: BN;\n minOutAmount: BN;\n }\n >\n >;\n }\n\n public async computeClmmToLaunchAmount({\n inputMint,\n inputAmount,\n fixClmmOut = false,\n clmmPoolId,\n launchPoolId,\n slippage: propsSlippage,\n epochInfo,\n shareFeeRate = new BN(0),\n\n clmmPoolData: propsClmmPoolData,\n launchPoolInfo: propsLaunchPoolInfo,\n launchPlatformInfo: propsLaunchPlatformInfo,\n slot,\n mintInfo: propsMintInfo,\n }: {\n clmmPoolId: string | PublicKey;\n launchPoolId: string | PublicKey;\n inputMint: string | PublicKey;\n inputAmount: BN;\n fixClmmOut?: boolean;\n slippage: number;\n epochInfo?: EpochInfo;\n shareFeeRate?: BN;\n\n clmmPoolData?: {\n poolInfo: ApiV3PoolInfoConcentratedItem;\n poolKeys: ClmmKeys;\n computePoolInfo: ComputeClmmPoolInfo;\n tickData: ReturnTypeFetchMultiplePoolTickArrays;\n };\n launchPoolInfo?: LaunchpadPoolInfo & { programId: PublicKey; configInfo: LaunchpadConfigInfo };\n launchPlatformInfo?: Pick<LaunchpadPlatformInfo, \"feeRate\" | \"creatorFeeRate\">;\n slot?: number;\n mintInfo?: ApiV3Token;\n }): Promise<{\n clmmPoolData: {\n poolInfo: ApiV3PoolInfoConcentratedItem;\n poolKeys: ClmmKeys;\n computePoolInfo: ComputeClmmPoolInfo;\n tickData: ReturnTypeFetchMultiplePoolTickArrays;\n };\n clmmComputeAmount: { maxClmmAmountIn: BN; clmmAmountOut: BN; remainingAccounts: PublicKey[] };\n clmmComputeInfo: ReturnTypeComputeAmountOutBaseOut | ReturnTypeComputeAmountOutFormat;\n launchPoolInfo: LaunchpadPoolInfo & { programId: PublicKey; configInfo: LaunchpadConfigInfo };\n launchAuthProgramId: PublicKey;\n outAmount: BN;\n minOutAmount: BN;\n launchSwapInfo: SwapInfoReturn;\n launchMintTransferFeeConfig?: TransferFeeConfig;\n }> {\n // split slippage for clmm swap and launch buy\n const slippage =\n propsSlippage > 0\n ? new Decimal(propsSlippage).div(2).toDecimalPlaces(4, Decimal.ROUND_DOWN).toNumber()\n : propsSlippage;\n const clmmPoolData = propsClmmPoolData ?? (await this.scope.clmm.getPoolInfoFromRpc(clmmPoolId.toString()));\n if (\n inputMint.toString() !== clmmPoolData.poolInfo.mintA.address &&\n inputMint.toString() !== clmmPoolData.poolInfo.mintB.address\n )\n throw new Error(\"input mint does not match clmm pool mints, please check\");\n const baseIn = inputMint.toString() === clmmPoolData.poolInfo.mintA.address;\n const tokenOut = clmmPoolData.poolInfo[baseIn ? \"mintB\" : \"mintA\"];\n\n const clmmComputeAmount = fixClmmOut\n ? await PoolUtils.computeAmountIn({\n poolInfo: clmmPoolData.computePoolInfo,\n tickArrayCache: clmmPoolData.tickData[clmmPoolId.toString()],\n amountOut: inputAmount,\n baseMint: new PublicKey(clmmPoolData.poolInfo[baseIn ? \"mintB\" : \"mintA\"].address),\n slippage,\n epochInfo: epochInfo ?? (await this.scope.fetchEpochInfo()),\n })\n : await PoolUtils.computeAmountOutFormat({\n poolInfo: clmmPoolData.computePoolInfo,\n tickArrayCache: clmmPoolData.tickData[clmmPoolId.toString()],\n amountIn: inputAmount,\n tokenOut,\n slippage,\n epochInfo: epochInfo ?? (await this.scope.fetchEpochInfo()),\n });\n\n let launchPoolInfo = propsLaunchPoolInfo;\n if (!launchPoolInfo)\n launchPoolInfo = await this.scope.launchpad.getRpcPoolInfo({ poolId: new PublicKey(launchPoolId) });\n\n if (tokenOut.address !== launchPoolInfo.mintB.toBase58())\n throw new Error(`clmm swap mint(${tokenOut.address}) != launch pool mintB(${launchPoolInfo.mintB.toBase58()})`);\n let platformInfo = propsLaunchPlatformInfo;\n if (!platformInfo) {\n const data = await this.scope.connection.getAccountInfo(launchPoolInfo.platformId);\n platformInfo = PlatformConfig.decode(data!.data);\n }\n const mintInfo = propsMintInfo ?? (await this.scope.token.getTokenInfo(launchPoolInfo.mintA));\n const authProgramId = getPdaLaunchpadAuth(launchPoolInfo.programId).publicKey;\n\n const launchMintTransferFeeConfig = mintInfo.extensions.feeConfig\n ? {\n transferFeeConfigAuthority: PublicKey.default,\n withdrawWithheldAuthority: PublicKey.default,\n withheldAmount: BigInt(0),\n olderTransferFee: {\n epoch: BigInt(mintInfo.extensions.feeConfig.olderTransferFee.epoch ?? epochInfo?.epoch ?? 0),\n maximumFee: BigInt(mintInfo.extensions.feeConfig.olderTransferFee.maximumFee),\n transferFeeBasisPoints: mintInfo.extensions.feeConfig.olderTransferFee.transferFeeBasisPoints,\n },\n newerTransferFee: {\n epoch: BigInt(mintInfo.extensions.feeConfig.newerTransferFee.epoch ?? epochInfo?.epoch ?? 0),\n maximumFee: BigInt(mintInfo.extensions.feeConfig.newerTransferFee.maximumFee),\n transferFeeBasisPoints: mintInfo.extensions.feeConfig.newerTransferFee.transferFeeBasisPoints,\n },\n }\n : undefined;\n\n const launchBuyAmount = fixClmmOut\n ? inputAmount\n : (clmmComputeAmount as ReturnTypeComputeAmountOutFormat).minAmountOut.amount.raw;\n\n const launchSwapInfo = Curve.buyExactIn({\n poolInfo: launchPoolInfo,\n amountB: launchBuyAmount,\n protocolFeeRate: launchPoolInfo.configInfo.tradeFeeRate,\n platformFeeRate: platformInfo.feeRate,\n curveType: launchPoolInfo.configInfo.curveType,\n shareFeeRate,\n creatorFeeRate: platformInfo.creatorFeeRate,\n transferFeeConfigA: launchMintTransferFeeConfig,\n slot: slot ?? (await this.scope.connection.getSlot()),\n });\n\n const outAmount = launchSwapInfo.amountA.amount.sub(launchSwapInfo.amountA.fee ?? new BN(0));\n const decimalAmountA = new Decimal(outAmount.toString());\n\n const SLIPPAGE_UNIT = new BN(10000);\n const multiplier = slippage\n ? new Decimal(SLIPPAGE_UNIT.sub(new BN(slippage * 10000)).toNumber() / SLIPPAGE_UNIT.toNumber()).clampedTo(0, 1)\n : new Decimal(1);\n\n return {\n clmmPoolData,\n clmmComputeAmount: {\n maxClmmAmountIn: fixClmmOut\n ? (clmmComputeAmount as ReturnTypeComputeAmountOutBaseOut).maxAmountIn.amount\n : inputAmount,\n clmmAmountOut: launchBuyAmount,\n remainingAccounts: clmmComputeAmount.remainingAccounts,\n },\n clmmComputeInfo: clmmComputeAmount,\n\n launchPoolInfo,\n launchAuthProgramId: authProgramId,\n launchMintTransferFeeConfig,\n launchSwapInfo,\n outAmount: launchSwapInfo.amountA.amount.sub(launchSwapInfo.amountA.fee ?? new BN(0)),\n minOutAmount: new BN(decimalAmountA.mul(multiplier).toFixed(0)),\n };\n }\n\n public async swapLaunchMintToClmm<T extends TxVersion>({\n inputAmount,\n clmmPoolId,\n launchPoolId,\n priceLimit,\n slippage = 0.01,\n shareFeeRate = new BN(0),\n shareFeeReceiver,\n ownerInfo = { useSOLBalance: true },\n checkCreateATAOwner = false,\n computeBudgetConfig,\n txVersion,\n }: {\n inputAmount: BN;\n clmmPoolId: string | PublicKey;\n launchPoolId: string | PublicKey;\n priceLimit?: Decimal;\n slippage: number; // from 0~1\n shareFeeRate?: BN;\n shareFeeReceiver?: PublicKey;\n ownerInfo?: {\n useSOLBalance?: boolean;\n feePayer?: PublicKey;\n };\n checkCreateATAOwner?: boolean;\n computeBudgetConfig?: ComputeBudgetConfig;\n txVersion: T;\n }): Promise<\n MakeTxData<\n T,\n {\n routes: { mint: PublicKey; amount: BN; decimal: number }[];\n outAmount: BN;\n minOutAmount: BN;\n }\n >\n > {\n const feePayer = ownerInfo?.feePayer || this.scope.ownerPubKey;\n const epochInfo = await this.scope.fetchEpochInfo();\n\n const {\n clmmPoolData,\n clmmComputeAmount: { remainingAccounts },\n launchPoolInfo,\n launchAuthProgramId,\n launchSwapInfo,\n minLaunchOutAmount,\n outAmount,\n minOutAmount,\n } = await this.computeLaunchToClmmAmount({\n inputAmount,\n clmmPoolId,\n launchPoolId,\n slippage,\n epochInfo,\n shareFeeRate,\n });\n\n const txBuilder = this.createTxBuilder(feePayer);\n const tokenAccountMap: Record<string, PublicKey> = {};\n\n const launchMintAProgram = launchPoolInfo.mintProgramFlag === 0 ? TOKEN_PROGRAM_ID : TOKEN_2022_PROGRAM_ID;\n\n const { account: launchTokenAccountA } = await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: launchMintAProgram,\n mint: launchPoolInfo.mintA,\n notUseTokenAccount: false,\n owner: this.scope.ownerPubKey,\n skipCloseAccount: true,\n createInfo: undefined,\n associatedOnly: true,\n checkCreateATAOwner,\n });\n if (!launchTokenAccountA)\n throw new Error(`do not have launch mint(${launchPoolInfo.mintA.toString()}) token account`);\n\n const mintBUseSol = launchPoolInfo.mintB.equals(WSOLMint);\n const { account: launchTokenAccountB, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: TOKEN_PROGRAM_ID,\n mint: launchPoolInfo.mintB,\n notUseTokenAccount: mintBUseSol,\n owner: this.scope.ownerPubKey,\n skipCloseAccount: !mintBUseSol,\n createInfo: {\n payer: this.scope.ownerPubKey!,\n amount: 0,\n },\n associatedOnly: false,\n checkCreateATAOwner,\n });\n instructionParams && txBuilder.addInstruction(instructionParams);\n if (!launchTokenAccountB)\n throw new Error(`do not have launch mint(${launchPoolInfo.mintA.toString()}) token account`);\n tokenAccountMap[launchPoolInfo.mintB.toBase58()] = launchTokenAccountB;\n\n txBuilder.addInstruction({\n instructions: [\n sellExactInInstruction(\n launchPoolInfo.programId,\n this.scope.ownerPubKey,\n launchAuthProgramId,\n launchPoolInfo.configId,\n launchPoolInfo.platformId,\n new PublicKey(launchPoolId),\n launchTokenAccountA,\n launchTokenAccountB,\n launchPoolInfo.vaultA,\n launchPoolInfo.vaultB,\n launchPoolInfo.mintA,\n launchPoolInfo.mintB,\n launchMintAProgram,\n TOKEN_PROGRAM_ID,\n\n getPdaPlatformVault(launchPoolInfo.programId, launchPoolInfo.platformId, launchPoolInfo.mintB).publicKey,\n getPdaCreatorVault(launchPoolInfo.programId, launchPoolInfo.creator, launchPoolInfo.mintB).publicKey,\n\n launchSwapInfo.amountA.amount.lt(inputAmount) ? launchSwapInfo.amountA.amount : inputAmount,\n minLaunchOutAmount,\n shareFeeRate,\n shareFeeReceiver,\n ),\n ],\n });\n\n const baseIn = launchPoolInfo.mintB.toString() === clmmPoolData.poolInfo.mintA.address;\n const mintAUseSOLBalance = ownerInfo.useSOLBalance && clmmPoolData.poolInfo.mintA.address === WSOLMint.toBase58();\n const mintBUseSOLBalance = ownerInfo.useSOLBalance && clmmPoolData.poolInfo.mintB.address === WSOLMint.toBase58();\n\n let sqrtPriceLimitX64: BN;\n if (!priceLimit || priceLimit.equals(new Decimal(0))) {\n sqrtPriceLimitX64 = baseIn ? MIN_SQRT_PRICE_X64.add(new BN(1)) : MAX_SQRT_PRICE_X64.sub(new BN(1));\n } else {\n sqrtPriceLimitX64 = SqrtPriceMath.priceToSqrtPriceX64(\n priceLimit,\n clmmPoolData.poolInfo.mintA.decimals,\n clmmPoolData.poolInfo.mintB.decimals,\n );\n }\n\n const [clmmMintA, clmmMintB] = [\n new PublicKey(clmmPoolData.poolInfo.mintA.address),\n new PublicKey(clmmPoolData.poolInfo.mintB.address),\n ];\n const [clmmMintAProgram, clmmMintBProgram] = [\n new PublicKey(clmmPoolData.poolInfo.mintA.programId),\n new PublicKey(clmmPoolData.poolInfo.mintB.programId),\n ];\n\n let ownerTokenAccountA = mintAUseSOLBalance\n ? undefined\n : this.scope.account.getAssociatedTokenAccount(clmmMintA, clmmMintAProgram);\n\n let ownerTokenAccountB = mintBUseSOLBalance\n ? undefined\n : this.scope.account.getAssociatedTokenAccount(clmmMintB, clmmMintBProgram);\n\n // this means mintA is wsol\n if (!ownerTokenAccountA) {\n const { account, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: clmmMintAProgram,\n mint: clmmMintA,\n notUseTokenAccount: true,\n owner: this.scope.ownerPubKey,\n skipCloseAccount: false,\n createInfo: {\n payer: ownerInfo.feePayer || this.scope.ownerPubKey,\n amount: baseIn ? inputAmount : 0,\n },\n associatedOnly: false,\n checkCreateATAOwner,\n });\n ownerTokenAccountA = account!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n\n // this means mintB is wsol\n if (!ownerTokenAccountB) {\n const { account, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: clmmMintBProgram,\n mint: clmmMintB,\n notUseTokenAccount: true,\n owner: this.scope.ownerPubKey,\n skipCloseAccount: false,\n createInfo: {\n payer: ownerInfo.feePayer || this.scope.ownerPubKey,\n amount: baseIn ? 0 : inputAmount,\n },\n associatedOnly: false,\n checkCreateATAOwner,\n });\n ownerTokenAccountB = account!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n tokenAccountMap[clmmPoolData.poolInfo.mintA.address] = ownerTokenAccountA;\n tokenAccountMap[clmmPoolData.poolInfo.mintB.address] = ownerTokenAccountB;\n\n if (!ownerTokenAccountA || !ownerTokenAccountB)\n this.logAndCreateError(\"user do not have token account\", {\n ownerTokenAccountA,\n ownerTokenAccountB,\n });\n\n txBuilder.addInstruction(\n ClmmInstrument.makeSwapBaseInInstructions({\n poolInfo: clmmPoolData.poolInfo,\n poolKeys: clmmPoolData.poolKeys,\n observationId: clmmPoolData.computePoolInfo.observationId,\n ownerInfo: {\n wallet: this.scope.ownerPubKey,\n tokenAccountA: ownerTokenAccountA!,\n tokenAccountB: ownerTokenAccountB!,\n },\n inputMint: new PublicKey(clmmPoolData.poolKeys[baseIn ? \"mintA\" : \"mintB\"].address),\n amountIn: minLaunchOutAmount,\n amountOutMin: minOutAmount,\n sqrtPriceLimitX64,\n remainingAccounts,\n }),\n );\n\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n\n return txBuilder.versionBuild({\n txVersion,\n extInfo: {\n routes: [\n {\n mint: launchPoolInfo.mintA,\n amount: inputAmount,\n decimal: launchPoolInfo.mintDecimalsA,\n },\n {\n mint: launchPoolInfo.mintB,\n amount: minLaunchOutAmount,\n decimal: launchPoolInfo.mintDecimalsB,\n },\n {\n mint: new PublicKey(clmmPoolData.poolKeys[baseIn ? \"mintB\" : \"mintA\"].address),\n amount: outAmount,\n decimal: clmmPoolData.poolKeys[baseIn ? \"mintB\" : \"mintA\"].decimals,\n },\n ],\n outAmount,\n minOutAmount,\n },\n }) as Promise<\n MakeTxData<\n T,\n {\n routes: { mint: PublicKey; amount: BN; decimal: number }[];\n outAmount: BN;\n minOutAmount: BN;\n }\n >\n >;\n }\n\n public async computeLaunchToClmmAmount({\n inputAmount,\n clmmPoolId,\n launchPoolId,\n slippage: propsSlippage,\n epochInfo,\n shareFeeRate = new BN(0),\n\n clmmPoolData: propsClmmPoolData,\n launchPoolInfo: propsLaunchPoolInfo,\n launchPlatformInfo: propsLaunchPlatformInfo,\n }: {\n clmmPoolId: string | PublicKey;\n launchPoolId: string | PublicKey;\n inputAmount: BN;\n slippage: number;\n epochInfo?: EpochInfo;\n shareFeeRate?: BN;\n\n clmmPoolData?: {\n poolInfo: ApiV3PoolInfoConcentratedItem;\n poolKeys: ClmmKeys;\n computePoolInfo: ComputeClmmPoolInfo;\n tickData: ReturnTypeFetchMultiplePoolTickArrays;\n };\n launchPoolInfo?: LaunchpadPoolInfo & { programId: PublicKey; configInfo: LaunchpadConfigInfo };\n launchPlatformInfo?: LaunchpadPlatformInfo;\n }): Promise<{\n clmmPoolData: {\n poolInfo: ApiV3PoolInfoConcentratedItem;\n poolKeys: ClmmKeys;\n computePoolInfo: ComputeClmmPoolInfo;\n tickData: ReturnTypeFetchMultiplePoolTickArrays;\n };\n clmmComputeAmount: ReturnTypeComputeAmountOutFormat;\n launchPoolInfo: LaunchpadPoolInfo & { programId: PublicKey; configInfo: LaunchpadConfigInfo };\n launchAuthProgramId: PublicKey;\n minLaunchOutAmount: BN;\n outAmount: BN;\n minOutAmount: BN;\n launchSwapInfo: SwapInfoReturn;\n launchMintTransferFeeConfig?: TransferFeeConfig;\n }> {\n // split slippage for clmm swap and launch buy\n const slippage =\n propsSlippage > 0\n ? new Decimal(propsSlippage).div(2).toDecimalPlaces(4, Decimal.ROUND_DOWN).toNumber()\n : propsSlippage;\n\n let launchPoolInfo = propsLaunchPoolInfo;\n if (!launchPoolInfo)\n launchPoolInfo = await this.scope.launchpad.getRpcPoolInfo({ poolId: new PublicKey(launchPoolId) });\n\n const inputMint = launchPoolInfo.mintB;\n\n const clmmPoolData = propsClmmPoolData ?? (await this.scope.clmm.getPoolInfoFromRpc(clmmPoolId.toString()));\n if (\n inputMint.toString() !== clmmPoolData.poolInfo.mintA.address &&\n inputMint.toString() !== clmmPoolData.poolInfo.mintB.address\n )\n throw new Error(\"input mint does not match clmm pool mints, please check\");\n\n const baseIn = inputMint.toString() === clmmPoolData.poolInfo.mintA.address;\n const tokenOut = clmmPoolData.poolInfo[baseIn ? \"mintB\" : \"mintA\"];\n\n let platformInfo = propsLaunchPlatformInfo;\n if (!platformInfo) {\n const data = await this.scope.connection.getAccountInfo(launchPoolInfo.platformId);\n platformInfo = PlatformConfig.decode(data!.data);\n }\n const mintInfo = await this.scope.token.getTokenInfo(launchPoolInfo.mintA);\n const authProgramId = getPdaLaunchpadAuth(launchPoolInfo.programId).publicKey;\n\n const launchMintTransferFeeConfig = mintInfo.extensions.feeConfig\n ? {\n transferFeeConfigAuthority: PublicKey.default,\n withdrawWithheldAuthority: PublicKey.default,\n withheldAmount: BigInt(0),\n olderTransferFee: {\n epoch: BigInt(mintInfo.extensions.feeConfig.olderTransferFee.epoch ?? epochInfo?.epoch ?? 0),\n maximumFee: BigInt(mintInfo.extensions.feeConfig.olderTransferFee.maximumFee),\n transferFeeBasisPoints: mintInfo.extensions.feeConfig.olderTransferFee.transferFeeBasisPoints,\n },\n newerTransferFee: {\n epoch: BigInt(mintInfo.extensions.feeConfig.newerTransferFee.epoch ?? epochInfo?.epoch ?? 0),\n maximumFee: BigInt(mintInfo.extensions.feeConfig.newerTransferFee.maximumFee),\n transferFeeBasisPoints: mintInfo.extensions.feeConfig.newerTransferFee.transferFeeBasisPoints,\n },\n }\n : undefined;\n\n const launchSwapInfo = Curve.sellExactIn({\n poolInfo: launchPoolInfo,\n amountA: inputAmount,\n protocolFeeRate: launchPoolInfo.configInfo.tradeFeeRate,\n platformFeeRate: platformInfo.feeRate,\n curveType: launchPoolInfo.configInfo.curveType,\n shareFeeRate,\n creatorFeeRate: platformInfo.creatorFeeRate,\n transferFeeConfigA: launchMintTransferFeeConfig,\n slot: await this.scope.connection.getSlot(),\n });\n\n const outAmount = launchSwapInfo.amountB;\n const decimalAmountB = new Decimal(outAmount.toString());\n\n const SLIPPAGE_UNIT = new BN(10000);\n const multiplier = slippage\n ? new Decimal(SLIPPAGE_UNIT.sub(new BN(slippage * 10000)).toNumber() / SLIPPAGE_UNIT.toNumber()).clampedTo(0, 1)\n : new Decimal(1);\n\n const minLaunchOutAmount = new BN(decimalAmountB.mul(multiplier).toFixed(0));\n\n const clmmComputeAmount = await PoolUtils.computeAmountOutFormat({\n poolInfo: clmmPoolData.computePoolInfo,\n tickArrayCache: clmmPoolData.tickData[clmmPoolId.toString()],\n amountIn: minLaunchOutAmount,\n tokenOut,\n slippage,\n epochInfo: epochInfo ?? (await this.scope.fetchEpochInfo()),\n });\n\n return {\n clmmPoolData,\n clmmComputeAmount,\n\n launchPoolInfo,\n launchAuthProgramId: authProgramId,\n launchMintTransferFeeConfig,\n launchSwapInfo,\n minLaunchOutAmount,\n outAmount: clmmComputeAmount.amountOut.amount.raw,\n minOutAmount: clmmComputeAmount.minAmountOut.amount.raw,\n };\n }\n\n // get all amm/clmm/cpmm pools data only with id and mint\n public async fetchRoutePoolBasicInfo(programIds?: { amm: PublicKey; clmm: PublicKey; cpmm: PublicKey }): Promise<{\n ammPools: BasicPoolInfo[];\n clmmPools: BasicPoolInfo[];\n cpmmPools: BasicPoolInfo[];\n }> {\n const { amm = AMM_V4, clmm = CLMM_PROGRAM_ID, cpmm = CREATE_CPMM_POOL_PROGRAM } = programIds || {};\n const ammPoolsData = await this.scope.connection.getProgramAccounts(amm, {\n dataSlice: { offset: liquidityStateV4Layout.offsetOf(\"baseMint\"), length: 64 },\n });\n\n const layoutAmm = struct([publicKey(\"baseMint\"), publicKey(\"quoteMint\")]);\n const ammData = ammPoolsData.map((data) => ({\n id: data.pubkey,\n version: 4,\n mintA: layoutAmm.decode(data.account.data).baseMint,\n mintB: layoutAmm.decode(data.account.data).quoteMint,\n }));\n\n const layout = struct([publicKey(\"mintA\"), publicKey(\"mintB\")]);\n const clmmPoolsData = await this.scope.connection.getProgramAccounts(clmm, {\n filters: [{ dataSize: PoolInfoLayout.span }],\n dataSlice: { offset: PoolInfoLayout.offsetOf(\"mintA\"), length: 64 },\n });\n\n const clmmData = clmmPoolsData.map((data) => {\n const clmm = layout.decode(data.account.data);\n return {\n id: data.pubkey,\n version: 6,\n mintA: clmm.mintA,\n mintB: clmm.mintB,\n };\n });\n\n const cpmmPools = await this.scope.connection.getProgramAccounts(cpmm, {\n dataSlice: { offset: CpmmPoolInfoLayout.offsetOf(\"mintA\"), length: 64 },\n });\n\n const cpmmData = cpmmPools.map((data) => {\n const clmm = layout.decode(data.account.data);\n return {\n id: data.pubkey,\n version: 7,\n mintA: clmm.mintA,\n mintB: clmm.mintB,\n };\n });\n\n return {\n clmmPools: clmmData,\n ammPools: ammData,\n cpmmPools: cpmmData,\n };\n }\n\n // get pools with in routes\n public getAllRoute({\n inputMint,\n outputMint,\n clmmPools,\n ammPools,\n cpmmPools,\n }: {\n inputMint: PublicKey;\n outputMint: PublicKey;\n clmmPools: BasicPoolInfo[];\n ammPools: BasicPoolInfo[];\n cpmmPools: BasicPoolInfo[];\n }): ReturnTypeGetAllRoute {\n inputMint = inputMint.toString() === PublicKey.default.toString() ? WSOLMint : inputMint;\n outputMint = outputMint.toString() === PublicKey.default.toString() ? WSOLMint : outputMint;\n\n const needSimulate: { [poolKey: string]: BasicPoolInfo } = {};\n const needTickArray: { [poolKey: string]: BasicPoolInfo } = {};\n const cpmmPoolList: { [poolKey: string]: BasicPoolInfo } = {};\n\n const directPath: BasicPoolInfo[] = [];\n\n const routePathDict: RoutePathType = {}; // {[route mint: string]: {in: [] , out: []}}\n\n for (const itemClmmPool of clmmPools ?? []) {\n if (\n (itemClmmPool.mintA.equals(inputMint) && itemClmmPool.mintB.equals(outputMint)) ||\n (itemClmmPool.mintA.equals(outputMint) && itemClmmPool.mintB.equals(inputMint))\n ) {\n directPath.push(itemClmmPool);\n needTickArray[itemClmmPool.id.toString()] = itemClmmPool;\n }\n\n if (itemClmmPool.mintA.equals(inputMint)) {\n const t = itemClmmPool.mintB.toString();\n if (routePathDict[t] === undefined)\n routePathDict[t] = {\n mintProgram: TOKEN_PROGRAM_ID, // to fetch later\n in: [],\n out: [],\n mDecimals: 0, // to fetch later\n };\n routePathDict[t].in.push(itemClmmPool);\n }\n if (itemClmmPool.mintB.equals(inputMint)) {\n const t = itemClmmPool.mintA.toString();\n if (routePathDict[t] === undefined)\n routePathDict[t] = {\n mintProgram: TOKEN_PROGRAM_ID, // to fetch later\n in: [],\n out: [],\n mDecimals: 0, // to fetch later\n };\n routePathDict[t].in.push(itemClmmPool);\n }\n if (itemClmmPool.mintA.equals(outputMint)) {\n const t = itemClmmPool.mintB.toString();\n if (routePathDict[t] === undefined)\n routePathDict[t] = {\n mintProgram: TOKEN_PROGRAM_ID, // to fetch later\n in: [],\n out: [],\n mDecimals: 0, // to fetch later\n };\n routePathDict[t].out.push(itemClmmPool);\n }\n if (itemClmmPool.mintB.equals(outputMint)) {\n const t = itemClmmPool.mintA.toString();\n if (routePathDict[t] === undefined)\n routePathDict[t] = {\n mintProgram: TOKEN_PROGRAM_ID, // to fetch later\n in: [],\n out: [],\n mDecimals: 0, // to fetch later\n };\n routePathDict[t].out.push(itemClmmPool);\n }\n }\n\n co