UNPKG

@raydium-io/raydium-sdk-v2

Version:

An SDK for building applications on top of Raydium.

1 lines 386 kB
{"version":3,"sources":["../../../src/raydium/account/account.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/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","../../../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"],"sourcesContent":["import {\n createAssociatedTokenAccountInstruction,\n TOKEN_PROGRAM_ID,\n AccountLayout,\n TOKEN_2022_PROGRAM_ID,\n} from \"@solana/spl-token\";\nimport { Commitment, PublicKey, SystemProgram, TransactionInstruction } from \"@solana/web3.js\";\nimport { getATAAddress, BigNumberish, InstructionType, WSOLMint } from \"@/common\";\nimport { AddInstructionParam } from \"@/common/txTool/txTool\";\n\nimport ModuleBase, { ModuleBaseProps } from \"../moduleBase\";\nimport {\n closeAccountInstruction,\n createWSolAccountInstructions,\n makeTransferInstruction,\n initTokenAccountInstruction,\n} from \"./instruction\";\nimport { HandleTokenAccountParams, TokenAccount, TokenAccountRaw, GetOrCreateTokenAccountParams } from \"./types\";\nimport { parseTokenAccountResp, generatePubKey } from \"./util\";\n\nexport interface TokenAccountDataProp {\n tokenAccounts?: TokenAccount[];\n tokenAccountRawInfos?: TokenAccountRaw[];\n}\nexport default class Account extends ModuleBase {\n private _tokenAccounts: TokenAccount[] = [];\n private _tokenAccountRawInfos: TokenAccountRaw[] = [];\n private _accountChangeListenerId?: number;\n private _accountListener: ((data: TokenAccountDataProp) => void)[] = [];\n private _clientOwnedToken = false;\n private _accountFetchTime = 0;\n\n constructor(params: TokenAccountDataProp & ModuleBaseProps) {\n super(params);\n const { tokenAccounts, tokenAccountRawInfos } = params;\n this._tokenAccounts = tokenAccounts || [];\n this._tokenAccountRawInfos = tokenAccountRawInfos || [];\n this._clientOwnedToken = !!(tokenAccounts || tokenAccountRawInfos);\n }\n\n get tokenAccounts(): TokenAccount[] {\n return this._tokenAccounts;\n }\n get tokenAccountRawInfos(): TokenAccountRaw[] {\n return this._tokenAccountRawInfos;\n }\n\n public updateTokenAccount({ tokenAccounts, tokenAccountRawInfos }: TokenAccountDataProp): Account {\n if (tokenAccounts) this._tokenAccounts = tokenAccounts;\n if (tokenAccountRawInfos) this._tokenAccountRawInfos = tokenAccountRawInfos;\n this._accountChangeListenerId && this.scope.connection.removeAccountChangeListener(this._accountChangeListenerId);\n this._accountChangeListenerId = undefined;\n this._clientOwnedToken = true;\n return this;\n }\n\n public addAccountChangeListener(cbk: (data: TokenAccountDataProp) => void): Account {\n this._accountListener.push(cbk);\n return this;\n }\n\n public removeAccountChangeListener(cbk: (data: TokenAccountDataProp) => void): Account {\n this._accountListener = this._accountListener.filter((listener) => listener !== cbk);\n return this;\n }\n\n public getAssociatedTokenAccount(mint: PublicKey, programId?: PublicKey): PublicKey {\n return getATAAddress(this.scope.ownerPubKey, mint, programId).publicKey;\n }\n\n public resetTokenAccounts(): void {\n if (this._clientOwnedToken) return;\n this._tokenAccounts = [];\n this._tokenAccountRawInfos = [];\n }\n\n public async fetchWalletTokenAccounts(config?: { forceUpdate?: boolean; commitment?: Commitment }): Promise<{\n tokenAccounts: TokenAccount[];\n tokenAccountRawInfos: TokenAccountRaw[];\n }> {\n if (\n this._clientOwnedToken ||\n (!config?.forceUpdate && this._tokenAccounts.length && Date.now() - this._accountFetchTime < 1000 * 60 * 3)\n ) {\n return {\n tokenAccounts: this._tokenAccounts,\n tokenAccountRawInfos: this._tokenAccountRawInfos,\n };\n }\n this.scope.checkOwner();\n\n const defaultConfig = {};\n const customConfig = { ...defaultConfig, ...config };\n\n const [solAccountResp, ownerTokenAccountResp, ownerToken2022AccountResp] = await Promise.all([\n this.scope.connection.getAccountInfo(this.scope.ownerPubKey, customConfig.commitment),\n this.scope.connection.getTokenAccountsByOwner(\n this.scope.ownerPubKey,\n { programId: TOKEN_PROGRAM_ID },\n customConfig.commitment,\n ),\n this.scope.connection.getTokenAccountsByOwner(\n this.scope.ownerPubKey,\n { programId: TOKEN_2022_PROGRAM_ID },\n customConfig.commitment,\n ),\n ]);\n\n const { tokenAccounts, tokenAccountRawInfos } = parseTokenAccountResp({\n owner: this.scope.ownerPubKey,\n solAccountResp,\n tokenAccountResp: {\n context: ownerTokenAccountResp.context,\n value: [...ownerTokenAccountResp.value, ...ownerToken2022AccountResp.value],\n },\n });\n\n this._tokenAccounts = tokenAccounts;\n this._tokenAccountRawInfos = tokenAccountRawInfos;\n\n this._accountFetchTime = Date.now();\n\n this._accountChangeListenerId && this.scope.connection.removeAccountChangeListener(this._accountChangeListenerId);\n this._accountChangeListenerId = this.scope.connection.onAccountChange(\n this.scope.ownerPubKey,\n () => this.fetchWalletTokenAccounts({ forceUpdate: true }),\n config?.commitment,\n );\n\n return { tokenAccounts, tokenAccountRawInfos };\n }\n\n // user token account needed, old _selectTokenAccount\n public async getCreatedTokenAccount({\n mint,\n programId = TOKEN_PROGRAM_ID,\n associatedOnly = true,\n }: {\n mint: PublicKey;\n programId?: PublicKey;\n associatedOnly?: boolean;\n }): Promise<PublicKey | undefined> {\n await this.fetchWalletTokenAccounts();\n const tokenAccounts = this._tokenAccounts\n .filter(({ mint: accountMint }) => accountMint?.equals(mint))\n // sort by balance\n .sort((a, b) => (a.amount.lt(b.amount) ? 1 : -1));\n\n const ata = this.getAssociatedTokenAccount(mint, programId);\n for (const tokenAccount of tokenAccounts) {\n const { publicKey } = tokenAccount;\n if (publicKey) {\n if (!associatedOnly || (associatedOnly && ata.equals(publicKey))) return publicKey;\n }\n }\n }\n\n // old _selectOrCreateTokenAccount\n public async getOrCreateTokenAccount(params: GetOrCreateTokenAccountParams): Promise<{\n account?: PublicKey;\n instructionParams?: AddInstructionParam;\n }> {\n await this.fetchWalletTokenAccounts();\n const {\n mint,\n createInfo,\n associatedOnly,\n owner,\n notUseTokenAccount = false,\n skipCloseAccount = false,\n checkCreateATAOwner = false,\n } = params;\n const tokenProgram = new PublicKey(params.tokenProgram || TOKEN_PROGRAM_ID);\n const ata = this.getAssociatedTokenAccount(mint, new PublicKey(tokenProgram));\n const accounts = (notUseTokenAccount ? [] : this.tokenAccountRawInfos)\n .filter((i) => i.accountInfo.mint.equals(mint) && (!associatedOnly || i.pubkey.equals(ata)))\n .sort((a, b) => (a.accountInfo.amount.lt(b.accountInfo.amount) ? 1 : -1));\n // find token or don't need create\n if (createInfo === undefined || accounts.length > 0) {\n return accounts.length > 0 ? { account: accounts[0].pubkey } : {};\n }\n\n const newTxInstructions: AddInstructionParam = {\n instructions: [],\n endInstructions: [],\n signers: [],\n instructionTypes: [],\n endInstructionTypes: [],\n };\n\n if (associatedOnly) {\n const _createATAIns = createAssociatedTokenAccountInstruction(owner, ata, owner, mint, tokenProgram);\n if (checkCreateATAOwner) {\n const ataInfo = await this.scope.connection.getAccountInfo(ata);\n if (ataInfo === null) {\n newTxInstructions.instructions?.push(_createATAIns);\n newTxInstructions.instructionTypes!.push(InstructionType.CreateATA);\n } else if (\n ataInfo.owner.equals(tokenProgram) &&\n AccountLayout.decode(ataInfo.data).mint.equals(mint) &&\n AccountLayout.decode(ataInfo.data).owner.equals(owner)\n ) {\n /* empty */\n } else {\n throw Error(`create ata check error -> mint: ${mint.toString()}, ata: ${ata.toString()}`);\n }\n } else {\n newTxInstructions.instructions!.push(_createATAIns);\n newTxInstructions.instructionTypes!.push(InstructionType.CreateATA);\n }\n if (mint.equals(WSOLMint) && createInfo.amount) {\n const txInstruction = await createWSolAccountInstructions({\n connection: this.scope.connection,\n owner: this.scope.ownerPubKey,\n payer: createInfo.payer || this.scope.ownerPubKey,\n amount: createInfo.amount ?? 0,\n skipCloseAccount,\n });\n newTxInstructions.instructions!.push(...(txInstruction.instructions || []));\n newTxInstructions.endInstructions!.push(...(txInstruction.endInstructions || []));\n newTxInstructions.instructionTypes!.push(...(txInstruction.instructionTypes || []));\n newTxInstructions.endInstructionTypes!.push(...(txInstruction.endInstructionTypes || []));\n\n if (createInfo.amount) {\n newTxInstructions.instructions!.push(\n makeTransferInstruction({\n source: txInstruction.addresses.newAccount,\n destination: ata,\n owner: this.scope.ownerPubKey,\n amount: createInfo.amount,\n tokenProgram: TOKEN_PROGRAM_ID,\n }),\n );\n newTxInstructions.instructionTypes!.push(InstructionType.TransferAmount);\n }\n }\n\n if (!skipCloseAccount) {\n newTxInstructions.endInstructions!.push(\n closeAccountInstruction({\n owner,\n payer: createInfo.payer || owner,\n tokenAccount: ata,\n programId: tokenProgram,\n }),\n );\n newTxInstructions.endInstructionTypes!.push(InstructionType.CloseAccount);\n }\n\n return { account: ata, instructionParams: newTxInstructions };\n } else {\n // if (mint.equals(WSOLMint)) {\n // const txInstruction = await createWSolAccountInstructions({\n // connection: this.scope.connection,\n // owner: this.scope.ownerPubKey,\n // payer: createInfo.payer || this.scope.ownerPubKey,\n // amount: createInfo.amount ?? 0,\n // skipCloseAccount,\n // });\n // newTxInstructions.instructions!.push(...(txInstruction.instructions || []));\n // newTxInstructions.endInstructions!.push(...(txInstruction.endInstructions || []));\n // newTxInstructions.signers!.push(...(txInstruction.signers || []));\n // newTxInstructions.instructionTypes!.push(...(txInstruction.instructionTypes || []));\n // newTxInstructions.endInstructionTypes!.push(...(txInstruction.endInstructionTypes || []));\n\n // return { account: txInstruction.addresses.newAccount, instructionParams: newTxInstructions };\n // } else {\n const newTokenAccount = generatePubKey({ fromPublicKey: owner, programId: tokenProgram });\n const balanceNeeded = await this.scope.connection.getMinimumBalanceForRentExemption(AccountLayout.span);\n\n const createAccountIns = SystemProgram.createAccountWithSeed({\n fromPubkey: owner,\n basePubkey: owner,\n seed: newTokenAccount.seed,\n newAccountPubkey: newTokenAccount.publicKey,\n lamports: balanceNeeded + Number(createInfo.amount?.toString() ?? 0),\n space: AccountLayout.span,\n programId: tokenProgram,\n });\n\n newTxInstructions.instructions!.push(\n createAccountIns,\n initTokenAccountInstruction({\n mint,\n tokenAccount: newTokenAccount.publicKey,\n owner: this.scope.ownerPubKey,\n programId: tokenProgram,\n }),\n );\n newTxInstructions.instructionTypes!.push(InstructionType.CreateAccount);\n newTxInstructions.instructionTypes!.push(InstructionType.InitAccount);\n if (!skipCloseAccount) {\n newTxInstructions.endInstructions!.push(\n closeAccountInstruction({\n owner,\n payer: createInfo.payer || owner,\n tokenAccount: newTokenAccount.publicKey,\n programId: tokenProgram,\n }),\n );\n newTxInstructions.endInstructionTypes!.push(InstructionType.CloseAccount);\n }\n return { account: newTokenAccount.publicKey, instructionParams: newTxInstructions };\n }\n // }\n }\n\n public async checkOrCreateAta({\n mint,\n programId = TOKEN_PROGRAM_ID,\n autoUnwrapWSOLToSOL,\n }: {\n mint: PublicKey;\n programId?: PublicKey;\n autoUnwrapWSOLToSOL?: boolean;\n }): Promise<{ pubKey: PublicKey; newInstructions: AddInstructionParam }> {\n await this.fetchWalletTokenAccounts();\n let tokenAccountAddress = this.scope.account.tokenAccounts.find(\n ({ mint: accountTokenMint }) => accountTokenMint?.toBase58() === mint.toBase58(),\n )?.publicKey;\n\n const owner = this.scope.ownerPubKey;\n const newTxInstructions: AddInstructionParam = {};\n\n if (!tokenAccountAddress) {\n const ataAddress = this.getAssociatedTokenAccount(mint, programId);\n const instruction = await createAssociatedTokenAccountInstruction(owner, ataAddress, owner, mint, programId);\n newTxInstructions.instructions = [instruction];\n newTxInstructions.instructionTypes = [InstructionType.CreateATA];\n tokenAccountAddress = ataAddress;\n }\n if (autoUnwrapWSOLToSOL && WSOLMint.toBase58() === mint.toBase58()) {\n newTxInstructions.endInstructions = [\n closeAccountInstruction({ owner, payer: owner, tokenAccount: tokenAccountAddress, programId }),\n ];\n newTxInstructions.endInstructionTypes = [InstructionType.CloseAccount];\n }\n\n return {\n pubKey: tokenAccountAddress,\n newInstructions: newTxInstructions,\n };\n }\n\n // old _handleTokenAccount\n public async handleTokenAccount(\n params: HandleTokenAccountParams,\n ): Promise<AddInstructionParam & { tokenAccount: PublicKey }> {\n const {\n side,\n amount,\n mint,\n programId = TOKEN_PROGRAM_ID,\n tokenAccount,\n payer = this.scope.ownerPubKey,\n bypassAssociatedCheck,\n skipCloseAccount,\n checkCreateATAOwner,\n } = params;\n\n const ata = this.getAssociatedTokenAccount(mint, programId);\n\n if (new PublicKey(WSOLMint).equals(mint)) {\n const txInstruction = await createWSolAccountInstructions({\n connection: this.scope.connection,\n owner: this.scope.ownerPubKey,\n payer,\n amount,\n skipCloseAccount,\n });\n return { tokenAccount: txInstruction.addresses.newAccount, ...txInstruction };\n } else if (!tokenAccount || (side === \"out\" && !ata.equals(tokenAccount) && !bypassAssociatedCheck)) {\n const instructions: TransactionInstruction[] = [];\n const _createATAIns = createAssociatedTokenAccountInstruction(\n this.scope.ownerPubKey,\n ata,\n this.scope.ownerPubKey,\n mint,\n programId,\n );\n\n if (checkCreateATAOwner) {\n const ataInfo = await this.scope.connection.getAccountInfo(ata);\n if (ataInfo === null) {\n instructions.push(_createATAIns);\n } else if (\n ataInfo.owner.equals(TOKEN_PROGRAM_ID) &&\n AccountLayout.decode(ataInfo.data).mint.equals(mint) &&\n AccountLayout.decode(ataInfo.data).owner.equals(this.scope.ownerPubKey)\n ) {\n /* empty */\n } else {\n throw Error(`create ata check error -> mint: ${mint.toString()}, ata: ${ata.toString()}`);\n }\n } else {\n instructions.push(_createATAIns);\n }\n\n return {\n tokenAccount: ata,\n instructions,\n instructionTypes: [InstructionType.CreateATA],\n };\n }\n\n return { tokenAccount };\n }\n\n public async processTokenAccount(props: {\n mint: PublicKey;\n programId?: PublicKey;\n amount?: BigNumberish;\n useSOLBalance?: boolean;\n handleTokenAccount?: boolean;\n }): Promise<Promise<AddInstructionParam & { tokenAccount?: PublicKey }>> {\n const { mint, programId = TOKEN_PROGRAM_ID, amount, useSOLBalance, handleTokenAccount } = props;\n let tokenAccount: PublicKey | undefined;\n const txBuilder = this.createTxBuilder();\n\n if (mint.equals(new PublicKey(WSOLMint)) && useSOLBalance) {\n // mintA\n const { tokenAccount: _tokenAccount, ...instructions } = await this.handleTokenAccount({\n side: \"in\",\n amount: amount || 0,\n mint,\n bypassAssociatedCheck: true,\n programId,\n });\n tokenAccount = _tokenAccount;\n txBuilder.addInstruction(instructions);\n } else {\n tokenAccount = await this.getCreatedTokenAccount({\n mint,\n associatedOnly: false,\n programId,\n });\n if (!tokenAccount && handleTokenAccount) {\n const { tokenAccount: _tokenAccount, ...instructions } = await this.scope.account.handleTokenAccount({\n side: \"in\",\n amount: 0,\n mint,\n bypassAssociatedCheck: true,\n programId,\n });\n tokenAccount = _tokenAccount;\n txBuilder.addInstruction(instructions);\n }\n }\n\n return { tokenAccount, ...txBuilder.AllTxData };\n }\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 { 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 // wrap to Fraction\n const n = String(value);\n const details = parseNumberInfo(n);\n return new Fraction(details.numerator, details.denominator);\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\nexport 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","/*\r\n * decimal.js v10.3.1\r\n * An arbitrary-precision Decimal type for JavaScript.\r\n * https://github.com/MikeMcl/decimal.js\r\n * Copyright (c) 2021 Michael Mclaughlin <M8ch88l@gmail.com>\r\n * MIT Licence\r\n */\r\n\r\n\r\n// ----------------------------------- EDITABLE DEFAULTS ------------------------------------ //\r\n\r\n\r\n // The maximum exponent magnitude.\r\n // The limit on the value of `toExpNeg`, `toExpPos`, `minE` and `maxE`.\r\nvar EXP_LIMIT = 9e15, // 0 to 9e15\r\n\r\n // The limit on the value of `precision`, and on the value of the first argument to\r\n // `toDecimalPlaces`, `toExponential`, `toFixed`, `toPrecision` and `toSignificantDigits`.\r\n MAX_DIGITS = 1e9, // 0 to 1e9\r\n\r\n // Base conversion alphabet.\r\n NUMERALS = '0123456789abcdef',\r\n\r\n // The natural logarithm of 10 (1025 digits).\r\n LN10 = '2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220114804663715659121373450747856947683463616792101806445070648000277502684916746550586856935673420670581136429224554405758925724208241314695689016758940256776311356919292033376587141660230105703089634572075440370847469940168269282808481184289314848524948644871927809676271275775397027668605952496716674183485704422507197965004714951050492214776567636938662976979522110718264549734772662425709429322582798502585509785265383207606726317164309505995087807523710333101197857547331541421808427543863591778117054309827482385045648019095610299291824318237525357709750539565187697510374970888692180205189339507238539205144634197265287286965110862571492198849978748873771345686209167058',\r\n\r\n // Pi (1025 digits).\r\n PI = '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632789',\r\n\r\n\r\n // The initial configuration properties of the Decimal constructor.\r\n DEFAULTS = {\r\n\r\n // These values must be integers within the stated ranges (inclusive).\r\n // Most of these values can be changed at run-time using the `Decimal.config` method.\r\n\r\n // The maximum number of significant digits of the result of a calculation or base conversion.\r\n // E.g. `Decimal.config({ precision: 20 });`\r\n precision: 20, // 1 to MAX_DIGITS\r\n\r\n // The rounding mode used when rounding to `precision`.\r\n //\r\n // ROUND_UP 0 Away from zero.\r\n // ROUND_DOWN 1 Towards zero.\r\n // ROUND_CEIL 2 Towards +Infinity.\r\n // ROUND_FLOOR 3 Towards -Infinity.\r\n // ROUND_HALF_UP 4 Towards nearest neighbour. If equidistant, up.\r\n // ROUND_HALF_DOWN 5 Towards nearest neighbour. If equidistant, down.\r\n // ROUND_HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour.\r\n // ROUND_HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity.\r\n // ROUND_HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.\r\n //\r\n // E.g.\r\n // `Decimal.rounding = 4;`\r\n // `Decimal.rounding = Decimal.ROUND_HALF_UP;`\r\n rounding: 4, // 0 to 8\r\n\r\n // The modulo mode used when calculating the modulus: a mod n.\r\n // The quotient (q = a / n) is calculated according to the corresponding rounding mode.\r\n // The remainder (r) is calculated as: r = a - n * q.\r\n //\r\n // UP 0 The remainder is positive if the dividend is negative, else is negative.\r\n // DOWN 1 The remainder has the same sign as the dividend (JavaScript %).\r\n // FLOOR 3 The remainder has the same sign as the divisor (Python %).\r\n // HALF_EVEN 6 The IEEE 754 remainder function.\r\n // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). Always positive.\r\n //\r\n // Truncated division (1), floored division (3), the IEEE 754 remainder (6), and Euclidian\r\n // division (9) are commonly used for the modulus operation. The other rounding modes can also\r\n // be used, but they may not give useful results.\r\n modulo: 1, // 0 to 9\r\n\r\n // The exponent value at and beneath which `toString` returns exponential notation.\r\n // JavaScript numbers: -7\r\n toExpNeg: -7, // 0 to -EXP_LIMIT\r\n\r\n // The exponent value at and above which `toString` returns exponential notation.\r\n // JavaScript numbers: 21\r\n toExpPos: 21, // 0 to EXP_LIMIT\r\n\r\n // The minimum exponent value, beneath which underflow to zero occurs.\r\n // JavaScript numbers: -324 (5e-324)\r\n minE: -EXP_LIMIT, // -1 to -EXP_LIMIT\r\n\r\n // The maximum exponent value, above which overflow to Infinity occurs.\r\n // JavaScript numbers: 308 (1.7976931348623157e+308)\r\n maxE: EXP_LIMIT, // 1 to EXP_LIMIT\r\n\r\n // Whether to use cryptographically-secure random number generation, if available.\r\n crypto: false // true/false\r\n },\r\n\r\n\r\n// ----------------------------------- END OF EDITABLE DEFAULTS ------------------------------- //\r\n\r\n\r\n inexact, quadrant,\r\n external = true,\r\n\r\n decimalError = '[DecimalError] ',\r\n invalidArgument = decimalError + 'Invalid argument: ',\r\n precisionLimitExceeded = decimalError + 'Precision limit exceeded',\r\n cryptoUnavailable = decimalError + 'crypto unavailable',\r\n tag = '[object Decimal]',\r\n\r\n mathfloor = Math.floor,\r\n mathpow = Math.pow,\r\n\r\n isBinary = /^0b([01]+(\\.[01]*)?|\\.[01]+)(p[+-]?\\d+)?$/i,\r\n isHex = /^0x([0-9a-f]+(\\.[0-9a-f]*)?|\\.[0-9a-f]+)(p[+-]?\\d+)?$/i,\r\n isOctal = /^0o([0-7]+(\\.[0-7]*)?|\\.[0-7]+)(p[+-]?\\d+)?$/i,\r\n isDecimal = /^(\\d+(\\.\\d*)?|\\.\\d+)(e[+-]?\\d+)?$/i,\r\n\r\n BASE = 1e7,\r\n LOG_BASE = 7,\r\n MAX_SAFE_INTEGER = 9007199254740991,\r\n\r\n LN10_PRECISION = LN10.length - 1,\r\n PI_PRECISION = PI.length - 1,\r\n\r\n // Decimal.prototype object\r\n P = { toStringTag: tag };\r\n\r\n\r\n// Decimal prototype methods\r\n\r\n\r\n/*\r\n * absoluteValue abs\r\n * ceil\r\n * clampedTo clamp\r\n * comparedTo cmp\r\n * cosine cos\r\n * cubeRoot cbrt\r\n * decimalPlaces dp\r\n * dividedBy div\r\n * dividedToIntegerBy divToInt\r\n * equals eq\r\n * floor\r\n * greaterThan gt\r\n * greaterThanOrEqualTo gte\r\n * hyperbolicCosine cosh\r\n * hyperbolicSine sinh\r\n * hyperbolicTangent tanh\r\n * inverseCosine acos\r\n * inverseHyperbolicCosine acosh\r\n * inverseHyperbolicSine asinh\r\n * inverseHyperbolicTangent atanh\r\n * inverseSine asin\r\n * inverseTangent atan\r\n * isFinite\r\n * isInteger isInt\r\n * isNaN\r\n * isNegative isNeg\r\n * isPositive isPos\r\n * isZero\r\n * lessThan lt\r\n * lessThanOrEqualTo lte\r\n * logarithm log\r\n * [maximum] [max]\r\n * [minimum] [min]\r\n * minus sub\r\n * modulo mod\r\n * naturalExponential exp\r\n * naturalLogarithm ln\r\n * negated neg\r\n * plus add\r\n * precision sd\r\n * round\r\n * sine sin\r\n * squareRoot sqrt\r\n * tangent tan\r\n * times mul\r\n * toBinary\r\n * toDecimalPlaces toDP\r\n * toExponential\r\n * toFixed\r\n * toFraction\r\n * toHexadecimal toHex\r\n * toNearest\r\n * toNumber\r\n * toOctal\r\n * toPower pow\r\n * toPrecision\r\n * toSignificantDigits toSD\r\n * toString\r\n * truncated trunc\r\n * valueOf toJSON\r\n */\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the absolute value of this Decimal.\r\n *\r\n */\r\nP.absoluteValue = P.abs = function () {\r\n var x = new this.constructor(this);\r\n if (x.s < 0) x.s = 1;\r\n return finalise(x);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the\r\n * direction of positive Infinity.\r\n *\r\n */\r\nP.ceil = function () {\r\n return finalise(new this.constructor(this), this.e + 1, 2);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the value of this Decimal clamped to the range\r\n * delineated by `min` and `max`.\r\n *\r\n * min {number|string|Decimal}\r\n * max {number|string|Decimal}\r\n *\r\n */\r\nP.clampedTo = P.clamp = function (min, max) {\r\n var k,\r\n x = this,\r\n Ctor = x.constructor;\r\n min = new Ctor(min);\r\n max = new Ctor(max);\r\n if (!min.s || !max.s) return new Ctor(NaN);\r\n if (min.gt(max)) throw Error(invalidArgument + max);\r\n k = x.cmp(min);\r\n return k < 0 ? min : x.cmp(max) > 0 ? max : new Ctor(x);\r\n};\r\n\r\n\r\n/*\r\n * Return\r\n * 1 if the value of this Decimal is greater than the value of `y`,\r\n * -1 if the value of this Decimal is less than the value of `y`,\r\n * 0 if they have the same value,\r\n * NaN if the value of either Decimal is NaN.\r\n *\r\n */\r\nP.comparedTo = P.cmp = function (y) {\r\n var i, j, xdL, ydL,\r\n x = this,\r\n xd = x.d,\r\n yd = (y = new x.constructor(y)).d,\r\n xs = x.s,\r\n ys = y.s;\r\n\r\n // Either NaN or ±Infinity?\r\n if (!xd || !yd) {\r\n return !xs || !ys ? NaN : xs !== ys ? xs : xd === yd ? 0 : !xd ^ xs < 0 ? 1 : -1;\r\n }\r\n\r\n // Either zero?\r\n if (!xd[0] || !yd[0]) return xd[0] ? xs : yd[0] ? -ys : 0;\r\n\r\n // Signs differ?\r\n if (xs !== ys) return xs;\r\n\r\n // Compare exponents.\r\n if (x.e !== y.e) return x.e > y.e ^ xs < 0 ? 1 : -1;\r\n\r\n xdL = xd.length;\r\n ydL = yd.length;\r\n\r\n // Compare digit by digit.\r\n for (i = 0, j = xdL < ydL ? xdL : ydL; i < j; ++i) {\r\n if (xd[i] !== yd[i]) return xd[i] > yd[i] ^ xs < 0 ? 1 : -1;\r\n }\r\n\r\n // Compare lengths.\r\n return xdL === ydL ? 0 : xdL > ydL ^ xs < 0 ? 1 : -1;\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the cosine of the value in radians of this Decimal.\r\n *\r\n * Domain: [-Infinity, Infinity]\r\n * Range: [-1, 1]\r\n *\r\n * cos(0) = 1\r\n * cos(-0) = 1\r\n * cos(Infinity) = NaN\r\n * cos(-Infinity) = NaN\r\n * cos(NaN) = NaN\r\n *\r\n */\r\nP.cosine = P.cos = function () {\r\n var pr, rm,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.d) return new Ctor(NaN);\r\n\r\n // cos(0) = cos(-0) = 1\r\n if (!x.d[0]) return new Ctor(1);\r\n\r\n pr = Ctor.precision;\r\n rm = Ctor.rounding;\r\n Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE;\r\n Ctor.rounding = 1;\r\n\r\n x = cosine(Ctor, toLessThanHalfPi(Ctor, x));\r\n\r\n Ctor.precision = pr;\r\n Ctor.rounding = rm;\r\n\r\n return finalise(quadrant == 2 || quadrant == 3 ? x.neg() : x, pr, rm, true);\r\n};\r\n\r\n\r\n/*\r\n *\r\n * Return a new Decimal whose value is the cube root of the value of this Decimal, rounded to\r\n * `precision` significant digits using rounding mode `rounding`.\r\n *\r\n * cbrt(0) = 0\r\n * cbrt(-0) = -0\r\n * cbrt(1) = 1\r\n * cbrt(-1) = -1\r\n * cbrt(N) = N\r\n * cbrt(-I) = -I\r\n * cbrt(I) = I\r\n *\r\n * Math.cbrt(x) = (x < 0 ? -Math.pow(-x, 1/3) : Math.pow(x, 1/3))\r\n *\r\n */\r\nP.cubeRoot = P.cbrt = function () {\r\n var e, m, n, r, rep, s, sd, t, t3, t3plusx,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.isFinite() || x.isZero()) return new Ctor(x);\r\n external = false;\r\n\r\n // Initial estimate.\r\n s = x.s * mathpow(x.s * x, 1 / 3);\r\n\r\n // Math.cbrt underflow/overflow?\r\n // Pass x to Math.pow as integer, then adjust the exponent of the result.\r\n if (!s || Math.abs(s) == 1 / 0) {\r\n n = digitsToString(x.d);\r\n e = x.e;\r\n\r\n // Adjust n exponent so it is a multiple of 3 away from x exponent.\r\n if (s = (e - n.length + 1) % 3) n += (s =