UNPKG

@raydium-io/raydium-sdk-v2

Version:

An SDK for building applications on top of Raydium.

1 lines 819 kB
{"version":3,"sources":["../../../src/raydium/cpmm/cpmm.ts","../../../src/common/bignumber.ts","../../../node_modules/decimal.js/decimal.mjs","../../../src/module/amount.ts","../../../src/common/logger.ts","../../../src/common/accountInfo.ts","../../../src/common/constant.ts","../../../src/raydium/token/constant.ts","../../../src/module/token.ts","../../../src/common/pubKey.ts","../../../src/module/currency.ts","../../../src/module/formatter.ts","../../../src/module/fraction.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/raydium/cpmm/curve/calculator.ts","../../../src/raydium/cpmm/curve/constantProduct.ts","../../../src/raydium/cpmm/curve/fee.ts","../../../src/raydium/moduleBase.ts","../../../src/marshmallow/index.ts","../../../src/marshmallow/buffer-layout.ts","../../../src/raydium/token/layout.ts","../../../src/raydium/token/utils.ts","../../../src/raydium/cpmm/instruction.ts","../../../src/raydium/cpmm/pda.ts","../../../src/raydium/clmm/clmm.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/pda.ts","../../../src/raydium/clmm/utils/pool.ts","../../../src/raydium/clmm/utils/position.ts","../../../src/raydium/clmm/utils/tickarrayBitmap.ts","../../../src/raydium/clmm/layout.ts","../../../src/raydium/cpmm/layout.ts"],"sourcesContent":["import { PublicKey } from \"@solana/web3.js\";\nimport { ApiV3PoolInfoStandardItemCpmm, CpmmKeys } from \"../../api/type\";\nimport {\n AccountLayout,\n NATIVE_MINT,\n TOKEN_PROGRAM_ID,\n createAssociatedTokenAccountIdempotentInstruction,\n} from \"@solana/spl-token\";\nimport { BN_ZERO } from \"@/common/bignumber\";\nimport { getATAAddress } from \"@/common/pda\";\nimport { WSOLMint } from \"@/common/pubKey\";\nimport { MakeMultiTxData, MakeTxData } from \"@/common/txTool/txTool\";\nimport { InstructionType, TxVersion } from \"@/common/txTool/txType\";\nimport { Percent } from \"../../module\";\nimport { CurveCalculator, SwapResult } from \"./curve/calculator\";\n\nimport BN from \"bn.js\";\nimport Decimal from \"decimal.js\";\nimport {\n CREATE_CPMM_POOL_PROGRAM,\n fetchMultipleMintInfos,\n getMultipleAccountsInfoWithCustomFlags,\n getTransferAmountFeeV2,\n LOCK_CPMM_AUTH,\n LOCK_CPMM_PROGRAM,\n} from \"@/common\";\nimport { GetTransferAmountFee, ReturnTypeFetchMultipleMintInfos } from \"../../raydium/type\";\nimport ModuleBase, { ModuleBaseProps } from \"../moduleBase\";\nimport { toApiV3Token, toFeeConfig } from \"../token\";\nimport {\n makeCreateCpmmPoolInInstruction,\n makeDepositCpmmInInstruction,\n makeSwapCpmmBaseInInstruction,\n makeSwapCpmmBaseOutInstruction,\n makeWithdrawCpmmInInstruction,\n makeCpmmLockInstruction,\n collectCpFeeInstruction,\n initializeWithPermission,\n makeCollectCreatorFeeInstruction,\n} from \"./instruction\";\nimport { CpmmConfigInfoLayout, CpmmPoolInfoLayout } from \"./layout\";\nimport { getCreatePoolKeys, getPdaObservationId, getPdaPermissionId, getPdaPoolAuthority } from \"./pda\";\nimport {\n AddCpmmLiquidityParams,\n ComputePairAmountParams,\n CpmmComputeData,\n CpmmLockExtInfo,\n CpmmParsedRpcData,\n CpmmSwapParams,\n CreateCpmmPoolAddress,\n CreateCpmmPoolParam,\n LockCpmmLpParams,\n HarvestLockCpmmLpParams,\n WithdrawCpmmLiquidityParams,\n HarvestMultiLockCpmmLpParams,\n FeeOn,\n CreateCpmmPoolPermissionParam,\n CollectCreatorFees,\n CollectMultiCreatorFees,\n} from \"./type\";\nimport { getCpLockPda } from \"./pda\";\n\nexport default class CpmmModule extends ModuleBase {\n constructor(params: ModuleBaseProps) {\n super(params);\n }\n\n public async load(): Promise<void> {\n this.checkDisabled();\n }\n\n public async getCpmmPoolKeys(poolId: string): Promise<CpmmKeys> {\n return ((await this.scope.api.fetchPoolKeysById({ idList: [poolId] })) as CpmmKeys[])[0];\n }\n\n public async getRpcPoolInfo(poolId: string, fetchConfigInfo?: boolean): Promise<CpmmParsedRpcData> {\n return (await this.getRpcPoolInfos([poolId], fetchConfigInfo))[poolId];\n }\n\n public async getRpcPoolInfos(\n poolIds: string[],\n fetchConfigInfo?: boolean,\n ): Promise<{\n [poolId: string]: CpmmParsedRpcData;\n }> {\n const accounts = await getMultipleAccountsInfoWithCustomFlags(\n this.scope.connection,\n poolIds.map((i) => ({ pubkey: new PublicKey(i) })),\n );\n const poolInfos: { [poolId: string]: ReturnType<typeof CpmmPoolInfoLayout.decode> & { programId: PublicKey } } = {};\n\n const needFetchConfigId = new Set<string>();\n const needFetchVaults: PublicKey[] = [];\n\n for (let i = 0; i < poolIds.length; i++) {\n const item = accounts[i];\n if (item.accountInfo === null) throw Error(\"fetch pool info error: \" + String(poolIds[i]));\n const rpc = CpmmPoolInfoLayout.decode(item.accountInfo.data);\n poolInfos[String(poolIds[i])] = {\n ...rpc,\n programId: item.accountInfo.owner,\n };\n needFetchConfigId.add(String(rpc.configId));\n\n needFetchVaults.push(rpc.vaultA, rpc.vaultB);\n }\n\n const configInfo: { [configId: string]: ReturnType<typeof CpmmConfigInfoLayout.decode> } = {};\n\n if (fetchConfigInfo) {\n const configIds = [...needFetchConfigId];\n const configState = await getMultipleAccountsInfoWithCustomFlags(\n this.scope.connection,\n configIds.map((i) => ({ pubkey: new PublicKey(i) })),\n );\n\n for (let i = 0; i < configIds.length; i++) {\n const configItemInfo = configState[i].accountInfo;\n if (configItemInfo === null) throw Error(\"fetch pool config error: \" + configIds[i]);\n configInfo[configIds[i]] = CpmmConfigInfoLayout.decode(configItemInfo.data);\n }\n }\n\n const vaultInfo: { [vaultId: string]: BN } = {};\n\n const vaultAccountInfo = await getMultipleAccountsInfoWithCustomFlags(\n this.scope.connection,\n needFetchVaults.map((i) => ({ pubkey: new PublicKey(i) })),\n );\n\n for (let i = 0; i < needFetchVaults.length; i++) {\n const vaultItemInfo = vaultAccountInfo[i].accountInfo;\n if (vaultItemInfo === null) throw Error(\"fetch vault info error: \" + needFetchVaults[i]);\n\n vaultInfo[String(needFetchVaults[i])] = new BN(AccountLayout.decode(vaultItemInfo.data).amount.toString());\n }\n\n const returnData: { [poolId: string]: CpmmParsedRpcData } = {};\n\n for (const [id, info] of Object.entries(poolInfos)) {\n const baseReserve = vaultInfo[info.vaultA.toString()]\n .sub(info.protocolFeesMintA)\n .sub(info.fundFeesMintA)\n .sub(info.creatorFeesMintA);\n const quoteReserve = vaultInfo[info.vaultB.toString()]\n .sub(info.protocolFeesMintB)\n .sub(info.fundFeesMintB)\n .sub(info.creatorFeesMintB);\n returnData[id] = {\n ...info,\n baseReserve,\n quoteReserve,\n vaultAAmount: vaultInfo[info.vaultA.toString()],\n vaultBAmount: vaultInfo[info.vaultB.toString()],\n configInfo: configInfo[info.configId.toString()],\n poolPrice: new Decimal(quoteReserve.toString())\n .div(new Decimal(10).pow(info.mintDecimalB))\n .div(new Decimal(baseReserve.toString()).div(new Decimal(10).pow(info.mintDecimalA))),\n };\n }\n\n return returnData;\n }\n\n public toComputePoolInfos({\n pools,\n mintInfos,\n }: {\n pools: Record<string, CpmmParsedRpcData>;\n mintInfos: ReturnTypeFetchMultipleMintInfos;\n }): Record<string, CpmmComputeData> {\n return Object.keys(pools).reduce((acc, cur) => {\n const pool = pools[cur];\n const [mintA, mintB] = [pool.mintA.toBase58(), pool.mintB.toBase58()];\n\n return {\n ...acc,\n [cur]: {\n ...pool,\n id: new PublicKey(cur),\n configInfo: pool.configInfo!,\n version: 7 as const,\n authority: getPdaPoolAuthority(pool.programId).publicKey,\n mintA: toApiV3Token({\n address: mintA,\n decimals: pool.mintDecimalA,\n programId: pool.mintProgramA.toBase58(),\n extensions: {\n feeConfig: mintInfos[mintA]?.feeConfig ? toFeeConfig(mintInfos[mintA]?.feeConfig) : undefined,\n },\n }),\n mintB: toApiV3Token({\n address: mintB,\n decimals: pool.mintDecimalB,\n programId: pool.mintProgramB.toBase58(),\n extensions: {\n feeConfig: mintInfos[mintB]?.feeConfig ? toFeeConfig(mintInfos[mintB]?.feeConfig) : undefined,\n },\n }),\n },\n };\n }, {} as Record<string, CpmmComputeData>);\n }\n\n public async getPoolInfoFromRpc(poolId: string): Promise<{\n poolInfo: ApiV3PoolInfoStandardItemCpmm;\n poolKeys: CpmmKeys;\n rpcData: CpmmParsedRpcData;\n computePoolInfo: CpmmComputeData;\n }> {\n const rpcData = await this.getRpcPoolInfo(poolId, true);\n const mintInfos = await fetchMultipleMintInfos({\n connection: this.scope.connection,\n mints: [rpcData.mintA, rpcData.mintB],\n });\n\n const mintA = toApiV3Token({\n address: rpcData.mintA.toBase58(),\n decimals: rpcData.mintDecimalA,\n programId: rpcData.mintProgramA.toBase58(),\n extensions: {\n feeConfig: mintInfos[rpcData.mintA.toBase58()].feeConfig\n ? toFeeConfig(mintInfos[rpcData.mintA.toBase58()].feeConfig)\n : undefined,\n },\n });\n const mintB = toApiV3Token({\n address: rpcData.mintB.toBase58(),\n decimals: rpcData.mintDecimalB,\n programId: rpcData.mintProgramB.toBase58(),\n extensions: {\n feeConfig: mintInfos[rpcData.mintB.toBase58()].feeConfig\n ? toFeeConfig(mintInfos[rpcData.mintB.toBase58()].feeConfig)\n : undefined,\n },\n });\n\n const lpMint = toApiV3Token({\n address: rpcData.mintLp.toBase58(),\n decimals: rpcData.lpDecimals,\n programId: TOKEN_PROGRAM_ID.toBase58(),\n });\n\n const configInfo = {\n id: rpcData.configId.toBase58(),\n index: rpcData.configInfo!.index,\n protocolFeeRate: rpcData.configInfo!.protocolFeeRate.toNumber(),\n tradeFeeRate: rpcData.configInfo!.tradeFeeRate.toNumber(),\n fundFeeRate: rpcData.configInfo!.fundFeeRate.toNumber(),\n createPoolFee: rpcData.configInfo!.createPoolFee.toString(),\n };\n\n const mockRewardData = {\n volume: 0,\n volumeQuote: 0,\n volumeFee: 0,\n apr: 0,\n feeApr: 0,\n priceMin: 0,\n priceMax: 0,\n rewardApr: [],\n };\n\n return {\n poolInfo: {\n programId: rpcData.programId.toBase58(),\n id: poolId,\n type: \"Standard\",\n lpMint,\n lpPrice: 0,\n lpAmount: rpcData.lpAmount.toNumber(),\n config: configInfo,\n mintA,\n mintB,\n rewardDefaultInfos: [],\n rewardDefaultPoolInfos: \"Ecosystem\",\n price: rpcData.poolPrice.toNumber(),\n mintAmountA: new Decimal(rpcData.vaultAAmount.toString()).div(10 ** mintA.decimals).toNumber(),\n mintAmountB: new Decimal(rpcData.vaultBAmount.toString()).div(10 ** mintB.decimals).toNumber(),\n feeRate: rpcData.configInfo!.tradeFeeRate.toNumber(),\n openTime: rpcData.openTime.toString(),\n tvl: 0,\n burnPercent: 0,\n\n day: mockRewardData,\n week: mockRewardData,\n month: mockRewardData,\n pooltype: [],\n\n farmUpcomingCount: 0,\n farmOngoingCount: 0,\n farmFinishedCount: 0,\n },\n poolKeys: {\n programId: rpcData.programId.toBase58(),\n id: poolId,\n mintA,\n mintB,\n openTime: rpcData.openTime.toString(),\n vault: { A: rpcData.vaultA.toBase58(), B: rpcData.vaultB.toBase58() },\n authority: getPdaPoolAuthority(rpcData.programId).publicKey.toBase58(),\n mintLp: lpMint,\n config: configInfo,\n observationId: getPdaObservationId(rpcData.programId, new PublicKey(poolId)).publicKey.toBase58(),\n },\n rpcData,\n computePoolInfo: {\n ...rpcData,\n id: new PublicKey(poolId),\n configInfo: rpcData.configInfo!,\n version: 7 as const,\n authority: getPdaPoolAuthority(rpcData.programId).publicKey,\n mintA,\n mintB,\n },\n };\n }\n\n public async createPool<T extends TxVersion>({\n poolId,\n programId,\n poolFeeAccount,\n startTime,\n ownerInfo,\n associatedOnly = false,\n checkCreateATAOwner = false,\n txVersion,\n feeConfig,\n computeBudgetConfig,\n txTipConfig,\n feePayer,\n ...params\n }: CreateCpmmPoolParam<T>): Promise<MakeTxData<T, { address: CreateCpmmPoolAddress }>> {\n const payer = ownerInfo.feePayer || this.scope.owner?.publicKey;\n const isFront = new BN(new PublicKey(params.mintA.address).toBuffer()).lte(\n new BN(new PublicKey(params.mintB.address).toBuffer()),\n );\n\n const [mintA, mintB] = isFront ? [params.mintA, params.mintB] : [params.mintB, params.mintA];\n const [mintAAmount, mintBAmount] = isFront\n ? [params.mintAAmount, params.mintBAmount]\n : [params.mintBAmount, params.mintAAmount];\n\n const mintAUseSOLBalance = ownerInfo.useSOLBalance && mintA.address === NATIVE_MINT.toBase58();\n const mintBUseSOLBalance = ownerInfo.useSOLBalance && mintB.address === NATIVE_MINT.toBase58();\n const [mintAPubkey, mintBPubkey] = [new PublicKey(mintA.address), new PublicKey(mintB.address)];\n const txBuilder = this.createTxBuilder(feePayer);\n\n const { account: userVaultA, instructionParams: userVaultAInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n mint: mintAPubkey,\n tokenProgram: mintA.programId,\n owner: this.scope.ownerPubKey,\n createInfo: mintAUseSOLBalance\n ? {\n payer: payer!,\n amount: mintAAmount,\n }\n : undefined,\n notUseTokenAccount: mintAUseSOLBalance,\n skipCloseAccount: !mintAUseSOLBalance,\n associatedOnly: mintAUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n txBuilder.addInstruction(userVaultAInstruction || {});\n const { account: userVaultB, instructionParams: userVaultBInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n mint: new PublicKey(mintB.address),\n tokenProgram: mintB.programId,\n owner: this.scope.ownerPubKey,\n createInfo: mintBUseSOLBalance\n ? {\n payer: payer!,\n amount: mintBAmount,\n }\n : undefined,\n\n notUseTokenAccount: mintBUseSOLBalance,\n skipCloseAccount: !mintBUseSOLBalance,\n associatedOnly: mintBUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n txBuilder.addInstruction(userVaultBInstruction || {});\n\n if (userVaultA === undefined || userVaultB === undefined) throw Error(\"you don't has some token account\");\n\n const poolKeys = getCreatePoolKeys({\n poolId,\n programId,\n configId: new PublicKey(feeConfig.id),\n mintA: mintAPubkey,\n mintB: mintBPubkey,\n });\n\n txBuilder.addInstruction({\n instructions: [\n makeCreateCpmmPoolInInstruction(\n programId,\n this.scope.ownerPubKey,\n new PublicKey(feeConfig.id),\n poolKeys.authority,\n poolKeys.poolId,\n mintAPubkey,\n mintBPubkey,\n poolKeys.lpMint,\n userVaultA,\n userVaultB,\n getATAAddress(this.scope.ownerPubKey, poolKeys.lpMint).publicKey,\n poolKeys.vaultA,\n poolKeys.vaultB,\n poolFeeAccount,\n new PublicKey(mintA.programId ?? TOKEN_PROGRAM_ID),\n new PublicKey(mintB.programId ?? TOKEN_PROGRAM_ID),\n poolKeys.observationId,\n mintAAmount,\n mintBAmount,\n startTime,\n ),\n ],\n instructionTypes: [InstructionType.CpmmCreatePool],\n });\n\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n txBuilder.addTipInstruction(txTipConfig);\n return txBuilder.versionBuild({\n txVersion,\n extInfo: {\n address: { ...poolKeys, mintA, mintB, programId, poolFeeAccount, feeConfig },\n },\n }) as Promise<MakeTxData<T, { address: CreateCpmmPoolAddress }>>;\n }\n\n public async addLiquidity<T extends TxVersion>(params: AddCpmmLiquidityParams<T>): Promise<MakeTxData<T>> {\n const {\n poolInfo,\n poolKeys: propPoolKeys,\n inputAmount,\n baseIn,\n slippage,\n computeResult,\n computeBudgetConfig,\n txTipConfig,\n config,\n txVersion,\n feePayer,\n } = params;\n\n if (this.scope.availability.addStandardPosition === false)\n this.logAndCreateError(\"add liquidity feature disabled in your region\");\n\n if (inputAmount.isZero())\n this.logAndCreateError(\"amounts must greater than zero\", \"amountInA\", {\n amountInA: inputAmount.toString(),\n });\n const { account } = this.scope;\n const { bypassAssociatedCheck, checkCreateATAOwner } = {\n // default\n ...{ bypassAssociatedCheck: false, checkCreateATAOwner: false },\n // custom\n ...config,\n };\n const rpcPoolData = computeResult ? undefined : await this.getRpcPoolInfo(poolInfo.id);\n\n const {\n liquidity,\n inputAmountFee,\n anotherAmount: _anotherAmount,\n } = computeResult ||\n this.computePairAmount({\n poolInfo: {\n ...poolInfo,\n lpAmount: new Decimal(rpcPoolData!.lpAmount.toString()).div(10 ** poolInfo.lpMint.decimals).toNumber(),\n },\n baseReserve: rpcPoolData!.baseReserve,\n quoteReserve: rpcPoolData!.quoteReserve,\n slippage: new Percent(0),\n baseIn,\n epochInfo: await this.scope.fetchEpochInfo(),\n amount: new Decimal(inputAmount.toString()).div(\n 10 ** (baseIn ? poolInfo.mintA.decimals : poolInfo.mintB.decimals),\n ),\n });\n\n const anotherAmount = _anotherAmount.amount;\n const mintAUseSOLBalance = poolInfo.mintA.address === NATIVE_MINT.toString();\n const mintBUseSOLBalance = poolInfo.mintB.address === NATIVE_MINT.toString();\n\n const txBuilder = this.createTxBuilder(feePayer);\n const [mintA, mintB] = [new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address)];\n\n const { account: tokenAccountA, instructionParams: _tokenAccountAInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintA.programId,\n mint: new PublicKey(poolInfo.mintA.address),\n owner: this.scope.ownerPubKey,\n\n createInfo:\n mintAUseSOLBalance || (baseIn ? inputAmount : anotherAmount).isZero()\n ? {\n payer: this.scope.ownerPubKey,\n amount: baseIn ? inputAmount : anotherAmount,\n }\n : undefined,\n skipCloseAccount: !mintAUseSOLBalance,\n notUseTokenAccount: mintAUseSOLBalance,\n associatedOnly: false,\n checkCreateATAOwner,\n });\n\n txBuilder.addInstruction(_tokenAccountAInstruction || {});\n\n const { account: tokenAccountB, instructionParams: _tokenAccountBInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintB.programId,\n mint: new PublicKey(poolInfo.mintB.address),\n owner: this.scope.ownerPubKey,\n\n createInfo:\n mintBUseSOLBalance || (baseIn ? anotherAmount : inputAmount).isZero()\n ? {\n payer: this.scope.ownerPubKey,\n amount: baseIn ? anotherAmount : inputAmount,\n }\n : undefined,\n skipCloseAccount: !mintBUseSOLBalance,\n notUseTokenAccount: mintBUseSOLBalance,\n associatedOnly: false,\n checkCreateATAOwner,\n });\n\n txBuilder.addInstruction(_tokenAccountBInstruction || {});\n\n if (!tokenAccountA && !tokenAccountB)\n this.logAndCreateError(\"cannot found target token accounts\", \"tokenAccounts\", account.tokenAccounts);\n const lpTokenAccount = await account.getCreatedTokenAccount({\n mint: new PublicKey(poolInfo.lpMint.address),\n });\n const { tokenAccount: _lpTokenAccount, ...lpInstruction } = await account.handleTokenAccount({\n side: \"out\",\n amount: 0,\n mint: new PublicKey(poolInfo.lpMint.address),\n tokenAccount: lpTokenAccount,\n bypassAssociatedCheck,\n checkCreateATAOwner,\n });\n txBuilder.addInstruction(lpInstruction);\n const poolKeys = propPoolKeys ?? (await this.getCpmmPoolKeys(poolInfo.id));\n const _slippage = new Percent(new BN(1)).sub(slippage);\n\n txBuilder.addInstruction({\n instructions: [\n makeDepositCpmmInInstruction(\n new PublicKey(poolInfo.programId),\n this.scope.ownerPubKey,\n new PublicKey(poolKeys.authority),\n new PublicKey(poolInfo.id),\n _lpTokenAccount!,\n tokenAccountA!,\n tokenAccountB!,\n new PublicKey(poolKeys.vault.A),\n new PublicKey(poolKeys.vault.B),\n mintA,\n mintB,\n new PublicKey(poolInfo.lpMint.address),\n\n computeResult ? computeResult?.liquidity : _slippage.mul(liquidity).quotient,\n baseIn ? inputAmountFee.amount : anotherAmount,\n baseIn ? anotherAmount : inputAmountFee.amount,\n ),\n ],\n instructionTypes: [InstructionType.CpmmAddLiquidity],\n lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [],\n });\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n txBuilder.addTipInstruction(txTipConfig);\n return txBuilder.versionBuild({\n txVersion,\n lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : undefined,\n }) as Promise<MakeTxData<T>>;\n }\n\n public async withdrawLiquidity<T extends TxVersion>(params: WithdrawCpmmLiquidityParams<T>): Promise<MakeTxData<T>> {\n const {\n poolInfo,\n poolKeys: propPoolKeys,\n lpAmount,\n slippage,\n computeBudgetConfig,\n txTipConfig,\n txVersion,\n feePayer,\n closeWsol = true,\n } = params;\n\n if (this.scope.availability.addStandardPosition === false)\n this.logAndCreateError(\"add liquidity feature disabled in your region\");\n\n const _slippage = new Percent(new BN(1)).sub(slippage);\n\n const rpcPoolData = await this.getRpcPoolInfo(poolInfo.id);\n const [amountMintA, amountMintB] = [\n _slippage.mul(lpAmount.mul(rpcPoolData.baseReserve).div(rpcPoolData.lpAmount)).quotient,\n _slippage.mul(lpAmount.mul(rpcPoolData.quoteReserve).div(rpcPoolData.lpAmount)).quotient,\n ];\n\n const epochInfo = await this.scope.fetchEpochInfo();\n const [mintAAmountFee, mintBAmountFee] = [\n getTransferAmountFeeV2(amountMintA, poolInfo.mintA.extensions.feeConfig, epochInfo, false),\n getTransferAmountFeeV2(amountMintB, poolInfo.mintB.extensions.feeConfig, epochInfo, false),\n ];\n\n const { account } = this.scope;\n const txBuilder = this.createTxBuilder(feePayer);\n const [mintA, mintB] = [new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address)];\n\n const mintAUseSOLBalance = mintA.equals(WSOLMint);\n const mintBUseSOLBalance = mintB.equals(WSOLMint);\n\n let tokenAccountA: PublicKey | undefined = undefined;\n let tokenAccountB: PublicKey | undefined = undefined;\n const { account: _ownerTokenAccountA, instructionParams: accountAInstructions } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintA.programId,\n mint: new PublicKey(poolInfo.mintA.address),\n notUseTokenAccount: mintAUseSOLBalance,\n owner: this.scope.ownerPubKey,\n createInfo: {\n payer: this.scope.ownerPubKey,\n amount: 0,\n },\n skipCloseAccount: !(mintAUseSOLBalance && closeWsol),\n associatedOnly: mintAUseSOLBalance ? false : true,\n checkCreateATAOwner: false,\n });\n tokenAccountA = _ownerTokenAccountA;\n accountAInstructions && txBuilder.addInstruction(accountAInstructions);\n\n const { account: _ownerTokenAccountB, instructionParams: accountBInstructions } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintB.programId,\n mint: new PublicKey(poolInfo.mintB.address),\n notUseTokenAccount: mintBUseSOLBalance,\n owner: this.scope.ownerPubKey,\n createInfo: {\n payer: this.scope.ownerPubKey,\n amount: 0,\n },\n skipCloseAccount: !(mintBUseSOLBalance && closeWsol),\n associatedOnly: mintBUseSOLBalance ? false : true,\n checkCreateATAOwner: false,\n });\n tokenAccountB = _ownerTokenAccountB;\n accountBInstructions && txBuilder.addInstruction(accountBInstructions);\n\n if (!tokenAccountA || !tokenAccountB)\n this.logAndCreateError(\"cannot found target token accounts\", \"tokenAccounts\", account.tokenAccounts);\n\n const lpTokenAccount = await account.getCreatedTokenAccount({\n mint: new PublicKey(poolInfo.lpMint.address),\n });\n\n if (!lpTokenAccount)\n this.logAndCreateError(\"cannot found lp token account\", \"tokenAccounts\", account.tokenAccounts);\n const poolKeys = propPoolKeys ?? (await this.getCpmmPoolKeys(poolInfo.id));\n txBuilder.addInstruction({\n instructions: [\n makeWithdrawCpmmInInstruction(\n new PublicKey(poolInfo.programId),\n this.scope.ownerPubKey,\n new PublicKey(poolKeys.authority),\n new PublicKey(poolInfo.id),\n lpTokenAccount!,\n tokenAccountA!,\n tokenAccountB!,\n new PublicKey(poolKeys.vault.A),\n new PublicKey(poolKeys.vault.B),\n mintA,\n mintB,\n new PublicKey(poolInfo.lpMint.address),\n\n lpAmount,\n amountMintA.sub(mintAAmountFee.fee ?? new BN(0)),\n amountMintB.sub(mintBAmountFee.fee ?? new BN(0)),\n ),\n ],\n instructionTypes: [InstructionType.CpmmWithdrawLiquidity],\n lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : [],\n });\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n txBuilder.addTipInstruction(txTipConfig);\n return txBuilder.versionBuild({\n txVersion,\n lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : undefined,\n }) as Promise<MakeTxData<T>>;\n }\n\n public async swap<T extends TxVersion>(params: CpmmSwapParams<T>): Promise<MakeTxData<T>> {\n const {\n poolInfo,\n poolKeys: propPoolKeys,\n baseIn,\n fixedOut,\n inputAmount,\n swapResult,\n slippage = 0,\n config,\n computeBudgetConfig,\n txTipConfig,\n txVersion,\n feePayer,\n } = params;\n\n const { bypassAssociatedCheck, checkCreateATAOwner, associatedOnly } = {\n // default\n ...{ bypassAssociatedCheck: false, checkCreateATAOwner: false, associatedOnly: true },\n // custom\n ...config,\n };\n\n const txBuilder = this.createTxBuilder(feePayer);\n\n const [mintA, mintB] = [new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address)];\n\n if (!fixedOut) {\n swapResult.outputAmount = swapResult.outputAmount.mul(new BN((1 - slippage) * 10000)).div(new BN(10000));\n } else {\n swapResult.inputAmount = swapResult.inputAmount.mul(new BN((1 + slippage) * 10000)).div(new BN(10000));\n }\n\n const mintAUseSOLBalance = poolInfo.mintA.address === WSOLMint.toBase58();\n const mintBUseSOLBalance = poolInfo.mintB.address === WSOLMint.toBase58();\n const { account: mintATokenAcc, instructionParams: mintATokenAccInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n mint: mintA,\n tokenProgram: new PublicKey(poolInfo.mintA.programId ?? TOKEN_PROGRAM_ID),\n owner: this.scope.ownerPubKey,\n createInfo:\n mintAUseSOLBalance || !baseIn\n ? {\n payer: feePayer || this.scope.ownerPubKey,\n amount: baseIn ? swapResult.inputAmount : 0,\n }\n : undefined,\n notUseTokenAccount: mintAUseSOLBalance,\n skipCloseAccount: !mintAUseSOLBalance,\n associatedOnly: mintAUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n mintATokenAccInstruction && txBuilder.addInstruction(mintATokenAccInstruction);\n\n const { account: mintBTokenAcc, instructionParams: mintBTokenAccInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n mint: mintB,\n tokenProgram: new PublicKey(poolInfo.mintB.programId ?? TOKEN_PROGRAM_ID),\n owner: this.scope.ownerPubKey,\n createInfo:\n mintBUseSOLBalance || baseIn\n ? {\n payer: feePayer || this.scope.ownerPubKey,\n amount: baseIn ? 0 : swapResult.inputAmount,\n }\n : undefined,\n notUseTokenAccount: mintBUseSOLBalance,\n skipCloseAccount: !mintBUseSOLBalance,\n associatedOnly: mintBUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n mintBTokenAccInstruction && txBuilder.addInstruction(mintBTokenAccInstruction);\n\n if (!mintATokenAcc || !mintBTokenAcc)\n this.logAndCreateError(\"user do not have token account\", {\n mintA: poolInfo.mintA.symbol || poolInfo.mintA.address,\n mintB: poolInfo.mintB.symbol || poolInfo.mintB.address,\n mintATokenAcc,\n mintBTokenAcc,\n mintAUseSOLBalance,\n mintBUseSOLBalance,\n associatedOnly,\n });\n\n const poolKeys = propPoolKeys ?? (await this.getCpmmPoolKeys(poolInfo.id));\n\n txBuilder.addInstruction({\n instructions: [\n !fixedOut\n ? makeSwapCpmmBaseInInstruction(\n new PublicKey(poolInfo.programId),\n this.scope.ownerPubKey,\n new PublicKey(poolKeys.authority),\n new PublicKey(poolKeys.config.id),\n new PublicKey(poolInfo.id),\n baseIn ? mintATokenAcc! : mintBTokenAcc!,\n baseIn ? mintBTokenAcc! : mintATokenAcc!,\n new PublicKey(poolKeys.vault[baseIn ? \"A\" : \"B\"]),\n new PublicKey(poolKeys.vault[baseIn ? \"B\" : \"A\"]),\n new PublicKey(poolInfo[baseIn ? \"mintA\" : \"mintB\"].programId ?? TOKEN_PROGRAM_ID),\n new PublicKey(poolInfo[baseIn ? \"mintB\" : \"mintA\"].programId ?? TOKEN_PROGRAM_ID),\n baseIn ? mintA : mintB,\n baseIn ? mintB : mintA,\n getPdaObservationId(new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)).publicKey,\n\n inputAmount,\n swapResult.outputAmount,\n )\n : makeSwapCpmmBaseOutInstruction(\n new PublicKey(poolInfo.programId),\n this.scope.ownerPubKey,\n new PublicKey(poolKeys.authority),\n new PublicKey(poolKeys.config.id),\n new PublicKey(poolInfo.id),\n\n baseIn ? mintATokenAcc! : mintBTokenAcc!,\n baseIn ? mintBTokenAcc! : mintATokenAcc!,\n\n new PublicKey(poolKeys.vault[baseIn ? \"A\" : \"B\"]),\n new PublicKey(poolKeys.vault[baseIn ? \"B\" : \"A\"]),\n new PublicKey(poolInfo[baseIn ? \"mintA\" : \"mintB\"].programId ?? TOKEN_PROGRAM_ID),\n new PublicKey(poolInfo[baseIn ? \"mintB\" : \"mintA\"].programId ?? TOKEN_PROGRAM_ID),\n baseIn ? mintA : mintB,\n baseIn ? mintB : mintA,\n\n getPdaObservationId(new PublicKey(poolInfo.programId), new PublicKey(poolInfo.id)).publicKey,\n\n swapResult.inputAmount,\n swapResult.outputAmount,\n ),\n ],\n instructionTypes: [fixedOut ? InstructionType.CpmmSwapBaseOut : InstructionType.ClmmSwapBaseIn],\n });\n\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n txBuilder.addTipInstruction(txTipConfig);\n return txBuilder.versionBuild({\n txVersion,\n lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : undefined,\n }) as Promise<MakeTxData<T>>;\n }\n\n public async lockLp<T extends TxVersion>(params: LockCpmmLpParams<T>): Promise<MakeTxData<CpmmLockExtInfo>> {\n const { poolInfo, lpAmount, computeBudgetConfig, txTipConfig, txVersion, feePayer, feeNftOwner } = params;\n\n if (lpAmount.isZero())\n this.logAndCreateError(\"lpAmount must greater than zero\", {\n lpAmount: lpAmount.toString(),\n });\n\n const txBuilder = this.createTxBuilder(feePayer);\n\n const poolKeys = params.poolKeys ?? (await this.getCpmmPoolKeys(poolInfo.id));\n\n const insData = await makeCpmmLockInstruction({\n poolInfo,\n poolKeys,\n ownerInfo: {\n wallet: this.scope.ownerPubKey,\n feePayer: params.feePayer ?? this.scope.ownerPubKey,\n },\n feeNftOwner: feeNftOwner ?? this.scope.ownerPubKey,\n lockProgram: params.programId ?? LOCK_CPMM_PROGRAM,\n lockAuthProgram: params.authProgram ?? LOCK_CPMM_AUTH,\n lpAmount,\n withMetadata: params.withMetadata ?? true,\n getEphemeralSigners: params.getEphemeralSigners,\n });\n\n txBuilder.addInstruction(insData);\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n txBuilder.addTipInstruction(txTipConfig);\n return txBuilder.versionBuild({\n txVersion,\n extInfo: insData.address,\n lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : undefined,\n }) as Promise<MakeTxData<CpmmLockExtInfo>>;\n }\n\n public async harvestLockLp<T extends TxVersion>(params: HarvestLockCpmmLpParams<T>): Promise<MakeTxData> {\n const {\n poolInfo,\n lpFeeAmount,\n nftMint,\n programId = LOCK_CPMM_PROGRAM,\n authProgram = LOCK_CPMM_AUTH,\n cpmmProgram,\n computeBudgetConfig,\n txTipConfig,\n txVersion,\n closeWsol = true,\n } = params;\n\n if (lpFeeAmount.isZero())\n this.logAndCreateError(\"lpFeeAmount must greater than zero\", {\n lpAmount: lpFeeAmount.toString(),\n });\n\n const feePayer = params.feePayer || this.scope.ownerPubKey;\n\n const txBuilder = this.createTxBuilder(feePayer);\n\n const [mintA, mintB] = [new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address)];\n\n const mintAUseSOLBalance = mintA.equals(WSOLMint);\n const mintBUseSOLBalance = mintB.equals(WSOLMint);\n\n let tokenAccountA: PublicKey | undefined = undefined;\n let tokenAccountB: PublicKey | undefined = undefined;\n const { account: _ownerTokenAccountA, instructionParams: accountAInstructions } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintA.programId,\n mint: new PublicKey(poolInfo.mintA.address),\n notUseTokenAccount: mintAUseSOLBalance,\n owner: this.scope.ownerPubKey,\n createInfo: {\n payer: this.scope.ownerPubKey,\n amount: 0,\n },\n skipCloseAccount: !(mintAUseSOLBalance && closeWsol),\n associatedOnly: mintAUseSOLBalance ? false : true,\n checkCreateATAOwner: false,\n });\n tokenAccountA = _ownerTokenAccountA;\n accountAInstructions && txBuilder.addInstruction(accountAInstructions);\n\n const { account: _ownerTokenAccountB, instructionParams: accountBInstructions } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintB.programId,\n mint: new PublicKey(poolInfo.mintB.address),\n notUseTokenAccount: mintBUseSOLBalance,\n owner: this.scope.ownerPubKey,\n createInfo: {\n payer: this.scope.ownerPubKey,\n amount: 0,\n },\n skipCloseAccount: !(mintBUseSOLBalance && closeWsol),\n associatedOnly: mintBUseSOLBalance ? false : true,\n checkCreateATAOwner: false,\n });\n tokenAccountB = _ownerTokenAccountB;\n accountBInstructions && txBuilder.addInstruction(accountBInstructions);\n\n if (!tokenAccountA || !tokenAccountB)\n this.logAndCreateError(\"cannot found target token accounts\", { tokenAccountA, tokenAccountB });\n\n const poolKeys = params.poolKeys ?? (await this.getCpmmPoolKeys(poolInfo.id));\n\n const { publicKey: nftAccount } = getATAAddress(feePayer, nftMint, TOKEN_PROGRAM_ID);\n const { publicKey: lockPda } = getCpLockPda(programId, nftMint);\n const { publicKey: lockLpVault } = getATAAddress(\n authProgram,\n new PublicKey(poolInfo.lpMint.address),\n TOKEN_PROGRAM_ID,\n );\n\n txBuilder.addInstruction({\n instructions: [\n collectCpFeeInstruction({\n programId,\n nftOwner: this.scope.ownerPubKey,\n auth: authProgram,\n\n nftMint,\n nftAccount,\n\n lockPda,\n poolId: new PublicKey(poolInfo.id),\n mintLp: new PublicKey(poolKeys.mintLp.address),\n\n userVaultA: tokenAccountA!,\n userVaultB: tokenAccountB!,\n poolVaultA: new PublicKey(poolKeys.vault.A),\n poolVaultB: new PublicKey(poolKeys.vault.B),\n\n mintA,\n mintB,\n lockLpVault,\n lpFeeAmount,\n\n cpmmProgram: cpmmProgram?.programId,\n cpmmAuthProgram: cpmmProgram?.authProgram,\n }),\n ],\n instructionTypes: [InstructionType.CpmmCollectLockFee],\n });\n\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n txBuilder.addTipInstruction(txTipConfig);\n return txBuilder.versionBuild({\n txVersion,\n lookupTableAddress: poolKeys.lookupTableAccount ? [poolKeys.lookupTableAccount] : undefined,\n }) as Promise<MakeTxData>;\n }\n\n public async harvestMultiLockLp<T extends TxVersion>(\n params: HarvestMultiLockCpmmLpParams<T>,\n ): Promise<MakeMultiTxData<T>> {\n const {\n lockInfo,\n programId = LOCK_CPMM_PROGRAM,\n authProgram = LOCK_CPMM_AUTH,\n cpmmProgram,\n computeBudgetConfig,\n txVersion,\n closeWsol = true,\n } = params;\n\n const feePayer = params.feePayer || this.scope.ownerPubKey;\n const txBuilder = this.createTxBuilder(feePayer);\n const tokenAccRecord: Record<string, PublicKey | undefined> = {};\n const lookupTableAccounts: string[] = [];\n\n for (const lockData of lockInfo) {\n const { poolInfo, lpFeeAmount, nftMint } = lockData;\n if (lpFeeAmount.isZero()) continue;\n\n const [mintA, mintB] = [new PublicKey(poolInfo.mintA.address), new PublicKey(poolInfo.mintB.address)];\n\n const mintAUseSOLBalance = mintA.equals(WSOLMint);\n const mintBUseSOLBalance = mintB.equals(WSOLMint);\n\n let tokenAccountA: PublicKey | undefined = tokenAccRecord[poolInfo.mintA.address];\n let tokenAccountB: PublicKey | undefined = tokenAccRecord[poolInfo.mintB.address];\n\n if (!tokenAccountA) {\n if (mintAUseSOLBalance) {\n const { account: _ownerTokenAccountA, instructionParams: accountAInstructions } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintA.programId,\n mint: new PublicKey(poolInfo.mintA.address),\n notUseTokenAccount: true,\n owner: this.scope.ownerPubKey,\n createInfo: {\n payer: this.scope.ownerPubKey,\n amount: 0,\n },\n skipCloseAccount: !closeWsol,\n associatedOnly: false,\n checkCreateATAOwner: false,\n });\n tokenAccountA = _ownerTokenAccountA;\n accountAInstructions && txBuilder.addInstruction(accountAInstructions);\n tokenAccRecord[poolInfo.mintA.address] = _ownerTokenAccountA;\n } else {\n const mint = new PublicKey(poolInfo.mintA.address);\n tokenAccountA = this.scope.account.getAssociatedTokenAccount(mint, new PublicKey(poolInfo.mintA.programId));\n txBuilder.addInstruction({\n instructions: [\n createAssociatedTokenAccountIdempotentInstruction(\n this.scope.ownerPubKey,\n tokenAccountA,\n this.scope.ownerPubKey,\n mint,\n new PublicKey(poolInfo.mintA.programId),\n ),\n ],\n });\n tokenAccRecord[poolInfo.mintA.address] = tokenAccountA;\n }\n }\n\n if (!tokenAccountB) {\n if (mintBUseSOLBalance) {\n const { account: _ownerTokenAccountB, instructionParams: accountBInstructions } =\n await this.scope.account.getOrCreateTokenAccount({\n tokenProgram: poolInfo.mintB.programId,\n mint: new PublicKey(poolInfo.mintB.address),\n notUseTokenAccount: true,\n owner: this.scope.ownerPubKey,\n createInfo: {\n payer: this.scope.ownerPubKey,\n amount: 0,\n },\n skipCloseAccount: !closeWsol,\n associatedOnly: false,\n checkCreateATAOwner: false,\n });\n tokenAccountB = _ownerTokenAccountB;\n accountBInstructions && txBuilder.addInstruction(accountBInstructions);\n tokenAccRecord[poolInfo.mintB.address] = _ownerTokenAccountB;\n } else {\n const mint = new PublicKey(poolInfo.mintB.address);\n tokenAccountB = this.scope.account.getAssociatedTokenAccount(mint, new PublicKey(poolInfo.mintB.programId));\n txBuilder.addInstruction({\n instructions: [\n createAssociatedTokenAccountIdempotentInstruction(\n this.scope.ownerPubKey,\n tokenAccountB,\n this.scope.ownerPubKey,\n mint,\n new PublicKey(poolInfo.mintB.programId),\n ),\n ],\n });\n tokenAccRecord[poolInfo.mintB.address] = tokenAccountB;\n }\n }\n\n if (!tokenAccountA || !tokenAccountB)\n this.logAndCreateError(\"cannot found target token accounts\", { tokenAccountA, tokenAccountB });\n\n const poolKeys = lockData.poolKeys ?? (await this.getCpmmPoolKeys(poolInfo.id));\n if (poolKeys.lookupTableAccount) lookupTableAccounts.push(poolKeys.lookupTableAccount);\n\n const { publicKey: nftAccount } = getATAAddress(feePayer, nftMint, TOKEN_PROGRAM_ID);\n const { publicKey: lockPda } = getCpLockPda(programId, nftMint);\n const { publicKey: lockLpVault } = getATAAddress(\n authProgram,\n new PublicKey(poolInfo.lpMint.address),\n TOKEN_PROGRAM_ID,\n );\n\n txBuilder.addInstruction({\n instructions: [\n collectCpFeeInstruction({\n programId,\n nftOwner: this.scope.ownerPubKey,\n auth: authProgram,\n\n nftMint,\n nftAccount,\n\n lockPda,\n poolId: new PublicKey(poolInfo.id),\n mintLp: new PublicKey(poolKeys.mintLp.address),\n\n userVaultA: tokenAccountA!,\n userVaultB: tokenAccountB!,\n poolVaultA: new PublicKey(poolKeys.vault.A),\n poolVaultB: new PublicKey(poolKeys.vault.B),\n\n mintA,\n mintB,\n lockLpVault,\n lpFeeAmount,\n\n cpmmProgram: cpmmProgram?.programId,\n cpmmAuthProgram: cpmmProgram?.authProgram,\n }),\n ],\n instructionTypes: [InstructionType.CpmmCollectLockFee],\n });\n }\n\n if (txVersion === TxVersion.V0)\n return txBuilder.sizeCheckBuildV0({ computeBudgetConfig, lookupTableAddress: lookupTableAccounts }) as Promise<\n MakeMultiTxData<T>\n >;\n return txBuilder.sizeCheckBuild({ computeBudgetConfig }) as Promise<MakeMultiTxData<T>>;\n }\n\n public async createPoolWithPermission<T extends TxVersion>({\n poolId,\n programId,\n poolFeeAccount,\n startTime,\n ownerInfo,\n associatedOnly = false,\n checkCreateATAOwner = false,\n txVersion,\n feeConfig,\n computeBudgetConfig,\n txTipConfig,\n feePayer,\n feeOn,\n ...params\n }: CreateCpmmPoolPermissionParam<T>): Promise<MakeTxData<T, { address: CreateCpmmPoolAddress }>> {\n console.log(\"***this method only available for wallet with permissions***\");\n const payer = ownerInfo.feePayer || this.scope.owner?.publicKey;\n const isFront = new BN(new PublicKey(params.mintA.address).toBuffer()).lte(\n new BN(new PublicKey(params.mintB.address).toBuffer()),\n );\n\n const [mintA, mintB] = isFront ? [params.mintA, params.mintB] : [params.mintB, params.mintA];\n const [mintAAmount, mintBAmount] = isFront\n ? [params.mintAAmount, params.mintBAmount]\n : [params.mintBAmount, params.mintAAmount];\n\n const mintAUseSOLBalance = ownerInfo.useSOLBalance && mintA.address === NATIVE_MINT.toBase58();\n const mintBUseSOLBalance = ownerInfo.useSOLBalance && mintB.address === NATIVE_MINT.toBase58();\n const [mintAPubkey, mintBPubkey] = [new PublicKey(mintA.address), new PublicKey(mintB.address)];\n const txBuilder = this.createTxBuilder(feePayer);\n\n const { account: userVaultA, instructionParams: userVaultAInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n mint: mintAPubkey,\n tokenProgram: mintA.programId,\n owner: this.scope.ownerPubKey,\n createInfo: mintAUseSOLBalance\n ? {\n payer: payer!,\n amount: mintAAmount,\n }\n : undefined,\n notUseTokenAccount: mintAUseSOLBalance,\n skipCloseAccount: !mintAUseSOLBalance,\n associatedOnly: mintAUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n txBuilder.addInstruction(userVaultAInstruction || {});\n const { account: userVaultB, instructionParams: userVaultBInstruction } =\n await this.scope.account.getOrCreateTokenAccount({\n mint: new PublicKey(mintB.address),\n tokenProgram: mintB.programId,\n owner: this.scope.ownerPubKey,\n createInfo: mintBUseSOLBalance\n ? {\n payer: payer!,\n amount: mintBAmount,\n }\n : undefined,\n\n notUseTokenAccount: mintBUseSOLBalance,\n skipCloseAccount: !mintBUseSOLBalance,\n associatedOnly: mintBUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n txBuilder.addInstruction(userVaultBInstruction || {});\n\n if (userVaultA === undefined || userVaultB === undefined) throw Error(\"you don't has some token account\");\n\n const poolKeys = getCreatePoolKeys({\n poolId,\n programId,\n configId: new PublicKey(feeConfig.id),\n mintA: mintAPubkey,\n mintB: mintBPubkey,\n });\n\n txBuilder.addInstruction({\n instructions: [\n initializeWithPermission(\n programId,\n this.scope.ownerPubKey,\n this.scope.ownerPubKey,\n new PublicKey(feeConfig.id),\n poolKeys.authority,\n poolKeys.poolId,\n mintAPubkey,\n mintBPubkey,\n poolKeys.lpMint,\n userVaultA,\n userVaultB,\n getATAAddress(this.scope.ownerPubKey, poolKeys.lpMint).publicKey,\n poolKeys.vaultA,\n poolKeys.vaultB,\n poolFeeAccount,\n new PublicKey(mintA.programId ?? TOKEN_PROGRAM_ID),\n new PublicKey(mintB.programId ?? TOKEN_PROGRAM_ID),\n poolKeys.observationId,\n getPdaPermissionId(programId, this.scope.ownerPubKey).publicKey,\n\n mintAAmount,\n mintBAmount,\n startTime,\n\n feeOn,\n ),\n ],\n instructionTypes: [InstructionType.CpmmCreatePool],\n });\n\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n txBuilder.addTipInstruction(txTipConfig);\n return txBuilder.versionBuild({\n txVersion,\n extInfo: {\n address: { ...poolKeys, mintA, mintB, programId, poolFeeAccount, feeConfig },\n },\n }) as Promise<MakeTxData<T, { address: CreateCpmmPoolAddress }>>;\n }\n\n public async collectCreatorFees<T extends TxVersion>({\n poolInfo,\n poolKeys: propPoolKeys,\n programId = CREATE_CPMM_POOL_PROGRAM,\n txVersion,\n computeBudgetConfig,\n txTipConfig,\n feePayer,\n }: CollectCreatorFees<T>): Promise<MakeTxData<T>> {\n const payer = feePayer || this.scope.ownerPubKey;\n const txBuilder = this.createTxBuilder(payer);\n\n const poolKeys = propPoolKeys ?? (await this.getCpmmPoolKeys(poolInfo.id));\n\n const [mintA, mintB, mintAProgram, mintBProgram] = [\n new PublicKey(poolInfo.mintA.address),\n new PublicKey(poolInfo.mintB.address),\n new PublicKey(poolInfo.mintA.programId),\n new PublicKey(poolInfo.mintB.programId),\n ];\n\n const tokenAccount