Skip to content

Commit

Permalink
Merge pull request #1209 from bancorprotocol/unknown-market-price-war…
Browse files Browse the repository at this point in the history
…ning

Show unknown market price warning
  • Loading branch information
tiagofilipenunes committed May 15, 2024
2 parents 092f84f + d41f5f0 commit 1d9dc54
Show file tree
Hide file tree
Showing 18 changed files with 85 additions and 97 deletions.
4 changes: 2 additions & 2 deletions src/components/common/TokenInputField/Slippage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface Props {

const slippageColor = (slippage: SafeDecimal) => {
if (slippage?.gt(0)) return 'text-primary';
if (slippage?.isZero()) return 'text-error';
if (slippage?.isZero()) return 'text-warning';
if (slippage?.lt(-3)) return 'text-error';
return 'text-white/80';
};
Expand All @@ -29,7 +29,7 @@ export const Slippage: FC<Props> = ({ slippage }) => {
{slippage?.eq(0) && <IconWarning className="size-12" />}
{slippage?.gt(0) && <>(+{slippageValue}%)</>}
{slippage?.lt(0) && <>(-{slippageValue}%)</>}
{slippage?.eq(0) && <>Notice: price & slippage are unknown</>}
{slippage?.isZero() && <>Notice: price & slippage are unknown</>}
{slippage.lt(-3) && <IconWarning className="size-12" />}
</span>
</Tooltip>
Expand Down
7 changes: 3 additions & 4 deletions src/components/debug/DebugCreateStrategy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import { useQueryClient } from '@tanstack/react-query';
import { useModal } from 'hooks/useModal';
import { Input, Label } from 'components/common/inputField';
import { Checkbox } from 'components/common/Checkbox/Checkbox';
import { useFiatCurrency } from 'hooks/useFiatCurrency';
import { getMarketPrice } from 'hooks/useMarketPrice';
import { useMarketPrice } from 'hooks/useMarketPrice';
import { calculateOverlappingPrices } from '@bancor/carbon-sdk/strategy-management';

const TOKENS = FAUCET_TOKENS.map((tkn) => ({
Expand Down Expand Up @@ -63,7 +62,6 @@ export const DebugCreateStrategy = () => {
const baseSymbol = selectedTokens?.[0]?.symbol ?? '';
const quoteSymbol = selectedTokens?.[1]?.symbol ?? '';

const { selectedFiatCurrency } = useFiatCurrency();
const balanceQueries = useGetTokenBalances(selectedTokens);

const perRound = 1;
Expand Down Expand Up @@ -130,7 +128,8 @@ export const DebugCreateStrategy = () => {
},
};
if (spread) {
const price = await getMarketPrice(base, quote, selectedFiatCurrency);
const price = useMarketPrice({ base, quote });
if (!price) throw new Error('price is undefined');
const params = calculateOverlappingPrices(
buyMin,
sellMax,
Expand Down
4 changes: 2 additions & 2 deletions src/components/strategies/UserMarketPrice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createContext, FC, ReactNode, useContext } from 'react';

interface Props {
children: ReactNode;
marketPrice: number;
marketPrice?: number;
}

export const UserMarketContext = createContext(0);
Expand All @@ -21,7 +21,7 @@ interface MarketPriceProps {
base?: Token;
quote?: Token;
}
/** Use external market price or */
/** Use external market price or user price */
export const useUserMarketPrice = ({ base, quote }: MarketPriceProps) => {
const externalMarketPrice = useMarketPrice({ base, quote });
const userMarketPrice = useContext(UserMarketContext);
Expand Down
4 changes: 2 additions & 2 deletions src/components/strategies/create/BuySellBlock/InputLimit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const InputLimit: FC<InputLimitProps> = ({
)}
data-testid="input-price"
/>
{marketPrice !== 0 && (
{!!marketPrice && (
<button
className="text-12 font-weight-500 text-primary hover:text-primary-light focus:text-primary-light active:text-primary"
type="button"
Expand All @@ -110,7 +110,7 @@ export const InputLimit: FC<InputLimitProps> = ({
</button>
)}
</div>
{marketPrice !== 0 && (
{!!marketPrice && (
<p className="flex flex-wrap items-center gap-8">
<span className="text-12 break-all text-white/60">
{fiatAsString}
Expand Down
8 changes: 4 additions & 4 deletions src/components/strategies/create/BuySellBlock/InputRange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export const InputRange: FC<InputRangeProps> = ({
>
<label htmlFor={inputMinId}>{minLabel}</label>
</Tooltip>
{marketPrice !== 0 && (
{!!marketPrice && (
<button
className="text-12 font-weight-500 text-primary hover:text-primary-light focus:text-primary-light active:text-primary"
type="button"
Expand All @@ -136,7 +136,7 @@ export const InputRange: FC<InputRangeProps> = ({
onBlur={handleBlurMin}
data-testid="input-min"
/>
{marketPrice !== 0 && (
{!!marketPrice && (
<p className="flex flex-wrap items-center gap-4">
<span className="text-12 break-all text-white/60">
{getFiatAsString(min)}
Expand Down Expand Up @@ -169,7 +169,7 @@ export const InputRange: FC<InputRangeProps> = ({
>
<label htmlFor={inputMaxId}>{maxLabel}</label>
</Tooltip>
{marketPrice !== 0 && (
{!!marketPrice && (
<button
className="text-12 font-weight-500 text-primary hover:text-primary-light focus:text-primary-light active:text-primary"
type="button"
Expand All @@ -195,7 +195,7 @@ export const InputRange: FC<InputRangeProps> = ({
onBlur={handleBlurMax}
data-testid="input-max"
/>
{marketPrice !== 0 && (
{!!marketPrice && (
<div className="flex flex-wrap items-center gap-4">
<p className="text-12 break-all text-white/60">
{getFiatAsString(max)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { OrderCreate } from 'components/strategies/create/useOrder';
import { InputLimit } from 'components/strategies/create/BuySellBlock/InputLimit';
import { InputRange } from 'components/strategies/create/BuySellBlock/InputRange';
import { useMarketIndication } from 'components/strategies/marketPriceIndication/useMarketIndication';
import { useMarketPrice } from 'hooks/useMarketPrice';

type Props = {
base: Token;
Expand Down Expand Up @@ -33,16 +34,23 @@ export const LimitRangeSection: FC<Props> = ({
const overlappingOrdersPricesMessage =
'Notice: your Buy and Sell orders overlap';

const warningMarketPriceUnknownMessage =
'Notice: price & slippage are unknown';

const warningMarketPriceMessage = buy
? `Notice: you offer to buy ${base.symbol} above current market price`
: `Notice: you offer to sell ${base.symbol} below current market price`;

const marketPrice = useMarketPrice({ base, quote });
const isMarketPriceUnknown = !marketPrice;

const getWarnings = () => {
let warnings = [];
if (isOrdersOverlap && !isOrdersReversed)
warnings.push(overlappingOrdersPricesMessage);
if (isOrderAboveOrBelowMarketPrice)
warnings.push(warningMarketPriceMessage);
if (isMarketPriceUnknown) warnings.push(warningMarketPriceUnknownMessage);
return warnings;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,7 @@ export const CreateOverlappingStrategy: FC<OverlappingStrategyProps> = (
{...props}
order0={order0}
order1={order1}
externalPrice={externalPrice}
marketPrice={marketPrice}
marketPricePercentage={marketPricePercentage}
setMin={setMin}
setMax={setMax}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
isMinAboveMarket,
isOverlappingBudgetTooSmall,
} from '../../overlapping/utils';
import { useMarketIndication } from 'components/strategies/marketPriceIndication';
import { OrderCreate } from 'components/strategies/create/useOrder';
import { ReactComponent as IconAction } from 'assets/icons/action.svg';
import { ReactComponent as IconLink } from 'assets/icons/link.svg';
Expand Down Expand Up @@ -42,13 +41,6 @@ export const DepositOverlappingStrategy: FC<Props> = (props) => {
const oldMarketPrice = geoMean(order0.marginalPrice, order1.marginalPrice);

const spread = getRoundedSpread(strategy);
const min = order0.min;
const max = order1.max;
const { marketPricePercentage } = useMarketIndication({
base,
quote,
order: { min, max, price: '', isRange: true },
});

const aboveMarket = isMinAboveMarket(order0);
const belowMarket = isMaxBelowMarket(order1);
Expand Down Expand Up @@ -152,9 +144,8 @@ export const DepositOverlappingStrategy: FC<Props> = (props) => {
quote={quote}
order0={order0}
order1={order1}
marketPrice={externalMarketPrice}
marketPrice={oldMarketPrice?.toNumber()}
spread={spread}
marketPricePercentage={marketPricePercentage}
disabled
/>
</article>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface Props {
strategy: Strategy;
order0: OrderCreate;
order1: OrderCreate;
marketPrice: string;
marketPrice?: string;
anchoredOrder: 'buy' | 'sell';
setAnchoredOrder: (value: 'buy' | 'sell') => any;
setBuyBudget: (sellBudget: string, min: string, max: string) => any;
Expand Down Expand Up @@ -62,9 +62,11 @@ export const EditOverlappingStrategyBudget: FC<Props> = (props) => {

// We need to use external market price for the initial state in case of dust
const disableBuy =
minAboveMarket || new SafeDecimal(order0.min).gt(marketPrice);
minAboveMarket ||
(!!marketPrice && new SafeDecimal(order0.min).gt(marketPrice));
const disableSell =
maxBelowMarket || new SafeDecimal(order1.max).lt(marketPrice);
maxBelowMarket ||
(!!marketPrice && new SafeDecimal(order1.max).lt(marketPrice));

const quoteBalanceChange = balanceChange(
strategy.order0.balance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface Props {
export const EditPriceOverlappingStrategy: FC<Props> = (props) => {
const { strategy, order0, order1 } = props;
const { base, quote } = strategy;
const marketPrice = useMarketPrice({ base, quote }).toString();
const marketPrice = useMarketPrice({ base, quote })?.toString();
const { marketPricePercentage } = useMarketIndication({
base,
quote,
Expand All @@ -56,7 +56,7 @@ export const EditPriceOverlappingStrategy: FC<Props> = (props) => {
quote.decimals,
buyMin,
sellMax,
marketPrice,
marketPrice || '0',
spread.toString(),
sellBudget
);
Expand All @@ -75,7 +75,7 @@ export const EditPriceOverlappingStrategy: FC<Props> = (props) => {
quote.decimals,
buyMin,
sellMax,
marketPrice,
marketPrice || '0',
spread.toString(),
buyBudget
);
Expand All @@ -92,7 +92,7 @@ export const EditPriceOverlappingStrategy: FC<Props> = (props) => {
const prices = calculateOverlappingPrices(
min,
max,
marketPrice,
marketPrice || '0',
spread.toString()
);

Expand Down Expand Up @@ -129,7 +129,7 @@ export const EditPriceOverlappingStrategy: FC<Props> = (props) => {

// Initialize order when market price is available
useEffect(() => {
if (!quote || !base || +marketPrice <= 0) return;
if (!quote || !base || !marketPrice) return;
if (!mounted) return setMounted(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [marketPrice, spread]);
Expand Down Expand Up @@ -177,7 +177,6 @@ export const EditPriceOverlappingStrategy: FC<Props> = (props) => {
order1={order1}
marketPrice={marketPrice}
spread={spread}
marketPricePercentage={marketPricePercentage}
setMin={setMin}
setMax={setMax}
/>
Expand Down
4 changes: 2 additions & 2 deletions src/components/strategies/edit/overlapping/MarketWarning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { FC } from 'react';
import { ReactComponent as IconWarning } from 'assets/icons/warning.svg';

interface Props {
externalMarketPrice: number;
externalMarketPrice?: number;
oldMarketPrice?: SafeDecimal;
}
export const MarketWarning: FC<Props> = (props) => {
const { externalMarketPrice, oldMarketPrice } = props;
if (!oldMarketPrice) return <></>;
if (!oldMarketPrice || !externalMarketPrice) return <></>;
const delta = new SafeDecimal(externalMarketPrice)
.div(oldMarketPrice)
.minus(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
isMinAboveMarket,
isOverlappingBudgetTooSmall,
} from '../../overlapping/utils';
import { useMarketIndication } from 'components/strategies/marketPriceIndication';
import { OrderCreate } from 'components/strategies/create/useOrder';
import { ReactComponent as IconAction } from 'assets/icons/action.svg';
import { ReactComponent as IconLink } from 'assets/icons/link.svg';
Expand Down Expand Up @@ -42,13 +41,6 @@ export const WithdrawOverlappingStrategy: FC<Props> = (props) => {
const oldMarketPrice = geoMean(order0.marginalPrice, order1.marginalPrice)!;

const spread = getRoundedSpread(strategy);
const min = order0.min;
const max = order1.max;
const { marketPricePercentage } = useMarketIndication({
base,
quote,
order: { min, max, price: '', isRange: true },
});
const budgetTooSmall = isOverlappingBudgetTooSmall(order0, order1);
const buyBudgetId = useId();
const sellBudgetId = useId();
Expand Down Expand Up @@ -153,9 +145,8 @@ export const WithdrawOverlappingStrategy: FC<Props> = (props) => {
quote={quote}
order0={order0}
order1={order1}
marketPrice={externalMarketPrice}
marketPrice={oldMarketPrice?.toNumber()}
spread={spread}
marketPricePercentage={marketPricePercentage}
disabled
/>
</article>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,19 @@ export const useMarketIndication = ({
buy = false,
}: UseMarketIndicationProps) => {
const marketPrice = useUserMarketPrice({ base, quote });
const marketPriceNotZero = +marketPrice > 0;
const isOrderAboveOrBelowMarketPrice = useMemo(() => {
if (order.isRange) {
const min = new SafeDecimal(order.min);
const max = new SafeDecimal(order.max);
const isInputNotZero = buy ? max.gt(0) : min.gt(0);
if (!isInputNotZero || !marketPriceNotZero) return false;
if (!isInputNotZero || !marketPrice) return false;
return buy ? max.gt(marketPrice) : min.lt(marketPrice);
} else {
const price = new SafeDecimal(order.price);
if (!price.gt(0) || !marketPriceNotZero) return false;
if (!price.gt(0) || !marketPrice) return false;
return buy ? price.gt(marketPrice) : price.lt(marketPrice);
}
}, [
order.isRange,
order.price,
order.max,
order.min,
buy,
marketPrice,
marketPriceNotZero,
]);
}, [order.isRange, order.price, order.max, order.min, buy, marketPrice]);

const marketPricePercentage = useMemo(
() => ({
Expand All @@ -68,10 +59,10 @@ export const useMarketIndication = ({

export const marketPricePercent = (
price: string,
marketPrice: string | number
marketPrice?: string | number
) => {
const value = new SafeDecimal(price || 0);
if (value.eq(0)) return value;
if (+marketPrice === 0) return new SafeDecimal(0);
if (!marketPrice) return new SafeDecimal(0);
return new SafeDecimal(value).minus(marketPrice).div(marketPrice).times(100);
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { WarningMessageWithIcon } from 'components/common/WarningMessageWithIcon
interface Props {
base: Token;
quote: Token;
externalPrice: number;
externalPrice?: number;
marketPrice: string;
setMarketPrice: (price: string) => void;
}
Expand Down

0 comments on commit 1d9dc54

Please sign in to comment.