diff --git a/builder/public/index.html b/builder/index.html similarity index 91% rename from builder/public/index.html rename to builder/index.html index baca02011..cb3ed2c60 100644 --- a/builder/public/index.html +++ b/builder/index.html @@ -2,7 +2,7 @@ - + - + - + Customize Connect + diff --git a/builder/package.json b/builder/package.json index 7f91cad8a..30d1c2dc8 100644 --- a/builder/package.json +++ b/builder/package.json @@ -14,7 +14,7 @@ "@types/node": "^16.18.25", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.1", - "@wormhole-foundation/wormhole-connect": "^0.1.4", + "@wormhole-foundation/wormhole-connect": "0.3.3", "react": "^18.2.0", "react-color": "^2.19.3", "react-dom": "^18.2.0", @@ -26,10 +26,8 @@ }, "scripts": { "lint:ci": "prettier -c ./src && eslint --max-warnings=0 ./src", - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" + "start": "vite", + "build": "NODE_OPTIONS=--max-old-space-size=8192 vite build" }, "eslintConfig": { "extends": [ @@ -50,6 +48,12 @@ ] }, "devDependencies": { - "@types/react-color": "^3.0.7" + "@types/react-color": "^3.0.7", + "vite": "^5.0.8", + "vite-bundle-visualizer": "^0.11.0", + "vite-plugin-checker": "^0.6.2", + "vite-plugin-dts": "^3.7.3", + "vite-plugin-node-polyfills": "^0.17.0", + "@vitejs/plugin-react-swc": "^3.5.0" } } diff --git a/builder/src/App.tsx b/builder/src/App.tsx index ec5ffe160..d71829299 100644 --- a/builder/src/App.tsx +++ b/builder/src/App.tsx @@ -20,9 +20,7 @@ import { DialogTitle, Divider, Drawer, - FormControl, FormControlLabel, - FormLabel, Grid, IconButton, ListItemText, @@ -36,44 +34,40 @@ import { Typography, useMediaQuery, } from "@mui/material"; -import WormholeBridge, { +import WormholeConnect, { ChainName, - MAINNET_CHAINS, - MainnetChainName, - Rpcs, - TESTNET_CHAINS, - TestnetChainName, - Theme, WormholeConnectConfig, - defaultTheme, + dark, + MAINNET, + TESTNET, } from "@wormhole-foundation/wormhole-connect"; +import type { WormholeConnectPartialTheme } from "@wormhole-foundation/wormhole-connect"; + import { useCallback, useEffect, useMemo, useState } from "react"; import { useDebounce } from "use-debounce"; import Background from "./Background"; import ColorPicker from "./components/ColorPicker"; import RouteCard from "./components/RouteCard"; -import { - DEFAULT_MAINNET_RPCS, - DEFAULT_TESTNET_RPCS, - MAINNET_TOKEN_KEYS, - NETWORKS, - ROUTE_INFOS, - TESTNET_TOKEN_KEYS, -} from "./consts"; +import ErrorBoundary from "./components/ErrorBoundary"; +import { ROUTE_INFOS } from "./consts"; import { copyTextToClipboard, getObjectPath, setObjectPathImmutable, } from "./utils"; -const version = "0.1.4"; +export type Rpcs = { + [chain in ChainName]?: string; +}; + +const MAINNET_TOKENS = Object.keys(MAINNET.tokens); +const TESTNET_TOKENS = Object.keys(TESTNET.tokens); +const VERSION = "0.3.3"; // generated with https://www.srihash.org/ -const versionScriptIntegrity = - "sha384-NUeZzmcZSVf4i3sUHD1rhtihig08WkCKu42too+Na8ll/2Sxr8v8D1i9IuVrF70A"; -const versionLinkIntegrity = - "sha384-KGZI5sQxWDSIe8Xzhvu4eO0fi8KYtEmDnYS2Qn5xrtw667xfxFINL3uN48d/djuY"; -const nonBreakingTag = "latest-v0.1"; -const latestTag = "latest"; +const SCRIPT_INTEGRITY_HASH = + "sha384-be7tSjGKf3akqV+FFKLt4241MoVYmg6rZKe9k3uQLePzk4lEY0t9VZvLjduwsVgG"; +const STYLESHEET_INTEGRITY_HASH = + "sha384-BTkX2AhTeIfxDRFsJbLtR26TQ9QKKpi7EMe807JdfQQBTAkUT9a2mSGwf/5CJ4bF"; // registerRpcProvider throws on invalid RPCs const isValidRpc = (rpc?: string) => @@ -165,7 +159,7 @@ const ScreenButton = ({ ); }; -const customized = defaultTheme; +const customized = dark; customized.background.default = "transparent"; const defaultThemeJSON = JSON.stringify(customized, undefined, 2); @@ -215,17 +209,16 @@ function App() { }; } }, [debouncedFontHref]); - const [_customTheme, setCustomTheme] = useState(undefined); - const [debouncedCustomTheme] = useDebounce(_customTheme, 1000); - const customTheme = - _customTheme === undefined ? undefined : debouncedCustomTheme; + const [customTheme, setCustomTheme] = useState< + WormholeConnectPartialTheme | undefined + >(undefined); const [customThemeText, setCustomThemeText] = useState(defaultThemeJSON); // const [customThemeError, setCustomThemeError] = useState(false); const handleModeChange = useCallback( (e: any, value: string) => { if (value === "dark" || value === "light") { setMode(value); - setCustomTheme(undefined); + setCustomTheme({ mode: value }); } else { setMode(undefined); try { @@ -266,17 +259,12 @@ function App() { }, []); // END ROUTES // BEGIN ENV - const [env, setEnv] = useState<"testnet" | "mainnet">("testnet"); - const [_networkIndexes, setNetworkIndexes] = useState( + const [env, setEnv] = useState<"testnet" | "mainnet">("mainnet"); + const [selectedChains, setSelectedChains] = useState( undefined ); - const [networkIndexes] = useDebounce(_networkIndexes, 1000); const [_tokens, setTokens] = useState(undefined); const [tokens] = useDebounce(_tokens, 1000); - const testnetTokens = useMemo( - () => tokens && TESTNET_TOKEN_KEYS.filter((t) => tokens?.includes(t)), - [tokens] - ); const [defaultFromNetwork, setDefaultFromNetwork] = useState< ChainName | undefined >(undefined); @@ -296,6 +284,7 @@ function App() { const [defaultToken, setDefaultToken] = useState( undefined ); + const [hideConnect, setHideConnect] = useState(false); const handleDefaultTokenChange = useCallback((e: any) => { e.target.value ? setDefaultToken(e.target.value) @@ -311,21 +300,21 @@ function App() { }, []); // networks and tokens handlers come after defaults so they can appropriately reset them const handleClearNetworks = useCallback(() => { - setNetworkIndexes(undefined); + setSelectedChains(undefined); }, []); const handleNoneNetworks = useCallback(() => { // clear defaults to avoid bugs (could be smarter) setDefaultFromNetwork(undefined); setDefaultToNetwork(undefined); setRequiredNetwork(undefined); - setNetworkIndexes([]); + setSelectedChains([]); }, []); const handleNetworksChange = useCallback((e: any) => { // clear defaults to avoid bugs (could be smarter) setDefaultFromNetwork(undefined); setDefaultToNetwork(undefined); setRequiredNetwork(undefined); - setNetworkIndexes( + setSelectedChains( typeof e.target.value === "string" ? e.target.value .split(",") @@ -352,7 +341,18 @@ function App() { ); }, []); const [_rpcs, setRpcs] = useState(undefined); - const [deRpcs] = useDebounce(_rpcs, 1000); + const rpcs = useMemo(() => { + let valid: Rpcs = {}; + for (let key in _rpcs) { + let cn = key as ChainName; + if (isValidRpc(_rpcs[cn])) { + valid[cn] = _rpcs[cn]; + } + } + if (Object.keys(valid).length === 0) return undefined; + return valid; + }, [_rpcs]); + const handleRpcChange = useCallback((e: any) => { setRpcs((prevState) => ({ ...prevState, @@ -366,58 +366,35 @@ function App() { const handleRpcsClose = useCallback(() => { setRpcsOpen(false); }, []); - const [rpcs, testnetRpcs] = useMemo(() => { - // Connect doesn't like if you specify an rpc for a chain name that isn't in the env - // For now, filter the config so it doesn't cause an error - // TODO: change Connect so that the chain names are the same for testnet and mainnet - return !deRpcs - ? [undefined, undefined] - : Object.entries(deRpcs).reduce< - [ - { [chain in ChainName]?: string } | undefined, - { [chain in TestnetChainName]?: string } | undefined - ] - >( - ([rpcs, testnetRpcs], [n, rpc]) => [ - isValidRpc(rpc) && - (env === "mainnet" - ? MAINNET_CHAINS[n as MainnetChainName] - : TESTNET_CHAINS[n as TestnetChainName]) - ? { ...rpcs, [n]: rpc } - : rpcs, - isValidRpc(rpc) && TESTNET_CHAINS[n as TestnetChainName] - ? { ...testnetRpcs, [n]: rpc } - : testnetRpcs, - ], - [undefined, undefined] - ); - }, [deRpcs, env]); const handleEnvChange = useCallback((e: any, value: string) => { if (value === "testnet" || value === "mainnet") { - // TODO: keep tokens that exist in both envs, for now clear it before it doesn't match the options setTokens(undefined); - // clear defaults to avoid bugs (could be smarter) + setSelectedChains(undefined); setDefaultFromNetwork(undefined); setDefaultToNetwork(undefined); setDefaultToken(undefined); setRequiredNetwork(undefined); - // set env last - setEnv(value); + + // These timeouts are necessary because the config + // is used to reset the transferInput redux store + // and if we change the network before that can happen + // we get all kinds of fun errors + setTimeout(() => { + setHideConnect(true); + + setTimeout(() => { + setEnv(value); + + setTimeout(() => { + setHideConnect(false); + }, 50); + }, 50); + }, 50); } }, []); - const [networks, testnetNetworks] = useMemo(() => { - return !networkIndexes - ? [undefined, undefined] - : NETWORKS.filter((v, i) => networkIndexes.indexOf(i) > -1).reduce< - [ChainName[], TestnetChainName[]] - >( - ([networks, testnetNetworks], v) => [ - [...networks, v[env]], - [...testnetNetworks, v.testnet], - ], - [[], []] - ); - }, [networkIndexes, env]); + + const chains = env === "mainnet" ? MAINNET.chains : TESTNET.chains; + // END ENV // START BRIDGE COMPLETE const [_ctaText, setCtaText] = useState(""); @@ -441,7 +418,7 @@ function App() { setDefaultToNetwork(undefined); setDefaultToken(undefined); setRequiredNetwork(undefined); - setNetworkIndexes(undefined); + setSelectedChains(undefined); setTokens(undefined); setRpcs(undefined); setEnv("testnet"); @@ -458,16 +435,13 @@ function App() { }, [] ); - // NOTE: the WormholeBridge component is keyed by the stringified version of config + // NOTE: the WormholeConnect component is keyed by the stringified version of config // because otherwise the component did not update on changes const config: WormholeConnectConfig = useMemo( () => ({ - env: "testnet", // always testnet for the builder - rpcs: testnetRpcs, - networks: testnetNetworks, // always testnet for the builder - tokens: testnetTokens, // always testnet for the builder - mode, - customTheme, + env, + rpcs, + tokens, // always testnet for the builder cta: ctaText && ctaLink ? { @@ -489,14 +463,14 @@ function App() { : undefined, routes, pageHeader, + networks: selectedChains, showHamburgerMenu, }), [ - testnetRpcs, - testnetNetworks, - testnetTokens, - mode, - customTheme, + env, + rpcs, + tokens, + selectedChains, ctaText, ctaLink, defaultFromNetwork, @@ -508,35 +482,31 @@ function App() { showHamburgerMenu, ] ); - const [versionOrTag, setVersionOrTag] = useState(version); - const handleVersionOrTagChange = useCallback((e: any, value: string) => { - setVersionOrTag(value); - }, []); + const [htmlCode, jsxCode] = useMemo(() => { - const realConfig = { ...config, env, rpcs, networks, tokens }; - const realConfigString = JSON.stringify(realConfig); + const configString = JSON.stringify(config); + const themeStringHTML = customTheme + ? ` data-theme='${JSON.stringify(customTheme)}'` + : ""; + const themeStringJSX = customTheme + ? ` theme={${JSON.stringify(customTheme)}}` + : ""; + return [ - `
- -`, - `import WormholeBridge from '@wormhole-foundation/wormhole-connect'; + // Hosted version (CDN) + `
+ +`, + + // React version + `import WormholeConnect from '@wormhole-foundation/wormhole-connect'; function App() { return ( - + ); }`, ]; - }, [config, env, rpcs, networks, tokens, versionOrTag]); + }, [config, customTheme]); const [openCopySnack, setOpenCopySnack] = useState(false); const handleCopySnackClose = useCallback(() => { setOpenCopySnack(false); @@ -706,7 +676,7 @@ function App() { Widget @@ -818,7 +788,7 @@ function App() { Action Configure RPCs - {NETWORKS.map((n) => ( - - ))} + {Object.keys( + env === "testnet" ? TESTNET.chains : MAINNET.chains + ).map((cn) => { + const chain = cn as ChainName; + return ( + + ); + })} - - Automatic Updates - - } - label="Disabled (Pinned)" - /> - } - label="Non-Breaking" - /> - } - label="Latest" - /> - - Preview - + + + {!hideConnect ? ( + + ) : ( + <> + )} + diff --git a/builder/src/Background.tsx b/builder/src/Background.tsx index 090f6014c..c2df9e27a 100644 --- a/builder/src/Background.tsx +++ b/builder/src/Background.tsx @@ -1,7 +1,6 @@ import React from "react"; import { makeStyles } from "tss-react/mui"; import bg from "./bg.svg"; -import { OPACITY } from "./theme"; const colors = { bg: "#030712", @@ -65,7 +64,7 @@ const useStyles = makeStyles()((theme) => ({ width: "1379px", height: "1378px", position: "absolute", - background: `radial-gradient(closest-side at 50% 50%, ${colors.pink}${OPACITY[60]} 0%, ${colors.pink}00 100%)`, + background: `radial-gradient(closest-side at 50% 50%, ${colors.pink}99 0%, ${colors.pink}00 100%)`, opacity: "0.5", zIndex: "-1", pointerEvent: "none", diff --git a/builder/src/components/ColorPicker.tsx b/builder/src/components/ColorPicker.tsx index bb4c163bf..710373ea2 100644 --- a/builder/src/components/ColorPicker.tsx +++ b/builder/src/components/ColorPicker.tsx @@ -1,5 +1,8 @@ import { Box, Button, ClickAwayListener, Tooltip } from "@mui/material"; -import { Theme } from "@wormhole-foundation/wormhole-connect"; +import { + WormholeConnectTheme, + WormholeConnectPartialTheme, +} from "@wormhole-foundation/wormhole-connect"; import { useCallback, useMemo, useState } from "react"; import { Color, @@ -37,10 +40,12 @@ export default function ColorPicker({ path, defaultTheme, }: { - customTheme: Theme | undefined; - setCustomTheme: React.Dispatch>; + customTheme: WormholeConnectPartialTheme | undefined; + setCustomTheme: React.Dispatch< + React.SetStateAction + >; path: string; - defaultTheme: Theme; + defaultTheme: WormholeConnectTheme; }) { const color = useMemo( () => diff --git a/builder/src/components/ErrorBoundary.tsx b/builder/src/components/ErrorBoundary.tsx new file mode 100644 index 000000000..025efa9c5 --- /dev/null +++ b/builder/src/components/ErrorBoundary.tsx @@ -0,0 +1,27 @@ +import React from "react"; + +export default class ErrorBoundary extends React.Component< + { children: React.ReactElement }, + { hasError: boolean } +> { + constructor(props: any) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError(error: any) { + return { hasError: true }; + } + + componentDidCatch(error: any, errorInfo: any) { + console.error(error, errorInfo); + } + + render() { + if (this.state.hasError) { + return "An unexpected error has occurred. Please refresh the page."; + } + + return this.props.children; + } +} diff --git a/builder/src/consts.ts b/builder/src/consts.ts index 5f9238a8d..54f61a6b7 100644 --- a/builder/src/consts.ts +++ b/builder/src/consts.ts @@ -1,7 +1,7 @@ -import { - MainnetChainName, - TestnetChainName, -} from "@wormhole-foundation/wormhole-connect"; +import { MAINNET, TESTNET } from "@wormhole-foundation/wormhole-connect"; + +export type MainnetChainName = keyof typeof MAINNET.chains; +export type TestnetChainName = keyof typeof TESTNET.chains; export type Network = { name: string; @@ -9,193 +9,6 @@ export type Network = { mainnet: MainnetChainName; }; -export const NETWORKS: Network[] = [ - { - name: "Solana", - testnet: "solana", - mainnet: "solana", - }, - { - name: "Ethereum", - testnet: "goerli", - mainnet: "ethereum", - }, - { - name: "BSC", - testnet: "bsc", - mainnet: "bsc", - }, - { - name: "Polygon", - testnet: "mumbai", - mainnet: "polygon", - }, - { - name: "Avalanche", - testnet: "fuji", - mainnet: "avalanche", - }, - { - name: "Fantom", - testnet: "fantom", - mainnet: "fantom", - }, - { - name: "Celo", - testnet: "alfajores", - mainnet: "celo", - }, - { - name: "Moonbeam", - testnet: "moonbasealpha", - mainnet: "moonbeam", - }, - { - name: "Sui", - testnet: "sui", - mainnet: "sui", - }, - { - name: "Aptos", - testnet: "aptos", - mainnet: "aptos", - }, - { - name: "Arbitrum", - testnet: "arbitrumgoerli", - mainnet: "arbitrum", - }, - { - name: "Optimism", - testnet: "optimismgoerli", - mainnet: "optimism", - }, - { - name: "Base", - testnet: "basegoerli", - mainnet: "base", - }, - { - name: "Osmosis", - testnet: "osmosis", - mainnet: "osmosis", - }, - // TO DO uncomment Klaytn lines when Klaytn is on npm version of wormhole-connect - /*{ - name: "Klaytn", - testnet: "klaytn", - mainnet: "klaytn", - },*/ -]; - -// TODO: move the connect config to a shared sdk -export const TESTNET_TOKEN_KEYS: string[] = [ - "ETH", - "WETH", - "USDCeth", - "WBTC", - "USDT", - "DAI", - "MATIC", - "WMATIC", - "USDCpolygon", - "BNB", - "WBNB", - "AVAX", - "WAVAX", - "USDCavax", - "FTM", - "WFTM", - "CELO", - "GLMR", - "WGLMR", - "SOL", - "WSOL", - "USDCsol", - "SUI", - "APT", - "ETHarbitrum", - "WETHarbitrum", - "USDCarbitrum", - "ETHoptimism", - "WETHoptimism", - "USDCoptimism", - "ETHbase", - "WETHbase", - "USDCbase", - "OSMO", - "tBTC", - "tBTCpolygon", - "tBTCoptimism", - "tBTCarbitrum", - "tBTCbase", - "tBTCsol", - "wstETH", - "SEI", - "ATOM", - "EVMOS", - "KUJI", - /*"KLAY", - "WKLAY",*/ -].sort(); - -export const MAINNET_TOKEN_KEYS: string[] = [ - "ETH", - "WETH", - "USDCeth", - "WBTC", - "USDT", - "DAI", - "BUSD", - "MATIC", - "WMATIC", - "USDCpolygon", - "BNB", - "WBNB", - "USDCbnb", - "AVAX", - "WAVAX", - "USDCavax", - "FTM", - "WFTM", - "CELO", - "GLMR", - "WGLMR", - "SOL", - "WSOL", - "USDCsol", - "SUI", - "APT", - "ETHarbitrum", - "WETHarbitrum", - "USDCarbitrum", - "ETHoptimism", - "WETHoptimism", - "USDCoptimism", - "ETHbase", - "WETHbase", - "USDCbase", - "OSMO", - "tBTC", - "tBTCpolygon", - "tBTCoptimism", - "tBTCarbitrum", - "tBTCbase", - "tBTCsol", - "wstETH", - "EVMOS", - "KUJI", - "PYTH", - "WETHpolygon", - "WETHbsc", - "wstETHarbitrum", - "wstETHoptimism", - "wstETHpolygon", - "wstETHbase", - /*"KLAY", - "WKLAY",*/ -].sort(); - export type RouteInfo = { key: string; title: string; @@ -269,49 +82,3 @@ export const ROUTE_INFOS: RouteInfo[] = [ }, ]; export const ROUTES = ROUTE_INFOS.map((r) => r.key); - -export const DEFAULT_MAINNET_RPCS = { - ethereum: "https://rpc.ankr.com/eth", - solana: "https://solana-mainnet.rpc.extrnode.com", - polygon: "https://rpc.ankr.com/polygon", - bsc: "https://bscrpc.com", - avalanche: "https://rpc.ankr.com/avalanche", - fantom: "https://rpc.ankr.com/fantom", - celo: "https://rpc.ankr.com/celo", - moonbeam: "https://rpc.ankr.com/moonbeam", - sui: "https://rpc.mainnet.sui.io", - aptos: "https://fullnode.mainnet.aptoslabs.com/v1", - arbitrum: "https://rpc.ankr.com/arbitrum", - optimism: "https://rpc.ankr.com/optimism", - base: "https://base.publicnode.com", - sei: "", // TODO: fill in - wormchain: "", - osmosis: "https://osmosis-rpc.polkachu.com", - cosmoshub: "https://cosmos-rpc.polkachu.com", - evmos: "https://evmos-rpc.polkachu.com", - kujira: "https://kujira-rpc.polkachu.com", - // klaytn: "https://rpc.ankr.com/klaytn", -}; - -export const DEFAULT_TESTNET_RPCS = { - goerli: "https://rpc.ankr.com/eth_goerli", - mumbai: "https://rpc.ankr.com/polygon_mumbai", - bsc: "https://data-seed-prebsc-1-s3.binance.org:8545", - fuji: "https://api.avax-test.network/ext/bc/C/rpc", - fantom: "https://rpc.ankr.com/fantom_testnet", - alfajores: "https://alfajores-forno.celo-testnet.org", - solana: "https://api.devnet.solana.com", - moonbasealpha: "https://rpc.api.moonbase.moonbeam.network", - sui: "https://fullnode.testnet.sui.io", - aptos: "https://fullnode.testnet.aptoslabs.com/v1", - arbitrumgoerli: "https://arbitrum-goerli.publicnode.com", - optimismgoerli: "https://optimism-goerli.publicnode.com", - basegoerli: "https://base-goerli.publicnode.com", - sei: "https://rpc.atlantic-2.seinetwork.io", - wormchain: "", - osmosis: "https://rpc.osmotest5.osmosis.zone", - cosmoshub: "https://rpc.sentry-02.theta-testnet.polypore.xyz", - evmos: "https://evmos-testnet-rpc.polkachu.com", - kujira: "https://kujira-testnet-rpc.polkachu.com", - // klaytn: "https://rpc.ankr.com/klaytn_testnet", -}; diff --git a/builder/src/theme.ts b/builder/src/theme.ts deleted file mode 100644 index 1c8e4de55..000000000 --- a/builder/src/theme.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { Theme } from "@wormhole-foundation/wormhole-connect"; -import { grey, green, orange, red, cyan, purple } from "@mui/material/colors"; - -export const OPACITY = { - 0: "00", - 5: "0C", - 7: "0F", - 10: "19", - 15: "26", - 20: "33", - 25: "3F", - 30: "4C", - 35: "59", - 40: "66", - 45: "72", - 50: "7F", - 55: "8C", - 60: "99", - 65: "A5", - 70: "B2", - 75: "BF", - 80: "CC", - 85: "D8", - 90: "E5", - 95: "F2", - 100: "FF", -}; - -export const light: Theme = { - primary: { - 50: "#161718", - 100: "#2d2e30", - 200: "#444548", - 300: "#5b5c60", - 400: "#727479", - 500: "#898b91", - 600: "#a0a2a9", - 700: "#b7b9c1", - 800: "#ced0d9", - 900: "#E5E8F2", - A100: "#ceced1", - A200: "#9d9ea4", - A400: "#535660", - A700: "#0a0e1c", - }, - secondary: grey, - divider: "#a0a2a9", - background: { - default: "#E5E8F2", - }, - text: { - primary: grey[900], - secondary: grey[800], - }, - error: red, - info: { - 50: "#d1e3f9", - 100: "#c8def7", - 200: "#bfd8f6", - 300: "#b6d3f5", - 400: "#adcdf4", - 500: "#A4C8F3", - 600: "#93b4da", - 700: "#83a0c2", - 800: "#728caa", - 900: "#627891", - A100: "#A4C8F3", - A200: "#A4C8F3", - A400: "#A4C8F3", - A700: "#A4C8F3", - }, - success: green, - warning: orange, - button: { - primary: "#ffffff", - primaryText: grey[900], - disabled: "#c8cad1", - disabledText: grey[800], - action: "#F3A01E", - actionText: "#000000", - hover: "#b7b9c1", - }, - options: { - hover: "#f9f9fb", - select: "#F0F0F5", - }, - card: { - background: "#ffffff", - elevation: "10px 10px 30px 15px #CCD2E7", - secondary: "#F0F0F5", - }, - popover: { - background: "#ffffff", - elevation: "10px 10px 30px 15px #CCD2E7", - secondary: "#F0F0F5", - }, - modal: { - background: "#ffffff", - }, - font: { - primary: '"Inter", sans-serif', - header: '"IBM Plex Mono", monospace', - }, -}; - -export const dark: Theme = { - primary: grey, - secondary: grey, - divider: "#ffffff" + OPACITY[20], - background: { - default: "#212121", - }, - text: { - primary: "#ffffff", - secondary: grey[500], - }, - error: red, - info: cyan, - success: green, - warning: orange, - button: { - primary: "#ffffff" + OPACITY[20], - primaryText: "#ffffff", - disabled: "#ffffff" + OPACITY[10], - disabledText: "#ffffff" + OPACITY[40], - action: purple[400], - actionText: "#000000", - hover: "#ffffff" + OPACITY[7], - }, - options: { - hover: "#373737", - select: "#3F3F3F", - }, - card: { - background: "#2F2F2F", - secondary: "#474747", - elevation: "none", - }, - popover: { - background: "#111111", - secondary: "#ffffff" + OPACITY[5], - elevation: "none", - }, - modal: { - background: "#2d2d2d", - }, - font: { - primary: '"Inter", sans-serif', - header: '"IBM Plex Mono", monospace', - }, -}; - -export const custom: Theme = { - primary: grey, - secondary: grey, - divider: "#ffffff" + OPACITY[20], - background: { - default: "transparent", - }, - text: { - primary: "#ffffff", - secondary: grey[500], - }, - error: red, - info: { - 50: "#97a5b7", - 100: "#8293a9", - 200: "#6e819a", - 300: "#596f8c", - 400: "#445d7e", - 500: "#304C70", - 600: "#2b4464", - 700: "#263c59", - 800: "#21354e", - 900: "#1c2d43", - A100: "#304C70", - A200: "#304C70", - A400: "#304C70", - A700: "#304C70", - }, - // success: green, - success: { - 50: "#66d6cd", - 100: "#4dcfc4", - 200: "#33c8bc", - 300: "#1ac1b4", - 400: "#01BBAC", - 500: "#00a89a", - 600: "#009589", - 700: "#008278", - 800: "#007067", - 900: "#005d56", - A100: "#00a89a", - A200: "#00a89a", - A400: "#00a89a", - A700: "#00a89a", - }, - warning: { - 50: "#ffe3a4", - 100: "#ffdd91", - 200: "#ffd77f", - 300: "#ffd26d", - 400: "#ffcc5b", - 500: "#FFC749", - 600: "#e5b341", - 700: "#cc9f3a", - 800: "#b28b33", - 900: "#99772b", - A100: "#FFC749", - A200: "#FFC749", - A400: "#FFC749", - A700: "#FFC749", - }, - button: { - primary: "#ffffff" + OPACITY[10], - primaryText: "#ffffff", - disabled: "#ffffff" + OPACITY[7], - disabledText: "#ffffff" + OPACITY[40], - action: "#ffffff" + OPACITY[20], - actionText: "#ffffff", - hover: "#ffffff" + OPACITY[7], - }, - options: { - hover: "#ffffff" + OPACITY[7], - select: "#ffffff" + OPACITY[10], - }, - card: { - background: "#ffffff" + OPACITY[5], - secondary: "#ffffff" + OPACITY[5], - elevation: "none", - }, - popover: { - background: "#1b2033", - secondary: "#ffffff" + OPACITY[5], - elevation: "none", - }, - modal: { - background: "#0F1024", - }, - font: { - primary: '"Inter", sans-serif', - header: '"IBM Plex Mono", monospace', - }, -}; diff --git a/builder/vite.config.ts b/builder/vite.config.ts new file mode 100644 index 000000000..9ac5191cf --- /dev/null +++ b/builder/vite.config.ts @@ -0,0 +1,64 @@ +import react from "@vitejs/plugin-react-swc"; +import checker from "vite-plugin-checker"; +import { nodePolyfills } from "vite-plugin-node-polyfills"; +import dts from "vite-plugin-dts"; +import path from "path"; + +const resolve = { + alias: { + components: path.resolve(__dirname, "./src/components"), + }, +}; + +const plugins = [ + checker({ + typescript: true, + }), + dts({ + insertTypesEntry: true, + }), + react(), + nodePolyfills({ + include: [ + "crypto", + "http", + "https", + "stream", + "buffer", + "url", + "os", + "zlib", + ], + globals: { + Buffer: true, + }, + }), +]; + +let output = { + assetFileNames: "[name]-[hash][extname]", + inlineDynamicImports: false, + exports: "named", +}; + +let external = [ + // TODO figure out why these have to be here. build fails without it + "@particle-network/solana-wallet", + "@particle-network/auth", +]; + +export default { + resolve, + build: { + outDir: "./build", + rollupOptions: { + input: { + main: "src/index.tsx", + index: "index.html", + }, + output, + external, + }, + }, + plugins, +}; diff --git a/package-lock.json b/package-lock.json index b9288ad81..979997fb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "@types/node": "^16.18.25", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.1", - "@wormhole-foundation/wormhole-connect": "^0.1.4", + "@wormhole-foundation/wormhole-connect": "0.3.3", "react": "^18.2.0", "react-color": "^2.19.3", "react-dom": "^18.2.0", @@ -50,7 +50,13 @@ "web-vitals": "^2.1.4" }, "devDependencies": { - "@types/react-color": "^3.0.7" + "@types/react-color": "^3.0.7", + "@vitejs/plugin-react-swc": "^3.5.0", + "vite": "^5.0.8", + "vite-bundle-visualizer": "^0.11.0", + "vite-plugin-checker": "^0.6.2", + "vite-plugin-dts": "^3.7.3", + "vite-plugin-node-polyfills": "^0.17.0" } }, "builder/node_modules/@types/node": { @@ -59,11 +65,44 @@ "integrity": "sha512-sG3hPIQwJLoewrN7cr0dwEy+yF5nD4D/4FxtQpFciRD/xwUzgD+G05uxZHv5mhfXo4F9Jkp13jjn0CC2q325sg==" }, "builder/node_modules/@wormhole-foundation/wormhole-connect": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@wormhole-foundation/wormhole-connect/-/wormhole-connect-0.1.7.tgz", - "integrity": "sha512-f3iyNi85X4VH2f2aNUNJbULsk3e/qOuvUSqUtndZfLIbfK1eznHfSZiGZgfDry8xqVay4p1G+Fy1LgjSP/RG/Q==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@wormhole-foundation/wormhole-connect/-/wormhole-connect-0.3.3.tgz", + "integrity": "sha512-PHE9s0SI9IW0hPvXrln+eAQuGLCFuFQOPsMadei1IKGI6Zv4lNxHnssKHbZecf6AM3E2pOsc/ySb49caxrdOuQ==", "dependencies": { - "@mui/material": "^5.12.1" + "@certusone/wormhole-sdk": "^0.10.10", + "@coral-xyz/anchor": "^0.29.0", + "@cosmjs/cosmwasm-stargate": "^0.31.3", + "@cosmjs/stargate": "^0.31.3", + "@cosmjs/tendermint-rpc": "^0.31.3", + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@manahippo/aptos-wallet-adapter": "^1.0.8", + "@mui/icons-material": "^5.11.0", + "@mui/material": "^5.11.4", + "@mysten/sui.js": "^0.32.2", + "@reduxjs/toolkit": "^1.9.1", + "@solana/wallet-adapter-wallets": "^0.19.25", + "@solana/web3.js": "^1.73.0", + "@wormhole-foundation/sdk-definitions": "^0.5.2-beta.0", + "@xlabs-libs/wallet-aggregator-aptos": "^0.0.1-alpha.14", + "@xlabs-libs/wallet-aggregator-core": "^0.0.1-alpha.18", + "@xlabs-libs/wallet-aggregator-cosmos": "^0.0.1-alpha.14", + "@xlabs-libs/wallet-aggregator-cosmos-evm": "^0.0.1-alpha.6", + "@xlabs-libs/wallet-aggregator-evm": "^0.0.1-alpha.37", + "@xlabs-libs/wallet-aggregator-sei": "^0.0.1-alpha.14", + "@xlabs-libs/wallet-aggregator-solana": "^0.0.1-alpha.15", + "@xlabs-libs/wallet-aggregator-sui": "^0.0.1-alpha.10", + "aptos": "1.5.0", + "axios": "^1.2.4", + "cosmjs-types": "^0.9.0", + "ethers": "^5.7.2", + "material-ui-popup-state": "^5.0.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-redux": "^8.0.5", + "tss-react": "^4.5.2", + "use-debounce": "^9.0.4", + "web-vitals": "^2.1.4" }, "peerDependencies": { "react": "^18.2.0", @@ -9962,11 +10001,11 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=10" } @@ -9978,11 +10017,11 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=10" } @@ -9994,11 +10033,11 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=10" } @@ -10010,11 +10049,11 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=10" } @@ -10026,11 +10065,11 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=10" } @@ -10042,11 +10081,11 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=10" } @@ -10058,11 +10097,11 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">=10" } @@ -10074,11 +10113,11 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">=10" } @@ -10090,11 +10129,11 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">=10" } diff --git a/wormhole-connect/src/routes/cctpManual/chains/abstract.ts b/wormhole-connect/src/routes/cctpManual/chains/abstract.ts index fd33f7eb3..5ef1700d2 100644 --- a/wormhole-connect/src/routes/cctpManual/chains/abstract.ts +++ b/wormhole-connect/src/routes/cctpManual/chains/abstract.ts @@ -41,4 +41,5 @@ export default interface ManualCCTP { destChain: ChainName | ChainId, messageInfo: SignedMessage, ): Promise; + // eslint-disable-next-line semi } diff --git a/wormhole-connect/src/views/Bridge/Inputs/From.tsx b/wormhole-connect/src/views/Bridge/Inputs/From.tsx index e8ea93672..35cf1faa0 100644 --- a/wormhole-connect/src/views/Bridge/Inputs/From.tsx +++ b/wormhole-connect/src/views/Bridge/Inputs/From.tsx @@ -187,14 +187,16 @@ function FromInputs() { balance={balance} tokenPrice={getTokenPrice(prices, config.tokens[token])} /> - setShowTokensModal(false)} - /> + {showTokensModal && ( + setShowTokensModal(false)} + /> + )} } tokenPrice={getTokenPrice(prices, config.tokens[destToken])} /> - setShowTokensModal(false)} - /> + {showTokensModal && ( + setShowTokensModal(false)} + /> + )} { + if (assetInfo.name === 'main.css') { + return '[name][extname]'; + } + + return '[name]-[hash][extname]'; + }, inlineDynamicImports: false, exports: 'named', };