import { CurrencyAmount, Fraction, JSBI, Percent, TokenAmount, Trade } from '@pancakeswap/sdk' import { BLOCKED_PRICE_IMPACT_NON_EXPERT, ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM, } from '../config/constants' import { Field } from '../state/swap/actions' import { basisPointsToPercent } from './index' const BASE_FEE = new Percent(JSBI.BigInt(25), JSBI.BigInt(10000)) const ONE_HUNDRED_PERCENT = new Percent(JSBI.BigInt(10000), JSBI.BigInt(10000)) const INPUT_FRACTION_AFTER_FEE = ONE_HUNDRED_PERCENT.subtract(BASE_FEE) // computes price breakdown for the trade export function computeTradePriceBreakdown(trade?: Trade | null): { priceImpactWithoutFee: Percent | undefined realizedLPFee: CurrencyAmount | undefined | null } { // for each hop in our trade, take away the x*y=k price impact from 0.3% fees // e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03)) const realizedLPFee = !trade ? undefined : ONE_HUNDRED_PERCENT.subtract( trade.route.pairs.reduce( (currentFee: Fraction): Fraction => currentFee.multiply(INPUT_FRACTION_AFTER_FEE), ONE_HUNDRED_PERCENT, ), ) // remove lp fees from price impact const priceImpactWithoutFeeFraction = trade && realizedLPFee ? trade.priceImpact.subtract(realizedLPFee) : undefined // the x*y=k impact const priceImpactWithoutFeePercent = priceImpactWithoutFeeFraction ? new Percent(priceImpactWithoutFeeFraction?.numerator, priceImpactWithoutFeeFraction?.denominator) : undefined // the amount of the input that accrues to LPs const realizedLPFeeAmount = realizedLPFee && trade && (trade.inputAmount instanceof TokenAmount ? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient) : CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient)) return { priceImpactWithoutFee: priceImpactWithoutFeePercent, realizedLPFee: realizedLPFeeAmount } } // computes the minimum amount out and maximum amount in for a trade given a user specified allowed slippage in bips export function computeSlippageAdjustedAmounts( trade: Trade | undefined, allowedSlippage: number, ): { [field in Field]?: CurrencyAmount } { const pct = basisPointsToPercent(allowedSlippage) return { [Field.INPUT]: trade?.maximumAmountIn(pct), [Field.OUTPUT]: trade?.minimumAmountOut(pct), } } export function warningSeverity(priceImpact: Percent | undefined): 0 | 1 | 2 | 3 | 4 { if (!priceImpact?.lessThan(BLOCKED_PRICE_IMPACT_NON_EXPERT)) return 4 if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_HIGH)) return 3 if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_MEDIUM)) return 2 if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_LOW)) return 1 return 0 } export function formatExecutionPrice(trade?: Trade, inverted?: boolean): string { if (!trade) { return '' } return inverted ? `${trade.executionPrice.invert().toSignificant(6)} ${trade.inputAmount.currency.symbol} / ${ trade.outputAmount.currency.symbol }` : `${trade.executionPrice.toSignificant(6)} ${trade.outputAmount.currency.symbol} / ${ trade.inputAmount.currency.symbol }` }