layout changes and est price impact

This commit is contained in:
saml33 2021-10-01 00:21:45 +10:00
parent 71945ff9ce
commit b38fc8594d
7 changed files with 239 additions and 167 deletions

View File

@ -2,6 +2,7 @@ import { FunctionComponent } from 'react'
interface ButtonGroupProps {
activeValue: string
className?: string
onChange: (x) => void
unit?: string
values: Array<string>
@ -9,6 +10,7 @@ interface ButtonGroupProps {
const ButtonGroup: FunctionComponent<ButtonGroupProps> = ({
activeValue,
className,
unit,
values,
onChange,
@ -29,7 +31,7 @@ const ButtonGroup: FunctionComponent<ButtonGroupProps> = ({
) : null}
{values.map((v, i) => (
<button
className={`cursor-pointer default-transition font-normal px-2 py-1.5 relative rounded-md text-center text-xs w-1/2
className={`${className} cursor-pointer default-transition font-normal px-2 py-1.5 relative rounded-md text-center text-xs w-1/2
${
v === activeValue
? `text-th-primary`

View File

@ -22,10 +22,10 @@ import Tooltip from '../Tooltip'
import OrderSideTabs from './OrderSideTabs'
import { ElementTitle } from '../styles'
import ButtonGroup from '../ButtonGroup'
import SlippageWarning from './SlippageWarning'
import Checkbox from '../Checkbox'
import { useViewport } from '../../hooks/useViewport'
import { breakpoints } from '../TradePageGrid'
import EstPriceImpact from './EstPriceImpact'
interface AdvancedTradeFormProps {
initLeverage?: number
@ -72,10 +72,12 @@ export default function AdvancedTradeForm({
const isMarketOrder = ['Market', 'Stop Loss', 'Take Profit'].includes(
tradeType
)
const isTriggerLimit = ['Stop Limit', 'Take Profit Limit'].includes(tradeType)
const isTriggerOrder = [
'Stop Loss',
'Stop Limit',
'Take Profit',
'Stop Limit',
'Take Profit Limit',
].includes(tradeType)
@ -530,46 +532,39 @@ export default function AdvancedTradeForm({
</span>
</ElementTitle>
<OrderSideTabs onChange={onChangeSide} side={side} />
<div className="grid grid-cols-12 md:gap-2 text-left">
<div className="col-span-12 md:col-span-2 flex items-center">
<label className="text-xxs md:text-xs text-th-fgd-3">Type</label>
</div>
<div className="col-span-12 md:col-span-10 pb-2 md:pb-0">
<div className="grid grid-cols-12 gap-2 text-left">
<div className="col-span-12 md:col-span-6">
<label className="text-xxs text-th-fgd-3">Type</label>
<TradeType
onChange={onTradeTypeChange}
value={tradeType}
offerTriggers={isPerpMarket}
/>
</div>
<div className="col-span-12 md:col-span-2 flex items-center">
<label className="text-xxs md:text-xs text-th-fgd-3">Price</label>
</div>
<div className="col-span-12 md:col-span-10 pb-2 md:pb-0">
<Input
type="number"
min="0"
step={tickSize}
onChange={(e) => onSetPrice(e.target.value)}
value={price}
disabled={isMarketOrder}
placeholder={tradeType === 'Market' ? markPrice : null}
prefix={
<img
src={`/assets/icons/${groupConfig.quoteSymbol.toLowerCase()}.svg`}
width="16"
height="16"
<div className="col-span-12 md:col-span-6">
{!isTriggerOrder ? (
<>
<label className="text-xxs text-th-fgd-3">Price</label>
<Input
type="number"
min="0"
step={tickSize}
onChange={(e) => onSetPrice(e.target.value)}
value={price}
disabled={isMarketOrder}
placeholder={tradeType === 'Market' ? markPrice : null}
prefix={
<img
src={`/assets/icons/${groupConfig.quoteSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
}
/>
</div>
{isTriggerOrder && (
<>
<div className="col-span-12 md:col-span-2 flex items-center">
<label className="text-xxs md:text-xs text-th-fgd-3">
Trigger Price
</label>
</div>
<div className="col-span-12 md:col-span-10 pb-2 md:pb-0">
</>
) : (
<>
<label className="text-xxs text-th-fgd-3">Trigger Price</label>
<Input
type="number"
min="0"
@ -584,47 +579,65 @@ export default function AdvancedTradeForm({
/>
}
/>
</>
)}
</div>
{isTriggerLimit && (
<>
<div className="col-span-12">
<label className="text-xxs text-th-fgd-3">Price</label>
<Input
type="number"
min="0"
step={tickSize}
onChange={(e) => onSetPrice(e.target.value)}
value={price}
prefix={
<img
src={`/assets/icons/${groupConfig.quoteSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
</div>
</>
)}
<div className="col-span-12 md:col-span-2 flex items-center">
<label className="text-xxs md:text-xs text-th-fgd-3">Size</label>
<div className="col-span-6">
<label className="text-xxs text-th-fgd-3">Size</label>
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetBaseSize(e.target.value)}
value={baseSize}
prefix={
<img
src={`/assets/icons/${marketConfig.baseSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
</div>
<div className="col-span-12 md:col-span-10 pb-2 md:pb-0">
<Input.Group className="-mb-1">
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetBaseSize(e.target.value)}
value={baseSize}
wrapperClassName="mr-0.5 w-1/2"
prefix={
<img
src={`/assets/icons/${marketConfig.baseSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetQuoteSize(e.target.value)}
value={quoteSize}
wrapperClassName="ml-0.5 w-1/2"
prefix={
<img
src={`/assets/icons/${groupConfig.quoteSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
</Input.Group>
<div className="col-span-6">
<label className="text-xxs text-th-fgd-3">Quantity</label>
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetQuoteSize(e.target.value)}
value={quoteSize}
prefix={
<img
src={`/assets/icons/${groupConfig.quoteSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
</div>
<div className="col-span-12 md:col-span-10 md:col-start-3">
<div className="col-span-12 -mt-1">
<ButtonGroup
activeValue={positionSizePercent}
onChange={(p) => handleSetPositionSize(p)}
@ -719,6 +732,11 @@ export default function AdvancedTradeForm({
</div>
) : null}
</div>
{tradeType === 'Market' ? (
<div className="col-span-12 md:col-span-10 md:col-start-3 pt-2">
<EstPriceImpact />
</div>
) : null}
<div className={`flex pt-4`}>
{ipAllowed ? (
<Button
@ -774,11 +792,6 @@ export default function AdvancedTradeForm({
</Button>
)}
</div>
{tradeType === 'Market' ? (
<div className="col-span-12 md:col-span-10 md:col-start-3 pt-2">
<SlippageWarning slippage={0.2} />
</div>
) : null}
<div className="flex text-xs text-th-fgd-4 pt-4">
<MarketFee />
</div>

View File

@ -0,0 +1,82 @@
import { InformationCircleIcon } from '@heroicons/react/outline'
import Tippy from '@tippyjs/react'
import 'tippy.js/animations/scale.css'
const priceImpact = {
slippage: [10.1, 0.2],
makerFee: [0.0, 0.0],
takerFee: [2.3, 0.13],
}
const EstPriceImpact = () => {
const priceImpactTotal = Object.values(priceImpact).reduce(
(t, c) => t + c[0],
0
)
const priceImpactPercent =
Object.values(priceImpact).reduce((t, c) => t + c[1], 0) / 3
return (
<div
className={`border-t border-th-bkg-4 flex items-center justify-center mt-2 pt-2 text-th-fgd-3 text-xs`}
>
Est. Price Impact:
<span
className={`font-bold ml-2 ${
priceImpactPercent <= 0.5
? 'text-th-green'
: priceImpactPercent > 0.5 && priceImpactPercent <= 2
? 'text-th-orange'
: 'text-th-red'
}`}
>
${priceImpactTotal.toFixed(2)}
<span className="mx-2 text-th-fgd-4">|</span>
{priceImpactPercent.toFixed(2)}%
</span>
<Tippy
animation="scale"
placement="top"
appendTo={() => document.body}
maxWidth="20rem"
interactive
delay={0}
content={
<div
className={`rounded p-4 text-xs bg-th-bkg-3 leading-4 shadow-md text-th-fgd-3 outline-none space-y-1.5 w-56 focus:outline-none`}
>
<div className="flex justify-between">
Est. Slippage:
<span className="text-th-fgd-1">
${priceImpact.slippage[0]}
<span className="px-1 text-th-fgd-4">|</span>
{priceImpact.slippage[1]}%
</span>
</div>
<div className="flex justify-between">
Maker Fee:
<span className="text-th-fgd-1">
${priceImpact.makerFee[0]}
<span className="px-1 text-th-fgd-4">|</span>
{priceImpact.makerFee[1]}%
</span>
</div>
<div className="flex justify-between">
Taker Fee:
<span className="text-th-fgd-1">
${priceImpact.takerFee[0]}
<span className="px-1 text-th-fgd-4">|</span>
{priceImpact.takerFee[1]}%
</span>
</div>
</div>
}
>
<div className="outline-none focus:outline-none">
<InformationCircleIcon className="h-5 w-5 ml-2 text-th-primary" />
</div>
</Tippy>
</div>
)
}
export default EstPriceImpact

View File

@ -15,7 +15,7 @@ const OrderSideTabs: FunctionComponent<OrderSideTabsProps> = ({
}) => {
const market = useMangoStore((s) => s.selectedMarket.current)
return (
<div className={`border-b border-th-fgd-4 mb-2 md:mb-4 relative`}>
<div className={`border-b border-th-fgd-4 mb-3 relative`}>
<div
className={`absolute ${
side === 'buy'

View File

@ -21,7 +21,7 @@ import ButtonGroup from '../ButtonGroup'
import Checkbox from '../Checkbox'
import OrderSideTabs from './OrderSideTabs'
import Tooltip from '../Tooltip'
import SlippageWarning from './SlippageWarning'
import EstPriceImpact from './EstPriceImpact'
export default function SimpleTradeForm({ initLeverage }) {
const set = useMangoStore((s) => s.set)
@ -425,20 +425,17 @@ export default function SimpleTradeForm({ initLeverage }) {
</ElementTitle>
<OrderSideTabs isSimpleForm onChange={setSide} side={side} />
<div className="grid grid-cols-12 gap-2 text-left">
<div className="col-span-2 flex items-center">
<label className="text-xs text-th-fgd-3">Type</label>
</div>
<div className="col-span-10">
<div className="col-span-6">
<label className="text-xxs text-th-fgd-3">Type</label>
<ButtonGroup
activeValue={tradeType}
className="h-10"
onChange={(p) => onTradeTypeChange(p)}
values={['Limit', 'Market']}
/>
</div>
<div className="col-span-2 flex items-center">
<label className="text-xs text-th-fgd-3">Price</label>
</div>
<div className="col-span-10">
<div className="col-span-6">
<label className="text-xxs text-th-fgd-3">Price</label>
<Input
type="number"
min="0"
@ -456,50 +453,49 @@ export default function SimpleTradeForm({ initLeverage }) {
}
/>
</div>
<div className="col-span-2 flex items-center">
<label className="text-xs text-th-fgd-3">Size</label>
</div>
<div className="col-span-10">
<Input.Group className="-mb-1">
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetBaseSize(e.target.value)}
value={baseSize}
wrapperClassName="mr-0.5 w-1/2"
prefix={
<img
src={`/assets/icons/${marketConfig.baseSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetQuoteSize(e.target.value)}
value={quoteSize}
wrapperClassName="ml-0.5 w-1/2"
prefix={
<img
src={`/assets/icons/${groupConfig.quoteSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
</Input.Group>
</div>
<div className="col-span-10 col-start-3 pb-2">
<ButtonGroup
activeValue={positionSizePercent}
onChange={(p) => handleSetPositionSize(p)}
unit="%"
values={['10', '25', '50', '75', '100']}
<div className="col-span-6">
<label className="text-xxs text-th-fgd-3">Size</label>
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetBaseSize(e.target.value)}
value={baseSize}
prefix={
<img
src={`/assets/icons/${marketConfig.baseSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
</div>
<div className="col-span-6">
<label className="text-xxs text-th-fgd-3">Quantity</label>
<Input
type="number"
min="0"
step={minOrderSize}
onChange={(e) => onSetQuoteSize(e.target.value)}
value={quoteSize}
prefix={
<img
src={`/assets/icons/${groupConfig.quoteSymbol.toLowerCase()}.svg`}
width="16"
height="16"
/>
}
/>
</div>
<div className="col-span-12">
<div className="-mt-1">
<ButtonGroup
activeValue={positionSizePercent}
onChange={(p) => handleSetPositionSize(p)}
unit="%"
values={['10', '25', '50', '75', '100']}
/>
</div>
{side === 'sell' ? (
<div className="text-th-fgd-3 text-xs tracking-normal mt-2">
<span>{roundedDeposits > 0 ? closeDepositString : null}</span>
@ -514,7 +510,7 @@ export default function SimpleTradeForm({ initLeverage }) {
<div
className={`${
showStopForm ? 'bg-th-bkg-4' : 'bg-th-bkg-3'
} mt-2 p-2 rounded-md w-1/2`}
} mt-1 p-2 rounded-md w-1/2`}
>
<Checkbox
checked={showStopForm}
@ -528,7 +524,7 @@ export default function SimpleTradeForm({ initLeverage }) {
<div
className={`${
showTakeProfitForm ? 'bg-th-bkg-4' : 'bg-th-bkg-3'
} mt-2 p-2 rounded-md w-1/2`}
} mt-1 p-2 rounded-md w-1/2`}
>
<Checkbox
checked={showTakeProfitForm}
@ -542,10 +538,8 @@ export default function SimpleTradeForm({ initLeverage }) {
</div>
{showStopForm && !hideProfitStop ? (
<>
<div className="col-span-2 flex items-center">
<label className="text-xs text-th-fgd-3">Stop Price</label>
</div>
<div className="col-span-10 -mb-1">
<div className="col-span-12">
<label className="text-xxs text-th-fgd-3">Stop Price</label>
<Input
type="number"
min="0"
@ -561,7 +555,7 @@ export default function SimpleTradeForm({ initLeverage }) {
}
/>
</div>
<div className="col-span-10 col-start-3 pb-2">
<div className="col-span-12 -mt-1">
<ButtonGroup
activeValue={stopSizePercent}
onChange={(p) => setStopSizePercent(p)}
@ -572,12 +566,10 @@ export default function SimpleTradeForm({ initLeverage }) {
) : null}
{showTakeProfitForm && !hideProfitStop ? (
<>
<div className="col-span-2 flex items-center">
<div className="col-span-12">
<label className="text-left text-xs text-th-fgd-3">
Profit Price
</label>
</div>
<div className="col-span-10 -mb-1">
<Input
type="number"
min="0"
@ -593,7 +585,7 @@ export default function SimpleTradeForm({ initLeverage }) {
}
/>
</div>
<div className="col-span-10 col-start-3 pb-2">
<div className="col-span-12 -mt-1">
<ButtonGroup
activeValue={stopSizePercent}
onChange={(p) => setStopSizePercent(p)}
@ -602,7 +594,7 @@ export default function SimpleTradeForm({ initLeverage }) {
</div>
</>
) : null}
<div className="col-span-10 col-start-3 flex">
<div className="col-span-12 flex pt-2">
{tradeType === 'Limit' ? (
<>
<div className="mr-4">
@ -666,7 +658,12 @@ export default function SimpleTradeForm({ initLeverage }) {
</Tooltip>
) : null}
</div>
<div className={`col-span-10 col-start-3 flex pt-2`}>
{tradeType === 'Market' ? (
<div className="col-span-12">
<EstPriceImpact />
</div>
) : null}
<div className={`col-span-12 flex pt-2`}>
{ipAllowed ? (
<Button
disabled={disabledTradeButton}
@ -707,12 +704,7 @@ export default function SimpleTradeForm({ initLeverage }) {
</Button>
)}
</div>
{tradeType === 'Market' ? (
<div className="col-span-10 col-start-3">
<SlippageWarning slippage={0.2} />
</div>
) : null}
<div className="col-span-10 col-start-3 flex pt-2 text-xs text-th-fgd-4">
<div className="col-span-12 flex pt-2 text-xs text-th-fgd-4">
<MarketFee />
</div>
</div>

View File

@ -1,17 +0,0 @@
const SlippageWarning = ({ slippage }) => {
return (
<div
className={`font-bold ${
slippage <= 0.5
? 'text-th-green'
: slippage > 0.5 && slippage <= 2
? 'text-th-orange'
: 'text-th-red'
} pt-2 rounded-md text-center text-th-fgd-3 text-xs`}
>
{slippage}% expected slippage
</div>
)
}
export default SlippageWarning

View File

@ -22,7 +22,7 @@ const TradeType = ({
{({ open }) => (
<>
<Listbox.Button
className={`font-normal h-full w-full bg-th-bkg-1 border border-th-fgd-4 p-2 hover:border-th-primary rounded-md focus:outline-none focus:border-th-primary`}
className={`font-normal w-full bg-th-bkg-1 border border-th-fgd-4 px-2 h-10 hover:border-th-primary rounded-md focus:outline-none focus:border-th-primary`}
>
<div className={`flex items-center justify-between space-x-4`}>
<span>{value}</span>