UNPKG

goosefx-amm-sdk

Version:

SDK for the GooseFx AMM

1 lines 34 kB
{"version":3,"sources":["../../../../src/gfx/cpmm/curve/oracleCalculator.ts","../../../../src/gfx/cpmm/curve/fee.ts","../../../../src/gfx/cpmm/curve/common.ts","../../../../src/gfx/cpmm/curve/constantProduct.ts","../../../../src/gfx/cpmm/curve/calculator.ts"],"sourcesContent":["import BN from \"bn.js\";\nimport { DynamicFee, FEE_RATE_DENOMINATOR_VALUE } from \"./fee\";\nimport { ConstantProductCurve } from \"./constantProduct\";\nimport { CpmmObservationState, CpmmPool } from \"../type\";\nimport { SwapResult, CurveCalculator } from \"./calculator\";\nimport { saturatingSub, checkedCeilDiv } from \"./common\";\n\n// Price scaled to 9 decimal places\nconst D9 = new BN(Math.pow(10, 9));\nconst D9_SQUARED = D9.mul(D9);\n\nexport class OracleBasedCurveCalculator {\n static validate_supply(tokenAmount0: BN, tokenAmount1: BN): void {\n return CurveCalculator.validate_supply(tokenAmount0, tokenAmount1);\n }\n\n static swap(\n sourceAmount: BN,\n zeroForOne: boolean,\n baseReserve: BN,\n quoteReserve: BN,\n tradeFeeRate: BN,\n observationState: CpmmObservationState,\n poolState: CpmmPool,\n isInvokedWithSignedSegmenter = false,\n ): SwapResult {\n const swapSourceAmount = zeroForOne ? baseReserve : quoteReserve;\n const swapDestinationAmount = zeroForOne ? quoteReserve : baseReserve;\n\n const oraclePriceUpdatedAt = poolState.oraclePriceUpdatedAt;\n const blockTimestamp = new BN(new Date().getTime() / 1000);\n const timeDiff = saturatingSub(blockTimestamp, oraclePriceUpdatedAt);\n if (\n timeDiff.gtn(poolState.maxOraclePriceUpdateTimeDiff) ||\n blockTimestamp.lt(oraclePriceUpdatedAt) ||\n oraclePriceUpdatedAt.eqn(0) ||\n poolState.oraclePriceToken0ByToken1.eqn(0)\n ) {\n return CurveCalculator.swapBaseIn(\n sourceAmount,\n swapSourceAmount,\n swapDestinationAmount,\n tradeFeeRate,\n observationState,\n poolState.volatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n }\n\n const spotPrice = swapDestinationAmount.mul(D9).div(swapSourceAmount);\n const oraclePrice = zeroForOne\n ? D9_SQUARED.div(poolState.oraclePriceToken0ByToken1)\n : poolState.oraclePriceToken0ByToken1;\n const rateDifference = OracleBasedCurveCalculator.getSpotPriceAndOraclePriceRateDifference(oraclePrice, spotPrice);\n if (rateDifference.gtn(poolState.acceptablePriceDifference)) {\n return CurveCalculator.swapBaseIn(\n sourceAmount,\n swapSourceAmount,\n swapDestinationAmount,\n tradeFeeRate,\n observationState,\n poolState.volatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n }\n\n const amountToBeSwappedAtOraclePrice = OracleBasedCurveCalculator.getAmountToBeSwappedAtOraclePrice(\n sourceAmount,\n swapSourceAmount,\n swapDestinationAmount,\n oraclePrice,\n poolState,\n );\n const amountToBeSwappedWithInvariantCurve = sourceAmount.sub(amountToBeSwappedAtOraclePrice);\n\n if (amountToBeSwappedAtOraclePrice.eqn(0)) {\n return CurveCalculator.swapBaseIn(\n sourceAmount,\n swapSourceAmount,\n swapDestinationAmount,\n tradeFeeRate,\n observationState,\n poolState.volatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n }\n\n const dynamicFeeRate = DynamicFee.calculateDynamicFeeRate(\n blockTimestamp,\n observationState,\n \"volatility\",\n tradeFeeRate,\n poolState.volatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n\n const oracleSwapFeeRate = dynamicFeeRate.gten(poolState.minTradeRateAtOraclePrice)\n ? dynamicFeeRate\n : new BN(poolState.minTradeRateAtOraclePrice);\n const oracleSwapTradeFees = checkedCeilDiv(\n amountToBeSwappedAtOraclePrice.mul(oracleSwapFeeRate),\n FEE_RATE_DENOMINATOR_VALUE,\n )[0];\n const oracleSwapSourceAmountAfterFees = amountToBeSwappedAtOraclePrice.sub(oracleSwapTradeFees);\n const executionOraclePrice = OracleBasedCurveCalculator.getExecutionOraclePrice(\n oraclePrice,\n new BN(poolState.pricePremiumForSwapAtOraclePrice),\n );\n\n const outputTokensFromOracleSwap = executionOraclePrice.mul(oracleSwapSourceAmountAfterFees).div(D9);\n\n const newSwapSourceAmount = swapSourceAmount.add(amountToBeSwappedAtOraclePrice);\n const newSwapDestinationAmount = swapDestinationAmount.sub(outputTokensFromOracleSwap);\n\n const invariantSwapTradeFees = checkedCeilDiv(\n amountToBeSwappedWithInvariantCurve.mul(dynamicFeeRate),\n FEE_RATE_DENOMINATOR_VALUE,\n )[0];\n\n const sourceAmountAfterFees = saturatingSub(amountToBeSwappedWithInvariantCurve, invariantSwapTradeFees);\n let outputTokensFromInvariantSwap = new BN(0);\n if (!sourceAmountAfterFees.isZero()) {\n outputTokensFromInvariantSwap = ConstantProductCurve.swapWithoutFees(\n sourceAmountAfterFees,\n newSwapSourceAmount,\n newSwapDestinationAmount,\n ).destinationAmountSwapped;\n }\n\n const destinationAmountSwapped = outputTokensFromOracleSwap.add(outputTokensFromInvariantSwap);\n return {\n newSwapSourceAmount: swapSourceAmount.add(sourceAmount),\n newSwapDestinationAmount: swapDestinationAmount.sub(destinationAmountSwapped),\n sourceAmountSwapped: sourceAmount,\n destinationAmountSwapped,\n tradeFee: invariantSwapTradeFees.add(oracleSwapTradeFees),\n };\n }\n\n private static getAmountToBeSwappedAtOraclePrice(\n sourceAmountToBeSwapped: BN,\n swapSourceAmount: BN,\n swapDestinationAmount: BN,\n oraclePrice: BN,\n poolState: CpmmPool,\n ): BN {\n const maxAmountSwappableAtOraclePrice = swapSourceAmount\n .muln(poolState.maxAmountSwappableAtOraclePrice)\n .div(FEE_RATE_DENOMINATOR_VALUE);\n const priceDifferenceLimit = FEE_RATE_DENOMINATOR_VALUE.subn(poolState.acceptablePriceDifference);\n const spotPriceAtAcceptablePriceDifferenceLimit = oraclePrice\n .mul(priceDifferenceLimit)\n .div(FEE_RATE_DENOMINATOR_VALUE);\n\n // To find Max tradeable amount with price Oracle Price P before we reach spot_price_at_acceptable_price_difference_limit Z:\n // x_delta_max = (|(Z*X) - Y)| / (Z + P)\n const numerator = spotPriceAtAcceptablePriceDifferenceLimit\n .mul(swapSourceAmount)\n .sub(swapDestinationAmount.mul(D9))\n .abs();\n const denominator = oraclePrice.add(spotPriceAtAcceptablePriceDifferenceLimit);\n const maxSwappableWithoutExceedingPriceDifference = numerator.div(denominator);\n\n const min = maxSwappableWithoutExceedingPriceDifference.gt(maxAmountSwappableAtOraclePrice)\n ? maxAmountSwappableAtOraclePrice\n : maxSwappableWithoutExceedingPriceDifference;\n return min.gt(sourceAmountToBeSwapped) ? sourceAmountToBeSwapped : min;\n }\n\n private static getSpotPriceAndOraclePriceRateDifference(oraclePrice: BN, spotPrice: BN): BN {\n return spotPrice.sub(oraclePrice).abs().mul(FEE_RATE_DENOMINATOR_VALUE).div(oraclePrice);\n }\n\n private static getExecutionOraclePrice(oraclePrice: BN, pricePremiumForOracleSwaps: BN): BN {\n const premium = oraclePrice.mul(pricePremiumForOracleSwaps).div(FEE_RATE_DENOMINATOR_VALUE);\n return oraclePrice.add(premium);\n }\n}\n","import BN from \"bn.js\";\nimport { CpmmObservationState, CpmmObservation } from \"../type\";\nimport Decimal from \"decimal.js-light\";\nimport { checkedCeilDiv, saturatingSub } from \"./common\";\n\nexport const ONE_BASIS_POINT = new BN(100);\nexport const FEE_RATE_DENOMINATOR_VALUE = new BN(1_000_000);\nconst OBSERVATION_LEN = 100;\n// Volatility-based fee constants\n// const MAX_FEE_VOLATILITY = new BN(10000); // 1% max fee\nconst VOLATILITY_WINDOW = new BN(3600); // 1 hour window for volatility calculation\n\nconst MAX_FEE = new BN(100000); // 10% max fee\nconst DEFAULT_VOLATILITY_FACTOR = new BN(300000); // Adjust based on desired sensitivity\n\ntype PriceRange = {\n minPrice: BN;\n maxPrice: BN;\n twapPrice: BN;\n};\n\ntype FeeType = \"volatility\";\n\nexport class DynamicFee {\n static calculateDynamicFee(\n amount: BN,\n blockTimestamp: BN,\n observationState: CpmmObservationState,\n feeType: FeeType,\n baseFees: BN,\n poolVolatilityFactor: BN,\n isInvokedWithSignedSegmenter: boolean,\n ): BN {\n const feeRate = this.calculateDynamicFeeRate(\n blockTimestamp,\n observationState,\n feeType,\n baseFees,\n poolVolatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n\n const [dynamicFee, _feeRateDenominator] = checkedCeilDiv(amount.mul(feeRate), FEE_RATE_DENOMINATOR_VALUE);\n return dynamicFee;\n }\n\n static calculatePreDynamicFee(\n amount: BN,\n blockTimestamp: BN,\n observationState: CpmmObservationState,\n feeType: FeeType,\n baseFees: BN,\n poolVolatilityFactor: BN,\n isInvokedWithSignedSegmenter: boolean,\n ): BN {\n const feeRate = this.calculateDynamicFeeRate(\n blockTimestamp,\n observationState,\n feeType,\n baseFees,\n poolVolatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n\n if (feeRate.isZero()) {\n return amount; // No fee, pre-fee amount = post-fee amount\n }\n\n const denominator = FEE_RATE_DENOMINATOR_VALUE.sub(feeRate);\n if (denominator.isZero()) {\n throw new Error(\"Fee rate equals denominator, causing division by zero\");\n }\n\n // x = (y * D + (D - r) - 1) / (D - r)\n const numerator = amount.mul(FEE_RATE_DENOMINATOR_VALUE);\n const result = numerator.add(denominator).sub(new BN(1)).div(denominator);\n\n return result;\n }\n\n static calculateDynamicFeeRate(\n blockTimestamp: BN,\n observationState: CpmmObservationState,\n feeType: FeeType,\n baseFees: BN,\n poolVolatilityFactor: BN,\n isInvokedWithSignedSegmenter: boolean,\n ): BN {\n switch (feeType) {\n case \"volatility\": {\n return this.calculateVolatileFee(\n blockTimestamp,\n observationState,\n baseFees,\n poolVolatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n }\n }\n }\n\n static calculateVolatileFee(\n blockTimestamp: BN,\n observationState: CpmmObservationState,\n baseFees: BN,\n poolSpecifiedVolatilityFactor: BN,\n isInvokedWithSignedSegmenter: boolean,\n ): BN {\n const { minPrice, maxPrice, twapPrice } = this.getPriceRange(observationState, blockTimestamp, VOLATILITY_WINDOW);\n if (minPrice.eqn(0) || maxPrice.eqn(0) || twapPrice.eqn(0) || twapPrice.eqn(1)) {\n return baseFees;\n }\n\n const logMaxPrice = new Decimal(maxPrice.toString()).ln();\n const logMinPrice = new Decimal(minPrice.toString()).ln();\n const logTwapPrice = new Decimal(twapPrice.toString()).ln();\n\n const numerator = logMaxPrice.sub(logMinPrice);\n const denominator = logTwapPrice.abs();\n\n if (denominator.eq(0)) {\n return baseFees;\n }\n\n const volatility = numerator.div(denominator);\n const volatilityFactor = poolSpecifiedVolatilityFactor.eqn(0)\n ? DEFAULT_VOLATILITY_FACTOR\n : poolSpecifiedVolatilityFactor;\n const volatilityComponent = new Decimal(volatilityFactor.toString()).mul(volatility);\n\n const dynamicFee = new Decimal(baseFees.toString()).add(volatilityComponent);\n const finalFee = new BN(\n dynamicFee.lessThan(new Decimal(MAX_FEE.toString())) ? dynamicFee.toString() : MAX_FEE.toString(),\n );\n if (isInvokedWithSignedSegmenter) {\n const discountedFee = saturatingSub(finalFee, ONE_BASIS_POINT);\n return baseFees.gt(discountedFee) ? baseFees : discountedFee;\n } else {\n return finalFee;\n }\n }\n\n static getPriceRange(observationState: CpmmObservationState, currentTime: BN, window: BN): PriceRange {\n let minPrice = new BN(1).ushln(128).subn(1);\n let maxPrice = new BN(0);\n\n let descendingObservations = observationState.observations\n .map((observation, idx) => ({ observation, idx }))\n .filter(({ observation }) => {\n observation.blockTimestamp.eqn(0) &&\n !observation.cumulativeToken0PriceX32.eqn(0) &&\n !observation.cumulativeToken1PriceX32.eqn(0) &&\n currentTime.sub(observation.blockTimestamp) <= window;\n })\n .map(({ observation, idx }) => {\n return {\n index: idx,\n observation,\n };\n });\n\n if (descendingObservations.length < 2) {\n return {\n minPrice: new BN(0),\n maxPrice: new BN(0),\n twapPrice: new BN(0),\n };\n }\n\n descendingObservations.sort((a, b) => b.observation.blockTimestamp.cmp(a.observation.blockTimestamp));\n\n const newestObs = descendingObservations[0];\n const oldestObs = descendingObservations[descendingObservations.length - 1];\n\n const totalTimeDelta = saturatingSub(newestObs.observation.blockTimestamp, oldestObs.observation.blockTimestamp);\n if (totalTimeDelta.eqn(0)) {\n return {\n minPrice: new BN(0),\n maxPrice: new BN(0),\n twapPrice: new BN(0),\n };\n }\n\n const twapPrice = newestObs.observation.cumulativeToken0PriceX32\n .sub(oldestObs.observation.cumulativeToken0PriceX32)\n .div(totalTimeDelta);\n\n for (const indexedObservation of descendingObservations) {\n let lastObservation: CpmmObservation;\n if (indexedObservation.index == 0) {\n lastObservation = observationState.observations[OBSERVATION_LEN - 1];\n } else {\n lastObservation = observationState.observations[indexedObservation.index - 1];\n }\n\n if (lastObservation.blockTimestamp.eqn(0)) {\n continue;\n }\n\n if (lastObservation.blockTimestamp > indexedObservation.observation.blockTimestamp) {\n break;\n }\n\n const nextObservation = indexedObservation.observation;\n const timeDelta = saturatingSub(nextObservation.blockTimestamp, lastObservation.blockTimestamp);\n\n if (timeDelta.eqn(0)) {\n continue;\n }\n\n const price = nextObservation.cumulativeToken0PriceX32\n .sub(lastObservation.cumulativeToken0PriceX32)\n .div(timeDelta);\n\n minPrice = BN.min(minPrice, price);\n maxPrice = BN.max(maxPrice, price);\n }\n\n return {\n minPrice,\n maxPrice,\n twapPrice,\n };\n }\n\n static calculatePreFeeAmount(\n blockTimestamp: BN,\n postFeeAmount: BN,\n observationState: CpmmObservationState,\n feeType: FeeType,\n baseFees: BN,\n poolVolatilityFactor: BN,\n isInvokedWithSignedSegmenter: boolean,\n ): BN {\n const dynamicFeeRate = this.calculateDynamicFeeRate(\n blockTimestamp,\n observationState,\n feeType,\n baseFees,\n poolVolatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n if (dynamicFeeRate.eqn(0)) {\n return postFeeAmount;\n } else {\n const numerator = postFeeAmount.mul(FEE_RATE_DENOMINATOR_VALUE);\n const denominator = FEE_RATE_DENOMINATOR_VALUE.sub(dynamicFeeRate);\n\n return numerator.add(denominator).subn(1).div(denominator);\n }\n }\n}\n","import BN from \"bn.js\";\n\nexport const ZERO = new BN(0);\n\nexport function checkedRem(dividend: BN, divisor: BN): BN {\n if (divisor.isZero()) throw Error(\"divisor is zero\");\n\n const result = dividend.mod(divisor);\n return result;\n}\n\nexport function checkedCeilDiv(dividend: BN, rhs: BN): BN[] {\n if (rhs.isZero()) throw Error(\"rhs is zero\");\n const quotient = dividend.div(rhs);\n if (quotient.isZero()) return [quotient, rhs];\n const remainder = dividend.sub(quotient.mul(rhs));\n if (remainder.isZero()) return [quotient, rhs];\n return [quotient.add(new BN(1)), rhs];\n}\n\nexport function saturatingSub(a: BN, b: BN): BN {\n return a.gt(b) ? a.sub(b) : new BN(0);\n}\n","import BN from \"bn.js\";\nimport { RoundDirection, SwapWithoutFeesResult, TradingTokenResult } from \"./calculator\";\nimport { checkedCeilDiv, checkedRem, ZERO } from \"./common\";\n\nexport class ConstantProductCurve {\n static swapWithoutFees(sourceAmount: BN, swapSourceAmount: BN, swapDestinationAmount: BN): SwapWithoutFeesResult {\n const invariant = swapSourceAmount.mul(swapDestinationAmount);\n\n const newSwapSourceAmount = swapSourceAmount.add(sourceAmount);\n const [newSwapDestinationAmount, _newSwapSourceAmount] = checkedCeilDiv(invariant, newSwapSourceAmount);\n\n const sourceAmountSwapped = _newSwapSourceAmount.sub(swapSourceAmount);\n const destinationAmountSwapped = swapDestinationAmount.sub(newSwapDestinationAmount);\n if (destinationAmountSwapped.isZero()) throw Error(\"destinationAmountSwapped is zero\");\n\n return {\n sourceAmountSwapped,\n destinationAmountSwapped,\n };\n }\n\n static swapWithoutFeesBaseOut(\n destinationAmount: BN,\n swapSourceAmount: BN,\n swapDestinationAmount: BN,\n ): SwapWithoutFeesResult {\n // Ensure inputs are valid\n if (destinationAmount.isZero()) {\n throw new Error(\"destinationAmount is zero\");\n }\n if (destinationAmount.gt(swapDestinationAmount)) {\n throw new Error(\"destinationAmount exceeds available destination reserve\");\n }\n\n // Numerator: x * Δy\n const numerator = swapSourceAmount.mul(destinationAmount);\n // Denominator: y - Δy\n const denominator = swapDestinationAmount.sub(destinationAmount);\n\n if (denominator.isZero()) {\n throw new Error(\"denominator is zero\");\n }\n\n // Ceiling division: Δx = ceil((x * Δy) / (y - Δy))\n const [sourceAmountSwapped] = checkedCeilDiv(numerator, denominator);\n\n return {\n sourceAmountSwapped,\n destinationAmountSwapped: destinationAmount,\n };\n }\n\n static lpTokensToTradingTokens(\n lpTokenAmount: BN,\n lpTokenSupply: BN,\n swapTokenAmount0: BN,\n swapTokenAmount1: BN,\n roundDirection: RoundDirection,\n ): TradingTokenResult {\n let tokenAmount0 = lpTokenAmount.mul(swapTokenAmount0).div(lpTokenSupply);\n let tokenAmount1 = lpTokenAmount.mul(swapTokenAmount1).div(lpTokenSupply);\n\n if (roundDirection === RoundDirection.Floor) {\n return { tokenAmount0, tokenAmount1 };\n } else if (roundDirection === RoundDirection.Ceiling) {\n const tokenRemainder0 = checkedRem(lpTokenAmount.mul(swapTokenAmount0), lpTokenSupply);\n\n if (tokenRemainder0.gt(ZERO) && tokenAmount0.gt(ZERO)) {\n tokenAmount0 = tokenAmount0.add(new BN(1));\n }\n\n const token1Remainder = checkedRem(lpTokenAmount.mul(swapTokenAmount1), lpTokenSupply);\n\n if (token1Remainder.gt(ZERO) && tokenAmount1.gt(ZERO)) {\n tokenAmount1 = tokenAmount1.add(new BN(1));\n }\n\n return { tokenAmount0, tokenAmount1 };\n }\n throw Error(\"roundDirection value error\");\n }\n}\n","import BN from \"bn.js\";\nimport { DynamicFee } from \"./fee\";\nimport { ConstantProductCurve } from \"./constantProduct\";\nimport { CpmmObservationState } from \"../type\";\n\nexport enum RoundDirection {\n Floor,\n Ceiling,\n}\n\nexport type SwapWithoutFeesResult = { sourceAmountSwapped: BN; destinationAmountSwapped: BN };\n\nexport type TradingTokenResult = { tokenAmount0: BN; tokenAmount1: BN };\n\nexport type SwapResult = {\n newSwapSourceAmount: BN;\n newSwapDestinationAmount: BN;\n sourceAmountSwapped: BN;\n destinationAmountSwapped: BN;\n tradeFee: BN;\n};\n\nexport class CurveCalculator {\n static validate_supply(tokenAmount0: BN, tokenAmount1: BN): void {\n if (tokenAmount0.isZero()) throw Error(\"tokenAmount0 is zero\");\n if (tokenAmount1.isZero()) throw Error(\"tokenAmount1 is zero\");\n }\n\n static swapBaseIn(\n sourceAmount: BN,\n swapSourceAmount: BN,\n swapDestinationAmount: BN,\n tradeFeeRate: BN,\n observationState: CpmmObservationState,\n poolVolatilityFactor: BN,\n isInvokedWithSignedSegmenter = false,\n ): SwapResult {\n const tradeFee = DynamicFee.calculateDynamicFee(\n sourceAmount,\n new BN(new Date().getTime() / 1000),\n observationState,\n \"volatility\",\n tradeFeeRate,\n poolVolatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n\n const sourceAmountLessFees = sourceAmount.sub(tradeFee);\n\n const { sourceAmountSwapped, destinationAmountSwapped } = ConstantProductCurve.swapWithoutFees(\n sourceAmountLessFees,\n swapSourceAmount,\n swapDestinationAmount,\n );\n\n const _sourceAmountSwapped = sourceAmountSwapped.add(tradeFee);\n return {\n newSwapSourceAmount: swapSourceAmount.add(_sourceAmountSwapped),\n newSwapDestinationAmount: swapDestinationAmount.sub(destinationAmountSwapped),\n sourceAmountSwapped: _sourceAmountSwapped,\n destinationAmountSwapped,\n tradeFee,\n };\n }\n\n static swapBaseOut(\n destinationAmount: BN,\n swapSourceAmount: BN,\n swapDestinationAmount: BN,\n tradeFeeRate: BN,\n observationState: CpmmObservationState,\n poolVolatilityFactor: BN,\n isInvokedWithSignedSegmenter = false,\n ): SwapResult {\n // Validate inputs\n if (destinationAmount.isZero()) throw new Error(\"destinationAmount is zero\");\n if (destinationAmount.gt(swapDestinationAmount)) {\n throw new Error(\"destinationAmount exceeds available destination reserve\");\n }\n\n // Calculate source amount without fees\n const { sourceAmountSwapped: sourceAmountLessFees, destinationAmountSwapped } =\n ConstantProductCurve.swapWithoutFeesBaseOut(destinationAmount, swapSourceAmount, swapDestinationAmount);\n\n const sourceAmount = DynamicFee.calculatePreDynamicFee(\n sourceAmountLessFees,\n new BN(new Date().getTime() / 1000),\n observationState,\n \"volatility\",\n tradeFeeRate,\n poolVolatilityFactor,\n isInvokedWithSignedSegmenter,\n );\n\n return {\n newSwapSourceAmount: swapSourceAmount.add(sourceAmount),\n newSwapDestinationAmount: swapDestinationAmount.sub(destinationAmountSwapped),\n sourceAmountSwapped: sourceAmount,\n destinationAmountSwapped,\n tradeFee: sourceAmount.sub(sourceAmountLessFees),\n };\n }\n}\n"],"mappings":"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","names":["BN","BN","Decimal","BN","ZERO","checkedRem","dividend","divisor","checkedCeilDiv","rhs","quotient","saturatingSub","a","b","ONE_BASIS_POINT","BN","FEE_RATE_DENOMINATOR_VALUE","OBSERVATION_LEN","VOLATILITY_WINDOW","MAX_FEE","DEFAULT_VOLATILITY_FACTOR","DynamicFee","amount","blockTimestamp","observationState","feeType","baseFees","poolVolatilityFactor","isInvokedWithSignedSegmenter","feeRate","dynamicFee","_feeRateDenominator","checkedCeilDiv","denominator","poolSpecifiedVolatilityFactor","minPrice","maxPrice","twapPrice","logMaxPrice","Decimal","logMinPrice","logTwapPrice","numerator","volatility","volatilityFactor","volatilityComponent","finalFee","discountedFee","saturatingSub","currentTime","window","descendingObservations","observation","idx","a","b","newestObs","oldestObs","totalTimeDelta","indexedObservation","lastObservation","nextObservation","timeDelta","price","postFeeAmount","dynamicFeeRate","BN","BN","CurveCalculator","tokenAmount0","tokenAmount1","sourceAmount","swapSourceAmount","swapDestinationAmount","tradeFeeRate","observationState","poolVolatilityFactor","isInvokedWithSignedSegmenter","tradeFee","DynamicFee","BN","sourceAmountLessFees","sourceAmountSwapped","destinationAmountSwapped","ConstantProductCurve","_sourceAmountSwapped","destinationAmount","ConstantProductCurve","sourceAmount","swapSourceAmount","swapDestinationAmount","invariant","newSwapSourceAmount","newSwapDestinationAmount","_newSwapSourceAmount","checkedCeilDiv","sourceAmountSwapped","destinationAmountSwapped","destinationAmount","numerator","denominator","lpTokenAmount","lpTokenSupply","swapTokenAmount0","swapTokenAmount1","roundDirection","tokenAmount0","tokenAmount1","checkedRem","ZERO","BN","D9","BN","D9_SQUARED","OracleBasedCurveCalculator","tokenAmount0","tokenAmount1","CurveCalculator","sourceAmount","zeroForOne","baseReserve","quoteReserve","tradeFeeRate","observationState","poolState","isInvokedWithSignedSegmenter","swapSourceAmount","swapDestinationAmount","oraclePriceUpdatedAt","blockTimestamp","saturatingSub","spotPrice","oraclePrice","amountToBeSwappedAtOraclePrice","amountToBeSwappedWithInvariantCurve","dynamicFeeRate","DynamicFee","oracleSwapFeeRate","oracleSwapTradeFees","checkedCeilDiv","FEE_RATE_DENOMINATOR_VALUE","oracleSwapSourceAmountAfterFees","outputTokensFromOracleSwap","newSwapSourceAmount","newSwapDestinationAmount","invariantSwapTradeFees","sourceAmountAfterFees","outputTokensFromInvariantSwap","ConstantProductCurve","destinationAmountSwapped","sourceAmountToBeSwapped","maxAmountSwappableAtOraclePrice","priceDifferenceLimit","spotPriceAtAcceptablePriceDifferenceLimit","numerator","denominator","maxSwappableWithoutExceedingPriceDifference","min","pricePremiumForOracleSwaps","premium"]}