Merge branch 'main' into saml33/follow-accounts

This commit is contained in:
saml33 2023-11-10 21:39:15 +11:00
commit ed1485d44a
22 changed files with 324 additions and 112 deletions

View File

@ -7,7 +7,7 @@ const RpcPing = ({ rpcPing }: { rpcPing: number }) => {
<div>
<div className="flex items-center">
<StatusDot
status={rpcPing}
status={rpcPing ? rpcPing : 1000}
alert={rpcAlertThreshold}
warning={rpcWarningThreshold}
/>

View File

@ -43,13 +43,7 @@ export const StatusDot = ({
} else return status > threshold
}
const dotColor = isLessThan
? greaterOrLessThan(status, alert)
? 'bg-th-warning'
: greaterOrLessThan(status, warning)
? 'bg-th-error'
: 'bg-th-success'
: greaterOrLessThan(status, warning)
const dotColor = greaterOrLessThan(status, warning)
? 'bg-th-error'
: greaterOrLessThan(status, alert)
? 'bg-th-warning'

View File

@ -1,12 +1,11 @@
import TabsText from '@components/shared/TabsText'
import SwapOrders from '@components/swap/SwapTriggerOrders'
import OpenOrders from '@components/trade/OpenOrders'
import mangoStore from '@store/mangoStore'
import useMangoAccount from 'hooks/useMangoAccount'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
const AccountOrders = () => {
const { t } = useTranslation('trade')
const { mangoAccount } = useMangoAccount()
const openOrders = mangoStore((s) => s.mangoAccount.openOrders)
const [activeTab, setActiveTab] = useState('trade:limit')
@ -24,21 +23,12 @@ const AccountOrders = () => {
return (
<>
<div className="flex space-x-6 px-4 py-4 md:px-6">
{tabsWithCount.map((tab) => (
<button
className={`flex items-center space-x-2 text-base font-bold focus:outline-none ${
activeTab === tab[0] ? 'text-th-active' : ''
}`}
onClick={() => setActiveTab(tab[0])}
key={tab[0]}
>
<span>{t(tab[0])}</span>
<div className="rounded-md bg-th-bkg-3 px-1.5 py-0.5 font-body text-xs font-medium text-th-fgd-2">
<span>{tab[1]}</span>
</div>
</button>
))}
<div className="px-4 py-4 md:px-6">
<TabsText
activeTab={activeTab}
onChange={setActiveTab}
tabs={tabsWithCount}
/>
</div>
<div className="flex flex-1 flex-col border-t border-th-bkg-3">
{activeTab === 'trade:limit' ? <OpenOrders /> : <SwapOrders />}

View File

@ -16,6 +16,7 @@ import { COLORS } from 'styles/colors'
import useThemeWrapper from 'hooks/useThemeWrapper'
import dayjs from 'dayjs'
import TokenReduceOnlyDesc from '@components/shared/TokenReduceOnlyDesc'
import CollateralWeightDisplay from '@components/shared/CollateralWeightDisplay'
const SpotCards = ({ tokens }: { tokens: BankWithMarketData[] }) => {
const { t } = useTranslation(['common', 'explore', 'trade'])
@ -37,7 +38,6 @@ const SpotCards = ({ tokens }: { tokens: BankWithMarketData[] }) => {
).mul(bank.uiPrice)
const depositRate = bank.getDepositRateUi()
const borrowRate = bank.getBorrowRateUi()
const assetWeight = bank.scaledInitAssetWeight(bank.price).toFixed(2)
const pastPrice = token.market?.marketData?.price_24h
const volume = token.market?.marketData?.quote_volume_24h || 0
const change =
@ -132,7 +132,9 @@ const SpotCards = ({ tokens }: { tokens: BankWithMarketData[] }) => {
{t('explore:collateral-weight')}
</p>
</Tooltip>
<span className="font-mono text-th-fgd-2">{assetWeight}x</span>
<span className="font-mono text-th-fgd-2">
<CollateralWeightDisplay bank={bank} />
</span>
</div>
<div>
<Tooltip

View File

@ -34,6 +34,7 @@ import dayjs from 'dayjs'
import TableTokenName from '@components/shared/TableTokenName'
import { LinkButton } from '@components/shared/Button'
import { formatTokenSymbol } from 'utils/tokens'
import CollateralWeightDisplay from '@components/shared/CollateralWeightDisplay'
type TableData = {
assetWeight: string
@ -231,7 +232,6 @@ const SpotTable = ({ tokens }: { tokens: BankWithMarketData[] }) => {
{tableData.map((data) => {
const {
available,
assetWeight,
baseBank,
borrowRate,
change,
@ -327,7 +327,11 @@ const SpotTable = ({ tokens }: { tokens: BankWithMarketData[] }) => {
/>
</div>
</Td>
<Td className="text-right font-mono">{assetWeight}x</Td>
<Td className="font-mono">
<div className="flex justify-end">
<CollateralWeightDisplay bank={baseBank} />
</div>
</Td>
<Td>
<div className="flex justify-end space-x-1.5">
<p className="text-th-up">
@ -375,7 +379,6 @@ const MobileSpotItem = ({ data }: { data: TableData }) => {
const {
available,
assetWeight,
baseBank,
borrowRate,
change,
@ -468,7 +471,9 @@ const MobileSpotItem = ({ data }: { data: TableData }) => {
<p className="text-xs text-th-fgd-3">
{t('explore:collateral-weight')}
</p>
<p className="font-mono text-th-fgd-2">{assetWeight}x</p>
<div className="font-mono text-th-fgd-2">
<CollateralWeightDisplay bank={baseBank} />
</div>
</div>
<div className="col-span-1">
<p className="text-xs text-th-fgd-3">{t('rates')}</p>

View File

@ -9,40 +9,92 @@ import { useMemo, useState } from 'react'
import { EmptyObject } from 'types'
import { MANGO_DATA_API_URL } from 'utils/constants'
import LeaderboardTable from './LeaderboardTable'
import TabsText from '@components/shared/TabsText'
export interface LeaderboardRes {
date_hour: string
mango_account: string
pnl: number
profile_image_url: string | null
profile_name: string
start_date_hour: string
trader_category: string
wallet_pk: string
}
type DaysToShow = '1DAY' | '1WEEK' | 'ALLTIME'
export interface PnlLeaderboardRes extends LeaderboardRes {
pnl: number
start_date_hour: string
}
const isLeaderboard = (
response: null | EmptyObject | LeaderboardRes[],
): response is LeaderboardRes[] => {
export interface EquityLeaderboardRes extends LeaderboardRes {
account_equity: number
}
const isPnlLeaderboardRes = (
response: null | EmptyObject | PnlLeaderboardRes[],
): response is PnlLeaderboardRes[] => {
if (response && Array.isArray(response)) {
return true
}
return false
}
const fetchLeaderboard = async (
const isEquityLeaderboardRes = (
response: null | EmptyObject | EquityLeaderboardRes[],
): response is EquityLeaderboardRes[] => {
if (response && Array.isArray(response)) {
return true
}
return false
}
export const isPnlLeaderboard = (
item: PnlLeaderboardRes | EquityLeaderboardRes,
): item is PnlLeaderboardRes => {
if ('pnl' in item) {
return true
}
return false
}
export const isEquityLeaderboard = (
item: PnlLeaderboardRes | EquityLeaderboardRes,
): item is EquityLeaderboardRes => {
if ('account_equity' in item) {
return true
}
return false
}
type DaysToShow = '1DAY' | '1WEEK' | 'ALLTIME'
const fetchPnlLeaderboard = async (
daysToShow: DaysToShow,
offset = 0,
): Promise<Array<LeaderboardRes>> => {
): Promise<Array<PnlLeaderboardRes>> => {
const data = await fetch(
`${MANGO_DATA_API_URL}/leaderboard-pnl?over_period=${daysToShow}&offset=${offset}`,
)
const parsedData: null | EmptyObject | LeaderboardRes[] = await data.json()
const parsedData: null | EmptyObject | PnlLeaderboardRes[] = await data.json()
let leaderboardData
if (isLeaderboard(parsedData)) {
if (isPnlLeaderboardRes(parsedData)) {
leaderboardData = parsedData
}
return leaderboardData ?? []
}
const fetchEquityLeaderboard = async (
offset = 0,
): Promise<Array<EquityLeaderboardRes>> => {
const data = await fetch(
`${MANGO_DATA_API_URL}/leaderboard-account-equity?offset=${offset}`,
)
const parsedData: null | EmptyObject | EquityLeaderboardRes[] =
await data.json()
let leaderboardData
if (isEquityLeaderboardRes(parsedData)) {
leaderboardData = parsedData
}
@ -52,72 +104,135 @@ const fetchLeaderboard = async (
const LeaderboardPage = () => {
const { t } = useTranslation(['common', 'leaderboard'])
const [daysToShow, setDaysToShow] = useState<DaysToShow>('ALLTIME')
const [leaderboardToShow, setLeaderboardToShow] = useState('pnl')
const { hiddenAccounts } = useHiddenMangoAccounts()
const { data, isLoading, isFetching, isFetchingNextPage, fetchNextPage } =
useInfiniteQuery(
['leaderboard', daysToShow],
({ pageParam }) => fetchLeaderboard(daysToShow, pageParam),
{
cacheTime: 1000 * 60 * 10,
staleTime: 1000 * 60 * 5,
retry: 3,
refetchOnWindowFocus: false,
keepPreviousData: true,
getNextPageParam: (_lastPage, pages) => pages.length * 20,
},
)
const {
data: pnlData,
isLoading: loadingPnl,
isFetching: fetchingPnl,
isFetchingNextPage: fetchingNextPnlPage,
fetchNextPage: fetchNextPnlPage,
} = useInfiniteQuery(
['pnl-leaderboard', daysToShow, leaderboardToShow],
({ pageParam }) => fetchPnlLeaderboard(daysToShow, pageParam),
{
cacheTime: 1000 * 60 * 10,
staleTime: 1000 * 60 * 5,
retry: 3,
refetchOnWindowFocus: false,
keepPreviousData: true,
getNextPageParam: (_lastPage, pages) => pages.length * 20,
},
)
const leaderboardData = useMemo(() => {
if (data?.pages.length) {
const {
data: equityData,
isLoading: loadingEquity,
isFetching: fetchingEquity,
isFetchingNextPage: fetchingNextEquityPage,
fetchNextPage: fetchNextEquityPage,
} = useInfiniteQuery(
['equity-leaderboard', leaderboardToShow],
({ pageParam }) => fetchEquityLeaderboard(pageParam),
{
cacheTime: 1000 * 60 * 10,
staleTime: 1000 * 60 * 5,
retry: 3,
refetchOnWindowFocus: false,
keepPreviousData: true,
getNextPageParam: (_lastPage, pages) => pages.length * 20,
},
)
const pnlLeaderboardData = useMemo(() => {
if (pnlData?.pages.length) {
if (hiddenAccounts) {
return data.pages
return pnlData.pages
.flat()
.filter((d) => !hiddenAccounts.includes(d.mango_account))
} else {
return data.pages.flat()
return pnlData.pages.flat()
}
}
return []
}, [data, daysToShow])
}, [pnlData, daysToShow])
const equityLeaderboardData = useMemo(() => {
if (equityData?.pages.length) {
if (hiddenAccounts) {
return equityData.pages
.flat()
.filter((d) => !hiddenAccounts.includes(d.mango_account))
} else {
return equityData.pages.flat()
}
}
return []
}, [equityData])
const leaderboardData = useMemo(() => {
return leaderboardToShow === 'pnl'
? pnlLeaderboardData
: equityLeaderboardData
}, [leaderboardToShow, pnlLeaderboardData, equityLeaderboardData])
const handleDaysToShow = (days: DaysToShow) => {
setDaysToShow(days)
}
const isPnl = leaderboardToShow === 'pnl'
const loading = isPnl ? loadingPnl : loadingEquity
const fetching = isPnl ? fetchingPnl : fetchingEquity
const fetchingNextPage = isPnl ? fetchingNextPnlPage : fetchingNextEquityPage
const fetchNextPage = isPnl ? fetchNextPnlPage : fetchNextEquityPage
return (
<div className="p-4 md:p-10 lg:px-0">
<div className="grid grid-cols-12">
<div className="col-span-12 lg:col-span-8 lg:col-start-3">
<div className="mb-6 flex flex-col md:flex-row md:items-center md:justify-between">
<h1 className="mb-2">{t('leaderboard')}</h1>
<div className="mb-4 flex items-center justify-between">
<div>
<h1 className="mb-2">{t('leaderboard')}</h1>
<p className="mb-4 md:mb-0">
{t('leaderboard:leaderboard-desc')}
<TabsText
activeTab={leaderboardToShow}
onChange={(v: string) => setLeaderboardToShow(v)}
tabs={[
['pnl', 0],
['equity', 0],
]}
/>
<p className="mt-1">
{isPnl
? t('leaderboard:leaderboard-desc-pnl')
: t('leaderboard:leaderboard-desc-equity')}
</p>
</div>
<div className="w-full md:w-48">
<ButtonGroup
activeValue={daysToShow}
disabled={isLoading}
onChange={(v) => handleDaysToShow(v)}
names={['24h', '7d', '30d', t('all')]}
values={['1DAY', '1WEEK', 'ALLTIME']}
/>
</div>
{isPnl ? (
<div className="w-full md:w-48">
<ButtonGroup
activeValue={daysToShow}
disabled={loadingPnl}
onChange={(v) => handleDaysToShow(v)}
names={['24h', '7d', '30d', t('all')]}
values={['1DAY', '1WEEK', 'ALLTIME']}
/>
</div>
) : null}
</div>
{leaderboardData.length ? (
<LeaderboardTable
data={leaderboardData}
loading={isFetching && !isFetchingNextPage}
loading={fetching && !fetchingNextPage}
type={leaderboardToShow}
/>
) : !isFetching && !isLoading ? (
) : !fetching && !loading ? (
<div className="flex flex-col items-center rounded-md border border-th-bkg-3 p-4">
<NoSymbolIcon className="mb-1 h-7 w-7 text-th-fgd-4" />
<p>{t('leaderboard:leaderboard-unavailable')}</p>
</div>
) : null}
{isLoading || isFetchingNextPage ? (
{loading || fetchingNextPage ? (
<div className="mt-2 space-y-2">
{[...Array(20)].map((x, i) => (
<SheenLoader className="flex flex-1" key={i}>

View File

@ -4,14 +4,21 @@ import SheenLoader from '@components/shared/SheenLoader'
import { ChevronRightIcon } from '@heroicons/react/20/solid'
import { useViewport } from 'hooks/useViewport'
import { formatCurrencyValue } from 'utils/numbers'
import { LeaderboardRes } from './LeaderboardPage'
import {
EquityLeaderboardRes,
PnlLeaderboardRes,
isEquityLeaderboard,
isPnlLeaderboard,
} from './LeaderboardPage'
const LeaderboardTable = ({
data,
loading,
type,
}: {
data: LeaderboardRes[]
data: PnlLeaderboardRes[] | EquityLeaderboardRes[]
loading: boolean
type: string
}) => {
return (
<>
@ -21,7 +28,8 @@ const LeaderboardTable = ({
item={d}
loading={loading}
rank={i + 1}
key={d.mango_account + d.pnl + i}
key={d.mango_account + i}
type={type}
/>
))}
</div>
@ -35,13 +43,20 @@ const LeaderboardRow = ({
item,
loading,
rank,
type,
}: {
item: LeaderboardRes
item: PnlLeaderboardRes | EquityLeaderboardRes
loading?: boolean
rank: number
type: string
}) => {
const { profile_name, profile_image_url, mango_account, pnl, wallet_pk } =
item
const { profile_name, profile_image_url, mango_account, wallet_pk } = item
const value =
type === 'pnl' && isPnlLeaderboard(item)
? item.pnl
: isEquityLeaderboard(item)
? item.account_equity
: 0
const { isTablet } = useViewport()
return !loading ? (
@ -83,7 +98,7 @@ const LeaderboardRow = ({
</div>
<div className="flex items-center">
<span className="mr-3 text-right font-mono md:text-base">
{formatCurrencyValue(pnl, 2)}
{formatCurrencyValue(value, 2)}
</span>
<ChevronRightIcon className="h-5 w-5 text-th-fgd-3" />
</div>

View File

@ -30,6 +30,7 @@ import Tooltip from '@components/shared/Tooltip'
import { abbreviateAddress } from 'utils/formatting'
import { handleCopyAddress } from '@components/account/AccountActions'
import useUnownedAccount from 'hooks/useUnownedAccount'
import { floorToDecimal, numberCompacter } from 'utils/numbers'
const MangoAccountsListModal = ({
isOpen,
@ -116,9 +117,10 @@ const MangoAccountsListModal = ({
) {
acc = mangoAccount
}
const accountValue = toUiDecimalsForQuote(
Number(acc.getEquity(group!)),
).toFixed(2)
const accountValue = floorToDecimal(
toUiDecimalsForQuote(Number(acc.getEquity(group!))),
2,
)
const maintHealth = acc.getHealthRatioUi(
group!,
HealthType.maint,
@ -172,9 +174,9 @@ const MangoAccountsListModal = ({
</div>
</div>
</div>
<div className="flex">
<span className="text-sm text-th-fgd-2">
${accountValue}
<div className="flex font-mono">
<span className="text-th-fgd-2">
${numberCompacter.format(accountValue.toNumber())}
</span>
<span className="mx-2 text-th-fgd-4">|</span>
<div
@ -189,7 +191,7 @@ const MangoAccountsListModal = ({
}`}
>
<HeartIcon className="mr-1 h-4 w-4 flex-shrink-0" />
<span className="text-sm">{maintHealth}%</span>
<span>{maintHealth}%</span>
</div>
</div>
</div>

View File

@ -0,0 +1,41 @@
import { Bank } from '@blockworks-foundation/mango-v4'
import { InformationCircleIcon } from '@heroicons/react/20/solid'
import { useMemo } from 'react'
import Tooltip from './Tooltip'
import { useTranslation } from 'react-i18next'
import { floorToDecimal } from 'utils/numbers'
const CollateralWeightDisplay = ({ bank }: { bank: Bank }) => {
const { t } = useTranslation('common')
const [scaled, init, isScaled] = useMemo(() => {
if (!bank) return [0, 0, false]
const scaled = floorToDecimal(
bank.scaledInitAssetWeight(bank.price).toNumber(),
2,
).toNumber()
const init = floorToDecimal(bank.initAssetWeight.toNumber(), 2).toNumber()
const isScaled = scaled < init
return [scaled, init, isScaled]
}, [bank])
return (
<Tooltip
content={
isScaled
? t('tooltip-scaled-collateral-weight', {
token: bank?.name,
init: init.toFixed(2),
})
: ''
}
>
<div className={`flex items-center ${isScaled ? 'cursor-help' : ''}`}>
<span>{scaled.toFixed(2)}x</span>
{isScaled ? (
<InformationCircleIcon className="ml-1 h-3.5 w-3.5 text-th-fgd-4" />
) : null}
</div>
</Tooltip>
)
}
export default CollateralWeightDisplay

View File

@ -0,0 +1,35 @@
import { useTranslation } from 'react-i18next'
const TabsText = ({
tabs,
activeTab,
onChange,
}: {
tabs: [string, number][]
activeTab: string
onChange: (tab: string) => void
}) => {
const { t } = useTranslation(['common', 'trade'])
return (
<div className="flex space-x-6">
{tabs.map((tab) => (
<button
className={`flex items-center space-x-2 text-base font-bold focus:outline-none ${
activeTab === tab[0] ? 'text-th-active' : ''
}`}
onClick={() => onChange(tab[0])}
key={tab[0]}
>
<span>{t(tab[0])}</span>
{tab[1] ? (
<div className="rounded-md bg-th-bkg-3 px-1.5 py-0.5 font-body text-xs font-medium text-th-fgd-2">
<span>{tab[1]}</span>
</div>
) : null}
</button>
))}
</div>
)
}
export default TabsText

View File

@ -27,6 +27,7 @@ import { LinkButton } from '@components/shared/Button'
import { useCallback } from 'react'
import { useSortableData } from 'hooks/useSortableData'
import TableTokenName from '@components/shared/TableTokenName'
import CollateralWeightDisplay from '@components/shared/CollateralWeightDisplay'
const TokenDetailsTable = () => {
const { t } = useTranslation(['common', 'activity', 'token', 'trade'])
@ -173,7 +174,6 @@ const TokenDetailsTable = () => {
{tableData.map((data) => {
const {
bank,
initAssetWeight,
initLiabWeight,
isInsured,
liquidationFee,
@ -193,10 +193,10 @@ const TokenDetailsTable = () => {
<TableTokenName bank={bank} symbol={symbol} />
</Td>
<Td>
<div className="flex justify-end space-x-1.5 text-right">
<p>{initAssetWeight.toFixed(2)}</p>
<div className="flex justify-end space-x-1.5 text-right font-mono">
<CollateralWeightDisplay bank={bank} />
<span className="text-th-fgd-4">|</span>
<p>{initLiabWeight.toFixed(2)}</p>
<p>{initLiabWeight.toFixed(2)}x</p>
</div>
</Td>
<Td>
@ -278,18 +278,15 @@ const TokenDetailsTable = () => {
{t('asset-liability-weight')}
</p>
</Tooltip>
<div className="flex space-x-1.5 text-right font-mono">
<p className="text-th-fgd-1">
{bank
.scaledInitAssetWeight(bank.price)
.toFixed(2)}
</p>
<div className="flex space-x-1.5 text-right font-mono text-th-fgd-1">
<CollateralWeightDisplay bank={bank} />
<span className="text-th-fgd-4">|</span>
<p className="text-th-fgd-1">
<span>
{bank
.scaledInitLiabWeight(bank.price)
.toFixed(2)}
</p>
x
</span>
</div>
</div>
<div className="col-span-1">

View File

@ -12,6 +12,7 @@ import { getOracleProvider } from 'hooks/useOracleProvider'
import { useTranslation } from 'next-i18next'
import { useMemo } from 'react'
import { formatCurrencyValue } from 'utils/numbers'
import CollateralWeightDisplay from '@components/shared/CollateralWeightDisplay'
const TokenParams = ({ bank }: { bank: Bank }) => {
const { t } = useTranslation(['common', 'activity', 'token'])
@ -40,12 +41,12 @@ const TokenParams = ({ bank }: { bank: Bank }) => {
</p>
</Tooltip>
<div className="flex space-x-2">
<p className="font-mono text-th-fgd-2">
{bank.scaledInitAssetWeight(bank.price).toFixed(2)}
</p>
<div className="font-mono text-th-fgd-2">
<CollateralWeightDisplay bank={bank} />
</div>
<span className="text-th-fgd-4">|</span>
<p className="font-mono text-th-fgd-2">
{bank.scaledInitLiabWeight(bank.price).toFixed(2)}
{bank.scaledInitLiabWeight(bank.price).toFixed(2)}x
</p>
</div>
</div>
@ -57,11 +58,11 @@ const TokenParams = ({ bank }: { bank: Bank }) => {
</Tooltip>
<div className="flex space-x-2">
<p className="font-mono text-th-fgd-2">
{bank.maintAssetWeight.toFixed(2)}
{bank.maintAssetWeight.toFixed(2)}x
</p>
<span className="text-th-fgd-4">|</span>
<p className="font-mono text-th-fgd-2">
{bank.maintLiabWeight.toFixed(2)}
{bank.maintLiabWeight.toFixed(2)}x
</p>
</div>
</div>

View File

@ -79,6 +79,7 @@
"edit-account": "Edit Account Name",
"edit-profile-image": "Edit Profile Image",
"enable-notifications": "Enable Notifications",
"equity": "Equity",
"error-borrow-exceeds-limit": "Maximum borrow for the current period is {{remaining}}. New period starts {{resetTime}}",
"error-repay-insufficient-funds": "Not enough {{token}} in your wallet to repay this amount",
"error-token-positions-full": "Not enough token positions available in your account",
@ -177,6 +178,7 @@
"tooltip-collateral-value": "The USD amount you can trade or borrow against",
"tooltip-collateral-weight": "The multiplier applied to the notional value of {{token}} collateral",
"tooltip-interest-rates": "The interest rates for depositing (green/left) and borrowing (red/right)",
"tooltip-scaled-collateral-weight": "Collateral weight is currently scaled down due to the value of {{token}} deposits being above the threshold. The default weight for {{token}} is {{init}}x. If deposits are withdrawn the collateral weight will increase. This is a safety precaution to prevent positions that could be difficult to liquidate. It does not affect the health of your account.",
"total": "Total",
"total-borrows": "Total Borrows",
"total-borrow-value": "Total Borrow Value",

View File

@ -1,4 +1,5 @@
{
"leaderboard-desc": "Top 100 Mango traders by total PnL (spot and perp)",
"leaderboard-desc-equity": "Top 100 Mango traders by account equity",
"leaderboard-desc-pnl": "Top 100 Mango traders by total PnL (spot and perp)",
"leaderboard-unavailable": "Leaderboard unavailable"
}

View File

@ -79,6 +79,7 @@
"edit-account": "Edit Account Name",
"edit-profile-image": "Edit Profile Image",
"enable-notifications": "Enable Notifications",
"equity": "Equity",
"error-borrow-exceeds-limit": "Maximum borrow for the current period is {{remaining}}. New period starts {{resetTime}}",
"error-repay-insufficient-funds": "Not enough {{token}} in your wallet to repay this amount",
"error-token-positions-full": "Not enough token positions available in your account",
@ -177,6 +178,7 @@
"tooltip-collateral-value": "The USD amount you can trade or borrow against",
"tooltip-collateral-weight": "The multiplier applied to the notional value of {{token}} collateral",
"tooltip-interest-rates": "The interest rates for depositing (green/left) and borrowing (red/right)",
"tooltip-scaled-collateral-weight": "Collateral weight is currently scaled down due to the value of {{token}} deposits being above the threshold. The default weight for {{token}} is {{init}}x. If deposits are withdrawn the collateral weight will increase. This is a safety precaution to prevent positions that could be difficult to liquidate. It does not affect the health of your account.",
"total": "Total",
"total-borrows": "Total Borrows",
"total-borrow-value": "Total Borrow Value",

View File

@ -1,4 +1,5 @@
{
"leaderboard-desc": "Top 100 Mango traders by total PnL (spot and perp)",
"leaderboard-desc-equity": "Top 100 Mango traders by account equity",
"leaderboard-desc-pnl": "Top 100 Mango traders by total PnL (spot and perp)",
"leaderboard-unavailable": "Leaderboard unavailable"
}

View File

@ -79,6 +79,7 @@
"edit-account": "Edit Account Name",
"edit-profile-image": "Edit Profile Image",
"enable-notifications": "Enable Notifications",
"equity": "Equity",
"error-borrow-exceeds-limit": "Maximum borrow for the current period is {{remaining}}. New period starts {{resetTime}}",
"error-repay-insufficient-funds": "Not enough {{token}} in your wallet to repay this amount",
"error-token-positions-full": "Not enough token positions available in your account",
@ -177,6 +178,7 @@
"tooltip-collateral-value": "The USD amount you can trade or borrow against",
"tooltip-collateral-weight": "The multiplier applied to the notional value of {{token}} collateral",
"tooltip-interest-rates": "The interest rates for depositing (green/left) and borrowing (red/right)",
"tooltip-scaled-collateral-weight": "Collateral weight is currently scaled down due to the value of {{token}} deposits being above the threshold. The default weight for {{token}} is {{init}}x. If deposits are withdrawn the collateral weight will increase. This is a safety precaution to prevent positions that could be difficult to liquidate. It does not affect the health of your account.",
"total": "Total",
"total-borrows": "Total Borrows",
"total-borrow-value": "Total Borrow Value",

View File

@ -1,4 +1,5 @@
{
"leaderboard-desc": "Top 100 Mango traders by total PnL (spot and perp)",
"leaderboard-desc-equity": "Top 100 Mango traders by account equity",
"leaderboard-desc-pnl": "Top 100 Mango traders by total PnL (spot and perp)",
"leaderboard-unavailable": "Leaderboard unavailable"
}

View File

@ -79,6 +79,7 @@
"edit-account": "编辑帐户标签",
"edit-profile-image": "切换头像",
"enable-notifications": "开启通知",
"equity": "Equity",
"error-borrow-exceeds-limit": "目前期间的最大借贷为{{remaining}}.新期间从{{resetTime}}开始",
"error-repay-insufficient-funds": "钱包里的{{token}}不足归还",
"error-token-positions-full": "你帐户的币位已占满",
@ -176,6 +177,7 @@
"tooltip-collateral-value": "您可以交易或借入的美元金额",
"tooltip-collateral-weight": "适用于 {{token}} 抵押品名义价值的乘数",
"tooltip-interest-rates": "存款利率(绿/左)和借贷利率(红/右)",
"tooltip-scaled-collateral-weight": "Collateral weight is currently scaled down due to the value of {{token}} deposits being above the threshold. The default weight for {{token}} is {{init}}x. If deposits are withdrawn the collateral weight will increase. This is a safety precaution to prevent positions that could be difficult to liquidate. It does not affect the health of your account.",
"total": "总计",
"total-borrow-value": "总借贷价值",
"total-borrows": "总借贷",

View File

@ -1,4 +1,5 @@
{
"leaderboard-desc": "按总盈亏现货和永续合约计算的前100名Mango交易商",
"leaderboard-desc-equity": "Top 100 Mango traders by account equity",
"leaderboard-desc-pnl": "按总盈亏现货和永续合约计算的前100名Mango交易商",
"leaderboard-unavailable": "无法显示排行榜"
}

View File

@ -79,6 +79,7 @@
"edit-account": "編輯帳戶標籤",
"edit-profile-image": "切換頭像",
"enable-notifications": "開啟通知",
"equity": "Equity",
"error-borrow-exceeds-limit": "目前期間的最大借貸為{{remaining}}.新期間從{{resetTime}}開始",
"error-repay-insufficient-funds": "錢包裡的{{token}}不足歸還",
"error-token-positions-full": "你帳戶的幣位已占滿",
@ -176,6 +177,7 @@
"tooltip-collateral-value": "您可以交易或借入的美元金額",
"tooltip-collateral-weight": "適用於 {{token}} 抵押品名義價值的乘數",
"tooltip-interest-rates": "存款利率(綠/左)和借貸利率(紅/右)",
"tooltip-scaled-collateral-weight": "Collateral weight is currently scaled down due to the value of {{token}} deposits being above the threshold. The default weight for {{token}} is {{init}}x. If deposits are withdrawn the collateral weight will increase. This is a safety precaution to prevent positions that could be difficult to liquidate. It does not affect the health of your account.",
"total": "總計",
"total-borrow-value": "總借貸價值",
"total-borrows": "總借貸",

View File

@ -1,4 +1,5 @@
{
"leaderboard-desc": "按總盈虧現貨和永續合約計算的前100名Mango交易商",
"leaderboard-desc-equity": "Top 100 Mango traders by account equity",
"leaderboard-desc-pnl": "按總盈虧現貨和永續合約計算的前100名Mango交易商",
"leaderboard-unavailable": "無法顯示排行榜"
}