add mobile table

This commit is contained in:
saml33 2022-09-28 23:04:58 +10:00
parent b6513b70d1
commit 50aa9afc0c
12 changed files with 372 additions and 126 deletions

View File

@ -23,7 +23,7 @@ const AccountTabs = () => {
<TabButtons <TabButtons
activeValue={activeTab} activeValue={activeTab}
onChange={(v) => setActiveTab(v)} onChange={(v) => setActiveTab(v)}
values={['balances', 'activity', 'swap:swap-history']} values={['balances', 'activity:activity', 'swap:swap-history']}
showBorders showBorders
/> />
<TabContent activeTab={activeTab} /> <TabContent activeTab={activeTab} />
@ -37,7 +37,7 @@ const TabContent = ({ activeTab }: { activeTab: string }) => {
switch (activeTab) { switch (activeTab) {
case 'balances': case 'balances':
return <TokenList /> return <TokenList />
case 'activity': case 'activity:activity':
return <ActivityFeed /> return <ActivityFeed />
case 'swap:swap-history': case 'swap:swap-history':
return <SwapHistoryTable swapHistory={swapHistory} loading={loading} /> return <SwapHistoryTable swapHistory={swapHistory} loading={loading} />

View File

@ -1,9 +1,6 @@
import { IconButton } from '@components/shared/Button' import { IconButton } from '@components/shared/Button'
import { ArrowLeftIcon } from '@heroicons/react/20/solid' import { ArrowLeftIcon } from '@heroicons/react/20/solid'
import mangoStore, { import mangoStore, { LiquidationFeedItem } from '@store/mangoStore'
DepositWithdrawFeedItem,
LiquidationFeedItem,
} from '@store/mangoStore'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import useLocalStorageState from 'hooks/useLocalStorageState' import useLocalStorageState from 'hooks/useLocalStorageState'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
@ -45,8 +42,7 @@ const ActivityDetails = ({
activity: LiquidationFeedItem activity: LiquidationFeedItem
setShowActivityDetail: (x: any) => void setShowActivityDetail: (x: any) => void
}) => { }) => {
console.log(activity) const { t } = useTranslation(['common', 'activity', 'settings'])
const { t } = useTranslation(['common', 'activity'])
const [preferredExplorer] = useLocalStorageState( const [preferredExplorer] = useLocalStorageState(
PREFERRED_EXPLORER_KEY, PREFERRED_EXPLORER_KEY,
EXPLORERS[0] EXPLORERS[0]
@ -70,9 +66,9 @@ const ActivityDetails = ({
> >
<ArrowLeftIcon className="h-5 w-5" /> <ArrowLeftIcon className="h-5 w-5" />
</IconButton> </IconButton>
<h2 className="text-lg">Liquidation Details</h2> <h2 className="text-lg">{t('activity:liquidation-details')}</h2>
</div> </div>
<div className="grid grid-cols-3 gap-6 px-6"> <div className="grid grid-cols-1 gap-4 px-6 lg:grid-cols-3">
<div className="col-span-1"> <div className="col-span-1">
<p className="mb-0.5 text-sm">{t('date')}</p> <p className="mb-0.5 text-sm">{t('date')}</p>
<p className="text-th-fgd-1"> <p className="text-th-fgd-1">
@ -84,29 +80,34 @@ const ActivityDetails = ({
</div> </div>
<div className="col-span-1"> <div className="col-span-1">
<p className="mb-0.5 text-sm">{t('activity:asset-liquidated')}</p> <p className="mb-0.5 text-sm">{t('activity:asset-liquidated')}</p>
<p className="text-th-fgd-1"> <p className="font-mono text-th-fgd-1">
{`${formatDecimal( {formatDecimal(asset_amount)}{' '}
asset_amount <span className="font-body tracking-wide">{asset_symbol}</span>
)} ${asset_symbol} at ${formatFixedDecimals(asset_price, true)}`} <span className="ml-2 font-body tracking-wide text-th-fgd-3">
at
</span>{' '}
{formatFixedDecimals(asset_price, true)}
</p> </p>
<p className="text-xs text-th-fgd-3"> <p className="font-mono text-xs text-th-fgd-3">
{formatFixedDecimals(asset_price * asset_amount, true)} {formatFixedDecimals(asset_price * asset_amount, true)}
</p> </p>
</div> </div>
<div className="col-span-1"> <div className="col-span-1">
<p className="mb-0.5 text-sm">{t('activity:asset-returned')}</p> <p className="mb-0.5 text-sm">{t('activity:asset-returned')}</p>
<p className="text-th-fgd-1"> <p className="font-mono text-th-fgd-1">
{`${formatDecimal( {formatDecimal(liab_amount)}{' '}
liab_amount <span className="font-body tracking-wide">{liab_symbol}</span>
)} ${liab_symbol} at ${formatFixedDecimals(liab_price, true)}`} <span className="ml-2 font-body tracking-wide text-th-fgd-3">
at
</span>{' '}
{formatFixedDecimals(liab_price, true)}
</p> </p>
<p className="text-xs text-th-fgd-3"> <p className="font-mono text-xs text-th-fgd-3">
{formatFixedDecimals(liab_price * liab_amount, true)} {formatFixedDecimals(liab_price * liab_amount, true)}
</p> </p>
</div> </div>
</div> </div>
<div className="col-span-3 mt-8 flex justify-center border-y border-th-bkg-3 py-3"> <div className="col-span-3 mt-8 flex justify-center border-y border-th-bkg-3 py-3">
{/* <p className="mb-0.5 text-sm">{t('transaction')}</p> */}
<a <a
className="default-transition flex items-center text-th-fgd-1 hover:text-th-fgd-3" className="default-transition flex items-center text-th-fgd-1 hover:text-th-fgd-3"
href={`${preferredExplorer.url}${signature}`} href={`${preferredExplorer.url}${signature}`}

View File

@ -1,20 +1,24 @@
import { LinkButton } from '@components/shared/Button' import { IconButton, LinkButton } from '@components/shared/Button'
import Tooltip from '@components/shared/Tooltip' import Tooltip from '@components/shared/Tooltip'
import { BoltIcon, ChevronRightIcon, LinkIcon } from '@heroicons/react/20/solid' import { Transition } from '@headlessui/react'
import {
BoltIcon,
ChevronDownIcon,
ChevronRightIcon,
LinkIcon,
} from '@heroicons/react/20/solid'
import { useWallet } from '@solana/wallet-adapter-react' import { useWallet } from '@solana/wallet-adapter-react'
import mangoStore, { import mangoStore, { LiquidationFeedItem } from '@store/mangoStore'
DepositWithdrawFeedItem,
LiquidationFeedItem,
} from '@store/mangoStore'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import useLocalStorageState from 'hooks/useLocalStorageState' import useLocalStorageState from 'hooks/useLocalStorageState'
import { capitalize } from 'lodash' import { useViewport } from 'hooks/useViewport'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import Image from 'next/image' import Image from 'next/image'
import { EXPLORERS } from 'pages/settings' import { EXPLORERS } from 'pages/settings'
import { useCallback, useState } from 'react' import { Fragment, useCallback, useState } from 'react'
import { PREFERRED_EXPLORER_KEY } from 'utils/constants' import { PREFERRED_EXPLORER_KEY } from 'utils/constants'
import { formatDecimal, formatFixedDecimals } from 'utils/numbers' import { formatDecimal, formatFixedDecimals } from 'utils/numbers'
import { breakpoints } from 'utils/theme'
const ActivityFeedTable = ({ const ActivityFeedTable = ({
activityFeed, activityFeed,
@ -25,13 +29,14 @@ const ActivityFeedTable = ({
}) => { }) => {
const { t } = useTranslation(['common', 'activity']) const { t } = useTranslation(['common', 'activity'])
const { connected } = useWallet() const { connected } = useWallet()
// const activityFeed = mangoStore((s) => s.activityFeed.feed)
const actions = mangoStore((s) => s.actions) const actions = mangoStore((s) => s.actions)
const [offset, setOffset] = useState(0) const [offset, setOffset] = useState(0)
const [preferredExplorer] = useLocalStorageState( const [preferredExplorer] = useLocalStorageState(
PREFERRED_EXPLORER_KEY, PREFERRED_EXPLORER_KEY,
EXPLORERS[0] EXPLORERS[0]
) )
const { width } = useViewport()
const showTableView = width ? width > breakpoints.md : false
const handleShowMore = useCallback(() => { const handleShowMore = useCallback(() => {
const mangoAccount = mangoStore.getState().mangoAccount.current const mangoAccount = mangoStore.getState().mangoAccount.current
@ -42,28 +47,31 @@ const ActivityFeedTable = ({
const getCreditAndDebit = (activity: any) => { const getCreditAndDebit = (activity: any) => {
const { activity_type } = activity const { activity_type } = activity
let credit = '0' let credit = { value: '0', symbol: '' }
let debit = '0' let debit = { value: '0', symbol: '' }
if (activity_type === 'liquidate_token_with_token') { if (activity_type === 'liquidate_token_with_token') {
const { side, liab_amount, liab_symbol, asset_amount, asset_symbol } = const { side, liab_amount, liab_symbol, asset_amount, asset_symbol } =
activity.activity_details activity.activity_details
if (side === 'liqee') { if (side === 'liqee') {
credit = `${formatDecimal(liab_amount)} ${liab_symbol}` credit = { value: formatDecimal(liab_amount), symbol: liab_symbol }
debit = `${formatDecimal(asset_amount)} ${asset_symbol}` debit = {
value: formatDecimal(asset_amount * -1),
symbol: asset_symbol,
}
} else { } else {
credit = `${formatDecimal(asset_amount)} ${asset_symbol}` credit = { value: formatDecimal(asset_amount), symbol: asset_symbol }
debit = `${formatDecimal(liab_amount)} ${liab_symbol}` debit = { value: formatDecimal(liab_amount * -1), symbol: liab_symbol }
} }
} }
if (activity_type === 'deposit') { if (activity_type === 'deposit') {
const { symbol, quantity } = activity.activity_details const { symbol, quantity } = activity.activity_details
credit = `${formatDecimal(quantity)} ${symbol}` credit = { value: formatDecimal(quantity), symbol }
debit = '0' debit = { value: '0', symbol: '' }
} }
if (activity_type === 'withdraw') { if (activity_type === 'withdraw') {
const { symbol, quantity } = activity.activity_details const { symbol, quantity } = activity.activity_details
credit = '0' credit = { value: '0', symbol: '' }
debit = `${formatDecimal(quantity)} ${symbol}` debit = { value: formatDecimal(quantity * -1), symbol }
} }
return { credit, debit } return { credit, debit }
} }
@ -82,7 +90,8 @@ const ActivityFeedTable = ({
} }
if (activity_type === 'deposit' || activity_type === 'withdraw') { if (activity_type === 'deposit' || activity_type === 'withdraw') {
const { usd_equivalent } = activity.activity_details const { usd_equivalent } = activity.activity_details
value = usd_equivalent value =
activity_type === 'withdraw' ? usd_equivalent * -1 : usd_equivalent
} }
return value return value
} }
@ -90,92 +99,122 @@ const ActivityFeedTable = ({
return connected ? ( return connected ? (
activityFeed.length ? ( activityFeed.length ? (
<> <>
<table className="min-w-full"> {showTableView ? (
<thead> <table className="min-w-full">
<tr className="sticky top-0 z-10"> <thead>
<th className="bg-th-bkg-1 text-left">{t('date')}</th> <tr className="sticky top-0 z-10">
<th className="bg-th-bkg-1 text-right"> <th className="bg-th-bkg-1 text-left">{t('date')}</th>
{t('activity:activity')} <th className="bg-th-bkg-1 text-right">
</th> {t('activity:activity')}
<th className="bg-th-bkg-1 text-right">{t('activity:credit')}</th> </th>
<th className="bg-th-bkg-1 text-right">{t('activity:debit')}</th> <th className="bg-th-bkg-1 text-right">
<th className="bg-th-bkg-1 text-right"> {t('activity:credit')}
{t('activity:activity-value')} </th>
</th> <th className="bg-th-bkg-1 text-right">
<th className="bg-th-bkg-1 text-right">{t('explorer')}</th> {t('activity:debit')}
</tr> </th>
</thead> <th className="bg-th-bkg-1 text-right">
<tbody> {t('activity:activity-value')}
{activityFeed.map((activity: any, i: number) => { </th>
const { activity_type, block_datetime } = activity <th className="bg-th-bkg-1 text-right">{t('explorer')}</th>
const { signature } = activity.activity_details </tr>
const isLiquidation = </thead>
activity_type === 'liquidate_token_with_token' <tbody>
const activityName = isLiquidation ? 'liquidation' : activity_type {activityFeed.map((activity: any, i: number) => {
const amounts = getCreditAndDebit(activity) const { activity_type, block_datetime } = activity
const value = getValue(activity) const { signature } = activity.activity_details
return ( const isLiquidation =
<tr activity_type === 'liquidate_token_with_token'
key={block_datetime + i} const activityName = isLiquidation
className={`default-transition text-sm hover:bg-th-bkg-2 ${ ? 'liquidation'
isLiquidation ? 'cursor-pointer' : '' : activity_type
}`} const amounts = getCreditAndDebit(activity)
onClick={ const value = getValue(activity)
isLiquidation return (
? () => handleShowActivityDetails(activity) <tr
: undefined key={signature}
} className={`default-transition text-sm hover:bg-th-bkg-2 ${
> isLiquidation ? 'cursor-pointer' : ''
<td> }`}
<p className="font-body tracking-wide"> onClick={
{dayjs(block_datetime).format('ddd D MMM')} isLiquidation
</p> ? () => handleShowActivityDetails(activity)
<p className="text-xs text-th-fgd-3"> : undefined
{dayjs(block_datetime).format('h:mma')} }
</p> >
</td> <td>
<td className="text-right">{capitalize(activityName)}</td> <p className="font-body tracking-wide">
<td className="text-right">{amounts.credit}</td> {dayjs(block_datetime).format('ddd D MMM')}
<td className="text-right">{amounts.debit}</td> </p>
<td className="text-right"> <p className="text-xs text-th-fgd-3">
{formatFixedDecimals(value, true)} {dayjs(block_datetime).format('h:mma')}
</td> </p>
<td> </td>
{activity_type !== 'liquidate_token_with_token' ? ( <td className="text-right">
<div className="flex items-center justify-end"> {t(`activity:${activityName}`)}
<Tooltip </td>
content={`View on ${t( <td className="text-right font-mono">
`settings:${preferredExplorer.name}` {amounts.credit.value}{' '}
)}`} <span className="font-body tracking-wide text-th-fgd-3">
placement="top-end" {amounts.credit.symbol}
> </span>
<a </td>
href={`${preferredExplorer.url}${signature}`} <td className="text-right font-mono">
target="_blank" {amounts.debit.value}{' '}
rel="noopener noreferrer" <span className="font-body tracking-wide text-th-fgd-3">
{amounts.debit.symbol}
</span>
</td>
<td className="text-right font-mono">
{formatFixedDecimals(value, true)}
</td>
<td>
{activity_type !== 'liquidate_token_with_token' ? (
<div className="flex items-center justify-end">
<Tooltip
content={`View on ${t(
`settings:${preferredExplorer.name}`
)}`}
placement="top-end"
> >
<div className="h-6 w-6"> <a
<Image href={`${preferredExplorer.url}${signature}`}
alt="" target="_blank"
width="24" rel="noopener noreferrer"
height="24" >
src={`/explorer-logos/${preferredExplorer.name}.png`} <div className="h-6 w-6">
/> <Image
</div> alt=""
</a> width="24"
</Tooltip> height="24"
</div> src={`/explorer-logos/${preferredExplorer.name}.png`}
) : ( />
<div className="flex items-center justify-end"> </div>
<ChevronRightIcon className="h-6 w-6 text-th-fgd-3" /> </a>
</div> </Tooltip>
)} </div>
</td> ) : (
</tr> <div className="flex items-center justify-end">
) <ChevronRightIcon className="h-6 w-6 text-th-fgd-3" />
})} </div>
</tbody> )}
</table> </td>
</tr>
)
})}
</tbody>
</table>
) : (
<div>
{activityFeed.map((activity: any, i: number) => (
<MobileActivityFeedItem
activity={activity}
getValue={getValue}
key={activity.activity_details.signature}
/>
))}
</div>
)}
{activityFeed.length % 25 === 0 ? ( {activityFeed.length % 25 === 0 ? (
<div className="flex justify-center pt-6"> <div className="flex justify-center pt-6">
<LinkButton onClick={handleShowMore}>Show More</LinkButton> <LinkButton onClick={handleShowMore}>Show More</LinkButton>
@ -197,3 +236,156 @@ const ActivityFeedTable = ({
} }
export default ActivityFeedTable export default ActivityFeedTable
const MobileActivityFeedItem = ({
activity,
getValue,
}: {
activity: any
getValue: (x: any) => number
}) => {
const { t } = useTranslation(['common', 'activity'])
const [expandActivityDetails, setExpandActivityDetails] = useState(false)
const [preferredExplorer] = useLocalStorageState(
PREFERRED_EXPLORER_KEY,
EXPLORERS[0]
)
const { activity_type, block_datetime } = activity
const { signature } = activity.activity_details
const isLiquidation = activity_type === 'liquidate_token_with_token'
const activityName = isLiquidation ? 'liquidation' : activity_type
const value = getValue(activity)
return (
<div key={signature} className="border-b border-th-bkg-3 px-6 py-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-th-fgd-1">
{dayjs(block_datetime).format('ddd D MMM')}
</p>
<p className="text-xs text-th-fgd-3">
{dayjs(block_datetime).format('h:mma')}
</p>
</div>
<div className="flex items-center space-x-4">
<div>
<p className="text-right text-xs">
{t(`activity:${activityName}`)}
</p>
<p className="text-right font-mono text-sm text-th-fgd-1">
{isLiquidation ? (
formatFixedDecimals(value, true)
) : (
<>
<span className="mr-1">
{activity.activity_details.quantity}
</span>
<span className="font-body tracking-wide text-th-fgd-3">
{activity.activity_details.symbol}
</span>
</>
)}
</p>
</div>
{isLiquidation ? (
<IconButton
onClick={() => setExpandActivityDetails((prev) => !prev)}
>
<ChevronDownIcon
className={`${
expandActivityDetails ? 'rotate-180' : 'rotate-360'
} h-6 w-6 flex-shrink-0 text-th-fgd-1`}
/>
</IconButton>
) : (
<a
href={`${preferredExplorer.url}${signature}`}
target="_blank"
rel="noopener noreferrer"
>
<div className="flex h-10 w-10 items-center justify-center">
<Image
alt=""
width="24"
height="24"
src={`/explorer-logos/${preferredExplorer.name}.png`}
/>
</div>
</a>
)}
</div>
</div>
<Transition
appear={true}
show={expandActivityDetails}
as={Fragment}
enter="transition ease-in duration-200"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition ease-out"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="mt-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4">
<div className="col-span-1">
<p className="mb-0.5 text-sm">{t('activity:asset-liquidated')}</p>
<p className="font-mono text-sm text-th-fgd-1">
{formatDecimal(activity.activity_details.asset_amount)}{' '}
<span className="font-body tracking-wide">
{activity.activity_details.asset_symbol}
</span>
<span className="ml-2 font-body tracking-wide text-th-fgd-3">
at
</span>{' '}
{formatFixedDecimals(activity.activity_details.asset_price, true)}
</p>
<p className="font-mono text-xs text-th-fgd-3">
{formatFixedDecimals(
activity.activity_details.asset_price *
activity.activity_details.asset_amount,
true
)}
</p>
</div>
<div className="col-span-1">
<p className="mb-0.5 text-sm">{t('activity:asset-returned')}</p>
<p className="font-mono text-sm text-th-fgd-1">
{formatDecimal(activity.activity_details.liab_amount)}{' '}
<span className="font-body tracking-wide">
{activity.activity_details.liab_symbol}
</span>
<span className="ml-2 font-body tracking-wide text-th-fgd-3">
at
</span>{' '}
{formatFixedDecimals(activity.activity_details.liab_price, true)}
</p>
<p className="font-mono text-xs text-th-fgd-3">
{formatFixedDecimals(
activity.activity_details.liab_price *
activity.activity_details.liab_amount,
true
)}
</p>
</div>
<div className="col-span-2 flex justify-center pt-3">
<a
className="default-transition flex items-center text-sm text-th-fgd-1 hover:text-th-fgd-3"
href={`${preferredExplorer.url}${signature}`}
target="_blank"
rel="noopener noreferrer"
>
<Image
alt=""
width="20"
height="20"
src={`/explorer-logos/${preferredExplorer.name}.png`}
/>
<span className="ml-2 text-base">{`View on ${t(
`settings:${preferredExplorer.name}`
)}`}</span>
</a>
</div>
</div>
</Transition>
</div>
)
}

View File

@ -10,6 +10,7 @@ export async function getStaticProps({ locale }: { locale: string }) {
'close-account', 'close-account',
'profile', 'profile',
'swap', 'swap',
'activity',
])), ])),
}, },
} }

View File

@ -0,0 +1,12 @@
{
"activity": "Activity",
"activity-value": "Activity Value",
"asset-liquidated": "Asset Liquidated",
"asset-returned": "Asset Returned",
"credit": "Credit",
"debit": "Debit",
"deposit": "Deposit",
"liquidation": "Liquidation",
"liquidation-details": "Liquidation Details",
"withdraw": "Withdraw"
}

View File

@ -40,6 +40,7 @@
"disconnect": "Disconnect", "disconnect": "Disconnect",
"edit-account": "Edit Account", "edit-account": "Edit Account",
"edit-profile-image": "Edit Profile Image", "edit-profile-image": "Edit Profile Image",
"explorer": "Explorer",
"fee": "Fee", "fee": "Fee",
"fees": "Fees", "fees": "Fees",
"free-collateral": "Free Collateral", "free-collateral": "Free Collateral",

View File

@ -0,0 +1,12 @@
{
"activity": "Activity",
"activity-value": "Activity Value",
"asset-liquidated": "Asset Liquidated",
"asset-returned": "Asset Returned",
"credit": "Credit",
"debit": "Debit",
"deposit": "Deposit",
"liquidation": "Liquidation",
"liquidation-details": "Liquidation Details",
"withdraw": "Withdraw"
}

View File

@ -40,6 +40,7 @@
"disconnect": "Disconnect", "disconnect": "Disconnect",
"edit-account": "Edit Account", "edit-account": "Edit Account",
"edit-profile-image": "Edit Profile Image", "edit-profile-image": "Edit Profile Image",
"explorer": "Explorer",
"fee": "Fee", "fee": "Fee",
"fees": "Fees", "fees": "Fees",
"free-collateral": "Free Collateral", "free-collateral": "Free Collateral",

View File

@ -0,0 +1,12 @@
{
"activity": "Activity",
"activity-value": "Activity Value",
"asset-liquidated": "Asset Liquidated",
"asset-returned": "Asset Returned",
"credit": "Credit",
"debit": "Debit",
"deposit": "Deposit",
"liquidation": "Liquidation",
"liquidation-details": "Liquidation Details",
"withdraw": "Withdraw"
}

View File

@ -40,6 +40,7 @@
"disconnect": "Disconnect", "disconnect": "Disconnect",
"edit-account": "Edit Account", "edit-account": "Edit Account",
"edit-profile-image": "Edit Profile Image", "edit-profile-image": "Edit Profile Image",
"explorer": "Explorer",
"fee": "Fee", "fee": "Fee",
"fees": "Fees", "fees": "Fees",
"free-collateral": "Free Collateral", "free-collateral": "Free Collateral",

View File

@ -0,0 +1,12 @@
{
"activity": "Activity",
"activity-value": "Activity Value",
"asset-liquidated": "Asset Liquidated",
"asset-returned": "Asset Returned",
"credit": "Credit",
"debit": "Debit",
"deposit": "Deposit",
"liquidation": "Liquidation",
"liquidation-details": "Liquidation Details",
"withdraw": "Withdraw"
}

View File

@ -40,6 +40,7 @@
"disconnect": "Disconnect", "disconnect": "Disconnect",
"edit-account": "Edit Account", "edit-account": "Edit Account",
"edit-profile-image": "Edit Profile Image", "edit-profile-image": "Edit Profile Image",
"explorer": "Explorer",
"fee": "Fee", "fee": "Fee",
"fees": "Fees", "fees": "Fees",
"free-collateral": "Free Collateral", "free-collateral": "Free Collateral",