mango-v4-ui/components/account/HistoryTabs.tsx

225 lines
7.6 KiB
TypeScript
Raw Normal View History

2023-02-03 00:27:54 -08:00
import { useEffect, useState } from 'react'
import SwapHistoryTable from '../swap/SwapHistoryTable'
import TradeHistory from '@components/trade/TradeHistory'
import mangoStore from '@store/mangoStore'
import useMangoAccount from 'hooks/useMangoAccount'
2023-04-20 03:55:52 -07:00
import ActivityFeedTable, {
getCreditAndDebit,
getFee,
getValue,
} from './ActivityFeedTable'
import { handleExport } from 'utils/export'
import { LinkButton } from '@components/shared/Button'
import Loading from '@components/shared/Loading'
import { ArrowDownTrayIcon } from '@heroicons/react/20/solid'
import {
countLeadingZeros,
floorToDecimal,
formatCurrencyValue,
formatNumericValue,
} from 'utils/numbers'
import { formatTokenSymbol } from 'utils/tokens'
import { fetchTradeHistory, parseApiTradeHistory } from 'hooks/useTradeHistory'
import { PublicKey } from '@solana/web3.js'
import { PerpMarket } from '@blockworks-foundation/mango-v4'
import useUnownedAccount from 'hooks/useUnownedAccount'
2023-04-26 19:33:03 -07:00
import SecondaryTabBar from '@components/shared/SecondaryTabBar'
2023-04-28 20:21:54 -07:00
import ActivityFilters from './ActivityFilters'
import { useTranslation } from 'react-i18next'
2023-02-03 00:27:54 -08:00
2023-02-08 02:47:31 -08:00
const TABS = ['activity:activity-feed', 'activity:swaps', 'activity:trades']
2023-02-03 00:27:54 -08:00
const HistoryTabs = () => {
2023-04-20 03:55:52 -07:00
const { t } = useTranslation(['common', 'account', 'activity', 'trade'])
2023-04-28 20:21:54 -07:00
const [activeTab, setActiveTab] = useState<string>('activity:activity-feed')
2023-02-03 00:27:54 -08:00
const actions = mangoStore((s) => s.actions)
const { mangoAccountAddress } = useMangoAccount()
2023-04-20 03:55:52 -07:00
const { isUnownedAccount } = useUnownedAccount()
const [loadExportData, setLoadExportData] = useState(false)
2023-02-03 00:27:54 -08:00
useEffect(() => {
if (actions && mangoAccountAddress) {
actions.fetchActivityFeed(mangoAccountAddress)
}
}, [actions, mangoAccountAddress])
2023-04-20 03:55:52 -07:00
const exportActivityDataToCSV = async () => {
setLoadExportData(true)
await actions.fetchActivityFeed(mangoAccountAddress, 0, '', 10000)
const activityFeed = mangoStore.getState().activityFeed.feed
const dataToExport = activityFeed.map((row) => {
const { activity_type, block_datetime } = row
const { signature } = row.activity_details
const amounts = getCreditAndDebit(row, mangoAccountAddress)
const value = getValue(row, mangoAccountAddress)
const fee = getFee(row, mangoAccountAddress)
const timestamp = new Date(block_datetime)
return {
date: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`,
activity: t(`activity:${activity_type}`),
credit: `${amounts.credit.value} ${amounts.credit.symbol}`,
debit: `${amounts.debit.value} ${amounts.debit.symbol}`,
fee: `${fee.value} ${fee.symbol}`,
value: value.toFixed(3),
signature,
}
})
const title = `${mangoAccountAddress}-Activity-${new Date().toLocaleDateString()}`
handleExport(dataToExport, title)
setLoadExportData(false)
}
const exportSwapsDataToCSV = async () => {
setLoadExportData(true)
await actions.fetchSwapHistory(mangoAccountAddress, 0, 0, 10000)
const swapHistory = mangoStore.getState().mangoAccount.swapHistory.data
const dataToExport = swapHistory.map((row) => {
const {
block_datetime,
signature,
swap_in_amount,
swap_in_loan_origination_fee,
swap_in_symbol,
swap_out_amount,
loan,
loan_origination_fee,
swap_out_price_usd,
swap_out_symbol,
} = row
const borrowAmount =
loan > 0 ? `${floorToDecimal(loan, countLeadingZeros(loan) + 2)}` : 0
const borrowFee =
swap_in_loan_origination_fee > 0
? swap_in_loan_origination_fee.toFixed(4)
: loan_origination_fee > 0
? loan_origination_fee.toFixed(4)
: 0
const inSymbol = formatTokenSymbol(swap_in_symbol)
const outSymbol = formatTokenSymbol(swap_out_symbol)
const inDecimals = countLeadingZeros(swap_in_amount) + 2
const outDecimals = countLeadingZeros(swap_out_amount) + 2
const timestamp = new Date(block_datetime)
return {
date: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`,
paid: `${formatNumericValue(swap_in_amount, inDecimals)} ${inSymbol}`,
received: `${formatNumericValue(
swap_out_amount,
2023-07-21 11:47:53 -07:00
outDecimals,
2023-04-20 03:55:52 -07:00
)} ${outSymbol}`,
value: formatCurrencyValue(swap_out_price_usd * swap_out_amount),
borrow: `${borrowAmount} ${inSymbol}`,
['borrow fee']: `${borrowFee} ${inSymbol}`,
signature,
}
})
const title = `${mangoAccountAddress}-Swaps-${new Date().toLocaleDateString()}`
handleExport(dataToExport, title)
setLoadExportData(false)
}
const exportTradesDataToCSV = async () => {
setLoadExportData(true)
const group = mangoStore.getState().group
if (!group) return
const tradeHistory = await fetchTradeHistory(mangoAccountAddress, 0, 10000)
const dataToExport = tradeHistory.map((row) => {
const trade = parseApiTradeHistory(mangoAccountAddress, row)
const timestamp = new Date(trade.block_datetime)
let market
if ('market' in trade) {
market = group.getSerum3MarketByExternalMarket(
2023-07-21 11:47:53 -07:00
new PublicKey(trade.market),
2023-04-20 03:55:52 -07:00
)
} else if ('perp_market' in trade) {
market = group.getPerpMarketByMarketIndex(trade.market_index)
}
const { side, price, size, feeCost, liquidity, signature } = trade
return {
date: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`,
market: market?.name,
side:
market instanceof PerpMarket
? side === 'buy'
? t('trade:long')
: t('trade:short')
: t(side),
size: size,
price: price,
value: (price * size).toFixed(2),
fee: formatNumericValue(feeCost),
type: liquidity,
signature,
}
})
const title = `${mangoAccountAddress}-Trades-${new Date().toLocaleDateString()}`
handleExport(dataToExport, title)
setLoadExportData(false)
}
2023-04-28 20:21:54 -07:00
const handleExportData = (dataType: string) => {
2023-04-20 03:55:52 -07:00
if (dataType === 'activity:activity-feed') {
exportActivityDataToCSV()
} else if (dataType === 'activity:swaps') {
exportSwapsDataToCSV()
} else {
exportTradesDataToCSV()
}
}
2023-02-03 00:27:54 -08:00
return (
<>
2023-04-28 20:21:54 -07:00
<div className="relative">
<SecondaryTabBar
activeTab={activeTab}
setActiveTab={setActiveTab}
tabs={TABS}
/>
2023-05-09 03:15:56 -07:00
<div className="flex w-full items-center justify-end border-b border-th-bkg-3 py-3 pr-4 sm:-mt-14 sm:h-14 sm:border-b-0 sm:py-0 md:pr-6">
2023-04-20 03:55:52 -07:00
{!isUnownedAccount ? (
<LinkButton
className="flex items-center font-normal no-underline"
disabled={loadExportData}
onClick={() => handleExportData(activeTab)}
>
<span className="mr-2">
{t('account:export', { dataType: t(activeTab) })}
</span>
{loadExportData ? (
<Loading />
) : (
<ArrowDownTrayIcon className="h-5 w-5" />
)}
</LinkButton>
) : null}
{activeTab === 'activity:activity-feed' ? <ActivityFilters /> : null}
</div>
2023-02-03 00:27:54 -08:00
</div>
<TabContent activeTab={activeTab} />
</>
)
}
const TabContent = ({ activeTab }: { activeTab: string }) => {
switch (activeTab) {
2023-02-08 02:47:31 -08:00
case 'activity:activity-feed':
return <ActivityFeedTable />
2023-02-03 00:27:54 -08:00
case 'activity:swaps':
return <SwapHistoryTable />
case 'activity:trades':
return <TradeHistory />
default:
return <ActivityFeedTable />
2023-02-03 00:27:54 -08:00
}
}
export default HistoryTabs