From 768ed1170e789bcaa4f58e13c8cc7a71b007f35e Mon Sep 17 00:00:00 2001 From: saml33 Date: Fri, 11 Aug 2023 13:06:38 +1000 Subject: [PATCH 01/12] only show increase account size when account not full --- components/account/AccountActions.tsx | 30 +++++++---- components/modals/MangoAccountSizeModal.tsx | 22 ++++++-- components/settings/AccountSettings.tsx | 58 ++++++++++++++++++--- public/locales/en/settings.json | 1 + public/locales/es/settings.json | 1 + public/locales/ru/settings.json | 1 + public/locales/zh/settings.json | 1 + public/locales/zh_tw/settings.json | 1 + 8 files changed, 91 insertions(+), 24 deletions(-) diff --git a/components/account/AccountActions.tsx b/components/account/AccountActions.tsx index 4f30592b..fbf399c0 100644 --- a/components/account/AccountActions.tsx +++ b/components/account/AccountActions.tsx @@ -1,4 +1,4 @@ -import { Fragment, useState } from 'react' +import { Fragment, useMemo, useState } from 'react' import Button, { IconButton } from '../shared/Button' import { ArrowDownRightIcon, @@ -28,6 +28,7 @@ import useUnownedAccount from 'hooks/useUnownedAccount' import { useViewport } from 'hooks/useViewport' import { breakpoints } from 'utils/theme' import MangoAccountSizeModal from '@components/modals/MangoAccountSizeModal' +import { getIsAccountSizeFull } from '@components/settings/AccountSettings' export const handleCopyAddress = ( mangoAccount: MangoAccount, @@ -63,6 +64,11 @@ const AccountActions = () => { } } + const isAccountFull = useMemo(() => { + if (!mangoAccountAddress) return true + return getIsAccountSizeFull() + }, [mangoAccountAddress]) + return ( <> {isUnownedAccount ? null : ( @@ -147,16 +153,18 @@ const AccountActions = () => { {t('delegate-account')} - setShowAccountSizeModal(true)} - > - - - {t('settings:increase-account-size')} - - + {!isAccountFull ? ( + setShowAccountSizeModal(true)} + > + + + {t('settings:increase-account-size')} + + + ) : null} { }, [mangoAccountAddress]) useEffect(() => { - if (mangoAccountAddress) { + if (mangoAccount) { setAccountSizeForm({ - tokenAccounts: mangoAccount?.tokens.length.toString(), - spotOpenOrders: mangoAccount?.serum3.length.toString(), - perpAccounts: mangoAccount?.perps.length.toString(), - perpOpenOrders: mangoAccount?.perpOpenOrders.length.toString(), + tokenAccounts: mangoAccount.tokens.length.toString(), + spotOpenOrders: mangoAccount.serum3.length.toString(), + perpAccounts: mangoAccount.perps.length.toString(), + perpOpenOrders: mangoAccount.perpOpenOrders.length.toString(), }) } }, [mangoAccountAddress]) @@ -246,6 +246,12 @@ const MangoAccountSizeModal = ({ isOpen, onClose }: ModalProps) => {
= + Number(MAX_ACCOUNTS.tokenAccounts) + : false + } error={formErrors?.tokenAccounts} label={t('tokens')} handleMax={() => handleMax('tokenAccounts')} @@ -290,6 +296,12 @@ const MangoAccountSizeModal = ({ isOpen, onClose }: ModalProps) => {
= + Number(MAX_ACCOUNTS.perpOpenOrders) + : false + } error={formErrors?.perpOpenOrders} label={t('settings:perp-open-orders')} handleMax={() => handleMax('perpOpenOrders')} diff --git a/components/settings/AccountSettings.tsx b/components/settings/AccountSettings.tsx index a0c98169..c6f47155 100644 --- a/components/settings/AccountSettings.tsx +++ b/components/settings/AccountSettings.tsx @@ -3,7 +3,10 @@ import MangoAccountSizeModal, { } from '@components/modals/MangoAccountSizeModal' import { LinkButton } from '@components/shared/Button' import Tooltip from '@components/shared/Tooltip' -import { SquaresPlusIcon } from '@heroicons/react/20/solid' +import { + ExclamationCircleIcon, + SquaresPlusIcon, +} from '@heroicons/react/20/solid' import mangoStore from '@store/mangoStore' import useMangoAccount from 'hooks/useMangoAccount' import { useTranslation } from 'next-i18next' @@ -47,6 +50,31 @@ export const getAvaialableAccountsColor = (used: number, total: number) => { : 'text-th-down' } +const isAccountSlotFull = (slots: number, max: string) => { + const numberMax = Number(max) + return slots >= numberMax +} + +export const getIsAccountSizeFull = () => { + const mangoAccount = mangoStore.getState().mangoAccount.current + if (!mangoAccount) return true + return ( + isAccountSlotFull( + mangoAccount.tokens.length, + MAX_ACCOUNTS.tokenAccounts!, + ) && + isAccountSlotFull( + mangoAccount.serum3.length, + MAX_ACCOUNTS.spotOpenOrders!, + ) && + isAccountSlotFull(mangoAccount.perps.length, MAX_ACCOUNTS.perpAccounts!) && + isAccountSlotFull( + mangoAccount.perpOpenOrders.length, + MAX_ACCOUNTS.perpOpenOrders!, + ) + ) +} + const AccountSettings = () => { const { t } = useTranslation(['common', 'settings']) const { mangoAccountAddress } = useMangoAccount() @@ -81,17 +109,31 @@ const AccountSettings = () => { ] }, [mangoAccountAddress]) + const isAccountFull = useMemo(() => { + if (!mangoAccountAddress) return true + return getIsAccountSizeFull() + }, [mangoAccountAddress]) + return ( <>

{t('account')}

- setShowAccountSizeModal(true)} - > - - {t('settings:increase-account-size')} - + {!isAccountFull ? ( + setShowAccountSizeModal(true)} + > + + {t('settings:increase-account-size')} + + ) : ( +
+ +

+ {t('settings:error-account-size-full')} +

+
+ )}
Date: Fri, 11 Aug 2023 14:09:00 +1000 Subject: [PATCH 02/12] sort token stats tables by deposits value and add sorting to details table --- components/stats/TokenDetailsTable.tsx | 197 ++++++++++++++++-------- components/stats/TokenOverviewTable.tsx | 4 +- 2 files changed, 136 insertions(+), 65 deletions(-) diff --git a/components/stats/TokenDetailsTable.tsx b/components/stats/TokenDetailsTable.tsx index c9e635f4..6798a399 100644 --- a/components/stats/TokenDetailsTable.tsx +++ b/components/stats/TokenDetailsTable.tsx @@ -10,7 +10,14 @@ import { breakpoints } from '../../utils/theme' import ContentBox from '../shared/ContentBox' import Tooltip from '@components/shared/Tooltip' import { Bank } from '@blockworks-foundation/mango-v4' -import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' +import { + SortableColumnHeader, + Table, + Td, + Th, + TrBody, + TrHead, +} from '@components/shared/TableElements' import useMangoGroup from 'hooks/useMangoGroup' import useBanksWithBalances from 'hooks/useBanksWithBalances' import { getOracleProvider } from 'hooks/useOracleProvider' @@ -18,6 +25,8 @@ import { useRouter } from 'next/router' import { goToTokenPage } from './TokenOverviewTable' import { LinkButton } from '@components/shared/Button' import TokenLogo from '@components/shared/TokenLogo' +import { useCallback } from 'react' +import { useSortableData } from 'hooks/useSortableData' const TokenDetailsTable = () => { const { t } = useTranslation(['common', 'activity', 'token', 'trade']) @@ -27,6 +36,45 @@ const TokenDetailsTable = () => { const banks = useBanksWithBalances() const router = useRouter() + const formattedTableData = useCallback(() => { + const formatted = [] + for (const b of banks) { + const bank: Bank = b.bank + const mintInfo = group?.mintInfosMapByMint.get(bank.mint.toString()) + const deposits = bank.uiDeposits() + const initAssetWeight = bank.scaledInitAssetWeight(bank.price) + const initLiabWeight = bank.scaledInitLiabWeight(bank.price) + const isInsured = mintInfo?.groupInsuranceFund ? t('yes') : t('no') + const liquidationFee = bank.liquidationFee.toNumber() * 100 + const loanOriginationFee = 100 * bank.loanOriginationFeeRate.toNumber() + const [oracleProvider, oracleLinkPath] = getOracleProvider(bank) + const symbol = bank.name + + const data = { + bank, + deposits, + initAssetWeight, + initLiabWeight, + isInsured, + liquidationFee, + loanOriginationFee, + oracleLinkPath, + oracleProvider, + symbol, + } + formatted.push(data) + } + return formatted.sort( + (a, b) => b.deposits * b.bank.uiPrice - a.deposits * a.bank.uiPrice, + ) + }, [banks, group]) + + const { + items: tableData, + requestSort, + sortConfig, + } = useSortableData(formattedTableData()) + return group ? ( {showTableView ? ( @@ -34,117 +82,138 @@ const TokenDetailsTable = () => { - + - + - - {banks.map((b) => { - const bank: Bank = b.bank - - const [oracleProvider, oracleLinkPath] = getOracleProvider(bank) - - const mintInfo = group.mintInfosMapByMint.get( - bank.mint.toString(), - ) + {tableData.map((data) => { + const { + bank, + initAssetWeight, + initLiabWeight, + isInsured, + liquidationFee, + loanOriginationFee, + oracleLinkPath, + oracleProvider, + symbol, + } = data return ( - goToTokenPage(bank.name.split(' ')[0], router) - } + key={symbol} + onClick={() => goToTokenPage(symbol.split(' ')[0], router)} >
{t('token')} + requestSort('symbol')} + sortConfig={sortConfig} + title={t('token')} + /> + -
+
- - {t('asset-liability-weight')} - + requestSort('initAssetWeight')} + sortConfig={sortConfig} + title={t('asset-liability-weight')} + />
-
+
- - {t('borrow-fee')} - + requestSort('loanOriginationFee')} + sortConfig={sortConfig} + title={t('borrow-fee')} + />
-
+
- - {t('activity:liquidation-fee')} - + requestSort('liquidationFee')} + sortConfig={sortConfig} + title={t('activity:liquidation-fee')} + />
- - {t('trade:tooltip-insured', { tokenOrMarket: '' })} - - Learn more - - - } - > - - {t('trade:insured', { token: '' })} - - + +
+ + {t('trade:tooltip-insured', { tokenOrMarket: '' })} + + Learn more + +
+ } + > + requestSort('isInsured')} + sortConfig={sortConfig} + title={t('trade:insured', { token: '' })} + /> + + +
+
+ requestSort('oracleProvider')} + sortConfig={sortConfig} + title={t('trade:oracle')} + /> +
{t('trade:oracle')}
-

