bridge_ui: migration eligible asset detecting

Change-Id: I40a828eb81d333145c5768a6bff7fb8da3eeaa27
This commit is contained in:
Chase Moran 2021-09-14 16:44:05 -04:00 committed by Evan Gray
parent 0498454193
commit c5c18edd27
3 changed files with 76 additions and 26 deletions

View File

@ -1,6 +1,6 @@
import { CircularProgress, TextField, Typography } from "@material-ui/core"; import { CircularProgress, TextField, Typography } from "@material-ui/core";
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles"; import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
import { Autocomplete } from "@material-ui/lab"; import { Alert, Autocomplete } from "@material-ui/lab";
import { createFilterOptions } from "@material-ui/lab/Autocomplete"; import { createFilterOptions } from "@material-ui/lab/Autocomplete";
import { TokenInfo } from "@solana/spl-token-registry"; import { TokenInfo } from "@solana/spl-token-registry";
import React, { useCallback, useMemo } from "react"; import React, { useCallback, useMemo } from "react";
@ -8,7 +8,10 @@ import useMetaplexData from "../../hooks/useMetaplexData";
import useSolanaTokenMap from "../../hooks/useSolanaTokenMap"; import useSolanaTokenMap from "../../hooks/useSolanaTokenMap";
import { DataWrapper } from "../../store/helpers"; import { DataWrapper } from "../../store/helpers";
import { ParsedTokenAccount } from "../../store/transferSlice"; import { ParsedTokenAccount } from "../../store/transferSlice";
import { WORMHOLE_V1_MINT_AUTHORITY } from "../../utils/consts"; import {
MIGRATION_ASSET_MAP,
WORMHOLE_V1_MINT_AUTHORITY,
} from "../../utils/consts";
import { shortenAddress } from "../../utils/solana"; import { shortenAddress } from "../../utils/solana";
import NFTViewer from "./NFTViewer"; import NFTViewer from "./NFTViewer";
import RefreshButtonWrapper from "./RefreshButtonWrapper"; import RefreshButtonWrapper from "./RefreshButtonWrapper";
@ -146,6 +149,10 @@ export default function SolanaSourceTokenSelector(
[props.mintAccounts] [props.mintAccounts]
); );
const isMigrationEligible = useCallback((address: string) => {
return !!MIGRATION_ASSET_MAP.get(address);
}, []);
const renderAccount = useCallback( const renderAccount = useCallback(
(account: ParsedTokenAccount) => { (account: ParsedTokenAccount) => {
const mintPrettyString = shortenAddress(account.mintKey); const mintPrettyString = shortenAddress(account.mintKey);
@ -189,9 +196,24 @@ export default function SolanaSourceTokenSelector(
</div> </div>
); );
return isWormholev1(account.mintKey) ? v1Warning : content; const migrationRender = (
<div>
<Alert severity="warning">
<Typography variant="body2">
This is a legacy asset eligible for migration.
</Typography>
<div>{content}</div>
</Alert>
</div>
);
return isMigrationEligible(account.mintKey)
? migrationRender
: isWormholev1(account.mintKey)
? v1Warning
: content;
}, },
[getLogo, getSymbol, getName, classes, isWormholev1] [getLogo, getSymbol, getName, classes, isWormholev1, isMigrationEligible]
); );
//The autocomplete doesn't rerender the option label unless the value changes. //The autocomplete doesn't rerender the option label unless the value changes.
@ -218,8 +240,10 @@ export default function SolanaSourceTokenSelector(
}, [metaplex.data, nft, props.accounts]); }, [metaplex.data, nft, props.accounts]);
const isOptionDisabled = useMemo(() => { const isOptionDisabled = useMemo(() => {
return (value: ParsedTokenAccount) => isWormholev1(value.mintKey); return (value: ParsedTokenAccount) => {
}, [isWormholev1]); return isWormholev1(value.mintKey) && !isMigrationEligible(value.mintKey);
};
}, [isWormholev1, isMigrationEligible]);
const onAutocompleteChange = useCallback( const onAutocompleteChange = useCallback(
(event, newValue) => { (event, newValue) => {

View File

@ -1,7 +1,9 @@
import { CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
import { Button, makeStyles, MenuItem, TextField } from "@material-ui/core"; import { Button, makeStyles, MenuItem, TextField } from "@material-ui/core";
import { Restore } from "@material-ui/icons"; import { Restore } from "@material-ui/icons";
import { useCallback } from "react"; import { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router";
import useIsWalletReady from "../../hooks/useIsWalletReady"; import useIsWalletReady from "../../hooks/useIsWalletReady";
import useTokenBlacklistWarning from "../../hooks/useTokenBlacklistWarning"; import useTokenBlacklistWarning from "../../hooks/useTokenBlacklistWarning";
import { import {
@ -18,7 +20,7 @@ import {
setAmount, setAmount,
setSourceChain, setSourceChain,
} from "../../store/transferSlice"; } from "../../store/transferSlice";
import { CHAINS } from "../../utils/consts"; import { CHAINS, MIGRATION_ASSET_MAP } from "../../utils/consts";
import ButtonWithLoader from "../ButtonWithLoader"; import ButtonWithLoader from "../ButtonWithLoader";
import KeyAndBalance from "../KeyAndBalance"; import KeyAndBalance from "../KeyAndBalance";
import StepDescription from "../StepDescription"; import StepDescription from "../StepDescription";
@ -37,11 +39,16 @@ function Source({
}) { }) {
const classes = useStyles(); const classes = useStyles();
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory();
const sourceChain = useSelector(selectTransferSourceChain); const sourceChain = useSelector(selectTransferSourceChain);
const parsedTokenAccount = useSelector( const parsedTokenAccount = useSelector(
selectTransferSourceParsedTokenAccount selectTransferSourceParsedTokenAccount
); );
const hasParsedTokenAccount = !!parsedTokenAccount; const hasParsedTokenAccount = !!parsedTokenAccount;
const isMigrationAsset =
sourceChain === CHAIN_ID_SOLANA &&
!!parsedTokenAccount &&
!!MIGRATION_ASSET_MAP.get(parsedTokenAccount.mintKey);
const uiAmountString = useSelector(selectTransferSourceBalanceString); const uiAmountString = useSelector(selectTransferSourceBalanceString);
const amount = useSelector(selectTransferAmount); const amount = useSelector(selectTransferAmount);
const error = useSelector(selectTransferSourceError); const error = useSelector(selectTransferSourceError);
@ -52,6 +59,10 @@ function Source({
sourceChain, sourceChain,
parsedTokenAccount?.mintKey parsedTokenAccount?.mintKey
); );
const handleMigrationClick = useCallback(() => {
parsedTokenAccount?.mintKey &&
history.push("/migrate/" + parsedTokenAccount.mintKey);
}, [history, parsedTokenAccount]);
const handleSourceChange = useCallback( const handleSourceChange = useCallback(
(event) => { (event) => {
dispatch(setSourceChain(event.target.value)); dispatch(setSourceChain(event.target.value));
@ -102,25 +113,38 @@ function Source({
<TokenSelector disabled={shouldLockFields} /> <TokenSelector disabled={shouldLockFields} />
</div> </div>
) : null} ) : null}
{hasParsedTokenAccount ? ( {isMigrationAsset ? (
<TextField <Button
label="Amount" variant="contained"
type="number" color="primary"
fullWidth fullWidth
className={classes.transferField} onClick={handleMigrationClick}
value={amount} >
onChange={handleAmountChange} Go to Migration Page
disabled={shouldLockFields} </Button>
/> ) : (
) : null} <>
<ButtonWithLoader {hasParsedTokenAccount ? (
disabled={!isSourceComplete} <TextField
onClick={handleNextClick} label="Amount"
showLoader={false} type="number"
error={statusMessage || error || tokenBlacklistWarning} fullWidth
> className={classes.transferField}
Next value={amount}
</ButtonWithLoader> onChange={handleAmountChange}
disabled={shouldLockFields}
/>
) : null}
<ButtonWithLoader
disabled={!isSourceComplete}
onClick={handleNextClick}
showLoader={false}
error={statusMessage || error || tokenBlacklistWarning}
>
Next
</ButtonWithLoader>
</>
)}
</> </>
); );
} }

View File

@ -371,7 +371,9 @@ function useGetAvailableTokens(nft: boolean = false) {
setSolanaMintAccountsError(undefined); setSolanaMintAccountsError(undefined);
const mintAddresses = tokenAccounts.data.map((x) => x.mintKey); const mintAddresses = tokenAccounts.data.map((x) => x.mintKey);
//This is a known wormhole v1 token on testnet //This is a known wormhole v1 token on testnet
//mintAddresses.push("4QixXecTZ4zdZGa39KH8gVND5NZ2xcaB12wiBhE4S7rn"); // mintAddresses.push("4QixXecTZ4zdZGa39KH8gVND5NZ2xcaB12wiBhE4S7rn");
//SOLT devnet token
// mintAddresses.push("2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ");
const connection = new Connection(SOLANA_HOST, "finalized"); const connection = new Connection(SOLANA_HOST, "finalized");
getMultipleAccountsRPC( getMultipleAccountsRPC(