import React, { Fragment, useCallback, useEffect, useMemo, useState, } from 'react' import { BellIcon, CurrencyDollarIcon, DuplicateIcon, ExclamationCircleIcon, GiftIcon, LinkIcon, PencilIcon, SwitchHorizontalIcon, TrashIcon, UsersIcon, } from '@heroicons/react/outline' import { ChevronDownIcon } from '@heroicons/react/solid' import { nativeToUi, ZERO_BN } from '@blockworks-foundation/mango-client' import useMangoStore, { serumProgramId, MNGO_INDEX, } from '../stores/useMangoStore' import PageBodyContainer from '../components/PageBodyContainer' import TopBar from '../components/TopBar' import AccountOrders from '../components/account_page/AccountOrders' import AccountHistory from '../components/account_page/AccountHistory' import AccountsModal from '../components/AccountsModal' import AccountOverview from '../components/account_page/AccountOverview' import AccountInterest from '../components/account_page/AccountInterest' import AccountFunding from '../components/account_page/AccountFunding' import AccountNameModal from '../components/AccountNameModal' import { IconButton, LinkButton } from '../components/Button' import EmptyState from '../components/EmptyState' import Loading from '../components/Loading' import Swipeable from '../components/mobile/Swipeable' import Tabs from '../components/Tabs' import { useViewport } from '../hooks/useViewport' import { breakpoints } from '../components/TradePageGrid' import { serverSideTranslations } from 'next-i18next/serverSideTranslations' import { useTranslation } from 'next-i18next' import Select from '../components/Select' import { useRouter } from 'next/router' import { PublicKey } from '@solana/web3.js' import CloseAccountModal from '../components/CloseAccountModal' import { notify } from '../utils/notifications' import { actionsSelector, mangoAccountSelector, mangoGroupSelector, walletConnectedSelector, } from '../stores/selectors' import CreateAlertModal from '../components/CreateAlertModal' import { copyToClipboard } from '../utils' import DelegateModal from '../components/DelegateModal' import { Menu, Transition } from '@headlessui/react' export async function getStaticProps({ locale }) { return { props: { ...(await serverSideTranslations(locale, [ 'common', 'close-account', 'delegate', 'alerts', ])), // Will be passed to the page component as props }, } } const TABS = ['Portfolio', 'Orders', 'History', 'Interest', 'Funding'] export default function Account() { const { t } = useTranslation(['common', 'close-account', 'delegate']) const { width } = useViewport() const router = useRouter() const connected = useMangoStore(walletConnectedSelector) const mangoAccount = useMangoStore(mangoAccountSelector) const mangoClient = useMangoStore((s) => s.connection.client) const mangoGroup = useMangoStore(mangoGroupSelector) const wallet = useMangoStore((s) => s.wallet.current) const isLoading = useMangoStore((s) => s.selectedMangoAccount.initialLoad) const actions = useMangoStore(actionsSelector) const setMangoStore = useMangoStore((s) => s.set) const [showAccountsModal, setShowAccountsModal] = useState(false) const [showNameModal, setShowNameModal] = useState(false) const [showCloseAccountModal, setShowCloseAccountModal] = useState(false) const [showAlertsModal, setShowAlertsModal] = useState(false) const [showDelegateModal, setShowDelegateModal] = useState(false) const [isCopied, setIsCopied] = useState(false) const [resetOnLeave, setResetOnLeave] = useState(false) const [mngoAccrued, setMngoAccrued] = useState(ZERO_BN) const [viewIndex, setViewIndex] = useState(0) const [activeTab, setActiveTab] = useState(TABS[0]) const isMobile = width ? width < breakpoints.sm : false const { pubkey } = router.query const isDelegatedAccount = wallet?.publicKey ? !mangoAccount?.owner?.equals(wallet?.publicKey) : false const handleCloseAlertModal = useCallback(() => { setShowAlertsModal(false) }, []) const handleCloseAccounts = useCallback(() => { setShowAccountsModal(false) }, []) const handleCloseNameModal = useCallback(() => { setShowNameModal(false) }, []) const handleCloseCloseAccountModal = useCallback(() => { setShowCloseAccountModal(false) }, []) const handleCloseDelegateModal = useCallback(() => { setShowDelegateModal(false) }, []) useEffect(() => { async function loadUnownedMangoAccount() { try { const unownedMangoAccountPubkey = new PublicKey(pubkey) if (mangoGroup) { const unOwnedMangoAccount = await mangoClient.getMangoAccount( unownedMangoAccountPubkey, serumProgramId ) setMangoStore((state) => { state.selectedMangoAccount.current = unOwnedMangoAccount state.selectedMangoAccount.initialLoad = false }) actions.fetchTradeHistory() setResetOnLeave(true) } } catch (error) { router.push('/account') } } if (pubkey) { setMangoStore((state) => { state.selectedMangoAccount.initialLoad = true }) loadUnownedMangoAccount() } }, [pubkey, mangoGroup]) useEffect(() => { if (connected) { router.push('/account') } }, [connected]) useEffect(() => { const handleRouteChange = () => { if (resetOnLeave) { setMangoStore((state) => { state.selectedMangoAccount.current = undefined }) } } router.events.on('routeChangeStart', handleRouteChange) return () => { router.events.off('routeChangeStart', handleRouteChange) } }, [resetOnLeave]) useEffect(() => { if (isCopied) { const timer = setTimeout(() => { setIsCopied(false) }, 1500) return () => clearTimeout(timer) } }, [isCopied]) const handleCopyAddress = (address) => { setIsCopied(true) copyToClipboard(address) } const handleChangeViewIndex = (index) => { setViewIndex(index) } const handleTabChange = (tabName) => { setActiveTab(tabName) } useMemo(() => { setMngoAccrued( mangoAccount ? mangoAccount.perpAccounts.reduce((acc, perpAcct) => { return perpAcct.mngoAccrued.add(acc) }, ZERO_BN) : ZERO_BN ) }, [mangoAccount]) const handleRedeemMngo = async () => { const wallet = useMangoStore.getState().wallet.current const mngoNodeBank = mangoGroup.rootBankAccounts[MNGO_INDEX].nodeBankAccounts[0] try { const txid = await mangoClient.redeemAllMngo( mangoGroup, mangoAccount, wallet, mangoGroup.tokens[MNGO_INDEX].rootBank, mngoNodeBank.publicKey, mngoNodeBank.vault ) actions.reloadMangoAccount() setMngoAccrued(ZERO_BN) notify({ title: t('redeem-success'), description: '', txid, }) } catch (e) { notify({ title: t('redeem-failure'), description: e.message, txid: e.txid, type: 'error', }) } } return (
{mangoAccount ? ( <>

{mangoAccount?.name || t('account')}

{!pubkey ? ( setShowNameModal(true)} > ) : null}
handleCopyAddress(mangoAccount.publicKey.toString()) } > {mangoAccount.publicKey.toBase58()} {isCopied ? ( Copied ) : null}
{t('account-address-warning')}
{!pubkey ? (
{({ open }) => (
More {!isDelegatedAccount ? ( ) : null} {!isDelegatedAccount ? ( ) : null}
)}
) : null} ) : null}
{mangoAccount ? ( !isMobile ? ( ) : (
) ) : null} {mangoAccount ? ( !isMobile ? ( ) : (
) ) : connected ? ( isLoading ? (
) : ( } onClickButton={() => setShowAccountsModal(true)} title={t('no-account-found')} /> ) ) : ( } onClickButton={() => wallet.connect()} title={t('connect-wallet')} /> )}
{showAccountsModal ? ( ) : null} {showNameModal ? ( ) : null} {showCloseAccountModal ? ( ) : null} {showAlertsModal ? ( ) : null} {showDelegateModal ? ( ) : null}
) } const TabContent = ({ activeTab }) => { switch (activeTab) { case 'Portfolio': return case 'Orders': return case 'History': return case 'Interest': return case 'Funding': return default: return } }