import React, { useMemo, useState } from 'react' import Modal from './Modal' import Input from './Input' import AccountSelect from './AccountSelect' import { ElementTitle } from './styles' import useMangoStore from '../stores/useMangoStore' import useMarketList from '../hooks/useMarketList' import { getSymbolForTokenMintAddress, formatBalanceDisplay, } from '../utils/index' import useConnection from '../hooks/useConnection' import { borrowAndWithdraw, withdraw } from '../utils/mango' import Loading from './Loading' import Button from './Button' import { notify } from '../utils/notifications' const WithdrawModal = ({ isOpen, onClose }) => { const [inputAmount, setInputAmount] = useState('') const [submitting, setSubmitting] = useState(false) const { getTokenIndex, symbols } = useMarketList() const { connection, programId } = useConnection() const walletAccounts = useMangoStore((s) => s.wallet.balances) const selectedMangoGroup = useMangoStore((s) => s.selectedMangoGroup.current) const mintDecimals = useMangoStore((s) => s.selectedMangoGroup.mintDecimals) const selectedMarginAccount = useMangoStore( (s) => s.selectedMarginAccount.current ) const actions = useMangoStore((s) => s.actions) const withdrawAccounts = useMemo( () => walletAccounts.filter((acc) => Object.values(symbols).includes(acc.account.mint.toString()) ), [symbols, walletAccounts] ) const [selectedAccount, setSelectedAccount] = useState(withdrawAccounts[0]) const mintAddress = useMemo(() => selectedAccount?.account.mint.toString(), [ selectedAccount, ]) const tokenIndex = useMemo(() => getTokenIndex(mintAddress), [ mintAddress, getTokenIndex, ]) const handleSetSelectedAccount = (val) => { setInputAmount('') setSelectedAccount(val) } const withdrawDisabled = Number(inputAmount) <= 0 const getMaxForSelectedAccount = () => { const marginAccount = useMangoStore.getState().selectedMarginAccount.current const mangoGroup = useMangoStore.getState().selectedMangoGroup.current return marginAccount.getUiDeposit(mangoGroup, tokenIndex) } const setMaxForSelectedAccount = () => { setInputAmount(getMaxForSelectedAccount().toString()) } const setMaxBorrowForSelectedAccount = async () => { const prices = await selectedMangoGroup.getPrices(connection) const assetsValBeforeTokenBal = selectedMarginAccount.getAssetsVal( selectedMangoGroup, prices ) const assetsVal = assetsValBeforeTokenBal - getMaxForSelectedAccount() const currentLiabs = selectedMarginAccount.getLiabsVal( selectedMangoGroup, prices ) const liabsAvail = (assetsVal / 1.2 - currentLiabs) * 0.99 - 0.01 console.log('selected token deposits', getMaxForSelectedAccount()) console.log('prices', prices) console.log('assetsVal', assetsVal) console.log('currentLiabs', currentLiabs) console.log('liabsAvail', liabsAvail) const amountToWithdraw = liabsAvail / prices[tokenIndex] + getMaxForSelectedAccount() const decimals = mintDecimals[getTokenIndex(mintAddress)] setInputAmount(formatBalanceDisplay(amountToWithdraw, decimals).toString()) } const handleWithdraw = () => { setSubmitting(true) const marginAccount = useMangoStore.getState().selectedMarginAccount.current const mangoGroup = useMangoStore.getState().selectedMangoGroup.current const wallet = useMangoStore.getState().wallet.current if (!marginAccount || !mangoGroup) return if (Number(inputAmount) <= getMaxForSelectedAccount()) { console.log('=withdraw without borrow=') withdraw( connection, programId, mangoGroup, marginAccount, wallet, selectedAccount.account.mint, selectedAccount.publicKey, Number(inputAmount) ) .then((_transSig: string) => { setSubmitting(false) actions.fetchMangoGroup() actions.fetchMarginAccounts() actions.fetchWalletBalances() onClose() }) .catch((err) => { setSubmitting(false) console.warn('Error withdrawing:', err) notify({ message: 'Could not perform withdraw', description: `${err}`, type: 'error', }) onClose() }) } else { console.log('-withdraw with borrow-') borrowAndWithdraw( connection, programId, mangoGroup, marginAccount, wallet, selectedAccount.account.mint, selectedAccount.publicKey, Number(inputAmount) ) .then((_transSig: string) => { setSubmitting(false) actions.fetchMangoGroup() actions.fetchMarginAccounts() actions.fetchWalletBalances() onClose() }) .catch((err) => { setSubmitting(false) console.warn('Error borrowing and withdrawing:', err) notify({ message: 'Could not perform borrow and withdraw', description: `${err}`, type: 'error', }) onClose() }) } } if (!selectedAccount) return null return ( Withdraw Funds
Token Account
Amount
Max
Max With Borrow
setInputAmount(e.target.value)} suffix={getSymbolForTokenMintAddress( selectedAccount?.account?.mint.toString() )} />
{/*
Balance: {getMaxForSelectedAccount()}
setInputAmount(e.target.value)} >
*/}
) } export default React.memo(WithdrawModal)