2020-08-08 23:02:01 +08:00
|
|
|
import React from "react";
|
|
|
|
import { Account, useFetchAccountInfo } from "providers/accounts";
|
|
|
|
import {
|
|
|
|
TokenAccount,
|
|
|
|
MintAccountInfo,
|
|
|
|
TokenAccountInfo,
|
|
|
|
MultisigAccountInfo,
|
|
|
|
} from "validators/accounts/token";
|
|
|
|
import { coerce } from "superstruct";
|
|
|
|
import { TableCardBody } from "components/common/TableCardBody";
|
|
|
|
import { Address } from "components/common/Address";
|
|
|
|
import { UnknownAccountCard } from "./UnknownAccountCard";
|
2020-08-13 01:31:21 +08:00
|
|
|
import { useFetchTokenSupply, useTokenSupply } from "providers/mints/supply";
|
|
|
|
import { FetchStatus } from "providers/cache";
|
2020-08-08 23:02:01 +08:00
|
|
|
|
|
|
|
export function TokenAccountSection({
|
|
|
|
account,
|
|
|
|
tokenAccount,
|
|
|
|
}: {
|
|
|
|
account: Account;
|
|
|
|
tokenAccount: TokenAccount;
|
|
|
|
}) {
|
|
|
|
try {
|
|
|
|
switch (tokenAccount.type) {
|
|
|
|
case "mint": {
|
|
|
|
const info = coerce(tokenAccount.info, MintAccountInfo);
|
|
|
|
return <MintAccountCard account={account} info={info} />;
|
|
|
|
}
|
|
|
|
case "account": {
|
|
|
|
const info = coerce(tokenAccount.info, TokenAccountInfo);
|
|
|
|
return <TokenAccountCard account={account} info={info} />;
|
|
|
|
}
|
|
|
|
case "multisig": {
|
|
|
|
const info = coerce(tokenAccount.info, MultisigAccountInfo);
|
|
|
|
return <MultisigAccountCard account={account} info={info} />;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {}
|
|
|
|
return <UnknownAccountCard account={account} />;
|
|
|
|
}
|
|
|
|
|
|
|
|
function MintAccountCard({
|
|
|
|
account,
|
|
|
|
info,
|
|
|
|
}: {
|
|
|
|
account: Account;
|
|
|
|
info: MintAccountInfo;
|
|
|
|
}) {
|
2020-08-13 01:31:21 +08:00
|
|
|
const mintAddress = account.pubkey.toBase58();
|
|
|
|
const fetchInfo = useFetchAccountInfo();
|
|
|
|
const supply = useTokenSupply(mintAddress);
|
|
|
|
const fetchSupply = useFetchTokenSupply();
|
|
|
|
const refreshSupply = () => fetchSupply(account.pubkey);
|
|
|
|
const refresh = () => {
|
|
|
|
fetchInfo(account.pubkey);
|
|
|
|
refreshSupply();
|
|
|
|
};
|
|
|
|
|
|
|
|
let renderSupply;
|
|
|
|
const supplyTotal = supply?.data?.uiAmount;
|
|
|
|
if (supplyTotal === undefined) {
|
|
|
|
if (!supply || supply?.status === FetchStatus.Fetching) {
|
|
|
|
renderSupply = (
|
|
|
|
<>
|
|
|
|
<span className="spinner-grow spinner-grow-sm mr-2"></span>
|
|
|
|
Loading
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
renderSupply = "Fetch failed";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
renderSupply = supplyTotal;
|
|
|
|
}
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (!supply) refreshSupply();
|
|
|
|
}, [mintAddress]); // eslint-disable-line react-hooks/exhaustive-deps
|
2020-08-08 23:02:01 +08:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="card">
|
|
|
|
<div className="card-header">
|
|
|
|
<h3 className="card-header-title mb-0 d-flex align-items-center">
|
|
|
|
Token Mint Account
|
|
|
|
</h3>
|
2020-08-13 01:31:21 +08:00
|
|
|
<button className="btn btn-white btn-sm" onClick={refresh}>
|
2020-08-08 23:02:01 +08:00
|
|
|
<span className="fe fe-refresh-cw mr-2"></span>
|
|
|
|
Refresh
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<TableCardBody>
|
|
|
|
<tr>
|
|
|
|
<td>Address</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
<Address pubkey={account.pubkey} alignRight raw />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
2020-08-13 01:31:21 +08:00
|
|
|
<td>Total Supply</td>
|
|
|
|
<td className="text-lg-right">{renderSupply}</td>
|
2020-08-08 23:02:01 +08:00
|
|
|
</tr>
|
|
|
|
<tr>
|
2020-08-13 01:31:21 +08:00
|
|
|
<td>Decimals</td>
|
|
|
|
<td className="text-lg-right">{info.decimals}</td>
|
2020-08-08 23:02:01 +08:00
|
|
|
</tr>
|
2020-08-13 01:31:21 +08:00
|
|
|
{!info.isInitialized && (
|
|
|
|
<tr>
|
|
|
|
<td>Status</td>
|
|
|
|
<td className="text-lg-right">Uninitialized</td>
|
|
|
|
</tr>
|
|
|
|
)}
|
2020-08-13 02:06:49 +08:00
|
|
|
{info.owner && (
|
2020-08-08 23:02:01 +08:00
|
|
|
<tr>
|
|
|
|
<td>Owner</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
<Address pubkey={info.owner} alignRight link />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
)}
|
|
|
|
</TableCardBody>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function TokenAccountCard({
|
|
|
|
account,
|
|
|
|
info,
|
|
|
|
}: {
|
|
|
|
account: Account;
|
|
|
|
info: TokenAccountInfo;
|
|
|
|
}) {
|
|
|
|
const refresh = useFetchAccountInfo();
|
|
|
|
|
|
|
|
let balance;
|
|
|
|
if ("amount" in info) {
|
|
|
|
balance = info.amount;
|
|
|
|
} else {
|
|
|
|
balance = info.tokenAmount?.uiAmount;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="card">
|
|
|
|
<div className="card-header">
|
|
|
|
<h3 className="card-header-title mb-0 d-flex align-items-center">
|
|
|
|
Token Account
|
|
|
|
</h3>
|
|
|
|
<button
|
|
|
|
className="btn btn-white btn-sm"
|
|
|
|
onClick={() => refresh(account.pubkey)}
|
|
|
|
>
|
|
|
|
<span className="fe fe-refresh-cw mr-2"></span>
|
|
|
|
Refresh
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<TableCardBody>
|
|
|
|
<tr>
|
|
|
|
<td>Address</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
<Address pubkey={account.pubkey} alignRight raw />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Mint</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
<Address pubkey={info.mint} alignRight link />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Owner</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
<Address pubkey={info.owner} alignRight link />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Balance (tokens)</td>
|
|
|
|
<td className="text-lg-right">{balance}</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Status</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
{info.isInitialized ? "Initialized" : "Uninitialized"}
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</TableCardBody>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function MultisigAccountCard({
|
|
|
|
account,
|
|
|
|
info,
|
|
|
|
}: {
|
|
|
|
account: Account;
|
|
|
|
info: MultisigAccountInfo;
|
|
|
|
}) {
|
|
|
|
const refresh = useFetchAccountInfo();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="card">
|
|
|
|
<div className="card-header">
|
|
|
|
<h3 className="card-header-title mb-0 d-flex align-items-center">
|
|
|
|
Multisig Account
|
|
|
|
</h3>
|
|
|
|
<button
|
|
|
|
className="btn btn-white btn-sm"
|
|
|
|
onClick={() => refresh(account.pubkey)}
|
|
|
|
>
|
|
|
|
<span className="fe fe-refresh-cw mr-2"></span>
|
|
|
|
Refresh
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<TableCardBody>
|
|
|
|
<tr>
|
|
|
|
<td>Address</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
<Address pubkey={account.pubkey} alignRight raw />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Required Signers</td>
|
|
|
|
<td className="text-lg-right">{info.numRequiredSigners}</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Valid Signers</td>
|
|
|
|
<td className="text-lg-right">{info.numValidSigners}</td>
|
|
|
|
</tr>
|
|
|
|
{info.signers.map((signer) => (
|
|
|
|
<tr key={signer.toString()}>
|
|
|
|
<td>Signer</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
<Address pubkey={signer} alignRight link />
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
))}
|
|
|
|
<tr>
|
|
|
|
<td>Status</td>
|
|
|
|
<td className="text-lg-right">
|
|
|
|
{info.isInitialized ? "Initialized" : "Uninitialized"}
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</TableCardBody>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|