add trade page swap summary details
This commit is contained in:
parent
e5945b60e2
commit
848286d947
|
@ -233,6 +233,7 @@ const useQuoteRoutes = ({
|
|||
cacheTime: 1000 * 60,
|
||||
staleTime: 1000 * 3,
|
||||
enabled: enabled ? enabled() : amount ? true : false,
|
||||
refetchInterval: 20000,
|
||||
retry: 3,
|
||||
}
|
||||
)
|
||||
|
|
|
@ -19,6 +19,7 @@ import Button from '@components/shared/Button'
|
|||
import Image from 'next/image'
|
||||
import useQuoteRoutes from '@components/swap/useQuoteRoutes'
|
||||
import {
|
||||
HealthType,
|
||||
Serum3Market,
|
||||
fetchJupiterTransaction,
|
||||
} from '@blockworks-foundation/mango-v4'
|
||||
|
@ -31,6 +32,10 @@ import SwapSlider from '@components/swap/SwapSlider'
|
|||
import PercentageSelectButtons from '@components/swap/PercentageSelectButtons'
|
||||
import { SIZE_INPUT_UI_KEY } from 'utils/constants'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import MaxSwapAmount from '@components/swap/MaxSwapAmount'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
import HealthImpact from '@components/shared/HealthImpact'
|
||||
import Tooltip from '@components/shared/Tooltip'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
const slippage = 100
|
||||
|
@ -44,8 +49,9 @@ function stringToNumberOrZero(s: string): number {
|
|||
}
|
||||
|
||||
export default function SpotMarketOrderSwapForm() {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const { t } = useTranslation()
|
||||
const { baseSize, price, quoteSize, side } = mangoStore((s) => s.tradeForm)
|
||||
const { isUnownedAccount } = useUnownedAccount()
|
||||
const [placingOrder, setPlacingOrder] = useState(false)
|
||||
const { ipAllowed, ipCountry } = useIpAddress()
|
||||
const { connected, publicKey } = useWallet()
|
||||
|
@ -64,8 +70,6 @@ export default function SpotMarketOrderSwapForm() {
|
|||
const handleBaseSizeChange = useCallback(
|
||||
(e: NumberFormatValues, info: SourceInfo) => {
|
||||
if (info.source !== 'event') return
|
||||
console.log('base size change')
|
||||
|
||||
set((s) => {
|
||||
const price =
|
||||
s.tradeForm.tradeType === 'Market'
|
||||
|
@ -103,12 +107,8 @@ export default function SpotMarketOrderSwapForm() {
|
|||
[oraclePrice]
|
||||
)
|
||||
|
||||
console.log('side outer', side)
|
||||
|
||||
const setAmountFromSlider = useCallback(
|
||||
(amount: string) => {
|
||||
console.log('amount', amount)
|
||||
|
||||
if (side === 'buy') {
|
||||
handleQuoteSizeChange(
|
||||
{ value: amount } as NumberFormatValues,
|
||||
|
@ -121,7 +121,7 @@ export default function SpotMarketOrderSwapForm() {
|
|||
)
|
||||
}
|
||||
},
|
||||
[side]
|
||||
[side, handleBaseSizeChange, handleQuoteSizeChange]
|
||||
)
|
||||
|
||||
const [inputBank, outputBank] = useMemo(() => {
|
||||
|
@ -168,7 +168,6 @@ export default function SpotMarketOrderSwapForm() {
|
|||
const connection = mangoStore.getState().connection
|
||||
|
||||
if (!group || !mangoAccount) return
|
||||
console.log('placing order')
|
||||
|
||||
if (
|
||||
!mangoAccount ||
|
||||
|
@ -177,22 +176,10 @@ export default function SpotMarketOrderSwapForm() {
|
|||
!outputBank ||
|
||||
!publicKey ||
|
||||
!selectedRoute
|
||||
) {
|
||||
console.log(
|
||||
mangoAccount,
|
||||
group,
|
||||
inputBank,
|
||||
outputBank,
|
||||
publicKey,
|
||||
selectedRoute
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
setPlacingOrder(true)
|
||||
console.log('placing order 2')
|
||||
console.log('selected route', selectedRoute)
|
||||
|
||||
const [ixs, alts] = await fetchJupiterTransaction(
|
||||
connection,
|
||||
selectedRoute,
|
||||
|
@ -256,16 +243,61 @@ export default function SpotMarketOrderSwapForm() {
|
|||
connected ? handlePlaceOrder() : handleConnect()
|
||||
}
|
||||
|
||||
const maintProjectedHealth = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
if (!inputBank || !mangoAccount || !outputBank || !group) return 0
|
||||
|
||||
const simulatedHealthRatio =
|
||||
mangoAccount.simHealthRatioWithTokenPositionUiChanges(
|
||||
group,
|
||||
[
|
||||
{
|
||||
mintPk: inputBank.mint,
|
||||
uiTokenAmount:
|
||||
(side === 'buy'
|
||||
? stringToNumberOrZero(quoteSize)
|
||||
: stringToNumberOrZero(baseSize)) * -1,
|
||||
},
|
||||
{
|
||||
mintPk: outputBank.mint,
|
||||
uiTokenAmount:
|
||||
side === 'buy'
|
||||
? stringToNumberOrZero(baseSize)
|
||||
: stringToNumberOrZero(quoteSize),
|
||||
},
|
||||
],
|
||||
HealthType.maint
|
||||
)
|
||||
return simulatedHealthRatio > 100
|
||||
? 100
|
||||
: simulatedHealthRatio < 0
|
||||
? 0
|
||||
: Math.trunc(simulatedHealthRatio)
|
||||
}, [inputBank, outputBank, baseSize, quoteSize, side])
|
||||
|
||||
const disabled =
|
||||
(connected && (!baseSize || !price)) ||
|
||||
!serumOrPerpMarket ||
|
||||
parseFloat(baseSize) < serumOrPerpMarket.minOrderSize ||
|
||||
isLoading
|
||||
|
||||
const useMargin = true
|
||||
|
||||
return (
|
||||
<>
|
||||
<form onSubmit={(e) => handleSubmit(e)}>
|
||||
<div className="mt-3 px-3 md:px-4">
|
||||
<div className="mb-2 flex items-end justify-end">
|
||||
{!isUnownedAccount ? (
|
||||
<>
|
||||
<MaxSwapAmount
|
||||
useMargin={useMargin}
|
||||
setAmountIn={setAmountFromSlider}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="relative">
|
||||
<NumberFormat
|
||||
|
@ -337,20 +369,20 @@ export default function SpotMarketOrderSwapForm() {
|
|||
<div className="mt-6 mb-4 flex px-3 md:px-4">
|
||||
{swapFormSizeUi === 'slider' ? (
|
||||
<SwapSlider
|
||||
useMargin={true}
|
||||
useMargin={useMargin}
|
||||
amount={
|
||||
side === 'buy'
|
||||
? stringToNumberOrZero(quoteSize)
|
||||
: stringToNumberOrZero(baseSize)
|
||||
}
|
||||
onChange={(v) => setAmountFromSlider(v)}
|
||||
onChange={setAmountFromSlider}
|
||||
step={1 / 10 ** (inputBank?.mintDecimals || 6)}
|
||||
/>
|
||||
) : (
|
||||
<PercentageSelectButtons
|
||||
amountIn={side === 'buy' ? quoteSize : baseSize}
|
||||
setAmountIn={(v) => setAmountFromSlider(v)}
|
||||
useMargin={true}
|
||||
setAmountIn={setAmountFromSlider}
|
||||
useMargin={useMargin}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -403,6 +435,57 @@ export default function SpotMarketOrderSwapForm() {
|
|||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-2 px-3 md:px-4">
|
||||
<div className="">
|
||||
<HealthImpact maintProjectedHealth={maintProjectedHealth} small />
|
||||
</div>
|
||||
<div className="flex justify-between text-xs">
|
||||
<Tooltip
|
||||
content={
|
||||
<>
|
||||
<p>
|
||||
The price impact is the difference observed between the
|
||||
total value of the entry tokens swapped and the destination
|
||||
tokens obtained.
|
||||
</p>
|
||||
<p className="mt-1">
|
||||
The bigger the trade is, the bigger the price impact can be.
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<p className="tooltip-underline">{t('swap:price-impact')}</p>
|
||||
</Tooltip>
|
||||
<p className="text-right font-mono text-th-fgd-2">
|
||||
{selectedRoute
|
||||
? selectedRoute?.priceImpactPct * 100 < 0.1
|
||||
? '<0.1%'
|
||||
: `${(selectedRoute?.priceImpactPct * 100).toFixed(2)}%`
|
||||
: '-'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-xs">
|
||||
<p className="pr-2 text-th-fgd-3">{t('common:route')}</p>
|
||||
<div className="flex items-center overflow-hidden text-th-fgd-3">
|
||||
<div className="truncate whitespace-nowrap">
|
||||
{selectedRoute?.marketInfos.map((info, index) => {
|
||||
let includeSeparator = false
|
||||
if (
|
||||
selectedRoute?.marketInfos.length > 1 &&
|
||||
index !== selectedRoute?.marketInfos.length - 1
|
||||
) {
|
||||
includeSeparator = true
|
||||
}
|
||||
return (
|
||||
<span key={index}>{`${info?.label} ${
|
||||
includeSeparator ? 'x ' : ''
|
||||
}`}</span>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -53,12 +53,13 @@
|
|||
"html-react-parser": "3.0.4",
|
||||
"html2canvas": "1.4.1",
|
||||
"http-proxy-middleware": "2.0.6",
|
||||
"i18next": "23.2.11",
|
||||
"immer": "9.0.12",
|
||||
"js-cookie": "3.0.1",
|
||||
"klinecharts": "8.6.3",
|
||||
"lodash": "4.17.21",
|
||||
"next": "13.4.4",
|
||||
"next-i18next": "11.1.1",
|
||||
"next-i18next": "14.0.0",
|
||||
"next-themes": "0.1.1",
|
||||
"process": "0.11.10",
|
||||
"react": "18.2.0",
|
||||
|
@ -66,6 +67,7 @@
|
|||
"react-flip-numbers": "3.0.5",
|
||||
"react-grid-layout": "1.3.4",
|
||||
"react-hot-keys": "2.7.2",
|
||||
"react-i18next": "13.0.2",
|
||||
"react-nice-dates": "3.1.0",
|
||||
"react-number-format": "4.9.2",
|
||||
"react-tsparticles": "2.2.4",
|
||||
|
|
|
@ -19,12 +19,10 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
'notifications',
|
||||
'onboarding',
|
||||
'onboarding-tours',
|
||||
'profile',
|
||||
'search',
|
||||
'settings',
|
||||
'trade',
|
||||
'close-account',
|
||||
'tv-chart',
|
||||
'swap',
|
||||
])),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@
|
|||
"repay-borrow": "Repay Borrow",
|
||||
"repayment-amount": "Repayment Amount",
|
||||
"rolling-change": "24h Change",
|
||||
"route": "Route",
|
||||
"save": "Save",
|
||||
"select": "Select",
|
||||
"select-borrow-token": "Select Borrow Token",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"repay-borrow": "Repay Borrow",
|
||||
"repayment-amount": "Repayment Amount",
|
||||
"rolling-change": "24h Change",
|
||||
"route": "Route",
|
||||
"save": "Save",
|
||||
"select": "Select",
|
||||
"select-borrow-token": "Select Borrow Token",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"repay-borrow": "Repay Borrow",
|
||||
"repayment-amount": "Repayment Amount",
|
||||
"rolling-change": "24h Change",
|
||||
"route": "Route",
|
||||
"save": "Save",
|
||||
"select": "Select",
|
||||
"select-borrow-token": "Select Borrow Token",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"repay-deposit": "归还及存入",
|
||||
"repayment-amount": "还贷额",
|
||||
"rolling-change": "24小时变化",
|
||||
"route": "Route",
|
||||
"save": "存",
|
||||
"select": "选择",
|
||||
"select-borrow-token": "选借入币种",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"repay-deposit": "歸還及存入",
|
||||
"repayment-amount": "還貸額",
|
||||
"rolling-change": "24小時變化",
|
||||
"route": "Route",
|
||||
"save": "存",
|
||||
"select": "選擇",
|
||||
"select-borrow-token": "選借入幣種",
|
||||
|
|
51
yarn.lock
51
yarn.lock
|
@ -7,13 +7,20 @@
|
|||
resolved "https://registry.yarnpkg.com/@apocentre/alias-sampling/-/alias-sampling-0.5.3.tgz#897ff181b48ad7b2bcb4ecf29400214888244f08"
|
||||
integrity sha512-7UDWIIF9hIeJqfKXkNIzkVandlwLf1FWTSdrb9iXvOP8oF544JRXQjCbiTmCv2c9n44n/FIWtehhBfNuAx2CZA==
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.6", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.7":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.7":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
|
||||
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@babel/runtime@^7.20.13", "@babel/runtime@^7.22.5":
|
||||
version "7.22.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438"
|
||||
integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@blockworks-foundation/mango-feeds@0.1.7":
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-feeds/-/mango-feeds-0.1.7.tgz#07283e4f6b52ce2e631b866f7675b395dcc15f9e"
|
||||
|
@ -5673,17 +5680,17 @@ husky@8.0.1:
|
|||
resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.1.tgz#511cb3e57de3e3190514ae49ed50f6bc3f50b3e9"
|
||||
integrity sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==
|
||||
|
||||
i18next-fs-backend@^1.1.4:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-1.2.0.tgz#c498c68c8e6a8ae5ed59bea5e5392a11991de696"
|
||||
integrity sha512-pUx3AcgXCbur0jpFA7U67Z2RJflAcIi698Y8VL+phdOqUchahxriV3Cs+M6UkPNQSS/zPEzWLfdJ8EgjB7HVxg==
|
||||
i18next-fs-backend@^2.1.5:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-2.1.5.tgz#03347eacde6a35b599da1889a048ae63bcf0c687"
|
||||
integrity sha512-7fgSH8nVhXSBYPHR/W3tEXXhcnwHwNiND4Dfx9knzPzdsWTUTL/TdDVV+DY0dL0asHKLbdoJaXS4LdVW6R8MVQ==
|
||||
|
||||
i18next@^21.8.13:
|
||||
version "21.10.0"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.10.0.tgz#85429af55fdca4858345d0e16b584ec29520197d"
|
||||
integrity sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==
|
||||
i18next@23.2.11:
|
||||
version "23.2.11"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.2.11.tgz#0c6f3a637fa87d3243e64b78ad285b7f77d41353"
|
||||
integrity sha512-MA4FsxOjyCaOZtRDB4yuwjCvqYEioD4G4LlXOn7SO3rnQUlxTufyLsOqfL9MKakeLRBkefe8bqcs0D6Z/xFk1w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.17.2"
|
||||
"@babel/runtime" "^7.22.5"
|
||||
|
||||
iconv-lite@^0.4.24:
|
||||
version "0.4.24"
|
||||
|
@ -6634,18 +6641,16 @@ near-seed-phrase@^0.2.0:
|
|||
near-hd-key "^1.2.1"
|
||||
tweetnacl "^1.0.2"
|
||||
|
||||
next-i18next@11.1.1:
|
||||
version "11.1.1"
|
||||
resolved "https://registry.yarnpkg.com/next-i18next/-/next-i18next-11.1.1.tgz#27650f1995c306174ed96436fa77ab4db2273e6a"
|
||||
integrity sha512-msffPxyaU7oM5s55taIlvhSbVa8E62tXbuFZr+4myrhALQzRY+N8ExurJG33LvM9GbcwQazzXt1yeNYUynm4qQ==
|
||||
next-i18next@14.0.0:
|
||||
version "14.0.0"
|
||||
resolved "https://registry.yarnpkg.com/next-i18next/-/next-i18next-14.0.0.tgz#fd637c81df96c9d6f2cc4716037130ac4e5d6968"
|
||||
integrity sha512-umv8hOZoSoAA+td3ErfemyO/5Ib2pnYCdQ8/Oy+fncS2skFIL3hHKRer3Oa3Nfm4Xbv5p6DHWzm3NhT1j4tWwg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.18.6"
|
||||
"@babel/runtime" "^7.20.13"
|
||||
"@types/hoist-non-react-statics" "^3.3.1"
|
||||
core-js "^3"
|
||||
hoist-non-react-statics "^3.3.2"
|
||||
i18next "^21.8.13"
|
||||
i18next-fs-backend "^1.1.4"
|
||||
react-i18next "^11.18.0"
|
||||
i18next-fs-backend "^2.1.5"
|
||||
|
||||
next-themes@0.1.1:
|
||||
version "0.1.1"
|
||||
|
@ -7390,12 +7395,12 @@ react-hot-keys@2.7.2:
|
|||
hotkeys-js "^3.8.1"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-i18next@^11.18.0:
|
||||
version "11.18.6"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.18.6.tgz#e159c2960c718c1314f1e8fcaa282d1c8b167887"
|
||||
integrity sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==
|
||||
react-i18next@13.0.2:
|
||||
version "13.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-13.0.2.tgz#1708a9bdabc1fe1dd4a8534f4c3a80ab784b01e9"
|
||||
integrity sha512-NEVxC32v0oR4egwYM0QM0WE93AiJG5r0NTXTL8mhQfAhsMfDS2fSO6jpluyfsfypP988KzUQrAXncspcJ7+GHA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.14.5"
|
||||
"@babel/runtime" "^7.22.5"
|
||||
html-parse-stringify "^3.0.1"
|
||||
|
||||
react-is@^16.10.2, react-is@^16.13.1, react-is@^16.7.0:
|
||||
|
|
Loading…
Reference in New Issue