Merge branch 'main' into kierangillen/wallet-updates
This commit is contained in:
commit
587949e9e8
|
@ -359,101 +359,107 @@ const BalancesTable = ({
|
||||||
</TrHead>
|
</TrHead>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{items.map((balance, index) => (
|
{items.map((balance, index) => {
|
||||||
<TrBody key={`${balance.symbol}${index}`}>
|
console.log('balance', balance)
|
||||||
<Td>
|
if (!balance) {
|
||||||
<div className="flex items-center">
|
return null
|
||||||
<img
|
}
|
||||||
alt=""
|
return (
|
||||||
width="20"
|
<TrBody key={`${balance.symbol}${index}`}>
|
||||||
height="20"
|
|
||||||
src={`/assets/icons/${balance.symbol.toLowerCase()}.svg`}
|
|
||||||
className={`mr-2.5`}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{balance.symbol === 'USDC' ||
|
|
||||||
decodeURIComponent(asPath).includes(
|
|
||||||
`${balance.symbol}/USDC`
|
|
||||||
) ? (
|
|
||||||
<span>{balance.symbol}</span>
|
|
||||||
) : (
|
|
||||||
<Link
|
|
||||||
href={{
|
|
||||||
pathname: '/',
|
|
||||||
query: { name: `${balance.symbol}/USDC` },
|
|
||||||
}}
|
|
||||||
shallow={true}
|
|
||||||
>
|
|
||||||
<a className="text-th-fgd-1 underline hover:text-th-fgd-1 hover:no-underline">
|
|
||||||
{balance.symbol}
|
|
||||||
</a>
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Td>
|
|
||||||
<Td>{balance.deposits.toFormat(balance.decimals)}</Td>
|
|
||||||
<Td>{balance.borrows.toFormat(balance.decimals)}</Td>
|
|
||||||
<Td>{balance.orders}</Td>
|
|
||||||
<Td>{balance.unsettled}</Td>
|
|
||||||
<Td>
|
|
||||||
{marketConfig.kind === 'spot' &&
|
|
||||||
marketConfig.name.includes(balance.symbol) &&
|
|
||||||
selectedMarket &&
|
|
||||||
clickToPopulateTradeForm ? (
|
|
||||||
<span
|
|
||||||
className={
|
|
||||||
balance.net.toNumber() != 0
|
|
||||||
? 'cursor-pointer underline hover:no-underline'
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
onClick={() =>
|
|
||||||
handleSizeClick(balance.net, balance.symbol)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{balance.net.toFormat(balance.decimals)}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
balance.net.toFormat(balance.decimals)
|
|
||||||
)}
|
|
||||||
</Td>
|
|
||||||
<Td>{formatUsdValue(balance.value.toNumber())}</Td>
|
|
||||||
<Td>
|
|
||||||
<span className="text-th-green">
|
|
||||||
{balance.depositRate.toFixed(2)}%
|
|
||||||
</span>
|
|
||||||
</Td>
|
|
||||||
<Td>
|
|
||||||
<span className="text-th-red">
|
|
||||||
{balance.borrowRate.toFixed(2)}%
|
|
||||||
</span>
|
|
||||||
</Td>
|
|
||||||
{showDepositWithdraw ? (
|
|
||||||
<Td>
|
<Td>
|
||||||
<div className="flex justify-end">
|
<div className="flex items-center">
|
||||||
<Button
|
<img
|
||||||
className="h-7 pt-0 pb-0 pl-3 pr-3 text-xs"
|
alt=""
|
||||||
onClick={() =>
|
width="20"
|
||||||
handleOpenDepositModal(balance.symbol)
|
height="20"
|
||||||
}
|
src={`/assets/icons/${balance.symbol.toLowerCase()}.svg`}
|
||||||
>
|
className={`mr-2.5`}
|
||||||
{balance.borrows.toNumber() > 0
|
/>
|
||||||
? t('repay')
|
|
||||||
: t('deposit')}
|
{balance.symbol === 'USDC' ||
|
||||||
</Button>
|
decodeURIComponent(asPath).includes(
|
||||||
<Button
|
`${balance.symbol}/USDC`
|
||||||
className="ml-4 h-7 pt-0 pb-0 pl-3 pr-3 text-xs"
|
) ? (
|
||||||
onClick={() =>
|
<span>{balance.symbol}</span>
|
||||||
handleOpenWithdrawModal(balance.symbol)
|
) : (
|
||||||
}
|
<Link
|
||||||
disabled={!canWithdraw}
|
href={{
|
||||||
>
|
pathname: '/',
|
||||||
{t('withdraw')}
|
query: { name: `${balance.symbol}/USDC` },
|
||||||
</Button>
|
}}
|
||||||
|
shallow={true}
|
||||||
|
>
|
||||||
|
<a className="text-th-fgd-1 underline hover:text-th-fgd-1 hover:no-underline">
|
||||||
|
{balance.symbol}
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Td>
|
</Td>
|
||||||
) : null}
|
<Td>{balance.deposits.toFormat(balance.decimals)}</Td>
|
||||||
</TrBody>
|
<Td>{balance.borrows.toFormat(balance.decimals)}</Td>
|
||||||
))}
|
<Td>{balance.orders}</Td>
|
||||||
|
<Td>{balance.unsettled}</Td>
|
||||||
|
<Td>
|
||||||
|
{marketConfig.kind === 'spot' &&
|
||||||
|
marketConfig.name.includes(balance.symbol) &&
|
||||||
|
selectedMarket &&
|
||||||
|
clickToPopulateTradeForm ? (
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
balance.net.toNumber() != 0
|
||||||
|
? 'cursor-pointer underline hover:no-underline'
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
handleSizeClick(balance.net, balance.symbol)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{balance.net.toFormat(balance.decimals)}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
balance.net.toFormat(balance.decimals)
|
||||||
|
)}
|
||||||
|
</Td>
|
||||||
|
<Td>{formatUsdValue(balance.value.toNumber())}</Td>
|
||||||
|
<Td>
|
||||||
|
<span className="text-th-green">
|
||||||
|
{balance.depositRate.toFixed(2)}%
|
||||||
|
</span>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<span className="text-th-red">
|
||||||
|
{balance.borrowRate.toFixed(2)}%
|
||||||
|
</span>
|
||||||
|
</Td>
|
||||||
|
{showDepositWithdraw ? (
|
||||||
|
<Td>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Button
|
||||||
|
className="h-7 pt-0 pb-0 pl-3 pr-3 text-xs"
|
||||||
|
onClick={() =>
|
||||||
|
handleOpenDepositModal(balance.symbol)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{balance.borrows.toNumber() > 0
|
||||||
|
? t('repay')
|
||||||
|
: t('deposit')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className="ml-4 h-7 pt-0 pb-0 pl-3 pr-3 text-xs"
|
||||||
|
onClick={() =>
|
||||||
|
handleOpenWithdrawModal(balance.symbol)
|
||||||
|
}
|
||||||
|
disabled={!canWithdraw}
|
||||||
|
>
|
||||||
|
{t('withdraw')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
) : null}
|
||||||
|
</TrBody>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
{showDepositModal && (
|
{showDepositModal && (
|
||||||
<DepositModal
|
<DepositModal
|
||||||
|
|
|
@ -38,6 +38,12 @@ const MarketNavItem: FunctionComponent<MarketNavItemProps> = ({
|
||||||
mangoGroupConfig,
|
mangoGroupConfig,
|
||||||
market.baseSymbol
|
market.baseSymbol
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The following if statement is for markets not on devnet
|
||||||
|
if (!mangoGroup.spotMarkets[marketIndex]) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
const ws = getWeights(mangoGroup, marketIndex, 'Init')
|
const ws = getWeights(mangoGroup, marketIndex, 'Init')
|
||||||
const w = market.name.includes('PERP')
|
const w = market.name.includes('PERP')
|
||||||
? ws.perpAssetWeight
|
? ws.perpAssetWeight
|
||||||
|
@ -85,7 +91,7 @@ const MarketNavItem: FunctionComponent<MarketNavItemProps> = ({
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</button>
|
</button>
|
||||||
<div className="ml-2">
|
<div className="ml-1">
|
||||||
<FavoriteMarketButton market={market} />
|
<FavoriteMarketButton market={market} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -22,6 +22,50 @@ import { useTranslation } from 'next-i18next'
|
||||||
import useMangoAccount from '../hooks/useMangoAccount'
|
import useMangoAccount from '../hooks/useMangoAccount'
|
||||||
import { useWallet, Wallet } from '@solana/wallet-adapter-react'
|
import { useWallet, Wallet } from '@solana/wallet-adapter-react'
|
||||||
|
|
||||||
|
export const settlePosPnl = async (
|
||||||
|
perpMarkets: PerpMarket[],
|
||||||
|
perpAccount: PerpAccount,
|
||||||
|
t,
|
||||||
|
mangoAccounts: MangoAccount[] | undefined
|
||||||
|
) => {
|
||||||
|
const mangoAccount = useMangoStore.getState().selectedMangoAccount.current
|
||||||
|
const mangoGroup = useMangoStore.getState().selectedMangoGroup.current
|
||||||
|
const mangoCache = useMangoStore.getState().selectedMangoGroup.cache
|
||||||
|
const wallet = useMangoStore.getState().wallet.current
|
||||||
|
const actions = useMangoStore.getState().actions
|
||||||
|
const mangoClient = useMangoStore.getState().connection.client
|
||||||
|
|
||||||
|
try {
|
||||||
|
const txids = await mangoClient.settlePosPnl(
|
||||||
|
mangoGroup,
|
||||||
|
mangoCache,
|
||||||
|
mangoAccount,
|
||||||
|
perpMarkets,
|
||||||
|
mangoGroup.rootBankAccounts[QUOTE_INDEX],
|
||||||
|
wallet,
|
||||||
|
mangoAccounts
|
||||||
|
)
|
||||||
|
actions.reloadMangoAccount()
|
||||||
|
for (const txid of txids) {
|
||||||
|
if (txid) {
|
||||||
|
notify({
|
||||||
|
title: t('pnl-success'),
|
||||||
|
description: '',
|
||||||
|
txid,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error settling PNL: ', `${e}`, `${perpAccount}`)
|
||||||
|
notify({
|
||||||
|
title: t('pnl-error'),
|
||||||
|
description: e.message,
|
||||||
|
txid: e.txid,
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const settlePnl = async (
|
export const settlePnl = async (
|
||||||
perpMarket: PerpMarket,
|
perpMarket: PerpMarket,
|
||||||
perpAccount: PerpAccount,
|
perpAccount: PerpAccount,
|
||||||
|
|
|
@ -278,9 +278,7 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
<Td>
|
<Td>
|
||||||
{funding1h ? (
|
{funding1h ? (
|
||||||
<>
|
<>
|
||||||
<span>{`${funding1h.toLocaleString(undefined, {
|
<span>{`${funding1h.toFixed(4)}%`}</span>{' '}
|
||||||
maximumSignificantDigits: 3,
|
|
||||||
})}%`}</span>{' '}
|
|
||||||
<span className="text-xs text-th-fgd-3">{`(${fundingApr}% APR)`}</span>
|
<span className="text-xs text-th-fgd-3">{`(${fundingApr}% APR)`}</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
import { ChevronDownIcon } from '@heroicons/react/solid'
|
||||||
|
import React, { Fragment, useState } from 'react'
|
||||||
|
import { settlePnl, settlePosPnl } from 'components/MarketPosition'
|
||||||
|
import Button from 'components/Button'
|
||||||
|
import { Transition } from '@headlessui/react'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
import Loading from 'components/Loading'
|
||||||
|
import useMangoStore from 'stores/useMangoStore'
|
||||||
|
|
||||||
|
const MenuButton: React.FC<{
|
||||||
|
onClick: () => void
|
||||||
|
text: string
|
||||||
|
disabled?: boolean
|
||||||
|
}> = ({ onClick, text, disabled }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`default-transition flex items-center justify-end whitespace-nowrap pb-2.5 text-xs tracking-wider hover:cursor-pointer hover:text-th-primary ${
|
||||||
|
disabled ? 'pointer-events-none text-th-fgd-4' : 'text-th-fgd-1'
|
||||||
|
}`}
|
||||||
|
onClick={disabled ? null : onClick}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RedeemDropdown: React.FC = () => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
const { reloadMangoAccount } = useMangoStore((s) => s.actions)
|
||||||
|
const [settling, setSettling] = useState(false)
|
||||||
|
const [settlingPosPnl, setSettlingPosPnl] = useState(false)
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const unsettledPositions =
|
||||||
|
useMangoStore.getState().selectedMangoAccount.unsettledPerpPositions
|
||||||
|
const unsettledPositivePositions = useMangoStore
|
||||||
|
.getState()
|
||||||
|
.selectedMangoAccount.unsettledPerpPositions?.filter(
|
||||||
|
(p) => p.unsettledPnl > 0
|
||||||
|
)
|
||||||
|
|
||||||
|
const loading = settling || settlingPosPnl
|
||||||
|
|
||||||
|
const handleSettleAll = async () => {
|
||||||
|
setOpen(false)
|
||||||
|
setSettling(true)
|
||||||
|
for (const p of unsettledPositions) {
|
||||||
|
await settlePnl(p.perpMarket, p.perpAccount, t, undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadMangoAccount()
|
||||||
|
setSettling(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSettlePosPnl = async () => {
|
||||||
|
setOpen(false)
|
||||||
|
setSettlingPosPnl(true)
|
||||||
|
for (const p of unsettledPositivePositions) {
|
||||||
|
console.log('settlePosPnl', p)
|
||||||
|
await settlePosPnl([p.perpMarket], p.perpAccount, t, null)
|
||||||
|
}
|
||||||
|
setSettlingPosPnl(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttons = [
|
||||||
|
{ onClick: handleSettleAll, disabled: false, text: t('redeem-all') },
|
||||||
|
{
|
||||||
|
onClick: handleSettlePosPnl,
|
||||||
|
disabled: !unsettledPositivePositions?.length,
|
||||||
|
text: t('redeem-positive'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="relative"
|
||||||
|
onMouseOver={() => setOpen(true)}
|
||||||
|
onMouseOut={() => setOpen(false)}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className="flex h-8 w-full items-center justify-center rounded-full bg-th-bkg-button pt-0 pb-0 pl-3 pr-2 text-xs font-bold hover:brightness-[1.1] hover:filter sm:w-auto"
|
||||||
|
disabled={!unsettledPositions?.length}
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<Loading />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{t('redeem-pnl')}
|
||||||
|
<ChevronDownIcon
|
||||||
|
className={`default-transition h-5 w-5 ${
|
||||||
|
open ? 'rotate-180 transform' : 'rotate-360 transform'
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
<Transition
|
||||||
|
appear={true}
|
||||||
|
show={open}
|
||||||
|
as={Fragment}
|
||||||
|
enter="transition-all ease-in duration-200"
|
||||||
|
enterFrom="opacity-0 transform scale-75"
|
||||||
|
enterTo="opacity-100 transform scale-100"
|
||||||
|
leave="transition ease-out duration-200"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="absolute right-0 rounded-md bg-th-bkg-3 px-4 pt-2.5">
|
||||||
|
{buttons.map((b) => {
|
||||||
|
return (
|
||||||
|
<MenuButton
|
||||||
|
key={b.text}
|
||||||
|
onClick={b.onClick}
|
||||||
|
text={b.text}
|
||||||
|
disabled={b.disabled}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './RedeemDropdown'
|
|
@ -5,7 +5,7 @@ import { useTranslation } from 'next-i18next'
|
||||||
import { ExclamationIcon } from '@heroicons/react/outline'
|
import { ExclamationIcon } from '@heroicons/react/outline'
|
||||||
|
|
||||||
import useMangoStore from '../stores/useMangoStore'
|
import useMangoStore from '../stores/useMangoStore'
|
||||||
import Button, { LinkButton } from '../components/Button'
|
import { LinkButton } from '../components/Button'
|
||||||
import { useViewport } from '../hooks/useViewport'
|
import { useViewport } from '../hooks/useViewport'
|
||||||
import { breakpoints } from './TradePageGrid'
|
import { breakpoints } from './TradePageGrid'
|
||||||
import { ExpandableRow, Table, Td, Th, TrBody, TrHead } from './TableElements'
|
import { ExpandableRow, Table, Td, Th, TrBody, TrHead } from './TableElements'
|
||||||
|
@ -17,11 +17,10 @@ import PnlText from './PnlText'
|
||||||
import { settlePnl } from './MarketPosition'
|
import { settlePnl } from './MarketPosition'
|
||||||
import MobileTableHeader from './mobile/MobileTableHeader'
|
import MobileTableHeader from './mobile/MobileTableHeader'
|
||||||
import { useWallet } from '@solana/wallet-adapter-react'
|
import { useWallet } from '@solana/wallet-adapter-react'
|
||||||
|
import { RedeemDropdown } from 'components/PerpPositions'
|
||||||
|
|
||||||
const PositionsTable: React.FC = () => {
|
const PositionsTable: React.FC = () => {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
const { reloadMangoAccount } = useMangoStore((s) => s.actions)
|
|
||||||
const [settling, setSettling] = useState(false)
|
|
||||||
const [settleSinglePos, setSettleSinglePos] = useState(null)
|
const [settleSinglePos, setSettleSinglePos] = useState(null)
|
||||||
const { wallet } = useWallet()
|
const { wallet } = useWallet()
|
||||||
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
|
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
|
||||||
|
@ -54,16 +53,6 @@ const PositionsTable: React.FC = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSettleAll = async () => {
|
|
||||||
setSettling(true)
|
|
||||||
for (const p of unsettledPositions) {
|
|
||||||
await settlePnl(p.perpMarket, p.perpAccount, t, undefined, wallet)
|
|
||||||
}
|
|
||||||
|
|
||||||
reloadMangoAccount()
|
|
||||||
setSettling(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSettlePnl = async (perpMarket, perpAccount, index) => {
|
const handleSettlePnl = async (perpMarket, perpAccount, index) => {
|
||||||
setSettleSinglePos(index)
|
setSettleSinglePos(index)
|
||||||
await settlePnl(perpMarket, perpAccount, t, undefined, wallet)
|
await settlePnl(perpMarket, perpAccount, t, undefined, wallet)
|
||||||
|
@ -80,12 +69,7 @@ const PositionsTable: React.FC = () => {
|
||||||
<h3>{t('unsettled-positions')}</h3>
|
<h3>{t('unsettled-positions')}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<RedeemDropdown />
|
||||||
className="h-8 whitespace-nowrap pt-0 pb-0 pl-3 pr-3 text-xs"
|
|
||||||
onClick={handleSettleAll}
|
|
||||||
>
|
|
||||||
{settling ? <Loading /> : t('redeem-all')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-flow-row grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
|
<div className="grid grid-flow-row grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||||
{unsettledPositions.map((p, index) => {
|
{unsettledPositions.map((p, index) => {
|
||||||
|
|
|
@ -23,22 +23,14 @@ import usePagination from '../hooks/usePagination'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import useMangoStore from '../stores/useMangoStore'
|
import useMangoStore from '../stores/useMangoStore'
|
||||||
|
|
||||||
const renderTradeDateTime = (timestamp: BN | string) => {
|
const formatTradeDateTime = (timestamp: BN | string) => {
|
||||||
let date
|
|
||||||
// don't compare to BN because of npm maddness
|
// don't compare to BN because of npm maddness
|
||||||
// prototypes can be different due to multiple versions being imported
|
// prototypes can be different due to multiple versions being imported
|
||||||
if (typeof timestamp === 'string') {
|
if (typeof timestamp === 'string') {
|
||||||
date = new Date(timestamp)
|
return timestamp
|
||||||
} else {
|
} else {
|
||||||
date = new Date(timestamp.toNumber() * 1000)
|
return (timestamp.toNumber() * 1000).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div>{date.toLocaleDateString()}</div>
|
|
||||||
<div className="text-xs text-th-fgd-3">{date.toLocaleTimeString()}</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const TradeHistoryTable = ({ numTrades }: { numTrades?: number }) => {
|
const TradeHistoryTable = ({ numTrades }: { numTrades?: number }) => {
|
||||||
|
@ -280,7 +272,9 @@ const TradeHistoryTable = ({ numTrades }: { numTrades?: number }) => {
|
||||||
<Td className="!py-2">
|
<Td className="!py-2">
|
||||||
{trade.loadTimestamp || trade.timestamp ? (
|
{trade.loadTimestamp || trade.timestamp ? (
|
||||||
<TableDateDisplay
|
<TableDateDisplay
|
||||||
date={trade.loadTimestamp || trade.timestamp}
|
date={formatTradeDateTime(
|
||||||
|
trade.loadTimestamp || trade.timestamp
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
t('recent')
|
t('recent')
|
||||||
|
@ -333,11 +327,15 @@ const TradeHistoryTable = ({ numTrades }: { numTrades?: number }) => {
|
||||||
<>
|
<>
|
||||||
<div className="text-fgd-1 flex w-full items-center justify-between">
|
<div className="text-fgd-1 flex w-full items-center justify-between">
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
{trade.loadTimestamp || trade.timestamp
|
{trade.loadTimestamp || trade.timestamp ? (
|
||||||
? renderTradeDateTime(
|
<TableDateDisplay
|
||||||
|
date={formatTradeDateTime(
|
||||||
trade.loadTimestamp || trade.timestamp
|
trade.loadTimestamp || trade.timestamp
|
||||||
)
|
)}
|
||||||
: t('recent')}
|
/>
|
||||||
|
) : (
|
||||||
|
t('recent')
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
|
|
|
@ -240,14 +240,14 @@ export const FavoriteMarketButton = ({ market }) => {
|
||||||
|
|
||||||
return favoriteMarkets.find((mkt) => mkt.name === market.name) ? (
|
return favoriteMarkets.find((mkt) => mkt.name === market.name) ? (
|
||||||
<button
|
<button
|
||||||
className="default-transition text-th-primary hover:text-th-fgd-3"
|
className="default-transition flex items-center justify-center text-th-primary hover:text-th-fgd-3"
|
||||||
onClick={() => removeFromFavorites(market)}
|
onClick={() => removeFromFavorites(market)}
|
||||||
>
|
>
|
||||||
<FilledStarIcon className="h-5 w-5" />
|
<FilledStarIcon className="h-5 w-5" />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
className="default-transition text-th-fgd-4 hover:text-th-primary"
|
className="default-transition flex items-center justify-center text-th-fgd-4 hover:text-th-primary"
|
||||||
onClick={() => addToFavorites(market)}
|
onClick={() => addToFavorites(market)}
|
||||||
>
|
>
|
||||||
<StarIcon className="h-5 w-5" />
|
<StarIcon className="h-5 w-5" />
|
||||||
|
|
|
@ -91,8 +91,7 @@ const usePerpPositions = () => {
|
||||||
const mangoGroup = useMangoStore(mangoGroupSelector)
|
const mangoGroup = useMangoStore(mangoGroupSelector)
|
||||||
const mangoCache = useMangoStore(mangoCacheSelector)
|
const mangoCache = useMangoStore(mangoCacheSelector)
|
||||||
const allMarkets = useMangoStore(marketsSelector)
|
const allMarkets = useMangoStore(marketsSelector)
|
||||||
const tradeHistory = useMangoStore.getState().tradeHistory.parsed
|
const tradeHistory = useMangoStore((s) => s.tradeHistory.parsed)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
mangoAccount &&
|
mangoAccount &&
|
||||||
|
|
|
@ -300,6 +300,7 @@
|
||||||
"redeem-all": "Redeem All",
|
"redeem-all": "Redeem All",
|
||||||
"redeem-failure": "Error redeeming MNGO",
|
"redeem-failure": "Error redeeming MNGO",
|
||||||
"redeem-pnl": "Redeem",
|
"redeem-pnl": "Redeem",
|
||||||
|
"redeem-positive": "Redeem positive",
|
||||||
"redeem-success": "Successfully redeemed MNGO",
|
"redeem-success": "Successfully redeemed MNGO",
|
||||||
"referrals": "Referrals",
|
"referrals": "Referrals",
|
||||||
"refresh": "Refresh",
|
"refresh": "Refresh",
|
||||||
|
|
Loading…
Reference in New Issue