|
|
@@ -1,6 +1,11 @@
|
|
|
import { CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
|
|
|
-import { CircularProgress, TextField, Typography } from "@material-ui/core";
|
|
|
-import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
|
|
|
+import {
|
|
|
+ CircularProgress,
|
|
|
+ TextField,
|
|
|
+ Typography,
|
|
|
+ createStyles,
|
|
|
+ makeStyles,
|
|
|
+} from "@material-ui/core";
|
|
|
import { Alert, Autocomplete } from "@material-ui/lab";
|
|
|
import { createFilterOptions } from "@material-ui/lab/Autocomplete";
|
|
|
import { TokenInfo } from "@solana/spl-token-registry";
|
|
|
@@ -15,21 +20,46 @@ import {
|
|
|
WORMHOLE_V1_MINT_AUTHORITY,
|
|
|
} from "../../utils/consts";
|
|
|
import { ExtractedMintInfo, shortenAddress } from "../../utils/solana";
|
|
|
+import { sortParsedTokenAccounts } from "../../utils/sort";
|
|
|
import NFTViewer from "./NFTViewer";
|
|
|
import RefreshButtonWrapper from "./RefreshButtonWrapper";
|
|
|
|
|
|
-const useStyles = makeStyles((theme: Theme) =>
|
|
|
+const useStyles = makeStyles((theme) =>
|
|
|
createStyles({
|
|
|
selectInput: { minWidth: "10rem" },
|
|
|
tokenOverviewContainer: {
|
|
|
display: "flex",
|
|
|
+ width: "100%",
|
|
|
+ alignItems: "center",
|
|
|
"& div": {
|
|
|
- margin: ".5rem",
|
|
|
+ margin: theme.spacing(1),
|
|
|
+ flexBasis: "33%",
|
|
|
+ "&$tokenImageContainer": {
|
|
|
+ maxWidth: 40,
|
|
|
+ },
|
|
|
+ "&:last-child": {
|
|
|
+ textAlign: "right",
|
|
|
+ },
|
|
|
},
|
|
|
},
|
|
|
+ tokenImageContainer: {
|
|
|
+ display: "flex",
|
|
|
+ alignItems: "center",
|
|
|
+ justifyContent: "center",
|
|
|
+ width: 40,
|
|
|
+ },
|
|
|
tokenImage: {
|
|
|
maxHeight: "2.5rem", //Eyeballing this based off the text size
|
|
|
},
|
|
|
+ v1Warning: {
|
|
|
+ width: "100%",
|
|
|
+ },
|
|
|
+ migrationAlert: {
|
|
|
+ width: "100%",
|
|
|
+ "& .MuiAlert-message": {
|
|
|
+ width: "100%",
|
|
|
+ },
|
|
|
+ },
|
|
|
})
|
|
|
);
|
|
|
|
|
|
@@ -169,39 +199,39 @@ export default function SolanaSourceTokenSelector(
|
|
|
const name = getName(account) || "--";
|
|
|
|
|
|
const content = (
|
|
|
- <>
|
|
|
- <div className={classes.tokenOverviewContainer}>
|
|
|
- <div>
|
|
|
- {uri && <img alt="" className={classes.tokenImage} src={uri} />}
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <Typography variant="subtitle1">{symbol}</Typography>
|
|
|
- <Typography variant="subtitle2">{name}</Typography>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- {account.isNativeAsset ? (
|
|
|
- <Typography>{"Native"}</Typography>
|
|
|
- ) : (
|
|
|
- <>
|
|
|
- <Typography variant="body1">
|
|
|
- {"Mint : " + mintPrettyString}
|
|
|
- </Typography>
|
|
|
- <Typography variant="body1">
|
|
|
- {"Account :" + accountAddressPrettyString}
|
|
|
- </Typography>
|
|
|
- </>
|
|
|
- )}
|
|
|
- </div>
|
|
|
+ <div className={classes.tokenOverviewContainer}>
|
|
|
+ <div className={classes.tokenImageContainer}>
|
|
|
+ {uri && <img alt="" className={classes.tokenImage} src={uri} />}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <Typography variant="subtitle1">{symbol}</Typography>
|
|
|
+ <Typography variant="subtitle2">{name}</Typography>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {account.isNativeAsset ? (
|
|
|
+ <Typography>{"Native"}</Typography>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ <Typography variant="body1">
|
|
|
+ {"Mint : " + mintPrettyString}
|
|
|
+ </Typography>
|
|
|
+ <Typography variant="body1">
|
|
|
+ {"Account :" + accountAddressPrettyString}
|
|
|
+ </Typography>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ {nft ? null : (
|
|
|
<div>
|
|
|
<Typography variant="body2">{"Balance"}</Typography>
|
|
|
<Typography variant="h6">{account.uiAmountString}</Typography>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
);
|
|
|
|
|
|
const v1Warning = (
|
|
|
- <div>
|
|
|
+ <div className={classes.v1Warning}>
|
|
|
<Typography variant="body2">
|
|
|
Wormhole v1 tokens are not eligible for transfer.
|
|
|
</Typography>
|
|
|
@@ -210,7 +240,7 @@ export default function SolanaSourceTokenSelector(
|
|
|
);
|
|
|
|
|
|
const migrationRender = (
|
|
|
- <div>
|
|
|
+ <div className={classes.migrationAlert}>
|
|
|
<Alert severity="warning">
|
|
|
<Typography variant="body2">
|
|
|
This is a legacy asset eligible for migration.
|
|
|
@@ -226,7 +256,15 @@ export default function SolanaSourceTokenSelector(
|
|
|
? v1Warning
|
|
|
: content;
|
|
|
},
|
|
|
- [getLogo, getSymbol, getName, classes, isWormholev1, isMigrationEligible]
|
|
|
+ [
|
|
|
+ getLogo,
|
|
|
+ getSymbol,
|
|
|
+ getName,
|
|
|
+ classes,
|
|
|
+ isWormholev1,
|
|
|
+ isMigrationEligible,
|
|
|
+ nft,
|
|
|
+ ]
|
|
|
);
|
|
|
|
|
|
//The autocomplete doesn't rerender the option label unless the value changes.
|
|
|
@@ -244,18 +282,26 @@ export default function SolanaSourceTokenSelector(
|
|
|
//This exists to remove NFTs from the list of potential options. It requires reading the metaplex data, so it would be
|
|
|
//difficult to do before this point.
|
|
|
const filteredOptions = useMemo(() => {
|
|
|
- return props.accounts.filter((x) => {
|
|
|
- const zeroBalance = x.amount === "0";
|
|
|
- if (zeroBalance) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- const isNFT =
|
|
|
- x.decimals === 0 &&
|
|
|
- metaplex.data?.get(x.mintKey)?.data?.uri &&
|
|
|
- mintAccounts?.data?.get(x.mintKey)?.supply === "1";
|
|
|
- return nft ? isNFT : !isNFT;
|
|
|
- });
|
|
|
- }, [mintAccounts?.data, metaplex.data, nft, props.accounts]);
|
|
|
+ const tokenList = props.accounts
|
|
|
+ .filter((x) => {
|
|
|
+ const zeroBalance = x.amount === "0";
|
|
|
+ if (zeroBalance) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const isNFT =
|
|
|
+ x.decimals === 0 &&
|
|
|
+ metaplex.data?.get(x.mintKey)?.data?.uri &&
|
|
|
+ mintAccounts?.data?.get(x.mintKey)?.supply === "1";
|
|
|
+ return nft ? isNFT : !isNFT;
|
|
|
+ })
|
|
|
+ .map((account) => ({
|
|
|
+ ...account,
|
|
|
+ symbol: account.symbol || getSymbol(account) || undefined,
|
|
|
+ }));
|
|
|
+ tokenList.sort(sortParsedTokenAccounts);
|
|
|
+ return tokenList;
|
|
|
+ }, [mintAccounts?.data, metaplex.data, nft, props.accounts, getSymbol]);
|
|
|
+ console.log(filteredOptions);
|
|
|
|
|
|
const isOptionDisabled = useMemo(() => {
|
|
|
return (value: ParsedTokenAccount) => {
|
|
|
@@ -314,7 +360,6 @@ export default function SolanaSourceTokenSelector(
|
|
|
<Autocomplete
|
|
|
autoComplete
|
|
|
autoHighlight
|
|
|
- autoSelect
|
|
|
blurOnSelect
|
|
|
clearOnBlur
|
|
|
fullWidth={false}
|