Skip to content
This repository has been archived by the owner on Jan 15, 2021. It is now read-only.

Commit

Permalink
[Price Impact] - Fix price calculation and price warnings (#1580)
Browse files Browse the repository at this point in the history
* fix price calculation

1. pass raw price values to calculate
2. use price floor when price extremely small
3. show raw value in limit price and title tag for accuracy

* addressed PR comments

1. better var names
2. fixed comments in utils
3. use string for bignumber constructor
  • Loading branch information
W3stside authored Nov 4, 2020
1 parent 8953f68 commit 378fcdb
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 19 deletions.
4 changes: 2 additions & 2 deletions src/components/TradeWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,10 @@ const TradeWidget: React.FC<TradeWidgetProps> = ({
useEffect(() => {
if (priceValue && sellValue) {
// If price is quoted in sell tokens, we use it, otherwise we use the inverse
const priceUsedForReceiveAmount = sellToken === quoteToken ? priceValue : priceInverseValue
const priceUsedForReceiveAmount = sellToken.address === quoteToken.address ? priceValue : priceInverseValue
setValue(receiveInputId, calculateReceiveAmount(priceUsedForReceiveAmount, sellValue))
}
}, [isPriceInverted, quoteToken, sellToken, priceValue, priceInverseValue, setValue, sellValue])
}, [isPriceInverted, quoteToken.address, sellToken.address, priceValue, priceInverseValue, setValue, sellValue])

const url = buildUrl({
sell: sellValue,
Expand Down
5 changes: 4 additions & 1 deletion src/components/TradeWidget/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { encodeTokenSymbol } from '@gnosis.pm/dex-js'
import { BATCH_START_THRESHOLD } from './validationSchema'
import { BATCH_TIME_IN_MS } from 'const'
import { TokenDetails } from 'types'
import { formatPriceToPrecision } from 'components/trade/PriceSuggestions/PriceSuggestionItem'

export function calculateReceiveAmount(priceValue: string, sellValue: string): string {
let receiveAmount = ''
Expand All @@ -16,7 +17,9 @@ export function calculateReceiveAmount(priceValue: string, sellValue: string): s

if (sellAmount && price) {
const receiveBigNumber = sellAmount.dividedBy(price)
receiveAmount = receiveBigNumber.isNaN() || !receiveBigNumber.isFinite() ? '0' : receiveBigNumber.toString(10)
// Format the "Receive at least" input amount same as PriceSuggestions price
receiveAmount =
receiveBigNumber.isNaN() || !receiveBigNumber.isFinite() ? '0' : formatPriceToPrecision(receiveBigNumber)
}
}

Expand Down
45 changes: 29 additions & 16 deletions src/components/trade/PriceSuggestions/PriceSuggestionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,55 +20,68 @@ export interface Props {
}

interface FormattedPrices {
priceFormatted: string
invertedPriceFormatted: string
priceLabel: string
inversePriceLabel: string
priceValue: string
inversePriceValue: string
}

function formatPriceToPrecision(price: BigNumber): string {
return price.toFixed(PRICE_ESTIMATION_PRECISION)
const LOW_PRICE_FLOOR = new BigNumber('0.0001')

export function formatPriceToPrecision(price: BigNumber): string {
return price.gt(LOW_PRICE_FLOOR) ? price.toFixed(PRICE_ESTIMATION_PRECISION) : '< ' + LOW_PRICE_FLOOR.toString()
}

function getPriceFormatted(price: BigNumber | null, isPriceInverted: boolean): FormattedPrices {
if (price) {
const invertedPriceFormattedAux = formatPriceToPrecision(invertPrice(price))
const priceFormattedAux = formatPriceToPrecision(price)
const inversePriceLabel = formatPriceToPrecision(invertPrice(price))
const priceLabel = formatPriceToPrecision(price)
const inversePriceValue = invertPrice(price).toString(10)
const priceValue = price.toString(10)

if (isPriceInverted) {
// Price is inverted
return {
priceFormatted: invertedPriceFormattedAux,
invertedPriceFormatted: priceFormattedAux,
priceLabel: inversePriceLabel,
inversePriceLabel: priceLabel,
priceValue: inversePriceValue,
inversePriceValue: priceValue,
}
} else {
// Price is not inverted
return {
priceFormatted: priceFormattedAux,
invertedPriceFormatted: invertedPriceFormattedAux,
priceLabel,
inversePriceLabel,
priceValue,
inversePriceValue,
}
}
} else {
return {
priceFormatted: 'N/A',
invertedPriceFormatted: 'N/A',
priceLabel: 'N/A',
inversePriceLabel: 'N/A',
priceValue: 'N/A',
inversePriceValue: 'N/A',
}
}
}

export const PriceSuggestionItem: React.FC<Props> = (props) => {
const { label, isPriceInverted, price, loading, baseToken, quoteToken, onSwapPrices, onClickPrice } = props

const { priceFormatted, invertedPriceFormatted } = getPriceFormatted(price, isPriceInverted)
const displayPrice = priceFormatted === 'Infinity' || invertedPriceFormatted === 'Infinity' ? 'N/A' : priceFormatted

// Return raw, unformatted values to pass to price calculations
const { priceValue, inversePriceValue, priceLabel, inversePriceLabel } = getPriceFormatted(price, isPriceInverted)
const displayPrice = priceLabel === 'Infinity' || inversePriceLabel === 'Infinity' ? 'N/A' : priceLabel
return (
<>
<span>
<span>{label}</span>{' '}
</span>
<button
type="button"
title={isPriceInverted ? inversePriceValue : priceValue}
disabled={loading || displayPrice === 'N/A'}
onClick={(): void => onClickPrice(priceFormatted, invertedPriceFormatted)}
onClick={(): void => onClickPrice(priceValue, inversePriceValue)}
>
{loading ? <Spinner /> : displayPrice}
</button>
Expand Down

0 comments on commit 378fcdb

Please sign in to comment.