add hook for banks and balances
This commit is contained in:
parent
52e871e566
commit
d8970b02c6
|
@ -1,4 +1,4 @@
|
||||||
import { Bank, HealthType } from '@blockworks-foundation/mango-v4'
|
import { HealthType } from '@blockworks-foundation/mango-v4'
|
||||||
import {
|
import {
|
||||||
ArrowLeftIcon,
|
ArrowLeftIcon,
|
||||||
ArrowUpLeftIcon,
|
ArrowUpLeftIcon,
|
||||||
|
@ -42,6 +42,7 @@ import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
||||||
import FormatNumericValue from './shared/FormatNumericValue'
|
import FormatNumericValue from './shared/FormatNumericValue'
|
||||||
import { floorToDecimal } from 'utils/numbers'
|
import { floorToDecimal } from 'utils/numbers'
|
||||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
interface BorrowFormProps {
|
interface BorrowFormProps {
|
||||||
onSuccess: () => void
|
onSuccess: () => void
|
||||||
|
@ -62,6 +63,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
||||||
const { mangoAccount } = useMangoAccount()
|
const { mangoAccount } = useMangoAccount()
|
||||||
const { connected, publicKey } = useWallet()
|
const { connected, publicKey } = useWallet()
|
||||||
const { handleConnect } = useEnhancedWallet()
|
const { handleConnect } = useEnhancedWallet()
|
||||||
|
const banks = useBanksWithBalances('maxBorrow')
|
||||||
|
|
||||||
const bank = useMemo(() => {
|
const bank = useMemo(() => {
|
||||||
const group = mangoStore.getState().group
|
const group = mangoStore.getState().group
|
||||||
|
@ -154,28 +156,6 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
||||||
}
|
}
|
||||||
}, [bank, inputAmount, onSuccess, publicKey])
|
}, [bank, inputAmount, onSuccess, publicKey])
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
|
||||||
if (mangoAccount) {
|
|
||||||
return group?.banksMapByName
|
|
||||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
|
||||||
const bank: Bank = value[0]
|
|
||||||
const maxAmount = getMaxWithdrawForBank(
|
|
||||||
group,
|
|
||||||
bank,
|
|
||||||
mangoAccount,
|
|
||||||
true
|
|
||||||
).toNumber()
|
|
||||||
return {
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
maxAmount,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: []
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}, [mangoAccount, group])
|
|
||||||
|
|
||||||
const handleInputChange = (e: NumberFormatValues, info: SourceInfo) => {
|
const handleInputChange = (e: NumberFormatValues, info: SourceInfo) => {
|
||||||
if (info.source === 'event') {
|
if (info.source === 'event') {
|
||||||
setSizePercentage('')
|
setSizePercentage('')
|
||||||
|
@ -221,8 +201,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
||||||
banks={banks}
|
banks={banks}
|
||||||
onSelect={handleSelectToken}
|
onSelect={handleSelectToken}
|
||||||
showBorrowRates
|
showBorrowRates
|
||||||
sortByKey="maxAmount"
|
valueKey="maxBorrow"
|
||||||
valueKey="maxAmount"
|
|
||||||
/>
|
/>
|
||||||
</EnterBottomExitBottom>
|
</EnterBottomExitBottom>
|
||||||
<FadeInFadeOut show={!showTokenList}>
|
<FadeInFadeOut show={!showTokenList}>
|
||||||
|
|
|
@ -32,13 +32,13 @@ import Tooltip from '@components/shared/Tooltip'
|
||||||
import HealthImpactTokenChange from '@components/HealthImpactTokenChange'
|
import HealthImpactTokenChange from '@components/HealthImpactTokenChange'
|
||||||
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
||||||
import useJupiterMints from 'hooks/useJupiterMints'
|
import useJupiterMints from 'hooks/useJupiterMints'
|
||||||
import useMangoGroup from 'hooks/useMangoGroup'
|
|
||||||
import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
||||||
import useSolBalance from 'hooks/useSolBalance'
|
import useSolBalance from 'hooks/useSolBalance'
|
||||||
import FormatNumericValue from './shared/FormatNumericValue'
|
import FormatNumericValue from './shared/FormatNumericValue'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
import { floorToDecimal } from 'utils/numbers'
|
import { floorToDecimal } from 'utils/numbers'
|
||||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
interface DepositFormProps {
|
interface DepositFormProps {
|
||||||
onSuccess: () => void
|
onSuccess: () => void
|
||||||
|
@ -89,7 +89,6 @@ export const useAlphaMax = (inputAmount: string, bank: Bank | undefined) => {
|
||||||
|
|
||||||
function DepositForm({ onSuccess, token }: DepositFormProps) {
|
function DepositForm({ onSuccess, token }: DepositFormProps) {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
const { group } = useMangoGroup()
|
|
||||||
const [inputAmount, setInputAmount] = useState('')
|
const [inputAmount, setInputAmount] = useState('')
|
||||||
const [submitting, setSubmitting] = useState(false)
|
const [submitting, setSubmitting] = useState(false)
|
||||||
const [selectedToken, setSelectedToken] = useState(
|
const [selectedToken, setSelectedToken] = useState(
|
||||||
|
@ -100,6 +99,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
||||||
const { mangoTokens } = useJupiterMints()
|
const { mangoTokens } = useJupiterMints()
|
||||||
const { handleConnect } = useEnhancedWallet()
|
const { handleConnect } = useEnhancedWallet()
|
||||||
const { maxSolDeposit } = useSolBalance()
|
const { maxSolDeposit } = useSolBalance()
|
||||||
|
const banks = useBanksWithBalances('walletBalance')
|
||||||
|
|
||||||
const bank = useMemo(() => {
|
const bank = useMemo(() => {
|
||||||
const group = mangoStore.getState().group
|
const group = mangoStore.getState().group
|
||||||
|
@ -185,22 +185,6 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
||||||
}
|
}
|
||||||
}, [bank, publicKey, inputAmount])
|
}, [bank, publicKey, inputAmount])
|
||||||
|
|
||||||
// TODO extract into a shared hook for UserSetup.tsx
|
|
||||||
const banks = useMemo(() => {
|
|
||||||
const banks = group?.banksMapByName
|
|
||||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
|
||||||
const walletBalance = walletBalanceForToken(walletTokens, key)
|
|
||||||
return {
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
walletBalance: walletBalance.maxAmount,
|
|
||||||
walletBalanceValue: walletBalance.maxAmount * value[0].uiPrice!,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: []
|
|
||||||
return banks
|
|
||||||
}, [group?.banksMapByName, walletTokens])
|
|
||||||
|
|
||||||
const showInsufficientBalance =
|
const showInsufficientBalance =
|
||||||
tokenMax.maxAmount < Number(inputAmount) ||
|
tokenMax.maxAmount < Number(inputAmount) ||
|
||||||
(selectedToken === 'SOL' && maxSolDeposit <= 0)
|
(selectedToken === 'SOL' && maxSolDeposit <= 0)
|
||||||
|
@ -235,7 +219,6 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
||||||
banks={banks}
|
banks={banks}
|
||||||
onSelect={handleSelectToken}
|
onSelect={handleSelectToken}
|
||||||
showDepositRates
|
showDepositRates
|
||||||
sortByKey="walletBalanceValue"
|
|
||||||
valueKey="walletBalance"
|
valueKey="walletBalance"
|
||||||
/>
|
/>
|
||||||
</EnterBottomExitBottom>
|
</EnterBottomExitBottom>
|
||||||
|
|
|
@ -27,13 +27,13 @@ import { useAlphaMax, walletBalanceForToken } from './DepositForm'
|
||||||
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
||||||
import useMangoAccount from 'hooks/useMangoAccount'
|
import useMangoAccount from 'hooks/useMangoAccount'
|
||||||
import useJupiterMints from 'hooks/useJupiterMints'
|
import useJupiterMints from 'hooks/useJupiterMints'
|
||||||
import useMangoGroup from 'hooks/useMangoGroup'
|
|
||||||
import {
|
import {
|
||||||
ACCOUNT_ACTION_MODAL_INNER_HEIGHT,
|
ACCOUNT_ACTION_MODAL_INNER_HEIGHT,
|
||||||
INPUT_TOKEN_DEFAULT,
|
INPUT_TOKEN_DEFAULT,
|
||||||
} from 'utils/constants'
|
} from 'utils/constants'
|
||||||
import ConnectEmptyState from './shared/ConnectEmptyState'
|
import ConnectEmptyState from './shared/ConnectEmptyState'
|
||||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
interface RepayFormProps {
|
interface RepayFormProps {
|
||||||
onSuccess: () => void
|
onSuccess: () => void
|
||||||
|
@ -42,7 +42,6 @@ interface RepayFormProps {
|
||||||
|
|
||||||
function RepayForm({ onSuccess, token }: RepayFormProps) {
|
function RepayForm({ onSuccess, token }: RepayFormProps) {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
const { group } = useMangoGroup()
|
|
||||||
const { mangoAccount } = useMangoAccount()
|
const { mangoAccount } = useMangoAccount()
|
||||||
const [inputAmount, setInputAmount] = useState('')
|
const [inputAmount, setInputAmount] = useState('')
|
||||||
const [submitting, setSubmitting] = useState(false)
|
const [submitting, setSubmitting] = useState(false)
|
||||||
|
@ -52,6 +51,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
||||||
const [showTokenList, setShowTokenList] = useState(false)
|
const [showTokenList, setShowTokenList] = useState(false)
|
||||||
const [sizePercentage, setSizePercentage] = useState('')
|
const [sizePercentage, setSizePercentage] = useState('')
|
||||||
const { mangoTokens } = useJupiterMints()
|
const { mangoTokens } = useJupiterMints()
|
||||||
|
const banks = useBanksWithBalances('borrowedAmount')
|
||||||
// const { maxSolDeposit } = useSolBalance()
|
// const { maxSolDeposit } = useSolBalance()
|
||||||
|
|
||||||
const bank = useMemo(() => {
|
const bank = useMemo(() => {
|
||||||
|
@ -168,27 +168,9 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
||||||
[bank, publicKey?.toBase58(), sizePercentage]
|
[bank, publicKey?.toBase58(), sizePercentage]
|
||||||
)
|
)
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
|
||||||
const banks =
|
|
||||||
group?.banksMapByName && mangoAccount
|
|
||||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
|
||||||
return {
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
borrowAmount: mangoAccount.getTokenBorrowsUi(value[0]),
|
|
||||||
borrowAmountValue:
|
|
||||||
mangoAccount.getTokenBorrowsUi(value[0]) * value[0].uiPrice,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter((b) => b.borrowAmount > 0)
|
|
||||||
.sort((a, b) => a.borrowAmount - b.borrowAmount)
|
|
||||||
: []
|
|
||||||
return banks
|
|
||||||
}, [group?.banksMapByName, mangoAccount])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedToken && !token && banks.length) {
|
if (!selectedToken && !token && banks.length) {
|
||||||
setSelectedToken(banks[0].key)
|
setSelectedToken(banks[0].bank.name)
|
||||||
}
|
}
|
||||||
}, [token, banks, selectedToken])
|
}, [token, banks, selectedToken])
|
||||||
|
|
||||||
|
@ -220,8 +202,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
||||||
<ActionTokenList
|
<ActionTokenList
|
||||||
banks={banks}
|
banks={banks}
|
||||||
onSelect={handleSelectToken}
|
onSelect={handleSelectToken}
|
||||||
sortByKey="borrowAmountValue"
|
valueKey="borrowedAmount"
|
||||||
valueKey="borrowAmount"
|
|
||||||
/>
|
/>
|
||||||
</EnterBottomExitBottom>
|
</EnterBottomExitBottom>
|
||||||
<FadeInFadeOut show={!showTokenList}>
|
<FadeInFadeOut show={!showTokenList}>
|
||||||
|
|
|
@ -23,7 +23,6 @@ import { formatTokenSymbol } from 'utils/tokens'
|
||||||
import useMangoAccount from 'hooks/useMangoAccount'
|
import useMangoAccount from 'hooks/useMangoAccount'
|
||||||
import useJupiterMints from '../hooks/useJupiterMints'
|
import useJupiterMints from '../hooks/useJupiterMints'
|
||||||
import { Table, Td, Th, TrBody, TrHead } from './shared/TableElements'
|
import { Table, Td, Th, TrBody, TrHead } from './shared/TableElements'
|
||||||
import useMangoGroup from 'hooks/useMangoGroup'
|
|
||||||
import DepositWithdrawModal from './modals/DepositWithdrawModal'
|
import DepositWithdrawModal from './modals/DepositWithdrawModal'
|
||||||
import BorrowRepayModal from './modals/BorrowRepayModal'
|
import BorrowRepayModal from './modals/BorrowRepayModal'
|
||||||
import { WRAPPED_SOL_MINT } from '@project-serum/serum/lib/token-instructions'
|
import { WRAPPED_SOL_MINT } from '@project-serum/serum/lib/token-instructions'
|
||||||
|
@ -32,6 +31,9 @@ import { PublicKey } from '@solana/web3.js'
|
||||||
import ActionsLinkButton from './account/ActionsLinkButton'
|
import ActionsLinkButton from './account/ActionsLinkButton'
|
||||||
import FormatNumericValue from './shared/FormatNumericValue'
|
import FormatNumericValue from './shared/FormatNumericValue'
|
||||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||||
|
import useBanksWithBalances, {
|
||||||
|
BankWithBalance,
|
||||||
|
} from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
const TokenList = () => {
|
const TokenList = () => {
|
||||||
const { t } = useTranslation(['common', 'token', 'trade'])
|
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||||
|
@ -39,7 +41,6 @@ const TokenList = () => {
|
||||||
const [showZeroBalances, setShowZeroBalances] = useState(true)
|
const [showZeroBalances, setShowZeroBalances] = useState(true)
|
||||||
const { mangoAccount } = useMangoAccount()
|
const { mangoAccount } = useMangoAccount()
|
||||||
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
||||||
const { group } = useMangoGroup()
|
|
||||||
const { mangoTokens } = useJupiterMints()
|
const { mangoTokens } = useJupiterMints()
|
||||||
const totalInterestData = mangoStore(
|
const totalInterestData = mangoStore(
|
||||||
(s) => s.mangoAccount.interestTotals.data
|
(s) => s.mangoAccount.interestTotals.data
|
||||||
|
@ -47,40 +48,16 @@ const TokenList = () => {
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
const showTableView = width ? width > breakpoints.md : false
|
const showTableView = width ? width > breakpoints.md : false
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const banks = useBanksWithBalances('balance')
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
const filteredBanks = useMemo(() => {
|
||||||
if (group) {
|
if (banks.length) {
|
||||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
return showZeroBalances
|
||||||
key,
|
? banks
|
||||||
value,
|
: banks.filter((b) => Math.abs(b.balance) > 0)
|
||||||
}))
|
|
||||||
const sortedBanks = mangoAccount
|
|
||||||
? rawBanks.sort((a, b) => {
|
|
||||||
const aBalance = Math.abs(
|
|
||||||
mangoAccount.getTokenBalanceUi(a.value[0]) * a.value[0].uiPrice
|
|
||||||
)
|
|
||||||
const bBalance = Math.abs(
|
|
||||||
mangoAccount.getTokenBalanceUi(b.value[0]) * b.value[0].uiPrice
|
|
||||||
)
|
|
||||||
if (aBalance > bBalance) return -1
|
|
||||||
if (aBalance < bBalance) return 1
|
|
||||||
|
|
||||||
const aName = a.value[0].name
|
|
||||||
const bName = b.value[0].name
|
|
||||||
if (aName > bName) return 1
|
|
||||||
if (aName < bName) return -1
|
|
||||||
return 1
|
|
||||||
})
|
|
||||||
: rawBanks.sort((a, b) => a.key.localeCompare(b.key))
|
|
||||||
|
|
||||||
return mangoAccount && !showZeroBalances
|
|
||||||
? sortedBanks.filter(
|
|
||||||
(b) => mangoAccount?.getTokenBalanceUi(b.value[0]) !== 0
|
|
||||||
)
|
|
||||||
: sortedBanks
|
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}, [showZeroBalances, group, mangoAccount])
|
}, [banks, showZeroBalances])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
|
@ -88,8 +65,8 @@ const TokenList = () => {
|
||||||
}
|
}
|
||||||
}, [connected])
|
}, [connected])
|
||||||
|
|
||||||
const goToTokenPage = (bank: Bank) => {
|
const goToTokenPage = (symbol: string) => {
|
||||||
router.push(`/token/${bank.name}`, undefined, { shallow: true })
|
router.push(`/token/${symbol}`, undefined, { shallow: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -135,8 +112,8 @@ const TokenList = () => {
|
||||||
</TrHead>
|
</TrHead>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{banks.map(({ key, value }) => {
|
{filteredBanks.map((b) => {
|
||||||
const bank = value[0]
|
const bank = b.bank
|
||||||
|
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens?.length) {
|
if (mangoTokens?.length) {
|
||||||
|
@ -145,9 +122,7 @@ const TokenList = () => {
|
||||||
)?.logoURI
|
)?.logoURI
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokenBalance = mangoAccount
|
const tokenBalance = b.balance
|
||||||
? mangoAccount.getTokenBalanceUi(bank)
|
|
||||||
: 0
|
|
||||||
|
|
||||||
const hasInterestEarned = totalInterestData.find(
|
const hasInterestEarned = totalInterestData.find(
|
||||||
(d) => d.symbol === bank.name
|
(d) => d.symbol === bank.name
|
||||||
|
@ -169,7 +144,7 @@ const TokenList = () => {
|
||||||
spotBalances[bank.mint.toString()]?.unsettled || 0
|
spotBalances[bank.mint.toString()]?.unsettled || 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TrBody className="last:border-y-0" key={key}>
|
<TrBody className="last:border-y-0" key={bank.name}>
|
||||||
<Td>
|
<Td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||||
|
@ -237,7 +212,7 @@ const TokenList = () => {
|
||||||
<div className="flex justify-end space-x-2">
|
<div className="flex justify-end space-x-2">
|
||||||
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
|
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => goToTokenPage(bank)}
|
onClick={() => goToTokenPage(bank.name)}
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<ChevronRightIcon className="h-5 w-5" />
|
<ChevronRightIcon className="h-5 w-5" />
|
||||||
|
@ -251,8 +226,8 @@ const TokenList = () => {
|
||||||
</Table>
|
</Table>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
{banks.map(({ key, value }) => {
|
{filteredBanks.map((b) => {
|
||||||
return <MobileTokenListItem key={key} bank={value[0]} />
|
return <MobileTokenListItem key={b.bank.name} bank={b} />
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -262,7 +237,7 @@ const TokenList = () => {
|
||||||
|
|
||||||
export default TokenList
|
export default TokenList
|
||||||
|
|
||||||
const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
|
||||||
const { t } = useTranslation(['common', 'token'])
|
const { t } = useTranslation(['common', 'token'])
|
||||||
const [showTokenDetails, setShowTokenDetails] = useState(false)
|
const [showTokenDetails, setShowTokenDetails] = useState(false)
|
||||||
const { mangoTokens } = useJupiterMints()
|
const { mangoTokens } = useJupiterMints()
|
||||||
|
@ -271,19 +246,19 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||||
const totalInterestData = mangoStore(
|
const totalInterestData = mangoStore(
|
||||||
(s) => s.mangoAccount.interestTotals.data
|
(s) => s.mangoAccount.interestTotals.data
|
||||||
)
|
)
|
||||||
const symbol = bank.name
|
const tokenBank = bank.bank
|
||||||
|
const mint = tokenBank.mint
|
||||||
|
const symbol = tokenBank.name
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens?.length) {
|
if (mangoTokens?.length) {
|
||||||
logoURI = mangoTokens.find(
|
logoURI = mangoTokens.find(
|
||||||
(t) => t.address === bank.mint.toString()
|
(t) => t.address === tokenBank.mint.toString()
|
||||||
)!.logoURI
|
)!.logoURI
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasInterestEarned = totalInterestData.find(
|
const hasInterestEarned = totalInterestData.find((d) => d.symbol === symbol)
|
||||||
(d) => d.symbol === bank.name
|
|
||||||
)
|
|
||||||
|
|
||||||
const interestAmount = hasInterestEarned
|
const interestAmount = hasInterestEarned
|
||||||
? hasInterestEarned.borrow_interest * -1 +
|
? hasInterestEarned.borrow_interest * -1 +
|
||||||
|
@ -295,14 +270,14 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||||
hasInterestEarned.deposit_interest_usd
|
hasInterestEarned.deposit_interest_usd
|
||||||
: 0
|
: 0
|
||||||
|
|
||||||
const tokenBalance = mangoAccount ? mangoAccount.getTokenBalanceUi(bank) : 0
|
const tokenBalance = bank.balance
|
||||||
|
|
||||||
const inOrders = spotBalances[bank.mint.toString()]?.inOrders || 0
|
const inOrders = spotBalances[mint.toString()]?.inOrders || 0
|
||||||
|
|
||||||
const unsettled = spotBalances[bank.mint.toString()]?.unsettled || 0
|
const unsettled = spotBalances[mint.toString()]?.unsettled || 0
|
||||||
|
|
||||||
const goToTokenPage = (bank: Bank) => {
|
const goToTokenPage = (symbol: string) => {
|
||||||
router.push(`/token/${bank.name}`, undefined, { shallow: true })
|
router.push(`/token/${symbol}`, undefined, { shallow: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -317,20 +292,20 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-th-fgd-1">{bank.name}</p>
|
<p className="text-th-fgd-1">{symbol}</p>
|
||||||
<p className="font-mono text-sm text-th-fgd-1">
|
<p className="font-mono text-sm text-th-fgd-1">
|
||||||
<span className="mr-1 font-body text-th-fgd-4">
|
<span className="mr-1 font-body text-th-fgd-4">
|
||||||
{t('balance')}:
|
{t('balance')}:
|
||||||
</span>
|
</span>
|
||||||
<FormatNumericValue
|
<FormatNumericValue
|
||||||
value={tokenBalance}
|
value={tokenBalance}
|
||||||
decimals={bank.mintDecimals}
|
decimals={tokenBank.mintDecimals}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
|
<ActionsMenu bank={tokenBank} mangoAccount={mangoAccount} />
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => setShowTokenDetails((prev) => !prev)}
|
onClick={() => setShowTokenDetails((prev) => !prev)}
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -357,17 +332,17 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||||
<div className="mt-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4">
|
<div className="mt-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4">
|
||||||
<div className="col-span-1">
|
<div className="col-span-1">
|
||||||
<p className="text-xs text-th-fgd-3">{t('trade:in-orders')}</p>
|
<p className="text-xs text-th-fgd-3">{t('trade:in-orders')}</p>
|
||||||
<BankAmountWithValue amount={inOrders} bank={bank} />
|
<BankAmountWithValue amount={inOrders} bank={tokenBank} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-1">
|
<div className="col-span-1">
|
||||||
<p className="text-xs text-th-fgd-3">{t('trade:unsettled')}</p>
|
<p className="text-xs text-th-fgd-3">{t('trade:unsettled')}</p>
|
||||||
<BankAmountWithValue amount={unsettled} bank={bank} />
|
<BankAmountWithValue amount={unsettled} bank={tokenBank} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-1">
|
<div className="col-span-1">
|
||||||
<p className="text-xs text-th-fgd-3">{t('interest-earned-paid')}</p>
|
<p className="text-xs text-th-fgd-3">{t('interest-earned-paid')}</p>
|
||||||
<BankAmountWithValue
|
<BankAmountWithValue
|
||||||
amount={interestAmount}
|
amount={interestAmount}
|
||||||
bank={bank}
|
bank={tokenBank}
|
||||||
value={interestValue}
|
value={interestValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -376,7 +351,7 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||||
<p className="space-x-2 font-mono">
|
<p className="space-x-2 font-mono">
|
||||||
<span className="text-th-up">
|
<span className="text-th-up">
|
||||||
<FormatNumericValue
|
<FormatNumericValue
|
||||||
value={bank.getDepositRateUi()}
|
value={tokenBank.getDepositRateUi()}
|
||||||
decimals={2}
|
decimals={2}
|
||||||
/>
|
/>
|
||||||
%
|
%
|
||||||
|
@ -384,7 +359,7 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||||
<span className="font-normal text-th-fgd-4">|</span>
|
<span className="font-normal text-th-fgd-4">|</span>
|
||||||
<span className="text-th-down">
|
<span className="text-th-down">
|
||||||
<FormatNumericValue
|
<FormatNumericValue
|
||||||
value={bank.getBorrowRateUi()}
|
value={tokenBank.getBorrowRateUi()}
|
||||||
decimals={2}
|
decimals={2}
|
||||||
roundUp
|
roundUp
|
||||||
/>
|
/>
|
||||||
|
@ -395,7 +370,7 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||||
<div className="col-span-1">
|
<div className="col-span-1">
|
||||||
<LinkButton
|
<LinkButton
|
||||||
className="flex items-center"
|
className="flex items-center"
|
||||||
onClick={() => goToTokenPage(bank)}
|
onClick={() => goToTokenPage(symbol)}
|
||||||
>
|
>
|
||||||
{t('token:token-details')}
|
{t('token:token-details')}
|
||||||
<ChevronRightIcon className="ml-1.5 h-5 w-5" />
|
<ChevronRightIcon className="ml-1.5 h-5 w-5" />
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Bank, HealthType } from '@blockworks-foundation/mango-v4'
|
import { HealthType } from '@blockworks-foundation/mango-v4'
|
||||||
import {
|
import {
|
||||||
ArrowLeftIcon,
|
ArrowLeftIcon,
|
||||||
ArrowUpTrayIcon,
|
ArrowUpTrayIcon,
|
||||||
|
@ -37,6 +37,7 @@ import { useWallet } from '@solana/wallet-adapter-react'
|
||||||
import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
||||||
import { floorToDecimal } from 'utils/numbers'
|
import { floorToDecimal } from 'utils/numbers'
|
||||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
interface WithdrawFormProps {
|
interface WithdrawFormProps {
|
||||||
onSuccess: () => void
|
onSuccess: () => void
|
||||||
|
@ -57,6 +58,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
||||||
const { mangoAccount } = useMangoAccount()
|
const { mangoAccount } = useMangoAccount()
|
||||||
const { connected } = useWallet()
|
const { connected } = useWallet()
|
||||||
const { handleConnect } = useEnhancedWallet()
|
const { handleConnect } = useEnhancedWallet()
|
||||||
|
const banks = useBanksWithBalances('maxWithdraw')
|
||||||
|
|
||||||
const bank = useMemo(() => {
|
const bank = useMemo(() => {
|
||||||
const group = mangoStore.getState().group
|
const group = mangoStore.getState().group
|
||||||
|
@ -140,32 +142,6 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
||||||
setShowTokenList(false)
|
setShowTokenList(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const withdrawBanks = useMemo(() => {
|
|
||||||
if (mangoAccount) {
|
|
||||||
const banks = group?.banksMapByName
|
|
||||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
|
||||||
const bank: Bank = value[0]
|
|
||||||
const accountBalance = getMaxWithdrawForBank(
|
|
||||||
group,
|
|
||||||
bank,
|
|
||||||
mangoAccount
|
|
||||||
).toNumber()
|
|
||||||
return {
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
accountBalance,
|
|
||||||
accountBalanceValue:
|
|
||||||
accountBalance && bank.uiPrice
|
|
||||||
? accountBalance * bank.uiPrice
|
|
||||||
: 0,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: []
|
|
||||||
return banks
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}, [mangoAccount, group])
|
|
||||||
|
|
||||||
const initHealth = useMemo(() => {
|
const initHealth = useMemo(() => {
|
||||||
return group && mangoAccount
|
return group && mangoAccount
|
||||||
? mangoAccount.getHealthRatioUi(group, HealthType.init)
|
? mangoAccount.getHealthRatioUi(group, HealthType.init)
|
||||||
|
@ -200,10 +176,9 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ActionTokenList
|
<ActionTokenList
|
||||||
banks={withdrawBanks}
|
banks={banks}
|
||||||
onSelect={handleSelectToken}
|
onSelect={handleSelectToken}
|
||||||
sortByKey="accountBalanceValue"
|
valueKey="maxWithdraw"
|
||||||
valueKey="accountBalance"
|
|
||||||
/>
|
/>
|
||||||
</EnterBottomExitBottom>
|
</EnterBottomExitBottom>
|
||||||
<FadeInFadeOut show={!showTokenList}>
|
<FadeInFadeOut show={!showTokenList}>
|
||||||
|
|
|
@ -3,31 +3,31 @@ import useMangoAccount from 'hooks/useMangoAccount'
|
||||||
import ActionTokenItem from './ActionTokenItem'
|
import ActionTokenItem from './ActionTokenItem'
|
||||||
|
|
||||||
type BankParams = {
|
type BankParams = {
|
||||||
key: string
|
bank: Bank
|
||||||
value: Bank[]
|
balance: number
|
||||||
walletBalance?: number
|
borrowedAmount: number
|
||||||
maxAmount?: number
|
walletBalance: number
|
||||||
accountBalance?: number
|
maxBorrow: number
|
||||||
|
maxWithdraw: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActionTokenList = ({
|
const ActionTokenList = ({
|
||||||
banks,
|
banks,
|
||||||
onSelect,
|
onSelect,
|
||||||
sortByKey,
|
|
||||||
showBorrowRates,
|
showBorrowRates,
|
||||||
showDepositRates,
|
showDepositRates,
|
||||||
valueKey,
|
valueKey,
|
||||||
}: {
|
}: {
|
||||||
banks: BankParams[]
|
banks: BankParams[]
|
||||||
onSelect: (x: string) => void
|
onSelect: (x: string) => void
|
||||||
sortByKey:
|
|
||||||
| 'maxAmount'
|
|
||||||
| 'walletBalanceValue'
|
|
||||||
| 'accountBalanceValue'
|
|
||||||
| 'borrowAmountValue'
|
|
||||||
showBorrowRates?: boolean
|
showBorrowRates?: boolean
|
||||||
showDepositRates?: boolean
|
showDepositRates?: boolean
|
||||||
valueKey: 'maxAmount' | 'walletBalance' | 'accountBalance' | 'borrowAmount'
|
valueKey:
|
||||||
|
| 'balance'
|
||||||
|
| 'borrowedAmount'
|
||||||
|
| 'maxBorrow'
|
||||||
|
| 'maxWithdraw'
|
||||||
|
| 'walletBalance'
|
||||||
}) => {
|
}) => {
|
||||||
const { mangoAccount } = useMangoAccount()
|
const { mangoAccount } = useMangoAccount()
|
||||||
|
|
||||||
|
@ -37,15 +37,14 @@ const ActionTokenList = ({
|
||||||
{banks?.length ? (
|
{banks?.length ? (
|
||||||
banks
|
banks
|
||||||
.filter((b: BankParams) => !!b)
|
.filter((b: BankParams) => !!b)
|
||||||
.sort((a: any, b: any) => b[sortByKey] - a[sortByKey])
|
.map((b: any) => {
|
||||||
.map((bank: any) => {
|
|
||||||
return (
|
return (
|
||||||
<ActionTokenItem
|
<ActionTokenItem
|
||||||
bank={bank.value[0]}
|
bank={b.bank}
|
||||||
customValue={bank[valueKey]}
|
customValue={b[valueKey]}
|
||||||
key={bank.value[0].name}
|
key={b.bank.name}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
roundUp={valueKey === 'borrowAmount'}
|
roundUp={valueKey === 'borrowedAmount'}
|
||||||
showBorrowRates={showBorrowRates}
|
showBorrowRates={showBorrowRates}
|
||||||
showDepositRates={showDepositRates}
|
showDepositRates={showDepositRates}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
} from '@heroicons/react/20/solid'
|
} from '@heroicons/react/20/solid'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import Image from 'next/legacy/image'
|
import Image from 'next/legacy/image'
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { useViewport } from '../../hooks/useViewport'
|
import { useViewport } from '../../hooks/useViewport'
|
||||||
import { formatNumericValue } from '../../utils/numbers'
|
import { formatNumericValue } from '../../utils/numbers'
|
||||||
import { breakpoints } from '../../utils/theme'
|
import { breakpoints } from '../../utils/theme'
|
||||||
|
@ -14,10 +14,9 @@ import useJupiterMints from 'hooks/useJupiterMints'
|
||||||
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
||||||
import useMangoGroup from 'hooks/useMangoGroup'
|
import useMangoGroup from 'hooks/useMangoGroup'
|
||||||
import mangoStore from '@store/mangoStore'
|
import mangoStore from '@store/mangoStore'
|
||||||
import { getMaxWithdrawForBank } from '@components/swap/useTokenMax'
|
|
||||||
import useMangoAccount from 'hooks/useMangoAccount'
|
|
||||||
import BorrowRepayModal from '@components/modals/BorrowRepayModal'
|
import BorrowRepayModal from '@components/modals/BorrowRepayModal'
|
||||||
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
const AssetsBorrowsTable = () => {
|
const AssetsBorrowsTable = () => {
|
||||||
const { t } = useTranslation(['common', 'token'])
|
const { t } = useTranslation(['common', 'token'])
|
||||||
|
@ -26,10 +25,10 @@ const AssetsBorrowsTable = () => {
|
||||||
const actions = mangoStore.getState().actions
|
const actions = mangoStore.getState().actions
|
||||||
const initialStatsLoad = mangoStore((s) => s.tokenStats.initialLoad)
|
const initialStatsLoad = mangoStore((s) => s.tokenStats.initialLoad)
|
||||||
const { group } = useMangoGroup()
|
const { group } = useMangoGroup()
|
||||||
const { mangoAccount } = useMangoAccount()
|
|
||||||
const { mangoTokens } = useJupiterMints()
|
const { mangoTokens } = useJupiterMints()
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
const showTableView = width ? width > breakpoints.md : false
|
const showTableView = width ? width > breakpoints.md : false
|
||||||
|
const banks = useBanksWithBalances('maxBorrow')
|
||||||
|
|
||||||
const handleShowBorrowModal = useCallback((token: string) => {
|
const handleShowBorrowModal = useCallback((token: string) => {
|
||||||
setSelectedToken(token)
|
setSelectedToken(token)
|
||||||
|
@ -42,17 +41,6 @@ const AssetsBorrowsTable = () => {
|
||||||
}
|
}
|
||||||
}, [group])
|
}, [group])
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
|
||||||
if (group) {
|
|
||||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
}))
|
|
||||||
return rawBanks.sort((a, b) => a.key.localeCompare(b.key))
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}, [group])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showTableView ? (
|
{showTableView ? (
|
||||||
|
@ -75,8 +63,8 @@ const AssetsBorrowsTable = () => {
|
||||||
</TrHead>
|
</TrHead>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{banks.map(({ key, value }) => {
|
{banks.map((b) => {
|
||||||
const bank = value[0]
|
const bank = b.bank
|
||||||
|
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens?.length) {
|
if (mangoTokens?.length) {
|
||||||
|
@ -86,18 +74,8 @@ const AssetsBorrowsTable = () => {
|
||||||
}
|
}
|
||||||
const borrows = bank.uiBorrows()
|
const borrows = bank.uiBorrows()
|
||||||
|
|
||||||
const available =
|
|
||||||
group && mangoAccount
|
|
||||||
? getMaxWithdrawForBank(
|
|
||||||
group,
|
|
||||||
bank,
|
|
||||||
mangoAccount,
|
|
||||||
true
|
|
||||||
).toNumber()
|
|
||||||
: 0
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TrBody key={key}>
|
<TrBody key={bank.name}>
|
||||||
<Td>
|
<Td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||||
|
@ -123,7 +101,7 @@ const AssetsBorrowsTable = () => {
|
||||||
<Td>
|
<Td>
|
||||||
<div className="flex flex-col text-right">
|
<div className="flex flex-col text-right">
|
||||||
<BankAmountWithValue
|
<BankAmountWithValue
|
||||||
amount={available}
|
amount={b.maxBorrow}
|
||||||
bank={bank}
|
bank={bank}
|
||||||
stacked
|
stacked
|
||||||
/>
|
/>
|
||||||
|
@ -138,7 +116,7 @@ const AssetsBorrowsTable = () => {
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Tooltip content={`${t('borrow')} ${bank.name}`}>
|
<Tooltip content={`${t('borrow')} ${bank.name}`}>
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={available === 0}
|
disabled={b.maxBorrow === 0}
|
||||||
onClick={() => handleShowBorrowModal(bank.name)}
|
onClick={() => handleShowBorrowModal(bank.name)}
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
|
@ -154,8 +132,8 @@ const AssetsBorrowsTable = () => {
|
||||||
</Table>
|
</Table>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
{banks.map(({ key, value }) => {
|
{banks.map((b) => {
|
||||||
const bank = value[0]
|
const bank = b.bank
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens?.length) {
|
if (mangoTokens?.length) {
|
||||||
logoURI = mangoTokens.find(
|
logoURI = mangoTokens.find(
|
||||||
|
@ -163,18 +141,11 @@ const AssetsBorrowsTable = () => {
|
||||||
)?.logoURI
|
)?.logoURI
|
||||||
}
|
}
|
||||||
|
|
||||||
const available =
|
|
||||||
group && mangoAccount
|
|
||||||
? getMaxWithdrawForBank(
|
|
||||||
group,
|
|
||||||
bank,
|
|
||||||
mangoAccount,
|
|
||||||
true
|
|
||||||
).toNumber()
|
|
||||||
: 0
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={key} className="border-b border-th-bkg-3 px-6 py-4">
|
<div
|
||||||
|
key={bank.name}
|
||||||
|
className="border-b border-th-bkg-3 px-6 py-4"
|
||||||
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||||
|
@ -191,7 +162,7 @@ const AssetsBorrowsTable = () => {
|
||||||
<p className="mb-0.5 text-right text-xs">
|
<p className="mb-0.5 text-right text-xs">
|
||||||
{t('available')}
|
{t('available')}
|
||||||
</p>
|
</p>
|
||||||
<BankAmountWithValue amount={available} bank={bank} />
|
<BankAmountWithValue amount={b.maxBorrow} bank={bank} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="mb-0.5 text-right text-xs">{t('rate')}</p>
|
<p className="mb-0.5 text-right text-xs">{t('rate')}</p>
|
||||||
|
@ -200,7 +171,7 @@ const AssetsBorrowsTable = () => {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={available === 0}
|
disabled={b.maxBorrow === 0}
|
||||||
onClick={() => handleShowBorrowModal(bank.name)}
|
onClick={() => handleShowBorrowModal(bank.name)}
|
||||||
size="medium"
|
size="medium"
|
||||||
>
|
>
|
||||||
|
|
|
@ -21,6 +21,7 @@ import TabButtons from '@components/shared/TabButtons'
|
||||||
import { useViewport } from 'hooks/useViewport'
|
import { useViewport } from 'hooks/useViewport'
|
||||||
import { breakpoints } from 'utils/theme'
|
import { breakpoints } from 'utils/theme'
|
||||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
const BorrowPage = () => {
|
const BorrowPage = () => {
|
||||||
const { t } = useTranslation(['common', 'borrow'])
|
const { t } = useTranslation(['common', 'borrow'])
|
||||||
|
@ -33,6 +34,7 @@ const BorrowPage = () => {
|
||||||
const { connected } = useWallet()
|
const { connected } = useWallet()
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
const fullWidthTabs = width ? width < breakpoints.sm : false
|
const fullWidthTabs = width ? width < breakpoints.sm : false
|
||||||
|
const banks = useBanksWithBalances('borrowedAmount')
|
||||||
|
|
||||||
const handleBorrowModal = () => {
|
const handleBorrowModal = () => {
|
||||||
if (!connected || mangoAccount) {
|
if (!connected || mangoAccount) {
|
||||||
|
@ -57,35 +59,20 @@ const BorrowPage = () => {
|
||||||
}
|
}
|
||||||
}, [actions, mangoAccountAddress])
|
}, [actions, mangoAccountAddress])
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
const filteredBanks = useMemo(() => {
|
||||||
if (group && mangoAccount) {
|
if (banks.length) {
|
||||||
const borrowBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
return banks.filter((b) => b.borrowedAmount > 0)
|
||||||
key,
|
|
||||||
value,
|
|
||||||
})).filter((b) => {
|
|
||||||
const bank = b.value[0]
|
|
||||||
return mangoAccount.getTokenBalanceUi(bank) < 0
|
|
||||||
})
|
|
||||||
return borrowBanks
|
|
||||||
.map((b) => {
|
|
||||||
return {
|
|
||||||
balance: mangoAccount.getTokenBalanceUi(b.value[0]),
|
|
||||||
bank: b.value[0],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
const aBalance = Math.abs(a.balance * a.bank.uiPrice)
|
|
||||||
const bBalance = Math.abs(b.balance * b.bank.uiPrice)
|
|
||||||
return aBalance > bBalance ? -1 : 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}, [group, mangoAccount])
|
}, [banks])
|
||||||
|
|
||||||
const borrowValue = useMemo(() => {
|
const borrowValue = useMemo(() => {
|
||||||
if (!banks.length) return 0
|
if (!filteredBanks.length) return 0
|
||||||
return banks.reduce((a, c) => a + Math.abs(c.balance) * c.bank.uiPrice, 0)
|
return filteredBanks.reduce(
|
||||||
}, [banks])
|
(a, c) => a + Math.abs(c.borrowedAmount) * c.bank.uiPrice,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
}, [filteredBanks])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mangoAccountAddress && !borrowValue) {
|
if (mangoAccountAddress && !borrowValue) {
|
||||||
|
@ -205,7 +192,7 @@ const BorrowPage = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{activeTab === 'borrow:your-borrows' ? (
|
{activeTab === 'borrow:your-borrows' ? (
|
||||||
<YourBorrowsTable banks={banks} />
|
<YourBorrowsTable banks={filteredBanks} />
|
||||||
) : (
|
) : (
|
||||||
<AssetsBorrowsTable />
|
<AssetsBorrowsTable />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -23,11 +23,7 @@ import { useCallback, useState } from 'react'
|
||||||
import BorrowRepayModal from '@components/modals/BorrowRepayModal'
|
import BorrowRepayModal from '@components/modals/BorrowRepayModal'
|
||||||
import Tooltip from '@components/shared/Tooltip'
|
import Tooltip from '@components/shared/Tooltip'
|
||||||
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||||
|
import { BankWithBalance } from 'hooks/useBanksWithBalances'
|
||||||
interface BankWithBalance {
|
|
||||||
balance: number
|
|
||||||
bank: Bank
|
|
||||||
}
|
|
||||||
|
|
||||||
const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
||||||
const { t } = useTranslation(['common', 'trade'])
|
const { t } = useTranslation(['common', 'trade'])
|
||||||
|
@ -82,14 +78,9 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
||||||
)?.logoURI
|
)?.logoURI
|
||||||
}
|
}
|
||||||
|
|
||||||
const available =
|
const available = b.maxBorrow
|
||||||
group && mangoAccount
|
|
||||||
? getMaxWithdrawForBank(group, bank, mangoAccount, true)
|
|
||||||
: new Decimal(0)
|
|
||||||
|
|
||||||
const borrowedAmount = mangoAccount
|
const borrowedAmount = b.borrowedAmount
|
||||||
? Math.abs(mangoAccount.getTokenBalanceUi(bank))
|
|
||||||
: 0
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TrBody key={bank.name} className="text-sm">
|
<TrBody key={bank.name} className="text-sm">
|
||||||
|
@ -141,7 +132,7 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip content={`${t('borrow')} ${bank.name}`}>
|
<Tooltip content={`${t('borrow')} ${bank.name}`}>
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={available.eq(0)}
|
disabled={available === 0}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleShowActionModals(bank.name, 'borrow')
|
handleShowActionModals(bank.name, 'borrow')
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import ButtonGroup from '../forms/ButtonGroup'
|
||||||
import Input from '../forms/Input'
|
import Input from '../forms/Input'
|
||||||
import Label from '../forms/Label'
|
import Label from '../forms/Label'
|
||||||
import WalletIcon from '../icons/WalletIcon'
|
import WalletIcon from '../icons/WalletIcon'
|
||||||
import { walletBalanceForToken } from '../DepositForm'
|
|
||||||
import ParticlesBackground from '../ParticlesBackground'
|
import ParticlesBackground from '../ParticlesBackground'
|
||||||
// import EditNftProfilePic from '../profile/EditNftProfilePic'
|
// import EditNftProfilePic from '../profile/EditNftProfilePic'
|
||||||
// import EditProfileForm from '../profile/EditProfileForm'
|
// import EditProfileForm from '../profile/EditProfileForm'
|
||||||
|
@ -43,7 +42,8 @@ import { useEnhancedWallet } from '../wallet/EnhancedWalletProvider'
|
||||||
import Modal from '../shared/Modal'
|
import Modal from '../shared/Modal'
|
||||||
import NumberFormat, { NumberFormatValues } from 'react-number-format'
|
import NumberFormat, { NumberFormatValues } from 'react-number-format'
|
||||||
import { withValueLimit } from '@components/swap/SwapForm'
|
import { withValueLimit } from '@components/swap/SwapForm'
|
||||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||||
|
|
||||||
const UserSetupModal = ({
|
const UserSetupModal = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
|
@ -65,9 +65,9 @@ const UserSetupModal = ({
|
||||||
const [submitDeposit, setSubmitDeposit] = useState(false)
|
const [submitDeposit, setSubmitDeposit] = useState(false)
|
||||||
const [sizePercentage, setSizePercentage] = useState('')
|
const [sizePercentage, setSizePercentage] = useState('')
|
||||||
// const [showEditProfilePic, setShowEditProfilePic] = useState(false)
|
// const [showEditProfilePic, setShowEditProfilePic] = useState(false)
|
||||||
const walletTokens = mangoStore((s) => s.wallet.tokens)
|
|
||||||
const { handleConnect } = useEnhancedWallet()
|
const { handleConnect } = useEnhancedWallet()
|
||||||
const { maxSolDeposit } = useSolBalance()
|
const { maxSolDeposit } = useSolBalance()
|
||||||
|
const banks = useBanksWithBalances('walletBalance')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
|
@ -157,24 +157,8 @@ const UserSetupModal = ({
|
||||||
}
|
}
|
||||||
}, [mangoAccount, showSetupStep, onClose])
|
}, [mangoAccount, showSetupStep, onClose])
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
|
||||||
const banks = group?.banksMapByName
|
|
||||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
|
||||||
const walletBalance = walletBalanceForToken(walletTokens, key)
|
|
||||||
return {
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
tokenDecimals: walletBalance.maxDecimals,
|
|
||||||
walletBalance: walletBalance.maxAmount,
|
|
||||||
walletBalanceValue: walletBalance.maxAmount * value?.[0].uiPrice,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: []
|
|
||||||
return banks
|
|
||||||
}, [group?.banksMapByName, walletTokens])
|
|
||||||
|
|
||||||
const depositBank = useMemo(() => {
|
const depositBank = useMemo(() => {
|
||||||
return banks.find((b) => b.key === depositToken)?.value[0]
|
return banks.find((b) => b.bank.name === depositToken)?.bank
|
||||||
}, [depositToken, banks])
|
}, [depositToken, banks])
|
||||||
|
|
||||||
const exceedsAlphaMax = useMemo(() => {
|
const exceedsAlphaMax = useMemo(() => {
|
||||||
|
@ -195,9 +179,9 @@ const UserSetupModal = ({
|
||||||
}, [depositAmount, depositBank, group])
|
}, [depositAmount, depositBank, group])
|
||||||
|
|
||||||
const tokenMax = useMemo(() => {
|
const tokenMax = useMemo(() => {
|
||||||
const bank = banks.find((bank) => bank.key === depositToken)
|
const bank = banks.find((b) => b.bank.name === depositToken)
|
||||||
if (bank) {
|
if (bank) {
|
||||||
return { amount: bank.walletBalance, decimals: bank.tokenDecimals }
|
return { amount: bank.walletBalance, decimals: bank.bank.mintDecimals }
|
||||||
}
|
}
|
||||||
return { amount: 0, decimals: 0 }
|
return { amount: 0, decimals: 0 }
|
||||||
}, [banks, depositToken])
|
}, [banks, depositToken])
|
||||||
|
@ -481,7 +465,11 @@ const UserSetupModal = ({
|
||||||
<div className="flex justify-between px-2 py-4">
|
<div className="flex justify-between px-2 py-4">
|
||||||
<p>{t('deposit-amount')}</p>
|
<p>{t('deposit-amount')}</p>
|
||||||
<p className="font-mono text-th-fgd-2">
|
<p className="font-mono text-th-fgd-2">
|
||||||
{depositAmount ? (
|
<BankAmountWithValue
|
||||||
|
amount={depositAmount}
|
||||||
|
bank={depositBank}
|
||||||
|
/>
|
||||||
|
{/* {depositAmount ? (
|
||||||
<>
|
<>
|
||||||
<FormatNumericValue
|
<FormatNumericValue
|
||||||
value={depositAmount}
|
value={depositAmount}
|
||||||
|
@ -506,7 +494,7 @@ const UserSetupModal = ({
|
||||||
($0.00)
|
($0.00)
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)} */}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -566,7 +554,6 @@ const UserSetupModal = ({
|
||||||
banks={banks}
|
banks={banks}
|
||||||
onSelect={setDepositToken}
|
onSelect={setDepositToken}
|
||||||
showDepositRates
|
showDepositRates
|
||||||
sortByKey="walletBalanceValue"
|
|
||||||
valueKey="walletBalance"
|
valueKey="walletBalance"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Bank, Serum3Market } from '@blockworks-foundation/mango-v4'
|
import { Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||||
import useJupiterMints from 'hooks/useJupiterMints'
|
import useJupiterMints from 'hooks/useJupiterMints'
|
||||||
import { NoSymbolIcon, QuestionMarkCircleIcon } from '@heroicons/react/20/solid'
|
import { NoSymbolIcon, QuestionMarkCircleIcon } from '@heroicons/react/20/solid'
|
||||||
import mangoStore from '@store/mangoStore'
|
import mangoStore from '@store/mangoStore'
|
||||||
|
@ -18,53 +18,40 @@ import { calculateLimitPriceForMarketOrder } from 'utils/tradeForm'
|
||||||
import { LinkButton } from './Button'
|
import { LinkButton } from './Button'
|
||||||
import { Table, Td, Th, TrBody, TrHead } from './TableElements'
|
import { Table, Td, Th, TrBody, TrHead } from './TableElements'
|
||||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||||
import useMangoGroup from 'hooks/useMangoGroup'
|
|
||||||
import ConnectEmptyState from './ConnectEmptyState'
|
import ConnectEmptyState from './ConnectEmptyState'
|
||||||
import { useWallet } from '@solana/wallet-adapter-react'
|
import { useWallet } from '@solana/wallet-adapter-react'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
import FormatNumericValue from './FormatNumericValue'
|
import FormatNumericValue from './FormatNumericValue'
|
||||||
import BankAmountWithValue from './BankAmountWithValue'
|
import BankAmountWithValue from './BankAmountWithValue'
|
||||||
|
import useBanksWithBalances, {
|
||||||
|
BankWithBalance,
|
||||||
|
} from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
const BalancesTable = () => {
|
const BalancesTable = () => {
|
||||||
const { t } = useTranslation(['common', 'trade'])
|
const { t } = useTranslation(['common', 'trade'])
|
||||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||||
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
||||||
const { group } = useMangoGroup()
|
|
||||||
const { mangoTokens } = useJupiterMints()
|
const { mangoTokens } = useJupiterMints()
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
const { connected } = useWallet()
|
const { connected } = useWallet()
|
||||||
const showTableView = width ? width > breakpoints.md : false
|
const showTableView = width ? width > breakpoints.md : false
|
||||||
|
const banks = useBanksWithBalances('balance')
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
const filteredBanks = useMemo(() => {
|
||||||
if (!group || !mangoAccount) return []
|
if (banks.length) {
|
||||||
|
return banks.filter((b) => {
|
||||||
|
return (
|
||||||
|
Math.abs(floorToDecimal(b.balance, b.bank.mintDecimals).toNumber()) >
|
||||||
|
0 ||
|
||||||
|
spotBalances[b.bank.mint.toString()]?.unsettled > 0 ||
|
||||||
|
spotBalances[b.bank.mint.toString()]?.inOrders > 0
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}, [banks])
|
||||||
|
|
||||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
return filteredBanks.length ? (
|
||||||
key,
|
|
||||||
value,
|
|
||||||
balance: mangoAccount.getTokenBalanceUi(value[0]),
|
|
||||||
}))
|
|
||||||
const sortedBanks = mangoAccount
|
|
||||||
? rawBanks
|
|
||||||
.sort(
|
|
||||||
(a, b) =>
|
|
||||||
Math.abs(b.balance * b.value[0].uiPrice) -
|
|
||||||
Math.abs(a.balance * a.value[0].uiPrice)
|
|
||||||
)
|
|
||||||
.filter((c) => {
|
|
||||||
return (
|
|
||||||
Math.abs(
|
|
||||||
floorToDecimal(c.balance, c.value[0].mintDecimals).toNumber()
|
|
||||||
) > 0 ||
|
|
||||||
spotBalances[c.value[0].mint.toString()]?.unsettled > 0 ||
|
|
||||||
spotBalances[c.value[0].mint.toString()]?.inOrders > 0
|
|
||||||
)
|
|
||||||
})
|
|
||||||
: rawBanks
|
|
||||||
|
|
||||||
return sortedBanks
|
|
||||||
}, [group, mangoAccount, spotBalances])
|
|
||||||
|
|
||||||
return banks?.length ? (
|
|
||||||
showTableView ? (
|
showTableView ? (
|
||||||
<Table>
|
<Table>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -78,8 +65,8 @@ const BalancesTable = () => {
|
||||||
</TrHead>
|
</TrHead>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{banks.map(({ key, value }) => {
|
{filteredBanks.map((b) => {
|
||||||
const bank = value[0]
|
const bank = b.bank
|
||||||
|
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens.length) {
|
if (mangoTokens.length) {
|
||||||
|
@ -92,7 +79,7 @@ const BalancesTable = () => {
|
||||||
const unsettled = spotBalances[bank.mint.toString()]?.unsettled || 0
|
const unsettled = spotBalances[bank.mint.toString()]?.unsettled || 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TrBody key={key} className="text-sm">
|
<TrBody key={bank.name} className="text-sm">
|
||||||
<Td>
|
<Td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||||
|
@ -106,14 +93,10 @@ const BalancesTable = () => {
|
||||||
</div>
|
</div>
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="text-right">
|
<Td className="text-right">
|
||||||
<Balance bank={bank} />
|
<Balance bank={b} />
|
||||||
<p className="text-sm text-th-fgd-4">
|
<p className="text-sm text-th-fgd-4">
|
||||||
<FormatNumericValue
|
<FormatNumericValue
|
||||||
value={
|
value={mangoAccount ? b.balance * bank.uiPrice : 0}
|
||||||
mangoAccount
|
|
||||||
? mangoAccount.getTokenBalanceUi(bank) * bank.uiPrice
|
|
||||||
: 0
|
|
||||||
}
|
|
||||||
isUsd
|
isUsd
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
@ -131,8 +114,8 @@ const BalancesTable = () => {
|
||||||
</Table>
|
</Table>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{banks.map(({ key, value }) => {
|
{filteredBanks.map((b) => {
|
||||||
const bank = value[0]
|
const bank = b.bank
|
||||||
|
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens.length) {
|
if (mangoTokens.length) {
|
||||||
|
@ -147,7 +130,7 @@ const BalancesTable = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex items-center justify-between border-b border-th-bkg-3 p-4"
|
className="flex items-center justify-between border-b border-th-bkg-3 p-4"
|
||||||
key={key}
|
key={bank.name}
|
||||||
>
|
>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||||
|
@ -161,14 +144,10 @@ const BalancesTable = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<div className="mb-0.5 flex justify-end space-x-1.5">
|
<div className="mb-0.5 flex justify-end space-x-1.5">
|
||||||
<Balance bank={bank} />
|
<Balance bank={b} />
|
||||||
<span className="text-sm text-th-fgd-4">
|
<span className="text-sm text-th-fgd-4">
|
||||||
<FormatNumericValue
|
<FormatNumericValue
|
||||||
value={
|
value={mangoAccount ? b.balance * bank.uiPrice : 0}
|
||||||
mangoAccount
|
|
||||||
? mangoAccount.getTokenBalanceUi(bank) * bank.uiPrice
|
|
||||||
: 0
|
|
||||||
}
|
|
||||||
isUsd
|
isUsd
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
@ -213,11 +192,12 @@ const BalancesTable = () => {
|
||||||
|
|
||||||
export default BalancesTable
|
export default BalancesTable
|
||||||
|
|
||||||
const Balance = ({ bank }: { bank: Bank }) => {
|
const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
||||||
const { mangoAccount } = useMangoAccount()
|
|
||||||
const { selectedMarket } = useSelectedMarket()
|
const { selectedMarket } = useSelectedMarket()
|
||||||
const { asPath } = useRouter()
|
const { asPath } = useRouter()
|
||||||
|
|
||||||
|
const tokenBank = bank.bank
|
||||||
|
|
||||||
const handleTradeFormBalanceClick = useCallback(
|
const handleTradeFormBalanceClick = useCallback(
|
||||||
(balance: number, type: 'base' | 'quote') => {
|
(balance: number, type: 'base' | 'quote') => {
|
||||||
const set = mangoStore.getState().set
|
const set = mangoStore.getState().set
|
||||||
|
@ -279,14 +259,14 @@ const Balance = ({ bank }: { bank: Bank }) => {
|
||||||
const set = mangoStore.getState().set
|
const set = mangoStore.getState().set
|
||||||
if (balance >= 0) {
|
if (balance >= 0) {
|
||||||
set((s) => {
|
set((s) => {
|
||||||
s.swap.inputBank = bank
|
s.swap.inputBank = tokenBank
|
||||||
s.swap.amountIn = balance.toString()
|
s.swap.amountIn = balance.toString()
|
||||||
s.swap.amountOut = ''
|
s.swap.amountOut = ''
|
||||||
s.swap.swapMode = 'ExactIn'
|
s.swap.swapMode = 'ExactIn'
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
set((s) => {
|
set((s) => {
|
||||||
s.swap.outputBank = bank
|
s.swap.outputBank = tokenBank
|
||||||
s.swap.amountIn = ''
|
s.swap.amountIn = ''
|
||||||
s.swap.amountOut = Math.abs(balance).toString()
|
s.swap.amountOut = Math.abs(balance).toString()
|
||||||
s.swap.swapMode = 'ExactOut'
|
s.swap.swapMode = 'ExactOut'
|
||||||
|
@ -296,21 +276,19 @@ const Balance = ({ bank }: { bank: Bank }) => {
|
||||||
[bank]
|
[bank]
|
||||||
)
|
)
|
||||||
|
|
||||||
const balance = useMemo(() => {
|
const balance = bank.balance
|
||||||
return mangoAccount ? mangoAccount.getTokenBalanceUi(bank) : 0
|
|
||||||
}, [bank, mangoAccount])
|
|
||||||
|
|
||||||
const isBaseOrQuote = useMemo(() => {
|
const isBaseOrQuote = useMemo(() => {
|
||||||
if (selectedMarket instanceof Serum3Market) {
|
if (selectedMarket instanceof Serum3Market) {
|
||||||
if (bank.tokenIndex === selectedMarket.baseTokenIndex) {
|
if (tokenBank.tokenIndex === selectedMarket.baseTokenIndex) {
|
||||||
return 'base'
|
return 'base'
|
||||||
} else if (bank.tokenIndex === selectedMarket.quoteTokenIndex) {
|
} else if (tokenBank.tokenIndex === selectedMarket.quoteTokenIndex) {
|
||||||
return 'quote'
|
return 'quote'
|
||||||
} else return ''
|
} else return ''
|
||||||
}
|
}
|
||||||
}, [bank, selectedMarket])
|
}, [tokenBank, selectedMarket])
|
||||||
|
|
||||||
console.log(bank.name, ' balance', new Decimal(balance).toFixed())
|
console.log(tokenBank.name, ' balance', new Decimal(balance).toFixed())
|
||||||
if (!balance) return <p className="flex justify-end">0</p>
|
if (!balance) return <p className="flex justify-end">0</p>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -322,21 +300,27 @@ const Balance = ({ bank }: { bank: Bank }) => {
|
||||||
handleTradeFormBalanceClick(Math.abs(balance), isBaseOrQuote)
|
handleTradeFormBalanceClick(Math.abs(balance), isBaseOrQuote)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<FormatNumericValue value={balance} decimals={bank.mintDecimals} />
|
<FormatNumericValue
|
||||||
|
value={balance}
|
||||||
|
decimals={tokenBank.mintDecimals}
|
||||||
|
/>
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
) : asPath.includes('/swap') ? (
|
) : asPath.includes('/swap') ? (
|
||||||
<LinkButton
|
<LinkButton
|
||||||
className="font-normal underline-offset-4"
|
className="font-normal underline-offset-4"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleSwapFormBalanceClick(
|
handleSwapFormBalanceClick(
|
||||||
Number(formatNumericValue(balance, bank.mintDecimals))
|
Number(formatNumericValue(balance, tokenBank.mintDecimals))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<FormatNumericValue value={balance} decimals={bank.mintDecimals} />
|
<FormatNumericValue
|
||||||
|
value={balance}
|
||||||
|
decimals={tokenBank.mintDecimals}
|
||||||
|
/>
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
) : (
|
) : (
|
||||||
<FormatNumericValue value={balance} decimals={bank.mintDecimals} />
|
<FormatNumericValue value={balance} decimals={tokenBank.mintDecimals} />
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
} from '@heroicons/react/20/solid'
|
} from '@heroicons/react/20/solid'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import Image from 'next/legacy/image'
|
import Image from 'next/legacy/image'
|
||||||
import { Fragment, useEffect, useMemo, useState } from 'react'
|
import { Fragment, useEffect, useState } from 'react'
|
||||||
import { useViewport } from '../../hooks/useViewport'
|
import { useViewport } from '../../hooks/useViewport'
|
||||||
import { breakpoints } from '../../utils/theme'
|
import { breakpoints } from '../../utils/theme'
|
||||||
import { IconButton, LinkButton } from '../shared/Button'
|
import { IconButton, LinkButton } from '../shared/Button'
|
||||||
|
@ -20,6 +20,7 @@ import useMangoGroup from 'hooks/useMangoGroup'
|
||||||
import mangoStore from '@store/mangoStore'
|
import mangoStore from '@store/mangoStore'
|
||||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||||
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
|
|
||||||
const TokenStats = () => {
|
const TokenStats = () => {
|
||||||
const { t } = useTranslation(['common', 'token'])
|
const { t } = useTranslation(['common', 'token'])
|
||||||
|
@ -31,6 +32,7 @@ const TokenStats = () => {
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
const showTableView = width ? width > breakpoints.md : false
|
const showTableView = width ? width > breakpoints.md : false
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const banks = useBanksWithBalances()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (group && !initialStatsLoad) {
|
if (group && !initialStatsLoad) {
|
||||||
|
@ -38,17 +40,6 @@ const TokenStats = () => {
|
||||||
}
|
}
|
||||||
}, [group])
|
}, [group])
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
|
||||||
if (group) {
|
|
||||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
}))
|
|
||||||
return rawBanks.sort((a, b) => a.key.localeCompare(b.key))
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}, [group])
|
|
||||||
|
|
||||||
const handleShowTokenDetails = (name: string) => {
|
const handleShowTokenDetails = (name: string) => {
|
||||||
showTokenDetails ? setShowTokenDetails('') : setShowTokenDetails(name)
|
showTokenDetails ? setShowTokenDetails('') : setShowTokenDetails(name)
|
||||||
}
|
}
|
||||||
|
@ -100,8 +91,8 @@ const TokenStats = () => {
|
||||||
</TrHead>
|
</TrHead>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{banks.map(({ key, value }) => {
|
{banks.map((b) => {
|
||||||
const bank: Bank = value[0]
|
const bank: Bank = b.bank
|
||||||
|
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens?.length) {
|
if (mangoTokens?.length) {
|
||||||
|
@ -115,7 +106,7 @@ const TokenStats = () => {
|
||||||
deposits - deposits * bank.minVaultToDepositsRatio - borrows
|
deposits - deposits * bank.minVaultToDepositsRatio - borrows
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TrBody key={key}>
|
<TrBody key={bank.name}>
|
||||||
<Td>
|
<Td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||||
|
@ -213,8 +204,8 @@ const TokenStats = () => {
|
||||||
</Table>
|
</Table>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
{banks.map(({ key, value }) => {
|
{banks.map((b) => {
|
||||||
const bank = value[0]
|
const bank = b.bank
|
||||||
let logoURI
|
let logoURI
|
||||||
if (mangoTokens?.length) {
|
if (mangoTokens?.length) {
|
||||||
logoURI = mangoTokens.find(
|
logoURI = mangoTokens.find(
|
||||||
|
@ -227,7 +218,10 @@ const TokenStats = () => {
|
||||||
const available =
|
const available =
|
||||||
deposits - deposits * bank.minVaultToDepositsRatio - borrows
|
deposits - deposits * bank.minVaultToDepositsRatio - borrows
|
||||||
return (
|
return (
|
||||||
<div key={key} className="border-b border-th-bkg-3 px-6 py-4">
|
<div
|
||||||
|
key={bank.name}
|
||||||
|
className="border-b border-th-bkg-3 px-6 py-4"
|
||||||
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { TokenStatsItem } from '@store/mangoStore'
|
import { TokenStatsItem } from '@store/mangoStore'
|
||||||
import useMangoGroup from 'hooks/useMangoGroup'
|
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { formatYAxis } from 'utils/formatting'
|
import { formatYAxis } from 'utils/formatting'
|
||||||
|
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||||
const DetailedAreaChart = dynamic(
|
const DetailedAreaChart = dynamic(
|
||||||
() => import('@components/shared/DetailedAreaChart'),
|
() => import('@components/shared/DetailedAreaChart'),
|
||||||
{ ssr: false }
|
{ ssr: false }
|
||||||
|
@ -26,7 +26,7 @@ const TotalDepositBorrowCharts = ({
|
||||||
const { t } = useTranslation(['common', 'token', 'trade'])
|
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||||
const [borrowDaysToShow, setBorrowDaysToShow] = useState('30')
|
const [borrowDaysToShow, setBorrowDaysToShow] = useState('30')
|
||||||
const [depositDaysToShow, setDepositDaysToShow] = useState('30')
|
const [depositDaysToShow, setDepositDaysToShow] = useState('30')
|
||||||
const { group } = useMangoGroup()
|
const banks = useBanksWithBalances()
|
||||||
|
|
||||||
const totalDepositBorrowValues = useMemo(() => {
|
const totalDepositBorrowValues = useMemo(() => {
|
||||||
if (!tokenStats) return []
|
if (!tokenStats) return []
|
||||||
|
@ -82,28 +82,11 @@ const TotalDepositBorrowCharts = ({
|
||||||
return totalDepositBorrowValues
|
return totalDepositBorrowValues
|
||||||
}, [totalDepositBorrowValues, depositDaysToShow])
|
}, [totalDepositBorrowValues, depositDaysToShow])
|
||||||
|
|
||||||
const banks = useMemo(() => {
|
|
||||||
if (group) {
|
|
||||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
}))
|
|
||||||
return rawBanks
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}, [group])
|
|
||||||
|
|
||||||
const [currentTotalDepositValue, currentTotalBorrowValue] = useMemo(() => {
|
const [currentTotalDepositValue, currentTotalBorrowValue] = useMemo(() => {
|
||||||
if (banks.length) {
|
if (banks.length) {
|
||||||
return [
|
return [
|
||||||
banks.reduce(
|
banks.reduce((a, c) => a + c.bank.uiPrice * c.bank.uiDeposits(), 0),
|
||||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiDeposits(),
|
banks.reduce((a, c) => a + c.bank.uiPrice * c.bank.uiBorrows(), 0),
|
||||||
0
|
|
||||||
),
|
|
||||||
banks.reduce(
|
|
||||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiBorrows(),
|
|
||||||
0
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
return [0, 0]
|
return [0, 0]
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import { Bank } from '@blockworks-foundation/mango-v4'
|
||||||
|
import { walletBalanceForToken } from '@components/DepositForm'
|
||||||
|
import { getMaxWithdrawForBank } from '@components/swap/useTokenMax'
|
||||||
|
import mangoStore from '@store/mangoStore'
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
import useMangoAccount from './useMangoAccount'
|
||||||
|
import useMangoGroup from './useMangoGroup'
|
||||||
|
|
||||||
|
export interface BankWithBalance {
|
||||||
|
balance: number
|
||||||
|
bank: Bank
|
||||||
|
borrowedAmount: number
|
||||||
|
maxBorrow: number
|
||||||
|
maxWithdraw: number
|
||||||
|
walletBalance: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useBanksWithBalances(
|
||||||
|
sortByKey?:
|
||||||
|
| 'balance'
|
||||||
|
| 'borrowedAmount'
|
||||||
|
| 'maxBorrow'
|
||||||
|
| 'maxWithdraw'
|
||||||
|
| 'walletBalance'
|
||||||
|
) {
|
||||||
|
const { group } = useMangoGroup()
|
||||||
|
const { mangoAccount } = useMangoAccount()
|
||||||
|
const walletTokens = mangoStore((s) => s.wallet.tokens)
|
||||||
|
|
||||||
|
const banks: BankWithBalance[] = useMemo(() => {
|
||||||
|
if (group) {
|
||||||
|
const banksWithBalances = Array.from(
|
||||||
|
group?.banksMapByName,
|
||||||
|
([key, value]) => ({
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
})
|
||||||
|
).map((b) => {
|
||||||
|
const bank = b.value[0]
|
||||||
|
const balance = mangoAccount ? mangoAccount.getTokenBalanceUi(bank) : 0
|
||||||
|
const maxBorrow = mangoAccount
|
||||||
|
? getMaxWithdrawForBank(group, bank, mangoAccount, true).toNumber()
|
||||||
|
: 0
|
||||||
|
const maxWithdraw = mangoAccount
|
||||||
|
? getMaxWithdrawForBank(group, bank, mangoAccount).toNumber()
|
||||||
|
: 0
|
||||||
|
const borrowedAmount = mangoAccount
|
||||||
|
? mangoAccount.getTokenBorrowsUi(bank)
|
||||||
|
: 0
|
||||||
|
const walletBalance =
|
||||||
|
walletBalanceForToken(walletTokens, bank.name)?.maxAmount || 0
|
||||||
|
return {
|
||||||
|
bank,
|
||||||
|
balance,
|
||||||
|
borrowedAmount,
|
||||||
|
maxBorrow,
|
||||||
|
maxWithdraw,
|
||||||
|
walletBalance,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const sortedBanks = banksWithBalances.sort((a, b) => {
|
||||||
|
if (sortByKey) {
|
||||||
|
const aPrice = a.bank.uiPrice
|
||||||
|
const bPrice = b.bank.uiPrice
|
||||||
|
const aValue = Math.abs(a[sortByKey]) * aPrice
|
||||||
|
const bValue = Math.abs(b[sortByKey]) * bPrice
|
||||||
|
if (aValue > bValue) return -1
|
||||||
|
if (aValue < bValue) return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const aName = a.bank.name
|
||||||
|
const bName = b.bank.name
|
||||||
|
if (aName > bName) return 1
|
||||||
|
if (aName < bName) return -1
|
||||||
|
return 1
|
||||||
|
})
|
||||||
|
|
||||||
|
return sortedBanks
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}, [group, mangoAccount])
|
||||||
|
|
||||||
|
return banks
|
||||||
|
}
|
Loading…
Reference in New Issue