diff --git a/src/App.tsx b/src/App.tsx index 2ed1cb94..ee3362bd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,11 +7,10 @@ import { ToasterProvider, } from "@chainsafe/common-components"; -import ChainbridgeRoutes from "./Components/Routes"; -import { lightTheme } from "./Themes/LightTheme"; -import { ChainbridgeProvider } from "./Contexts/ChainbridgeContext"; -import AppWrapper from "./Layouts/AppWrapper"; -import { NetworkManagerProvider } from "./Contexts/NetworkManagerContext"; +import { ChainbridgeRoutes } from "./routes"; +import { lightTheme } from "./themes/LightTheme"; +import { ChainbridgeProvider, NetworkManagerProvider } from "./contexts"; +import { AppWrapper } from "./layouts"; import { chainbridgeConfig } from "./chainbridgeConfig"; import { Web3Provider } from "@chainsafe/web3-context"; import { utils } from "ethers"; diff --git a/src/Components/Custom/index.ts b/src/Components/Custom/index.ts deleted file mode 100644 index ebc81d31..00000000 --- a/src/Components/Custom/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as ExplorerTable } from "./ExplorerTable"; diff --git a/src/Components/Pages/TransferPage.tsx b/src/Components/Pages/TransferPage.tsx deleted file mode 100644 index a2bd1b7d..00000000 --- a/src/Components/Pages/TransferPage.tsx +++ /dev/null @@ -1,580 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import AboutDrawer from "../../Modules/AboutDrawer"; -import ChangeNetworkDrawer from "../../Modules/ChangeNetworkDrawer"; -import PreflightModalTransfer from "../../Modules/PreflightModalTransfer"; -import { - Button, - Typography, - QuestionCircleSvg, - SelectInput, - useHistory, -} from "@chainsafe/common-components"; -import { Form, Formik } from "formik"; -import AddressInput from "../Custom/AddressInput"; -import clsx from "clsx"; -import TransferActiveModal from "../../Modules/TransferActiveModal"; -import { useChainbridge } from "../../Contexts/ChainbridgeContext"; -import TokenSelectInput from "../Custom/TokenSelectInput"; -import TokenInput from "../Custom/TokenInput"; -import { object, string } from "yup"; -import { utils } from "ethers"; -import FeesFormikWrapped from "./FormikContextElements/Fees"; -import { useNetworkManager } from "../../Contexts/NetworkManagerContext"; -import NetworkUnsupportedModal from "../../Modules/NetworkUnsupportedModal"; -import { isValidSubstrateAddress } from "../../Utils/Helpers"; -import { useHomeBridge } from "../../Contexts/HomeBridgeContext"; -import { showImageUrl } from "../../Utils/Helpers"; - -const useStyles = makeStyles(({ constants, palette }: ITheme) => - createStyles({ - root: { - padding: constants.generalUnit * 6, - position: "relative", - }, - walletArea: { - display: "flex", - flexDirection: "column", - alignItems: "center", - justifyContent: "center", - width: "100%", - }, - connectButton: { - margin: `${constants.generalUnit * 3}px 0 ${constants.generalUnit * 6}px`, - }, - connecting: { - textAlign: "center", - marginBottom: constants.generalUnit * 2, - }, - connected: { - width: "100%", - "& > *:first-child": { - display: "flex", - flexDirection: "row", - alignItems: "center", - justifyContent: "space-between", - width: "100%", - }, - }, - changeButton: { - cursor: "pointer", - }, - networkName: { - padding: `${constants.generalUnit * 2}px ${ - constants.generalUnit * 1.5 - }px`, - border: `1px solid ${palette.additional["gray"][6]}`, - borderRadius: 2, - color: palette.additional["gray"][9], - marginTop: constants.generalUnit, - marginBottom: constants.generalUnit * 3, - }, - formArea: { - "&.disabled": { - opacity: 0.4, - }, - }, - currencySection: { - display: "flex", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "flex-end", - margin: `${constants.generalUnit * 3}px 0`, - }, - tokenInputArea: { - display: "flex", - flexDirection: "row", - alignItems: "flex-end", - justifyContent: "space-around", - }, - tokenInputSection: { - width: "60%", - }, - tokenInput: { - margin: 0, - "& > div": { - height: 32, - "& input": { - borderBottomRightRadius: 0, - borderTopRightRadius: 0, - borderRight: 0, - }, - }, - "& span:last-child.error": { - position: "absolute", - width: "calc(100% + 62px)", - }, - }, - maxButton: { - height: 32, - borderBottomLeftRadius: 0, - borderTopLeftRadius: 0, - left: -1, - color: palette.additional["gray"][8], - backgroundColor: palette.additional["gray"][3], - borderColor: palette.additional["gray"][6], - "&:hover": { - borderColor: palette.additional["gray"][6], - backgroundColor: palette.additional["gray"][7], - color: palette.common.white.main, - }, - "&:focus": { - borderColor: palette.additional["gray"][6], - }, - }, - currencySelector: { - width: "40%", - paddingRight: constants.generalUnit, - "& *": { - cursor: "pointer", - }, - }, - token: {}, - address: { - margin: 0, - marginBottom: constants.generalUnit * 3, - }, - addressInput: {}, - generalInput: { - "& > span": { - marginBottom: constants.generalUnit, - }, - }, - faqButton: { - cursor: "pointer", - height: 20, - width: 20, - marginTop: constants.generalUnit * 5, - fill: `${palette.additional["transferUi"][1]} !important`, - }, - tokenItem: { - display: "flex", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center", - cursor: "pointer", - "& img, & svg": { - display: "block", - height: 14, - width: 14, - marginRight: 10, - }, - "& span": { - minWidth: `calc(100% - 20px)`, - textAlign: "left", - }, - }, - fees: { - display: "flex", - flexDirection: "row", - flexWrap: "wrap", - justifyContent: "space-between", - marginBottom: constants.generalUnit, - "& > *": { - display: "block", - width: "50%", - color: palette.additional["gray"][8], - marginBottom: constants.generalUnit / 2, - "&:nth-child(even)": { - textAlign: "right", - }, - }, - }, - accountSelector: { - marginBottom: 24, - }, - }) -); - -type PreflightDetails = { - tokenAmount: number; - token: string; - tokenSymbol: string; - receiver: string; -}; - -const TransferPage = () => { - const classes = useStyles(); - const { walletType, setWalletType } = useNetworkManager(); - - const { - deposit, - setDestinationChain, - transactionStatus, - resetDeposit, - bridgeFee, - tokens, - isReady, - homeConfig, - destinationChainConfig, - destinationChains, - address, - checkSupplies, - } = useChainbridge(); - - const { accounts, selectAccount } = useHomeBridge(); - const [aboutOpen, setAboutOpen] = useState(false); - const [walletConnecting, setWalletConnecting] = useState(false); - const [changeNetworkOpen, setChangeNetworkOpen] = useState(false); - const [preflightModalOpen, setPreflightModalOpen] = useState(false); - - const [preflightDetails, setPreflightDetails] = useState({ - receiver: "", - token: "", - tokenAmount: 0, - tokenSymbol: "", - }); - - const { redirect } = useHistory(); - - useEffect(() => { - if (walletType !== "select" && walletConnecting === true) { - setWalletConnecting(false); - } else if (walletType === "select") { - setWalletConnecting(true); - } - }, [walletType, walletConnecting]); - - const selectedToken = homeConfig?.tokens.find( - (token) => token.address === preflightDetails.token - ); - - const DECIMALS = - selectedToken && selectedToken.decimals ? selectedToken.decimals : 18; - - const REGEX = - DECIMALS > 0 - ? new RegExp(`^[0-9]{1,18}(.[0-9]{1,${DECIMALS}})?$`) - : new RegExp(`^[0-9]{1,18}?$`); - - const transferSchema = object().shape({ - tokenAmount: string() - .test("Token selected", "Please select a token", (value) => { - if ( - !!value && - preflightDetails && - tokens[preflightDetails.token] && - tokens[preflightDetails.token].balance !== undefined - ) { - return true; - } else { - return false; - } - }) - .test("InputValid", "Input invalid", (value) => { - try { - return REGEX.test(`${value}`); - } catch (error) { - console.error(error); - return false; - } - }) - .test("Max", "Insufficent funds", (value) => { - if ( - value && - preflightDetails && - tokens[preflightDetails.token] && - tokens[preflightDetails.token].balance - ) { - if (homeConfig?.type === "Ethereum") { - return parseFloat(value) <= tokens[preflightDetails.token].balance; - } else { - return ( - parseFloat(value + (bridgeFee || 0)) <= - tokens[preflightDetails.token].balance - ); - } - } - return false; - }) - .test( - "Bridge Supplies", - "Not enough tokens on the destination chain. Please contact support.", - async (value) => { - if (checkSupplies && destinationChainConfig && value) { - const supplies = await checkSupplies( - parseFloat(value), - preflightDetails.token, - destinationChainConfig.domainId - ); - return Boolean(supplies); - } - return false; - } - ) - .test("Min", "Less than minimum", (value) => { - if (value) { - return parseFloat(value) > 0; - } - return false; - }) - .required("Please set a value"), - token: string().required("Please select a token"), - receiver: string() - .test("Valid address", "Please add a valid address", (value) => { - if (destinationChainConfig?.type === "Substrate") { - return isValidSubstrateAddress(value as string); - } - return utils.isAddress(value as string); - }) - .required("Please add a receiving address"), - }); - - const handleClick = (txHash: string) => { - const url = `/explorer/transaction/${txHash}`; - - redirect(url); - }; - - return ( -
-
- {!isReady ? ( - - ) : walletConnecting ? ( -
- - This app requires access to your wallet,
- please login and authorize access to continue. -
-
- ) : ( -
-
- Home network - setChangeNetworkOpen(true)} - > - Change - -
- - {homeConfig?.name} - -
- )} -
- {isReady && - walletType === "Substrate" && - accounts && - accounts.length > 0 && ( -
-
- ({ - label: acc.address, - value: i, - }))} - onChange={(value) => selectAccount && selectAccount(value)} - value={accounts.findIndex((v) => v.address === address)} - placeholder="Select an account" - /> -
-
- )} - { - setPreflightDetails({ - ...values, - tokenSymbol: tokens[values.token].symbol || "", - }); - setPreflightModalOpen(true); - }} - > - {(props) => ( -
-
- ({ - label: dc.name, - value: dc.domainId, - }))} - onChange={(value) => setDestinationChain(value)} - value={destinationChainConfig?.domainId} - /> -
-
- {/*
-
- -
-
*/} -
- { - setPreflightDetails({ - ...preflightDetails, - token: tokenAddress, - receiver: "", - tokenAmount: 0, - tokenSymbol: "", - }); - }} - options={ - Object.keys(tokens).map((t) => ({ - value: t, - label: ( -
- {tokens[t]?.imageUri && ( - {tokens[t]?.symbol} - )} - {tokens[t]?.symbol || t} -
- ), - })) || [] - } - /> -
-
-
- -
-
-
-
- -
- -
- -
-
- setAboutOpen(true)} - className={classes.faqButton} - /> -
- - )} -
- setAboutOpen(false)} /> - setChangeNetworkOpen(false)} - /> - setPreflightModalOpen(false)} - receiver={preflightDetails?.receiver || ""} - sender={address || ""} - start={() => { - setPreflightModalOpen(false); - preflightDetails && - deposit( - preflightDetails.tokenAmount, - preflightDetails.receiver, - preflightDetails.token - ); - }} - sourceNetwork={homeConfig?.name || ""} - targetNetwork={destinationChainConfig?.name || ""} - tokenSymbol={preflightDetails?.tokenSymbol || ""} - value={preflightDetails?.tokenAmount || 0} - /> - - {/* This is here due to requiring router */} - -
- ); -}; -export default TransferPage; diff --git a/src/Components/Pages/WrapperPage.tsx b/src/Components/Pages/WrapperPage.tsx deleted file mode 100644 index ebcc8919..00000000 --- a/src/Components/Pages/WrapperPage.tsx +++ /dev/null @@ -1,513 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import AboutDrawer from "../../Modules/AboutDrawer"; -import ChangeNetworkDrawer from "../../Modules/ChangeNetworkDrawer"; -import { - Button, - Typography, - QuestionCircleSvg, - SelectInput, -} from "@chainsafe/common-components"; -import { Form, Formik } from "formik"; -import clsx from "clsx"; -import { useChainbridge } from "../../Contexts/ChainbridgeContext"; -import { object, string } from "yup"; -import { ReactComponent as ETHIcon } from "../../media/tokens/eth.svg"; -import { TokenConfig } from "../../chainbridgeConfig"; -import PreflightModalWrap from "../../Modules/PreflightModalWrap"; -import WrapActiveModal from "../../Modules/WrapActiveModal"; -import { forwardTo } from "../../Utils/History"; -import { ROUTE_LINKS } from "../Routes"; -import SimpleTokenInput from "../Custom/SimpleTokenInput"; -import { useNetworkManager } from "../../Contexts/NetworkManagerContext"; -import NetworkUnsupportedModal from "../../Modules/NetworkUnsupportedModal"; -import { showImageUrl } from "../../Utils/Helpers"; - -const useStyles = makeStyles(({ constants, palette }: ITheme) => - createStyles({ - root: { - minHeight: constants.generalUnit * 69, - padding: constants.generalUnit * 6, - overflow: "hidden", - position: "relative", - }, - walletArea: { - display: "flex", - flexDirection: "column", - alignItems: "center", - justifyContent: "center", - width: "100%", - }, - blurb: { - color: palette.common.black.main, - }, - connectButton: { - margin: `${constants.generalUnit * 3}px 0 ${constants.generalUnit * 6}px`, - }, - connecting: { - textAlign: "center", - marginBottom: constants.generalUnit * 2, - }, - connected: { - width: "100%", - "& > *:first-child": { - display: "flex", - flexDirection: "row", - alignItems: "center", - justifyContent: "space-between", - width: "100%", - }, - }, - changeButton: { - cursor: "pointer", - }, - networkName: { - padding: `${constants.generalUnit * 2}px ${ - constants.generalUnit * 1.5 - }px`, - border: `1px solid ${palette.additional["gray"][6]}`, - borderRadius: 2, - color: palette.additional["gray"][9], - marginTop: constants.generalUnit, - marginBottom: constants.generalUnit * 3, - }, - formArea: { - "&.disabled": { - opacity: 0.4, - }, - }, - currencySection: { - display: "flex", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "flex-end", - margin: `${constants.generalUnit * 3}px 0`, - }, - tokenInputArea: { - display: "flex", - flexDirection: "row", - alignItems: "flex-end", - justifyContent: "space-around", - paddingRight: constants.generalUnit, - }, - tokenInput: { - margin: 0, - "& > div": { - height: 32, - "& input": { - borderBottomRightRadius: 0, - borderTopRightRadius: 0, - borderRight: 0, - }, - }, - "& span:last-child.error": { - position: "absolute", - }, - }, - maxButton: { - height: 32, - borderBottomLeftRadius: 0, - borderTopLeftRadius: 0, - left: -1, - color: palette.additional["gray"][8], - backgroundColor: palette.additional["gray"][3], - borderColor: palette.additional["gray"][6], - "&:hover": { - borderColor: palette.additional["gray"][6], - backgroundColor: palette.additional["gray"][7], - color: palette.common.white.main, - }, - "&:focus": { - borderColor: palette.additional["gray"][6], - }, - }, - tokenIndicator: { - width: 120, - textAlign: "right", - "& p": { - marginBottom: constants.generalUnit, - }, - "& *": { - cursor: "pointer", - }, - }, - generalInput: { - "& > span": { - marginBottom: constants.generalUnit, - }, - }, - faqButton: { - cursor: "pointer", - height: 20, - width: 20, - marginTop: constants.generalUnit * 5, - fill: `${palette.additional["transferUi"][1]} !important`, - }, - token: { - backgroundColor: palette.additional["gray"][1], - borderRadius: 2, - border: `1px solid ${palette.additional["gray"][6]}`, - padding: `${constants.generalUnit * 1}px ${ - constants.generalUnit * 1.5 - }px`, - display: "flex", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center", - cursor: "pointer", - height: constants.generalUnit * 4, - "& img, & svg": { - display: "block", - height: 14, - width: 14, - marginLeft: 10, - }, - "& span": { - minWidth: `calc(100% - 30px)`, - textAlign: "right", - color: palette.additional["gray"][9], - }, - }, - tokenItem: { - display: "flex", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center", - cursor: "pointer", - "& img, & svg": { - display: "block", - height: 14, - width: 14, - marginRight: 10, - }, - "& span": { - minWidth: `calc(100% - 30px)`, - textAlign: "right", - }, - }, - submitButtonArea: {}, - }) -); - -type PreflightDetails = { - tokenAmount: number; -}; - -const MainPage = () => { - const classes = useStyles(); - const { walletType, setWalletType, homeChainConfig } = useNetworkManager(); - const { - wrapTokenConfig, - wrapToken, - unwrapToken, - homeConfig, - isReady, - tokens, - nativeTokenBalance, - address, - } = useChainbridge(); - - const [aboutOpen, setAboutOpen] = useState(false); - const [walletConnecting, setWalletConnecting] = useState(false); - const [changeNetworkOpen, setChangeNetworkOpen] = useState(false); - const [preflightModalOpen, setPreflightModalOpen] = useState(false); - const [preflightDetails, setPreflightDetails] = useState({ - tokenAmount: 0, - }); - const [action, setAction] = useState<"wrap" | "unwrap">("wrap"); - - const [txDetails, setTxDetails] = useState< - | { - txState?: "inProgress" | "done"; - value: number; - tokenInfo: TokenConfig; - txHash?: string; - action: "wrap" | "unwrap"; - } - | undefined - >(undefined); - - useEffect(() => { - if (walletType !== "select" && walletConnecting === true) { - setWalletConnecting(false); - } else if (walletType === "select") { - setWalletConnecting(true); - } - }, [walletType, walletConnecting]); - - const handleWrapToken = async () => { - if (!wrapTokenConfig || !wrapToken || !homeConfig) return; - - try { - setTxDetails({ - tokenInfo: wrapTokenConfig, - value: preflightDetails.tokenAmount, - txState: "inProgress", - action: action, - }); - const txHash = await wrapToken(preflightDetails.tokenAmount); - - if (txHash === "") { - setTxDetails(undefined); - throw Error("Wrap Transaction failed"); - } - - setTxDetails({ - tokenInfo: wrapTokenConfig, - value: preflightDetails.tokenAmount, - txHash: txHash, - txState: "done", - action: action, - }); - } catch (error) { - console.error(error); - } - }; - - const handleUnwrapToken = async () => { - if (!wrapTokenConfig || !unwrapToken || !homeConfig) return; - - try { - setTxDetails({ - tokenInfo: wrapTokenConfig, - value: preflightDetails.tokenAmount, - txState: "inProgress", - action: action, - }); - - const txHash = await unwrapToken(preflightDetails.tokenAmount); - - if (txHash === "") { - setTxDetails(undefined); - throw Error("Unwrap Transaction failed"); - } - - setTxDetails({ - tokenInfo: wrapTokenConfig, - value: preflightDetails.tokenAmount, - txHash: txHash, - txState: "done", - action: action, - }); - } catch (error) { - console.error(error); - } - }; - - const REGEX = - homeChainConfig?.decimals && homeChainConfig.decimals > 0 - ? new RegExp(`^[0-9]{1,18}(.[0-9]{1,${homeChainConfig.decimals}})?$`) - : new RegExp(`^[0-9]{1,18}?$`); - - const wrapSchema = object().shape({ - tokenAmount: string() - .matches(REGEX, "Input invalid") - .test("Min", "Less than minimum", (value) => { - if (value) { - return parseFloat(value) > 0; - } - return false; - }) - .test("Max", "Insufficent funds", (value) => { - return action === "wrap" - ? nativeTokenBalance && - value && - parseFloat(value) <= nativeTokenBalance - ? true - : false - : tokens[wrapTokenConfig?.address || "0x"].balance && - value && - parseFloat(value) <= - tokens[wrapTokenConfig?.address || "0x"]?.balance - ? true - : false; - }) - .required("Please set a value"), - }); - - return ( -
-
- {!isReady ? ( - <> - - To convert a token that needs to be wrapped, please connect to the - network that the token exists natively for. For example, to - convert ETH into wrapped ETH (WETH), your wallet must be connected - to an Ethereum network. - - - - ) : walletConnecting ? ( -
- - This app requires access to your wallet,
- please login and authorize access to continue. -
-
- ) : ( -
-
- Home network - setChangeNetworkOpen(true)} - > - Change - -
- - {homeConfig?.name} - -
- )} -
- { - setPreflightDetails({ - ...values, - }); - setPreflightModalOpen(true); - }} - > -
-
-
-
- -
-
-
- - Balance:{" "} - {action === "wrap" - ? nativeTokenBalance - ? nativeTokenBalance.toFixed(2) - : 0.0 - : tokens[wrapTokenConfig?.address || "0x"].balance} - - - - ETH - - ), - value: "wrap", - }, - { - label: ( -
- {wrapTokenConfig?.symbol} - {wrapTokenConfig?.symbol || "wETH"} -
- ), - value: "unwrap", - }, - ]} - onChange={(val) => setAction(val)} - value={action} - /> -
-
-
- -
-
- setAboutOpen(true)} - className={classes.faqButton} - /> -
-
-
- setAboutOpen(false)} /> - setChangeNetworkOpen(false)} - /> - setPreflightModalOpen(false)} - sender={address || ""} - start={() => { - if (action === "wrap") { - handleWrapToken(); - setPreflightModalOpen(false); - } else { - handleUnwrapToken(); - setPreflightModalOpen(false); - } - }} - sourceNetwork={homeConfig?.name || ""} - tokenSymbol={ - action === "wrap" - ? homeConfig?.nativeTokenSymbol || "ETH" - : wrapTokenConfig?.symbol || "wETH" - } - value={preflightDetails?.tokenAmount || 0} - wrappedTitle={ - action === "wrap" - ? `${wrapTokenConfig?.name} (${wrapTokenConfig?.symbol})` - : homeConfig?.nativeTokenSymbol || "ETH" - } - action={action} - /> - {txDetails && ( - { - setTxDetails(undefined); - forwardTo(ROUTE_LINKS.Transfer); - }} - /> - )} - {/* This is here due to requiring router */} - -
- ); -}; -export default MainPage; diff --git a/src/Layouts/AppHeader.tsx b/src/Layouts/AppHeader.tsx deleted file mode 100644 index 3c0e163f..00000000 --- a/src/Layouts/AppHeader.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import { createStyles, ITheme, makeStyles } from "@chainsafe/common-theme"; -import React from "react"; -import clsx from "clsx"; -import { Typography, NavLink } from "@chainsafe/common-components"; -import { shortenAddress } from "../Utils/Helpers"; -import { useChainbridge } from "../Contexts/ChainbridgeContext"; - -const ROUTE_LINKS_HEADERS = [ - { route: "/transfer", label: "Transfer" }, - { route: "/explorer/transaction/list", label: "Explorer" }, -]; - -const useStyles = makeStyles( - ({ constants, palette, zIndex, breakpoints }: ITheme) => { - return createStyles({ - root: { - display: "flex", - position: "fixed", - justifyContent: "space-between", - padding: `${constants.generalUnit * 2}px ${ - constants.generalUnit * 4 - }px`, - width: "100%", - top: 0, - left: 0, - backgroundColor: palette.additional["header"][1], - borderBottom: `1px solid ${palette.additional["header"][3]}`, - color: palette.additional["header"][2], - alignItems: "center", - zIndex: zIndex?.layer2, - [breakpoints.down("sm")]: { - flexDirection: "column", - }, - }, - left: { - display: "flex", - flexDirection: "row", - justifyContent: "flex-start", - alignItems: "center", - [breakpoints.down("sm")]: { - display: "flex", - flexDirection: "column", - }, - }, - logo: { - height: constants.generalUnit * 5, - width: constants.generalUnit * 5, - "& svg, & img": { - maxHeight: "100%", - maxWidth: "100%", - }, - }, - state: { - display: "flex", - flexDirection: "row", - alignItems: "center", - }, - indicator: { - display: "block", - height: 10, - width: 10, - borderRadius: "50%", - backgroundColor: palette.additional["green"][6], - marginRight: constants.generalUnit, - }, - address: { - marginRight: constants.generalUnit, - }, - network: {}, - accountInfo: { - display: "flex", - flexDirection: "row", - alignItems: "center", - justifyContent: "center", - }, - mainInfo: { - display: "flex", - flexDirection: "column", - }, - mainTitle: {}, - headerLinks: { - marginLeft: 49, - [breakpoints.down("sm")]: { - display: "flex", - flexDirection: "row", - justifyContent: "center", - marginLeft: "unset", - alignItems: "center", - width: "100%", - "& > a:last-child": { - marginLeft: 5, - }, - }, - }, - link: { - marginLeft: 46, - textDecoration: "none", - [breakpoints.down("sm")]: { - marginLeft: "unset", - }, - }, - linkTitle: { - fontSize: 16, - }, - }); - } -); - -interface IAppHeader {} - -const AppHeader: React.FC = () => { - const classes = useStyles(); - const { homeConfig, isReady, address } = useChainbridge(); - - const { __RUNTIME_CONFIG__ } = window; - - const indexerEnabled = "INDEXER_URL" in __RUNTIME_CONFIG__; - - return ( -
-
- {/* ADD LOGO HERE */} - {/*
-
*/} -
- ChainBridge Token Swap -
-
- {indexerEnabled ? ( - ROUTE_LINKS_HEADERS.map(({ route, label }) => ( - - {label} - - )) - ) : ( - - - {ROUTE_LINKS_HEADERS[0].label} - - - )} -
-
-
- {!isReady ? ( - No wallet connected - ) : ( - <> -
-
- - - {address && shortenAddress(address)} - -
- -
- connected to - - {homeConfig?.name} - -
-
-
- - )} -
-
- ); -}; - -export default AppHeader; diff --git a/src/Components/Custom/AddressInput.tsx b/src/components/AddressInput/AddressInput.tsx similarity index 85% rename from src/Components/Custom/AddressInput.tsx rename to src/components/AddressInput/AddressInput.tsx index 6bbdb6e0..0f131e37 100644 --- a/src/Components/Custom/AddressInput.tsx +++ b/src/components/AddressInput/AddressInput.tsx @@ -1,6 +1,4 @@ import React, { useCallback, useState } from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; import { CheckboxInput, FormikTextInputProps, @@ -8,22 +6,7 @@ import { } from "@chainsafe/common-components"; import clsx from "clsx"; import { useField } from "formik"; - -const useStyles = makeStyles(({ constants }: ITheme) => - createStyles({ - root: {}, - input: { - margin: 0, - width: "100%", - }, - label: { - marginBottom: constants.generalUnit, - }, - checkbox: { - marginTop: constants.generalUnit * 3, - }, - }) -); +import { useStyles } from "./styles"; interface IAddressInput extends FormikTextInputProps { senderAddress: string; diff --git a/src/components/AddressInput/index.ts b/src/components/AddressInput/index.ts new file mode 100644 index 00000000..bde38327 --- /dev/null +++ b/src/components/AddressInput/index.ts @@ -0,0 +1 @@ +export { default } from "./AddressInput"; diff --git a/src/components/AddressInput/styles.ts b/src/components/AddressInput/styles.ts new file mode 100644 index 00000000..c383a5c3 --- /dev/null +++ b/src/components/AddressInput/styles.ts @@ -0,0 +1,17 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants }: ITheme) => + createStyles({ + root: {}, + input: { + margin: 0, + width: "100%", + }, + label: { + marginBottom: constants.generalUnit, + }, + checkbox: { + marginTop: constants.generalUnit * 3, + }, + }) +); diff --git a/src/Components/Custom/AddressOrLink.tsx b/src/components/AddressOrLink/AddressOrLink.tsx similarity index 100% rename from src/Components/Custom/AddressOrLink.tsx rename to src/components/AddressOrLink/AddressOrLink.tsx diff --git a/src/components/AddressOrLink/index.ts b/src/components/AddressOrLink/index.ts new file mode 100644 index 00000000..e0b758c8 --- /dev/null +++ b/src/components/AddressOrLink/index.ts @@ -0,0 +1 @@ +export { default } from "./AddressOrLink"; diff --git a/src/Components/Custom/CustomDrawer.tsx b/src/components/CustomDrawer/CustomDrawer.tsx similarity index 51% rename from src/Components/Custom/CustomDrawer.tsx rename to src/components/CustomDrawer/CustomDrawer.tsx index 80d0c27d..25b14a40 100644 --- a/src/Components/Custom/CustomDrawer.tsx +++ b/src/components/CustomDrawer/CustomDrawer.tsx @@ -1,23 +1,7 @@ import React from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; import { Drawer, IDrawerProps } from "@chainsafe/common-components"; import clsx from "clsx"; - -const useStyles = makeStyles(({ constants, palette }: ITheme) => - createStyles({ - root: { - backgroundColor: `${palette.additional["gray"][9]} !important`, - color: palette.common.white.main, - border: "none", - padding: `${constants.generalUnit * 3}px ${constants.generalUnit * 4}px`, - }, - backdrop: { - backgroundColor: `${palette.additional["gray"][9]} !important`, - opacity: `0.6 !important`, - }, - }) -); +import { useStyles } from "./styles"; interface ICustomDrawerProps extends IDrawerProps {} diff --git a/src/components/CustomDrawer/index.ts b/src/components/CustomDrawer/index.ts new file mode 100644 index 00000000..8cf19c90 --- /dev/null +++ b/src/components/CustomDrawer/index.ts @@ -0,0 +1 @@ +export { default } from "./CustomDrawer"; diff --git a/src/components/CustomDrawer/styles.ts b/src/components/CustomDrawer/styles.ts new file mode 100644 index 00000000..c9d5e18c --- /dev/null +++ b/src/components/CustomDrawer/styles.ts @@ -0,0 +1,16 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants, palette }: ITheme) => + createStyles({ + root: { + backgroundColor: `${palette.additional["gray"][9]} !important`, + color: palette.common.white.main, + border: "none", + padding: `${constants.generalUnit * 3}px ${constants.generalUnit * 4}px`, + }, + backdrop: { + backgroundColor: `${palette.additional["gray"][9]} !important`, + opacity: `0.6 !important`, + }, + }) +); diff --git a/src/Components/Custom/CustomModal.tsx b/src/components/CustomModal/CustomModal.tsx similarity index 55% rename from src/Components/Custom/CustomModal.tsx rename to src/components/CustomModal/CustomModal.tsx index 97322c3d..ee469ac0 100644 --- a/src/Components/Custom/CustomModal.tsx +++ b/src/components/CustomModal/CustomModal.tsx @@ -1,20 +1,7 @@ import React from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; import { IModalProps, Modal } from "@chainsafe/common-components"; import clsx from "clsx"; - -const useStyles = makeStyles(({ constants }: ITheme) => - createStyles({ - root: { - height: `100% !important`, - borderTopLeftRadius: constants.generalUnit / 2, - borderTopRightRadius: constants.generalUnit / 2, - overflow: "hidden", - position: "absolute", - }, - }) -); +import { useStyles } from "./styles"; interface ICustomModalProps extends IModalProps {} diff --git a/src/components/CustomModal/index.ts b/src/components/CustomModal/index.ts new file mode 100644 index 00000000..f13c96c8 --- /dev/null +++ b/src/components/CustomModal/index.ts @@ -0,0 +1 @@ +export { default } from "./CustomModal"; diff --git a/src/components/CustomModal/styles.ts b/src/components/CustomModal/styles.ts new file mode 100644 index 00000000..5ca68136 --- /dev/null +++ b/src/components/CustomModal/styles.ts @@ -0,0 +1,13 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants }: ITheme) => + createStyles({ + root: { + height: `100% !important`, + borderTopLeftRadius: constants.generalUnit / 2, + borderTopRightRadius: constants.generalUnit / 2, + overflow: "hidden", + position: "absolute", + }, + }) +); diff --git a/src/Components/Custom/DetailView.test.tsx b/src/components/DetailView/DetailView.test.tsx similarity index 94% rename from src/Components/Custom/DetailView.test.tsx rename to src/components/DetailView/DetailView.test.tsx index 1edbc450..a9ad08f6 100644 --- a/src/Components/Custom/DetailView.test.tsx +++ b/src/components/DetailView/DetailView.test.tsx @@ -1,9 +1,9 @@ import React from "react"; import { ThemeSwitcher } from "@chainsafe/common-theme"; import { render } from "@testing-library/react"; -import { lightTheme } from "../../Themes/LightTheme"; -import { computeTransferDetails } from "../../Utils/Helpers"; -import { runtimeTestingConfig, testResponse } from "../../Utils/TestUtils"; +import { lightTheme } from "../../themes/LightTheme"; +import { computeTransferDetails } from "../../utils/Helpers"; +import { runtimeTestingConfig, testResponse } from "../../utils/TestUtils"; import DetailView from "./DetailView"; describe("DetailView", () => { diff --git a/src/Components/Custom/DetailView.tsx b/src/components/DetailView/DetailView.tsx similarity index 98% rename from src/Components/Custom/DetailView.tsx rename to src/components/DetailView/DetailView.tsx index fdcbae89..db74f63f 100644 --- a/src/Components/Custom/DetailView.tsx +++ b/src/components/DetailView/DetailView.tsx @@ -9,15 +9,15 @@ import { Blockies, } from "@chainsafe/common-components"; import clsx from "clsx"; -import { TransferDetails } from "../../Contexts/Reducers/TransfersReducer"; +import { TransferDetails } from "../../reducers/TransfersReducer"; import { getProposalStatus, getRandomSeed, showImageUrlNetworkIcons, getNetworkIcon, -} from "../../Utils/Helpers"; +} from "../../utils/Helpers"; import { ReactComponent as HashTxIcon } from "../../media/Icons/hashTx.svg"; -import AddressOrLink from "./AddressOrLink"; +import AddressOrLink from "../AddressOrLink/AddressOrLink"; type DetailView = { active: boolean; diff --git a/src/components/DetailView/index.ts b/src/components/DetailView/index.ts new file mode 100644 index 00000000..e44f3b48 --- /dev/null +++ b/src/components/DetailView/index.ts @@ -0,0 +1 @@ +export { default } from "./DetailView"; diff --git a/src/Components/Custom/ExplorerTable/ExplorerTable.tsx b/src/components/ExplorerTable/ExplorerTable.tsx similarity index 95% rename from src/Components/Custom/ExplorerTable/ExplorerTable.tsx rename to src/components/ExplorerTable/ExplorerTable.tsx index 5d4b1d22..cee13f60 100644 --- a/src/Components/Custom/ExplorerTable/ExplorerTable.tsx +++ b/src/components/ExplorerTable/ExplorerTable.tsx @@ -14,7 +14,7 @@ import { import { DepositRecord, TransferDetails, -} from "../../../Contexts/Reducers/TransfersReducer"; +} from "../../reducers/TransfersReducer"; import { formatTransferDate, getRandomSeed, @@ -26,13 +26,13 @@ import { selectToken, showImageUrlNetworkIcons, getNetworkIcon, -} from "../../../Utils/Helpers"; -import { ReactComponent as DirectionalIcon } from "../../../media/Icons/directional.svg"; -import DetailView from "../DetailView"; +} from "../../utils/Helpers"; +import { ReactComponent as DirectionalIcon } from "../../media/Icons/directional.svg"; +import DetailView from "../DetailView/DetailView"; import { EvmBridgeConfig, SubstrateBridgeConfig, -} from "../../../chainbridgeConfig"; +} from "../../chainbridgeConfig"; import { useStyles } from "./styles"; // TODO: just for mocking purposes diff --git a/src/Components/Custom/ExplorerTable/index.ts b/src/components/ExplorerTable/index.ts similarity index 100% rename from src/Components/Custom/ExplorerTable/index.ts rename to src/components/ExplorerTable/index.ts diff --git a/src/Components/Custom/ExplorerTable/styles.ts b/src/components/ExplorerTable/styles.ts similarity index 100% rename from src/Components/Custom/ExplorerTable/styles.ts rename to src/components/ExplorerTable/styles.ts diff --git a/src/Components/Pages/FormikContextElements/Fees.tsx b/src/components/FormikContextElements/Fees.tsx similarity index 100% rename from src/Components/Pages/FormikContextElements/Fees.tsx rename to src/components/FormikContextElements/Fees.tsx diff --git a/src/components/FormikContextElements/index.ts b/src/components/FormikContextElements/index.ts new file mode 100644 index 00000000..b0d853f1 --- /dev/null +++ b/src/components/FormikContextElements/index.ts @@ -0,0 +1 @@ +export { default } from "./Fees"; diff --git a/src/Components/Custom/SimpleTokenInput.tsx b/src/components/SimpleTokenInput/SimpleTokenInput.tsx similarity index 99% rename from src/Components/Custom/SimpleTokenInput.tsx rename to src/components/SimpleTokenInput/SimpleTokenInput.tsx index 24cea246..248246cc 100644 --- a/src/Components/Custom/SimpleTokenInput.tsx +++ b/src/components/SimpleTokenInput/SimpleTokenInput.tsx @@ -1,5 +1,4 @@ import React from "react"; - import { useField } from "formik"; import { Button, FormikTextInput } from "@chainsafe/common-components"; diff --git a/src/components/SimpleTokenInput/index.ts b/src/components/SimpleTokenInput/index.ts new file mode 100644 index 00000000..ad10ad76 --- /dev/null +++ b/src/components/SimpleTokenInput/index.ts @@ -0,0 +1 @@ +export { default } from "./SimpleTokenInput"; diff --git a/src/Components/Custom/TokenInput.tsx b/src/components/TokenInput/TokenInput.tsx similarity index 99% rename from src/Components/Custom/TokenInput.tsx rename to src/components/TokenInput/TokenInput.tsx index 333140a9..43681ef5 100644 --- a/src/Components/Custom/TokenInput.tsx +++ b/src/components/TokenInput/TokenInput.tsx @@ -1,5 +1,4 @@ import React from "react"; - import { useField, useFormikContext } from "formik"; import { Button, FormikTextInput } from "@chainsafe/common-components"; import { Tokens } from "@chainsafe/web3-context/dist/context/tokensReducer"; diff --git a/src/components/TokenInput/index.ts b/src/components/TokenInput/index.ts new file mode 100644 index 00000000..1f7161f5 --- /dev/null +++ b/src/components/TokenInput/index.ts @@ -0,0 +1 @@ +export { default } from "./TokenInput"; diff --git a/src/Components/Custom/TokenSelectInput.tsx b/src/components/TokenSelectInput/TokenSelectInput.tsx similarity index 100% rename from src/Components/Custom/TokenSelectInput.tsx rename to src/components/TokenSelectInput/TokenSelectInput.tsx diff --git a/src/components/TokenSelectInput/index.ts b/src/components/TokenSelectInput/index.ts new file mode 100644 index 00000000..b582bddc --- /dev/null +++ b/src/components/TokenSelectInput/index.ts @@ -0,0 +1 @@ +export { default } from "./TokenSelectInput"; diff --git a/src/Components/Custom/TransferDetailView.tsx b/src/components/TransferDetailView/TransferDetailView.tsx similarity index 97% rename from src/Components/Custom/TransferDetailView.tsx rename to src/components/TransferDetailView/TransferDetailView.tsx index 4050fbf3..b404b876 100644 --- a/src/Components/Custom/TransferDetailView.tsx +++ b/src/components/TransferDetailView/TransferDetailView.tsx @@ -10,11 +10,11 @@ import { getRandomSeed, showImageUrlNetworkIcons, getProposalStatus, -} from "../../Utils/Helpers"; -import { TransferDetails } from "../../Contexts/Reducers/TransfersReducer"; +} from "../../utils/Helpers"; +import { TransferDetails } from "../../reducers/TransfersReducer"; import { ReactComponent as HashTxIcon } from "../../media/Icons/hashTx.svg"; -import AddressOrLink from "./AddressOrLink"; -import { useStyles } from "../Custom/ExplorerTable/styles"; +import AddressOrLink from "../AddressOrLink/AddressOrLink"; +import { useStyles } from "../ExplorerTable/styles"; type TransferDetailView = { transferDetails: TransferDetails; diff --git a/src/components/TransferDetailView/index.ts b/src/components/TransferDetailView/index.ts new file mode 100644 index 00000000..ffbf1a5d --- /dev/null +++ b/src/components/TransferDetailView/index.ts @@ -0,0 +1 @@ +export { default } from "./TransferDetailView"; diff --git a/src/Components/Custom/__snapshots__/DetailView.test.tsx.snap b/src/components/__snapshots__/DetailView.test.tsx.snap similarity index 100% rename from src/Components/Custom/__snapshots__/DetailView.test.tsx.snap rename to src/components/__snapshots__/DetailView.test.tsx.snap diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 00000000..8f8b530d --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,10 @@ +export { default as ExplorerTable } from "./ExplorerTable"; +export { default as AddressInput } from "./AddressInput"; +export { default as AddressOrLink } from "./AddressOrLink"; +export { default as CustomDrawer } from "./CustomDrawer"; +export { default as CustomModal } from "./CustomModal"; +export { default as Fees } from "./FormikContextElements"; +export { default as SimpleTokenInput } from "./SimpleTokenInput"; +export { default as TokenInput } from "./TokenInput"; +export { default as TokenSelectInput } from "./TokenSelectInput"; +export { default as TransferDetailView } from "./TransferDetailView"; diff --git a/src/Contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx b/src/contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx similarity index 97% rename from src/Contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx rename to src/contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx index c8d282ae..015056e2 100644 --- a/src/Contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx +++ b/src/contexts/Adaptors/EVMAdaptors/EVMDestinationAdaptorProvider.tsx @@ -1,9 +1,10 @@ +// @ts-nocheck import React from "react"; import { Bridge, BridgeFactory } from "@chainsafe/chainbridge-contracts"; import { BigNumber } from "ethers"; import { useEffect, useState } from "react"; import { EvmBridgeConfig } from "../../../chainbridgeConfig"; -import { useNetworkManager } from "../../NetworkManagerContext"; +import { useNetworkManager } from "../../NetworkManagerContext/NetworkManagerContext"; import { IDestinationBridgeProviderProps } from "../interfaces"; import { DestinationBridgeContext } from "../../DestinationBridgeContext"; diff --git a/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx b/src/contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx similarity index 98% rename from src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx rename to src/contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx index 136cfa0c..239f6d28 100644 --- a/src/Contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx +++ b/src/contexts/Adaptors/EVMAdaptors/EVMHomeAdaptorProvider.tsx @@ -1,3 +1,4 @@ +// @ts-nocheck import React from "react"; import { Bridge, BridgeFactory } from "@chainsafe/chainbridge-contracts"; import { useWeb3 } from "@chainsafe/web3-context"; @@ -11,12 +12,12 @@ import { import { Erc20DetailedFactory } from "../../../Contracts/Erc20DetailedFactory"; import { Weth } from "../../../Contracts/Weth"; import { WethFactory } from "../../../Contracts/WethFactory"; -import { useNetworkManager } from "../../NetworkManagerContext"; +import { useNetworkManager } from "../../NetworkManagerContext/NetworkManagerContext"; import { IHomeBridgeProviderProps } from "../interfaces"; import { HomeBridgeContext } from "../../HomeBridgeContext"; import { parseUnits } from "ethers/lib/utils"; import { decodeAddress } from "@polkadot/util-crypto"; -import { getNetworkName } from "../../../Utils/Helpers"; +import { getNetworkName } from "../../../utils/Helpers"; import { hasTokenSupplies, getPriceCompatibility } from "./helpers"; diff --git a/src/Contexts/Adaptors/EVMAdaptors/helpers.ts b/src/contexts/Adaptors/EVMAdaptors/helpers.ts similarity index 100% rename from src/Contexts/Adaptors/EVMAdaptors/helpers.ts rename to src/contexts/Adaptors/EVMAdaptors/helpers.ts diff --git a/src/Contexts/Adaptors/EVMAdaptors/index.tsx b/src/contexts/Adaptors/EVMAdaptors/index.tsx similarity index 100% rename from src/Contexts/Adaptors/EVMAdaptors/index.tsx rename to src/contexts/Adaptors/EVMAdaptors/index.tsx diff --git a/src/Contexts/Adaptors/SubstrateAdaptors.tsx b/src/contexts/Adaptors/SubstrateAdaptors.tsx similarity index 99% rename from src/Contexts/Adaptors/SubstrateAdaptors.tsx rename to src/contexts/Adaptors/SubstrateAdaptors.tsx index 85a8dd8e..0aee2dcf 100644 --- a/src/Contexts/Adaptors/SubstrateAdaptors.tsx +++ b/src/contexts/Adaptors/SubstrateAdaptors.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useState } from "react"; import { DestinationBridgeContext } from "../DestinationBridgeContext"; import { HomeBridgeContext } from "../HomeBridgeContext"; -import { useNetworkManager } from "../NetworkManagerContext"; +import { useNetworkManager } from "../NetworkManagerContext/NetworkManagerContext"; import { createApi, submitDeposit } from "./SubstrateApis/ChainBridgeAPI"; import { IDestinationBridgeProviderProps, diff --git a/src/Contexts/Adaptors/SubstrateApis/ChainBridgeAPI.tsx b/src/contexts/Adaptors/SubstrateApis/ChainBridgeAPI.tsx similarity index 100% rename from src/Contexts/Adaptors/SubstrateApis/ChainBridgeAPI.tsx rename to src/contexts/Adaptors/SubstrateApis/ChainBridgeAPI.tsx diff --git a/src/Contexts/Adaptors/SubstrateApis/bridgeTypes.json b/src/contexts/Adaptors/SubstrateApis/bridgeTypes.json similarity index 100% rename from src/Contexts/Adaptors/SubstrateApis/bridgeTypes.json rename to src/contexts/Adaptors/SubstrateApis/bridgeTypes.json diff --git a/src/Contexts/Adaptors/SubstrateApis/centrifuge-types.ts b/src/contexts/Adaptors/SubstrateApis/centrifuge-types.ts similarity index 100% rename from src/Contexts/Adaptors/SubstrateApis/centrifuge-types.ts rename to src/contexts/Adaptors/SubstrateApis/centrifuge-types.ts diff --git a/src/Contexts/Adaptors/interfaces.tsx b/src/contexts/Adaptors/interfaces.tsx similarity index 100% rename from src/Contexts/Adaptors/interfaces.tsx rename to src/contexts/Adaptors/interfaces.tsx diff --git a/src/Contexts/ChainbridgeContext.tsx b/src/contexts/ChainbridgeContext/ChainbridgeContext.tsx similarity index 96% rename from src/Contexts/ChainbridgeContext.tsx rename to src/contexts/ChainbridgeContext/ChainbridgeContext.tsx index 946e1d89..553c9cdb 100644 --- a/src/Contexts/ChainbridgeContext.tsx +++ b/src/contexts/ChainbridgeContext/ChainbridgeContext.tsx @@ -5,15 +5,15 @@ import { EvmBridgeConfig, SubstrateBridgeConfig, TokenConfig, -} from "../chainbridgeConfig"; +} from "../../chainbridgeConfig"; import { Tokens } from "@chainsafe/web3-context/dist/context/tokensReducer"; import { TransactionStatus, useNetworkManager, TransitMessage, -} from "./NetworkManagerContext"; -import { useHomeBridge } from "./HomeBridgeContext"; -import NetworkSelectModal from "../Modules/NetworkSelectModal"; +} from "../NetworkManagerContext/NetworkManagerContext"; +import { useHomeBridge } from "../HomeBridgeContext"; +import NetworkSelectModal from "../../modules/NetworkSelectModal"; interface IChainbridgeContextProps { children: React.ReactNode | React.ReactNode[]; diff --git a/src/contexts/ChainbridgeContext/index.ts b/src/contexts/ChainbridgeContext/index.ts new file mode 100644 index 00000000..3af58226 --- /dev/null +++ b/src/contexts/ChainbridgeContext/index.ts @@ -0,0 +1 @@ +export { ChainbridgeProvider, useChainbridge } from "./ChainbridgeContext"; diff --git a/src/Contexts/DestinationBridgeContext.tsx b/src/contexts/DestinationBridgeContext/DestinationBridgeContext.tsx similarity index 86% rename from src/Contexts/DestinationBridgeContext.tsx rename to src/contexts/DestinationBridgeContext/DestinationBridgeContext.tsx index 535473ac..f55a469f 100644 --- a/src/Contexts/DestinationBridgeContext.tsx +++ b/src/contexts/DestinationBridgeContext/DestinationBridgeContext.tsx @@ -1,5 +1,5 @@ import React, { useContext } from "react"; -import { DestinationChainContext } from "./Adaptors/interfaces"; +import { DestinationChainContext } from "../Adaptors/interfaces"; const DestinationBridgeContext = React.createContext< DestinationChainContext | undefined diff --git a/src/contexts/DestinationBridgeContext/index.ts b/src/contexts/DestinationBridgeContext/index.ts new file mode 100644 index 00000000..7b7f805b --- /dev/null +++ b/src/contexts/DestinationBridgeContext/index.ts @@ -0,0 +1,4 @@ +export { + DestinationBridgeContext, + useDestinationBridge, +} from "./DestinationBridgeContext"; diff --git a/src/Contexts/ExplorerContext.tsx b/src/contexts/ExplorerContext/ExplorerContext.tsx similarity index 90% rename from src/Contexts/ExplorerContext.tsx rename to src/contexts/ExplorerContext/ExplorerContext.tsx index d81ad85b..85f4d80e 100644 --- a/src/Contexts/ExplorerContext.tsx +++ b/src/contexts/ExplorerContext/ExplorerContext.tsx @@ -1,6 +1,9 @@ import React, { useContext, useEffect, useState } from "react"; -import { ExplorerState, PaginationParams } from "./Reducers/TransfersReducer"; -import { fetchTransfers } from "../Services/ExplorerService"; +import { + ExplorerState, + PaginationParams, +} from "../../reducers/TransfersReducer"; +import { fetchTransfers } from "../../services/ExplorerService"; const DEFAULT_PAGINATION_OPTIONS = { first: "10" }; diff --git a/src/contexts/ExplorerContext/index.ts b/src/contexts/ExplorerContext/index.ts new file mode 100644 index 00000000..165100d8 --- /dev/null +++ b/src/contexts/ExplorerContext/index.ts @@ -0,0 +1 @@ +export { ExplorerProvider, useExplorer } from "./ExplorerContext"; diff --git a/src/Contexts/HomeBridgeContext.tsx b/src/contexts/HomeBridgeContext/HomeBridgeContext.tsx similarity index 86% rename from src/Contexts/HomeBridgeContext.tsx rename to src/contexts/HomeBridgeContext/HomeBridgeContext.tsx index 3d1d0796..b963d899 100644 --- a/src/Contexts/HomeBridgeContext.tsx +++ b/src/contexts/HomeBridgeContext/HomeBridgeContext.tsx @@ -1,5 +1,5 @@ import React, { useContext } from "react"; -import { HomeChainAdaptorContext } from "./Adaptors/interfaces"; +import { HomeChainAdaptorContext } from "../Adaptors/interfaces"; const HomeBridgeContext = React.createContext< HomeChainAdaptorContext | undefined diff --git a/src/contexts/HomeBridgeContext/index.ts b/src/contexts/HomeBridgeContext/index.ts new file mode 100644 index 00000000..d6c33c49 --- /dev/null +++ b/src/contexts/HomeBridgeContext/index.ts @@ -0,0 +1 @@ +export { HomeBridgeContext, useHomeBridge } from "./HomeBridgeContext"; diff --git a/src/Contexts/LanguageContext.tsx b/src/contexts/LanguageContext/LanguageContext.tsx similarity index 100% rename from src/Contexts/LanguageContext.tsx rename to src/contexts/LanguageContext/LanguageContext.tsx diff --git a/src/contexts/LanguageContext/index.ts b/src/contexts/LanguageContext/index.ts new file mode 100644 index 00000000..a6850cf7 --- /dev/null +++ b/src/contexts/LanguageContext/index.ts @@ -0,0 +1 @@ +export { LanguageProvider, useLanguageContext } from "./LanguageContext"; diff --git a/src/Contexts/NetworkManagerContext.tsx b/src/contexts/NetworkManagerContext/NetworkManagerContext.tsx similarity index 95% rename from src/Contexts/NetworkManagerContext.tsx rename to src/contexts/NetworkManagerContext/NetworkManagerContext.tsx index f2cd4a2e..9c01d843 100644 --- a/src/Contexts/NetworkManagerContext.tsx +++ b/src/contexts/NetworkManagerContext/NetworkManagerContext.tsx @@ -10,23 +10,22 @@ import { BridgeConfig, chainbridgeConfig, ChainType, -} from "../chainbridgeConfig"; +} from "../../chainbridgeConfig"; import { EVMDestinationAdaptorProvider, EVMHomeAdaptorProvider, -} from "./Adaptors/EVMAdaptors"; -import { IDestinationBridgeProviderProps } from "./Adaptors/interfaces"; +} from "../Adaptors/EVMAdaptors"; +import { IDestinationBridgeProviderProps } from "../Adaptors/interfaces"; import { SubstrateDestinationAdaptorProvider, SubstrateHomeAdaptorProvider, -} from "./Adaptors/SubstrateAdaptors"; -import { DestinationBridgeContext } from "./DestinationBridgeContext"; -import { HomeBridgeContext } from "./HomeBridgeContext"; +} from "../Adaptors/SubstrateAdaptors"; +import { HomeBridgeContext, DestinationBridgeContext } from ".."; import { AddMessageAction, ResetAction, transitMessageReducer, -} from "./Reducers/TransitMessageReducer"; +} from "../../reducers/TransitMessageReducer"; interface INetworkManagerProviderProps { children: React.ReactNode | React.ReactNode[]; diff --git a/src/contexts/NetworkManagerContext/index.ts b/src/contexts/NetworkManagerContext/index.ts new file mode 100644 index 00000000..70632d76 --- /dev/null +++ b/src/contexts/NetworkManagerContext/index.ts @@ -0,0 +1,4 @@ +export { + NetworkManagerProvider, + useNetworkManager, +} from "./NetworkManagerContext"; diff --git a/src/contexts/index.ts b/src/contexts/index.ts new file mode 100644 index 00000000..f00af8ef --- /dev/null +++ b/src/contexts/index.ts @@ -0,0 +1,12 @@ +export { ChainbridgeProvider, useChainbridge } from "./ChainbridgeContext"; +export { + DestinationBridgeContext, + useDestinationBridge, +} from "./DestinationBridgeContext"; +export { ExplorerProvider, useExplorer } from "./ExplorerContext"; +export { HomeBridgeContext, useHomeBridge } from "./HomeBridgeContext"; +export { LanguageProvider, useLanguageContext } from "./LanguageContext"; +export { + NetworkManagerProvider, + useNetworkManager, +} from "./NetworkManagerContext"; diff --git a/src/layouts/AppHeader/AppHeader.tsx b/src/layouts/AppHeader/AppHeader.tsx new file mode 100644 index 00000000..5f00c732 --- /dev/null +++ b/src/layouts/AppHeader/AppHeader.tsx @@ -0,0 +1,80 @@ +import React from "react"; +import clsx from "clsx"; +import { Typography, NavLink } from "@chainsafe/common-components"; +import { shortenAddress } from "../../utils/Helpers"; +import { useChainbridge } from "../../contexts/ChainbridgeContext/ChainbridgeContext"; +import { useStyles } from "./styles"; + +const ROUTE_LINKS_HEADERS = [ + { route: "/transfer", label: "Transfer" }, + { route: "/explorer/transaction/list", label: "Explorer" }, +]; + +interface IAppHeader {} + +const AppHeader: React.FC = () => { + const classes = useStyles(); + const { homeConfig, isReady, address } = useChainbridge(); + + const { __RUNTIME_CONFIG__ } = window; + + const indexerEnabled = "INDEXER_URL" in __RUNTIME_CONFIG__; + + return ( +
+
+ {/* ADD LOGO HERE */} + {/*
+
*/} +
+ ChainBridge Token Swap +
+
+ {indexerEnabled ? ( + ROUTE_LINKS_HEADERS.map(({ route, label }) => ( + + {label} + + )) + ) : ( + + + {ROUTE_LINKS_HEADERS[0].label} + + + )} +
+
+
+ {!isReady ? ( + No wallet connected + ) : ( + <> +
+
+ + + {address && shortenAddress(address)} + +
+ +
+ connected to + + {homeConfig?.name} + +
+
+
+ + )} +
+
+ ); +}; + +export default AppHeader; diff --git a/src/layouts/AppHeader/index.ts b/src/layouts/AppHeader/index.ts new file mode 100644 index 00000000..8ad0d174 --- /dev/null +++ b/src/layouts/AppHeader/index.ts @@ -0,0 +1 @@ +export { default } from "./AppHeader"; diff --git a/src/layouts/AppHeader/styles.ts b/src/layouts/AppHeader/styles.ts new file mode 100644 index 00000000..81f09c5e --- /dev/null +++ b/src/layouts/AppHeader/styles.ts @@ -0,0 +1,97 @@ +import { createStyles, ITheme, makeStyles } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles( + ({ constants, palette, zIndex, breakpoints }: ITheme) => { + return createStyles({ + root: { + display: "flex", + position: "fixed", + justifyContent: "space-between", + padding: `${constants.generalUnit * 2}px ${ + constants.generalUnit * 4 + }px`, + width: "100%", + top: 0, + left: 0, + backgroundColor: palette.additional["header"][1], + borderBottom: `1px solid ${palette.additional["header"][3]}`, + color: palette.additional["header"][2], + alignItems: "center", + zIndex: zIndex?.layer2, + [breakpoints.down("sm")]: { + flexDirection: "column", + }, + }, + left: { + display: "flex", + flexDirection: "row", + justifyContent: "flex-start", + alignItems: "center", + [breakpoints.down("sm")]: { + display: "flex", + flexDirection: "column", + }, + }, + logo: { + height: constants.generalUnit * 5, + width: constants.generalUnit * 5, + "& svg, & img": { + maxHeight: "100%", + maxWidth: "100%", + }, + }, + state: { + display: "flex", + flexDirection: "row", + alignItems: "center", + }, + indicator: { + display: "block", + height: 10, + width: 10, + borderRadius: "50%", + backgroundColor: palette.additional["green"][6], + marginRight: constants.generalUnit, + }, + address: { + marginRight: constants.generalUnit, + }, + network: {}, + accountInfo: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + }, + mainInfo: { + display: "flex", + flexDirection: "column", + }, + mainTitle: {}, + headerLinks: { + marginLeft: 49, + [breakpoints.down("sm")]: { + display: "flex", + flexDirection: "row", + justifyContent: "center", + marginLeft: "unset", + alignItems: "center", + width: "100%", + "& > a:last-child": { + marginLeft: 5, + }, + }, + }, + link: { + marginLeft: 46, + textDecoration: "none", + [breakpoints.down("sm")]: { + marginLeft: "unset", + }, + }, + linkTitle: { + fontSize: 16, + }, + }); + } +); diff --git a/src/layouts/AppWrapper/AppWrapper.tsx b/src/layouts/AppWrapper/AppWrapper.tsx new file mode 100644 index 00000000..00c6a40a --- /dev/null +++ b/src/layouts/AppWrapper/AppWrapper.tsx @@ -0,0 +1,84 @@ +import { + NavLink, + Typography, + useHistory, + useLocation, +} from "@chainsafe/common-components"; +import React, { useEffect, useState } from "react"; +import { ReactNode } from "react"; +import AppHeader from "../AppHeader/AppHeader"; +import { ReactComponent as GlobalSvg } from "../../media/Icons/global.svg"; +import { ReactComponent as GiftSvg } from "../../media/Icons/gift.svg"; +import { ROUTE_LINKS } from "../../routes"; +import { useStyles } from "./styles"; + +interface IAppWrapper { + children: ReactNode | ReactNode[]; + wrapTokenPage?: boolean; +} + +const AppWrapper: React.FC = ({ + children, + wrapTokenPage, +}: IAppWrapper) => { + const classes = useStyles(); + const [enableNavTabs, setEnableNavTabs] = useState(true); + + const location = useLocation(); + const { redirect } = useHistory(); + + const { __RUNTIME_CONFIG__ } = window; + + const indexerEnabled = "INDEXER_URL" in __RUNTIME_CONFIG__; + + useEffect(() => { + if (location.pathname.includes("/explorer") && !indexerEnabled) { + redirect("/transfer"); + } + }, []); + + useEffect(() => { + if (location.pathname.includes("/explorer")) { + return setEnableNavTabs(false); + } + return setEnableNavTabs(true); + }, [location]); + + return ( +
+ {enableNavTabs ? ( +
+ +
+ {enableNavTabs && ( +
+ + + Transfer + + {wrapTokenPage && ( + + + Wrap token + + )} +
+ )} +
{children}
+
+ + {/* Put CTA here */} + {/* + */} +
+ ) : ( +
+ +
{children}
+
+ )} +
+ ); +}; + +export default AppWrapper; diff --git a/src/layouts/AppWrapper/index.ts b/src/layouts/AppWrapper/index.ts new file mode 100644 index 00000000..0ed1284b --- /dev/null +++ b/src/layouts/AppWrapper/index.ts @@ -0,0 +1 @@ +export { default } from "./AppWrapper"; diff --git a/src/Layouts/AppWrapper.tsx b/src/layouts/AppWrapper/styles.ts similarity index 54% rename from src/Layouts/AppWrapper.tsx rename to src/layouts/AppWrapper/styles.ts index 5a78430a..a2880309 100644 --- a/src/Layouts/AppWrapper.tsx +++ b/src/layouts/AppWrapper/styles.ts @@ -1,23 +1,6 @@ -import { - NavLink, - Typography, - useHistory, - useLocation, -} from "@chainsafe/common-components"; import { createStyles, ITheme, makeStyles } from "@chainsafe/common-theme"; -import React, { useEffect, useState } from "react"; -import { ReactNode } from "react"; -import AppHeader from "./AppHeader"; -import { ReactComponent as GlobalSvg } from "../media/Icons/global.svg"; -import { ReactComponent as GiftSvg } from "../media/Icons/gift.svg"; -import { ROUTE_LINKS } from "../Components/Routes"; -interface IAppWrapper { - children: ReactNode | ReactNode[]; - wrapTokenPage?: boolean; -} - -const useStyles = makeStyles( +export const useStyles = makeStyles( ({ animation, constants, palette, breakpoints }: ITheme) => { return createStyles({ root: { @@ -121,69 +104,3 @@ const useStyles = makeStyles( }); } ); - -const AppWrapper: React.FC = ({ - children, - wrapTokenPage, -}: IAppWrapper) => { - const classes = useStyles(); - const [enableNavTabs, setEnableNavTabs] = useState(true); - - const location = useLocation(); - const { redirect } = useHistory(); - - const { __RUNTIME_CONFIG__ } = window; - - const indexerEnabled = "INDEXER_URL" in __RUNTIME_CONFIG__; - - useEffect(() => { - if (location.pathname.includes("/explorer") && !indexerEnabled) { - redirect("/transfer"); - } - }, []); - - useEffect(() => { - if (location.pathname.includes("/explorer")) { - return setEnableNavTabs(false); - } - return setEnableNavTabs(true); - }, [location]); - - return ( -
- {enableNavTabs ? ( -
- -
- {enableNavTabs && ( -
- - - Transfer - - {wrapTokenPage && ( - - - Wrap token - - )} -
- )} -
{children}
-
- - {/* Put CTA here */} - {/* - */} -
- ) : ( -
- -
{children}
-
- )} -
- ); -}; - -export default AppWrapper; diff --git a/src/layouts/index.ts b/src/layouts/index.ts new file mode 100644 index 00000000..15b93543 --- /dev/null +++ b/src/layouts/index.ts @@ -0,0 +1,2 @@ +export { default as AppHeader } from "./AppHeader"; +export { default as AppWrapper } from "./AppWrapper"; diff --git a/src/Modules/AboutDrawer.tsx b/src/modules/AboutDrawer/AboutDrawer.tsx similarity index 74% rename from src/Modules/AboutDrawer.tsx rename to src/modules/AboutDrawer/AboutDrawer.tsx index b60c28f6..fa2c5915 100644 --- a/src/Modules/AboutDrawer.tsx +++ b/src/modules/AboutDrawer/AboutDrawer.tsx @@ -1,27 +1,7 @@ import React from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import CustomDrawer from "../Components/Custom/CustomDrawer"; +import { CustomDrawer } from "../../components"; import { Button, Typography } from "@chainsafe/common-components"; - -const useStyles = makeStyles(({ constants }: ITheme) => - createStyles({ - root: { - display: "flex", - flexDirection: "column", - justifyContent: "space-between", - }, - buttons: { - display: "flex", - flexDirection: "row", - alignItems: "center", - "& *": { - marginRight: constants.generalUnit, - textDecoration: "none", - }, - }, - }) -); +import { useStyles } from "./styles"; interface IAboutDrawerProps { open: boolean; diff --git a/src/modules/AboutDrawer/index.ts b/src/modules/AboutDrawer/index.ts new file mode 100644 index 00000000..ba1ef688 --- /dev/null +++ b/src/modules/AboutDrawer/index.ts @@ -0,0 +1 @@ +export { default } from "./AboutDrawer"; diff --git a/src/modules/AboutDrawer/styles.ts b/src/modules/AboutDrawer/styles.ts new file mode 100644 index 00000000..733e34d8 --- /dev/null +++ b/src/modules/AboutDrawer/styles.ts @@ -0,0 +1,20 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants }: ITheme) => + createStyles({ + root: { + display: "flex", + flexDirection: "column", + justifyContent: "space-between", + }, + buttons: { + display: "flex", + flexDirection: "row", + alignItems: "center", + "& *": { + marginRight: constants.generalUnit, + textDecoration: "none", + }, + }, + }) +); diff --git a/src/Modules/ChangeNetworkDrawer.tsx b/src/modules/ChangeNetworkDrawer/ChangeNetworkDrawer.tsx similarity index 71% rename from src/Modules/ChangeNetworkDrawer.tsx rename to src/modules/ChangeNetworkDrawer/ChangeNetworkDrawer.tsx index f9c84a27..30ae8dc2 100644 --- a/src/Modules/ChangeNetworkDrawer.tsx +++ b/src/modules/ChangeNetworkDrawer/ChangeNetworkDrawer.tsx @@ -1,30 +1,10 @@ import React from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import CustomDrawer from "../Components/Custom/CustomDrawer"; +import { CustomDrawer } from "../../components"; import { Button, Typography } from "@chainsafe/common-components"; -import { useNetworkManager } from "../Contexts/NetworkManagerContext"; -import { useHomeBridge } from "../Contexts/HomeBridgeContext"; -import { useDestinationBridge } from "../Contexts/DestinationBridgeContext"; - -const useStyles = makeStyles(({ constants }: ITheme) => - createStyles({ - root: {}, - buttons: { - display: "flex", - flexDirection: "row", - flexWrap: "wrap", - "& > *": { - marginTop: constants.generalUnit * 2, - marginRight: constants.generalUnit, - textDecoration: "none", - }, - }, - paragraph: { - margin: `${constants.generalUnit * 3}px 0`, - }, - }) -); +import { useNetworkManager } from "../../contexts/NetworkManagerContext/NetworkManagerContext"; +import { useHomeBridge } from "../../contexts/HomeBridgeContext"; +import { useDestinationBridge } from "../../contexts/DestinationBridgeContext"; +import { useStyles } from "./styles"; interface IChangeNetworkDrawerProps { open: boolean; diff --git a/src/modules/ChangeNetworkDrawer/index.ts b/src/modules/ChangeNetworkDrawer/index.ts new file mode 100644 index 00000000..5d7768b0 --- /dev/null +++ b/src/modules/ChangeNetworkDrawer/index.ts @@ -0,0 +1 @@ +export { default } from "./ChangeNetworkDrawer"; diff --git a/src/modules/ChangeNetworkDrawer/styles.ts b/src/modules/ChangeNetworkDrawer/styles.ts new file mode 100644 index 00000000..8c86e2d7 --- /dev/null +++ b/src/modules/ChangeNetworkDrawer/styles.ts @@ -0,0 +1,20 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants }: ITheme) => + createStyles({ + root: {}, + buttons: { + display: "flex", + flexDirection: "row", + flexWrap: "wrap", + "& > *": { + marginTop: constants.generalUnit * 2, + marginRight: constants.generalUnit, + textDecoration: "none", + }, + }, + paragraph: { + margin: `${constants.generalUnit * 3}px 0`, + }, + }) +); diff --git a/src/Modules/NetworkSelectModal.tsx b/src/modules/NetworkSelectModal/NetworkSelectModal.tsx similarity index 66% rename from src/Modules/NetworkSelectModal.tsx rename to src/modules/NetworkSelectModal/NetworkSelectModal.tsx index f8f8de15..247aaa35 100644 --- a/src/Modules/NetworkSelectModal.tsx +++ b/src/modules/NetworkSelectModal/NetworkSelectModal.tsx @@ -1,34 +1,13 @@ import React from "react"; -import { createStyles, ITheme, makeStyles } from "@chainsafe/common-theme"; -import { useChainbridge } from "../Contexts/ChainbridgeContext"; -import { useNetworkManager } from "../Contexts/NetworkManagerContext"; +import { useChainbridge } from "../../contexts/ChainbridgeContext/ChainbridgeContext"; +import { useNetworkManager } from "../../contexts/NetworkManagerContext/NetworkManagerContext"; import { Button, Modal, ProgressBar, Typography, } from "@chainsafe/common-components"; - -const useStyles = makeStyles(({ constants, palette, zIndex }: ITheme) => { - return createStyles({ - root: {}, - slide: { - borderRadius: constants.generalUnit / 2, - padding: `${constants.generalUnit}px ${constants.generalUnit * 2}px`, - "& > p": { - marginTop: constants.generalUnit * 2, - marginBottom: constants.generalUnit * 3, - textAlign: "center", - }, - }, - buttons: { - marginBottom: constants.generalUnit * 2, - display: "flex", - flexDirection: "row", - justifyContent: "space-around", - }, - }); -}); +import { useStyles } from "./styles"; const NetworkSelectModal = () => { const classes = useStyles(); diff --git a/src/modules/NetworkSelectModal/index.ts b/src/modules/NetworkSelectModal/index.ts new file mode 100644 index 00000000..49c1b096 --- /dev/null +++ b/src/modules/NetworkSelectModal/index.ts @@ -0,0 +1 @@ +export { default } from "./NetworkSelectModal"; diff --git a/src/modules/NetworkSelectModal/styles.ts b/src/modules/NetworkSelectModal/styles.ts new file mode 100644 index 00000000..f3b4bec8 --- /dev/null +++ b/src/modules/NetworkSelectModal/styles.ts @@ -0,0 +1,24 @@ +import { createStyles, ITheme, makeStyles } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles( + ({ constants, palette, zIndex }: ITheme) => { + return createStyles({ + root: {}, + slide: { + borderRadius: constants.generalUnit / 2, + padding: `${constants.generalUnit}px ${constants.generalUnit * 2}px`, + "& > p": { + marginTop: constants.generalUnit * 2, + marginBottom: constants.generalUnit * 3, + textAlign: "center", + }, + }, + buttons: { + marginBottom: constants.generalUnit * 2, + display: "flex", + flexDirection: "row", + justifyContent: "space-around", + }, + }); + } +); diff --git a/src/Modules/NetworkUnsupportedModal.tsx b/src/modules/NetworkUnsupportedModal/NetworkUnsupportedModal.tsx similarity index 64% rename from src/Modules/NetworkUnsupportedModal.tsx rename to src/modules/NetworkUnsupportedModal/NetworkUnsupportedModal.tsx index 43285336..46f3ff7d 100644 --- a/src/Modules/NetworkUnsupportedModal.tsx +++ b/src/modules/NetworkUnsupportedModal/NetworkUnsupportedModal.tsx @@ -1,61 +1,15 @@ import React, { useEffect, useState } from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import CustomModal from "../Components/Custom/CustomModal"; +import { CustomModal } from "../../components"; import { Button, ExclamationCircleInverseSvg, Typography, useLocation, } from "@chainsafe/common-components"; -import { useNetworkManager } from "../Contexts/NetworkManagerContext"; -import { ROUTE_LINKS } from "../Components/Routes"; -import { useHomeBridge } from "../Contexts/HomeBridgeContext"; -import { chainbridgeConfig } from "../chainbridgeConfig"; - -const useStyles = makeStyles(({ constants, palette }: ITheme) => - createStyles({ - root: { - width: "100%", - }, - inner: { - width: "100% !important", - maxWidth: "unset !important", - borderRadius: "4px", - display: "flex", - flexDirection: "row", - padding: `${constants.generalUnit * 6}px ${constants.generalUnit * 7}px`, - }, - heading: { - marginBottom: constants.generalUnit, - }, - icon: { - height: 20, - width: 20, - marginTop: constants.generalUnit * 0.8, - marginRight: constants.generalUnit * 2, - fill: palette.additional["gray"][7], - }, - buttons: { - display: "flex", - flexDirection: "row", - marginTop: constants.generalUnit * 5, - "& > *": { - textDecoration: "none", - marginRight: constants.generalUnit, - }, - }, - button: { - borderColor: palette.additional["gray"][8], - color: palette.additional["gray"][8], - "&:hover": { - borderColor: palette.additional["gray"][8], - backgroundColor: palette.additional["gray"][8], - color: palette.common.white.main, - }, - }, - }) -); +import { useNetworkManager, useHomeBridge } from "../../contexts"; +import { ROUTE_LINKS } from "../../routes"; +import { chainbridgeConfig } from "../../chainbridgeConfig"; +import { useStyles } from "./styles"; const NetworkUnsupportedModal = () => { const classes = useStyles(); diff --git a/src/modules/NetworkUnsupportedModal/index.ts b/src/modules/NetworkUnsupportedModal/index.ts new file mode 100644 index 00000000..1b5362e4 --- /dev/null +++ b/src/modules/NetworkUnsupportedModal/index.ts @@ -0,0 +1 @@ +export { default } from "./NetworkUnsupportedModal"; diff --git a/src/modules/NetworkUnsupportedModal/styles.ts b/src/modules/NetworkUnsupportedModal/styles.ts new file mode 100644 index 00000000..584b14af --- /dev/null +++ b/src/modules/NetworkUnsupportedModal/styles.ts @@ -0,0 +1,45 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants, palette }: ITheme) => + createStyles({ + root: { + width: "100%", + }, + inner: { + width: "100% !important", + maxWidth: "unset !important", + borderRadius: "4px", + display: "flex", + flexDirection: "row", + padding: `${constants.generalUnit * 6}px ${constants.generalUnit * 7}px`, + }, + heading: { + marginBottom: constants.generalUnit, + }, + icon: { + height: 20, + width: 20, + marginTop: constants.generalUnit * 0.8, + marginRight: constants.generalUnit * 2, + fill: palette.additional["gray"][7], + }, + buttons: { + display: "flex", + flexDirection: "row", + marginTop: constants.generalUnit * 5, + "& > *": { + textDecoration: "none", + marginRight: constants.generalUnit, + }, + }, + button: { + borderColor: palette.additional["gray"][8], + color: palette.additional["gray"][8], + "&:hover": { + borderColor: palette.additional["gray"][8], + backgroundColor: palette.additional["gray"][8], + color: palette.common.white.main, + }, + }, + }) +); diff --git a/src/Modules/PreflightModalTransfer.tsx b/src/modules/PreflightModalTransfer/PreflightModalTransfer.tsx similarity index 63% rename from src/Modules/PreflightModalTransfer.tsx rename to src/modules/PreflightModalTransfer/PreflightModalTransfer.tsx index 84397def..2c382835 100644 --- a/src/Modules/PreflightModalTransfer.tsx +++ b/src/modules/PreflightModalTransfer/PreflightModalTransfer.tsx @@ -1,51 +1,8 @@ import React from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import CustomDrawer from "../Components/Custom/CustomDrawer"; +import { CustomDrawer } from "../../components"; import { Button, Typography } from "@chainsafe/common-components"; -import { shortenAddress } from "../Utils/Helpers"; - -const useStyles = makeStyles(({ constants, palette, zIndex }: ITheme) => - createStyles({ - root: { - zIndex: zIndex?.blocker, - position: "absolute", - "& li": { - position: "relative", - padding: `${constants.generalUnit}px 0 ${constants.generalUnit}px ${ - constants.generalUnit * 8 - }px`, - "&:before": { - content: "''", - display: "block", - backgroundColor: palette.additional["gray"][2], - height: constants.generalUnit, - width: constants.generalUnit, - borderRadius: "50%", - position: "absolute", - top: "50%", - left: constants.generalUnit * 4, - transform: "translate(-50%, -50%)", - }, - }, - }, - subtitle: { - margin: `${constants.generalUnit * 2}px 0`, - }, - agreement: { - margin: `${constants.generalUnit * 2}px 0`, - }, - startButton: { - backgroundColor: palette.additional["preflight"][1], - color: palette.additional["preflight"][2], - marginBottom: constants.generalUnit * 2, - }, - backdrop: { - position: "absolute", - zIndex: zIndex?.layer4, - }, - }) -); +import { shortenAddress } from "../../utils/Helpers"; +import { useStyles } from "./styles"; interface IPreflightModalTransferProps { open: boolean; diff --git a/src/modules/PreflightModalTransfer/index.ts b/src/modules/PreflightModalTransfer/index.ts new file mode 100644 index 00000000..30600501 --- /dev/null +++ b/src/modules/PreflightModalTransfer/index.ts @@ -0,0 +1 @@ +export { default } from "./PreflightModalTransfer"; diff --git a/src/modules/PreflightModalTransfer/styles.ts b/src/modules/PreflightModalTransfer/styles.ts new file mode 100644 index 00000000..114ea95f --- /dev/null +++ b/src/modules/PreflightModalTransfer/styles.ts @@ -0,0 +1,43 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants, palette, zIndex }: ITheme) => + createStyles({ + root: { + zIndex: zIndex?.blocker, + position: "absolute", + "& li": { + position: "relative", + padding: `${constants.generalUnit}px 0 ${constants.generalUnit}px ${ + constants.generalUnit * 8 + }px`, + "&:before": { + content: "''", + display: "block", + backgroundColor: palette.additional["gray"][2], + height: constants.generalUnit, + width: constants.generalUnit, + borderRadius: "50%", + position: "absolute", + top: "50%", + left: constants.generalUnit * 4, + transform: "translate(-50%, -50%)", + }, + }, + }, + subtitle: { + margin: `${constants.generalUnit * 2}px 0`, + }, + agreement: { + margin: `${constants.generalUnit * 2}px 0`, + }, + startButton: { + backgroundColor: palette.additional["preflight"][1], + color: palette.additional["preflight"][2], + marginBottom: constants.generalUnit * 2, + }, + backdrop: { + position: "absolute", + zIndex: zIndex?.layer4, + }, + }) +); diff --git a/src/Modules/PreflightModalWrap.tsx b/src/modules/PreflightModalWrap/PreflightModalWrap.tsx similarity index 62% rename from src/Modules/PreflightModalWrap.tsx rename to src/modules/PreflightModalWrap/PreflightModalWrap.tsx index 8dec11f9..daa55f50 100644 --- a/src/Modules/PreflightModalWrap.tsx +++ b/src/modules/PreflightModalWrap/PreflightModalWrap.tsx @@ -1,50 +1,7 @@ import React from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import CustomDrawer from "../Components/Custom/CustomDrawer"; +import { CustomDrawer } from "../../components"; import { Button, Typography } from "@chainsafe/common-components"; - -const useStyles = makeStyles(({ constants, palette, zIndex }: ITheme) => - createStyles({ - root: { - position: "absolute", - zIndex: zIndex?.blocker, - "& li": { - position: "relative", - padding: `${constants.generalUnit}px 0 ${constants.generalUnit}px ${ - constants.generalUnit * 8 - }px`, - "&:before": { - content: "''", - display: "block", - backgroundColor: palette.additional["gray"][2], - height: constants.generalUnit, - width: constants.generalUnit, - borderRadius: "50%", - position: "absolute", - top: "50%", - left: constants.generalUnit * 4, - transform: "translate(-50%, -50%)", - }, - }, - }, - subtitle: { - margin: `${constants.generalUnit * 2}px 0`, - }, - agreement: { - margin: `${constants.generalUnit * 2}px 0`, - }, - startButton: { - backgroundColor: palette.additional["preflight"][1], - color: palette.additional["preflight"][2], - marginBottom: constants.generalUnit * 2, - }, - backdrop: { - position: "absolute", - zIndex: zIndex?.layer4, - }, - }) -); +import { useStyles } from "./styles"; interface IPreflightModalWrapProps { open: boolean; diff --git a/src/modules/PreflightModalWrap/index.ts b/src/modules/PreflightModalWrap/index.ts new file mode 100644 index 00000000..153bf135 --- /dev/null +++ b/src/modules/PreflightModalWrap/index.ts @@ -0,0 +1 @@ +export { default } from "./PreflightModalWrap"; diff --git a/src/modules/PreflightModalWrap/styles.ts b/src/modules/PreflightModalWrap/styles.ts new file mode 100644 index 00000000..fafb865d --- /dev/null +++ b/src/modules/PreflightModalWrap/styles.ts @@ -0,0 +1,43 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants, palette, zIndex }: ITheme) => + createStyles({ + root: { + position: "absolute", + zIndex: zIndex?.blocker, + "& li": { + position: "relative", + padding: `${constants.generalUnit}px 0 ${constants.generalUnit}px ${ + constants.generalUnit * 8 + }px`, + "&:before": { + content: "''", + display: "block", + backgroundColor: palette.additional["gray"][2], + height: constants.generalUnit, + width: constants.generalUnit, + borderRadius: "50%", + position: "absolute", + top: "50%", + left: constants.generalUnit * 4, + transform: "translate(-50%, -50%)", + }, + }, + }, + subtitle: { + margin: `${constants.generalUnit * 2}px 0`, + }, + agreement: { + margin: `${constants.generalUnit * 2}px 0`, + }, + startButton: { + backgroundColor: palette.additional["preflight"][1], + color: palette.additional["preflight"][2], + marginBottom: constants.generalUnit * 2, + }, + backdrop: { + position: "absolute", + zIndex: zIndex?.layer4, + }, + }) +); diff --git a/src/Modules/TransferActiveModal.tsx b/src/modules/TransferActiveModal/TransferActiveModal.tsx similarity index 67% rename from src/Modules/TransferActiveModal.tsx rename to src/modules/TransferActiveModal/TransferActiveModal.tsx index 786037e5..04e97ae0 100644 --- a/src/Modules/TransferActiveModal.tsx +++ b/src/modules/TransferActiveModal/TransferActiveModal.tsx @@ -1,137 +1,14 @@ import React from "react"; - -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; import { Button, ExclamationCircleSvg, ProgressBar, Typography, } from "@chainsafe/common-components"; -import CustomModal from "../Components/Custom/CustomModal"; -import { useChainbridge } from "../Contexts/ChainbridgeContext"; -import { EvmBridgeConfig } from "../chainbridgeConfig"; - -const useStyles = makeStyles( - ({ animation, constants, palette, typography }: ITheme) => - createStyles({ - root: { - width: "100%", - }, - inner: { - width: "100% !important", - maxWidth: "unset !important", - display: "flex", - flexDirection: "row", - padding: `${constants.generalUnit * 5}px ${ - constants.generalUnit * 3.5 - }px`, - bottom: 0, - top: "unset", - transform: "unset", - left: 0, - border: "none", - borderRadius: 0, - transitionDuration: `${animation.transform}ms`, - }, - heading: { - marginBottom: constants.generalUnit, - whiteSpace: "nowrap", - }, - stepIndicator: { - ...typography.h4, - height: 40, - width: 40, - marginRight: constants.generalUnit * 2, - borderRadius: "50%", - display: "flex", - justifyContent: "center", - alignItems: "center", - border: `1px solid ${palette.additional["transactionModal"][2]}`, - color: palette.additional["transactionModal"][3], - "& svg": { - height: 20, - width: 20, - display: "block", - }, - }, - content: { - display: "flex", - flexDirection: "column", - }, - buttons: { - display: "flex", - flexDirection: "row", - marginTop: constants.generalUnit * 5, - "& > *": { - textDecoration: "none", - marginRight: constants.generalUnit, - }, - }, - button: { - borderColor: `${palette.additional["gray"][8]} !important`, - color: `${palette.additional["gray"][8]} !important`, - textDecoration: "none", - "&:hover": { - borderColor: `${palette.additional["gray"][8]} !important`, - backgroundColor: `${palette.additional["gray"][8]} !important`, - color: `${palette.common.white.main} !important`, - textDecoration: "none", - }, - }, - initCopy: { - display: "flex", - flexDirection: "column", - justifyContent: "space-between", - "& > *:first-child": { - marginTop: constants.generalUnit * 3.5, - marginBottom: constants.generalUnit * 8, - }, - }, - sendingCopy: {}, - vote: { - display: "flex", - flexDirection: "row", - marginTop: constants.generalUnit, - "& > *": { - "&:first-child": { - whiteSpace: "nowrap", - overflow: "hidden", - textOverflow: "ellipsis", - maxWidth: 240, - }, - "&:last-child": { - marginLeft: constants.generalUnit * 3.5, - fontStyle: "italic", - }, - }, - }, - warning: { - marginTop: constants.generalUnit * 3.5, - display: "block", - fontWeight: 600, - }, - receipt: { - marginTop: constants.generalUnit * 3.5, - marginBottom: constants.generalUnit * 8, - }, - weighted: { - fontWeight: 600, - }, - progress: { - position: "absolute", - top: 0, - left: 0, - width: "100%", - "& > *": { - borderRadius: "0 !important", - "& > *": { - borderRadius: "0 !important", - background: `${palette.additional["transactionModal"][1]} !important`, - }, - }, - }, - }) -); +import { CustomModal } from "../../components"; +import { useChainbridge } from "../../contexts/ChainbridgeContext/ChainbridgeContext"; +import { EvmBridgeConfig } from "../../chainbridgeConfig"; +import { useStyles } from "./styles"; interface ITransferActiveModalProps { open: boolean; diff --git a/src/modules/TransferActiveModal/index.ts b/src/modules/TransferActiveModal/index.ts new file mode 100644 index 00000000..85b0165c --- /dev/null +++ b/src/modules/TransferActiveModal/index.ts @@ -0,0 +1 @@ +export { default } from "./TransferActiveModal"; diff --git a/src/modules/TransferActiveModal/styles.ts b/src/modules/TransferActiveModal/styles.ts new file mode 100644 index 00000000..171262c4 --- /dev/null +++ b/src/modules/TransferActiveModal/styles.ts @@ -0,0 +1,123 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles( + ({ animation, constants, palette, typography }: ITheme) => + createStyles({ + root: { + width: "100%", + }, + inner: { + width: "100% !important", + maxWidth: "unset !important", + display: "flex", + flexDirection: "row", + padding: `${constants.generalUnit * 5}px ${ + constants.generalUnit * 3.5 + }px`, + bottom: 0, + top: "unset", + transform: "unset", + left: 0, + border: "none", + borderRadius: 0, + transitionDuration: `${animation.transform}ms`, + }, + heading: { + marginBottom: constants.generalUnit, + whiteSpace: "nowrap", + }, + stepIndicator: { + ...typography.h4, + height: 40, + width: 40, + marginRight: constants.generalUnit * 2, + borderRadius: "50%", + display: "flex", + justifyContent: "center", + alignItems: "center", + border: `1px solid ${palette.additional["transactionModal"][2]}`, + color: palette.additional["transactionModal"][3], + "& svg": { + height: 20, + width: 20, + display: "block", + }, + }, + content: { + display: "flex", + flexDirection: "column", + }, + buttons: { + display: "flex", + flexDirection: "row", + marginTop: constants.generalUnit * 5, + "& > *": { + textDecoration: "none", + marginRight: constants.generalUnit, + }, + }, + button: { + borderColor: `${palette.additional["gray"][8]} !important`, + color: `${palette.additional["gray"][8]} !important`, + textDecoration: "none", + "&:hover": { + borderColor: `${palette.additional["gray"][8]} !important`, + backgroundColor: `${palette.additional["gray"][8]} !important`, + color: `${palette.common.white.main} !important`, + textDecoration: "none", + }, + }, + initCopy: { + display: "flex", + flexDirection: "column", + justifyContent: "space-between", + "& > *:first-child": { + marginTop: constants.generalUnit * 3.5, + marginBottom: constants.generalUnit * 8, + }, + }, + sendingCopy: {}, + vote: { + display: "flex", + flexDirection: "row", + marginTop: constants.generalUnit, + "& > *": { + "&:first-child": { + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + maxWidth: 240, + }, + "&:last-child": { + marginLeft: constants.generalUnit * 3.5, + fontStyle: "italic", + }, + }, + }, + warning: { + marginTop: constants.generalUnit * 3.5, + display: "block", + fontWeight: 600, + }, + receipt: { + marginTop: constants.generalUnit * 3.5, + marginBottom: constants.generalUnit * 8, + }, + weighted: { + fontWeight: 600, + }, + progress: { + position: "absolute", + top: 0, + left: 0, + width: "100%", + "& > *": { + borderRadius: "0 !important", + "& > *": { + borderRadius: "0 !important", + background: `${palette.additional["transactionModal"][1]} !important`, + }, + }, + }, + }) +); diff --git a/src/modules/WrapActiveModal/WrapActiveModal.tsx b/src/modules/WrapActiveModal/WrapActiveModal.tsx new file mode 100644 index 00000000..83931150 --- /dev/null +++ b/src/modules/WrapActiveModal/WrapActiveModal.tsx @@ -0,0 +1,107 @@ +import React from "react"; +import { Button, ProgressBar, Typography } from "@chainsafe/common-components"; +import { CustomModal } from "../../components"; +import { useChainbridge } from "../../contexts/ChainbridgeContext/ChainbridgeContext"; +import { EvmBridgeConfig, TokenConfig } from "../../chainbridgeConfig"; +import { useStyles } from "./styles"; + +interface IWrapActiveModalProps { + txState?: "inProgress" | "done"; + value: number; + tokenInfo: TokenConfig; + txHash?: string; + close: () => void; + action: "wrap" | "unwrap"; +} + +const WrapActiveModal: React.FC = ({ + txState, + value, + tokenInfo, + txHash, + close, + action, +}: IWrapActiveModalProps) => { + const classes = useStyles(); + const { homeConfig } = useChainbridge(); + + return ( + + +
+
+ {txState === "inProgress" ? 1 : 2} +
+
+
+ + {txState === "inProgress" + ? action === "wrap" + ? `Wrapping ${value} ${homeConfig?.nativeTokenSymbol}` + : `Unwrapping ${value} ${tokenInfo.symbol}` + : action === "wrap" + ? "Token wrapped" + : "Token unwrapped"} + + {txState !== "inProgress" && ( + <> + + {action === "wrap" + ? `Successfully wrapped ${homeConfig?.nativeTokenSymbol} to ${tokenInfo.symbol}` + : `Successfully unwrapped ${tokenInfo.symbol} to ${homeConfig?.nativeTokenSymbol}`} + {homeConfig && + (homeConfig as EvmBridgeConfig).blockExplorer && + txHash && ( + <> +
+ + View Transaction + + + )} +
+
+ + +
+ + )} +
+
+ ); +}; + +export default WrapActiveModal; diff --git a/src/modules/WrapActiveModal/index.ts b/src/modules/WrapActiveModal/index.ts new file mode 100644 index 00000000..0161a96e --- /dev/null +++ b/src/modules/WrapActiveModal/index.ts @@ -0,0 +1 @@ +export { default } from "./WrapActiveModal"; diff --git a/src/Modules/WrapActiveModal.tsx b/src/modules/WrapActiveModal/styles.ts similarity index 51% rename from src/Modules/WrapActiveModal.tsx rename to src/modules/WrapActiveModal/styles.ts index 6d84723a..686417b8 100644 --- a/src/Modules/WrapActiveModal.tsx +++ b/src/modules/WrapActiveModal/styles.ts @@ -1,12 +1,6 @@ -import React from "react"; - import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; -import { Button, ProgressBar, Typography } from "@chainsafe/common-components"; -import CustomModal from "../Components/Custom/CustomModal"; -import { useChainbridge } from "../Contexts/ChainbridgeContext"; -import { EvmBridgeConfig, TokenConfig } from "../chainbridgeConfig"; -const useStyles = makeStyles( +export const useStyles = makeStyles( ({ animation, constants, palette, typography }: ITheme) => createStyles({ root: { @@ -127,104 +121,3 @@ const useStyles = makeStyles( }, }) ); - -interface IWrapActiveModalProps { - txState?: "inProgress" | "done"; - value: number; - tokenInfo: TokenConfig; - txHash?: string; - close: () => void; - action: "wrap" | "unwrap"; -} - -const WrapActiveModal: React.FC = ({ - txState, - value, - tokenInfo, - txHash, - close, - action, -}: IWrapActiveModalProps) => { - const classes = useStyles(); - const { homeConfig } = useChainbridge(); - - return ( - - -
-
- {txState === "inProgress" ? 1 : 2} -
-
-
- - {txState === "inProgress" - ? action === "wrap" - ? `Wrapping ${value} ${homeConfig?.nativeTokenSymbol}` - : `Unwrapping ${value} ${tokenInfo.symbol}` - : action === "wrap" - ? "Token wrapped" - : "Token unwrapped"} - - {txState !== "inProgress" && ( - <> - - {action === "wrap" - ? `Successfully wrapped ${homeConfig?.nativeTokenSymbol} to ${tokenInfo.symbol}` - : `Successfully unwrapped ${tokenInfo.symbol} to ${homeConfig?.nativeTokenSymbol}`} - {homeConfig && - (homeConfig as EvmBridgeConfig).blockExplorer && - txHash && ( - <> -
- - View Transaction - - - )} -
-
- - -
- - )} -
-
- ); -}; - -export default WrapActiveModal; diff --git a/src/modules/index.ts b/src/modules/index.ts new file mode 100644 index 00000000..19aeef0e --- /dev/null +++ b/src/modules/index.ts @@ -0,0 +1,8 @@ +export { default as AboutDrawer } from "./AboutDrawer"; +export { default as ChangeNetworkDrawer } from "./ChangeNetworkDrawer"; +export { default as NetworkSelectModal } from "./NetworkSelectModal"; +export { default as NetworkUnsupportedModal } from "./NetworkUnsupportedModal"; +export { default as PreflightModalTransfer } from "./PreflightModalTransfer"; +export { default as PreflightModalWrap } from "./PreflightModalWrap"; +export { default as TransferActiveModal } from "./TransferActiveModal"; +export { default as WrapActiveModal } from "./WrapActiveModal"; diff --git a/src/Components/Pages/ExplorerPage.test.tsx b/src/pages/ExplorerPage/ExplorerPage.test.tsx similarity index 90% rename from src/Components/Pages/ExplorerPage.test.tsx rename to src/pages/ExplorerPage/ExplorerPage.test.tsx index 74ce4ad6..53c20fbd 100644 --- a/src/Components/Pages/ExplorerPage.test.tsx +++ b/src/pages/ExplorerPage/ExplorerPage.test.tsx @@ -2,9 +2,9 @@ import React from "react"; import { act, render, waitFor } from "@testing-library/react"; import { ThemeSwitcher } from "@chainsafe/common-theme"; import ExplorerPage from "./ExplorerPage"; -import { ExplorerProvider } from "../../Contexts/ExplorerContext"; -import { lightTheme } from "../../Themes/LightTheme"; -import { runtimeTestingConfig, testResponse } from "../../Utils/TestUtils"; +import { ExplorerProvider } from "../Contexts/ExplorerContext/ExplorerContext"; +import { lightTheme } from "../Themes/LightTheme"; +import { runtimeTestingConfig, testResponse } from "../Utils/TestUtils"; jest.mock("../../Contexts/NetworkManagerContext.tsx", () => { const FakeNetworkManager = (children: any) => <>{children}; diff --git a/src/Components/Pages/ExplorerPage.tsx b/src/pages/ExplorerPage/ExplorerPage.tsx similarity index 73% rename from src/Components/Pages/ExplorerPage.tsx rename to src/pages/ExplorerPage/ExplorerPage.tsx index e266bd51..cc697864 100644 --- a/src/Components/Pages/ExplorerPage.tsx +++ b/src/pages/ExplorerPage/ExplorerPage.tsx @@ -1,5 +1,4 @@ import React, { useState, useReducer, useEffect } from "react"; -import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; import { SelectInput, TextInput, @@ -9,93 +8,13 @@ import { useHistory, Button, } from "@chainsafe/common-components"; -import { ExplorerTable } from "../Custom"; -import { useExplorer } from "../../Contexts/ExplorerContext"; +import { ExplorerTable } from "../../components"; +import { useExplorer } from "../../contexts"; import { ExplorerPageState, transfersReducer, -} from "../../Contexts/Reducers/TransfersReducer"; - -const useStyles = makeStyles(({ constants, breakpoints }: ITheme) => - createStyles({ - root: { - padding: constants.generalUnit * 6, - position: "relative", - }, - mainContent: { - display: "grid", - gridTemplateRows: "repeat(1, 1fr)", - width: "70%", - [breakpoints.down("lg")]: { - width: "80%", - }, - }, - networkInfoContainer: { - display: "grid", - gridTemplateColumns: "repeat(2, 1fr)", - }, - networkInfo: { - display: "grid", - gridColumn: "1/5", - gridRow: "1", - }, - networkSelection: { - display: "flex", - alignItems: "center", - "& > h2": { - color: "#595959", - fontWeight: 600, - marginRight: 26, - [breakpoints.down("md")]: { - fontSize: 20, - }, - }, - }, - networkSelectorContainer: { - display: "flex", - width: 372, - }, - searchInput: { - display: "grid", - gridColumn: "3/4", - gridRow: "1", - }, - networkSelector: { - marginLeft: 21, - width: 327, - "& > div > div": { - lineHeight: 32, - color: "#262626", - "& > div > div": { - fontSize: 24, - fontWeight: 600, - }, - }, - }, - explorerTableContainer: { - display: "flex", - justifyContent: "center", - marginBottom: "100px", - }, - explorerTable: { - marginTop: 29, - borderRadius: 4, - border: "1px solid #B6B6B6", - background: "#FAFAFA", - minWidth: 955, - width: "100%", - height: "100%", - }, - paginationPanel: { - display: "flex", - justifyContent: "flex-end", - padding: "25px 16px 0", - }, - paginationButtons: { - marginLeft: "10px", - }, - }) -); +} from "../../reducers/TransfersReducer"; +import { useStyles } from "./styles"; type PreflightDetails = { tokenAmount: number; diff --git a/src/pages/ExplorerPage/index.ts b/src/pages/ExplorerPage/index.ts new file mode 100644 index 00000000..31286017 --- /dev/null +++ b/src/pages/ExplorerPage/index.ts @@ -0,0 +1 @@ +export { default } from "./ExplorerPage"; diff --git a/src/pages/ExplorerPage/styles.ts b/src/pages/ExplorerPage/styles.ts new file mode 100644 index 00000000..fbdefdad --- /dev/null +++ b/src/pages/ExplorerPage/styles.ts @@ -0,0 +1,82 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants, breakpoints }: ITheme) => + createStyles({ + root: { + padding: constants.generalUnit * 6, + position: "relative", + }, + mainContent: { + display: "grid", + gridTemplateRows: "repeat(1, 1fr)", + width: "70%", + [breakpoints.down("lg")]: { + width: "80%", + }, + }, + networkInfoContainer: { + display: "grid", + gridTemplateColumns: "repeat(2, 1fr)", + }, + networkInfo: { + display: "grid", + gridColumn: "1/5", + gridRow: "1", + }, + networkSelection: { + display: "flex", + alignItems: "center", + "& > h2": { + color: "#595959", + fontWeight: 600, + marginRight: 26, + [breakpoints.down("md")]: { + fontSize: 20, + }, + }, + }, + networkSelectorContainer: { + display: "flex", + width: 372, + }, + searchInput: { + display: "grid", + gridColumn: "3/4", + gridRow: "1", + }, + networkSelector: { + marginLeft: 21, + width: 327, + "& > div > div": { + lineHeight: 32, + color: "#262626", + "& > div > div": { + fontSize: 24, + fontWeight: 600, + }, + }, + }, + explorerTableContainer: { + display: "flex", + justifyContent: "center", + marginBottom: "100px", + }, + explorerTable: { + marginTop: 29, + borderRadius: 4, + border: "1px solid #B6B6B6", + background: "#FAFAFA", + minWidth: 955, + width: "100%", + height: "100%", + }, + paginationPanel: { + display: "flex", + justifyContent: "flex-end", + padding: "25px 16px 0", + }, + paginationButtons: { + marginLeft: "10px", + }, + }) +); diff --git a/src/Components/Pages/TransactionPage.tsx b/src/pages/TransactionPage/TransactionPage.tsx similarity index 76% rename from src/Components/Pages/TransactionPage.tsx rename to src/pages/TransactionPage/TransactionPage.tsx index 2d0b8515..7c287e2a 100644 --- a/src/Components/Pages/TransactionPage.tsx +++ b/src/pages/TransactionPage/TransactionPage.tsx @@ -1,25 +1,15 @@ import React, { useEffect, useState } from "react"; import useInterval from "@use-it/interval"; import { useHistory } from "@chainsafe/common-components"; -import { makeStyles, createStyles } from "@chainsafe/common-theme"; -import { useExplorer } from "../../Contexts/ExplorerContext"; -import TransferDetailView from "../Custom/TransferDetailView"; -import { fetchTransaction } from "../../Services/ExplorerService"; -import { computeTransferDetails } from "../../Utils/Helpers"; +import { useExplorer } from "../../contexts"; +import { TransferDetailView } from "../../components"; +import { fetchTransaction } from "../../services/ExplorerService"; +import { computeTransferDetails } from "../../utils/Helpers"; import { DepositRecord, TransferDetails, -} from "../../Contexts/Reducers/TransfersReducer"; - -const useStyles = makeStyles(() => - createStyles({ - transferDetailViewContainer: { - display: "flex", - flexDirection: "row", - justifyContent: "center", - }, - }) -); +} from "../../reducers/TransfersReducer"; +import { useStyles } from "./styles"; const TransactionPage = () => { const { diff --git a/src/pages/TransactionPage/index.ts b/src/pages/TransactionPage/index.ts new file mode 100644 index 00000000..93074b7d --- /dev/null +++ b/src/pages/TransactionPage/index.ts @@ -0,0 +1 @@ +export { default } from "./TransactionPage"; diff --git a/src/pages/TransactionPage/styles.ts b/src/pages/TransactionPage/styles.ts new file mode 100644 index 00000000..1f49ca36 --- /dev/null +++ b/src/pages/TransactionPage/styles.ts @@ -0,0 +1,11 @@ +import { makeStyles, createStyles } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(() => + createStyles({ + transferDetailViewContainer: { + display: "flex", + flexDirection: "row", + justifyContent: "center", + }, + }) +); diff --git a/src/pages/TransferPage/TransferPage.tsx b/src/pages/TransferPage/TransferPage.tsx new file mode 100644 index 00000000..e4f28fbd --- /dev/null +++ b/src/pages/TransferPage/TransferPage.tsx @@ -0,0 +1,185 @@ +import React, { useEffect, useState } from "react"; +import { useChainbridge, useHomeBridge } from "../../contexts"; +import { object, string } from "yup"; +import { useHistory } from "@chainsafe/common-components"; +import { utils } from "ethers"; +import { useNetworkManager } from "../../contexts/NetworkManagerContext/NetworkManagerContext"; +import { isValidSubstrateAddress } from "../../utils/Helpers"; +import { showImageUrl } from "../../utils/Helpers"; +import { useStyles } from "./styles"; +import TransferPageView from "./TransferPageView"; + +export type PreflightDetails = { + tokenAmount: number; + token: string; + tokenSymbol: string; + receiver: string; +}; + +const TransferPage = () => { + const classes = useStyles(); + const { walletType, setWalletType } = useNetworkManager(); + + const { + deposit, + setDestinationChain, + transactionStatus, + resetDeposit, + bridgeFee, + tokens, + isReady, + homeConfig, + destinationChainConfig, + destinationChains, + address, + checkSupplies, + } = useChainbridge(); + + const { accounts, selectAccount } = useHomeBridge(); + const [aboutOpen, setAboutOpen] = useState(false); + const [walletConnecting, setWalletConnecting] = useState(false); + const [changeNetworkOpen, setChangeNetworkOpen] = useState(false); + const [preflightModalOpen, setPreflightModalOpen] = useState(false); + + const [preflightDetails, setPreflightDetails] = useState({ + receiver: "", + token: "", + tokenAmount: 0, + tokenSymbol: "", + }); + + const { redirect } = useHistory(); + + useEffect(() => { + if (walletType !== "select" && walletConnecting === true) { + setWalletConnecting(false); + } else if (walletType === "select") { + setWalletConnecting(true); + } + }, [walletType, walletConnecting]); + + const selectedToken = homeConfig?.tokens.find( + (token) => token.address === preflightDetails.token + ); + + const DECIMALS = + selectedToken && selectedToken.decimals ? selectedToken.decimals : 18; + + const REGEX = + DECIMALS > 0 + ? new RegExp(`^[0-9]{1,18}(.[0-9]{1,${DECIMALS}})?$`) + : new RegExp(`^[0-9]{1,18}?$`); + + const transferSchema = object().shape({ + tokenAmount: string() + .test("Token selected", "Please select a token", (value) => { + if ( + !!value && + preflightDetails && + tokens[preflightDetails.token] && + tokens[preflightDetails.token].balance !== undefined + ) { + return true; + } else { + return false; + } + }) + .test("InputValid", "Input invalid", (value) => { + try { + return REGEX.test(`${value}`); + } catch (error) { + console.error(error); + return false; + } + }) + .test("Max", "Insufficent funds", (value) => { + if ( + value && + preflightDetails && + tokens[preflightDetails.token] && + tokens[preflightDetails.token].balance + ) { + if (homeConfig?.type === "Ethereum") { + return parseFloat(value) <= tokens[preflightDetails.token].balance; + } else { + return ( + parseFloat(value + (bridgeFee || 0)) <= + tokens[preflightDetails.token].balance + ); + } + } + return false; + }) + .test( + "Bridge Supplies", + "Not enough tokens on the destination chain. Please contact support.", + async (value) => { + if (checkSupplies && destinationChainConfig && value) { + const supplies = await checkSupplies( + parseFloat(value), + preflightDetails.token, + destinationChainConfig.chainId + ); + return Boolean(supplies); + } + return false; + } + ) + .test("Min", "Less than minimum", (value) => { + if (value) { + return parseFloat(value) > 0; + } + return false; + }) + .required("Please set a value"), + token: string().required("Please select a token"), + receiver: string() + .test("Valid address", "Please add a valid address", (value) => { + if (destinationChainConfig?.type === "Substrate") { + return isValidSubstrateAddress(value as string); + } + return utils.isAddress(value as string); + }) + .required("Please add a receiving address"), + }); + + const handleClick = (txHash: string) => { + const url = `/explorer/transaction/${txHash}`; + + redirect(url); + }; + + return ( + + ); +}; +export default TransferPage; diff --git a/src/pages/TransferPage/TransferPageView.tsx b/src/pages/TransferPage/TransferPageView.tsx new file mode 100644 index 00000000..a84b692f --- /dev/null +++ b/src/pages/TransferPage/TransferPageView.tsx @@ -0,0 +1,338 @@ +import React from "react"; +import { + Button, + Typography, + QuestionCircleSvg, + SelectInput, +} from "@chainsafe/common-components"; +import clsx from "clsx"; +import { Form, Formik } from "formik"; +import { + TransferActiveModal, + NetworkUnsupportedModal, + PreflightModalTransfer, + ChangeNetworkDrawer, + AboutDrawer, +} from "../../modules"; +import { + AddressInput, + TokenSelectInput, + TokenInput, + Fees, +} from "../../components"; +import { WalletType } from "../../contexts/NetworkManagerContext/NetworkManagerContext"; +import { BridgeConfig } from "../../chainbridgeConfig"; +import { PreflightDetails } from "./TransferPage"; + +type TransferPageView = { + isReady: boolean | undefined; + classes: any; + setWalletType: (walletType: WalletType) => void; + walletType: string; + walletConnecting: boolean; + setChangeNetworkOpen: React.Dispatch>; + homeConfig: BridgeConfig | undefined; + accounts: Array | undefined; + selectAccount: any; + transferSchema: object; + setPreflightDetails: React.Dispatch>; + setPreflightModalOpen: React.Dispatch>; + preflightModalOpen: boolean; + tokens: any; + destinationChains: any; + setDestinationChain: (chainId: number | undefined) => void; + destinationChainConfig: any; + showImageUrl: (url: string | undefined) => string; + preflightDetails: PreflightDetails; + bridgeFee: any; + address: string | undefined; + aboutOpen: any; + setAboutOpen: React.Dispatch>; + changeNetworkOpen: any; + deposit: any; + transactionStatus: string | undefined; + resetDeposit: () => void; + handleClick: (txHash: string) => void; +}; + +export default function TransferPageView({ + isReady, + classes, + setWalletType, + walletType, + walletConnecting, + setChangeNetworkOpen, + homeConfig, + accounts, + selectAccount, + transferSchema, + setPreflightDetails, + setPreflightModalOpen, + preflightModalOpen, + tokens, + destinationChains, + setDestinationChain, + destinationChainConfig, + showImageUrl, + preflightDetails, + bridgeFee, + address, + aboutOpen, + setAboutOpen, + changeNetworkOpen, + deposit, + transactionStatus, + resetDeposit, + handleClick, +}: TransferPageView) { + return ( +
+
+ {!isReady ? ( + + ) : walletConnecting ? ( +
+ + This app requires access to your wallet,
+ please login and authorize access to continue. +
+
+ ) : ( +
+
+ Home network + setChangeNetworkOpen(true)} + > + Change + +
+ + {homeConfig?.name} + +
+ )} +
+ {isReady && + walletType === "Substrate" && + accounts && + accounts.length > 0 && ( +
+
+ ({ + label: acc.address, + value: i, + }))} + onChange={(value) => selectAccount && selectAccount(value)} + value={accounts.findIndex((v) => v.address === address)} + placeholder="Select an account" + /> +
+
+ )} + { + setPreflightDetails({ + ...values, + tokenSymbol: tokens[values.token].symbol || "", + }); + setPreflightModalOpen(true); + }} + > + {(props) => ( +
+
+ ({ + label: dc.name, + value: dc.chainId, + }))} + onChange={(value) => setDestinationChain(value)} + value={destinationChainConfig?.chainId} + /> +
+
+ {/*
+
+ +
+ */} +
+ { + setPreflightDetails({ + ...preflightDetails, + token: tokenAddress, + receiver: "", + tokenAmount: 0, + tokenSymbol: "", + }); + }} + options={ + Object.keys(tokens).map((t) => ({ + value: t, + label: ( +
+ {tokens[t]?.imageUri && ( + {tokens[t]?.symbol} + )} + {tokens[t]?.symbol || t} +
+ ), + })) || [] + } + /> +
+
+
+ +
+
+
+
+ +
+ +
+ +
+
+ setAboutOpen(true)} + className={classes.faqButton} + /> +
+ + )} + + setAboutOpen(false)} /> + setChangeNetworkOpen(false)} + /> + setPreflightModalOpen(false)} + receiver={preflightDetails?.receiver || ""} + sender={address || ""} + start={() => { + setPreflightModalOpen(false); + preflightDetails && + deposit( + preflightDetails.tokenAmount, + preflightDetails.receiver, + preflightDetails.token + ); + }} + sourceNetwork={homeConfig?.name || ""} + targetNetwork={destinationChainConfig?.name || ""} + tokenSymbol={preflightDetails?.tokenSymbol || ""} + value={preflightDetails?.tokenAmount || 0} + /> + + {/* This is here due to requiring router */} + +
+ ); +} diff --git a/src/pages/TransferPage/index.ts b/src/pages/TransferPage/index.ts new file mode 100644 index 00000000..120bef85 --- /dev/null +++ b/src/pages/TransferPage/index.ts @@ -0,0 +1 @@ +export { default } from "./TransferPage"; diff --git a/src/pages/TransferPage/styles.ts b/src/pages/TransferPage/styles.ts new file mode 100644 index 00000000..edee19a3 --- /dev/null +++ b/src/pages/TransferPage/styles.ts @@ -0,0 +1,161 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants, palette }: ITheme) => + createStyles({ + root: { + padding: constants.generalUnit * 6, + position: "relative", + }, + walletArea: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + width: "100%", + }, + connectButton: { + margin: `${constants.generalUnit * 3}px 0 ${constants.generalUnit * 6}px`, + }, + connecting: { + textAlign: "center", + marginBottom: constants.generalUnit * 2, + }, + connected: { + width: "100%", + "& > *:first-child": { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + width: "100%", + }, + }, + changeButton: { + cursor: "pointer", + }, + networkName: { + padding: `${constants.generalUnit * 2}px ${ + constants.generalUnit * 1.5 + }px`, + border: `1px solid ${palette.additional["gray"][6]}`, + borderRadius: 2, + color: palette.additional["gray"][9], + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit * 3, + }, + formArea: { + "&.disabled": { + opacity: 0.4, + }, + }, + currencySection: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "flex-end", + margin: `${constants.generalUnit * 3}px 0`, + }, + tokenInputArea: { + display: "flex", + flexDirection: "row", + alignItems: "flex-end", + justifyContent: "space-around", + }, + tokenInputSection: { + width: "60%", + }, + tokenInput: { + margin: 0, + "& > div": { + height: 32, + "& input": { + borderBottomRightRadius: 0, + borderTopRightRadius: 0, + borderRight: 0, + }, + }, + "& span:last-child.error": { + position: "absolute", + width: "calc(100% + 62px)", + }, + }, + maxButton: { + height: 32, + borderBottomLeftRadius: 0, + borderTopLeftRadius: 0, + left: -1, + color: palette.additional["gray"][8], + backgroundColor: palette.additional["gray"][3], + borderColor: palette.additional["gray"][6], + "&:hover": { + borderColor: palette.additional["gray"][6], + backgroundColor: palette.additional["gray"][7], + color: palette.common.white.main, + }, + "&:focus": { + borderColor: palette.additional["gray"][6], + }, + }, + currencySelector: { + width: "40%", + paddingRight: constants.generalUnit, + "& *": { + cursor: "pointer", + }, + }, + token: {}, + address: { + margin: 0, + marginBottom: constants.generalUnit * 3, + }, + addressInput: {}, + generalInput: { + "& > span": { + marginBottom: constants.generalUnit, + }, + }, + faqButton: { + cursor: "pointer", + height: 20, + width: 20, + marginTop: constants.generalUnit * 5, + fill: `${palette.additional["transferUi"][1]} !important`, + }, + tokenItem: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + cursor: "pointer", + "& img, & svg": { + display: "block", + height: 14, + width: 14, + marginRight: 10, + }, + "& span": { + minWidth: `calc(100% - 20px)`, + textAlign: "left", + }, + }, + fees: { + display: "flex", + flexDirection: "row", + flexWrap: "wrap", + justifyContent: "space-between", + marginBottom: constants.generalUnit, + "& > *": { + display: "block", + width: "50%", + color: palette.additional["gray"][8], + marginBottom: constants.generalUnit / 2, + "&:nth-child(even)": { + textAlign: "right", + }, + }, + }, + accountSelector: { + marginBottom: 24, + }, + }) +); diff --git a/src/pages/WrapperPage/WrapperPage.tsx b/src/pages/WrapperPage/WrapperPage.tsx new file mode 100644 index 00000000..d332f86a --- /dev/null +++ b/src/pages/WrapperPage/WrapperPage.tsx @@ -0,0 +1,175 @@ +import React, { useEffect, useState } from "react"; +import { useChainbridge, useNetworkManager } from "../../contexts"; +import { object, string } from "yup"; +import { TokenConfig } from "../../chainbridgeConfig"; +import { showImageUrl } from "../../utils/Helpers"; +import { useStyles } from "./styles"; +import WrapperPageView from "./WrapperPageView"; + +export type PreflightDetails = { + tokenAmount: number; +}; + +const MainPage = () => { + const classes = useStyles(); + const { walletType, setWalletType, homeChainConfig } = useNetworkManager(); + const { + wrapTokenConfig, + wrapToken, + unwrapToken, + homeConfig, + isReady, + tokens, + nativeTokenBalance, + address, + } = useChainbridge(); + + const [aboutOpen, setAboutOpen] = useState(false); + const [walletConnecting, setWalletConnecting] = useState(false); + const [changeNetworkOpen, setChangeNetworkOpen] = useState(false); + const [preflightModalOpen, setPreflightModalOpen] = useState(false); + const [preflightDetails, setPreflightDetails] = useState({ + tokenAmount: 0, + }); + const [action, setAction] = useState<"wrap" | "unwrap">("wrap"); + + const [txDetails, setTxDetails] = useState< + | { + txState?: "inProgress" | "done"; + value: number; + tokenInfo: TokenConfig; + txHash?: string; + action: "wrap" | "unwrap"; + } + | undefined + >(undefined); + + useEffect(() => { + if (walletType !== "select" && walletConnecting === true) { + setWalletConnecting(false); + } else if (walletType === "select") { + setWalletConnecting(true); + } + }, [walletType, walletConnecting]); + + const handleWrapToken = async () => { + if (!wrapTokenConfig || !wrapToken || !homeConfig) return; + + try { + setTxDetails({ + tokenInfo: wrapTokenConfig, + value: preflightDetails.tokenAmount, + txState: "inProgress", + action: action, + }); + const txHash = await wrapToken(preflightDetails.tokenAmount); + + if (txHash === "") { + setTxDetails(undefined); + throw Error("Wrap Transaction failed"); + } + + setTxDetails({ + tokenInfo: wrapTokenConfig, + value: preflightDetails.tokenAmount, + txHash: txHash, + txState: "done", + action: action, + }); + } catch (error) { + console.error(error); + } + }; + + const handleUnwrapToken = async () => { + if (!wrapTokenConfig || !unwrapToken || !homeConfig) return; + + try { + setTxDetails({ + tokenInfo: wrapTokenConfig, + value: preflightDetails.tokenAmount, + txState: "inProgress", + action: action, + }); + + const txHash = await unwrapToken(preflightDetails.tokenAmount); + + if (txHash === "") { + setTxDetails(undefined); + throw Error("Unwrap Transaction failed"); + } + + setTxDetails({ + tokenInfo: wrapTokenConfig, + value: preflightDetails.tokenAmount, + txHash: txHash, + txState: "done", + action: action, + }); + } catch (error) { + console.error(error); + } + }; + + const REGEX = + homeChainConfig?.decimals && homeChainConfig.decimals > 0 + ? new RegExp(`^[0-9]{1,18}(.[0-9]{1,${homeChainConfig.decimals}})?$`) + : new RegExp(`^[0-9]{1,18}?$`); + + const wrapSchema = object().shape({ + tokenAmount: string() + .matches(REGEX, "Input invalid") + .test("Min", "Less than minimum", (value) => { + if (value) { + return parseFloat(value) > 0; + } + return false; + }) + .test("Max", "Insufficent funds", (value) => { + return action === "wrap" + ? nativeTokenBalance && + value && + parseFloat(value) <= nativeTokenBalance + ? true + : false + : tokens[wrapTokenConfig?.address || "0x"].balance && + value && + parseFloat(value) <= + tokens[wrapTokenConfig?.address || "0x"]?.balance + ? true + : false; + }) + .required("Please set a value"), + }); + + return ( + + ); +}; +export default MainPage; diff --git a/src/pages/WrapperPage/WrapperPageView.tsx b/src/pages/WrapperPage/WrapperPageView.tsx new file mode 100644 index 00000000..f9936022 --- /dev/null +++ b/src/pages/WrapperPage/WrapperPageView.tsx @@ -0,0 +1,304 @@ +import React from "react"; +import { Form, Formik } from "formik"; +import clsx from "clsx"; +import { + NetworkUnsupportedModal, + WrapActiveModal, + PreflightModalWrap, + ChangeNetworkDrawer, + AboutDrawer, +} from "../../modules"; +import { + Button, + Typography, + QuestionCircleSvg, + SelectInput, +} from "@chainsafe/common-components"; +import { SimpleTokenInput } from "../../components"; +import { ReactComponent as ETHIcon } from "../../media/tokens/eth.svg"; +import { WalletType } from "../../contexts/NetworkManagerContext/NetworkManagerContext"; +import { BridgeConfig, TokenConfig } from "../../chainbridgeConfig"; +import { PreflightDetails } from "./WrapperPage"; +import { forwardTo } from "../../utils/History"; +import { ROUTE_LINKS } from "../../routes"; + +type WrapperPageView = { + isReady: boolean | undefined; + classes: Record< + | "root" + | "walletArea" + | "blurb" + | "connectButton" + | "connecting" + | "connected" + | "changeButton" + | "networkName" + | "formArea" + | "currencySection" + | "tokenInputArea" + | "tokenInput" + | "maxButton" + | "tokenIndicator" + | "generalInput" + | "faqButton" + | "token" + | "tokenItem" + | "submitButtonArea", + string + >; + setWalletType: (walletType: WalletType) => void; + walletConnecting: boolean; + setChangeNetworkOpen: React.Dispatch>; + homeConfig: BridgeConfig | undefined; + setPreflightDetails: React.Dispatch>; + setPreflightModalOpen: React.Dispatch>; + preflightModalOpen: boolean; + tokens: any; + showImageUrl: (url: string | undefined) => string; + preflightDetails: PreflightDetails; + address: string | undefined; + aboutOpen: any; + setAboutOpen: React.Dispatch>; + changeNetworkOpen: any; + wrapSchema: any; + nativeTokenBalance: number | undefined; + wrapTokenConfig: TokenConfig | undefined; + action: "wrap" | "unwrap"; + setAction: React.Dispatch>; + handleWrapToken: () => void; + handleUnwrapToken: () => void; + txDetails: + | { + txState?: "inProgress" | "done"; + value: number; + tokenInfo: TokenConfig; + txHash?: string; + action: "wrap" | "unwrap"; + } + | undefined; + setTxDetails: React.Dispatch< + React.SetStateAction< + | { + txState?: "inProgress" | "done" | undefined; + value: number; + tokenInfo: TokenConfig; + txHash?: string | undefined; + action: "wrap" | "unwrap"; + } + | undefined + > + >; +}; + +export default function WrapperPageView({ + isReady, + classes, + setWalletType, + walletConnecting, + setChangeNetworkOpen, + homeConfig, + setPreflightDetails, + setPreflightModalOpen, + preflightModalOpen, + tokens, + showImageUrl, + preflightDetails, + address, + aboutOpen, + setAboutOpen, + changeNetworkOpen, + wrapSchema, + nativeTokenBalance, + wrapTokenConfig, + action, + setAction, + handleWrapToken, + handleUnwrapToken, + txDetails, + setTxDetails, +}: WrapperPageView) { + return ( +
+
+ {!isReady ? ( + <> + + To convert a token that needs to be wrapped, please connect to the + network that the token exists natively for. For example, to + convert ETH into wrapped ETH (WETH), your wallet must be connected + to an Ethereum network. + + + + ) : walletConnecting ? ( +
+ + This app requires access to your wallet,
+ please login and authorize access to continue. +
+
+ ) : ( +
+
+ Home network + setChangeNetworkOpen(true)} + > + Change + +
+ + {homeConfig?.name} + +
+ )} +
+ { + setPreflightDetails({ + ...values, + }); + setPreflightModalOpen(true); + }} + > +
+
+
+
+ +
+
+
+ + Balance:{" "} + {action === "wrap" + ? nativeTokenBalance + ? nativeTokenBalance.toFixed(2) + : 0.0 + : tokens[wrapTokenConfig?.address || "0x"].balance} + + + + ETH + + ), + value: "wrap", + }, + { + label: ( +
+ {wrapTokenConfig?.symbol} + {wrapTokenConfig?.symbol || "wETH"} +
+ ), + value: "unwrap", + }, + ]} + onChange={(val) => setAction(val)} + value={action} + /> +
+
+
+ +
+
+ setAboutOpen(true)} + className={classes.faqButton} + /> +
+
+
+ setAboutOpen(false)} /> + setChangeNetworkOpen(false)} + /> + setPreflightModalOpen(false)} + sender={address || ""} + start={() => { + if (action === "wrap") { + handleWrapToken(); + setPreflightModalOpen(false); + } else { + handleUnwrapToken(); + setPreflightModalOpen(false); + } + }} + sourceNetwork={homeConfig?.name || ""} + tokenSymbol={ + action === "wrap" + ? homeConfig?.nativeTokenSymbol || "ETH" + : wrapTokenConfig?.symbol || "wETH" + } + value={preflightDetails?.tokenAmount || 0} + wrappedTitle={ + action === "wrap" + ? `${wrapTokenConfig?.name} (${wrapTokenConfig?.symbol})` + : homeConfig?.nativeTokenSymbol || "ETH" + } + action={action} + /> + {txDetails && ( + { + setTxDetails(undefined); + forwardTo(ROUTE_LINKS.Transfer); + }} + /> + )} + {/* This is here due to requiring router */} + +
+ ); +} diff --git a/src/pages/WrapperPage/index.ts b/src/pages/WrapperPage/index.ts new file mode 100644 index 00000000..c20a7ace --- /dev/null +++ b/src/pages/WrapperPage/index.ts @@ -0,0 +1 @@ +export { default } from "./WrapperPage"; diff --git a/src/pages/WrapperPage/styles.ts b/src/pages/WrapperPage/styles.ts new file mode 100644 index 00000000..881dc92a --- /dev/null +++ b/src/pages/WrapperPage/styles.ts @@ -0,0 +1,167 @@ +import { makeStyles, createStyles, ITheme } from "@chainsafe/common-theme"; + +export const useStyles = makeStyles(({ constants, palette }: ITheme) => + createStyles({ + root: { + minHeight: constants.generalUnit * 69, + padding: constants.generalUnit * 6, + overflow: "hidden", + position: "relative", + }, + walletArea: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + width: "100%", + }, + blurb: { + color: palette.common.black.main, + }, + connectButton: { + margin: `${constants.generalUnit * 3}px 0 ${constants.generalUnit * 6}px`, + }, + connecting: { + textAlign: "center", + marginBottom: constants.generalUnit * 2, + }, + connected: { + width: "100%", + "& > *:first-child": { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + width: "100%", + }, + }, + changeButton: { + cursor: "pointer", + }, + networkName: { + padding: `${constants.generalUnit * 2}px ${ + constants.generalUnit * 1.5 + }px`, + border: `1px solid ${palette.additional["gray"][6]}`, + borderRadius: 2, + color: palette.additional["gray"][9], + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit * 3, + }, + formArea: { + "&.disabled": { + opacity: 0.4, + }, + }, + currencySection: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "flex-end", + margin: `${constants.generalUnit * 3}px 0`, + }, + tokenInputArea: { + display: "flex", + flexDirection: "row", + alignItems: "flex-end", + justifyContent: "space-around", + paddingRight: constants.generalUnit, + }, + tokenInput: { + margin: 0, + "& > div": { + height: 32, + "& input": { + borderBottomRightRadius: 0, + borderTopRightRadius: 0, + borderRight: 0, + }, + }, + "& span:last-child.error": { + position: "absolute", + }, + }, + maxButton: { + height: 32, + borderBottomLeftRadius: 0, + borderTopLeftRadius: 0, + left: -1, + color: palette.additional["gray"][8], + backgroundColor: palette.additional["gray"][3], + borderColor: palette.additional["gray"][6], + "&:hover": { + borderColor: palette.additional["gray"][6], + backgroundColor: palette.additional["gray"][7], + color: palette.common.white.main, + }, + "&:focus": { + borderColor: palette.additional["gray"][6], + }, + }, + tokenIndicator: { + width: 120, + textAlign: "right", + "& p": { + marginBottom: constants.generalUnit, + }, + "& *": { + cursor: "pointer", + }, + }, + generalInput: { + "& > span": { + marginBottom: constants.generalUnit, + }, + }, + faqButton: { + cursor: "pointer", + height: 20, + width: 20, + marginTop: constants.generalUnit * 5, + fill: `${palette.additional["transferUi"][1]} !important`, + }, + token: { + backgroundColor: palette.additional["gray"][1], + borderRadius: 2, + border: `1px solid ${palette.additional["gray"][6]}`, + padding: `${constants.generalUnit * 1}px ${ + constants.generalUnit * 1.5 + }px`, + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + cursor: "pointer", + height: constants.generalUnit * 4, + "& img, & svg": { + display: "block", + height: 14, + width: 14, + marginLeft: 10, + }, + "& span": { + minWidth: `calc(100% - 30px)`, + textAlign: "right", + color: palette.additional["gray"][9], + }, + }, + tokenItem: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + cursor: "pointer", + "& img, & svg": { + display: "block", + height: 14, + width: 14, + marginRight: 10, + }, + "& span": { + minWidth: `calc(100% - 30px)`, + textAlign: "right", + }, + }, + submitButtonArea: {}, + }) +); diff --git a/src/Components/Pages/__snapshots__/ExplorerPage.test.tsx.snap b/src/pages/__snapshots__/ExplorerPage.test.tsx.snap similarity index 100% rename from src/Components/Pages/__snapshots__/ExplorerPage.test.tsx.snap rename to src/pages/__snapshots__/ExplorerPage.test.tsx.snap diff --git a/src/pages/index.ts b/src/pages/index.ts new file mode 100644 index 00000000..e3b222f9 --- /dev/null +++ b/src/pages/index.ts @@ -0,0 +1,4 @@ +export { default as ExplorerPage } from "./ExplorerPage"; +export { default as TransactionPage } from "./TransactionPage"; +export { default as TransferPage } from "./TransferPage"; +export { default as WrapperPage } from "./WrapperPage"; diff --git a/src/Contexts/Reducers/TransfersReducer.tsx b/src/reducers/TransfersReducer.tsx similarity index 97% rename from src/Contexts/Reducers/TransfersReducer.tsx rename to src/reducers/TransfersReducer.tsx index 74cca7fb..09ac2b76 100644 --- a/src/Contexts/Reducers/TransfersReducer.tsx +++ b/src/reducers/TransfersReducer.tsx @@ -1,9 +1,6 @@ import { BigNumber } from "@ethersproject/bignumber"; -import { - EvmBridgeConfig, - SubstrateBridgeConfig, -} from "../../chainbridgeConfig"; -import { computeTransferDetails } from "../../Utils/Helpers"; +import { EvmBridgeConfig, SubstrateBridgeConfig } from "../chainbridgeConfig"; +import { computeTransferDetails } from "../utils/Helpers"; export enum ProposalStatus { Inactive, diff --git a/src/Contexts/Reducers/TransitMessageReducer.tsx b/src/reducers/TransitMessageReducer.tsx similarity index 91% rename from src/Contexts/Reducers/TransitMessageReducer.tsx rename to src/reducers/TransitMessageReducer.tsx index 622b004a..8f62a8a8 100644 --- a/src/Contexts/Reducers/TransitMessageReducer.tsx +++ b/src/reducers/TransitMessageReducer.tsx @@ -1,4 +1,4 @@ -import { TransitMessage } from "../NetworkManagerContext"; +import { TransitMessage } from "../contexts/NetworkManagerContext/NetworkManagerContext"; export type AddMessageAction = { type: "addMessage"; payload: TransitMessage }; export type ResetAction = { type: "resetMessages" }; diff --git a/src/Components/Routes.tsx b/src/routes/Routes.tsx similarity index 82% rename from src/Components/Routes.tsx rename to src/routes/Routes.tsx index bf72fc86..b7e7ddc8 100644 --- a/src/Components/Routes.tsx +++ b/src/routes/Routes.tsx @@ -1,10 +1,12 @@ import React from "react"; import { Switch, Route, Redirect } from "@chainsafe/common-components"; -import TransferPage from "./Pages/TransferPage"; -import WrapperPage from "./Pages/WrapperPage"; -import ExplorerPage from "./Pages/ExplorerPage"; -import TransactionPage from "./Pages/TransactionPage"; -import { ExplorerProvider } from "../Contexts/ExplorerContext"; +import { + TransactionPage, + WrapperPage, + ExplorerPage, + TransferPage, +} from "../pages"; +import { ExplorerProvider } from "../contexts/ExplorerContext/ExplorerContext"; export const ROUTE_LINKS = { Transfer: "/transfer", diff --git a/src/routes/index.ts b/src/routes/index.ts new file mode 100644 index 00000000..c5152322 --- /dev/null +++ b/src/routes/index.ts @@ -0,0 +1,2 @@ +export { default as ChainbridgeRoutes } from "./Routes"; +export { ROUTE_LINKS } from "./Routes"; diff --git a/src/Services/ExplorerService.tsx b/src/services/ExplorerService/ExplorerService.tsx similarity index 96% rename from src/Services/ExplorerService.tsx rename to src/services/ExplorerService/ExplorerService.tsx index 8e196d3d..7f460cf2 100644 --- a/src/Services/ExplorerService.tsx +++ b/src/services/ExplorerService/ExplorerService.tsx @@ -2,7 +2,7 @@ import { DepositRecord, ExplorerState, PageInfo, -} from "../Contexts/Reducers/TransfersReducer"; +} from "../../reducers/TransfersReducer"; export const fetchTransfers = async ( setState: React.SetStateAction, diff --git a/src/services/ExplorerService/index.ts b/src/services/ExplorerService/index.ts new file mode 100644 index 00000000..ce38aba1 --- /dev/null +++ b/src/services/ExplorerService/index.ts @@ -0,0 +1 @@ +export { fetchTransfers, fetchTransaction } from "./ExplorerService"; diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 00000000..eb3e98f3 --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1 @@ +export { fetchTransaction, fetchTransfers } from "./ExplorerService"; diff --git a/src/Themes/LightTheme.ts b/src/themes/LightTheme.ts similarity index 100% rename from src/Themes/LightTheme.ts rename to src/themes/LightTheme.ts diff --git a/src/Utils/Helper.test.ts b/src/utils/Helper.test.ts similarity index 98% rename from src/Utils/Helper.test.ts rename to src/utils/Helper.test.ts index 20d9260c..79102c0d 100644 --- a/src/Utils/Helper.test.ts +++ b/src/utils/Helper.test.ts @@ -1,4 +1,4 @@ -import { transfersReducer } from "../Contexts/Reducers/TransfersReducer"; +import { transfersReducer } from "../contexts/Reducers/TransfersReducer"; import { computeTransferDetails } from "./Helpers"; import { testResponse, diff --git a/src/Utils/Helpers.tsx b/src/utils/Helpers.tsx similarity index 98% rename from src/Utils/Helpers.tsx rename to src/utils/Helpers.tsx index f5318a55..4ee115ba 100644 --- a/src/Utils/Helpers.tsx +++ b/src/utils/Helpers.tsx @@ -18,12 +18,9 @@ import CosmosIcon from "../media/networks/cosmos.svg"; import EthermintIcon from "../media/networks/ethermint.svg"; import PolkadotIcon from "../media/networks/polkadot.svg"; import { BigNumber, BigNumberish, ethers } from "ethers"; -import { - DepositRecord, - TransferDetails, -} from "../Contexts/Reducers/TransfersReducer"; +import { DepositRecord, TransferDetails } from "../reducers/TransfersReducer"; import { EvmBridgeConfig, SubstrateBridgeConfig } from "../chainbridgeConfig"; -import { isCelo } from "../Contexts/Adaptors/EVMAdaptors/helpers"; +import { isCelo } from "../contexts/Adaptors/EVMAdaptors/helpers"; const { decodeAddress, encodeAddress } = require("@polkadot/keyring"); const { hexToU8a, isHex } = require("@polkadot/util"); diff --git a/src/Utils/History.tsx b/src/utils/History.tsx similarity index 100% rename from src/Utils/History.tsx rename to src/utils/History.tsx diff --git a/src/Utils/TestUtils.ts b/src/utils/TestUtils.ts similarity index 100% rename from src/Utils/TestUtils.ts rename to src/utils/TestUtils.ts