Skip to content

Commit

Permalink
speed up loading of main page for traesure stuff, fix sorting on main…
Browse files Browse the repository at this point in the history
… landing page of assets, fix asset calculation totals and sorting for treasury detail page, other tweaks
  • Loading branch information
ggnine-jito committed Dec 13, 2024
1 parent 24458c8 commit 2af5638
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 139 deletions.
67 changes: 26 additions & 41 deletions components/TreasuryAccount/AccountItem.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,52 @@
import { useMemo } from 'react'
import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools'
import { AssetAccount } from '@utils/uiTypes/assets'
import { AssetAccount, TreasuryAccountItemInfo } from '@utils/uiTypes/assets'
import TokenIcon from '@components/treasuryV2/icons/TokenIcon'
import { useTokenMetadata } from '@hooks/queries/tokenMetadata'
import { useJupiterPriceByMintQuery } from '../../hooks/queries/jupiterPrice'
import BigNumber from 'bignumber.js'
import { useMemo, useState } from 'react'

type AccountItemProps = {
governedAccountTokenAccount: AssetAccount
treasuryInfo: TreasuryAccountItemInfo
}

const AccountItem = ({
governedAccountTokenAccount,
}: {
governedAccountTokenAccount: AssetAccount
}) => {
treasuryInfo,
}: AccountItemProps) => {
const [imgError, setImgError] = useState(false)

const {
decimalAdjustedAmount,
amountFormatted,
logo,
name,
symbol,
} = getTreasuryAccountItemInfoV2(governedAccountTokenAccount)
displayPrice,
mintPubkey,
} = treasuryInfo || {}

const { data: priceData } = useJupiterPriceByMintQuery(
governedAccountTokenAccount.extensions.mint?.publicKey
)

const { data } = useTokenMetadata(
governedAccountTokenAccount.extensions.mint?.publicKey,
const { data: tokenMetadata } = useTokenMetadata(
mintPubkey,
!logo
)

const symbolFromMeta = useMemo(() => {
// data.symbol is kinda weird
//Handle null characters, whitespace, and ensure fallback to symbol
const cleanSymbol = data?.symbol
?.replace(/\0/g, '') // Remove null characters
?.replace(/\s+/g, ' ') // Normalize whitespace to single spaces
?.trim() // Remove leading/trailing whitespace

return cleanSymbol || symbol || ''
}, [data?.symbol, symbol])
const cleanSymbol = tokenMetadata?.symbol
?.replace(/\0/g, '')
?.replace(/\s+/g, ' ')
?.trim()

const displayPrice = useMemo(() => {
if (!decimalAdjustedAmount || !priceData?.result?.price) return ''

try {
const totalPrice = decimalAdjustedAmount * priceData.result.price
return new BigNumber(totalPrice).toFormat(0)
} catch (error) {
console.error('Error calculating display price:', error)
return ''
}
}, [priceData, decimalAdjustedAmount])
return cleanSymbol || symbol || ''
}, [tokenMetadata?.symbol, symbol])

