Skip to content

Commit

Permalink
Token Logo fix. (#34)
Browse files Browse the repository at this point in the history
* add token-logo fix, and use latest jupiter code

* wip token logo and prices

* update the deprecated signatures method (#33)

* removed unverifiedTokens, add dynamicComputeUnits, removed 0 priorityFees, add discussion on priorityFees

* fix comment

* Revert "fix comment"

This reverts commit ec2fa55.

* Reapply "fix comment"

This reverts commit 154922e.

* Revert "Reapply "fix comment""

This reverts commit 34b037b.

* remove priorityfees and dynamic fee changes

---------

Co-authored-by: Utkarsh <[email protected]>
  • Loading branch information
crypt0miester and 0xShuk authored Nov 19, 2024
1 parent 2c42e76 commit b962c4c
Show file tree
Hide file tree
Showing 18 changed files with 878 additions and 183 deletions.
2 changes: 1 addition & 1 deletion components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function AppContents(props: Props) {
handleRouterHistory()
useHandleGovernanceAssetsStore()
useEffect(() => {
tokenPriceService.fetchSolanaTokenList()
tokenPriceService.fetchSolanaTokenListV2()
}, [])

const { getOwnedDeposits, resetDepositState } = useDepositStore()
Expand Down
45 changes: 28 additions & 17 deletions components/TreasuryAccount/AccountItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMemo } from 'react'
import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools'
import { useEffect, useState, useMemo } from 'react'
import { getTreasuryAccountItemInfoV2Async } from '@utils/treasuryTools'
import { AssetAccount } from '@utils/uiTypes/assets'
import TokenIcon from '@components/treasuryV2/icons/TokenIcon'
import { useTokenMetadata } from '@hooks/queries/tokenMetadata'
Expand All @@ -9,23 +9,38 @@ const AccountItem = ({
}: {
governedAccountTokenAccount: AssetAccount
}) => {
const {
amountFormatted,
logo,
name,
symbol,
displayPrice,
} = getTreasuryAccountItemInfoV2(governedAccountTokenAccount)
const [accountAssetInfo, setAccountAssetInfo] = useState({
amountFormatted: '',
logo: '',
name: '',
symbol: '',
displayPrice: '',
})

useEffect(() => {
const fetchAccounAssetInfo = async () => {
try {
const info = await getTreasuryAccountItemInfoV2Async(governedAccountTokenAccount)
setAccountAssetInfo(info)
} catch (error) {
console.error('Error fetching treasury account info:', error)
}
}

fetchAccounAssetInfo()
}, [governedAccountTokenAccount])

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

const symbolFromMeta = useMemo(() => {
return data?.symbol
}, [data?.symbol])

const { amountFormatted, logo, name, symbol, displayPrice } = accountAssetInfo

return (
<div className="flex items-center w-full p-3 border rounded-lg text-fgd-1 border-fgd-4">
{logo ? (
Expand All @@ -51,14 +66,10 @@ const AccountItem = ({
<div className="text-xs text-fgd-3">
{amountFormatted} {symbolFromMeta ? symbolFromMeta : symbol}
</div>
{displayPrice ? (
<div className="mt-0.5 text-fgd-3 text-xs">≈${displayPrice}</div>
) : (
''
)}
<div className="mt-0.5 text-fgd-3 text-xs">≈${displayPrice || 0}</div>
</div>
</div>
)
}

export default AccountItem
export default AccountItem
81 changes: 56 additions & 25 deletions components/TreasuryAccount/AccountsItems.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,70 @@
import useGovernanceAssets from '@hooks/useGovernanceAssets'
import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools'
import React from 'react'
import { getTreasuryAccountItemInfoV2Async } from '@utils/treasuryTools'
import React, { useEffect, useState } from 'react'
import AccountItem from './AccountItem'
import { AssetAccount } from '@utils/uiTypes/assets'
import Loading from '@components/Loading'

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 [sortedAccounts, setSortedAccounts] = useState<AssetAccount[]>([])
const [isLoading, setIsLoading] = useState(true)

useEffect(() => {
const sortAccounts = async () => {
try {
setIsLoading(true)
const accounts = [
...governedTokenAccountsWithoutNfts,
...auxiliaryTokenAccounts,
]

// Get all account info in parallel
const accountsWithInfo = await Promise.all(
accounts.map(async (account) => ({
account,
info: await getTreasuryAccountItemInfoV2Async(account)
}))
)

// Sort based on the fetched info
const sorted = accountsWithInfo
.sort((a, b) => b.info.totalPrice - a.info.totalPrice)
.map(({ account }) => account)
.splice(
0,
Number(process?.env?.MAIN_VIEW_SHOW_MAX_TOP_TOKENS_NUM || accounts.length)
)

setSortedAccounts(sorted)
} catch (error) {
console.error('Error sorting accounts:', error)
} finally {
setIsLoading(false)
}
}

sortAccounts()
}, [])

if (isLoading) {
return <div className="space-y-3"><Loading></Loading></div>
}

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

export default AccountsItems
export default AccountsItems
7 changes: 6 additions & 1 deletion components/instructions/programs/stake.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ export const STAKE_INSTRUCTIONS = {
BufferLayout.u32('instruction'),
BufferLayout.ns64('lamports'),
]).decode(Buffer.from(_data))
const rent = await _connection.getMinimumBalanceForRentExemption(200)

// const rent = await _connection.getMinimumBalanceForRentExemption(200)

// > solana rent 200 --lamports
// Rent-exempt minimum: 2282880 lamports
const rent = 2282880
return (
<>
<p>
Expand Down
79 changes: 68 additions & 11 deletions hooks/queries/jupiterPrice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,51 @@ import { PublicKey } from '@solana/web3.js'
import { useQuery } from '@tanstack/react-query'
import queryClient from './queryClient'

const URL = 'https://price.jup.ag/v4/price'
const URL = 'https://api.jup.ag/price/v2'

/* example query
GET https://price.jup.ag/v4/price?ids=SOL
response: {"data":{"SOL":{"id":"So11111111111111111111111111111111111111112","mintSymbol":"SOL","vsToken":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","vsTokenSymbol":"USDC","price":26.649616441}},"timeTaken":0.0002587199999766199}
# Unit price of 1 JUP & 1 SOL based on the Derived Price in USDC
https://api.jup.ag/price/v2?ids=JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN,So11111111111111111111111111111111111111112
{
"data": {
"So11111111111111111111111111111111111111112": {
"id": "So11111111111111111111111111111111111111112",
"type": "derivedPrice",
"price": "133.890945000"
},
"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN": {
"id": "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN",
"type": "derivedPrice",
"price": "0.751467"
}
},
"timeTaken": 0.00395219
}
*/
/* example intentionally broken query
GET https://price.jup.ag/v4/price?ids=bingus
response: {"data":{},"timeTaken":0.00010941000005004753}
curl -X 'GET' 'https://api.jup.ag/price/v2?ids=So11111111111111111111111111111111111111112&showExtraInfo=true'
{
"data": {
"So11111111111111111111111111111111111111112": {
"id": "So11111111111111111111111111111111111111112",
"type": "derivedPrice",
"price": "134.170633378"
},
"8agCopCHWdpj7mHk3JUWrzt8pHAxMiPX5hLVDJh9TXWv": null
},
"timeTaken": 0.003186833
}
*/

type Price = {
id: string // pubkey,
mintSymbol: string
vsToken: string // pubkey,
vsTokenSymbol: string
// price is in USD
price: number
// removed in v2 API
// mintSymbol: string
// vsToken: string // pubkey,
// vsTokenSymbol: string
}
type Response = {
data: Record<string, Price> //uses whatever you input (so, pubkey OR symbol). no entry if data not found
Expand Down Expand Up @@ -76,11 +104,13 @@ export const getJupiterPriceSync = (mint: PublicKey) =>

export const useJupiterPricesByMintsQuery = (mints: PublicKey[]) => {
const enabled = mints.length > 0
const deduped = new Set(mints)
const dedupedMints = Array.from(deduped)
return useQuery({
enabled,
queryKey: jupiterPriceQueryKeys.byMints(mints),
queryKey: jupiterPriceQueryKeys.byMints(dedupedMints),
queryFn: async () => {
const batches = [...chunks(mints, 100)]
const batches = [...chunks(dedupedMints, 100)]
const responses = await Promise.all(
batches.map(async (batch) => {
const x = await fetch(`${URL}?ids=${batch.join(',')}`)
Expand All @@ -106,7 +136,7 @@ export const useJupiterPricesByMintsQuery = (mints: PublicKey[]) => {
return data
},
onSuccess: (data) => {
mints.forEach((mint) =>
dedupedMints.forEach((mint) =>
queryClient.setQueryData(
jupiterPriceQueryKeys.byMint(mint),
data[mint.toString()]
Expand All @@ -117,3 +147,30 @@ export const useJupiterPricesByMintsQuery = (mints: PublicKey[]) => {
},
})
}

// function is used to get fresh token prices
export const getJupiterPricesByMintStrings = async (mints: string[]) => {
if (mints.length === 0) return {}
const deduped = new Set(mints)
const dedupedMints = Array.from(deduped)
try {
const x = await fetch(`${URL}?ids=${dedupedMints.join(',')}`)
const response = (await x.json()) as Response
const data = response.data

//override chai price if its broken
const chaiMint = '3jsFX1tx2Z8ewmamiwSU851GzyzM2DJMq7KWW5DM8Py3'
const chaiData = data[chaiMint]

if (chaiData?.price && (chaiData.price > 1.3 || chaiData.price < 0.9)) {
data[chaiMint] = {
...chaiData,
price: 1,
}
}
return data
} catch (error) {
console.error('Error fetching Jupiter prices:', error)
throw error
}
}
33 changes: 33 additions & 0 deletions hooks/useLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
type UseStorageReturnValue = {
getItem: (key: string) => string;
setItem: (key: string, value: string) => boolean;
removeItem: (key: string) => void;
};

export const useLocalStorage = (): UseStorageReturnValue => {
const isBrowser: boolean = ((): boolean => typeof window !== "undefined")();

const getItem = (key: string): string => {
return isBrowser ? window.localStorage[key] : "";
};

const setItem = (key: string, value: string): boolean => {
if (isBrowser) {
window.localStorage.setItem(key, value);
return true;
}

return false;
};

const removeItem = (key: string): void => {
window.localStorage.removeItem(key);
};

return {
getItem,
setItem,
removeItem,
};
};

11 changes: 5 additions & 6 deletions hooks/useTreasuryInfo/convertAccountToAsset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ import { BigNumber } from 'bignumber.js'

import { AccountType, AssetAccount } from '@utils/uiTypes/assets'
import { AssetType, Asset } from '@models/treasury/Asset'
import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools'
import { getTreasuryAccountItemInfoV2Async } from '@utils/treasuryTools'
import TokenIcon from '@components/treasuryV2/icons/TokenIcon'
import { WSOL_MINT } from '@components/instructions/tools'
import { abbreviateAddress } from '@utils/formatting'

import { getAccountAssetCount } from './getAccountAssetCount'
import { fetchJupiterPrice } from '@hooks/queries/jupiterPrice'
import { getAccountValue, getStakeAccountValue } from './getAccountValue'
import tokenPriceService from '@utils/services/tokenPrice'

export const convertAccountToAsset = async (
account: AssetAccount,
councilMintAddress?: string,
communityMintAddress?: string
): Promise<Asset | null> => {
const info = getTreasuryAccountItemInfoV2(account)
const info = await getTreasuryAccountItemInfoV2Async(account)

switch (account.type) {
case AccountType.AUXILIARY_TOKEN:
Expand Down Expand Up @@ -65,8 +66,7 @@ export const convertAccountToAsset = async (
),
price: account.extensions.mint
? new BigNumber(
(await fetchJupiterPrice(account.extensions.mint.publicKey))
.result?.price ?? 0
await tokenPriceService.fetchTokenPrice(account.extensions.mint.publicKey.toString()) ?? 0
)
: undefined,
raw: account,
Expand All @@ -89,8 +89,7 @@ export const convertAccountToAsset = async (
name: info.accountName || info.info?.name || info.name || info.symbol,
price: account.extensions.mint
? new BigNumber(
(await fetchJupiterPrice(account.extensions.mint.publicKey))
.result?.price ?? 0
await tokenPriceService.fetchTokenPrice(account.extensions.mint.publicKey.toString()) ?? 0
)
: undefined,
raw: account,
Expand Down
1 change: 0 additions & 1 deletion hooks/useTreasuryInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ export default function useTreasuryInfo(
if (!loadingGovernedAccounts && accounts.length && getNftsAndDomains) {
setDomainsLoading(true)
setBuildingWallets(true)

getDomains(
accounts.filter((acc) => acc.isSol),
connection.current
Expand Down
Loading

0 comments on commit b962c4c

Please sign in to comment.