test-raydium-sdk-v2
Version:
An SDK for building applications on top of Raydium.
1 lines • 474 kB
Source Map (JSON)
{"version":3,"sources":["../../../src/raydium/farm/farm.ts","../../../src/common/logger.ts","../../../src/common/utility.ts","../../../src/module/amount.ts","../../../src/common/bignumber.ts","../../../node_modules/decimal.js/decimal.mjs","../../../src/module/token.ts","../../../src/common/pubKey.ts","../../../src/raydium/token/constant.ts","../../../src/module/fraction.ts","../../../src/module/formatter.ts","../../../src/module/price.ts","../../../src/module/currency.ts","../../../src/module/percent.ts","../../../src/common/txTool/txTool.ts","../../../src/common/txTool/txType.ts","../../../src/common/txTool/txUtils.ts","../../../src/common/txTool/lookupTable.ts","../../../src/common/accountInfo.ts","../../../src/common/lodash.ts","../../../src/common/programId.ts","../../../src/common/pda.ts","../../../src/common/transfer.ts","../../../src/raydium/account/util.ts","../../../src/marshmallow/index.ts","../../../src/marshmallow/buffer-layout.ts","../../../src/raydium/account/layout.ts","../../../node_modules/@noble/hashes/src/_assert.ts","../../../node_modules/@noble/hashes/src/utils.ts","../../../node_modules/@noble/hashes/src/_md.ts","../../../node_modules/@noble/hashes/src/sha256.ts","../../../src/raydium/account/instruction.ts","../../../src/raydium/moduleBase.ts","../../../src/raydium/farm/config.ts","../../../src/raydium/farm/layout.ts","../../../src/raydium/farm/instruction.ts","../../../src/raydium/farm/util.ts"],"sourcesContent":["import { createAssociatedTokenAccountInstruction } from \"@solana/spl-token\";\nimport { PublicKey, SystemProgram } from \"@solana/web3.js\";\n\nimport { FormatFarmKeyOut } from \"@/api/type\";\nimport { AddInstructionParam, jsonInfo2PoolKeys } from \"@/common\";\nimport { parseBigNumberish, BN_ZERO } from \"@/common/bignumber\";\nimport { SOLMint, WSOLMint } from \"@/common/pubKey\";\nimport { MakeTxData, MakeMultiTxData } from \"@/common/txTool/txTool\";\nimport { InstructionType, TxVersion } from \"@/common/txTool/txType\";\nimport { getATAAddress } from \"@/common/pda\";\nimport { FARM_PROGRAM_ID_V6 } from \"@/common/programId\";\nimport { generatePubKey } from \"../account/util\";\n\nimport { createWSolAccountInstructions } from \"../account/instruction\";\nimport ModuleBase from \"../moduleBase\";\nimport { TOKEN_WSOL } from \"../token/constant\";\nimport { ComputeBudgetConfig } from \"@/raydium/type\";\nimport {\n FARM_LOCK_MINT,\n FARM_LOCK_VAULT,\n isValidFarmVersion,\n poolTypeV6,\n validateFarmRewards,\n FARM_PROGRAM_TO_VERSION,\n} from \"./config\";\nimport {\n createAssociatedLedgerAccountInstruction,\n makeCreateFarmInstruction,\n makeCreatorWithdrawFarmRewardInstruction,\n makeRestartRewardInstruction,\n makeAddNewRewardInstruction,\n makeWithdrawInstructionV3,\n makeWithdrawInstructionV5,\n makeWithdrawInstructionV6,\n makeDepositInstructionV3,\n makeDepositInstructionV5,\n makeDepositInstructionV6,\n} from \"./instruction\";\nimport { farmStateV6Layout, FarmLedger } from \"./layout\";\nimport {\n CreateFarm,\n FarmDWParam,\n FarmRewardInfo,\n FarmRewardInfoConfig,\n RewardInfoKey,\n UpdateFarmReward,\n UpdateFarmRewards,\n CreateFarmExtInfo,\n} from \"./type\";\nimport {\n calFarmRewardAmount,\n farmRewardInfoToConfig,\n getAssociatedAuthority,\n getAssociatedLedgerAccount,\n getAssociatedLedgerPoolAccount,\n getFarmLedgerLayout,\n} from \"./util\";\nimport { FormatFarmInfoOut, FormatFarmKeyOutV6 } from \"@/api/type\";\nimport Decimal from \"decimal.js\";\n\nexport default class Farm extends ModuleBase {\n // token account needed\n private async _getUserRewardInfo({ payer, rewardInfo }: { payer: PublicKey; rewardInfo: FarmRewardInfo }): Promise<{\n rewardPubKey?: PublicKey;\n newInstruction?: AddInstructionParam;\n }> {\n if (rewardInfo.mint.equals(SOLMint)) {\n const txInstructions = await createWSolAccountInstructions({\n connection: this.scope.connection,\n owner: this.scope.ownerPubKey,\n payer,\n amount: calFarmRewardAmount(rewardInfo),\n });\n return {\n rewardPubKey: txInstructions.addresses.newAccount,\n newInstruction: txInstructions,\n };\n }\n\n return {\n rewardPubKey: await this.scope.account.getCreatedTokenAccount({\n mint: rewardInfo.mint,\n associatedOnly: false,\n })!,\n };\n }\n\n // token account needed\n public async create<T extends TxVersion>({\n poolInfo: propPoolInfo,\n rewardInfos,\n payer,\n programId = FARM_PROGRAM_ID_V6,\n txVersion,\n }: CreateFarm<T>): Promise<MakeTxData<T, CreateFarmExtInfo>> {\n this.checkDisabled();\n this.scope.checkOwner();\n\n const lpMint = new PublicKey(propPoolInfo.lpMint.address);\n const poolInfo = {\n lpMint,\n lockInfo: { lockMint: FARM_LOCK_MINT, lockVault: FARM_LOCK_VAULT },\n version: 6,\n rewardInfos,\n programId,\n };\n\n const txBuilder = this.createTxBuilder();\n const payerPubKey = payer ?? this.scope.ownerPubKey;\n const farmKeyPair = generatePubKey({ fromPublicKey: payerPubKey, programId: poolInfo.programId });\n const lamports = await this.scope.connection.getMinimumBalanceForRentExemption(farmStateV6Layout.span);\n\n txBuilder.addInstruction({\n instructions: [\n SystemProgram.createAccountWithSeed({\n fromPubkey: payerPubKey,\n basePubkey: payerPubKey,\n seed: farmKeyPair.seed,\n newAccountPubkey: farmKeyPair.publicKey,\n lamports,\n space: farmStateV6Layout.span,\n programId: poolInfo.programId,\n }),\n ],\n });\n\n const { publicKey: authority, nonce } = getAssociatedAuthority({\n programId: new PublicKey(poolInfo.programId),\n poolId: farmKeyPair.publicKey,\n });\n\n const lpVault = getAssociatedLedgerPoolAccount({\n programId: poolInfo.programId,\n poolId: farmKeyPair.publicKey,\n mint: poolInfo.lpMint,\n type: \"lpVault\",\n });\n\n const rewardInfoConfig: FarmRewardInfoConfig[] = [];\n const rewardInfoKey: RewardInfoKey[] = [];\n\n for (const rewardInfo of poolInfo.rewardInfos) {\n if (rewardInfo.openTime >= rewardInfo.endTime)\n this.logAndCreateError(\"start time error\", \"rewardInfo.rewardOpenTime\", rewardInfo.openTime.toString());\n if (isNaN(poolTypeV6[rewardInfo.rewardType])) this.logAndCreateError(\"rewardType error\", rewardInfo.rewardType);\n if (Number(rewardInfo.perSecond) <= 0) this.logAndCreateError(\"rewardPerSecond error\", rewardInfo.perSecond);\n\n rewardInfoConfig.push(farmRewardInfoToConfig(rewardInfo));\n\n const { rewardPubKey, newInstruction } = await this._getUserRewardInfo({\n rewardInfo,\n payer: payerPubKey,\n });\n if (newInstruction) txBuilder.addInstruction(newInstruction);\n\n if (!rewardPubKey) this.logAndCreateError(\"cannot found target token accounts\", this.scope.account.tokenAccounts);\n\n const rewardMint = rewardInfo.mint.equals(SOLMint) ? new PublicKey(TOKEN_WSOL.address) : rewardInfo.mint;\n rewardInfoKey.push({\n rewardMint,\n rewardVault: getAssociatedLedgerPoolAccount({\n programId: poolInfo.programId,\n poolId: farmKeyPair.publicKey,\n mint: rewardMint,\n type: \"rewardVault\",\n }),\n userRewardToken: rewardPubKey!,\n });\n }\n\n const lockUserAccount = await this.scope.account.getCreatedTokenAccount({\n mint: poolInfo.lockInfo.lockMint,\n });\n\n if (!lockUserAccount)\n this.logAndCreateError(\"cannot found lock vault\", \"tokenAccounts\", this.scope.account.tokenAccounts);\n\n const { instruction, instructionType } = makeCreateFarmInstruction({\n farmId: farmKeyPair.publicKey,\n owner: this.scope.ownerPubKey,\n farmAuthority: authority,\n lpVault,\n lpMint: poolInfo.lpMint,\n lockVault: poolInfo.lockInfo.lockVault,\n lockMint: poolInfo.lockInfo.lockMint,\n lockUserAccount,\n programId: poolInfo.programId,\n rewardInfo: rewardInfoKey,\n rewardInfoConfig,\n nonce,\n });\n\n return txBuilder\n .addInstruction({\n instructions: [instruction],\n instructionTypes: [instructionType],\n })\n .versionBuild<CreateFarmExtInfo>({\n txVersion,\n extInfo: {\n farmId: farmKeyPair.publicKey,\n farmAuthority: authority,\n lpVault,\n lockUserAccount: lockUserAccount!,\n nonce,\n },\n }) as Promise<MakeTxData<T, CreateFarmExtInfo>>;\n }\n\n public async restartReward<T extends TxVersion>({\n farmInfo,\n payer,\n newRewardInfo,\n txVersion,\n }: UpdateFarmReward): Promise<MakeTxData<T>> {\n const version = FARM_PROGRAM_TO_VERSION[farmInfo.programId];\n if (version !== 6) this.logAndCreateError(\"invalid farm version \", version);\n\n const farmInfoKeys = jsonInfo2PoolKeys((await this.scope.api.fetchFarmKeysById({ ids: farmInfo.id }))[0]);\n\n const farmKeys = {\n id: farmInfoKeys.id,\n rewardInfos: farmInfo.rewardInfos,\n lpVault: farmInfoKeys.lpVault,\n programId: farmInfoKeys.programId,\n };\n\n if (newRewardInfo.openTime >= newRewardInfo.endTime)\n this.logAndCreateError(\"start time error\", \"newRewardInfo\", newRewardInfo);\n\n const payerPubKey = payer || this.scope.ownerPubKey;\n\n const rewardMint = newRewardInfo.mint.equals(SOLMint) ? new PublicKey(TOKEN_WSOL.address) : newRewardInfo.mint;\n const rewardInfoIndex = farmKeys.rewardInfos.findIndex((item) =>\n new PublicKey(item.mint.address).equals(rewardMint),\n );\n const rewardInfo = farmInfoKeys.rewardInfos[rewardInfoIndex];\n\n if (!rewardInfo) this.logAndCreateError(\"configuration does not exist\", \"rewardMint\", rewardMint);\n\n const rewardVault = rewardInfo!.vault ?? SOLMint;\n const txBuilder = this.createTxBuilder();\n\n const { rewardPubKey: userRewardTokenPub, newInstruction } = await this._getUserRewardInfo({\n rewardInfo: newRewardInfo,\n payer: payerPubKey,\n });\n if (newInstruction) txBuilder.addInstruction(newInstruction);\n\n if (!userRewardTokenPub)\n this.logAndCreateError(\"cannot found target token accounts\", this.scope.account.tokenAccounts);\n\n return txBuilder\n .addInstruction({\n instructions: [\n makeRestartRewardInstruction({\n payer: this.scope.ownerPubKey,\n rewardVault,\n userRewardTokenPub: userRewardTokenPub!,\n farmKeys,\n rewardInfo: newRewardInfo,\n }),\n ],\n instructionTypes: [InstructionType.FarmV6Restart],\n })\n .versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n public async restartRewards<T extends TxVersion>({\n farmInfo,\n payer,\n newRewardInfos,\n txVersion,\n }: UpdateFarmRewards<T>): Promise<MakeTxData<T>> {\n const version = FARM_PROGRAM_TO_VERSION[farmInfo.programId];\n if (version !== 6) this.logAndCreateError(\"invalid farm version \", version);\n\n const farmInfoKeys = jsonInfo2PoolKeys((await this.scope.api.fetchFarmKeysById({ ids: farmInfo.id }))[0]);\n\n const farmKeys = {\n id: farmInfoKeys.id,\n rewardInfos: farmInfo.rewardInfos,\n lpVault: farmInfoKeys.lpVault,\n programId: farmInfoKeys.programId,\n };\n\n newRewardInfos.forEach((reward) => {\n if (reward.openTime >= reward.endTime) this.logAndCreateError(\"start time error\", \"newRewardInfo\", reward);\n });\n\n const payerPubKey = payer || this.scope.ownerPubKey;\n const txBuilder = this.createTxBuilder();\n\n for (const itemReward of newRewardInfos) {\n const rewardMint = itemReward.mint.equals(SOLMint) ? new PublicKey(TOKEN_WSOL.address) : itemReward.mint;\n const rewardInfoIndex = farmKeys.rewardInfos.findIndex((item) =>\n new PublicKey(item.mint.address).equals(rewardMint),\n );\n const rewardInfo = farmInfoKeys.rewardInfos[rewardInfoIndex];\n if (!rewardInfo) this.logAndCreateError(\"configuration does not exist\", \"rewardMint\", rewardMint);\n const rewardVault = rewardInfo!.vault ?? SOLMint;\n const { rewardPubKey: userRewardTokenPub, newInstruction } = await this._getUserRewardInfo({\n rewardInfo: itemReward,\n payer: payerPubKey,\n });\n if (newInstruction) txBuilder.addInstruction(newInstruction);\n if (!userRewardTokenPub)\n this.logAndCreateError(\"cannot found target token accounts\", this.scope.account.tokenAccounts);\n const ins = makeRestartRewardInstruction({\n payer: this.scope.ownerPubKey,\n rewardVault,\n userRewardTokenPub: userRewardTokenPub!,\n farmKeys,\n rewardInfo: itemReward,\n });\n txBuilder.addInstruction({\n instructions: [ins],\n instructionTypes: [InstructionType.FarmV6Restart],\n });\n }\n\n return txBuilder.versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n public async addNewRewardToken<T extends TxVersion>(params: UpdateFarmReward): Promise<MakeTxData<T>> {\n const { txVersion, farmInfo, newRewardInfo, payer } = params;\n const version = FARM_PROGRAM_TO_VERSION[farmInfo.programId];\n if (version !== 6) this.logAndCreateError(\"invalid farm version \", version);\n\n const farmKeys = jsonInfo2PoolKeys((await this.scope.api.fetchFarmKeysById({ ids: farmInfo.id }))[0]);\n const payerPubKey = payer ?? this.scope.ownerPubKey;\n const txBuilder = this.createTxBuilder();\n\n const rewardMint = newRewardInfo.mint.equals(SOLMint) ? new PublicKey(TOKEN_WSOL.address) : newRewardInfo.mint;\n\n const rewardVault = getAssociatedLedgerPoolAccount({\n programId: new PublicKey(farmInfo.programId),\n poolId: new PublicKey(farmInfo.id),\n mint: rewardMint,\n type: \"rewardVault\",\n });\n\n const { rewardPubKey: userRewardTokenPub, newInstruction } = await this._getUserRewardInfo({\n rewardInfo: newRewardInfo,\n payer: payerPubKey,\n });\n if (newInstruction) txBuilder.addInstruction(newInstruction);\n\n if (!userRewardTokenPub)\n this.logAndCreateError(\"annot found target token accounts\", this.scope.account.tokenAccounts);\n\n newRewardInfo.mint = rewardMint;\n\n return txBuilder\n .addInstruction({\n instructions: [\n makeAddNewRewardInstruction({\n payer: this.scope.ownerPubKey,\n userRewardTokenPub: userRewardTokenPub!,\n farmKeys,\n rewardVault,\n rewardInfo: newRewardInfo,\n }),\n ],\n instructionTypes: [InstructionType.FarmV6CreatorAddReward],\n })\n .versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n public async addNewRewardsToken<T extends TxVersion>(params: UpdateFarmRewards<T>): Promise<MakeTxData<T>> {\n const { txVersion, farmInfo, newRewardInfos, payer } = params;\n const version = FARM_PROGRAM_TO_VERSION[farmInfo.programId];\n if (version !== 6) this.logAndCreateError(\"invalid farm version \", version);\n\n const farmKeys = jsonInfo2PoolKeys((await this.scope.api.fetchFarmKeysById({ ids: farmInfo.id }))[0]);\n const payerPubKey = payer ?? this.scope.ownerPubKey;\n const txBuilder = this.createTxBuilder();\n\n for (const itemReward of newRewardInfos) {\n const rewardMint = itemReward.mint.equals(SOLMint) ? new PublicKey(TOKEN_WSOL.address) : itemReward.mint;\n const rewardVault = getAssociatedLedgerPoolAccount({\n programId: new PublicKey(farmInfo.programId),\n poolId: new PublicKey(farmInfo.id),\n mint: rewardMint,\n type: \"rewardVault\",\n });\n const { rewardPubKey: userRewardTokenPub, newInstruction } = await this._getUserRewardInfo({\n rewardInfo: itemReward,\n payer: payerPubKey,\n });\n if (newInstruction) txBuilder.addInstruction(newInstruction);\n if (!userRewardTokenPub)\n this.logAndCreateError(\"cannot found target token accounts\", this.scope.account.tokenAccounts);\n const ins = makeAddNewRewardInstruction({\n payer: this.scope.ownerPubKey,\n userRewardTokenPub: userRewardTokenPub!,\n farmKeys,\n rewardVault,\n rewardInfo: { ...itemReward, mint: rewardMint },\n });\n txBuilder.addInstruction({\n instructions: [ins],\n instructionTypes: [InstructionType.FarmV6CreatorAddReward],\n });\n }\n\n return txBuilder.versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n public async deposit<T extends TxVersion>(params: FarmDWParam<T>): Promise<MakeTxData<T>> {\n const {\n txVersion,\n farmInfo,\n amount,\n feePayer,\n useSOLBalance,\n associatedOnly = true,\n checkCreateATAOwner = false,\n userAuxiliaryLedgers,\n computeBudgetConfig,\n } = params;\n\n if (this.scope.availability.addFarm === false)\n this.logAndCreateError(\"farm deposit feature disabled in your region\");\n\n const { rewardInfos, programId } = farmInfo;\n const version = FARM_PROGRAM_TO_VERSION[programId];\n if (!isValidFarmVersion(version)) this.logAndCreateError(\"invalid farm program:\", farmInfo.programId);\n const [farmProgramId, farmId] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];\n const farmKeys = (await this.scope.api.fetchFarmKeysById({ ids: farmInfo.id }))[0];\n\n const ledger = getAssociatedLedgerAccount({\n programId: farmProgramId,\n poolId: farmId,\n owner: this.scope.ownerPubKey,\n version,\n });\n\n const txBuilder = this.createTxBuilder();\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n const ownerMintToAccount: { [mint: string]: PublicKey } = {};\n for (const item of this.scope.account.tokenAccounts) {\n if (associatedOnly) {\n const ata = getATAAddress(this.scope.ownerPubKey, item.mint, item.programId).publicKey;\n if (item.publicKey && ata.equals(item.publicKey)) ownerMintToAccount[item.mint.toString()] = item.publicKey;\n } else {\n ownerMintToAccount[item.mint.toString()] = item.publicKey!;\n }\n }\n\n const lpMint = farmKeys.lpMint;\n const ownerLpTokenAccount = ownerMintToAccount[lpMint.address];\n if (!ownerLpTokenAccount) this.logAndCreateError(\"you don't have any lp\", \"lp zero\", ownerMintToAccount);\n\n const rewardAccounts: PublicKey[] = [];\n for (const itemReward of rewardInfos) {\n const rewardUseSOLBalance = useSOLBalance && itemReward.mint.address === WSOLMint.toString();\n\n let ownerRewardAccount = ownerMintToAccount[itemReward.mint.address];\n\n if (!ownerRewardAccount) {\n const { account: _ownerRewardAccount, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n mint: new PublicKey(itemReward.mint.address),\n notUseTokenAccount: rewardUseSOLBalance,\n createInfo: {\n payer: feePayer || this.scope.ownerPubKey,\n amount: 0,\n },\n owner: this.scope.ownerPubKey,\n skipCloseAccount: !rewardUseSOLBalance,\n associatedOnly: rewardUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n ownerRewardAccount = _ownerRewardAccount!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n\n ownerMintToAccount[itemReward.mint.address] = ownerRewardAccount;\n rewardAccounts.push(ownerRewardAccount);\n }\n\n let ledgerInfo: FarmLedger | undefined = undefined;\n const ledgerData = await this.scope.connection.getAccountInfo(ledger);\n if (ledgerData) {\n const ledgerLayout = getFarmLedgerLayout(version)!;\n ledgerInfo = ledgerLayout.decode(ledgerData.data);\n }\n\n if (farmInfo.programId !== FARM_PROGRAM_ID_V6.toString() && !ledgerInfo) {\n const { instruction, instructionType } = createAssociatedLedgerAccountInstruction({\n id: farmId,\n programId: farmProgramId,\n version,\n ledger,\n owner: this.scope.ownerPubKey,\n });\n txBuilder.addInstruction({ instructions: [instruction], instructionTypes: [instructionType] });\n }\n\n const errorMsg = validateFarmRewards({\n version,\n rewardInfos,\n rewardTokenAccountsPublicKeys: rewardAccounts,\n });\n if (errorMsg) this.logAndCreateError(errorMsg);\n\n const insParams = {\n amount: parseBigNumberish(amount),\n owner: this.scope.ownerPubKey,\n farmInfo,\n farmKeys,\n lpAccount: ownerLpTokenAccount,\n rewardAccounts,\n userAuxiliaryLedgers: userAuxiliaryLedgers?.map((key) => new PublicKey(key)),\n };\n\n const newInstruction =\n version === 6\n ? makeDepositInstructionV6(insParams)\n : version === 5\n ? makeDepositInstructionV5(insParams)\n : makeDepositInstructionV3(insParams);\n\n const insType = {\n 3: InstructionType.FarmV3Deposit,\n 5: InstructionType.FarmV5Deposit,\n 6: InstructionType.FarmV6Deposit,\n };\n\n return txBuilder\n .addInstruction({\n instructions: [newInstruction],\n instructionTypes: [insType[version]],\n })\n .versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n public async withdraw<T extends TxVersion>(params: FarmDWParam<T>): Promise<MakeTxData<T>> {\n const {\n txVersion,\n farmInfo,\n amount,\n deposited,\n useSOLBalance,\n feePayer,\n associatedOnly = true,\n checkCreateATAOwner = false,\n userAuxiliaryLedgers,\n computeBudgetConfig,\n } = params;\n const { rewardInfos } = farmInfo;\n\n if (this.scope.availability.removeFarm === false)\n this.logAndCreateError(\"farm withdraw feature disabled in your region\");\n\n const version = FARM_PROGRAM_TO_VERSION[farmInfo.programId];\n\n if (!isValidFarmVersion(version)) this.logAndCreateError(\"invalid farm program:\", farmInfo.programId);\n\n const farmKeys = (await this.scope.api.fetchFarmKeysById({ ids: farmInfo.id }))[0];\n const txBuilder = this.createTxBuilder();\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n const ownerMintToAccount: { [mint: string]: PublicKey } = {};\n for (const item of this.scope.account.tokenAccounts) {\n if (associatedOnly) {\n const ata = getATAAddress(this.scope.ownerPubKey, item.mint).publicKey;\n if (item.publicKey && ata.equals(item.publicKey)) ownerMintToAccount[item.mint.toString()] = item.publicKey;\n } else {\n ownerMintToAccount[item.mint.toString()] = item.publicKey!;\n }\n }\n\n if (!deposited) {\n const ledger = getAssociatedLedgerAccount({\n programId: new PublicKey(farmInfo.programId),\n poolId: new PublicKey(farmInfo.id),\n owner: this.scope.ownerPubKey,\n version,\n });\n const ledgerData = await this.scope.connection.getAccountInfo(ledger);\n if (!ledgerData) this.logAndCreateError(\"no lp data\", { farmId: farmInfo.id, version, ledgerData });\n const ledgerLayout = getFarmLedgerLayout(version)!;\n const ledgerInfo = ledgerLayout.decode(ledgerData!.data);\n if (ledgerInfo.deposited.isZero()) this.logAndCreateError(\"no deposited lp\", { farmId: farmInfo.id });\n } else {\n if (deposited.isZero()) this.logAndCreateError(\"no deposited lp\", { farmId: farmInfo.id });\n }\n\n const lpMint = farmKeys.lpMint.address;\n const lpMintUseSOLBalance = useSOLBalance && lpMint === WSOLMint.toString();\n\n let ownerLpTokenAccount = ownerMintToAccount[lpMint.toString()];\n if (!ownerLpTokenAccount) {\n const { account: _ownerRewardAccount, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n mint: new PublicKey(lpMint),\n notUseTokenAccount: lpMintUseSOLBalance,\n createInfo: {\n payer: feePayer || this.scope.ownerPubKey,\n amount: 0,\n },\n owner: this.scope.ownerPubKey,\n skipCloseAccount: true,\n associatedOnly: lpMintUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n ownerLpTokenAccount = _ownerRewardAccount!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n ownerMintToAccount[lpMint.toString()] = ownerLpTokenAccount;\n\n const rewardAccounts: PublicKey[] = [];\n for (const itemReward of rewardInfos) {\n const rewardUseSOLBalance = useSOLBalance && itemReward.mint.address === WSOLMint.toString();\n\n let ownerRewardAccount = ownerMintToAccount[itemReward.mint.address];\n if (!ownerRewardAccount) {\n const { account: _ownerRewardAccount, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n mint: new PublicKey(itemReward.mint.address),\n notUseTokenAccount: rewardUseSOLBalance,\n createInfo: {\n payer: feePayer || this.scope.ownerPubKey,\n amount: 0,\n },\n owner: this.scope.ownerPubKey,\n skipCloseAccount: !rewardUseSOLBalance,\n associatedOnly: rewardUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n ownerRewardAccount = _ownerRewardAccount!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n\n ownerMintToAccount[itemReward.mint.address] = ownerRewardAccount;\n rewardAccounts.push(ownerRewardAccount);\n }\n\n const errorMsg = validateFarmRewards({\n version,\n rewardInfos,\n rewardTokenAccountsPublicKeys: rewardAccounts,\n });\n if (errorMsg) this.logAndCreateError(errorMsg);\n\n const insParams = {\n amount: parseBigNumberish(amount),\n owner: this.scope.ownerPubKey,\n farmInfo,\n farmKeys,\n lpAccount: ownerLpTokenAccount,\n rewardAccounts,\n userAuxiliaryLedgers: userAuxiliaryLedgers?.map((key) => new PublicKey(key)),\n };\n\n const newInstruction =\n version === 6\n ? makeWithdrawInstructionV6(insParams)\n : version === 5\n ? makeWithdrawInstructionV5(insParams)\n : makeWithdrawInstructionV3(insParams);\n\n const insType = {\n 3: InstructionType.FarmV3Withdraw,\n 5: InstructionType.FarmV5Withdraw,\n 6: InstructionType.FarmV6Withdraw,\n };\n\n return txBuilder\n .addInstruction({\n instructions: [newInstruction],\n instructionTypes: [insType[version]],\n })\n .versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n // token account needed\n public async withdrawFarmReward<T extends TxVersion>({\n farmInfo,\n withdrawMint,\n txVersion,\n }: {\n farmInfo: FormatFarmInfoOut;\n withdrawMint: PublicKey;\n payer?: PublicKey;\n txVersion?: T;\n }): Promise<MakeTxData<T>> {\n this.scope.checkOwner();\n const farmKeys = jsonInfo2PoolKeys(\n (await this.scope.api.fetchFarmKeysById({ ids: farmInfo.id }))[0] as FormatFarmKeyOutV6,\n );\n const version = FARM_PROGRAM_TO_VERSION[farmInfo.programId];\n if (version !== 6) this.logAndCreateError(\"invalid farm version\", version);\n\n const rewardInfoIdx = farmInfo.rewardInfos.findIndex((item) =>\n item.mint.address === SOLMint.toString() ? new PublicKey(TOKEN_WSOL.address) : withdrawMint,\n );\n const rewardInfo = farmKeys.rewardInfos[rewardInfoIdx];\n if (!rewardInfo) this.logAndCreateError(\"withdraw mint error\", \"rewardInfos\", farmInfo);\n\n const rewardVault = rewardInfo?.vault ?? SOLMint;\n const txBuilder = this.createTxBuilder();\n\n let userRewardToken: PublicKey;\n\n if (withdrawMint.equals(SOLMint)) {\n const txInstruction = await createWSolAccountInstructions({\n connection: this.scope.connection,\n owner: this.scope.ownerPubKey,\n payer: this.scope.ownerPubKey,\n amount: calFarmRewardAmount({\n ...rewardInfo,\n perSecond: new Decimal(rewardInfo.perSecond).mul(10 ** rewardInfo.mint.decimals).toString(),\n }),\n });\n userRewardToken = txInstruction.addresses.newAccount;\n txBuilder.addInstruction(txInstruction);\n } else {\n const selectUserRewardToken = await this.scope.account.getCreatedTokenAccount({\n mint: withdrawMint,\n });\n\n if (selectUserRewardToken === null) {\n userRewardToken = await this.scope.account.getAssociatedTokenAccount(withdrawMint);\n txBuilder.addInstruction({\n instructions: [\n createAssociatedTokenAccountInstruction(\n this.scope.ownerPubKey,\n userRewardToken,\n this.scope.ownerPubKey,\n withdrawMint,\n ),\n ],\n instructionTypes: [InstructionType.CreateATA],\n });\n } else {\n userRewardToken = selectUserRewardToken!;\n }\n }\n\n const { instruction, instructionType } = makeCreatorWithdrawFarmRewardInstruction({\n programId: farmKeys.programId,\n id: farmKeys.id,\n authority: farmKeys.authority,\n lpVault: farmKeys.lpVault,\n rewardVault,\n userRewardToken,\n owner: this.scope.ownerPubKey,\n });\n\n return txBuilder\n .addInstruction({\n instructions: [instruction],\n instructionTypes: [instructionType],\n })\n .versionBuild({ txVersion }) as Promise<MakeTxData<T>>;\n }\n\n public async harvestAllRewards<T extends TxVersion = TxVersion.LEGACY>(params: {\n farmInfoList: Record<string, FormatFarmInfoOut>;\n feePayer?: PublicKey;\n useSOLBalance?: boolean;\n associatedOnly?: boolean;\n checkCreateATAOwner?: boolean;\n userAuxiliaryLedgers?: string[];\n txVersion?: T;\n computeBudgetConfig?: ComputeBudgetConfig;\n }): Promise<MakeMultiTxData<T>> {\n const {\n farmInfoList,\n useSOLBalance,\n feePayer,\n associatedOnly = true,\n checkCreateATAOwner = false,\n userAuxiliaryLedgers,\n txVersion,\n computeBudgetConfig,\n } = params;\n\n const txBuilder = this.createTxBuilder();\n txBuilder.addCustomComputeBudget(computeBudgetConfig);\n const ownerMintToAccount: { [mint: string]: PublicKey } = {};\n for (const item of this.scope.account.tokenAccounts) {\n if (associatedOnly) {\n const ata = getATAAddress(this.scope.ownerPubKey, item.mint).publicKey;\n if (item.publicKey && ata.equals(item.publicKey)) ownerMintToAccount[item.mint.toString()] = item.publicKey;\n } else {\n ownerMintToAccount[item.mint.toString()] = item.publicKey!;\n }\n }\n\n const allFarmKeys = await this.scope.api.fetchFarmKeysById({\n ids: Object.values(farmInfoList)\n .map((f) => f.id)\n .join(\",\"),\n });\n const farmKeyMap: { [key: string]: FormatFarmKeyOut } = allFarmKeys.reduce(\n (acc, cur) => ({ ...acc, [cur.id]: cur }),\n {},\n );\n for (const farmInfo of Object.values(farmInfoList)) {\n const { programId, lpMint: farmLpMint, rewardInfos, id } = farmInfo;\n const version = FARM_PROGRAM_TO_VERSION[programId];\n\n const lpMint = farmLpMint.address;\n const lpMintUseSOLBalance = useSOLBalance && lpMint === WSOLMint.toString();\n let ownerLpTokenAccount = ownerMintToAccount[lpMint];\n\n if (!ownerLpTokenAccount) {\n const { account: _ownerLpAccount, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n mint: new PublicKey(lpMint),\n notUseTokenAccount: lpMintUseSOLBalance,\n createInfo: {\n payer: feePayer || this.scope.ownerPubKey,\n amount: 0,\n },\n owner: this.scope.ownerPubKey,\n skipCloseAccount: true,\n associatedOnly: lpMintUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n ownerLpTokenAccount = _ownerLpAccount!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n ownerMintToAccount[lpMint.toString()] = ownerLpTokenAccount;\n\n const rewardAccounts: PublicKey[] = [];\n for (const itemReward of rewardInfos) {\n const rewardUseSOLBalance = useSOLBalance && itemReward.mint.address === WSOLMint.toString();\n\n let ownerRewardAccount = ownerMintToAccount[itemReward.mint.address];\n if (!ownerRewardAccount) {\n const { account: _ownerRewardAccount, instructionParams } = await this.scope.account.getOrCreateTokenAccount({\n mint: new PublicKey(itemReward.mint.address),\n notUseTokenAccount: rewardUseSOLBalance,\n createInfo: {\n payer: feePayer || this.scope.ownerPubKey,\n amount: 0,\n },\n owner: this.scope.ownerPubKey,\n skipCloseAccount: !rewardUseSOLBalance,\n associatedOnly: rewardUseSOLBalance ? false : associatedOnly,\n checkCreateATAOwner,\n });\n ownerRewardAccount = _ownerRewardAccount!;\n instructionParams && txBuilder.addInstruction(instructionParams);\n }\n\n ownerMintToAccount[itemReward.mint.address] = ownerRewardAccount;\n rewardAccounts.push(ownerRewardAccount);\n }\n\n const farmKeys = farmKeyMap[id];\n const insParams = {\n amount: BN_ZERO,\n owner: this.scope.ownerPubKey,\n farmInfo,\n farmKeys,\n lpAccount: ownerLpTokenAccount,\n rewardAccounts,\n userAuxiliaryLedgers: userAuxiliaryLedgers?.map((key) => new PublicKey(key)),\n };\n\n const withdrawInstruction =\n version === 6\n ? makeWithdrawInstructionV6(insParams)\n : version === 5\n ? makeWithdrawInstructionV5(insParams)\n : makeWithdrawInstructionV3(insParams);\n\n const insType = {\n 3: InstructionType.FarmV3Withdraw,\n 5: InstructionType.FarmV5Withdraw,\n 6: InstructionType.FarmV6Withdraw,\n };\n\n txBuilder.addInstruction({\n instructions: [withdrawInstruction],\n instructionTypes: [insType[version]],\n });\n }\n\n if (txVersion === TxVersion.LEGACY) return txBuilder.sizeCheckBuild() as Promise<MakeMultiTxData<T>>;\n return txBuilder.sizeCheckBuildV0() as Promise<MakeMultiTxData<T>>;\n }\n}\n","import { get, set } from \"lodash\";\nimport dayjs from \"dayjs\";\nimport utc from \"dayjs/plugin/utc\";\ndayjs.extend(utc);\n\nexport type ModuleName = \"Common.Api\";\n\nexport enum LogLevel {\n Error,\n Warning,\n Info,\n Debug,\n}\nexport class Logger {\n private logLevel: LogLevel;\n private name: string;\n constructor(params: { name: string; logLevel?: LogLevel }) {\n this.logLevel = params.logLevel !== undefined ? params.logLevel : LogLevel.Error;\n this.name = params.name;\n }\n\n set level(logLevel: LogLevel) {\n this.logLevel = logLevel;\n }\n get time(): string {\n return dayjs().utc().format(\"YYYY/MM/DD HH:mm:ss UTC\");\n }\n get moduleName(): string {\n return this.name;\n }\n\n private isLogLevel(level: LogLevel): boolean {\n return level <= this.logLevel;\n }\n\n public error(...props): Logger {\n if (!this.isLogLevel(LogLevel.Error)) return this;\n console.error(this.time, this.name, \"sdk logger error\", ...props);\n return this;\n }\n\n public logWithError(...props): Logger {\n // this.error(...props)\n const msg = props.map((arg) => (typeof arg === \"object\" ? JSON.stringify(arg) : arg)).join(\", \");\n throw new Error(msg);\n }\n\n public warning(...props): Logger {\n if (!this.isLogLevel(LogLevel.Warning)) return this;\n console.warn(this.time, this.name, \"sdk logger warning\", ...props);\n return this;\n }\n\n public info(...props): Logger {\n if (!this.isLogLevel(LogLevel.Info)) return this;\n console.info(this.time, this.name, \"sdk logger info\", ...props);\n return this;\n }\n\n public debug(...props): Logger {\n if (!this.isLogLevel(LogLevel.Debug)) return this;\n console.debug(this.time, this.name, \"sdk logger debug\", ...props);\n return this;\n }\n}\n\nconst moduleLoggers: { [key in ModuleName]?: Logger } = {};\nconst moduleLevels: { [key in ModuleName]?: LogLevel } = {};\n\nexport function createLogger(moduleName: string): Logger {\n let logger = get(moduleLoggers, moduleName);\n if (!logger) {\n // default level is error\n const logLevel = get(moduleLevels, moduleName);\n\n logger = new Logger({ name: moduleName, logLevel });\n set(moduleLoggers, moduleName, logger);\n }\n\n return logger;\n}\n\nexport function setLoggerLevel(moduleName: string, level: LogLevel): void {\n set(moduleLevels, moduleName, level);\n\n const logger = get(moduleLoggers, moduleName);\n if (logger) logger.level = level;\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport BN from \"bn.js\";\n\nimport { Fraction, Percent, Price, Token, TokenAmount } from \"../module\";\nimport { ReplaceType } from \"../raydium/type\";\n\nimport { tryParsePublicKey } from \"./pubKey\";\n\nexport async function sleep(ms: number): Promise<void> {\n new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function getTimestamp(): number {\n return new Date().getTime();\n}\n\nexport function notInnerObject(v: unknown): v is Record<string, any> {\n return (\n typeof v === \"object\" &&\n v !== null &&\n ![Token, TokenAmount, PublicKey, Fraction, BN, Price, Percent].some((o) => typeof o === \"object\" && v instanceof o)\n );\n}\n\nexport function jsonInfo2PoolKeys<T>(jsonInfo: T): ReplaceType<T, string, PublicKey> {\n // @ts-expect-error no need type for inner code\n return typeof jsonInfo === \"string\"\n ? tryParsePublicKey(jsonInfo)\n : Array.isArray(jsonInfo)\n ? jsonInfo.map((k) => jsonInfo2PoolKeys(k))\n : notInnerObject(jsonInfo)\n ? Object.fromEntries(Object.entries(jsonInfo).map(([k, v]) => [k, jsonInfo2PoolKeys(v)]))\n : jsonInfo;\n}\n","import _Big from \"big.js\";\nimport BN from \"bn.js\";\n\nimport { BigNumberish, BN_TEN, parseBigNumberish, Rounding } from \"../common/bignumber\";\nimport { createLogger, Logger } from \"../common/logger\";\n\nimport toFormat, { WrappedBig } from \"./formatter\";\nimport { Fraction } from \"./fraction\";\nimport { Token } from \"./token\";\nimport { Currency } from \"./currency\";\n\nconst logger = createLogger(\"Raydium_amount\");\n\nconst Big = toFormat(_Big);\ntype Big = WrappedBig;\n\nexport function splitNumber(num: string, decimals: number): [string, string] {\n let integral = \"0\";\n let fractional = \"0\";\n\n if (num.includes(\".\")) {\n const splited = num.split(\".\");\n if (splited.length === 2) {\n [integral, fractional] = splited;\n fractional = fractional.padEnd(decimals, \"0\");\n } else {\n logger.logWithError(`invalid number string, num: ${num}`);\n }\n } else {\n integral = num;\n }\n\n // fix decimals is 0\n return [integral, fractional.slice(0, decimals) || fractional];\n}\n\nexport class TokenAmount extends Fraction {\n public readonly token: Token;\n protected logger: Logger;\n\n public constructor(token: Token, amount: BigNumberish, isRaw = true, name?: string) {\n let parsedAmount = new BN(0);\n const multiplier = BN_TEN.pow(new BN(token.decimals));\n\n if (isRaw) {\n parsedAmount = parseBigNumberish(amount);\n } else {\n let integralAmount = new BN(0);\n let fractionalAmount = new BN(0);\n\n // parse fractional string\n if (typeof amount === \"string\" || typeof amount === \"number\" || typeof amount === \"bigint\") {\n const [integral, fractional] = splitNumber(amount.toString(), token.decimals);\n integralAmount = parseBigNumberish(integral);\n fractionalAmount = parseBigNumberish(fractional);\n }\n\n integralAmount = integralAmount.mul(multiplier);\n parsedAmount = integralAmount.add(fractionalAmount);\n }\n\n super(parsedAmount, multiplier);\n this.logger = createLogger(name || \"TokenAmount\");\n this.token = token;\n }\n\n public get raw(): BN {\n return this.numerator;\n }\n public isZero(): boolean {\n return this.raw.isZero();\n }\n public gt(other: TokenAmount): boolean {\n if (!this.token.equals(other.token)) this.logger.logWithError(\"gt token not equals\");\n return this.raw.gt(other.raw);\n }\n\n /**\n * a less than b\n */\n public lt(other: TokenAmount): boolean {\n if (!this.token.equals(other.token)) this.logger.logWithError(\"lt token not equals\");\n return this.raw.lt(other.raw);\n }\n\n public add(other: TokenAmount): TokenAmount {\n if (!this.token.equals(other.token)) this.logger.logWithError(\"add token not equals\");\n return new TokenAmount(this.token, this.raw.add(other.raw));\n }\n\n public subtract(other: TokenAmount): TokenAmount {\n if (!this.token.equals(other.token)) this.logger.logWithError(\"sub token not equals\");\n return new TokenAmount(this.token, this.raw.sub(other.raw));\n }\n\n public toSignificant(\n significantDigits = this.token.decimals,\n format?: object,\n rounding: Rounding = Rounding.ROUND_DOWN,\n ): string {\n return super.toSignificant(significantDigits, format, rounding);\n }\n\n /**\n * To fixed\n *\n * @example\n * ```\n * 1 -> 1.000000000\n * 1.234 -> 1.234000000\n * 1.123456789876543 -> 1.123456789\n * ```\n */\n public toFixed(\n decimalPlaces = this.token.decimals,\n format?: object,\n rounding: Rounding = Rounding.ROUND_DOWN,\n ): string {\n if (decimalPlaces > this.token.decimals) this.logger.logWithError(\"decimals overflow\");\n return super.toFixed(decimalPlaces, format, rounding);\n }\n\n /**\n * To exact\n *\n * @example\n * ```\n * 1 -> 1\n * 1.234 -> 1.234\n * 1.123456789876543 -> 1.123456789\n * ```\n */\n public toExact(format: object = { groupSeparator: \"\" }): string {\n Big.DP = this.token.decimals;\n return new Big(this.numerator.toString()).div(this.denominator.toString()).toFormat(format);\n }\n}\n\nexport class CurrencyAmount extends Fraction {\n public readonly currency: Currency;\n protected logger: Logger;\n\n public constructor(currency: Currency, amount: BigNumberish, isRaw = true, name?: string) {\n let parsedAmount = new BN(0);\n const multiplier = BN_TEN.pow(new BN(currency.decimals));\n\n if (isRaw) {\n parsedAmount = parseBigNumberish(amount);\n } else {\n let integralAmount = new BN(0);\n let fractionalAmount = new BN(0);\n\n // parse fractional string\n if (typeof amount === \"string\" || typeof amount === \"number\" || typeof amount === \"bigint\") {\n const [integral, fractional] = splitNumber(amount.toString(), currency.decimals);\n integralAmount = parseBigNumberish(integral);\n fractionalAmount = parseBigNumberish(fractional);\n }\n\n integralAmount = integralAmount.mul(multiplier);\n parsedAmount = integralAmount.add(fractionalAmount);\n }\n\n super(parsedAmount, multiplier);\n this.logger = createLogger(name || \"TokenAmount\");\n this.currency = currency;\n }\n\n public get raw(): BN {\n return this.numerator;\n }\n\n public isZero(): boolean {\n return this.raw.isZero();\n }\n\n /**\n * a greater than b\n */\n public gt(other: CurrencyAmount): boolean {\n if (!this.currency.equals(other.currency)) this.logger.logWithError(\"gt currency not equals\");\n return this.raw.gt(other.raw);\n }\n\n /**\n * a less than b\n */\n public lt(other: CurrencyAmount): boolean {\n if (!this.currency.equals(other.currency)) this.logger.logWithError(\"lt currency not equals\");\n return this.raw.lt(other.raw);\n }\n\n public add(other: CurrencyAmount): CurrencyAmount {\n if (!this.currency.equals(other.currency)) this.logger.logWithError(\"add currency not equals\");\n return new CurrencyAmount(this.currency, this.raw.add(other.raw));\n }\n\n public sub(other: CurrencyAmount): CurrencyAmount {\n if (!this.currency.equals(other.currency)) this.logger.logWithError(\"sub currency not equals\");\n return new CurrencyAmount(this.currency, this.raw.sub(other.raw));\n }\n\n public toSignificant(\n significantDigits = this.currency.decimals,\n format?: object,\n rounding: Rounding = Rounding.ROUND_DOWN,\n ): string {\n return super.toSignificant(significantDigits, format, rounding);\n }\n\n /**\n * To fixed\n *\n * @example\n * ```\n * 1 -> 1.000000000\n * 1.234 -> 1.234000000\n * 1.123456789876543 -> 1.123456789\n * ```\n */\n public toFixed(\n decimalPlaces = this.currency.decimals,\n format?: object,\n rounding: Rounding = Rounding.ROUND_DOWN,\n ): string {\n if (decimalPlaces > this.currency.decimals) this.logger.logWithError(\"decimals overflow\");\n\n return super.toFixed(decimalPlaces, format, rounding);\n }\n\n /**\n * To exact\n *\n * @example\n * ```\n * 1 -> 1\n * 1.234 -> 1.234\n * 1.123456789876543 -> 1.123456789\n * ```\n */\n public toExact(format: object = { groupSeparator: \"\" }): string {\n Big.DP = this.currency.decimals;\n return new Big(this.numerator.toString()).div(this.denominator.toString()).toFormat(format);\n }\n}\n","import BN from \"bn.js\";\nimport Decimal from \"decimal.js\";\nimport { Token } from \"../module/token\";\nimport { Price } from \"../module/price\";\nimport { Currency } from \"../module/currency\";\nimport { TokenAmount, CurrencyAmount } from \"../module/amount\";\nimport { Fraction } from \"../module/fraction\";\nimport { Percent } from \"../module/percent\";\nimport { SplToken, TokenJson } from \"../raydium/token/type\";\nimport { ReplaceType } from \"../raydium/type\";\nimport { createLogger } from \"./logger\";\nimport { mul } from \"./fractionUtil\";\nimport { notInnerObject } from \"./utility\";\n\nexport enum Rounding {\n ROUND_DOWN,\n ROUND_HALF_UP,\n ROUND_UP,\n}\n\nexport const BN_ZERO = new BN(0);\nexport const BN_ONE = new BN(1);\nexport const BN_TWO = new BN(2);\nexport const BN_THREE = new BN(3);\nexport const BN_FIVE = new BN(5);\nexport const BN_TEN = new BN(10);\nexport const BN_100 = new BN(100);\nexport const BN_1000 = new BN(1000);\nexport const BN_10000 = new BN(10000);\nexport type BigNumberish = BN | string | number | bigint;\nexport type Numberish = number | string | bigint | Fraction | BN;\n\nconst MAX_SAFE = 0x1fffffffffffff;\n\nexport function parseBigNumberish(value: BigNumberish): BN {\n const logger = createLogger(\"Raydium_parseBigNumberish\");\n // BN\n if (value instanceof BN) {\n return value;\n }\n\n if (typeof value === \"string\") {\n if (value.match(/^-?[0-9]+$/)) {\n return new BN(value);\n }\n logger.logWithError(`invalid BigNumberish string: ${value}`);\n }\n\n if (typeof value === \"number\") {\n if (value % 1) {\n logger.logWithError(`BigNumberish number underflow: ${value}`);\n }\n\n if (value >= MAX_SAFE || value <= -MAX_SAFE) {\n logger.logWithError(`BigNumberish number overflow: ${value}`);\n }\n\n return new BN(String(value));\n }\n\n if (typeof value === \"bigint\") {\n return new BN(value.toString());\n }\n logger.error(`invalid BigNumberish value: ${value}`);\n return new BN(0); // never reach, because logWithError will throw error\n}\n\nexport function tenExponential(shift: BigNumberish): BN {\n return BN_TEN.pow(parseBigNumberish(shift));\n}\n\n/**\n *\n * @example\n * getIntInfo(0.34) => { numerator: '34', denominator: '100'}\n * getIntInfo('0.34') //=> { numerator: '34', denominator: '100'}\n */\nexport function parseNumberInfo(n: Numberish | undefined): {\n denominator: string;\n numerator: string;\n sign?: string;\n int?: string;\n dec?: string;\n} {\n if (n === undefined) return { denominator: \"1\", numerator: \"0\" };\n if (n instanceof BN) {\n return { numerator: n.toString(), denominator: \"1\" };\n }\n\n if (n instanceof Fraction) {\n return { denominator: n.denominator.toString(), numerator: n.numerator.toString() };\n }\n\n const s = String(n);\n const [, sign = \"\", int = \"\", dec = \"\"] = s.replace(\",\", \"\").match(/(-?)(\\d*)\\.?(\\d*)/) ?? [];\n const denominator = \"1\" + \"0\".repeat(dec.length);\n const numerator = sign + (int === \"0\" ? \"\" : int) + dec || \"0\";\n return { denominator, numerator, sign, int, dec };\n}\n\n// round up\nexport function divCeil(a: BN, b: BN): BN {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const dm = a.divmod(b);\n\n // Fast case - exact division\n if (dm.mod.isZero()) return dm.div;\n\n // Round up\n return dm.div.isNeg() ? dm.div.isubn(1) : dm.div.iaddn(1);\n}\n\nexport function shakeFractionDecimal(n: Fraction): string {\n const [, sign = \"\", int = \"\"] = n.toFixed(2).match(/(-?)(\\d*)\\.?(\\d*)/) ?? [];\n return `${sign}${int}`;\n}\n\nexport function toBN(n: Numberish, decimal: BigNumberish = 0): BN {\n if (n instanceof BN) return n;\n return new BN(shakeFractionDecimal(toFraction(n).mul(BN_TEN.pow(new BN(String(decimal))))));\n}\n\nexport function toFraction(value: Numberish): Fraction {\n // to complete math format(may have decimal), not int\n if (value instanceof Percent) return new Fraction(value.numerator, value.denominator);\n\n if (value instanceof Price) return value.adjusted;\n\n // to complete math format(may have decimal), not BN\n if (value instanceof TokenAmount)\n try {\n return toFraction(value.toExact());\n } catch {\n return new Fraction(BN_ZERO);\n }\n\n // do not ideal with other fraction value\n if (value instanceof Fraction) return value;\n\n /