diff --git a/explorer/src/components/account/OwnedTokensCard.tsx b/explorer/src/components/account/OwnedTokensCard.tsx index 85c3bdf74e..2845de2c6b 100644 --- a/explorer/src/components/account/OwnedTokensCard.tsx +++ b/explorer/src/components/account/OwnedTokensCard.tsx @@ -4,7 +4,6 @@ import { FetchStatus } from "providers/accounts"; import { useFetchAccountOwnedTokens, useAccountOwnedTokens, - TokenAccountData, } from "providers/accounts/tokens"; import { ErrorCard } from "components/common/ErrorCard"; import { LoadingCard } from "components/common/LoadingCard"; @@ -43,26 +42,27 @@ export function OwnedTokensCard({ pubkey }: { pubkey: PublicKey }) { ); } - const mappedTokens = new Map(); - for (const token of tokens) { + const mappedTokens = new Map(); + for (const { info: token } of tokens) { const mintAddress = token.mint.toBase58(); - const tokenInfo = mappedTokens.get(mintAddress); - if (tokenInfo) { - tokenInfo.amount += token.amount; - } else { - mappedTokens.set(mintAddress, { ...token }); + const totalByMint = mappedTokens.get(mintAddress); + + let amount = token?.amount || (token?.tokenAmount?.uiAmount as number); + if (totalByMint !== undefined) { + amount += totalByMint; } + + mappedTokens.set(mintAddress, amount); } const detailsList: React.ReactNode[] = []; - mappedTokens.forEach((tokenInfo, mintAddress) => { - const balance = tokenInfo.amount; + mappedTokens.forEach((totalByMint, mintAddress) => { detailsList.push(
- {balance} + {totalByMint} ); }); diff --git a/explorer/src/components/account/TokenHistoryCard.tsx b/explorer/src/components/account/TokenHistoryCard.tsx index 07069ab087..dcd1fdff1d 100644 --- a/explorer/src/components/account/TokenHistoryCard.tsx +++ b/explorer/src/components/account/TokenHistoryCard.tsx @@ -11,7 +11,7 @@ import { } from "providers/accounts/history"; import { useAccountOwnedTokens, - TokenAccountData, + TokenInfoWithPubkey, } from "providers/accounts/tokens"; import { ErrorCard } from "components/common/ErrorCard"; import { LoadingCard } from "components/common/LoadingCard"; @@ -40,7 +40,7 @@ export function TokenHistoryCard({ pubkey }: { pubkey: PublicKey }) { return ; } -function TokenHistoryTable({ tokens }: { tokens: TokenAccountData[] }) { +function TokenHistoryTable({ tokens }: { tokens: TokenInfoWithPubkey[] }) { const accountHistories = useAccountHistories(); const fetchAccountHistory = useFetchAccountHistory(); @@ -77,7 +77,7 @@ function TokenHistoryTable({ tokens }: { tokens: TokenAccountData[] }) { const mintAndTxs = tokens .map((token) => ({ - mint: token.mint, + mint: token.info.mint, history: accountHistories[token.pubkey.toBase58()], })) .filter(({ history }) => { diff --git a/explorer/src/providers/accounts/tokens.tsx b/explorer/src/providers/accounts/tokens.tsx index 62794b51eb..4008ec6db7 100644 --- a/explorer/src/providers/accounts/tokens.tsx +++ b/explorer/src/providers/accounts/tokens.tsx @@ -1,31 +1,18 @@ import React from "react"; import { Connection, PublicKey } from "@solana/web3.js"; import { FetchStatus } from "./index"; +import { TokenAccountInfo } from "validators/accounts/token"; import { useCluster } from "../cluster"; -import { number, string, boolean, coerce, object, nullable } from "superstruct"; +import { coerce } from "superstruct"; -export type TokenAccountData = { +export type TokenInfoWithPubkey = { + info: TokenAccountInfo; pubkey: PublicKey; - mint: PublicKey; - owner: PublicKey; - amount: number; - isInitialized: boolean; - isNative: boolean; }; -const TokenAccountInfo = object({ - mint: string(), - owner: string(), - amount: number(), - delegate: nullable(string()), - delegatedAmount: number(), - isInitialized: boolean(), - isNative: boolean(), -}); - interface AccountTokens { status: FetchStatus; - tokens?: TokenAccountData[]; + tokens?: TokenInfoWithPubkey[]; } interface Update { @@ -33,7 +20,7 @@ interface Update { url: string; pubkey: PublicKey; status: FetchStatus; - tokens?: TokenAccountData[]; + tokens?: TokenInfoWithPubkey[]; } interface Clear { @@ -129,14 +116,7 @@ async function fetchAccountTokens( tokens = value.map((accountInfo) => { const parsedInfo = accountInfo.account.data.parsed.info; const info = coerce(parsedInfo, TokenAccountInfo); - return { - pubkey: accountInfo.pubkey, - mint: new PublicKey(info.mint), - owner: new PublicKey(info.owner), - amount: info.amount, - isInitialized: info.isInitialized, - isNative: info.isNative, - }; + return { info, pubkey: accountInfo.pubkey }; }); status = FetchStatus.Fetched; } catch (error) { diff --git a/explorer/src/validators/accounts/token.ts b/explorer/src/validators/accounts/token.ts index 9a1fa5c7e4..33150bee52 100644 --- a/explorer/src/validators/accounts/token.ts +++ b/explorer/src/validators/accounts/token.ts @@ -8,6 +8,7 @@ import { boolean, string, array, + pick, nullable, } from "superstruct"; import { Pubkey } from "validators/pubkey"; @@ -16,7 +17,9 @@ export type TokenAccountType = StructType; export const TokenAccountType = enums(["mint", "account", "multisig"]); export type TokenAccountInfo = StructType; -export const TokenAccountInfo = object({ +export const TokenAccountInfo = pick({ + isInitialized: boolean(), + isNative: boolean(), mint: Pubkey, owner: Pubkey, amount: optional(number()), // TODO remove when ui amount is deployed @@ -28,9 +31,7 @@ export const TokenAccountInfo = object({ }) ), delegate: nullable(optional(Pubkey)), - isInitialized: boolean(), - isNative: boolean(), - delegatedAmount: number(), + delegatedAmount: optional(number()), }); export type MintAccountInfo = StructType;