Merge branch 'main' into saml33/spot-market-trade-fixes
This commit is contained in:
commit
63ae9d3810
|
@ -90,7 +90,7 @@ const CreateSwitchboardOracleModal = ({
|
||||||
MEME: {
|
MEME: {
|
||||||
fundAmount: 2,
|
fundAmount: 2,
|
||||||
minRequiredOracleResults: 1,
|
minRequiredOracleResults: 1,
|
||||||
minUpdateDelaySeconds: 30,
|
minUpdateDelaySeconds: 20,
|
||||||
batchSize: 2,
|
batchSize: 2,
|
||||||
},
|
},
|
||||||
SHIT: {
|
SHIT: {
|
||||||
|
|
|
@ -492,6 +492,72 @@ const AdvancedTradeForm = () => {
|
||||||
}
|
}
|
||||||
}, [isTriggerOrder, tickDecimals, tradeForm.side, tradeForm.tradeType])
|
}, [isTriggerOrder, tickDecimals, tradeForm.side, tradeForm.tradeType])
|
||||||
|
|
||||||
|
const isFormValid = useCallback(
|
||||||
|
(form: TradeForm) => {
|
||||||
|
const { baseSize, price, orderType, side } = form
|
||||||
|
const invalidFields: FormErrors = {}
|
||||||
|
setFormErrors({})
|
||||||
|
const requiredFields: (keyof TradeForm)[] = ['baseSize', 'price']
|
||||||
|
const priceNumber = price ? parseFloat(price) : 0
|
||||||
|
const baseTokenBalance = getTokenBalance(baseBank)
|
||||||
|
const isReducingShort = baseTokenBalance < 0
|
||||||
|
for (const key of requiredFields) {
|
||||||
|
const value = form[key] as string
|
||||||
|
if (!value) {
|
||||||
|
invalidFields[key] = t('settings:error-required-field')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (orderType === TriggerOrderTypes.STOP_LOSS) {
|
||||||
|
if (isReducingShort && priceNumber <= oraclePrice) {
|
||||||
|
invalidFields.price = t('trade:error-trigger-above')
|
||||||
|
}
|
||||||
|
if (!isReducingShort && priceNumber >= oraclePrice) {
|
||||||
|
invalidFields.price = t('trade:error-trigger-below')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (orderType === TriggerOrderTypes.TAKE_PROFIT) {
|
||||||
|
if (isReducingShort && priceNumber >= oraclePrice) {
|
||||||
|
invalidFields.price = t('trade:error-trigger-below')
|
||||||
|
}
|
||||||
|
if (!isReducingShort && priceNumber <= oraclePrice) {
|
||||||
|
invalidFields.price = t('trade:error-trigger-above')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (side === 'buy' && !isReducingShort && isTriggerOrder) {
|
||||||
|
invalidFields.baseSize = t('trade:error-no-short')
|
||||||
|
}
|
||||||
|
if (side === 'sell' && isReducingShort && isTriggerOrder) {
|
||||||
|
invalidFields.baseSize = t('trade:error-no-long')
|
||||||
|
}
|
||||||
|
if (baseSize > Math.abs(baseTokenBalance) && isTriggerOrder) {
|
||||||
|
invalidFields.baseSize = t('swap:insufficient-balance', {
|
||||||
|
symbol: baseBank?.name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseSize < minOrderSize) {
|
||||||
|
invalidFields.baseSize = t('trade:min-order-size-error', {
|
||||||
|
minSize: formatNumericValue(minOrderSize, minOrderDecimals),
|
||||||
|
symbol: baseSymbol,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (Object.keys(invalidFields).length) {
|
||||||
|
setFormErrors(invalidFields)
|
||||||
|
}
|
||||||
|
return invalidFields
|
||||||
|
},
|
||||||
|
[
|
||||||
|
baseBank,
|
||||||
|
isTriggerOrder,
|
||||||
|
minOrderDecimals,
|
||||||
|
minOrderSize,
|
||||||
|
oraclePrice,
|
||||||
|
setFormErrors,
|
||||||
|
baseSymbol,
|
||||||
|
t,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
const handleStandardOrder = useCallback(async () => {
|
const handleStandardOrder = useCallback(async () => {
|
||||||
const { client } = mangoStore.getState()
|
const { client } = mangoStore.getState()
|
||||||
const { group } = mangoStore.getState()
|
const { group } = mangoStore.getState()
|
||||||
|
@ -608,7 +674,7 @@ const AdvancedTradeForm = () => {
|
||||||
} finally {
|
} finally {
|
||||||
setPlacingOrder(false)
|
setPlacingOrder(false)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [isFormValid, soundSettings])
|
||||||
|
|
||||||
const handleTriggerOrder = useCallback(() => {
|
const handleTriggerOrder = useCallback(() => {
|
||||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||||
|
@ -635,14 +701,14 @@ const AdvancedTradeForm = () => {
|
||||||
false,
|
false,
|
||||||
setPlacingOrder,
|
setPlacingOrder,
|
||||||
)
|
)
|
||||||
}, [baseBank, quoteBank, setPlacingOrder])
|
}, [baseBank, quoteBank, setPlacingOrder, isFormValid])
|
||||||
|
|
||||||
const handleSubmit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
(e: FormEvent<HTMLFormElement>) => {
|
(e: FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
isTriggerOrder ? handleTriggerOrder() : handleStandardOrder()
|
isTriggerOrder ? handleTriggerOrder() : handleStandardOrder()
|
||||||
},
|
},
|
||||||
[isTriggerOrder],
|
[isTriggerOrder, handleTriggerOrder, handleStandardOrder],
|
||||||
)
|
)
|
||||||
|
|
||||||
const sideNames = useMemo(() => {
|
const sideNames = useMemo(() => {
|
||||||
|
@ -703,69 +769,6 @@ const AdvancedTradeForm = () => {
|
||||||
: orderTypesArray
|
: orderTypesArray
|
||||||
}, [baseBank, mangoAccountAddress, minOrderDecimals, selectedMarket])
|
}, [baseBank, mangoAccountAddress, minOrderDecimals, selectedMarket])
|
||||||
|
|
||||||
const isFormValid = useCallback(
|
|
||||||
(form: TradeForm) => {
|
|
||||||
const { baseSize, price, orderType, side } = form
|
|
||||||
const invalidFields: FormErrors = {}
|
|
||||||
setFormErrors({})
|
|
||||||
const requiredFields: (keyof TradeForm)[] = ['baseSize', 'price']
|
|
||||||
const priceNumber = price ? parseFloat(price) : 0
|
|
||||||
const baseTokenBalance = getTokenBalance(baseBank)
|
|
||||||
const isReducingShort = baseTokenBalance < 0
|
|
||||||
for (const key of requiredFields) {
|
|
||||||
const value = form[key] as string
|
|
||||||
if (!value) {
|
|
||||||
invalidFields[key] = t('settings:error-required-field')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (orderType === TriggerOrderTypes.STOP_LOSS) {
|
|
||||||
if (isReducingShort && priceNumber <= oraclePrice) {
|
|
||||||
invalidFields.price = t('trade:error-trigger-above')
|
|
||||||
}
|
|
||||||
if (!isReducingShort && priceNumber >= oraclePrice) {
|
|
||||||
invalidFields.price = t('trade:error-trigger-below')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (orderType === TriggerOrderTypes.TAKE_PROFIT) {
|
|
||||||
if (isReducingShort && priceNumber >= oraclePrice) {
|
|
||||||
invalidFields.price = t('trade:error-trigger-below')
|
|
||||||
}
|
|
||||||
if (!isReducingShort && priceNumber <= oraclePrice) {
|
|
||||||
invalidFields.price = t('trade:error-trigger-above')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (side === 'buy' && !isReducingShort && isTriggerOrder) {
|
|
||||||
invalidFields.baseSize = t('trade:error-no-short')
|
|
||||||
}
|
|
||||||
if (side === 'sell' && isReducingShort && isTriggerOrder) {
|
|
||||||
invalidFields.baseSize = t('trade:error-no-long')
|
|
||||||
}
|
|
||||||
if (baseSize > Math.abs(baseTokenBalance) && isTriggerOrder) {
|
|
||||||
invalidFields.baseSize = t('swap:insufficient-balance', {
|
|
||||||
symbol: baseBank?.name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (baseSize < minOrderSize) {
|
|
||||||
invalidFields.baseSize = t('trade:min-order-size-error', {
|
|
||||||
minSize: formatNumericValue(minOrderSize, minOrderDecimals),
|
|
||||||
symbol: baseSymbol,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (Object.keys(invalidFields).length) {
|
|
||||||
setFormErrors(invalidFields)
|
|
||||||
}
|
|
||||||
return invalidFields
|
|
||||||
},
|
|
||||||
[
|
|
||||||
baseBank,
|
|
||||||
isTriggerOrder,
|
|
||||||
minOrderDecimals,
|
|
||||||
minOrderSize,
|
|
||||||
oraclePrice,
|
|
||||||
setFormErrors,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
const tooMuchSize = useMemo(() => {
|
const tooMuchSize = useMemo(() => {
|
||||||
const { baseSize, quoteSize, side } = tradeForm
|
const { baseSize, quoteSize, side } = tradeForm
|
||||||
if (!baseSize || !quoteSize) return false
|
if (!baseSize || !quoteSize) return false
|
||||||
|
@ -905,6 +908,7 @@ const AdvancedTradeForm = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
{minOrderDecimals}
|
||||||
<NumberFormat
|
<NumberFormat
|
||||||
inputMode="decimal"
|
inputMode="decimal"
|
||||||
thousandSeparator=","
|
thousandSeparator=","
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"@blockworks-foundation/mango-feeds": "0.1.7",
|
"@blockworks-foundation/mango-feeds": "0.1.7",
|
||||||
"@blockworks-foundation/mango-mints-redemption": "^0.0.10",
|
"@blockworks-foundation/mango-mints-redemption": "^0.0.10",
|
||||||
"@blockworks-foundation/mango-v4": "0.20.9",
|
"@blockworks-foundation/mango-v4": "0.20.9",
|
||||||
"@blockworks-foundation/mango-v4-settings": "0.2.23",
|
"@blockworks-foundation/mango-v4-settings": "0.2.24",
|
||||||
"@blockworks-foundation/mangolana": "0.0.1-beta.15",
|
"@blockworks-foundation/mangolana": "0.0.1-beta.15",
|
||||||
"@headlessui/react": "1.6.6",
|
"@headlessui/react": "1.6.6",
|
||||||
"@heroicons/react": "2.0.18",
|
"@heroicons/react": "2.0.18",
|
||||||
|
|
|
@ -236,9 +236,17 @@ const Dashboard: NextPage = () => {
|
||||||
<ArrowTopRightOnSquareIcon className="ml-2 h-5 w-5 whitespace-nowrap" />
|
<ArrowTopRightOnSquareIcon className="ml-2 h-5 w-5 whitespace-nowrap" />
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<ExplorerLink
|
<a
|
||||||
address={formattedBankValues.oracle}
|
href={`https://pyth.network/price-feeds/crypto-${bankNameToOracleName(
|
||||||
/>
|
bank.name,
|
||||||
|
).toLowerCase()}-${'usd'}`}
|
||||||
|
className={`flex items-center break-all text-th-fgd-2 hover:text-th-fgd-3`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{bank.oracle.toString()}
|
||||||
|
<ArrowTopRightOnSquareIcon className="ml-2 h-5 w-5 whitespace-nowrap" />
|
||||||
|
</a>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -959,3 +967,13 @@ export const DashboardNavbar = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Dashboard
|
export default Dashboard
|
||||||
|
|
||||||
|
//some assets are listed with different pyth named oracles
|
||||||
|
const bankNameToOracleName = (val: string) => {
|
||||||
|
if (val === 'ETH (Portal)') {
|
||||||
|
return 'ETH'
|
||||||
|
}
|
||||||
|
if (val === 'CHAI') return 'DAI'
|
||||||
|
if (val === 'wBTC (Portal)') return 'BTC'
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
|
@ -42,10 +42,10 @@
|
||||||
keccak256 "^1.0.6"
|
keccak256 "^1.0.6"
|
||||||
merkletreejs "^0.3.11"
|
merkletreejs "^0.3.11"
|
||||||
|
|
||||||
"@blockworks-foundation/mango-v4-settings@0.2.23", "@blockworks-foundation/mango-v4-settings@^0.2.16":
|
"@blockworks-foundation/mango-v4-settings@0.2.24", "@blockworks-foundation/mango-v4-settings@^0.2.16":
|
||||||
version "0.2.23"
|
version "0.2.24"
|
||||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.2.23.tgz#a42a93f9b0b0449c1879386b00d81bebcfdc52e0"
|
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.2.24.tgz#0335f6e35ea67984699436e5177a1a1d768401a9"
|
||||||
integrity sha512-47NuZPHo0odIRxY0TFrMOqjnJJADzXuIIEG5urCOb4FhLClthCpyjZRbHsTSzHTk5RRHChO4ZtfP9+B+qT5LAw==
|
integrity sha512-jv4SvJ88N3YcQtUw4T4u/k6uA3fe216WX4A+aZ8iHLj9Zk3ADoILLsC/SWhGWRt2SaGv8ClndLmETIT4R1VDDw==
|
||||||
dependencies:
|
dependencies:
|
||||||
bn.js "^5.2.1"
|
bn.js "^5.2.1"
|
||||||
eslint-config-prettier "^9.0.0"
|
eslint-config-prettier "^9.0.0"
|
||||||
|
|
Loading…
Reference in New Issue