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