Compare commits
21 Commits
88d3f5e250
...
6cbe1e601c
Author | SHA1 | Date |
---|---|---|
Adrian Brzeziński | 6cbe1e601c | |
Finn Casey Fierro | 4b54fe33c6 | |
Finn Casey Fierro | 09a4113bd2 | |
Adrian Brzeziński | 59719cc810 | |
Adrian Brzeziński | 3ed3684d40 | |
saml33 | 6215d3bb03 | |
saml33 | 951b3fc796 | |
saml33 | 40670f3cfb | |
saml33 | d8967dcd71 | |
Adrian Brzeziński | 3e30fe0eb1 | |
Adrian Brzeziński | e1f791b5e8 | |
Finn | fb23b86b7c | |
saml33 | bdfd9ff466 | |
Adrian Brzeziński | 3d76a68f7b | |
saml33 | 1dfda6cd2b | |
saml33 | 6d86a6f607 | |
saml33 | 2ae3675bfe | |
saml33 | 5fecc0ad1d | |
saml33 | 017fed46d3 | |
rjpeterson | fe9a27174d | |
rjpeterson | 945ca79bf3 |
|
@ -1,5 +1,6 @@
|
|||
import { Bank, PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
import { LinkButton } from '@components/shared/Button'
|
||||
import ConnectEmptyState from '@components/shared/ConnectEmptyState'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import {
|
||||
|
@ -14,6 +15,8 @@ import {
|
|||
import TokenLogo from '@components/shared/TokenLogo'
|
||||
import MarketLogos from '@components/trade/MarketLogos'
|
||||
import { Disclosure, Transition } from '@headlessui/react'
|
||||
import { NoSymbolIcon } from '@heroicons/react/20/solid'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useInfiniteQuery } from '@tanstack/react-query'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
|
@ -62,6 +65,7 @@ export const fetchMarginFunding = async (
|
|||
const FundingTable = () => {
|
||||
const { t } = useTranslation(['common', 'account'])
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const { connected } = useWallet()
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
|
||||
|
@ -136,7 +140,8 @@ const FundingTable = () => {
|
|||
sortConfig,
|
||||
} = useSortableData(tableData)
|
||||
|
||||
return (
|
||||
return mangoAccountAddress &&
|
||||
(sortedTableData?.length || isLoading || isFetchingNextPage) ? (
|
||||
<>
|
||||
{showTableView ? (
|
||||
<Table>
|
||||
|
@ -194,9 +199,11 @@ const FundingTable = () => {
|
|||
<div className="flex items-center justify-end">
|
||||
{marketOrBank ? (
|
||||
marketOrBank instanceof PerpMarket ? (
|
||||
<MarketLogos market={marketOrBank} />
|
||||
<MarketLogos market={marketOrBank} size="small" />
|
||||
) : (
|
||||
<TokenLogo bank={marketOrBank} />
|
||||
<div className="mr-1.5">
|
||||
<TokenLogo bank={marketOrBank} size={16} />
|
||||
</div>
|
||||
)
|
||||
) : null}
|
||||
<p className="font-body">{asset}</p>
|
||||
|
@ -256,7 +263,9 @@ const FundingTable = () => {
|
|||
marketOrBank instanceof PerpMarket ? (
|
||||
<MarketLogos market={marketOrBank} size="small" />
|
||||
) : (
|
||||
<TokenLogo bank={marketOrBank} size={16} />
|
||||
<div className="mr-1.5">
|
||||
<TokenLogo bank={marketOrBank} size={16} />
|
||||
</div>
|
||||
)
|
||||
) : null}
|
||||
<p className="text-right">{asset}</p>
|
||||
|
@ -324,6 +333,17 @@ const FundingTable = () => {
|
|||
</LinkButton>
|
||||
) : null}
|
||||
</>
|
||||
) : mangoAccountAddress || connected ? (
|
||||
<div className="flex flex-1 flex-col items-center justify-center">
|
||||
<div className="flex flex-col items-center p-8">
|
||||
<NoSymbolIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p>{t('account:no-funding')}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-1 flex-col items-center justify-center p-8">
|
||||
<ConnectEmptyState text={t('account:connect-funding')} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -282,6 +282,7 @@ const SpotTable = ({ tokens }: { tokens: BankWithMarketData[] }) => {
|
|||
<TableTokenName
|
||||
bank={baseBank}
|
||||
symbol={tokenName}
|
||||
showLeverage
|
||||
/>
|
||||
</div>
|
||||
</Td>
|
||||
|
|
|
@ -58,7 +58,7 @@ const CollateralFeeWarningModal = ({ isOpen, onClose }: WarningProps) => {
|
|||
<thead>
|
||||
<TrHead>
|
||||
<Th className="text-left">{t('collateral')}</Th>
|
||||
<Th className="text-right">{t('funding-rate')} (APR)</Th>
|
||||
<Th className="text-right">{t('funding-rate')} Per Day</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">{t('daily-fee')}</div>
|
||||
</Th>
|
||||
|
@ -75,15 +75,12 @@ const CollateralFeeWarningModal = ({ isOpen, onClose }: WarningProps) => {
|
|||
</Td>
|
||||
<Td>
|
||||
<p className="text-right">
|
||||
{(ltvRatio * bank.collateralFeePerDay * 365 * 100).toFixed(
|
||||
2,
|
||||
)}
|
||||
%
|
||||
{(ltvRatio * bank.collateralFeePerDay * 100).toFixed(4)}%
|
||||
</p>
|
||||
</Td>
|
||||
<Td>
|
||||
<div className="flex flex-col items-end">
|
||||
<p>
|
||||
<p className="text-right">
|
||||
<FormatNumericValue value={dailyFee} />
|
||||
</p>
|
||||
<span className="font-mono text-th-fgd-4">
|
||||
|
|
|
@ -260,7 +260,7 @@ const UserSetupModal = ({
|
|||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} fullScreen disableOutsideClose>
|
||||
<div className="grid h-screen overflow-auto bg-th-bkg-1 text-left lg:grid-cols-2">
|
||||
<div className="grid h-screen overflow-hidden bg-th-bkg-1 text-left lg:grid-cols-2">
|
||||
<ColorBlur
|
||||
width="66%"
|
||||
height="300px"
|
||||
|
|
|
@ -33,7 +33,7 @@ function Modal({
|
|||
}, [isOpen])
|
||||
|
||||
const handleClose = () => {
|
||||
if (disableOutsideClose) return
|
||||
if (disableOutsideClose && !fullScreen) return
|
||||
onClose()
|
||||
}
|
||||
|
||||
|
@ -59,10 +59,10 @@ function Modal({
|
|||
themeData.fonts.display.variable
|
||||
} ${
|
||||
themeData.fonts.mono.variable
|
||||
} thin-scroll w-full overflow-auto bg-th-bkg-1 font-body ${
|
||||
} h-full w-full bg-th-bkg-1 font-body ${
|
||||
fullScreen
|
||||
? 'h-full'
|
||||
: 'max-h-[calc(100vh-5%)] p-4 sm:max-w-md sm:rounded-lg sm:border sm:border-th-bkg-3 sm:p-6'
|
||||
? ''
|
||||
: 'thin-scroll max-h-[calc(100vh-48px)] overflow-y-auto p-4 sm:h-auto sm:max-w-md sm:rounded-lg sm:border sm:border-th-bkg-3 sm:p-6'
|
||||
} relative ${panelClassNames}`}
|
||||
>
|
||||
<div>{children}</div>
|
||||
|
|
|
@ -5,28 +5,47 @@ import { useVaultLimits } from '@components/swap/useVaultLimits'
|
|||
import { ExclamationTriangleIcon } from '@heroicons/react/20/solid'
|
||||
import Tooltip from './Tooltip'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { floorToDecimal } from 'utils/numbers'
|
||||
import { LeverageBadge } from '@components/trade/MarketSelectDropdown'
|
||||
|
||||
const TableTokenName = ({ bank, symbol }: { bank: Bank; symbol: string }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const TableTokenName = ({
|
||||
bank,
|
||||
symbol,
|
||||
showLeverage,
|
||||
}: {
|
||||
bank: Bank
|
||||
symbol: string
|
||||
showLeverage?: boolean
|
||||
}) => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const { vaultFull } = useVaultLimits(bank)
|
||||
const weight = bank.scaledInitAssetWeight(bank.price)
|
||||
const leverageFactor = 1 / (1 - weight.toNumber())
|
||||
|
||||
const leverageMax = floorToDecimal(leverageFactor, 1).toNumber()
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex shrink-0 items-center">
|
||||
<TokenLogo bank={bank} showRewardsLogo />
|
||||
</div>
|
||||
<Tooltip
|
||||
content={
|
||||
vaultFull ? t('warning-deposits-full', { token: bank.name }) : ''
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center">
|
||||
<p className="font-body leading-none text-th-fgd-2">{symbol}</p>
|
||||
{showLeverage && leverageMax > 1 && leverageMax < Infinity ? (
|
||||
<div className="ml-1">
|
||||
<Tooltip content={t('trade:max-leverage')}>
|
||||
<LeverageBadge leverage={leverageMax} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
) : null}
|
||||
{vaultFull ? (
|
||||
<ExclamationTriangleIcon className="ml-1 h-4 w-4 text-th-warning" />
|
||||
<Tooltip content={t('warning-deposits-full', { token: bank.name })}>
|
||||
<ExclamationTriangleIcon className="ml-1 h-4 w-4 text-th-warning" />
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</div>
|
||||
<TokenReduceOnlyDesc bank={bank} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -213,7 +213,11 @@ const TokenDetailsTable = () => {
|
|||
onClick={() => goToTokenPage(symbol.split(' ')[0], router)}
|
||||
>
|
||||
<Td>
|
||||
<TableTokenName bank={bank} symbol={symbol} />
|
||||
<TableTokenName
|
||||
bank={bank}
|
||||
symbol={symbol}
|
||||
showLeverage
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<div className="flex justify-end space-x-1.5 text-right font-mono">
|
||||
|
@ -275,7 +279,11 @@ const TokenDetailsTable = () => {
|
|||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<TableTokenName bank={bank} symbol={bank.name} />
|
||||
<TableTokenName
|
||||
bank={bank}
|
||||
symbol={bank.name}
|
||||
showLeverage
|
||||
/>
|
||||
<ChevronDownIcon
|
||||
className={`${
|
||||
open ? 'rotate-180' : 'rotate-0'
|
||||
|
|
|
@ -209,7 +209,11 @@ const TokenOverviewTable = () => {
|
|||
}
|
||||
>
|
||||
<Td>
|
||||
<TableTokenName bank={bank} symbol={symbol} />
|
||||
<TableTokenName
|
||||
bank={bank}
|
||||
symbol={symbol}
|
||||
showLeverage
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<div className="flex flex-col text-right">
|
||||
|
@ -300,7 +304,11 @@ const TokenOverviewTable = () => {
|
|||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<TableTokenName bank={bank} symbol={symbol} />
|
||||
<TableTokenName
|
||||
bank={bank}
|
||||
symbol={symbol}
|
||||
showLeverage
|
||||
/>
|
||||
<ChevronDownIcon
|
||||
className={`${
|
||||
open ? 'rotate-180' : 'rotate-0'
|
||||
|
|
|
@ -58,7 +58,7 @@ const RateCurveChart = ({ bank }: { bank: Bank | undefined }) => {
|
|||
const rateCurveChartData = useMemo(() => {
|
||||
if (!bank) return []
|
||||
const defaults = [
|
||||
{ util: 0, rate: 0 },
|
||||
{ util: 0, rate: bank.loanFeeRate.toNumber() * 100 },
|
||||
{
|
||||
util: bank.util0.toNumber() * 100,
|
||||
rate:
|
||||
|
|
|
@ -524,10 +524,10 @@ const MarketSelectDropdown = () => {
|
|||
|
||||
export default MarketSelectDropdown
|
||||
|
||||
const LeverageBadge = ({ leverage }: { leverage: number }) => {
|
||||
export const LeverageBadge = ({ leverage }: { leverage: number }) => {
|
||||
return (
|
||||
<div className="rounded border border-th-fgd-4 px-1 py-0.5 text-xxs leading-none text-th-fgd-4">
|
||||
<span>{leverage < 1 ? leverage.toFixed(1) : leverage.toFixed()}x</span>
|
||||
<div className="rounded bg-th-bkg-3 px-1 py-0.5 font-mono text-xxs leading-none text-th-fgd-2">
|
||||
<span>{leverage < 2 ? leverage.toFixed(1) : leverage.toFixed()}x</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { COLLATERAL_FEE_KEY } from 'utils/constants'
|
|||
import useBanksWithBalances from './useBanksWithBalances'
|
||||
import useLocalStorageState from './useLocalStorageState'
|
||||
import { useMemo } from 'react'
|
||||
import useMangoAccount from './useMangoAccount'
|
||||
|
||||
const useCollateralFeePopupConditions = () => {
|
||||
const [wasModalOpen, setWasModalOpen] = useLocalStorageState(
|
||||
|
@ -9,7 +10,7 @@ const useCollateralFeePopupConditions = () => {
|
|||
false,
|
||||
)
|
||||
const banks = useBanksWithBalances('balance')
|
||||
//check if there is at least 100$ active margin position and bank has collateral fee active
|
||||
|
||||
const marginPositionBalanceWithBanks = banks.filter(
|
||||
(x) => x.balance < 0 && Math.abs(x.balance) * x.bank.uiPrice >= 100,
|
||||
)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"@blockworks-foundation/mango-feeds": "0.1.7",
|
||||
"@blockworks-foundation/mango-mints-redemption": "^0.0.10",
|
||||
"@blockworks-foundation/mango-v4": "0.24.0",
|
||||
"@blockworks-foundation/mango-v4-settings": "0.14.21",
|
||||
"@blockworks-foundation/mango-v4-settings": "0.14.22",
|
||||
"@blockworks-foundation/mangolana": "0.0.16",
|
||||
"@headlessui/react": "1.6.6",
|
||||
"@heroicons/react": "2.0.18",
|
||||
|
|
|
@ -22,8 +22,8 @@ export default async function handler(
|
|||
`https://public-api.birdeye.so/defi/tokenlist?sort_by=v24hUSD&sort_type=desc&offset=${offset}&limit=50`,
|
||||
options,
|
||||
)
|
||||
const tokenListResponse = await response.json()
|
||||
|
||||
const tokenListResponse = await response.json()
|
||||
const tokenList = tokenListResponse['data']['tokens']
|
||||
const filteredTokens = []
|
||||
|
||||
|
@ -35,7 +35,7 @@ export default async function handler(
|
|||
const nowInSeconds = Math.floor(now.getTime() / 1000)
|
||||
const pastDate = new Date()
|
||||
pastDate.setDate(pastDate.getDate() - 4)
|
||||
pastDate.setMonth(pastDate.getMonth() - 1)
|
||||
pastDate.setMonth(pastDate.getMonth() - 1.5)
|
||||
const pastDateInSeconds = Math.floor(pastDate.getTime() / 1000)
|
||||
|
||||
// Fetch history for the token
|
||||
|
@ -44,7 +44,6 @@ export default async function handler(
|
|||
options,
|
||||
)
|
||||
const historyData = await historyResponse.json()
|
||||
|
||||
if (historyData['data']['items']?.length >= 35) {
|
||||
const detailResponse = await fetch(
|
||||
`https://public-api.birdeye.so/defi/token_overview?address=${address}`,
|
||||
|
@ -61,7 +60,6 @@ export default async function handler(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the filtered list of tokens
|
||||
res.status(200).json(filteredTokens)
|
||||
} catch (error) {
|
||||
|
|
|
@ -64,15 +64,28 @@ const getSuggestedAndCurrentTier = (
|
|||
bank: Bank,
|
||||
midPriceImp: MidPriceImpact[],
|
||||
) => {
|
||||
const currentTier = Object.values(LISTING_PRESETS).find((x) => {
|
||||
return x.initLiabWeight.toFixed(1) === '1.8'
|
||||
? x.initLiabWeight.toFixed(1) ===
|
||||
bank?.initLiabWeight.toNumber().toFixed(1) &&
|
||||
x.reduceOnly === bank.reduceOnly
|
||||
: x.initLiabWeight.toFixed(1) ===
|
||||
bank?.initLiabWeight.toNumber().toFixed(1)
|
||||
const epsilon = 1e-8
|
||||
let currentTier = Object.values(LISTING_PRESETS).find((x) => {
|
||||
if (bank?.name == 'USDC' || bank?.name == 'USDT') return true
|
||||
if (bank?.depositWeightScaleStartQuote != 20000000000) {
|
||||
if (
|
||||
x.depositWeightScaleStartQuote === bank?.depositWeightScaleStartQuote
|
||||
) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
Math.abs(
|
||||
x.loanOriginationFeeRate - bank?.loanOriginationFeeRate.toNumber(),
|
||||
) < epsilon
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
if (currentTier == undefined) {
|
||||
currentTier = LISTING_PRESETS['asset_5000']
|
||||
}
|
||||
|
||||
const filteredResp = midPriceImp
|
||||
.filter((x) => x.avg_price_impact_percent < 1)
|
||||
.reduce((acc: { [key: string]: MidPriceImpact }, val: MidPriceImpact) => {
|
||||
|
@ -1393,6 +1406,19 @@ export const DashboardNavbar = () => {
|
|||
</h4>
|
||||
</Link>
|
||||
</div>
|
||||
<div>
|
||||
<Link href={'/dashboard/marketing'} shallow={true}>
|
||||
<h4
|
||||
className={`${
|
||||
asPath.includes('/dashboard/marketing')
|
||||
? 'bg-th-bkg-2 text-th-active'
|
||||
: ''
|
||||
} cursor-pointer border-r border-th-bkg-3 px-6 py-4`}
|
||||
>
|
||||
Marketing
|
||||
</h4>
|
||||
</Link>
|
||||
</div>
|
||||
<div>
|
||||
<Link
|
||||
href={
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
import type { NextPage } from 'next'
|
||||
import { DashboardNavbar } from '.'
|
||||
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
||||
import useBanks from 'hooks/useBanks'
|
||||
import { Bank } from '@blockworks-foundation/mango-v4'
|
||||
import { formatCurrencyValue } from 'utils/numbers'
|
||||
import { toUiDecimalsForQuote } from '@blockworks-foundation/mango-v4'
|
||||
import { useRouter } from 'next/router' // Import the useRouter hook
|
||||
|
||||
const Marketing: NextPage = () => {
|
||||
const banks = useBanks()['banks']
|
||||
const router = useRouter()
|
||||
|
||||
const getColorForPercent = (percent: number) => {
|
||||
// Use a smoother gradient of colors from red to green based on the percentage
|
||||
if (percent < 10) return '#ff073a' // Deep red
|
||||
else if (percent < 20) return '#ff6347' // Tomato
|
||||
else if (percent < 30) return '#ff7f50' // Coral
|
||||
else if (percent < 40) return '#ffa500' // Orange
|
||||
else if (percent < 50) return '#ffd700' // Gold
|
||||
else if (percent < 60) return '#ffff00' // Yellow
|
||||
else if (percent < 70) return '#adff2f' // Green Yellow
|
||||
else if (percent < 80) return '#7fff00' // Chartreuse
|
||||
else if (percent < 90) return '#32cd32' // Lime Green
|
||||
return '#00ff00' // Green
|
||||
}
|
||||
|
||||
const handleRowClick = (tokenName: string) => {
|
||||
router.push(`/stats?token=${tokenName}`)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="col-span-12 w-full lg:col-span-8 lg:col-start-3">
|
||||
<DashboardNavbar />
|
||||
<div className="mt-4">
|
||||
<div className="mx-20 mb-4">
|
||||
<p className="flex items-center space-x-4 text-th-fgd-4">
|
||||
<span>Fullness of Token Deposits</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="w-full overflow-scroll" style={{ maxHeight: '70vh' }}>
|
||||
<Table className="h-full">
|
||||
<thead>
|
||||
<TrHead
|
||||
style={{ boxShadow: '1px -5px 1px rgba(0,0,0,1)', zIndex: 19 }}
|
||||
className="sticky top-0 border-t bg-th-bkg-2"
|
||||
>
|
||||
<Th
|
||||
className="text-left"
|
||||
style={{ borderLeft: '1px solid #ccc' }}
|
||||
>
|
||||
{'Symbol'}
|
||||
</Th>
|
||||
<Th className="text-left">{'Leverage'}</Th>
|
||||
<Th className="text-left">{'Deposits'}</Th>
|
||||
<Th className="text-left">{'Limit'}</Th>
|
||||
<Th className="text-left">{'Percent'}</Th>
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{banks.map((bank: Bank, idx) => {
|
||||
const deposits = bank?.uiDeposits() * bank?.uiPrice
|
||||
const depositLimit = Number(
|
||||
toUiDecimalsForQuote(bank.borrowWeightScaleStartQuote),
|
||||
)
|
||||
const percent = (100 * deposits) / depositLimit
|
||||
|
||||
if (
|
||||
bank?.name !== 'USDC' &&
|
||||
bank?.maintAssetWeight.toNumber() > 0
|
||||
) {
|
||||
return (
|
||||
<TrBody
|
||||
key={idx}
|
||||
className="h-10 cursor-pointer text-xs md:hover:bg-th-bkg-2"
|
||||
onClick={() => handleRowClick(bank.name)}
|
||||
>
|
||||
<Td className={`sticky left-0 z-10 !py-3`}>
|
||||
{bank?.name}
|
||||
</Td>
|
||||
<Td className={`sticky left-0 z-10 !py-3`}>
|
||||
{(1 / (1 - bank?.initAssetWeight.toNumber())).toFixed()}
|
||||
x
|
||||
</Td>
|
||||
<Td className={`sticky left-0 z-10 !py-3`}>
|
||||
$
|
||||
{(bank?.uiDeposits() * bank?.uiPrice).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
},
|
||||
)}
|
||||
</Td>
|
||||
<Td className={`sticky left-0 z-10 !py-3`}>
|
||||
{formatCurrencyValue(
|
||||
toUiDecimalsForQuote(
|
||||
bank.borrowWeightScaleStartQuote,
|
||||
),
|
||||
)}
|
||||
</Td>
|
||||
<Td className={`sticky left-0 z-10 !py-3`}>
|
||||
<div className="relative h-full w-full">
|
||||
<div className="absolute flex h-full w-full items-center justify-start">
|
||||
<span className="absolute left-0 font-bold">
|
||||
{percent.toFixed(2)}%
|
||||
</span>
|
||||
<div
|
||||
style={{
|
||||
width: `${percent}%`,
|
||||
backgroundColor: getColorForPercent(percent),
|
||||
minHeight: '1rem',
|
||||
marginLeft: '50px', // Offset to the right to avoid overlap
|
||||
}}
|
||||
className="transition-all duration-300 ease-in-out"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Td>
|
||||
</TrBody>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Marketing
|
|
@ -74,6 +74,33 @@ const Prospective: NextPage = () => {
|
|||
return []
|
||||
}, [tokensList])
|
||||
|
||||
const downloadTokens = () => {
|
||||
let csvContent = 'data:text/csv;charset=utf-8,'
|
||||
const filteredTokens = tokensList.filter(
|
||||
(token) => !bankNames.includes(token.symbol.toUpperCase()),
|
||||
)
|
||||
|
||||
if (filteredTokens.length > 0) {
|
||||
const headers = Object.keys(filteredTokens[0]).join(',')
|
||||
const rows = filteredTokens.map((token) =>
|
||||
Object.values(token)
|
||||
.map(
|
||||
(value) => `"${value?.toString().replace(/"/g, '""')}"`, // Handle quotes in data
|
||||
)
|
||||
.join(','),
|
||||
)
|
||||
csvContent += headers + '\n' + rows.join('\n')
|
||||
}
|
||||
|
||||
const encodedUri = encodeURI(csvContent)
|
||||
const link = document.createElement('a')
|
||||
link.setAttribute('href', encodedUri)
|
||||
link.setAttribute('download', 'non_bank_tokens.csv')
|
||||
document.body.appendChild(link) // Required for FF
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="col-span-12 w-full lg:col-span-8 lg:col-start-3">
|
||||
<DashboardNavbar />
|
||||
|
@ -82,6 +109,12 @@ const Prospective: NextPage = () => {
|
|||
<p className="flex items-center space-x-4 text-th-fgd-4">
|
||||
<span>Hidden Gems to Prospect On</span>
|
||||
</p>
|
||||
<button
|
||||
onClick={downloadTokens}
|
||||
className="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
|
||||
>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
<div className="w-full overflow-scroll" style={{ maxHeight: '70vh' }}>
|
||||
<Table className="h-full">
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"collateral": "Collateral",
|
||||
"collateral-funding-modal-heading": "You'll be charged collateral fees in {{remaining_hours}} hours",
|
||||
"collateral-value": "Collateral Value",
|
||||
"connect-funding": "Connect to view your account funding",
|
||||
"custom-account-options-saved": "Advanced options set",
|
||||
"cumulative-interest-chart": "Cumulative Interest Chart",
|
||||
"daily-fee": "Est. Daily Fee",
|
||||
|
@ -18,6 +19,7 @@
|
|||
"followed-accounts": "Followed Accounts",
|
||||
"funding-chart": "Funding Chart",
|
||||
"funding-rate": "Funding Rate",
|
||||
"funding-type": "Funding Type",
|
||||
"hide-announcements": "Hide Announcements",
|
||||
"init-health": "Init Health",
|
||||
"maint-health": "Maint Health",
|
||||
|
@ -30,6 +32,7 @@
|
|||
"maint-health-contributions": "Maint Health Contributions",
|
||||
"more-account-stats": "More Account Stats",
|
||||
"no-data": "No data to display",
|
||||
"no-funding": "No funding earned or paid",
|
||||
"no-pnl-history": "No PnL History",
|
||||
"not-following-yet": "Your not following any accounts yet...",
|
||||
"okay-got-it": "Okay, Got It",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"collateral": "Collateral",
|
||||
"collateral-funding-modal-heading": "You'll be charged collateral fees in {{remaining_hours}} hours",
|
||||
"collateral-value": "Collateral Value",
|
||||
"connect-funding": "Connect to view your account funding",
|
||||
"custom-account-options-saved": "Advanced options set",
|
||||
"cumulative-interest-chart": "Cumulative Interest Chart",
|
||||
"daily-fee": "Est. Daily Fee",
|
||||
|
@ -30,6 +31,7 @@
|
|||
"maint-health-contributions": "Maint Health Contributions",
|
||||
"more-account-stats": "More Account Stats",
|
||||
"no-data": "No data to display",
|
||||
"no-funding": "No funding earned or paid",
|
||||
"no-pnl-history": "No PnL History",
|
||||
"not-following-yet": "Your not following any accounts yet...",
|
||||
"okay-got-it": "Okay, Got It",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"collateral": "Collateral",
|
||||
"collateral-funding-modal-heading": "You'll be charged collateral fees in {{remaining_hours}} hours",
|
||||
"collateral-value": "Valor do Colateral",
|
||||
"connect-funding": "Connect to view your account funding",
|
||||
"custom-account-options-saved": "Opções avançadas definidas",
|
||||
"cumulative-interest-chart": "Gráfico de Juros Acumulados",
|
||||
"daily-fee": "Est. Daily Fee",
|
||||
|
@ -30,6 +31,7 @@
|
|||
"maint-health-contributions": "Contribuições para a Saúde de Manutenção",
|
||||
"more-account-stats": "Mais Estatísticas da Conta",
|
||||
"no-data": "Sem dados para exibir",
|
||||
"no-funding": "No funding earned or paid",
|
||||
"no-pnl-history": "Sem Histórico de PnL",
|
||||
"not-following-yet": "Ainda não está seguindo nenhuma conta...",
|
||||
"okay-got-it": "Okay, Got It",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"collateral": "Collateral",
|
||||
"collateral-funding-modal-heading": "You'll be charged collateral fees in {{remaining_hours}} hours",
|
||||
"collateral-value": "Collateral Value",
|
||||
"connect-funding": "Connect to view your account funding",
|
||||
"custom-account-options-saved": "Advanced options set",
|
||||
"cumulative-interest-chart": "Cumulative Interest Chart",
|
||||
"daily-fee": "Est. Daily Fee",
|
||||
|
@ -30,6 +31,7 @@
|
|||
"maint-health-contributions": "Maint Health Contributions",
|
||||
"more-account-stats": "More Account Stats",
|
||||
"no-data": "No data to display",
|
||||
"no-funding": "No funding earned or paid",
|
||||
"no-pnl-history": "No PnL History",
|
||||
"not-following-yet": "Your not following any accounts yet...",
|
||||
"okay-got-it": "Okay, Got It",
|
||||
|
|
|
@ -5,20 +5,21 @@
|
|||
"advanced-options-desc": "Mango帐户对帐户一次可以持有的币种数量和市场数量有限制。 这是Solana 帐户的特征之一。 使用滑杆为你的新帐户自订币种以市场位置。",
|
||||
"assets": "资产",
|
||||
"assets-liabilities": "资产和债务",
|
||||
"collateral": "Collateral",
|
||||
"collateral-funding-modal-heading": "You'll be charged collateral fees in {{remaining_hours}} hours",
|
||||
"collateral": "质押品",
|
||||
"collateral-funding-modal-heading": "{{remaining_hours}}小时之后Mango将收取你的质押品费",
|
||||
"collateral-value": "质押品价值",
|
||||
"connect-funding": "Connect to view your account funding",
|
||||
"custom-account-options-saved": "已改高级设定",
|
||||
"cumulative-interest-chart": "累积利息图表",
|
||||
"daily-fee": "Est. Daily Fee",
|
||||
"daily-fee": "每日费用",
|
||||
"daily-volume": "24小时交易量",
|
||||
"export": "导出{{dataType}}",
|
||||
"find-accounts": "寻找帐户",
|
||||
"follow": "关注",
|
||||
"followed-accounts": "你关注的帐户",
|
||||
"funding-chart": "资金费图表",
|
||||
"funding-type": "Funding Type",
|
||||
"hide-announcements": "隐藏通知",
|
||||
"funding-type": "资金费类别",
|
||||
"hide-announcements": "隐藏通知",
|
||||
"health-contributions": "健康度贡献",
|
||||
"init-health": "初始健康度",
|
||||
"init-health-contribution": "初始健康贡献",
|
||||
|
@ -30,9 +31,10 @@
|
|||
"maint-health-contributions": "维持健康度",
|
||||
"more-account-stats": "更多帐户统计",
|
||||
"no-data": "无数据可显示",
|
||||
"no-funding": "No funding earned or paid",
|
||||
"no-pnl-history": "无盈亏历史",
|
||||
"not-following-yet": "你尚未关注任何帐户...",
|
||||
"okay-got-it": "Okay, Got It",
|
||||
"okay-got-it": "好,动了",
|
||||
"open-settings": "打开设定",
|
||||
"pnl-chart": "盈亏图表",
|
||||
"pnl-history": "盈亏历史",
|
||||
|
@ -64,7 +66,7 @@
|
|||
"volume-chart": "交易量图表",
|
||||
"warning-uninsured": "{{token}}不受保证。",
|
||||
"week-starting": "从{{week}}来算的一周",
|
||||
"whats-this": "What's This?",
|
||||
"whats-this": "这是什么?",
|
||||
"zero-balances": "显示等于零的余额",
|
||||
"zero-collateral": "无质押品"
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
"amount-owed": "欠款",
|
||||
"announcements": "通知",
|
||||
"asked-sign-transaction": "你会被要求签署交易",
|
||||
"asset": "Asset",
|
||||
"asset": "资产",
|
||||
"asset-liability-weight": "资产/债务权重",
|
||||
"asset-liability-weight-desc": "资产权重在账户健康计算中对质押品价值进行扣减。资产权重越低,资产对质押品的影响越小。债务权重恰恰相反(在健康计算中增加债务价值)。",
|
||||
"asset-weight": "资产权重",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"base-liquidation-fee": "基本清算费用",
|
||||
"closest-to-liquidation": "最接近清算的持仓",
|
||||
"collateral-funding-fee": "Collateral Funding Fee (Per Day)",
|
||||
"collateral-funding-fee": "质押品资金费用",
|
||||
"daily": "日",
|
||||
"hourly": "小时",
|
||||
"largest-perp-positions": "最大持仓",
|
||||
|
|
|
@ -5,19 +5,20 @@
|
|||
"advanced-options-desc": "Mango帳戶對帳戶一次可以持有的幣種數量和市場數量有限制。 這是 Solana 帳戶的特徵之一。 使用滑桿為你的新帳戶自訂幣種以市場位置。",
|
||||
"assets": "資產",
|
||||
"assets-liabilities": "資產和債務",
|
||||
"collateral": "Collateral",
|
||||
"collateral-funding-modal-heading": "You'll be charged collateral fees in {{remaining_hours}} hours",
|
||||
"collateral": "質押品",
|
||||
"collateral-funding-modal-heading": "{{remaining_hours}}小時之後Mango將收取你的質押品費",
|
||||
"collateral-value": "質押品價值",
|
||||
"connect-funding": "Connect to view your account funding",
|
||||
"custom-account-options-saved": "已改高級設定",
|
||||
"cumulative-interest-chart": "累積利息圖表",
|
||||
"daily-fee": "Est. Daily Fee",
|
||||
"daily-fee": "每日費用",
|
||||
"daily-volume": "24小時交易量",
|
||||
"export": "導出{{dataType}}",
|
||||
"find-accounts": "尋找帳戶",
|
||||
"follow": "關注",
|
||||
"followed-accounts": "你關注的帳戶",
|
||||
"funding-chart": "資金費圖表",
|
||||
"funding-type": "Funding Type",
|
||||
"funding-type": "資金費類別",
|
||||
"hide-announcements": "隱藏通知",
|
||||
"health-contributions": "健康度貢獻",
|
||||
"init-health": "初始健康度",
|
||||
|
@ -30,9 +31,10 @@
|
|||
"maint-health-contributions": "維持健康度",
|
||||
"more-account-stats": "更多帳戶統計",
|
||||
"no-data": "無數據可顯示",
|
||||
"no-funding": "No funding earned or paid",
|
||||
"no-pnl-history": "無盈虧歷史",
|
||||
"not-following-yet": "你尚未關注任何帳戶...",
|
||||
"okay-got-it": "Okay, Got It",
|
||||
"okay-got-it": "好,動了",
|
||||
"open-settings": "打開設定",
|
||||
"pnl-chart": "盈虧圖表",
|
||||
"pnl-history": "盈虧歷史",
|
||||
|
@ -64,7 +66,7 @@
|
|||
"volume-chart": "交易量圖表",
|
||||
"warning-uninsured": "{{token}}不受保證。",
|
||||
"week-starting": "從{{week}}來算的一周",
|
||||
"whats-this": "What's This?",
|
||||
"whats-this": "這是甚麼?",
|
||||
"zero-balances": "顯示等於零的餘額",
|
||||
"zero-collateral": "無質押品"
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
"amount-owed": "欠款",
|
||||
"announcements": "通知",
|
||||
"asked-sign-transaction": "你會被要求簽署交易",
|
||||
"asset": "Asset",
|
||||
"asset": "資產",
|
||||
"asset-liability-weight": "資產/債務權重",
|
||||
"asset-liability-weight-desc": "資產權重在賬戶健康計算中對質押品價值進行扣減。資產權重越低,資產對質押品的影響越小。債務權重恰恰相反(在健康計算中增加債務價值)。",
|
||||
"asset-weight": "資產權重",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"base-liquidation-fee": "基本清算費用",
|
||||
"closest-to-liquidation": "最接近清算的持倉",
|
||||
"collateral-funding-fee": "Collateral Funding Fee (Per Day)",
|
||||
"collateral-funding-fee": "質押品資金費用",
|
||||
"daily": "日",
|
||||
"hourly": "小時",
|
||||
"largest-perp-positions": "最大持倉",
|
||||
|
|
|
@ -350,10 +350,10 @@
|
|||
bn.js "^5.2.1"
|
||||
eslint-config-prettier "^9.0.0"
|
||||
|
||||
"@blockworks-foundation/mango-v4-settings@0.14.21":
|
||||
version "0.14.21"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.14.21.tgz#d7aeb3bc827acd7d558bfba5d8ec1b48c590a746"
|
||||
integrity sha512-QbveR8YSH4DI7sskeYBpEBHREWF2bCh/rJ7WymSlqmsIYR1DOvsk+ZqUdrDCtGEjZZb+3jrP77jjc3XMe1jZig==
|
||||
"@blockworks-foundation/mango-v4-settings@0.14.22":
|
||||
version "0.14.22"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.14.22.tgz#7d7c9759b73d2c8166cf5f0871969e3764ea4139"
|
||||
integrity sha512-YSJrCgeI6aC/RsL8dRyJmpKYB2CkY9YaiZ9PVjNWrQOcgQkp/DNaaI1CBFpZshtg6VtpFraQh6IrOmXzaAvglA==
|
||||
dependencies:
|
||||
bn.js "^5.2.1"
|
||||
eslint-config-prettier "^9.0.0"
|
||||
|
|
Loading…
Reference in New Issue