@raydium-io/raydium-sdk-v2
Version:
An SDK for building applications on top of Raydium.
1 lines • 1.27 MB
Source Map (JSON)
{"version":3,"sources":["../../../../src/raydium/launchpad/curve/curve.ts","../../../../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/raydium/raydium.ts","../../../../src/api/api.ts","../../../../src/api/url.ts","../../../../src/raydium/account/account.ts","../../../../src/common/txTool/txTool.ts","../../../../src/common/txTool/lookupTable.ts","../../../../src/common/txTool/txType.ts","../../../../src/common/txTool/txUtils.ts","../../../../src/raydium/moduleBase.ts","../../../../src/raydium/account/instruction.ts","../../../../src/raydium/account/util.ts","../../../../src/marshmallow/index.ts","../../../../src/marshmallow/buffer-layout.ts","../../../../src/raydium/account/layout.ts","../../../../src/raydium/farm/farm.ts","../../../../src/common/pda.ts","../../../../src/common/programId.ts","../../../../src/raydium/clmm/clmm.ts","../../../../src/raydium/token/utils.ts","../../../../src/raydium/token/layout.ts","../../../../src/raydium/clmm/instrument.ts","../../../../src/raydium/clmm/libraries/constants.ts","../../../../src/raydium/clmm/layout.ts","../../../../src/raydium/clmm/libraries/utils.ts","../../../../src/raydium/clmm/libraries/pda.ts","../../../../src/raydium/clmm/libraries/bigNum.ts","../../../../src/raydium/clmm/libraries/limitOrder.ts","../../../../src/raydium/clmm/libraries/tickArrayUtil.ts","../../../../src/raydium/clmm/libraries/liquidityMath.ts","../../../../src/raydium/clmm/libraries/pool.ts","../../../../src/raydium/clmm/libraries/swapSimulator.ts","../../../../src/raydium/clmm/libraries/swapMath.ts","../../../../src/raydium/clmm/libraries/position.ts","../../../../src/raydium/farm/config.ts","../../../../src/raydium/farm/layout.ts","../../../../src/raydium/farm/instruction.ts","../../../../src/raydium/farm/util.ts","../../../../src/common/utility.ts","../../../../src/raydium/liquidity/liquidity.ts","../../../../src/common/transfer.ts","../../../../src/raydium/liquidity/constant.ts","../../../../src/raydium/liquidity/instruction.ts","../../../../src/raydium/liquidity/layout.ts","../../../../src/raydium/liquidity/stable.ts","../../../../src/raydium/liquidity/utils.ts","../../../../src/raydium/liquidity/serum.ts","../../../../src/raydium/marketV2/createMarket.ts","../../../../src/raydium/marketV2/instrument.ts","../../../../src/raydium/marketV2/layout.ts","../../../../src/raydium/cpmm/cpmm.ts","../../../../src/raydium/cpmm/curve/calculator.ts","../../../../src/raydium/cpmm/curve/constantProduct.ts","../../../../src/raydium/cpmm/curve/fee.ts","../../../../src/common/fee.ts","../../../../src/raydium/cpmm/instruction.ts","../../../../src/raydium/cpmm/pda.ts","../../../../src/raydium/cpmm/layout.ts","../../../../src/raydium/tradeV2/trade.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/curveBase.ts","../../../../src/raydium/launchpad/curve/fixedPriceCurve.ts","../../../../src/raydium/launchpad/curve/func.ts","../../../../src/raydium/launchpad/curve/linearPriceCurve.ts","../../../../src/raydium/launchpad/launchpad.ts","../../../../src/raydium/serum/id.ts","../../../../src/raydium/serum/layout.ts","../../../../src/raydium/serum/serum.ts","../../../../src/raydium/tradeV2/instrument.ts","../../../../src/raydium/utils1216/utils1216.ts","../../../../src/raydium/ido/ido.ts","../../../../src/raydium/ido/instruction.ts","../../../../src/raydium/ido/layout.ts","../../../../src/raydium/token/token.ts","../../../../src/common/lodash.ts"],"sourcesContent":["import { TransferFeeConfig } from \"@solana/spl-token\";\nimport BN from \"bn.js\";\nimport Decimal from \"decimal.js\";\nimport { GetTransferAmountFee } from \"@/raydium/type\";\nimport { getTransferAmountFeeFromPre, getTransferAmountFeeFromPost } from \"@/common\";\nimport { LaunchpadConfig, LaunchpadPool } from \"../layout\";\nimport { LaunchConstantProductCurve } from \"./constantProductCurve\";\nimport { CurveBase, PoolBaseAmount } from \"./curveBase\";\n// import { ceilDiv, FEE_RATE_DENOMINATOR_VALUE } from \"./fee\";\nimport { ceilDiv, FEE_RATE_DENOMINATOR_VALUE } from \"@/common\";\nimport { FixedPriceCurve } from \"./fixedPriceCurve\";\nimport { LinearPriceCurve } from \"./linearPriceCurve\";\n\nexport interface SwapInfoReturn {\n amountA: GetTransferAmountFee;\n amountB: BN;\n splitFee: ReturnType<typeof Curve.splitFee>;\n}\n\nexport class Curve {\n static getPoolCurvePointByPoolInfo({\n curveType,\n pointCount,\n poolInfo,\n }: {\n curveType: number;\n poolInfo: ReturnType<typeof LaunchpadPool.decode>;\n pointCount: number;\n }): {\n price: Decimal;\n totalSellSupply: number;\n }[] {\n return this.getPoolCurvePointByInit({\n curveType,\n pointCount,\n supply: poolInfo.supply,\n totalFundRaising: poolInfo.totalFundRaisingB,\n totalSell: poolInfo.totalSellA,\n totalLockedAmount: poolInfo.vestingSchedule.totalLockedAmount,\n migrateFee: poolInfo.migrateFee,\n decimalA: poolInfo.mintDecimalsA,\n decimalB: poolInfo.mintDecimalsB,\n });\n }\n static getPoolCurvePointByInit({\n curveType,\n pointCount,\n supply,\n totalFundRaising,\n totalSell,\n totalLockedAmount,\n migrateFee,\n decimalA,\n decimalB,\n }: {\n curveType: number;\n supply: BN;\n totalSell: BN;\n totalLockedAmount: BN;\n totalFundRaising: BN;\n migrateFee: BN;\n decimalA: number;\n decimalB: number;\n pointCount: number;\n }): {\n price: Decimal;\n totalSellSupply: number;\n }[] {\n if (pointCount < 3) throw Error(\"point count < 3\");\n\n const curve = this.getCurve(curveType);\n const initParam = curve.getInitParam({ supply, totalFundRaising, totalSell, totalLockedAmount, migrateFee });\n const initPrice = curve.getPoolInitPriceByInit({ ...initParam, decimalA, decimalB });\n\n const itemStepBuy = totalFundRaising.div(new BN(pointCount - 1));\n\n const zero = new BN(0);\n\n const returnPoints: { price: Decimal; totalSellSupply: number }[] = [{ price: initPrice, totalSellSupply: 0 }];\n const { a, b } = initParam;\n let realA = zero;\n let realB = zero;\n for (let i = 1; i < pointCount; i++) {\n const amountB = i !== pointCount - 1 ? itemStepBuy : totalFundRaising.sub(realB);\n const itemBuy = this.buyExactIn({\n poolInfo: {\n virtualA: a,\n virtualB: b,\n realA,\n realB,\n totalFundRaisingB: totalFundRaising,\n totalSellA: totalSell,\n },\n amountB,\n protocolFeeRate: zero,\n platformFeeRate: zero,\n curveType,\n shareFeeRate: zero,\n creatorFeeRate: zero,\n transferFeeConfigA: undefined,\n slot: 0,\n });\n realA = realA.add(itemBuy.amountA.amount);\n realB = realB.add(itemBuy.amountB);\n\n const nowPoolPrice = this.getPrice({\n poolInfo: { virtualA: a, virtualB: b, realA, realB },\n decimalA,\n decimalB,\n curveType,\n });\n returnPoints.push({\n price: nowPoolPrice,\n totalSellSupply: new Decimal(realA.toString()).div(10 ** decimalA).toNumber(),\n });\n }\n\n return returnPoints;\n }\n\n static getPoolInitPriceByPool({\n poolInfo,\n decimalA,\n decimalB,\n curveType,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode> | PoolBaseAmount;\n decimalA: number;\n decimalB: number;\n curveType: number;\n }): Decimal {\n const curve = this.getCurve(curveType);\n return curve.getPoolInitPriceByPool({ poolInfo, decimalA, decimalB });\n }\n static getPoolInitPriceByInit({\n a,\n b,\n decimalA,\n decimalB,\n curveType,\n }: {\n a: BN;\n b: BN;\n decimalA: number;\n decimalB: number;\n curveType: number;\n }): Decimal {\n const curve = this.getCurve(curveType);\n return curve.getPoolInitPriceByInit({ a, b, decimalA, decimalB });\n }\n static getPrice({\n poolInfo,\n curveType,\n decimalA,\n decimalB,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode> | { virtualA: BN; virtualB: BN; realA: BN; realB: BN };\n decimalA: number;\n decimalB: number;\n curveType: number;\n }): Decimal {\n const curve = this.getCurve(curveType);\n return curve.getPoolPrice({ poolInfo, decimalA, decimalB });\n }\n static getEndPrice({\n poolInfo,\n curveType,\n decimalA,\n decimalB,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode>;\n curveType: number;\n decimalA: number;\n decimalB: number;\n }): Decimal {\n const curve = this.getCurve(curveType);\n return curve.getPoolPrice({ poolInfo, decimalA, decimalB });\n }\n static getPoolEndPriceReal({\n poolInfo,\n curveType,\n decimalA,\n decimalB,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode>;\n curveType: number;\n decimalA: number;\n decimalB: number;\n }): Decimal {\n const curve = this.getCurve(curveType);\n return curve.getPoolEndPriceReal({ poolInfo, decimalA, decimalB });\n }\n\n static checkParam({\n supply,\n totalFundRaising,\n totalSell,\n totalLockedAmount,\n decimals,\n config,\n migrateType,\n }: {\n supply: BN;\n totalSell: BN;\n totalLockedAmount: BN;\n totalFundRaising: BN;\n decimals: number;\n config: ReturnType<typeof LaunchpadConfig.decode>;\n migrateType: \"amm\" | \"cpmm\";\n }): void {\n if (Number(decimals) !== 6) throw Error(\"decimals = 6\");\n const maxLockedA = supply.mul(config.maxLockRate).div(FEE_RATE_DENOMINATOR_VALUE);\n if (maxLockedA.lt(totalLockedAmount)) throw Error(\"total lock amount gte max lock amount\");\n\n if (supply.lt(config.minSupplyA.mul(new BN(10 ** decimals)))) throw Error(\"supply lt min supply\");\n\n const minSellA = supply.mul(config.minSellRateA).div(FEE_RATE_DENOMINATOR_VALUE);\n if (totalSell.lt(minSellA)) throw Error(\"invalid input\");\n if (totalFundRaising.lt(config.minFundRaisingB)) throw Error(\"total fund raising lt min fund raising\");\n\n const amountMigrate = supply.sub(totalSell).sub(totalLockedAmount);\n const minAmountMigrate = supply.mul(config.minMigrateRateA).div(FEE_RATE_DENOMINATOR_VALUE);\n\n if (amountMigrate.lt(minAmountMigrate)) throw Error(\"migrate lt min migrate amoount\");\n\n const migrateAmountA = supply.sub(totalSell).sub(totalLockedAmount);\n const liquidity = new BN(new Decimal(migrateAmountA.mul(totalFundRaising).toString()).sqrt().toFixed(0));\n\n if (migrateType === \"amm\") {\n const minLockLp = new BN(10).pow(new BN(decimals));\n if (liquidity.lte(minLockLp)) throw Error(\"check migrate lp error\");\n } else if (migrateType === \"cpmm\") {\n const minLockLp = new BN(100);\n if (liquidity.lte(minLockLp)) throw Error(\"check migrate lp error\");\n } else {\n throw Error(\"migrate type error\");\n }\n }\n\n /**\n * @returns Please note that amountA/B is subject to change\n */\n static buyExactIn({\n poolInfo,\n amountB,\n protocolFeeRate,\n platformFeeRate,\n curveType,\n shareFeeRate,\n creatorFeeRate,\n transferFeeConfigA,\n slot,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode> | (PoolBaseAmount & { totalSellA: BN; totalFundRaisingB: BN });\n amountB: BN;\n protocolFeeRate: BN;\n platformFeeRate: BN;\n curveType: number;\n shareFeeRate: BN;\n creatorFeeRate: BN;\n\n transferFeeConfigA: TransferFeeConfig | undefined;\n slot: number;\n }): SwapInfoReturn {\n const feeRate = this.totalFeeRate({ protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n const _totalFee = this.calculateFee({ amount: amountB, feeRate });\n\n const amountLessFeeB = amountB.sub(_totalFee);\n\n const curve = this.getCurve(curveType);\n\n const _amountA = curve.buyExactIn({ poolInfo, amount: amountLessFeeB });\n\n const remainingAmountA = poolInfo.totalSellA.sub(poolInfo.realA);\n\n let amountA: BN;\n let realAmountB: BN;\n let totalFee: BN;\n if (_amountA.gt(remainingAmountA)) {\n amountA = remainingAmountA;\n\n const amountLessFeeB = curve.buyExactOut({\n poolInfo,\n amount: amountA,\n });\n\n realAmountB = this.calculatePreFee({ postFeeAmount: amountLessFeeB, feeRate });\n totalFee = realAmountB.sub(amountLessFeeB);\n } else {\n amountA = _amountA;\n realAmountB = amountB;\n totalFee = _totalFee;\n }\n\n const splitFee = this.splitFee({ totalFee, protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n\n return {\n amountA: getTransferAmountFeeFromPre(amountA, transferFeeConfigA, slot),\n amountB: realAmountB,\n splitFee,\n };\n }\n\n /**\n * @returns Please note that amountA/B is subject to change\n */\n static buyExactOut({\n poolInfo,\n amountA,\n protocolFeeRate,\n platformFeeRate,\n curveType,\n shareFeeRate,\n creatorFeeRate,\n transferFeeConfigA,\n slot,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode> | (PoolBaseAmount & { totalSellA: BN; totalFundRaisingB: BN });\n amountA: BN;\n protocolFeeRate: BN;\n platformFeeRate: BN;\n curveType: number;\n shareFeeRate: BN;\n creatorFeeRate: BN;\n\n transferFeeConfigA: TransferFeeConfig | undefined;\n slot: number;\n }): SwapInfoReturn {\n const remainingAmountA = poolInfo.totalSellA.sub(poolInfo.realA);\n\n const preAmountA = getTransferAmountFeeFromPost(amountA, transferFeeConfigA, slot);\n let realAmountA = preAmountA.fee ? preAmountA.amount.add(preAmountA.fee) : preAmountA.amount;\n if (amountA.gt(remainingAmountA)) {\n realAmountA = remainingAmountA;\n }\n\n const curve = this.getCurve(curveType);\n const amountInLessFeeB = curve.buyExactOut({ poolInfo, amount: realAmountA });\n\n const totalFeeRate = this.totalFeeRate({ protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n\n const amountB = this.calculatePreFee({ postFeeAmount: amountInLessFeeB, feeRate: totalFeeRate });\n const totalFee = amountB.sub(amountInLessFeeB);\n\n const splitFee = this.splitFee({ totalFee, protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n\n return { amountA: preAmountA, amountB, splitFee };\n }\n\n static sellExactIn({\n poolInfo,\n amountA: _amountA,\n protocolFeeRate,\n platformFeeRate,\n curveType,\n shareFeeRate,\n creatorFeeRate,\n transferFeeConfigA,\n slot,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode> | PoolBaseAmount;\n amountA: BN;\n protocolFeeRate: BN;\n platformFeeRate: BN;\n curveType: number;\n shareFeeRate: BN;\n creatorFeeRate: BN;\n\n transferFeeConfigA: TransferFeeConfig | undefined;\n slot: number;\n }): SwapInfoReturn {\n const curve = this.getCurve(curveType);\n\n const amountInfoA = getTransferAmountFeeFromPre(_amountA, transferFeeConfigA, slot);\n const amountA = amountInfoA.fee ? amountInfoA.amount.sub(amountInfoA.fee) : amountInfoA.amount;\n\n const amountB = curve.sellExactIn({ poolInfo, amount: amountA });\n\n const totalFee = this.calculateFee({\n amount: amountB,\n feeRate: this.totalFeeRate({ protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate }),\n });\n\n const splitFee = this.splitFee({ totalFee, protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n\n return { amountA: amountInfoA, amountB: amountB.sub(totalFee), splitFee };\n }\n\n static sellExactOut({\n poolInfo,\n amountB,\n protocolFeeRate,\n platformFeeRate,\n curveType,\n shareFeeRate,\n creatorFeeRate,\n transferFeeConfigA,\n slot,\n }: {\n poolInfo: ReturnType<typeof LaunchpadPool.decode> | PoolBaseAmount;\n amountB: BN;\n protocolFeeRate: BN;\n platformFeeRate: BN;\n curveType: number;\n shareFeeRate: BN;\n creatorFeeRate: BN;\n\n transferFeeConfigA: TransferFeeConfig | undefined;\n slot: number;\n }): SwapInfoReturn {\n const totalFeeRate = this.totalFeeRate({ protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n\n const amountOutWithFeeB = this.calculatePreFee({ postFeeAmount: amountB, feeRate: totalFeeRate });\n if (poolInfo.realB.lt(amountOutWithFeeB)) throw Error(\"Insufficient liquidity\");\n\n const totalFee = amountOutWithFeeB.sub(amountB);\n\n const curve = Curve.getCurve(curveType);\n const amountA = curve.sellExactOut({ poolInfo, amount: amountOutWithFeeB });\n\n if (amountA.gt(poolInfo.realA)) throw Error();\n\n const splitFee = this.splitFee({ totalFee, protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n\n return { amountA: getTransferAmountFeeFromPost(amountA, transferFeeConfigA, slot), amountB, splitFee };\n }\n\n static splitFee({\n totalFee,\n protocolFeeRate,\n platformFeeRate,\n shareFeeRate,\n creatorFeeRate,\n }: {\n totalFee: BN;\n protocolFeeRate: BN;\n platformFeeRate: BN;\n shareFeeRate: BN;\n creatorFeeRate: BN;\n }): { platformFee: BN; shareFee: BN; protocolFee: BN; creatorFee: BN } {\n const totalFeeRate = this.totalFeeRate({ protocolFeeRate, platformFeeRate, shareFeeRate, creatorFeeRate });\n const platformFee = totalFeeRate.isZero() ? new BN(0) : totalFee.mul(platformFeeRate).div(totalFeeRate);\n const shareFee = totalFeeRate.isZero() ? new BN(0) : totalFee.mul(shareFeeRate).div(totalFeeRate);\n const creatorFee = totalFeeRate.isZero() ? new BN(0) : totalFee.mul(creatorFeeRate).div(totalFeeRate);\n\n const protocolFee = totalFee.sub(platformFee).sub(shareFee).sub(creatorFee);\n\n return { platformFee, shareFee, protocolFee, creatorFee };\n }\n\n static calculateFee({ amount, feeRate }: { amount: BN; feeRate: BN }): BN {\n return ceilDiv(amount, feeRate, FEE_RATE_DENOMINATOR_VALUE);\n }\n static calculatePreFee({ postFeeAmount, feeRate }: { postFeeAmount: BN; feeRate: BN }): BN {\n if (feeRate.isZero()) return postFeeAmount;\n\n const numerator = postFeeAmount.mul(FEE_RATE_DENOMINATOR_VALUE);\n const denominator = FEE_RATE_DENOMINATOR_VALUE.sub(feeRate);\n\n return numerator.add(denominator).sub(new BN(1)).div(denominator);\n }\n\n static totalFeeRate({\n protocolFeeRate,\n platformFeeRate,\n shareFeeRate,\n creatorFeeRate,\n }: {\n protocolFeeRate: BN;\n platformFeeRate: BN;\n shareFeeRate: BN;\n creatorFeeRate: BN;\n }): BN {\n const totalFeeRate = protocolFeeRate.add(platformFeeRate).add(shareFeeRate).add(creatorFeeRate);\n if (totalFeeRate.gt(new BN(1_000_000))) throw Error(\"total fee rate gt 1_000_000\");\n return protocolFeeRate.add(platformFeeRate).add(shareFeeRate).add(creatorFeeRate);\n }\n\n static getCurve(curveType: number): typeof CurveBase {\n switch (curveType) {\n case 0:\n return LaunchConstantProductCurve;\n case 1:\n return FixedPriceCurve;\n case 2:\n return LinearPriceCurve;\n }\n throw Error(\"find curve error\");\n }\n}\n","import { AccountInfo, Commitment, Connection, PublicKey } from \"@solana/web3.js\";\nimport { ReturnTypeFetchMultipleMintInfos } from \"../raydium/type\";\nimport { WSOLMint, chunkArray, solToWSol } from \"./\";\nimport { createLogger } from \"./logger\";\nimport { MINT_SIZE, TOKEN_PROGRAM_ID, getTransferFeeConfig, unpackMint } from \"@solana/spl-token\";\n\ninterface MultipleAccountsJsonRpcResponse {\n jsonrpc: string;\n id: string;\n error?: {\n code: number;\n message: string;\n };\n result: {\n context: { slot: number };\n value: { data: Array<string>; executable: boolean; lamports: number; owner: string; rentEpoch: number }[];\n };\n}\n\nexport interface GetMultipleAccountsInfoConfig {\n batchRequest?: boolean;\n commitment?: Commitment;\n chunkCount?: number;\n}\n\nconst logger = createLogger(\"Raydium_accountInfo_util\");\n\nexport async function getMultipleAccountsInfo(\n connection: Connection,\n publicKeys: PublicKey[],\n config?: GetMultipleAccountsInfoConfig,\n): Promise<(AccountInfo<Buffer> | null)[]> {\n const {\n batchRequest,\n commitment = \"confirmed\",\n chunkCount = 100,\n } = {\n batchRequest: false,\n ...config,\n };\n\n const chunkedKeys = chunkArray(publicKeys, chunkCount);\n let results: (AccountInfo<Buffer> | null)[][] = new Array(chunkedKeys.length).fill([]);\n\n if (batchRequest) {\n const batch = chunkedKeys.map((keys) => {\n const args = connection._buildArgs([keys.map((key) => key.toBase58())], commitment, \"base64\");\n return {\n methodName: \"getMultipleAccounts\",\n args,\n };\n });\n\n const _batch = chunkArray(batch, 10);\n\n const unsafeResponse: MultipleAccountsJsonRpcResponse[] = await (\n await Promise.all(_batch.map(async (i) => await (connection as any)._rpcBatchRequest(i)))\n ).flat();\n results = unsafeResponse.map((unsafeRes: MultipleAccountsJsonRpcResponse) => {\n if (unsafeRes.error)\n logger.logWithError(`failed to get info for multiple accounts, RPC_ERROR, ${unsafeRes.error.message}`);\n\n return unsafeRes.result.value.map((accountInfo) => {\n if (accountInfo) {\n const { data, executable, lamports, owner, rentEpoch } = accountInfo;\n\n if (data.length !== 2 && data[1] !== \"base64\") logger.logWithError(`info must be base64 encoded, RPC_ERROR`);\n\n return {\n data: Buffer.from(data[0], \"base64\"),\n executable,\n lamports,\n owner: new PublicKey(owner),\n rentEpoch,\n };\n }\n return null;\n });\n });\n } else {\n try {\n results = (await Promise.all(\n chunkedKeys.map((keys) => connection.getMultipleAccountsInfo(keys, commitment)),\n )) as (AccountInfo<Buffer> | null)[][];\n } catch (error) {\n if (error instanceof Error) {\n logger.logWithError(`failed to get info for multiple accounts, RPC_ERROR, ${error.message}`);\n }\n }\n }\n\n return results.flat();\n}\n\nexport async function getMultipleAccountsInfoWithCustomFlags<T extends { pubkey: PublicKey }>(\n connection: Connection,\n publicKeysWithCustomFlag: T[],\n config?: GetMultipleAccountsInfoConfig,\n): Promise<({ accountInfo: AccountInfo<Buffer> | null } & T)[]> {\n const multipleAccountsInfo = await getMultipleAccountsInfo(\n connection,\n publicKeysWithCustomFlag.map((o) => o.pubkey),\n config,\n );\n\n return publicKeysWithCustomFlag.map((o, idx) => ({ ...o, accountInfo: multipleAccountsInfo[idx] }));\n}\n\nexport enum AccountType {\n Uninitialized,\n Mint,\n Account,\n}\nexport const ACCOUNT_TYPE_SIZE = 1;\n\nexport async function fetchMultipleMintInfos({\n connection,\n mints,\n config,\n}: {\n connection: Connection;\n mints: PublicKey[];\n config?: { batchRequest?: boolean };\n}): Promise<ReturnTypeFetchMultipleMintInfos> {\n if (mints.length === 0) return {};\n const mintInfos = await getMultipleAccountsInfoWithCustomFlags(\n connection,\n mints.map((i) => ({ pubkey: solToWSol(i) })),\n config,\n );\n\n const mintK: ReturnTypeFetchMultipleMintInfos = {};\n for (const i of mintInfos) {\n if (!i.accountInfo || i.accountInfo.data.length < MINT_SIZE) {\n console.log(\"invalid mint account\", i.pubkey.toBase58());\n continue;\n }\n const t = unpackMint(i.pubkey, i.accountInfo, i.accountInfo?.owner);\n mintK[i.pubkey.toString()] = {\n ...t,\n programId: i.accountInfo?.owner || TOKEN_PROGRAM_ID,\n feeConfig: getTransferFeeConfig(t) ?? undefined,\n };\n }\n mintK[PublicKey.default.toBase58()] = mintK[WSOLMint.toBase58()];\n\n return mintK;\n}\n","import { get, set } from \"lodash\";\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 Date.now().toString();\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 BN from \"bn.js\";\nimport Decimal from \"decimal.js\";\nimport { CurrencyAmount, TokenAmount } from \"../module/amount\";\nimport { Currency } from \"../module/currency\";\nimport { Fraction } from \"../module/fraction\";\nimport { Percent } from \"../module/percent\";\nimport { Price } from \"../module/price\";\nimport { Token } from \"../module/token\";\nimport { SplToken, TokenJson } from \"../raydium/token/type\";\nimport { parseBigNumberish } from \"./constant\";\nimport { mul } from \"./fractionUtil\";\nimport { BN_ZERO } from \"@/raydium\";\n\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\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 // wrap to Fraction\n const n = String(value);\n const details = parseNumberInfo(n);\n return new Fraction(details.numerator, details.denominator);\n}\n\nexport function ceilDiv(tokenAmount: BN, feeNumerator: BN, feeDenominator: BN): BN {\n return tokenAmount.mul(feeNumerator).add(feeDenominator).sub(new BN(1)).div(feeDenominator);\n}\n\nexport function floorDiv(tokenAmount: BN, feeNumerator: BN, feeDenominator: BN): BN {\n return tokenAmount.mul(feeNumerator).div(feeDenominator);\n}\n\n/**\n * @example\n * toPercent(3.14) // => Percent { 314.00% }\n * toPercent(3.14, { alreadyDecimaled: true }) // => Percent {3.14%}\n */\nexport function toPercent(\n n: Numberish,\n options?: { /* usually used for backend data */ alreadyDecimaled?: boolean },\n): Percent {\n const { numerator, denominator } = parseNumberInfo(n);\n return new Percent(new BN(numerator), new BN(denominator).mul(options?.alreadyDecimaled ? new BN(100) : new BN(1)));\n}\n\nexport function toTokenPrice(params: {\n token: TokenJson | Token | SplToken;\n numberPrice: Numberish;\n decimalDone?: boolean;\n}): Price {\n const { token, numberPrice, decimalDone } = params;\n const usdCurrency = new Token({ mint: \"\", decimals: 6, symbol: \"usd\", name: \"usd\", skipMint: true });\n const { numerator, denominator } = parseNumberInfo(numberPrice);\n const parsedNumerator = decimalDone ? new BN(numerator).mul(BN_TEN.pow(new BN(token.decimals))) : numerator;\n const parsedDenominator = new BN(denominator).mul(BN_TEN.pow(new BN(usdCurrency.decimals)));\n\n return new Price({\n baseToken: usdCurrency,\n denominator: parsedDenominator.toString(),\n quoteToken: new Token({ ...token, skipMint: true, mint: \"\" }),\n numerator: parsedNumerator.toString(),\n });\n}\n\nexport function toUsdCurrency(amount: Numberish): CurrencyAmount {\n const usdCurrency = new Currency({ decimals: 6, symbol: \"usd\", name: \"usd\" });\n const amountBigNumber = toBN(mul(amount, 10 ** usdCurrency.decimals)!);\n return new CurrencyAmount(usdCurrency, amountBigNumber);\n}\n\nexport function toTotalPrice(amount: Numberish | undefined, price: Price | undefined): CurrencyAmount {\n if (!price || !amount) return toUsdCurrency(0);\n return toUsdCurrency(mul(amount, price)!);\n}\n\nexport function decimalToFraction(n: Decimal | undefined): Fraction | undefined {\n if (n == null) return undefined;\n const { numerator, denominator } = parseNumberInfo(n.toString());\n return new Fraction(numerator, denominator);\n}\n\nexport function isDecimal(val: unknown): boolean {\n return val instanceof Decimal;\n}\n\n// export function recursivelyDecimalToFraction<T>(info: T): ReplaceType<T, Decimal, Fraction> {\n// // @ts-expect-error no need type for inner code\n// return isDecimal(info)\n// ? decimalToFraction(info as any)\n// : Array.isArray(info)\n// ? info.map((k) => recursivelyDecimalToFraction(k))\n// : notInnerObject(info)\n// ? Object.fromEntries(Object.entries(info as any).map(([k, v]) => [k, recursivelyDecimalToFraction(v)]))\n// : info;\n// }\n","import _Big from \"big.js\";\nimport BN from \"bn.js\";\n\nimport { BigNumberish, BN_TEN } from \"../common/bignumber\";\nimport { createLogger, Logger } from \"../common/logger\";\n\nimport { parseBigNumberish, Rounding } from \"../common\";\nimport { Currency } from \"./currency\";\nimport toFormat, { WrappedBig } from \"./formatter\";\nimport { Fraction } from \"./fraction\";\nimport { Token } from \"./token\";\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 Big, { BigConstructor, BigSource, RoundingMode } from \"big.js\";\nimport Decimal, { Config, Numeric } from \"decimal.js-light\";\nimport _toFarmat from \"toformat\";\n\ntype TakeStatic<T> = { [P in keyof T]: T[P] };\ninterface FormatOptions {\n decimalSeparator?: string;\n groupSeparator?: string;\n groupSize?: number;\n fractionGroupSeparator?: string;\n fractionGroupSize?: number;\n}\ninterface WrappedBigConstructor extends TakeStatic<BigConstructor> {\n new (value: BigSource): WrappedBig;\n (value: BigSource): WrappedBig;\n (): WrappedBigConstructor;\n\n format: FormatOptions;\n}\nexport interface WrappedBig extends Big {\n add(n: BigSource): WrappedBig;\n abs(): WrappedBig;\n div(n: BigSource): WrappedBig;\n minus(n: BigSource): WrappedBig;\n mod(n: BigSource): WrappedBig;\n mul(n: BigSource): WrappedBig;\n plus(n: BigSource): WrappedBig;\n pow(exp: number): WrappedBig;\n round(dp?: number, rm?: RoundingMode): WrappedBig;\n sqrt(): WrappedBig;\n sub(n: BigSource): WrappedBig;\n times(n: BigSource): WrappedBig;\n toFormat(): string;\n toFormat(options: FormatOptions): string;\n toFormat(fractionLength: number): string;\n toFormat(fractionLength: number, options: FormatOptions): string;\n toFormat(fractionLength: number, missionUnknown: number): string;\n toFormat(fractionLength: number, missionUnknown: number, options: FormatOptions): string;\n}\n\ntype DecimalConstructor = typeof Decimal;\ninterface WrappedDecimalConstructor extends TakeStatic<DecimalConstructor> {\n new (value: Numeric): WrappedDecimal;\n clone(config?: Config): WrappedDecimalConstructor;\n config(config: Config): WrappedDecimal;\n set(config: Config): WrappedDecimal;\n format: FormatOptions;\n}\nexport interface WrappedDecimal extends Decimal {\n absoluteValue(): WrappedDecimal;\n abs(): WrappedDecimal;\n dividedBy(y: Numeric): WrappedDecimal;\n div(y: Numeric): WrappedDecimal;\n dividedToIntegerBy(y: Numeric): WrappedDecimal;\n idiv(y: Numeric): WrappedDecimal;\n logarithm(base?: Numeric): WrappedDecimal;\n log(base?: Numeric): WrappedDecimal;\n minus(y: Numeric): WrappedDecimal;\n sub(y: Numeric): WrappedDecimal;\n modulo(y: Numeric): WrappedDecimal;\n mod(y: Numeric): WrappedDecimal;\n naturalExponetial(): WrappedDecimal;\n exp(): WrappedDecimal;\n naturalLogarithm(): WrappedDecimal;\n ln(): WrappedDecimal;\n negated(): WrappedDecimal;\n neg(): WrappedDecimal;\n plus(y: Numeric): WrappedDecimal;\n add(y: Numeric): WrappedDecimal;\n squareRoot(): WrappedDecimal;\n sqrt(): WrappedDecimal;\n times(y: Numeric): WrappedDecimal;\n mul(y: Numeric): WrappedDecimal;\n toWrappedDecimalPlaces(dp?: number, rm?: number): WrappedDecimal;\n todp(dp?: number, rm?: number): WrappedDecimal;\n toInteger(): WrappedDecimal;\n toint(): WrappedDecimal;\n toPower(y: Numeric): WrappedDecimal;\n pow(y: Numeric): WrappedDecimal;\n toSignificantDigits(sd?: number, rm?: number): WrappedDecimal;\n tosd(sd?: number, rm?: number): WrappedDecimal;\n toFormat(options: FormatOptions): string;\n toFormat(fractionLength: number): string;\n toFormat(fractionLength: number, options: FormatOptions): string;\n toFormat(fractionLength: number, missionUnknown: number): string;\n toFormat(fractionLength: number, missionUnknown: number, options: FormatOptions): string;\n}\n\nconst toFormat: {\n (fn: BigConstructor): WrappedBigConstructor;\n (fn: DecimalConstructor): WrappedDecimalConstructor;\n} = _toFarmat;\nexport default toFormat;\n","import _Big from \"big.js\";\nimport BN from \"bn.js\";\nimport _Decimal from \"decimal.js-light\";\n\nimport { BigNumberish } from \"../common/bignumber\";\nimport { createLogger } from \"../common/logger\";\n\nimport { parseBigNumberish, Rounding } from \"../common/constant\";\nimport toFormat, { WrappedBig } from \"./formatter\";\n\nconst logger = createLogger(\"module/fraction\");\n\nconst Big = toFormat(_Big);\ntype Big = WrappedBig;\n\nconst Decimal = toFormat(_Decimal);\n\nconst toSignificantRounding = {\n [Rounding.ROUND_DOWN]: Decimal.ROUND_DOWN,\n [Rounding.ROUND_HALF_UP]: Decimal.ROUND_HALF_UP,\n [Rounding.ROUND_UP]: Decimal.ROUND_UP,\n};\n\nconst toFixedRounding = {\n [Rounding.ROUND_DOWN]: _Big.roundDown,\n [Rounding.ROUND_HALF_UP]: _Big.roundHalfUp,\n [Rounding.ROUND_UP]: _Big.roundUp,\n};\n\nexport class Fraction {\n public readonly numerator: BN;\n public readonly denominator: BN;\n\n public constructor(numerator: BigNumberish, denominator: BigNumberish = new BN(1)) {\n this.numerator = parseBigNumberish(numerator);\n this.denominator = parseBigNumberish(denominator);\n }\n\n public get quotient(): BN {\n return this.numerator.div(this.denominator);\n }\n\n public invert(): Fraction {\n return new Fraction(this.denominator, this.numerator);\n }\n\n public add(other: Fraction | BigNumberish): Fraction {\n const otherParsed = other instanceof Fraction ? other : new Fraction(parseBigNumberish(other));\n\n if (this.denominator.eq(otherParsed.denominator)) {\n return new Fraction(this.numerator.add(otherParsed.numerator), this.denominator);\n }\n\n return new Fraction(\n this.numerator.mul(otherParsed.denominator).add(otherParsed.numerator.mul(this.denominator)),\n this.denominator.mul(otherParsed.denominator),\n );\n }\n\n public sub(other: Fraction | BigNumberish): Fraction {\n const otherParsed = other instanceof Fraction ? other : new Fraction(parseBigNumberish(other));\n\n if (this.denominator.eq(otherParsed.denominator)) {\n return new Fraction(this.numerator.sub(otherParsed.numerator), this.denominator);\n }\n\n return new Fraction(\n this.numerator.mul(otherParsed.denominator).sub(otherParsed.numerator.mul(this.denominator)),\n this.denominator.mul(otherParsed.denominator),\n );\n }\n\n public mul(other: Fraction | BigNumberish): Fraction {\n const otherParsed = other instanceof Fraction ? other : new Fraction(parseBigNumberish(other));\n\n return new Fraction(this.numerator.mul(otherParsed.numerator), this.denominator.mul(otherParsed.denominator));\n }\n\n public div(other: Fraction | BigNumberish): Fraction {\n const otherParsed = other instanceof Fraction ? other : new Fraction(parseBigNumberish(other));\n\n return new Fraction(this.numerator.mul(otherParsed.denominator), this.denominator.mul(otherParsed.numerator));\n }\n\n public toSignificant(\n significantDigits: number,\n format: object = { groupSeparator: \"\" },\n rounding: Rounding = Rounding.ROUND_HALF_UP,\n ): string {\n if (!Number.isInteger(significantDigits)) logger.logWithError(`${significantDigits} is not an integer.`);\n if (significantDigits <= 0) logger.logWithError(`${significantDigits} is not positive.`);\n\n Decimal.set({ precision: significantDigits + 1, rounding: toSignificantRounding[rounding] });\n const quotient = new Decimal(this.numerator.toString())\n .div(this.denominator.toString())\n .toSignificantDigits(significantDigits);\n return quotient.toFormat(quotient.decimalPlaces(), format);\n }\n\n public toFixed(\n decimalPlaces: number,\n format: object = { groupSeparator: \"\" },\n rounding: Rounding = Rounding.ROUND_HALF_UP,\n ): string {\n if (!Number.isInteger(decimalPlaces)) logger.logWithError(`${decimalPlaces} is not an integer.`);\n if (decimalPlaces < 0) logger.logWithError(`${decimalPlaces} is negative.`);\n\n Big.DP = decimalPlaces;\n Big.RM = toFixedRounding[rounding] || 1;\n return new Big(this.numerator.toString()).div(this.denominator.toString()).toFormat(decimalPlaces, format);\n }\n\n public isZero(): boolean {\n return this.numerator.isZero();\n }\n}\n","import BN from \"bn.js\";\nimport { BigNumberish } from \"./bignumber\";\nimport { createLogger } from \"./logger\";\n\nexport enum Rounding {\n ROUND_DOWN,\n ROUND_HALF_UP,\n ROUND_UP,\n}\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}","import { PublicKey } from \"@solana/web3.js\";\nimport { TOKEN_PROGRAM_ID } from \"@solana/spl-token\";\nimport { TokenInfo } from \"./type\";\n\nexport const SOL_INFO: TokenInfo = {\n chainId: 101,\n address: PublicKey.default.toBase58(),\n programId: TOKEN_PROGRAM_ID.toBase58(),\n decimals: 9,\n symbol: \"SOL\",\n name: \"solana\",\n logoURI: `https://img-v1.raydium.io/icon/So11111111111111111111111111111111111111112.png`,\n tags: [],\n priority: 2,\n type: \"raydium\",\n extensions: {\n coingeckoId: \"solana\",\n },\n};\n\nexport const TOKEN_WSOL: TokenInfo = {\n chainId: 101,\n address: \"So11111111111111111111111111