bridge_ui: evm token account fetch on selection
Change-Id: Ia9c9c54d61ab90b40616472628238ec1b5e00c0e
This commit is contained in:
parent
5ed2b2a06d
commit
b783a44fb0
|
@ -7,10 +7,15 @@ import {
|
||||||
import { WormholeAbi__factory } from "@certusone/wormhole-sdk/lib/ethers-contracts/abi";
|
import { WormholeAbi__factory } from "@certusone/wormhole-sdk/lib/ethers-contracts/abi";
|
||||||
import { getAddress as getEthAddress } from "@ethersproject/address";
|
import { getAddress as getEthAddress } from "@ethersproject/address";
|
||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import { useEthereumProvider } from "../../contexts/EthereumProviderContext";
|
import { useEthereumProvider } from "../../contexts/EthereumProviderContext";
|
||||||
import useIsWalletReady from "../../hooks/useIsWalletReady";
|
import useIsWalletReady from "../../hooks/useIsWalletReady";
|
||||||
import { DataWrapper } from "../../store/helpers";
|
import { DataWrapper } from "../../store/helpers";
|
||||||
import { NFTParsedTokenAccount } from "../../store/nftSlice";
|
import { NFTParsedTokenAccount } from "../../store/nftSlice";
|
||||||
|
import {
|
||||||
|
selectNFTSourceParsedTokenAccount,
|
||||||
|
selectTransferSourceParsedTokenAccount,
|
||||||
|
} from "../../store/selectors";
|
||||||
import { ParsedTokenAccount } from "../../store/transferSlice";
|
import { ParsedTokenAccount } from "../../store/transferSlice";
|
||||||
import {
|
import {
|
||||||
getMigrationAssetMap,
|
getMigrationAssetMap,
|
||||||
|
@ -60,6 +65,29 @@ export default function EvmTokenPicker(
|
||||||
} = props;
|
} = props;
|
||||||
const { provider, signerAddress } = useEthereumProvider();
|
const { provider, signerAddress } = useEthereumProvider();
|
||||||
const { isReady } = useIsWalletReady(chainId);
|
const { isReady } = useIsWalletReady(chainId);
|
||||||
|
const selectedTokenAccount: NFTParsedTokenAccount | undefined = useSelector(
|
||||||
|
nft
|
||||||
|
? selectNFTSourceParsedTokenAccount
|
||||||
|
: selectTransferSourceParsedTokenAccount
|
||||||
|
);
|
||||||
|
|
||||||
|
const shouldDisplayBalance = useCallback(
|
||||||
|
(tokenAccount: NFTParsedTokenAccount) => {
|
||||||
|
const selectedMintMatch =
|
||||||
|
selectedTokenAccount &&
|
||||||
|
selectedTokenAccount.mintKey.toLowerCase() ===
|
||||||
|
tokenAccount.mintKey.toLowerCase();
|
||||||
|
//added just in case we start displaying NFT balances again.
|
||||||
|
const selectedTokenIdMatch =
|
||||||
|
selectedTokenAccount &&
|
||||||
|
selectedTokenAccount.tokenId === tokenAccount.tokenId;
|
||||||
|
return !!(
|
||||||
|
tokenAccount.isNativeAsset || //The native asset amount isn't taken from covalent, so can be trusted.
|
||||||
|
(selectedMintMatch && selectedTokenIdMatch)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[selectedTokenAccount]
|
||||||
|
);
|
||||||
|
|
||||||
const isMigrationEligible = useCallback(
|
const isMigrationEligible = useCallback(
|
||||||
(address: string) => {
|
(address: string) => {
|
||||||
|
@ -118,23 +146,48 @@ export default function EvmTokenPicker(
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//For now, just swallow this one.
|
//For now, just swallow this one.
|
||||||
}
|
}
|
||||||
|
let newAccount = null;
|
||||||
|
try {
|
||||||
|
//Covalent balances tend to be stale, so we make an attempt to correct it at selection time.
|
||||||
|
if (!account.isNativeAsset) {
|
||||||
|
newAccount = await getAddress(account.mintKey, account.tokenId);
|
||||||
|
newAccount = { ...account, ...newAccount }; //We spread over the old account so we don't lose the logo, uri, or other useful info we got from covalent.
|
||||||
|
} else {
|
||||||
|
newAccount = account;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
//swallow
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
if (!newAccount) {
|
||||||
|
//Must reject otherwise downstream checks relying on the balance may fail.
|
||||||
|
//An error is thrown so that the code above us will display the message.
|
||||||
|
throw new Error(
|
||||||
|
"Unable to retrieve required information about this token. Ensure your wallet is connected, then refresh the list."
|
||||||
|
);
|
||||||
|
}
|
||||||
const migration = isMigrationEligible(account.publicKey);
|
const migration = isMigrationEligible(account.publicKey);
|
||||||
if (v1 === true && !migration) {
|
if (v1 === true && !migration) {
|
||||||
return Promise.reject(
|
throw new Error(
|
||||||
"Wormhole v1 assets cannot be transferred with this bridge."
|
"Wormhole v1 assets cannot be transferred with this bridge."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
onChange(account);
|
onChange(newAccount);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
[chainId, onChange, provider, isMigrationEligible]
|
[chainId, onChange, provider, isMigrationEligible, getAddress]
|
||||||
);
|
);
|
||||||
|
|
||||||
const RenderComp = useCallback(
|
const RenderComp = useCallback(
|
||||||
({ account }: { account: NFTParsedTokenAccount }) => {
|
({ account }: { account: NFTParsedTokenAccount }) => {
|
||||||
return BasicAccountRender(account, isMigrationEligible, nft || false);
|
return BasicAccountRender(
|
||||||
|
account,
|
||||||
|
isMigrationEligible,
|
||||||
|
nft || false,
|
||||||
|
shouldDisplayBalance
|
||||||
|
);
|
||||||
},
|
},
|
||||||
[nft, isMigrationEligible]
|
[nft, isMigrationEligible, shouldDisplayBalance]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -110,7 +110,8 @@ export const balancePretty = (uiString: string) => {
|
||||||
export const BasicAccountRender = (
|
export const BasicAccountRender = (
|
||||||
account: NFTParsedTokenAccount,
|
account: NFTParsedTokenAccount,
|
||||||
isMigrationEligible: (address: string) => boolean,
|
isMigrationEligible: (address: string) => boolean,
|
||||||
nft: boolean
|
nft: boolean,
|
||||||
|
displayBalance?: (account: NFTParsedTokenAccount) => boolean
|
||||||
) => {
|
) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const mintPrettyString = shortenAddress(account.mintKey);
|
const mintPrettyString = shortenAddress(account.mintKey);
|
||||||
|
@ -118,7 +119,7 @@ export const BasicAccountRender = (
|
||||||
const symbol = account.symbol || "Unknown";
|
const symbol = account.symbol || "Unknown";
|
||||||
const name = account.name || "Unknown";
|
const name = account.name || "Unknown";
|
||||||
const tokenId = account.tokenId;
|
const tokenId = account.tokenId;
|
||||||
const balancePrettyString = balancePretty(account.uiAmountString);
|
const shouldDisplayBalance = !displayBalance || displayBalance(account);
|
||||||
|
|
||||||
const nftContent = (
|
const nftContent = (
|
||||||
<div className={classes.tokenOverviewContainer}>
|
<div className={classes.tokenOverviewContainer}>
|
||||||
|
@ -152,8 +153,16 @@ export const BasicAccountRender = (
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
{shouldDisplayBalance ? (
|
||||||
|
<>
|
||||||
<Typography variant="body2">{"Balance"}</Typography>
|
<Typography variant="body2">{"Balance"}</Typography>
|
||||||
<Typography variant="h6">{balancePrettyString}</Typography>
|
<Typography variant="h6">
|
||||||
|
{balancePretty(account.uiAmountString)}
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -222,6 +231,7 @@ export default function TokenPicker({
|
||||||
|
|
||||||
const openDialog = useCallback(() => {
|
const openDialog = useCallback(() => {
|
||||||
setHolderString("");
|
setHolderString("");
|
||||||
|
setSelectionError("");
|
||||||
setDialogIsOpen(true);
|
setDialogIsOpen(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -244,6 +254,13 @@ export default function TokenPicker({
|
||||||
[onChange, closeDialog]
|
[onChange, closeDialog]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const resetAccountsWrapper = useCallback(() => {
|
||||||
|
setHolderString("");
|
||||||
|
setTokenIdHolderString("");
|
||||||
|
setSelectionError("");
|
||||||
|
resetAccounts && resetAccounts();
|
||||||
|
}, [resetAccounts]);
|
||||||
|
|
||||||
const filteredOptions = useMemo(() => {
|
const filteredOptions = useMemo(() => {
|
||||||
return options.filter((option: NFTParsedTokenAccount) => {
|
return options.filter((option: NFTParsedTokenAccount) => {
|
||||||
if (!holderString) {
|
if (!holderString) {
|
||||||
|
@ -359,7 +376,7 @@ export default function TokenPicker({
|
||||||
<Typography variant="h5">Select a token</Typography>
|
<Typography variant="h5">Select a token</Typography>
|
||||||
<div className={classes.grower} />
|
<div className={classes.grower} />
|
||||||
<Tooltip title="Reload tokens">
|
<Tooltip title="Reload tokens">
|
||||||
<IconButton onClick={resetAccounts}>
|
<IconButton onClick={resetAccountsWrapper}>
|
||||||
<RefreshIcon />
|
<RefreshIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
Loading…
Reference in New Issue