merge main
|
@ -118,7 +118,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
if (!mangoAccount || !group || !publicKey) return
|
||||
setSubmitting(true)
|
||||
try {
|
||||
const tx = await client.tokenWithdraw(
|
||||
const { signature: tx, slot } = await client.tokenWithdraw(
|
||||
group,
|
||||
mangoAccount,
|
||||
bank!.mint,
|
||||
|
@ -130,7 +130,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
type: 'success',
|
||||
txid: tx,
|
||||
})
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
actions.fetchWalletTokens(publicKey)
|
||||
setSubmitting(false)
|
||||
onSuccess()
|
||||
|
|
|
@ -130,7 +130,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
|
||||
setSubmitting(true)
|
||||
try {
|
||||
const tx = await client.tokenDeposit(
|
||||
const { signature: tx, slot } = await client.tokenDeposit(
|
||||
group,
|
||||
mangoAccount,
|
||||
bank.mint,
|
||||
|
@ -142,7 +142,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
txid: tx,
|
||||
})
|
||||
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
actions.fetchWalletTokens(publicKey)
|
||||
setSubmitting(false)
|
||||
onSuccess()
|
||||
|
|
|
@ -93,22 +93,24 @@ const HydrateStore = () => {
|
|||
async (info, context) => {
|
||||
if (info?.lamports === 0) return
|
||||
|
||||
const lastSeenSlot = mangoStore.getState().mangoAccount.lastSlot
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
if (!mangoAccount) return
|
||||
|
||||
if (context.slot > lastSeenSlot) {
|
||||
const newMangoAccount = await client.getMangoAccountFromAi(
|
||||
const newMangoAccount = client.getMangoAccountFromAi(
|
||||
mangoAccount.publicKey,
|
||||
info,
|
||||
)
|
||||
// don't fetch serum3OpenOrders if the slot is old
|
||||
if (context.slot > mangoStore.getState().mangoAccount.lastSlot) {
|
||||
if (newMangoAccount.serum3Active().length > 0) {
|
||||
await newMangoAccount.reloadSerum3OpenOrders(client)
|
||||
}
|
||||
// check again that the slot is still the most recent after the reloading open orders
|
||||
if (context.slot > mangoStore.getState().mangoAccount.lastSlot) {
|
||||
set((s) => {
|
||||
s.mangoAccount.current = newMangoAccount
|
||||
s.mangoAccount.lastSlot = context.slot
|
||||
})
|
||||
}
|
||||
}
|
||||
actions.fetchOpenOrders()
|
||||
}
|
||||
},
|
||||
|
|
|
@ -125,7 +125,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
|
||||
setSubmitting(true)
|
||||
try {
|
||||
const tx = await client.tokenDeposit(
|
||||
const { signature: tx, slot } = await client.tokenDeposit(
|
||||
group,
|
||||
mangoAccount,
|
||||
bank.mint,
|
||||
|
@ -138,7 +138,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
txid: tx,
|
||||
})
|
||||
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
actions.fetchWalletTokens(publicKey)
|
||||
setSubmitting(false)
|
||||
onSuccess()
|
||||
|
|
|
@ -61,7 +61,7 @@ const StatusBar = ({ collapsed }: { collapsed: boolean }) => {
|
|||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
<span className="text-th-fgd-3 text-xs">v{IDL.version}</span>
|
||||
<span>v{IDL.version}</span>
|
||||
</a>
|
||||
</Tooltip>
|
||||
{latestCommit.sha && latestCommit.url ? (
|
||||
|
|
|
@ -108,11 +108,13 @@ const TopBar = () => {
|
|||
<SolanaTps />
|
||||
</div>
|
||||
) : null} */}
|
||||
<div className="bg-th-bkg-1 flex items-center justify-center h-[63px] w-16 md:hidden">
|
||||
<img
|
||||
className="mr-4 h-9 w-9 flex-shrink-0 md:hidden"
|
||||
className="h-9 w-9 flex-shrink-0"
|
||||
src={themeData.logoPath}
|
||||
alt="logo"
|
||||
/>
|
||||
</div>
|
||||
{!connected ? (
|
||||
mangoAccount ? (
|
||||
<span className="hidden items-center md:flex md:pl-6">
|
||||
|
@ -189,7 +191,7 @@ const TopBar = () => {
|
|||
{isUnownedAccount || (!connected && isMobile) ? null : isMobile ? (
|
||||
<button
|
||||
onClick={() => handleDepositWithdrawModal('deposit')}
|
||||
className="h-16 border-l border-th-bkg-3 px-4 font-display text-th-fgd-1"
|
||||
className="h-[63px] bg-th-bkg-1 border-l border-th-bkg-3 px-4 font-display text-center text-th-fgd-1"
|
||||
>{`${t('deposit')} / ${t('withdraw')}`}</button>
|
||||
) : (
|
||||
<Button
|
||||
|
|
|
@ -111,7 +111,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
if (!mangoAccount || !group || !bank) return
|
||||
setSubmitting(true)
|
||||
try {
|
||||
const tx = await client.tokenWithdraw(
|
||||
const { signature: tx, slot } = await client.tokenWithdraw(
|
||||
group,
|
||||
mangoAccount,
|
||||
bank.mint,
|
||||
|
@ -123,7 +123,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
type: 'success',
|
||||
txid: tx,
|
||||
})
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
setSubmitting(false)
|
||||
onSuccess()
|
||||
} catch (e) {
|
||||
|
|
|
@ -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,6 +153,7 @@ const AccountActions = () => {
|
|||
<UserPlusIcon className="h-4 w-4" />
|
||||
<span className="ml-2">{t('delegate-account')}</span>
|
||||
</ActionsLinkButton>
|
||||
{!isAccountFull ? (
|
||||
<ActionsLinkButton
|
||||
disabled={isDelegatedAccount}
|
||||
mangoAccount={mangoAccount!}
|
||||
|
@ -157,6 +164,7 @@ const AccountActions = () => {
|
|||
{t('settings:increase-account-size')}
|
||||
</span>
|
||||
</ActionsLinkButton>
|
||||
) : null}
|
||||
<ActionsLinkButton
|
||||
disabled={isDelegatedAccount}
|
||||
mangoAccount={mangoAccount!}
|
||||
|
|
|
@ -50,11 +50,11 @@ const CreateAccountForm = ({
|
|||
setLoading(true)
|
||||
try {
|
||||
const newAccountNum = getNextAccountNumber(mangoAccounts)
|
||||
const tx = await client.createMangoAccount(
|
||||
const { signature: tx } = await client.createMangoAccount(
|
||||
group,
|
||||
newAccountNum,
|
||||
name || `Account ${newAccountNum + 1}`,
|
||||
16, // tokenCount
|
||||
10, // tokenCount
|
||||
)
|
||||
if (tx) {
|
||||
const pk = wallet.adapter.publicKey
|
||||
|
@ -66,7 +66,6 @@ const CreateAccountForm = ({
|
|||
(acc) => acc.accountNum === newAccountNum,
|
||||
)
|
||||
if (newAccount) {
|
||||
await newAccount.reloadSerum3OpenOrders(client)
|
||||
set((s) => {
|
||||
s.mangoAccount.current = newAccount
|
||||
s.mangoAccounts = reloadedMangoAccounts
|
||||
|
|
|
@ -925,7 +925,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
</div>
|
||||
<ol className="list-decimal pl-4">
|
||||
{!advForm.openBookMarketExternalPk &&
|
||||
liqudityTier &&
|
||||
listingTier &&
|
||||
!loadingListingParams ? (
|
||||
<li className="pl-2">
|
||||
<div className="mb-4">
|
||||
|
@ -956,7 +956,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
) : null}
|
||||
</li>
|
||||
) : null}
|
||||
{!advForm.oraclePk && liqudityTier && !loadingListingParams ? (
|
||||
{!advForm.oraclePk && listingTier && !loadingListingParams ? (
|
||||
<li
|
||||
className={`my-4 pl-2 ${
|
||||
!advForm.openBookMarketExternalPk
|
||||
|
@ -978,7 +978,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
type="error"
|
||||
/>
|
||||
<CreateSwitchboardOracleModal
|
||||
tier={liqudityTier}
|
||||
tier={listingTier}
|
||||
orcaPoolAddress={orcaPoolAddress}
|
||||
raydiumPoolAddress={raydiumPoolAddress}
|
||||
baseTokenName={currentTokenInfo.symbol}
|
||||
|
|
|
@ -24,7 +24,11 @@ const AccountNameModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
if (!mangoAccount || !group) return
|
||||
setLoading(true)
|
||||
try {
|
||||
const tx = await client.editMangoAccount(group, mangoAccount, name)
|
||||
const { signature: tx, slot } = await client.editMangoAccount(
|
||||
group,
|
||||
mangoAccount,
|
||||
name,
|
||||
)
|
||||
|
||||
setLoading(false)
|
||||
onClose()
|
||||
|
@ -33,7 +37,7 @@ const AccountNameModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
type: 'success',
|
||||
txid: tx,
|
||||
})
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
setLoading(false)
|
||||
|
|
|
@ -46,7 +46,10 @@ const CloseAccountModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
if (!mangoAccount || !group) return
|
||||
setLoading(true)
|
||||
try {
|
||||
const tx = await client.emptyAndCloseMangoAccount(group, mangoAccount)
|
||||
const { signature: tx } = await client.emptyAndCloseMangoAccount(
|
||||
group,
|
||||
mangoAccount,
|
||||
)
|
||||
if (tx) {
|
||||
const newMangoAccounts = mangoAccounts.filter(
|
||||
(ma) => !ma.publicKey.equals(mangoAccount.publicKey),
|
||||
|
|
|
@ -40,7 +40,7 @@ const DelegateModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
}
|
||||
|
||||
try {
|
||||
const tx = await client.editMangoAccount(
|
||||
const { signature: tx, slot } = await client.editMangoAccount(
|
||||
group,
|
||||
mangoAccount,
|
||||
undefined,
|
||||
|
@ -57,7 +57,7 @@ const DelegateModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
type: 'success',
|
||||
txid: tx,
|
||||
})
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
if (!isMangoError(e)) return
|
||||
|
|
|
@ -23,7 +23,7 @@ import {
|
|||
|
||||
const MIN_ACCOUNTS = 8
|
||||
export const MAX_ACCOUNTS: AccountSizeForm = {
|
||||
tokenAccounts: '16',
|
||||
tokenAccounts: '10',
|
||||
spotOpenOrders: '8',
|
||||
perpAccounts: '8',
|
||||
perpOpenOrders: '64',
|
||||
|
@ -87,12 +87,12 @@ const MangoAccountSizeModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
}, [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])
|
||||
|
@ -203,7 +203,7 @@ const MangoAccountSizeModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
return
|
||||
setSubmitting(true)
|
||||
try {
|
||||
const tx = await client.accountExpandV2(
|
||||
const { signature: tx, slot } = await client.accountExpandV2(
|
||||
group,
|
||||
mangoAccount,
|
||||
parseInt(tokenAccounts),
|
||||
|
@ -217,7 +217,7 @@ const MangoAccountSizeModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
type: 'success',
|
||||
txid: tx,
|
||||
})
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
setSubmitting(false)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
|
@ -246,6 +246,12 @@ const MangoAccountSizeModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
<div className="mb-4">
|
||||
<AccountSizeFormInput
|
||||
availableAccounts={availableTokens}
|
||||
disabled={
|
||||
mangoAccount
|
||||
? mangoAccount.tokens.length >=
|
||||
Number(MAX_ACCOUNTS.tokenAccounts)
|
||||
: false
|
||||
}
|
||||
error={formErrors?.tokenAccounts}
|
||||
label={t('tokens')}
|
||||
handleMax={() => handleMax('tokenAccounts')}
|
||||
|
@ -290,6 +296,12 @@ const MangoAccountSizeModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
<div>
|
||||
<AccountSizeFormInput
|
||||
availableAccounts={availablePerpOo}
|
||||
disabled={
|
||||
mangoAccount
|
||||
? mangoAccount.perpOpenOrders.length >=
|
||||
Number(MAX_ACCOUNTS.perpOpenOrders)
|
||||
: false
|
||||
}
|
||||
error={formErrors?.perpOpenOrders}
|
||||
label={t('settings:perp-open-orders')}
|
||||
handleMax={() => handleMax('perpOpenOrders')}
|
||||
|
|
|
@ -85,7 +85,7 @@ const ModifyTvOrderModal = ({
|
|||
: o.price
|
||||
if (!group || !mangoAccount) return
|
||||
try {
|
||||
let tx = ''
|
||||
let tx
|
||||
if (o instanceof PerpOrder) {
|
||||
tx = await client.modifyPerpOrder(
|
||||
group,
|
||||
|
@ -125,7 +125,7 @@ const ModifyTvOrderModal = ({
|
|||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
})
|
||||
onClose()
|
||||
} catch (e) {
|
||||
|
@ -139,7 +139,12 @@ const ModifyTvOrderModal = ({
|
|||
})
|
||||
}
|
||||
},
|
||||
[findSerum3MarketPkInOpenOrders, modifiedOrderPrice, modifiedOrderSize],
|
||||
[
|
||||
findSerum3MarketPkInOpenOrders,
|
||||
modifiedOrderPrice,
|
||||
modifiedOrderSize,
|
||||
tickDecimals,
|
||||
],
|
||||
)
|
||||
|
||||
return selectedMarket ? (
|
||||
|
|
|
@ -103,7 +103,7 @@ const UserSetupModal = ({
|
|||
if (!group || !publicKey) return
|
||||
setLoadingAccount(true)
|
||||
try {
|
||||
const tx = await client.createMangoAccount(
|
||||
const { signature: tx } = await client.createMangoAccount(
|
||||
group,
|
||||
0,
|
||||
accountName || 'Account 1',
|
||||
|
@ -143,7 +143,7 @@ const UserSetupModal = ({
|
|||
if (!mangoAccount || !group || !bank) return
|
||||
try {
|
||||
setSubmitDeposit(true)
|
||||
const tx = await client.tokenDeposit(
|
||||
const { signature: tx, slot } = await client.tokenDeposit(
|
||||
group,
|
||||
mangoAccount,
|
||||
bank.mint,
|
||||
|
@ -155,7 +155,7 @@ const UserSetupModal = ({
|
|||
txid: tx,
|
||||
})
|
||||
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
setSubmitDeposit(false)
|
||||
onClose()
|
||||
// setShowSetupStep(4)
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
import { useState } from 'react'
|
||||
import { MANGO_MINT_DECIMALS } from 'utils/governance/constants'
|
||||
// import { useTranslation } from 'next-i18next'
|
||||
// import ResponsivePagination from 'react-responsive-pagination'
|
||||
import { ImgWithLoader } from '@components/ImgWithLoader'
|
||||
import NftMarketButton from './NftMarketButton'
|
||||
|
||||
|
|
|
@ -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,10 +109,16 @@ const AccountSettings = () => {
|
|||
]
|
||||
}, [mangoAccountAddress])
|
||||
|
||||
const isAccountFull = useMemo(() => {
|
||||
if (!mangoAccountAddress) return true
|
||||
return getIsAccountSizeFull()
|
||||
}, [mangoAccountAddress])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<h2 className="text-base">{t('account')}</h2>
|
||||
{!isAccountFull ? (
|
||||
<LinkButton
|
||||
className="flex items-center"
|
||||
onClick={() => setShowAccountSizeModal(true)}
|
||||
|
@ -92,6 +126,14 @@ const AccountSettings = () => {
|
|||
<SquaresPlusIcon className="h-4 w-4 mr-1.5" />
|
||||
{t('settings:increase-account-size')}
|
||||
</LinkButton>
|
||||
) : (
|
||||
<div className="flex items-center">
|
||||
<ExclamationCircleIcon className="h-4 w-4 mr-1.5 text-th-error" />
|
||||
<p className="text-th-error">
|
||||
{t('settings:error-account-size-full')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col border-t border-th-bkg-3 py-4 md:flex-row md:items-center md:justify-between md:px-4">
|
||||
<Tooltip
|
||||
|
|
|
@ -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 ? (
|
||||
<ContentBox hideBorder hidePadding>
|
||||
{showTableView ? (
|
||||
|
@ -34,39 +82,56 @@ const TokenDetailsTable = () => {
|
|||
<Table>
|
||||
<thead>
|
||||
<TrHead>
|
||||
<Th className="text-left">{t('token')}</Th>
|
||||
<Th className="text-left">
|
||||
<SortableColumnHeader
|
||||
sortKey="symbol"
|
||||
sort={() => requestSort('symbol')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('token')}
|
||||
/>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end text-right">
|
||||
<div className="flex justify-end">
|
||||
<Tooltip content={t('asset-liability-weight-desc')}>
|
||||
<span className="tooltip-underline">
|
||||
{t('asset-liability-weight')}
|
||||
</span>
|
||||
<SortableColumnHeader
|
||||
sortKey="initAssetWeight"
|
||||
sort={() => requestSort('initAssetWeight')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('asset-liability-weight')}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end text-right">
|
||||
<div className="flex justify-end">
|
||||
<Tooltip content={t('tooltip-borrow-fee')}>
|
||||
<span className="tooltip-underline">
|
||||
{t('borrow-fee')}
|
||||
</span>
|
||||
<SortableColumnHeader
|
||||
sortKey="loanOriginationFee"
|
||||
sort={() => requestSort('loanOriginationFee')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('borrow-fee')}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end text-right">
|
||||
<div className="flex justify-end">
|
||||
<Tooltip
|
||||
content={t('token:tooltip-liquidation-fee', {
|
||||
symbol: t('tokens').toLowerCase(),
|
||||
})}
|
||||
>
|
||||
<span className="tooltip-underline">
|
||||
{t('activity:liquidation-fee')}
|
||||
</span>
|
||||
<SortableColumnHeader
|
||||
sortKey="liquidationFee"
|
||||
sort={() => requestSort('liquidationFee')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('activity:liquidation-fee')}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Th>
|
||||
<Th className="text-right">
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<Tooltip
|
||||
content={
|
||||
<div>
|
||||
|
@ -82,69 +147,73 @@ const TokenDetailsTable = () => {
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<span className="tooltip-underline">
|
||||
{t('trade:insured', { token: '' })}
|
||||
</span>
|
||||
<SortableColumnHeader
|
||||
sortKey="isInsured"
|
||||
sort={() => requestSort('isInsured')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('trade:insured', { token: '' })}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<SortableColumnHeader
|
||||
sortKey="oracleProvider"
|
||||
sort={() => requestSort('oracleProvider')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('trade:oracle')}
|
||||
/>
|
||||
</div>
|
||||
</Th>
|
||||
<Th className="text-right">{t('trade:oracle')}</Th>
|
||||
<Th />
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{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 (
|
||||
<TrBody
|
||||
className="default-transition md:hover:cursor-pointer md:hover:bg-th-bkg-2"
|
||||
key={bank.name}
|
||||
onClick={() =>
|
||||
goToTokenPage(bank.name.split(' ')[0], router)
|
||||
}
|
||||
key={symbol}
|
||||
onClick={() => goToTokenPage(symbol.split(' ')[0], router)}
|
||||
>
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
<TokenLogo bank={bank} />
|
||||
</div>
|
||||
<p className="font-body">{bank.name}</p>
|
||||
<p className="font-body">{symbol}</p>
|
||||
</div>
|
||||
</Td>
|
||||
<Td>
|
||||
<div className="flex justify-end space-x-1.5 text-right">
|
||||
<p>
|
||||
{bank.scaledInitAssetWeight(bank.price).toFixed(2)}
|
||||
</p>
|
||||
<p>{initAssetWeight.toFixed(2)}</p>
|
||||
<span className="text-th-fgd-4">|</span>
|
||||
<p>
|
||||
{bank.scaledInitLiabWeight(bank.price).toFixed(2)}
|
||||
</p>
|
||||
<p>{initLiabWeight.toFixed(2)}</p>
|
||||
</div>
|
||||
</Td>
|
||||
<Td>
|
||||
<p className="text-right">
|
||||
{(100 * bank.loanOriginationFeeRate.toNumber()).toFixed(
|
||||
2,
|
||||
)}
|
||||
%
|
||||
{loanOriginationFee.toFixed(2)}%
|
||||
</p>
|
||||
</Td>
|
||||
<Td>
|
||||
<p className="text-right">
|
||||
{(bank.liquidationFee.toNumber() * 100).toFixed(2)}%
|
||||
</p>
|
||||
<p className="text-right">{liquidationFee.toFixed(2)}%</p>
|
||||
</Td>
|
||||
<Td>
|
||||
<p className="text-right">
|
||||
{mintInfo?.groupInsuranceFund ? t('yes') : t('no')}
|
||||
</p>
|
||||
<p className="text-right">{isInsured}</p>
|
||||
</Td>
|
||||
<Td>
|
||||
{oracleLinkPath ? (
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -593,11 +593,11 @@ const LimitSwapForm = ({
|
|||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
type: 'success',
|
||||
txid: tx,
|
||||
txid: tx?.signature,
|
||||
noSound: true,
|
||||
})
|
||||
actions.fetchGroup()
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(tx?.slot)
|
||||
} catch (e) {
|
||||
console.error('onSwap error: ', e)
|
||||
sentry.captureException(e)
|
||||
|
|
|
@ -108,7 +108,7 @@ const SwapOrders = () => {
|
|||
setCancelId(id.toString())
|
||||
|
||||
try {
|
||||
const tx = await client.tokenConditionalSwapCancel(
|
||||
const { signature: tx, slot } = await client.tokenConditionalSwapCancel(
|
||||
group,
|
||||
mangoAccount,
|
||||
id,
|
||||
|
@ -120,7 +120,7 @@ const SwapOrders = () => {
|
|||
noSound: true,
|
||||
})
|
||||
actions.fetchGroup()
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
} catch (e) {
|
||||
console.error('failed to cancel swap order', e)
|
||||
sentry.captureException(e)
|
||||
|
@ -151,10 +151,8 @@ const SwapOrders = () => {
|
|||
setCancelId('all')
|
||||
|
||||
try {
|
||||
const tx = await client.tokenConditionalSwapCancelAll(
|
||||
group,
|
||||
mangoAccount,
|
||||
)
|
||||
const { signature: tx, slot } =
|
||||
await client.tokenConditionalSwapCancelAll(group, mangoAccount)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
type: 'success',
|
||||
|
@ -162,7 +160,7 @@ const SwapOrders = () => {
|
|||
noSound: true,
|
||||
})
|
||||
actions.fetchGroup()
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
} catch (e) {
|
||||
console.error('failed to cancel trigger orders', e)
|
||||
sentry.captureException(e)
|
||||
|
|
|
@ -287,7 +287,7 @@ const SwapReviewRouteInfo = ({
|
|||
)
|
||||
|
||||
try {
|
||||
const tx = await client.marginTrade({
|
||||
const { signature: tx, slot } = await client.marginTrade({
|
||||
group,
|
||||
mangoAccount,
|
||||
inputMintPk: inputBank.mint,
|
||||
|
@ -311,7 +311,7 @@ const SwapReviewRouteInfo = ({
|
|||
})
|
||||
actions.fetchGroup()
|
||||
actions.fetchSwapHistory(mangoAccount.publicKey.toString(), 30000)
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
} catch (e) {
|
||||
console.error('onSwap error: ', e)
|
||||
sentry.captureException(e)
|
||||
|
|
|
@ -392,7 +392,7 @@ const AdvancedTradeForm = () => {
|
|||
: tradeForm.postOnly && tradeForm.tradeType !== 'Market'
|
||||
? Serum3OrderType.postOnly
|
||||
: Serum3OrderType.limit
|
||||
const tx = await client.serum3PlaceOrder(
|
||||
const { signature: tx } = await client.serum3PlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
selectedMarket.serumMarketExternal,
|
||||
|
@ -427,7 +427,7 @@ const AdvancedTradeForm = () => {
|
|||
: PerpOrderType.limit
|
||||
console.log('perpOrderType', perpOrderType)
|
||||
|
||||
const tx = await client.perpPlaceOrder(
|
||||
const { signature: tx } = await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
selectedMarket.perpMarketIndex,
|
||||
|
|
|
@ -163,7 +163,7 @@ const MarketCloseModal: FunctionComponent<MarketCloseModalProps> = ({
|
|||
)
|
||||
|
||||
const maxSlippage = 0.025
|
||||
const tx = await client.perpPlaceOrder(
|
||||
const { signature: tx } = await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
perpMarket.perpMarketIndex,
|
||||
|
|
|
@ -93,7 +93,7 @@ const OpenOrders = () => {
|
|||
|
||||
setCancelId(o.orderId.toString())
|
||||
try {
|
||||
const tx = await client.serum3CancelOrder(
|
||||
const { signature: tx } = await client.serum3CancelOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
market!.serumMarketExternal,
|
||||
|
@ -135,7 +135,7 @@ const OpenOrders = () => {
|
|||
if (!group || !mangoAccount) return
|
||||
setLoadingModifyOrder(true)
|
||||
try {
|
||||
let tx = ''
|
||||
let tx
|
||||
if (o instanceof PerpOrder) {
|
||||
tx = await client.modifyPerpOrder(
|
||||
group,
|
||||
|
@ -175,7 +175,7 @@ const OpenOrders = () => {
|
|||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Error canceling', e)
|
||||
|
@ -203,7 +203,7 @@ const OpenOrders = () => {
|
|||
if (!group || !mangoAccount) return
|
||||
setCancelId(o.orderId.toString())
|
||||
try {
|
||||
const tx = await client.perpCancelOrder(
|
||||
const { signature: tx } = await client.perpCancelOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
o.perpMarketIndex,
|
||||
|
|
|
@ -31,7 +31,7 @@ import {
|
|||
updatePerpMarketOnGroup,
|
||||
} from 'utils/orderbook'
|
||||
import { OrderbookData, OrderbookL2 } from 'types'
|
||||
import { isEqual } from 'lodash'
|
||||
import isEqual from 'lodash/isEqual'
|
||||
|
||||
const sizeCompacter = Intl.NumberFormat('en', {
|
||||
maximumFractionDigits: 6,
|
||||
|
|
|
@ -200,7 +200,7 @@ export default function SpotMarketOrderSwapForm() {
|
|||
)
|
||||
|
||||
try {
|
||||
const tx = await client.marginTrade({
|
||||
const { signature: tx, slot } = await client.marginTrade({
|
||||
group,
|
||||
mangoAccount,
|
||||
inputMintPk: inputBank.mint,
|
||||
|
@ -227,7 +227,7 @@ export default function SpotMarketOrderSwapForm() {
|
|||
})
|
||||
actions.fetchGroup()
|
||||
actions.fetchSwapHistory(mangoAccount.publicKey.toString(), 30000)
|
||||
await actions.reloadMangoAccount()
|
||||
await actions.reloadMangoAccount(slot)
|
||||
set((s) => {
|
||||
s.tradeForm.baseSize = ''
|
||||
s.tradeForm.quoteSize = ''
|
||||
|
|
|
@ -306,7 +306,7 @@ const TradeHotKeys = ({ children }: { children: ReactNode }) => {
|
|||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
})
|
||||
} else if (selectedMarket instanceof PerpMarket) {
|
||||
const perpOrderType =
|
||||
|
@ -343,7 +343,7 @@ const TradeHotKeys = ({ children }: { children: ReactNode }) => {
|
|||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
@ -232,7 +232,7 @@ const TradingViewChart = () => {
|
|||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Error canceling', e)
|
||||
|
@ -266,7 +266,7 @@ const TradingViewChart = () => {
|
|||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Error canceling', e)
|
||||
|
|
|
@ -47,7 +47,7 @@ const UnsettledTrades = ({
|
|||
setSettleMktAddress(mktAddress)
|
||||
|
||||
try {
|
||||
const txid = await client.serum3SettleFunds(
|
||||
const tx = await client.serum3SettleFunds(
|
||||
group,
|
||||
mangoAccount,
|
||||
new PublicKey(mktAddress),
|
||||
|
@ -56,7 +56,7 @@ const UnsettledTrades = ({
|
|||
notify({
|
||||
type: 'success',
|
||||
title: 'Successfully settled funds',
|
||||
txid,
|
||||
txid: tx.signature,
|
||||
})
|
||||
} catch (e) {
|
||||
if (isMangoError(e)) {
|
||||
|
@ -107,7 +107,7 @@ const UnsettledTrades = ({
|
|||
const unprofitableAccount =
|
||||
mangoAccountPnl > 0 ? settleCandidates[0].account : mangoAccount
|
||||
|
||||
const txid = await client.perpSettlePnlAndFees(
|
||||
const { signature: txid, slot } = await client.perpSettlePnlAndFees(
|
||||
group,
|
||||
profitableAccount,
|
||||
unprofitableAccount,
|
||||
|
@ -115,7 +115,7 @@ const UnsettledTrades = ({
|
|||
mangoAccount,
|
||||
market.perpMarketIndex,
|
||||
)
|
||||
actions.reloadMangoAccount()
|
||||
actions.reloadMangoAccount(slot)
|
||||
notify({
|
||||
type: 'success',
|
||||
title: 'Successfully settled P&L',
|
||||
|
|
14
package.json
|
@ -22,28 +22,24 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@blockworks-foundation/mango-feeds": "0.1.7",
|
||||
"@blockworks-foundation/mango-v4": "^0.18.17",
|
||||
"@blockworks-foundation/mango-v4": "^0.19.2",
|
||||
"@blockworks-foundation/mango-v4-settings": "0.2.6",
|
||||
"@headlessui/react": "1.6.6",
|
||||
"@heroicons/react": "2.0.10",
|
||||
"@metaplex-foundation/js": "0.19.4",
|
||||
"@next/font": "13.4.4",
|
||||
"@project-serum/anchor": "0.25.0",
|
||||
"@pythnetwork/client": "2.15.0",
|
||||
"@sentry/nextjs": "7.58.0",
|
||||
"@solana/spl-governance": "0.3.27",
|
||||
"@solana/spl-token": "0.3.7",
|
||||
"@solana/wallet-adapter-base": "0.9.22",
|
||||
"@solana/wallet-adapter-base": "0.9.23",
|
||||
"@solana/wallet-adapter-react": "0.15.32",
|
||||
"@solana/wallet-adapter-wallets": "0.19.18",
|
||||
"@solflare-wallet/pfp": "0.0.6",
|
||||
"@solana/wallet-adapter-wallets": "0.19.20",
|
||||
"@switchboard-xyz/solana.js": "2.4.7",
|
||||
"@tanstack/react-query": "4.10.1",
|
||||
"@tippyjs/react": "4.2.6",
|
||||
"@types/howler": "2.2.7",
|
||||
"@types/lodash": "4.14.185",
|
||||
"@web3auth/sign-in-with-solana": "1.0.0",
|
||||
"assert": "2.0.0",
|
||||
"big.js": "6.2.1",
|
||||
"clsx": "1.2.1",
|
||||
"csv-stringify": "6.3.2",
|
||||
|
@ -63,7 +59,6 @@
|
|||
"next": "13.4.4",
|
||||
"next-i18next": "14.0.0",
|
||||
"next-themes": "0.2.0",
|
||||
"process": "0.11.10",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-flip-numbers": "3.0.5",
|
||||
|
@ -72,13 +67,11 @@
|
|||
"react-i18next": "13.0.2",
|
||||
"react-nice-dates": "3.1.0",
|
||||
"react-number-format": "4.9.2",
|
||||
"react-responsive-pagination": "^2.1.0",
|
||||
"react-tsparticles": "2.2.4",
|
||||
"react-window": "1.8.7",
|
||||
"recharts": "2.5.0",
|
||||
"tsparticles": "2.2.4",
|
||||
"walktour": "5.1.1",
|
||||
"webpack-node-externals": "3.0.0",
|
||||
"zustand": "4.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -91,6 +84,7 @@
|
|||
"@lavamoat/preinstall-always-fail": "^1.0.0",
|
||||
"@types/big.js": "6.1.6",
|
||||
"@types/js-cookie": "3.0.3",
|
||||
"@types/lodash": "4.14.185",
|
||||
"@types/node": "17.0.23",
|
||||
"@types/react": "18.0.3",
|
||||
"@types/react-dom": "18.0.0",
|
||||
|
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 36 KiB |
|
@ -23,6 +23,7 @@
|
|||
"custom": "Custom",
|
||||
"dark": "Dark",
|
||||
"display": "Display",
|
||||
"error-account-size-full": "Account size is full",
|
||||
"error-alphanumeric-only": "Alphanumeric characters only",
|
||||
"error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}",
|
||||
"error-key-in-use": "Hot key already in use. Choose a unique key",
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"custom": "Custom",
|
||||
"dark": "Dark",
|
||||
"display": "Display",
|
||||
"error-account-size-full": "Account size is full",
|
||||
"error-alphanumeric-only": "Alphanumeric characters only",
|
||||
"error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}",
|
||||
"error-key-in-use": "Hot key already in use. Choose a unique key",
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"custom": "Custom",
|
||||
"dark": "Dark",
|
||||
"display": "Display",
|
||||
"error-account-size-full": "Account size is full",
|
||||
"error-alphanumeric-only": "Alphanumeric characters only",
|
||||
"error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}",
|
||||
"error-key-in-use": "Hot key already in use. Choose a unique key",
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"custom": "自定",
|
||||
"dark": "暗",
|
||||
"display": "显示",
|
||||
"error-account-size-full": "Account size is full",
|
||||
"error-alphanumeric-only": "Alphanumeric characters only",
|
||||
"error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}",
|
||||
"error-key-in-use": "Hot key already in use. Choose a unique key",
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"custom": "自定",
|
||||
"dark": "暗",
|
||||
"display": "顯示",
|
||||
"error-account-size-full": "Account size is full",
|
||||
"error-alphanumeric-only": "Alphanumeric characters only",
|
||||
"error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}",
|
||||
"error-key-in-use": "Hot key already in use. Choose a unique key",
|
||||
|
|
|
@ -250,7 +250,7 @@ export type MangoStore = {
|
|||
limit?: number,
|
||||
) => Promise<void>
|
||||
fetchGroup: () => Promise<void>
|
||||
reloadMangoAccount: () => Promise<void>
|
||||
reloadMangoAccount: (slot?: number) => Promise<void>
|
||||
fetchMangoAccounts: (ownerPk: PublicKey) => Promise<void>
|
||||
fetchNfts: (connection: Connection, walletPk: PublicKey) => void
|
||||
fetchOpenOrders: (refetchMangoAccount?: boolean) => Promise<void>
|
||||
|
@ -571,20 +571,24 @@ const mangoStore = create<MangoStore>()(
|
|||
}
|
||||
}
|
||||
},
|
||||
reloadMangoAccount: async () => {
|
||||
reloadMangoAccount: async (confirmationSlot) => {
|
||||
const set = get().set
|
||||
const actions = get().actions
|
||||
try {
|
||||
const group = get().group
|
||||
const client = get().client
|
||||
const mangoAccount = get().mangoAccount.current
|
||||
const lastSlot = get().mangoAccount.lastSlot
|
||||
if (!group) throw new Error('Group not loaded')
|
||||
if (!mangoAccount)
|
||||
throw new Error('No mango account exists for reload')
|
||||
|
||||
const { value: reloadedMangoAccount, slot } =
|
||||
await mangoAccount.reloadWithSlot(client)
|
||||
const lastSlot = get().mangoAccount.lastSlot
|
||||
if (
|
||||
!confirmationSlot ||
|
||||
(confirmationSlot && slot > confirmationSlot)
|
||||
) {
|
||||
if (slot > lastSlot) {
|
||||
const ma = get().mangoAccounts.find((ma) =>
|
||||
ma.publicKey.equals(reloadedMangoAccount.publicKey),
|
||||
|
@ -597,6 +601,9 @@ const mangoStore = create<MangoStore>()(
|
|||
state.mangoAccount.lastSlot = slot
|
||||
})
|
||||
}
|
||||
} else if (confirmationSlot && slot < confirmationSlot) {
|
||||
actions.reloadMangoAccount(confirmationSlot)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error reloading mango acct', e)
|
||||
actions.reloadMangoAccount()
|
||||
|
|
|
@ -127,7 +127,7 @@ export async function castVote(
|
|||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
type: 'success',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
noSound: true,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ export async function relinquishVote(
|
|||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
type: 'success',
|
||||
txid: tx,
|
||||
txid: tx.signature,
|
||||
noSound: true,
|
||||
})
|
||||
}
|
||||
|
|