parent
2d2e221c37
commit
5396bf48c5
|
@ -15,7 +15,9 @@
|
|||
"bs58": "^4.0.1",
|
||||
"buffer-layout": "^1.2.0",
|
||||
"immutable-tuple": "^0.4.10",
|
||||
"mdi-material-ui": "^6.17.0",
|
||||
"notistack": "^0.9.17",
|
||||
"qrcode.react": "^1.0.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.1",
|
||||
|
|
|
@ -19,7 +19,7 @@ import { makeStyles } from '@material-ui/core/styles';
|
|||
import { abbreviateAddress } from '../utils/utils';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import SendIcon from '@material-ui/icons/Send';
|
||||
import ReceiveIcon from '@material-ui/icons/CallReceived';
|
||||
import ReceiveIcon from '@material-ui/icons/WorkOutline';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import AddIcon from '@material-ui/icons/Add';
|
||||
|
@ -28,6 +28,7 @@ import IconButton from '@material-ui/core/IconButton';
|
|||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import AddTokenDialog from './AddTokenDialog';
|
||||
import SendDialog from './SendDialog';
|
||||
import DepositDialog from './DepositDialog';
|
||||
import {
|
||||
refreshAccountInfo,
|
||||
useSolanaExplorerUrlSuffix,
|
||||
|
@ -109,6 +110,7 @@ function BalanceListItem({ publicKey }) {
|
|||
const classes = useStyles();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [sendDialogOpen, setSendDialogOpen] = useState(false);
|
||||
const [depositDialogOpen, setDepositDialogOpen] = useState(false);
|
||||
|
||||
if (!balanceInfo) {
|
||||
return <LoadingIndicator delay={0} />;
|
||||
|
@ -138,6 +140,7 @@ function BalanceListItem({ publicKey }) {
|
|||
variant="outlined"
|
||||
color="primary"
|
||||
startIcon={<ReceiveIcon />}
|
||||
onClick={() => setDepositDialogOpen(true)}
|
||||
>
|
||||
Receive
|
||||
</Button>
|
||||
|
@ -184,6 +187,12 @@ function BalanceListItem({ publicKey }) {
|
|||
balanceInfo={balanceInfo}
|
||||
publicKey={publicKey}
|
||||
/>
|
||||
<DepositDialog
|
||||
open={depositDialogOpen}
|
||||
onClose={() => setDepositDialogOpen(false)}
|
||||
balanceInfo={balanceInfo}
|
||||
publicKey={publicKey}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import React, { useRef } from 'react';
|
||||
import { Button, TextField } from '@material-ui/core';
|
||||
import CopyIcon from 'mdi-material-ui/ContentCopy';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
button: {
|
||||
marginLeft: theme.spacing(3),
|
||||
whiteSpace: 'nowrap',
|
||||
marginTop: theme.spacing(2),
|
||||
},
|
||||
buttonIcon: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
}));
|
||||
|
||||
export default function CopyableDisplay({
|
||||
value,
|
||||
label,
|
||||
autoFocus,
|
||||
buttonProps,
|
||||
}) {
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const textareaRef = useRef();
|
||||
const classes = useStyles();
|
||||
const copyLink = () => {
|
||||
let textArea = textareaRef.current;
|
||||
if (textArea) {
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
enqueueSnackbar('Address copied', {
|
||||
variant: 'success',
|
||||
autoHideDuration: 2500,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<TextField
|
||||
inputRef={(ref) => (textareaRef.current = ref)}
|
||||
multiline
|
||||
autoFocus={autoFocus}
|
||||
value={value}
|
||||
readOnly
|
||||
onFocus={(e) => e.currentTarget.select()}
|
||||
className={classes.textArea}
|
||||
fullWidth
|
||||
label={label}
|
||||
spellCheck={false}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={copyLink}
|
||||
className={classes.button}
|
||||
{...buttonProps}
|
||||
>
|
||||
<CopyIcon className={classes.buttonIcon} /> {'Copy'}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
import React from 'react';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogForm from './DialogForm';
|
||||
import { abbreviateAddress } from '../utils/utils';
|
||||
import { Button, Typography } from '@material-ui/core';
|
||||
import CopyableDisplay from './CopyableDisplay';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import QrcodeIcon from 'mdi-material-ui/Qrcode';
|
||||
import QRCode from 'qrcode.react';
|
||||
|
||||
export default function DepositDialog({
|
||||
open,
|
||||
onClose,
|
||||
publicKey,
|
||||
balanceInfo,
|
||||
}) {
|
||||
let { mint, tokenName, tokenSymbol, owner } = balanceInfo;
|
||||
|
||||
return (
|
||||
<DialogForm open={open} onClose={onClose}>
|
||||
<DialogTitle>
|
||||
Deposit {tokenName ?? abbreviateAddress(mint)}
|
||||
{tokenSymbol ? ` (${tokenSymbol})` : null}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
{publicKey.equals(owner) ? (
|
||||
<Typography>
|
||||
This address can only be used to receive SOL. Do not send other
|
||||
tokens to this address.
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography>
|
||||
This address can only be used to receive {tokenSymbol}. Do not send
|
||||
SOL to this address.
|
||||
</Typography>
|
||||
)}
|
||||
<CopyableDisplay
|
||||
value={publicKey.toBase58()}
|
||||
label={'Deposit Address'}
|
||||
autoFocus
|
||||
/>
|
||||
<Qrcode value={publicKey.toBase58()} />
|
||||
</DialogContent>
|
||||
</DialogForm>
|
||||
);
|
||||
}
|
||||
|
||||
const useQrCodeStyles = makeStyles((theme) => ({
|
||||
qrcodeButton: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
qrcodeIcon: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
qrcodeContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
function Qrcode({ value }) {
|
||||
const [showQrcode, setShowQrcode] = React.useState(false);
|
||||
|
||||
const classes = useQrCodeStyles();
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => setShowQrcode(!showQrcode)}
|
||||
className={classes.qrcodeButton}
|
||||
>
|
||||
<QrcodeIcon className={classes.qrcodeIcon} />
|
||||
{showQrcode ? 'Hide QR Code' : 'Show QR Code'}
|
||||
</Button>
|
||||
{showQrcode && (
|
||||
<div className={classes.qrcodeContainer}>
|
||||
<QRCode value={value} size={256} includeMargin />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
21
yarn.lock
21
yarn.lock
|
@ -7338,6 +7338,11 @@ md5.js@^1.3.4:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
mdi-material-ui@^6.17.0:
|
||||
version "6.17.0"
|
||||
resolved "https://registry.yarnpkg.com/mdi-material-ui/-/mdi-material-ui-6.17.0.tgz#da69f0b7d7c6fc2255e6007ed8b8ca858c1aede7"
|
||||
integrity sha512-eOprRu31lklPIS1WGe3cM0G/8glKl1WKRvewxjDrgXH2Ryxxg7uQ+uwDUwUEONtLku0p2ZOLzgXUIy2uRy5rLg==
|
||||
|
||||
mdn-data@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
||||
|
@ -9186,7 +9191,7 @@ prompts@^2.0.1:
|
|||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.4"
|
||||
|
||||
prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
|
@ -9270,6 +9275,20 @@ q@^1.1.2:
|
|||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
|
||||
|
||||
qr.js@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
|
||||
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
|
||||
|
||||
qrcode.react@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-1.0.0.tgz#7e8889db3b769e555e8eb463d4c6de221c36d5de"
|
||||
integrity sha512-jBXleohRTwvGBe1ngV+62QvEZ/9IZqQivdwzo9pJM4LQMoCM2VnvNBnKdjvGnKyDZ/l0nCDgsPod19RzlPvm/Q==
|
||||
dependencies:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.0"
|
||||
qr.js "0.0.0"
|
||||
|
||||
qs@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
|
|
Loading…
Reference in New Issue