wip: max borrow calculations
This commit is contained in:
parent
1c2d5dc60d
commit
671e50eba0
|
@ -1,4 +1,4 @@
|
|||
import React, { FunctionComponent, useEffect, useMemo, useState } from 'react'
|
||||
import React, { FunctionComponent, useEffect, useState } from 'react'
|
||||
import { Disclosure } from '@headlessui/react'
|
||||
import {
|
||||
ExclamationCircleIcon,
|
||||
|
@ -15,7 +15,6 @@ import AccountSelect from './AccountSelect'
|
|||
import { ElementTitle } from './styles'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import { DECIMALS, trimDecimals } from '../utils/index'
|
||||
import useConnection from '../hooks/useConnection'
|
||||
import Loading from './Loading'
|
||||
import Button, { LinkButton } from './Button'
|
||||
import Tooltip from './Tooltip'
|
||||
|
@ -41,21 +40,20 @@ const DepositModal: FunctionComponent<DepositModalProps> = ({
|
|||
|
||||
const [inputAmount, setInputAmount] = useState(settleDeficit || 0)
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [simulation, setSimulation] = useState(null)
|
||||
const [simulation /*setSimulation*/] = useState(null)
|
||||
const [showSimulation, setShowSimulation] = useState(false)
|
||||
const [invalidAmountMessage, setInvalidAmountMessage] = useState('')
|
||||
const [sliderPercentage, setSliderPercentage] = useState(0)
|
||||
const [maxButtonTransition, setMaxButtonTransition] = useState(false)
|
||||
const { connection, programId } = useConnection()
|
||||
const walletTokens = useMangoStore((s) => s.wallet.tokens)
|
||||
const actions = useMangoStore((s) => s.actions)
|
||||
const [selectedAccount, setSelectedAccount] = useState(walletTokens[0])
|
||||
|
||||
const prices = [] //useMangoStore((s) => s.selectedMangoGroup.prices)
|
||||
const selectedMangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
const selectedMangoAccount = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.current
|
||||
)
|
||||
// const prices = [] //useMangoStore((s) => s.selectedMangoGroup.prices)
|
||||
// const selectedMangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
// const selectedMangoAccount = useMangoStore(
|
||||
// (s) => s.selectedMangoAccount.current
|
||||
// )
|
||||
|
||||
useEffect(() => {
|
||||
if (tokenSymbol) {
|
||||
|
|
|
@ -55,6 +55,65 @@ export default function MarginInfo() {
|
|||
<div className={`text-th-fgd-1`}>{maintHealth.toFixed(3)}</div>
|
||||
</div>
|
||||
|
||||
{selectedMangoAccount ? (
|
||||
<>
|
||||
<div className={`flex justify-between pt-2 pb-2`}>
|
||||
<Tooltip content="Account health">
|
||||
<div
|
||||
className={`cursor-help font-normal text-th-fgd-4 border-b border-th-fgd-4 border-dashed border-opacity-20 leading-4 default-transition hover:border-th-bkg-2 hover:text-th-fgd-3`}
|
||||
>
|
||||
Assets Val
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={`text-th-fgd-1`}>
|
||||
{selectedMangoAccount
|
||||
.getAssetsVal(mangoGroup, mangoCache)
|
||||
.toString()}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`flex justify-between pt-2 pb-2`}>
|
||||
<Tooltip content="Account health">
|
||||
<div
|
||||
className={`cursor-help font-normal text-th-fgd-4 border-b border-th-fgd-4 border-dashed border-opacity-20 leading-4 default-transition hover:border-th-bkg-2 hover:text-th-fgd-3`}
|
||||
>
|
||||
Liabs Val
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={`text-th-fgd-1`}>
|
||||
{selectedMangoAccount
|
||||
.getLiabsVal(mangoGroup, mangoCache)
|
||||
.toString()}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`flex justify-between pt-2 pb-2`}>
|
||||
<Tooltip content="Account health">
|
||||
<div
|
||||
className={`cursor-help font-normal text-th-fgd-4 border-b border-th-fgd-4 border-dashed border-opacity-20 leading-4 default-transition hover:border-th-bkg-2 hover:text-th-fgd-3`}
|
||||
>
|
||||
Equity
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={`text-th-fgd-1`}>
|
||||
{selectedMangoAccount
|
||||
.computeValue(mangoGroup, mangoCache)
|
||||
.toString()}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`flex justify-between pt-2 pb-2`}>
|
||||
<Tooltip content="Account health">
|
||||
<div
|
||||
className={`cursor-help font-normal text-th-fgd-4 border-b border-th-fgd-4 border-dashed border-opacity-20 leading-4 default-transition hover:border-th-bkg-2 hover:text-th-fgd-3`}
|
||||
>
|
||||
BTC Price
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={`text-th-fgd-1`}>
|
||||
{mangoGroup.getPrice(0, mangoCache).toString()}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{/* <Button
|
||||
className="mt-4 w-full"
|
||||
disabled={!connected}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useState } from 'react'
|
||||
import styled from '@emotion/styled'
|
||||
import { RadioGroup } from '@headlessui/react'
|
||||
import useLocalStorageState from '../hooks/useLocalStorageState'
|
||||
// import useLocalStorageState from '../hooks/useLocalStorageState'
|
||||
import useMangoGroupConfig from '../hooks/useMangoGroupConfig'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import { getMarketByBaseSymbolAndKind } from '@blockworks-foundation/mango-client'
|
||||
|
|
|
@ -2,12 +2,17 @@ import { useState } from 'react'
|
|||
import FloatingElement from './FloatingElement'
|
||||
import OpenOrdersTable from './OpenOrdersTable'
|
||||
import BalancesTable from './BalancesTable'
|
||||
import PositionsTable from './PositionsTable'
|
||||
// import PositionsTable from './PositionsTable'
|
||||
import TradeHistoryTable from './TradeHistoryTable'
|
||||
import { Position } from '../public/charting_library/charting_library'
|
||||
// import FeeDiscountsTable from './FeeDiscountsTable'
|
||||
|
||||
const TABS = ['Open Orders', 'Balances', 'Trade History', 'Positions' /*'Fee Discounts'*/]
|
||||
const TABS = [
|
||||
'Open Orders',
|
||||
'Balances',
|
||||
'Trade History',
|
||||
'Positions' /*'Fee Discounts'*/,
|
||||
]
|
||||
|
||||
const UserInfoTabs = ({ activeTab, setActiveTab }) => {
|
||||
const handleTabChange = (tabName) => {
|
||||
|
|
|
@ -3,19 +3,10 @@ import Modal from './Modal'
|
|||
import Input from './Input'
|
||||
import { ElementTitle } from './styles'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import useMarketList from '../hooks/useMarketList'
|
||||
import {
|
||||
DECIMALS,
|
||||
floorToDecimal,
|
||||
tokenPrecision,
|
||||
displayDepositsForMangoAccount,
|
||||
} from '../utils/index'
|
||||
import useConnection from '../hooks/useConnection'
|
||||
// import { borrowAndWithdraw, withdraw } from '../utils/mango'
|
||||
import { DECIMALS, tokenPrecision } from '../utils/index'
|
||||
import Loading from './Loading'
|
||||
import Slider from './Slider'
|
||||
import Button, { LinkButton } from './Button'
|
||||
import { notify } from '../utils/notifications'
|
||||
import Switch from './Switch'
|
||||
import Tooltip from './Tooltip'
|
||||
import {
|
||||
|
@ -28,12 +19,14 @@ import {
|
|||
ChevronUpIcon,
|
||||
} from '@heroicons/react/solid'
|
||||
import { Disclosure } from '@headlessui/react'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import {
|
||||
MerpsAccount as MangoAccount,
|
||||
uiToNative,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import Select from './Select'
|
||||
import { withdraw } from '../utils/mango'
|
||||
import {
|
||||
ZERO_I80F48,
|
||||
I80F48,
|
||||
MangoAccount,
|
||||
ONE_I80F48,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
|
||||
interface WithdrawModalProps {
|
||||
onClose: () => void
|
||||
|
@ -46,12 +39,10 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
onClose,
|
||||
tokenSymbol = '',
|
||||
}) => {
|
||||
return <></>
|
||||
|
||||
const [withdrawTokenSymbol, setWithdrawTokenSymbol] = useState(
|
||||
tokenSymbol || 'USDC'
|
||||
)
|
||||
const [inputAmount, setInputAmount] = useState(0)
|
||||
const [inputAmount, setInputAmount] = useState('')
|
||||
const [invalidAmountMessage, setInvalidAmountMessage] = useState('')
|
||||
const [maxAmount, setMaxAmount] = useState(0)
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
@ -60,58 +51,105 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
const [showSimulation, setShowSimulation] = useState(false)
|
||||
const [sliderPercentage, setSliderPercentage] = useState(0)
|
||||
const [maxButtonTransition, setMaxButtonTransition] = useState(false)
|
||||
const { getTokenIndex, symbols } = useMarketList()
|
||||
const { connection, programId } = useConnection()
|
||||
const prices = useMangoStore((s) => s.selectedMangoGroup.prices)
|
||||
|
||||
const actions = useMangoStore((s) => s.actions)
|
||||
const selectedMangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
console.log('mg: ', selectedMangoGroup)
|
||||
|
||||
const selectedMangoAccount = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.current
|
||||
)
|
||||
const actions = useMangoStore((s) => s.actions)
|
||||
const tokenIndex = useMemo(
|
||||
() => getTokenIndex(symbols[withdrawTokenSymbol]),
|
||||
[withdrawTokenSymbol, getTokenIndex]
|
||||
const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
|
||||
const mangoGroupConfig = useMangoStore((s) => s.selectedMangoGroup.config)
|
||||
|
||||
const tokens = useMemo(() => mangoGroupConfig.tokens, [mangoGroupConfig])
|
||||
const token = useMemo(
|
||||
() => tokens.find((t) => t.symbol === withdrawTokenSymbol),
|
||||
[withdrawTokenSymbol, tokens]
|
||||
)
|
||||
const tokenIndex = selectedMangoGroup.getTokenIndex(token.mintKey)
|
||||
|
||||
console.log('mango Acc', selectedMangoAccount)
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedMangoGroup || !selectedMangoAccount || !withdrawTokenSymbol)
|
||||
return
|
||||
|
||||
const mintDecimals = selectedMangoGroup.mintDecimals[tokenIndex]
|
||||
const groupIndex = selectedMangoGroup.indexes[tokenIndex]
|
||||
const mintDecimals = selectedMangoGroup.tokens[tokenIndex].decimals
|
||||
const deposits = selectedMangoAccount.getUiDeposit(
|
||||
mangoCache.rootBankCache[tokenIndex],
|
||||
selectedMangoGroup,
|
||||
tokenIndex
|
||||
)
|
||||
const borrows = selectedMangoAccount.getUiBorrow(
|
||||
mangoCache.rootBankCache[tokenIndex],
|
||||
selectedMangoGroup,
|
||||
tokenIndex
|
||||
)
|
||||
|
||||
const currentAssetsVal =
|
||||
selectedMangoAccount.getAssetsVal(selectedMangoGroup, prices) -
|
||||
getMaxForSelectedAsset() * prices[tokenIndex]
|
||||
const currentLiabs = selectedMangoAccount.getLiabsVal(
|
||||
selectedMangoGroup,
|
||||
prices
|
||||
const maxValForSelectedAsset = getDepositsForSelectedAsset().mul(
|
||||
selectedMangoGroup.getPrice(tokenIndex, mangoCache) || ONE_I80F48
|
||||
)
|
||||
// multiply by 0.99 and subtract 0.01 to account for rounding issues
|
||||
const liabsAvail = (currentAssetsVal / 1.2 - currentLiabs) * 0.99 - 0.01
|
||||
|
||||
const currentAssetsVal = selectedMangoAccount
|
||||
.getAssetsVal(selectedMangoGroup, mangoCache)
|
||||
.sub(maxValForSelectedAsset)
|
||||
|
||||
const currentLiabsVal = selectedMangoAccount.getLiabsVal(
|
||||
selectedMangoGroup,
|
||||
mangoCache
|
||||
)
|
||||
|
||||
const liabsAvail = currentAssetsVal.sub(currentLiabsVal)
|
||||
|
||||
// calculate max withdraw amount
|
||||
const amountToWithdraw = includeBorrow
|
||||
? liabsAvail / prices[tokenIndex] + getMaxForSelectedAsset()
|
||||
: getMaxForSelectedAsset()
|
||||
console.log('currentAssetsVal', currentAssetsVal.toString())
|
||||
// console.log(
|
||||
// 'current assets / 1.2 == ',
|
||||
// currentAssetsVal.div(I80F48.fromNumber(1.19)).toString()
|
||||
// )
|
||||
|
||||
if (amountToWithdraw > 0) {
|
||||
setMaxAmount(amountToWithdraw)
|
||||
console.log('currentLiabsVal', currentLiabsVal.toString())
|
||||
|
||||
console.log('========================================')
|
||||
console.log('liabsAvail', liabsAvail.toString())
|
||||
console.log(
|
||||
'selected asset price',
|
||||
selectedMangoGroup.getPrice(tokenIndex, mangoCache)?.toString() ||
|
||||
ONE_I80F48.toString()
|
||||
)
|
||||
|
||||
const amountToWithdraw = includeBorrow
|
||||
? liabsAvail
|
||||
.div(
|
||||
selectedMangoGroup.getPrice(tokenIndex, mangoCache) || ONE_I80F48
|
||||
)
|
||||
.add(getDepositsForSelectedAsset())
|
||||
: getDepositsForSelectedAsset()
|
||||
|
||||
// liabsVal = equity * 5
|
||||
// 73550 =
|
||||
// health
|
||||
// 0 = quoteDeposits - quoteBorrows + spotHealth
|
||||
|
||||
console.log('amount to withdraw', amountToWithdraw.toString())
|
||||
|
||||
if (amountToWithdraw.gt(I80F48.fromNumber(0))) {
|
||||
setMaxAmount(amountToWithdraw.toNumber())
|
||||
} else {
|
||||
setMaxAmount(0)
|
||||
}
|
||||
|
||||
// simulate change to deposits & borrow based on input amount
|
||||
const newDeposit = Math.max(0, deposits - inputAmount)
|
||||
const newBorrows = borrows + Math.max(0, inputAmount - deposits)
|
||||
const parsedInputAmount = inputAmount
|
||||
? I80F48.fromString(inputAmount)
|
||||
: ZERO_I80F48
|
||||
let newDeposit = deposits.sub(parsedInputAmount)
|
||||
newDeposit = newDeposit.gt(ZERO_I80F48) ? newDeposit : ZERO_I80F48
|
||||
|
||||
let newBorrows = parsedInputAmount.sub(deposits)
|
||||
newBorrows = newBorrows.gt(ZERO_I80F48) ? newBorrows : ZERO_I80F48
|
||||
newBorrows = newBorrows.add(borrows)
|
||||
|
||||
// clone MangoAccount and arrays to not modify selectedMangoAccount
|
||||
const simulation = new MangoAccount(null, selectedMangoAccount)
|
||||
|
@ -119,119 +157,81 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
simulation.borrows = [...selectedMangoAccount.borrows]
|
||||
|
||||
// update with simulated values
|
||||
simulation.deposits[tokenIndex] =
|
||||
uiToNative(newDeposit, mintDecimals).toNumber() / groupIndex.deposit
|
||||
simulation.borrows[tokenIndex] =
|
||||
uiToNative(newBorrows, mintDecimals).toNumber() / groupIndex.borrow
|
||||
simulation.deposits[tokenIndex] = newDeposit
|
||||
.div(I80F48.fromNumber(Math.pow(10, mintDecimals)))
|
||||
.div(mangoCache.rootBankCache[tokenIndex].depositIndex)
|
||||
simulation.borrows[tokenIndex] = newBorrows
|
||||
.div(I80F48.fromNumber(Math.pow(10, mintDecimals)))
|
||||
.div(mangoCache.rootBankCache[tokenIndex].borrowIndex)
|
||||
|
||||
const equity = simulation.computeValue(selectedMangoGroup, prices)
|
||||
const assetsVal = simulation.getAssetsVal(selectedMangoGroup, prices)
|
||||
const liabsVal = simulation.getLiabsVal(selectedMangoGroup, prices)
|
||||
const collateralRatio = simulation.getCollateralRatio(
|
||||
selectedMangoGroup,
|
||||
prices
|
||||
)
|
||||
const leverage = 1 / Math.max(0, collateralRatio - 1)
|
||||
const equity = simulation.computeValue(selectedMangoGroup, mangoCache)
|
||||
const assetsVal = simulation.getAssetsVal(selectedMangoGroup, mangoCache)
|
||||
const liabsVal = simulation.getLiabsVal(selectedMangoGroup, mangoCache)
|
||||
// const collateralRatio = simulation.getCollateralRatio(
|
||||
// selectedMangoGroup,
|
||||
// prices
|
||||
// )
|
||||
// const leverage = 1 / Math.max(0, collateralRatio - 1)
|
||||
|
||||
setSimulation({
|
||||
equity,
|
||||
assetsVal,
|
||||
liabsVal,
|
||||
collateralRatio,
|
||||
leverage,
|
||||
})
|
||||
}, [
|
||||
includeBorrow,
|
||||
inputAmount,
|
||||
prices,
|
||||
tokenIndex,
|
||||
selectedMangoAccount,
|
||||
selectedMangoGroup,
|
||||
mangoCache,
|
||||
])
|
||||
|
||||
const handleWithdraw = () => {
|
||||
setSubmitting(true)
|
||||
const mangoAccount = useMangoStore.getState().selectedMangoAccount.current
|
||||
const mangoGroup = useMangoStore.getState().selectedMangoGroup.current
|
||||
const wallet = useMangoStore.getState().wallet.current
|
||||
if (!mangoAccount || !mangoGroup) return
|
||||
|
||||
if (!includeBorrow) {
|
||||
withdraw(
|
||||
connection,
|
||||
new PublicKey(programId),
|
||||
mangoGroup,
|
||||
mangoAccount,
|
||||
wallet,
|
||||
new PublicKey(symbols[withdrawTokenSymbol]),
|
||||
Number(inputAmount)
|
||||
)
|
||||
.then((_transSig: string) => {
|
||||
setSubmitting(false)
|
||||
actions.fetchMangoGroup()
|
||||
actions.fetchMangoAccounts()
|
||||
actions.fetchWalletTokens()
|
||||
onClose()
|
||||
})
|
||||
.catch((err) => {
|
||||
setSubmitting(false)
|
||||
console.warn('Error withdrawing:', err)
|
||||
notify({
|
||||
message: 'Could not perform withdraw',
|
||||
txid: err.txid,
|
||||
type: 'error',
|
||||
})
|
||||
onClose()
|
||||
})
|
||||
} else {
|
||||
borrowAndWithdraw(
|
||||
connection,
|
||||
new PublicKey(programId),
|
||||
mangoGroup,
|
||||
mangoAccount,
|
||||
wallet,
|
||||
new PublicKey(symbols[withdrawTokenSymbol]),
|
||||
Number(inputAmount)
|
||||
)
|
||||
.then((_transSig: string) => {
|
||||
setSubmitting(false)
|
||||
actions.fetchMangoGroup()
|
||||
actions.fetchMangoAccounts()
|
||||
actions.fetchWalletTokens()
|
||||
onClose()
|
||||
})
|
||||
.catch((err) => {
|
||||
setSubmitting(false)
|
||||
console.warn('Error borrowing and withdrawing:', err)
|
||||
notify({
|
||||
message: 'Could not perform borrow and withdraw',
|
||||
description: `${err}`,
|
||||
txid: err.txid,
|
||||
type: 'error',
|
||||
})
|
||||
onClose()
|
||||
})
|
||||
}
|
||||
withdraw({
|
||||
amount: Number(inputAmount),
|
||||
token: selectedMangoGroup.tokens[tokenIndex].mint,
|
||||
allowBorrow: includeBorrow,
|
||||
})
|
||||
.then((_transSig: string) => {
|
||||
setSubmitting(false)
|
||||
// actions.fetchMangoGroup()
|
||||
actions.fetchMangoAccounts()
|
||||
// actions.fetchWalletTokens()
|
||||
onClose()
|
||||
})
|
||||
.catch((err) => {
|
||||
setSubmitting(false)
|
||||
console.warn('Error withdrawing:', err)
|
||||
// notify({
|
||||
// message: 'Could not perform withdraw',
|
||||
// txid: err.txid,
|
||||
// type: 'error',
|
||||
// })
|
||||
onClose()
|
||||
})
|
||||
}
|
||||
|
||||
const handleSetSelectedAsset = (symbol) => {
|
||||
setInputAmount(0)
|
||||
setInputAmount('')
|
||||
setSliderPercentage(0)
|
||||
setWithdrawTokenSymbol(symbol)
|
||||
}
|
||||
|
||||
const getMaxForSelectedAsset = () => {
|
||||
return displayDepositsForMangoAccount(
|
||||
selectedMangoAccount,
|
||||
const getDepositsForSelectedAsset = (): I80F48 => {
|
||||
return selectedMangoAccount.getUiDeposit(
|
||||
mangoCache.rootBankCache[tokenIndex],
|
||||
selectedMangoGroup,
|
||||
tokenIndex
|
||||
)
|
||||
}
|
||||
|
||||
const getBorrowAmount = () => {
|
||||
const tokenBalance = getMaxForSelectedAsset()
|
||||
const borrowAmount = inputAmount - tokenBalance
|
||||
return borrowAmount > 0 ? borrowAmount : 0
|
||||
const tokenBalance = getDepositsForSelectedAsset()
|
||||
const borrowAmount = I80F48.fromString(inputAmount).sub(tokenBalance)
|
||||
return borrowAmount.gt(ZERO_I80F48) ? borrowAmount : 0
|
||||
}
|
||||
|
||||
const getAccountStatusColor = (
|
||||
|
@ -268,26 +268,28 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
|
||||
const handleIncludeBorrowSwitch = (checked) => {
|
||||
setIncludeBorrow(checked)
|
||||
setInputAmount(0)
|
||||
setInputAmount('0')
|
||||
setSliderPercentage(0)
|
||||
setInvalidAmountMessage('')
|
||||
}
|
||||
|
||||
const setMaxForSelectedAsset = () => {
|
||||
setInputAmount(getMaxForSelectedAsset())
|
||||
setInputAmount(getDepositsForSelectedAsset().toString())
|
||||
setSliderPercentage(100)
|
||||
setInvalidAmountMessage('')
|
||||
setMaxButtonTransition(true)
|
||||
}
|
||||
|
||||
const setMaxBorrowForSelectedAsset = async () => {
|
||||
console.log('setting max borrow for selected', maxAmount)
|
||||
|
||||
setInputAmount(trimDecimals(maxAmount, DECIMALS[withdrawTokenSymbol] + 4))
|
||||
setSliderPercentage(100)
|
||||
setInvalidAmountMessage('')
|
||||
setMaxButtonTransition(true)
|
||||
}
|
||||
|
||||
const onChangeAmountInput = (amount) => {
|
||||
const onChangeAmountInput = (amount: string) => {
|
||||
setInputAmount(amount)
|
||||
setSliderPercentage((amount / maxAmount) * 100)
|
||||
setInvalidAmountMessage('')
|
||||
|
@ -307,14 +309,14 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
|
||||
const validateAmountInput = (amount) => {
|
||||
if (
|
||||
(Number(amount) <= 0 && getMaxForSelectedAsset() > 0) ||
|
||||
(Number(amount) <= 0 && getDepositsForSelectedAsset() > 0) ||
|
||||
(Number(amount) <= 0 && includeBorrow)
|
||||
) {
|
||||
setInvalidAmountMessage('Enter an amount to withdraw')
|
||||
}
|
||||
if (
|
||||
(getMaxForSelectedAsset() === 0 ||
|
||||
Number(amount) > getMaxForSelectedAsset()) &&
|
||||
(getDepositsForSelectedAsset() === 0 ||
|
||||
Number(amount) > getDepositsForSelectedAsset()) &&
|
||||
!includeBorrow
|
||||
) {
|
||||
setInvalidAmountMessage('Insufficient balance. Borrow funds to withdraw')
|
||||
|
@ -336,16 +338,24 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
return temp / step
|
||||
}
|
||||
|
||||
const getTokenBalances = () =>
|
||||
Object.entries(symbols).map(([name], i) => {
|
||||
const getTokenBalances = () => {
|
||||
const mangoCache = useMangoStore.getState().selectedMangoGroup.cache
|
||||
const mangoGroup = useMangoStore.getState().selectedMangoGroup.current
|
||||
|
||||
return tokens.map((token) => {
|
||||
const tokenIndex = mangoGroup.getTokenIndex(token.mintKey)
|
||||
return {
|
||||
symbol: name,
|
||||
balance: floorToDecimal(
|
||||
selectedMangoAccount.getUiDeposit(selectedMangoGroup, i),
|
||||
tokenPrecision[name]
|
||||
),
|
||||
symbol: token.symbol,
|
||||
balance: selectedMangoAccount
|
||||
.getUiDeposit(
|
||||
mangoCache.rootBankCache[tokenIndex],
|
||||
mangoGroup,
|
||||
tokenIndex
|
||||
)
|
||||
.toFixed(tokenPrecision[token.symbol]),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// turn off slider transition for dragging slider handle interaction
|
||||
useEffect(() => {
|
||||
|
@ -356,7 +366,7 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
|
||||
// turn on borrow toggle when asset balance is zero
|
||||
// useEffect(() => {
|
||||
// if (withdrawTokenSymbol && getMaxForSelectedAsset() === 0) {
|
||||
// if (withdrawTokenSymbol && getDepositsForSelectedAsset() === 0) {
|
||||
// setIncludeBorrow(true)
|
||||
// }
|
||||
// }, [withdrawTokenSymbol])
|
||||
|
@ -386,13 +396,13 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
/>
|
||||
{withdrawTokenSymbol}
|
||||
</div>
|
||||
{floorToDecimal(
|
||||
selectedMangoAccount.getUiDeposit(
|
||||
{selectedMangoAccount
|
||||
.getUiDeposit(
|
||||
mangoCache.rootBankCache[tokenIndex],
|
||||
selectedMangoGroup,
|
||||
tokenIndex
|
||||
),
|
||||
tokenPrecision[withdrawTokenSymbol]
|
||||
)}
|
||||
)
|
||||
.toFixed(tokenPrecision[withdrawTokenSymbol])}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-th-fgd-4">Select an asset</span>
|
||||
|
@ -438,7 +448,10 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
<div className="flex space-x-4">
|
||||
<button
|
||||
className="font-normal text-th-fgd-1 underline cursor-pointer default-transition hover:text-th-primary hover:no-underline focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
disabled={!includeBorrow && getMaxForSelectedAsset() === 0}
|
||||
disabled={
|
||||
!includeBorrow &&
|
||||
getDepositsForSelectedAsset().eq(ZERO_I80F48)
|
||||
}
|
||||
onClick={
|
||||
includeBorrow
|
||||
? setMaxBorrowForSelectedAsset
|
||||
|
@ -546,20 +559,20 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<span className="flex h-2 w-2 mr-2.5 relative">
|
||||
<span
|
||||
{/* <span
|
||||
className={`animate-ping absolute inline-flex h-full w-full rounded-full ${getAccountStatusColor(
|
||||
simulation.collateralRatio,
|
||||
false,
|
||||
true
|
||||
)} opacity-75`}
|
||||
></span>
|
||||
<span
|
||||
></span> */}
|
||||
{/* <span
|
||||
className={`relative inline-flex rounded-full h-2 w-2 ${getAccountStatusColor(
|
||||
simulation.collateralRatio,
|
||||
false,
|
||||
true
|
||||
)}`}
|
||||
></span>
|
||||
></span> */}
|
||||
</span>
|
||||
Account Health Check
|
||||
<Tooltip content="The details of your account after this withdrawal.">
|
||||
|
@ -596,18 +609,18 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
</div>
|
||||
<div className="flex justify-between pb-2">
|
||||
<div className="text-th-fgd-4">Leverage</div>
|
||||
<div className="text-th-fgd-1">
|
||||
{/* <div className="text-th-fgd-1">
|
||||
{simulation.leverage.toFixed(2)}x
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<div className="text-th-fgd-4">Collateral Ratio</div>
|
||||
<div className="text-th-fgd-1">
|
||||
{/* <div className="text-th-fgd-1">
|
||||
{simulation.collateralRatio * 100 < 200
|
||||
? Math.floor(simulation.collateralRatio * 100)
|
||||
: '>200'}
|
||||
%
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
{simulation.liabsVal > 0.05 ? (
|
||||
<div className="flex justify-between pt-2">
|
||||
|
@ -626,7 +639,8 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
<Button
|
||||
onClick={handleWithdraw}
|
||||
disabled={
|
||||
Number(inputAmount) <= 0 || simulation.collateralRatio < 1.2
|
||||
Number(inputAmount) <=
|
||||
0 /* || simulation.collateralRatio < 1.2*/
|
||||
}
|
||||
className="w-full"
|
||||
>
|
||||
|
|
|
@ -41,7 +41,6 @@ const useHydrateStore = () => {
|
|||
const bidSubscriptionId = WEBSOCKET_CONNECTION.onAccountChange(
|
||||
marketConfig.bidsKey,
|
||||
(info) => {
|
||||
console.log('bid websocket')
|
||||
if (
|
||||
!previousBidInfo ||
|
||||
!previousBidInfo.data.equals(info.data) ||
|
||||
|
@ -58,7 +57,6 @@ const useHydrateStore = () => {
|
|||
const askSubscriptionId = WEBSOCKET_CONNECTION.onAccountChange(
|
||||
marketConfig.asksKey,
|
||||
(info) => {
|
||||
console.log('ask websocket')
|
||||
if (
|
||||
!previousAskInfo ||
|
||||
!previousAskInfo.data.equals(info.data) ||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@blockworks-foundation/mango-client": "git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-client-v3.git",
|
||||
"@blockworks-foundation/mango-client": "git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-client-v3.git#ts/mangoacc",
|
||||
"@emotion/react": "^11.1.5",
|
||||
"@emotion/styled": "^11.1.5",
|
||||
"@headlessui/react": "^1.2.0",
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { TokenAccount } from '@blockworks-foundation/mango-client'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import useMangoStore, { mangoClient } from '../stores/useMangoStore'
|
||||
import { findAssociatedTokenAddress } from './associated'
|
||||
|
||||
export async function deposit({
|
||||
amount,
|
||||
|
@ -42,6 +44,36 @@ export async function deposit({
|
|||
}
|
||||
}
|
||||
|
||||
export async function withdraw({
|
||||
amount,
|
||||
token,
|
||||
allowBorrow,
|
||||
}: {
|
||||
amount: number
|
||||
token: PublicKey
|
||||
allowBorrow: boolean
|
||||
}) {
|
||||
const mangoAccount = useMangoStore.getState().selectedMangoAccount.current
|
||||
const mangoGroup = useMangoStore.getState().selectedMangoGroup.current
|
||||
const wallet = useMangoStore.getState().wallet.current
|
||||
|
||||
const tokenAcc = await findAssociatedTokenAddress(wallet.publicKey, token)
|
||||
|
||||
const tokenIndex = mangoGroup.getTokenIndex(token)
|
||||
|
||||
return mangoClient.withdraw(
|
||||
mangoGroup,
|
||||
mangoAccount,
|
||||
wallet,
|
||||
mangoGroup.tokens[tokenIndex].rootBank,
|
||||
mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].publicKey,
|
||||
mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].vault,
|
||||
tokenAcc,
|
||||
Number(amount),
|
||||
allowBorrow
|
||||
)
|
||||
}
|
||||
|
||||
// import {
|
||||
// createAccountInstruction,
|
||||
// nativeToUi,
|
||||
|
|
|
@ -986,9 +986,9 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@blockworks-foundation/mango-client@git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-client-v3.git":
|
||||
"@blockworks-foundation/mango-client@git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-client-v3.git#ts/mangoacc":
|
||||
version "3.0.1"
|
||||
resolved "git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-client-v3.git#7f59596117f3fb9d572747735efe71a93b021f8d"
|
||||
resolved "git+https://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:x-oauth-basic@github.com/blockworks-foundation/mango-client-v3.git#4cf0e96e0982363028844592c52c1ce90bd7c70d"
|
||||
dependencies:
|
||||
"@project-serum/serum" "^0.13.38"
|
||||
"@project-serum/sol-wallet-adapter" "^0.2.0"
|
||||
|
|
Loading…
Reference in New Issue