import { useCallback, useMemo, useState } from 'react' import { ModalProps } from '../../types/modal' import Modal from '../shared/Modal' import { useTranslation } from 'next-i18next' import Label from '@components/forms/Label' import NumberFormat, { NumberFormatValues } from 'react-number-format' import { INPUT_CLASSES } from './TradeVolumeAlertModal' import { Order } from '@project-serum/serum/lib/market' import { PerpOrder, PerpOrderType, Serum3OrderType, Serum3SelfTradeBehavior, Serum3Side, } from '@blockworks-foundation/mango-v4' import mangoStore from '@store/mangoStore' import { PublicKey } from '@solana/web3.js' import { notify } from 'utils/notifications' import { isMangoError } from 'types' import Button, { LinkButton } from '@components/shared/Button' import { findSerum3MarketPkInOpenOrders } from '@components/trade/OpenOrders' import useSelectedMarket from 'hooks/useSelectedMarket' import { floorToDecimal, formatNumericValue, getDecimalCount, } from 'utils/numbers' import useLocalStorageState from 'hooks/useLocalStorageState' import { TRADE_CHECKBOXES_KEY } from 'utils/constants' import { DEFAULT_CHECKBOX_SETTINGS } from '@components/trade/AdvancedTradeForm' import MaxSizeButton from '@components/trade/MaxSizeButton' import InlineNotification from '@components/shared/InlineNotification' import MarketLogos from '@components/trade/MarketLogos' import PerpSideBadge from '@components/trade/PerpSideBadge' import SideBadge from '@components/shared/SideBadge' import { ArrowRightIcon } from '@heroicons/react/20/solid' interface ModifyModalProps { order: Order | PerpOrder price: string } type ModalCombinedProps = ModifyModalProps & ModalProps const ModifyTvOrderModal = ({ isOpen, onClose, order, price, }: ModalCombinedProps) => { const { t } = useTranslation(['common', 'trade']) const [modifiedOrderPrice, setModifiedOrderPrice] = useState(price) const [modifiedOrderSize, setModifiedOrderSize] = useState( order.size.toString() ) const { baseSymbol, selectedMarket, serumOrPerpMarket } = useSelectedMarket() const [savedCheckboxSettings] = useLocalStorageState( TRADE_CHECKBOXES_KEY, DEFAULT_CHECKBOX_SETTINGS ) const tickDecimals = useMemo(() => { if (!serumOrPerpMarket) return 1 const tickSize = serumOrPerpMarket.tickSize const tickDecimals = getDecimalCount(tickSize) return tickDecimals }, [serumOrPerpMarket]) const [minOrderDecimals, minOrderSize] = useMemo(() => { if (!serumOrPerpMarket) return [1, 0.1] const minOrderSize = serumOrPerpMarket.minOrderSize const minOrderDecimals = getDecimalCount(minOrderSize) return [minOrderDecimals, minOrderSize] }, [serumOrPerpMarket]) const modifyOrder = useCallback( async (o: PerpOrder | Order) => { const client = mangoStore.getState().client const group = mangoStore.getState().group const mangoAccount = mangoStore.getState().mangoAccount.current const actions = mangoStore.getState().actions const baseSize = modifiedOrderSize ? Number(modifiedOrderSize) : o.size const price = modifiedOrderPrice ? floorToDecimal(modifiedOrderPrice, tickDecimals).toNumber() : o.price if (!group || !mangoAccount) return try { let tx = '' if (o instanceof PerpOrder) { tx = await client.modifyPerpOrder( group, mangoAccount, o.perpMarketIndex, o.orderId, o.side, price, Math.abs(baseSize), undefined, // maxQuoteQuantity Date.now(), PerpOrderType.limit, undefined, undefined ) } else { const marketPk = findSerum3MarketPkInOpenOrders(o) if (!marketPk) return const market = group.getSerum3MarketByExternalMarket( new PublicKey(marketPk) ) tx = await client.modifySerum3Order( group, o.orderId, mangoAccount, market.serumMarketExternal, o.side === 'buy' ? Serum3Side.bid : Serum3Side.ask, price, baseSize, Serum3SelfTradeBehavior.decrementTake, Serum3OrderType.limit, Date.now(), 10 ) } actions.fetchOpenOrders() notify({ type: 'success', title: 'Transaction successful', txid: tx, }) onClose() } catch (e) { console.error('Error canceling', e) if (!isMangoError(e)) return notify({ title: 'Unable to modify order', description: e.message, txid: e.txid, type: 'error', }) } }, [findSerum3MarketPkInOpenOrders, modifiedOrderPrice, modifiedOrderSize] ) return selectedMarket ? (

{t('trade:edit-order')}

{selectedMarket.name}

setModifiedOrderSize(e.value) } /> {minOrderSize && modifiedOrderSize && parseFloat(modifiedOrderSize) < minOrderSize ? (
) : null}

{t('trade:side')}

{order instanceof PerpOrder ? ( ) : ( )}

{t('trade:order-type')}

{t('trade:limit')}

{t('trade:limit-price')}

{formatNumericValue(order.price, tickDecimals)}

{formatNumericValue(modifiedOrderPrice, tickDecimals)}

{t('trade:size')}

{order.size !== parseFloat(modifiedOrderSize) ? ( <>

{order.size}

) : null}

{formatNumericValue(modifiedOrderSize, minOrderDecimals)}

{t('cancel')}
) : null } export default ModifyTvOrderModal