return (
<div className="flex items-center w-full p-3 border rounded-lg text-fgd-1 border-fgd-4">
{logo ? (
{logo && !imgError ? (
<img
className={`flex-shrink-0 h-6 w-6 mr-2.5 mt-0.5 ${
governedAccountTokenAccount.isSol ? 'rounded-full' : ''
}`}
className={`flex-shrink-0 h-6 w-6 mr-2.5 mt-0.5 ${governedAccountTokenAccount.isSol ? 'rounded-full' : ''
}`}
src={logo}
onError={({ currentTarget }) => {
currentTarget.onerror = null
currentTarget.hidden = true
setImgError(true)
}}
alt={`${name} logo`}
/>
Expand Down
101 changes: 76 additions & 25 deletions components/TreasuryAccount/AccountsItems.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,90 @@
import useGovernanceAssets from '@hooks/useGovernanceAssets'
import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools'
import React from 'react'
import React, { useMemo } from 'react'
import AccountItem from './AccountItem'
import { useJupiterPricesByMintsQuery } from '../../hooks/queries/jupiterPrice'
import { PublicKey } from '@solana/web3.js'
import { WSOL_MINT } from '../instructions/tools'
import BigNumber from 'bignumber.js'
import { getTreasuryAccountItemInfoV3 } from '../../utils/treasuryToolsV3'

const AccountsItems = () => {
const {
governedTokenAccountsWithoutNfts,
auxiliaryTokenAccounts,
} = useGovernanceAssets()
const accounts = [
...governedTokenAccountsWithoutNfts,
...auxiliaryTokenAccounts,
]
const accountsSorted = accounts
.sort((a, b) => {
const infoA = getTreasuryAccountItemInfoV2(a)
const infoB = getTreasuryAccountItemInfoV2(b)
return infoB.totalPrice - infoA.totalPrice
})
.splice(
0,
Number(process?.env?.MAIN_VIEW_SHOW_MAX_TOP_TOKENS_NUM || accounts.length)
)

const accounts = useMemo(() => {
const allAccounts = [
...(governedTokenAccountsWithoutNfts || []),
...(auxiliaryTokenAccounts || []),
]
return allAccounts.filter(Boolean)
}, [governedTokenAccountsWithoutNfts, auxiliaryTokenAccounts])

const mintsToFetch = useMemo(() => {
return [
...governedTokenAccountsWithoutNfts,
...auxiliaryTokenAccounts,
]
.filter((x) => typeof x.extensions.mint !== 'undefined')
.map((x) => x.extensions.mint!.publicKey)
}, [governedTokenAccountsWithoutNfts, auxiliaryTokenAccounts])

const { data: prices } = useJupiterPricesByMintsQuery([
...mintsToFetch,
new PublicKey(WSOL_MINT),
])

const sortedAccounts = useMemo(() => {
if (!accounts.length || !prices) return []

try {
const accountsWithInfo = accounts.map((account) => {
try {
const info = getTreasuryAccountItemInfoV3(account)
// Override the price/total price with Jupiter price data
const mintAddress = account.extensions.mint?.publicKey.toBase58()
const jupiterPrice = mintAddress && Object.keys(prices || {}).length > 0 ? prices[mintAddress]?.price ?? 0 : 0
const amount = info.decimalAdjustedAmount
const totalPrice = amount * jupiterPrice

return {
account,
info: {
...info,
totalPrice,
displayPrice: totalPrice ? new BigNumber(totalPrice).toFormat(0) : ''
}
}
} catch (err) {
console.error(`Error processing account ${account?.pubkey?.toString()}:`, err)
return null
}
})

const validAccounts = accountsWithInfo
.filter((item) => item !== null)
.sort((a, b) => b.info.totalPrice - a.info.totalPrice)

const maxTokens = Number(process?.env?.MAIN_VIEW_SHOW_MAX_TOP_TOKENS_NUM) || accounts.length
return validAccounts.slice(0, maxTokens)
} catch (err) {
console.error('Error sorting accounts:', err)
return []
}
}, [accounts, prices])

return (
<div className="space-y-3">
{accountsSorted.map((account) => {
return (
<AccountItem
governedAccountTokenAccount={account}
key={account?.extensions.transferAddress?.toBase58()}
/>
)
})}
{sortedAccounts.map(({ account, info }) => (
<AccountItem
governedAccountTokenAccount={account}
treasuryInfo={info}
key={account?.extensions?.transferAddress?.toBase58() || account?.pubkey?.toBase58()}
/>
))}
</div>
)
}

export default AccountsItems
export default AccountsItems
107 changes: 107 additions & 0 deletions hooks/useGetTreasuryAccountItemInfoV3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { getAccountName, WSOL_MINT } from '@components/instructions/tools'
import { BN } from '@coral-xyz/anchor'
import { PublicKey } from '@solana/web3.js'
import { getMintDecimalAmountFromNatural } from '@tools/sdk/units'
import BigNumber from 'bignumber.js'
import { abbreviateAddress } from '@utils/formatting'
import { AccountType, AssetAccount } from '@utils/uiTypes/assets'
import { useJupiterPriceByMintQuery } from './queries/jupiterPrice'
import { useTokenMetadata } from './queries/tokenMetadata'
import { useMemo } from 'react'

export const useGetTreasuryAccountItemInfoV3 = (account: AssetAccount) => {
// Memoize these values since they're used in multiple places
const mintPubkey = useMemo(() =>
account.extensions.mint?.publicKey,
[account.extensions.mint]
)

const mintAddress = useMemo(() =>
account.type === AccountType.SOL
? WSOL_MINT
: mintPubkey?.toBase58(),
[account.type, mintPubkey]
)

const decimalAdjustedAmount = useMemo(() =>
account.extensions.amount && account.extensions.mint
? getMintDecimalAmountFromNatural(
account.extensions.mint.account,
new BN(
account.isSol
? account.extensions.solAccount!.lamports
: account.extensions.amount
)
).toNumber()
: 0
, [account])

const { data: priceData } = useJupiterPriceByMintQuery(mintPubkey)
const { data: tokenMetadata } = useTokenMetadata(mintPubkey, true)
// const info = tokenPriceService.getTokenInfo(mintAddress!)

const amountFormatted = useMemo(() =>
new BigNumber(decimalAdjustedAmount).toFormat()
, [decimalAdjustedAmount])

// Handle symbol with metadata fallback
const symbol = useMemo(() => {
if (account.type === AccountType.NFT) return 'NFTS'
if (account.type === AccountType.SOL) return 'SOL'

// Try to get from metadata first
const metadataSymbol = tokenMetadata?.symbol
?.replace(/\0/g, '')
?.replace(/\s+/g, ' ')
?.trim()

if (metadataSymbol) return metadataSymbol

// Fallback to abbreviated address
return account.extensions.mint
? abbreviateAddress(account.extensions.mint.publicKey)
: ''
}, [account, tokenMetadata])

const accountName = account.pubkey ? getAccountName(account.pubkey) : ''
const name = useMemo(() =>
accountName || (
account.extensions.transferAddress
? abbreviateAddress(account.extensions.transferAddress as PublicKey)
: ''
)
, [accountName, account.extensions.transferAddress])

const totalPrice = useMemo(() => {
if (!decimalAdjustedAmount || !priceData?.result?.price) return 0
try {
return decimalAdjustedAmount * priceData.result.price
} catch (error) {
console.error('Error calculating total price:', error)
return 0
}
}, [decimalAdjustedAmount, priceData])

const displayPrice = useMemo(() => {
if (!totalPrice) return ''
try {
return new BigNumber(totalPrice).toFormat(0)
} catch (error) {
console.error('Error formatting display price:', error)
return ''
}
}, [totalPrice])

return {
decimalAdjustedAmount,
amountFormatted,
name,
symbol,
totalPrice,
displayPrice,
logo: `https://jito.network/coinsByMint/${mintAddress}.webp`,
// logo: tokenMetadata?.image || '', // Use image instead of logoURI
mintPubkey,
mintAddress,
}
}
Loading

0 comments on commit 2af5638

Please sign in to comment.