parent
5396bf48c5
commit
4b9c87b2e1
|
@ -12,7 +12,7 @@ import {
|
||||||
import LoadingIndicator from './LoadingIndicator';
|
import LoadingIndicator from './LoadingIndicator';
|
||||||
import Collapse from '@material-ui/core/Collapse';
|
import Collapse from '@material-ui/core/Collapse';
|
||||||
import { Typography } from '@material-ui/core';
|
import { Typography } from '@material-ui/core';
|
||||||
import Link from '@material-ui/core/Link';
|
import TokenInfoDialog from './TokenInfoDialog';
|
||||||
import ExpandLess from '@material-ui/icons/ExpandLess';
|
import ExpandLess from '@material-ui/icons/ExpandLess';
|
||||||
import ExpandMore from '@material-ui/icons/ExpandMore';
|
import ExpandMore from '@material-ui/icons/ExpandMore';
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
@ -25,14 +25,12 @@ import Toolbar from '@material-ui/core/Toolbar';
|
||||||
import AddIcon from '@material-ui/icons/Add';
|
import AddIcon from '@material-ui/icons/Add';
|
||||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||||
import IconButton from '@material-ui/core/IconButton';
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import InfoIcon from '@material-ui/icons/Info';
|
||||||
import Tooltip from '@material-ui/core/Tooltip';
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
import AddTokenDialog from './AddTokenDialog';
|
import AddTokenDialog from './AddTokenDialog';
|
||||||
import SendDialog from './SendDialog';
|
import SendDialog from './SendDialog';
|
||||||
import DepositDialog from './DepositDialog';
|
import DepositDialog from './DepositDialog';
|
||||||
import {
|
import { refreshAccountInfo } from '../utils/connection';
|
||||||
refreshAccountInfo,
|
|
||||||
useSolanaExplorerUrlSuffix,
|
|
||||||
} from '../utils/connection';
|
|
||||||
|
|
||||||
const balanceFormat = new Intl.NumberFormat(undefined, {
|
const balanceFormat = new Intl.NumberFormat(undefined, {
|
||||||
minimumFractionDigits: 4,
|
minimumFractionDigits: 4,
|
||||||
|
@ -106,17 +104,17 @@ const useStyles = makeStyles((theme) => ({
|
||||||
|
|
||||||
function BalanceListItem({ publicKey }) {
|
function BalanceListItem({ publicKey }) {
|
||||||
const balanceInfo = useBalanceInfo(publicKey);
|
const balanceInfo = useBalanceInfo(publicKey);
|
||||||
const urlSuffix = useSolanaExplorerUrlSuffix();
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [sendDialogOpen, setSendDialogOpen] = useState(false);
|
const [sendDialogOpen, setSendDialogOpen] = useState(false);
|
||||||
const [depositDialogOpen, setDepositDialogOpen] = useState(false);
|
const [depositDialogOpen, setDepositDialogOpen] = useState(false);
|
||||||
|
const [tokenInfoDialogOpen, setTokenInfoDialogOpen] = useState(false);
|
||||||
|
|
||||||
if (!balanceInfo) {
|
if (!balanceInfo) {
|
||||||
return <LoadingIndicator delay={0} />;
|
return <LoadingIndicator delay={0} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { amount, decimals, mint, tokenName, tokenSymbol } = balanceInfo;
|
let { amount, decimals, mint, tokenName, tokenSymbol, owner } = balanceInfo;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -125,7 +123,8 @@ function BalanceListItem({ publicKey }) {
|
||||||
primary={
|
primary={
|
||||||
<>
|
<>
|
||||||
{balanceFormat.format(amount / Math.pow(10, decimals))}{' '}
|
{balanceFormat.format(amount / Math.pow(10, decimals))}{' '}
|
||||||
{tokenSymbol ?? abbreviateAddress(mint)}
|
{tokenName ?? abbreviateAddress(mint)}
|
||||||
|
{tokenSymbol ? ` (${tokenSymbol})` : null}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
secondary={publicKey.toBase58()}
|
secondary={publicKey.toBase58()}
|
||||||
|
@ -136,6 +135,16 @@ function BalanceListItem({ publicKey }) {
|
||||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
<div className={classes.itemDetails}>
|
<div className={classes.itemDetails}>
|
||||||
<div className={classes.buttonContainer}>
|
<div className={classes.buttonContainer}>
|
||||||
|
{!publicKey.equals(owner) && (
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="inherit"
|
||||||
|
startIcon={<InfoIcon />}
|
||||||
|
onClick={() => setTokenInfoDialogOpen(true)}
|
||||||
|
>
|
||||||
|
Token Info
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
@ -153,32 +162,6 @@ function BalanceListItem({ publicKey }) {
|
||||||
Send
|
Send
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Typography variant="body2" className={classes.address}>
|
|
||||||
Deposit Address: {publicKey.toBase58()}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2">
|
|
||||||
Token Name: {tokenName ?? 'Unknown'}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2">
|
|
||||||
Token Symbol: {tokenSymbol ?? 'Unknown'}
|
|
||||||
</Typography>
|
|
||||||
{mint ? (
|
|
||||||
<Typography variant="body2" className={classes.address}>
|
|
||||||
Token Address: {mint.toBase58()}
|
|
||||||
</Typography>
|
|
||||||
) : null}
|
|
||||||
<Typography variant="body2">
|
|
||||||
<Link
|
|
||||||
href={
|
|
||||||
`https://explorer.solana.com/account/${publicKey.toBase58()}` +
|
|
||||||
urlSuffix
|
|
||||||
}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>
|
|
||||||
View on Solana Explorer
|
|
||||||
</Link>
|
|
||||||
</Typography>
|
|
||||||
</div>
|
</div>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
<SendDialog
|
<SendDialog
|
||||||
|
@ -193,6 +176,12 @@ function BalanceListItem({ publicKey }) {
|
||||||
balanceInfo={balanceInfo}
|
balanceInfo={balanceInfo}
|
||||||
publicKey={publicKey}
|
publicKey={publicKey}
|
||||||
/>
|
/>
|
||||||
|
<TokenInfoDialog
|
||||||
|
open={tokenInfoDialogOpen}
|
||||||
|
onClose={() => setTokenInfoDialogOpen(false)}
|
||||||
|
balanceInfo={balanceInfo}
|
||||||
|
publicKey={publicKey}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ export default function CopyableDisplay({
|
||||||
label,
|
label,
|
||||||
autoFocus,
|
autoFocus,
|
||||||
buttonProps,
|
buttonProps,
|
||||||
|
helperText,
|
||||||
}) {
|
}) {
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
const textareaRef = useRef();
|
const textareaRef = useRef();
|
||||||
|
@ -34,8 +35,8 @@ export default function CopyableDisplay({
|
||||||
if (textArea) {
|
if (textArea) {
|
||||||
textArea.select();
|
textArea.select();
|
||||||
document.execCommand('copy');
|
document.execCommand('copy');
|
||||||
enqueueSnackbar('Address copied', {
|
enqueueSnackbar(`Copied ${label}`, {
|
||||||
variant: 'success',
|
variant: 'info',
|
||||||
autoHideDuration: 2500,
|
autoHideDuration: 2500,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -52,6 +53,7 @@ export default function CopyableDisplay({
|
||||||
onFocus={(e) => e.currentTarget.select()}
|
onFocus={(e) => e.currentTarget.select()}
|
||||||
className={classes.textArea}
|
className={classes.textArea}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
helperText={helperText}
|
||||||
label={label}
|
label={label}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { Typography } from '@material-ui/core';
|
||||||
|
import Link from '@material-ui/core/Link';
|
||||||
|
import React from 'react';
|
||||||
|
import { useSolanaExplorerUrlSuffix } from '../utils/connection';
|
||||||
|
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||||
|
import DialogContent from '@material-ui/core/DialogContent';
|
||||||
|
import DialogForm from './DialogForm';
|
||||||
|
import { abbreviateAddress } from '../utils/utils';
|
||||||
|
import CopyableDisplay from './CopyableDisplay';
|
||||||
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme) => ({
|
||||||
|
explorerLink: {
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
minWidth: 600,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default function TokenInfoDialog({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
publicKey,
|
||||||
|
balanceInfo,
|
||||||
|
}) {
|
||||||
|
let { mint, tokenName, tokenSymbol } = balanceInfo;
|
||||||
|
const urlSuffix = useSolanaExplorerUrlSuffix();
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DialogForm open={open} onClose={onClose}>
|
||||||
|
<DialogTitle>
|
||||||
|
{tokenName ?? abbreviateAddress(mint)}
|
||||||
|
{tokenSymbol ? ` (${tokenSymbol})` : null}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent className={classes.container}>
|
||||||
|
<Typography className={classes.warning}>
|
||||||
|
Information about {tokenName ?? abbreviateAddress(mint)}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" className={classes.explorerLink}>
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
`https://explorer.solana.com/account/${publicKey.toBase58()}` +
|
||||||
|
urlSuffix
|
||||||
|
}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>
|
||||||
|
View on Solana Explorer
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
{!!mint && (
|
||||||
|
<CopyableDisplay
|
||||||
|
value={mint.toBase58()}
|
||||||
|
label={'Token Mint Address'}
|
||||||
|
autoFocus
|
||||||
|
helperText={
|
||||||
|
<>
|
||||||
|
This is <strong>not</strong> your deposit address
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!!tokenName && (
|
||||||
|
<CopyableDisplay value={tokenName} label={'Token Name'} />
|
||||||
|
)}
|
||||||
|
{!!tokenSymbol && (
|
||||||
|
<CopyableDisplay value={tokenSymbol} label={'Token Symbol'} />
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
</DialogForm>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue