bridge_ui: add bsc migration support
Change-Id: Ia11a78be9318406ab72d7c9a58c6e74699379cff
This commit is contained in:
parent
e8b51439fe
commit
350244e8e4
|
@ -1,4 +1,8 @@
|
|||
import { CHAIN_ID_ETH, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
CHAIN_ID_BSC,
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_SOLANA,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
AppBar,
|
||||
Button,
|
||||
|
@ -28,7 +32,7 @@ import Attest from "./components/Attest";
|
|||
import Footer from "./components/Footer";
|
||||
import Home from "./components/Home";
|
||||
import Migration from "./components/Migration";
|
||||
import EthereumQuickMigrate from "./components/Migration/EthereumQuickMigrate";
|
||||
import EvmQuickMigrate from "./components/Migration/EvmQuickMigrate";
|
||||
import NFT from "./components/NFT";
|
||||
import NFTOriginVerifier from "./components/NFTOriginVerifier";
|
||||
import Recovery from "./components/Recovery";
|
||||
|
@ -124,6 +128,7 @@ function App() {
|
|||
const isBeta = useBetaContext();
|
||||
const isHomepage = useRouteMatch({ path: "/", exact: true });
|
||||
const isStats = useRouteMatch({ path: "/stats", exact: true });
|
||||
const isMigrate = useRouteMatch({ path: "/migrate" });
|
||||
const isOriginVerifier = useRouteMatch({
|
||||
path: "/nft-origin-verifier",
|
||||
exact: true,
|
||||
|
@ -244,7 +249,7 @@ function App() {
|
|||
</AppBar>
|
||||
) : null}
|
||||
<div className={classes.content}>
|
||||
{isHomepage || isOriginVerifier || isStats ? null : (
|
||||
{isHomepage || isOriginVerifier || isStats || isMigrate ? null : (
|
||||
<Container maxWidth="md" style={{ paddingBottom: 24 }}>
|
||||
<Tabs
|
||||
value={
|
||||
|
@ -284,8 +289,14 @@ function App() {
|
|||
<Route exact path="/migrate/Ethereum/:legacyAsset/">
|
||||
<Migration chainId={CHAIN_ID_ETH} />
|
||||
</Route>
|
||||
<Route exact path="/migrate/BinanceSmartChain/:legacyAsset/">
|
||||
<Migration chainId={CHAIN_ID_BSC} />
|
||||
</Route>
|
||||
<Route exact path="/migrate/Ethereum/">
|
||||
<EthereumQuickMigrate />
|
||||
<EvmQuickMigrate chainId={CHAIN_ID_ETH} />
|
||||
</Route>
|
||||
<Route exact path="/migrate/BinanceSmartChain/">
|
||||
<EvmQuickMigrate chainId={CHAIN_ID_BSC} />
|
||||
</Route>
|
||||
<Route exact path="/stats">
|
||||
<Stats />
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import {
|
||||
CHAIN_ID_ETH,
|
||||
TokenImplementation__factory,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import { ChainId, TokenImplementation__factory } from "@certusone/wormhole-sdk";
|
||||
import { Signer } from "@ethersproject/abstract-signer";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import {
|
||||
|
@ -20,7 +17,7 @@ import { useEthereumProvider } from "../../contexts/EthereumProviderContext";
|
|||
import useEthereumMigratorInformation from "../../hooks/useEthereumMigratorInformation";
|
||||
import useIsWalletReady from "../../hooks/useIsWalletReady";
|
||||
import { COLORS } from "../../muiTheme";
|
||||
import { ETH_MIGRATION_ASSET_MAP } from "../../utils/consts";
|
||||
import { CHAINS, getMigrationAssetMap } from "../../utils/consts";
|
||||
import ButtonWithLoader from "../ButtonWithLoader";
|
||||
import EthereumSignerKey from "../EthereumSignerKey";
|
||||
import ShowTx from "../ShowTx";
|
||||
|
@ -89,10 +86,12 @@ export const compareWithDecimalOffset = (
|
|||
}
|
||||
};
|
||||
|
||||
function EthereumMigrationLineItem({
|
||||
function EvmMigrationLineItem({
|
||||
chainId,
|
||||
migratorAddress,
|
||||
onLoadComplete,
|
||||
}: {
|
||||
chainId: ChainId;
|
||||
migratorAddress: string;
|
||||
onLoadComplete: () => void;
|
||||
}) {
|
||||
|
@ -175,7 +174,7 @@ function EthereumMigrationLineItem({
|
|||
Successfully migrated your tokens. They will become available once
|
||||
this transaction confirms.
|
||||
</Typography>
|
||||
<ShowTx chainId={CHAIN_ID_ETH} tx={{ id: transaction, block: 1 }} />
|
||||
<ShowTx chainId={chainId} tx={{ id: transaction, block: 1 }} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -189,10 +188,7 @@ function EthereumMigrationLineItem({
|
|||
<Typography className={classes.balance}>
|
||||
{poolInfo.data.fromWalletBalance}
|
||||
</Typography>
|
||||
<SmartAddress
|
||||
chainId={CHAIN_ID_ETH}
|
||||
address={poolInfo.data.fromAddress}
|
||||
/>
|
||||
<SmartAddress chainId={chainId} address={poolInfo.data.fromAddress} />
|
||||
</div>
|
||||
<div>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
|
@ -207,10 +203,7 @@ function EthereumMigrationLineItem({
|
|||
<Typography className={classes.balance}>
|
||||
{poolInfo.data.fromWalletBalance}
|
||||
</Typography>
|
||||
<SmartAddress
|
||||
chainId={CHAIN_ID_ETH}
|
||||
address={poolInfo.data.toAddress}
|
||||
/>
|
||||
<SmartAddress chainId={chainId} address={poolInfo.data.toAddress} />
|
||||
</div>
|
||||
<div className={classes.convertButton}>
|
||||
<ButtonWithLoader
|
||||
|
@ -261,13 +254,14 @@ const getAddressBalances = async (
|
|||
}
|
||||
};
|
||||
|
||||
export default function EthereumQuickMigrate() {
|
||||
export default function EvmQuickMigrate({ chainId }: { chainId: ChainId }) {
|
||||
const classes = useStyles();
|
||||
const { signer, signerAddress } = useEthereumProvider();
|
||||
const { isReady } = useIsWalletReady(CHAIN_ID_ETH);
|
||||
const { isReady } = useIsWalletReady(chainId);
|
||||
const migrationMap = useMemo(() => getMigrationAssetMap(chainId), [chainId]);
|
||||
const eligibleTokens = useMemo(
|
||||
() => Array.from(ETH_MIGRATION_ASSET_MAP.keys()),
|
||||
[]
|
||||
() => Array.from(migrationMap.keys()),
|
||||
[migrationMap]
|
||||
);
|
||||
const [migrators, setMigrators] = useState<string[] | null>(null);
|
||||
const [migratorsError, setMigratorsError] = useState("");
|
||||
|
@ -297,8 +291,7 @@ export default function EthereumQuickMigrate() {
|
|||
const migratorAddresses = [];
|
||||
for (const tokenAddress of result.keys()) {
|
||||
if (result.get(tokenAddress) && result.get(tokenAddress)?.gt(0)) {
|
||||
const migratorAddress =
|
||||
ETH_MIGRATION_ASSET_MAP.get(tokenAddress);
|
||||
const migratorAddress = migrationMap.get(tokenAddress);
|
||||
if (migratorAddress) {
|
||||
migratorAddresses.push(migratorAddress);
|
||||
}
|
||||
|
@ -323,15 +316,18 @@ export default function EthereumQuickMigrate() {
|
|||
cancelled = true;
|
||||
};
|
||||
}
|
||||
}, [isReady, signer, signerAddress, eligibleTokens]);
|
||||
}, [isReady, signer, signerAddress, eligibleTokens, migrationMap]);
|
||||
|
||||
const hasEligibleAssets = migrators && migrators.length > 0;
|
||||
const chainName = CHAINS[chainId]?.name;
|
||||
|
||||
const content = (
|
||||
<div className={classes.containerDiv}>
|
||||
<Typography variant="h5">
|
||||
This page allows you to convert certain wrapped tokens on Ethereum into
|
||||
Wormhole V2 tokens.
|
||||
{`This page allows you to convert certain wrapped tokens ${
|
||||
chainName ? "on " + chainName : ""
|
||||
} into
|
||||
Wormhole V2 tokens.`}
|
||||
</Typography>
|
||||
<EthereumSignerKey />
|
||||
{!isReady ? (
|
||||
|
@ -351,8 +347,9 @@ export default function EthereumQuickMigrate() {
|
|||
<div className={classes.spacer} />
|
||||
{migrators?.map((address) => {
|
||||
return (
|
||||
<EthereumMigrationLineItem
|
||||
<EvmMigrationLineItem
|
||||
key={address}
|
||||
chainId={chainId}
|
||||
migratorAddress={address}
|
||||
onLoadComplete={reportLoadComplete}
|
||||
/>
|
|
@ -1,4 +1,4 @@
|
|||
import { CHAIN_ID_ETH } from "@certusone/wormhole-sdk";
|
||||
import { ChainId } from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
CircularProgress,
|
||||
makeStyles,
|
||||
|
@ -27,15 +27,17 @@ const useStyles = makeStyles((theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
export default function EthereumWorkflow({
|
||||
export default function EvmWorkflow({
|
||||
chainId,
|
||||
migratorAddress,
|
||||
}: {
|
||||
chainId: ChainId;
|
||||
migratorAddress: string;
|
||||
}) {
|
||||
const classes = useStyles();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const { signer, signerAddress } = useEthereumProvider();
|
||||
const { isReady } = useIsWalletReady(CHAIN_ID_ETH);
|
||||
const { isReady } = useIsWalletReady(chainId);
|
||||
const [toggleRefresh, setToggleRefresh] = useState(false);
|
||||
const forceRefresh = useCallback(
|
||||
() => setToggleRefresh((prevState) => !prevState),
|
||||
|
@ -144,20 +146,20 @@ export default function EthereumWorkflow({
|
|||
//TODO tokenName
|
||||
const toTokenPretty = (
|
||||
<SmartAddress
|
||||
chainId={CHAIN_ID_ETH}
|
||||
chainId={chainId}
|
||||
address={poolInfo.data?.toAddress}
|
||||
symbol={poolInfo.data?.toSymbol}
|
||||
/>
|
||||
);
|
||||
const fromTokenPretty = (
|
||||
<SmartAddress
|
||||
chainId={CHAIN_ID_ETH}
|
||||
chainId={chainId}
|
||||
address={poolInfo.data?.fromAddress}
|
||||
symbol={poolInfo.data?.fromSymbol}
|
||||
/>
|
||||
);
|
||||
const poolPretty = (
|
||||
<SmartAddress chainId={CHAIN_ID_ETH} address={poolInfo.data?.poolAddress} />
|
||||
<SmartAddress chainId={chainId} address={poolInfo.data?.poolAddress} />
|
||||
);
|
||||
|
||||
const fatalError = poolInfo.error
|
||||
|
@ -218,7 +220,7 @@ export default function EthereumWorkflow({
|
|||
Successfully migrated your tokens! They will be available once this
|
||||
transaction confirms.
|
||||
</Typography>
|
||||
<ShowTx tx={{ id: transaction, block: 1 }} chainId={CHAIN_ID_ETH} />
|
||||
<ShowTx tx={{ id: transaction, block: 1 }} chainId={chainId} />
|
||||
</>
|
||||
) : null}
|
||||
</>
|
|
@ -7,10 +7,7 @@ import {
|
|||
} from "@material-ui/core";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import {
|
||||
ETH_MIGRATION_ASSET_MAP,
|
||||
MIGRATION_ASSET_MAP,
|
||||
} from "../../utils/consts";
|
||||
import { getMigrationAssetMap, MIGRATION_ASSET_MAP } from "../../utils/consts";
|
||||
import SolanaWorkflow from "./SolanaWorkflow";
|
||||
import { withRouter } from "react-router";
|
||||
import { COLORS } from "../../muiTheme";
|
||||
|
@ -18,8 +15,9 @@ import {
|
|||
ChainId,
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_SOLANA,
|
||||
CHAIN_ID_BSC,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import EthereumWorkflow from "./EthereumWorkflow";
|
||||
import EvmWorkflow from "./EvmWorkflow";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
mainPaper: {
|
||||
|
@ -91,7 +89,8 @@ const SolanaRoot: React.FC<Migration> = (props) => {
|
|||
|
||||
const EthereumRoot: React.FC<Migration> = (props) => {
|
||||
const legacyAsset: string = props.match.params.legacyAsset;
|
||||
const targetPool = ETH_MIGRATION_ASSET_MAP.get(legacyAsset);
|
||||
const assetMap = getMigrationAssetMap(props.chainId);
|
||||
const targetPool = assetMap.get(legacyAsset);
|
||||
|
||||
let content = null;
|
||||
if (!legacyAsset || !targetPool) {
|
||||
|
@ -101,7 +100,9 @@ const EthereumRoot: React.FC<Migration> = (props) => {
|
|||
</Typography>
|
||||
);
|
||||
} else {
|
||||
content = <EthereumWorkflow migratorAddress={targetPool} />;
|
||||
content = (
|
||||
<EvmWorkflow migratorAddress={targetPool} chainId={props.chainId} />
|
||||
);
|
||||
}
|
||||
|
||||
return content;
|
||||
|
@ -113,7 +114,7 @@ const MigrationRoot: React.FC<Migration> = (props) => {
|
|||
|
||||
if (props.chainId === CHAIN_ID_SOLANA) {
|
||||
content = <SolanaRoot {...props} />;
|
||||
} else if (props.chainId === CHAIN_ID_ETH) {
|
||||
} else if (props.chainId === CHAIN_ID_ETH || props.chainId === CHAIN_ID_BSC) {
|
||||
content = <EthereumRoot {...props} />;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import { CovalentData } from "../../hooks/useGetSourceParsedTokenAccounts";
|
|||
import { DataWrapper } from "../../store/helpers";
|
||||
import { ParsedTokenAccount } from "../../store/transferSlice";
|
||||
import {
|
||||
ETH_MIGRATION_ASSET_MAP,
|
||||
getMigrationAssetMap,
|
||||
WORMHOLE_V1_ETH_ADDRESS,
|
||||
} from "../../utils/consts";
|
||||
import {
|
||||
|
@ -94,8 +94,9 @@ const isWormholev1 = (provider: any, address: string, chainId: ChainId) => {
|
|||
return connection.isWrappedAsset(address);
|
||||
};
|
||||
|
||||
const isMigrationEligible = (address: string) => {
|
||||
return !!ETH_MIGRATION_ASSET_MAP.get(address);
|
||||
const isMigrationEligible = (chainId: ChainId, address: string) => {
|
||||
const assetMap = getMigrationAssetMap(chainId);
|
||||
return !!assetMap.get(address);
|
||||
};
|
||||
|
||||
type EthereumSourceTokenSelectorProps = {
|
||||
|
@ -110,6 +111,7 @@ type EthereumSourceTokenSelectorProps = {
|
|||
};
|
||||
|
||||
const renderAccount = (
|
||||
chainId: ChainId,
|
||||
account: ParsedTokenAccount,
|
||||
covalentData: CovalentData | undefined,
|
||||
classes: any
|
||||
|
@ -150,7 +152,9 @@ const renderAccount = (
|
|||
</div>
|
||||
);
|
||||
|
||||
return isMigrationEligible(account.mintKey) ? migrationRender : content;
|
||||
return isMigrationEligible(chainId, account.mintKey)
|
||||
? migrationRender
|
||||
: content;
|
||||
};
|
||||
|
||||
const renderNFTAccount = (
|
||||
|
@ -534,6 +538,7 @@ export default function EthereumSourceTokenSelector(
|
|||
classes
|
||||
)
|
||||
: renderAccount(
|
||||
chainId,
|
||||
option,
|
||||
covalent?.data?.find(
|
||||
(x) => x.contract_address === option.mintKey
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import { CHAIN_ID_ETH, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
CHAIN_ID_BSC,
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_SOLANA,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import { Button, makeStyles, MenuItem, TextField } from "@material-ui/core";
|
||||
import { useCallback } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
@ -21,6 +25,7 @@ import {
|
|||
} from "../../store/transferSlice";
|
||||
import {
|
||||
BETA_CHAINS,
|
||||
BSC_MIGRATION_ASSET_MAP,
|
||||
CHAINS,
|
||||
ETH_MIGRATION_ASSET_MAP,
|
||||
MIGRATION_ASSET_MAP,
|
||||
|
@ -56,7 +61,12 @@ function Source() {
|
|||
sourceChain === CHAIN_ID_ETH &&
|
||||
!!parsedTokenAccount &&
|
||||
!!ETH_MIGRATION_ASSET_MAP.get(parsedTokenAccount.mintKey);
|
||||
const isMigrationAsset = isSolanaMigration || isEthereumMigration;
|
||||
const isBscMigration =
|
||||
sourceChain === CHAIN_ID_BSC &&
|
||||
!!parsedTokenAccount &&
|
||||
!!BSC_MIGRATION_ASSET_MAP.get(parsedTokenAccount.mintKey);
|
||||
const isMigrationAsset =
|
||||
isSolanaMigration || isEthereumMigration || isBscMigration;
|
||||
const uiAmountString = useSelector(selectTransferSourceBalanceString);
|
||||
const amount = useSelector(selectTransferAmount);
|
||||
const error = useSelector(selectTransferSourceError);
|
||||
|
@ -70,6 +80,8 @@ function Source() {
|
|||
);
|
||||
} else if (sourceChain === CHAIN_ID_ETH) {
|
||||
history.push(`/migrate/Ethereum/${parsedTokenAccount?.mintKey}`);
|
||||
} else if (sourceChain === CHAIN_ID_BSC) {
|
||||
history.push(`/migrate/BinanceSmartChain/${parsedTokenAccount?.mintKey}`);
|
||||
}
|
||||
}, [history, parsedTokenAccount, sourceChain]);
|
||||
const handleSourceChange = useCallback(
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
CHAIN_ID_SOLANA,
|
||||
CHAIN_ID_TERRA,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import { ChainID } from "@certusone/wormhole-sdk/lib/proto/publicrpc/v1/publicrpc";
|
||||
import { clusterApiUrl } from "@solana/web3.js";
|
||||
import { getAddress } from "ethers/lib/utils";
|
||||
|
||||
|
@ -464,4 +465,33 @@ export const ETH_MIGRATION_ASSET_MAP = new Map<string, string>(
|
|||
]
|
||||
);
|
||||
|
||||
export const BSC_MIGRATION_ASSET_MAP = new Map<string, string>(
|
||||
CLUSTER === "mainnet"
|
||||
? []
|
||||
: CLUSTER === "testnet"
|
||||
? []
|
||||
: [
|
||||
// [
|
||||
// "0x2D8BE6BF0baA74e0A907016679CaE9190e80dD0A",
|
||||
// "0x4bf3A7dFB3b76b5B3E169ACE65f888A4b4FCa5Ee",
|
||||
// ],
|
||||
// [
|
||||
// "0x68d1569d1a6968f194b4d93f8d0b416c123a599f",
|
||||
// "0xFcCeD5E997E7fb1D0594518D3eD57245bB8ed17E",
|
||||
// ],
|
||||
]
|
||||
);
|
||||
|
||||
export const getMigrationAssetMap = (chainId: ChainID) => {
|
||||
if (chainId === CHAIN_ID_BSC) {
|
||||
return BSC_MIGRATION_ASSET_MAP;
|
||||
} else if (chainId === CHAIN_ID_ETH) {
|
||||
return ETH_MIGRATION_ASSET_MAP;
|
||||
} else if (chainId === CHAIN_ID_SOLANA) {
|
||||
return MIGRATION_ASSET_MAP;
|
||||
} else {
|
||||
return new Map<string, string>();
|
||||
}
|
||||
};
|
||||
|
||||
export const SUPPORTED_TERRA_TOKENS = ["uluna", "uusd"];
|
||||
|
|
Loading…
Reference in New Issue