explorer: 11938 display owner in token distribution table (#11953)
* include owner on largest token distribution tab * run format:fix
This commit is contained in:
parent
839b926e0b
commit
53a900a28c
|
@ -1,11 +1,12 @@
|
|||
import React from "react";
|
||||
import { PublicKey, TokenAccountBalancePair } from "@solana/web3.js";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { LoadingCard } from "components/common/LoadingCard";
|
||||
import { ErrorCard } from "components/common/ErrorCard";
|
||||
import { Address } from "components/common/Address";
|
||||
import {
|
||||
useTokenLargestTokens,
|
||||
useFetchTokenLargestAccounts,
|
||||
TokenAccountBalancePairWithOwner,
|
||||
} from "providers/mints/largest";
|
||||
import { FetchStatus } from "providers/cache";
|
||||
import { TokenRegistry } from "tokenRegistry";
|
||||
|
@ -64,11 +65,12 @@ export function TokenLargestAccountsCard({ pubkey }: { pubkey: PublicKey }) {
|
|||
</div>
|
||||
|
||||
<div className="table-responsive mb-0">
|
||||
<table className="table table-sm table-nowrap card-table">
|
||||
<table className="table table-sm card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-muted">Rank</th>
|
||||
<th className="text-muted">Address</th>
|
||||
<th className="text-muted">Owner</th>
|
||||
<th className="text-muted text-right">Balance {unitLabel}</th>
|
||||
<th className="text-muted text-right">% of Total Supply</th>
|
||||
</tr>
|
||||
|
@ -86,7 +88,7 @@ export function TokenLargestAccountsCard({ pubkey }: { pubkey: PublicKey }) {
|
|||
}
|
||||
|
||||
const renderAccountRow = (
|
||||
account: TokenAccountBalancePair,
|
||||
account: TokenAccountBalancePairWithOwner,
|
||||
index: number,
|
||||
supply: number
|
||||
) => {
|
||||
|
@ -99,8 +101,13 @@ const renderAccountRow = (
|
|||
<td>
|
||||
<span className="badge badge-soft-gray badge-pill">{index + 1}</span>
|
||||
</td>
|
||||
<td className="td">
|
||||
<Address pubkey={account.address} link truncate />
|
||||
</td>
|
||||
<td>
|
||||
<Address pubkey={account.address} link />
|
||||
{account.owner && (
|
||||
<Address pubkey={account.owner} alignRight link truncate />
|
||||
)}
|
||||
</td>
|
||||
<td className="text-right">{account.uiAmount}</td>
|
||||
<td className="text-right">{percent}</td>
|
||||
|
|
|
@ -127,6 +127,7 @@ async function fetchAccountInfo(
|
|||
try {
|
||||
const info = coerce(result.data.parsed, ParsedInfo);
|
||||
const parsed = coerce(info, TokenAccount);
|
||||
|
||||
data = {
|
||||
program: "spl-token",
|
||||
parsed,
|
||||
|
|
|
@ -7,10 +7,14 @@ import {
|
|||
PublicKey,
|
||||
Connection,
|
||||
TokenAccountBalancePair,
|
||||
ParsedAccountData,
|
||||
} from "@solana/web3.js";
|
||||
import { TokenAccountInfo, TokenAccount } from "validators/accounts/token";
|
||||
import { ParsedInfo } from "validators";
|
||||
import { coerce } from "superstruct";
|
||||
|
||||
type LargestAccounts = {
|
||||
largest: TokenAccountBalancePair[];
|
||||
largest: TokenAccountBalancePairWithOwner[];
|
||||
};
|
||||
|
||||
type State = Cache.State<LargestAccounts>;
|
||||
|
@ -38,6 +42,13 @@ export function LargestAccountsProvider({ children }: ProviderProps) {
|
|||
);
|
||||
}
|
||||
|
||||
type OptionalOwner = {
|
||||
owner?: PublicKey;
|
||||
};
|
||||
|
||||
export type TokenAccountBalancePairWithOwner = TokenAccountBalancePair &
|
||||
OptionalOwner;
|
||||
|
||||
async function fetchLargestAccounts(
|
||||
dispatch: Dispatch,
|
||||
pubkey: PublicKey,
|
||||
|
@ -59,6 +70,33 @@ async function fetchLargestAccounts(
|
|||
await new Connection(url, "single").getTokenLargestAccounts(pubkey)
|
||||
).value,
|
||||
};
|
||||
|
||||
data.largest = await Promise.all(
|
||||
data.largest.map(
|
||||
async (account): Promise<TokenAccountBalancePairWithOwner> => {
|
||||
try {
|
||||
const accountInfo = (
|
||||
await new Connection(url, "single").getParsedAccountInfo(
|
||||
account.address
|
||||
)
|
||||
).value;
|
||||
if (accountInfo && "parsed" in accountInfo.data) {
|
||||
const info = coerceParsedAccountInfo(accountInfo.data);
|
||||
return {
|
||||
...account,
|
||||
owner: info.owner,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
if (cluster !== Cluster.Custom) {
|
||||
Sentry.captureException(error, { tags: { url } });
|
||||
}
|
||||
}
|
||||
return account;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
fetchStatus = FetchStatus.Fetched;
|
||||
} catch (error) {
|
||||
if (cluster !== Cluster.Custom) {
|
||||
|
@ -105,3 +143,15 @@ export function useTokenLargestTokens(
|
|||
|
||||
return context.entries[address];
|
||||
}
|
||||
|
||||
function coerceParsedAccountInfo(
|
||||
parsedData: ParsedAccountData
|
||||
): TokenAccountInfo {
|
||||
try {
|
||||
const data = coerce(parsedData.parsed, ParsedInfo);
|
||||
const parsed = coerce(data, TokenAccount);
|
||||
return coerce(parsed.info, TokenAccountInfo);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue