Fix owned token validation in explorer (#11581)

This commit is contained in:
Justin Starry 2020-08-12 20:11:38 +08:00 committed by GitHub
parent c300748884
commit 8ddb116659
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 45 deletions

View File

@ -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<string, TokenAccountData>();
for (const token of tokens) {
const mappedTokens = new Map<string, number>();
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(
<tr key={mintAddress}>
<td>
<Address pubkey={new PublicKey(mintAddress)} link />
</td>
<td>{balance}</td>
<td>{totalByMint}</td>
</tr>
);
});

View File

@ -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 <TokenHistoryTable tokens={tokens} />;
}
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 }) => {

View File

@ -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) {

View File

@ -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<typeof TokenAccountType>;
export const TokenAccountType = enums(["mint", "account", "multisig"]);
export type TokenAccountInfo = StructType<typeof TokenAccountInfo>;
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<typeof MintAccountInfo>;