From ced64cc14ebc23d70bd444e5d2870fc85eaefbb7 Mon Sep 17 00:00:00 2001 From: zzq0826 <770166635@qq.com> Date: Mon, 17 Feb 2025 10:57:01 +0800 Subject: [PATCH] Bridge revision (#1412) * Bridge revision * Remove * Update mobile version * Review fix * Feedback resolve --- public/imgs/logo/STONE.svg | 10 + public/imgs/logo/applepay.svg | 3 + public/imgs/logo/arbitrum.svg | 9 + public/imgs/logo/avalanche.svg | 9 + public/imgs/logo/bank.svg | 8 + public/imgs/logo/base.svg | 9 + public/imgs/logo/binance.svg | 9 + public/imgs/logo/bitget.svg | 9 + public/imgs/logo/bithumb.svg | 9 + public/imgs/logo/blast.svg | 9 + public/imgs/logo/bybit.svg | 9 + public/imgs/logo/free.svg | 9 + public/imgs/logo/googlepay.svg | 9 + public/imgs/logo/hashkey.svg | 9 + public/imgs/logo/huobi.svg | 9 + public/imgs/logo/kelpdao.svg | 9 + public/imgs/logo/kucoin.svg | 9 + public/imgs/logo/logo.svg | 10 + public/imgs/logo/mastercard.svg | 5 + public/imgs/logo/more.svg | 6 + public/imgs/logo/okx.svg | 9 + public/imgs/logo/optimism.svg | 9 + public/imgs/logo/polygon.svg | 9 + public/imgs/logo/scroll.svg | 10 + public/imgs/logo/solana.svg | 9 + public/imgs/logo/stargate.svg | 9 + public/imgs/logo/starknet.svg | 9 + public/imgs/logo/sui.svg | 16 ++ public/imgs/logo/visa.svg | 3 + public/imgs/logo/zksync.svg | 9 + public/imgs/token/STONE.svg | 10 + public/imgs/token/SolvBTC.svg | 14 + public/imgs/token/USDe.svg | 17 ++ public/imgs/token/rsETH.svg | 1 + public/imgs/token/sUSDe.svg | 14 + src/app/bridge/Send/Buy.tsx | 62 +++++ src/app/bridge/Send/Claim.tsx | 3 + src/app/bridge/Send/Exchanges.tsx | 76 ++++++ src/app/bridge/Send/OfficialBridge.tsx | 194 ++++++++++++++ .../Send/SendTransaction/BalanceInput.tsx | 2 + .../SendTransaction/CustomiseRecipient.tsx | 3 +- .../Send/SendTransaction/ExternalBridge.tsx | 51 ++++ .../SendTransaction/InfoTooltip/DetailRow.tsx | 6 +- .../Send/SendTransaction/NetworkDirection.tsx | 55 ---- .../SendTransaction/TransactionSummary.tsx | 4 +- src/app/bridge/Send/SendTransaction/index.tsx | 214 ++++++++------- src/app/bridge/Send/ThirdParty.tsx | 77 ++++++ src/app/bridge/Send/Withdraw.tsx | 22 +- src/app/bridge/Send/index.tsx | 233 +++++++++-------- src/app/bridge/page.tsx | 5 +- src/constants/bridge.ts | 132 ++++++++++ src/constants/networks.ts | 247 ++++++++++++++++++ src/constants/searchParamsKey.ts | 1 + src/stores/bridgeStore.ts | 4 +- src/types/token.d.ts | 7 + 55 files changed, 1413 insertions(+), 301 deletions(-) create mode 100644 public/imgs/logo/STONE.svg create mode 100644 public/imgs/logo/applepay.svg create mode 100644 public/imgs/logo/arbitrum.svg create mode 100644 public/imgs/logo/avalanche.svg create mode 100644 public/imgs/logo/bank.svg create mode 100644 public/imgs/logo/base.svg create mode 100644 public/imgs/logo/binance.svg create mode 100644 public/imgs/logo/bitget.svg create mode 100644 public/imgs/logo/bithumb.svg create mode 100644 public/imgs/logo/blast.svg create mode 100644 public/imgs/logo/bybit.svg create mode 100644 public/imgs/logo/free.svg create mode 100644 public/imgs/logo/googlepay.svg create mode 100644 public/imgs/logo/hashkey.svg create mode 100644 public/imgs/logo/huobi.svg create mode 100644 public/imgs/logo/kelpdao.svg create mode 100644 public/imgs/logo/kucoin.svg create mode 100644 public/imgs/logo/logo.svg create mode 100644 public/imgs/logo/mastercard.svg create mode 100644 public/imgs/logo/more.svg create mode 100644 public/imgs/logo/okx.svg create mode 100644 public/imgs/logo/optimism.svg create mode 100644 public/imgs/logo/polygon.svg create mode 100644 public/imgs/logo/scroll.svg create mode 100644 public/imgs/logo/solana.svg create mode 100644 public/imgs/logo/stargate.svg create mode 100644 public/imgs/logo/starknet.svg create mode 100644 public/imgs/logo/sui.svg create mode 100644 public/imgs/logo/visa.svg create mode 100644 public/imgs/logo/zksync.svg create mode 100644 public/imgs/token/STONE.svg create mode 100644 public/imgs/token/SolvBTC.svg create mode 100644 public/imgs/token/USDe.svg create mode 100644 public/imgs/token/rsETH.svg create mode 100644 public/imgs/token/sUSDe.svg create mode 100644 src/app/bridge/Send/Buy.tsx create mode 100644 src/app/bridge/Send/Exchanges.tsx create mode 100644 src/app/bridge/Send/OfficialBridge.tsx create mode 100644 src/app/bridge/Send/SendTransaction/ExternalBridge.tsx delete mode 100644 src/app/bridge/Send/SendTransaction/NetworkDirection.tsx create mode 100644 src/app/bridge/Send/ThirdParty.tsx create mode 100644 src/constants/bridge.ts diff --git a/public/imgs/logo/STONE.svg b/public/imgs/logo/STONE.svg new file mode 100644 index 000000000..d5d8b9042 --- /dev/null +++ b/public/imgs/logo/STONE.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/imgs/logo/applepay.svg b/public/imgs/logo/applepay.svg new file mode 100644 index 000000000..64b829d4d --- /dev/null +++ b/public/imgs/logo/applepay.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/imgs/logo/arbitrum.svg b/public/imgs/logo/arbitrum.svg new file mode 100644 index 000000000..9a34bd56c --- /dev/null +++ b/public/imgs/logo/arbitrum.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/avalanche.svg b/public/imgs/logo/avalanche.svg new file mode 100644 index 000000000..2e3dc644c --- /dev/null +++ b/public/imgs/logo/avalanche.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/bank.svg b/public/imgs/logo/bank.svg new file mode 100644 index 000000000..c7f436299 --- /dev/null +++ b/public/imgs/logo/bank.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/imgs/logo/base.svg b/public/imgs/logo/base.svg new file mode 100644 index 000000000..1469757e2 --- /dev/null +++ b/public/imgs/logo/base.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/binance.svg b/public/imgs/logo/binance.svg new file mode 100644 index 000000000..e05df9059 --- /dev/null +++ b/public/imgs/logo/binance.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/bitget.svg b/public/imgs/logo/bitget.svg new file mode 100644 index 000000000..c0af87a2d --- /dev/null +++ b/public/imgs/logo/bitget.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/bithumb.svg b/public/imgs/logo/bithumb.svg new file mode 100644 index 000000000..8a8443f36 --- /dev/null +++ b/public/imgs/logo/bithumb.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/blast.svg b/public/imgs/logo/blast.svg new file mode 100644 index 000000000..683ebc7ac --- /dev/null +++ b/public/imgs/logo/blast.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/bybit.svg b/public/imgs/logo/bybit.svg new file mode 100644 index 000000000..dc58e5fe5 --- /dev/null +++ b/public/imgs/logo/bybit.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/free.svg b/public/imgs/logo/free.svg new file mode 100644 index 000000000..553ad4346 --- /dev/null +++ b/public/imgs/logo/free.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/googlepay.svg b/public/imgs/logo/googlepay.svg new file mode 100644 index 000000000..5eb3c3a64 --- /dev/null +++ b/public/imgs/logo/googlepay.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/hashkey.svg b/public/imgs/logo/hashkey.svg new file mode 100644 index 000000000..5cf68bf8d --- /dev/null +++ b/public/imgs/logo/hashkey.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/huobi.svg b/public/imgs/logo/huobi.svg new file mode 100644 index 000000000..700d3c4d4 --- /dev/null +++ b/public/imgs/logo/huobi.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/kelpdao.svg b/public/imgs/logo/kelpdao.svg new file mode 100644 index 000000000..9881398b3 --- /dev/null +++ b/public/imgs/logo/kelpdao.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/kucoin.svg b/public/imgs/logo/kucoin.svg new file mode 100644 index 000000000..8a4c69128 --- /dev/null +++ b/public/imgs/logo/kucoin.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/logo.svg b/public/imgs/logo/logo.svg new file mode 100644 index 000000000..4b0e235ff --- /dev/null +++ b/public/imgs/logo/logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/imgs/logo/mastercard.svg b/public/imgs/logo/mastercard.svg new file mode 100644 index 000000000..c78848273 --- /dev/null +++ b/public/imgs/logo/mastercard.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/imgs/logo/more.svg b/public/imgs/logo/more.svg new file mode 100644 index 000000000..969af1aff --- /dev/null +++ b/public/imgs/logo/more.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/imgs/logo/okx.svg b/public/imgs/logo/okx.svg new file mode 100644 index 000000000..ccad12ec4 --- /dev/null +++ b/public/imgs/logo/okx.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/optimism.svg b/public/imgs/logo/optimism.svg new file mode 100644 index 000000000..89da3abda --- /dev/null +++ b/public/imgs/logo/optimism.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/polygon.svg b/public/imgs/logo/polygon.svg new file mode 100644 index 000000000..fa02178b8 --- /dev/null +++ b/public/imgs/logo/polygon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/scroll.svg b/public/imgs/logo/scroll.svg new file mode 100644 index 000000000..4b0e235ff --- /dev/null +++ b/public/imgs/logo/scroll.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/imgs/logo/solana.svg b/public/imgs/logo/solana.svg new file mode 100644 index 000000000..2db42ea48 --- /dev/null +++ b/public/imgs/logo/solana.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/stargate.svg b/public/imgs/logo/stargate.svg new file mode 100644 index 000000000..8d1114d3c --- /dev/null +++ b/public/imgs/logo/stargate.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/starknet.svg b/public/imgs/logo/starknet.svg new file mode 100644 index 000000000..2e9cf6387 --- /dev/null +++ b/public/imgs/logo/starknet.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/logo/sui.svg b/public/imgs/logo/sui.svg new file mode 100644 index 000000000..db0730231 --- /dev/null +++ b/public/imgs/logo/sui.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/public/imgs/logo/visa.svg b/public/imgs/logo/visa.svg new file mode 100644 index 000000000..eca4fcc7c --- /dev/null +++ b/public/imgs/logo/visa.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/imgs/logo/zksync.svg b/public/imgs/logo/zksync.svg new file mode 100644 index 000000000..0e9886747 --- /dev/null +++ b/public/imgs/logo/zksync.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/imgs/token/STONE.svg b/public/imgs/token/STONE.svg new file mode 100644 index 000000000..d5d8b9042 --- /dev/null +++ b/public/imgs/token/STONE.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/imgs/token/SolvBTC.svg b/public/imgs/token/SolvBTC.svg new file mode 100644 index 000000000..188afc41c --- /dev/null +++ b/public/imgs/token/SolvBTC.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/imgs/token/USDe.svg b/public/imgs/token/USDe.svg new file mode 100644 index 000000000..ca96911dd --- /dev/null +++ b/public/imgs/token/USDe.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/public/imgs/token/rsETH.svg b/public/imgs/token/rsETH.svg new file mode 100644 index 000000000..07e0a5a08 --- /dev/null +++ b/public/imgs/token/rsETH.svg @@ -0,0 +1 @@ + diff --git a/public/imgs/token/sUSDe.svg b/public/imgs/token/sUSDe.svg new file mode 100644 index 000000000..ec6405c10 --- /dev/null +++ b/public/imgs/token/sUSDe.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/app/bridge/Send/Buy.tsx b/src/app/bridge/Send/Buy.tsx new file mode 100644 index 000000000..123fa0590 --- /dev/null +++ b/src/app/bridge/Send/Buy.tsx @@ -0,0 +1,62 @@ +import { sendGAEvent } from "@next/third-parties/google" +import Image from "next/image" + +import { Box, Stack, Typography } from "@mui/material" + +import { ONRAMP_PLATFORMS } from "@/constants/bridge" + +const ThirdParty = () => { + return ( + + {ONRAMP_PLATFORMS.map(item => ( + { + sendGAEvent("event", "bridge_onramp_click", { + label: item.name, + }) + }} + sx={{ + width: "100%", + padding: "1.2rem 1.6rem", + backgroundColor: "#FFF8F3", + borderRadius: "1rem", + "&:hover": { + backgroundColor: "#FFFFFF", + }, + }} + > + {item.name} + + + {item.name} + + + {item.description.map((item, idx) => ( + thirdparty + ))} + + + ))} + + ) +} + +export default ThirdParty diff --git a/src/app/bridge/Send/Claim.tsx b/src/app/bridge/Send/Claim.tsx index 4588a1430..2f9abe5e8 100644 --- a/src/app/bridge/Send/Claim.tsx +++ b/src/app/bridge/Send/Claim.tsx @@ -21,6 +21,9 @@ const useStyles = makeStyles()(theme => ({ [theme.breakpoints.down("sm")]: { height: "41.8rem", }, + "& *": { + fontFamily: "var(--developer-page-font-family) !important", + }, }, loadingBox: { position: "absolute", diff --git a/src/app/bridge/Send/Exchanges.tsx b/src/app/bridge/Send/Exchanges.tsx new file mode 100644 index 000000000..46a1d70ee --- /dev/null +++ b/src/app/bridge/Send/Exchanges.tsx @@ -0,0 +1,76 @@ +import { sendGAEvent } from "@next/third-parties/google" +import Image from "next/image" + +import { Box, Stack, Typography } from "@mui/material" + +import { EXCHANGES } from "@/constants/bridge" + +const Exchanges = () => { + return ( + + + Choose + thirdparty + + Scroll{" "} + + as the withdrawal network on supported exchange. + + + {EXCHANGES.map(item => ( + { + sendGAEvent("event", "bridge_exchange_click", { + label: item.name, + }) + }} + sx={{ + width: "100%", + padding: "1.2rem 1.6rem", + backgroundColor: "#FFF8F3", + borderRadius: "1rem", + cursor: "pointer", + textDecoration: "none", + transition: "all 0.2s", + "&:hover": { + backgroundColor: "#FFFFFF", + }, + }} + > + + {item.name} + + + {item.name} + + + ))} + + + ) +} + +export default Exchanges diff --git a/src/app/bridge/Send/OfficialBridge.tsx b/src/app/bridge/Send/OfficialBridge.tsx new file mode 100644 index 000000000..cfc31679f --- /dev/null +++ b/src/app/bridge/Send/OfficialBridge.tsx @@ -0,0 +1,194 @@ +import { useEffect } from "react" +import { makeStyles } from "tss-react/mui" + +import { TabContext, TabList, TabPanel } from "@mui/lab" +import { Box, Snackbar, Tab } from "@mui/material" + +import Alert from "@/components/Alert" +import TextButton from "@/components/TextButton" +import { CHAIN_ID } from "@/constants" +import { useRainbowContext } from "@/contexts/RainbowProvider" +import useBridgeStore from "@/stores/bridgeStore" + +import Deposit from "./Deposit" +import Withdraw from "./Withdraw" + +const useStyles = makeStyles()(theme => ({ + sendWrapper: { + borderRadius: "2rem", + overflow: "hidden", + maxWidth: "66rem", + width: "100%", + position: "relative", + [theme.breakpoints.down("sm")]: { + maxWidth: "100%", + }, + }, + tabList: { + width: "100%", + justifyContent: "space-between", + [theme.breakpoints.down("sm")]: { + borderBottom: "0.5px solid rgba(16, 16, 16, 0.20)", + }, + }, + tab: { + flex: 1, + height: "5.6rem", + fontSize: "1.8rem", + fontWeight: 500, + color: (theme as any).vars.palette.text.primary, + padding: 0, + backgroundColor: "#FFE6C8", + textTransform: "unset", + "&.Mui-selected": { + fontWeight: 600, + color: "#FF684B", + backgroundColor: (theme as any).vars.palette.themeBackground.normal, + }, + + [theme.breakpoints.down("sm")]: { + width: "50%", + fontSize: "1.4rem", + backgroundColor: (theme as any).vars.palette.themeBackground.normal, + // "&.Mui-selected": { + // backgroundColor: (theme as any).vars.palette.themeBackground.normal, + // }, + }, + }, + indicator: { + height: "0", + backgroundColor: "#FF684B", + [theme.breakpoints.down("sm")]: { + height: "4px", + }, + }, + tabPanel: { + padding: "2.4rem 3.2rem", + backgroundColor: (theme as any).vars.palette.themeBackground.normal, + borderRadius: "2rem", + [theme.breakpoints.down("sm")]: { + padding: "1.6rem 0", + }, + }, + + snackbar: { + width: "max-content", + maxWidth: "calc(100% - 1.6rem)", + + [theme.breakpoints.down("sm")]: { + left: "50%", + transform: "translateX(-50%)", + }, + }, + + mobileSelect: { + width: "100%", + borderRadius: "10px", + backgroundColor: "white", + border: "1px solid #473835", + "& .MuiSelect-select": { + fontSize: "1.8rem", + padding: "1rem 1.6rem", + height: "36px", + display: "flex", + alignItems: "center", + fontWeight: 600, + fontFamily: "var(--default-font-family) !important", + }, + "& .MuiOutlinedInput-root": { + height: "36px", + }, + "& .MuiOutlinedInput-notchedOutline": { + border: "none", + }, + "& .MuiSelect-icon": { + right: "1rem", + top: "2rem", + }, + }, +})) + +const OfficialBridge = () => { + const { classes, cx } = useStyles() + const { chainId } = useRainbowContext() + const { txType, txResult, fromNetwork, withdrawStep, changeTxType, changeTxResult, changeHistoryVisible, changeIsNetworkCorrect } = useBridgeStore() + + useEffect(() => { + let networkCorrect + if (txType === "Deposit") { + networkCorrect = fromNetwork.isL1 && chainId === CHAIN_ID.L1 + } else if (withdrawStep === "1") { + networkCorrect = !fromNetwork.isL1 && chainId === CHAIN_ID.L2 + } else { + networkCorrect = chainId === CHAIN_ID.L1 + } + changeIsNetworkCorrect(networkCorrect) + }, [fromNetwork, txType, withdrawStep, chainId]) + + const handleChange = (e, newValue) => { + changeTxType(newValue) + handleClose() + } + + const handleOpenHistory = () => { + changeHistoryVisible(true) + handleClose() + } + + const handleClose = () => { + changeTxResult(null) + } + + return ( + + + + + + + + + + + + + + + +
+ {txResult?.code === 1 && ( + + <> + Submitted successfully!
+ {txType === "Deposit" ? "Funds take up to 20 mins to be ready" : "Funds take up to 2h to be claimable"}
+ + View transaction history + + +
+ )} + {txResult?.code === 0 && ( + + <> + Failed in submission. +
{txResult?.message} + +
+ )} +
+
+
+ ) +} + +export default OfficialBridge diff --git a/src/app/bridge/Send/SendTransaction/BalanceInput.tsx b/src/app/bridge/Send/SendTransaction/BalanceInput.tsx index 05dcd8770..3778ffbb0 100644 --- a/src/app/bridge/Send/SendTransaction/BalanceInput.tsx +++ b/src/app/bridge/Send/SendTransaction/BalanceInput.tsx @@ -21,6 +21,7 @@ const useStyles = makeStyles()(theme => ({ }, }, inputWrapper: { + fontFamily: "var(--developer-page-font-family) !important", "&.Mui-error": { ".MuiInputBase-input": { border: `1px solid ${theme.vars.palette.primary.main}`, @@ -55,6 +56,7 @@ const useStyles = makeStyles()(theme => ({ lineHeight: 2, color: "#A39B9A", whiteSpace: "nowrap", + fontFamily: "var(--developer-page-font-family) !important", [theme.breakpoints.down("sm")]: { fontSize: "1.2rem", }, diff --git a/src/app/bridge/Send/SendTransaction/CustomiseRecipient.tsx b/src/app/bridge/Send/SendTransaction/CustomiseRecipient.tsx index e7810e4fb..7e4765a36 100644 --- a/src/app/bridge/Send/SendTransaction/CustomiseRecipient.tsx +++ b/src/app/bridge/Send/SendTransaction/CustomiseRecipient.tsx @@ -12,7 +12,7 @@ import useInputAddress from "@/hooks/useInputAddress" const useStyles = makeStyles()(theme => ({ title: { fontSize: "1.8rem", - lineHeight: "3.6rem", + lineHeight: "2.4rem", fontWeight: 500, textAlign: "left", cursor: "pointer", @@ -90,6 +90,7 @@ const CustomiseRecipient = props => { background: "#ffffff", border: showErrorMessage ? "2px solid #FF684B" : "1px solid #473835", borderRadius: "1rem", + fontFamily: "var(--developer-page-font-family) !important", }} disabled={disabled} onChange={v => setAddressInputValue(v.target.value)} diff --git a/src/app/bridge/Send/SendTransaction/ExternalBridge.tsx b/src/app/bridge/Send/SendTransaction/ExternalBridge.tsx new file mode 100644 index 000000000..9f453d983 --- /dev/null +++ b/src/app/bridge/Send/SendTransaction/ExternalBridge.tsx @@ -0,0 +1,51 @@ +import Image from "next/image" + +import { Box, Typography } from "@mui/material" + +const ExternalBridge = ({ selectedToken, txType }: { selectedToken: Token; txType: "Deposit" | "Withdraw" }) => { + const bridgeInfo = selectedToken.extensions?.bridgeInfo + return ( + + + Use third party bridge to {txType === "Deposit" ? "deposit" : "withdraw"} {selectedToken.symbol} to{" "} + {txType === "Deposit" ? "Scroll" : "Ethereum"} + + + bridge + {bridgeInfo?.bridgeName} + + + ) +} + +export default ExternalBridge diff --git a/src/app/bridge/Send/SendTransaction/InfoTooltip/DetailRow.tsx b/src/app/bridge/Send/SendTransaction/InfoTooltip/DetailRow.tsx index 30fe0d88f..f7ab407fc 100644 --- a/src/app/bridge/Send/SendTransaction/InfoTooltip/DetailRow.tsx +++ b/src/app/bridge/Send/SendTransaction/InfoTooltip/DetailRow.tsx @@ -20,11 +20,11 @@ export type DetailRowProps = { const useStyles = makeStyles()(theme => ({ rowItem: { "& td": { - width: "auto", + width: "20rem", padding: 0, }, "& td:last-child": { - width: "100%", + width: "auto", }, [theme.breakpoints.down("sm")]: { verticalAlign: "top", @@ -48,6 +48,7 @@ const useStyles = makeStyles()(theme => ({ lineHeight: "3rem", whiteSpace: "nowrap", paddingRight: "2.4rem", + fontFamily: "var(--developer-page-font-family) !important", [theme.breakpoints.down("sm")]: { fontSize: "1.4rem", lineHeight: "2.4rem", @@ -58,6 +59,7 @@ const useStyles = makeStyles()(theme => ({ fontWeight: 400, lineHeight: "3rem", color: "#5B5B5B", + fontFamily: "var(--developer-page-font-family) !important", [theme.breakpoints.down("sm")]: { fontSize: "1.4rem", lineHeight: "2.4rem", diff --git a/src/app/bridge/Send/SendTransaction/NetworkDirection.tsx b/src/app/bridge/Send/SendTransaction/NetworkDirection.tsx deleted file mode 100644 index 81f40a171..000000000 --- a/src/app/bridge/Send/SendTransaction/NetworkDirection.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { makeStyles } from "tss-react/mui" - -import { Chip, Stack, SvgIcon, Typography } from "@mui/material" - -import useBridgeStore from "@/stores/bridgeStore" - -const useStyles = makeStyles()(theme => ({ - chip: { - background: "transparent", - padding: "0 1rem", - height: "3.5rem", - [theme.breakpoints.down("sm")]: { - overflow: "hidden", - padding: "0 1rem", - }, - }, - chipLabel: { - paddingLeft: "1rem", - paddingRight: 0, - fontWeight: 600, - fontSize: "1.8rem", - [theme.breakpoints.down("sm")]: { - fontSize: "1.4rem", - paddingLeft: "0.6rem", - }, - }, - icon: { - width: "3.2rem", - height: "3.2rem", - margin: "0 !important", - }, -})) - -const TxDirection = () => { - const { classes } = useStyles() - const { fromNetwork, toNetwork } = useBridgeStore() - return ( - - From - } - label={fromNetwork.name} - > - To - } - label={toNetwork.name} - > - - ) -} - -export default TxDirection diff --git a/src/app/bridge/Send/SendTransaction/TransactionSummary.tsx b/src/app/bridge/Send/SendTransaction/TransactionSummary.tsx index d969549d1..b53aae853 100644 --- a/src/app/bridge/Send/SendTransaction/TransactionSummary.tsx +++ b/src/app/bridge/Send/SendTransaction/TransactionSummary.tsx @@ -13,8 +13,6 @@ import DetailRow from "./InfoTooltip/DetailRow" const useStyles = makeStyles()(theme => ({ root: { width: "100%", - marginTop: "1.2rem", - marginBottom: "1.2rem", }, title: { fontSize: "1.8rem", @@ -25,7 +23,7 @@ const useStyles = makeStyles()(theme => ({ table: { borderRadius: "1rem", overflow: "hidden", - background: theme.vars.palette.themeBackground.normal, + backgroundColor: theme.vars.palette.themeBackground.light, width: "100%", border: `1.6rem solid ${theme.vars.palette.themeBackground.normal}`, borderTopWidth: " 1.2rem", diff --git a/src/app/bridge/Send/SendTransaction/index.tsx b/src/app/bridge/Send/SendTransaction/index.tsx index 5e371147e..50ad889c6 100644 --- a/src/app/bridge/Send/SendTransaction/index.tsx +++ b/src/app/bridge/Send/SendTransaction/index.tsx @@ -24,8 +24,7 @@ import { amountToBN, checkApproved, switchNetwork, trimErrorMessage } from "@/ut import ApprovalDialog from "./ApprovalDialog" import BalanceInput from "./BalanceInput" import CustomiseRecipient from "./CustomiseRecipient" -import DepositSelector from "./DepositSelector" -import NetworkDirection from "./NetworkDirection" +import ExternalBridge from "./ExternalBridge" import TransactionSummary from "./TransactionSummary" import useBatchDeposit from "./hooks/useBatchDeposit" @@ -69,6 +68,10 @@ const SendTransaction = () => { // const { balance, isLoading: balanceLoading } = useBalance(selectedToken.address) const { balance, loading: balanceLoading } = useBalance(selectedToken, fromNetwork) + const externalBridge = useMemo(() => { + return selectedToken.extensions?.bridgeInfo + }, [selectedToken]) + const { isNeeded: needApproval, approve, @@ -136,22 +139,7 @@ const SendTransaction = () => { useEffect(() => { let nextBridgeWarning let nextInputError = false - if (!walletCurrentAddress) { - nextBridgeWarning = ( - - Connect wallet - - ) - } else if (chainId !== fromNetwork.chainId) { - nextBridgeWarning = ( - <> - Wrong network.{" "} - switchNetwork(fromNetwork.chainId)}> - Switch to {fromNetwork.name} - - - ) - } else if (maxWarning && maxWarning !== "FeeError") { + if (maxWarning && maxWarning !== "FeeError") { nextBridgeWarning = <>{maxWarning} nextInputError = true } else if (gasFeeErrorMessage && (validAmount || maxWarning) && needApproval === false) { @@ -188,13 +176,13 @@ const SendTransaction = () => { const sendText = useMemo(() => { if (txType === "Deposit" && sendLoading) { - return "Depositing funds" + return "Depositing to Scroll" } else if (txType === "Deposit" && !sendLoading) { - return "Deposit funds" + return "Deposit to Scroll" } else if (txType === "Withdraw" && sendLoading) { - return "Withdrawing funds" + return "Withdrawing to Ethereum" } - return "Withdraw funds" + return "Withdraw to Ethereum" }, [txType, sendLoading]) useEffect(() => { @@ -304,99 +292,103 @@ const SendTransaction = () => { } return ( - - - - - {!!bridgeWarning && bridgeWarning !== ">0" && ( - - - - {bridgeWarning} - - + + + + + {!!bridgeWarning && bridgeWarning !== ">0" && ( + + + + {bridgeWarning} + + + )} + + {!externalBridge && ( + )} - {bridgeSummaryType === BridgeSummaryType.Selector && ( - - )} - {!(bridgeSummaryType === BridgeSummaryType.Selector && depositBatchMode === DepositBatchMode.Economy) && ( - - )} - - {bridgeSummaryType === BridgeSummaryType.Summary && ( - + {externalBridge ? ( + + ) : ( + <> + {bridgeSummaryType === BridgeSummaryType.Summary && ( + + )} + + {renderButton()} + + + )} - - {renderButton()} - - ) } diff --git a/src/app/bridge/Send/ThirdParty.tsx b/src/app/bridge/Send/ThirdParty.tsx new file mode 100644 index 000000000..b332ba58a --- /dev/null +++ b/src/app/bridge/Send/ThirdParty.tsx @@ -0,0 +1,77 @@ +import { sendGAEvent } from "@next/third-parties/google" +import Image from "next/image" + +import { Box, Stack, Typography } from "@mui/material" + +import { CROSS_CHAIN_BRIDGES } from "@/constants/bridge" +import useCheckViewport from "@/hooks/useCheckViewport" + +const ThirdParty = () => { + const { isMobile } = useCheckViewport() + return ( + + {CROSS_CHAIN_BRIDGES.map(item => ( + { + sendGAEvent("event", "bridge_dex_click", { + label: item.name, + }) + }} + sx={{ + width: "100%", + padding: "1.2rem 1.6rem", + backgroundColor: "#FFF8F3", + borderRadius: "1rem", + cursor: "pointer", + textDecoration: "none", + transition: "all 0.2s", + "&:hover": { + backgroundColor: "#FFFFFF", + }, + }} + > + {item.name} + + {item.name} + + + {item.description.map((item, idx) => ( + thirdparty + ))} + + + + ))} + + ) +} + +export default ThirdParty diff --git a/src/app/bridge/Send/Withdraw.tsx b/src/app/bridge/Send/Withdraw.tsx index f283fbf5f..03fd5556e 100644 --- a/src/app/bridge/Send/Withdraw.tsx +++ b/src/app/bridge/Send/Withdraw.tsx @@ -11,39 +11,43 @@ import SendTransaction from "./SendTransaction" const useStyles = makeStyles()(theme => ({ tabList: { minHeight: "unset", + marginBottom: "1.6rem", }, tabFlex: { width: "100%", - justifyContent: "center", - borderBottom: "1px solid #5b5b5b", + justifyContent: "flex-start", margin: "0 auto", + gap: "0.8rem", }, tab: { minHeight: "unset", height: "4.4rem", fontSize: "1.6rem", - fontWeight: 600, + fontWeight: 500, textTransform: "unset", color: theme.vars.palette.text.primary, padding: 0, - flex: 1, + width: "16rem", + backgroundColor: "white", + borderRadius: "0.8rem", "&.Mui-selected": { - color: theme.vars.palette.text.primary, + backgroundColor: theme.vars.palette.text.primary, + color: "white", + fontWeight: 700, }, [theme.breakpoints.down("sm")]: { fontSize: "1.4rem", padding: "0 1rem", width: "unset", + flex: 1, }, }, indicator: { - height: "4px", - backgroundColor: "#FF684B", + display: "none", }, tabPanel: { - backgroundColor: theme.vars.palette.themeBackground.optionHightlight, flex: 1, - padding: "1.6rem 0 0", + padding: "0", }, })) diff --git a/src/app/bridge/Send/index.tsx b/src/app/bridge/Send/index.tsx index 053771b2b..d97fa38da 100644 --- a/src/app/bridge/Send/index.tsx +++ b/src/app/bridge/Send/index.tsx @@ -1,30 +1,24 @@ -import { useSearchParams } from "next/navigation" -import { useEffect, useMemo } from "react" +import { sendGAEvent } from "@next/third-parties/google" +import { usePathname, useRouter, useSearchParams } from "next/navigation" +import { useState } from "react" import { makeStyles } from "tss-react/mui" import { TabContext, TabList, TabPanel } from "@mui/lab" -import { Box, Snackbar, Tab } from "@mui/material" +import { Box, MenuItem, Select, Tab, useMediaQuery, useTheme } from "@mui/material" -import Alert from "@/components/Alert" -import TextButton from "@/components/TextButton" -import { CHAIN_ID, ETH_SYMBOL } from "@/constants" -import { BRIDGE_TOKEN } from "@/constants/searchParamsKey" -import { useRainbowContext } from "@/contexts/RainbowProvider" -import useBatchBridgeStore, { DepositBatchMode } from "@/stores/batchBridgeStore" -import useBridgeStore from "@/stores/bridgeStore" +import ArrowDownSvg from "@/assets/svgs/bridge/arrow-down.svg" +import { BRIDGE_TAB } from "@/constants/searchParamsKey" -import Deposit from "./Deposit" -import Withdraw from "./Withdraw" +import Buy from "./Buy" +import Exchanges from "./Exchanges" +import OfficialBridge from "./OfficialBridge" +import ThirdParty from "./ThirdParty" const useStyles = makeStyles()(theme => ({ sendWrapper: { - borderRadius: "2rem", overflow: "hidden", - maxWidth: "64rem", + maxWidth: "66rem", width: "100%", - "& *": { - fontFamily: "var(--developer-page-font-family) !important", - }, position: "relative", [theme.breakpoints.down("sm")]: { maxWidth: "100%", @@ -32,20 +26,23 @@ const useStyles = makeStyles()(theme => ({ }, tabList: { width: "100%", + justifyContent: "space-between", + borderBottom: "0.5px solid rgba(16, 16, 16, 0.20)", + [theme.breakpoints.down("sm")]: { + display: "none", + }, }, tab: { - flex: 1, + width: "fit-content", + minWidth: "fit-content", height: "5.6rem", - fontSize: "2rem", - fontWeight: 500, - color: theme.vars.palette.text.primary, + fontSize: "1.8rem", + fontWeight: 600, + color: (theme as any).vars.palette.text.primary, padding: 0, - backgroundColor: theme.vars.palette.themeBackground.normal, textTransform: "unset", "&.Mui-selected": { - color: theme.vars.palette.text.primary, - fontWeight: 600, - backgroundColor: theme.vars.palette.themeBackground.optionHightlight, + color: "#FF684B", }, [theme.breakpoints.down("sm")]: { @@ -54,126 +51,132 @@ const useStyles = makeStyles()(theme => ({ }, }, indicator: { - display: "none", + height: "4px", + backgroundColor: "#FF684B", }, tabPanel: { - backgroundColor: theme.vars.palette.themeBackground.optionHightlight, - padding: "3rem 5.4rem", + padding: "3.2rem", + backgroundColor: theme.vars.palette.themeBackground.normal, + borderRadius: "2rem", + marginTop: "2.4rem", + }, - "&.withdraw": { - padding: "1rem 3rem 3rem", + mobileSelect: { + width: "100%", + borderRadius: "10px", + backgroundColor: "white", + border: "1px solid #473835", + "& .MuiSelect-select": { + fontSize: "1.8rem", + padding: "1rem 1.6rem", + height: "36px", + display: "flex", + alignItems: "center", + fontWeight: 600, + fontFamily: "var(--default-font-family) !important", }, - - [theme.breakpoints.down("sm")]: { - padding: "3rem 2rem 2rem", - - "&.withdraw": { - padding: "1rem 2rem 2rem", - }, + "& .MuiOutlinedInput-root": { + height: "36px", }, - }, - - snackbar: { - width: "max-content", - maxWidth: "calc(100% - 1.6rem)", - - [theme.breakpoints.down("sm")]: { - left: "50%", - transform: "translateX(-50%)", + "& .MuiOutlinedInput-notchedOutline": { + border: "none", + }, + "& .MuiSelect-icon": { + right: "1rem", + top: "2rem", }, }, })) const Send = () => { - const { classes, cx } = useStyles() - const { chainId } = useRainbowContext() - const { txType, txResult, fromNetwork, withdrawStep, changeTxType, changeTxResult, changeHistoryVisible, changeIsNetworkCorrect } = useBridgeStore() - - const { depositBatchMode } = useBatchBridgeStore() + const { classes } = useStyles() + const router = useRouter() + const pathname = usePathname() const searchParams = useSearchParams() - const token = searchParams.get(BRIDGE_TOKEN) - const tokenSymbol = useMemo(() => token || ETH_SYMBOL, [token]) - - const isEconomyDeposit = useMemo(() => depositBatchMode === DepositBatchMode.Economy && tokenSymbol === ETH_SYMBOL, [depositBatchMode, tokenSymbol]) - - useEffect(() => { - let networkCorrect - if (txType === "Deposit") { - networkCorrect = fromNetwork.isL1 && chainId === CHAIN_ID.L1 - } else if (withdrawStep === "1") { - networkCorrect = !fromNetwork.isL1 && chainId === CHAIN_ID.L2 - } else { - networkCorrect = chainId === CHAIN_ID.L1 - } - changeIsNetworkCorrect(networkCorrect) - }, [fromNetwork, txType, withdrawStep, chainId]) + const tab = searchParams.get(BRIDGE_TAB) - const handleChange = (e, newValue) => { - changeTxType(newValue) - handleClose() - } + const [txType, setTxType] = useState(tab || "OfficialBridge") + + const theme = useTheme() + const isMobile = useMediaQuery(theme.breakpoints.down("sm")) - const handleOpenHistory = () => { - changeHistoryVisible(true) - handleClose() + const handleChange = (e, newValue) => { + setTxType(newValue) + router.push(`${pathname}?${BRIDGE_TAB}=${newValue}`) + sendGAEvent("event", "bridge_tab_change", { + label: newValue, + }) } - const handleClose = () => { - changeTxResult(null) + const options = [ + { value: "OfficialBridge", label: "From/to Ethereum" }, + { value: "ThirdParty", label: "From other chains" }, + { value: "Exchanges", label: "Exchanges" }, + { value: "Buy", label: "Buy with Fiat" }, + ] + + const handleSelectChange = event => { + setTxType(event.target.value) + router.push(`${pathname}?${BRIDGE_TAB}=${event.target.value}`) + sendGAEvent("event", "bridge_tab_change", { + label: event.target.value, + }) } return ( + {isMobile && ( + + )} + - - + {options.map(option => ( + + ))} - - + + - - + + + + + + + + - - -
- {txResult?.code === 1 && ( - - <> - Submitted successfully!
- {txType === "Deposit" - ? `Funds take up to ${isEconomyDeposit ? "1h" : "20 mins"} to be ready` - : "Funds take up to 2h to be claimable"}{" "} -
- - View transaction history - - -
- )} - {txResult?.code === 0 && ( - - <> - Failed in submission. -
{txResult?.message} - -
- )} -
-
) } diff --git a/src/app/bridge/page.tsx b/src/app/bridge/page.tsx index 7a9bedcc5..34c0a31c1 100644 --- a/src/app/bridge/page.tsx +++ b/src/app/bridge/page.tsx @@ -42,7 +42,7 @@ const Bridge = () => { sx={{ pt: ["4.8rem", "8.4rem"], pb: "6rem", - minHeight: "calc(100vh - 69.2rem)", + minHeight: "calc(100vh - 38.8rem)", display: "flex", flexDirection: "column", alignItems: ["flex-start", "center"], @@ -51,7 +51,7 @@ const Bridge = () => { > { - {/* */} ) } diff --git a/src/constants/bridge.ts b/src/constants/bridge.ts new file mode 100644 index 000000000..4316f0a3f --- /dev/null +++ b/src/constants/bridge.ts @@ -0,0 +1,132 @@ +export const EXCHANGES = [ + { + name: "Binance", + icon: "/imgs/logo/binance.svg", + url: "https://www.binance.com/trade/SCR_USDT?type=spot", + }, + { + name: "OKX", + icon: "/imgs/logo/okx.svg", + url: "https://www.okx.com/trade-spot/scr-usdt", + }, + { + name: "Bithumb", + icon: "/imgs/logo/bithumb.svg", + url: "https://www.bithumb.com/react/trade/order/SCR-KRW", + }, + { + name: "Bybit", + icon: "/imgs/logo/bybit.svg", + url: "https://www.bybit.com/trade/spot/SCR/USDT", + }, + + { + name: "Bitget", + icon: "/imgs/logo/bitget.svg", + url: "https://www.bitget.com/spot/SCRUSDT", + }, + + { + name: "Huobi", + icon: "/imgs/logo/huobi.svg", + url: "https://www.htx.com/trade/scr_usdt?type=isolated", + }, + { + name: "Kucoin", + icon: "/imgs/logo/kucoin.svg", + url: "https://www.kucoin.com/trade/SCR-USDT", + }, + { + name: "Hashkey", + icon: "/imgs/logo/hashkey.svg", + url: "https://global.hashkey.com/spot/SCR_USDT", + }, +] + +export const CROSS_CHAIN_BRIDGES = [ + { + name: "Across", + icon: "https://scroll-eco-list.netlify.app/logos/across.jpg", + url: "https://app.across.to/bridge", + description: [ + "/imgs/logo/arbitrum.svg", + "/imgs/logo/base.svg", + "/imgs/logo/blast.svg", + "/imgs/logo/optimism.svg", + "/imgs/logo/polygon.svg", + "/imgs/logo/zksync.svg", + "/imgs/logo/more.svg", + ], + }, + { + name: "Bungee", + icon: "https://scroll-eco-list.netlify.app/logos/bungee.jpg", + url: "https://www.bungee.exchange/", + description: [ + "/imgs/logo/arbitrum.svg", + "/imgs/logo/base.svg", + "/imgs/logo/blast.svg", + "/imgs/logo/optimism.svg", + "/imgs/logo/polygon.svg", + "/imgs/logo/zksync.svg", + "/imgs/logo/more.svg", + ], + }, + { + name: "Orbiter Finance", + icon: "https://scroll-eco-list.netlify.app/logos/orbiter finance.png", + url: "https://www.orbiter.finance/en?src_chain=1&tgt_chain=534352&src_token=ETH", + description: [ + "/imgs/logo/arbitrum.svg", + "/imgs/logo/base.svg", + "/imgs/logo/binance.svg", + "/imgs/logo/optimism.svg", + "/imgs/logo/solana.svg", + "/imgs/logo/sui.svg", + "/imgs/logo/more.svg", + ], + }, + { + name: "Synapse", + icon: "https://scroll-eco-list.netlify.app/logos/synapse.png", + url: "https://synapseprotocol.com/?fromChainId=1&toChainId=534352", + description: [ + "/imgs/logo/arbitrum.svg", + "/imgs/logo/base.svg", + "/imgs/logo/binance.svg", + "/imgs/logo/optimism.svg", + "/imgs/logo/solana.svg", + "/imgs/logo/zksync.svg", + "/imgs/logo/more.svg", + ], + }, + { + name: "Stargate", + icon: "https://scroll-eco-list.netlify.app/logos/stargate.png", + url: "https://stargate.finance/bridge?srcChain=ethereum&srcToken=0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6&dstChain=scroll&dstToken=0x8731d54E9D02c286767d56ac03e8037C07e01e98", + description: ["/imgs/logo/base.svg", "/imgs/logo/binance.svg"], + }, + { + name: "Symbiosis", + icon: "https://scroll-eco-list.netlify.app/logos/symbiosis.png", + url: "https://app.symbiosis.finance/swap?chainIn=Ethereum&chainOut=Scroll&tokenIn=ETH&tokenOut=ETH&_gl=1*8xiyz2*_ga*MTU3MTU0MjUzMy4xNzM3MTgwNjM1*_ga_YKCPZTG9X6*MTczNzY5ODg2My4yLjEuMTczNzY5ODg3MS41Mi4wLjA.", + description: [ + "/imgs/logo/arbitrum.svg", + "/imgs/logo/base.svg", + "/imgs/logo/solana.svg", + "/imgs/logo/optimism.svg", + "/imgs/logo/polygon.svg", + "/imgs/logo/zksync.svg", + "/imgs/logo/more.svg", + ], + }, +] + +export const ONRAMP_PLATFORMS = [ + { + name: "Alchemy pay", + icon: "https://scroll-eco-list.netlify.app/logos/alchemy pay.jpeg", + url: "https://ramp.alchemypay.org/#/index", + description: ["/imgs/logo/visa.svg", "/imgs/logo/mastercard.svg", "/imgs/logo/applepay.svg", "/imgs/logo/googlepay.svg"], + }, +] diff --git a/src/constants/networks.ts b/src/constants/networks.ts index ee8e5005d..d744cf6b6 100644 --- a/src/constants/networks.ts +++ b/src/constants/networks.ts @@ -45,3 +45,250 @@ export const NATIVE_TOKEN_LIST: Token[] = [ logoURI: ETHSvg.src, }, ] + +export const EXTERNAL_BRIDGE_TOKEN_LIST = [ + // for testing, remove later + { + chainId: 11155111, + address: "0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7", + name: "KelpDao Restaked ETH", + symbol: "rsETH", + decimals: 18, + logoURI: "/imgs/token/rsETH.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "rsETH", + bridgeInfo: { + bridgeUrl: "https://kerneldao.com/kelp/bridge-wrap/", + bridgeName: "KelpDao", + bridgeIcon: "/imgs/logo/kelpdao.svg", + }, + }, + }, + { + chainId: 534351, + address: "0x65421ba909200b81640d98B979d07487C9781B66", + name: "KelpDao Restaked ETH", + symbol: "rsETH", + decimals: 18, + logoURI: "/imgs/token/rsETH.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "rsETH", + bridgeInfo: { + bridgeUrl: "https://kerneldao.com/kelp/bridge-wrap/", + bridgeName: "KelpDao", + bridgeIcon: "/imgs/logo/kelpdao.svg", + }, + }, + }, + { + chainId: 11155111, + address: "0x7A56E1C57C7475CCf742a1832B028F0456652F97", + name: "Free Bridged SolvBTC", + symbol: "SolvBTC", + decimals: 18, + logoURI: "/imgs/token/SolvBTC.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "SolvBTC", + bridgeInfo: { + bridgeUrl: "https://app.free.tech/SolvBTC?from=eth&to=scroll", + bridgeName: "Free", + bridgeIcon: "/imgs/logo/free.svg", + }, + }, + }, + { + chainId: 534351, + address: "0x3Ba89d490AB1C0c9CC2313385b30710e838370a4", + name: "Free Bridged SolvBTC", + symbol: "SolvBTC", + decimals: 18, + logoURI: "/imgs/token/SolvBTC.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "SolvBTC", + bridgeInfo: { + bridgeUrl: "https://app.free.tech/SolvBTC?from=scroll&to=eth", + bridgeName: "Free", + bridgeIcon: "/imgs/logo/free.svg", + }, + }, + }, + + { + chainId: 1, + address: "0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7", + name: "KelpDao Restaked ETH", + symbol: "rsETH", + decimals: 18, + logoURI: "/imgs/token/rsETH.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "rsETH", + bridgeInfo: { + bridgeUrl: "https://kerneldao.com/kelp/bridge-wrap/", + bridgeName: "KelpDao", + bridgeIcon: "/imgs/logo/kelpdao.svg", + }, + }, + }, + { + chainId: 534352, + address: "0x65421ba909200b81640d98B979d07487C9781B66", + name: "KelpDao Restaked ETH", + symbol: "rsETH", + decimals: 18, + logoURI: "/imgs/token/rsETH.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "rsETH", + bridgeInfo: { + bridgeUrl: "https://kerneldao.com/kelp/bridge-wrap/", + bridgeName: "KelpDao", + bridgeIcon: "/imgs/logo/kelpdao.svg", + }, + }, + }, + { + chainId: 1, + address: "0x7A56E1C57C7475CCf742a1832B028F0456652F97", + name: "Free Bridged SolvBTC", + symbol: "SolvBTC", + decimals: 18, + logoURI: "/imgs/token/SolvBTC.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "SolvBTC", + bridgeInfo: { + bridgeUrl: "https://app.free.tech/SolvBTC?from=eth&to=scroll", + bridgeName: "Free", + bridgeIcon: "/imgs/logo/free.svg", + }, + }, + }, + { + chainId: 534352, + address: "0x3Ba89d490AB1C0c9CC2313385b30710e838370a4", + name: "Free Bridged SolvBTC", + symbol: "SolvBTC", + decimals: 18, + logoURI: "/imgs/token/SolvBTC.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "SolvBTC", + bridgeInfo: { + bridgeUrl: "https://app.free.tech/SolvBTC?from=scroll&to=eth", + bridgeName: "Free", + bridgeIcon: "/imgs/logo/free.svg", + }, + }, + }, + { + chainId: 1, + address: "0x7122985656e38bdc0302db86685bb972b145bd3c", + name: "StakeStone Ether", + symbol: "STONE", + decimals: 18, + logoURI: "/imgs/token/STONE.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "STONE", + bridgeInfo: { + bridgeUrl: "https://app.stakestone.io/u/eth/bridge", + bridgeName: "StakeStone", + bridgeIcon: "/imgs/logo/STONE.svg", + }, + }, + }, + { + chainId: 534352, + address: "0x80137510979822322193FC997d400D5A6C747bf7", + name: "StakeStone Ether", + symbol: "STONE", + decimals: 18, + logoURI: "/imgs/token/STONE.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "STONE", + bridgeInfo: { + bridgeUrl: "https://app.stakestone.io/u/eth/bridge", + bridgeName: "StakeStone", + bridgeIcon: "/imgs/logo/STONE.svg", + }, + }, + }, + { + chainId: 1, + address: "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497", + name: "Staked USDe", + symbol: "sUSDe", + decimals: 18, + logoURI: "/imgs/token/sUSDe.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "sUSDe", + bridgeInfo: { + bridgeUrl: + "https://stargate.finance/bridge?srcChain=ethereum&srcToken=0x9D39A5DE30e57443BfF2A8307A4256c8797A3497&dstChain=scroll&dstToken=0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2", + bridgeName: "Stargate", + bridgeIcon: "/imgs/logo/Stargate.svg", + }, + }, + }, + { + chainId: 534352, + address: "0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2", + name: "Staked USDe", + symbol: "sUSDe", + decimals: 18, + logoURI: "/imgs/token/sUSDe.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "sUSDe", + bridgeInfo: { + bridgeUrl: + "https://stargate.finance/bridge?srcChain=scroll&srcToken=0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2&dstChain=ethereum&dstToken=0x9D39A5DE30e57443BfF2A8307A4256c8797A3497", + bridgeName: "Stargate", + bridgeIcon: "/imgs/logo/Stargate.svg", + }, + }, + }, + { + chainId: 1, + address: "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3", + name: "USDe", + symbol: "USDe", + decimals: 18, + logoURI: "/imgs/token/USDe.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "USDe", + bridgeInfo: { + bridgeUrl: + "https://stargate.finance/bridge?srcChain=ethereum&srcToken=0x4c9EDD5852cd905f086C759E8383e09bff1E68B3&dstChain=scroll&dstToken=0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34", + bridgeName: "Stargate", + bridgeIcon: "/imgs/logo/Stargate.svg", + }, + }, + }, + { + chainId: 534352, + address: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34", + name: "USDe", + symbol: "USDe", + decimals: 18, + logoURI: "/imgs/token/USDe.svg", + extensions: { + scrollListId: "extended", + scrollTokenId: "USDe", + bridgeInfo: { + bridgeUrl: + "https://stargate.finance/bridge?srcChain=scroll&srcToken=0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34&dstChain=ethereum&dstToken=0x4c9EDD5852cd905f086C759E8383e09bff1E68B3", + bridgeName: "Stargate", + bridgeIcon: "/imgs/logo/Stargate.svg", + }, + }, + }, +] diff --git a/src/constants/searchParamsKey.ts b/src/constants/searchParamsKey.ts index 1aa6fdf60..9b553f0e4 100644 --- a/src/constants/searchParamsKey.ts +++ b/src/constants/searchParamsKey.ts @@ -1 +1,2 @@ export const BRIDGE_TOKEN = "token" +export const BRIDGE_TAB = "tab" diff --git a/src/stores/bridgeStore.ts b/src/stores/bridgeStore.ts index 508ecc70b..c61b502e1 100644 --- a/src/stores/bridgeStore.ts +++ b/src/stores/bridgeStore.ts @@ -1,7 +1,7 @@ import { create } from "zustand" import { tokenListUrl } from "@/apis/dynamic" -import { NATIVE_TOKEN_LIST, NETWORKS } from "@/constants" +import { EXTERNAL_BRIDGE_TOKEN_LIST, NATIVE_TOKEN_LIST, NETWORKS } from "@/constants" import { USER_TOKEN_LIST } from "@/constants/storageKey" import { loadState } from "@/utils/localStorage" @@ -55,7 +55,7 @@ const useBridgeStore = create()((set, get) => ({ const { tokens: tokensListTokens } = await scrollRequest(tokenListUrl) const currentUserTokens = loadState(USER_TOKEN_LIST) || [] - const combinedList = [...NATIVE_TOKEN_LIST, ...tokensListTokens, ...currentUserTokens] + const combinedList = [...NATIVE_TOKEN_LIST, ...tokensListTokens, ...currentUserTokens, ...EXTERNAL_BRIDGE_TOKEN_LIST] const uniqueList = combinedList.reduce( (accumulator, token) => { // If the token doesn't have an address, consider it a native token and add it directly diff --git a/src/types/token.d.ts b/src/types/token.d.ts index f8398d1e0..153b553d3 100644 --- a/src/types/token.d.ts +++ b/src/types/token.d.ts @@ -4,6 +4,13 @@ type BaseToken = { symbol: string decimals: bigint logoURI: string + extensions?: { + bridgeInfo: { + bridgeUrl: string + bridgeName: string + bridgeIcon: string + } + } } type NativeToken = BaseToken & {