bridge_ui: transfer confirmation dialog
Change-Id: I232f60354388b0b88ba3ab43d9bbd9cb5ceb255e
This commit is contained in:
parent
6cd43fdbc8
commit
e5642a788d
|
@ -24,10 +24,22 @@ import KeyAndBalance from "../KeyAndBalance";
|
|||
import ShowTx from "../ShowTx";
|
||||
import StepDescription from "../StepDescription";
|
||||
import TransactionProgress from "../TransactionProgress";
|
||||
import SendConfirmationDialog from "./SendConfirmationDialog";
|
||||
import WaitingForWalletMessage from "./WaitingForWalletMessage";
|
||||
|
||||
function Send() {
|
||||
const { handleClick, disabled, showLoader } = useHandleTransfer();
|
||||
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
|
||||
const handleTransferClick = useCallback(() => {
|
||||
setIsConfirmOpen(true);
|
||||
}, []);
|
||||
const handleConfirmClick = useCallback(() => {
|
||||
handleClick();
|
||||
setIsConfirmOpen(false);
|
||||
}, [handleClick]);
|
||||
const handleConfirmClose = useCallback(() => {
|
||||
setIsConfirmOpen(false);
|
||||
}, []);
|
||||
|
||||
const sourceChain = useSelector(selectTransferSourceChain);
|
||||
const sourceAsset = useSelector(selectTransferSourceAsset);
|
||||
|
@ -143,14 +155,21 @@ function Send() {
|
|||
</ButtonWithLoader>
|
||||
</>
|
||||
) : (
|
||||
<ButtonWithLoader
|
||||
disabled={isDisabled}
|
||||
onClick={handleClick}
|
||||
showLoader={showLoader}
|
||||
error={errorMessage}
|
||||
>
|
||||
Transfer
|
||||
</ButtonWithLoader>
|
||||
<>
|
||||
<ButtonWithLoader
|
||||
disabled={isDisabled}
|
||||
onClick={handleTransferClick}
|
||||
showLoader={showLoader}
|
||||
error={errorMessage}
|
||||
>
|
||||
Transfer
|
||||
</ButtonWithLoader>
|
||||
<SendConfirmationDialog
|
||||
open={isConfirmOpen}
|
||||
onClick={handleConfirmClick}
|
||||
onClose={handleConfirmClose}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<WaitingForWalletMessage />
|
||||
{transferTx ? <ShowTx chainId={sourceChain} tx={transferTx} /> : null}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { ArrowDownward } from "@material-ui/icons";
|
||||
import { Alert } from "@material-ui/lab";
|
||||
import { useSelector } from "react-redux";
|
||||
import {
|
||||
selectTransferSourceChain,
|
||||
selectTransferSourceParsedTokenAccount,
|
||||
} from "../../store/selectors";
|
||||
import { CHAINS_BY_ID } from "../../utils/consts";
|
||||
import SmartAddress from "../SmartAddress";
|
||||
import { useTargetInfo } from "./Target";
|
||||
|
||||
function SendConfirmationContent() {
|
||||
const sourceChain = useSelector(selectTransferSourceChain);
|
||||
const sourceParsedTokenAccount = useSelector(
|
||||
selectTransferSourceParsedTokenAccount
|
||||
);
|
||||
const { targetChain, targetAsset, symbol, tokenName, logo } = useTargetInfo();
|
||||
return (
|
||||
<>
|
||||
{targetAsset ? (
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<SmartAddress
|
||||
variant="h6"
|
||||
chainId={sourceChain}
|
||||
parsedTokenAccount={sourceParsedTokenAccount}
|
||||
/>
|
||||
<div>
|
||||
<Typography variant="caption">
|
||||
{CHAINS_BY_ID[sourceChain].name}
|
||||
</Typography>
|
||||
</div>
|
||||
<div style={{ paddingTop: 4 }}>
|
||||
<ArrowDownward fontSize="inherit" />
|
||||
</div>
|
||||
<SmartAddress
|
||||
variant="h6"
|
||||
chainId={targetChain}
|
||||
address={targetAsset}
|
||||
symbol={symbol}
|
||||
tokenName={tokenName}
|
||||
logo={logo}
|
||||
/>
|
||||
<div>
|
||||
<Typography variant="caption">
|
||||
{CHAINS_BY_ID[targetChain].name}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
<Alert severity="warning" variant="outlined" style={{ marginTop: 8 }}>
|
||||
Once the transfer transaction is submitted, the transfer must be
|
||||
completed by redeeming the tokens on the target chain. Please ensure
|
||||
that the token listed above is the desired token and confirm that
|
||||
markets exist on the target chain.
|
||||
</Alert>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default function SendConfirmationDialog({
|
||||
open,
|
||||
onClick,
|
||||
onClose,
|
||||
}: {
|
||||
open: boolean;
|
||||
onClick: () => void;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<DialogTitle>Are you sure?</DialogTitle>
|
||||
<DialogContent>
|
||||
<SendConfirmationContent />
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="outlined" onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="contained" color="primary" onClick={onClick}>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import { makeStyles, Typography } from "@material-ui/core";
|
||||
import { useSelector } from "react-redux";
|
||||
import {
|
||||
selectSourceWalletAddress,
|
||||
selectTransferAmount,
|
||||
selectTransferSourceChain,
|
||||
selectTransferSourceParsedTokenAccount,
|
||||
|
@ -21,6 +22,7 @@ export default function SourcePreview() {
|
|||
const sourceParsedTokenAccount = useSelector(
|
||||
selectTransferSourceParsedTokenAccount
|
||||
);
|
||||
const sourceWalletAddress = useSelector(selectSourceWalletAddress);
|
||||
const sourceAmount = useSelector(selectTransferAmount);
|
||||
|
||||
const explainerContent =
|
||||
|
@ -31,7 +33,13 @@ export default function SourcePreview() {
|
|||
chainId={sourceChain}
|
||||
parsedTokenAccount={sourceParsedTokenAccount}
|
||||
/>
|
||||
<span>from {CHAINS_BY_ID[sourceChain].name}</span>
|
||||
{sourceWalletAddress ? (
|
||||
<>
|
||||
<span>from</span>
|
||||
<SmartAddress chainId={sourceChain} address={sourceWalletAddress} />
|
||||
</>
|
||||
) : null}
|
||||
<span>on {CHAINS_BY_ID[sourceChain].name}</span>
|
||||
</>
|
||||
) : (
|
||||
""
|
||||
|
|
|
@ -43,15 +43,7 @@ const useStyles = makeStyles((theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
function Target() {
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const isBeta = useBetaContext();
|
||||
const sourceChain = useSelector(selectTransferSourceChain);
|
||||
const chains = useMemo(
|
||||
() => CHAINS.filter((c) => c.id !== sourceChain),
|
||||
[sourceChain]
|
||||
);
|
||||
export const useTargetInfo = () => {
|
||||
const targetChain = useSelector(selectTransferTargetChain);
|
||||
const targetAddressHex = useSelector(selectTransferTargetAddressHex);
|
||||
const targetAsset = useSelector(selectTransferTargetAsset);
|
||||
|
@ -68,6 +60,36 @@ function Target() {
|
|||
(targetAsset && metadata.data?.get(targetAsset)?.logo) || undefined;
|
||||
const readableTargetAddress =
|
||||
hexToNativeString(targetAddressHex, targetChain) || "";
|
||||
return useMemo(
|
||||
() => ({
|
||||
targetChain,
|
||||
targetAsset,
|
||||
tokenName,
|
||||
symbol,
|
||||
logo,
|
||||
readableTargetAddress,
|
||||
}),
|
||||
[targetChain, targetAsset, tokenName, symbol, logo, readableTargetAddress]
|
||||
);
|
||||
};
|
||||
|
||||
function Target() {
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const isBeta = useBetaContext();
|
||||
const sourceChain = useSelector(selectTransferSourceChain);
|
||||
const chains = useMemo(
|
||||
() => CHAINS.filter((c) => c.id !== sourceChain),
|
||||
[sourceChain]
|
||||
);
|
||||
const {
|
||||
targetChain,
|
||||
targetAsset,
|
||||
tokenName,
|
||||
symbol,
|
||||
logo,
|
||||
readableTargetAddress,
|
||||
} = useTargetInfo();
|
||||
const uiAmountString = useSelector(selectTransferTargetBalanceString);
|
||||
const transferAmount = useSelector(selectTransferAmount);
|
||||
const error = useSelector(selectTransferTargetError);
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
import { hexToNativeString } from "@certusone/wormhole-sdk";
|
||||
import { makeStyles, Typography } from "@material-ui/core";
|
||||
import { useSelector } from "react-redux";
|
||||
import {
|
||||
selectTransferTargetAddressHex,
|
||||
selectTransferTargetChain,
|
||||
} from "../../store/selectors";
|
||||
import { CHAINS_BY_ID } from "../../utils/consts";
|
||||
import SmartAddress from "../SmartAddress";
|
||||
import { useTargetInfo } from "./Target";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
description: {
|
||||
|
@ -16,15 +11,32 @@ const useStyles = makeStyles((theme) => ({
|
|||
|
||||
export default function TargetPreview() {
|
||||
const classes = useStyles();
|
||||
const targetChain = useSelector(selectTransferTargetChain);
|
||||
const targetAddress = useSelector(selectTransferTargetAddressHex);
|
||||
const targetAddressNative = hexToNativeString(targetAddress, targetChain);
|
||||
const {
|
||||
targetChain,
|
||||
readableTargetAddress,
|
||||
targetAsset,
|
||||
symbol,
|
||||
tokenName,
|
||||
logo,
|
||||
} = useTargetInfo();
|
||||
|
||||
const explainerContent =
|
||||
targetChain && targetAddressNative ? (
|
||||
targetChain && readableTargetAddress ? (
|
||||
<>
|
||||
{targetAsset ? (
|
||||
<>
|
||||
<span>and receive</span>
|
||||
<SmartAddress
|
||||
chainId={targetChain}
|
||||
address={targetAsset}
|
||||
symbol={symbol}
|
||||
tokenName={tokenName}
|
||||
logo={logo}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<span>to</span>
|
||||
<SmartAddress chainId={targetChain} address={targetAddressNative} />
|
||||
<SmartAddress chainId={targetChain} address={readableTargetAddress} />
|
||||
<span>on {CHAINS_BY_ID[targetChain].name}</span>
|
||||
</>
|
||||
) : (
|
||||
|
|
Loading…
Reference in New Issue