{bank.name}

+

{symbol}

-

- {bank.scaledInitAssetWeight(bank.price).toFixed(2)} -

+

{initAssetWeight.toFixed(2)}

| -

- {bank.scaledInitLiabWeight(bank.price).toFixed(2)} -

+

{initLiabWeight.toFixed(2)}

- {(100 * bank.loanOriginationFeeRate.toNumber()).toFixed( - 2, - )} - % + {loanOriginationFee.toFixed(2)}%

-

- {(bank.liquidationFee.toNumber() * 100).toFixed(2)}% -

+

{liquidationFee.toFixed(2)}%

-

- {mintInfo?.groupInsuranceFund ? t('yes') : t('no')} -

+

{isInsured}

{oracleLinkPath ? ( diff --git a/components/stats/TokenOverviewTable.tsx b/components/stats/TokenOverviewTable.tsx index f645f271..9264b68f 100644 --- a/components/stats/TokenOverviewTable.tsx +++ b/components/stats/TokenOverviewTable.tsx @@ -84,7 +84,9 @@ const TokenOverviewTable = () => { } formatted.push(data) } - return formatted + return formatted.sort( + (a, b) => b.deposits * b.bank.uiPrice - a.deposits * a.bank.uiPrice, + ) }, [banks, group]) const { From 82de613eb9370e57e812c19c7c1c7d23a65311e9 Mon Sep 17 00:00:00 2001 From: saml33 Date: Fri, 11 Aug 2023 14:55:22 +1000 Subject: [PATCH 03/12] optimize pepe theme images and fix mobile topbar spacing --- components/StatusBar.tsx | 2 +- components/TopBar.tsx | 14 ++++++++------ public/images/themes/pepe/pepe-hori-tile.png | Bin 17118 -> 5948 bytes public/images/themes/pepe/pepe-logo.png | Bin 30160 -> 11439 bytes .../themes/pepe/pepe-vert-tile-expanded.png | Bin 51183 -> 17483 bytes public/images/themes/pepe/pepe-vert-tile.png | Bin 18425 -> 5998 bytes public/images/themes/pepe/sidenav-image.png | Bin 132048 -> 41015 bytes public/images/themes/pepe/tv-chart-image.png | Bin 104105 -> 36418 bytes 8 files changed, 9 insertions(+), 7 deletions(-) diff --git a/components/StatusBar.tsx b/components/StatusBar.tsx index 3e6dff93..ee9668af 100644 --- a/components/StatusBar.tsx +++ b/components/StatusBar.tsx @@ -61,7 +61,7 @@ const StatusBar = ({ collapsed }: { collapsed: boolean }) => { rel="noreferrer noopener" target="_blank" > - v{IDL.version} + v{IDL.version} {latestCommit.sha && latestCommit.url ? ( diff --git a/components/TopBar.tsx b/components/TopBar.tsx index b5cbe3e6..29470648 100644 --- a/components/TopBar.tsx +++ b/components/TopBar.tsx @@ -108,11 +108,13 @@ const TopBar = () => { ) : null} */} - logo +
+ logo +
{!connected ? ( mangoAccount ? ( @@ -189,7 +191,7 @@ const TopBar = () => { {isUnownedAccount || (!connected && isMobile) ? null : isMobile ? ( ) : (