diff --git a/apps/connect/src/hooks/useConnectConfig.ts b/apps/connect/src/hooks/useConnectConfig.ts index f104c0128..df994bb63 100644 --- a/apps/connect/src/hooks/useConnectConfig.ts +++ b/apps/connect/src/hooks/useConnectConfig.ts @@ -14,6 +14,7 @@ import { isPreview, isProduction } from "../utils/constants"; import { ENV } from "@env"; import { validateTransfer } from "../utils/transferVerification"; import { getSortedChains } from "../utils/getSortedChains"; +import isRouteSupported from "../utils/isRouteSupported"; const defaultConfig: WormholeConnectConfig = { ...ENV.wormholeConnectConfig, @@ -29,17 +30,7 @@ const defaultConfig: WormholeConnectConfig = { }, // validateTransfer validateTransferHandler: validateTransfer, - isRouteSupportedHandler: async (td: any) => { - // Disable manual NTT for Lido wstETHÆ’ - return !( - td.route === "ManualNtt" && - td.fromToken.tokenId !== "native" && - [ - "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", - "0x26c5e01524d2E6280A48F2c50fF6De7e52E9611C", - ].includes(td.fromToken.tokenId.address) - ); - }, + isRouteSupportedHandler: isRouteSupported, }; export const useConnectConfig = () => { diff --git a/apps/connect/src/utils/isRouteSupported.test.ts b/apps/connect/src/utils/isRouteSupported.test.ts new file mode 100644 index 000000000..bcb2177e6 --- /dev/null +++ b/apps/connect/src/utils/isRouteSupported.test.ts @@ -0,0 +1,81 @@ +import { ENV } from "@env"; +import isRouteSupported from "./isRouteSupported"; +jest.mock("@env", () => ({ + ...require('../env/token-bridge.mainnet') +})); + +const Layer3Ethereum = ENV.wormholeConnectConfig?.tokensConfig?.Layer3Ethereum.tokenId?.address; +const Layer3Solana = ENV.wormholeConnectConfig?.tokensConfig?.Layer3Solana.tokenId?.address; + +describe('isRouteSupported', () => { + // Disable manual NTT for Lido wstETH + it('is wstETH manual NTT disabled fo sourceToken 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0', async () => { + const td = { + route: "ManualNtt", + fromToken: { + tokenId: { + address: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0" + } + } + } as any; + expect(await isRouteSupported(td)).toBe(false); + }); + + it('is wstETH manual NTT disabled fo sourceToken 0x26c5e01524d2E6280A48F2c50fF6De7e52E9611C', async () => { + const td = { + route: "ManualNtt", + fromToken: { + tokenId: ENV.wormholeConnectConfig?.tokensConfig?.wstETHBsc.tokenId + } + } as any; + expect(await isRouteSupported(td)).toBe(false); + }); + + it(`is Layer3 AutomaticTokenBridge is disabled for sourceToken ${Layer3Ethereum}`, async () => { + const td = { + route: "AutomaticTokenBridge", + fromToken: { + tokenId: { + address: Layer3Ethereum + } + } + } as any; + expect(await isRouteSupported(td)).toBe(false); + }); + + it(`is Layer3 ManualTokenBridge is disabled for sourceToken ${Layer3Ethereum}`, async () => { + const td = { + route: "ManualTokenBridge", + fromToken: { + tokenId: { + address: Layer3Ethereum + } + } + } as any; + expect(await isRouteSupported(td)).toBe(false); + }); + + it(`is Layer3 AutomaticTokenBridge is disabled for sourceToken ${Layer3Solana}`, async () => { + const td = { + route: "AutomaticTokenBridge", + fromToken: { + tokenId: { + address: Layer3Solana + } + } + } as any; + expect(await isRouteSupported(td)).toBe(false); + }); + + it(`is Layer3 ManualTokenBridge is disabled for sourceToken ${Layer3Solana}`, async () => { + const td = { + route: "ManualTokenBridge", + fromToken: { + tokenId: { + address: Layer3Solana + } + } + } as any; + expect(await isRouteSupported(td)).toBe(false); + }); +}); \ No newline at end of file diff --git a/apps/connect/src/utils/isRouteSupported.ts b/apps/connect/src/utils/isRouteSupported.ts new file mode 100644 index 000000000..4572be8ab --- /dev/null +++ b/apps/connect/src/utils/isRouteSupported.ts @@ -0,0 +1,36 @@ +import { ENV } from "@env"; +import { WormholeConnectConfig } from "@wormhole-foundation/wormhole-connect"; +const Layer3Ethereum = ENV.wormholeConnectConfig?.tokensConfig?.Layer3Ethereum.tokenId?.address; +const Layer3Solana = ENV.wormholeConnectConfig?.tokensConfig?.Layer3Solana.tokenId?.address; + +export type TransferDetails = Parameters>[0] + +/** + * Check if the td involve a token in the list of tokens + * + * @param td transfer details to check against + * @param tokens list of token address to check against + * @returns true if the token is in the list of tokens + */ +const isFromToken = (td: TransferDetails, ...tokens: string[]) => td.fromToken.tokenId !== 'native' && tokens.includes(td.fromToken.tokenId.address); + +/** + * Check if a route is in the list of routes + * + * @param td transfer details to check against + * @param routes list of routes to disable + * @returns true it the route is in the list of routes + */ +const isRoute = (td: TransferDetails, ...routes: string[]) => routes.includes(td.route); + +export default async function isRouteSupported(td: TransferDetails): Promise { + // Disable manual NTT for Lido wstETHÆ’ + if (isRoute(td, "ManualNtt") && isFromToken(td, "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "0x26c5e01524d2E6280A48F2c50fF6De7e52E9611C")) { + return false; + } + if (isRoute(td, "ManualTokenBridge", "AutomaticTokenBridge") && isFromToken(td, Layer3Ethereum!, Layer3Solana!)) { + console.info(`Route ${td.route} is disabled for token ${(td.fromToken.tokenId as any).address}`); + return false; + } + return true; + }