diff --git a/wormhole-connect/src/hooks/useComputeDestinationTokens.ts b/wormhole-connect/src/hooks/useComputeDestinationTokens.ts
new file mode 100644
index 000000000..6a0b089b9
--- /dev/null
+++ b/wormhole-connect/src/hooks/useComputeDestinationTokens.ts
@@ -0,0 +1,125 @@
+import config from 'config';
+import { useEffect } from 'react';
+import { useDispatch } from 'react-redux';
+
+import {
+ setDestToken,
+ setSupportedDestTokens,
+ setAllSupportedDestTokens,
+ getNativeVersionOfToken,
+} from 'store/transferInput';
+
+import type { Route } from 'config/types';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+
+import { isPorticoRoute } from 'routes/porticoBridge/utils';
+import { ETHBridge } from 'routes/porticoBridge/ethBridge';
+import { wstETHBridge } from 'routes/porticoBridge/wstETHBridge';
+import RouteOperator from 'routes/operator';
+
+import { getWrappedToken } from 'utils';
+
+type Props = {
+ sourceChain: ChainName | undefined;
+ sourceToken: string;
+ destChain: ChainName | undefined;
+ destToken: string;
+ route: Route | undefined;
+};
+
+export const useComputeDestinationTokens = (props: Props): void => {
+ const { sourceChain, destChain, sourceToken, destToken, route } = props;
+
+ const dispatch = useDispatch();
+
+ useEffect(() => {
+ if (!destChain) {
+ return;
+ }
+
+ let canceled = false;
+
+ const computeDestTokens = async () => {
+ let supported = await RouteOperator.allSupportedDestTokens(
+ config.tokens[sourceToken],
+ sourceChain,
+ destChain,
+ );
+ if (sourceToken) {
+ // If any of the tokens are native to the chain, only select those.
+ // This is to avoid users inadvertently receiving wrapped versions of the token.
+ const nativeTokens = supported.filter(
+ (t) => t.nativeChain === destChain,
+ );
+ if (nativeTokens.length > 0) {
+ supported = nativeTokens;
+ }
+ }
+ dispatch(setSupportedDestTokens(supported));
+ const allSupported = await RouteOperator.allSupportedDestTokens(
+ undefined,
+ sourceChain,
+ destChain,
+ );
+ dispatch(setAllSupportedDestTokens(allSupported));
+ if (destChain && supported.length === 1) {
+ if (!canceled) {
+ dispatch(setDestToken(supported[0].key));
+ }
+ }
+
+ // If all the supported tokens are the same token
+ // select the native version for applicable tokens
+ const symbols = supported.map((t) => t.symbol);
+ if (
+ destChain &&
+ symbols.every((s) => s === symbols[0]) &&
+ ['USDC', 'tBTC'].includes(symbols[0])
+ ) {
+ const key = supported.find(
+ (t) =>
+ t.symbol === symbols[0] &&
+ t.nativeChain === t.tokenId?.chain &&
+ t.nativeChain === destChain,
+ )?.key;
+ if (!canceled && key) {
+ dispatch(setDestToken(key));
+ }
+ }
+
+ // If the source token is supported by a Portico bridge route,
+ // then select the native version on the dest chain
+ if (
+ sourceToken &&
+ destToken === '' &&
+ destChain &&
+ (!route || isPorticoRoute(route))
+ ) {
+ const tokenSymbol = config.tokens[sourceToken]?.symbol;
+ const porticoTokens = [
+ ...ETHBridge.SUPPORTED_TOKENS,
+ ...wstETHBridge.SUPPORTED_TOKENS,
+ ];
+ if (porticoTokens.includes(tokenSymbol)) {
+ const isTokenSupported =
+ sourceToken && supported.some((t) => t.key === sourceToken);
+ let key = getNativeVersionOfToken(tokenSymbol, destChain);
+ if (!key) {
+ const wrapped = getWrappedToken(config.tokens[sourceToken]);
+ key = getNativeVersionOfToken(wrapped.symbol, destChain);
+ }
+ if (!canceled && key && isTokenSupported) {
+ dispatch(setDestToken(key));
+ }
+ }
+ }
+ };
+
+ computeDestTokens();
+
+ return () => {
+ canceled = true;
+ };
+ // IMPORTANT: do not include destToken in dependency array
+ }, [route, sourceToken, sourceChain, destChain, dispatch]);
+};
diff --git a/wormhole-connect/src/hooks/useComputeReceiveAmount.ts b/wormhole-connect/src/hooks/useComputeReceiveAmount.ts
new file mode 100644
index 000000000..bda08d4d0
--- /dev/null
+++ b/wormhole-connect/src/hooks/useComputeReceiveAmount.ts
@@ -0,0 +1,92 @@
+import { useEffect } from 'react';
+import { useDispatch } from 'react-redux';
+
+import { isPorticoRoute } from 'routes/porticoBridge/utils';
+import RouteOperator from 'routes/operator';
+
+import {
+ setReceiveAmount,
+ setFetchingReceiveAmount,
+ setReceiveAmountError,
+} from 'store/transferInput';
+
+import type { Route } from 'config/types';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { PorticoBridgeState } from 'store/porticoBridge';
+
+type Props = {
+ sourceChain: ChainName | undefined;
+ sourceToken: string;
+ destChain: ChainName | undefined;
+ destToken: string;
+ route: Route | undefined;
+ amount: string;
+ portico: PorticoBridgeState;
+ toNativeToken: number;
+ relayerFee: number | undefined;
+};
+
+export const useComputeReceiveAmount = (props: Props): void => {
+ const {
+ sourceChain,
+ destChain,
+ sourceToken,
+ destToken,
+ amount,
+ portico,
+ route,
+ toNativeToken,
+ relayerFee,
+ } = props;
+
+ const dispatch = useDispatch();
+
+ useEffect(() => {
+ if (
+ !route ||
+ !amount ||
+ !sourceToken ||
+ !destToken ||
+ !sourceChain ||
+ !destChain
+ ) {
+ return;
+ }
+
+ const recomputeReceive = async () => {
+ try {
+ const routeOptions = isPorticoRoute(route)
+ ? portico
+ : { toNativeToken, relayerFee };
+
+ dispatch(setFetchingReceiveAmount());
+
+ const newReceiveAmount = await RouteOperator.computeReceiveAmount(
+ route,
+ Number.parseFloat(amount),
+ sourceToken,
+ destToken,
+ sourceChain,
+ destChain,
+ routeOptions,
+ );
+ dispatch(setReceiveAmount(newReceiveAmount.toString()));
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (e: any) {
+ dispatch(setReceiveAmountError(e.message));
+ }
+ };
+ recomputeReceive();
+ }, [
+ amount,
+ toNativeToken,
+ relayerFee,
+ route,
+ sourceToken,
+ destToken,
+ destChain,
+ sourceChain,
+ portico,
+ dispatch,
+ ]);
+};
diff --git a/wormhole-connect/src/hooks/useComputeReceiverNativeBalance.ts b/wormhole-connect/src/hooks/useComputeReceiverNativeBalance.ts
new file mode 100644
index 000000000..bc3c45773
--- /dev/null
+++ b/wormhole-connect/src/hooks/useComputeReceiverNativeBalance.ts
@@ -0,0 +1,46 @@
+import config from 'config';
+import { useEffect } from 'react';
+import { useDispatch } from 'react-redux';
+import { BigNumber } from 'ethers';
+import { setReceiverNativeBalance } from 'store/transferInput';
+
+import type { WalletData } from 'store/wallet';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+
+import { getTokenDecimals } from 'utils';
+import { toChainId } from 'utils/sdk';
+import { toDecimals } from 'utils/balance';
+
+type Props = {
+ sourceChain: ChainName | undefined;
+ destChain: ChainName | undefined;
+ receiving: WalletData;
+};
+
+export const useComputeReceiverNativeBalance = (props: Props): void => {
+ const { sourceChain, destChain, receiving } = props;
+ const dispatch = useDispatch();
+ // check destination native balance
+ useEffect(() => {
+ if (!sourceChain || !destChain || !receiving.address) {
+ return;
+ }
+
+ const chainConfig = config.chains?.[destChain];
+
+ config.wh
+ .getNativeBalance(receiving.address, destChain)
+ .then((res: BigNumber) => {
+ const tokenConfig = chainConfig?.gasToken
+ ? config.tokens[chainConfig.gasToken]
+ : undefined;
+ if (!tokenConfig)
+ throw new Error('Could not get native gas token config');
+ const decimals = getTokenDecimals(
+ toChainId(tokenConfig.nativeChain),
+ 'native',
+ );
+ dispatch(setReceiverNativeBalance(toDecimals(res, decimals, 6)));
+ });
+ }, [sourceChain, destChain, receiving.address, dispatch]);
+};
diff --git a/wormhole-connect/src/hooks/useComputeSourceTokens.ts b/wormhole-connect/src/hooks/useComputeSourceTokens.ts
new file mode 100644
index 000000000..4cacb40a1
--- /dev/null
+++ b/wormhole-connect/src/hooks/useComputeSourceTokens.ts
@@ -0,0 +1,58 @@
+import config from 'config';
+import { useEffect } from 'react';
+import { useDispatch } from 'react-redux';
+
+import { setToken, setSupportedSourceTokens } from 'store/transferInput';
+
+import type { Route } from 'config/types';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+
+import RouteOperator from 'routes/operator';
+
+type Props = {
+ sourceChain: ChainName | undefined;
+ sourceToken: string;
+ destChain: ChainName | undefined;
+ destToken: string;
+ route: Route | undefined;
+};
+
+export const useComputeSourceTokens = (props: Props): void => {
+ const { sourceChain, destChain, sourceToken, destToken, route } = props;
+
+ const dispatch = useDispatch();
+
+ useEffect(() => {
+ if (!sourceChain) {
+ return;
+ }
+
+ let active = true;
+
+ const computeSrcTokens = async () => {
+ const supported = await RouteOperator.allSupportedSourceTokens(
+ config.tokens[destToken],
+ sourceChain,
+ destChain,
+ );
+ if (active) {
+ dispatch(setSupportedSourceTokens(supported));
+ const isTokenSupported =
+ sourceToken && supported.some((t) => t.key === sourceToken);
+ if (!isTokenSupported) {
+ dispatch(setToken(''));
+ }
+ if (supported.length === 1 && sourceToken === '') {
+ dispatch(setToken(supported[0].key));
+ }
+ }
+ };
+
+ computeSrcTokens();
+
+ return () => {
+ active = false;
+ };
+ // IMPORTANT: do not include token in dependency array
+ }, [route, sourceChain, destToken, dispatch]);
+};
diff --git a/wormhole-connect/src/hooks/useGasSlider.ts b/wormhole-connect/src/hooks/useGasSlider.ts
new file mode 100644
index 000000000..83de7633b
--- /dev/null
+++ b/wormhole-connect/src/hooks/useGasSlider.ts
@@ -0,0 +1,43 @@
+import config from 'config';
+import RouteOperator from 'routes/operator';
+import { getWrappedToken } from 'utils';
+
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { Route } from 'config/types';
+
+type Props = {
+ destChain: ChainName | undefined;
+ destToken: string;
+ route: Route | undefined;
+ valid: boolean;
+ isTransactionInProgress: boolean;
+};
+
+export const useGasSlider = (
+ props: Props,
+): {
+ disabled: boolean;
+ showGasSlider: boolean | undefined;
+} => {
+ const { destChain, destToken, route, isTransactionInProgress, valid } = props;
+
+ const disabled = !valid || isTransactionInProgress;
+ const toChainConfig = destChain ? config.chains[destChain] : undefined;
+ const gasTokenConfig = toChainConfig
+ ? config.tokens[toChainConfig.gasToken]
+ : undefined;
+ const wrappedGasTokenConfig = gasTokenConfig
+ ? getWrappedToken(gasTokenConfig)
+ : undefined;
+ const willReceiveGasToken =
+ wrappedGasTokenConfig && destToken === wrappedGasTokenConfig.key;
+ const showGasSlider =
+ route &&
+ RouteOperator.getRoute(route).NATIVE_GAS_DROPOFF_SUPPORTED &&
+ !willReceiveGasToken;
+
+ return {
+ disabled,
+ showGasSlider,
+ };
+};
diff --git a/wormhole-connect/src/utils/index.ts b/wormhole-connect/src/utils/index.ts
index 5bfe0cd2c..f4ed68446 100644
--- a/wormhole-connect/src/utils/index.ts
+++ b/wormhole-connect/src/utils/index.ts
@@ -354,7 +354,7 @@ export const removeDust = (amount: BigNumber, decimals: number): BigNumber => {
* isEmptyObject({ 'a': 1 })
* // => false
*/
-export const isEmptyObject = (value: Object | null | undefined) => {
+export const isEmptyObject = (value: object | null | undefined) => {
if (value === null || value === undefined) {
return true;
}
diff --git a/wormhole-connect/src/views/Bridge/Bridge.tsx b/wormhole-connect/src/views/Bridge/Bridge.tsx
index 303cd64f8..b02b8c3ff 100644
--- a/wormhole-connect/src/views/Bridge/Bridge.tsx
+++ b/wormhole-connect/src/views/Bridge/Bridge.tsx
@@ -1,31 +1,13 @@
-import React, { useEffect } from 'react';
-import { useSelector, useDispatch } from 'react-redux';
+import React from 'react';
+import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
-import { BigNumber } from 'ethers';
import { RootState } from 'store';
-import {
- setReceiverNativeBalance,
- setReceiveAmount,
- setDestToken,
- setToken,
- setSupportedSourceTokens,
- setSupportedDestTokens,
- setAllSupportedDestTokens,
- TransferInputState,
- getNativeVersionOfToken,
- setFetchingReceiveAmount,
- setReceiveAmountError,
-} from 'store/transferInput';
+import { TransferInputState } from 'store/transferInput';
import config from 'config';
-import { TokenConfig } from 'config/types';
-import { getTokenDecimals, getWrappedToken } from 'utils';
-import { toChainId } from 'utils/sdk';
import { joinClass } from 'utils/style';
-import { toDecimals } from 'utils/balance';
import { isTransferValid, useValidate } from 'utils/transferValidation';
import useConfirmBeforeLeaving from 'utils/confirmBeforeLeaving';
-import RouteOperator from 'routes/operator';
import GasSlider from './NativeGasSlider';
import Preview from './Preview';
@@ -41,15 +23,17 @@ import ValidationError from './ValidationError';
import PoweredByIcon from 'icons/PoweredBy';
import { Alignment } from 'components/Header';
import FooterNavBar from 'components/FooterNavBar';
-import { isPorticoRoute } from 'routes/porticoBridge/utils';
-import { ETHBridge } from 'routes/porticoBridge/ethBridge';
-import { wstETHBridge } from 'routes/porticoBridge/wstETHBridge';
+import { useComputeDestinationTokens } from 'hooks/useComputeDestinationTokens';
+import { useComputeReceiveAmount } from 'hooks/useComputeReceiveAmount';
+import { useComputeSourceTokens } from 'hooks/useComputeSourceTokens';
import { usePorticoSwapInfo } from 'hooks/usePorticoSwapInfo';
import { usePorticoRelayerFee } from 'hooks/usePorticoRelayerFee';
import { useFetchTokenPrices } from 'hooks/useFetchTokenPrices';
+import { useGasSlider } from 'hooks/useGasSlider';
import NttInboundCapacityWarning from './NttInboundCapacityWarning';
import { isNttRoute } from 'routes/utils';
import { useConnectToLastUsedWallet } from 'utils/wallet';
+import { useComputeReceiverNativeBalance } from 'hooks/useComputeReceiverNativeBalance';
const useStyles = makeStyles()((_theme) => ({
spacer: {
@@ -79,18 +63,9 @@ const useStyles = makeStyles()((_theme) => ({
},
}));
-function isSupportedToken(
- token: string,
- supportedTokens: TokenConfig[],
-): boolean {
- if (!token) return true;
- return supportedTokens.some((t) => t.key === token);
-}
-
function Bridge() {
const { classes } = useStyles();
const theme = useTheme();
- const dispatch = useDispatch();
const {
showValidationState,
validations,
@@ -108,193 +83,48 @@ function Bridge() {
(state: RootState) => state.relay,
);
const portico = useSelector((state: RootState) => state.porticoBridge);
- const { receiving } = useSelector((state: RootState) => state.wallet);
+ const receiving = useSelector((state: RootState) => state.wallet.receiving);
// Warn user before closing tab if transaction has begun
useConfirmBeforeLeaving(isTransactionInProgress);
- // check destination native balance
- useEffect(() => {
- if (!fromChain || !toChain || !receiving.address) {
- return;
- }
-
- const chainConfig = config.chains[toChain]!;
-
- config.wh
- .getNativeBalance(receiving.address, toChain)
- .then((res: BigNumber) => {
- const tokenConfig = config.tokens[chainConfig.gasToken];
- if (!tokenConfig)
- throw new Error('Could not get native gas token config');
- const decimals = getTokenDecimals(
- toChainId(tokenConfig.nativeChain),
- 'native',
- );
- dispatch(setReceiverNativeBalance(toDecimals(res, decimals, 6)));
- });
- }, [fromChain, toChain, receiving.address, dispatch]);
-
- useEffect(() => {
- if (!fromChain) {
- return;
- }
-
- let active = true;
-
- const computeSrcTokens = async () => {
- const supported = await RouteOperator.allSupportedSourceTokens(
- config.tokens[destToken],
- fromChain,
- toChain,
- );
- if (active) {
- dispatch(setSupportedSourceTokens(supported));
- const selectedIsSupported = isSupportedToken(token, supported);
- if (!selectedIsSupported) {
- dispatch(setToken(''));
- }
- if (supported.length === 1 && token === '') {
- dispatch(setToken(supported[0].key));
- }
- }
- };
-
- computeSrcTokens();
-
- return () => {
- active = false;
- };
- // IMPORTANT: do not include token in dependency array
- }, [route, fromChain, destToken, dispatch]);
-
- useEffect(() => {
- if (!toChain) {
- return;
- }
-
- let canceled = false;
-
- const computeDestTokens = async () => {
- let supported = await RouteOperator.allSupportedDestTokens(
- config.tokens[token],
- fromChain,
- toChain,
- );
- if (token) {
- // If any of the tokens are native to the chain, only select those.
- // This is to avoid users inadvertently receiving wrapped versions of the token.
- const nativeTokens = supported.filter((t) => t.nativeChain === toChain);
- if (nativeTokens.length > 0) {
- supported = nativeTokens;
- }
- }
- dispatch(setSupportedDestTokens(supported));
- const allSupported = await RouteOperator.allSupportedDestTokens(
- undefined,
- fromChain,
- toChain,
- );
- dispatch(setAllSupportedDestTokens(allSupported));
- if (toChain && supported.length === 1) {
- if (!canceled) {
- dispatch(setDestToken(supported[0].key));
- }
- }
-
- // If all the supported tokens are the same token
- // select the native version for applicable tokens
- const symbols = supported.map((t) => t.symbol);
- if (
- toChain &&
- symbols.every((s) => s === symbols[0]) &&
- ['USDC', 'tBTC'].includes(symbols[0])
- ) {
- const key = supported.find(
- (t) =>
- t.symbol === symbols[0] &&
- t.nativeChain === t.tokenId?.chain &&
- t.nativeChain === toChain,
- )?.key;
- if (!canceled && key) {
- dispatch(setDestToken(key));
- }
- }
-
- // If the source token is supported by a Portico bridge route,
- // then select the native version on the dest chain
- if (
- token &&
- destToken === '' &&
- toChain &&
- (!route || isPorticoRoute(route))
- ) {
- const tokenSymbol = config.tokens[token]?.symbol;
- const porticoTokens = [
- ...ETHBridge.SUPPORTED_TOKENS,
- ...wstETHBridge.SUPPORTED_TOKENS,
- ];
- if (porticoTokens.includes(tokenSymbol)) {
- let key = getNativeVersionOfToken(tokenSymbol, toChain);
- if (!key) {
- const wrapped = getWrappedToken(config.tokens[token]);
- key = getNativeVersionOfToken(wrapped.symbol, toChain);
- }
- if (!canceled && key && isSupportedToken(key, supported)) {
- dispatch(setDestToken(key));
- }
- }
- }
- };
-
- computeDestTokens();
-
- return () => {
- canceled = true;
- };
- // IMPORTANT: do not include destToken in dependency array
- }, [route, token, fromChain, toChain, dispatch]);
-
- useEffect(() => {
- if (!route || !amount || !token || !destToken || !fromChain || !toChain) {
- return;
- }
-
- const recomputeReceive = async () => {
- try {
- const routeOptions = isPorticoRoute(route)
- ? portico
- : { toNativeToken, relayerFee };
+ // Compute and set destination native balance
+ useComputeReceiverNativeBalance({
+ sourceChain: fromChain,
+ destChain: toChain,
+ receiving,
+ });
+
+ // Compute and set source tokens
+ useComputeSourceTokens({
+ sourceChain: fromChain,
+ destChain: toChain,
+ sourceToken: token,
+ destToken,
+ route,
+ });
- dispatch(setFetchingReceiveAmount());
+ // Compute and set destination tokens
+ useComputeDestinationTokens({
+ sourceChain: fromChain,
+ destChain: toChain,
+ sourceToken: token,
+ destToken,
+ route,
+ });
- const newReceiveAmount = await RouteOperator.computeReceiveAmount(
- route,
- Number.parseFloat(amount),
- token,
- destToken,
- fromChain,
- toChain,
- routeOptions,
- );
- dispatch(setReceiveAmount(newReceiveAmount.toString()));
- } catch (e: any) {
- dispatch(setReceiveAmountError(e.message));
- }
- };
- recomputeReceive();
- }, [
+ // Compute and set receive amount
+ useComputeReceiveAmount({
+ sourceChain: fromChain,
+ destChain: toChain,
+ sourceToken: token,
+ destToken,
amount,
+ portico,
+ route,
toNativeToken,
relayerFee,
- route,
- token,
- destToken,
- toChain,
- fromChain,
- portico,
- dispatch,
- ]);
+ });
// Route specific hooks
usePorticoSwapInfo();
@@ -305,26 +135,15 @@ function Bridge() {
// validate transfer inputs
useValidate();
const valid = isTransferValid(validations);
- const disabled = !valid || isTransactionInProgress;
- // if the dest token is the wrapped gas token, then disable the gas slider,
- // because it will be unwrapped by the relayer contract
- const toChainConfig = toChain ? config.chains[toChain] : undefined;
- const gasTokenConfig = toChainConfig
- ? config.tokens[toChainConfig.gasToken]
- : undefined;
- const wrappedGasTokenConfig = gasTokenConfig
- ? getWrappedToken(gasTokenConfig)
- : undefined;
- const willReceiveGasToken =
- wrappedGasTokenConfig && destToken === wrappedGasTokenConfig.key;
-
- const showGasSlider =
- route &&
- RouteOperator.getRoute(route).NATIVE_GAS_DROPOFF_SUPPORTED &&
- !willReceiveGasToken;
- const showRouteValidation =
- !!fromChain && !!toChain && !!token && !!destToken && !!amount;
+ // Get Gas Slider props
+ const { disabled, showGasSlider } = useGasSlider({
+ destChain: toChain,
+ destToken: destToken,
+ route,
+ valid,
+ isTransactionInProgress,
+ });
const pageHeader = getPageHeader();
@@ -340,7 +159,9 @@ function Bridge() {
diff --git a/wormhole-connect/src/views/Bridge/Inputs/From.tsx b/wormhole-connect/src/views/Bridge/Inputs/From.tsx
index dd502b800..9b611c703 100644
--- a/wormhole-connect/src/views/Bridge/Inputs/From.tsx
+++ b/wormhole-connect/src/views/Bridge/Inputs/From.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import { RootState } from 'store';
import {
diff --git a/wormhole-connect/src/views/Bridge/Inputs/Inputs.tsx b/wormhole-connect/src/views/Bridge/Inputs/Inputs.tsx
index 689badabb..8ff4778da 100644
--- a/wormhole-connect/src/views/Bridge/Inputs/Inputs.tsx
+++ b/wormhole-connect/src/views/Bridge/Inputs/Inputs.tsx
@@ -3,7 +3,7 @@ import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import config from 'config';
import { TransferSide } from 'config/types';
diff --git a/wormhole-connect/src/views/Bridge/Inputs/To.tsx b/wormhole-connect/src/views/Bridge/Inputs/To.tsx
index 26178b124..c1b5001e0 100644
--- a/wormhole-connect/src/views/Bridge/Inputs/To.tsx
+++ b/wormhole-connect/src/views/Bridge/Inputs/To.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import { RootState } from 'store';
import {
diff --git a/wormhole-connect/src/views/Bridge/RouteOptions.tsx b/wormhole-connect/src/views/Bridge/RouteOptions.tsx
index 57ecb655b..36a91177d 100644
--- a/wormhole-connect/src/views/Bridge/RouteOptions.tsx
+++ b/wormhole-connect/src/views/Bridge/RouteOptions.tsx
@@ -13,7 +13,7 @@ import { calculateUSDPrice, getDisplayName } from 'utils';
import config from 'config';
import { Route } from 'config/types';
import { RoutesConfig, RouteData } from 'config/routes';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import BridgeCollapse, { CollapseControlStyle } from './Collapse';
import TokenIcon from 'icons/TokenIcons';
diff --git a/wormhole-connect/src/views/Bridge/Send.tsx b/wormhole-connect/src/views/Bridge/Send.tsx
index a89462806..2ace036b2 100644
--- a/wormhole-connect/src/views/Bridge/Send.tsx
+++ b/wormhole-connect/src/views/Bridge/Send.tsx
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
-import { Context, TokenId } from '@wormhole-foundation/wormhole-connect-sdk';
+import { Context } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { TokenId } from '@wormhole-foundation/wormhole-connect-sdk';
import { makeStyles } from 'tss-react/mui';
import config from 'config';
diff --git a/wormhole-connect/src/views/Bridge/TransferLimitedWarning.tsx b/wormhole-connect/src/views/Bridge/TransferLimitedWarning.tsx
index 9c2131fc7..d451ef63b 100644
--- a/wormhole-connect/src/views/Bridge/TransferLimitedWarning.tsx
+++ b/wormhole-connect/src/views/Bridge/TransferLimitedWarning.tsx
@@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import useIsTransferLimited from 'hooks/useIsTransferLimited';
import Dialog from '@mui/material/Dialog';
import ScopedCssBaseline from '@mui/material/ScopedCssBaseline';
diff --git a/wormhole-connect/src/views/Redeem/AddToWallet.tsx b/wormhole-connect/src/views/Redeem/AddToWallet.tsx
index 807a2abd8..be3f20d63 100644
--- a/wormhole-connect/src/views/Redeem/AddToWallet.tsx
+++ b/wormhole-connect/src/views/Redeem/AddToWallet.tsx
@@ -1,9 +1,8 @@
import { Link, Typography } from '@mui/material';
-import { isEVMChain } from '@certusone/wormhole-sdk';
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
-import {
+import type {
ChainName,
SuiContext,
WormholeContext,
@@ -20,6 +19,7 @@ import {
getDisplayName,
getChainConfig,
} from 'utils';
+import { isEvmChain } from 'utils/sdk';
import { TransferWallet, switchChain, watchAsset } from 'utils/wallet';
import TokenIcon from 'icons/TokenIcons';
@@ -219,7 +219,7 @@ function AddToWallet() {
if (!targetToken || !targetAddress) return <>>;
- if (isEVMChain(chainId)) {
+ if (isEvmChain(chainId)) {
return ;
} else if (
chainId === MAINNET_CHAINS.solana?.id &&
diff --git a/wormhole-connect/src/views/Redeem/Confirmations.tsx b/wormhole-connect/src/views/Redeem/Confirmations.tsx
index ac5883695..206bc86eb 100644
--- a/wormhole-connect/src/views/Redeem/Confirmations.tsx
+++ b/wormhole-connect/src/views/Redeem/Confirmations.tsx
@@ -1,6 +1,6 @@
import { LinearProgress, linearProgressClasses } from '@mui/material';
import { styled } from '@mui/material/styles';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import React, { useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
diff --git a/wormhole-connect/src/views/Redeem/ExplorerLink.tsx b/wormhole-connect/src/views/Redeem/ExplorerLink.tsx
index 05412beaf..ebc807c2a 100644
--- a/wormhole-connect/src/views/Redeem/ExplorerLink.tsx
+++ b/wormhole-connect/src/views/Redeem/ExplorerLink.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import { makeStyles } from 'tss-react/mui';
import { LINK } from 'utils/style';
import config from 'config';
diff --git a/wormhole-connect/src/views/Redeem/GovernorEnqueuedWarning.tsx b/wormhole-connect/src/views/Redeem/GovernorEnqueuedWarning.tsx
index 1ad2a14be..86578ed28 100644
--- a/wormhole-connect/src/views/Redeem/GovernorEnqueuedWarning.tsx
+++ b/wormhole-connect/src/views/Redeem/GovernorEnqueuedWarning.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { makeStyles } from 'tss-react/mui';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import config from 'config';
import { GOVERNOR_WHITEPAPER_URL } from 'consts';
import AlertBanner from 'components/AlertBanner';
diff --git a/wormhole-connect/src/views/Redeem/Header.tsx b/wormhole-connect/src/views/Redeem/Header.tsx
index 4e5c8494c..83b88d041 100644
--- a/wormhole-connect/src/views/Redeem/Header.tsx
+++ b/wormhole-connect/src/views/Redeem/Header.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { makeStyles } from 'tss-react/mui';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import config from 'config';
import { displayAddress } from 'utils';
diff --git a/wormhole-connect/src/views/TxSearch.tsx b/wormhole-connect/src/views/TxSearch.tsx
index 970e0a362..5e27fd532 100644
--- a/wormhole-connect/src/views/TxSearch.tsx
+++ b/wormhole-connect/src/views/TxSearch.tsx
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useState } from 'react';
import { makeStyles } from 'tss-react/mui';
import { useDispatch } from 'react-redux';
import { Select, MenuItem, CircularProgress } from '@mui/material';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import config from 'config';
import { isValidTxId } from 'utils';
diff --git a/wormhole-connect/src/views/WalletModal.tsx b/wormhole-connect/src/views/WalletModal.tsx
index 09b4b5d0c..527d5af26 100644
--- a/wormhole-connect/src/views/WalletModal.tsx
+++ b/wormhole-connect/src/views/WalletModal.tsx
@@ -3,7 +3,7 @@ import { makeStyles } from 'tss-react/mui';
import { useTheme } from '@mui/material/styles';
import CircularProgress from '@mui/material/CircularProgress';
import { useDispatch, useSelector } from 'react-redux';
-import { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
+import type { ChainName } from '@wormhole-foundation/wormhole-connect-sdk';
import config from 'config';
import { RootState } from 'store';